Make public pointer icon API with custom icons.

BUG: 25778347, 23804184
Change-Id: If138b97c750c912e9848412c27b65004899961eb
This commit is contained in:
Jun Mukai
2015-10-30 15:54:33 -07:00
parent 40aa9f1b98
commit d4eaef7f4c
18 changed files with 269 additions and 165 deletions

View File

@ -40337,6 +40337,38 @@ package android.view {
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 @@ package android.view {
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 @@ package android.view {
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);

View File

@ -42675,6 +42675,38 @@ package android.view {
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 @@ package android.view {
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 @@ package android.view {
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);

View File

@ -40339,6 +40339,38 @@ package android.view {
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 @@ package android.view {
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 @@ package android.view {
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);

View File

@ -24,6 +24,7 @@ import android.hardware.input.TouchCalibration;
import android.os.IBinder;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.PointerIcon;
/** @hide */
interface IInputManager {
@ -71,4 +72,5 @@ interface IInputManager {
void cancelVibrate(int deviceId, IBinder token);
void setPointerIconShape(int shapeId);
void setCustomPointerIcon(in PointerIcon icon);
}

View File

@ -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 @@ public final class InputManager {
}
}
/** @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();

View File

@ -783,6 +783,15 @@ public final class InputDevice implements Parcelable {
InputManager.getInstance().setPointerIconShape(pointerShape);
}
/**
* 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.
*

View File

@ -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 @@ import android.util.Log;
* 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 @@ public final class PointerIcon implements Parcelable {
/** 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 @@ public final class PointerIcon implements Parcelable {
// 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 @@ public final class PointerIcon implements Parcelable {
* @return The null pointer icon.
*
* @see #STYLE_NULL
* @hide
*/
public static PointerIcon getNullIcon() {
return gNullIcon;
@ -172,8 +175,9 @@ public final class PointerIcon implements Parcelable {
* @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 @@ public final class PointerIcon implements Parcelable {
*
* @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 @@ public final class PointerIcon implements Parcelable {
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 @@ public final class PointerIcon implements Parcelable {
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 @@ public final class PointerIcon implements Parcelable {
* @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 @@ public final class PointerIcon implements Parcelable {
* @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 @@ public final class PointerIcon implements Parcelable {
* @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 @@ public final class PointerIcon implements Parcelable {
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) {

View File

@ -2628,7 +2628,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
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;
@ -2637,15 +2637,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
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
@ -3926,6 +3921,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
private HandlerActionQueue mRunQueue;
/**
* The pointer icon when the mouse hovers on this view. The default is null.
*/
private PointerIcon mPointerIcon;
/**
* @hide
*/
@ -4490,7 +4490,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
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 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
/** @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;
}
//

View File

@ -1715,9 +1715,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
? 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// 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);
}
/**

View File

@ -332,6 +332,7 @@ public final class ViewRootImpl implements ViewParent,
private int mFpsNumFrames;
private int mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
private PointerIcon mCustomPointerIcon = null;
/**
* see {@link #playSoundEffect(int)}
@ -4210,16 +4211,23 @@ public final class ViewRootImpl implements ViewParent,
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) {

View File

@ -5955,15 +5955,12 @@ 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) {
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

View File

@ -65,33 +65,34 @@ status_t android_view_PointerIcon_load(JNIEnv* env, jobject pointerIconObj, jobj
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 @@ status_t android_view_PointerIcon_load(JNIEnv* env, jobject pointerIconObj, jobj
}
}
env->DeleteLocalRef(loadedPointerIconObj);
return OK;
}

View File

@ -97,6 +97,11 @@ extern jobject android_view_PointerIcon_getSystemIcon(JNIEnv* env,
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,

View File

@ -439,6 +439,17 @@ void PointerController::updatePointerShape(int32_t iconId) {
}
}
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:

View File

@ -67,6 +67,7 @@ public:
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 @@ public:
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();

View File

@ -30,6 +30,7 @@ import android.util.AttributeSet;
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 @@ public class DividerView extends FrameLayout implements OnTouchListener,
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);
}

View File

@ -213,6 +213,7 @@ public class InputManagerService extends IInputManager.Stub
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 @@ public class InputManagerService extends IInputManager.Stub
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)

View File

@ -206,6 +206,7 @@ public:
void reloadCalibration();
void setPointerIconShape(int32_t iconId);
void reloadPointerIcons();
void setCustomPointerIcon(const SpriteIcon& icon);
/* --- InputReaderPolicyInterface implementation --- */
@ -248,6 +249,7 @@ public:
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::reloadPointerIcons() {
}
}
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 @@ int32_t NativeInputManager::getDefaultPointerIconId() {
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 @@ static void nativeReloadPointerIcons(JNIEnv* /* env */, jclass /* clazz */, jlon
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 @@ static const JNINativeMethod gInputManagerMethods[] = {
(void*) nativeSetPointerIconShape },
{ "nativeReloadPointerIcons", "(J)V",
(void*) nativeReloadPointerIcons },
{ "nativeSetCustomPointerIcon", "(JLandroid/view/PointerIcon;)V",
(void*) nativeSetCustomPointerIcon },
};
#define FIND_CLASS(var, className) \