diff options
author | Jim Huang <jim.huang@linaro.org> | 2011-04-27 15:17:20 +0200 |
---|---|---|
committer | Patrik Ryd <patrik.ryd@linaro.org> | 2011-04-28 12:26:29 +0200 |
commit | 3537671d57c0412427df095bf15828dfafe83a80 (patch) | |
tree | 395d4a200e6f4eca07576987b8003bbe529c1474 | |
parent | b417337486667a47c6e0c8430d4095e182f4aaa0 (diff) | |
download | base-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.xml | 24 | ||||
-rw-r--r-- | core/java/android/view/IWindowManager.aidl | 3 | ||||
-rw-r--r-- | core/java/android/view/MotionEvent.java | 8 | ||||
-rw-r--r-- | core/java/android/view/ViewRoot.java | 18 | ||||
-rw-r--r-- | include/ui/EventHub.h | 5 | ||||
-rw-r--r-- | include/ui/Input.h | 3 | ||||
-rw-r--r-- | include/ui/InputReader.h | 56 | ||||
-rw-r--r-- | libs/ui/EventHub.cpp | 58 | ||||
-rw-r--r-- | libs/ui/InputDispatcher.cpp | 20 | ||||
-rw-r--r-- | libs/ui/InputReader.cpp | 273 | ||||
-rw-r--r-- | services/java/com/android/server/WindowManagerService.java | 99 |
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); } |