blob: cf0c38af33d516ee4cb8b0d2caeb4c85c8c01afb [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
chaviw98318de2021-05-19 16:45:23 -050017#include <gui/WindowInfo.h>
Garfield Tane84e6f92019-08-29 17:28:41 -070018
19#include "InputTarget.h"
20
21#include "TouchState.h"
22
chaviw98318de2021-05-19 16:45:23 -050023using android::gui::WindowInfo;
24using android::gui::WindowInfoHandle;
Garfield Tane84e6f92019-08-29 17:28:41 -070025
26namespace android::inputdispatcher {
27
Garfield Tane84e6f92019-08-29 17:28:41 -070028void TouchState::reset() {
Prabir Pradhane680f9b2022-02-04 04:24:00 -080029 *this = TouchState();
Garfield Tane84e6f92019-08-29 17:28:41 -070030}
31
chaviw98318de2021-05-19 16:45:23 -050032void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, int32_t targetFlags,
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000033 BitSet32 pointerIds, std::optional<nsecs_t> eventTime) {
Garfield Tane84e6f92019-08-29 17:28:41 -070034 if (targetFlags & InputTarget::FLAG_SPLIT) {
35 split = true;
36 }
37
38 for (size_t i = 0; i < windows.size(); i++) {
39 TouchedWindow& touchedWindow = windows[i];
40 if (touchedWindow.windowHandle == windowHandle) {
41 touchedWindow.targetFlags |= targetFlags;
42 if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
43 touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
44 }
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000045 // For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have
46 // downTime set initially. Need to update existing window when an pointer is down for
47 // the window.
Garfield Tane84e6f92019-08-29 17:28:41 -070048 touchedWindow.pointerIds.value |= pointerIds.value;
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000049 if (!touchedWindow.firstDownTimeInTarget.has_value()) {
50 touchedWindow.firstDownTimeInTarget = eventTime;
51 }
Garfield Tane84e6f92019-08-29 17:28:41 -070052 return;
53 }
54 }
55
56 TouchedWindow touchedWindow;
57 touchedWindow.windowHandle = windowHandle;
58 touchedWindow.targetFlags = targetFlags;
59 touchedWindow.pointerIds = pointerIds;
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000060 touchedWindow.firstDownTimeInTarget = eventTime;
Garfield Tane84e6f92019-08-29 17:28:41 -070061 windows.push_back(touchedWindow);
62}
63
Garfield Tane84e6f92019-08-29 17:28:41 -070064void TouchState::removeWindowByToken(const sp<IBinder>& token) {
65 for (size_t i = 0; i < windows.size(); i++) {
66 if (windows[i].windowHandle->getToken() == token) {
67 windows.erase(windows.begin() + i);
68 return;
69 }
70 }
71}
72
73void TouchState::filterNonAsIsTouchWindows() {
74 for (size_t i = 0; i < windows.size();) {
75 TouchedWindow& window = windows[i];
76 if (window.targetFlags &
77 (InputTarget::FLAG_DISPATCH_AS_IS | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
78 window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
79 window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
80 i += 1;
81 } else {
82 windows.erase(windows.begin() + i);
83 }
84 }
85}
86
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000087void TouchState::cancelPointersForWindowsExcept(const BitSet32 pointerIds,
88 const sp<IBinder>& token) {
89 if (pointerIds.isEmpty()) return;
90 std::for_each(windows.begin(), windows.end(), [&pointerIds, &token](TouchedWindow& w) {
91 if (w.windowHandle->getToken() != token) {
92 w.pointerIds &= BitSet32(~pointerIds.value);
93 }
94 });
95 std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
96}
97
98void TouchState::cancelPointersForNonPilferingWindows(const BitSet32 pointerIds) {
99 if (pointerIds.isEmpty()) return;
100 std::for_each(windows.begin(), windows.end(), [&pointerIds](TouchedWindow& w) {
101 if (!w.isPilferingPointers) {
102 w.pointerIds &= BitSet32(~pointerIds.value);
103 }
104 });
105 std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
106}
107
Prabir Pradhan07e05b62021-11-19 03:57:24 -0800108void TouchState::filterWindowsExcept(const sp<IBinder>& token) {
Siarhei Vishniakouf47c339e2021-12-30 11:22:26 -0800109 std::erase_if(windows,
110 [&token](const TouchedWindow& w) { return w.windowHandle->getToken() != token; });
Garfield Tane84e6f92019-08-29 17:28:41 -0700111}
112
chaviw98318de2021-05-19 16:45:23 -0500113sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700114 for (size_t i = 0; i < windows.size(); i++) {
115 const TouchedWindow& window = windows[i];
116 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
117 return window.windowHandle;
118 }
119 }
120 return nullptr;
121}
122
123bool TouchState::isSlippery() const {
124 // Must have exactly one foreground window.
125 bool haveSlipperyForegroundWindow = false;
126 for (const TouchedWindow& window : windows) {
127 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
128 if (haveSlipperyForegroundWindow ||
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800129 !window.windowHandle->getInfo()->inputConfig.test(
130 WindowInfo::InputConfig::SLIPPERY)) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700131 return false;
132 }
133 haveSlipperyForegroundWindow = true;
134 }
135 }
136 return haveSlipperyForegroundWindow;
137}
138
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000139sp<WindowInfoHandle> TouchState::getWallpaperWindow() const {
140 for (size_t i = 0; i < windows.size(); i++) {
141 const TouchedWindow& window = windows[i];
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800142 if (window.windowHandle->getInfo()->inputConfig.test(
143 gui::WindowInfo::InputConfig::IS_WALLPAPER)) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000144 return window.windowHandle;
145 }
146 }
147 return nullptr;
148}
149
Prabir Pradhan07e05b62021-11-19 03:57:24 -0800150sp<WindowInfoHandle> TouchState::getWindow(const sp<IBinder>& token) const {
151 for (const TouchedWindow& touchedWindow : windows) {
152 const auto& windowHandle = touchedWindow.windowHandle;
153 if (windowHandle->getToken() == token) {
154 return windowHandle;
155 }
156 }
157 return nullptr;
158}
159
Garfield Tane84e6f92019-08-29 17:28:41 -0700160} // namespace android::inputdispatcher