Separate default pointer for mouse and stylus (frameworks/base part)
PointerIcon.TYPE_NOT_SPECIFIED will be used for requesting default
pointer.
For the type, MouseCursorController will decide whether to show mouse or
stylus icon, based on the active source.
Need complement: the resource for default stylus icon should be added.
Test: Manual Test(hover pointer on handwriting area)
Bug: b/215436642
Change-Id: I6a337cb69bea57427f676e561900802270d206ae
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 125960f..308248c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -772,7 +772,12 @@
private long mFpsPrevTime = -1;
private int mFpsNumFrames;
- private int mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
+ /**
+ * The resolved pointer icon type requested by this window.
+ * A null value indicates the resolved pointer icon has not yet been calculated.
+ */
+ @Nullable
+ private Integer mPointerIconType = null;
private PointerIcon mCustomPointerIcon = null;
/**
@@ -6905,13 +6910,13 @@
|| event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
// Other apps or the window manager may change the icon type outside of
// this app, therefore the icon type has to be reset on enter/exit event.
- mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
+ mPointerIconType = null;
}
if (event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT) {
if (!updatePointerIcon(event) &&
event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) {
- mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
+ mPointerIconType = null;
}
}
}
@@ -6950,7 +6955,7 @@
}
private void resetPointerIcon(MotionEvent event) {
- mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
+ mPointerIconType = null;
updatePointerIcon(event);
}
@@ -6980,9 +6985,9 @@
}
final int pointerType = (pointerIcon != null) ?
- pointerIcon.getType() : PointerIcon.TYPE_DEFAULT;
+ pointerIcon.getType() : PointerIcon.TYPE_NOT_SPECIFIED;
- if (mPointerIconType != pointerType) {
+ if (mPointerIconType == null || mPointerIconType != pointerType) {
mPointerIconType = pointerType;
mCustomPointerIcon = null;
if (mPointerIconType != PointerIcon.TYPE_CUSTOM) {
diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp
index a835167..24cfc9d 100644
--- a/libs/input/MouseCursorController.cpp
+++ b/libs/input/MouseCursorController.cpp
@@ -38,6 +38,8 @@
: mContext(context) {
std::scoped_lock lock(mLock);
+ mLocked.stylusHoverMode = false;
+
mLocked.animationFrameIndex = 0;
mLocked.lastFrameUpdatedTime = 0;
@@ -47,7 +49,8 @@
mLocked.pointerAlpha = 0.0f; // pointer is initially faded
mLocked.pointerSprite = mContext.getSpriteController()->createSprite();
mLocked.updatePointerIcon = false;
- mLocked.requestedPointerType = mContext.getPolicy()->getDefaultPointerIconId();
+ mLocked.requestedPointerType = PointerIconStyle::TYPE_NOT_SPECIFIED;
+ mLocked.resolvedPointerType = PointerIconStyle::TYPE_NOT_SPECIFIED;
mLocked.resourcesLoaded = false;
@@ -184,6 +187,15 @@
}
}
+void MouseCursorController::setStylusHoverMode(bool stylusHoverMode) {
+ std::scoped_lock lock(mLock);
+
+ if (mLocked.stylusHoverMode != stylusHoverMode) {
+ mLocked.stylusHoverMode = stylusHoverMode;
+ mLocked.updatePointerIcon = true;
+ }
+}
+
void MouseCursorController::reloadPointerResources(bool getAdditionalMouseResources) {
std::scoped_lock lock(mLock);
@@ -339,7 +351,7 @@
bool MouseCursorController::doBitmapAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
std::map<PointerIconStyle, PointerAnimation>::const_iterator iter =
- mLocked.animationResources.find(mLocked.requestedPointerType);
+ mLocked.animationResources.find(mLocked.resolvedPointerType);
if (iter == mLocked.animationResources.end()) {
return false;
}
@@ -381,14 +393,23 @@
}
if (mLocked.updatePointerIcon) {
- if (mLocked.requestedPointerType == mContext.getPolicy()->getDefaultPointerIconId()) {
+ mLocked.resolvedPointerType = mLocked.requestedPointerType;
+ const PointerIconStyle defaultPointerIconId =
+ mContext.getPolicy()->getDefaultPointerIconId();
+ if (mLocked.resolvedPointerType == PointerIconStyle::TYPE_NOT_SPECIFIED) {
+ mLocked.resolvedPointerType = mLocked.stylusHoverMode
+ ? mContext.getPolicy()->getDefaultStylusIconId()
+ : defaultPointerIconId;
+ }
+
+ if (mLocked.resolvedPointerType == defaultPointerIconId) {
mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
} else {
std::map<PointerIconStyle, SpriteIcon>::const_iterator iter =
- mLocked.additionalMouseResources.find(mLocked.requestedPointerType);
+ mLocked.additionalMouseResources.find(mLocked.resolvedPointerType);
if (iter != mLocked.additionalMouseResources.end()) {
std::map<PointerIconStyle, PointerAnimation>::const_iterator anim_iter =
- mLocked.animationResources.find(mLocked.requestedPointerType);
+ mLocked.animationResources.find(mLocked.resolvedPointerType);
if (anim_iter != mLocked.animationResources.end()) {
mLocked.animationFrameIndex = 0;
mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -396,7 +417,7 @@
}
mLocked.pointerSprite->setIcon(iter->second);
} else {
- ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType);
+ ALOGW("Can't find the resource for icon id %d", mLocked.resolvedPointerType);
mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
}
}
diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h
index 208d33d..db0ab56 100644
--- a/libs/input/MouseCursorController.h
+++ b/libs/input/MouseCursorController.h
@@ -53,6 +53,7 @@
void fade(PointerControllerInterface::Transition transition);
void unfade(PointerControllerInterface::Transition transition);
void setDisplayViewport(const DisplayViewport& viewport, bool getAdditionalMouseResources);
+ void setStylusHoverMode(bool stylusHoverMode);
void updatePointerIcon(PointerIconStyle iconId);
void setCustomPointerIcon(const SpriteIcon& icon);
@@ -74,6 +75,7 @@
struct Locked {
DisplayViewport viewport;
+ bool stylusHoverMode;
size_t animationFrameIndex;
nsecs_t lastFrameUpdatedTime;
@@ -92,6 +94,7 @@
std::map<PointerIconStyle, PointerAnimation> animationResources;
PointerIconStyle requestedPointerType;
+ PointerIconStyle resolvedPointerType;
int32_t buttonState;
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 099efd3..fedf58d 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -195,7 +195,11 @@
return;
}
- if (presentation == Presentation::POINTER) {
+ if (presentation == Presentation::POINTER || presentation == Presentation::STYLUS_HOVER) {
+ // For now, we support stylus hover using the mouse cursor implementation.
+ // TODO: Add proper support for stylus hover icons.
+ mCursorController.setStylusHoverMode(presentation == Presentation::STYLUS_HOVER);
+
mCursorController.getAdditionalMouseResources();
clearSpotsLocked();
}
@@ -249,7 +253,8 @@
if (mCursorController.resourcesLoaded()) {
bool getAdditionalMouseResources = false;
- if (mLocked.presentation == PointerController::Presentation::POINTER) {
+ if (mLocked.presentation == PointerController::Presentation::POINTER ||
+ mLocked.presentation == PointerController::Presentation::STYLUS_HOVER) {
getAdditionalMouseResources = true;
}
mCursorController.reloadPointerResources(getAdditionalMouseResources);
@@ -260,7 +265,8 @@
std::scoped_lock lock(getLock());
bool getAdditionalMouseResources = false;
- if (mLocked.presentation == PointerController::Presentation::POINTER) {
+ if (mLocked.presentation == PointerController::Presentation::POINTER ||
+ mLocked.presentation == PointerController::Presentation::STYLUS_HOVER) {
getAdditionalMouseResources = true;
}
mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources);
diff --git a/libs/input/PointerControllerContext.h b/libs/input/PointerControllerContext.h
index 1797428..96d83a5 100644
--- a/libs/input/PointerControllerContext.h
+++ b/libs/input/PointerControllerContext.h
@@ -79,6 +79,7 @@
std::map<PointerIconStyle, PointerAnimation>* outAnimationResources,
int32_t displayId) = 0;
virtual PointerIconStyle getDefaultPointerIconId() = 0;
+ virtual PointerIconStyle getDefaultStylusIconId() = 0;
virtual PointerIconStyle getCustomPointerIconId() = 0;
virtual void onPointerDisplayIdChanged(int32_t displayId, float xPos, float yPos) = 0;
};
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp
index a6a4115..c820d00 100644
--- a/libs/input/tests/PointerController_test.cpp
+++ b/libs/input/tests/PointerController_test.cpp
@@ -35,6 +35,7 @@
CURSOR_TYPE_ANCHOR,
CURSOR_TYPE_ADDITIONAL,
CURSOR_TYPE_ADDITIONAL_ANIM,
+ CURSOR_TYPE_STYLUS,
CURSOR_TYPE_CUSTOM = -1,
};
@@ -57,6 +58,7 @@
std::map<PointerIconStyle, PointerAnimation>* outAnimationResources,
int32_t displayId) override;
virtual PointerIconStyle getDefaultPointerIconId() override;
+ virtual PointerIconStyle getDefaultStylusIconId() override;
virtual PointerIconStyle getCustomPointerIconId() override;
virtual void onPointerDisplayIdChanged(int32_t displayId, float xPos, float yPos) override;
@@ -105,6 +107,11 @@
(*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
(*outAnimationResources)[static_cast<PointerIconStyle>(cursorType)] = anim;
+ // CURSOR_TYPE_STYLUS doesn't have animation resource.
+ cursorType = CURSOR_TYPE_STYLUS;
+ loadPointerIconForType(&icon, cursorType);
+ (*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
+
additionalMouseResourcesLoaded = true;
}
@@ -112,6 +119,10 @@
return static_cast<PointerIconStyle>(CURSOR_TYPE_DEFAULT);
}
+PointerIconStyle MockPointerControllerPolicyInterface::getDefaultStylusIconId() {
+ return static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS);
+}
+
PointerIconStyle MockPointerControllerPolicyInterface::getCustomPointerIconId() {
return static_cast<PointerIconStyle>(CURSOR_TYPE_CUSTOM);
}
@@ -214,6 +225,21 @@
mPointerController->reloadPointerResources();
}
+TEST_F(PointerControllerTest, useStylusTypeForStylusHover) {
+ ensureDisplayViewportIsSet();
+ mPointerController->setPresentation(PointerController::Presentation::STYLUS_HOVER);
+ mPointerController->unfade(PointerController::Transition::IMMEDIATE);
+ std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_STYLUS);
+ EXPECT_CALL(*mPointerSprite, setVisible(true));
+ EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
+ EXPECT_CALL(*mPointerSprite,
+ setIcon(AllOf(Field(&SpriteIcon::style,
+ static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS)),
+ Field(&SpriteIcon::hotSpotX, hotspot.first),
+ Field(&SpriteIcon::hotSpotY, hotspot.second))));
+ mPointerController->reloadPointerResources();
+}
+
TEST_F(PointerControllerTest, updatePointerIcon) {
ensureDisplayViewportIsSet();
mPointerController->setPresentation(PointerController::Presentation::POINTER);
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index f4d1d1e..56ccf87 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -363,6 +363,7 @@
std::map<PointerIconStyle, SpriteIcon>* outResources,
std::map<PointerIconStyle, PointerAnimation>* outAnimationResources, int32_t displayId);
virtual PointerIconStyle getDefaultPointerIconId();
+ virtual PointerIconStyle getDefaultStylusIconId();
virtual PointerIconStyle getCustomPointerIconId();
virtual void onPointerDisplayIdChanged(int32_t displayId, float xPos, float yPos);
@@ -1605,6 +1606,11 @@
return PointerIconStyle::TYPE_ARROW;
}
+PointerIconStyle NativeInputManager::getDefaultStylusIconId() {
+ // TODO: add resource for default stylus icon and change this
+ return PointerIconStyle::TYPE_CROSSHAIR;
+}
+
PointerIconStyle NativeInputManager::getCustomPointerIconId() {
return PointerIconStyle::TYPE_CUSTOM;
}