Merge "Make public pointer icon API with custom icons."
diff --git a/api/current.txt b/api/current.txt
index f5ccf0e..df6c473a3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -40337,6 +40337,38 @@
field public static final int ORIENTATION_UNKNOWN = -1; // 0xffffffff
}
+ public final class PointerIcon implements android.os.Parcelable {
+ method public static android.view.PointerIcon createCustomIcon(android.graphics.Bitmap, float, float);
+ method public int describeContents();
+ method public static android.view.PointerIcon getSystemIcon(android.content.Context, int);
+ method public static android.view.PointerIcon loadCustomIcon(android.content.res.Resources, int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.PointerIcon> CREATOR;
+ field public static final int STYLE_ALIAS = 1010; // 0x3f2
+ field public static final int STYLE_ALL_SCROLL = 1013; // 0x3f5
+ field public static final int STYLE_ARROW = 1000; // 0x3e8
+ field public static final int STYLE_CELL = 1006; // 0x3ee
+ field public static final int STYLE_CONTEXT_MENU = 1001; // 0x3e9
+ field public static final int STYLE_COPY = 1011; // 0x3f3
+ field public static final int STYLE_CROSSHAIR = 1007; // 0x3ef
+ field public static final int STYLE_DEFAULT = 1000; // 0x3e8
+ field public static final int STYLE_GRAB = 1020; // 0x3fc
+ field public static final int STYLE_GRABBING = 1021; // 0x3fd
+ field public static final int STYLE_HAND = 1002; // 0x3ea
+ field public static final int STYLE_HELP = 1003; // 0x3eb
+ field public static final int STYLE_HORIZONTAL_DOUBLE_ARROW = 1014; // 0x3f6
+ field public static final int STYLE_NO_DROP = 1012; // 0x3f4
+ field public static final int STYLE_NULL = 0; // 0x0
+ field public static final int STYLE_TEXT = 1008; // 0x3f0
+ field public static final int STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017; // 0x3f9
+ field public static final int STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016; // 0x3f8
+ field public static final int STYLE_VERTICAL_DOUBLE_ARROW = 1015; // 0x3f7
+ field public static final int STYLE_VERTICAL_TEXT = 1009; // 0x3f1
+ field public static final int STYLE_WAIT = 1004; // 0x3ec
+ field public static final int STYLE_ZOOM_IN = 1018; // 0x3fa
+ field public static final int STYLE_ZOOM_OUT = 1019; // 0x3fb
+ }
+
public class ScaleGestureDetector {
ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener);
ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener, android.os.Handler);
@@ -40696,6 +40728,7 @@
method public android.view.ViewParent getParentForAccessibility();
method public float getPivotX();
method public float getPivotY();
+ method public android.view.PointerIcon getPointerIcon(android.view.MotionEvent, float, float);
method public android.content.res.Resources getResources();
method public final int getRight();
method protected float getRightFadingEdgeStrength();
@@ -40978,6 +41011,7 @@
method public void setPaddingRelative(int, int, int, int);
method public void setPivotX(float);
method public void setPivotY(float);
+ method public void setPointerIcon(android.view.PointerIcon);
method public void setPressed(boolean);
method public final void setRight(int);
method public void setRotation(float);
diff --git a/api/system-current.txt b/api/system-current.txt
index bc63b48..ee975d1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -42675,6 +42675,38 @@
field public static final int ORIENTATION_UNKNOWN = -1; // 0xffffffff
}
+ public final class PointerIcon implements android.os.Parcelable {
+ method public static android.view.PointerIcon createCustomIcon(android.graphics.Bitmap, float, float);
+ method public int describeContents();
+ method public static android.view.PointerIcon getSystemIcon(android.content.Context, int);
+ method public static android.view.PointerIcon loadCustomIcon(android.content.res.Resources, int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.PointerIcon> CREATOR;
+ field public static final int STYLE_ALIAS = 1010; // 0x3f2
+ field public static final int STYLE_ALL_SCROLL = 1013; // 0x3f5
+ field public static final int STYLE_ARROW = 1000; // 0x3e8
+ field public static final int STYLE_CELL = 1006; // 0x3ee
+ field public static final int STYLE_CONTEXT_MENU = 1001; // 0x3e9
+ field public static final int STYLE_COPY = 1011; // 0x3f3
+ field public static final int STYLE_CROSSHAIR = 1007; // 0x3ef
+ field public static final int STYLE_DEFAULT = 1000; // 0x3e8
+ field public static final int STYLE_GRAB = 1020; // 0x3fc
+ field public static final int STYLE_GRABBING = 1021; // 0x3fd
+ field public static final int STYLE_HAND = 1002; // 0x3ea
+ field public static final int STYLE_HELP = 1003; // 0x3eb
+ field public static final int STYLE_HORIZONTAL_DOUBLE_ARROW = 1014; // 0x3f6
+ field public static final int STYLE_NO_DROP = 1012; // 0x3f4
+ field public static final int STYLE_NULL = 0; // 0x0
+ field public static final int STYLE_TEXT = 1008; // 0x3f0
+ field public static final int STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017; // 0x3f9
+ field public static final int STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016; // 0x3f8
+ field public static final int STYLE_VERTICAL_DOUBLE_ARROW = 1015; // 0x3f7
+ field public static final int STYLE_VERTICAL_TEXT = 1009; // 0x3f1
+ field public static final int STYLE_WAIT = 1004; // 0x3ec
+ field public static final int STYLE_ZOOM_IN = 1018; // 0x3fa
+ field public static final int STYLE_ZOOM_OUT = 1019; // 0x3fb
+ }
+
public class ScaleGestureDetector {
ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener);
ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener, android.os.Handler);
@@ -43034,6 +43066,7 @@
method public android.view.ViewParent getParentForAccessibility();
method public float getPivotX();
method public float getPivotY();
+ method public android.view.PointerIcon getPointerIcon(android.view.MotionEvent, float, float);
method public android.content.res.Resources getResources();
method public final int getRight();
method protected float getRightFadingEdgeStrength();
@@ -43316,6 +43349,7 @@
method public void setPaddingRelative(int, int, int, int);
method public void setPivotX(float);
method public void setPivotY(float);
+ method public void setPointerIcon(android.view.PointerIcon);
method public void setPressed(boolean);
method public final void setRight(int);
method public void setRotation(float);
diff --git a/api/test-current.txt b/api/test-current.txt
index a222037..c494895 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -40339,6 +40339,38 @@
field public static final int ORIENTATION_UNKNOWN = -1; // 0xffffffff
}
+ public final class PointerIcon implements android.os.Parcelable {
+ method public static android.view.PointerIcon createCustomIcon(android.graphics.Bitmap, float, float);
+ method public int describeContents();
+ method public static android.view.PointerIcon getSystemIcon(android.content.Context, int);
+ method public static android.view.PointerIcon loadCustomIcon(android.content.res.Resources, int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.PointerIcon> CREATOR;
+ field public static final int STYLE_ALIAS = 1010; // 0x3f2
+ field public static final int STYLE_ALL_SCROLL = 1013; // 0x3f5
+ field public static final int STYLE_ARROW = 1000; // 0x3e8
+ field public static final int STYLE_CELL = 1006; // 0x3ee
+ field public static final int STYLE_CONTEXT_MENU = 1001; // 0x3e9
+ field public static final int STYLE_COPY = 1011; // 0x3f3
+ field public static final int STYLE_CROSSHAIR = 1007; // 0x3ef
+ field public static final int STYLE_DEFAULT = 1000; // 0x3e8
+ field public static final int STYLE_GRAB = 1020; // 0x3fc
+ field public static final int STYLE_GRABBING = 1021; // 0x3fd
+ field public static final int STYLE_HAND = 1002; // 0x3ea
+ field public static final int STYLE_HELP = 1003; // 0x3eb
+ field public static final int STYLE_HORIZONTAL_DOUBLE_ARROW = 1014; // 0x3f6
+ field public static final int STYLE_NO_DROP = 1012; // 0x3f4
+ field public static final int STYLE_NULL = 0; // 0x0
+ field public static final int STYLE_TEXT = 1008; // 0x3f0
+ field public static final int STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017; // 0x3f9
+ field public static final int STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016; // 0x3f8
+ field public static final int STYLE_VERTICAL_DOUBLE_ARROW = 1015; // 0x3f7
+ field public static final int STYLE_VERTICAL_TEXT = 1009; // 0x3f1
+ field public static final int STYLE_WAIT = 1004; // 0x3ec
+ field public static final int STYLE_ZOOM_IN = 1018; // 0x3fa
+ field public static final int STYLE_ZOOM_OUT = 1019; // 0x3fb
+ }
+
public class ScaleGestureDetector {
ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener);
ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener, android.os.Handler);
@@ -40698,6 +40730,7 @@
method public android.view.ViewParent getParentForAccessibility();
method public float getPivotX();
method public float getPivotY();
+ method public android.view.PointerIcon getPointerIcon(android.view.MotionEvent, float, float);
method public android.content.res.Resources getResources();
method public final int getRight();
method protected float getRightFadingEdgeStrength();
@@ -40980,6 +41013,7 @@
method public void setPaddingRelative(int, int, int, int);
method public void setPivotX(float);
method public void setPivotY(float);
+ method public void setPointerIcon(android.view.PointerIcon);
method public void setPressed(boolean);
method public final void setRight(int);
method public void setRotation(float);
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 174291e..ff33bd9 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -24,6 +24,7 @@
import android.os.IBinder;
import android.view.InputDevice;
import android.view.InputEvent;
+import android.view.PointerIcon;
/** @hide */
interface IInputManager {
@@ -71,4 +72,5 @@
void cancelVibrate(int deviceId, IBinder token);
void setPointerIconShape(int shapeId);
+ void setCustomPointerIcon(in PointerIcon icon);
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 201afee..fab4718 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -16,6 +16,7 @@
package android.hardware.input;
+import android.view.PointerIcon;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
@@ -819,6 +820,15 @@
}
}
+ /** @hide */
+ public void setCustomPointerIcon(PointerIcon icon) {
+ try {
+ mIm.setCustomPointerIcon(icon);
+ } 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 46b9a46..88cd7ca 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -784,6 +784,15 @@
}
/**
+ * Specifies the current custom pointer.
+ * @param icon the icon data.
+ * @hide
+ */
+ public void setCustomPointerIcon(PointerIcon icon) {
+ InputManager.getInstance().setCustomPointerIcon(icon);
+ }
+
+ /**
* 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 d2a7d4a..aa879cd 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -16,8 +16,10 @@
package android.view;
+import android.annotation.NonNull;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.SparseArray;
import com.android.internal.util.XmlUtils;
import android.annotation.XmlRes;
@@ -39,13 +41,11 @@
* Pointer icons can be provided either by the system using system styles,
* or by applications using bitmaps or application resources.
* </p>
- *
- * @hide
*/
public final class PointerIcon implements Parcelable {
private static final String TAG = "PointerIcon";
- /** Style constant: Custom icon with a user-supplied bitmap. */
+ /** {@hide} Style constant: Custom icon with a user-supplied bitmap. */
public static final int STYLE_CUSTOM = -1;
/** Style constant: Null icon. It has no bitmap. */
@@ -54,6 +54,7 @@
/** 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.
+ * @hide
*/
public static final int STYLE_NOT_SPECIFIED = 1;
@@ -135,10 +136,11 @@
// conflicts with any system styles that may be defined in the future.
private static final int STYLE_OEM_FIRST = 10000;
- /** {@hide} The default pointer icon. */
+ /** The default pointer icon. */
public static final int STYLE_DEFAULT = STYLE_ARROW;
private static final PointerIcon gNullIcon = new PointerIcon(STYLE_NULL);
+ private static final SparseArray<PointerIcon> gSystemIcons = new SparseArray<PointerIcon>();
private final int mStyle;
private int mSystemIconResourceId;
@@ -160,6 +162,7 @@
* @return The null pointer icon.
*
* @see #STYLE_NULL
+ * @hide
*/
public static PointerIcon getNullIcon() {
return gNullIcon;
@@ -172,8 +175,9 @@
* @return The default pointer icon.
*
* @throws IllegalArgumentException if context is null.
+ * @hide
*/
- public static PointerIcon getDefaultIcon(Context context) {
+ public static PointerIcon getDefaultIcon(@NonNull Context context) {
return getSystemIcon(context, STYLE_DEFAULT);
}
@@ -187,7 +191,7 @@
*
* @throws IllegalArgumentException if context is null.
*/
- public static PointerIcon getSystemIcon(Context context, int style) {
+ public static PointerIcon getSystemIcon(@NonNull Context context, int style) {
if (context == null) {
throw new IllegalArgumentException("context must not be null");
}
@@ -196,6 +200,11 @@
return gNullIcon;
}
+ PointerIcon icon = gSystemIcons.get(style);
+ if (icon != null) {
+ return icon;
+ }
+
int styleIndex = getSystemIconStyleIndex(style);
if (styleIndex == 0) {
styleIndex = getSystemIconStyleIndex(STYLE_DEFAULT);
@@ -217,12 +226,13 @@
return style == STYLE_DEFAULT ? gNullIcon : getSystemIcon(context, STYLE_DEFAULT);
}
- PointerIcon icon = new PointerIcon(style);
+ icon = new PointerIcon(style);
if ((resourceId & 0xff000000) == 0x01000000) {
icon.mSystemIconResourceId = resourceId;
} else {
icon.loadResource(context, context.getResources(), resourceId);
}
+ gSystemIcons.append(style, icon);
return icon;
}
@@ -239,7 +249,8 @@
* @throws IllegalArgumentException if bitmap is null, or if the x/y hotspot
* parameters are invalid.
*/
- public static PointerIcon createCustomIcon(Bitmap bitmap, float hotSpotX, float hotSpotY) {
+ public static PointerIcon createCustomIcon(
+ @NonNull Bitmap bitmap, float hotSpotX, float hotSpotY) {
if (bitmap == null) {
throw new IllegalArgumentException("bitmap must not be null");
}
@@ -273,7 +284,7 @@
* @throws Resources.NotFoundException if the resource was not found or the drawable
* linked in the resource was not found.
*/
- public static PointerIcon loadCustomIcon(Resources resources, @XmlRes int resourceId) {
+ public static PointerIcon loadCustomIcon(@NonNull Resources resources, @XmlRes int resourceId) {
if (resources == null) {
throw new IllegalArgumentException("resources must not be null");
}
@@ -291,10 +302,9 @@
* @return The loaded pointer icon.
*
* @throws IllegalArgumentException if context is null.
- * @see #isLoaded()
* @hide
*/
- public PointerIcon load(Context context) {
+ public PointerIcon load(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("context must not be null");
}
@@ -309,83 +319,11 @@
return result;
}
- /**
- * Returns true if the pointer icon style is {@link #STYLE_NULL}.
- *
- * @return True if the pointer icon style is {@link #STYLE_NULL}.
- */
- public boolean isNullIcon() {
- return mStyle == STYLE_NULL;
- }
-
- /**
- * Returns true if the pointer icon has been loaded and its bitmap and hotspot
- * information are available.
- *
- * @return True if the pointer icon is loaded.
- * @see #load(Context)
- */
- public boolean isLoaded() {
- return mBitmap != null || mStyle == STYLE_NULL;
- }
-
- /**
- * Gets the style of the pointer icon.
- *
- * @return The pointer icon style.
- */
+ /** @hide */
public int getStyle() {
return mStyle;
}
- /**
- * Gets the bitmap of the pointer icon.
- *
- * @return The pointer icon bitmap, or null if the style is {@link #STYLE_NULL}.
- *
- * @throws IllegalStateException if the bitmap is not loaded.
- * @see #isLoaded()
- * @see #load(Context)
- */
- public Bitmap getBitmap() {
- throwIfIconIsNotLoaded();
- return mBitmap;
- }
-
- /**
- * Gets the X offset of the pointer icon hotspot.
- *
- * @return The hotspot X offset.
- *
- * @throws IllegalStateException if the bitmap is not loaded.
- * @see #isLoaded()
- * @see #load(Context)
- */
- public float getHotSpotX() {
- throwIfIconIsNotLoaded();
- return mHotSpotX;
- }
-
- /**
- * Gets the Y offset of the pointer icon hotspot.
- *
- * @return The hotspot Y offset.
- *
- * @throws IllegalStateException if the bitmap is not loaded.
- * @see #isLoaded()
- * @see #load(Context)
- */
- public float getHotSpotY() {
- throwIfIconIsNotLoaded();
- return mHotSpotY;
- }
-
- private void throwIfIconIsNotLoaded() {
- if (!isLoaded()) {
- throw new IllegalStateException("The icon is not loaded.");
- }
- }
-
public static final Parcelable.Creator<PointerIcon> CREATOR
= new Parcelable.Creator<PointerIcon>() {
public PointerIcon createFromParcel(Parcel in) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3db18066..2368642 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2628,7 +2628,7 @@
static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
/**
- * Value indicating {@link PointerIcon.STYLE_NOT_SPECIFIED}.
+ * Value indicating no specific pointer icons.
*/
private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
@@ -2638,14 +2638,9 @@
private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
/**
- * Value incicating {@link PointerIcon.STYLE_CUSTOM}.
- */
- private static final int PFLAG3_POINTER_ICON_CUSTOM = 2 << PFLAG3_POINTER_ICON_LSHIFT;
-
- /**
* The base value for other pointer icon shapes.
*/
- private static final int PFLAG3_POINTER_ICON_VALUE_START = 3 << PFLAG3_POINTER_ICON_LSHIFT;
+ private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
/**
* Always allow a user to over-scroll this view, provided it is a
@@ -3927,6 +3922,11 @@
private HandlerActionQueue mRunQueue;
/**
+ * The pointer icon when the mouse hovers on this view. The default is null.
+ */
+ private PointerIcon mPointerIcon;
+
+ /**
* @hide
*/
String mStartActivityRequestWho;
@@ -4490,7 +4490,7 @@
case R.styleable.View_pointerShape:
final int pointerShape = a.getInt(attr, PointerIcon.STYLE_NOT_SPECIFIED);
if (pointerShape != PointerIcon.STYLE_NOT_SPECIFIED) {
- setPointerShape(pointerShape);
+ setPointerIcon(PointerIcon.getSystemIcon(context, pointerShape));
}
break;
}
@@ -21191,42 +21191,25 @@
}
}
- /** @hide */
- public int getPointerShape(MotionEvent event, float x, float y) {
- final int value = (mPrivateFlags3 & PFLAG3_POINTER_ICON_MASK);
- switch (value) {
- case PFLAG3_POINTER_ICON_NOT_SPECIFIED:
- return PointerIcon.STYLE_NOT_SPECIFIED;
- case PFLAG3_POINTER_ICON_NULL:
- return PointerIcon.STYLE_NULL;
- case PFLAG3_POINTER_ICON_CUSTOM:
- return PointerIcon.STYLE_CUSTOM;
- default:
- return ((value - PFLAG3_POINTER_ICON_VALUE_START) >> PFLAG3_POINTER_ICON_LSHIFT)
- + PointerIcon.STYLE_ARROW;
- }
+ /**
+ * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
+ * The default implementation does not care the location or event types, but some subclasses
+ * may use it (such as WebViews).
+ * @param event The MotionEvent from a mouse
+ * @param x The x position of the event, local to the view
+ * @param y The y position of the event, local to the view
+ * @see PointerIcon
+ */
+ public PointerIcon getPointerIcon(MotionEvent event, float x, float y) {
+ return mPointerIcon;
}
- /** @hide */
- public void setPointerShape(int pointerShape) {
- int newValue;
- if (pointerShape == PointerIcon.STYLE_NOT_SPECIFIED) {
- newValue = PFLAG3_POINTER_ICON_NOT_SPECIFIED;
- } else if (pointerShape == PointerIcon.STYLE_NULL) {
- newValue = PFLAG3_POINTER_ICON_NULL;
- } else if (pointerShape == PointerIcon.STYLE_CUSTOM) {
- newValue = PFLAG3_POINTER_ICON_CUSTOM;
- } else if (pointerShape >= PointerIcon.STYLE_ARROW
- && pointerShape <= PointerIcon.STYLE_GRABBING) {
- newValue = ((pointerShape - PointerIcon.STYLE_ARROW) << PFLAG3_POINTER_ICON_LSHIFT)
- + PFLAG3_POINTER_ICON_VALUE_START;
- } else {
- Log.w(VIEW_LOG_TAG, "Invalid pointer shape " + pointerShape + " is specified.");
- return;
- }
- if (newValue != (mPrivateFlags3 & PFLAG3_POINTER_ICON_MASK)) {
- mPrivateFlags3 = (mPrivateFlags3 & ~PFLAG3_POINTER_ICON_MASK) | newValue;
- }
+ /**
+ * Set the pointer icon for the current view.
+ * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
+ */
+ public void setPointerIcon(PointerIcon pointerIcon) {
+ mPointerIcon = pointerIcon;
}
//
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 0f7d296..cd93dab 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1715,9 +1715,8 @@
return false;
}
- /** @hide */
@Override
- public int getPointerShape(MotionEvent event, float x, float y) {
+ public PointerIcon getPointerIcon(MotionEvent event, float x, float y) {
// Check what the child under the pointer says about the pointer.
final int childrenCount = mChildrenCount;
if (childrenCount != 0) {
@@ -1731,9 +1730,9 @@
? 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;
+ final PointerIcon pointerIcon = child.getPointerIcon(event, point.x, point.y);
+ if (pointerIcon != null) {
+ return pointerIcon;
}
break;
}
@@ -1742,7 +1741,7 @@
// The pointer is not a child or the child has no preferences, returning the default
// implementation.
- return super.getPointerShape(event, x, y);
+ return super.getPointerIcon(event, x, y);
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 12cf66e..faf2640 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -332,6 +332,7 @@
private int mFpsNumFrames;
private int mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
+ private PointerIcon mCustomPointerIcon = null;
/**
* see {@link #playSoundEffect(int)}
@@ -4210,16 +4211,23 @@
final float y = event.getY();
if (event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT
&& 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;
- }
+ PointerIcon pointerIcon = mView.getPointerIcon(event, x, y);
+ int pointerShape = (pointerIcon != null) ?
+ pointerIcon.getStyle() : PointerIcon.STYLE_DEFAULT;
- if (mPointerIconShape != pointerShape) {
- mPointerIconShape = pointerShape;
- final InputDevice inputDevice = event.getDevice();
- if (inputDevice != null) {
- inputDevice.setPointerShape(pointerShape);
+ 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) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5574f86..17c803f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5955,15 +5955,12 @@
return mLayout != null ? mLayout.getHeight() : 0;
}
- /**
- * @hide
- */
@Override
- public int getPointerShape(MotionEvent event, float x, float y) {
+ public PointerIcon getPointerIcon(MotionEvent event, float x, float y) {
if (isTextSelectable() || isTextEditable()) {
- return PointerIcon.STYLE_TEXT;
+ return PointerIcon.getSystemIcon(mContext, PointerIcon.STYLE_TEXT);
}
- return super.getPointerShape(event, x, y);
+ return super.getPointerIcon(event, x, y);
}
@Override
diff --git a/core/jni/android_view_PointerIcon.cpp b/core/jni/android_view_PointerIcon.cpp
index d7e2c02..71be52e 100644
--- a/core/jni/android_view_PointerIcon.cpp
+++ b/core/jni/android_view_PointerIcon.cpp
@@ -65,33 +65,34 @@
return OK;
}
- jobject loadedPointerIconObj = env->CallObjectMethod(pointerIconObj,
- gPointerIconClassInfo.load, contextObj);
- if (env->ExceptionCheck() || !loadedPointerIconObj) {
+ ScopedLocalRef<jobject> loadedPointerIconObj(env, env->CallObjectMethod(pointerIconObj,
+ gPointerIconClassInfo.load, contextObj));
+ if (env->ExceptionCheck() || !loadedPointerIconObj.get()) {
ALOGW("An exception occurred while loading a pointer icon.");
LOGW_EX(env);
env->ExceptionClear();
return UNKNOWN_ERROR;
}
+ return android_view_PointerIcon_getLoadedIcon(env, loadedPointerIconObj.get(), outPointerIcon);
+}
- outPointerIcon->style = env->GetIntField(loadedPointerIconObj,
- gPointerIconClassInfo.mStyle);
- outPointerIcon->hotSpotX = env->GetFloatField(loadedPointerIconObj,
- gPointerIconClassInfo.mHotSpotX);
- outPointerIcon->hotSpotY = env->GetFloatField(loadedPointerIconObj,
- gPointerIconClassInfo.mHotSpotY);
+status_t android_view_PointerIcon_getLoadedIcon(JNIEnv* env, jobject pointerIconObj,
+ PointerIcon* outPointerIcon) {
+ outPointerIcon->style = env->GetIntField(pointerIconObj, gPointerIconClassInfo.mStyle);
+ outPointerIcon->hotSpotX = env->GetFloatField(pointerIconObj, gPointerIconClassInfo.mHotSpotX);
+ outPointerIcon->hotSpotY = env->GetFloatField(pointerIconObj, gPointerIconClassInfo.mHotSpotY);
- jobject bitmapObj = env->GetObjectField(loadedPointerIconObj, gPointerIconClassInfo.mBitmap);
- if (bitmapObj) {
- GraphicsJNI::getSkBitmap(env, bitmapObj, &(outPointerIcon->bitmap));
- env->DeleteLocalRef(bitmapObj);
+ ScopedLocalRef<jobject> bitmapObj(
+ env, env->GetObjectField(pointerIconObj, gPointerIconClassInfo.mBitmap));
+ if (bitmapObj.get()) {
+ GraphicsJNI::getSkBitmap(env, bitmapObj.get(), &(outPointerIcon->bitmap));
}
ScopedLocalRef<jobjectArray> bitmapFramesObj(env, reinterpret_cast<jobjectArray>(
- env->GetObjectField(loadedPointerIconObj, gPointerIconClassInfo.mBitmapFrames)));
+ env->GetObjectField(pointerIconObj, gPointerIconClassInfo.mBitmapFrames)));
if (bitmapFramesObj.get()) {
outPointerIcon->durationPerFrame = env->GetIntField(
- loadedPointerIconObj, gPointerIconClassInfo.mDurationPerFrame);
+ pointerIconObj, gPointerIconClassInfo.mDurationPerFrame);
jsize size = env->GetArrayLength(bitmapFramesObj.get());
outPointerIcon->bitmapFrames.resize(size);
for (jsize i = 0; i < size; ++i) {
@@ -100,7 +101,6 @@
}
}
- env->DeleteLocalRef(loadedPointerIconObj);
return OK;
}
diff --git a/core/jni/android_view_PointerIcon.h b/core/jni/android_view_PointerIcon.h
index ca08085..00bdfb4 100644
--- a/core/jni/android_view_PointerIcon.h
+++ b/core/jni/android_view_PointerIcon.h
@@ -97,6 +97,11 @@
extern status_t android_view_PointerIcon_load(JNIEnv* env,
jobject pointerIconObj, jobject contextObj, PointerIcon* outPointerIcon);
+/* Obtain the data of pointerIconObj and put to outPointerIcon. */
+extern status_t android_view_PointerIcon_getLoadedIcon(JNIEnv* env, jobject pointerIconObj,
+ PointerIcon* outPointerIcon);
+
+
/* Loads the bitmap associated with a pointer icon by style.
* If pointerIconObj is NULL, returns OK and a pointer icon with POINTER_ICON_STYLE_NULL. */
extern status_t android_view_PointerIcon_loadSystemIcon(JNIEnv* env,
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 6a1167a..529849e 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -439,6 +439,17 @@
}
}
+void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
+ AutoMutex _l(mLock);
+
+ const int32_t iconId = mPolicy->getCustomPointerIconId();
+ mLocked.additionalMouseResources[iconId] = icon;
+ mLocked.requestedPointerShape = iconId;
+ mLocked.presentationChanged = true;
+
+ updatePointerLocked();
+}
+
void PointerController::handleMessage(const Message& message) {
switch (message.what) {
case MSG_INACTIVITY_TIMEOUT:
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 4fd2d85..9ba37b3 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -67,6 +67,7 @@
virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
std::map<int32_t, PointerAnimation>* outAnimationResources) = 0;
virtual int32_t getDefaultPointerIconId() = 0;
+ virtual int32_t getCustomPointerIconId() = 0;
};
@@ -105,6 +106,7 @@
virtual void clearSpots();
void updatePointerShape(int32_t iconId);
+ void setCustomPointerIcon(const SpriteIcon& icon);
void setDisplayViewport(int32_t width, int32_t height, int32_t orientation);
void setInactivityTimeout(InactivityTimeout inactivityTimeout);
void reloadPointerResources();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 93264ff..c01f170 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -30,6 +30,7 @@
import android.view.Display;
import android.view.DisplayInfo;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View.OnTouchListener;
@@ -118,8 +119,8 @@
updateDisplayInfo();
boolean landscape = getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE;
- mHandle.setPointerShape(
- landscape ? STYLE_HORIZONTAL_DOUBLE_ARROW : STYLE_VERTICAL_DOUBLE_ARROW);
+ mHandle.setPointerIcon(PointerIcon.getSystemIcon(getContext(),
+ landscape ? STYLE_HORIZONTAL_DOUBLE_ARROW : STYLE_VERTICAL_DOUBLE_ARROW));
getViewTreeObserver().addOnComputeInternalInsetsListener(this);
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index f2d0031..8b37383 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -213,6 +213,7 @@
private static native void nativeMonitor(long ptr);
private static native void nativeSetPointerIconShape(long ptr, int iconId);
private static native void nativeReloadPointerIcons(long ptr);
+ private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon);
// Input event injection constants defined in InputDispatcher.h.
private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
@@ -1451,6 +1452,12 @@
nativeSetPointerIconShape(mPtr, iconId);
}
+ // Binder call
+ @Override
+ public void setCustomPointerIcon(PointerIcon icon) {
+ nativeSetCustomPointerIcon(mPtr, icon);
+ }
+
@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 9c9a5da..4c8474a 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -206,6 +206,7 @@
void reloadCalibration();
void setPointerIconShape(int32_t iconId);
void reloadPointerIcons();
+ void setCustomPointerIcon(const SpriteIcon& icon);
/* --- InputReaderPolicyInterface implementation --- */
@@ -248,6 +249,7 @@
virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
std::map<int32_t, PointerAnimation>* outAnimationResources);
virtual int32_t getDefaultPointerIconId();
+ virtual int32_t getCustomPointerIconId();
private:
sp<InputManager> mInputManager;
@@ -790,6 +792,14 @@
}
}
+void NativeInputManager::setCustomPointerIcon(const SpriteIcon& icon) {
+ AutoMutex _l(mLock);
+ sp<PointerController> controller = mLocked.pointerController.promote();
+ if (controller != NULL) {
+ controller->setCustomPointerIcon(icon);
+ }
+}
+
TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
JNIEnv *env, jfloatArray matrixArr) {
ScopedFloatArrayRO matrix(env, matrixArr);
@@ -1090,6 +1100,10 @@
return POINTER_ICON_STYLE_ARROW;
}
+int32_t NativeInputManager::getCustomPointerIconId() {
+ return POINTER_ICON_STYLE_CUSTOM;
+}
+
// ----------------------------------------------------------------------------
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
@@ -1437,6 +1451,20 @@
im->reloadPointerIcons();
}
+static void nativeSetCustomPointerIcon(JNIEnv* env, jclass /* clazz */,
+ jlong ptr, jobject iconObj) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+ PointerIcon pointerIcon;
+ android_view_PointerIcon_getLoadedIcon(env, iconObj, &pointerIcon);
+
+ SpriteIcon spriteIcon;
+ pointerIcon.bitmap.copyTo(&spriteIcon.bitmap, kN32_SkColorType);
+ spriteIcon.hotSpotX = pointerIcon.hotSpotX;
+ spriteIcon.hotSpotY = pointerIcon.hotSpotY;
+ im->setCustomPointerIcon(spriteIcon);
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gInputManagerMethods[] = {
@@ -1499,6 +1527,8 @@
(void*) nativeSetPointerIconShape },
{ "nativeReloadPointerIcons", "(J)V",
(void*) nativeReloadPointerIcons },
+ { "nativeSetCustomPointerIcon", "(JLandroid/view/PointerIcon;)V",
+ (void*) nativeSetCustomPointerIcon },
};
#define FIND_CLASS(var, className) \