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

Commit b4013013 authored by Vladislav Kaznacheev's avatar Vladislav Kaznacheev Committed by android-build-merger
Browse files

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

am: 477243b0

* commit '477243b0':
  Update pointer icon when View.setPointerIcon is called
parents 59615d28 477243b0
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