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

Commit 847b1d42 authored by Joshua Tsuji's avatar Joshua Tsuji Committed by Josh Tsuji
Browse files

Make the bubbles window NOT_FOCUSABLE when the IME is up, but FOCUSABLE otherwise.

This works around an issue where the IME doesn't appear due to bugs with virtual displays + focus. By making Bubbles FOCUSABLE during the initial tap to bring up the IME, we ensure that the Bubbles window has focus and no other windows do. Once the IME is up, we make Bubbles NOT_FOCUSABLE so that swipes on the Bubbles UI doesn't steal focus from the ActivityView.

Also, adds a touch listener to the expanded view that prevents the stack from collapsing if the side padding is touched during a back gesture.

Test: manual, lots of IME mashing
Bug: 156785479
Change-Id: Ia9de170a9ce4c9b99017d0ce6901621f70b414fc
parent af9a747e
Loading
Loading
Loading
Loading
+20 −6
Original line number Diff line number Diff line
@@ -211,6 +211,13 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
    // TODO (b/145659174): allow for multiple callbacks to support the "shadow" new notif pipeline
    private final List<NotifCallback> mCallbacks = new ArrayList<>();

    /**
     * Whether the IME is visible, as reported by the BubbleStackView. If it is, we'll make the
     * Bubbles window NOT_FOCUSABLE so that touches on the Bubbles UI doesn't steal focus from the
     * ActivityView and hide the IME.
     */
    private boolean mImeVisible = false;

    /**
     * Listener to find out about stack expansion / collapse events.
     */
@@ -598,7 +605,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        if (mStackView == null) {
            mStackView = new BubbleStackView(
                    mContext, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator,
                    mSysUiState, mNotificationShadeWindowController, this::onAllBubblesAnimatedOut);
                    mSysUiState, mNotificationShadeWindowController, this::onAllBubblesAnimatedOut,
                    this::onImeVisibilityChanged);
            mStackView.addView(mBubbleScrim);
            if (mExpandListener != null) {
                mStackView.setExpandListener(mExpandListener);
@@ -649,6 +657,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        }
    }

    private void onImeVisibilityChanged(boolean imeVisible) {
        mImeVisible = imeVisible;
        updateWmFlags();
    }

    /** Removes the BubbleStackView from the WindowManager if it's there. */
    private void removeFromWindowManagerMaybe() {
        if (!mAddedToWindowManager) {
@@ -676,13 +689,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
     * the new params if the stack has been added.
     */
    private void updateWmFlags() {
        if (isStackExpanded()) {
            // If we're expanded, we want to be focusable so that the ActivityView can receive focus
            // and show the IME.
        if (isStackExpanded() && !mImeVisible) {
            // If we're expanded, and the IME isn't visible, we want to be focusable. This ensures
            // that any taps within Bubbles (including on the ActivityView) results in Bubbles
            // receiving focus and clearing it from any other windows that might have it.
            mWmLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        } else {
            // If we're collapsed, we don't want to be able to receive focus. Doing so would
            // preclude applications from using the IME since we are always above them.
            // If we're collapsed, we don't want to be focusable since tapping on the stack would
            // steal focus from apps. We also don't want to be focusable if the IME is visible,
            mWmLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        }

+36 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;

import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.ActivityView;
@@ -239,6 +240,7 @@ public class BubbleExpandedView extends LinearLayout {
        mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
@@ -290,6 +292,30 @@ public class BubbleExpandedView extends LinearLayout {
            }
            return view.onApplyWindowInsets(insets);
        });

        final int expandedViewPadding =
                res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);

        setPadding(
                expandedViewPadding, expandedViewPadding, expandedViewPadding, expandedViewPadding);
        setOnTouchListener((view, motionEvent) -> {
            if (!usingActivityView()) {
                return false;
            }

            final Rect avBounds = new Rect();
            mActivityView.getBoundsOnScreen(avBounds);

            // Consume and ignore events on the expanded view padding that are within the
            // ActivityView's vertical bounds. These events are part of a back gesture, and so they
            // should not collapse the stack (which all other touches on areas around the AV would
            // do).
            if (motionEvent.getRawY() >= avBounds.top && motionEvent.getRawY() <= avBounds.bottom) {
                return true;
            }

            return false;
        });
    }

    private String getBubbleKey() {
@@ -323,9 +349,19 @@ public class BubbleExpandedView extends LinearLayout {
        }
    }

    /**
     * Hides the IME if it's showing. This is currently done by dispatching a back press to the AV.
     */
    void hideImeIfVisible() {
        if (mKeyboardVisible) {
            performBackPressIfNeeded();
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        hideImeIfVisible();
        mKeyboardVisible = false;
        mNeedsNewHeight = false;
        if (mActivityView != null) {
+19 −3
Original line number Diff line number Diff line
@@ -341,6 +341,12 @@ public class BubbleStackView extends FrameLayout

    private final NotificationShadeWindowController mNotificationShadeWindowController;

    /**
     * Callback to run when the IME visibility changes - BubbleController uses this to update the
     * Bubbles window focusability flags with the WindowManager.
     */
    public final Consumer<Boolean> mOnImeVisibilityChanged;

    /**
     * The currently magnetized object, which is being dragged and will be attracted to the magnetic
     * dismiss target.
@@ -667,7 +673,8 @@ public class BubbleStackView extends FrameLayout
            FloatingContentCoordinator floatingContentCoordinator,
            SysUiState sysUiState,
            NotificationShadeWindowController notificationShadeWindowController,
            Runnable allBubblesAnimatedOutAction) {
            Runnable allBubblesAnimatedOutAction,
            Consumer<Boolean> onImeVisibilityChanged) {
        super(context);

        mBubbleData = data;
@@ -724,8 +731,6 @@ public class BubbleStackView extends FrameLayout

        mExpandedViewContainer = new FrameLayout(context);
        mExpandedViewContainer.setElevation(elevation);
        mExpandedViewContainer.setPadding(mExpandedViewPadding, mExpandedViewPadding,
                mExpandedViewPadding, mExpandedViewPadding);
        mExpandedViewContainer.setClipChildren(false);
        addView(mExpandedViewContainer);

@@ -793,7 +798,11 @@ public class BubbleStackView extends FrameLayout

        setUpOverflow();

        mOnImeVisibilityChanged = onImeVisibilityChanged;

        setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
            onImeVisibilityChanged.accept(insets.getInsets(WindowInsets.Type.ime()).bottom > 0);

            if (!mIsExpanded || mIsExpansionAnimating) {
                return view.onApplyWindowInsets(insets);
            }
@@ -2126,6 +2135,13 @@ public class BubbleStackView extends FrameLayout
        if (DEBUG_BUBBLE_STACK_VIEW) {
            Log.d(TAG, "updateExpandedBubble()");
        }

        if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
            // Hide the currently expanded bubble's IME if it's visible before switching to a new
            // bubble.
            mExpandedBubble.getExpandedView().hideImeIfVisible();
        }

        mExpandedViewContainer.removeAllViews();
        if (mIsExpanded && mExpandedBubble != null
                && mExpandedBubble.getExpandedView() != null) {