Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8148cc3e authored by Jeff Brown's avatar Jeff Brown Committed by Android Git Automerger
Browse files

am 86ea1f5f: Initial checkin of spot presentation for touchpad gestures. (DO NOT MERGE)

* commit '86ea1f5f':
  Initial checkin of spot presentation for touchpad gestures. (DO NOT MERGE)
parents e8dc05aa 86ea1f5f
Loading
Loading
Loading
Loading
+2 −28
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.view;

import com.android.internal.util.XmlUtils;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

/**
 * Represents an icon that can be used as a mouse pointer.
 * <p>
 * Pointer icons can be provided either by the system using system styles,
 * or by applications using bitmaps or application resources.
 * </p>
 *
 * @hide
 */
public final class PointerIcon implements Parcelable {
    private static final String TAG = "PointerIcon";

    /** Style constant: Custom icon with a user-supplied bitmap. */
    public static final int STYLE_CUSTOM = -1;

    /** Style constant: Null icon.  It has no bitmap. */
    public static final int STYLE_NULL = 0;

    /** Style constant: Arrow icon.  (Default mouse pointer) */
    public static final int STYLE_ARROW = 1000;

    /** {@hide} Style constant: Spot hover icon for touchpads. */
    public static final int STYLE_SPOT_HOVER = 2000;

    /** {@hide} Style constant: Spot touch icon for touchpads. */
    public static final int STYLE_SPOT_TOUCH = 2001;

    /** {@hide} Style constant: Spot anchor icon for touchpads. */
    public static final int STYLE_SPOT_ANCHOR = 2002;

    // OEM private styles should be defined starting at this range to avoid
    // conflicts with any system styles that may be defined in the future.
    private static final int STYLE_OEM_FIRST = 10000;

    // The default pointer icon.
    private static final int STYLE_DEFAULT = STYLE_ARROW;

    private static final PointerIcon gNullIcon = new PointerIcon(STYLE_NULL);

    private final int mStyle;
    private int mSystemIconResourceId;
    private Bitmap mBitmap;
    private float mHotSpotX;
    private float mHotSpotY;

    private PointerIcon(int style) {
        mStyle = style;
    }

    /**
     * Gets a special pointer icon that has no bitmap.
     *
     * @return The null pointer icon.
     *
     * @see #STYLE_NULL
     */
    public static PointerIcon getNullIcon() {
        return gNullIcon;
    }

    /**
     * Gets the default pointer icon.
     *
     * @param context The context.
     * @return The default pointer icon.
     *
     * @throws IllegalArgumentException if context is null.
     */
    public static PointerIcon getDefaultIcon(Context context) {
        return getSystemIcon(context, STYLE_DEFAULT);
    }

    /**
     * Gets a system pointer icon for the given style.
     * If style is not recognized, returns the default pointer icon.
     *
     * @param context The context.
     * @param style The pointer icon style.
     * @return The pointer icon.
     *
     * @throws IllegalArgumentException if context is null.
     */
    public static PointerIcon getSystemIcon(Context context, int style) {
        if (context == null) {
            throw new IllegalArgumentException("context must not be null");
        }

        if (style == STYLE_NULL) {
            return gNullIcon;
        }

        int styleIndex = getSystemIconStyleIndex(style);
        if (styleIndex == 0) {
            styleIndex = getSystemIconStyleIndex(STYLE_DEFAULT);
        }

        TypedArray a = context.obtainStyledAttributes(null,
                com.android.internal.R.styleable.Pointer,
                com.android.internal.R.attr.pointerStyle, 0);
        int resourceId = a.getResourceId(styleIndex, -1);
        a.recycle();

        if (resourceId == -1) {
            Log.w(TAG, "Missing theme resources for pointer icon style " + style);
            return style == STYLE_DEFAULT ? gNullIcon : getSystemIcon(context, STYLE_DEFAULT);
        }

        PointerIcon icon = new PointerIcon(style);
        if ((resourceId & 0xff000000) == 0x01000000) {
            icon.mSystemIconResourceId = resourceId;
        } else {
            icon.loadResource(context.getResources(), resourceId);
        }
        return icon;
    }

