Loading services/inputflinger/dispatcher/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ filegroup { "InputTarget.cpp", "Monitor.cpp", "TouchState.cpp", "DragState.cpp", ], } Loading services/inputflinger/dispatcher/DragState.cpp 0 → 100644 +38 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "DragState.h" #include <android-base/stringprintf.h> #include <input/InputWindow.h> using android::InputWindowHandle; using android::base::StringPrintf; namespace android::inputdispatcher { void DragState::dump(std::string& dump, const char* prefix) { dump += prefix + StringPrintf("Drag Window: %s\n", dragWindow->getName().c_str()); if (dragHoverWindowHandle) { dump += prefix + StringPrintf("Drag Hover Window: %s\n", dragHoverWindowHandle->getName().c_str()); } dump += prefix + StringPrintf("isStartDrag: %s\n", isStartDrag ? "true" : "false"); dump += prefix + StringPrintf("isStylusButtonDownAtStart: %s\n", isStylusButtonDownAtStart ? "true" : "false"); } } // namespace android::inputdispatcher No newline at end of file services/inputflinger/dispatcher/DragState.h 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _UI_INPUT_INPUTDISPATCHER_DRAGSTATE_H #define _UI_INPUT_INPUTDISPATCHER_DRAGSTATE_H #include <utils/RefBase.h> #include <string> namespace android { class InputWindowHandle; namespace inputdispatcher { struct DragState { DragState(const sp<android::InputWindowHandle>& windowHandle) : dragWindow(windowHandle) {} void dump(std::string& dump, const char* prefix = ""); // The window being dragged. const sp<InputWindowHandle> dragWindow; // The last drag hover window which could receive the drag event. sp<InputWindowHandle> dragHoverWindowHandle; // Indicates the if received first event to check for button state. bool isStartDrag = false; // Indicate if the stylus button is down at the start of the drag. bool isStylusButtonDownAtStart = false; }; } // namespace inputdispatcher } // namespace android #endif // _UI_INPUT_INPUTDISPATCHER_DRAGSTATE_H No newline at end of file services/inputflinger/dispatcher/InputDispatcher.cpp +50 −24 Original line number Diff line number Diff line Loading @@ -961,7 +961,7 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display // Traverse windows from front to back to find touched window. const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId); for (const sp<InputWindowHandle>& windowHandle : windowHandles) { if (ignoreDragWindow && haveSameToken(windowHandle, touchState->dragWindow)) { if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) { continue; } const InputWindowInfo* windowInfo = windowHandle->getInfo(); Loading Loading @@ -2061,7 +2061,7 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( goto Failed; } addDragEventLocked(entry, tempTouchState); addDragEventLocked(entry); // Check whether touches should slip outside of the current foreground window. if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry.pointerCount == 1 && Loading Loading @@ -2318,39 +2318,61 @@ Failed: return injectionResult; } void InputDispatcher::addDragEventLocked(const MotionEntry& entry, TouchState& state) { if (entry.pointerCount != 1 || !state.dragWindow) { void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) { const sp<InputWindowHandle> dropWindow = findTouchedWindowAtLocked(displayId, x, y, nullptr /*touchState*/, false /*addOutsideTargets*/, false /*addPortalWindows*/, true /*ignoreDragWindow*/); if (dropWindow) { vec2 local = dropWindow->getInfo()->transform.transform(x, y); notifyDropWindowLocked(dropWindow->getToken(), local.x, local.y); } mDragState.reset(); } void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { if (entry.pointerCount != 1 || !mDragState) { return; } if (!mDragState->isStartDrag) { mDragState->isStartDrag = true; mDragState->isStylusButtonDownAtStart = (entry.buttonState & AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) != 0; } int32_t maskedAction = entry.action & AMOTION_EVENT_ACTION_MASK; int32_t x = static_cast<int32_t>(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = static_cast<int32_t>(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); if (maskedAction == AMOTION_EVENT_ACTION_MOVE) { // Handle the special case : stylus button no longer pressed. bool isStylusButtonDown = (entry.buttonState & AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) != 0; if (mDragState->isStylusButtonDownAtStart && !isStylusButtonDown) { finishDragAndDrop(entry.displayId, x, y); return; } const sp<InputWindowHandle> hoverWindowHandle = findTouchedWindowAtLocked(entry.displayId, x, y, &state, findTouchedWindowAtLocked(entry.displayId, x, y, nullptr /*touchState*/, false /*addOutsideTargets*/, false /*addPortalWindows*/, true /*ignoreDragWindow*/); // enqueue drag exit if needed. if (hoverWindowHandle != state.dragHoverWindowHandle && !haveSameToken(hoverWindowHandle, state.dragHoverWindowHandle)) { if (state.dragHoverWindowHandle != nullptr) { enqueueDragEventLocked(state.dragHoverWindowHandle, true /*isExiting*/, entry); if (hoverWindowHandle != mDragState->dragHoverWindowHandle && !haveSameToken(hoverWindowHandle, mDragState->dragHoverWindowHandle)) { if (mDragState->dragHoverWindowHandle != nullptr) { enqueueDragEventLocked(mDragState->dragHoverWindowHandle, true /*isExiting*/, entry); } state.dragHoverWindowHandle = hoverWindowHandle; mDragState->dragHoverWindowHandle = hoverWindowHandle; } // enqueue drag location if needed. if (hoverWindowHandle != nullptr) { enqueueDragEventLocked(hoverWindowHandle, false /*isExiting*/, entry); } } else if (maskedAction == AMOTION_EVENT_ACTION_UP || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { if (state.dragHoverWindowHandle && maskedAction == AMOTION_EVENT_ACTION_UP) { vec2 local = state.dragHoverWindowHandle->getInfo()->transform.transform(x, y); notifyDropWindowLocked(state.dragHoverWindowHandle->getToken(), local.x, local.y); } state.dragWindow = nullptr; state.dragHoverWindowHandle = nullptr; } else if (maskedAction == AMOTION_EVENT_ACTION_UP) { finishDragAndDrop(entry.displayId, x, y); } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) { mDragState.reset(); } } Loading Loading @@ -4445,13 +4467,12 @@ void InputDispatcher::setInputWindowsLocked( } } // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. we // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We // could just clear the state here. if (state.dragWindow && std::find(windowHandles.begin(), windowHandles.end(), state.dragWindow) == if (mDragState && std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) == windowHandles.end()) { state.dragWindow = nullptr; state.dragHoverWindowHandle = nullptr; mDragState.reset(); } } Loading Loading @@ -4690,7 +4711,7 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp< // Store the dragging window. if (isDragDrop) { state.dragWindow = toWindowHandle; mDragState = std::make_unique<DragState>(toWindowHandle); } found = true; Loading Loading @@ -4833,6 +4854,11 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += INDENT "TouchStates: <no displays touched>\n"; } if (mDragState) { dump += StringPrintf(INDENT "DragState:\n"); mDragState->dump(dump, INDENT2); } if (!mWindowHandlesByDisplay.empty()) { for (auto& it : mWindowHandlesByDisplay) { const std::vector<sp<InputWindowHandle>> windowHandles = it.second; Loading services/inputflinger/dispatcher/InputDispatcher.h +4 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "AnrTracker.h" #include "CancelationOptions.h" #include "DragState.h" #include "Entry.h" #include "FocusResolver.h" #include "InjectionState.h" Loading Loading @@ -340,6 +341,7 @@ private: REQUIRES(mLock); std::unordered_map<int32_t, TouchState> mTouchStatesByDisplay GUARDED_BY(mLock); std::unique_ptr<DragState> mDragState GUARDED_BY(mLock); // Focused applications. std::unordered_map<int32_t, std::shared_ptr<InputApplicationHandle>> Loading Loading @@ -499,7 +501,8 @@ private: const InjectionState* injectionState); // Enqueue a drag event if needed, and update the touch state. // Uses findTouchedWindowTargetsLocked to make the decision void addDragEventLocked(const MotionEntry& entry, TouchState& state) REQUIRES(mLock); void addDragEventLocked(const MotionEntry& entry) REQUIRES(mLock); void finishDragAndDrop(int32_t displayId, float x, float y) REQUIRES(mLock); struct TouchOcclusionInfo { bool hasBlockingOcclusion; Loading Loading
services/inputflinger/dispatcher/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ filegroup { "InputTarget.cpp", "Monitor.cpp", "TouchState.cpp", "DragState.cpp", ], } Loading
services/inputflinger/dispatcher/DragState.cpp 0 → 100644 +38 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "DragState.h" #include <android-base/stringprintf.h> #include <input/InputWindow.h> using android::InputWindowHandle; using android::base::StringPrintf; namespace android::inputdispatcher { void DragState::dump(std::string& dump, const char* prefix) { dump += prefix + StringPrintf("Drag Window: %s\n", dragWindow->getName().c_str()); if (dragHoverWindowHandle) { dump += prefix + StringPrintf("Drag Hover Window: %s\n", dragHoverWindowHandle->getName().c_str()); } dump += prefix + StringPrintf("isStartDrag: %s\n", isStartDrag ? "true" : "false"); dump += prefix + StringPrintf("isStylusButtonDownAtStart: %s\n", isStylusButtonDownAtStart ? "true" : "false"); } } // namespace android::inputdispatcher No newline at end of file
services/inputflinger/dispatcher/DragState.h 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _UI_INPUT_INPUTDISPATCHER_DRAGSTATE_H #define _UI_INPUT_INPUTDISPATCHER_DRAGSTATE_H #include <utils/RefBase.h> #include <string> namespace android { class InputWindowHandle; namespace inputdispatcher { struct DragState { DragState(const sp<android::InputWindowHandle>& windowHandle) : dragWindow(windowHandle) {} void dump(std::string& dump, const char* prefix = ""); // The window being dragged. const sp<InputWindowHandle> dragWindow; // The last drag hover window which could receive the drag event. sp<InputWindowHandle> dragHoverWindowHandle; // Indicates the if received first event to check for button state. bool isStartDrag = false; // Indicate if the stylus button is down at the start of the drag. bool isStylusButtonDownAtStart = false; }; } // namespace inputdispatcher } // namespace android #endif // _UI_INPUT_INPUTDISPATCHER_DRAGSTATE_H No newline at end of file
services/inputflinger/dispatcher/InputDispatcher.cpp +50 −24 Original line number Diff line number Diff line Loading @@ -961,7 +961,7 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display // Traverse windows from front to back to find touched window. const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId); for (const sp<InputWindowHandle>& windowHandle : windowHandles) { if (ignoreDragWindow && haveSameToken(windowHandle, touchState->dragWindow)) { if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) { continue; } const InputWindowInfo* windowInfo = windowHandle->getInfo(); Loading Loading @@ -2061,7 +2061,7 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( goto Failed; } addDragEventLocked(entry, tempTouchState); addDragEventLocked(entry); // Check whether touches should slip outside of the current foreground window. if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry.pointerCount == 1 && Loading Loading @@ -2318,39 +2318,61 @@ Failed: return injectionResult; } void InputDispatcher::addDragEventLocked(const MotionEntry& entry, TouchState& state) { if (entry.pointerCount != 1 || !state.dragWindow) { void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) { const sp<InputWindowHandle> dropWindow = findTouchedWindowAtLocked(displayId, x, y, nullptr /*touchState*/, false /*addOutsideTargets*/, false /*addPortalWindows*/, true /*ignoreDragWindow*/); if (dropWindow) { vec2 local = dropWindow->getInfo()->transform.transform(x, y); notifyDropWindowLocked(dropWindow->getToken(), local.x, local.y); } mDragState.reset(); } void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { if (entry.pointerCount != 1 || !mDragState) { return; } if (!mDragState->isStartDrag) { mDragState->isStartDrag = true; mDragState->isStylusButtonDownAtStart = (entry.buttonState & AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) != 0; } int32_t maskedAction = entry.action & AMOTION_EVENT_ACTION_MASK; int32_t x = static_cast<int32_t>(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = static_cast<int32_t>(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); if (maskedAction == AMOTION_EVENT_ACTION_MOVE) { // Handle the special case : stylus button no longer pressed. bool isStylusButtonDown = (entry.buttonState & AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) != 0; if (mDragState->isStylusButtonDownAtStart && !isStylusButtonDown) { finishDragAndDrop(entry.displayId, x, y); return; } const sp<InputWindowHandle> hoverWindowHandle = findTouchedWindowAtLocked(entry.displayId, x, y, &state, findTouchedWindowAtLocked(entry.displayId, x, y, nullptr /*touchState*/, false /*addOutsideTargets*/, false /*addPortalWindows*/, true /*ignoreDragWindow*/); // enqueue drag exit if needed. if (hoverWindowHandle != state.dragHoverWindowHandle && !haveSameToken(hoverWindowHandle, state.dragHoverWindowHandle)) { if (state.dragHoverWindowHandle != nullptr) { enqueueDragEventLocked(state.dragHoverWindowHandle, true /*isExiting*/, entry); if (hoverWindowHandle != mDragState->dragHoverWindowHandle && !haveSameToken(hoverWindowHandle, mDragState->dragHoverWindowHandle)) { if (mDragState->dragHoverWindowHandle != nullptr) { enqueueDragEventLocked(mDragState->dragHoverWindowHandle, true /*isExiting*/, entry); } state.dragHoverWindowHandle = hoverWindowHandle; mDragState->dragHoverWindowHandle = hoverWindowHandle; } // enqueue drag location if needed. if (hoverWindowHandle != nullptr) { enqueueDragEventLocked(hoverWindowHandle, false /*isExiting*/, entry); } } else if (maskedAction == AMOTION_EVENT_ACTION_UP || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { if (state.dragHoverWindowHandle && maskedAction == AMOTION_EVENT_ACTION_UP) { vec2 local = state.dragHoverWindowHandle->getInfo()->transform.transform(x, y); notifyDropWindowLocked(state.dragHoverWindowHandle->getToken(), local.x, local.y); } state.dragWindow = nullptr; state.dragHoverWindowHandle = nullptr; } else if (maskedAction == AMOTION_EVENT_ACTION_UP) { finishDragAndDrop(entry.displayId, x, y); } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) { mDragState.reset(); } } Loading Loading @@ -4445,13 +4467,12 @@ void InputDispatcher::setInputWindowsLocked( } } // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. we // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We // could just clear the state here. if (state.dragWindow && std::find(windowHandles.begin(), windowHandles.end(), state.dragWindow) == if (mDragState && std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) == windowHandles.end()) { state.dragWindow = nullptr; state.dragHoverWindowHandle = nullptr; mDragState.reset(); } } Loading Loading @@ -4690,7 +4711,7 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp< // Store the dragging window. if (isDragDrop) { state.dragWindow = toWindowHandle; mDragState = std::make_unique<DragState>(toWindowHandle); } found = true; Loading Loading @@ -4833,6 +4854,11 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += INDENT "TouchStates: <no displays touched>\n"; } if (mDragState) { dump += StringPrintf(INDENT "DragState:\n"); mDragState->dump(dump, INDENT2); } if (!mWindowHandlesByDisplay.empty()) { for (auto& it : mWindowHandlesByDisplay) { const std::vector<sp<InputWindowHandle>> windowHandles = it.second; Loading
services/inputflinger/dispatcher/InputDispatcher.h +4 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "AnrTracker.h" #include "CancelationOptions.h" #include "DragState.h" #include "Entry.h" #include "FocusResolver.h" #include "InjectionState.h" Loading Loading @@ -340,6 +341,7 @@ private: REQUIRES(mLock); std::unordered_map<int32_t, TouchState> mTouchStatesByDisplay GUARDED_BY(mLock); std::unique_ptr<DragState> mDragState GUARDED_BY(mLock); // Focused applications. std::unordered_map<int32_t, std::shared_ptr<InputApplicationHandle>> Loading Loading @@ -499,7 +501,8 @@ private: const InjectionState* injectionState); // Enqueue a drag event if needed, and update the touch state. // Uses findTouchedWindowTargetsLocked to make the decision void addDragEventLocked(const MotionEntry& entry, TouchState& state) REQUIRES(mLock); void addDragEventLocked(const MotionEntry& entry) REQUIRES(mLock); void finishDragAndDrop(int32_t displayId, float x, float y) REQUIRES(mLock); struct TouchOcclusionInfo { bool hasBlockingOcclusion; Loading