blob: 4165f4934c3b8859fe982483c462a4e8e0bf7d0e [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
17#include <input/InputWindow.h>
18
19#include "InputTarget.h"
20
21#include "TouchState.h"
22
23using android::InputWindowHandle;
24
25namespace android::inputdispatcher {
26
27TouchState::TouchState()
28 : down(false), split(false), deviceId(-1), source(0), displayId(ADISPLAY_ID_NONE) {}
29
30TouchState::~TouchState() {}
31
32void 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
43void 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;
arthurhungb89ccb02020-12-30 16:19:01 +080052 dragHoverWindowHandle = other.dragHoverWindowHandle;
53 dragWindow = other.dragWindow;
Garfield Tane84e6f92019-08-29 17:28:41 -070054}
55
56void TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags,
57 BitSet32 pointerIds) {
58 if (targetFlags & InputTarget::FLAG_SPLIT) {
59 split = true;
60 }
61
62 for (size_t i = 0; i < windows.size(); i++) {
63 TouchedWindow& touchedWindow = windows[i];
64 if (touchedWindow.windowHandle == windowHandle) {
65 touchedWindow.targetFlags |= targetFlags;
66 if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
67 touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
68 }
69 touchedWindow.pointerIds.value |= pointerIds.value;
70 return;
71 }
72 }
73
74 TouchedWindow touchedWindow;
75 touchedWindow.windowHandle = windowHandle;
76 touchedWindow.targetFlags = targetFlags;
77 touchedWindow.pointerIds = pointerIds;
78 windows.push_back(touchedWindow);
79}
80
81void TouchState::addPortalWindow(const sp<InputWindowHandle>& windowHandle) {
82 size_t numWindows = portalWindows.size();
83 for (size_t i = 0; i < numWindows; i++) {
84 if (portalWindows[i] == windowHandle) {
85 return;
86 }
87 }
88 portalWindows.push_back(windowHandle);
89}
90
91void TouchState::addGestureMonitors(const std::vector<TouchedMonitor>& newMonitors) {
92 const size_t newSize = gestureMonitors.size() + newMonitors.size();
93 gestureMonitors.reserve(newSize);
94 gestureMonitors.insert(std::end(gestureMonitors), std::begin(newMonitors),
95 std::end(newMonitors));
96}
97
Garfield Tane84e6f92019-08-29 17:28:41 -070098void TouchState::removeWindowByToken(const sp<IBinder>& token) {
99 for (size_t i = 0; i < windows.size(); i++) {
100 if (windows[i].windowHandle->getToken() == token) {
101 windows.erase(windows.begin() + i);
102 return;
103 }
104 }
105}
106
107void TouchState::filterNonAsIsTouchWindows() {
108 for (size_t i = 0; i < windows.size();) {
109 TouchedWindow& window = windows[i];
110 if (window.targetFlags &
111 (InputTarget::FLAG_DISPATCH_AS_IS | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
112 window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
113 window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
114 i += 1;
115 } else {
116 windows.erase(windows.begin() + i);
117 }
118 }
119}
120
121void TouchState::filterNonMonitors() {
122 windows.clear();
123 portalWindows.clear();
124}
125
126sp<InputWindowHandle> TouchState::getFirstForegroundWindowHandle() const {
127 for (size_t i = 0; i < windows.size(); i++) {
128 const TouchedWindow& window = windows[i];
129 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
130 return window.windowHandle;
131 }
132 }
133 return nullptr;
134}
135
136bool TouchState::isSlippery() const {
137 // Must have exactly one foreground window.
138 bool haveSlipperyForegroundWindow = false;
139 for (const TouchedWindow& window : windows) {
140 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
141 if (haveSlipperyForegroundWindow ||
Michael Wright44753b12020-07-08 13:48:11 +0100142 !window.windowHandle->getInfo()->flags.test(InputWindowInfo::Flag::SLIPPERY)) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700143 return false;
144 }
145 haveSlipperyForegroundWindow = true;
146 }
147 }
148 return haveSlipperyForegroundWindow;
149}
150
151} // namespace android::inputdispatcher