Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c07fb08a authored by Tony Wickham's avatar Tony Wickham Committed by Schneider Victor-tulias
Browse files

Make taskbar focusable when folder is open to get IME input

- Remove ActivityContext#supportsIme(), as it's always true now
- Add OnFolderStateChangedListener, which we register when clicking on a taskbar folder icon to set the window focusable/not.
- Also remove Folder.STATE_NONE and instead default to STATE_CLOSED (renamed from STATE_SMALL).

TODO: make sure back button is visible above IME (followup CL)

Test: Open a folder from taskbar while in an app, no animation jump and can change folder name
Bug: 180051157
Change-Id: I7c7847657d462c16677d66b9ffa8b6fe5f164084
parent 1af0e4d2
Loading
Loading
Loading
Loading
+26 −8
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.launcher3.taskbar;
package com.android.launcher3.taskbar;


import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;


@@ -197,6 +198,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
        mWindowLayoutParams.packageName = getPackageName();
        mWindowLayoutParams.packageName = getPackageName();
        mWindowLayoutParams.gravity = Gravity.BOTTOM;
        mWindowLayoutParams.gravity = Gravity.BOTTOM;
        mWindowLayoutParams.setFitInsetsTypes(0);
        mWindowLayoutParams.setFitInsetsTypes(0);
        mWindowLayoutParams.receiveInsetsIgnoringZOrder = true;
        mWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
        mWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
        mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        mWindowLayoutParams.privateFlags =
        mWindowLayoutParams.privateFlags =