    /**
     * Creates a custom pointer from the given bitmap and hotspot information.
     *
     * @param bitmap The bitmap for the icon.
     * @param hotspotX The X offset of the pointer icon hotspot in the bitmap.
     *        Must be within the [0, bitmap.getWidth()) range.
     * @param hotspotY The Y offset of the pointer icon hotspot in the bitmap.
     *        Must be within the [0, bitmap.getHeight()) range.
     * @return A pointer icon for this bitmap.
     *
     * @throws IllegalArgumentException if bitmap is null, or if the x/y hotspot
     *         parameters are invalid.
     */
    public static PointerIcon createCustomIcon(Bitmap bitmap, float hotSpotX, float hotSpotY) {
        if (bitmap == null) {
            throw new IllegalArgumentException("bitmap must not be null");
        }
        validateHotSpot(bitmap, hotSpotX, hotSpotY);

        PointerIcon icon = new PointerIcon(STYLE_CUSTOM);
        icon.mBitmap = bitmap;
        icon.mHotSpotX = hotSpotX;
        icon.mHotSpotY = hotSpotY;
        return icon;
    }

    /**
     * Loads a custom pointer icon from an XML resource.
     * <p>
     * The XML resource should have the following form:
     * <code>
     * &lt;?xml version="1.0" encoding="utf-8"?&gt;
     * &lt;pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
     *   android:bitmap="@drawable/my_pointer_bitmap"
     *   android:hotSpotX="24"
     *   android:hotSpotY="24" /&gt;
     * </code>
     * </p>
     *
     * @param resources The resources object.
     * @param resourceId The resource id.
     * @return The pointer icon.
     *
     * @throws IllegalArgumentException if resources is null.
     * @throws Resources.NotFoundException if the resource was not found or the drawable
     * linked in the resource was not found.
     */
    public static PointerIcon loadCustomIcon(Resources resources, int resourceId) {
        if (resources == null) {
            throw new IllegalArgumentException("resources must not be null");
        }

        PointerIcon icon = new PointerIcon(STYLE_CUSTOM);
        icon.loadResource(resources, resourceId);
        return icon;
    }

    /**
     * Loads the bitmap and hotspot information for a pointer icon, if it is not already loaded.
     * Returns a pointer icon (not necessarily the same instance) with the information filled in.
     *
     * @param context The context.
     * @return The loaded pointer icon.
     *
     * @throws IllegalArgumentException if context is null.
     * @see #isLoaded()
     * @hide
     */
    public PointerIcon load(Context context) {
        if (context == null) {
            throw new IllegalArgumentException("context must not be null");
        }

        if (mSystemIconResourceId == 0 || mBitmap != null) {
            return this;
        }

        PointerIcon result = new PointerIcon(mStyle);
        result.mSystemIconResourceId = mSystemIconResourceId;
        result.loadResource(context.getResources(), mSystemIconResourceId);
        return result;
    }

    /**
     * Returns true if the pointer icon style is {@link #STYLE_NULL}.
     *
     * @return True if the pointer icon style is {@link #STYLE_NULL}.
     */
    public boolean isNullIcon() {
        return mStyle == STYLE_NULL;
    }

    /**
     * Returns true if the pointer icon has been loaded and its bitmap and hotspot
     * information are available.
     *
     * @return True if the pointer icon is loaded.
     * @see #load(Context)
     */
    public boolean isLoaded() {
        return mBitmap != null || mStyle == STYLE_NULL;
    }

    /**
     * Gets the style of the pointer icon.
     *
     * @return The pointer icon style.
     */
    public int getStyle() {
        return mStyle;
    }

    /**
     * Gets the bitmap of the pointer icon.
     *
     * @return The pointer icon bitmap, or null if the style is {@link #STYLE_NULL}.
     *
     * @throws IllegalStateException if the bitmap is not loaded.
     * @see #isLoaded()
     * @see #load(Context)
     */
    public Bitmap getBitmap() {
        throwIfIconIsNotLoaded();
        return mBitmap;
    }

    /**
     * Gets the X offset of the pointer icon hotspot.
     *
     * @return The hotspot X offset.
     *
     * @throws IllegalStateException if the bitmap is not loaded.
     * @see #isLoaded()
     * @see #load(Context)
     */
    public float getHotSpotX() {
        throwIfIconIsNotLoaded();
        return mHotSpotX;
    }

    /**
     * Gets the Y offset of the pointer icon hotspot.
     *
     * @return The hotspot Y offset.
     *
     * @throws IllegalStateException if the bitmap is not loaded.
     * @see #isLoaded()
     * @see #load(Context)
     */
    public float getHotSpotY() {
        throwIfIconIsNotLoaded();
        return mHotSpotY;
    }

