summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/view/PointerIcon.aidl19
-rw-r--r--core/java/android/view/PointerIcon.java435
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android_view_PointerIcon.cpp149
-rw-r--r--core/jni/android_view_PointerIcon.h80
-rw-r--r--core/res/res/drawable-mdpi/pointer_spot_anchor.pngbin0 -> 6817 bytes
-rw-r--r--core/res/res/drawable-mdpi/pointer_spot_anchor_icon.xml5
-rw-r--r--core/res/res/drawable-mdpi/pointer_spot_hover.pngbin0 -> 9669 bytes
-rw-r--r--core/res/res/drawable-mdpi/pointer_spot_hover_icon.xml5
-rw-r--r--core/res/res/drawable-mdpi/pointer_spot_touch.pngbin0 -> 2880 bytes
-rw-r--r--core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml5
-rwxr-xr-xcore/res/res/values/attrs.xml18
-rw-r--r--core/res/res/values/styles.xml8
-rw-r--r--core/res/res/values/themes.xml2
15 files changed, 729 insertions, 0 deletions
diff --git a/core/java/android/view/PointerIcon.aidl b/core/java/android/view/PointerIcon.aidl
new file mode 100644
index 0000000..b09340b
--- /dev/null
+++ b/core/java/android/view/PointerIcon.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+parcelable PointerIcon;
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
new file mode 100644
index 0000000..bb7ed41
--- /dev/null
+++ b/core/java/android/view/PointerIcon.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import com.android.internal.util.XmlUtils;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Represents an icon that can be used as a mouse pointer.
+ * <p>
+ * 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. */
+ public static final int STYLE_CUSTOM = -1;
+
+ /** Style constant: Null icon. It has no bitmap. */
+ public static final int STYLE_NULL = 0;
+
+ /** Style constant: Arrow icon. (Default mouse pointer) */
+ public static final int STYLE_ARROW = 1000;
+
+ /** {@hide} Style constant: Spot hover icon for touchpads. */
+ public static final int STYLE_SPOT_HOVER = 2000;
+
+ /** {@hide} Style constant: Spot touch icon for touchpads. */
+ public static final int STYLE_SPOT_TOUCH = 2001;
+
+ /** {@hide} Style constant: Spot anchor icon for touchpads. */
+ public static final int STYLE_SPOT_ANCHOR = 2002;
+
+ // 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;
+
+ private static final PointerIcon gNullIcon = new PointerIcon(STYLE_NULL);
+
+ private final int mStyle;
+ private int mSystemIconResourceId;
+ private Bitmap mBitmap;
+ private float mHotSpotX;
+ private float mHotSpotY;
+
+ private PointerIcon(int style) {
+ mStyle = style;
+ }
+
+ /**
+ * Gets a special pointer icon that has no bitmap.
+ *
+ * @return The null pointer icon.
+ *
+ * @see #STYLE_NULL
+ */
+ public static PointerIcon getNullIcon() {
+ return gNullIcon;
+ }
+
+ /**
+ * Gets the default pointer icon.
+ *
+ * @param context The context.
+ * @return The default pointer icon.
+ *
+ * @throws IllegalArgumentException if context is null.
+ */
+ public static PointerIcon getDefaultIcon(Context context) {
+ return getSystemIcon(context, STYLE_DEFAULT);
+ }
+
+ /**
+ * Gets a system pointer icon for the given style.
+ * If style is not recognized, returns the default pointer icon.
+ *
+ * @param context The context.
+ * @param style The pointer icon style.
+ * @return The pointer icon.
+ *
+ * @throws IllegalArgumentException if context is null.
+ */
+ public static PointerIcon getSystemIcon(Context context, int style) {
+ if (context == null) {
+ throw new IllegalArgumentException("context must not be null");
+ }
+
+ if (style == STYLE_NULL) {
+ return gNullIcon;
+ }
+
+ int styleIndex = getSystemIconStyleIndex(style);
+ if (styleIndex == 0) {
+ styleIndex = getSystemIconStyleIndex(STYLE_DEFAULT);
+ }
+
+ TypedArray a = context.obtainStyledAttributes(null,
+ com.android.internal.R.styleable.Pointer,
+ com.android.internal.R.attr.pointerStyle, 0);
+ int resourceId = a.getResourceId(styleIndex, -1);
+ a.recycle();
+
+ if (resourceId == -1) {
+ Log.w(TAG, "Missing theme resources for pointer icon style " + style);
+ return style == STYLE_DEFAULT ? gNullIcon : getSystemIcon(context, STYLE_DEFAULT);
+ }
+
+ PointerIcon icon = new PointerIcon(style);
+ if ((resourceId & 0xff000000) == 0x01000000) {
+ icon.mSystemIconResourceId = resourceId;
+ } else {
+ icon.loadResource(context.getResources(), resourceId);
+ }
+ return icon;
+ }
+
+ /**
+ * Creates a custom pointer from the given bitmap and hotspot information.
+ *
+ * @param bitmap The bitmap for the icon.
+ * @param hotspotX The X offset of the pointer icon hotspot in the bitmap.
+ * Must be within the [0, bitmap.getWidth()) range.
+ * @param hotspotY The Y offset of the pointer icon hotspot in the bitmap.
+ * Must be within the [0, bitmap.getHeight()) range.
+ * @return A pointer icon for this bitmap.
+ *
+ * @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) {
+ if (bitmap == null) {
+ throw new IllegalArgumentException("bitmap must not be null");
+ }
+ validateHotSpot(bitmap, hotSpotX, hotSpotY);
+
+ PointerIcon icon = new PointerIcon(STYLE_CUSTOM);
+ icon.mBitmap = bitmap;
+ icon.mHotSpotX = hotSpotX;
+ icon.mHotSpotY = hotSpotY;
+ return icon;
+ }
+
+ /**
+ * Loads a custom pointer icon from an XML resource.
+ * <p>
+ * The XML resource should have the following form:
+ * <code>
+ * &lt;?xml version="1.0" encoding="utf-8"?&gt;
+ * &lt;pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ * android:bitmap="@drawable/my_pointer_bitmap"
+ * android:hotSpotX="24"
+ * android:hotSpotY="24" /&gt;
+ * </code>
+ * </p>
+ *
+ * @param resources The resources object.
+ * @param resourceId The resource id.
+ * @return The pointer icon.
+ *
+ * @throws IllegalArgumentException if resources is null.
+ * @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, int resourceId) {
+ if (resources == null) {
+ throw new IllegalArgumentException("resources must not be null");
+ }
+
+ PointerIcon icon = new PointerIcon(STYLE_CUSTOM);
+ icon.loadResource(resources, resourceId);
+ return icon;
+ }
+
+ /**
+ * Loads the bitmap and hotspot information for a pointer icon, if it is not already loaded.
+ * Returns a pointer icon (not necessarily the same instance) with the information filled in.
+ *
+ * @param context The context.
+ * @return The loaded pointer icon.
+ *
+ * @throws IllegalArgumentException if context is null.
+ * @see #isLoaded()
+ * @hide
+ */
+ public PointerIcon load(Context context) {
+ if (context == null) {
+ throw new IllegalArgumentException("context must not be null");
+ }
+
+ if (mSystemIconResourceId == 0 || mBitmap != null) {
+ return this;
+ }
+
+ PointerIcon result = new PointerIcon(mStyle);
+ result.mSystemIconResourceId = mSystemIconResourceId;
+ result.loadResource(context.getResources(), mSystemIconResourceId);
+ 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.
+ */
+ 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) {
+ int style = in.readInt();
+ if (style == STYLE_NULL) {
+ return getNullIcon();
+ }
+
+ int systemIconResourceId = in.readInt();
+ if (systemIconResourceId != 0) {
+ PointerIcon icon = new PointerIcon(style);
+ icon.mSystemIconResourceId = systemIconResourceId;
+ return icon;
+ }
+
+ Bitmap bitmap = Bitmap.CREATOR.createFromParcel(in);
+ float hotSpotX = in.readFloat();
+ float hotSpotY = in.readFloat();
+ return PointerIcon.createCustomIcon(bitmap, hotSpotX, hotSpotY);
+ }
+
+ public PointerIcon[] newArray(int size) {
+ return new PointerIcon[size];
+ }
+ };
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mStyle);
+
+ if (mStyle != STYLE_NULL) {
+ out.writeInt(mSystemIconResourceId);
+ if (mSystemIconResourceId == 0) {
+ mBitmap.writeToParcel(out, flags);
+ out.writeFloat(mHotSpotX);
+ out.writeFloat(mHotSpotY);
+ }
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || !(other instanceof PointerIcon)) {
+ return false;
+ }
+
+ PointerIcon otherIcon = (PointerIcon) other;
+ if (mStyle != otherIcon.mStyle
+ || mSystemIconResourceId != otherIcon.mSystemIconResourceId) {
+ return false;
+ }
+
+ if (mSystemIconResourceId == 0 && (mBitmap != otherIcon.mBitmap
+ || mHotSpotX != otherIcon.mHotSpotX
+ || mHotSpotY != otherIcon.mHotSpotY)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private void loadResource(Resources resources, int resourceId) {
+ XmlResourceParser parser = resources.getXml(resourceId);
+ final int bitmapRes;
+ final float hotSpotX;
+ final float hotSpotY;
+ try {
+ XmlUtils.beginDocument(parser, "pointer-icon");
+
+ TypedArray a = resources.obtainAttributes(
+ parser, com.android.internal.R.styleable.PointerIcon);
+ bitmapRes = a.getResourceId(com.android.internal.R.styleable.PointerIcon_bitmap, 0);
+ hotSpotX = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotX, 0);
+ hotSpotY = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotY, 0);
+ a.recycle();
+ } catch (Exception ex) {
+ throw new IllegalArgumentException("Exception parsing pointer icon resource.", ex);
+ } finally {
+ parser.close();
+ }
+
+ if (bitmapRes == 0) {
+ throw new IllegalArgumentException("<pointer-icon> is missing bitmap attribute.");
+ }
+
+ Drawable drawable = resources.getDrawable(bitmapRes);
+ if (!(drawable instanceof BitmapDrawable)) {
+ throw new IllegalArgumentException("<pointer-icon> bitmap attribute must "
+ + "refer to a bitmap drawable.");
+ }
+
+ // Set the properties now that we have successfully loaded the icon.
+ mBitmap = ((BitmapDrawable)drawable).getBitmap();
+ mHotSpotX = hotSpotX;
+ mHotSpotY = hotSpotY;
+ }
+
+ private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY) {
+ if (hotSpotX < 0 || hotSpotX >= bitmap.getWidth()) {
+ throw new IllegalArgumentException("x hotspot lies outside of the bitmap area");
+ }
+ if (hotSpotY < 0 || hotSpotY >= bitmap.getHeight()) {
+ throw new IllegalArgumentException("y hotspot lies outside of the bitmap area");
+ }
+ }
+
+ private static int getSystemIconStyleIndex(int style) {
+ switch (style) {
+ case STYLE_ARROW:
+ return com.android.internal.R.styleable.Pointer_pointerIconArrow;
+ case STYLE_SPOT_HOVER:
+ return com.android.internal.R.styleable.Pointer_pointerIconSpotHover;
+ case STYLE_SPOT_TOUCH:
+ return com.android.internal.R.styleable.Pointer_pointerIconSpotTouch;
+ case STYLE_SPOT_ANCHOR:
+ return com.android.internal.R.styleable.Pointer_pointerIconSpotAnchor;
+ default:
+ return 0;
+ }
+ }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f8f8761..290f528 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -54,6 +54,7 @@ LOCAL_SRC_FILES:= \
android_view_KeyCharacterMap.cpp \
android_view_GLES20Canvas.cpp \
android_view_MotionEvent.cpp \
+ android_view_PointerIcon.cpp \
android_view_VelocityTracker.cpp \
android_text_AndroidCharacter.cpp \
android_text_AndroidBidi.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index b628b9d..a4a229a 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -170,6 +170,7 @@ extern int register_android_view_InputChannel(JNIEnv* env);
extern int register_android_view_InputQueue(JNIEnv* env);
extern int register_android_view_KeyEvent(JNIEnv* env);
extern int register_android_view_MotionEvent(JNIEnv* env);
+extern int register_android_view_PointerIcon(JNIEnv* env);
extern int register_android_view_VelocityTracker(JNIEnv* env);
extern int register_android_content_res_ObbScanner(JNIEnv* env);
extern int register_android_content_res_Configuration(JNIEnv* env);
@@ -1212,6 +1213,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_view_InputQueue),
REG_JNI(register_android_view_KeyEvent),
REG_JNI(register_android_view_MotionEvent),
+ REG_JNI(register_android_view_PointerIcon),
REG_JNI(register_android_view_VelocityTracker),
REG_JNI(register_android_content_res_ObbScanner),
diff --git a/core/jni/android_view_PointerIcon.cpp b/core/jni/android_view_PointerIcon.cpp
new file mode 100644
index 0000000..091341a
--- /dev/null
+++ b/core/jni/android_view_PointerIcon.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PointerIcon-JNI"
+
+#include "JNIHelp.h"
+
+#include "android_view_PointerIcon.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/Log.h>
+#include <android/graphics/GraphicsJNI.h>
+
+namespace android {
+
+static struct {
+ jclass clazz;
+ jfieldID mStyle;
+ jfieldID mBitmap;
+ jfieldID mHotSpotX;
+ jfieldID mHotSpotY;
+ jmethodID getSystemIcon;
+ jmethodID load;
+} gPointerIconClassInfo;
+
+
+// --- Global Functions ---
+
+jobject android_view_PointerIcon_getSystemIcon(JNIEnv* env, jobject contextObj, int32_t style) {
+ jobject pointerIconObj = env->CallStaticObjectMethod(gPointerIconClassInfo.clazz,
+ gPointerIconClassInfo.getSystemIcon, contextObj, style);
+ if (env->ExceptionCheck()) {
+ LOGW("An exception occurred while getting a pointer icon with style %d.", style);
+ LOGW_EX(env);
+ env->ExceptionClear();
+ return NULL;
+ }
+ return pointerIconObj;
+}
+
+status_t android_view_PointerIcon_load(JNIEnv* env, jobject pointerIconObj, jobject contextObj,
+ PointerIcon* outPointerIcon) {
+ outPointerIcon->reset();
+
+ if (!pointerIconObj) {
+ return OK;
+ }
+
+ jobject loadedPointerIconObj = env->CallObjectMethod(pointerIconObj,
+ gPointerIconClassInfo.load, contextObj);
+ if (env->ExceptionCheck() || !loadedPointerIconObj) {
+ LOGW("An exception occurred while loading a pointer icon.");
+ LOGW_EX(env);
+ env->ExceptionClear();
+ return UNKNOWN_ERROR;
+ }
+
+ outPointerIcon->style = env->GetIntField(loadedPointerIconObj,
+ gPointerIconClassInfo.mStyle);
+ outPointerIcon->hotSpotX = env->GetFloatField(loadedPointerIconObj,
+ gPointerIconClassInfo.mHotSpotX);
+ outPointerIcon->hotSpotY = env->GetFloatField(loadedPointerIconObj,
+ gPointerIconClassInfo.mHotSpotY);
+
+ jobject bitmapObj = env->GetObjectField(loadedPointerIconObj, gPointerIconClassInfo.mBitmap);
+ if (bitmapObj) {
+ SkBitmap* bitmap = GraphicsJNI::getNativeBitmap(env, bitmapObj);
+ if (bitmap) {
+ outPointerIcon->bitmap = *bitmap; // use a shared pixel ref
+ }
+ env->DeleteLocalRef(bitmapObj);
+ }
+
+ env->DeleteLocalRef(loadedPointerIconObj);
+ return OK;
+}
+
+status_t android_view_PointerIcon_loadSystemIcon(JNIEnv* env, jobject contextObj,
+ int32_t style, PointerIcon* outPointerIcon) {
+ jobject pointerIconObj = android_view_PointerIcon_getSystemIcon(env, contextObj, style);
+ if (!pointerIconObj) {
+ outPointerIcon->reset();
+ return UNKNOWN_ERROR;
+ }
+
+ status_t status = android_view_PointerIcon_load(env, pointerIconObj,
+ contextObj, outPointerIcon);
+ env->DeleteLocalRef(pointerIconObj);
+ return status;
+}
+
+
+// --- JNI Registration ---
+
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#define GET_STATIC_METHOD_ID(var, clazz, methodName, methodDescriptor) \
+ var = env->GetStaticMethodID(clazz, methodName, methodDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find method " methodName);
+
+#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
+ var = env->GetMethodID(clazz, methodName, methodDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find method " methodName);
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+ var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_view_PointerIcon(JNIEnv* env) {
+ FIND_CLASS(gPointerIconClassInfo.clazz, "android/view/PointerIcon");
+
+ GET_FIELD_ID(gPointerIconClassInfo.mBitmap, gPointerIconClassInfo.clazz,
+ "mBitmap", "Landroid/graphics/Bitmap;");
+
+ GET_FIELD_ID(gPointerIconClassInfo.mStyle, gPointerIconClassInfo.clazz,
+ "mStyle", "I");
+
+ GET_FIELD_ID(gPointerIconClassInfo.mHotSpotX, gPointerIconClassInfo.clazz,
+ "mHotSpotX", "F");
+
+ GET_FIELD_ID(gPointerIconClassInfo.mHotSpotY, gPointerIconClassInfo.clazz,
+ "mHotSpotY", "F");
+
+ GET_STATIC_METHOD_ID(gPointerIconClassInfo.getSystemIcon, gPointerIconClassInfo.clazz,
+ "getSystemIcon", "(Landroid/content/Context;I)Landroid/view/PointerIcon;");
+
+ GET_METHOD_ID(gPointerIconClassInfo.load, gPointerIconClassInfo.clazz,
+ "load", "(Landroid/content/Context;)Landroid/view/PointerIcon;");
+
+ return 0;
+}
+
+} // namespace android
diff --git a/core/jni/android_view_PointerIcon.h b/core/jni/android_view_PointerIcon.h
new file mode 100644
index 0000000..3bfd645
--- /dev/null
+++ b/core/jni/android_view_PointerIcon.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_VIEW_POINTER_ICON_H
+#define _ANDROID_VIEW_POINTER_ICON_H
+
+#include "jni.h"
+
+#include <utils/Errors.h>
+#include <SkBitmap.h>
+
+namespace android {
+
+/* Pointer icon styles.
+ * Must match the definition in android.view.PointerIcon.
+ */
+enum {
+ POINTER_ICON_STYLE_CUSTOM = -1,
+ POINTER_ICON_STYLE_NULL = 0,
+ POINTER_ICON_STYLE_ARROW = 1000,
+ POINTER_ICON_STYLE_SPOT_HOVER = 2000,
+ POINTER_ICON_STYLE_SPOT_TOUCH = 2001,
+ POINTER_ICON_STYLE_SPOT_ANCHOR = 2002,
+};
+
+/*
+ * Describes a pointer icon.
+ */
+struct PointerIcon {
+ inline PointerIcon() {
+ reset();
+ }
+
+ int32_t style;
+ SkBitmap bitmap;
+ float hotSpotX;
+ float hotSpotY;
+
+ inline bool isNullIcon() {
+ return style == POINTER_ICON_STYLE_NULL;
+ }
+
+ inline void reset() {
+ style = POINTER_ICON_STYLE_NULL;
+ bitmap.reset();
+ hotSpotX = 0;
+ hotSpotY = 0;
+ }
+};
+
+/* Gets a system pointer icon with the specified style. */
+extern jobject android_view_PointerIcon_getSystemIcon(JNIEnv* env,
+ jobject contextObj, int32_t style);
+
+/* Loads the bitmap associated with a pointer icon.
+ * If pointerIconObj is NULL, returns OK and a pointer icon with POINTER_ICON_STYLE_NULL. */
+extern status_t android_view_PointerIcon_load(JNIEnv* env,
+ jobject pointerIconObj, jobject contextObj, 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,
+ jobject contextObj, int32_t style, PointerIcon* outPointerIcon);
+
+} // namespace android
+
+#endif // _ANDROID_OS_POINTER_ICON_H
diff --git a/core/res/res/drawable-mdpi/pointer_spot_anchor.png b/core/res/res/drawable-mdpi/pointer_spot_anchor.png
new file mode 100644
index 0000000..d7aca36
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_spot_anchor.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_spot_anchor_icon.xml b/core/res/res/drawable-mdpi/pointer_spot_anchor_icon.xml
new file mode 100644
index 0000000..2222b8e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_spot_anchor_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_spot_anchor"
+ android:hotSpotX="33"
+ android:hotSpotY="33" />
diff --git a/core/res/res/drawable-mdpi/pointer_spot_hover.png b/core/res/res/drawable-mdpi/pointer_spot_hover.png
new file mode 100644
index 0000000..5041aa3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_spot_hover.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_spot_hover_icon.xml b/core/res/res/drawable-mdpi/pointer_spot_hover_icon.xml
new file mode 100644
index 0000000..dc62a69
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_spot_hover_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_spot_hover"
+ android:hotSpotX="33"
+ android:hotSpotY="33" />
diff --git a/core/res/res/drawable-mdpi/pointer_spot_touch.png b/core/res/res/drawable-mdpi/pointer_spot_touch.png
new file mode 100644
index 0000000..64a42a1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_spot_touch.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml b/core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml
new file mode 100644
index 0000000..4bffee6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_spot_touch"
+ android:hotSpotX="24"
+ android:hotSpotY="24" />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 819ce58..e8767d8 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -757,6 +757,13 @@
<!-- Default style for the Switch widget. -->
<attr name="switchStyle" format="reference" />
+ <!-- ============== -->
+ <!-- Pointer styles -->
+ <!-- ============== -->
+ <eat-comment />
+
+ <!-- Reference to the Pointer style -->
+ <attr name="pointerStyle" format="reference" />
</declare-styleable>
<!-- **************************************************************** -->
@@ -4921,6 +4928,17 @@
<attr name="switchPadding" format="dimension" />
</declare-styleable>
+ <declare-styleable name="Pointer">
+ <!-- Reference to a pointer icon drawable with STYLE_ARROW -->
+ <attr name="pointerIconArrow" format="reference" />
+ <!-- Reference to a pointer icon drawable with STYLE_SPOT_HOVER -->
+ <attr name="pointerIconSpotHover" format="reference" />
+ <!-- Reference to a pointer icon drawable with STYLE_SPOT_TOUCH -->
+ <attr name="pointerIconSpotTouch" format="reference" />
+ <!-- Reference to a pointer icon drawable with STYLE_SPOT_ANCHOR -->
+ <attr name="pointerIconSpotAnchor" format="reference" />
+ </declare-styleable>
+
<declare-styleable name="PointerIcon">
<!-- Drawable to use as the icon bitmap. -->
<attr name="bitmap" format="reference" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index bf4c6d7..b4042c0 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -2210,4 +2210,12 @@
<item name="android:borderLeft">0dip</item>
<item name="android:borderRight">0dip</item>
</style>
+
+ <!-- Pointer styles -->
+ <style name="Pointer">
+ <item name="android:pointerIconArrow">@android:drawable/pointer_arrow_icon</item>
+ <item name="android:pointerIconSpotHover">@android:drawable/pointer_spot_hover_icon</item>
+ <item name="android:pointerIconSpotTouch">@android:drawable/pointer_spot_touch_icon</item>
+ <item name="android:pointerIconSpotAnchor">@android:drawable/pointer_spot_anchor_icon</item>
+ </style>
</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index b1e4f0f..0748b10 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -323,6 +323,8 @@
<item name="fastScrollOverlayPosition">floating</item>
<item name="fastScrollTextColor">@android:color/primary_text_dark</item>
+ <!-- Pointer style -->
+ <item name="pointerStyle">@android:style/Pointer</item>
</style>
<!-- Variant of the default (dark) theme with no title bar -->