From c07fb08a1e51b0901ec3a59aff108f6bc93ad122 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Thu, 16 Dec 2021 17:40:38 +0000 Subject: [PATCH 1/2] 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 --- .../taskbar/TaskbarActivityContext.java | 34 +++++++--- src/com/android/launcher3/folder/Folder.java | 66 ++++++++++++------- .../launcher3/util/UiThreadHelper.java | 3 +- .../launcher3/views/ActivityContext.java | 7 -- 4 files changed, 69 insertions(+), 41 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index b1f027a00d..bef62584ae 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -16,6 +16,7 @@ package com.android.launcher3.taskbar; 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.TYPE_NAVIGATION_BAR_PANEL; @@ -197,6 +198,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ mWindowLayoutParams.packageName = getPackageName(); mWindowLayoutParams.gravity = Gravity.BOTTOM; mWindowLayoutParams.setFitInsetsTypes(0); + mWindowLayoutParams.receiveInsetsIgnoringZOrder = true; mWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; mWindowLayoutParams.privateFlags = @@ -267,14 +269,6 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ 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 public View.OnClickListener getItemOnClickListener() { return this::onTaskbarIconClicked; @@ -501,6 +495,19 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ 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) { Object tag = view.getTag(); if (tag instanceof Task) { @@ -510,6 +517,17 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ } else if (tag instanceof FolderInfo) { FolderIcon folderIcon = (FolderIcon) view; 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); getDragLayer().post(() -> { diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index daef68226d..1e6342cc8b 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -57,6 +57,7 @@ import android.view.animation.AnimationUtils; import android.view.inputmethod.EditorInfo; import android.widget.TextView; +import androidx.annotation.IntDef; import androidx.annotation.Nullable; 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.widget.PendingAddShortcutInfo; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -130,10 +133,13 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo */ private static final int MIN_CONTENT_DIMEN = 5; - static final int STATE_NONE = -1; - static final int STATE_SMALL = 0; - static final int STATE_ANIMATING = 1; - static final int STATE_OPEN = 2; + public static final int STATE_CLOSED = 0; + public static final int STATE_ANIMATING = 1; + public 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. @@ -198,13 +204,12 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo @ViewDebug.ExportedProperty(category = "launcher", mapping = { - @ViewDebug.IntToString(from = STATE_NONE, to = "STATE_NONE"), - @ViewDebug.IntToString(from = STATE_SMALL, to = "STATE_SMALL"), + @ViewDebug.IntToString(from = STATE_CLOSED, to = "STATE_CLOSED"), @ViewDebug.IntToString(from = STATE_ANIMATING, to = "STATE_ANIMATING"), @ViewDebug.IntToString(from = STATE_OPEN, to = "STATE_OPEN"), }) - @Thunk - int mState = STATE_NONE; + private int mState = STATE_CLOSED; + private OnFolderStateChangedListener mOnFolderStateChangedListener; @ViewDebug.ExportedProperty(category = "launcher") private boolean mRearrangeOnClose = false; boolean mItemsInvalidated = false; @@ -277,19 +282,15 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo mPageIndicator = findViewById(R.id.folder_page_indicator); mFolderName = findViewById(R.id.folder_name); mFolderName.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.folderLabelTextSizePx); - if (mActivityContext.supportsIme()) { - mFolderName.setOnBackKeyListener(this); - mFolderName.setOnFocusChangeListener(this); - mFolderName.setOnEditorActionListener(this); - mFolderName.setSelectAllOnFocus(true); - mFolderName.setInputType(mFolderName.getInputType() - & ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT - | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS - | InputType.TYPE_TEXT_FLAG_CAP_WORDS); - mFolderName.forceDisableSuggestions(true); - } else { - mFolderName.setEnabled(false); - } + mFolderName.setOnBackKeyListener(this); + mFolderName.setOnFocusChangeListener(this); + mFolderName.setOnEditorActionListener(this); + mFolderName.setSelectAllOnFocus(true); + mFolderName.setInputType(mFolderName.getInputType() + & ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS + | InputType.TYPE_TEXT_FLAG_CAP_WORDS); + mFolderName.forceDisableSuggestions(true); mFooter = findViewById(R.id.folder_footer); mFooterHeight = getResources().getDimensionPixelSize(R.dimen.folder_label_height); @@ -561,7 +562,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo a.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { - mState = STATE_ANIMATING; + setState(STATE_ANIMATING); mCurrentAnimator = a; } @@ -686,7 +687,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo @Override public void onAnimationEnd(Animator animation) { - mState = STATE_OPEN; + setState(STATE_OPEN); announceAccessibilityChanges(); AccessibilityManagerCompat.sendFolderOpenedEventToTest(getContext()); @@ -862,7 +863,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo } mSuppressFolderDeletion = false; clearDragInfo(); - mState = STATE_SMALL; + setState(STATE_CLOSED); mContent.setCurrentPage(0); } @@ -1655,4 +1656,21 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo 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); + } } diff --git a/src/com/android/launcher3/util/UiThreadHelper.java b/src/com/android/launcher3/util/UiThreadHelper.java index ac5368c8b4..a1f31fe459 100644 --- a/src/com/android/launcher3/util/UiThreadHelper.java +++ b/src/com/android/launcher3/util/UiThreadHelper.java @@ -28,7 +28,6 @@ import android.os.Message; import android.view.View; import android.view.inputmethod.InputMethodManager; -import com.android.launcher3.BaseActivity; import com.android.launcher3.views.ActivityContext; /** @@ -56,7 +55,7 @@ public class UiThreadHelper { STATS_LOGGER_KEY, Message.obtain( HANDLER.get(root.getContext()), - () -> BaseActivity.fromContext(root.getContext()) + () -> ActivityContext.lookupContext(root.getContext()) .getStatsLogManager() .logger() .log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED) diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java index e09eff6f94..c0f6316b95 100644 --- a/src/com/android/launcher3/views/ActivityContext.java +++ b/src/com/android/launcher3/views/ActivityContext.java @@ -124,13 +124,6 @@ public interface ActivityContext { 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. */ From 66971f87e19aa97da512ec42fff88d796310256b Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 10 Jan 2022 22:30:14 +0000 Subject: [PATCH 2/2] Create new window for Taskbar Nav Buttons when taskbar is focusable Test: Open folder from taskbar, edit name, ensure back button displays above IME and that IME sends input to the taskbar folder name Bug: 205803170 Change-Id: I36f6cfb835aa7da280f15ea4b0aed8923ce8a012 --- .../taskbar/NavbarButtonsViewController.java | 84 ++++++++++++++++++- .../taskbar/TaskbarActivityContext.java | 52 ++++++++---- .../launcher3/taskbar/TaskbarDragLayer.java | 18 ++++ src/com/android/launcher3/Utilities.java | 2 +- 4 files changed, 137 insertions(+), 19 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java index a4ecd8b13d..6ae8c9d31e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java @@ -36,6 +36,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING; +import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION; import android.animation.ArgbEvaluator; import android.animation.ObjectAnimator; @@ -53,9 +54,11 @@ import android.util.Property; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; +import android.view.View.OnAttachStateChangeListener; import android.view.View.OnClickListener; import android.view.View.OnHoverListener; import android.view.ViewGroup; +import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; @@ -65,10 +68,13 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.AlphaUpdateListener; import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton; import com.android.launcher3.util.MultiValueAlpha; +import com.android.launcher3.util.TouchController; +import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.AnimatedFloat; import com.android.systemui.shared.rotation.FloatingRotationButton; import com.android.systemui.shared.rotation.RotationButton; import com.android.systemui.shared.rotation.RotationButtonController; +import com.android.systemui.shared.system.ViewTreeObserverWrapper; import java.util.ArrayList; import java.util.function.IntPredicate; @@ -95,6 +101,8 @@ public class NavbarButtonsViewController { private static final int MASK_IME_SWITCHER_VISIBLE = FLAG_SWITCHER_SUPPORTED | FLAG_IME_VISIBLE; + private static final String NAV_BUTTONS_SEPARATE_WINDOW_TITLE = "Taskbar Nav Buttons"; + private final ArrayList mPropertyHolders = new ArrayList<>(); private final ArrayList mAllButtons = new ArrayList<>(); private int mState; @@ -130,6 +138,12 @@ public class NavbarButtonsViewController { private View mBackButton; private FloatingRotationButton mFloatingRotationButton; + // Variables for moving nav buttons to a separate window above IME + private boolean mAreNavButtonsInSeparateWindow = false; + private BaseDragLayer mSeparateWindowParent; // Initialized in init. + private final ViewTreeObserverWrapper.OnComputeInsetsListener mSeparateWindowInsetsComputer = + this::onComputeInsetsForSeparateWindow; + public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) { mContext = context; mNavButtonsView = navButtonsView; @@ -258,6 +272,21 @@ public class NavbarButtonsViewController { R.id.notifications_button); } + // Initialize things needed to move nav buttons to separate window. + mSeparateWindowParent = new BaseDragLayer(mContext, null, 0) { + @Override + public void recreateControllers() { + mControllers = new TouchController[0]; + } + + @Override + protected boolean canFindActiveController() { + // We don't have any controllers, but we don't want any floating views such as + // folder to intercept, either. This ensures nav buttons can always be pressed. + return false; + } + }; + mSeparateWindowParent.recreateControllers(); } private void initButtons(ViewGroup navContainer, ViewGroup endContainer, @@ -393,7 +422,7 @@ public class NavbarButtonsViewController { /** * Adds the bounds corresponding to all visible buttons to provided region */ - public void addVisibleButtonsRegion(TaskbarDragLayer parent, Region outRegion) { + public void addVisibleButtonsRegion(BaseDragLayer parent, Region outRegion) { int count = mAllButtons.size(); for (int i = 0; i < count; i++) { View button = mAllButtons.get(i); @@ -498,6 +527,59 @@ public class NavbarButtonsViewController { if (mFloatingRotationButton != null) { mFloatingRotationButton.hide(); } + + moveNavButtonsBackToTaskbarWindow(); + } + + /** + * Moves mNavButtonsView from TaskbarDragLayer to a placeholder BaseDragLayer on a new window. + */ + public void moveNavButtonsToNewWindow() { + if (mAreNavButtonsInSeparateWindow) { + return; + } + + mSeparateWindowParent.addOnAttachStateChangeListener(new OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View view) { + ViewTreeObserverWrapper.addOnComputeInsetsListener( + mSeparateWindowParent.getViewTreeObserver(), mSeparateWindowInsetsComputer); + } + + @Override + public void onViewDetachedFromWindow(View view) { + mSeparateWindowParent.removeOnAttachStateChangeListener(this); + ViewTreeObserverWrapper.removeOnComputeInsetsListener( + mSeparateWindowInsetsComputer); + } + }); + + mAreNavButtonsInSeparateWindow = true; + mContext.getDragLayer().removeView(mNavButtonsView); + mSeparateWindowParent.addView(mNavButtonsView); + WindowManager.LayoutParams windowLayoutParams = mContext.createDefaultWindowLayoutParams(); + windowLayoutParams.setTitle(NAV_BUTTONS_SEPARATE_WINDOW_TITLE); + mContext.addWindowView(mSeparateWindowParent, windowLayoutParams); + + } + + /** + * Moves mNavButtonsView from its temporary window and reattaches it to TaskbarDragLayer. + */ + public void moveNavButtonsBackToTaskbarWindow() { + if (!mAreNavButtonsInSeparateWindow) { + return; + } + + mAreNavButtonsInSeparateWindow = false; + mContext.removeWindowView(mSeparateWindowParent); + mSeparateWindowParent.removeView(mNavButtonsView); + mContext.getDragLayer().addView(mNavButtonsView); + } + + private void onComputeInsetsForSeparateWindow(ViewTreeObserverWrapper.InsetsInfo insetsInfo) { + addVisibleButtonsRegion(mSeparateWindowParent, insetsInfo.touchableRegion); + insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); } private class RotationButtonListener implements RotationButton.RotationButtonUpdatesCallback { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index bef62584ae..e48b26be76 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -187,22 +187,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ public void init(TaskbarSharedState sharedState) { mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight(); - mWindowLayoutParams = new WindowManager.LayoutParams( - MATCH_PARENT, - mLastRequestedNonFullscreenHeight, - TYPE_NAVIGATION_BAR_PANEL, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_SLIPPERY, - PixelFormat.TRANSLUCENT); - mWindowLayoutParams.setTitle(WINDOW_TITLE); - mWindowLayoutParams.packageName = getPackageName(); - mWindowLayoutParams.gravity = Gravity.BOTTOM; - mWindowLayoutParams.setFitInsetsTypes(0); - mWindowLayoutParams.receiveInsetsIgnoringZOrder = true; - mWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; - mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; - mWindowLayoutParams.privateFlags = - WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; + mWindowLayoutParams = createDefaultWindowLayoutParams(); WindowManagerWrapper wmWrapper = WindowManagerWrapper.getInstance(); wmWrapper.setProvidesInsetsTypes( @@ -223,6 +208,27 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ mWindowManager.addView(mDragLayer, mWindowLayoutParams); } + /** Creates LayoutParams for adding a view directly to WindowManager as a new window */ + public WindowManager.LayoutParams createDefaultWindowLayoutParams() { + WindowManager.LayoutParams windowLayoutParams = new WindowManager.LayoutParams( + MATCH_PARENT, + mLastRequestedNonFullscreenHeight, + TYPE_NAVIGATION_BAR_PANEL, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_SLIPPERY, + PixelFormat.TRANSLUCENT); + windowLayoutParams.setTitle(WINDOW_TITLE); + windowLayoutParams.packageName = getPackageName(); + windowLayoutParams.gravity = Gravity.BOTTOM; + windowLayoutParams.setFitInsetsTypes(0); + windowLayoutParams.receiveInsetsIgnoringZOrder = true; + windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; + windowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + windowLayoutParams.privateFlags = + WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; + return windowLayoutParams; + } + public void onConfigurationChanged(@Config int configChanges) { mControllers.onConfigurationChanged(configChanges); } @@ -497,17 +503,29 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ /** * Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar - * window. + * window. If we're now focusable, also move nav buttons to a separate window above IME. */ public void setTaskbarWindowFocusableForIme(boolean focusable) { if (focusable) { mWindowLayoutParams.flags &= ~FLAG_NOT_FOCUSABLE; + mControllers.navbarButtonsViewController.moveNavButtonsToNewWindow(); } else { mWindowLayoutParams.flags |= FLAG_NOT_FOCUSABLE; + mControllers.navbarButtonsViewController.moveNavButtonsBackToTaskbarWindow(); } mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams); } + /** Adds the given view to WindowManager with the provided LayoutParams (creates new window). */ + public void addWindowView(View view, WindowManager.LayoutParams windowLayoutParams) { + mWindowManager.addView(view, windowLayoutParams); + } + + /** Removes the given view from WindowManager. See {@link #addWindowView}. */ + public void removeWindowView(View view) { + mWindowManager.removeViewImmediate(view); + } + protected void onTaskbarIconClicked(View view) { Object tag = view.getTag(); if (tag instanceof Task) { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java index b42a60ceea..df004ef6e4 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java @@ -15,17 +15,22 @@ */ package com.android.launcher3.taskbar; +import static android.view.KeyEvent.ACTION_UP; +import static android.view.KeyEvent.KEYCODE_BACK; + import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.R; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.TestProtocol; @@ -187,4 +192,17 @@ public class TaskbarDragLayer extends BaseDragLayer { TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev); return super.dispatchTouchEvent(ev); } + + /** Called while Taskbar window is focusable, e.g. when pressing back while a folder is open */ + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) { + AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity); + if (topView != null && topView.onBackPressed()) { + // Handled by the floating view. + return true; + } + } + return super.dispatchKeyEvent(event); + } } diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index ac194d2077..5bcc2ad26d 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -228,7 +228,7 @@ public final class Utilities { offsetPoints(coord, v.getLeft(), v.getTop()); scale *= v.getScaleX(); - v = (View) v.getParent(); + v = v.getParent() instanceof View ? (View) v.getParent() : null; } return scale; }