@@ -267,14 +269,6 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
        return mViewCache;
        return mViewCache;
    }
    }


    @Override
    public boolean supportsIme() {
        // Currently we don't support IME because we have FLAG_NOT_FOCUSABLE. We can remove that
        // flag when opening a floating view that needs IME (such as Folder), but then that means
        // Taskbar will be below IME and thus users can't click the back button.
        return false;
    }

    @Override
    @Override
    public View.OnClickListener getItemOnClickListener() {
    public View.OnClickListener getItemOnClickListener() {
        return this::onTaskbarIconClicked;
        return this::onTaskbarIconClicked;
@@ -501,6 +495,19 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
        return mTaskbarHeightForIme;
        return mTaskbarHeightForIme;
    }
    }


    /**
     * Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar
     * window.
     */
    public void setTaskbarWindowFocusableForIme(boolean focusable) {
        if (focusable) {
            mWindowLayoutParams.flags &= ~FLAG_NOT_FOCUSABLE;
        } else {
            mWindowLayoutParams.flags |= FLAG_NOT_FOCUSABLE;
        }
        mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
    }

    protected void onTaskbarIconClicked(View view) {
    protected void onTaskbarIconClicked(View view) {
        Object tag = view.getTag();
        Object tag = view.getTag();
        if (tag instanceof Task) {
        if (tag instanceof Task) {
@@ -510,6 +517,17 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
        } else if (tag instanceof FolderInfo) {
        } else if (tag instanceof FolderInfo) {
            FolderIcon folderIcon = (FolderIcon) view;
            FolderIcon folderIcon = (FolderIcon) view;
            Folder folder = folderIcon.getFolder();
            Folder folder = folderIcon.getFolder();

            folder.setOnFolderStateChangedListener(newState -> {
                if (newState == Folder.STATE_OPEN) {
                    setTaskbarWindowFocusableForIme(true);
                } else if (newState == Folder.STATE_CLOSED) {
                    // Defer by a frame to ensure we're no longer fullscreen and thus won't jump.
                    getDragLayer().post(() -> setTaskbarWindowFocusableForIme(false));
                    folder.setOnFolderStateChangedListener(null);
                }
            });

            setTaskbarWindowFullscreen(true);
            setTaskbarWindowFullscreen(true);


            getDragLayer().post(() -> {
            getDragLayer().post(() -> {
+42 −24
Original line number Original line Diff line number Diff line
@@ -57,6 +57,7 @@ import android.view.animation.AnimationUtils;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import android.widget.TextView;


import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.content.res.ResourcesCompat;


@@ -101,6 +102,8 @@ import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.views.ClipPathView;
import com.android.launcher3.views.ClipPathView;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddShortcutInfo;


import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Collections;
import java.util.Comparator;
import java.util.Comparator;
@@ -130,10 +133,13 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
     */
     */
    private static final int MIN_CONTENT_DIMEN = 5;
    private static final int MIN_CONTENT_DIMEN = 5;


    static final int STATE_NONE = -1;
    public static final int STATE_CLOSED = 0;
    static final int STATE_SMALL = 0;
    public static final int STATE_ANIMATING = 1;
    static final int STATE_ANIMATING = 1;
    public static final int STATE_OPEN = 2;
    static final int STATE_OPEN = 2;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({STATE_CLOSED, STATE_ANIMATING, STATE_OPEN})
    public @interface FolderState {}


    /**
    /**
     * Time for which the scroll hint is shown before automatically changing page.
     * Time for which the scroll hint is shown before automatically changing page.
@@ -198,13 +204,12 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo


    @ViewDebug.ExportedProperty(category = "launcher",
    @ViewDebug.ExportedProperty(category = "launcher",
            mapping = {
            mapping = {
                    @ViewDebug.IntToString(from = STATE_NONE, to = "STATE_NONE"),
                    @ViewDebug.IntToString(from = STATE_CLOSED, to = "STATE_CLOSED"),
                    @ViewDebug.IntToString(from = STATE_SMALL, to = "STATE_SMALL"),
                    @ViewDebug.IntToString(from = STATE_ANIMATING, to = "STATE_ANIMATING"),
                    @ViewDebug.IntToString(from = STATE_ANIMATING, to = "STATE_ANIMATING"),
                    @ViewDebug.IntToString(from = STATE_OPEN, to = "STATE_OPEN"),
                    @ViewDebug.IntToString(from = STATE_OPEN, to = "STATE_OPEN"),
            })
            })
    @Thunk
    private int mState = STATE_CLOSED;
    int mState = STATE_NONE;
    private OnFolderStateChangedListener mOnFolderStateChangedListener;
    @ViewDebug.ExportedProperty(category = "launcher")
    @ViewDebug.ExportedProperty(category = "launcher")
    private boolean mRearrangeOnClose = false;
    private boolean mRearrangeOnClose = false;
    boolean mItemsInvalidated = false;
    boolean mItemsInvalidated = false;
@@ -277,7 +282,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
        mPageIndicator = findViewById(R.id.folder_page_indicator);
        mPageIndicator = findViewById(R.id.folder_page_indicator);
        mFolderName = findViewById(R.id.folder_name);
        mFolderName = findViewById(R.id.folder_name);
        mFolderName.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.folderLabelTextSizePx);
        mFolderName.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.folderLabelTextSizePx);
        if (mActivityContext.supportsIme()) {
        mFolderName.setOnBackKeyListener(this);
        mFolderName.setOnBackKeyListener(this);
        mFolderName.setOnFocusChangeListener(this);
        mFolderName.setOnFocusChangeListener(this);
        mFolderName.setOnEditorActionListener(this);
        mFolderName.setOnEditorActionListener(this);
@@ -287,9 +291,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
                | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
                | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
                | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
                | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
        mFolderName.forceDisableSuggestions(true);
        mFolderName.forceDisableSuggestions(true);
        } else {
            mFolderName.setEnabled(false);
        }


        mFooter = findViewById(R.id.folder_footer);
        mFooter = findViewById(R.id.folder_footer);
        mFooterHeight = getResources().getDimensionPixelSize(R.dimen.folder_label_height);
        mFooterHeight = getResources().getDimensionPixelSize(R.dimen.folder_label_height);
@@ -561,7 +562,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
        a.addListener(new AnimatorListenerAdapter() {
        a.addListener(new AnimatorListenerAdapter() {
            @Override
            @Override
            public void onAnimationStart(Animator animation) {
            public void onAnimationStart(Animator animation) {
                mState = STATE_ANIMATING;
                setState(STATE_ANIMATING);
                mCurrentAnimator = a;
                mCurrentAnimator = a;
            }
            }


@@ -686,7 +687,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo


            @Override
            @Override
            public void onAnimationEnd(Animator animation) {
            public void onAnimationEnd(Animator animation) {
                mState = STATE_OPEN;
                setState(STATE_OPEN);
                announceAccessibilityChanges();
                announceAccessibilityChanges();
                AccessibilityManagerCompat.sendFolderOpenedEventToTest(getContext());
                AccessibilityManagerCompat.sendFolderOpenedEventToTest(getContext());


@@ -862,7 +863,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
        }
        }
        mSuppressFolderDeletion = false;
        mSuppressFolderDeletion = false;
        clearDragInfo();
        clearDragInfo();
        mState = STATE_SMALL;
        setState(STATE_CLOSED);
        mContent.setCurrentPage(0);
        mContent.setCurrentPage(0);
    }
    }


@@ -1655,4 +1656,21 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo


        return windowBottomPx - folderBottomPx;
        return windowBottomPx - folderBottomPx;
    }
    }

    private void setState(@FolderState int newState) {
        mState = newState;
        if (mOnFolderStateChangedListener != null) {
            mOnFolderStateChangedListener.onFolderStateChanged(mState);
        }
    }

    public void setOnFolderStateChangedListener(@Nullable OnFolderStateChangedListener listener) {
        mOnFolderStateChangedListener = listener;
    }

    /** Listener that can be registered via {@link Folder#setOnFolderStateChangedListener} */
    public interface OnFolderStateChangedListener {
        /** See {@link Folder.FolderState} */
        void onFolderStateChanged(@FolderState int newState);
    }
}
}
+1 −2
Original line number Original line Diff line number Diff line
@@ -28,7 +28,6 @@ import android.os.Message;
import android.view.View;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodManager;


import com.android.launcher3.BaseActivity;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.ActivityContext;


/**
/**
@@ -56,7 +55,7 @@ public class UiThreadHelper {
                STATS_LOGGER_KEY,
                STATS_LOGGER_KEY,
                Message.obtain(
                Message.obtain(
                        HANDLER.get(root.getContext()),
                        HANDLER.get(root.getContext()),
                        () -> BaseActivity.fromContext(root.getContext())
                        () -> ActivityContext.lookupContext(root.getContext())
                                .getStatsLogManager()
                                .getStatsLogManager()
                                .logger()
                                .logger()
                                .log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED)
                                .log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED)
+0 −7
Original line number Original line Diff line number Diff line
@@ -124,13 +124,6 @@ public interface ActivityContext {
        return true;
        return true;
    }
    }


    /**
     * Returns whether we can show the IME for elements hosted by this ActivityContext.
     */
    default boolean supportsIme() {
        return true;
    }

    /**
    /**
     * Called just before logging the given item.
     * Called just before logging the given item.
     */
     */