1 /*
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
17 #include <input/InputWindow.h>
18
19 #include "InputTarget.h"
20
21 #include "TouchState.h"
22
23 using android::InputWindowHandle;
24
25 namespace android::inputdispatcher {
26
TouchState()27 TouchState::TouchState()
28 : down(false), split(false), deviceId(-1), source(0), displayId(ADISPLAY_ID_NONE) {}
29
~TouchState()30 TouchState::~TouchState() {}
31
reset()32 void TouchState::reset() {
33 down = false;
34 split = false;
35 deviceId = -1;
36 source = 0;
37 displayId = ADISPLAY_ID_NONE;
38 windows.clear();
39 portalWindows.clear();
40 gestureMonitors.clear();
41 }
42
copyFrom(const TouchState & other)43 void TouchState::copyFrom(const TouchState& other) {
44 down = other.down;
45 split = other.split;
46 deviceId = other.deviceId;
47 source = other.source;
48 displayId = other.displayId;
49 windows = other.windows;
50 portalWindows = other.portalWindows;
51 gestureMonitors = other.gestureMonitors;
52 }
53
addOrUpdateWindow(const sp<InputWindowHandle> & windowHandle,int32_t targetFlags,BitSet32 pointerIds)54 void TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags,
55 BitSet32 pointerIds) {
56 if (targetFlags & InputTarget::FLAG_SPLIT) {
57 split = true;
58 }
59
60 for (size_t i = 0; i < windows.size(); i++) {
61 TouchedWindow& touchedWindow = windows[i];
62 if (touchedWindow.windowHandle == windowHandle) {
63 touchedWindow.targetFlags |= targetFlags;
64 if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
65 touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
66 }
67 touchedWindow.pointerIds.value |= pointerIds.value;
68 return;
69 }
70 }
71
72 TouchedWindow touchedWindow;
73 touchedWindow.windowHandle = windowHandle;
74 touchedWindow.targetFlags = targetFlags;
75 touchedWindow.pointerIds = pointerIds;
76 windows.push_back(touchedWindow);
77 }
78
addPortalWindow(const sp<InputWindowHandle> & windowHandle)79 void TouchState::addPortalWindow(const sp<InputWindowHandle>& windowHandle) {
80 size_t numWindows = portalWindows.size();
81 for (size_t i = 0; i < numWindows; i++) {
82 if (portalWindows[i] == windowHandle) {
83 return;
84 }
85 }
86 portalWindows.push_back(windowHandle);
87 }
88
addGestureMonitors(const std::vector<TouchedMonitor> & newMonitors)89 void TouchState::addGestureMonitors(const std::vector<TouchedMonitor>& newMonitors) {
90 const size_t newSize = gestureMonitors.size() + newMonitors.size();
91 gestureMonitors.reserve(newSize);
92 gestureMonitors.insert(std::end(gestureMonitors), std::begin(newMonitors),
93 std::end(newMonitors));
94 }
95
removeWindow(const sp<InputWindowHandle> & windowHandle)96 void TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) {
97 for (size_t i = 0; i < windows.size(); i++) {
98 if (windows[i].windowHandle == windowHandle) {
99 windows.erase(windows.begin() + i);
100 return;
101 }
102 }
103 }
104
removeWindowByToken(const sp<IBinder> & token)105 void TouchState::removeWindowByToken(const sp<IBinder>& token) {
106 for (size_t i = 0; i < windows.size(); i++) {
107 if (windows[i].windowHandle->getToken() == token) {
108 windows.erase(windows.begin() + i);
109 return;
110 }
111 }
112 }
113
filterNonAsIsTouchWindows()114 void TouchState::filterNonAsIsTouchWindows() {
115 for (size_t i = 0; i < windows.size();) {
116 TouchedWindow& window = windows[i];
117 if (window.targetFlags &
118 (InputTarget::FLAG_DISPATCH_AS_IS | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
119 window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
120 window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
121 i += 1;
122 } else {
123 windows.erase(windows.begin() + i);
124 }
125 }
126 }
127
filterNonMonitors()128 void TouchState::filterNonMonitors() {
129 windows.clear();
130 portalWindows.clear();
131 }
132
getFirstForegroundWindowHandle() const133 sp<InputWindowHandle> TouchState::getFirstForegroundWindowHandle() const {
134 for (size_t i = 0; i < windows.size(); i++) {
135 const TouchedWindow& window = windows[i];
136 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
137 return window.windowHandle;
138 }
139 }
140 return nullptr;
141 }
142
isSlippery() const143 bool TouchState::isSlippery() const {
144 // Must have exactly one foreground window.
145 bool haveSlipperyForegroundWindow = false;
146 for (const TouchedWindow& window : windows) {
147 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
148 if (haveSlipperyForegroundWindow ||
149 !(window.windowHandle->getInfo()->layoutParamsFlags &
150 InputWindowInfo::FLAG_SLIPPERY)) {
151 return false;
152 }
153 haveSlipperyForegroundWindow = true;
154 }
155 }
156 return haveSlipperyForegroundWindow;
157 }
158
159 } // namespace android::inputdispatcher
160