blob: 0cc2c6da9bdf596a1c062820bf22f65817763cb8 [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 Vishniakou6e1e9872022-11-08 17:51:35 -080023using android::base::StringPrintf;
chaviw98318de2021-05-19 16:45:23 -050024using android::gui::WindowInfo;
25using android::gui::WindowInfoHandle;
Garfield Tane84e6f92019-08-29 17:28:41 -070026
27namespace android::inputdispatcher {
28
Garfield Tane84e6f92019-08-29 17:28:41 -070029void TouchState::reset() {
Prabir Pradhane680f9b2022-02-04 04:24:00 -080030 *this = TouchState();
Garfield Tane84e6f92019-08-29 17:28:41 -070031}
32
chaviw98318de2021-05-19 16:45:23 -050033void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, int32_t targetFlags,
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000034 BitSet32 pointerIds, std::optional<nsecs_t> eventTime) {
Garfield Tane84e6f92019-08-29 17:28:41 -070035 for (size_t i = 0; i < windows.size(); i++) {
36 TouchedWindow& touchedWindow = windows[i];
37 if (touchedWindow.windowHandle == windowHandle) {
38 touchedWindow.targetFlags |= targetFlags;
39 if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
40 touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
41 }
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000042 // For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have
43 // downTime set initially. Need to update existing window when an pointer is down for
44 // the window.
Garfield Tane84e6f92019-08-29 17:28:41 -070045 touchedWindow.pointerIds.value |= pointerIds.value;
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000046 if (!touchedWindow.firstDownTimeInTarget.has_value()) {
47 touchedWindow.firstDownTimeInTarget = eventTime;
48 }
Garfield Tane84e6f92019-08-29 17:28:41 -070049 return;
50 }
51 }
52
53 TouchedWindow touchedWindow;
54 touchedWindow.windowHandle = windowHandle;
55 touchedWindow.targetFlags = targetFlags;
56 touchedWindow.pointerIds = pointerIds;
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000057 touchedWindow.firstDownTimeInTarget = eventTime;
Garfield Tane84e6f92019-08-29 17:28:41 -070058 windows.push_back(touchedWindow);
59}
60
Garfield Tane84e6f92019-08-29 17:28:41 -070061void TouchState::removeWindowByToken(const sp<IBinder>& token) {
62 for (size_t i = 0; i < windows.size(); i++) {
63 if (windows[i].windowHandle->getToken() == token) {
64 windows.erase(windows.begin() + i);
65 return;
66 }
67 }
68}
69
70void TouchState::filterNonAsIsTouchWindows() {
71 for (size_t i = 0; i < windows.size();) {
72 TouchedWindow& window = windows[i];
73 if (window.targetFlags &
74 (InputTarget::FLAG_DISPATCH_AS_IS | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
75 window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
76 window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
77 i += 1;
78 } else {
79 windows.erase(windows.begin() + i);
80 }
81 }
82}
83
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000084void TouchState::cancelPointersForWindowsExcept(const BitSet32 pointerIds,
85 const sp<IBinder>& token) {
86 if (pointerIds.isEmpty()) return;
87 std::for_each(windows.begin(), windows.end(), [&pointerIds, &token](TouchedWindow& w) {
88 if (w.windowHandle->getToken() != token) {
89 w.pointerIds &= BitSet32(~pointerIds.value);
90 }
91 });
92 std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
93}
94
95void TouchState::cancelPointersForNonPilferingWindows(const BitSet32 pointerIds) {
96 if (pointerIds.isEmpty()) return;
97 std::for_each(windows.begin(), windows.end(), [&pointerIds](TouchedWindow& w) {
98 if (!w.isPilferingPointers) {
99 w.pointerIds &= BitSet32(~pointerIds.value);
100 }
101 });
102 std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
103}
104
chaviw98318de2021-05-19 16:45:23 -0500105sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700106 for (size_t i = 0; i < windows.size(); i++) {
107 const TouchedWindow& window = windows[i];
108 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
109 return window.windowHandle;
110 }
111 }
112 return nullptr;
113}
114
115bool TouchState::isSlippery() const {
116 // Must have exactly one foreground window.
117 bool haveSlipperyForegroundWindow = false;
118 for (const TouchedWindow& window : windows) {
119 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
120 if (haveSlipperyForegroundWindow ||
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800121 !window.windowHandle->getInfo()->inputConfig.test(
122 WindowInfo::InputConfig::SLIPPERY)) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700123 return false;
124 }
125 haveSlipperyForegroundWindow = true;
126 }
127 }
128 return haveSlipperyForegroundWindow;
129}
130
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000131sp<WindowInfoHandle> TouchState::getWallpaperWindow() const {
132 for (size_t i = 0; i < windows.size(); i++) {
133 const TouchedWindow& window = windows[i];
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800134 if (window.windowHandle->getInfo()->inputConfig.test(
135 gui::WindowInfo::InputConfig::IS_WALLPAPER)) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000136 return window.windowHandle;
137 }
138 }
139 return nullptr;
140}
141
Siarhei Vishniakou3ad385b2022-11-04 10:09:53 -0700142bool TouchState::isDown() const {
143 return std::any_of(windows.begin(), windows.end(),
144 [](const TouchedWindow& window) { return !window.pointerIds.isEmpty(); });
145}
146
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800147std::string TouchState::dump() const {
148 std::string out;
149 out += StringPrintf("deviceId=%d, source=0x%08x\n", deviceId, source);
150 if (!windows.empty()) {
151 out += " Windows:\n";
152 for (size_t i = 0; i < windows.size(); i++) {
153 const TouchedWindow& touchedWindow = windows[i];
154 out += StringPrintf(" %zu : ", i) + touchedWindow.dump();
155 }
156 } else {
157 out += " Windows: <none>\n";
158 }
159 return out;
160}
161
Garfield Tane84e6f92019-08-29 17:28:41 -0700162} // namespace android::inputdispatcher