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

Commit e0d0c020 authored by mattsziklay's avatar mattsziklay
Browse files

Change input handling to allow button ripples.

The desktop mode touch handler would consume ACTION_DOWN input events
if they occur in app pill / maximize / close buttons, preventing them
from displaying ripple effects. This CL changes the touch handler and
buttons themselves to prevent these events from being consumed while
leaving other functionality (double tap, drag, long press) in tact.

Because there are less input events being consumed, this CL removes
variables mShouldClick and shouldLongClick as we can now allow the
listener itself to determine these events.

Bug: 316194617
Test: Manual
Change-Id: I07a80d7952bfcc7e01d18449282e4339b0fcd6bb
parent c5b8dc18
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
  -->
<com.android.wm.shell.windowdecor.WindowDecorLinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/desktop_mode_caption"
    android:layout_width="match_parent"
@@ -27,6 +28,8 @@
        android:id="@+id/open_menu_button"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:tint="?androidprv:attr/materialColorOnSurface"
        android:background="?android:selectableItemBackground"
        android:orientation="horizontal"
        android:clickable="true"
        android:focusable="true"
@@ -78,7 +81,9 @@
        android:id="@+id/maximize_button_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end"/>
        android:layout_gravity="end"
        android:clickable="true"
        android:focusable="true" />

    <ImageButton
        android:id="@+id/close_window"
@@ -86,9 +91,10 @@
        android:layout_height="40dp"
        android:padding="4dp"
        android:layout_marginEnd="8dp"
        android:tint="?androidprv:attr/materialColorOnSurface"
        android:background="?android:selectableItemBackgroundBorderless"
        android:contentDescription="@string/close_button_text"
        android:src="@drawable/decor_close_button_dark"
        android:scaleType="fitCenter"
        android:gravity="end"
        android:background="@null"/>
        android:gravity="end"/>
</com.android.wm.shell.windowdecor.WindowDecorLinearLayout>
 No newline at end of file
+5 −3
Original line number Diff line number Diff line
@@ -14,7 +14,8 @@
  ~ limitations under the License.
  -->

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
    <ProgressBar
        android:id="@+id/progress_bar"
        style="?android:attr/progressBarStyleHorizontal"
@@ -30,7 +31,8 @@
        android:layout_height="40dp"
        android:padding="9dp"
        android:contentDescription="@string/maximize_button_text"
        android:tint="?androidprv:attr/materialColorOnSurface"
        android:background="?android:selectableItemBackgroundBorderless"
        android:src="@drawable/decor_desktop_mode_maximize_button_dark"
        android:scaleType="fitCenter"
        android:background="@drawable/rounded_button"/>
        android:scaleType="fitCenter" />
</merge>
 No newline at end of file
+28 −31
Original line number Diff line number Diff line
@@ -22,8 +22,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_HOVER_ENTER;
import static android.view.MotionEvent.ACTION_HOVER_EXIT;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.WindowInsets.Type.statusBars;

import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -59,7 +61,6 @@ import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.View;
import android.view.ViewConfiguration;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;

@@ -321,8 +322,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        private final GestureDetector mGestureDetector;

        private boolean mIsDragging;
        private boolean mTouchscreenInUse;
        private boolean mHasLongClicked;
        private boolean mShouldClick;
        private int mDragPointerId = -1;
        private final Runnable mCloseMaximizeWindowRunnable;

@@ -343,6 +344,10 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {

        @Override
        public void onClick(View v) {
            if (mIsDragging) {
                mIsDragging = false;
                return;
            }
            final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
            final int id = v.getId();
            if (id == R.id.close_window) {
@@ -421,6 +426,10 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        @Override
        public boolean onTouch(View v, MotionEvent e) {
            final int id = v.getId();
            if ((e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN) {
                mTouchscreenInUse = e.getActionMasked() != ACTION_UP
                        && e.getActionMasked() != ACTION_CANCEL;
            }
            if (id != R.id.caption_handle && id != R.id.desktop_mode_caption
                    && id != R.id.open_menu_button && id != R.id.close_window
                    && id != R.id.maximize_window) {
@@ -432,31 +441,19 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            if (!mHasLongClicked && id != R.id.maximize_window) {
                decoration.closeMaximizeMenuIfNeeded(e);
            }

            final long eventDuration = e.getEventTime() - e.getDownTime();
            final boolean isTouchScreen =
                    (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN;
            final boolean shouldLongClick = isTouchScreen && id == R.id.maximize_window
                    && !mIsDragging && !mHasLongClicked
                    && eventDuration >= ViewConfiguration.getLongPressTimeout();
            if (shouldLongClick) {
                v.performLongClick();
                mHasLongClicked = true;
                return true;
            }

            return mDragDetector.onMotionEvent(v, e);
        }

        @Override
        public boolean onLongClick(View v) {
            final int id = v.getId();
            if (id == R.id.maximize_window) {
            if (id == R.id.maximize_window && mTouchscreenInUse) {
                final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
                moveTaskToFront(decoration.mTaskInfo);
                if (decoration.isMaximizeMenuActive()) {
                    decoration.closeMaximizeMenu();
                } else {
                    mHasLongClicked = true;
                    decoration.createMaximizeMenu();
                }
                return true;
@@ -515,11 +512,9 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            if (mGestureDetector.onTouchEvent(e)) {
                return true;
            }
            if (e.getActionMasked() == MotionEvent.ACTION_CANCEL) {
                // If a motion event is cancelled, reset mShouldClick so a click is not accidentally
                // performed.
                mShouldClick = false;
            }
            final int id = v.getId();
            final boolean touchingButton = (id == R.id.close_window || id == R.id.maximize_window
                    || id == R.id.open_menu_button);
            switch (e.getActionMasked()) {
                case MotionEvent.ACTION_DOWN: {
                    mDragPointerId = e.getPointerId(0);
@@ -527,12 +522,12 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                            0 /* ctrlType */, e.getRawX(0),
                            e.getRawY(0));
                    mIsDragging = false;
                    mShouldClick = true;
                    mHasLongClicked = false;
                    return true;
                    // Do not consume input event if a button is touched, otherwise it would
                    // prevent the button's ripple effect from showing.
                    return !touchingButton;
                }
                case MotionEvent.ACTION_MOVE: {
                    mShouldClick = false;
                    // If a decor's resize drag zone is active, don't also try to reposition it.
                    if (decoration.isHandlingDragResize()) break;
                    decoration.closeMaximizeMenu();
@@ -553,11 +548,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                case MotionEvent.ACTION_CANCEL: {
                    final boolean wasDragging = mIsDragging;
                    if (!wasDragging) {
                        if (mShouldClick && v != null && !mHasLongClicked) {
                            v.performClick();
                            mShouldClick = false;
                            return true;
                        }
                        return false;
                    }
                    if (e.findPointerIndex(mDragPointerId) == -1) {
@@ -576,10 +566,17 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                            position,
                            new PointF(e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)),
                            newTaskBounds));
                    if (touchingButton && !mHasLongClicked) {
                        // We need the input event to not be consumed here to end the ripple
                        // effect on the touched button. We will reset drag state in the ensuing
                        // onClick call that results.
                        return false;
                    } else {
                        mIsDragging = false;
                        return true;
                    }
                }
            }
            return true;
        }