Add support for transferring touch focus.

Prerequisite for drag and drop.

Change-Id: Iedbe93ed0f3e1c4083130fe66b4ba06d416afce0
This commit is contained in:
Jeff Brown 2010-09-27 14:52:15 -07:00
parent e457038905
commit 744c559ac7
2 changed files with 75 additions and 0 deletions

View File

@ -355,6 +355,14 @@ public:
*/
virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;
/* Transfers touch focus from the window associated with one channel to the
* window associated with the other channel.
*
* Returns true on success. False if the window did not actually have touch focus.
*/
virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
const sp<InputChannel>& toChannel) = 0;
/* Registers or unregister input channels that may be used as targets for input events.
* If monitor is true, the channel will receive a copy of all input events.
*
@ -409,6 +417,9 @@ public:
virtual void setFocusedApplication(const InputApplication* inputApplication);
virtual void setInputDispatchMode(bool enabled, bool frozen);
virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
const sp<InputChannel>& toChannel);
virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor);
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);

View File

@ -2464,6 +2464,70 @@ void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
}
}
bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
const sp<InputChannel>& toChannel) {
#if DEBUG_FOCUS
LOGD("transferTouchFocus: fromChannel=%s, toChannel=%s",
fromChannel->getName().string(), toChannel->getName().string());
#endif
{ // acquire lock
AutoMutex _l(mLock);
const InputWindow* fromWindow = getWindowLocked(fromChannel);
const InputWindow* toWindow = getWindowLocked(toChannel);
if (! fromWindow || ! toWindow) {
#if DEBUG_FOCUS
LOGD("Cannot transfer focus because from or to window not found.");
#endif
return false;
}
if (fromWindow == toWindow) {
#if DEBUG_FOCUS
LOGD("Trivial transfer to same window.");
#endif
return true;
}
bool found = false;
for (size_t i = 0; i < mTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTouchState.windows[i];
if (touchedWindow.window == fromWindow) {
int32_t oldTargetFlags = touchedWindow.targetFlags;
BitSet32 pointerIds = touchedWindow.pointerIds;
mTouchState.windows.removeAt(i);
int32_t newTargetFlags = 0;
if (oldTargetFlags & InputTarget::FLAG_FOREGROUND) {
newTargetFlags |= InputTarget::FLAG_FOREGROUND;
if (toWindow->layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH) {
newTargetFlags |= InputTarget::FLAG_SPLIT;
}
}
mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds);
found = true;
break;
}
}
if (! found) {
#if DEBUG_FOCUS
LOGD("Focus transfer failed because from window did not have focus.");
#endif
return false;
}
#if DEBUG_FOCUS
logDispatchStateLocked();
#endif
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
mLooper->wake();
return true;
}
void InputDispatcher::logDispatchStateLocked() {
String8 dump;
dumpDispatchStateLocked(dump);