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

Commit 59934bee authored by Chavi Weingarten's avatar Chavi Weingarten Committed by Android (Google) Code Review
Browse files

Merge "Add onPointerDownOutsideFocus for events outside the focused window (4/4)"

parents c6d74601 fa2f004f
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1846,6 +1846,7 @@ public class InputManagerService extends IInputManager.Stub

    // Native callback.
    private void onPointerDownOutsideFocus(IBinder touchedToken) {
        mWindowManagerCallbacks.onPointerDownOutsideFocus(touchedToken);
    }

    // Native callback.
@@ -2060,6 +2061,14 @@ public class InputManagerService extends IInputManager.Stub
        public int getPointerLayer();

        public int getPointerDisplayId();

        /**
         * Notifies window manager that a {@link android.view.MotionEvent#ACTION_DOWN} pointer event
         * occurred on a window that did not have focus.
         *
         * @param touchedToken The token for the window that received the input event.
         */
        void onPointerDownOutsideFocus(IBinder touchedToken);
    }

    /**
+6 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.ON_POINTER_DOWN_OUTSIDE_FOCUS;

import android.os.Debug;
import android.os.IBinder;
@@ -232,6 +233,11 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
        }
    }

    @Override
    public void onPointerDownOutsideFocus(IBinder touchedToken) {
        mService.mH.obtainMessage(ON_POINTER_DOWN_OUTSIDE_FOCUS, touchedToken).sendToTarget();
    }

    /** Waits until the built-in input devices have been configured. */
    public boolean waitForInputDevicesReady(long timeoutMillis) {
        synchronized (mInputDevicesReadyMonitor) {
+0 −71
Original line number Diff line number Diff line
@@ -22,12 +22,9 @@ import static android.view.PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW;
import static android.view.PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW;
import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;

import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;

import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.WindowManagerPolicyConstants.PointerEventListener;

@@ -40,67 +37,15 @@ import com.android.server.wm.WindowManagerService.H;
public class TaskTapPointerEventListener implements PointerEventListener {

    private final Region mTouchExcludeRegion = new Region();
    private final Region mTmpRegion = new Region();
    private final WindowManagerService mService;
    private final DisplayContent mDisplayContent;
    private final Handler mHandler;
    private final Runnable mMoveDisplayToTop;
    private final Rect mTmpRect = new Rect();
    private int mPointerIconType = TYPE_NOT_SPECIFIED;
    private int mLastDownX;
    private int mLastDownY;

    public TaskTapPointerEventListener(WindowManagerService service,
            DisplayContent displayContent) {
        mService = service;
        mDisplayContent = displayContent;
        mHandler = new Handler(mService.mH.getLooper());
        mMoveDisplayToTop = () -> {
            int x;
            int y;
            synchronized (this) {
                x = mLastDownX;
                y = mLastDownY;
            }
            synchronized (mService.mGlobalLock) {
                if (!mService.mPerDisplayFocusEnabled
                        && mService.mRoot.getTopFocusedDisplayContent() != mDisplayContent
                        && inputMethodWindowContains(x, y)) {
                    // In a single focus system, if the input method window and the input method
                    // target window are on the different displays, when the user is tapping on the
                    // input method window, we don't move its display to top. Otherwise, the input
                    // method target window will lose the focus.
                    return;
                }
                final Region windowTapExcludeRegion = Region.obtain();
                mDisplayContent.amendWindowTapExcludeRegion(windowTapExcludeRegion);
                if (windowTapExcludeRegion.contains(x, y)) {
                    windowTapExcludeRegion.recycle();
                    // The user is tapping on the window tap exclude region. We don't move this
                    // display to top. A window tap exclude region, for example, may be set by an
                    // ActivityView, and the region would match the bounds of both the ActivityView
                    // and the virtual display in it. In this case, we would take the tap that is on
                    // the embedded virtual display instead of this display.
                    return;
                }
                windowTapExcludeRegion.recycle();
                WindowContainer parent = mDisplayContent.getParent();
                if (parent != null && parent.getTopChild() != mDisplayContent) {
                    parent.positionChildAt(WindowContainer.POSITION_TOP, mDisplayContent,
                            true /* includingParents */);
                    // For compatibility, only the topmost activity is allowed to be resumed for
                    // pre-Q app. Ensure the topmost activities are resumed whenever a display is
                    // moved to top.
                    // TODO(b/123761773): Investigate whether we can move this into
                    // RootActivityContainer#updateTopResumedActivityIfNeeded(). Currently, it is
                    // risky to do so because it seems possible to resume activities as part of a
                    // larger transaction and it's too early to resume based on current order
                    // when performing updateTopResumedActivityIfNeeded().
                    mDisplayContent.mAcitvityDisplay.ensureActivitiesVisible(null /* starting */,
                            0 /* configChanges */, !PRESERVE_WINDOWS, true /* notifyClients */);
                }
            }
        };
    }

    @Override
@@ -115,9 +60,6 @@ public class TaskTapPointerEventListener implements PointerEventListener {
                        mService.mTaskPositioningController.handleTapOutsideTask(
                                mDisplayContent, x, y);
                    }
                    mLastDownX = x;
                    mLastDownY = y;
                    mHandler.post(mMoveDisplayToTop);
                }
            }
            break;
@@ -178,17 +120,4 @@ public class TaskTapPointerEventListener implements PointerEventListener {
           mTouchExcludeRegion.set(newRegion);
        }
    }

    private int getDisplayId() {
        return mDisplayContent.getDisplayId();
    }

    private boolean inputMethodWindowContains(int x, int y) {
        final WindowState inputMethodWindow = mDisplayContent.mInputMethodWindow;
        if (inputMethodWindow == null || !inputMethodWindow.isVisibleLw()) {
            return false;
        }
        inputMethodWindow.getTouchableRegion(mTmpRegion);
        return mTmpRegion.contains(x, y);
    }
}
+42 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN;
import static com.android.server.LockGuard.INDEX_WINDOW;
import static com.android.server.LockGuard.installLock;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
@@ -4519,6 +4520,7 @@ public class WindowManagerService extends IWindowManager.Stub
        public static final int SET_RUNNING_REMOTE_ANIMATION = 59;
        public static final int ANIMATION_FAILSAFE = 60;
        public static final int RECOMPUTE_FOCUS = 61;
        public static final int ON_POINTER_DOWN_OUTSIDE_FOCUS = 62;

        /**
         * Used to denote that an integer field in a message will not be used.
@@ -4910,6 +4912,13 @@ public class WindowManagerService extends IWindowManager.Stub
                    }
                    break;
                }
                case ON_POINTER_DOWN_OUTSIDE_FOCUS: {
                    synchronized (mGlobalLock) {
                        final IBinder touchedToken = (IBinder) msg.obj;
                        onPointerDownOutsideFocusLocked(touchedToken);
                    }
                    break;
                }
            }
            if (DEBUG_WINDOW_TRACE) {
                Slog.v(TAG_WM, "handleMessage: exit");
@@ -7569,4 +7578,37 @@ public class WindowManagerService extends IWindowManager.Stub
            mGlobalLock.notifyAll();
        }
    }

    private void onPointerDownOutsideFocusLocked(IBinder touchedToken) {
        final WindowState touchedWindow = windowForClientLocked(null, touchedToken, false);
        if (touchedWindow == null) {
            return;
        }

        final DisplayContent displayContent = touchedWindow.getDisplayContent();
        if (displayContent == null) {
            return;
        }

        if (!touchedWindow.canReceiveKeys()) {
            // If the window that received the input event cannot receive keys, don't move the
            // display it's on to the top since that window won't be able to get focus anyway.
            return;
        }

        final WindowContainer parent = displayContent.getParent();
        if (parent != null && parent.getTopChild() != displayContent) {
            parent.positionChildAt(WindowContainer.POSITION_TOP, displayContent,
                    true /* includingParents */);
            // For compatibility, only the topmost activity is allowed to be resumed for pre-Q
            // app. Ensure the topmost activities are resumed whenever a display is moved to top.
            // TODO(b/123761773): Investigate whether we can move this into
            // RootActivityContainer#updateTopResumedActivityIfNeeded(). Currently, it is risky
            // to do so because it seems possible to resume activities as part of a larger
            // transaction and it's too early to resume based on current order when performing
            // updateTopResumedActivityIfNeeded().
            displayContent.mAcitvityDisplay.ensureActivitiesVisible(null /* starting */,
                    0 /* configChanges */, !PRESERVE_WINDOWS, true /* notifyClients */);
        }
    }
}