    private void throwIfIconIsNotLoaded() {
        if (!isLoaded()) {
            throw new IllegalStateException("The icon is not loaded.");
        }
    }

    public static final Parcelable.Creator<PointerIcon> CREATOR
            = new Parcelable.Creator<PointerIcon>() {
        public PointerIcon createFromParcel(Parcel in) {
            int style = in.readInt();
            if (style == STYLE_NULL) {
                return getNullIcon();
            }

            int systemIconResourceId = in.readInt();
            if (systemIconResourceId != 0) {
                PointerIcon icon = new PointerIcon(style);
                icon.mSystemIconResourceId = systemIconResourceId;
                return icon;
            }

            Bitmap bitmap = Bitmap.CREATOR.createFromParcel(in);
            float hotSpotX = in.readFloat();
            float hotSpotY = in.readFloat();
            return PointerIcon.createCustomIcon(bitmap, hotSpotX, hotSpotY);
        }

        public PointerIcon[] newArray(int size) {
            return new PointerIcon[size];
        }
    };

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mStyle);

        if (mStyle != STYLE_NULL) {
            out.writeInt(mSystemIconResourceId);
            if (mSystemIconResourceId == 0) {
                mBitmap.writeToParcel(out, flags);
                out.writeFloat(mHotSpotX);
                out.writeFloat(mHotSpotY);
            }
        }
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }

        if (other == null || !(other instanceof PointerIcon)) {
            return false;
        }

        PointerIcon otherIcon = (PointerIcon) other;
        if (mStyle != otherIcon.mStyle
                || mSystemIconResourceId != otherIcon.mSystemIconResourceId) {
            return false;
        }

        if (mSystemIconResourceId == 0 && (mBitmap != otherIcon.mBitmap
                || mHotSpotX != otherIcon.mHotSpotX
                || mHotSpotY != otherIcon.mHotSpotY)) {
            return false;
        }

        return true;
    }

    private void loadResource(Resources resources, int resourceId) {
        XmlResourceParser parser = resources.getXml(resourceId);
        final int bitmapRes;
        final float hotSpotX;
        final float hotSpotY;
        try {
            XmlUtils.beginDocument(parser, "pointer-icon");

            TypedArray a = resources.obtainAttributes(
                    parser, com.android.internal.R.styleable.PointerIcon);
            bitmapRes = a.getResourceId(com.android.internal.R.styleable.PointerIcon_bitmap, 0);
            hotSpotX = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotX, 0);
            hotSpotY = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotY, 0);
            a.recycle();
        } catch (Exception ex) {
            throw new IllegalArgumentException("Exception parsing pointer icon resource.", ex);
        } finally {
            parser.close();
        }

        if (bitmapRes == 0) {
            throw new IllegalArgumentException("<pointer-icon> is missing bitmap attribute.");
        }

        Drawable drawable = resources.getDrawable(bitmapRes);
        if (!(drawable instanceof BitmapDrawable)) {
            throw new IllegalArgumentException("<pointer-icon> bitmap attribute must "
                    + "refer to a bitmap drawable.");
        }

        // Set the properties now that we have successfully loaded the icon.
        mBitmap = ((BitmapDrawable)drawable).getBitmap();
        mHotSpotX = hotSpotX;
        mHotSpotY = hotSpotY;
    }

    private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY) {
        if (hotSpotX < 0 || hotSpotX >= bitmap.getWidth()) {
            throw new IllegalArgumentException("x hotspot lies outside of the bitmap area");
        }
        if (hotSpotY < 0 || hotSpotY >= bitmap.getHeight()) {
            throw new IllegalArgumentException("y hotspot lies outside of the bitmap area");
        }
    }

    private static int getSystemIconStyleIndex(int style) {
        switch (style) {
            case STYLE_ARROW:
                return com.android.internal.R.styleable.Pointer_pointerIconArrow;
            case STYLE_SPOT_HOVER:
                return com.android.internal.R.styleable.Pointer_pointerIconSpotHover;
            case STYLE_SPOT_TOUCH:
                return com.android.internal.R.styleable.Pointer_pointerIconSpotTouch;
            case STYLE_SPOT_ANCHOR:
                return com.android.internal.R.styleable.Pointer_pointerIconSpotAnchor;
            default:
                return 0;
        }
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -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 \
+2 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
/*
 * 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
Loading