Loading core/java/android/view/PointerIcon.java +50 −4 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.graphics.RectF; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; Loading Loading @@ -144,7 +145,8 @@ public final class PointerIcon implements Parcelable { public static final int TYPE_DEFAULT = TYPE_ARROW; private static final PointerIcon gNullIcon = new PointerIcon(TYPE_NULL); private static final SparseArray<PointerIcon> gSystemIcons = new SparseArray<PointerIcon>(); private static final SparseArray<SparseArray<PointerIcon>> gSystemIconsByDisplay = new SparseArray<SparseArray<PointerIcon>>(); private static boolean sUseLargeIcons = false; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) Loading @@ -163,6 +165,12 @@ public final class PointerIcon implements Parcelable { @UnsupportedAppUsage private int mDurationPerFrame; /** * Listener for displays lifecycle. * @hide */ private static DisplayManager.DisplayListener sDisplayListener; private PointerIcon(int type) { mType = type; } Loading Loading @@ -211,7 +219,19 @@ public final class PointerIcon implements Parcelable { return gNullIcon; } PointerIcon icon = gSystemIcons.get(type); if (sDisplayListener == null) { registerDisplayListener(context); } final int displayId = context.getDisplayId(); SparseArray<PointerIcon> systemIcons = gSystemIconsByDisplay.get(displayId); if (systemIcons == null) { systemIcons = new SparseArray<>(); gSystemIconsByDisplay.put(displayId, systemIcons); } PointerIcon icon = systemIcons.get(type); // Reload if not in the same display. if (icon != null) { return icon; } Loading Loading @@ -240,7 +260,7 @@ public final class PointerIcon implements Parcelable { } else { icon.loadResource(context, context.getResources(), resourceId); } gSystemIcons.append(type, icon); systemIcons.append(type, icon); return icon; } Loading @@ -250,7 +270,7 @@ public final class PointerIcon implements Parcelable { */ public static void setUseLargeIcons(boolean use) { sUseLargeIcons = use; gSystemIcons.clear(); gSystemIconsByDisplay.clear(); } /** Loading Loading @@ -576,4 +596,30 @@ public final class PointerIcon implements Parcelable { return 0; } } /** * Manage system icon cache handled by display lifecycle. * @param context The context. */ private static void registerDisplayListener(@NonNull Context context) { sDisplayListener = new DisplayManager.DisplayListener() { @Override public void onDisplayAdded(int displayId) { } @Override public void onDisplayRemoved(int displayId) { gSystemIconsByDisplay.remove(displayId); } @Override public void onDisplayChanged(int displayId) { gSystemIconsByDisplay.remove(displayId); } }; DisplayManager displayManager = context.getSystemService(DisplayManager.class); displayManager.registerDisplayListener(sDisplayListener, null /* handler */); } } libs/input/PointerController.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -255,7 +255,7 @@ void PointerController::setPresentation(Presentation presentation) { if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) { mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources, &mLocked.animationResources); &mLocked.animationResources, mLocked.viewport.displayId); } if (mLocked.presentation != presentation) { Loading Loading @@ -727,14 +727,14 @@ void PointerController::fadeOutAndReleaseAllSpotsLocked() { } void PointerController::loadResourcesLocked() REQUIRES(mLock) { mPolicy->loadPointerResources(&mResources); mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId); if (mLocked.presentation == PRESENTATION_POINTER) { mLocked.additionalMouseResources.clear(); mLocked.animationResources.clear(); mPolicy->loadPointerIcon(&mLocked.pointerIcon); mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId); mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources, &mLocked.animationResources); &mLocked.animationResources, mLocked.viewport.displayId); } mLocked.pointerIconChanged = true; Loading libs/input/PointerController.h +3 −3 Original line number Diff line number Diff line Loading @@ -62,10 +62,10 @@ protected: virtual ~PointerControllerPolicyInterface() { } public: virtual void loadPointerIcon(SpriteIcon* icon) = 0; virtual void loadPointerResources(PointerResources* outResources) = 0; virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) = 0; virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) = 0; virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources, std::map<int32_t, PointerAnimation>* outAnimationResources) = 0; std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) = 0; virtual int32_t getDefaultPointerIconId() = 0; virtual int32_t getCustomPointerIconId() = 0; }; Loading services/core/java/com/android/server/input/InputManagerService.java +22 −2 Original line number Diff line number Diff line Loading @@ -138,6 +138,9 @@ public class InputManagerService extends IInputManager.Stub private final Context mContext; private final InputManagerHandler mHandler; // Context cache used for loading pointer resources. private Context mDisplayContext; private final File mDoubleTouchGestureEnableFile; private WindowManagerCallbacks mWindowManagerCallbacks; Loading Loading @@ -1923,8 +1926,25 @@ public class InputManagerService extends IInputManager.Stub } // Native callback. private PointerIcon getPointerIcon() { return PointerIcon.getDefaultIcon(mContext); private PointerIcon getPointerIcon(int displayId) { return PointerIcon.getDefaultIcon(getContextForDisplay(displayId)); } private Context getContextForDisplay(int displayId) { if (mDisplayContext != null && mDisplayContext.getDisplay().getDisplayId() == displayId) { return mDisplayContext; } if (mContext.getDisplay().getDisplayId() == displayId) { mDisplayContext = mContext; return mDisplayContext; } // Create and cache context for non-default display. final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class); final Display display = displayManager.getDisplay(displayId); mDisplayContext = mContext.createDisplayContext(display); return mDisplayContext; } // Native callback. Loading services/core/java/com/android/server/wm/TaskTapPointerEventListener.java +19 −3 Original line number Diff line number Diff line Loading @@ -31,6 +31,10 @@ import android.view.WindowManagerPolicyConstants.PointerEventListener; import com.android.server.wm.WindowManagerService.H; /** * 1. Adjust the top most focus display if touch down on some display. * 2. Adjust the pointer icon when cursor moves to the task bounds. */ public class TaskTapPointerEventListener implements PointerEventListener { private final Region mTouchExcludeRegion = new Region(); Loading Loading @@ -80,8 +84,7 @@ public class TaskTapPointerEventListener implements PointerEventListener { if (motionEvent.getDisplayId() != getDisplayId()) { return; } final int action = motionEvent.getAction(); switch (action & MotionEvent.ACTION_MASK) { switch (motionEvent.getActionMasked()) { case MotionEvent.ACTION_DOWN: { final int x = (int) motionEvent.getX(); final int y = (int) motionEvent.getY(); Loading @@ -97,7 +100,7 @@ public class TaskTapPointerEventListener implements PointerEventListener { } } break; case MotionEvent.ACTION_HOVER_ENTER: case MotionEvent.ACTION_HOVER_MOVE: { final int x = (int) motionEvent.getX(); final int y = (int) motionEvent.getY(); Loading Loading @@ -125,6 +128,7 @@ public class TaskTapPointerEventListener implements PointerEventListener { mPointerIconType = iconType; if (mPointerIconType == TYPE_NOT_SPECIFIED) { // Find the underlying window and ask it restore the pointer icon. mService.mH.removeMessages(H.RESTORE_POINTER_ICON); mService.mH.obtainMessage(H.RESTORE_POINTER_ICON, x, y, mDisplayContent).sendToTarget(); } else { Loading @@ -133,6 +137,18 @@ public class TaskTapPointerEventListener implements PointerEventListener { } } break; case MotionEvent.ACTION_HOVER_EXIT: { final int x = (int) motionEvent.getX(); final int y = (int) motionEvent.getY(); if (mPointerIconType != TYPE_NOT_SPECIFIED) { mPointerIconType = TYPE_NOT_SPECIFIED; // Find the underlying window and ask it to restore the pointer icon. mService.mH.removeMessages(H.RESTORE_POINTER_ICON); mService.mH.obtainMessage(H.RESTORE_POINTER_ICON, x, y, mDisplayContent).sendToTarget(); } } break; } } Loading Loading
core/java/android/view/PointerIcon.java +50 −4 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.graphics.RectF; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; Loading Loading @@ -144,7 +145,8 @@ public final class PointerIcon implements Parcelable { public static final int TYPE_DEFAULT = TYPE_ARROW; private static final PointerIcon gNullIcon = new PointerIcon(TYPE_NULL); private static final SparseArray<PointerIcon> gSystemIcons = new SparseArray<PointerIcon>(); private static final SparseArray<SparseArray<PointerIcon>> gSystemIconsByDisplay = new SparseArray<SparseArray<PointerIcon>>(); private static boolean sUseLargeIcons = false; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) Loading @@ -163,6 +165,12 @@ public final class PointerIcon implements Parcelable { @UnsupportedAppUsage private int mDurationPerFrame; /** * Listener for displays lifecycle. * @hide */ private static DisplayManager.DisplayListener sDisplayListener; private PointerIcon(int type) { mType = type; } Loading Loading @@ -211,7 +219,19 @@ public final class PointerIcon implements Parcelable { return gNullIcon; } PointerIcon icon = gSystemIcons.get(type); if (sDisplayListener == null) { registerDisplayListener(context); } final int displayId = context.getDisplayId(); SparseArray<PointerIcon> systemIcons = gSystemIconsByDisplay.get(displayId); if (systemIcons == null) { systemIcons = new SparseArray<>(); gSystemIconsByDisplay.put(displayId, systemIcons); } PointerIcon icon = systemIcons.get(type); // Reload if not in the same display. if (icon != null) { return icon; } Loading Loading @@ -240,7 +260,7 @@ public final class PointerIcon implements Parcelable { } else { icon.loadResource(context, context.getResources(), resourceId); } gSystemIcons.append(type, icon); systemIcons.append(type, icon); return icon; } Loading @@ -250,7 +270,7 @@ public final class PointerIcon implements Parcelable { */ public static void setUseLargeIcons(boolean use) { sUseLargeIcons = use; gSystemIcons.clear(); gSystemIconsByDisplay.clear(); } /** Loading Loading @@ -576,4 +596,30 @@ public final class PointerIcon implements Parcelable { return 0; } } /** * Manage system icon cache handled by display lifecycle. * @param context The context. */ private static void registerDisplayListener(@NonNull Context context) { sDisplayListener = new DisplayManager.DisplayListener() { @Override public void onDisplayAdded(int displayId) { } @Override public void onDisplayRemoved(int displayId) { gSystemIconsByDisplay.remove(displayId); } @Override public void onDisplayChanged(int displayId) { gSystemIconsByDisplay.remove(displayId); } }; DisplayManager displayManager = context.getSystemService(DisplayManager.class); displayManager.registerDisplayListener(sDisplayListener, null /* handler */); } }
libs/input/PointerController.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -255,7 +255,7 @@ void PointerController::setPresentation(Presentation presentation) { if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) { mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources, &mLocked.animationResources); &mLocked.animationResources, mLocked.viewport.displayId); } if (mLocked.presentation != presentation) { Loading Loading @@ -727,14 +727,14 @@ void PointerController::fadeOutAndReleaseAllSpotsLocked() { } void PointerController::loadResourcesLocked() REQUIRES(mLock) { mPolicy->loadPointerResources(&mResources); mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId); if (mLocked.presentation == PRESENTATION_POINTER) { mLocked.additionalMouseResources.clear(); mLocked.animationResources.clear(); mPolicy->loadPointerIcon(&mLocked.pointerIcon); mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId); mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources, &mLocked.animationResources); &mLocked.animationResources, mLocked.viewport.displayId); } mLocked.pointerIconChanged = true; Loading
libs/input/PointerController.h +3 −3 Original line number Diff line number Diff line Loading @@ -62,10 +62,10 @@ protected: virtual ~PointerControllerPolicyInterface() { } public: virtual void loadPointerIcon(SpriteIcon* icon) = 0; virtual void loadPointerResources(PointerResources* outResources) = 0; virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) = 0; virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) = 0; virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources, std::map<int32_t, PointerAnimation>* outAnimationResources) = 0; std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) = 0; virtual int32_t getDefaultPointerIconId() = 0; virtual int32_t getCustomPointerIconId() = 0; }; Loading
services/core/java/com/android/server/input/InputManagerService.java +22 −2 Original line number Diff line number Diff line Loading @@ -138,6 +138,9 @@ public class InputManagerService extends IInputManager.Stub private final Context mContext; private final InputManagerHandler mHandler; // Context cache used for loading pointer resources. private Context mDisplayContext; private final File mDoubleTouchGestureEnableFile; private WindowManagerCallbacks mWindowManagerCallbacks; Loading Loading @@ -1923,8 +1926,25 @@ public class InputManagerService extends IInputManager.Stub } // Native callback. private PointerIcon getPointerIcon() { return PointerIcon.getDefaultIcon(mContext); private PointerIcon getPointerIcon(int displayId) { return PointerIcon.getDefaultIcon(getContextForDisplay(displayId)); } private Context getContextForDisplay(int displayId) { if (mDisplayContext != null && mDisplayContext.getDisplay().getDisplayId() == displayId) { return mDisplayContext; } if (mContext.getDisplay().getDisplayId() == displayId) { mDisplayContext = mContext; return mDisplayContext; } // Create and cache context for non-default display. final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class); final Display display = displayManager.getDisplay(displayId); mDisplayContext = mContext.createDisplayContext(display); return mDisplayContext; } // Native callback. Loading
services/core/java/com/android/server/wm/TaskTapPointerEventListener.java +19 −3 Original line number Diff line number Diff line Loading @@ -31,6 +31,10 @@ import android.view.WindowManagerPolicyConstants.PointerEventListener; import com.android.server.wm.WindowManagerService.H; /** * 1. Adjust the top most focus display if touch down on some display. * 2. Adjust the pointer icon when cursor moves to the task bounds. */ public class TaskTapPointerEventListener implements PointerEventListener { private final Region mTouchExcludeRegion = new Region(); Loading Loading @@ -80,8 +84,7 @@ public class TaskTapPointerEventListener implements PointerEventListener { if (motionEvent.getDisplayId() != getDisplayId()) { return; } final int action = motionEvent.getAction(); switch (action & MotionEvent.ACTION_MASK) { switch (motionEvent.getActionMasked()) { case MotionEvent.ACTION_DOWN: { final int x = (int) motionEvent.getX(); final int y = (int) motionEvent.getY(); Loading @@ -97,7 +100,7 @@ public class TaskTapPointerEventListener implements PointerEventListener { } } break; case MotionEvent.ACTION_HOVER_ENTER: case MotionEvent.ACTION_HOVER_MOVE: { final int x = (int) motionEvent.getX(); final int y = (int) motionEvent.getY(); Loading Loading @@ -125,6 +128,7 @@ public class TaskTapPointerEventListener implements PointerEventListener { mPointerIconType = iconType; if (mPointerIconType == TYPE_NOT_SPECIFIED) { // Find the underlying window and ask it restore the pointer icon. mService.mH.removeMessages(H.RESTORE_POINTER_ICON); mService.mH.obtainMessage(H.RESTORE_POINTER_ICON, x, y, mDisplayContent).sendToTarget(); } else { Loading @@ -133,6 +137,18 @@ public class TaskTapPointerEventListener implements PointerEventListener { } } break; case MotionEvent.ACTION_HOVER_EXIT: { final int x = (int) motionEvent.getX(); final int y = (int) motionEvent.getY(); if (mPointerIconType != TYPE_NOT_SPECIFIED) { mPointerIconType = TYPE_NOT_SPECIFIED; // Find the underlying window and ask it to restore the pointer icon. mService.mH.removeMessages(H.RESTORE_POINTER_ICON); mService.mH.obtainMessage(H.RESTORE_POINTER_ICON, x, y, mDisplayContent).sendToTarget(); } } break; } } Loading