am 86ea1f5f: Initial checkin of spot presentation for touchpad gestures. (DO NOT MERGE)
* commit '86ea1f5f521981d075aef56f11693e4f3bc32fdb': Initial checkin of spot presentation for touchpad gestures. (DO NOT MERGE)
This commit is contained in:
@@ -14,32 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SpotController"
|
||||
package android.view;
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
// Log debug messages about spot updates
|
||||
#define DEBUG_SPOT_UPDATES 0
|
||||
|
||||
#include "SpotController.h"
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// --- SpotController ---
|
||||
|
||||
SpotController::SpotController(const sp<Looper>& looper,
|
||||
const sp<SpriteController>& spriteController) :
|
||||
mLooper(looper), mSpriteController(spriteController) {
|
||||
mHandler = new WeakMessageHandler(this);
|
||||
}
|
||||
|
||||
SpotController::~SpotController() {
|
||||
mLooper->removeMessages(mHandler);
|
||||
}
|
||||
|
||||
void SpotController:: handleMessage(const Message& message) {
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
parcelable PointerIcon;
|
||||
435
core/java/android/view/PointerIcon.java
Normal file
435
core/java/android/view/PointerIcon.java
Normal file
@@ -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>
|
||||
* <?xml version="1.0" encoding="utf-8"?>
|
||||
* <pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* android:bitmap="@drawable/my_pointer_bitmap"
|
||||
* android:hotSpotX="24"
|
||||
* android:hotSpotY="24" />
|
||||
* </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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 \
|
||||
|
||||
@@ -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);
|
||||
@@ -1303,6 +1304,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),
|
||||
|
||||
149
core/jni/android_view_PointerIcon.cpp
Normal file
149
core/jni/android_view_PointerIcon.cpp
Normal file
@@ -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
|
||||
80
core/jni/android_view_PointerIcon.h
Normal file
80
core/jni/android_view_PointerIcon.h
Normal file
@@ -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
|
||||
BIN
core/res/res/drawable-mdpi/pointer_spot_anchor.png
Normal file
BIN
core/res/res/drawable-mdpi/pointer_spot_anchor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
5
core/res/res/drawable-mdpi/pointer_spot_anchor_icon.xml
Normal file
5
core/res/res/drawable-mdpi/pointer_spot_anchor_icon.xml
Normal file
@@ -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" />
|
||||
BIN
core/res/res/drawable-mdpi/pointer_spot_hover.png
Normal file
BIN
core/res/res/drawable-mdpi/pointer_spot_hover.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
5
core/res/res/drawable-mdpi/pointer_spot_hover_icon.xml
Normal file
5
core/res/res/drawable-mdpi/pointer_spot_hover_icon.xml
Normal file
@@ -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" />
|
||||
BIN
core/res/res/drawable-mdpi/pointer_spot_touch.png
Normal file
BIN
core/res/res/drawable-mdpi/pointer_spot_touch.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
5
core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml
Normal file
5
core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml
Normal file
@@ -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" />
|
||||
@@ -746,6 +746,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>
|
||||
|
||||
<!-- **************************************************************** -->
|
||||
@@ -4873,6 +4880,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" />
|
||||
|
||||
@@ -2187,4 +2187,12 @@
|
||||
<item name="android:borderLeft">@dimen/preference_fragment_padding_side</item>
|
||||
<item name="android:borderRight">@dimen/preference_fragment_padding_side</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>
|
||||
|
||||
@@ -321,6 +321,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 -->
|
||||
|
||||
@@ -608,6 +608,11 @@ private:
|
||||
// Oldest sample to consider when calculating the velocity.
|
||||
static const nsecs_t MAX_AGE = 200 * 1000000; // 200 ms
|
||||
|
||||
// When the total duration of the window of samples being averaged is less
|
||||
// than the window size, the resulting velocity is scaled to reduce the impact
|
||||
// of overestimation in short traces.
|
||||
static const nsecs_t MIN_WINDOW = 100 * 1000000; // 100 ms
|
||||
|
||||
// The minimum duration between samples when estimating velocity.
|
||||
static const nsecs_t MIN_DURATION = 10 * 1000000; // 10 ms
|
||||
|
||||
|
||||
@@ -831,6 +831,7 @@ bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const
|
||||
const Position& oldestPosition =
|
||||
oldestMovement.positions[oldestMovement.idBits.getIndexOfBit(id)];
|
||||
nsecs_t lastDuration = 0;
|
||||
|
||||
while (numTouches-- > 1) {
|
||||
if (++index == HISTORY_SIZE) {
|
||||
index = 0;
|
||||
@@ -857,6 +858,14 @@ bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const
|
||||
|
||||
// Make sure we used at least one sample.
|
||||
if (samplesUsed != 0) {
|
||||
// Scale the velocity linearly if the window of samples is small.
|
||||
nsecs_t totalDuration = newestMovement.eventTime - oldestMovement.eventTime;
|
||||
if (totalDuration < MIN_WINDOW) {
|
||||
float scale = float(totalDuration) / float(MIN_WINDOW);
|
||||
accumVx *= scale;
|
||||
accumVy *= scale;
|
||||
}
|
||||
|
||||
*outVx = accumVx;
|
||||
*outVy = accumVy;
|
||||
return true;
|
||||
|
||||
@@ -662,7 +662,8 @@ void Looper::wakeAndLock() {
|
||||
#endif
|
||||
|
||||
void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
|
||||
sendMessageAtTime(LLONG_MIN, handler, message);
|
||||
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
sendMessageAtTime(now, handler, message);
|
||||
}
|
||||
|
||||
void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
|
||||
|
||||
@@ -23,7 +23,6 @@ LOCAL_SRC_FILES:= \
|
||||
InputReader.cpp \
|
||||
InputWindow.cpp \
|
||||
PointerController.cpp \
|
||||
SpotController.cpp \
|
||||
SpriteController.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,6 @@
|
||||
#include "EventHub.h"
|
||||
#include "InputDispatcher.h"
|
||||
#include "PointerController.h"
|
||||
#include "SpotController.h"
|
||||
|
||||
#include <ui/Input.h>
|
||||
#include <ui/DisplayInfo.h>
|
||||
@@ -90,9 +89,6 @@ public:
|
||||
|
||||
/* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
|
||||
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
|
||||
|
||||
/* Gets a spot controller associated with the specified touch pad device. */
|
||||
virtual sp<SpotControllerInterface> obtainSpotController(int32_t deviceId) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -648,6 +644,20 @@ protected:
|
||||
idBits.clear();
|
||||
buttonState = 0;
|
||||
}
|
||||
|
||||
void getCentroid(float* outX, float* outY) {
|
||||
float x = 0, y = 0;
|
||||
if (pointerCount != 0) {
|
||||
for (uint32_t i = 0; i < pointerCount; i++) {
|
||||
x += pointers[i].x;
|
||||
y += pointers[i].y;
|
||||
}
|
||||
x /= pointerCount;
|
||||
y /= pointerCount;
|
||||
}
|
||||
*outX = x;
|
||||
*outY = y;
|
||||
}
|
||||
};
|
||||
|
||||
// Input sources supported by the device.
|
||||
@@ -670,6 +680,12 @@ protected:
|
||||
bool useJumpyTouchFilter;
|
||||
bool useAveragingTouchFilter;
|
||||
nsecs_t virtualKeyQuietTime;
|
||||
|
||||
enum GestureMode {
|
||||
GESTURE_MODE_POINTER,
|
||||
GESTURE_MODE_SPOTS,
|
||||
};
|
||||
GestureMode gestureMode;
|
||||
} mParameters;
|
||||
|
||||
// Immutable calibration parameters in parsed form.
|
||||
@@ -841,8 +857,8 @@ protected:
|
||||
float pointerGestureXZoomScale;
|
||||
float pointerGestureYZoomScale;
|
||||
|
||||
// The maximum swipe width squared.
|
||||
int32_t pointerGestureMaxSwipeWidthSquared;
|
||||
// The maximum swipe width.
|
||||
float pointerGestureMaxSwipeWidth;
|
||||
} mLocked;
|
||||
|
||||
virtual void configureParameters();
|
||||
@@ -929,28 +945,32 @@ private:
|
||||
// Emits HOVER_MOVE events at the pointer location.
|
||||
HOVER,
|
||||
|
||||
// More than two fingers involved but they haven't moved enough for us
|
||||
// to figure out what is intended.
|
||||
INDETERMINATE_MULTITOUCH,
|
||||
// Exactly two fingers but neither have moved enough to clearly indicate
|
||||
// whether a swipe or freeform gesture was intended. We consider the
|
||||
// pointer to be pressed so this enables clicking or long-pressing on buttons.
|
||||
// Pointer does not move.
|
||||
// Emits DOWN, MOVE and UP events with a single stationary pointer coordinate.
|
||||
PRESS,
|
||||
|
||||
// Exactly two fingers moving in the same direction, button is not pressed.
|
||||
// Pointer does not move.
|
||||
// Emits DOWN, MOVE and UP events with a single pointer coordinate that
|
||||
// follows the midpoint between both fingers.
|
||||
// The centroid is fixed when entering this state.
|
||||
SWIPE,
|
||||
|
||||
// Two or more fingers moving in arbitrary directions, button is not pressed.
|
||||
// Pointer does not move.
|
||||
// Emits DOWN, POINTER_DOWN, MOVE, POINTER_UP and UP events that follow
|
||||
// each finger individually relative to the initial centroid of the finger.
|
||||
// The centroid is fixed when entering this state.
|
||||
FREEFORM,
|
||||
|
||||
// Waiting for quiet time to end before starting the next gesture.
|
||||
QUIET,
|
||||
};
|
||||
|
||||
// Time the first finger went down.
|
||||
nsecs_t firstTouchTime;
|
||||
|
||||
// The active pointer id from the raw touch data.
|
||||
int32_t activeTouchId; // -1 if none
|
||||
|
||||
@@ -959,32 +979,20 @@ private:
|
||||
|
||||
// Pointer coords and ids for the current and previous pointer gesture.
|
||||
Mode currentGestureMode;
|
||||
uint32_t currentGesturePointerCount;
|
||||
BitSet32 currentGestureIdBits;
|
||||
uint32_t currentGestureIdToIndex[MAX_POINTER_ID + 1];
|
||||
PointerCoords currentGestureCoords[MAX_POINTERS];
|
||||
|
||||
Mode lastGestureMode;
|
||||
uint32_t lastGesturePointerCount;
|
||||
BitSet32 lastGestureIdBits;
|
||||
uint32_t lastGestureIdToIndex[MAX_POINTER_ID + 1];
|
||||
PointerCoords lastGestureCoords[MAX_POINTERS];
|
||||
|
||||
// Tracks for all pointers originally went down.
|
||||
TouchData touchOrigin;
|
||||
|
||||
// Describes how touch ids are mapped to gesture ids for freeform gestures.
|
||||
uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1];
|
||||
|
||||
// Initial centroid of the movement.
|
||||
// Used to calculate how far the touch pointers have moved since the gesture started.
|
||||
int32_t initialCentroidX;
|
||||
int32_t initialCentroidY;
|
||||
|
||||
// Initial pointer location.
|
||||
// Used to track where the pointer was when the gesture started.
|
||||
float initialPointerX;
|
||||
float initialPointerY;
|
||||
// Pointer coords and ids for the current spots.
|
||||
PointerControllerInterface::SpotGesture spotGesture;
|
||||
BitSet32 spotIdBits; // same set of ids as touch ids
|
||||
uint32_t spotIdToIndex[MAX_POINTER_ID + 1];
|
||||
PointerCoords spotCoords[MAX_POINTERS];
|
||||
|
||||
// Time the pointer gesture last went down.
|
||||
nsecs_t downTime;
|
||||
@@ -992,26 +1000,34 @@ private:
|
||||
// Time we started waiting for a tap gesture.
|
||||
nsecs_t tapTime;
|
||||
|
||||
// Location of initial tap.
|
||||
float tapX, tapY;
|
||||
|
||||
// Time we started waiting for quiescence.
|
||||
nsecs_t quietTime;
|
||||
|
||||
// Reference points for multitouch gestures.
|
||||
float referenceTouchX; // reference touch X/Y coordinates in surface units
|
||||
float referenceTouchY;
|
||||
float referenceGestureX; // reference gesture X/Y coordinates in pixels
|
||||
float referenceGestureY;
|
||||
|
||||
// Describes how touch ids are mapped to gesture ids for freeform gestures.
|
||||
uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1];
|
||||
|
||||
// A velocity tracker for determining whether to switch active pointers during drags.
|
||||
VelocityTracker velocityTracker;
|
||||
|
||||
void reset() {
|
||||
firstTouchTime = LLONG_MIN;
|
||||
activeTouchId = -1;
|
||||
activeGestureId = -1;
|
||||
currentGestureMode = NEUTRAL;
|
||||
currentGesturePointerCount = 0;
|
||||
currentGestureIdBits.clear();
|
||||
lastGestureMode = NEUTRAL;
|
||||
lastGesturePointerCount = 0;
|
||||
lastGestureIdBits.clear();
|
||||
touchOrigin.clear();
|
||||
initialCentroidX = 0;
|
||||
initialCentroidY = 0;
|
||||
initialPointerX = 0;
|
||||
initialPointerY = 0;
|
||||
spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
|
||||
spotIdBits.clear();
|
||||
downTime = 0;
|
||||
velocityTracker.clear();
|
||||
resetTapTime();
|
||||
@@ -1035,6 +1051,7 @@ private:
|
||||
void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags);
|
||||
void preparePointerGestures(nsecs_t when,
|
||||
bool* outCancelPreviousGesture, bool* outFinishPreviousGesture);
|
||||
void moveSpotsLocked();
|
||||
|
||||
// Dispatches a motion event.
|
||||
// If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the
|
||||
|
||||
@@ -36,40 +36,49 @@ namespace android {
|
||||
// --- PointerController ---
|
||||
|
||||
// Time to wait before starting the fade when the pointer is inactive.
|
||||
static const nsecs_t INACTIVITY_FADE_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
|
||||
static const nsecs_t INACTIVITY_FADE_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
|
||||
static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
|
||||
static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
|
||||
|
||||
// Time to wait between animation frames.
|
||||
static const nsecs_t ANIMATION_FRAME_INTERVAL = 1000000000LL / 60;
|
||||
|
||||
// Time to spend fading out the spot completely.
|
||||
static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms
|
||||
|
||||
// Time to spend fading out the pointer completely.
|
||||
static const nsecs_t FADE_DURATION = 500 * 1000000LL; // 500 ms
|
||||
|
||||
// Time to wait between frames.
|
||||
static const nsecs_t FADE_FRAME_INTERVAL = 1000000000LL / 60;
|
||||
|
||||
// Amount to subtract from alpha per frame.
|
||||
static const float FADE_DECAY_PER_FRAME = float(FADE_FRAME_INTERVAL) / FADE_DURATION;
|
||||
static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
|
||||
|
||||
|
||||
PointerController::PointerController(const sp<Looper>& looper,
|
||||
const sp<SpriteController>& spriteController) :
|
||||
mLooper(looper), mSpriteController(spriteController) {
|
||||
// --- PointerController ---
|
||||
|
||||
PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
|
||||
const sp<Looper>& looper, const sp<SpriteController>& spriteController) :
|
||||
mPolicy(policy), mLooper(looper), mSpriteController(spriteController) {
|
||||
mHandler = new WeakMessageHandler(this);
|
||||
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
mLocked.animationPending = false;
|
||||
|
||||
mLocked.displayWidth = -1;
|
||||
mLocked.displayHeight = -1;
|
||||
mLocked.displayOrientation = DISPLAY_ORIENTATION_0;
|
||||
|
||||
mLocked.presentation = PRESENTATION_POINTER;
|
||||
mLocked.presentationChanged = false;
|
||||
|
||||
mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL;
|
||||
|
||||
mLocked.pointerIsFading = true; // keep the pointer initially faded
|
||||
mLocked.pointerX = 0;
|
||||
mLocked.pointerY = 0;
|
||||
mLocked.pointerAlpha = 0.0f;
|
||||
mLocked.pointerSprite = mSpriteController->createSprite();
|
||||
mLocked.pointerIconChanged = false;
|
||||
|
||||
mLocked.buttonState = 0;
|
||||
|
||||
mLocked.fadeAlpha = 1;
|
||||
mLocked.inactivityFadeDelay = INACTIVITY_FADE_DELAY_NORMAL;
|
||||
|
||||
mLocked.visible = false;
|
||||
|
||||
mLocked.sprite = mSpriteController->createSprite();
|
||||
loadResources();
|
||||
}
|
||||
|
||||
PointerController::~PointerController() {
|
||||
@@ -77,7 +86,13 @@ PointerController::~PointerController() {
|
||||
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
mLocked.sprite.clear();
|
||||
mLocked.pointerSprite.clear();
|
||||
|
||||
for (size_t i = 0; i < mLocked.spots.size(); i++) {
|
||||
delete mLocked.spots.itemAt(i);
|
||||
}
|
||||
mLocked.spots.clear();
|
||||
mLocked.recycledSprites.clear();
|
||||
}
|
||||
|
||||
bool PointerController::getBounds(float* outMinX, float* outMinY,
|
||||
@@ -130,8 +145,6 @@ void PointerController::setButtonState(uint32_t buttonState) {
|
||||
|
||||
if (mLocked.buttonState != buttonState) {
|
||||
mLocked.buttonState = buttonState;
|
||||
unfadeBeforeUpdateLocked();
|
||||
updateLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,8 +180,7 @@ void PointerController::setPositionLocked(float x, float y) {
|
||||
} else {
|
||||
mLocked.pointerY = y;
|
||||
}
|
||||
unfadeBeforeUpdateLocked();
|
||||
updateLocked();
|
||||
updatePointerLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,32 +194,105 @@ void PointerController::getPosition(float* outX, float* outY) const {
|
||||
void PointerController::fade() {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
startFadeLocked();
|
||||
sendImmediateInactivityTimeoutLocked();
|
||||
}
|
||||
|
||||
void PointerController::unfade() {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
if (unfadeBeforeUpdateLocked()) {
|
||||
updateLocked();
|
||||
// Always reset the inactivity timer.
|
||||
resetInactivityTimeoutLocked();
|
||||
|
||||
// Unfade immediately if needed.
|
||||
if (mLocked.pointerIsFading) {
|
||||
mLocked.pointerIsFading = false;
|
||||
mLocked.pointerAlpha = 1.0f;
|
||||
updatePointerLocked();
|
||||
}
|
||||
}
|
||||
|
||||
void PointerController::setInactivityFadeDelay(InactivityFadeDelay inactivityFadeDelay) {
|
||||
void PointerController::setPresentation(Presentation presentation) {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
if (mLocked.inactivityFadeDelay != inactivityFadeDelay) {
|
||||
mLocked.inactivityFadeDelay = inactivityFadeDelay;
|
||||
startInactivityFadeDelayLocked();
|
||||
if (mLocked.presentation != presentation) {
|
||||
mLocked.presentation = presentation;
|
||||
mLocked.presentationChanged = true;
|
||||
|
||||
if (presentation != PRESENTATION_SPOT) {
|
||||
fadeOutAndReleaseAllSpotsLocked();
|
||||
}
|
||||
|
||||
updatePointerLocked();
|
||||
}
|
||||
}
|
||||
|
||||
void PointerController::updateLocked() {
|
||||
mLocked.sprite->openTransaction();
|
||||
mLocked.sprite->setPosition(mLocked.pointerX, mLocked.pointerY);
|
||||
mLocked.sprite->setAlpha(mLocked.fadeAlpha);
|
||||
mLocked.sprite->setVisible(mLocked.visible);
|
||||
mLocked.sprite->closeTransaction();
|
||||
void PointerController::setSpots(SpotGesture spotGesture,
|
||||
const PointerCoords* spotCoords, const uint32_t* spotIdToIndex, BitSet32 spotIdBits) {
|
||||
#if DEBUG_POINTER_UPDATES
|
||||
LOGD("setSpots: spotGesture=%d", spotGesture);
|
||||
for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
|
||||
uint32_t id = idBits.firstMarkedBit();
|
||||
idBits.clearBit(id);
|
||||
const PointerCoords& c = spotCoords[spotIdToIndex[id]];
|
||||
LOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f", id,
|
||||
c.getAxisValue(AMOTION_EVENT_AXIS_X),
|
||||
c.getAxisValue(AMOTION_EVENT_AXIS_Y),
|
||||
c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
|
||||
}
|
||||
#endif
|
||||
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
mSpriteController->openTransaction();
|
||||
|
||||
// Add or move spots for fingers that are down.
|
||||
for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
|
||||
uint32_t id = idBits.firstMarkedBit();
|
||||
idBits.clearBit(id);
|
||||
|
||||
const PointerCoords& c = spotCoords[spotIdToIndex[id]];
|
||||
const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0
|
||||
? mResources.spotTouch : mResources.spotHover;
|
||||
float x = c.getAxisValue(AMOTION_EVENT_AXIS_X);
|
||||
float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
|
||||
|
||||
Spot* spot = getSpotLocked(id);
|
||||
if (!spot) {
|
||||
spot = createAndAddSpotLocked(id);
|
||||
}
|
||||
|
||||
spot->updateSprite(&icon, x, y);
|
||||
}
|
||||
|
||||
// Remove spots for fingers that went up.
|
||||
for (size_t i = 0; i < mLocked.spots.size(); i++) {
|
||||
Spot* spot = mLocked.spots.itemAt(i);
|
||||
if (spot->id != Spot::INVALID_ID
|
||||
&& !spotIdBits.hasBit(spot->id)) {
|
||||
fadeOutAndReleaseSpotLocked(spot);
|
||||
}
|
||||
}
|
||||
|
||||
mSpriteController->closeTransaction();
|
||||
}
|
||||
|
||||
void PointerController::clearSpots() {
|
||||
#if DEBUG_POINTER_UPDATES
|
||||
LOGD("clearSpots");
|
||||
#endif
|
||||
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
fadeOutAndReleaseAllSpotsLocked();
|
||||
}
|
||||
|
||||
void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
if (mLocked.inactivityTimeout != inactivityTimeout) {
|
||||
mLocked.inactivityTimeout = inactivityTimeout;
|
||||
resetInactivityTimeoutLocked();
|
||||
}
|
||||
}
|
||||
|
||||
void PointerController::setDisplaySize(int32_t width, int32_t height) {
|
||||
@@ -226,7 +311,8 @@ void PointerController::setDisplaySize(int32_t width, int32_t height) {
|
||||
mLocked.pointerY = 0;
|
||||
}
|
||||
|
||||
updateLocked();
|
||||
fadeOutAndReleaseAllSpotsLocked();
|
||||
updatePointerLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,74 +369,217 @@ void PointerController::setDisplayOrientation(int32_t orientation) {
|
||||
mLocked.pointerY = y - 0.5f;
|
||||
mLocked.displayOrientation = orientation;
|
||||
|
||||
updateLocked();
|
||||
updatePointerLocked();
|
||||
}
|
||||
}
|
||||
|
||||
void PointerController::setPointerIcon(const SkBitmap* bitmap, float hotSpotX, float hotSpotY) {
|
||||
void PointerController::setPointerIcon(const SpriteIcon& icon) {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
mLocked.sprite->setBitmap(bitmap, hotSpotX, hotSpotY);
|
||||
mLocked.pointerIcon = icon.copy();
|
||||
mLocked.pointerIconChanged = true;
|
||||
|
||||
updatePointerLocked();
|
||||
}
|
||||
|
||||
void PointerController::handleMessage(const Message& message) {
|
||||
switch (message.what) {
|
||||
case MSG_FADE_STEP: {
|
||||
AutoMutex _l(mLock);
|
||||
fadeStepLocked();
|
||||
case MSG_ANIMATE:
|
||||
doAnimate();
|
||||
break;
|
||||
case MSG_INACTIVITY_TIMEOUT:
|
||||
doInactivityTimeout();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PointerController::unfadeBeforeUpdateLocked() {
|
||||
sendFadeStepMessageDelayedLocked(getInactivityFadeDelayTimeLocked());
|
||||
void PointerController::doAnimate() {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
if (isFadingLocked()) {
|
||||
mLocked.visible = true;
|
||||
mLocked.fadeAlpha = 1;
|
||||
return true; // update required to effect the unfade
|
||||
}
|
||||
return false; // update not required
|
||||
}
|
||||
bool keepAnimating = false;
|
||||
mLocked.animationPending = false;
|
||||
nsecs_t frameDelay = systemTime(SYSTEM_TIME_MONOTONIC) - mLocked.animationTime;
|
||||
|
||||
void PointerController::startFadeLocked() {
|
||||
if (!isFadingLocked()) {
|
||||
sendFadeStepMessageDelayedLocked(0);
|
||||
}
|
||||
}
|
||||
|
||||
void PointerController::startInactivityFadeDelayLocked() {
|
||||
if (!isFadingLocked()) {
|
||||
sendFadeStepMessageDelayedLocked(getInactivityFadeDelayTimeLocked());
|
||||
}
|
||||
}
|
||||
|
||||
void PointerController::fadeStepLocked() {
|
||||
if (mLocked.visible) {
|
||||
mLocked.fadeAlpha -= FADE_DECAY_PER_FRAME;
|
||||
if (mLocked.fadeAlpha < 0) {
|
||||
mLocked.fadeAlpha = 0;
|
||||
mLocked.visible = false;
|
||||
// Animate pointer fade.
|
||||
if (mLocked.pointerIsFading) {
|
||||
mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
|
||||
if (mLocked.pointerAlpha <= 0) {
|
||||
mLocked.pointerAlpha = 0;
|
||||
} else {
|
||||
sendFadeStepMessageDelayedLocked(FADE_FRAME_INTERVAL);
|
||||
keepAnimating = true;
|
||||
}
|
||||
updateLocked();
|
||||
updatePointerLocked();
|
||||
}
|
||||
|
||||
// Animate spots that are fading out and being removed.
|
||||
for (size_t i = 0; i < mLocked.spots.size(); i++) {
|
||||
Spot* spot = mLocked.spots.itemAt(i);
|
||||
if (spot->id == Spot::INVALID_ID) {
|
||||
spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
|
||||
if (spot->alpha <= 0) {
|
||||
mLocked.spots.removeAt(i--);
|
||||
releaseSpotLocked(spot);
|
||||
} else {
|
||||
spot->sprite->setAlpha(spot->alpha);
|
||||
keepAnimating = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (keepAnimating) {
|
||||
startAnimationLocked();
|
||||
}
|
||||
}
|
||||
|
||||
bool PointerController::isFadingLocked() {
|
||||
return !mLocked.visible || mLocked.fadeAlpha != 1;
|
||||
void PointerController::doInactivityTimeout() {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
if (!mLocked.pointerIsFading) {
|
||||
mLocked.pointerIsFading = true;
|
||||
startAnimationLocked();
|
||||
}
|
||||
}
|
||||
|
||||
nsecs_t PointerController::getInactivityFadeDelayTimeLocked() {
|
||||
return mLocked.inactivityFadeDelay == INACTIVITY_FADE_DELAY_SHORT
|
||||
? INACTIVITY_FADE_DELAY_TIME_SHORT : INACTIVITY_FADE_DELAY_TIME_NORMAL;
|
||||
void PointerController::startAnimationLocked() {
|
||||
if (!mLocked.animationPending) {
|
||||
mLocked.animationPending = true;
|
||||
mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
mLooper->sendMessageDelayed(ANIMATION_FRAME_INTERVAL, mHandler, Message(MSG_ANIMATE));
|
||||
}
|
||||
}
|
||||
|
||||
void PointerController::sendFadeStepMessageDelayedLocked(nsecs_t delayTime) {
|
||||
mLooper->removeMessages(mHandler, MSG_FADE_STEP);
|
||||
mLooper->sendMessageDelayed(delayTime, mHandler, Message(MSG_FADE_STEP));
|
||||
void PointerController::resetInactivityTimeoutLocked() {
|
||||
mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
|
||||
|
||||
nsecs_t timeout = mLocked.inactivityTimeout == INACTIVITY_TIMEOUT_SHORT
|
||||
? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
|
||||
mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT);
|
||||
}
|
||||
|
||||
void PointerController::sendImmediateInactivityTimeoutLocked() {
|
||||
mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
|
||||
mLooper->sendMessage(mHandler, MSG_INACTIVITY_TIMEOUT);
|
||||
}
|
||||
|
||||
void PointerController::updatePointerLocked() {
|
||||
mSpriteController->openTransaction();
|
||||
|
||||
mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
|
||||
mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
|
||||
|
||||
if (mLocked.pointerAlpha > 0) {
|
||||
mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
|
||||
mLocked.pointerSprite->setVisible(true);
|
||||
} else {
|
||||
mLocked.pointerSprite->setVisible(false);
|
||||
}
|
||||
|
||||
if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
|
||||
mLocked.pointerSprite->setIcon(mLocked.presentation == PRESENTATION_POINTER
|
||||
? mLocked.pointerIcon : mResources.spotAnchor);
|
||||
mLocked.pointerIconChanged = false;
|
||||
mLocked.presentationChanged = false;
|
||||
}
|
||||
|
||||
mSpriteController->closeTransaction();
|
||||
}
|
||||
|
||||
PointerController::Spot* PointerController::getSpotLocked(uint32_t id) {
|
||||
for (size_t i = 0; i < mLocked.spots.size(); i++) {
|
||||
Spot* spot = mLocked.spots.itemAt(i);
|
||||
if (spot->id == id) {
|
||||
return spot;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id) {
|
||||
// Remove spots until we have fewer than MAX_SPOTS remaining.
|
||||
while (mLocked.spots.size() >= MAX_SPOTS) {
|
||||
Spot* spot = removeFirstFadingSpotLocked();
|
||||
if (!spot) {
|
||||
spot = mLocked.spots.itemAt(0);
|
||||
mLocked.spots.removeAt(0);
|
||||
}
|
||||
releaseSpotLocked(spot);
|
||||
}
|
||||
|
||||
// Obtain a sprite from the recycled pool.
|
||||
sp<Sprite> sprite;
|
||||
if (! mLocked.recycledSprites.isEmpty()) {
|
||||
sprite = mLocked.recycledSprites.top();
|
||||
mLocked.recycledSprites.pop();
|
||||
} else {
|
||||
sprite = mSpriteController->createSprite();
|
||||
}
|
||||
|
||||
// Return the new spot.
|
||||
Spot* spot = new Spot(id, sprite);
|
||||
mLocked.spots.push(spot);
|
||||
return spot;
|
||||
}
|
||||
|
||||
PointerController::Spot* PointerController::removeFirstFadingSpotLocked() {
|
||||
for (size_t i = 0; i < mLocked.spots.size(); i++) {
|
||||
Spot* spot = mLocked.spots.itemAt(i);
|
||||
if (spot->id == Spot::INVALID_ID) {
|
||||
mLocked.spots.removeAt(i);
|
||||
return spot;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void PointerController::releaseSpotLocked(Spot* spot) {
|
||||
spot->sprite->clearIcon();
|
||||
|
||||
if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
|
||||
mLocked.recycledSprites.push(spot->sprite);
|
||||
}
|
||||
|
||||
delete spot;
|
||||
}
|
||||
|
||||
void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
|
||||
if (spot->id != Spot::INVALID_ID) {
|
||||
spot->id = Spot::INVALID_ID;
|
||||
startAnimationLocked();
|
||||
}
|
||||
}
|
||||
|
||||
void PointerController::fadeOutAndReleaseAllSpotsLocked() {
|
||||
for (size_t i = 0; i < mLocked.spots.size(); i++) {
|
||||
Spot* spot = mLocked.spots.itemAt(i);
|
||||
fadeOutAndReleaseSpotLocked(spot);
|
||||
}
|
||||
}
|
||||
|
||||
void PointerController::loadResources() {
|
||||
mPolicy->loadPointerResources(&mResources);
|
||||
}
|
||||
|
||||
|
||||
// --- PointerController::Spot ---
|
||||
|
||||
void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y) {
|
||||
sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
|
||||
sprite->setAlpha(alpha);
|
||||
sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
|
||||
sprite->setPosition(x, y);
|
||||
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
|
||||
if (icon != lastIcon) {
|
||||
lastIcon = icon;
|
||||
if (icon) {
|
||||
sprite->setIcon(*icon);
|
||||
sprite->setVisible(true);
|
||||
} else {
|
||||
sprite->setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -30,7 +30,10 @@
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* Interface for tracking a single (mouse) pointer.
|
||||
* Interface for tracking a mouse / touch pad pointer and touch pad spots.
|
||||
*
|
||||
* The spots are sprites on screen that visually represent the positions of
|
||||
* fingers
|
||||
*
|
||||
* The pointer controller is responsible for providing synchronization and for tracking
|
||||
* display orientation changes if needed.
|
||||
@@ -64,8 +67,95 @@ public:
|
||||
/* Fades the pointer out now. */
|
||||
virtual void fade() = 0;
|
||||
|
||||
/* Makes the pointer visible if it has faded out. */
|
||||
/* Makes the pointer visible if it has faded out.
|
||||
* The pointer never unfades itself automatically. This method must be called
|
||||
* by the client whenever the pointer is moved or a button is pressed and it
|
||||
* wants to ensure that the pointer becomes visible again. */
|
||||
virtual void unfade() = 0;
|
||||
|
||||
enum Presentation {
|
||||
// Show the mouse pointer.
|
||||
PRESENTATION_POINTER,
|
||||
// Show spots and a spot anchor in place of the mouse pointer.
|
||||
PRESENTATION_SPOT,
|
||||
};
|
||||
|
||||
/* Sets the mode of the pointer controller. */
|
||||
virtual void setPresentation(Presentation presentation) = 0;
|
||||
|
||||
// Describes the current gesture.
|
||||
enum SpotGesture {
|
||||
// No gesture.
|
||||
// Do not display any spots.
|
||||
SPOT_GESTURE_NEUTRAL,
|
||||
// Tap at current location.
|
||||
// Briefly display one spot at the tapped location.
|
||||
SPOT_GESTURE_TAP,
|
||||
// Button pressed but no finger is down.
|
||||
// Display spot at pressed location.
|
||||
SPOT_GESTURE_BUTTON_CLICK,
|
||||
// Button pressed and a finger is down.
|
||||
// Display spot at pressed location.
|
||||
SPOT_GESTURE_BUTTON_DRAG,
|
||||
// One finger down and hovering.
|
||||
// Display spot at the hovered location.
|
||||
SPOT_GESTURE_HOVER,
|
||||
// Two fingers down but not sure in which direction they are moving so we consider
|
||||
// it a press at the pointer location.
|
||||
// Display two spots near the pointer location.
|
||||
SPOT_GESTURE_PRESS,
|
||||
// Two fingers down and moving in same direction.
|
||||
// Display two spots near the pointer location.
|
||||
SPOT_GESTURE_SWIPE,
|
||||
// Two or more fingers down and moving in arbitrary directions.
|
||||
// Display two or more spots near the pointer location, one for each finger.
|
||||
SPOT_GESTURE_FREEFORM,
|
||||
};
|
||||
|
||||
/* Sets the spots for the current gesture.
|
||||
* The spots are not subject to the inactivity timeout like the pointer
|
||||
* itself it since they are expected to remain visible for so long as
|
||||
* the fingers are on the touch pad.
|
||||
*
|
||||
* The values of the AMOTION_EVENT_AXIS_PRESSURE axis is significant.
|
||||
* For spotCoords, pressure != 0 indicates that the spot's location is being
|
||||
* pressed (not hovering).
|
||||
*/
|
||||
virtual void setSpots(SpotGesture spotGesture,
|
||||
const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
|
||||
BitSet32 spotIdBits) = 0;
|
||||
|
||||
/* Removes all spots. */
|
||||
virtual void clearSpots() = 0;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Pointer resources.
|
||||
*/
|
||||
struct PointerResources {
|
||||
SpriteIcon spotHover;
|
||||
SpriteIcon spotTouch;
|
||||
SpriteIcon spotAnchor;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Pointer controller policy interface.
|
||||
*
|
||||
* The pointer controller policy is used by the pointer controller to interact with
|
||||
* the Window Manager and other system components.
|
||||
*
|
||||
* The actual implementation is partially supported by callbacks into the DVM
|
||||
* via JNI. This interface is also mocked in the unit tests.
|
||||
*/
|
||||
class PointerControllerPolicyInterface : public virtual RefBase {
|
||||
protected:
|
||||
PointerControllerPolicyInterface() { }
|
||||
virtual ~PointerControllerPolicyInterface() { }
|
||||
|
||||
public:
|
||||
virtual void loadPointerResources(PointerResources* outResources) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -79,12 +169,13 @@ protected:
|
||||
virtual ~PointerController();
|
||||
|
||||
public:
|
||||
enum InactivityFadeDelay {
|
||||
INACTIVITY_FADE_DELAY_NORMAL = 0,
|
||||
INACTIVITY_FADE_DELAY_SHORT = 1,
|
||||
enum InactivityTimeout {
|
||||
INACTIVITY_TIMEOUT_NORMAL = 0,
|
||||
INACTIVITY_TIMEOUT_SHORT = 1,
|
||||
};
|
||||
|
||||
PointerController(const sp<Looper>& looper, const sp<SpriteController>& spriteController);
|
||||
PointerController(const sp<PointerControllerPolicyInterface>& policy,
|
||||
const sp<Looper>& looper, const sp<SpriteController>& spriteController);
|
||||
|
||||
virtual bool getBounds(float* outMinX, float* outMinY,
|
||||
float* outMaxX, float* outMaxY) const;
|
||||
@@ -96,51 +187,101 @@ public:
|
||||
virtual void fade();
|
||||
virtual void unfade();
|
||||
|
||||
virtual void setPresentation(Presentation presentation);
|
||||
virtual void setSpots(SpotGesture spotGesture,
|
||||
const PointerCoords* spotCoords, const uint32_t* spotIdToIndex, BitSet32 spotIdBits);
|
||||
virtual void clearSpots();
|
||||
|
||||
void setDisplaySize(int32_t width, int32_t height);
|
||||
void setDisplayOrientation(int32_t orientation);
|
||||
void setPointerIcon(const SkBitmap* bitmap, float hotSpotX, float hotSpotY);
|
||||
void setInactivityFadeDelay(InactivityFadeDelay inactivityFadeDelay);
|
||||
void setPointerIcon(const SpriteIcon& icon);
|
||||
void setInactivityTimeout(InactivityTimeout inactivityTimeout);
|
||||
|
||||
private:
|
||||
static const size_t MAX_RECYCLED_SPRITES = 12;
|
||||
static const size_t MAX_SPOTS = 12;
|
||||
|
||||
enum {
|
||||
MSG_FADE_STEP = 0,
|
||||
MSG_ANIMATE,
|
||||
MSG_INACTIVITY_TIMEOUT,
|
||||
};
|
||||
|
||||
struct Spot {
|
||||
static const uint32_t INVALID_ID = 0xffffffff;
|
||||
|
||||
uint32_t id;
|
||||
sp<Sprite> sprite;
|
||||
float alpha;
|
||||
float scale;
|
||||
float x, y;
|
||||
|
||||
inline Spot(uint32_t id, const sp<Sprite>& sprite)
|
||||
: id(id), sprite(sprite), alpha(1.0f), scale(1.0f),
|
||||
x(0.0f), y(0.0f), lastIcon(NULL) { }
|
||||
|
||||
void updateSprite(const SpriteIcon* icon, float x, float y);
|
||||
|
||||
private:
|
||||
const SpriteIcon* lastIcon;
|
||||
};
|
||||
|
||||
mutable Mutex mLock;
|
||||
|
||||
sp<PointerControllerPolicyInterface> mPolicy;
|
||||
sp<Looper> mLooper;
|
||||
sp<SpriteController> mSpriteController;
|
||||
sp<WeakMessageHandler> mHandler;
|
||||
|
||||
PointerResources mResources;
|
||||
|
||||
struct Locked {
|
||||
bool animationPending;
|
||||
nsecs_t animationTime;
|
||||
|
||||
int32_t displayWidth;
|
||||
int32_t displayHeight;
|
||||
int32_t displayOrientation;
|
||||
|
||||
InactivityTimeout inactivityTimeout;
|
||||
|
||||
Presentation presentation;
|
||||
bool presentationChanged;
|
||||
|
||||
bool pointerIsFading;
|
||||
float pointerX;
|
||||
float pointerY;
|
||||
float pointerAlpha;
|
||||
sp<Sprite> pointerSprite;
|
||||
SpriteIcon pointerIcon;
|
||||
bool pointerIconChanged;
|
||||
|
||||
uint32_t buttonState;
|
||||
|
||||
float fadeAlpha;
|
||||
InactivityFadeDelay inactivityFadeDelay;
|
||||
|
||||
bool visible;
|
||||
|
||||
sp<Sprite> sprite;
|
||||
Vector<Spot*> spots;
|
||||
Vector<sp<Sprite> > recycledSprites;
|
||||
} mLocked;
|
||||
|
||||
bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
|
||||
void setPositionLocked(float x, float y);
|
||||
void updateLocked();
|
||||
|
||||
void handleMessage(const Message& message);
|
||||
bool unfadeBeforeUpdateLocked();
|
||||
void startFadeLocked();
|
||||
void startInactivityFadeDelayLocked();
|
||||
void fadeStepLocked();
|
||||
bool isFadingLocked();
|
||||
nsecs_t getInactivityFadeDelayTimeLocked();
|
||||
void sendFadeStepMessageDelayedLocked(nsecs_t delayTime);
|
||||
void doAnimate();
|
||||
void doInactivityTimeout();
|
||||
|
||||
void startAnimationLocked();
|
||||
|
||||
void resetInactivityTimeoutLocked();
|
||||
void sendImmediateInactivityTimeoutLocked();
|
||||
void updatePointerLocked();
|
||||
|
||||
Spot* getSpotLocked(uint32_t id);
|
||||
Spot* createAndAddSpotLocked(uint32_t id);
|
||||
Spot* removeFirstFadingSpotLocked();
|
||||
void releaseSpotLocked(Spot* spot);
|
||||
void fadeOutAndReleaseSpotLocked(Spot* spot);
|
||||
void fadeOutAndReleaseAllSpotsLocked();
|
||||
|
||||
void loadResources();
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* 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 _UI_SPOT_CONTROLLER_H
|
||||
#define _UI_SPOT_CONTROLLER_H
|
||||
|
||||
#include "SpriteController.h"
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/Looper.h>
|
||||
|
||||
#include <SkBitmap.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* Interface for displaying spots on screen that visually represent the positions
|
||||
* of fingers on a touch pad.
|
||||
*
|
||||
* The spot controller is responsible for providing synchronization and for tracking
|
||||
* display orientation changes if needed.
|
||||
*/
|
||||
class SpotControllerInterface : public virtual RefBase {
|
||||
protected:
|
||||
SpotControllerInterface() { }
|
||||
virtual ~SpotControllerInterface() { }
|
||||
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Sprite-based spot controller implementation.
|
||||
*/
|
||||
class SpotController : public SpotControllerInterface, public MessageHandler {
|
||||
protected:
|
||||
virtual ~SpotController();
|
||||
|
||||
public:
|
||||
SpotController(const sp<Looper>& looper, const sp<SpriteController>& spriteController);
|
||||
|
||||
private:
|
||||
mutable Mutex mLock;
|
||||
|
||||
sp<Looper> mLooper;
|
||||
sp<SpriteController> mSpriteController;
|
||||
sp<WeakMessageHandler> mHandler;
|
||||
|
||||
struct Locked {
|
||||
} mLocked;
|
||||
|
||||
void handleMessage(const Message& message);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _UI_SPOT_CONTROLLER_H
|
||||
@@ -36,6 +36,9 @@ namespace android {
|
||||
SpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer) :
|
||||
mLooper(looper), mOverlayLayer(overlayLayer) {
|
||||
mHandler = new WeakMessageHandler(this);
|
||||
|
||||
mLocked.transactionNestingCount = 0;
|
||||
mLocked.deferredSpriteUpdate = false;
|
||||
}
|
||||
|
||||
SpriteController::~SpriteController() {
|
||||
@@ -51,17 +54,40 @@ sp<Sprite> SpriteController::createSprite() {
|
||||
return new SpriteImpl(this);
|
||||
}
|
||||
|
||||
void SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) {
|
||||
bool wasEmpty = mInvalidatedSprites.isEmpty();
|
||||
mInvalidatedSprites.push(sprite);
|
||||
if (wasEmpty) {
|
||||
void SpriteController::openTransaction() {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
mLocked.transactionNestingCount += 1;
|
||||
}
|
||||
|
||||
void SpriteController::closeTransaction() {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(mLocked.transactionNestingCount == 0,
|
||||
"Sprite closeTransaction() called but there is no open sprite transaction");
|
||||
|
||||
mLocked.transactionNestingCount -= 1;
|
||||
if (mLocked.transactionNestingCount == 0 && mLocked.deferredSpriteUpdate) {
|
||||
mLocked.deferredSpriteUpdate = false;
|
||||
mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) {
|
||||
bool wasEmpty = mLocked.invalidatedSprites.isEmpty();
|
||||
mLocked.invalidatedSprites.push(sprite);
|
||||
if (wasEmpty) {
|
||||
if (mLocked.transactionNestingCount != 0) {
|
||||
mLocked.deferredSpriteUpdate = true;
|
||||
} else {
|
||||
mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) {
|
||||
bool wasEmpty = mDisposedSurfaces.isEmpty();
|
||||
mDisposedSurfaces.push(surfaceControl);
|
||||
bool wasEmpty = mLocked.disposedSurfaces.isEmpty();
|
||||
mLocked.disposedSurfaces.push(surfaceControl);
|
||||
if (wasEmpty) {
|
||||
mLooper->sendMessage(mHandler, Message(MSG_DISPOSE_SURFACES));
|
||||
}
|
||||
@@ -89,14 +115,14 @@ void SpriteController::doUpdateSprites() {
|
||||
{ // acquire lock
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
numSprites = mInvalidatedSprites.size();
|
||||
numSprites = mLocked.invalidatedSprites.size();
|
||||
for (size_t i = 0; i < numSprites; i++) {
|
||||
const sp<SpriteImpl>& sprite = mInvalidatedSprites.itemAt(i);
|
||||
const sp<SpriteImpl>& sprite = mLocked.invalidatedSprites.itemAt(i);
|
||||
|
||||
updates.push(SpriteUpdate(sprite, sprite->getStateLocked()));
|
||||
sprite->resetDirtyLocked();
|
||||
}
|
||||
mInvalidatedSprites.clear();
|
||||
mLocked.invalidatedSprites.clear();
|
||||
} // release lock
|
||||
|
||||
// Create missing surfaces.
|
||||
@@ -105,8 +131,8 @@ void SpriteController::doUpdateSprites() {
|
||||
SpriteUpdate& update = updates.editItemAt(i);
|
||||
|
||||
if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) {
|
||||
update.state.surfaceWidth = update.state.bitmap.width();
|
||||
update.state.surfaceHeight = update.state.bitmap.height();
|
||||
update.state.surfaceWidth = update.state.icon.bitmap.width();
|
||||
update.state.surfaceHeight = update.state.icon.bitmap.height();
|
||||
update.state.surfaceDrawn = false;
|
||||
update.state.surfaceVisible = false;
|
||||
update.state.surfaceControl = obtainSurface(
|
||||
@@ -123,8 +149,8 @@ void SpriteController::doUpdateSprites() {
|
||||
SpriteUpdate& update = updates.editItemAt(i);
|
||||
|
||||
if (update.state.surfaceControl != NULL && update.state.wantSurfaceVisible()) {
|
||||
int32_t desiredWidth = update.state.bitmap.width();
|
||||
int32_t desiredHeight = update.state.bitmap.height();
|
||||
int32_t desiredWidth = update.state.icon.bitmap.width();
|
||||
int32_t desiredHeight = update.state.icon.bitmap.height();
|
||||
if (update.state.surfaceWidth < desiredWidth
|
||||
|| update.state.surfaceHeight < desiredHeight) {
|
||||
if (!haveGlobalTransaction) {
|
||||
@@ -187,16 +213,16 @@ void SpriteController::doUpdateSprites() {
|
||||
|
||||
SkPaint paint;
|
||||
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
|
||||
surfaceCanvas.drawBitmap(update.state.bitmap, 0, 0, &paint);
|
||||
surfaceCanvas.drawBitmap(update.state.icon.bitmap, 0, 0, &paint);
|
||||
|
||||
if (surfaceInfo.w > uint32_t(update.state.bitmap.width())) {
|
||||
if (surfaceInfo.w > uint32_t(update.state.icon.bitmap.width())) {
|
||||
paint.setColor(0); // transparent fill color
|
||||
surfaceCanvas.drawRectCoords(update.state.bitmap.width(), 0,
|
||||
surfaceInfo.w, update.state.bitmap.height(), paint);
|
||||
surfaceCanvas.drawRectCoords(update.state.icon.bitmap.width(), 0,
|
||||
surfaceInfo.w, update.state.icon.bitmap.height(), paint);
|
||||
}
|
||||
if (surfaceInfo.h > uint32_t(update.state.bitmap.height())) {
|
||||
if (surfaceInfo.h > uint32_t(update.state.icon.bitmap.height())) {
|
||||
paint.setColor(0); // transparent fill color
|
||||
surfaceCanvas.drawRectCoords(0, update.state.bitmap.height(),
|
||||
surfaceCanvas.drawRectCoords(0, update.state.icon.bitmap.height(),
|
||||
surfaceInfo.w, surfaceInfo.h, paint);
|
||||
}
|
||||
|
||||
@@ -246,8 +272,8 @@ void SpriteController::doUpdateSprites() {
|
||||
&& (becomingVisible || (update.state.dirty & (DIRTY_POSITION
|
||||
| DIRTY_HOTSPOT)))) {
|
||||
status = update.state.surfaceControl->setPosition(
|
||||
update.state.positionX - update.state.hotSpotX,
|
||||
update.state.positionY - update.state.hotSpotY);
|
||||
update.state.positionX - update.state.icon.hotSpotX,
|
||||
update.state.positionY - update.state.icon.hotSpotY);
|
||||
if (status) {
|
||||
LOGE("Error %d setting sprite surface position.", status);
|
||||
}
|
||||
@@ -329,8 +355,10 @@ void SpriteController::doDisposeSurfaces() {
|
||||
// Collect disposed surfaces.
|
||||
Vector<sp<SurfaceControl> > disposedSurfaces;
|
||||
{ // acquire lock
|
||||
disposedSurfaces = mDisposedSurfaces;
|
||||
mDisposedSurfaces.clear();
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
disposedSurfaces = mLocked.disposedSurfaces;
|
||||
mLocked.disposedSurfaces.clear();
|
||||
} // release lock
|
||||
|
||||
// Release the last reference to each surface outside of the lock.
|
||||
@@ -349,7 +377,8 @@ sp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height
|
||||
|
||||
sp<SurfaceControl> surfaceControl = mSurfaceComposerClient->createSurface(
|
||||
getpid(), String8("Sprite"), 0, width, height, PIXEL_FORMAT_RGBA_8888);
|
||||
if (surfaceControl == NULL) {
|
||||
if (surfaceControl == NULL || !surfaceControl->isValid()
|
||||
|| !surfaceControl->getSurface()->isValid()) {
|
||||
LOGE("Error creating sprite surface.");
|
||||
return NULL;
|
||||
}
|
||||
@@ -360,7 +389,7 @@ sp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height
|
||||
// --- SpriteController::SpriteImpl ---
|
||||
|
||||
SpriteController::SpriteImpl::SpriteImpl(const sp<SpriteController> controller) :
|
||||
mController(controller), mTransactionNestingCount(0) {
|
||||
mController(controller) {
|
||||
}
|
||||
|
||||
SpriteController::SpriteImpl::~SpriteImpl() {
|
||||
@@ -368,27 +397,33 @@ SpriteController::SpriteImpl::~SpriteImpl() {
|
||||
|
||||
// Let the controller take care of deleting the last reference to sprite
|
||||
// surfaces so that we do not block the caller on an IPC here.
|
||||
if (mState.surfaceControl != NULL) {
|
||||
mController->disposeSurfaceLocked(mState.surfaceControl);
|
||||
mState.surfaceControl.clear();
|
||||
if (mLocked.state.surfaceControl != NULL) {
|
||||
mController->disposeSurfaceLocked(mLocked.state.surfaceControl);
|
||||
mLocked.state.surfaceControl.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteController::SpriteImpl::setBitmap(const SkBitmap* bitmap,
|
||||
float hotSpotX, float hotSpotY) {
|
||||
void SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) {
|
||||
AutoMutex _l(mController->mLock);
|
||||
|
||||
if (bitmap) {
|
||||
bitmap->copyTo(&mState.bitmap, SkBitmap::kARGB_8888_Config);
|
||||
} else {
|
||||
mState.bitmap.reset();
|
||||
}
|
||||
uint32_t dirty;
|
||||
if (icon.isValid()) {
|
||||
icon.bitmap.copyTo(&mLocked.state.icon.bitmap, SkBitmap::kARGB_8888_Config);
|
||||
|
||||
uint32_t dirty = DIRTY_BITMAP;
|
||||
if (mState.hotSpotX != hotSpotX || mState.hotSpotY != hotSpotY) {
|
||||
mState.hotSpotX = hotSpotX;
|
||||
mState.hotSpotY = hotSpotY;
|
||||
dirty |= DIRTY_HOTSPOT;
|
||||
if (!mLocked.state.icon.isValid()
|
||||
|| mLocked.state.icon.hotSpotX != icon.hotSpotX
|
||||
|| mLocked.state.icon.hotSpotY != icon.hotSpotY) {
|
||||
mLocked.state.icon.hotSpotX = icon.hotSpotX;
|
||||
mLocked.state.icon.hotSpotY = icon.hotSpotY;
|
||||
dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
|
||||
} else {
|
||||
dirty = DIRTY_BITMAP;
|
||||
}
|
||||
} else if (mLocked.state.icon.isValid()) {
|
||||
mLocked.state.icon.bitmap.reset();
|
||||
dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
|
||||
} else {
|
||||
return; // setting to invalid icon and already invalid so nothing to do
|
||||
}
|
||||
|
||||
invalidateLocked(dirty);
|
||||
@@ -397,8 +432,8 @@ void SpriteController::SpriteImpl::setBitmap(const SkBitmap* bitmap,
|
||||
void SpriteController::SpriteImpl::setVisible(bool visible) {
|
||||
AutoMutex _l(mController->mLock);
|
||||
|
||||
if (mState.visible != visible) {
|
||||
mState.visible = visible;
|
||||
if (mLocked.state.visible != visible) {
|
||||
mLocked.state.visible = visible;
|
||||
invalidateLocked(DIRTY_VISIBILITY);
|
||||
}
|
||||
}
|
||||
@@ -406,9 +441,9 @@ void SpriteController::SpriteImpl::setVisible(bool visible) {
|
||||
void SpriteController::SpriteImpl::setPosition(float x, float y) {
|
||||
AutoMutex _l(mController->mLock);
|
||||
|
||||
if (mState.positionX != x || mState.positionY != y) {
|
||||
mState.positionX = x;
|
||||
mState.positionY = y;
|
||||
if (mLocked.state.positionX != x || mLocked.state.positionY != y) {
|
||||
mLocked.state.positionX = x;
|
||||
mLocked.state.positionY = y;
|
||||
invalidateLocked(DIRTY_POSITION);
|
||||
}
|
||||
}
|
||||
@@ -416,8 +451,8 @@ void SpriteController::SpriteImpl::setPosition(float x, float y) {
|
||||
void SpriteController::SpriteImpl::setLayer(int32_t layer) {
|
||||
AutoMutex _l(mController->mLock);
|
||||
|
||||
if (mState.layer != layer) {
|
||||
mState.layer = layer;
|
||||
if (mLocked.state.layer != layer) {
|
||||
mLocked.state.layer = layer;
|
||||
invalidateLocked(DIRTY_LAYER);
|
||||
}
|
||||
}
|
||||
@@ -425,8 +460,8 @@ void SpriteController::SpriteImpl::setLayer(int32_t layer) {
|
||||
void SpriteController::SpriteImpl::setAlpha(float alpha) {
|
||||
AutoMutex _l(mController->mLock);
|
||||
|
||||
if (mState.alpha != alpha) {
|
||||
mState.alpha = alpha;
|
||||
if (mLocked.state.alpha != alpha) {
|
||||
mLocked.state.alpha = alpha;
|
||||
invalidateLocked(DIRTY_ALPHA);
|
||||
}
|
||||
}
|
||||
@@ -435,38 +470,19 @@ void SpriteController::SpriteImpl::setTransformationMatrix(
|
||||
const SpriteTransformationMatrix& matrix) {
|
||||
AutoMutex _l(mController->mLock);
|
||||
|
||||
if (mState.transformationMatrix != matrix) {
|
||||
mState.transformationMatrix = matrix;
|
||||
if (mLocked.state.transformationMatrix != matrix) {
|
||||
mLocked.state.transformationMatrix = matrix;
|
||||
invalidateLocked(DIRTY_TRANSFORMATION_MATRIX);
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteController::SpriteImpl::openTransaction() {
|
||||
AutoMutex _l(mController->mLock);
|
||||
void SpriteController::SpriteImpl::invalidateLocked(uint32_t dirty) {
|
||||
bool wasDirty = mLocked.state.dirty;
|
||||
mLocked.state.dirty |= dirty;
|
||||
|
||||
mTransactionNestingCount += 1;
|
||||
}
|
||||
|
||||
void SpriteController::SpriteImpl::closeTransaction() {
|
||||
AutoMutex _l(mController->mLock);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(mTransactionNestingCount == 0,
|
||||
"Sprite closeTransaction() called but there is no open sprite transaction");
|
||||
|
||||
mTransactionNestingCount -= 1;
|
||||
if (mTransactionNestingCount == 0 && mState.dirty) {
|
||||
if (!wasDirty) {
|
||||
mController->invalidateSpriteLocked(this);
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteController::SpriteImpl::invalidateLocked(uint32_t dirty) {
|
||||
if (mTransactionNestingCount > 0) {
|
||||
bool wasDirty = mState.dirty;
|
||||
mState.dirty |= dirty;
|
||||
if (!wasDirty) {
|
||||
mController->invalidateSpriteLocked(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -33,6 +33,8 @@ namespace android {
|
||||
*/
|
||||
struct SpriteTransformationMatrix {
|
||||
inline SpriteTransformationMatrix() : dsdx(1.0f), dtdx(0.0f), dsdy(0.0f), dtdy(1.0f) { }
|
||||
inline SpriteTransformationMatrix(float dsdx, float dtdx, float dsdy, float dtdy) :
|
||||
dsdx(dsdx), dtdx(dtdx), dsdy(dsdy), dtdy(dtdy) { }
|
||||
|
||||
float dsdx;
|
||||
float dtdx;
|
||||
@@ -51,6 +53,35 @@ struct SpriteTransformationMatrix {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Icon that a sprite displays, including its hotspot.
|
||||
*/
|
||||
struct SpriteIcon {
|
||||
inline SpriteIcon() : hotSpotX(0), hotSpotY(0) { }
|
||||
inline SpriteIcon(const SkBitmap& bitmap, float hotSpotX, float hotSpotY) :
|
||||
bitmap(bitmap), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
|
||||
|
||||
SkBitmap bitmap;
|
||||
float hotSpotX;
|
||||
float hotSpotY;
|
||||
|
||||
inline SpriteIcon copy() const {
|
||||
SkBitmap bitmapCopy;
|
||||
bitmap.copyTo(&bitmapCopy, SkBitmap::kARGB_8888_Config);
|
||||
return SpriteIcon(bitmapCopy, hotSpotX, hotSpotY);
|
||||
}
|
||||
|
||||
inline void reset() {
|
||||
bitmap.reset();
|
||||
hotSpotX = 0;
|
||||
hotSpotY = 0;
|
||||
}
|
||||
|
||||
inline bool isValid() const {
|
||||
return !bitmap.isNull() && !bitmap.empty();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* A sprite is a simple graphical object that is displayed on-screen above other layers.
|
||||
* The basic sprite class is an interface.
|
||||
@@ -62,9 +93,21 @@ protected:
|
||||
virtual ~Sprite() { }
|
||||
|
||||
public:
|
||||
enum {
|
||||
// The base layer for pointer sprites.
|
||||
BASE_LAYER_POINTER = 0, // reserve space for 1 pointer
|
||||
|
||||
// The base layer for spot sprites.
|
||||
BASE_LAYER_SPOT = 1, // reserve space for MAX_POINTER_ID spots
|
||||
};
|
||||
|
||||
/* Sets the bitmap that is drawn by the sprite.
|
||||
* The sprite retains a copy of the bitmap for subsequent rendering. */
|
||||
virtual void setBitmap(const SkBitmap* bitmap, float hotSpotX, float hotSpotY) = 0;
|
||||
virtual void setIcon(const SpriteIcon& icon) = 0;
|
||||
|
||||
inline void clearIcon() {
|
||||
setIcon(SpriteIcon());
|
||||
}
|
||||
|
||||
/* Sets whether the sprite is visible. */
|
||||
virtual void setVisible(bool visible) = 0;
|
||||
@@ -81,14 +124,6 @@ public:
|
||||
|
||||
/* Sets the sprite transformation matrix. */
|
||||
virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix) = 0;
|
||||
|
||||
/* Opens or closes a transaction to perform a batch of sprite updates as part of
|
||||
* a single operation such as setPosition and setAlpha. It is not necessary to
|
||||
* open a transaction when updating a single property.
|
||||
* Calls to openTransaction() nest and must be matched by an equal number
|
||||
* of calls to closeTransaction(). */
|
||||
virtual void openTransaction() = 0;
|
||||
virtual void closeTransaction() = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -112,6 +147,14 @@ public:
|
||||
/* Creates a new sprite, initially invisible. */
|
||||
sp<Sprite> createSprite();
|
||||
|
||||
/* Opens or closes a transaction to perform a batch of sprite updates as part of
|
||||
* a single operation such as setPosition and setAlpha. It is not necessary to
|
||||
* open a transaction when updating a single property.
|
||||
* Calls to openTransaction() nest and must be matched by an equal number
|
||||
* of calls to closeTransaction(). */
|
||||
void openTransaction();
|
||||
void closeTransaction();
|
||||
|
||||
private:
|
||||
enum {
|
||||
MSG_UPDATE_SPRITES,
|
||||
@@ -135,16 +178,14 @@ private:
|
||||
* Note that the SkBitmap holds a reference to a shared (and immutable) pixel ref. */
|
||||
struct SpriteState {
|
||||
inline SpriteState() :
|
||||
dirty(0), hotSpotX(0), hotSpotY(0), visible(false),
|
||||
dirty(0), visible(false),
|
||||
positionX(0), positionY(0), layer(0), alpha(1.0f),
|
||||
surfaceWidth(0), surfaceHeight(0), surfaceDrawn(false), surfaceVisible(false) {
|
||||
}
|
||||
|
||||
uint32_t dirty;
|
||||
|
||||
SkBitmap bitmap;
|
||||
float hotSpotX;
|
||||
float hotSpotY;
|
||||
SpriteIcon icon;
|
||||
bool visible;
|
||||
float positionX;
|
||||
float positionY;
|
||||
@@ -159,7 +200,7 @@ private:
|
||||
bool surfaceVisible;
|
||||
|
||||
inline bool wantSurfaceVisible() const {
|
||||
return visible && alpha > 0.0f && !bitmap.isNull() && !bitmap.empty();
|
||||
return visible && alpha > 0.0f && icon.isValid();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -177,37 +218,36 @@ private:
|
||||
public:
|
||||
SpriteImpl(const sp<SpriteController> controller);
|
||||
|
||||
virtual void setBitmap(const SkBitmap* bitmap, float hotSpotX, float hotSpotY);
|
||||
virtual void setIcon(const SpriteIcon& icon);
|
||||
virtual void setVisible(bool visible);
|
||||
virtual void setPosition(float x, float y);
|
||||
virtual void setLayer(int32_t layer);
|
||||
virtual void setAlpha(float alpha);
|
||||
virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix);
|
||||
virtual void openTransaction();
|
||||
virtual void closeTransaction();
|
||||
|
||||
inline const SpriteState& getStateLocked() const {
|
||||
return mState;
|
||||
return mLocked.state;
|
||||
}
|
||||
|
||||
inline void resetDirtyLocked() {
|
||||
mState.dirty = 0;
|
||||
mLocked.state.dirty = 0;
|
||||
}
|
||||
|
||||
inline void setSurfaceLocked(const sp<SurfaceControl>& surfaceControl,
|
||||
int32_t width, int32_t height, bool drawn, bool visible) {
|
||||
mState.surfaceControl = surfaceControl;
|
||||
mState.surfaceWidth = width;
|
||||
mState.surfaceHeight = height;
|
||||
mState.surfaceDrawn = drawn;
|
||||
mState.surfaceVisible = visible;
|
||||
mLocked.state.surfaceControl = surfaceControl;
|
||||
mLocked.state.surfaceWidth = width;
|
||||
mLocked.state.surfaceHeight = height;
|
||||
mLocked.state.surfaceDrawn = drawn;
|
||||
mLocked.state.surfaceVisible = visible;
|
||||
}
|
||||
|
||||
private:
|
||||
sp<SpriteController> mController;
|
||||
|
||||
SpriteState mState; // guarded by mController->mLock
|
||||
uint32_t mTransactionNestingCount; // guarded by mController->mLock
|
||||
struct Locked {
|
||||
SpriteState state;
|
||||
} mLocked; // guarded by mController->mLock
|
||||
|
||||
void invalidateLocked(uint32_t dirty);
|
||||
};
|
||||
@@ -232,8 +272,12 @@ private:
|
||||
|
||||
sp<SurfaceComposerClient> mSurfaceComposerClient;
|
||||
|
||||
Vector<sp<SpriteImpl> > mInvalidatedSprites; // guarded by mLock
|
||||
Vector<sp<SurfaceControl> > mDisposedSurfaces; // guarded by mLock
|
||||
struct Locked {
|
||||
Vector<sp<SpriteImpl> > invalidatedSprites;
|
||||
Vector<sp<SurfaceControl> > disposedSurfaces;
|
||||
uint32_t transactionNestingCount;
|
||||
bool deferredSpriteUpdate;
|
||||
} mLocked; // guarded by mLock
|
||||
|
||||
void invalidateSpriteLocked(const sp<SpriteImpl>& sprite);
|
||||
void disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl);
|
||||
|
||||
@@ -97,6 +97,16 @@ private:
|
||||
|
||||
virtual void unfade() {
|
||||
}
|
||||
|
||||
virtual void setPresentation(Presentation presentation) {
|
||||
}
|
||||
|
||||
virtual void setSpots(SpotGesture spotGesture,
|
||||
const PointerCoords* spotCoords, const uint32_t* spotIdToIndex, BitSet32 spotIdBits) {
|
||||
}
|
||||
|
||||
virtual void clearSpots() {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -192,10 +202,6 @@ private:
|
||||
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) {
|
||||
return mPointerControllers.valueFor(deviceId);
|
||||
}
|
||||
|
||||
virtual sp<SpotControllerInterface> obtainSpotController(int32_t device) {
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -23,12 +23,6 @@ import org.xmlpull.v1.XmlPullParser;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
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.Environment;
|
||||
import android.os.Looper;
|
||||
import android.os.MessageQueue;
|
||||
@@ -39,6 +33,7 @@ import android.view.InputChannel;
|
||||
import android.view.InputDevice;
|
||||
import android.view.InputEvent;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.PointerIcon;
|
||||
import android.view.Surface;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.WindowManager;
|
||||
@@ -62,7 +57,8 @@ public class InputManager {
|
||||
private final Context mContext;
|
||||
private final WindowManagerService mWindowManagerService;
|
||||
|
||||
private static native void nativeInit(Callbacks callbacks, MessageQueue messageQueue);
|
||||
private static native void nativeInit(Context context,
|
||||
Callbacks callbacks, MessageQueue messageQueue);
|
||||
private static native void nativeStart();
|
||||
private static native void nativeSetDisplaySize(int displayId, int width, int height);
|
||||
private static native void nativeSetDisplayOrientation(int displayId, int rotation);
|
||||
@@ -125,7 +121,7 @@ public class InputManager {
|
||||
Looper looper = windowManagerService.mH.getLooper();
|
||||
|
||||
Slog.i(TAG, "Initializing input manager");
|
||||
nativeInit(mCallbacks, looper.getQueue());
|
||||
nativeInit(mContext, mCallbacks, looper.getQueue());
|
||||
}
|
||||
|
||||
public void start() {
|
||||
@@ -370,48 +366,6 @@ public class InputManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PointerIcon {
|
||||
public Bitmap bitmap;
|
||||
public float hotSpotX;
|
||||
public float hotSpotY;
|
||||
|
||||
public static PointerIcon load(Resources resources, int resourceId) {
|
||||
PointerIcon icon = new PointerIcon();
|
||||
|
||||
XmlResourceParser parser = resources.getXml(resourceId);
|
||||
final int bitmapRes;
|
||||
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);
|
||||
icon.hotSpotX = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotX, 0);
|
||||
icon.hotSpotY = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotY, 0);
|
||||
a.recycle();
|
||||
} catch (Exception ex) {
|
||||
Slog.e(TAG, "Exception parsing pointer icon resource.", ex);
|
||||
return null;
|
||||
} finally {
|
||||
parser.close();
|
||||
}
|
||||
|
||||
if (bitmapRes == 0) {
|
||||
Slog.e(TAG, "<pointer-icon> is missing bitmap attribute");
|
||||
return null;
|
||||
}
|
||||
|
||||
Drawable drawable = resources.getDrawable(bitmapRes);
|
||||
if (!(drawable instanceof BitmapDrawable)) {
|
||||
Slog.e(TAG, "<pointer-icon> bitmap attribute must refer to a bitmap drawable");
|
||||
return null;
|
||||
}
|
||||
|
||||
icon.bitmap = ((BitmapDrawable)drawable).getBitmap();
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Callbacks from native.
|
||||
*/
|
||||
@@ -564,8 +518,7 @@ public class InputManager {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public PointerIcon getPointerIcon() {
|
||||
return PointerIcon.load(mContext.getResources(),
|
||||
com.android.internal.R.drawable.pointer_arrow_icon);
|
||||
return PointerIcon.getDefaultIcon(mContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,13 +36,13 @@
|
||||
|
||||
#include <input/InputManager.h>
|
||||
#include <input/PointerController.h>
|
||||
#include <input/SpotController.h>
|
||||
#include <input/SpriteController.h>
|
||||
|
||||
#include <android_os_MessageQueue.h>
|
||||
#include <android_view_KeyEvent.h>
|
||||
#include <android_view_MotionEvent.h>
|
||||
#include <android_view_InputChannel.h>
|
||||
#include <android_view_PointerIcon.h>
|
||||
#include <android/graphics/GraphicsJNI.h>
|
||||
|
||||
#include "com_android_server_PowerManagerService.h"
|
||||
@@ -104,14 +104,6 @@ static struct {
|
||||
jfieldID navigation;
|
||||
} gConfigurationClassInfo;
|
||||
|
||||
static struct {
|
||||
jclass clazz;
|
||||
|
||||
jfieldID bitmap;
|
||||
jfieldID hotSpotX;
|
||||
jfieldID hotSpotY;
|
||||
} gPointerIconClassInfo;
|
||||
|
||||
|
||||
// --- Global functions ---
|
||||
|
||||
@@ -133,17 +125,30 @@ static jobject getInputWindowHandleObjLocalRef(JNIEnv* env,
|
||||
getInputWindowHandleObjLocalRef(env);
|
||||
}
|
||||
|
||||
static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, int32_t style,
|
||||
SpriteIcon* outSpriteIcon) {
|
||||
PointerIcon pointerIcon;
|
||||
status_t status = android_view_PointerIcon_loadSystemIcon(env,
|
||||
contextObj, style, &pointerIcon);
|
||||
if (!status) {
|
||||
pointerIcon.bitmap.copyTo(&outSpriteIcon->bitmap, SkBitmap::kARGB_8888_Config);
|
||||
outSpriteIcon->hotSpotX = pointerIcon.hotSpotX;
|
||||
outSpriteIcon->hotSpotY = pointerIcon.hotSpotY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- NativeInputManager ---
|
||||
|
||||
class NativeInputManager : public virtual RefBase,
|
||||
public virtual InputReaderPolicyInterface,
|
||||
public virtual InputDispatcherPolicyInterface {
|
||||
public virtual InputDispatcherPolicyInterface,
|
||||
public virtual PointerControllerPolicyInterface {
|
||||
protected:
|
||||
virtual ~NativeInputManager();
|
||||
|
||||
public:
|
||||
NativeInputManager(jobject callbacksObj, const sp<Looper>& looper);
|
||||
NativeInputManager(jobject contextObj, jobject callbacksObj, const sp<Looper>& looper);
|
||||
|
||||
inline sp<InputManager> getInputManager() const { return mInputManager; }
|
||||
|
||||
@@ -170,7 +175,6 @@ public:
|
||||
virtual nsecs_t getVirtualKeyQuietTime();
|
||||
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
|
||||
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
|
||||
virtual sp<SpotControllerInterface> obtainSpotController(int32_t deviceId);
|
||||
|
||||
/* --- InputDispatcherPolicyInterface implementation --- */
|
||||
|
||||
@@ -193,9 +197,14 @@ public:
|
||||
virtual bool checkInjectEventsPermissionNonReentrant(
|
||||
int32_t injectorPid, int32_t injectorUid);
|
||||
|
||||
/* --- PointerControllerPolicyInterface implementation --- */
|
||||
|
||||
virtual void loadPointerResources(PointerResources* outResources);
|
||||
|
||||
private:
|
||||
sp<InputManager> mInputManager;
|
||||
|
||||
jobject mContextObj;
|
||||
jobject mCallbacksObj;
|
||||
sp<Looper> mLooper;
|
||||
|
||||
@@ -227,7 +236,7 @@ private:
|
||||
wp<PointerController> pointerController;
|
||||
} mLocked;
|
||||
|
||||
void updateInactivityFadeDelayLocked(const sp<PointerController>& controller);
|
||||
void updateInactivityTimeoutLocked(const sp<PointerController>& controller);
|
||||
void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
|
||||
void ensureSpriteControllerLocked();
|
||||
|
||||
@@ -244,13 +253,15 @@ private:
|
||||
|
||||
|
||||
|
||||
NativeInputManager::NativeInputManager(jobject callbacksObj, const sp<Looper>& looper) :
|
||||
NativeInputManager::NativeInputManager(jobject contextObj,
|
||||
jobject callbacksObj, const sp<Looper>& looper) :
|
||||
mLooper(looper),
|
||||
mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), mVirtualKeyQuietTime(-1),
|
||||
mKeyRepeatTimeout(-1), mKeyRepeatDelay(-1),
|
||||
mMaxEventsPerSecond(-1) {
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
mContextObj = env->NewGlobalRef(contextObj);
|
||||
mCallbacksObj = env->NewGlobalRef(callbacksObj);
|
||||
|
||||
{
|
||||
@@ -269,6 +280,7 @@ NativeInputManager::NativeInputManager(jobject callbacksObj, const sp<Looper>& l
|
||||
NativeInputManager::~NativeInputManager() {
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
env->DeleteGlobalRef(mContextObj);
|
||||
env->DeleteGlobalRef(mCallbacksObj);
|
||||
}
|
||||
|
||||
@@ -292,9 +304,13 @@ bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const c
|
||||
|
||||
void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
|
||||
if (displayId == 0) {
|
||||
AutoMutex _l(mLock);
|
||||
{ // acquire lock
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
if (mLocked.displayWidth == width && mLocked.displayHeight == height) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
|
||||
mLocked.displayWidth = width;
|
||||
mLocked.displayHeight = height;
|
||||
|
||||
@@ -302,7 +318,7 @@ void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_
|
||||
if (controller != NULL) {
|
||||
controller->setDisplaySize(width, height);
|
||||
}
|
||||
}
|
||||
} // release lock
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,40 +448,33 @@ sp<PointerControllerInterface> NativeInputManager::obtainPointerController(int32
|
||||
if (controller == NULL) {
|
||||
ensureSpriteControllerLocked();
|
||||
|
||||
controller = new PointerController(mLooper, mLocked.spriteController);
|
||||
controller = new PointerController(this, mLooper, mLocked.spriteController);
|
||||
mLocked.pointerController = controller;
|
||||
|
||||
controller->setDisplaySize(mLocked.displayWidth, mLocked.displayHeight);
|
||||
controller->setDisplayOrientation(mLocked.displayOrientation);
|
||||
|
||||
JNIEnv* env = jniEnv();
|
||||
jobject iconObj = env->CallObjectMethod(mCallbacksObj, gCallbacksClassInfo.getPointerIcon);
|
||||
if (!checkAndClearExceptionFromCallback(env, "getPointerIcon") && iconObj) {
|
||||
jfloat iconHotSpotX = env->GetFloatField(iconObj, gPointerIconClassInfo.hotSpotX);
|
||||
jfloat iconHotSpotY = env->GetFloatField(iconObj, gPointerIconClassInfo.hotSpotY);
|
||||
jobject iconBitmapObj = env->GetObjectField(iconObj, gPointerIconClassInfo.bitmap);
|
||||
if (iconBitmapObj) {
|
||||
SkBitmap* iconBitmap = GraphicsJNI::getNativeBitmap(env, iconBitmapObj);
|
||||
if (iconBitmap) {
|
||||
controller->setPointerIcon(iconBitmap, iconHotSpotX, iconHotSpotY);
|
||||
}
|
||||
env->DeleteLocalRef(iconBitmapObj);
|
||||
jobject pointerIconObj = env->CallObjectMethod(mCallbacksObj,
|
||||
gCallbacksClassInfo.getPointerIcon);
|
||||
if (!checkAndClearExceptionFromCallback(env, "getPointerIcon")) {
|
||||
PointerIcon pointerIcon;
|
||||
status_t status = android_view_PointerIcon_load(env, pointerIconObj,
|
||||
mContextObj, &pointerIcon);
|
||||
if (!status && !pointerIcon.isNullIcon()) {
|
||||
controller->setPointerIcon(SpriteIcon(pointerIcon.bitmap,
|
||||
pointerIcon.hotSpotX, pointerIcon.hotSpotY));
|
||||
} else {
|
||||
controller->setPointerIcon(SpriteIcon());
|
||||
}
|
||||
env->DeleteLocalRef(iconObj);
|
||||
env->DeleteLocalRef(pointerIconObj);
|
||||
}
|
||||
|
||||
updateInactivityFadeDelayLocked(controller);
|
||||
updateInactivityTimeoutLocked(controller);
|
||||
}
|
||||
return controller;
|
||||
}
|
||||
|
||||
sp<SpotControllerInterface> NativeInputManager::obtainSpotController(int32_t deviceId) {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
ensureSpriteControllerLocked();
|
||||
return new SpotController(mLooper, mLocked.spriteController);
|
||||
}
|
||||
|
||||
void NativeInputManager::ensureSpriteControllerLocked() {
|
||||
if (mLocked.spriteController == NULL) {
|
||||
JNIEnv* env = jniEnv();
|
||||
@@ -646,16 +655,16 @@ void NativeInputManager::setSystemUiVisibility(int32_t visibility) {
|
||||
|
||||
sp<PointerController> controller = mLocked.pointerController.promote();
|
||||
if (controller != NULL) {
|
||||
updateInactivityFadeDelayLocked(controller);
|
||||
updateInactivityTimeoutLocked(controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NativeInputManager::updateInactivityFadeDelayLocked(const sp<PointerController>& controller) {
|
||||
void NativeInputManager::updateInactivityTimeoutLocked(const sp<PointerController>& controller) {
|
||||
bool lightsOut = mLocked.systemUiVisibility & ASYSTEM_UI_VISIBILITY_STATUS_BAR_HIDDEN;
|
||||
controller->setInactivityFadeDelay(lightsOut
|
||||
? PointerController::INACTIVITY_FADE_DELAY_SHORT
|
||||
: PointerController::INACTIVITY_FADE_DELAY_NORMAL);
|
||||
controller->setInactivityTimeout(lightsOut
|
||||
? PointerController::INACTIVITY_TIMEOUT_SHORT
|
||||
: PointerController::INACTIVITY_TIMEOUT_NORMAL);
|
||||
}
|
||||
|
||||
bool NativeInputManager::isScreenOn() {
|
||||
@@ -856,6 +865,17 @@ bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
|
||||
return result;
|
||||
}
|
||||
|
||||
void NativeInputManager::loadPointerResources(PointerResources* outResources) {
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_HOVER,
|
||||
&outResources->spotHover);
|
||||
loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_TOUCH,
|
||||
&outResources->spotTouch);
|
||||
loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_ANCHOR,
|
||||
&outResources->spotAnchor);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -871,10 +891,10 @@ static bool checkInputManagerUnitialized(JNIEnv* env) {
|
||||
}
|
||||
|
||||
static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
|
||||
jobject callbacks, jobject messageQueueObj) {
|
||||
jobject contextObj, jobject callbacksObj, jobject messageQueueObj) {
|
||||
if (gNativeInputManager == NULL) {
|
||||
sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
|
||||
gNativeInputManager = new NativeInputManager(callbacks, looper);
|
||||
gNativeInputManager = new NativeInputManager(contextObj, callbacksObj, looper);
|
||||
} else {
|
||||
LOGE("Input manager already initialized.");
|
||||
jniThrowRuntimeException(env, "Input manager already initialized.");
|
||||
@@ -1207,7 +1227,8 @@ static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz)
|
||||
|
||||
static JNINativeMethod gInputManagerMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{ "nativeInit", "(Lcom/android/server/wm/InputManager$Callbacks;Landroid/os/MessageQueue;)V",
|
||||
{ "nativeInit", "(Landroid/content/Context;"
|
||||
"Lcom/android/server/wm/InputManager$Callbacks;Landroid/os/MessageQueue;)V",
|
||||
(void*) android_server_InputManager_nativeInit },
|
||||
{ "nativeStart", "()V",
|
||||
(void*) android_server_InputManager_nativeStart },
|
||||
@@ -1328,7 +1349,7 @@ int register_android_server_InputManager(JNIEnv* env) {
|
||||
"getPointerLayer", "()I");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.getPointerIcon, gCallbacksClassInfo.clazz,
|
||||
"getPointerIcon", "()Lcom/android/server/wm/InputManager$PointerIcon;");
|
||||
"getPointerIcon", "()Landroid/view/PointerIcon;");
|
||||
|
||||
// KeyEvent
|
||||
|
||||
@@ -1373,19 +1394,6 @@ int register_android_server_InputManager(JNIEnv* env) {
|
||||
GET_FIELD_ID(gConfigurationClassInfo.navigation, gConfigurationClassInfo.clazz,
|
||||
"navigation", "I");
|
||||
|
||||
// PointerIcon
|
||||
|
||||
FIND_CLASS(gPointerIconClassInfo.clazz, "com/android/server/wm/InputManager$PointerIcon");
|
||||
|
||||
GET_FIELD_ID(gPointerIconClassInfo.bitmap, gPointerIconClassInfo.clazz,
|
||||
"bitmap", "Landroid/graphics/Bitmap;");
|
||||
|
||||
GET_FIELD_ID(gPointerIconClassInfo.hotSpotX, gPointerIconClassInfo.clazz,
|
||||
"hotSpotX", "F");
|
||||
|
||||
GET_FIELD_ID(gPointerIconClassInfo.hotSpotY, gPointerIconClassInfo.clazz,
|
||||
"hotSpotY", "F");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user