summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Huang <jim.huang@linaro.org>2011-04-27 15:17:20 +0200
committerPatrik Ryd <patrik.ryd@linaro.org>2011-04-28 12:26:29 +0200
commit3537671d57c0412427df095bf15828dfafe83a80 (patch)
tree395d4a200e6f4eca07576987b8003bbe529c1474
parentb417337486667a47c6e0c8430d4095e182f4aaa0 (diff)
downloadbase-dev_mouse_preview.tar.gz
Incomplete but usable software cursor implementation for Android Gingerbreaddev_mouse_preview
(Should not be contributed to AOSP) Bug #771674 Change-Id: Icd4045da90b8e2a0ea063fc636399992e5cc2ff9 Signed-off-by: Patrik Ryd <patrik.ryd@linaro.org>
-rw-r--r--api/current.xml24
-rw-r--r--core/java/android/view/IWindowManager.aidl3
-rw-r--r--core/java/android/view/MotionEvent.java8
-rw-r--r--core/java/android/view/ViewRoot.java18
-rw-r--r--include/ui/EventHub.h5
-rw-r--r--include/ui/Input.h3
-rw-r--r--include/ui/InputReader.h56
-rw-r--r--libs/ui/EventHub.cpp58
-rw-r--r--libs/ui/InputDispatcher.cpp20
-rw-r--r--libs/ui/InputReader.cpp273
-rw-r--r--services/java/com/android/server/WindowManagerService.java99
11 files changed, 525 insertions, 42 deletions
diff --git a/api/current.xml b/api/current.xml
index e10b35779fac..0523e2dd2444 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -76307,7 +76307,7 @@
type="float"
transient="false"
volatile="false"
- value="0.0010f"
+ value="0.001f"
static="true"
final="true"
deprecated="not deprecated"
@@ -183540,6 +183540,17 @@
<parameter name="pointerIndex" type="int">
</parameter>
</method>
+<method name="getXOffset"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getXPrecision"
return="float"
abstract="false"
@@ -183575,6 +183586,17 @@
<parameter name="pointerIndex" type="int">
</parameter>
</method>
+<method name="getYOffset"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getYPrecision"
return="float"
abstract="false"
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index d4dd05c19adc..b125ec018ef9 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -51,6 +51,9 @@ interface IWindowManager
IWindowSession openSession(in IInputMethodClient client,
in IInputContext inputContext);
boolean inputMethodClientHasFocus(IInputMethodClient client);
+
+ // Draws the mouse cursor on the screen
+ boolean moveMouseSurface(int dx, int dy);
// These can only be called when injecting events to your own window,
// or by holding the INJECT_EVENTS permission. These methods may block
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index c2fec968172c..23f2d5672615 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -781,6 +781,14 @@ public final class MotionEvent extends InputEvent implements Parcelable {
return mDataSamples[mLastDataSampleIndex + SAMPLE_Y] + mYOffset;
}
+ public final float getXOffset() {
+ return mXOffset;
+ }
+
+ public final float getYOffset() {
+ return mYOffset;
+ }
+
/**
* {@link #getPressure(int)} for the first pointer index (may be an
* arbitrary pointer identifier).
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index c58207ee9999..573d6f14ef5e 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -215,6 +215,8 @@ public final class ViewRoot extends Handler implements ViewParent,
final ViewConfiguration mViewConfiguration;
+ static IWindowManager wm;
+
/**
* see {@link #playSoundEffect(int)}
*/
@@ -227,9 +229,8 @@ public final class ViewRoot extends Handler implements ViewParent,
if (!mInitialized) {
try {
InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
- sWindowSession = IWindowManager.Stub.asInterface(
- ServiceManager.getService("window"))
- .openSession(imm.getClient(), imm.getInputContext());
+ wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
+ sWindowSession = wm.openSession(imm.getClient(), imm.getInputContext());
mInitialized = true;
} catch (RemoteException e) {
}
@@ -1895,6 +1896,7 @@ public final class ViewRoot extends Handler implements ViewParent,
}
}
} break;
+
case DISPATCH_APP_VISIBILITY:
handleAppVisibility(msg.arg1 != 0);
break;
@@ -2837,7 +2839,15 @@ public final class ViewRoot extends Handler implements ViewParent,
private void dispatchMotion(MotionEvent event, boolean sendDone) {
int source = event.getSource();
- if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+ if ((source & InputDevice.SOURCE_MOUSE) != 0) {
+ try {
+ wm.moveMouseSurface((int)event.getX() - (int)event.getXOffset(),
+ (int)event.getY() - (int)event.getYOffset());
+ } catch (RemoteException e){
+ Log.e(TAG,"RemoteException thrown in moveMouseSurface");
+ }
+ dispatchPointer(event, sendDone);
+ } else if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
dispatchPointer(event, sendDone);
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
dispatchTrackball(event, sendDone);
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index d78e35fbfa6c..b33364a328e2 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -119,6 +119,9 @@ enum {
/* The input device has switches. */
INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
+
+ /* The input device is a mouse */
+ INPUT_DEVICE_CLASS_MOUSE = 0x00000100,
};
/*
@@ -238,7 +241,7 @@ private:
const String8 path;
String8 name;
uint32_t classes;
- uint8_t* keyBitmask;
+ uint32_t* keyBitmask;
KeyLayoutMap* layoutMap;
String8 keylayoutFilename;
int fd;
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 8c6018bfeeb2..026d10e8fc93 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -138,7 +138,8 @@ struct InputConfiguration {
NAVIGATION_NONAV = 1,
NAVIGATION_DPAD = 2,
NAVIGATION_TRACKBALL = 3,
- NAVIGATION_WHEEL = 4
+ NAVIGATION_WHEEL = 4,
+ NAVIGATION_MOUSE = 5
};
int32_t touchScreen;
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index 7568ba72329a..a3062bb25d20 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -504,6 +504,62 @@ private:
void sync(nsecs_t when);
};
+class MouseInputMapper : public InputMapper
+{
+public:
+ MouseInputMapper(InputDevice* device, int32_t associatedDisplayId);
+ virtual ~MouseInputMapper();
+
+ virtual uint32_t getSources();
+ virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+ virtual void dump(String8& dump);
+ virtual void reset();
+ virtual void process(const RawEvent* rawEvent);
+
+ virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+
+private:
+ Mutex mLock;
+
+ int32_t mAssociatedDisplayId;
+
+ struct Accumulator
+ {
+ enum
+ {
+ FIELD_BTN_MOUSE = 1,
+ FIELD_REL_X = 2,
+ FIELD_REL_Y = 4,
+ FIELD_BTN_RIGHT = 8,
+ FIELD_BTN_MIDDLE = 16,
+ };
+
+ uint32_t fields;
+
+ bool btnMouse;
+ bool btnRight;
+ bool btnMiddle;
+ int32_t relX;
+ int32_t relY;
+ int32_t absX;
+ int32_t absY;
+
+ inline void clear()
+ {
+ fields = 0;
+ }
+ } mAccumulator;
+
+ struct LockedState
+ {
+ bool down;
+ nsecs_t downTime;
+ } mLocked;
+
+ void initializeLocked();
+
+ void sync(nsecs_t when);
+};
class TouchInputMapper : public InputMapper {
public:
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index 41daa9ca0dbc..6924c5b3c142 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -47,15 +47,15 @@
#include <sys/poll.h>
#include <sys/ioctl.h>
-/* this macro is used to tell if "bit" is set in "array"
- * it selects a byte from the array, and does a boolean AND
- * operation with a byte that only has the relevant bit set.
- * eg. to check for the 12th bit, we do (array[1] & 1<<4)
+/*
+ * The kernel EVIOCG* ioctls return bitmaps defined in terms of longs
+ * This code assumes sizeof(long) == sizeof(int32_t)
*/
-#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
-
-/* this macro computes the number of bytes needed to represent a bit array of the specified size */
-#define sizeof_bit_array(bits) ((bits + 7) / 8)
+#define BITS_PER_LONG 32
+#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
+#define BITS_TO_LONGS(nr) (((nr)+(BITS_PER_LONG-1)) / BITS_PER_LONG)
+#define test_bit(bit, array) (array[BIT_WORD(bit)] & BIT_MASK(bit))
#define ID_MASK 0x0000ffff
#define SEQ_MASK 0x7fff0000
@@ -184,7 +184,7 @@ int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
}
int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) const {
- uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
+ uint32_t key_bitmask[BITS_TO_LONGS(KEY_MAX+1)];
memset(key_bitmask, 0, sizeof(key_bitmask));
if (ioctl(device->fd,
EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
@@ -207,7 +207,7 @@ int32_t EventHub::getKeyCodeStateLocked(device_t* device, int32_t keyCode) const
Vector<int32_t> scanCodes;
device->layoutMap->findScancodes(keyCode, &scanCodes);
- uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
+ uint32_t key_bitmask[BITS_TO_LONGS(KEY_MAX+1)];
memset(key_bitmask, 0, sizeof(key_bitmask));
if (ioctl(device->fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
#if 0
@@ -243,7 +243,7 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
}
int32_t EventHub::getSwitchStateLocked(device_t* device, int32_t sw) const {
- uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
+ uint32_t sw_bitmask[BITS_TO_LONGS(SW_MAX+1)];
memset(sw_bitmask, 0, sizeof(sw_bitmask));
if (ioctl(device->fd,
EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
@@ -537,8 +537,8 @@ bool EventHub::openPlatformInput(void)
// ----------------------------------------------------------------------------
-static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) {
- const uint8_t* end = array + endIndex;
+static bool containsNonZeroLong(const uint32_t* array, uint32_t startIndex, uint32_t endIndex) {
+ const uint32_t* end = array + endIndex;
array += startIndex;
while (array != end) {
if (*(array++) != 0) {
@@ -682,26 +682,26 @@ int EventHub::openDevice(const char *deviceName) {
// Figure out the kinds of events the device reports.
- uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
+ uint32_t key_bitmask[BITS_TO_LONGS(KEY_MAX+1)];
memset(key_bitmask, 0, sizeof(key_bitmask));
LOGV("Getting keys...");
if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
//LOGI("MAP\n");
- //for (int i = 0; i < sizeof(key_bitmask); i++) {
- // LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
+ //for (int i=0; i<BITS_TO_LONGS(KEY_MAX+1); i++) {
+ // LOGI("%d: 0x%08x\n", i*4, key_bitmask[i]);
//}
// See if this is a keyboard. Ignore everything in the button range except for
// gamepads which are also considered keyboards.
- if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
- || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),
- sizeof_bit_array(BTN_DIGI))
- || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
- sizeof_bit_array(KEY_MAX + 1))) {
+ if (containsNonZeroLong(key_bitmask, 0, BITS_TO_LONGS(BTN_MISC))
+ || containsNonZeroLong(key_bitmask, BITS_TO_LONGS(BTN_GAMEPAD),
+ BITS_TO_LONGS(BTN_DIGI))
+ || containsNonZeroLong(key_bitmask, BITS_TO_LONGS(KEY_OK),
+ BITS_TO_LONGS(KEY_MAX + 1))) {
device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
- device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
+ device->keyBitmask = new uint32_t[BITS_TO_LONGS(KEY_MAX+1)];
if (device->keyBitmask != NULL) {
memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
} else {
@@ -714,36 +714,42 @@ int EventHub::openDevice(const char *deviceName) {
// See if this is a trackball (or mouse).
if (test_bit(BTN_MOUSE, key_bitmask)) {
- uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)];
+ uint32_t rel_bitmask[BITS_TO_LONGS(REL_MAX+1)];
memset(rel_bitmask, 0, sizeof(rel_bitmask));
LOGV("Getting relative controllers...");
if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) {
if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_TRACKBALL;
+ if (test_bit(BTN_LEFT, key_bitmask) && test_bit(BTN_RIGHT, key_bitmask)) {
+ device->classes |= INPUT_DEVICE_CLASS_MOUSE;
+ } else {
+ device->classes |= INPUT_DEVICE_CLASS_TRACKBALL;
+ }
}
}
}
// See if this is a touch pad.
- uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];
+ uint32_t abs_bitmask[BITS_TO_LONGS(ABS_MAX+1)];
memset(abs_bitmask, 0, sizeof(abs_bitmask));
LOGV("Getting absolute controllers...");
if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {
// Is this a new modern multi-touch driver?
if (test_bit(ABS_MT_POSITION_X, abs_bitmask)
&& test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
+ device->classes &= ~INPUT_DEVICE_CLASS_MOUSE;
device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT;
// Is this an old style single-touch driver?
} else if (test_bit(BTN_TOUCH, key_bitmask)
&& test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
+ device->classes &= ~INPUT_DEVICE_CLASS_MOUSE;
device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN;
}
}
#ifdef EV_SW
// figure out the switches this device reports
- uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
+ uint32_t sw_bitmask[BITS_TO_LONGS(SW_MAX+1)];
memset(sw_bitmask, 0, sizeof(sw_bitmask));
bool hasSwitches = false;
if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 421ad663f8fd..d65bbe6296f1 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -732,18 +732,22 @@ bool InputDispatcher::dispatchMotionLocked(
}
bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
+ bool isMouseEvent = entry->source & AINPUT_SOURCE_MOUSE;
+ bool isTouchEvent = entry->source & (AINPUT_SOURCE_TOUCHSCREEN & ~AINPUT_SOURCE_CLASS_POINTER);
+ bool isDownEvent = (entry->action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN;
// Identify targets.
if (! mCurrentInputTargetsValid) {
int32_t injectionResult;
- if (isPointerEvent) {
- // Pointer event. (eg. touchscreen)
- injectionResult = findTouchedWindowTargetsLocked(currentTime,
- entry, nextWakeupTime);
- } else {
- // Non touch event. (eg. trackball)
- injectionResult = findFocusedWindowTargetsLocked(currentTime,
- entry, nextWakeupTime);
+ if ( isPointerEvent && (isTouchEvent || (isMouseEvent && (isDownEvent || mTouchState.down))))
+ {
+ // Touch-like event. (eg. touchscreen or mouse drag-n-drop )
+ injectionResult = findTouchedWindowTargetsLocked(currentTime, entry, nextWakeupTime);
+ }
+ else
+ {
+ // Non touch event. (eg. trackball or mouse simple move)
+ injectionResult = findFocusedWindowTargetsLocked(currentTime, entry, nextWakeupTime);
}
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 83b382b9a7b0..b5b18cf8c627 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -22,6 +22,9 @@
// Log debug messages about pointer assignment calculations.
#define DEBUG_POINTER_ASSIGNMENT 0
+//Log debug messages about the mouse whatevers
+#define DEBUG_MOUSE 0
+
#include <cutils/log.h>
#include <ui/InputReader.h>
@@ -347,6 +350,12 @@ InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, ui
device->addMapper(new SingleTouchInputMapper(device, associatedDisplayId));
}
+ // Mouse-like devices.
+ if (classes & INPUT_DEVICE_CLASS_MOUSE)
+ {
+ device->addMapper(new MouseInputMapper(device, associatedDisplayId));
+ }
+
return device;
}
@@ -441,6 +450,10 @@ void InputReader::updateInputConfiguration() {
} else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
navigationConfig = InputConfiguration::NAVIGATION_DPAD;
}
+ if ((sources & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE)
+ {
+ navigationConfig = InputConfiguration::NAVIGATION_MOUSE;
+ }
if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
}
@@ -1227,6 +1240,266 @@ int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scan
}
+// Mouse input mapper
+
+MouseInputMapper::MouseInputMapper(InputDevice* device, int32_t associatedDisplayId) :
+ InputMapper(device), mAssociatedDisplayId(associatedDisplayId)
+{
+ initializeLocked();
+}
+
+MouseInputMapper::~MouseInputMapper()
+{
+
+}
+
+uint32_t MouseInputMapper::getSources()
+{
+ return AINPUT_SOURCE_MOUSE;
+}
+
+void MouseInputMapper::populateDeviceInfo(InputDeviceInfo* info)
+{
+ InputMapper::populateDeviceInfo(info);
+}
+
+void MouseInputMapper::dump(String8& dump)
+{
+ { // acquire lock
+ AutoMutex _l(mLock);
+ dump.append(INDENT2 "Mouse Input Mapper:\n");
+ dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
+ dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
+ dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
+ } // release lock
+}
+
+void MouseInputMapper::initializeLocked()
+{
+ mAccumulator.clear();
+
+ mLocked.down = false;
+ mLocked.downTime = 0;
+
+ int32_t screenWidth;
+ int32_t screenHeight;
+ if (mAssociatedDisplayId < 0 || ! getPolicy()->getDisplayInfo(mAssociatedDisplayId, &screenWidth, &screenHeight, NULL))
+ {
+ mAccumulator.absX = 0;
+ mAccumulator.absY = 0;
+ }
+ else
+ {
+ mAccumulator.absX = screenWidth/2;
+ mAccumulator.absY = screenHeight/2;
+ }
+}
+
+void MouseInputMapper::reset()
+{
+ for (;;)
+ {
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ if (!mLocked.down)
+ {
+ initializeLocked();
+ break; // done
+ }
+ } // release lock
+
+ // Synthesize trackball button up event on reset.
+ nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
+ mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
+ mAccumulator.btnMouse = false;
+ sync(when);
+ }
+
+ InputMapper::reset();
+}
+
+void MouseInputMapper::process(const RawEvent* rawEvent) {
+ switch (rawEvent->type)
+ {
+ case EV_KEY:
+ switch (rawEvent->scanCode)
+ {
+ case BTN_MOUSE:
+ mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
+ mAccumulator.btnMouse = rawEvent->value != 0;
+ sync(rawEvent->when);
+ break;
+ case BTN_RIGHT:
+ mAccumulator.fields |= Accumulator::FIELD_BTN_RIGHT;
+ mAccumulator.btnRight = rawEvent->value != 0;
+ sync(rawEvent->when);
+ break;
+ case BTN_MIDDLE:
+ mAccumulator.fields |= Accumulator::FIELD_BTN_MIDDLE;
+ mAccumulator.btnMiddle = rawEvent->value != 0;
+ sync(rawEvent->when);
+ break;
+ }
+ break;
+
+ case EV_REL:
+ switch (rawEvent->scanCode)
+ {
+ case REL_X:
+ mAccumulator.fields |= Accumulator::FIELD_REL_X;
+ mAccumulator.relX = rawEvent->value;
+ break;
+ case REL_Y:
+ mAccumulator.fields |= Accumulator::FIELD_REL_Y;
+ mAccumulator.relY = rawEvent->value;
+ break;
+ }
+ break;
+
+ case EV_SYN:
+ switch (rawEvent->scanCode)
+ {
+ case SYN_REPORT:
+ sync(rawEvent->when);
+ break;
+ }
+ break;
+ }
+}
+
+void MouseInputMapper::sync(nsecs_t when)
+{
+ uint32_t fields = mAccumulator.fields;
+ if (fields == 0)
+ {
+ return; // no new state changes, so nothing to do
+ }
+
+ int motionEventAction;
+ PointerCoords pointerCoords;
+ nsecs_t downTime;
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ if (fields & Accumulator::FIELD_BTN_RIGHT)
+ {
+ getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_DPAD, 0,
+ mAccumulator.btnRight ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
+ AKEY_EVENT_FLAG_FROM_SYSTEM, 0x4 /*Keycode for back key*/,
+ 0x18 /*Scancode*/, mContext->getGlobalMetaState(), when);
+ }
+
+ if (fields & Accumulator::FIELD_BTN_MIDDLE)
+ {
+ getDispatcher()->notifyKey(when, getDeviceId(),AINPUT_SOURCE_DPAD, 0,
+ mAccumulator.btnMiddle ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
+ AKEY_EVENT_FLAG_FROM_SYSTEM, 0x52 /*Keycode for menu key*/,
+ 0x19 /*Scancode*/, mContext->getGlobalMetaState(), when);
+ }
+
+ bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
+ if (downChanged)
+ {
+ if (mAccumulator.btnMouse)
+ {
+ mLocked.down = true;
+ mLocked.downTime = when;
+ }
+ else
+ {
+ mLocked.down = false;
+ }
+ motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
+ }
+ else
+ {
+ motionEventAction = AMOTION_EVENT_ACTION_MOVE;
+ }
+
+ downTime = mLocked.downTime;
+
+ float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX : 0.0f;
+ float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY : 0.0f;
+
+ int32_t screenWidth;
+ int32_t screenHeight;
+ int32_t orientation;
+
+ if (mAssociatedDisplayId < 0 || ! getPolicy()->getDisplayInfo(mAssociatedDisplayId, &screenWidth, &screenHeight, &orientation))
+ {
+ return;
+ }
+
+ float temp;
+ switch (orientation)
+ {
+ case InputReaderPolicyInterface::ROTATION_90:
+ {
+ temp = x;
+ x = y;
+ y = - temp;
+ temp = screenHeight;
+ screenHeight = screenWidth;
+ screenWidth = temp;
+ break;
+ }
+ case InputReaderPolicyInterface::ROTATION_180:
+ {
+ x = - x;
+ y = - y;
+ break;
+ }
+ case InputReaderPolicyInterface::ROTATION_270:
+ {
+ temp = x;
+ x = - y;
+ y = temp;
+ temp = screenHeight;
+ screenHeight = screenWidth;
+ screenWidth = temp;
+ break;
+ }
+ }
+
+ mAccumulator.absX =
+ (mAccumulator.absX + x) > screenWidth ? screenWidth -1 :
+ ((mAccumulator.absX + x) < 0 ? 0 : mAccumulator.absX + x);
+ mAccumulator.absY = (mAccumulator.absY + y) > screenHeight ? screenHeight -1 :
+ ((mAccumulator.absY + y) < 0 ? 0 : mAccumulator.absY + y);
+ pointerCoords.x = mAccumulator.absX;
+ pointerCoords.y = mAccumulator.absY;
+ pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
+ pointerCoords.size = 0;
+ pointerCoords.touchMajor = 0;
+ pointerCoords.touchMinor = 0;
+ pointerCoords.toolMajor = 0;
+ pointerCoords.toolMinor = 0;
+ pointerCoords.orientation = 0;
+
+ } // release lock
+
+ int32_t metaState = mContext->getGlobalMetaState();
+ int32_t pointerId = 0;
+ getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_MOUSE, 0,
+ motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ 1, &pointerId, &pointerCoords, 1, 1, downTime);
+ mAccumulator.clear();
+}
+
+int32_t MouseInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode)
+{
+ if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK)
+ {
+ return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
+ }
+ else
+ {
+ return AKEY_STATE_UNKNOWN;
+ }
+}
+
+
// --- TouchInputMapper ---
TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index efd0bb49dc1b..49864d320b70 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -43,6 +43,7 @@ import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.WindowManagerPolicyThread;
+import com.android.internal.view.BaseInputHandler;
import com.android.server.am.BatteryStatsService;
import android.Manifest;
@@ -60,6 +61,7 @@ import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
@@ -103,6 +105,8 @@ import android.view.IWindowSession;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
+import android.view.InputQueue;
+import android.view.InputHandler;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
@@ -479,6 +483,13 @@ public class WindowManagerService extends IWindowManager.Stub
final InputManager mInputManager;
+ Surface mMouseSurface;
+ boolean mMouseDisplayed = false;
+ private int mMlx;
+ private int mMly;
+ int mMlw;
+ int mMlh;
+
// Who is holding the screen on.
Session mHoldingScreenOn;
PowerManager.WakeLock mHoldingScreenWakeLock;
@@ -5400,6 +5411,40 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ public boolean moveMouseSurface(int x, int y)
+ {
+ if (mMouseSurface != null && (x != 0 || y != 0))
+ {
+ synchronized(mWindowMap)
+ {
+ Surface.openTransaction();
+ WindowState top =
+ (WindowState)mWindows.get(mWindows.size() - 1);
+ try
+ {
+ int mDisplayWidth = mDisplay.getWidth();
+ mMlx = x;
+ mMly = y;
+ mMouseSurface.setPosition(mMlx, mMly);
+ mMouseSurface.setLayer(top.mAnimLayer + 1);
+ if (!mMouseDisplayed)
+ {
+ mMouseSurface.show();
+ mMouseDisplayed = !mMouseDisplayed;
+ }
+ }
+ catch ( RuntimeException e)
+ {
+ Slog.e(TAG, "Failure showing mouse surface",e);
+ }
+
+ Surface.closeTransaction();
+ }
+ }
+
+ return true;
+ }
+
/**
* Injects a keystroke event into the UI.
* Even when sync is false, this method may block while waiting for current
@@ -8497,6 +8542,55 @@ public class WindowManagerService extends IWindowManager.Stub
createWatermark = true;
}
+ if (mMouseSurface == null) {
+ int mMx, mMy, mMw, mMh;
+ Canvas mCanvas;
+ Path mPath = new Path();
+ mMw = 13;
+ mMh = 22;
+ mMx = (mDisplay.getWidth() - mMw) / 2;
+ mMy = (mDisplay.getHeight() - mMh) / 2;
+ try {
+ /*
+ * First Mouse event, create Surface
+ */
+ mMouseSurface =
+ new Surface(mFxSession,
+ 0, -1, mMw, mMh,
+ PixelFormat.TRANSPARENT,
+ Surface.FX_SURFACE_NORMAL);
+ mCanvas = mMouseSurface.lockCanvas(null);
+ Paint tPaint = new Paint();
+ tPaint.setStyle(Paint.Style.STROKE);
+ tPaint.setStrokeWidth(2);
+ tPaint.setColor(0xffffffff);
+ mPath.moveTo(0.0f, 0.0f);
+ mPath.lineTo(12.0f, 12.0f);
+ mPath.lineTo(7.0f, 12.0f);
+ mPath.lineTo(11.0f, 20.0f);
+ mPath.lineTo(8.0f, 21.0f);
+ mPath.lineTo(4.0f, 13.0f);
+ mPath.lineTo(0.0f, 17.0f);
+ mPath.close();
+ mCanvas.clipPath(mPath);
+ mCanvas.drawColor(0xff000000);
+ mCanvas.drawPath(mPath, tPaint);
+
+ mMouseSurface.unlockCanvasAndPost(mCanvas);
+ mMouseSurface.openTransaction();
+ mMouseSurface.setSize(mMw, mMh);
+ mMouseSurface.closeTransaction();
+
+ }
+ catch (Exception e) {
+ Slog.e(TAG, "Exception creating mouse surface",e);
+ }
+ mMlx = mMx;
+ mMly = mMy;
+ mMlw = mMw;
+ mMlh = mMh;
+ }
+
if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
Surface.openTransaction();
@@ -8504,6 +8598,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (createWatermark) {
createWatermark();
}
+
if (mWatermark != null) {
mWatermark.positionSurface(dw, dh);
}
@@ -9522,7 +9617,9 @@ public class WindowManagerService extends IWindowManager.Stub
mBlurShown = false;
}
- if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
+ if (SHOW_TRANSACTIONS) {
+ Slog.i(TAG, "<<< CLOSE TRANSACTION");
+ }
} catch (RuntimeException e) {
Slog.e(TAG, "Unhandled exception in Window Manager", e);
}