blob: f5b7cb88d9abe2342bdef1ff461e241820fc68cc [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 for (size_t i = 0; i < windows.size(); i++) {
35 TouchedWindow& touchedWindow = windows[i];
36 if (touchedWindow.windowHandle == windowHandle) {
37 touchedWindow.targetFlags |= targetFlags;
38 if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
39 touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
40 }
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000041 // For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have
42 // downTime set initially. Need to update existing window when an pointer is down for
43 // the window.
Garfield Tane84e6f92019-08-29 17:28:41 -070044 touchedWindow.pointerIds.value |= pointerIds.value;
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000045 if (!touchedWindow.firstDownTimeInTarget.has_value()) {
46 touchedWindow.firstDownTimeInTarget = eventTime;
47 }
Garfield Tane84e6f92019-08-29 17:28:41 -070048 return;
49 }
50 }
51
52 TouchedWindow touchedWindow;
53 touchedWindow.windowHandle = windowHandle;
54 touchedWindow.targetFlags = targetFlags;
55 touchedWindow.pointerIds = pointerIds;
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000056 touchedWindow.firstDownTimeInTarget = eventTime;
Garfield Tane84e6f92019-08-29 17:28:41 -070057 windows.push_back(touchedWindow);
58}
59
Garfield Tane84e6f92019-08-29 17:28:41 -070060void TouchState::removeWindowByToken(const sp<IBinder>& token) {
61 for (size_t i = 0; i < windows.size(); i++) {
62 if (windows[i].windowHandle->getToken() == token) {
63 windows.erase(windows.begin() + i);
64 return;
65 }
66 }
67}
68
69void TouchState::filterNonAsIsTouchWindows() {
70 for (size_t i = 0; i < windows.size();) {
71 TouchedWindow& window = windows[i];
72 if (window.targetFlags &
73 (InputTarget::FLAG_DISPATCH_AS_IS | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
74 window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
75 window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
76 i += 1;
77 } else {
78 windows.erase(windows.begin() + i);
79 }
80 }
81}
82
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000083void TouchState::cancelPointersForWindowsExcept(const BitSet32 pointerIds,
84 const sp<IBinder>& token) {
85 if (pointerIds.isEmpty()) return;
86 std::for_each(windows.begin(), windows.end(), [&pointerIds, &token](TouchedWindow& w) {
87 if (w.windowHandle->getToken() != token) {
88 w.pointerIds &= BitSet32(~pointerIds.value);
89 }
90 });
91 std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
92}
93
94void TouchState::cancelPointersForNonPilferingWindows(const BitSet32 pointerIds) {
95 if (pointerIds.isEmpty()) return;
96 std::for_each(windows.begin(), windows.end(), [&pointerIds](TouchedWindow& w) {
97 if (!w.isPilferingPointers) {
98 w.pointerIds &= BitSet32(~pointerIds.value);
99 }
100 });
101 std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
102}
103
chaviw98318de2021-05-19 16:45:23 -0500104sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700105 for (size_t i = 0; i < windows.size(); i++) {
106 const TouchedWindow& window = windows[i];
107 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
108 return window.windowHandle;
109 }
110 }
111 return nullptr;
112}
113
114bool TouchState::isSlippery() const {
115 // Must have exactly one foreground window.
116 bool haveSlipperyForegroundWindow = false;
117 for (const TouchedWindow& window : windows) {
118 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
119 if (haveSlipperyForegroundWindow ||
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800120 !window.windowHandle->getInfo()->inputConfig.test(
121 WindowInfo::InputConfig::SLIPPERY)) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700122 return false;
123 }
124 haveSlipperyForegroundWindow = true;
125 }
126 }
127 return haveSlipperyForegroundWindow;
128}
129
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000130sp<WindowInfoHandle> TouchState::getWallpaperWindow() const {
131 for (size_t i = 0; i < windows.size(); i++) {
132 const TouchedWindow& window = windows[i];
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800133 if (window.windowHandle->getInfo()->inputConfig.test(
134 gui::WindowInfo::InputConfig::IS_WALLPAPER)) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000135 return window.windowHandle;
136 }
137 }
138 return nullptr;
139}
140
Siarhei Vishniakou3ad385b2022-11-04 10:09:53 -0700141bool TouchState::isDown() const {
142 return std::any_of(windows.begin(), windows.end(),
143 [](const TouchedWindow& window) { return !window.pointerIds.isEmpty(); });
144}
145
Garfield Tane84e6f92019-08-29 17:28:41 -0700146} // namespace android::inputdispatcher