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
removeWindowByToken(const sp<IBinder> & token)96 void TouchState::removeWindowByToken(const sp<IBinder>& token) {
97 for (size_t i = 0; i < windows.size(); i++) {
98 if (windows[i].windowHandle->getToken() == token) {
99 windows.erase(windows.begin() + i);
100 return;
101 }
102 }
103 }
104
filterNonAsIsTouchWindows()105 void TouchState::filterNonAsIsTouchWindows() {
106 for (size_t i = 0; i < windows.size();) {
107 TouchedWindow& window = windows[i];
108 if (window.targetFlags &
109 (InputTarget::FLAG_DISPATCH_AS_IS | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
110 window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
111 window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
112 i += 1;
113 } else {
114 windows.erase(windows.begin() + i);
115 }
116 }
117 }
118
filterNonMonitors()119 void TouchState::filterNonMonitors() {
120 windows.clear();
121 portalWindows.clear();
122 }
123
getFirstForegroundWindowHandle() const124 sp<InputWindowHandle> TouchState::getFirstForegroundWindowHandle() const {
125 for (size_t i = 0; i < windows.size(); i++) {
126 const TouchedWindow& window = windows[i];
127 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
128 return window.windowHandle;
129 }
130 }
131 return nullptr;
132 }
133
isSlippery() const134 bool TouchState::isSlippery() const {
135 // Must have exactly one foreground window.
136 bool haveSlipperyForegroundWindow = false;
137 for (const TouchedWindow& window : windows) {
138 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
139 if (haveSlipperyForegroundWindow ||
140 !(window.windowHandle->getInfo()->layoutParamsFlags &
141 InputWindowInfo::FLAG_SLIPPERY)) {
142 return false;
143 }
144 haveSlipperyForegroundWindow = true;
145 }
146 }
147 return haveSlipperyForegroundWindow;
148 }
149
150 } // namespace android::inputdispatcher
151