blob: ad37d025cad174159a20871b6884d0619d50d6fa [file] [log] [blame]
Garfield Tane84e6f92019-08-29 17:28:41 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -080017#include <android-base/stringprintf.h>
chaviw98318de2021-05-19 16:45:23 -050018#include <gui/WindowInfo.h>
Garfield Tane84e6f92019-08-29 17:28:41 -070019
20#include "InputTarget.h"
Garfield Tane84e6f92019-08-29 17:28:41 -070021#include "TouchState.h"
22
Siarhei Vishniakou253f4642022-11-09 13:42:06 -080023using namespace android::ftl::flag_operators;
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -080024using android::base::StringPrintf;
chaviw98318de2021-05-19 16:45:23 -050025using android::gui::WindowInfo;
26using android::gui::WindowInfoHandle;
Garfield Tane84e6f92019-08-29 17:28:41 -070027
28namespace android::inputdispatcher {
29
Garfield Tane84e6f92019-08-29 17:28:41 -070030void TouchState::reset() {
Prabir Pradhane680f9b2022-02-04 04:24:00 -080031 *this = TouchState();
Garfield Tane84e6f92019-08-29 17:28:41 -070032}
33
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000034void TouchState::removeTouchedPointer(int32_t pointerId) {
35 for (TouchedWindow& touchedWindow : windows) {
36 touchedWindow.pointerIds.clearBit(pointerId);
37 }
38}
39
Siarhei Vishniakou0026b4c2022-11-10 19:33:29 -080040void TouchState::removeTouchedPointerFromWindow(
41 int32_t pointerId, const sp<android::gui::WindowInfoHandle>& windowHandle) {
42 for (TouchedWindow& touchedWindow : windows) {
43 if (touchedWindow.windowHandle == windowHandle) {
44 touchedWindow.pointerIds.clearBit(pointerId);
45 return;
46 }
47 }
48}
49
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000050void TouchState::clearHoveringPointers() {
51 for (TouchedWindow& touchedWindow : windows) {
52 touchedWindow.clearHoveringPointers();
53 }
54}
55
56void TouchState::clearWindowsWithoutPointers() {
57 std::erase_if(windows, [](const TouchedWindow& w) {
58 return w.pointerIds.isEmpty() && !w.hasHoveringPointers();
59 });
60}
61
Siarhei Vishniakou253f4642022-11-09 13:42:06 -080062void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
63 ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds,
64 std::optional<nsecs_t> eventTime) {
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -080065 for (TouchedWindow& touchedWindow : windows) {
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000066 // We do not compare windows by token here because two windows that share the same token
67 // may have a different transform
Garfield Tane84e6f92019-08-29 17:28:41 -070068 if (touchedWindow.windowHandle == windowHandle) {
69 touchedWindow.targetFlags |= targetFlags;
Siarhei Vishniakou253f4642022-11-09 13:42:06 -080070 if (targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
71 touchedWindow.targetFlags.clear(InputTarget::Flags::DISPATCH_AS_IS);
Garfield Tane84e6f92019-08-29 17:28:41 -070072 }
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000073 // For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have
74 // downTime set initially. Need to update existing window when an pointer is down for
75 // the window.
Garfield Tane84e6f92019-08-29 17:28:41 -070076 touchedWindow.pointerIds.value |= pointerIds.value;
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000077 if (!touchedWindow.firstDownTimeInTarget.has_value()) {
78 touchedWindow.firstDownTimeInTarget = eventTime;
79 }
Garfield Tane84e6f92019-08-29 17:28:41 -070080 return;
81 }
82 }
Garfield Tane84e6f92019-08-29 17:28:41 -070083 TouchedWindow touchedWindow;
84 touchedWindow.windowHandle = windowHandle;
85 touchedWindow.targetFlags = targetFlags;
86 touchedWindow.pointerIds = pointerIds;
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000087 touchedWindow.firstDownTimeInTarget = eventTime;
Garfield Tane84e6f92019-08-29 17:28:41 -070088 windows.push_back(touchedWindow);
89}
90
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000091void TouchState::addHoveringPointerToWindow(const sp<WindowInfoHandle>& windowHandle,
92 int32_t hoveringDeviceId, int32_t hoveringPointerId) {
93 for (TouchedWindow& touchedWindow : windows) {
94 if (touchedWindow.windowHandle == windowHandle) {
95 touchedWindow.addHoveringPointer(hoveringDeviceId, hoveringPointerId);
96 return;
97 }
98 }
99
100 TouchedWindow touchedWindow;
101 touchedWindow.windowHandle = windowHandle;
102 touchedWindow.addHoveringPointer(hoveringDeviceId, hoveringPointerId);
103 windows.push_back(touchedWindow);
104}
105
Garfield Tane84e6f92019-08-29 17:28:41 -0700106void TouchState::removeWindowByToken(const sp<IBinder>& token) {
107 for (size_t i = 0; i < windows.size(); i++) {
108 if (windows[i].windowHandle->getToken() == token) {
109 windows.erase(windows.begin() + i);
110 return;
111 }
112 }
113}
114
115void TouchState::filterNonAsIsTouchWindows() {
116 for (size_t i = 0; i < windows.size();) {
117 TouchedWindow& window = windows[i];
Siarhei Vishniakou253f4642022-11-09 13:42:06 -0800118 if (window.targetFlags.any(InputTarget::Flags::DISPATCH_AS_IS |
119 InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
120 window.targetFlags.clear(InputTarget::DISPATCH_MASK);
121 window.targetFlags |= InputTarget::Flags::DISPATCH_AS_IS;
Garfield Tane84e6f92019-08-29 17:28:41 -0700122 i += 1;
123 } else {
124 windows.erase(windows.begin() + i);
125 }
126 }
127}
128
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000129void TouchState::cancelPointersForWindowsExcept(const BitSet32 pointerIds,
130 const sp<IBinder>& token) {
131 if (pointerIds.isEmpty()) return;
132 std::for_each(windows.begin(), windows.end(), [&pointerIds, &token](TouchedWindow& w) {
133 if (w.windowHandle->getToken() != token) {
134 w.pointerIds &= BitSet32(~pointerIds.value);
135 }
136 });
137 std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
138}
139
140void TouchState::cancelPointersForNonPilferingWindows(const BitSet32 pointerIds) {
141 if (pointerIds.isEmpty()) return;
142 std::for_each(windows.begin(), windows.end(), [&pointerIds](TouchedWindow& w) {
143 if (!w.isPilferingPointers) {
144 w.pointerIds &= BitSet32(~pointerIds.value);
145 }
146 });
147 std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
148}
149
chaviw98318de2021-05-19 16:45:23 -0500150sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700151 for (size_t i = 0; i < windows.size(); i++) {
152 const TouchedWindow& window = windows[i];
Siarhei Vishniakou253f4642022-11-09 13:42:06 -0800153 if (window.targetFlags.test(InputTarget::Flags::FOREGROUND)) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700154 return window.windowHandle;
155 }
156 }
157 return nullptr;
158}
159
160bool TouchState::isSlippery() const {
161 // Must have exactly one foreground window.
162 bool haveSlipperyForegroundWindow = false;
163 for (const TouchedWindow& window : windows) {
Siarhei Vishniakou253f4642022-11-09 13:42:06 -0800164 if (window.targetFlags.test(InputTarget::Flags::FOREGROUND)) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700165 if (haveSlipperyForegroundWindow ||
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800166 !window.windowHandle->getInfo()->inputConfig.test(
167 WindowInfo::InputConfig::SLIPPERY)) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700168 return false;
169 }
170 haveSlipperyForegroundWindow = true;
171 }
172 }
173 return haveSlipperyForegroundWindow;
174}
175
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000176sp<WindowInfoHandle> TouchState::getWallpaperWindow() const {
177 for (size_t i = 0; i < windows.size(); i++) {
178 const TouchedWindow& window = windows[i];
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800179 if (window.windowHandle->getInfo()->inputConfig.test(
180 gui::WindowInfo::InputConfig::IS_WALLPAPER)) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000181 return window.windowHandle;
182 }
183 }
184 return nullptr;
185}
186
Siarhei Vishniakou0026b4c2022-11-10 19:33:29 -0800187const TouchedWindow& TouchState::getTouchedWindow(const sp<WindowInfoHandle>& windowHandle) const {
188 auto it = std::find_if(windows.begin(), windows.end(),
189 [&](const TouchedWindow& w) { return w.windowHandle == windowHandle; });
190 LOG_ALWAYS_FATAL_IF(it == windows.end(), "Could not find %s", windowHandle->getName().c_str());
191 return *it;
192}
193
Siarhei Vishniakou3ad385b2022-11-04 10:09:53 -0700194bool TouchState::isDown() const {
195 return std::any_of(windows.begin(), windows.end(),
196 [](const TouchedWindow& window) { return !window.pointerIds.isEmpty(); });
197}
198
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000199std::set<sp<WindowInfoHandle>> TouchState::getWindowsWithHoveringPointer(int32_t hoveringDeviceId,
200 int32_t pointerId) const {
201 std::set<sp<WindowInfoHandle>> out;
202 for (const TouchedWindow& window : windows) {
203 if (window.hasHoveringPointer(hoveringDeviceId, pointerId)) {
204 out.insert(window.windowHandle);
205 }
206 }
207 return out;
208}
209
210void TouchState::removeHoveringPointer(int32_t hoveringDeviceId, int32_t hoveringPointerId) {
211 for (TouchedWindow& window : windows) {
212 window.removeHoveringPointer(hoveringDeviceId, hoveringPointerId);
213 }
214 std::erase_if(windows, [](const TouchedWindow& w) {
215 return w.pointerIds.isEmpty() && !w.hasHoveringPointers();
216 });
217}
218
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800219std::string TouchState::dump() const {
220 std::string out;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800221 out += StringPrintf("deviceId=%d, source=%s\n", deviceId,
222 inputEventSourceToString(source).c_str());
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800223 if (!windows.empty()) {
224 out += " Windows:\n";
225 for (size_t i = 0; i < windows.size(); i++) {
226 const TouchedWindow& touchedWindow = windows[i];
227 out += StringPrintf(" %zu : ", i) + touchedWindow.dump();
228 }
229 } else {
230 out += " Windows: <none>\n";
231 }
232 return out;
233}
234
Garfield Tane84e6f92019-08-29 17:28:41 -0700235} // namespace android::inputdispatcher