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

Commit 66dcca80 authored by Mady Mellor's avatar Mady Mellor
Browse files

Fix touches for manage menu

The manage menu can overlap the expanded view (TaskView).

To fix this we need to adjust the touchableRegion in
TaskView. This CL adds a method to specify a region that
is not touchable on the TaskView.

Also removes some code associated with old method of doing
this when we had ActivityView.

Test: manual - 1) expand bubble, tap "manage"
               2) make sure you can tap each of the three
                  menu options
               3) make sure tapping outside the menu hides
                  the menu
               4) make sure interaction with TaskView is
                  normal after manage menu is hidden
Fixes: 171233619
Change-Id: I3ef75b84f1b5f5b24aa19b192c7c2b7545b91cad
parent 3b1852bd
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
    private boolean mIsInitialized;
    private Listener mListener;
    private Executor mListenerExecutor;
    private Rect mObscuredTouchRect;

    private final Rect mTmpRect = new Rect();
    private final Rect mTmpRootRect = new Rect();
@@ -160,6 +161,15 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
        options.setRemoveWithTaskOrganizer(true);
    }

    /**
     * Indicates a region of the view that is not touchable.
     *
     * @param obscuredRect the obscured region of the view.
     */
    public void setObscuredTouchRect(Rect obscuredRect) {
        mObscuredTouchRect = obscuredRect;
    }

    /**
     * Call when view position or size has changed. Do not call when animating.
     */
@@ -384,6 +394,10 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
        mTmpRect.set(mTmpLocation[0], mTmpLocation[1],
                mTmpLocation[0] + getWidth(), mTmpLocation[1] + getHeight());
        inoutInfo.touchableRegion.op(mTmpRect, Region.Op.DIFFERENCE);

        if (mObscuredTouchRect != null) {
            inoutInfo.touchableRegion.union(mObscuredTouchRect);
        }
    }

    @Override
+6 −45
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
@@ -1046,6 +1045,7 @@ public class BubbleStackView extends FrameLayout
        }
    };

    // TODO: Create ManageMenuView and move setup / animations there
    private void setUpManageMenu() {
        if (mManageMenu != null) {
            removeView(mManageMenu);
@@ -2146,50 +2146,6 @@ public class BubbleStackView extends FrameLayout
    }

    /**
     * This method is called by {@link android.app.ActivityView} because the BubbleStackView has a
     * higher Z-index than the ActivityView (so that dragged-out bubbles are visible over the AV).
     * ActivityView is asking BubbleStackView to subtract the stack's bounds from the provided
     * touchable region, so that the ActivityView doesn't consume events meant for the stack. Due to
     * the special nature of ActivityView, it does not respect the standard
     * {@link #dispatchTouchEvent} and {@link #onInterceptTouchEvent} methods typically used for
     * this purpose.
     *
     * BubbleStackView is MATCH_PARENT, so that bubbles can be positioned via their translation
     * properties for performance reasons. This means that the default implementation of this method
     * subtracts the entirety of the screen from the ActivityView's touchable region, resulting in
     * it not receiving any touch events. This was previously addressed by returning false in the
     * stack's {@link View#canReceivePointerEvents()} method, but this precluded the use of any
     * touch handlers in the stack or its child views.
     *
     * To support touch handlers, we're overriding this method to leave the ActivityView's touchable
     * region alone. The only touchable part of the stack that can ever overlap the AV is a
     * dragged-out bubble that is animating back into the row of bubbles. It's not worth continually
     * updating the touchable region to allow users to grab a bubble while it completes its ~50ms
     * animation back to the bubble row.
     *
     * NOTE: Any future additions to the stack that obscure the ActivityView region will need their
     * bounds subtracted here in order to receive touch events.
     */
    @Override
    public void subtractObscuredTouchableRegion(Region touchableRegion, View view) {
        // If the notification shade is expanded, or the manage menu is open, or we are showing
        // manage bubbles user education, we shouldn't let the ActivityView steal any touch events
        // from any location.
        if (!mIsExpanded
                || mShowingManage
                || (mManageEduView != null
                    && mManageEduView.getVisibility() == VISIBLE)) {
            touchableRegion.setEmpty();
        }
    }

    /**
     * If you're here because you're not receiving touch events on a view that is a descendant of
     * BubbleStackView, and you think BSV is intercepting them - it's not! You need to subtract the
     * bounds of the view in question in {@link #subtractObscuredTouchableRegion}. The ActivityView
     * consumes all touch events within its bounds, even for views like the BubbleStackView that are
     * above it. It ignores typical view touch handling methods like this one and
     * dispatchTouchEvent.
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
@@ -2539,6 +2495,11 @@ public class BubbleStackView extends FrameLayout
        }

        mExpandedBubble.getExpandedView().getManageButtonBoundsOnScreen(mTempRect);
        if (mExpandedBubble.getExpandedView().getTaskView() != null) {
            mExpandedBubble.getExpandedView().getTaskView().setObscuredTouchRect(mShowingManage
                    ? new Rect(0, 0, getWidth(), getHeight())
                    : null);
        }

        final boolean isLtr =
                getResources().getConfiguration().getLayoutDirection() == LAYOUT_DIRECTION_LTR;