From 1db5397d88e722b1ab82ccb2b429ceec1179ccd8 Mon Sep 17 00:00:00 2001 From: Jun Mukai Date: Fri, 11 Sep 2015 18:08:31 -0700 Subject: [PATCH] Allow changing mouse pointer icon for the current context. Right now, it only supports I-beam on EditText, but further rules will come in the future. The png files for the icons are from chromium. Bug: 24180385 Change-Id: I8de4ec8a5412b4830c08aa232c5083841c5c751c --- .../java/android/hardware/input/IInputManager.aidl | 2 + core/java/android/hardware/input/InputManager.java | 16 +++ core/java/android/view/InputDevice.java | 9 ++ core/java/android/view/PointerIcon.java | 115 ++++++++++++++++++++- core/java/android/view/View.java | 5 + core/java/android/view/ViewGroup.java | 30 ++++++ core/java/android/view/ViewRootImpl.java | 27 +++++ core/java/android/widget/TextView.java | 12 +++ core/jni/android_view_PointerIcon.h | 21 ++++ core/res/res/drawable-mdpi/pointer_alias.png | Bin 0 -> 517 bytes core/res/res/drawable-mdpi/pointer_all_scroll.png | Bin 0 -> 382 bytes core/res/res/drawable-mdpi/pointer_cell.png | Bin 0 -> 232 bytes .../res/res/drawable-mdpi/pointer_context_menu.png | Bin 0 -> 489 bytes core/res/res/drawable-mdpi/pointer_copy.png | Bin 0 -> 806 bytes core/res/res/drawable-mdpi/pointer_crosshair.png | Bin 0 -> 101 bytes core/res/res/drawable-mdpi/pointer_grab.png | Bin 0 -> 561 bytes core/res/res/drawable-mdpi/pointer_grabbing.png | Bin 0 -> 422 bytes core/res/res/drawable-mdpi/pointer_hand.png | Bin 0 -> 482 bytes core/res/res/drawable-mdpi/pointer_help.png | Bin 0 -> 630 bytes .../pointer_horizontal_double_arrow.png | Bin 0 -> 368 bytes core/res/res/drawable-mdpi/pointer_nodrop.png | Bin 0 -> 882 bytes core/res/res/drawable-mdpi/pointer_text.png | Bin 0 -> 163 bytes .../pointer_top_left_diagonal_double_arrow.png | Bin 0 -> 402 bytes .../pointer_top_right_diagonal_double_arrow.png | Bin 0 -> 404 bytes .../pointer_vertical_double_arrow.png | Bin 0 -> 381 bytes .../res/drawable-mdpi/pointer_vertical_text.png | Bin 0 -> 161 bytes core/res/res/drawable-mdpi/pointer_zoom_in.png | Bin 0 -> 530 bytes core/res/res/drawable-mdpi/pointer_zoom_out.png | Bin 0 -> 533 bytes core/res/res/drawable-xhdpi/pointer_alias.png | Bin 0 -> 1187 bytes core/res/res/drawable-xhdpi/pointer_all_scroll.png | Bin 0 -> 749 bytes core/res/res/drawable-xhdpi/pointer_cell.png | Bin 0 -> 467 bytes .../res/drawable-xhdpi/pointer_context_menu.png | Bin 0 -> 1057 bytes core/res/res/drawable-xhdpi/pointer_copy.png | Bin 0 -> 1817 bytes core/res/res/drawable-xhdpi/pointer_crosshair.png | Bin 0 -> 144 bytes core/res/res/drawable-xhdpi/pointer_grab.png | Bin 0 -> 1249 bytes core/res/res/drawable-xhdpi/pointer_grabbing.png | Bin 0 -> 883 bytes core/res/res/drawable-xhdpi/pointer_hand.png | Bin 0 -> 999 bytes core/res/res/drawable-xhdpi/pointer_help.png | Bin 0 -> 1483 bytes .../pointer_horizontal_double_arrow.png | Bin 0 -> 800 bytes core/res/res/drawable-xhdpi/pointer_nodrop.png | Bin 0 -> 1949 bytes core/res/res/drawable-xhdpi/pointer_text.png | Bin 0 -> 294 bytes .../pointer_top_left_diagonal_double_arrow.png | Bin 0 -> 808 bytes .../pointer_top_right_diagonal_double_arrow.png | Bin 0 -> 808 bytes .../pointer_vertical_double_arrow.png | Bin 0 -> 808 bytes .../res/drawable-xhdpi/pointer_vertical_text.png | Bin 0 -> 368 bytes core/res/res/drawable-xhdpi/pointer_zoom_in.png | Bin 0 -> 1255 bytes core/res/res/drawable-xhdpi/pointer_zoom_out.png | Bin 0 -> 1256 bytes core/res/res/drawable/pointer_alias_icon.xml | 5 + core/res/res/drawable/pointer_all_scroll_icon.xml | 5 + core/res/res/drawable/pointer_cell_icon.xml | 5 + .../res/res/drawable/pointer_context_menu_icon.xml | 5 + core/res/res/drawable/pointer_copy_icon.xml | 5 + core/res/res/drawable/pointer_crosshair_icon.xml | 5 + core/res/res/drawable/pointer_grab_icon.xml | 5 + core/res/res/drawable/pointer_grabbing_icon.xml | 5 + core/res/res/drawable/pointer_hand_icon.xml | 5 + core/res/res/drawable/pointer_help_icon.xml | 5 + .../pointer_horizontal_double_arrow_icon.xml | 5 + core/res/res/drawable/pointer_nodrop_icon.xml | 5 + core/res/res/drawable/pointer_text_icon.xml | 5 + ...pointer_top_left_diagonal_double_arrow_icon.xml | 5 + ...ointer_top_right_diagonal_double_arrow_icon.xml | 5 + .../pointer_vertical_double_arrow_icon.xml | 5 + .../res/drawable/pointer_vertical_text_icon.xml | 5 + core/res/res/drawable/pointer_zoom_in_icon.xml | 5 + core/res/res/drawable/pointer_zoom_out_icon.xml | 5 + core/res/res/values/attrs.xml | 38 +++++++ core/res/res/values/styles.xml | 27 +++++ libs/input/PointerController.cpp | 32 +++++- libs/input/PointerController.h | 9 +- .../android/server/input/InputManagerService.java | 7 ++ ...om_android_server_input_InputManagerService.cpp | 27 +++++ 72 files changed, 467 insertions(+), 5 deletions(-) create mode 100644 core/res/res/drawable-mdpi/pointer_alias.png create mode 100644 core/res/res/drawable-mdpi/pointer_all_scroll.png create mode 100644 core/res/res/drawable-mdpi/pointer_cell.png create mode 100644 core/res/res/drawable-mdpi/pointer_context_menu.png create mode 100644 core/res/res/drawable-mdpi/pointer_copy.png create mode 100644 core/res/res/drawable-mdpi/pointer_crosshair.png create mode 100644 core/res/res/drawable-mdpi/pointer_grab.png create mode 100644 core/res/res/drawable-mdpi/pointer_grabbing.png create mode 100644 core/res/res/drawable-mdpi/pointer_hand.png create mode 100644 core/res/res/drawable-mdpi/pointer_help.png create mode 100644 core/res/res/drawable-mdpi/pointer_horizontal_double_arrow.png create mode 100644 core/res/res/drawable-mdpi/pointer_nodrop.png create mode 100644 core/res/res/drawable-mdpi/pointer_text.png create mode 100644 core/res/res/drawable-mdpi/pointer_top_left_diagonal_double_arrow.png create mode 100644 core/res/res/drawable-mdpi/pointer_top_right_diagonal_double_arrow.png create mode 100644 core/res/res/drawable-mdpi/pointer_vertical_double_arrow.png create mode 100644 core/res/res/drawable-mdpi/pointer_vertical_text.png create mode 100644 core/res/res/drawable-mdpi/pointer_zoom_in.png create mode 100644 core/res/res/drawable-mdpi/pointer_zoom_out.png create mode 100644 core/res/res/drawable-xhdpi/pointer_alias.png create mode 100644 core/res/res/drawable-xhdpi/pointer_all_scroll.png create mode 100644 core/res/res/drawable-xhdpi/pointer_cell.png create mode 100644 core/res/res/drawable-xhdpi/pointer_context_menu.png create mode 100644 core/res/res/drawable-xhdpi/pointer_copy.png create mode 100644 core/res/res/drawable-xhdpi/pointer_crosshair.png create mode 100644 core/res/res/drawable-xhdpi/pointer_grab.png create mode 100644 core/res/res/drawable-xhdpi/pointer_grabbing.png create mode 100644 core/res/res/drawable-xhdpi/pointer_hand.png create mode 100644 core/res/res/drawable-xhdpi/pointer_help.png create mode 100644 core/res/res/drawable-xhdpi/pointer_horizontal_double_arrow.png create mode 100644 core/res/res/drawable-xhdpi/pointer_nodrop.png create mode 100644 core/res/res/drawable-xhdpi/pointer_text.png create mode 100644 core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow.png create mode 100644 core/res/res/drawable-xhdpi/pointer_top_right_diagonal_double_arrow.png create mode 100644 core/res/res/drawable-xhdpi/pointer_vertical_double_arrow.png create mode 100644 core/res/res/drawable-xhdpi/pointer_vertical_text.png create mode 100644 core/res/res/drawable-xhdpi/pointer_zoom_in.png create mode 100644 core/res/res/drawable-xhdpi/pointer_zoom_out.png create mode 100644 core/res/res/drawable/pointer_alias_icon.xml create mode 100644 core/res/res/drawable/pointer_all_scroll_icon.xml create mode 100644 core/res/res/drawable/pointer_cell_icon.xml create mode 100644 core/res/res/drawable/pointer_context_menu_icon.xml create mode 100644 core/res/res/drawable/pointer_copy_icon.xml create mode 100644 core/res/res/drawable/pointer_crosshair_icon.xml create mode 100644 core/res/res/drawable/pointer_grab_icon.xml create mode 100644 core/res/res/drawable/pointer_grabbing_icon.xml create mode 100644 core/res/res/drawable/pointer_hand_icon.xml create mode 100644 core/res/res/drawable/pointer_help_icon.xml create mode 100644 core/res/res/drawable/pointer_horizontal_double_arrow_icon.xml create mode 100644 core/res/res/drawable/pointer_nodrop_icon.xml create mode 100644 core/res/res/drawable/pointer_text_icon.xml create mode 100644 core/res/res/drawable/pointer_top_left_diagonal_double_arrow_icon.xml create mode 100644 core/res/res/drawable/pointer_top_right_diagonal_double_arrow_icon.xml create mode 100644 core/res/res/drawable/pointer_vertical_double_arrow_icon.xml create mode 100644 core/res/res/drawable/pointer_vertical_text_icon.xml create mode 100644 core/res/res/drawable/pointer_zoom_in_icon.xml create mode 100644 core/res/res/drawable/pointer_zoom_out_icon.xml diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl index c8b45c78c5b5..c6ae14ea9bc1 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -67,4 +67,6 @@ interface IInputManager { // Input device vibrator control. void vibrate(int deviceId, in long[] pattern, int repeat, IBinder token); void cancelVibrate(int deviceId, IBinder token); + + void setPointerIconShape(int shapeId); } diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index bae5757b03a7..3949d97e4088 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -757,6 +757,22 @@ public final class InputManager { } } + /** + * Changes the mouse pointer's icon shape into the specified id. + * + * @param iconId The id of the pointer graphic, as a value between + * {@link PointerIcon.STYLE_ARROW} and {@link PointerIcon.STYLE_GRABBING}. + * + * @hide + */ + public void setPointerIconShape(int iconId) { + try { + mIm.setPointerIconShape(iconId); + } catch (RemoteException ex) { + // Do nothing. + } + } + private void populateInputDevicesLocked() { if (mInputDevicesChangedListener == null) { final InputDevicesChangedListener listener = new InputDevicesChangedListener(); diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index cc4598d16de9..bae51d3b9d1f 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -766,6 +766,15 @@ public final class InputDevice implements Parcelable { } /** + * Sets the current pointer shape. + * @param pointerShape the id of the pointer icon. + * @hide + */ + public void setPointerShape(int pointerShape) { + InputManager.getInstance().setPointerIconShape(pointerShape); + } + + /** * Provides information about the range of values for a particular {@link MotionEvent} axis. * * @see InputDevice#getMotionRange(int) diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java index cf35ce534a97..88e9a952f778 100644 --- a/core/java/android/view/PointerIcon.java +++ b/core/java/android/view/PointerIcon.java @@ -48,6 +48,12 @@ public final class PointerIcon implements Parcelable { /** Style constant: Null icon. It has no bitmap. */ public static final int STYLE_NULL = 0; + /** Style constant: no icons are specified. If all views uses this, then falls back + * to the default style, but this is helpful to distinguish a view explicitly want + * to have the default icon. + */ + public static final int STYLE_NOT_SPECIFIED = 1; + /** Style constant: Arrow icon. (Default mouse pointer) */ public static final int STYLE_ARROW = 1000; @@ -60,12 +66,74 @@ public final class PointerIcon implements Parcelable { /** {@hide} Style constant: Spot anchor icon for touchpads. */ public static final int STYLE_SPOT_ANCHOR = 2002; + // Style constants for additional predefined icons for mice. + /** Style constant: context-menu. */ + public static final int STYLE_CONTEXT_MENU = 1001; + + /** Style constant: hand. */ + public static final int STYLE_HAND = 1002; + + /** Style constant: help. */ + public static final int STYLE_HELP = 1003; + + /** Style constant: wait. */ + public static final int STYLE_WAIT = 1004; + + /** Style constant: cell. */ + public static final int STYLE_CELL = 1006; + + /** Style constant: crosshair. */ + public static final int STYLE_CROSSHAIR = 1007; + + /** Style constant: text. */ + public static final int STYLE_TEXT = 1008; + + /** Style constant: vertical-text. */ + public static final int STYLE_VERTICAL_TEXT = 1009; + + /** Style constant: alias (indicating an alias of/shortcut to something is + * to be created. */ + public static final int STYLE_ALIAS = 1010; + + /** Style constant: copy. */ + public static final int STYLE_COPY = 1011; + + /** Style constant: no-drop. */ + public static final int STYLE_NO_DROP = 1012; + + /** Style constant: all-scroll. */ + public static final int STYLE_ALL_SCROLL = 1013; + + /** Style constant: horizontal double arrow mainly for resizing. */ + public static final int STYLE_HORIZONTAL_DOUBLE_ARROW = 1014; + + /** Style constant: vertical double arrow mainly for resizing. */ + public static final int STYLE_VERTICAL_DOUBLE_ARROW = 1015; + + /** Style constant: diagonal double arrow -- top-right to bottom-left. */ + public static final int STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016; + + /** Style constant: diagonal double arrow -- top-left to bottom-right. */ + public static final int STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017; + + /** Style constant: zoom-in. */ + public static final int STYLE_ZOOM_IN = 1018; + + /** Style constant: zoom-out. */ + public static final int STYLE_ZOOM_OUT = 1019; + + /** Style constant: grab. */ + public static final int STYLE_GRAB = 1020; + + /** Style constant: grabbing. */ + public static final int STYLE_GRABBING = 1021; + // OEM private styles should be defined starting at this range to avoid // conflicts with any system styles that may be defined in the future. private static final int STYLE_OEM_FIRST = 10000; - // The default pointer icon. - private static final int STYLE_DEFAULT = STYLE_ARROW; + /** {@hide} The default pointer icon. */ + public static final int STYLE_DEFAULT = STYLE_ARROW; private static final PointerIcon gNullIcon = new PointerIcon(STYLE_NULL); @@ -434,6 +502,49 @@ public final class PointerIcon implements Parcelable { return com.android.internal.R.styleable.Pointer_pointerIconSpotTouch; case STYLE_SPOT_ANCHOR: return com.android.internal.R.styleable.Pointer_pointerIconSpotAnchor; + case STYLE_HAND: + return com.android.internal.R.styleable.Pointer_pointerIconHand; + case STYLE_CONTEXT_MENU: + return com.android.internal.R.styleable.Pointer_pointerIconContextMenu; + case STYLE_HELP: + return com.android.internal.R.styleable.Pointer_pointerIconHelp; + case STYLE_WAIT: + // falls back to the default icon because no animation support. + return com.android.internal.R.styleable.Pointer_pointerIconArrow; + case STYLE_CELL: + return com.android.internal.R.styleable.Pointer_pointerIconCell; + case STYLE_CROSSHAIR: + return com.android.internal.R.styleable.Pointer_pointerIconCrosshair; + case STYLE_TEXT: + return com.android.internal.R.styleable.Pointer_pointerIconText; + case STYLE_VERTICAL_TEXT: + return com.android.internal.R.styleable.Pointer_pointerIconVerticalText; + case STYLE_ALIAS: + return com.android.internal.R.styleable.Pointer_pointerIconAlias; + case STYLE_COPY: + return com.android.internal.R.styleable.Pointer_pointerIconCopy; + case STYLE_ALL_SCROLL: + return com.android.internal.R.styleable.Pointer_pointerIconAllScroll; + case STYLE_NO_DROP: + return com.android.internal.R.styleable.Pointer_pointerIconNodrop; + case STYLE_HORIZONTAL_DOUBLE_ARROW: + return com.android.internal.R.styleable.Pointer_pointerIconHorizontalDoubleArrow; + case STYLE_VERTICAL_DOUBLE_ARROW: + return com.android.internal.R.styleable.Pointer_pointerIconVerticalDoubleArrow; + case STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW: + return com.android.internal.R.styleable. + Pointer_pointerIconTopRightDiagonalDoubleArrow; + case STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW: + return com.android.internal.R.styleable. + Pointer_pointerIconTopLeftDiagonalDoubleArrow; + case STYLE_ZOOM_IN: + return com.android.internal.R.styleable.Pointer_pointerIconZoomIn; + case STYLE_ZOOM_OUT: + return com.android.internal.R.styleable.Pointer_pointerIconZoomOut; + case STYLE_GRAB: + return com.android.internal.R.styleable.Pointer_pointerIconGrab; + case STYLE_GRABBING: + return com.android.internal.R.styleable.Pointer_pointerIconGrabbing; default: return 0; } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 7752ed890dc0..4bc211220d36 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -20995,6 +20995,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } + /** @hide */ + public int getPointerShape(MotionEvent event, float x, float y) { + return PointerIcon.STYLE_NOT_SPECIFIED; + } + // // Properties // diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 475ce2feed50..44aabd2e739e 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -1715,6 +1715,36 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return false; } + /** @hide */ + @Override + public int getPointerShape(MotionEvent event, float x, float y) { + // Check what the child under the pointer says about the pointer. + final int childrenCount = mChildrenCount; + if (childrenCount != 0) { + final ArrayList preorderedList = buildOrderedChildList(); + final boolean customOrder = preorderedList == null + && isChildrenDrawingOrderEnabled(); + final View[] children = mChildren; + for (int i = childrenCount - 1; i >= 0; i--) { + final int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i; + final View child = (preorderedList == null) + ? children[childIndex] : preorderedList.get(childIndex); + PointF point = getLocalPoint(); + if (isTransformedTouchPointInView(x, y, child, point)) { + final int pointerShape = child.getPointerShape(event, point.x, point.y); + if (pointerShape != PointerIcon.STYLE_NOT_SPECIFIED) { + return pointerShape; + } + break; + } + } + } + + // The pointer is not a child or the child has no preferences, returning the default + // implementation. + return super.getPointerShape(event, x, y); + } + /** * {@inheritDoc} */ diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 3d10289ac8e9..13b6a42e8d02 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -37,6 +37,7 @@ import android.graphics.Region; import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; +import android.hardware.input.InputManager; import android.media.AudioManager; import android.os.Binder; import android.os.Build; @@ -324,6 +325,8 @@ public final class ViewRootImpl implements ViewParent, private long mFpsPrevTime = -1; private int mFpsNumFrames; + private int mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED; + /** * see {@link #playSoundEffect(int)} */ @@ -4168,6 +4171,30 @@ public final class ViewRootImpl implements ViewParent, private int processPointerEvent(QueuedInputEvent q) { final MotionEvent event = (MotionEvent)q.mEvent; + if (event.getPointerCount() == 1 + && event.isFromSource(InputDevice.SOURCE_MOUSE)) { + if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER + || event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) { + // Other apps or the window manager may change the icon shape outside of + // this app, therefore the icon shape has to be reset on enter/exit event. + mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED; + } + + final float x = event.getX(); + final float y = event.getY(); + if (x >= 0 && x < mView.getWidth() && y >= 0 && y < mView.getHeight()) { + int pointerShape = mView.getPointerShape(event, x, y); + if (pointerShape == PointerIcon.STYLE_NOT_SPECIFIED) { + pointerShape = PointerIcon.STYLE_DEFAULT; + } + + if (mPointerIconShape != pointerShape) { + mPointerIconShape = pointerShape; + event.getDevice().setPointerShape(pointerShape); + } + } + } + mAttachInfo.mUnbufferedDispatchRequested = false; boolean handled = mView.dispatchPointerEvent(event); if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) { diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 071205248c91..1aeb9c938c0c 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -116,6 +116,7 @@ import android.view.HapticFeedbackConstants; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.PointerIcon; import android.view.View; import android.view.ViewParent; import android.view.ViewStructure; @@ -5905,6 +5906,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mLayout != null ? mLayout.getHeight() : 0; } + /** + * @hide + */ + @Override + public int getPointerShape(MotionEvent event, float x, float y) { + if (isTextSelectable() || isTextEditable()) { + return PointerIcon.STYLE_TEXT; + } + return super.getPointerShape(event, x, y); + } + @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { // Note: If the IME is in fullscreen mode and IMS#mExtractEditText is in text action mode, diff --git a/core/jni/android_view_PointerIcon.h b/core/jni/android_view_PointerIcon.h index 3bfd64526ad6..86f288d0d711 100644 --- a/core/jni/android_view_PointerIcon.h +++ b/core/jni/android_view_PointerIcon.h @@ -31,6 +31,27 @@ enum { POINTER_ICON_STYLE_CUSTOM = -1, POINTER_ICON_STYLE_NULL = 0, POINTER_ICON_STYLE_ARROW = 1000, + POINTER_ICON_STYLE_CONTEXT_MENU = 1001, + POINTER_ICON_STYLE_HAND = 1002, + POINTER_ICON_STYLE_HELP = 1003, + POINTER_ICON_STYLE_WAIT = 1004, + POINTER_ICON_STYLE_CELL = 1006, + POINTER_ICON_STYLE_CROSSHAIR = 1007, + POINTER_ICON_STYLE_TEXT = 1008, + POINTER_ICON_STYLE_VERTICAL_TEXT = 1009, + POINTER_ICON_STYLE_ALIAS = 1010, + POINTER_ICON_STYLE_COPY = 1011, + POINTER_ICON_STYLE_NO_DROP = 1012, + POINTER_ICON_STYLE_ALL_SCROLL = 1013, + POINTER_ICON_STYLE_HORIZONTAL_DOUBLE_ARROW = 1014, + POINTER_ICON_STYLE_VERTICAL_DOUBLE_ARROW = 1015, + POINTER_ICON_STYLE_TOP_RIGHT_DOUBLE_ARROW = 1016, + POINTER_ICON_STYLE_TOP_LEFT_DOUBLE_ARROW = 1017, + POINTER_ICON_STYLE_ZOOM_IN = 1018, + POINTER_ICON_STYLE_ZOOM_OUT = 1019, + POINTER_ICON_STYLE_GRAB = 1020, + POINTER_ICON_STYLE_GRABBING = 1021, + POINTER_ICON_STYLE_SPOT_HOVER = 2000, POINTER_ICON_STYLE_SPOT_TOUCH = 2001, POINTER_ICON_STYLE_SPOT_ANCHOR = 2002, diff --git a/core/res/res/drawable-mdpi/pointer_alias.png b/core/res/res/drawable-mdpi/pointer_alias.png new file mode 100644 index 0000000000000000000000000000000000000000..8f61a39dd20970732c10e6602458a440f20e7c71 GIT binary patch literal 517 zcmV+g0{Z=lP)P000>X1ONa4Zs1Mm0005ZNklR6-O6CRr?USY$BZ zUnCNf+}Fwd7v0Xs&Y$-8YveG86BB!D#+NIE9C_NB!NyD{2G-k)LF8+yhXj4zdw3cP zBaN7hZr-a31!}k2Eia<|$Bbg8lVj@-4v4Smsp+ZxeobYq?J%LRD=KJk?au ztai0lkLIKuj8nZiSI84_W%YYFWYgBqQG9dL6ROMC#`^9?HR205$YUfC$WXxDS$5>8 z_v6W}%}-q+SHBl2kVz&6c_tR_HliOJs)S!n$k+2r*ceF!vW#(dXSpt->Iy_if4=4@ zW->7k=G?yOE6_J>ugpK~bt*z#aU3g|#QQ8RAy*%oOuoF+5DMZeNG1k0rB}78P;>C* znJ-6Z^%o}@Nh9%`cT0|l^R)7a5_UQ<$Wy$2`TbmT(9o<_2lMwi!&vGr@th+}aE=R< z!_MO}j*U5t7-Sj2p~Q)>B83Q$N@8SUVUrKbk&OTx@(c49CwJ3dFx3Y!00000NkvXX Hu0mjfOGN46 literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-mdpi/pointer_all_scroll.png b/core/res/res/drawable-mdpi/pointer_all_scroll.png new file mode 100644 index 0000000000000000000000000000000000000000..a897ef4799a4034bb836ad8e8006d769b8d00e4c GIT binary patch literal 382 zcmV-^0fGLBP)P000>X1ONa4Zs1Mm0003+Nkl+Rtk=FPS+E}Q~ZHy0);xrEx3}>5HxqAZ-!H2MO*I4c?6XU?Jc=I<4 z%Lo4qTp$?r3H~7jBB<;7x`smZo-l~dxi!|DbHt381i)!ytajQNd)g3^M1tSK1M(6{ zB7s1H$V%Y24~crhz*^T2fnkh!A|?#92UuV^5G=89q8=bBc{0QNMdp|}u@fM67)HJs z0f4$_0`EiUqMP)P000>X1ONa4Zs1Mm00025Nkl5Cta)Vi_yJMo1e-6G)Z+|E=5>;Sm<(JUFsb53D1~^)oLjPmzg0BpH#wBmufg zAYJ#62qQ`)U*=*8nK+^(ij+bcQ>v8uS4EYKnI@$%lYBj2=>|jN>OCuU@bz4!4yxyr zFN;ahVk~Uz#=)s#CkMN+vG~OTiArqA&)l;ROB2P000>X1ONa4Zs1Mm00057NkleAHZI)NWd>3egiG+v{ux{ zN(A2;3qgFT1X;-I5}Q48VFn&%81$TCV7Nb?2j&h!(25nd%|VdhHdk;Y71F}t38o%L z3&9j&GX8mqX^Q|yP$dK$0?(YZJN|gZBEZv=FqP=x5d`|u`3eF8StMm5AtMk8LkWvY zk{1U>N%E595*1`fOcSx_f2J7p>1ss(o>E60`<_N(QJ0}AA+w~0Uav9WD9fBKy38Uy zydhPzHGX-60Ymbl89f5dk~)f$x^!xH%#wpb56tfI?!{x+ShB9C6LehrqwE4_IK?sM znW5c4BG~#q-aRbzLa*+yNKT(QLODf6Deu_2w!dAz_W8*@p;hg?XFytPpFo`qq`j}J zE1bN$_G{ubr5}2Bkx>4rbu!JN{V%u9a)g|v(VLq>8yY<(C21mUW;agIr%Ouq{PqVu z)ZU-pkC??Z5r?NkpdInT(&pQD_phI0p0t^?NN^1KIqEP)P000>X1^@s6#OZ}&0008*NklHNFAF6BOH+iHI$gpiY}6bqCrbATS zy|J6+{6Q@7&I=d1wB)6LRoR@+V zgmYqIB9#A?M+SxxtYaVNaNdqYsX}GkQ&UsXbS@1683jbxpP89?#FAPIiF`e^%pK;Y zNdHEEe}B|YCL<#wVSJR8L=}Qhp-_n0+uL#Ir_bjjzu!*_3k$kgPvRe6(9X`z7Z$Wx zWuh=H=Ca4*p~J&NJWYZOpCIE#>Ogi zBr25(M92uGqf{ydA%(+XNMcN@xJ&-xr9@q+86q}iDRaNs#OG~yz0|Nt)ykWfJ;m9y* z{CV**UdLiF+mc`~2+33C0#jopQE)&U47*&eQZAP}RP000>X1ONa4Zs1Mm0005_Nkl4CO?|^ciHi+!bSe}FDT0HblQ5#nNW$~37K2AT9AWXDZwV^Rh zOOon(Bxyk`k-_ap0*Z7LjQ#2Z39oNf}b zxFD(7Au~~L=)N{JEv}I=V&{+~$J|9p>z(1NQ9rM5k}ik_1GwspyCj)nhEdKQkH&6A z{Z7;`OWILEOfhK0CB?%7IxSY2^V%(0)}lTy>4W$}*`5ME)uLL_4t1gT>djs8l>N4g zLyA*n{ZSOX*3UlVjJQG;AB+@uUe^!BrKOnUl+M97Ae`qG-9VS z%n{zsYE71HJ(2&58d;J!-Nbg9;00}D#R{_&8R&ociFOL9FhP}*QB87`5<_vHnC-Ne zkP(U$8KFRqL3~{3C5Bvl0#a7^_RBDWc3uAgmD1Dv62?s300000NkvXXu0mjfv+x45 literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-mdpi/pointer_grabbing.png b/core/res/res/drawable-mdpi/pointer_grabbing.png new file mode 100644 index 0000000000000000000000000000000000000000..9deb64cb108d19fd7568116733c84faa7ca98d4b GIT binary patch literal 422 zcmV;X0a^ZuP)P000>X1ONa4Zs1Mm0004PNklEh?NWwdVHF4#Y5f3N zm@17H`V9hM10oiJ3G5!(*SPZ>1NNR%|G4iyE_!u&Bcx*5>L!C2d}8LACdVihLVV2s ziAT(jnuf(~qO$nOC{+SHOg1q@RP$=;uWD*#NPQ}aGxAuLCI+8~W%hg2%B&?TYN)BI z_{{+kUW(WqzE5aXmgtiuyB2QfTEk+I5c5O~Axq=Bmvq>WlVeG9VvRUWViqcvH1$0H z)YV{|oJ$f;ww0YzamAoJC8U=ruYQ?HK8hnsMDF@I%6#6+BqL&-B7ytK0Yzq_hhK7Y zA#NBU?|w3PcFwmQx!Dt6Nr*8nF@zME^y}v-aHmp(5B6EO1U$MJV3R*6)i0FE;bjp+ zK!Gx2)R@ASN#0Z89UP000>X1ONa4Zs1Mm00050NklUQNcni1rfBcva{7HjiOlj z9kj3$L{XgQxUG#&FvK+5x@x+1&m$cdaRXsA_9i%;Am z#%>Tp#KIx1NLrL5_j7V1hnMt0Gh&_yvq2J0cUG6QmTM~JnWU5AJc&>0O!DNM{z&?! za(<~XWR}z?5n~K^b63@QA>Omse+4WJGEUj$ca`L(Sfow7dE^>Rrg(6*lJvwy#t41l zRvYJd{PSZ8ycJ9IX!;|&SW>z?y#3M2iOp&+|=7KM;Fu= YU-+8Dr0@lwH~;_u07*qoM6N<$g44d&I{*Lx literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-mdpi/pointer_help.png b/core/res/res/drawable-mdpi/pointer_help.png new file mode 100644 index 0000000000000000000000000000000000000000..d54b2b109bbdef144b79a5bdb6c0545e5e0fee92 GIT binary patch literal 630 zcmV-+0*U>JP)P000>X1ONa4Zs1Mm0006#Nkl6vyG;y?5@Nt253xQ7Rionc;fkD)?N`?`waT-nUzjQz^cbNZKyqovo91aH|FqTUAt8x&SSkoO? zm_Z^iFtKq6;}F8c5C}rJUg1Y4VLt-E#2(&}fB1L8D=cJY`a2_77zi9{rF`MjQ9lB} zdfVm|ud7Y2wrfba0bEQ3E-7h$00Cf=oE<%-le(q`HECgrIH3}0knkZt89MJNH@-N3 zN>%daNa2)7S|We|2oZ~Kd~!B7_CS_;G&M|$@G1!)01RAG?=B6>&_(^p-Z)4SJ3vZk z>{tm2Y!aD!{o0`U{JBFk5yA42awG^*o4GGZ#Yr}kz{UuWAi^e@ec7WLP3q=eBA6mb zf++l-yttyYvfjWhsxX4297RanYR^wBo!Xi#r1vxzh*YH_hJ z@MY!3diCqu;jYim`h~jn`y=&4adEIPp`6r9vtPSA*m3pvPtQ?E8NE7yi{ZO!R4NdJ zSzG*aW)JI0)0%sKTBuLCr$jL;5t~@wHd4fiQuq48s2*u{F8i1mRwZKLP>qYdgqvHZ zKaAWyv5!Wgm5G6gg}MB?BxznAF^*GtFn=suqSR2m1pLdbOiCRs|MwvI2a*k;vc@iQ Q%m4rY07*qoM6N<$g1Xop#Q*>R literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-mdpi/pointer_horizontal_double_arrow.png b/core/res/res/drawable-mdpi/pointer_horizontal_double_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..a2951a9ef0770a3966dbde283e5f4ba291c8b88d GIT binary patch literal 368 zcmV-$0gwKPP)P000>X1ONa4Zs1Mm0003uNklX)SF+_&0RGfwD82Fp)TrRAiS)F3RXGcj2sez{JcInDi8w;1kPItImo|zx#SpO&g?S5!~eX+cMOc%-Z4=SE{8iygztz?w6n`0p`s!R=A)Gr zp+Uuw3JsCm&PR%hD9CLpBE&?FM8qPg*jy3753qSEe3K4MqM}VYB9st72_UDTga8b| zB6Z-mI}mjuWF O0000P000>X1^@s6#OZ}&0009yNklpLVR&$9l!{P7EoMboB)u4+4FT9FS!5G?=!cc-B76^e}nLihK6Lu9C zL>h+SmAlY+p%-Ha3-LlWof~ZqH#ggPd*8#$VYqcX7`^at_`ZER&-?S8D*&Jgj$-=) zBIY3!oVl!oUsy6fKW{!bICvV1#oY9qo13eqeG>kYgaxIMNMz_Nolb-n7a=%34fLe- z(b3T`{Z69GNEE^T{{Ch^ zqKZP_zDabB&TEkfdFT*hFc^FtoSK4-zCO7E60k^KZ}jxQ&zTts&v{T%t|C!hT82DC z?vns~@KM_xXG;P*R~L5n151+wD+aUr&dASu7T4 zY;1&hG@4t+=g!0gq*AFES0vAf_Oq!}vb(#xRjm>M(IfYaMkBQVGMNmZj9v)ga2Q5M zM?vj&t*@`YL4l=kCfp(xJV9QXOeWxf&dyHAX0s5F$HD1z!rtBX?>nJ&((CoU zr34XEk=v!r;8ROW3v_jLLB3=huV*foqdCCf;2`Yo?tV{Cz zfZQthPPmF|$m8bbW;nqNDQ0J9b8s$LL>0-co1C1Kg&iFol&uS?=4APc&y(;EPOH_b zNN64$1tMx4%_x~nLNpo$gTatPK^t;|yFyV^atHZ3FfagGf|4NN>gpPKohS)r(e z+jSFZ7e(=KdwUzShTH8X$$P}i7e|R=gTKz%yzB4p*DSHwY$SPxR3Rm55`hlz!3TQ1 z{uICF3k6$STO^1fHpGaCY7#=stL7tJ)r(?eWP~Iic%D2DH3`p#t8wUby2G`#wZ94y zi3FIP000>X1ONa4Zs1Mm00045NklehSa-*C=wk$-312?~vaNyNoQqhdgYXpE%pcl@}8l}{WtBvD`>->*TN z0y>`>Ez**B3eLUeblf}IbxLiwGs`EU8IY`lQ3b^?3rFh0BQu72Gs& zseHeNE466i-}EQbUWDcn2n$lfq=`)_Xj7$3kxg1L@`Z>{&k~J80fUXk4UvC$IbVR7 zG_pitp|MaAFJA0_y#>Njf)Hcup}#22%ETHq!&y^@w~S~Cc=+sc$WfF%w%NeRkT_U4 wl&DanP9usJ0)x&c3XP46NyI^;*8W}m0g8kY7#c;L_5c6?07*qoM6N<$g1O7HMgRZ+ literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-mdpi/pointer_top_right_diagonal_double_arrow.png b/core/res/res/drawable-mdpi/pointer_top_right_diagonal_double_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..f8d3527fcd0a900302d370a5594e150521e201fa GIT binary patch literal 404 zcmV;F0c-w=P)P000>X1ONa4Zs1Mm00047NkldZvDRX{Gvy>?CFp zp@N-r3!2*LUO4I`iHpvAi$$5{-Ni(Lm^9MFz70#LK8P000>X1ONa4Zs1Mm0003*Nklb;z6b9hmgp^2CXge^FA+Ry9b)^FmDv%r?Q#n*s4vMf|a07JVlflb(OpW5&w zt1qeA`k(wqpKLt`_SY!^+){nT>FNj?@VDdb7(N<55C*OF%xI(6Gqf0qgu!aA&D2h< zHmf-!fiQSY2#|)0Wa0uBiG;7@O!S_SM7+)9q;0uCIj@u6OyGSd3O+(a7~mG8Gr@>< z18PI~P{Jt)aD@(H44DjR*P%9$P5~653u4#kG3n7Rpw@$`d&&S2lL!I#eP000>X1ONa4Zs1Mm0005mNklj$2cf2mg)A0P z@CDk%LEUu765oocN$pahY8uk~Jdihlk5^&O!g39VCAs2A_b4Eg!QL z&`B@^V_`MBKJ#;aeWscn3kfjW5Inj{!_AL16*Ot9rsn6;ak}u_1dIhIH#c&M3n6U3 zq0NnV!xkAg2~O>4EaimuYf8^;rG-U}rPF-`E@Ft4&(#!FS}T%}Y)>n$n#$*iVLFLV zVs&m-C@-~%&9u<0R_93IcanhQ+QNj;Gto}_Ti3O=K$4)7L`YSO1)=GGrW8~yk|N@q z^5&B3U%qMaf}8jxj%I#UCWS>)dZBzPEp$avDMzo17-IB4$Tk~)@8z+=)P7YjS7ue^z|xnJjeFg&A@?UkH_E7R~E|;i{mfv)>|jqNT1FS z#W>CwA^i-J;V_469eH)T-Wn0Qqwi1X!FQfyVkAhCvgu_Xnb)`Kt-O}?AxDV6{e7{a zn?8mfU0iP000>X1ONa4Zs1Mm0005pNklgSS%)o)c&_3P9L>hawKJOiiKR&z=S3wGYp z+UmznL!O(2XZBX6b3z9+pqEyy!cb-UY%`&Yc*F}AN{Xpfb6Q#W_GV>a&QL-n6)qCT zt0e)+`Oy)fyf&Xfp%KlGk|d}lA*scQKA{(4BleDNYH@-TVJ)d6T^t)08vLiru!>`( zsdILDe`RBq62TmSWpMgr$eCQgzRX-gCP$-KK$R$j9z+#n*@ z`FpX@KrI3KWr~FQj{uAqK;m;2(ff)WoW-HneAA*JwADP-}J==(0-0(=bQI0Z}t5k>%aKj6KvN!$4 zt)n@ujGS$R4<3PXl?agzyr@_ixw}C8Bq&ZPBG&pRb9)%%7MS88(u42H7|^;L#Pm5 z3?TWfVE6oSl_gtv8D|s;jccVm(T#xcVt7{Es6-uFh7J%-NP3(x*-Ua~^2o8*lQa4t zowKNwK{mc!K{TQ5+IgZ-zW3+G@Dv6y`2EMkP`#9>7C|<y_6y8#Q-Ai7eZ)8yK~u*UTiV493aB(v_Y~L)XP#DK-6)m$F5Hg6^btyp+XVa zEG2s}fJiU3IWLPBWcQWSnDjv|%2FCYRFJE&6}zx6eKoh}VGY1OSZa__t(0aE4zk=! zTRi5-hA6Eq|1ddugeWSzub0vQqGim&-u0ycvMD0Ucj3La58+8x|Jrg&D zy@of`kLRmg7@~XGhVV0eD?i35 zLY8ze%)1~C!q^LF7aOTG?}_fEl9#$2t$5_bD+?F-0`QZ*x-`2q`}2o`{pf&&t@3ZH zIYfC8C#H@uVRWJk-FOT={MnC3u@7x%K?8#754br*k8(A;*@hPEMmsu%_VD+eXhuD1 zP$5pet7wRNUqKau?56=u*e=wBMh1i!?^lT8A?nS`13!ZTj0&NaKS9(m*blFIAu0`` zgS_y;FXV%l!2-ZS=@9*ORhLTv3?L=ze*<{{`3DO^4bV*XV}bwx002ovPDHLkV1nq9 BD`o%y literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-xhdpi/pointer_all_scroll.png b/core/res/res/drawable-xhdpi/pointer_all_scroll.png new file mode 100644 index 0000000000000000000000000000000000000000..e2374ece1067858f8fc2938a24255d5d0ab1e8f7 GIT binary patch literal 749 zcmVJ=bS0UzCv;|JgvU*UgK;A|;m0uICOB7#aUeucz$C}` znivJ4anFj}6Qd%0qmn=uhxm!(j|h&XdWddE2AYI4rCP_180t;4h)NiwjxBsggOG+)w@|k@GZs+^%sP12PE!akMBiy3!Y_5k zAlY6t86?Ci0shS7suv+^CW8Rs>B>t#jvwN${{oRN4}!e(Pgf8km?9a>qwwq7^MDzD z;(749hJtj?q!5%ljnU9DzJss+B}T)eZIshUfDm~^Sa1G#yfusmVu{Dw)&bTLA#XpI z3?2(8qJmnZW0(|z6C6pN7(}gGVz+}DDkx&X4t@?9zy=WtqB2zvLPx-ixoJ$8aqEPRs5h-jgf?zB z;%3~08*wvL2jN28jFWI9Zbl^l4}_WBjxc7KGvS9YQ)?ZJhNEHY05u}K5N1lKV6D?Q z+QyokN@>CuVP+9UL?}x}a$2;68=+8{92SsAK{79=oFN=Rh?B`8#JpsPED>G^GYJ$R fBN-$B6FTw-p=cYo%`V+d00000NkvXXu0mjf1!q6a literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-xhdpi/pointer_cell.png b/core/res/res/drawable-xhdpi/pointer_cell.png new file mode 100644 index 0000000000000000000000000000000000000000..4ca09e3229a26c720a8029d7cabf0df77501c05b GIT binary patch literal 467 zcmV;^0WAKBP)l*~%zHM5fH89&lnQVARuxOl8eJX{tym1uxO6s6$Z8kI;i10)VEzDRsr99xnZ z3)YxQKut9;tXVL#C2_|nDvcurlv!rRA5^a=1jSg*EmqZ%XN1{#ZmPn)e zp-tyk*LdZA7GT{3v%Rieu^Sfb0N8&5*cjR!@;lP_M9l^0(; zDHun zZstYo2{Gu)s99l6zy{N>Wk*aVl8l%gTTH`-fVE_0gg}mv`al0=oFtJp%BDn{X8ku+ zn$~WV4T&_Z)u{dw1!-ElQ8py4rb(lQOYC1v1)Epw5tt;s_y)hEj4>xzV)_68002ov JPDHLkV1m=*$Y%fm literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-xhdpi/pointer_context_menu.png b/core/res/res/drawable-xhdpi/pointer_context_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..05a59f8c9690c5de65a203f5c02cbf53ece51e68 GIT binary patch literal 1057 zcmV++1m63JP)H;G zW)fSCNF?}m-~2d$*Qdraw4j0(9$uaVkEYsq$Kt{|n$;RRZ_<`fr2x>TnJ2N!*932P z>%yVFH1>`*RM4ieGKt*MyzTL0)7MvOlsp&~bO8j6qL>8u$!K( ztwz(jwOS)0%CZ!%@QTm%cP&jt62U82oi&=As#1-BVypjhe|&E~%x-8yZcI zn23Nb9sViMp-VtSjL~>dOLL286j+H*m&=Ar1uh%9_{5}=#7P61l*nqzllVj=WRk=| zvyKLujD(1gpoCDqtX?6BlO`o0E+H{kg-F~r$Sx}-GiU=IxNG`tXb;>qWi6mf=u7e> zy1;ohf@y)L<_`_f_)ke5lEEw&%EoelT39PdTqFlL%FO`8OaW&W)%|LVy4RM*U22oM z-IU5;>+bE#R-qgu2be_hoD4o7W5a#ht|Y*xgKr3lNy%KRUKCox1giiz%Q3w6o7<(Q zOl?Rz#Uy0t+7eM@hu>KKYWTKw(^JTHUe z{KggQ=Qd08hV~tk(5s(B6h~iq;yA&+uaZl5G73P(`@p8%Wb{b$;z&iJ`;}4i|&M3Zp=|Q6qN$~d4^7pHF8Z7Su*X|s*%i`wlTndqu2o4u*>F9O4XBKbHpRF1d<>j zH6$dR=+{qSnm>4z^#s44e*J}KT@QEKZp?@f+5JL7^wx|{25I)ro%nF?)sKu!PhCVi zNMuD4WcSP7mtVvu=l(qW^TCPn!55!7k@!T&+-czrsU@=tStnw`n bp(^2D4Zg>em~ z65BN4K}`$Bq)Gc=9~y(97}H8otOP|=Dxrvjpa{cd^!OWt=VDSfQii->^WP?K+M zZ7qH9;6dHwHSmh(b6Nul>WJ&fAVYoJ-<&J zd_CVM*>NhF=ON-?i47Yzq(>r=3xwzm-=H;(t9kNK;rIDE4!)1?7a2#aMU;dac!!6F zzg7|@N0vM$U<{)SU#DdFejZ0HvsjA6OQCvBoH+6F%*@OrFPF8AZ;61p2;l40GMnUa zcs$^WiHLDYf#iXKfrEr-?rdTKQxP4$kAuhI@jyZ>MV!C`(#FQdxHf3h5ARwM;rlo+ z&hI=P@We_)Eh{ewOifJ<5Mt?;}1J(1mm>xcy@@y&82fS7CH!a zcXuDPW7onsU(G8c5HsssUBC?zqL2i9ARXlH+_`ft>SXF^&Jn(U_wL=R&1z(>?YB#o z%tzn?xC;irPhcIW1?RwDpcDK8DnSTYIZlWh;huS&?0h}P_3PJJp(?>&d#p5ckf=O$jqtNQWE#?-@jZ?Q1A)_^3*wERYaZA zKG2_>oJ`lQT_Y8Zjg2foKA(^7+_}TcfOi;bZf;gGoS`;I_jPo1MD*@=+0jzoVtIGs z*IW~-EuoQ-k*Dkf;6*UYqn=q@<7@EMojUXGIA* zolZJ?_AK4Hb&IZEy-KG~pQil$e5$Lf8@+VtQW#H)6S#i*(W6Iq5gl!9Z4H%`mFpp} zTqJTqhSvR>is-wO4{QRTff_JmCSsIfkw758ON0go2kG|h+q{iZe0;oKTM_Uncmu2g zWnc*iiiB@Y&m$6gVZRN!^fks0^L)72j&jJ(*g$Pf7R9jn1Uawcl zyaPg@5M)Vld*}Rws7pu|BK*m1+qR9Gnwn_;{{6fgJyGQR`SY}S^Jdbcp`n4QtE;(= zXkuc5@EopchXr_ZpuWC7s;Q|_nfU}1NMZYdM}KAq3(Q2EB9R5cJn1uM&X6(c>+3ZU z6C^XLX1K^XJ1oMIEENuic>_=)wNi^|nnav{&_$x}PFn!&+O>=H;K@`}RFIWm8Q#rU z2*pgDot-R2D00ra64?YY^_rOL7j$~-{Q;nT`}WZjLd%jhAtj~2Hp>!IU>OL=2kKH1 z^AT|vI@T3nJT*0ydV71HI1xJoTdvy0E=zr6NNqTuMkEykWxJ*F@^bC)vLAe@pz7lr zLmQGLb3#}XNs(fE5wrlpw|&o4Wb4+gN@R_ek!p}{I6s_LMf5|_4|1ew`wr0I!-s7bDK0K%i3zY0(ho9eBq8}{Nmz7;2 z(OUZq+2>zUOUwr9v_nu^R`!VKSxJ_4TnLtfdg)fXEN}&U3ql|$jcSrwR(6Z%S@Fmp z%mPKSBvyb`;5ATghFrH&K8RAu@FHV2crJE`=;*D>LXlZ4lPH!6g+$DZkknZb$OQq( zbfQT%Y!T7_L+g=)GF?vMY$?{D8FF2=+?QsMaDjMxMa*SfAW^d86DhxB$_&3;?~|pP zpi9I;WVU}TB+i2bxzDA4#bcLfULF7Nm|5M~&ZqpCse=lIH00000NkvXX Hu0mjfQ@UqE literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-xhdpi/pointer_crosshair.png b/core/res/res/drawable-xhdpi/pointer_crosshair.png new file mode 100644 index 0000000000000000000000000000000000000000..86c649c1a1bc03e808d317b55068a5b5fdec22b0 GIT binary patch literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=0wlMXIamRya8DPw%B>kg_l#!%7Ioec)I$ztaD0e0sv|xFEs!F literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-xhdpi/pointer_grab.png b/core/res/res/drawable-xhdpi/pointer_grab.png new file mode 100644 index 0000000000000000000000000000000000000000..b5c28ba1598045dff2a40e3f32d951f7f1b7571b GIT binary patch literal 1249 zcmV<71Rnc|P)ve7qmoC)TpIcgAufpSe3R`DJ6sSPgjY&^8S{FTj)DwSgWKpaidC|WY_ zx6S2x4%z9mrfzp5guSkrbc<8o16(F$3c%mtGMjDm3HRBS zu0UonqEef>#U)afHxgWFR@Yt531(cNB^#xrRCFV#HLCz zyaZ)+joWY=wiMCAZcGyvHgn0kh3iQprldNnLLN{6UXDLn>+h$6smM-|Ta@ zCrw)|c)azNS6DQhHo_! zvDRw<`zbxBY&4KH67RL;P1?TcJDzg0Wvkq3kKPf5VO-@H;DjSQ;WGgTo9(_~_qu_OXc#L191!`VfkGi7Es>kz)f&$8U61*sb#kNeTlih2Smf=>wArHp zF7X3@F&c#foOQS=iD?PIKBsrNKAnKoM&lv>-{nLB*gOA^L;vj%ku zsYGdD;FwRFy~{hCGCp@RaHt-7S|W-H13eulT<72;t}tsnj+y0%vj$2fi+G#N0ja{Fi0;IauBInnkCq4{-v*7 zo$vF$5jSg=2R&<$c0f*|iS_xlfA?lSoLOc)j{G+~ z>1TTCu}jEEHA;oPZnbO2-Bk2H;!aTtly#5HG_IC(G$L8BKh_a z5fys6Iy$;_$MBMnc$5a9ROqD=#QL7-Rf=jJj8TG!qPf@PvQ(nJz4a?aA&R3(QcV;U zvbrOcM1?Z>z#U6ML|IFMKq9GY#QGRt0#OuDk|-cHGDG;^`Mv8ukr5Ow*gt9K00000 LNkvXXu0mjfon=%2 literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-xhdpi/pointer_grabbing.png b/core/res/res/drawable-xhdpi/pointer_grabbing.png new file mode 100644 index 0000000000000000000000000000000000000000..6aba589f92356b14d2d04d731100f36cd3097410 GIT binary patch literal 883 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 literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-xhdpi/pointer_text.png b/core/res/res/drawable-xhdpi/pointer_text.png new file mode 100644 index 0000000000000000000000000000000000000000..0cebeae84cc9dc25fc3daf87fe1c82a8b892511e GIT binary patch literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=0wlMXIamRyx1KJJAr*|tKm6G(M06#$s=TQG z@LxcIhxO9C|E2$nnHJuwU;kh5fAat1fBV@Fv1COFeY5{l&oV>&tNpKfo~gQx1`+$b zV>Ms>k^gDGYKQwXt<&Wl8lt+64!cXsUQhTL!ne-5^WW#0bezL6&2ijp@iBr; zh%3V7t%ak*#QzV)gB^OjGabB-NIYohnr2|o5G3Bg=@sknZiVXNX+2R!Stn5#7Z%U- z+HvshPLaI_eJ`&&e6^%Q)#Me+&Gqijf_GbgcYfvNXuiTa`~vrzbAKB;F0D=W+O1cn h!szYRZtJGY$iQnFkX7G)BLwJi22WQ%mvv4FO#n7Rd+GoH literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow.png b/core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..5454a8ba5ccbf2677fc9b3f12ade1594321fa122 GIT binary patch literal 808 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 literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-xhdpi/pointer_zoom_out.png b/core/res/res/drawable-xhdpi/pointer_zoom_out.png new file mode 100644 index 0000000000000000000000000000000000000000..710552b66fbcc7583ee913d8a58979a745f24989 GIT binary patch literal 1256 zcmVP)P`0n8;njFqg~k;6xPAm#b6aXErs3 zi@{)5qYmb@UJmwQQ;lVI8)L0QLAs*Wk7U~TaZ+Qx&a;<42NE(T=OFaT^W2=1i~Kmx zd(Quy1bhT}B*+1Bfb6>2B=(%xBztdrBiWex`p1xmd^k{O#34s{@~Ke!Mhrl{exgyk zk{C@daYv6PXA?hbS0JT|)^Rsxq^Ps;cOl<4na_tq7Z7lq9u>%MX_m8Yw(&3h^;croL`R zk*drbVw^|m@`vPrAzvhAIO{W^o8gJ@MCj(mw2X?E2$icOmp??QaV{p2Jh*U38zavs z!pSY_j7*1uE5Y!1czh)o3Pz@NM(I?@X_DF)4#9;ylZYzIjml(*tW`)C(~N0L!Nu{V z8_R*^z|sxb3&yt6>{3WA$z%wXaI3;hA~JM%^*HHJNDq_TSjs6_K1s4iAq6D$1iWha zrjbH;;1h(!29jVT7m-gA*+?8dcu;5sDMNK4Og1RwW$tie>)zPi!0h#z(V5ZN>vse9 z#x}Ng*sYK{lF2ZtQDzxgpU4b;jZxm8%0})_MHw*$e~#q(xOGJ8n)xhq3HNfFo5{sH zbEAJt=0=xpZzi|dPpAx&{Oc2|b*aH$eqK*!ZpJ}jG)6X87giS{o0_2C8aHDD(=zr8 z&!I})DRxVjF#IdulY@qBXAd7R#%)PV_IhYH_#a7b&zK(T1WzfhUNN!BzA6+Nk7Kh-Jr1KDZG*k3C>iGfPxA=#S;V7!lOtkN z@)426#DBT$%`m1OTJXS&qiB1(d*LTtXU?W4ql@G`>-S(xJ$_LpOg);>@zyK1zWnFc z*s7jPCt|Ci$>0}fUORSbZE82>-AZH8H~S(1kCaw}2DG9bPvHbQB`5H-?8{Nx3lHx6 zms$TDMJRw&X8M%~B{&2xYT-vCn$aR@Mw3blj<-J>xt+~CNiwwpkE+aO;pGlRC>5wu zC?BdNK2%A3s1dlO{h7$08OE(vWRycaj4i&V!UZ=<;6a(hgHnk{;KxyiW`kiTJ^YGf z^f#%v7*g0iU%1u2OQ=fJ;#kK?VT?^rjJ$3gQIMi?lP^$-Vw(J&GXwFpbYlIFtLIRM z3b@VIwRhCS6jPzDzc#c>TJZ#YD1*z~;LS6|D2ESq@Js51D2H3!DSIGRlDYmo0v(oA zpbT!~p2z->+{>Z>g#r~z+;G8RVp*}u7`5dKRgnEN&jex>+U*DH!Jh?^1LR-2Y@GOS S>g_%N0000 + diff --git a/core/res/res/drawable/pointer_all_scroll_icon.xml b/core/res/res/drawable/pointer_all_scroll_icon.xml new file mode 100644 index 000000000000..e9469488be3a --- /dev/null +++ b/core/res/res/drawable/pointer_all_scroll_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_cell_icon.xml b/core/res/res/drawable/pointer_cell_icon.xml new file mode 100644 index 000000000000..da1e320c1d71 --- /dev/null +++ b/core/res/res/drawable/pointer_cell_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_context_menu_icon.xml b/core/res/res/drawable/pointer_context_menu_icon.xml new file mode 100644 index 000000000000..330b627b5d02 --- /dev/null +++ b/core/res/res/drawable/pointer_context_menu_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_copy_icon.xml b/core/res/res/drawable/pointer_copy_icon.xml new file mode 100644 index 000000000000..e299db5b23b5 --- /dev/null +++ b/core/res/res/drawable/pointer_copy_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_crosshair_icon.xml b/core/res/res/drawable/pointer_crosshair_icon.xml new file mode 100644 index 000000000000..3b96a8ad3ace --- /dev/null +++ b/core/res/res/drawable/pointer_crosshair_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_grab_icon.xml b/core/res/res/drawable/pointer_grab_icon.xml new file mode 100644 index 000000000000..d437b3a7bf8a --- /dev/null +++ b/core/res/res/drawable/pointer_grab_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_grabbing_icon.xml b/core/res/res/drawable/pointer_grabbing_icon.xml new file mode 100644 index 000000000000..38f4c3a064fa --- /dev/null +++ b/core/res/res/drawable/pointer_grabbing_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_hand_icon.xml b/core/res/res/drawable/pointer_hand_icon.xml new file mode 100644 index 000000000000..3d90b88d5dca --- /dev/null +++ b/core/res/res/drawable/pointer_hand_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_help_icon.xml b/core/res/res/drawable/pointer_help_icon.xml new file mode 100644 index 000000000000..49ae554249f8 --- /dev/null +++ b/core/res/res/drawable/pointer_help_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_horizontal_double_arrow_icon.xml b/core/res/res/drawable/pointer_horizontal_double_arrow_icon.xml new file mode 100644 index 000000000000..5a5ad9e62657 --- /dev/null +++ b/core/res/res/drawable/pointer_horizontal_double_arrow_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_nodrop_icon.xml b/core/res/res/drawable/pointer_nodrop_icon.xml new file mode 100644 index 000000000000..955b40f2d567 --- /dev/null +++ b/core/res/res/drawable/pointer_nodrop_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_text_icon.xml b/core/res/res/drawable/pointer_text_icon.xml new file mode 100644 index 000000000000..d948c8916963 --- /dev/null +++ b/core/res/res/drawable/pointer_text_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_top_left_diagonal_double_arrow_icon.xml b/core/res/res/drawable/pointer_top_left_diagonal_double_arrow_icon.xml new file mode 100644 index 000000000000..de5efe25dae2 --- /dev/null +++ b/core/res/res/drawable/pointer_top_left_diagonal_double_arrow_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_top_right_diagonal_double_arrow_icon.xml b/core/res/res/drawable/pointer_top_right_diagonal_double_arrow_icon.xml new file mode 100644 index 000000000000..e87b52686426 --- /dev/null +++ b/core/res/res/drawable/pointer_top_right_diagonal_double_arrow_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_vertical_double_arrow_icon.xml b/core/res/res/drawable/pointer_vertical_double_arrow_icon.xml new file mode 100644 index 000000000000..5759079a47fa --- /dev/null +++ b/core/res/res/drawable/pointer_vertical_double_arrow_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_vertical_text_icon.xml b/core/res/res/drawable/pointer_vertical_text_icon.xml new file mode 100644 index 000000000000..3b48dc89fb56 --- /dev/null +++ b/core/res/res/drawable/pointer_vertical_text_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_zoom_in_icon.xml b/core/res/res/drawable/pointer_zoom_in_icon.xml new file mode 100644 index 000000000000..e2dcb49c1600 --- /dev/null +++ b/core/res/res/drawable/pointer_zoom_in_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/drawable/pointer_zoom_out_icon.xml b/core/res/res/drawable/pointer_zoom_out_icon.xml new file mode 100644 index 000000000000..b805df3d18c1 --- /dev/null +++ b/core/res/res/drawable/pointer_zoom_out_icon.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index a6eb68b73baa..b818fe0a3e1a 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -7605,6 +7605,44 @@ i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 11c4cc01ee82..b831df827a8c 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1336,6 +1336,33 @@ please see styles_device_defaults.xml. @drawable/pointer_spot_hover_icon @drawable/pointer_spot_touch_icon @drawable/pointer_spot_anchor_icon + @drawable/pointer_hand_icon + @drawable/pointer_context_menu_icon + @drawable/pointer_help_icon + @drawable/pointer_cell_icon + @drawable/pointer_crosshair_icon + @drawable/pointer_text_icon + @drawable/pointer_vertical_text_icon + @drawable/pointer_alias_icon + @drawable/pointer_copy_icon + @drawable/pointer_all_scroll_icon + @drawable/pointer_nodrop_icon + + @drawable/pointer_horizontal_double_arrow_icon + + + @drawable/pointer_vertical_double_arrow_icon + + + @drawable/pointer_top_right_diagonal_double_arrow_icon + + + @drawable/pointer_top_left_diagonal_double_arrow_icon + + @drawable/pointer_zoom_in_icon + @drawable/pointer_zoom_out_icon + @drawable/pointer_grab_icon + @drawable/pointer_grabbing_icon diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index 11527378f586..0f86bc614b2b 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -78,6 +78,7 @@ PointerController::PointerController(const sp& mLocked.pointerAlpha = 0.0f; // pointer is initially faded mLocked.pointerSprite = mSpriteController->createSprite(); mLocked.pointerIconChanged = false; + mLocked.requestedPointerShape = 0; mLocked.buttonState = 0; @@ -231,6 +232,10 @@ void PointerController::unfade(Transition transition) { void PointerController::setPresentation(Presentation presentation) { AutoMutex _l(mLock); + if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) { + mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources); + } + if (mLocked.presentation != presentation) { mLocked.presentation = presentation; mLocked.presentationChanged = true; @@ -391,6 +396,15 @@ void PointerController::setDisplayViewport(int32_t width, int32_t height, int32_ updatePointerLocked(); } +void PointerController::updatePointerShape(int iconId) { + AutoMutex _l(mLock); + if (mLocked.requestedPointerShape != iconId) { + mLocked.requestedPointerShape = iconId; + mLocked.presentationChanged = true; + updatePointerLocked(); + } +} + void PointerController::setPointerIcon(const SpriteIcon& icon) { AutoMutex _l(mLock); @@ -497,8 +511,22 @@ void PointerController::updatePointerLocked() { } if (mLocked.pointerIconChanged || mLocked.presentationChanged) { - mLocked.pointerSprite->setIcon(mLocked.presentation == PRESENTATION_POINTER - ? mLocked.pointerIcon : mResources.spotAnchor); + if (mLocked.presentation == PRESENTATION_POINTER) { + if (mLocked.requestedPointerShape == 0) { + mLocked.pointerSprite->setIcon(mLocked.pointerIcon); + } else { + std::map::const_iterator iter = + mLocked.additionalMouseResources.find(mLocked.requestedPointerShape); + if (iter != mLocked.additionalMouseResources.end()) { + mLocked.pointerSprite->setIcon(iter->second); + } else { + ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerShape); + mLocked.pointerSprite->setIcon(mLocked.pointerIcon); + } + } + } else { + mLocked.pointerSprite->setIcon(mResources.spotAnchor); + } mLocked.pointerIconChanged = false; mLocked.presentationChanged = false; } diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index b9e4ce7e7ed0..308ff1242064 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -19,6 +19,8 @@ #include "SpriteController.h" +#include + #include #include #include @@ -40,7 +42,6 @@ struct PointerResources { SpriteIcon spotAnchor; }; - /* * Pointer controller policy interface. * @@ -57,6 +58,7 @@ protected: public: virtual void loadPointerResources(PointerResources* outResources) = 0; + virtual void loadAdditionalMouseResources(std::map* outResources) = 0; }; @@ -93,6 +95,7 @@ public: const uint32_t* spotIdToIndex, BitSet32 spotIdBits); virtual void clearSpots(); + void updatePointerShape(int iconId); void setDisplayViewport(int32_t width, int32_t height, int32_t orientation); void setPointerIcon(const SpriteIcon& icon); void setInactivityTimeout(InactivityTimeout inactivityTimeout); @@ -155,6 +158,10 @@ private: SpriteIcon pointerIcon; bool pointerIconChanged; + std::map additionalMouseResources; + + int32_t requestedPointerShape; + int32_t buttonState; Vector spots; diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 5a136729291a..5b40375007c1 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -206,6 +206,7 @@ public class InputManagerService extends IInputManager.Stub private static native void nativeReloadDeviceAliases(long ptr); private static native String nativeDump(long ptr); private static native void nativeMonitor(long ptr); + private static native void nativeSetPointerIconShape(long ptr, int iconId); // Input event injection constants defined in InputDispatcher.h. private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0; @@ -1407,6 +1408,12 @@ public class InputManagerService extends IInputManager.Stub } } + // Binder call + @Override + public void setPointerIconShape(int iconId) { + nativeSetPointerIconShape(mPtr, iconId); + } + @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 1d4f047ff605..8cb0a1310ec5 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -199,6 +199,7 @@ public: void setShowTouches(bool enabled); void setInteractive(bool interactive); void reloadCalibration(); + void setPointerIconShape(int32_t iconId); /* --- InputReaderPolicyInterface implementation --- */ @@ -237,6 +238,7 @@ public: /* --- PointerControllerPolicyInterface implementation --- */ virtual void loadPointerResources(PointerResources* outResources); + virtual void loadAdditionalMouseResources(std::map* outResources); private: sp mInputManager; @@ -779,6 +781,15 @@ void NativeInputManager::reloadCalibration() { InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION); } +void NativeInputManager::setPointerIconShape(int32_t iconId) { + AutoMutex _l(mLock); + sp controller = mLocked.pointerController.promote(); + if (controller != NULL) { + // Use 0 (the default icon) for ARROW. + controller->updatePointerShape((iconId == POINTER_ICON_STYLE_ARROW) ? 0 : iconId); + } +} + TouchAffineTransformation NativeInputManager::getTouchAffineTransformation( JNIEnv *env, jfloatArray matrixArr) { ScopedFloatArrayRO matrix(env, matrixArr); @@ -1029,6 +1040,15 @@ void NativeInputManager::loadPointerResources(PointerResources* outResources) { &outResources->spotAnchor); } +void NativeInputManager::loadAdditionalMouseResources(std::map* outResources) { + JNIEnv* env = jniEnv(); + + for (int iconId = POINTER_ICON_STYLE_CONTEXT_MENU; iconId <= POINTER_ICON_STYLE_GRABBING; + ++iconId) { + loadSystemIconAsSprite(env, mContextObj, iconId, &((*outResources)[iconId])); + } +} + // ---------------------------------------------------------------------------- @@ -1367,6 +1387,11 @@ static void nativeMonitor(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) { im->getInputManager()->getDispatcher()->monitor(); } +static void nativeSetPointerIconShape(JNIEnv* /* env */, jclass /* clazz */, jlong ptr, jint iconId) { + NativeInputManager* im = reinterpret_cast(ptr); + im->setPointerIconShape(iconId); +} + // ---------------------------------------------------------------------------- static const JNINativeMethod gInputManagerMethods[] = { @@ -1425,6 +1450,8 @@ static const JNINativeMethod gInputManagerMethods[] = { (void*) nativeDump }, { "nativeMonitor", "(J)V", (void*) nativeMonitor }, + { "nativeSetPointerIconShape", "(JI)V", + (void*) nativeSetPointerIconShape }, }; #define FIND_CLASS(var, className) \ -- 2.11.0