1 /*
2 * Copyright (C) 2010 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 #define LOG_TAG "PointerController"
18 //#define LOG_NDEBUG 0
19
20 // Log debug messages about pointer updates
21 #define DEBUG_POINTER_UPDATES 0
22
23 #include "PointerController.h"
24 #include "MouseCursorController.h"
25 #include "PointerControllerContext.h"
26 #include "TouchSpotController.h"
27
28 #include <log/log.h>
29
30 #include <SkBitmap.h>
31 #include <SkBlendMode.h>
32 #include <SkCanvas.h>
33 #include <SkColor.h>
34 #include <SkPaint.h>
35
36 namespace android {
37
38 // --- PointerController ---
39
create(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,const sp<SpriteController> & spriteController)40 std::shared_ptr<PointerController> PointerController::create(
41 const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
42 const sp<SpriteController>& spriteController) {
43 // using 'new' to access non-public constructor
44 std::shared_ptr<PointerController> controller = std::shared_ptr<PointerController>(
45 new PointerController(policy, looper, spriteController));
46
47 /*
48 * Now we need to hook up the constructed PointerController object to its callbacks.
49 *
50 * This must be executed after the constructor but before any other methods on PointerController
51 * in order to ensure that the fully constructed object is visible on the Looper thread, since
52 * that may be a different thread than where the PointerController is initially constructed.
53 *
54 * Unfortunately, this cannot be done as part of the constructor since we need to hand out
55 * weak_ptr's which themselves cannot be constructed until there's at least one shared_ptr.
56 */
57
58 controller->mContext.setHandlerController(controller);
59 controller->mContext.setCallbackController(controller);
60 return controller;
61 }
62
PointerController(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,const sp<SpriteController> & spriteController)63 PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
64 const sp<Looper>& looper,
65 const sp<SpriteController>& spriteController)
66 : mContext(policy, looper, spriteController, *this), mCursorController(mContext) {
67 std::scoped_lock lock(mLock);
68 mLocked.presentation = Presentation::SPOT;
69 }
70
getBounds(float * outMinX,float * outMinY,float * outMaxX,float * outMaxY) const71 bool PointerController::getBounds(float* outMinX, float* outMinY, float* outMaxX,
72 float* outMaxY) const {
73 return mCursorController.getBounds(outMinX, outMinY, outMaxX, outMaxY);
74 }
75
move(float deltaX,float deltaY)76 void PointerController::move(float deltaX, float deltaY) {
77 mCursorController.move(deltaX, deltaY);
78 }
79
setButtonState(int32_t buttonState)80 void PointerController::setButtonState(int32_t buttonState) {
81 mCursorController.setButtonState(buttonState);
82 }
83
getButtonState() const84 int32_t PointerController::getButtonState() const {
85 return mCursorController.getButtonState();
86 }
87
setPosition(float x,float y)88 void PointerController::setPosition(float x, float y) {
89 std::scoped_lock lock(mLock);
90 mCursorController.setPosition(x, y);
91 }
92
getPosition(float * outX,float * outY) const93 void PointerController::getPosition(float* outX, float* outY) const {
94 mCursorController.getPosition(outX, outY);
95 }
96
getDisplayId() const97 int32_t PointerController::getDisplayId() const {
98 return mCursorController.getDisplayId();
99 }
100
fade(Transition transition)101 void PointerController::fade(Transition transition) {
102 std::scoped_lock lock(mLock);
103 mCursorController.fade(transition);
104 }
105
unfade(Transition transition)106 void PointerController::unfade(Transition transition) {
107 std::scoped_lock lock(mLock);
108 mCursorController.unfade(transition);
109 }
110
setPresentation(Presentation presentation)111 void PointerController::setPresentation(Presentation presentation) {
112 std::scoped_lock lock(mLock);
113
114 if (mLocked.presentation == presentation) {
115 return;
116 }
117
118 mLocked.presentation = presentation;
119
120 if (!mCursorController.isViewportValid()) {
121 return;
122 }
123
124 if (presentation == Presentation::POINTER) {
125 mCursorController.getAdditionalMouseResources();
126 clearSpotsLocked();
127 }
128 }
129
setSpots(const PointerCoords * spotCoords,const uint32_t * spotIdToIndex,BitSet32 spotIdBits,int32_t displayId)130 void PointerController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
131 BitSet32 spotIdBits, int32_t displayId) {
132 std::scoped_lock lock(mLock);
133 auto it = mLocked.spotControllers.find(displayId);
134 if (it == mLocked.spotControllers.end()) {
135 mLocked.spotControllers.try_emplace(displayId, displayId, mContext);
136 }
137 mLocked.spotControllers.at(displayId).setSpots(spotCoords, spotIdToIndex, spotIdBits);
138 }
139
clearSpots()140 void PointerController::clearSpots() {
141 std::scoped_lock lock(mLock);
142 clearSpotsLocked();
143 }
144
clearSpotsLocked()145 void PointerController::clearSpotsLocked() REQUIRES(mLock) {
146 for (auto& [displayID, spotController] : mLocked.spotControllers) {
147 spotController.clearSpots();
148 }
149 }
150
setInactivityTimeout(InactivityTimeout inactivityTimeout)151 void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
152 mContext.setInactivityTimeout(inactivityTimeout);
153 }
154
reloadPointerResources()155 void PointerController::reloadPointerResources() {
156 std::scoped_lock lock(mLock);
157
158 for (auto& [displayID, spotController] : mLocked.spotControllers) {
159 spotController.reloadSpotResources();
160 }
161
162 if (mCursorController.resourcesLoaded()) {
163 bool getAdditionalMouseResources = false;
164 if (mLocked.presentation == PointerController::Presentation::POINTER) {
165 getAdditionalMouseResources = true;
166 }
167 mCursorController.reloadPointerResources(getAdditionalMouseResources);
168 }
169 }
170
setDisplayViewport(const DisplayViewport & viewport)171 void PointerController::setDisplayViewport(const DisplayViewport& viewport) {
172 std::scoped_lock lock(mLock);
173
174 bool getAdditionalMouseResources = false;
175 if (mLocked.presentation == PointerController::Presentation::POINTER) {
176 getAdditionalMouseResources = true;
177 }
178 mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources);
179 }
180
updatePointerIcon(int32_t iconId)181 void PointerController::updatePointerIcon(int32_t iconId) {
182 std::scoped_lock lock(mLock);
183 mCursorController.updatePointerIcon(iconId);
184 }
185
setCustomPointerIcon(const SpriteIcon & icon)186 void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
187 std::scoped_lock lock(mLock);
188 mCursorController.setCustomPointerIcon(icon);
189 }
190
doInactivityTimeout()191 void PointerController::doInactivityTimeout() {
192 fade(Transition::GRADUAL);
193 }
194
onDisplayViewportsUpdated(std::vector<DisplayViewport> & viewports)195 void PointerController::onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports) {
196 std::unordered_set<int32_t> displayIdSet;
197 for (DisplayViewport viewport : viewports) {
198 displayIdSet.insert(viewport.displayId);
199 }
200
201 std::scoped_lock lock(mLock);
202 for (auto it = mLocked.spotControllers.begin(); it != mLocked.spotControllers.end();) {
203 int32_t displayID = it->first;
204 if (!displayIdSet.count(displayID)) {
205 /*
206 * Ensures that an in-progress animation won't dereference
207 * a null pointer to TouchSpotController.
208 */
209 mContext.removeAnimationCallback(displayID);
210 it = mLocked.spotControllers.erase(it);
211 } else {
212 ++it;
213 }
214 }
215 }
216
217 } // namespace android
218