diff options
| author | 2011-02-19 05:07:28 -0800 | |
|---|---|---|
| committer | 2011-02-19 06:14:21 -0800 | |
| commit | cc0c159e9b3dd4e0f48da0ce3e33d2c68a651413 (patch) | |
| tree | 7a4e3c578e3e0f2c01fef4d64e721d81c851748e /services/input/InputDispatcher.cpp | |
| parent | 6f2fba428ca5e77a26d991ad728e346cc47609ee (diff) | |
Add new hover move action and scroll wheel plumbing.
Added support for tracking the mouse position even when the mouse button
is not pressed. To avoid confusing existing applications, mouse movements
are reported using the new ACTION_HOVER_MOVE action when the mouse button
is not pressed.
Added some more plumbing for the scroll wheel axes. The values are
reported to Views but they are not yet handled by the framework.
Change-Id: I1706be850d25cf34e5adf880bbed5cc3265cf4b1
Diffstat (limited to 'services/input/InputDispatcher.cpp')
| -rw-r--r-- | services/input/InputDispatcher.cpp | 165 |
1 files changed, 70 insertions, 95 deletions
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index ae11fb1e025e..ef984d41cf17 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -115,6 +115,7 @@ static bool isValidMotionAction(int32_t action, size_t pointerCount) { case AMOTION_EVENT_ACTION_CANCEL: case AMOTION_EVENT_ACTION_MOVE: case AMOTION_EVENT_ACTION_OUTSIDE: + case AMOTION_EVENT_ACTION_HOVER_MOVE: return true; case AMOTION_EVENT_ACTION_POINTER_DOWN: case AMOTION_EVENT_ACTION_POINTER_UP: { @@ -318,7 +319,8 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, uint32_t source = motionEntry->source; if (! isAppSwitchDue && motionEntry->next == & mInboundQueue.tailSentinel // exactly one event - && motionEntry->action == AMOTION_EVENT_ACTION_MOVE + && (motionEntry->action == AMOTION_EVENT_ACTION_MOVE + || motionEntry->action == AMOTION_EVENT_ACTION_HOVER_MOVE) && deviceId == mThrottleState.lastDeviceId && source == mThrottleState.lastSource) { nsecs_t nextTime = mThrottleState.lastEventTime @@ -478,7 +480,8 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { // If the application takes too long to catch up then we drop all events preceding // the touch into the other window. MotionEntry* motionEntry = static_cast<MotionEntry*>(entry); - if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN + if ((motionEntry->action == AMOTION_EVENT_ACTION_DOWN + || motionEntry->action == AMOTION_EVENT_ACTION_HOVER_MOVE) && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY && mInputTargetWaitApplication != NULL) { @@ -838,12 +841,13 @@ bool InputDispatcher::dispatchMotionLocked( bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER; // Identify targets. + bool conflictingPointerActions = false; if (! mCurrentInputTargetsValid) { int32_t injectionResult; if (isPointerEvent) { // Pointer event. (eg. touchscreen) injectionResult = findTouchedWindowTargetsLocked(currentTime, - entry, nextWakeupTime); + entry, nextWakeupTime, &conflictingPointerActions); } else { // Non touch event. (eg. trackball) injectionResult = findFocusedWindowTargetsLocked(currentTime, @@ -863,6 +867,10 @@ bool InputDispatcher::dispatchMotionLocked( } // Dispatch the motion. + if (conflictingPointerActions) { + synthesizeCancelationEventsForAllConnectionsLocked( + InputState::CANCEL_POINTER_EVENTS, "Conflicting pointer actions."); + } dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false); return true; } @@ -1123,7 +1131,7 @@ Unresponsive: } int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, - const MotionEntry* entry, nsecs_t* nextWakeupTime) { + const MotionEntry* entry, nsecs_t* nextWakeupTime, bool* outConflictingPointerActions) { enum InjectionPermission { INJECTION_PERMISSION_UNKNOWN, INJECTION_PERMISSION_GRANTED, @@ -1166,31 +1174,38 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, // Update the touch state as needed based on the properties of the touch event. int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING; InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN; - bool isSplit, wrongDevice; - if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { - mTempTouchState.reset(); - mTempTouchState.down = true; - mTempTouchState.deviceId = entry->deviceId; - mTempTouchState.source = entry->source; - isSplit = false; - wrongDevice = false; + + bool isSplit = mTouchState.split; + bool wrongDevice = mTouchState.down + && (mTouchState.deviceId != entry->deviceId + || mTouchState.source != entry->source); + if (maskedAction == AMOTION_EVENT_ACTION_DOWN + || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) { + bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN; + if (wrongDevice && !down) { + mTempTouchState.copyFrom(mTouchState); + } else { + mTempTouchState.reset(); + mTempTouchState.down = down; + mTempTouchState.deviceId = entry->deviceId; + mTempTouchState.source = entry->source; + isSplit = false; + wrongDevice = false; + } } else { mTempTouchState.copyFrom(mTouchState); - isSplit = mTempTouchState.split; - wrongDevice = mTempTouchState.down - && (mTempTouchState.deviceId != entry->deviceId - || mTempTouchState.source != entry->source); - if (wrongDevice) { + } + if (wrongDevice) { #if DEBUG_INPUT_DISPATCHER_POLICY - LOGD("Dropping event because a pointer for a different device is already down."); + LOGD("Dropping event because a pointer for a different device is already down."); #endif - injectionResult = INPUT_EVENT_INJECTION_FAILED; - goto Failed; - } + injectionResult = INPUT_EVENT_INJECTION_FAILED; + goto Failed; } if (maskedAction == AMOTION_EVENT_ACTION_DOWN - || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) { + || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) + || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) { /* Case 1: New splittable pointer going down. */ int32_t pointerIndex = getMotionEventActionPointerIndex(action); @@ -1365,7 +1380,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, // If this is the first pointer going down and the touched window has a wallpaper // then also add the touched wallpaper windows so they are locked in for the duration // of the touch gesture. - if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { + if (maskedAction == AMOTION_EVENT_ACTION_DOWN + || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) { const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow(); if (foregroundWindow->hasWallpaper) { for (size_t i = 0; i < mWindows.size(); i++) { @@ -1404,12 +1420,14 @@ Failed: if (injectionPermission == INJECTION_PERMISSION_GRANTED) { if (!wrongDevice) { if (maskedAction == AMOTION_EVENT_ACTION_UP - || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { + || maskedAction == AMOTION_EVENT_ACTION_CANCEL + || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) { // All pointers up or canceled. mTempTouchState.reset(); } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { // First pointer went down. if (mTouchState.down) { + *outConflictingPointerActions = true; #if DEBUG_FOCUS LOGD("Pointer down received while already down."); #endif @@ -1750,29 +1768,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, // Update the connection's input state. EventEntry* eventEntry = dispatchEntry->eventEntry; - InputState::Consistency consistency = connection->inputState.trackEvent(eventEntry); - -#if FILTER_INPUT_EVENTS - // Filter out inconsistent sequences of input events. - // The input system may drop or inject events in a way that could violate implicit - // invariants on input state and potentially cause an application to crash - // or think that a key or pointer is stuck down. Technically we make no guarantees - // of consistency but it would be nice to improve on this where possible. - // XXX: This code is a proof of concept only. Not ready for prime time. - if (consistency == InputState::TOLERABLE) { -#if DEBUG_DISPATCH_CYCLE - LOGD("channel '%s' ~ Sending an event that is inconsistent with the connection's " - "current input state but that is likely to be tolerated by the application.", - connection->getInputChannelName()); -#endif - } else if (consistency == InputState::BROKEN) { - LOGI("channel '%s' ~ Dropping an event that is inconsistent with the connection's " - "current input state and that is likely to cause the application to crash.", - connection->getInputChannelName()); - startNextDispatchCycleLocked(currentTime, connection); - return; - } -#endif + connection->inputState.trackEvent(eventEntry); // Publish the event. status_t status; @@ -2307,7 +2303,8 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t AutoMutex _l(mLock); // Attempt batching and streaming of move events. - if (action == AMOTION_EVENT_ACTION_MOVE) { + if (action == AMOTION_EVENT_ACTION_MOVE + || action == AMOTION_EVENT_ACTION_HOVER_MOVE) { // BATCHING CASE // // Try to append a move sample to the tail of the inbound queue for this device. @@ -2326,7 +2323,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t continue; } - if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE + if (motionEntry->action != action || motionEntry->source != source || motionEntry->pointerCount != pointerCount || motionEntry->isInjected()) { @@ -2385,7 +2382,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t MotionEntry* motionEntry = static_cast<MotionEntry*>( dispatchEntry->eventEntry); - if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE + if (motionEntry->action != action || motionEntry->deviceId != deviceId || motionEntry->source != source || motionEntry->pointerCount != pointerCount @@ -3529,21 +3526,20 @@ bool InputDispatcher::InputState::isNeutral() const { return mKeyMementos.isEmpty() && mMotionMementos.isEmpty(); } -InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackEvent( +void InputDispatcher::InputState::trackEvent( const EventEntry* entry) { switch (entry->type) { case EventEntry::TYPE_KEY: - return trackKey(static_cast<const KeyEntry*>(entry)); + trackKey(static_cast<const KeyEntry*>(entry)); + break; case EventEntry::TYPE_MOTION: - return trackMotion(static_cast<const MotionEntry*>(entry)); - - default: - return CONSISTENT; + trackMotion(static_cast<const MotionEntry*>(entry)); + break; } } -InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey( +void InputDispatcher::InputState::trackKey( const KeyEntry* entry) { int32_t action = entry->action; for (size_t i = 0; i < mKeyMementos.size(); i++) { @@ -3555,19 +3551,20 @@ InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey( switch (action) { case AKEY_EVENT_ACTION_UP: mKeyMementos.removeAt(i); - return CONSISTENT; + return; case AKEY_EVENT_ACTION_DOWN: - return TOLERABLE; + mKeyMementos.removeAt(i); + goto Found; default: - return BROKEN; + return; } } } - switch (action) { - case AKEY_EVENT_ACTION_DOWN: { +Found: + if (action == AKEY_EVENT_ACTION_DOWN) { mKeyMementos.push(); KeyMemento& memento = mKeyMementos.editTop(); memento.deviceId = entry->deviceId; @@ -3576,15 +3573,10 @@ InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey( memento.scanCode = entry->scanCode; memento.flags = entry->flags; memento.downTime = entry->downTime; - return CONSISTENT; - } - - default: - return BROKEN; } } -InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotion( +void InputDispatcher::InputState::trackMotion( const MotionEntry* entry) { int32_t action = entry->action & AMOTION_EVENT_ACTION_MASK; for (size_t i = 0; i < mMotionMementos.size(); i++) { @@ -3594,40 +3586,28 @@ InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotio switch (action) { case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_CANCEL: + case AMOTION_EVENT_ACTION_HOVER_MOVE: mMotionMementos.removeAt(i); - return CONSISTENT; + return; case AMOTION_EVENT_ACTION_DOWN: - return TOLERABLE; - - case AMOTION_EVENT_ACTION_POINTER_DOWN: - if (entry->pointerCount == memento.pointerCount + 1) { - memento.setPointers(entry); - return CONSISTENT; - } - return BROKEN; + mMotionMementos.removeAt(i); + goto Found; case AMOTION_EVENT_ACTION_POINTER_UP: - if (entry->pointerCount == memento.pointerCount - 1) { - memento.setPointers(entry); - return CONSISTENT; - } - return BROKEN; - + case AMOTION_EVENT_ACTION_POINTER_DOWN: case AMOTION_EVENT_ACTION_MOVE: - if (entry->pointerCount == memento.pointerCount) { - return CONSISTENT; - } - return BROKEN; + memento.setPointers(entry); + return; default: - return BROKEN; + return; } } } - switch (action) { - case AMOTION_EVENT_ACTION_DOWN: { +Found: + if (action == AMOTION_EVENT_ACTION_DOWN) { mMotionMementos.push(); MotionMemento& memento = mMotionMementos.editTop(); memento.deviceId = entry->deviceId; @@ -3636,11 +3616,6 @@ InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotio memento.yPrecision = entry->yPrecision; memento.downTime = entry->downTime; memento.setPointers(entry); - return CONSISTENT; - } - - default: - return BROKEN; } } |