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

Commit ec6a447c authored by Vladislav Kaznacheev's avatar Vladislav Kaznacheev
Browse files

Restore correct mouse pointer after drag and drop

This CL introduces IWindow.updatePointerIcon method.
When the drag is complete, this method is called on the window
directly under the pointer.

Same method can be used in the future to update mouse pointer
when a window appears or disappears.

Bug: 24415739
Change-Id: Ia7b0522448cb3cd754da5e24696060d3b3bf2e50
parent ba761124
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -75,6 +75,11 @@ oneway interface IWindow {
     */
    void dispatchDragEvent(in DragEvent event);

    /**
     * Pointer icon events
     */
    void updatePointerIcon(float x, float y);

    /**
     * System chrome visibility changes
     */
+61 −24
Original line number Diff line number Diff line
@@ -3278,6 +3278,7 @@ public final class ViewRootImpl implements ViewParent,
    private final static int MSG_SYNTHESIZE_INPUT_EVENT = 24;
    private final static int MSG_DISPATCH_WINDOW_SHOWN = 25;
    private final static int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26;
    private final static int MSG_UPDATE_POINTER_ICON = 27;

    final class ViewRootHandler extends Handler {
        @Override
@@ -3327,6 +3328,8 @@ public final class ViewRootImpl implements ViewParent,
                    return "MSG_SYNTHESIZE_INPUT_EVENT";
                case MSG_DISPATCH_WINDOW_SHOWN:
                    return "MSG_DISPATCH_WINDOW_SHOWN";
                case MSG_UPDATE_POINTER_ICON:
                    return "MSG_UPDATE_POINTER_ICON";
            }
            return super.getMessageName(message);
        }
@@ -3568,6 +3571,10 @@ public final class ViewRootImpl implements ViewParent,
                IResultReceiver receiver = (IResultReceiver) msg.obj;
                handleRequestKeyboardShortcuts(receiver);
            } break;
            case MSG_UPDATE_POINTER_ICON: {
                MotionEvent event = (MotionEvent) msg.obj;
                resetPointerIcon(event);
            } break;
            }
        }
    }
@@ -4311,33 +4318,13 @@ public final class ViewRootImpl implements ViewParent,
                    mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
                }

                final float x = event.getX();
                final float y = event.getY();
                if (event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT
                        && x >= 0 && x < mView.getWidth() && y >= 0 && y < mView.getHeight()) {
                    PointerIcon pointerIcon = mView.getPointerIcon(event, x, y);
                    int pointerShape = (pointerIcon != null) ?
                            pointerIcon.getStyle() : PointerIcon.STYLE_DEFAULT;

                    final InputDevice inputDevice = event.getDevice();
                    if (inputDevice != null) {
                        if (mPointerIconShape != pointerShape) {
                            mPointerIconShape = pointerShape;
                            if (mPointerIconShape != PointerIcon.STYLE_CUSTOM) {
                                mCustomPointerIcon = null;
                                inputDevice.setPointerShape(pointerShape);
                            }
                        }
                        if (mPointerIconShape == PointerIcon.STYLE_CUSTOM &&
                                !pointerIcon.equals(mCustomPointerIcon)) {
                            mCustomPointerIcon = pointerIcon;
                            inputDevice.setCustomPointerIcon(mCustomPointerIcon);
                        }
                    }
                } else if (event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) {
                if (event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT) {
                    if (!updatePointerIcon(event) &&
                            event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) {
                        mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
                    }
                }
            }

            mAttachInfo.mUnbufferedDispatchRequested = false;
            final View eventTarget =
@@ -4373,6 +4360,38 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    private void resetPointerIcon(MotionEvent event) {
        mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
        updatePointerIcon(event);
    }

    private boolean updatePointerIcon(MotionEvent event) {
        final float x = event.getX();
        final float y = event.getY();
        if (x < 0 || x >= mView.getWidth() || y < 0 || y >= mView.getHeight()) {
            Slog.e(mTag, "updatePointerIcon called with position out of bounds");
            return false;
        }
        final PointerIcon pointerIcon = mView.getPointerIcon(event, x, y);
        final int pointerShape = (pointerIcon != null) ?
                pointerIcon.getStyle() : PointerIcon.STYLE_DEFAULT;

        if (mPointerIconShape != pointerShape) {
            mPointerIconShape = pointerShape;
            if (mPointerIconShape != PointerIcon.STYLE_CUSTOM) {
                mCustomPointerIcon = null;
                InputManager.getInstance().setPointerIconShape(pointerShape);
                return true;
            }
        }
        if (mPointerIconShape == PointerIcon.STYLE_CUSTOM &&
                !pointerIcon.equals(mCustomPointerIcon)) {
            mCustomPointerIcon = pointerIcon;
            InputManager.getInstance().setCustomPointerIcon(mCustomPointerIcon);
        }
        return true;
    }

    /**
     * Performs synthesis of new input events from unhandled input events.
     */
@@ -6391,6 +6410,16 @@ public final class ViewRootImpl implements ViewParent,
        mHandler.sendMessage(msg);
    }

    public void updatePointerIcon(float x, float y) {
        final int what = MSG_UPDATE_POINTER_ICON;
        mHandler.removeMessages(what);
        final long now = SystemClock.uptimeMillis();
        final MotionEvent event = MotionEvent.obtain(
                0, now, MotionEvent.ACTION_HOVER_MOVE, x, y, 0);
        Message msg = mHandler.obtainMessage(what, event);
        mHandler.sendMessage(msg);
    }

    public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
            int localValue, int localChanges) {
        SystemUiVisibilityInfo args = new SystemUiVisibilityInfo();
@@ -6968,6 +6997,14 @@ public final class ViewRootImpl implements ViewParent,
            }
        }

        @Override
        public void updatePointerIcon(float x, float y) {
            final ViewRootImpl viewAncestor = mViewAncestor.get();
            if (viewAncestor != null) {
                viewAncestor.updatePointerIcon(x, y);
            }
        }

        @Override
        public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
                int localValue, int localChanges) {
+4 −0
Original line number Diff line number Diff line
@@ -85,6 +85,10 @@ public class BaseIWindow extends IWindow.Stub {
    public void dispatchDragEvent(DragEvent event) {
    }

    @Override
    public void updatePointerIcon(float x, float y) {
    }

    @Override
    public void dispatchSystemUiVisibilityChanged(int seq, int globalUi,
            int localValue, int localChanges) {
+26 −3
Original line number Diff line number Diff line
@@ -524,14 +524,26 @@ class DragState {
            ClipDescription description, ClipData data,
            IDropPermissions dropPermissions,
            boolean result) {
        final float winX = translateToWindowX(win, x);
        final float winY = translateToWindowY(win, 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;
        float winY = y - win.mFrame.top;
        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 DragEvent.obtain(action, winX, winY, localState, description, data,
                dropPermissions, result);
        return winY;
    }

    boolean stepAnimationLocked(long currentTimeMs) {
@@ -592,6 +604,17 @@ class DragState {

    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);
        }
    }