• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <gui/WindowInfo.h>
18 
19 #include "InputTarget.h"
20 
21 #include "TouchState.h"
22 
23 using android::gui::WindowInfo;
24 using android::gui::WindowInfoHandle;
25 
26 namespace android::inputdispatcher {
27 
reset()28 void TouchState::reset() {
29     *this = TouchState();
30 }
31 
addOrUpdateWindow(const sp<WindowInfoHandle> & windowHandle,int32_t targetFlags,BitSet32 pointerIds)32 void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, int32_t targetFlags,
33                                    BitSet32 pointerIds) {
34     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             }
45             touchedWindow.pointerIds.value |= pointerIds.value;
46             return;
47         }
48     }
49 
50     if (preventNewTargets) return; // Don't add new TouchedWindows.
51 
52     TouchedWindow touchedWindow;
53     touchedWindow.windowHandle = windowHandle;
54     touchedWindow.targetFlags = targetFlags;
55     touchedWindow.pointerIds = pointerIds;
56     windows.push_back(touchedWindow);
57 }
58 
removeWindowByToken(const sp<IBinder> & token)59 void TouchState::removeWindowByToken(const sp<IBinder>& token) {
60     for (size_t i = 0; i < windows.size(); i++) {
61         if (windows[i].windowHandle->getToken() == token) {
62             windows.erase(windows.begin() + i);
63             return;
64         }
65     }
66 }
67 
filterNonAsIsTouchWindows()68 void TouchState::filterNonAsIsTouchWindows() {
69     for (size_t i = 0; i < windows.size();) {
70         TouchedWindow& window = windows[i];
71         if (window.targetFlags &
72             (InputTarget::FLAG_DISPATCH_AS_IS | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
73             window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
74             window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
75             i += 1;
76         } else {
77             windows.erase(windows.begin() + i);
78         }
79     }
80 }
81 
filterWindowsExcept(const sp<IBinder> & token)82 void TouchState::filterWindowsExcept(const sp<IBinder>& token) {
83     std::erase_if(windows,
84                   [&token](const TouchedWindow& w) { return w.windowHandle->getToken() != token; });
85 }
86 
getFirstForegroundWindowHandle() const87 sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const {
88     for (size_t i = 0; i < windows.size(); i++) {
89         const TouchedWindow& window = windows[i];
90         if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
91             return window.windowHandle;
92         }
93     }
94     return nullptr;
95 }
96 
isSlippery() const97 bool TouchState::isSlippery() const {
98     // Must have exactly one foreground window.
99     bool haveSlipperyForegroundWindow = false;
100     for (const TouchedWindow& window : windows) {
101         if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
102             if (haveSlipperyForegroundWindow ||
103                 !window.windowHandle->getInfo()->inputConfig.test(
104                         WindowInfo::InputConfig::SLIPPERY)) {
105                 return false;
106             }
107             haveSlipperyForegroundWindow = true;
108         }
109     }
110     return haveSlipperyForegroundWindow;
111 }
112 
getWallpaperWindow() const113 sp<WindowInfoHandle> TouchState::getWallpaperWindow() const {
114     for (size_t i = 0; i < windows.size(); i++) {
115         const TouchedWindow& window = windows[i];
116         if (window.windowHandle->getInfo()->inputConfig.test(
117                     gui::WindowInfo::InputConfig::IS_WALLPAPER)) {
118             return window.windowHandle;
119         }
120     }
121     return nullptr;
122 }
123 
getWindow(const sp<IBinder> & token) const124 sp<WindowInfoHandle> TouchState::getWindow(const sp<IBinder>& token) const {
125     for (const TouchedWindow& touchedWindow : windows) {
126         const auto& windowHandle = touchedWindow.windowHandle;
127         if (windowHandle->getToken() == token) {
128             return windowHandle;
129         }
130     }
131     return nullptr;
132 }
133 
134 } // namespace android::inputdispatcher
135