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

Commit 477243b0 authored by Vladislav Kaznacheev's avatar Vladislav Kaznacheev Committed by Android (Google) Code Review
Browse files

Merge "Update pointer icon when View.setPointerIcon is called" into nyc-dev

parents 68088812 989b58a6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -260,4 +260,6 @@ interface IWindowSession {
     * Returns true if the move started successfully; false otherwise.
     */
    boolean startMovingTask(IWindow window, float startX, float startY);

    void updatePointerIcon(IWindow window);
}
+7 −0
Original line number Diff line number Diff line
@@ -21581,6 +21581,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    public void setPointerIcon(PointerIcon pointerIcon) {
        mPointerIcon = pointerIcon;
        if (mAttachInfo == null) {
            return;
        }
        try {
            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
        } catch (RemoteException e) {
        }
    }
    /**
+6 −85
Original line number Diff line number Diff line
@@ -378,7 +378,9 @@ class DragState {

    private void cleanUpDragLw() {
        broadcastDragEndedLw();
        restorePointerIconLw();
        if (isFromSource(InputDevice.SOURCE_MOUSE)) {
            mService.restorePointerIconLocked(mDisplay, mCurrentX, mCurrentY);
        }

        // stop intercepting input
        unregister();
@@ -416,7 +418,7 @@ class DragState {

    void notifyLocationLw(float x, float y) {
        // Tell the affected window
        WindowState touchedWin = getTouchedWinAtPointLw(x, y);
        WindowState touchedWin = mService.getTouchableWinAtPointLocked(mDisplay, x, y);
        if (touchedWin == null) {
            if (DEBUG_DRAG) Slog.d(TAG_WM, "No touched win at x=" + x + " y=" + y);
            return;
@@ -461,10 +463,6 @@ class DragState {
        mTargetWindow = touchedWin;
    }

    WindowState getDropTargetWinLw(float x, float y) {
        return getTouchedWinAtPointLw(x, y);
    }

    // Tell the drop target about the data.  Returns 'true' if we can immediately
    // dispatch the global drag-ended message, 'false' if we need to wait for a
    // result from the recipient.
@@ -512,77 +510,17 @@ class DragState {
        return false;
    }

    // Find the visible, touch-deliverable window under the given point
    private WindowState getTouchedWinAtPointLw(float xf, float yf) {
        WindowState touchedWin = null;
        final int x = (int) xf;
        final int y = (int) yf;

        final WindowList windows = mService.getWindowListLocked(mDisplay);
        if (windows == null) {
            return null;
        }
        final int N = windows.size();
        for (int i = N - 1; i >= 0; i--) {
            WindowState child = windows.get(i);
            final int flags = child.mAttrs.flags;
            if (!child.isVisibleLw()) {
                // not visible == don't tell about drags
                continue;
            }
            if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
                // not touchable == don't tell about drags
                continue;
            }

            child.getVisibleBounds(mTmpRect);
            if (!mTmpRect.contains(x, y)) {
                // outside of this window's activity stack == don't tell about drags
                continue;
            }

            child.getTouchableRegion(mTmpRegion);

            final int touchFlags = flags &
                    (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
            if (mTmpRegion.contains(x, y) || touchFlags == 0) {
                // Found it
                touchedWin = child;
                break;
            }
        }

        return touchedWin;
    }

    private static DragEvent obtainDragEvent(WindowState win, int action,
            float x, float y, Object localState,
            ClipDescription description, ClipData data,
            IDropPermissions dropPermissions,
            boolean result) {
        final float winX = translateToWindowX(win, x);
        final float winY = translateToWindowY(win, y);
        final float winX = win.translateToWindowX(x);
        final float winY = win.translateToWindowY(y);
        return DragEvent.obtain(action, winX, winY, localState, description, data,
                dropPermissions, result);
    }

    private static float translateToWindowX(WindowState win, float x) {
        float winX = x - win.mFrame.left;
        if (win.mEnforceSizeCompat) {
            winX *= win.mGlobalScale;
        }
        return winX;
    }

    private static float translateToWindowY(WindowState win, float y) {
        float winY = y - win.mFrame.top;
        if (win.mEnforceSizeCompat) {
            winY *= win.mGlobalScale;
        }
        return winY;
    }

    boolean stepAnimationLocked(long currentTimeMs) {
        if (mAnimation == null) {
            return false;
@@ -638,21 +576,4 @@ class DragState {
            InputManager.getInstance().setPointerIconShape(PointerIcon.STYLE_GRAB);
        }
    }

    private void restorePointerIconLw() {
        if (isFromSource(InputDevice.SOURCE_MOUSE)) {
            WindowState touchWin = getTouchedWinAtPointLw(mCurrentX, mCurrentY);
            if (touchWin != null) {
                try {
                    touchWin.mClient.updatePointerIcon(
                            translateToWindowX(touchWin, mCurrentX),
                            translateToWindowY(touchWin, mCurrentY));
                    return;
                } catch (RemoteException e) {
                    Slog.w(TAG_WM, "unable to restore pointer icon");
                }
            }
            InputManager.getInstance().setPointerIconShape(PointerIcon.STYLE_DEFAULT);
        }
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -528,6 +528,16 @@ final class Session extends IWindowSession.Stub
        }
    }

    @Override
    public void updatePointerIcon(IWindow window) {
        final long identity = Binder.clearCallingIdentity();
        try {
            mService.updatePointerIcon(window);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    void windowAddedLocked() {
        if (mSurfaceSession == null) {
            if (WindowManagerService.localLOGV) Slog.v(
+128 −1
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.input.InputManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -81,6 +82,7 @@ import android.view.Choreographer;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.PointerIcon;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.IApplicationToken;
import android.view.IDockedStackListener;
@@ -466,6 +468,7 @@ public class WindowManagerService extends IWindowManager.Stub
    final float[] mTmpFloats = new float[9];
    final Rect mTmpRect = new Rect();
    final Rect mTmpRect2 = new Rect();
    final Region mTmpRegion = new Region();

    boolean mDisplayReady;
    boolean mSafeMode;
@@ -758,7 +761,7 @@ public class WindowManagerService extends IWindowManager.Stub
    }

    private boolean completeDropLw(float x, float y) {
        WindowState dropTargetWin = mDragState.getDropTargetWinLw(x, y);
        WindowState dropTargetWin = getTouchableWinAtPointLocked(mDragState.mDisplay, x, y);

        DropPermissionsHandler dropPermissions = null;
        if (dropTargetWin != null &&
@@ -10170,6 +10173,7 @@ public class WindowManagerService extends IWindowManager.Stub
        if (displayId == Display.DEFAULT_DISPLAY) {
            displayContent.mTapDetector = new TaskTapPointerEventListener(this, displayContent);
            registerPointerEventListener(displayContent.mTapDetector);
            registerPointerEventListener(mMousePositionTracker);
        }

        return displayContent;
@@ -10262,6 +10266,7 @@ public class WindowManagerService extends IWindowManager.Stub
            displayContent.close();
            if (displayId == Display.DEFAULT_DISPLAY) {
                unregisterPointerEventListener(displayContent.mTapDetector);
                unregisterPointerEventListener(mMousePositionTracker);
            }
        }
        mAnimator.removeDisplayLocked(displayId);
@@ -10461,6 +10466,128 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    /**
     * Find the visible, touch-deliverable window under the given point
     */
    WindowState getTouchableWinAtPointLocked(Display display, float xf, float yf) {
        WindowState touchedWin = null;
        final int x = (int) xf;
        final int y = (int) yf;

        final WindowList windows = getWindowListLocked(display);
        if (windows == null) {
            return null;
        }
        final int N = windows.size();
        for (int i = N - 1; i >= 0; i--) {
            WindowState child = windows.get(i);
            final int flags = child.mAttrs.flags;
            if (!child.isVisibleLw()) {
                continue;
            }
            if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
                continue;
            }

            child.getTouchableRegion(mTmpRegion);

            final int touchFlags = flags &
                    (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
            if (mTmpRegion.contains(x, y) || touchFlags == 0) {
                touchedWin = child;
                break;
            }
        }

        return touchedWin;
    }

    private MousePositionTracker mMousePositionTracker = new MousePositionTracker();

    private static class MousePositionTracker implements PointerEventListener {
        private boolean mLatestEventWasMouse;
        private float mLatestMouseX;
        private float mLatestMouseY;

        void updatePosition(float x, float y) {
            synchronized (this) {
                mLatestEventWasMouse = true;
                mLatestMouseX = x;
                mLatestMouseY = y;
            }
        }

        @Override
        public void onPointerEvent(MotionEvent motionEvent) {
            if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) {
                updatePosition(motionEvent.getRawX(), motionEvent.getRawY());
            } else {
                synchronized (this) {
                    mLatestEventWasMouse = false;
                }
            }
        }
    };

    void updatePointerIcon(IWindow client) {
        float mouseX, mouseY;

        synchronized(mMousePositionTracker) {
            if (!mMousePositionTracker.mLatestEventWasMouse) {
                return;
            }
            mouseX = mMousePositionTracker.mLatestMouseX;
            mouseY = mMousePositionTracker.mLatestMouseY;
        }

        synchronized (mWindowMap) {
            if (mDragState != null) {
                // Drag cursor overrides the app cursor.
                return;
            }
            WindowState callingWin = windowForClientLocked(null, client, false);
            if (callingWin == null) {
                Slog.w(TAG_WM, "Bad requesting window " + client);
                return;
            }
            final DisplayContent displayContent = callingWin.getDisplayContent();
            if (displayContent == null) {
                return;
            }
            Display display = displayContent.getDisplay();
            WindowState windowUnderPointer = getTouchableWinAtPointLocked(display, mouseX, mouseY);
            if (windowUnderPointer != callingWin) {
                return;
            }
            try {
                windowUnderPointer.mClient.updatePointerIcon(
                        windowUnderPointer.translateToWindowX(mouseX),
                        windowUnderPointer.translateToWindowY(mouseY));
            } catch (RemoteException e) {
                Slog.w(TAG_WM, "unable to update pointer icon");
            }
        }
    }

    void restorePointerIconLocked(Display display, float latestX, float latestY) {
        // Mouse position tracker has not been getting updates while dragging, update it now.
        mMousePositionTracker.updatePosition(latestX, latestY);

        WindowState windowUnderPointer = getTouchableWinAtPointLocked(display, latestX, latestY);
        if (windowUnderPointer != null) {
            try {
                windowUnderPointer.mClient.updatePointerIcon(
                        windowUnderPointer.translateToWindowX(latestX),
                        windowUnderPointer.translateToWindowY(latestY));
            } catch (RemoteException e) {
                Slog.w(TAG_WM, "unable to restore pointer icon");
            }
        } else {
            InputManager.getInstance().setPointerIconShape(PointerIcon.STYLE_DEFAULT);
        }
    }

    private final class LocalService extends WindowManagerInternal {
        @Override
        public void requestTraversalFromDisplayManager() {
Loading