summaryrefslogtreecommitdiffstats
path: root/services/input
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2011-03-02 14:41:58 -0800
committerJeff Brown <jeffbrown@google.com>2011-03-02 15:37:57 -0800
commit05dc66ada6b61a6bdf806ffaa62617ac5394695d (patch)
treea7e395476241706de31498185a5c2ccb979bcb54 /services/input
parente43111fad31ad8e36a66df52a8c6002799996413 (diff)
downloadframeworks_base-05dc66ada6b61a6bdf806ffaa62617ac5394695d.zip
frameworks_base-05dc66ada6b61a6bdf806ffaa62617ac5394695d.tar.gz
frameworks_base-05dc66ada6b61a6bdf806ffaa62617ac5394695d.tar.bz2
Fade out the mouse pointer after inactivity or other events.
Fades out the mouse pointer: - after 15 seconds of inactivity normally - after 3 seconds of inactivity in lights out mode - after a non-modifier key down - after a touch down Extended the native Looper to support enqueuing time delayed messages. This is used by the PointerController to control pointer fade timing. Change-Id: I87792fea7dbe2d9376c78cf354fe3189a484d9da
Diffstat (limited to 'services/input')
-rw-r--r--services/input/InputReader.cpp44
-rw-r--r--services/input/InputReader.h10
-rw-r--r--services/input/PointerController.cpp118
-rw-r--r--services/input/PointerController.h39
-rw-r--r--services/input/tests/InputReader_test.cpp12
5 files changed, 214 insertions, 9 deletions
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index a865d9f..c3c143c 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -399,6 +399,17 @@ bool InputReader::shouldDropVirtualKey(nsecs_t now,
}
}
+void InputReader::fadePointer() {
+ { // acquire device registry reader lock
+ RWLock::AutoRLock _rl(mDeviceRegistryLock);
+
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ device->fadePointer();
+ }
+ } // release device registry reader lock
+}
+
void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
{ // acquire state lock
AutoMutex _l(mStateLock);
@@ -695,6 +706,14 @@ int32_t InputDevice::getMetaState() {
return result;
}
+void InputDevice::fadePointer() {
+ size_t numMappers = mMappers.size();
+ for (size_t i = 0; i < numMappers; i++) {
+ InputMapper* mapper = mMappers[i];
+ mapper->fadePointer();
+ }
+}
+
// --- InputMapper ---
@@ -739,6 +758,9 @@ int32_t InputMapper::getMetaState() {
return 0;
}
+void InputMapper::fadePointer() {
+}
+
void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
const RawAbsoluteAxisInfo& axis, const char* name) {
if (axis.valid) {
@@ -967,6 +989,10 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
getContext()->updateGlobalMetaState();
}
+ if (down && !isMetaKey(keyCode)) {
+ getContext()->fadePointer();
+ }
+
if (policyFlags & POLICY_FLAG_FUNCTION) {
newMetaState |= AMETA_FUNCTION_ON;
}
@@ -1348,6 +1374,9 @@ void CursorInputMapper::sync(nsecs_t when) {
} else {
hscroll = 0;
}
+ if (hscroll != 0 || vscroll != 0) {
+ mPointerController->unfade();
+ }
} // release lock
int32_t metaState = mContext->getGlobalMetaState();
@@ -1376,6 +1405,13 @@ int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCod
}
}
+void CursorInputMapper::fadePointer() {
+ { // acquire lock
+ AutoMutex _l(mLock);
+ mPointerController->fade();
+ } // release lock
+}
+
// --- TouchInputMapper ---
@@ -2275,7 +2311,6 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
uint32_t policyFlags = 0;
// Preprocess pointer data.
-
if (mParameters.useBadTouchFilter) {
if (applyBadTouchFilter()) {
havePointerIds = false;
@@ -2303,8 +2338,12 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
savedTouch = & mCurrentTouch;
}
- // Process touches and virtual keys.
+ // Hide the pointer on an initial down.
+ if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
+ getContext()->fadePointer();
+ }
+ // Process touches and virtual keys.
TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
if (touchResult == DISPATCH_TOUCH) {
detectGestures(when);
@@ -2312,7 +2351,6 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
}
// Copy current touch to last touch in preparation for the next cycle.
-
if (touchResult == DROP_STROKE) {
mLastTouch.clear();
} else {
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index cf41535..b344ffe 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -157,6 +157,8 @@ public:
virtual bool shouldDropVirtualKey(nsecs_t now,
InputDevice* device, int32_t keyCode, int32_t scanCode) = 0;
+ virtual void fadePointer() = 0;
+
virtual InputReaderPolicyInterface* getPolicy() = 0;
virtual InputDispatcherInterface* getDispatcher() = 0;
virtual EventHubInterface* getEventHub() = 0;
@@ -241,6 +243,8 @@ private:
virtual void updateGlobalMetaState();
virtual int32_t getGlobalMetaState();
+ virtual void fadePointer();
+
InputConfiguration mInputConfiguration;
void updateInputConfiguration();
@@ -299,6 +303,8 @@ public:
int32_t getMetaState();
+ void fadePointer();
+
inline const PropertyMap& getConfiguration() {
return mConfiguration;
}
@@ -351,6 +357,8 @@ public:
virtual int32_t getMetaState();
+ virtual void fadePointer();
+
protected:
InputDevice* mDevice;
InputReaderContext* mContext;
@@ -459,6 +467,8 @@ public:
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+ virtual void fadePointer();
+
private:
// Amount that trackball needs to move in order to generate a key event.
static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
diff --git a/services/input/PointerController.cpp b/services/input/PointerController.cpp
index 92af51e..954872b 100644
--- a/services/input/PointerController.cpp
+++ b/services/input/PointerController.cpp
@@ -35,8 +35,22 @@ namespace android {
// --- PointerController ---
-PointerController::PointerController(int32_t pointerLayer) :
- mPointerLayer(pointerLayer) {
+// 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
+
+// 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;
+
+
+PointerController::PointerController(const sp<Looper>& looper, int32_t pointerLayer) :
+ mLooper(looper), mPointerLayer(pointerLayer) {
AutoMutex _l(mLock);
mLocked.displayWidth = -1;
@@ -51,12 +65,19 @@ PointerController::PointerController(int32_t pointerLayer) :
mLocked.iconHotSpotX = 0;
mLocked.iconHotSpotY = 0;
+ mLocked.fadeAlpha = 1;
+ mLocked.inactivityFadeDelay = INACTIVITY_FADE_DELAY_NORMAL;
+
mLocked.wantVisible = false;
mLocked.visible = false;
mLocked.drawn = false;
+
+ mHandler = new WeakMessageHandler(this);
}
PointerController::~PointerController() {
+ mLooper->removeMessages(mHandler);
+
if (mSurfaceControl != NULL) {
mSurfaceControl->clear();
mSurfaceControl.clear();
@@ -120,7 +141,7 @@ void PointerController::setButtonState(uint32_t buttonState) {
if (mLocked.buttonState != buttonState) {
mLocked.buttonState = buttonState;
- mLocked.wantVisible = true;
+ unfadeBeforeUpdateLocked();
updateLocked();
}
}
@@ -157,7 +178,7 @@ void PointerController::setPositionLocked(float x, float y) {
} else {
mLocked.pointerY = y;
}
- mLocked.wantVisible = true;
+ unfadeBeforeUpdateLocked();
updateLocked();
}
}
@@ -169,6 +190,29 @@ void PointerController::getPosition(float* outX, float* outY) const {
*outY = mLocked.pointerY;
}
+void PointerController::fade() {
+ AutoMutex _l(mLock);
+
+ startFadeLocked();
+}
+
+void PointerController::unfade() {
+ AutoMutex _l(mLock);
+
+ if (unfadeBeforeUpdateLocked()) {
+ updateLocked();
+ }
+}
+
+void PointerController::setInactivityFadeDelay(InactivityFadeDelay inactivityFadeDelay) {
+ AutoMutex _l(mLock);
+
+ if (mLocked.inactivityFadeDelay != inactivityFadeDelay) {
+ mLocked.inactivityFadeDelay = inactivityFadeDelay;
+ startInactivityFadeDelayLocked();
+ }
+}
+
void PointerController::updateLocked() {
bool wantVisibleAndHavePointerIcon = mLocked.wantVisible && mLocked.iconBitmap;
@@ -201,6 +245,12 @@ void PointerController::updateLocked() {
goto CloseTransaction;
}
+ status = mSurfaceControl->setAlpha(mLocked.fadeAlpha);
+ if (status) {
+ LOGE("Error %d setting pointer surface alpha.", status);
+ goto CloseTransaction;
+ }
+
if (!mLocked.visible) {
status = mSurfaceControl->setLayer(mPointerLayer);
if (status) {
@@ -412,4 +462,64 @@ bool PointerController::resizeSurfaceLocked(int32_t width, int32_t height) {
return true;
}
+void PointerController::handleMessage(const Message& message) {
+ switch (message.what) {
+ case MSG_FADE_STEP: {
+ AutoMutex _l(mLock);
+ fadeStepLocked();
+ break;
+ }
+ }
+}
+
+bool PointerController::unfadeBeforeUpdateLocked() {
+ sendFadeStepMessageDelayedLocked(getInactivityFadeDelayTimeLocked());
+
+ if (isFadingLocked()) {
+ mLocked.wantVisible = true;
+ mLocked.fadeAlpha = 1;
+ return true; // update required to effect the unfade
+ }
+ return false; // update not required
+}
+
+void PointerController::startFadeLocked() {
+ if (!isFadingLocked()) {
+ sendFadeStepMessageDelayedLocked(0);
+ }
+}
+
+void PointerController::startInactivityFadeDelayLocked() {
+ if (!isFadingLocked()) {
+ sendFadeStepMessageDelayedLocked(getInactivityFadeDelayTimeLocked());
+ }
+}
+
+void PointerController::fadeStepLocked() {
+ if (mLocked.wantVisible) {
+ mLocked.fadeAlpha -= FADE_DECAY_PER_FRAME;
+ if (mLocked.fadeAlpha < 0) {
+ mLocked.fadeAlpha = 0;
+ mLocked.wantVisible = false;
+ } else {
+ sendFadeStepMessageDelayedLocked(FADE_FRAME_INTERVAL);
+ }
+ updateLocked();
+ }
+}
+
+bool PointerController::isFadingLocked() {
+ return !mLocked.wantVisible || mLocked.fadeAlpha != 1;
+}
+
+nsecs_t PointerController::getInactivityFadeDelayTimeLocked() {
+ return mLocked.inactivityFadeDelay == INACTIVITY_FADE_DELAY_SHORT
+ ? INACTIVITY_FADE_DELAY_TIME_SHORT : INACTIVITY_FADE_DELAY_TIME_NORMAL;
+}
+
+void PointerController::sendFadeStepMessageDelayedLocked(nsecs_t delayTime) {
+ mLooper->removeMessages(mHandler, MSG_FADE_STEP);
+ mLooper->sendMessageDelayed(delayTime, mHandler, Message(MSG_FADE_STEP));
+}
+
} // namespace android
diff --git a/services/input/PointerController.h b/services/input/PointerController.h
index a2a9955..e28dd7d 100644
--- a/services/input/PointerController.h
+++ b/services/input/PointerController.h
@@ -18,7 +18,9 @@
#define _UI_POINTER_CONTROLLER_H
#include <ui/DisplayInfo.h>
+#include <ui/Input.h>
#include <utils/RefBase.h>
+#include <utils/Looper.h>
#include <utils/String8.h>
#include <surfaceflinger/Surface.h>
@@ -64,6 +66,12 @@ public:
/* Gets the absolute location of the pointer. */
virtual void getPosition(float* outX, float* outY) const = 0;
+
+ /* Fades the pointer out now. */
+ virtual void fade() = 0;
+
+ /* Makes the pointer visible if it has faded out. */
+ virtual void unfade() = 0;
};
@@ -72,12 +80,17 @@ public:
*
* Handles pointer acceleration and animation.
*/
-class PointerController : public PointerControllerInterface {
+class PointerController : public PointerControllerInterface, public MessageHandler {
protected:
virtual ~PointerController();
public:
- PointerController(int32_t pointerLayer);
+ enum InactivityFadeDelay {
+ INACTIVITY_FADE_DELAY_NORMAL = 0,
+ INACTIVITY_FADE_DELAY_SHORT = 1,
+ };
+
+ PointerController(const sp<Looper>& looper, int32_t pointerLayer);
virtual bool getBounds(float* outMinX, float* outMinY,
float* outMaxX, float* outMaxY) const;
@@ -86,14 +99,22 @@ public:
virtual uint32_t getButtonState() const;
virtual void setPosition(float x, float y);
virtual void getPosition(float* outX, float* outY) const;
+ virtual void fade();
+ virtual void unfade();
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);
private:
+ enum {
+ MSG_FADE_STEP = 0,
+ };
+
mutable Mutex mLock;
+ sp<Looper> mLooper;
int32_t mPointerLayer;
sp<SurfaceComposerClient> mSurfaceComposerClient;
sp<SurfaceControl> mSurfaceControl;
@@ -111,17 +132,31 @@ private:
float iconHotSpotX;
float iconHotSpotY;
+ float fadeAlpha;
+ InactivityFadeDelay inactivityFadeDelay;
+
bool wantVisible;
bool visible;
bool drawn;
} mLocked;
+ sp<WeakMessageHandler> mHandler;
+
bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
void setPositionLocked(float x, float y);
void updateLocked();
bool createSurfaceIfNeededLocked();
bool drawPointerIfNeededLocked();
bool resizeSurfaceLocked(int32_t width, int32_t height);
+
+ void handleMessage(const Message& message);
+ bool unfadeBeforeUpdateLocked();
+ void startFadeLocked();
+ void startInactivityFadeDelayLocked();
+ void fadeStepLocked();
+ bool isFadingLocked();
+ nsecs_t getInactivityFadeDelayTimeLocked();
+ void sendFadeStepMessageDelayedLocked(nsecs_t delayTime);
};
} // namespace android
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index fac71bb..864241e 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -79,6 +79,12 @@ private:
*outX = 0;
*outY = 0;
}
+
+ virtual void fade() {
+ }
+
+ virtual void unfade() {
+ }
};
@@ -743,6 +749,9 @@ private:
InputDevice* device, int32_t keyCode, int32_t scanCode) {
return false;
}
+
+ virtual void fadePointer() {
+ }
};
@@ -875,6 +884,9 @@ private:
virtual int32_t getMetaState() {
return mMetaState;
}
+
+ virtual void fadePointer() {
+ }
};