diff options
author | Jeff Brown <jeffbrown@google.com> | 2012-09-09 20:33:43 -0700 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2012-09-10 15:48:47 -0700 |
commit | 83d616a9c7b9505153d258511eb5c16b552e268d (patch) | |
tree | 4df9620550008dc0e3e0daf21f442b9fe6cc8051 | |
parent | 7a8cce3d8a6fb781d840ddf60324a301f5a3f2d9 (diff) | |
download | frameworks_base-83d616a9c7b9505153d258511eb5c16b552e268d.zip frameworks_base-83d616a9c7b9505153d258511eb5c16b552e268d.tar.gz frameworks_base-83d616a9c7b9505153d258511eb5c16b552e268d.tar.bz2 |
Make input system aware of multiple displays.
The input system needs to know about the window that has
focus, even if it is on a secondary display. So now we
send it the list of all windows and indicate which display
they are on. We filter the list of windows as necessary
when delivering touch events.
To keep things simple, monitor input channels and input
filters are not supported except on the main display.
We also do not pass the display id to applications; it is
only used inside the input system for now.
Properly scale touch coordinates based on the viewport.
This will be needed to ensure that touch works on external
display as well as when the internal display is being used
to simulate a different resolution.
Change-Id: I1815579a52fcc852c519b5391fc7ab8767c2dc59
-rw-r--r-- | include/androidfw/Input.h | 9 | ||||
-rw-r--r-- | services/input/InputDispatcher.cpp | 129 | ||||
-rw-r--r-- | services/input/InputDispatcher.h | 18 | ||||
-rw-r--r-- | services/input/InputListener.cpp | 7 | ||||
-rw-r--r-- | services/input/InputListener.h | 3 | ||||
-rw-r--r-- | services/input/InputReader.cpp | 219 | ||||
-rw-r--r-- | services/input/InputReader.h | 54 | ||||
-rw-r--r-- | services/input/InputWindow.h | 1 | ||||
-rw-r--r-- | services/input/tests/InputReader_test.cpp | 3 | ||||
-rw-r--r-- | services/java/com/android/server/display/DisplayDevice.java | 6 | ||||
-rw-r--r-- | services/java/com/android/server/display/DisplayViewport.java | 10 | ||||
-rw-r--r-- | services/java/com/android/server/input/InputManagerService.java | 6 | ||||
-rw-r--r-- | services/java/com/android/server/wm/InputMonitor.java | 16 | ||||
-rwxr-xr-x | services/java/com/android/server/wm/WindowManagerService.java | 2 | ||||
-rw-r--r-- | services/jni/com_android_server_input_InputManagerService.cpp | 7 | ||||
-rw-r--r-- | services/jni/com_android_server_input_InputWindowHandle.cpp | 6 |
16 files changed, 352 insertions, 144 deletions
diff --git a/include/androidfw/Input.h b/include/androidfw/Input.h index 2c91fab..e88835e 100644 --- a/include/androidfw/Input.h +++ b/include/androidfw/Input.h @@ -49,6 +49,15 @@ enum { }; enum { + /* Used when a motion event is not associated with any display. + * Typically used for non-pointer events. */ + ADISPLAY_ID_NONE = -1, + + /* The default display id. */ + ADISPLAY_ID_DEFAULT = 0, +}; + +enum { /* * Indicates that an input device has switches. * This input source flag is hidden from the API because switches are only used by the system diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index 8604f95..87a6c1b 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -166,6 +166,10 @@ static bool validateMotionEvent(int32_t action, size_t pointerCount, return true; } +static bool isMainDisplay(int32_t displayId) { + return displayId == ADISPLAY_ID_DEFAULT || displayId == ADISPLAY_ID_NONE; +} + static void dumpRegion(String8& dump, const SkRegion& region) { if (region.isEmpty()) { dump.append("<empty>"); @@ -423,11 +427,12 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY && mInputTargetWaitApplicationHandle != NULL) { + int32_t displayId = motionEntry->displayId; int32_t x = int32_t(motionEntry->pointerCoords[0]. getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = int32_t(motionEntry->pointerCoords[0]. getAxisValue(AMOTION_EVENT_AXIS_Y)); - sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(x, y); + sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y); if (touchedWindowHandle != NULL && touchedWindowHandle->inputApplicationHandle != mInputTargetWaitApplicationHandle) { @@ -444,28 +449,31 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { return needWake; } -sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) { +sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, + int32_t x, int32_t y) { // Traverse windows from front to back to find touched window. size_t numWindows = mWindowHandles.size(); for (size_t i = 0; i < numWindows; i++) { sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); const InputWindowInfo* windowInfo = windowHandle->getInfo(); - int32_t flags = windowInfo->layoutParamsFlags; - - if (windowInfo->visible) { - if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { - bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE - | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0; - if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) { - // Found window. - return windowHandle; + if (windowInfo->displayId == displayId) { + int32_t flags = windowInfo->layoutParamsFlags; + + if (windowInfo->visible) { + if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { + bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE + | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0; + if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) { + // Found window. + return windowHandle; + } } } - } - if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { - // Error window is on top but not visible, so touch is dropped. - return NULL; + if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { + // Error window is on top but not visible, so touch is dropped. + return NULL; + } } } return NULL; @@ -826,7 +834,10 @@ bool InputDispatcher::dispatchMotionLocked( return true; } - addMonitoringTargetsLocked(inputTargets); + // TODO: support sending secondary display events to input monitors + if (isMainDisplay(entry->displayId)) { + addMonitoringTargetsLocked(inputTargets); + } // Dispatch the motion. if (conflictingPointerActions) { @@ -1117,6 +1128,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, // bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE; + int32_t displayId = entry->displayId; int32_t action = entry->action; int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK; @@ -1126,9 +1138,10 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, sp<InputWindowHandle> newHoverWindowHandle; bool isSplit = mTouchState.split; - bool switchedDevice = mTouchState.deviceId >= 0 + bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0 && (mTouchState.deviceId != entry->deviceId - || mTouchState.source != entry->source); + || mTouchState.source != entry->source + || mTouchState.displayId != displayId); bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT); @@ -1152,6 +1165,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, mTempTouchState.down = down; mTempTouchState.deviceId = entry->deviceId; mTempTouchState.source = entry->source; + mTempTouchState.displayId = displayId; isSplit = false; } else { mTempTouchState.copyFrom(mTouchState); @@ -1174,8 +1188,11 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, for (size_t i = 0; i < numWindows; i++) { sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); const InputWindowInfo* windowInfo = windowHandle->getInfo(); - int32_t flags = windowInfo->layoutParamsFlags; + if (windowInfo->displayId != displayId) { + continue; // wrong display + } + int32_t flags = windowInfo->layoutParamsFlags; if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { if (topErrorWindowHandle == NULL) { topErrorWindowHandle = windowHandle; @@ -1300,7 +1317,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, sp<InputWindowHandle> oldTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle(); - sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(x, y); + sp<InputWindowHandle> newTouchedWindowHandle = + findTouchedWindowAtLocked(displayId, x, y); if (oldTouchedWindowHandle != newTouchedWindowHandle && newTouchedWindowHandle != NULL) { #if DEBUG_FOCUS @@ -1438,8 +1456,10 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, if (foregroundWindowHandle->getInfo()->hasWallpaper) { for (size_t i = 0; i < mWindowHandles.size(); i++) { sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); - if (windowHandle->getInfo()->layoutParamsType - == InputWindowInfo::TYPE_WALLPAPER) { + const InputWindowInfo* info = windowHandle->getInfo(); + if (info->displayId == displayId + && windowHandle->getInfo()->layoutParamsType + == InputWindowInfo::TYPE_WALLPAPER) { mTempTouchState.addOrUpdateWindow(windowHandle, InputTarget::FLAG_WINDOW_IS_OBSCURED | InputTarget::FLAG_DISPATCH_AS_IS, @@ -1495,6 +1515,7 @@ Failed: || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) { mTouchState.deviceId = entry->deviceId; mTouchState.source = entry->source; + mTouchState.displayId = displayId; } } else if (maskedAction == AMOTION_EVENT_ACTION_UP || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { @@ -1610,6 +1631,7 @@ bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& wind bool InputDispatcher::isWindowObscuredAtPointLocked( const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const { + int32_t displayId = windowHandle->getInfo()->displayId; size_t numWindows = mWindowHandles.size(); for (size_t i = 0; i < numWindows; i++) { sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i); @@ -1618,7 +1640,8 @@ bool InputDispatcher::isWindowObscuredAtPointLocked( } const InputWindowInfo* otherInfo = otherHandle->getInfo(); - if (otherInfo->visible && ! otherInfo->isTrustedOverlay() + if (otherInfo->displayId == displayId + && otherInfo->visible && !otherInfo->isTrustedOverlay() && otherInfo->frameContainsPoint(x, y)) { return true; } @@ -1845,7 +1868,7 @@ void InputDispatcher::enqueueDispatchEntryLocked( } if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE && !connection->inputState.isHovering( - motionEntry->deviceId, motionEntry->source)) { + motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) { #if DEBUG_DISPATCH_CYCLE ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event", connection->getInputChannelName()); @@ -2271,6 +2294,7 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet originalMotionEntry->xPrecision, originalMotionEntry->yPrecision, originalMotionEntry->downTime, + originalMotionEntry->displayId, splitPointerCount, splitPointerProperties, splitPointerCoords); if (originalMotionEntry->injectionState) { @@ -2351,7 +2375,7 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { { // acquire lock mLock.lock(); - if (mInputFilterEnabled) { + if (shouldSendKeyToInputFilterLocked(args)) { mLock.unlock(); policyFlags |= POLICY_FLAG_FILTERED; @@ -2377,6 +2401,10 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { } } +bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) { + return mInputFilterEnabled; +} + void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS ALOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, " @@ -2415,7 +2443,7 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { { // acquire lock mLock.lock(); - if (mInputFilterEnabled) { + if (shouldSendMotionToInputFilterLocked(args)) { mLock.unlock(); MotionEvent event; @@ -2438,6 +2466,7 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { args->deviceId, args->source, policyFlags, args->action, args->flags, args->metaState, args->buttonState, args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime, + args->displayId, args->pointerCount, args->pointerProperties, args->pointerCoords); needWake = enqueueInboundEventLocked(newEntry); @@ -2449,6 +2478,11 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { } } +bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) { + // TODO: support sending secondary display events to input filter + return mInputFilterEnabled && isMainDisplay(args->displayId); +} + void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchCode=%d, switchValue=%d", @@ -2532,6 +2566,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, case AINPUT_EVENT_TYPE_MOTION: { const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event); + int32_t displayId = ADISPLAY_ID_DEFAULT; int32_t action = motionEvent->getAction(); size_t pointerCount = motionEvent->getPointerCount(); const PointerProperties* pointerProperties = motionEvent->getPointerProperties(); @@ -2553,8 +2588,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, motionEvent->getMetaState(), motionEvent->getButtonState(), motionEvent->getEdgeFlags(), motionEvent->getXPrecision(), motionEvent->getYPrecision(), - motionEvent->getDownTime(), uint32_t(pointerCount), - pointerProperties, samplePointerCoords); + motionEvent->getDownTime(), displayId, + uint32_t(pointerCount), pointerProperties, samplePointerCoords); lastInjectedEntry = firstInjectedEntry; for (size_t i = motionEvent->getHistorySize(); i > 0; i--) { sampleEventTimes += 1; @@ -2565,8 +2600,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, motionEvent->getMetaState(), motionEvent->getButtonState(), motionEvent->getEdgeFlags(), motionEvent->getXPrecision(), motionEvent->getYPrecision(), - motionEvent->getDownTime(), uint32_t(pointerCount), - pointerProperties, samplePointerCoords); + motionEvent->getDownTime(), displayId, + uint32_t(pointerCount), pointerProperties, samplePointerCoords); lastInjectedEntry->next = nextInjectedEntry; lastInjectedEntry = nextInjectedEntry; } @@ -2939,6 +2974,12 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel, #endif return true; } + if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) { +#if DEBUG_FOCUS + ALOGD("Cannot transfer focus because windows are on different displays."); +#endif + return false; + } bool found = false; for (size_t i = 0; i < mTouchState.windows.size(); i++) { @@ -3040,6 +3081,7 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) { dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split)); dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId); dump.appendFormat(INDENT "TouchSource: 0x%08x\n", mTouchState.source); + dump.appendFormat(INDENT "TouchDisplayId: %d\n", mTouchState.displayId); if (!mTouchState.windows.isEmpty()) { dump.append(INDENT "TouchedWindows:\n"); for (size_t i = 0; i < mTouchState.windows.size(); i++) { @@ -3059,11 +3101,12 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) { const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i); const InputWindowInfo* windowInfo = windowHandle->getInfo(); - dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, " + dump.appendFormat(INDENT2 "%d: name='%s', displayId=%d, " + "paused=%s, hasFocus=%s, hasWallpaper=%s, " "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, " "frame=[%d,%d][%d,%d], scale=%f, " "touchableRegion=", - i, windowInfo->name.string(), + i, windowInfo->name.string(), windowInfo->displayId, toString(windowInfo->paused), toString(windowInfo->hasFocus), toString(windowInfo->hasWallpaper), @@ -3802,14 +3845,14 @@ InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, float xPrecision, float yPrecision, - nsecs_t downTime, uint32_t pointerCount, + nsecs_t downTime, int32_t displayId, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) : EventEntry(TYPE_MOTION, eventTime, policyFlags), eventTime(eventTime), deviceId(deviceId), source(source), action(action), flags(flags), metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags), xPrecision(xPrecision), yPrecision(yPrecision), - downTime(downTime), pointerCount(pointerCount) { + downTime(downTime), displayId(displayId), pointerCount(pointerCount) { for (uint32_t i = 0; i < pointerCount; i++) { this->pointerProperties[i].copyFrom(pointerProperties[i]); this->pointerCoords[i].copyFrom(pointerCoords[i]); @@ -3820,8 +3863,8 @@ InputDispatcher::MotionEntry::~MotionEntry() { } void InputDispatcher::MotionEntry::appendDescription(String8& msg) const { - msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x)", - action, deviceId, source); + msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x, displayId=%d)", + action, deviceId, source, displayId); } @@ -3864,11 +3907,13 @@ bool InputDispatcher::InputState::isNeutral() const { return mKeyMementos.isEmpty() && mMotionMementos.isEmpty(); } -bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source) const { +bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source, + int32_t displayId) const { for (size_t i = 0; i < mMotionMementos.size(); i++) { const MotionMemento& memento = mMotionMementos.itemAt(i); if (memento.deviceId == deviceId && memento.source == source + && memento.displayId == displayId && memento.hovering) { return true; } @@ -4025,6 +4070,7 @@ ssize_t InputDispatcher::InputState::findMotionMemento(const MotionEntry* entry, const MotionMemento& memento = mMotionMementos.itemAt(i); if (memento.deviceId == entry->deviceId && memento.source == entry->source + && memento.displayId == entry->displayId && memento.hovering == hovering) { return i; } @@ -4055,6 +4101,7 @@ void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry, memento.xPrecision = entry->xPrecision; memento.yPrecision = entry->yPrecision; memento.downTime = entry->downTime; + memento.displayId = entry->displayId; memento.setPointers(entry); memento.hovering = hovering; memento.policyFlags = entry->policyFlags; @@ -4090,6 +4137,7 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim : AMOTION_EVENT_ACTION_CANCEL, memento.flags, 0, 0, 0, memento.xPrecision, memento.yPrecision, memento.downTime, + memento.displayId, memento.pointerCount, memento.pointerProperties, memento.pointerCoords)); } } @@ -4108,7 +4156,8 @@ void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const { for (size_t j = 0; j < other.mMotionMementos.size(); ) { const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j); if (memento.deviceId == otherMemento.deviceId - && memento.source == otherMemento.source) { + && memento.source == otherMemento.source + && memento.displayId == otherMemento.displayId) { other.mMotionMementos.removeAt(j); } else { j += 1; @@ -4240,7 +4289,7 @@ InputDispatcher::CommandEntry::~CommandEntry() { // --- InputDispatcher::TouchState --- InputDispatcher::TouchState::TouchState() : - down(false), split(false), deviceId(-1), source(0) { + down(false), split(false), deviceId(-1), source(0), displayId(-1) { } InputDispatcher::TouchState::~TouchState() { @@ -4251,6 +4300,7 @@ void InputDispatcher::TouchState::reset() { split = false; deviceId = -1; source = 0; + displayId = -1; windows.clear(); } @@ -4259,6 +4309,7 @@ void InputDispatcher::TouchState::copyFrom(const TouchState& other) { split = other.split; deviceId = other.deviceId; source = other.source; + displayId = other.displayId; windows = other.windows; } diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h index d0824fc..af7ff5e 100644 --- a/services/input/InputDispatcher.h +++ b/services/input/InputDispatcher.h @@ -511,15 +511,17 @@ private: float xPrecision; float yPrecision; nsecs_t downTime; + int32_t displayId; uint32_t pointerCount; PointerProperties pointerProperties[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; MotionEntry(nsecs_t eventTime, - int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, - int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, + int32_t deviceId, uint32_t source, uint32_t policyFlags, + int32_t action, int32_t flags, + int32_t metaState, int32_t buttonState, int32_t edgeFlags, float xPrecision, float yPrecision, - nsecs_t downTime, uint32_t pointerCount, + nsecs_t downTime, int32_t displayId, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords); virtual void appendDescription(String8& msg) const; @@ -696,7 +698,7 @@ private: // Returns true if the specified source is known to have received a hover enter // motion event. - bool isHovering(int32_t deviceId, uint32_t source) const; + bool isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const; // Records tracking information for a key event that has just been published. // Returns true if the event should be delivered, false if it is inconsistent @@ -752,6 +754,7 @@ private: float xPrecision; float yPrecision; nsecs_t downTime; + int32_t displayId; uint32_t pointerCount; PointerProperties pointerProperties[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; @@ -867,7 +870,7 @@ private: // to transfer focus to a new application. EventEntry* mNextUnblockedEvent; - sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t x, int32_t y); + sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y); // All registered connections mapped by channel file descriptor. KeyedVector<int, sp<Connection> > mConnectionsByFd; @@ -899,6 +902,10 @@ private: bool runCommandsLockedInterruptible(); CommandEntry* postCommandLocked(Command command); + // Input filter processing. + bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args); + bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args); + // Inbound event processing. void drainInboundQueueLocked(); void releasePendingEventLocked(); @@ -928,6 +935,7 @@ private: bool split; int32_t deviceId; // id of the device that is currently down, others are rejected uint32_t source; // source of the device that is current down, others are rejected + int32_t displayId; // id to the display that currently has a touch, others are rejected Vector<TouchedWindow> windows; TouchState(); diff --git a/services/input/InputListener.cpp b/services/input/InputListener.cpp index 657a6b9..c2705b0 100644 --- a/services/input/InputListener.cpp +++ b/services/input/InputListener.cpp @@ -69,12 +69,12 @@ void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const { NotifyMotionArgs::NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, - int32_t edgeFlags, uint32_t pointerCount, + int32_t edgeFlags, int32_t displayId, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, float xPrecision, float yPrecision, nsecs_t downTime) : eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags), action(action), flags(flags), metaState(metaState), buttonState(buttonState), - edgeFlags(edgeFlags), pointerCount(pointerCount), + edgeFlags(edgeFlags), displayId(displayId), pointerCount(pointerCount), xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime) { for (uint32_t i = 0; i < pointerCount; i++) { this->pointerProperties[i].copyFrom(pointerProperties[i]); @@ -87,7 +87,8 @@ NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) : policyFlags(other.policyFlags), action(other.action), flags(other.flags), metaState(other.metaState), buttonState(other.buttonState), - edgeFlags(other.edgeFlags), pointerCount(other.pointerCount), + edgeFlags(other.edgeFlags), displayId(other.displayId), + pointerCount(other.pointerCount), xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime) { for (uint32_t i = 0; i < pointerCount; i++) { pointerProperties[i].copyFrom(other.pointerProperties[i]); diff --git a/services/input/InputListener.h b/services/input/InputListener.h index b1dc0b8..486852b 100644 --- a/services/input/InputListener.h +++ b/services/input/InputListener.h @@ -88,6 +88,7 @@ struct NotifyMotionArgs : public NotifyArgs { int32_t metaState; int32_t buttonState; int32_t edgeFlags; + int32_t displayId; uint32_t pointerCount; PointerProperties pointerProperties[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; @@ -99,7 +100,7 @@ struct NotifyMotionArgs : public NotifyArgs { NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, - int32_t edgeFlags, uint32_t pointerCount, + int32_t edgeFlags, int32_t displayId, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, float xPrecision, float yPrecision, nsecs_t downTime); diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 513dc13..d56b9a9 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -2431,6 +2431,7 @@ void CursorInputMapper::sync(nsecs_t when) { mPointerVelocityControl.move(when, &deltaX, &deltaY); + int32_t displayId; if (mPointerController != NULL) { if (moved || scrolled || buttonsChanged) { mPointerController->setPresentation( @@ -2451,9 +2452,11 @@ void CursorInputMapper::sync(nsecs_t when) { mPointerController->getPosition(&x, &y); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); + displayId = ADISPLAY_ID_DEFAULT; } else { pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY); + displayId = ADISPLAY_ID_NONE; } pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f); @@ -2485,7 +2488,8 @@ void CursorInputMapper::sync(nsecs_t when) { NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, motionEventAction, 0, metaState, currentButtonState, 0, - 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); + displayId, 1, &pointerProperties, &pointerCoords, + mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&args); // Send hover move after UP to tell the application that the mouse is hovering now. @@ -2494,7 +2498,8 @@ void CursorInputMapper::sync(nsecs_t when) { NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); + displayId, 1, &pointerProperties, &pointerCoords, + mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&hoverArgs); } @@ -2506,7 +2511,8 @@ void CursorInputMapper::sync(nsecs_t when) { NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); + displayId, 1, &pointerProperties, &pointerCoords, + mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&scrollArgs); } } @@ -2539,7 +2545,8 @@ void CursorInputMapper::fadePointer() { TouchInputMapper::TouchInputMapper(InputDevice* device) : InputMapper(device), mSource(0), mDeviceMode(DEVICE_MODE_DISABLED), - mSurfaceOrientation(-1), mSurfaceWidth(-1), mSurfaceHeight(-1) { + mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0), + mSurfaceOrientation(DISPLAY_ORIENTATION_0) { } TouchInputMapper::~TouchInputMapper() { @@ -2601,6 +2608,8 @@ void TouchInputMapper::dump(String8& dump) { dumpSurface(dump); dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n"); + dump.appendFormat(INDENT4 "XTranslate: %0.3f\n", mXTranslate); + dump.appendFormat(INDENT4 "YTranslate: %0.3f\n", mYTranslate); dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale); dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale); dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision); @@ -2810,7 +2819,7 @@ void TouchInputMapper::dumpParameters(String8& dump) { ALOG_ASSERT(false); } - dump.appendFormat(INDENT4 "AssociatedDisplay: present=%s, isExternal=%s\n", + dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n", toString(mParameters.hasAssociatedDisplay), toString(mParameters.associatedDisplayIsExternal)); dump.appendFormat(INDENT4 "OrientationAware: %s\n", @@ -2869,10 +2878,15 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { return; } + // Raw width and height in the natural orientation. + int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; + int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; + // Get associated display dimensions. + bool viewportChanged = false; + DisplayViewport newViewport; if (mParameters.hasAssociatedDisplay) { - if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, - &mAssociatedDisplayViewport)) { + if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) { ALOGI(INDENT "Touch device '%s' could not query the properties of its associated " "display. The device will be inoperable until the display size " "becomes available.", @@ -2880,25 +2894,77 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mDeviceMode = DEVICE_MODE_DISABLED; return; } - } + } else { + newViewport.setNonDisplayViewport(rawWidth, rawHeight); + } + if (mViewport != newViewport) { + mViewport = newViewport; + viewportChanged = true; + + if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) { + // Convert rotated viewport to natural surface coordinates. + int32_t naturalLogicalWidth, naturalLogicalHeight; + int32_t naturalPhysicalWidth, naturalPhysicalHeight; + int32_t naturalPhysicalLeft, naturalPhysicalTop; + int32_t naturalDeviceWidth, naturalDeviceHeight; + switch (mViewport.orientation) { + case DISPLAY_ORIENTATION_90: + naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop; + naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft; + naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop; + naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft; + naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom; + naturalPhysicalTop = mViewport.physicalLeft; + naturalDeviceWidth = mViewport.deviceHeight; + naturalDeviceHeight = mViewport.deviceWidth; + break; + case DISPLAY_ORIENTATION_180: + naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft; + naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop; + naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft; + naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop; + naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight; + naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom; + naturalDeviceWidth = mViewport.deviceWidth; + naturalDeviceHeight = mViewport.deviceHeight; + break; + case DISPLAY_ORIENTATION_270: + naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop; + naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft; + naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop; + naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft; + naturalPhysicalLeft = mViewport.physicalTop; + naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight; + naturalDeviceWidth = mViewport.deviceHeight; + naturalDeviceHeight = mViewport.deviceWidth; + break; + case DISPLAY_ORIENTATION_0: + default: + naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft; + naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop; + naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft; + naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop; + naturalPhysicalLeft = mViewport.physicalLeft; + naturalPhysicalTop = mViewport.physicalTop; + naturalDeviceWidth = mViewport.deviceWidth; + naturalDeviceHeight = mViewport.deviceHeight; + break; + } + + mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; + mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; + mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth; + mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight; - // Configure dimensions. - int32_t width, height, orientation; - if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) { - width = mAssociatedDisplayViewport.logicalRight - mAssociatedDisplayViewport.logicalLeft; - height = mAssociatedDisplayViewport.logicalBottom - mAssociatedDisplayViewport.logicalTop; - if (mAssociatedDisplayViewport.orientation == DISPLAY_ORIENTATION_90 - || mAssociatedDisplayViewport.orientation == DISPLAY_ORIENTATION_270) { - int32_t temp = height; - height = width; - width = temp; + mSurfaceOrientation = mParameters.orientationAware ? + mViewport.orientation : DISPLAY_ORIENTATION_0; + } else { + mSurfaceWidth = rawWidth; + mSurfaceHeight = rawHeight; + mSurfaceLeft = 0; + mSurfaceTop = 0; + mSurfaceOrientation = DISPLAY_ORIENTATION_0; } - orientation = mParameters.orientationAware ? - mAssociatedDisplayViewport.orientation : DISPLAY_ORIENTATION_0; - } else { - width = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; - height = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; - orientation = DISPLAY_ORIENTATION_0; } // If moving between pointer modes, need to reset some state. @@ -2918,22 +2984,17 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mPointerController.clear(); } - bool orientationChanged = mSurfaceOrientation != orientation; - if (orientationChanged) { - mSurfaceOrientation = orientation; - } - - bool sizeChanged = mSurfaceWidth != width || mSurfaceHeight != height; - if (sizeChanged || deviceModeChanged) { - ALOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d, mode is %d", - getDeviceId(), getDeviceName().string(), width, height, mDeviceMode); - - mSurfaceWidth = width; - mSurfaceHeight = height; + if (viewportChanged || deviceModeChanged) { + ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, " + "display id %d", + getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight, + mSurfaceOrientation, mDeviceMode, mViewport.displayId); // Configure X and Y factors. - mXScale = float(width) / (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1); - mYScale = float(height) / (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1); + mXScale = float(mSurfaceWidth) / rawWidth; + mYScale = float(mSurfaceHeight) / rawHeight; + mXTranslate = -mSurfaceLeft; + mYTranslate = -mSurfaceTop; mXPrecision = 1.0f / mXScale; mYPrecision = 1.0f / mYScale; @@ -2950,7 +3011,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mGeometricScale = avg(mXScale, mYScale); // Size of diagonal axis. - float diagonalSize = hypotf(width, height); + float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight); // Size factors. if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) { @@ -3102,50 +3163,38 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mOrientedRanges.distance.fuzz = mRawPointerAxes.distance.fuzz * mDistanceScale; } - } - if (orientationChanged || sizeChanged || deviceModeChanged) { - // Compute oriented surface dimensions, precision, scales and ranges. + // Compute oriented precision, scales and ranges. // Note that the maximum value reported is an inclusive maximum value so it is one // unit less than the total width or height of surface. switch (mSurfaceOrientation) { case DISPLAY_ORIENTATION_90: case DISPLAY_ORIENTATION_270: - mOrientedSurfaceWidth = mSurfaceHeight; - mOrientedSurfaceHeight = mSurfaceWidth; - mOrientedXPrecision = mYPrecision; mOrientedYPrecision = mXPrecision; - mOrientedRanges.x.min = 0; - mOrientedRanges.x.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue) - * mYScale; + mOrientedRanges.x.min = mYTranslate; + mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1; mOrientedRanges.x.flat = 0; mOrientedRanges.x.fuzz = mYScale; - mOrientedRanges.y.min = 0; - mOrientedRanges.y.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue) - * mXScale; + mOrientedRanges.y.min = mXTranslate; + mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1; mOrientedRanges.y.flat = 0; mOrientedRanges.y.fuzz = mXScale; break; default: - mOrientedSurfaceWidth = mSurfaceWidth; - mOrientedSurfaceHeight = mSurfaceHeight; - mOrientedXPrecision = mXPrecision; mOrientedYPrecision = mYPrecision; - mOrientedRanges.x.min = 0; - mOrientedRanges.x.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue) - * mXScale; + mOrientedRanges.x.min = mXTranslate; + mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1; mOrientedRanges.x.flat = 0; mOrientedRanges.x.fuzz = mXScale; - mOrientedRanges.y.min = 0; - mOrientedRanges.y.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue) - * mYScale; + mOrientedRanges.y.min = mYTranslate; + mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1; mOrientedRanges.y.flat = 0; mOrientedRanges.y.fuzz = mYScale; break; @@ -3153,10 +3202,8 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { // Compute pointer gesture detection parameters. if (mDeviceMode == DEVICE_MODE_POINTER) { - int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; - int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; float rawDiagonal = hypotf(rawWidth, rawHeight); - float displayDiagonal = hypotf(width, height); + float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight); // Scale movements such that one whole swipe of the touch pad covers a // given area relative to the diagonal size of the display when no acceleration @@ -3191,8 +3238,21 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { } void TouchInputMapper::dumpSurface(String8& dump) { + dump.appendFormat(INDENT3 "Viewport: displayId=%d, orientation=%d, " + "logicalFrame=[%d, %d, %d, %d], " + "physicalFrame=[%d, %d, %d, %d], " + "deviceSize=[%d, %d]\n", + mViewport.displayId, mViewport.orientation, + mViewport.logicalLeft, mViewport.logicalTop, + mViewport.logicalRight, mViewport.logicalBottom, + mViewport.physicalLeft, mViewport.physicalTop, + mViewport.physicalRight, mViewport.physicalBottom, + mViewport.deviceWidth, mViewport.deviceHeight); + dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth); dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight); + dump.appendFormat(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft); + dump.appendFormat(INDENT3 "SurfaceTop: %d\n", mSurfaceTop); dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation); } @@ -4087,28 +4147,28 @@ void TouchInputMapper::cookPointerData() { float x, y; switch (mSurfaceOrientation) { case DISPLAY_ORIENTATION_90: - x = float(in.y - mRawPointerAxes.y.minValue) * mYScale; - y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale; + x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; + y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate; orientation -= M_PI_2; if (orientation < - M_PI_2) { orientation += M_PI; } break; case DISPLAY_ORIENTATION_180: - x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale; - y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale; + x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate; + y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate; break; case DISPLAY_ORIENTATION_270: - x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale; - y = float(in.x - mRawPointerAxes.x.minValue) * mXScale; + x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate; + y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; orientation += M_PI_2; if (orientation > M_PI_2) { orientation -= M_PI; } break; default: - x = float(in.x - mRawPointerAxes.x.minValue) * mXScale; - y = float(in.y - mRawPointerAxes.y.minValue) * mYScale; + x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; + y = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; break; } @@ -4364,7 +4424,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime); + mViewport.displayId, 1, &pointerProperties, &pointerCoords, + 0, 0, mPointerGesture.downTime); getListener()->notifyMotion(&args); } @@ -5272,6 +5333,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send up. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5284,6 +5346,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send hover exit. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5298,6 +5361,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send down. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5307,6 +5371,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send move. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5320,6 +5385,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send hover enter. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5329,6 +5395,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, // Send hover move. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5349,6 +5416,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0, + mViewport.displayId, 1, &mPointerSimple.currentProperties, &pointerCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -5410,7 +5478,8 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 NotifyMotionArgs args(when, getDeviceId(), source, policyFlags, action, flags, metaState, buttonState, edgeFlags, - pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime); + mViewport.displayId, pointerCount, pointerProperties, pointerCoords, + xPrecision, yPrecision, downTime); getListener()->notifyMotion(&args); } @@ -6213,7 +6282,7 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) { } } - // Moving a joystick axis should not wake the devide because joysticks can + // Moving a joystick axis should not wake the device because joysticks can // be fairly noisy even when not in use. On the other hand, pushing a gamepad // button will likely wake the device. // TODO: Use the input device configuration to control this behavior more finely. @@ -6221,7 +6290,7 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) { NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, 0, 0, 0); + ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0); getListener()->notifyMotion(&args); } diff --git a/services/input/InputReader.h b/services/input/InputReader.h index e345a5f..e1a8dd8 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -62,11 +62,14 @@ struct DisplayViewport { int32_t physicalTop; int32_t physicalRight; int32_t physicalBottom; + int32_t deviceWidth; + int32_t deviceHeight; DisplayViewport() : - displayId(-1), orientation(DISPLAY_ORIENTATION_0), + displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0), logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0), - physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0) { + physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0), + deviceWidth(0), deviceHeight(0) { } bool operator==(const DisplayViewport& other) const { @@ -79,12 +82,33 @@ struct DisplayViewport { && physicalLeft == other.physicalLeft && physicalTop == other.physicalTop && physicalRight == other.physicalRight - && physicalBottom == other.physicalBottom; + && physicalBottom == other.physicalBottom + && deviceWidth == other.deviceWidth + && deviceHeight == other.deviceHeight; } bool operator!=(const DisplayViewport& other) const { return !(*this == other); } + + inline bool isValid() const { + return displayId >= 0; + } + + void setNonDisplayViewport(int32_t width, int32_t height) { + displayId = ADISPLAY_ID_NONE; + orientation = DISPLAY_ORIENTATION_0; + logicalLeft = 0; + logicalTop = 0; + logicalRight = width; + logicalBottom = height; + physicalLeft = 0; + physicalTop = 0; + physicalRight = width; + physicalBottom = height; + deviceWidth = width; + deviceHeight = height; + } }; /* @@ -1297,18 +1321,30 @@ protected: virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 0; private: - // The surface orientation and width and height set by configureSurface(). - int32_t mSurfaceOrientation; + // The current viewport. + // The components of the viewport are specified in the display's rotated orientation. + DisplayViewport mViewport; + + // The surface orientation, width and height set by configureSurface(). + // The width and height are derived from the viewport but are specified + // in the natural orientation. + // The surface origin specifies how the surface coordinates should be translated + // to align with the logical display coordinate space. + // The orientation may be different from the viewport orientation as it specifies + // the rotation of the surface coordinates required to produce the viewport's + // requested orientation, so it will depend on whether the device is orientation aware. int32_t mSurfaceWidth; int32_t mSurfaceHeight; - - // The associated display viewport set by configureSurface(). - DisplayViewport mAssociatedDisplayViewport; + int32_t mSurfaceLeft; + int32_t mSurfaceTop; + int32_t mSurfaceOrientation; // Translation and scaling factors, orientation-independent. + float mXTranslate; float mXScale; float mXPrecision; + float mYTranslate; float mYScale; float mYPrecision; @@ -1369,8 +1405,6 @@ private: } mOrientedRanges; // Oriented dimensions and precision. - float mOrientedSurfaceWidth; - float mOrientedSurfaceHeight; float mOrientedXPrecision; float mOrientedYPrecision; diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h index 824a64b..3118099 100644 --- a/services/input/InputWindow.h +++ b/services/input/InputWindow.h @@ -132,6 +132,7 @@ struct InputWindowInfo { int32_t ownerPid; int32_t ownerUid; int32_t inputFeatures; + int32_t displayId; bool touchableRegionContainsPoint(int32_t x, int32_t y) const; bool frameContainsPoint(int32_t x, int32_t y) const; diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp index 03516af..c6dbbf3 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -151,6 +151,8 @@ public: v.physicalTop = 0; v.physicalRight = isRotated ? height : width; v.physicalBottom = isRotated ? width : height; + v.deviceWidth = isRotated ? height : width; + v.deviceHeight = isRotated ? width : height; mConfig.setDisplayInfo(false /*external*/, v); mConfig.setDisplayInfo(true /*external*/, v); } @@ -487,6 +489,7 @@ private: return OK; } } + outAxisInfo->clear(); return -1; } diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java index 8eeefb4..f5aa3d4 100644 --- a/services/java/com/android/server/display/DisplayDevice.java +++ b/services/java/com/android/server/display/DisplayDevice.java @@ -176,6 +176,12 @@ abstract class DisplayDevice { } else { viewport.physicalFrame.setEmpty(); } + + boolean isRotated = (mCurrentOrientation == Surface.ROTATION_90 + || mCurrentOrientation == Surface.ROTATION_270); + DisplayDeviceInfo info = getDisplayDeviceInfoLocked(); + viewport.deviceWidth = isRotated ? info.height : info.width; + viewport.deviceHeight = isRotated ? info.width : info.height; } /** diff --git a/services/java/com/android/server/display/DisplayViewport.java b/services/java/com/android/server/display/DisplayViewport.java index ed4016d..5080556 100644 --- a/services/java/com/android/server/display/DisplayViewport.java +++ b/services/java/com/android/server/display/DisplayViewport.java @@ -44,12 +44,20 @@ public final class DisplayViewport { // should be scaled or translated after rotation. public final Rect physicalFrame = new Rect(); + // The full width and height of the display device, rotated in the same + // manner as physicalFrame. This expresses the full native size of the display device. + // The physical frame should usually fit within this area. + public int deviceWidth; + public int deviceHeight; + public void copyFrom(DisplayViewport viewport) { valid = viewport.valid; displayId = viewport.displayId; orientation = viewport.orientation; logicalFrame.set(viewport.logicalFrame); physicalFrame.set(viewport.physicalFrame); + deviceWidth = viewport.deviceWidth; + deviceHeight = viewport.deviceHeight; } // For debugging purposes. @@ -60,6 +68,8 @@ public final class DisplayViewport { + ", orientation=" + orientation + ", logicalFrame=" + logicalFrame + ", physicalFrame=" + physicalFrame + + ", deviceWidth=" + deviceWidth + + ", deviceHeight=" + deviceHeight + "}"; } } diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java index 95655a5..805818a 100644 --- a/services/java/com/android/server/input/InputManagerService.java +++ b/services/java/com/android/server/input/InputManagerService.java @@ -149,7 +149,8 @@ public class InputManagerService extends IInputManager.Stub private static native void nativeSetDisplayViewport(int ptr, boolean external, int displayId, int rotation, int logicalLeft, int logicalTop, int logicalRight, int logicalBottom, - int physicalLeft, int physicalTop, int physicalRight, int physicalBottom); + int physicalLeft, int physicalTop, int physicalRight, int physicalBottom, + int deviceWidth, int deviceHeight); private static native int nativeGetScanCodeState(int ptr, int deviceId, int sourceMask, int scanCode); @@ -305,7 +306,8 @@ public class InputManagerService extends IInputManager.Stub viewport.logicalFrame.left, viewport.logicalFrame.top, viewport.logicalFrame.right, viewport.logicalFrame.bottom, viewport.physicalFrame.left, viewport.physicalFrame.top, - viewport.physicalFrame.right, viewport.physicalFrame.bottom); + viewport.physicalFrame.right, viewport.physicalFrame.bottom, + viewport.deviceWidth, viewport.deviceHeight); } /** diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java index 5ff8a9b..aa18ee4 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/java/com/android/server/wm/InputMonitor.java @@ -19,11 +19,13 @@ package com.android.server.wm; import com.android.server.input.InputManagerService; import com.android.server.input.InputApplicationHandle; import com.android.server.input.InputWindowHandle; +import com.android.server.wm.WindowManagerService.AllWindowsIterator; import android.graphics.Rect; import android.os.RemoteException; import android.util.Log; import android.util.Slog; +import android.view.Display; import android.view.InputChannel; import android.view.KeyEvent; import android.view.WindowManager; @@ -225,10 +227,11 @@ final class InputMonitor implements InputManagerService.Callbacks { addInputWindowHandleLw(mService.mFakeWindows.get(i).mWindowHandle); } - // TODO(multidisplay): Input only occurs on the default display. - final WindowList windows = mService.getDefaultWindowList(); - for (int i = windows.size() - 1; i >= 0; i--) { - final WindowState child = windows.get(i); + // Add all windows on the default display. + final AllWindowsIterator iterator = mService.new AllWindowsIterator( + WindowManagerService.REVERSE_ITERATOR); + while (iterator.hasNext()) { + final WindowState child = iterator.next(); final InputChannel inputChannel = child.mInputChannel; final InputWindowHandle inputWindowHandle = child.mInputWindowHandle; if (inputChannel == null || inputWindowHandle == null || child.mRemoved) { @@ -243,15 +246,16 @@ final class InputMonitor implements InputManagerService.Callbacks { final boolean isVisible = child.isVisibleLw(); final boolean hasWallpaper = (child == mService.mWallpaperTarget) && (type != WindowManager.LayoutParams.TYPE_KEYGUARD); + final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY); // If there's a drag in progress and 'child' is a potential drop target, // make sure it's been told about the drag - if (inDrag && isVisible) { + if (inDrag && isVisible && onDefaultDisplay) { mService.mDragState.sendDragStartedIfNeededLw(child); } if (universeBackground != null && !addedUniverse - && child.mBaseLayer < aboveUniverseLayer) { + && child.mBaseLayer < aboveUniverseLayer && onDefaultDisplay) { final WindowState u = universeBackground.mWin; if (u.mInputChannel != null && u.mInputWindowHandle != null) { addInputWindowHandleLw(u.mInputWindowHandle, u, u.mAttrs.flags, diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index cdca8bc..a7ea01d 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -10744,7 +10744,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - boolean REVERSE_ITERATOR = true; + final static boolean REVERSE_ITERATOR = true; class AllWindowsIterator implements Iterator<WindowState> { private DisplayContent mDisplayContent; private DisplayContentsIterator mDisplayContentsIterator; diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp index 5e36bf8..319cacd 100644 --- a/services/jni/com_android_server_input_InputManagerService.cpp +++ b/services/jni/com_android_server_input_InputManagerService.cpp @@ -993,7 +993,8 @@ static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) { static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jint ptr, jboolean external, jint displayId, jint orientation, jint logicalLeft, jint logicalTop, jint logicalRight, jint logicalBottom, - jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom) { + jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom, + jint deviceWidth, jint deviceHeight) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); DisplayViewport v; @@ -1007,6 +1008,8 @@ static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jint ptr, jboole v.physicalTop = physicalTop; v.physicalRight = physicalRight; v.physicalBottom = physicalBottom; + v.deviceWidth = deviceWidth; + v.deviceHeight = deviceHeight; im->setDisplayViewport(external, v); } @@ -1288,7 +1291,7 @@ static JNINativeMethod gInputManagerMethods[] = { (void*) nativeInit }, { "nativeStart", "(I)V", (void*) nativeStart }, - { "nativeSetDisplayViewport", "(IZIIIIIIIIII)V", + { "nativeSetDisplayViewport", "(IZIIIIIIIIIIII)V", (void*) nativeSetDisplayViewport }, { "nativeGetScanCodeState", "(IIII)I", (void*) nativeGetScanCodeState }, diff --git a/services/jni/com_android_server_input_InputWindowHandle.cpp b/services/jni/com_android_server_input_InputWindowHandle.cpp index 01fb781..6692994 100644 --- a/services/jni/com_android_server_input_InputWindowHandle.cpp +++ b/services/jni/com_android_server_input_InputWindowHandle.cpp @@ -52,6 +52,7 @@ static struct { jfieldID ownerPid; jfieldID ownerUid; jfieldID inputFeatures; + jfieldID displayId; } gInputWindowHandleClassInfo; static Mutex gHandleMutex; @@ -151,6 +152,8 @@ bool NativeInputWindowHandle::updateInfo() { gInputWindowHandleClassInfo.ownerUid); mInfo->inputFeatures = env->GetIntField(obj, gInputWindowHandleClassInfo.inputFeatures); + mInfo->displayId = env->GetIntField(obj, + gInputWindowHandleClassInfo.displayId); env->DeleteLocalRef(obj); return true; @@ -291,6 +294,9 @@ int register_android_server_InputWindowHandle(JNIEnv* env) { GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz, "inputFeatures", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz, + "displayId", "I"); return 0; } |