blob: 4330f0addaa9187a2e864df18e2ad1fb6e82209a [file] [log] [blame]
Liam Harringtonc782be62020-07-17 19:48:24 +00001/*
2 * Copyright (C) 2020 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 "MouseCursorController"
18//#define LOG_NDEBUG 0
19
20// Log debug messages about pointer updates
21#define DEBUG_MOUSE_CURSOR_UPDATES 0
22
23#include "MouseCursorController.h"
24
Brandon Pollack015f5d92022-06-02 06:59:33 +000025#include <input/Input.h>
Liam Harringtonc782be62020-07-17 19:48:24 +000026#include <log/log.h>
27
Arpit Singh05215af2024-08-25 17:49:32 +000028#define INDENT " "
29#define INDENT2 " "
30
Arpit Singh24c8ba62024-10-25 21:08:08 +000031namespace android {
32
Liam Harringtonc782be62020-07-17 19:48:24 +000033namespace {
Arpit Singh24c8ba62024-10-25 21:08:08 +000034
Liam Harringtonc782be62020-07-17 19:48:24 +000035// Time to spend fading out the pointer completely.
36const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
Liam Harringtonc782be62020-07-17 19:48:24 +000037
Arpit Singh24c8ba62024-10-25 21:08:08 +000038} // namespace
Liam Harringtonc782be62020-07-17 19:48:24 +000039
40// --- MouseCursorController ---
41
42MouseCursorController::MouseCursorController(PointerControllerContext& context)
43 : mContext(context) {
44 std::scoped_lock lock(mLock);
45
Seunghwan Choi670b33d2023-01-13 21:12:59 +090046 mLocked.stylusHoverMode = false;
47
Liam Harringtonc782be62020-07-17 19:48:24 +000048 mLocked.animationFrameIndex = 0;
49 mLocked.lastFrameUpdatedTime = 0;
50
51 mLocked.pointerFadeDirection = 0;
52 mLocked.pointerX = 0;
53 mLocked.pointerY = 0;
54 mLocked.pointerAlpha = 0.0f; // pointer is initially faded
Prabir Pradhan27c6d992023-08-18 19:44:55 +000055 mLocked.pointerSprite = mContext.getSpriteController().createSprite();
Liam Harringtonc782be62020-07-17 19:48:24 +000056 mLocked.updatePointerIcon = false;
Seunghwan Choi670b33d2023-01-13 21:12:59 +090057 mLocked.requestedPointerType = PointerIconStyle::TYPE_NOT_SPECIFIED;
58 mLocked.resolvedPointerType = PointerIconStyle::TYPE_NOT_SPECIFIED;
Liam Harringtonc782be62020-07-17 19:48:24 +000059
60 mLocked.resourcesLoaded = false;
Liam Harringtonc782be62020-07-17 19:48:24 +000061}
62
63MouseCursorController::~MouseCursorController() {
64 std::scoped_lock lock(mLock);
65
66 mLocked.pointerSprite.clear();
67}
68
Arpit Singh24c8ba62024-10-25 21:08:08 +000069vec2 MouseCursorController::move(float deltaX, float deltaY) {
Liam Harringtonc782be62020-07-17 19:48:24 +000070#if DEBUG_MOUSE_CURSOR_UPDATES
71 ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
72#endif
73 if (deltaX == 0.0f && deltaY == 0.0f) {
Arpit Singh24c8ba62024-10-25 21:08:08 +000074 return {};
Liam Harringtonc782be62020-07-17 19:48:24 +000075 }
76
Arpit Singh24c8ba62024-10-25 21:08:08 +000077 // When transition occurs, the MouseCursorController object may or may not be deleted, depending
78 // if there's another display on the other side of the transition. At this point we still need
79 // to move the cursor to the boundary.
Liam Harringtonc782be62020-07-17 19:48:24 +000080 std::scoped_lock lock(mLock);
Arpit Singh24c8ba62024-10-25 21:08:08 +000081 const vec2 pos{mLocked.pointerX + deltaX, mLocked.pointerY + deltaY};
82 setPositionLocked(pos.x, pos.y);
83 return vec2{pos.x - mLocked.pointerX, pos.y - mLocked.pointerY};
Liam Harringtonc782be62020-07-17 19:48:24 +000084}
85
Liam Harringtonc782be62020-07-17 19:48:24 +000086void MouseCursorController::setPosition(float x, float y) {
87#if DEBUG_MOUSE_CURSOR_UPDATES
88 ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
89#endif
90 std::scoped_lock lock(mLock);
Arpit Singh24c8ba62024-10-25 21:08:08 +000091
Liam Harringtonc782be62020-07-17 19:48:24 +000092 setPositionLocked(x, y);
93}
94
Arpit Singh24c8ba62024-10-25 21:08:08 +000095FloatRect MouseCursorController::getBoundsLocked() REQUIRES(mLock) {
Prabir Pradhaneb0c5072024-09-09 19:53:06 +000096 // The valid bounds for a mouse cursor. Since the right and bottom edges are considered outside
97 // the display, clip the bounds by one pixel instead of letting the cursor get arbitrarily
98 // close to the outside edge.
Arpit Singh24c8ba62024-10-25 21:08:08 +000099 return FloatRect{
Prabir Pradhaneb0c5072024-09-09 19:53:06 +0000100 static_cast<float>(mLocked.viewport.logicalLeft),
101 static_cast<float>(mLocked.viewport.logicalTop),
102 static_cast<float>(mLocked.viewport.logicalRight - 1),
103 static_cast<float>(mLocked.viewport.logicalBottom - 1),
104 };
Arpit Singh24c8ba62024-10-25 21:08:08 +0000105}
106void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) {
107 const auto& v = mLocked.viewport;
108 if (!v.isValid()) return;
109
110 const FloatRect bounds = getBoundsLocked();
Prabir Pradhaneb0c5072024-09-09 19:53:06 +0000111 mLocked.pointerX = std::max(bounds.left, std::min(bounds.right, x));
112 mLocked.pointerY = std::max(bounds.top, std::min(bounds.bottom, y));
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000113
114 updatePointerLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000115}
116
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000117FloatPoint MouseCursorController::getPosition() const {
Liam Harringtonc782be62020-07-17 19:48:24 +0000118 std::scoped_lock lock(mLock);
119
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000120 return {mLocked.pointerX, mLocked.pointerY};
Liam Harringtonc782be62020-07-17 19:48:24 +0000121}
122
Linnan Li0defadf2024-05-05 19:17:05 +0800123ui::LogicalDisplayId MouseCursorController::getDisplayId() const {
Liam Harringtonc782be62020-07-17 19:48:24 +0000124 std::scoped_lock lock(mLock);
125 return mLocked.viewport.displayId;
126}
127
128void MouseCursorController::fade(PointerControllerInterface::Transition transition) {
129 std::scoped_lock lock(mLock);
130
131 // Remove the inactivity timeout, since we are fading now.
132 mContext.removeInactivityTimeout();
133
134 // Start fading.
135 if (transition == PointerControllerInterface::Transition::IMMEDIATE) {
136 mLocked.pointerFadeDirection = 0;
137 mLocked.pointerAlpha = 0.0f;
138 updatePointerLocked();
139 } else {
140 mLocked.pointerFadeDirection = -1;
Liam Harringtonce637132020-08-14 04:00:11 +0000141 startAnimationLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000142 }
143}
144
145void MouseCursorController::unfade(PointerControllerInterface::Transition transition) {
146 std::scoped_lock lock(mLock);
147
148 // Always reset the inactivity timer.
149 mContext.resetInactivityTimeout();
150
151 // Start unfading.
152 if (transition == PointerControllerInterface::Transition::IMMEDIATE) {
153 mLocked.pointerFadeDirection = 0;
154 mLocked.pointerAlpha = 1.0f;
155 updatePointerLocked();
156 } else {
157 mLocked.pointerFadeDirection = 1;
Liam Harringtonce637132020-08-14 04:00:11 +0000158 startAnimationLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000159 }
160}
161
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900162void MouseCursorController::setStylusHoverMode(bool stylusHoverMode) {
163 std::scoped_lock lock(mLock);
164
165 if (mLocked.stylusHoverMode != stylusHoverMode) {
166 mLocked.stylusHoverMode = stylusHoverMode;
167 mLocked.updatePointerIcon = true;
168 }
169}
170
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000171void MouseCursorController::setSkipScreenshot(bool skip) {
172 std::scoped_lock lock(mLock);
173 if (mLocked.skipScreenshot == skip) {
174 return;
175 }
176 mLocked.skipScreenshot = skip;
177 updatePointerLocked();
178}
179
Liam Harringtonc782be62020-07-17 19:48:24 +0000180void MouseCursorController::reloadPointerResources(bool getAdditionalMouseResources) {
181 std::scoped_lock lock(mLock);
182
183 loadResourcesLocked(getAdditionalMouseResources);
184 updatePointerLocked();
185}
186
187/**
188 * The viewport values for deviceHeight and deviceWidth have already been adjusted for rotation,
189 * so here we are getting the dimensions in the original, unrotated orientation (orientation 0).
190 */
191static void getNonRotatedSize(const DisplayViewport& viewport, int32_t& width, int32_t& height) {
192 width = viewport.deviceWidth;
193 height = viewport.deviceHeight;
194
Michael Wrightecde4d02022-11-25 00:20:19 +0000195 if (viewport.orientation == ui::ROTATION_90 || viewport.orientation == ui::ROTATION_270) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000196 std::swap(width, height);
197 }
198}
199
200void MouseCursorController::setDisplayViewport(const DisplayViewport& viewport,
201 bool getAdditionalMouseResources) {
202 std::scoped_lock lock(mLock);
203
204 if (viewport == mLocked.viewport) {
205 return;
206 }
207
208 const DisplayViewport oldViewport = mLocked.viewport;
209 mLocked.viewport = viewport;
210
211 int32_t oldDisplayWidth, oldDisplayHeight;
212 getNonRotatedSize(oldViewport, oldDisplayWidth, oldDisplayHeight);
213 int32_t newDisplayWidth, newDisplayHeight;
214 getNonRotatedSize(viewport, newDisplayWidth, newDisplayHeight);
215
216 // Reset cursor position to center if size or display changed.
217 if (oldViewport.displayId != viewport.displayId || oldDisplayWidth != newDisplayWidth ||
218 oldDisplayHeight != newDisplayHeight) {
Prabir Pradhaneb0c5072024-09-09 19:53:06 +0000219 if (viewport.isValid()) {
220 // Use integer coordinates as the starting point for the cursor location.
221 // We usually expect display sizes to be even numbers, so the flooring is precautionary.
222 mLocked.pointerX = std::floor((viewport.logicalLeft + viewport.logicalRight) / 2);
223 mLocked.pointerY = std::floor((viewport.logicalTop + viewport.logicalBottom) / 2);
Liam Harringtonc782be62020-07-17 19:48:24 +0000224 // Reload icon resources for density may be changed.
225 loadResourcesLocked(getAdditionalMouseResources);
226 } else {
227 mLocked.pointerX = 0;
228 mLocked.pointerY = 0;
229 }
230 } else if (oldViewport.orientation != viewport.orientation) {
231 // Apply offsets to convert from the pixel top-left corner position to the pixel center.
232 // This creates an invariant frame of reference that we can easily rotate when
233 // taking into account that the pointer may be located at fractional pixel offsets.
234 float x = mLocked.pointerX + 0.5f;
235 float y = mLocked.pointerY + 0.5f;
236 float temp;
237
238 // Undo the previous rotation.
239 switch (oldViewport.orientation) {
Michael Wrightecde4d02022-11-25 00:20:19 +0000240 case ui::ROTATION_90:
Liam Harringtonc782be62020-07-17 19:48:24 +0000241 temp = x;
242 x = oldViewport.deviceHeight - y;
243 y = temp;
244 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000245 case ui::ROTATION_180:
Liam Harringtonc782be62020-07-17 19:48:24 +0000246 x = oldViewport.deviceWidth - x;
247 y = oldViewport.deviceHeight - y;
248 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000249 case ui::ROTATION_270:
Liam Harringtonc782be62020-07-17 19:48:24 +0000250 temp = x;
251 x = y;
252 y = oldViewport.deviceWidth - temp;
253 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000254 case ui::ROTATION_0:
255 break;
Liam Harringtonc782be62020-07-17 19:48:24 +0000256 }
257
258 // Perform the new rotation.
259 switch (viewport.orientation) {
Michael Wrightecde4d02022-11-25 00:20:19 +0000260 case ui::ROTATION_90:
Liam Harringtonc782be62020-07-17 19:48:24 +0000261 temp = x;
262 x = y;
263 y = viewport.deviceHeight - temp;
264 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000265 case ui::ROTATION_180:
Liam Harringtonc782be62020-07-17 19:48:24 +0000266 x = viewport.deviceWidth - x;
267 y = viewport.deviceHeight - y;
268 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000269 case ui::ROTATION_270:
Liam Harringtonc782be62020-07-17 19:48:24 +0000270 temp = x;
271 x = viewport.deviceWidth - y;
272 y = temp;
273 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000274 case ui::ROTATION_0:
275 break;
Liam Harringtonc782be62020-07-17 19:48:24 +0000276 }
277
278 // Apply offsets to convert from the pixel center to the pixel top-left corner position
279 // and save the results.
280 mLocked.pointerX = x - 0.5f;
281 mLocked.pointerY = y - 0.5f;
282 }
283
284 updatePointerLocked();
285}
286
Brandon Pollack015f5d92022-06-02 06:59:33 +0000287void MouseCursorController::updatePointerIcon(PointerIconStyle iconId) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000288 std::scoped_lock lock(mLock);
289
290 if (mLocked.requestedPointerType != iconId) {
291 mLocked.requestedPointerType = iconId;
292 mLocked.updatePointerIcon = true;
293 updatePointerLocked();
294 }
295}
296
297void MouseCursorController::setCustomPointerIcon(const SpriteIcon& icon) {
298 std::scoped_lock lock(mLock);
299
Brandon Pollack015f5d92022-06-02 06:59:33 +0000300 const PointerIconStyle iconId = mContext.getPolicy()->getCustomPointerIconId();
Liam Harringtonc782be62020-07-17 19:48:24 +0000301 mLocked.additionalMouseResources[iconId] = icon;
302 mLocked.requestedPointerType = iconId;
303 mLocked.updatePointerIcon = true;
304 updatePointerLocked();
305}
306
Liam Harringtonce637132020-08-14 04:00:11 +0000307bool MouseCursorController::doFadingAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000308 nsecs_t frameDelay = timestamp - mContext.getAnimationTime();
Liam Harringtonce637132020-08-14 04:00:11 +0000309 bool keepAnimating = false;
Liam Harringtonc782be62020-07-17 19:48:24 +0000310
311 // Animate pointer fade.
312 if (mLocked.pointerFadeDirection < 0) {
313 mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
314 if (mLocked.pointerAlpha <= 0.0f) {
315 mLocked.pointerAlpha = 0.0f;
316 mLocked.pointerFadeDirection = 0;
317 } else {
318 keepAnimating = true;
319 }
320 updatePointerLocked();
321 } else if (mLocked.pointerFadeDirection > 0) {
322 mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
323 if (mLocked.pointerAlpha >= 1.0f) {
324 mLocked.pointerAlpha = 1.0f;
325 mLocked.pointerFadeDirection = 0;
326 } else {
327 keepAnimating = true;
328 }
329 updatePointerLocked();
330 }
Liam Harringtonc782be62020-07-17 19:48:24 +0000331 return keepAnimating;
332}
333
Liam Harringtonce637132020-08-14 04:00:11 +0000334bool MouseCursorController::doBitmapAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000335 std::map<PointerIconStyle, PointerAnimation>::const_iterator iter =
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900336 mLocked.animationResources.find(mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000337 if (iter == mLocked.animationResources.end()) {
338 return false;
339 }
340
341 if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000342 auto& spriteController = mContext.getSpriteController();
343 spriteController.openTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000344
345 int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
346 mLocked.animationFrameIndex += incr;
347 mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
348 while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
349 mLocked.animationFrameIndex -= iter->second.animationFrames.size();
350 }
351 mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
352
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000353 spriteController.closeTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000354 }
Liam Harringtonc782be62020-07-17 19:48:24 +0000355 // Keep animating.
356 return true;
357}
358
359void MouseCursorController::updatePointerLocked() REQUIRES(mLock) {
360 if (!mLocked.viewport.isValid()) {
361 return;
362 }
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000363 auto& spriteController = mContext.getSpriteController();
364 spriteController.openTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000365
366 mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
367 mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
368 mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000369 mLocked.pointerSprite->setSkipScreenshot(mLocked.skipScreenshot);
Liam Harringtonc782be62020-07-17 19:48:24 +0000370
371 if (mLocked.pointerAlpha > 0) {
372 mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
373 mLocked.pointerSprite->setVisible(true);
374 } else {
375 mLocked.pointerSprite->setVisible(false);
376 }
377
378 if (mLocked.updatePointerIcon) {
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900379 mLocked.resolvedPointerType = mLocked.requestedPointerType;
380 const PointerIconStyle defaultPointerIconId =
381 mContext.getPolicy()->getDefaultPointerIconId();
382 if (mLocked.resolvedPointerType == PointerIconStyle::TYPE_NOT_SPECIFIED) {
383 mLocked.resolvedPointerType = mLocked.stylusHoverMode
384 ? mContext.getPolicy()->getDefaultStylusIconId()
385 : defaultPointerIconId;
386 }
387
388 if (mLocked.resolvedPointerType == defaultPointerIconId) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000389 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
390 } else {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000391 std::map<PointerIconStyle, SpriteIcon>::const_iterator iter =
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900392 mLocked.additionalMouseResources.find(mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000393 if (iter != mLocked.additionalMouseResources.end()) {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000394 std::map<PointerIconStyle, PointerAnimation>::const_iterator anim_iter =
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900395 mLocked.animationResources.find(mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000396 if (anim_iter != mLocked.animationResources.end()) {
397 mLocked.animationFrameIndex = 0;
398 mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
Liam Harringtonce637132020-08-14 04:00:11 +0000399 startAnimationLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000400 }
401 mLocked.pointerSprite->setIcon(iter->second);
402 } else {
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900403 ALOGW("Can't find the resource for icon id %d", mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000404 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
405 }
406 }
407 mLocked.updatePointerIcon = false;
408 }
409
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000410 spriteController.closeTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000411}
412
413void MouseCursorController::loadResourcesLocked(bool getAdditionalMouseResources) REQUIRES(mLock) {
414 if (!mLocked.viewport.isValid()) {
415 return;
416 }
417
418 if (!mLocked.resourcesLoaded) mLocked.resourcesLoaded = true;
419
420 sp<PointerControllerPolicyInterface> policy = mContext.getPolicy();
421 policy->loadPointerResources(&mResources, mLocked.viewport.displayId);
422 policy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
423
424 mLocked.additionalMouseResources.clear();
425 mLocked.animationResources.clear();
426 if (getAdditionalMouseResources) {
427 policy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
428 &mLocked.animationResources,
429 mLocked.viewport.displayId);
430 }
431
432 mLocked.updatePointerIcon = true;
433}
434
435bool MouseCursorController::isViewportValid() {
436 std::scoped_lock lock(mLock);
437 return mLocked.viewport.isValid();
438}
439
440void MouseCursorController::getAdditionalMouseResources() {
441 std::scoped_lock lock(mLock);
442
443 if (mLocked.additionalMouseResources.empty()) {
444 mContext.getPolicy()->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
445 &mLocked.animationResources,
446 mLocked.viewport.displayId);
447 }
448 mLocked.updatePointerIcon = true;
449 updatePointerLocked();
450}
451
452bool MouseCursorController::resourcesLoaded() {
453 std::scoped_lock lock(mLock);
454 return mLocked.resourcesLoaded;
455}
456
Arpit Singh05215af2024-08-25 17:49:32 +0000457std::string MouseCursorController::dump() const {
458 std::string dump = INDENT "MouseCursorController:\n";
459 std::scoped_lock lock(mLock);
460 dump += StringPrintf(INDENT2 "viewport: %s\n", mLocked.viewport.toString().c_str());
461 dump += StringPrintf(INDENT2 "stylusHoverMode: %s\n",
462 mLocked.stylusHoverMode ? "true" : "false");
463 dump += StringPrintf(INDENT2 "pointerFadeDirection: %d\n", mLocked.pointerFadeDirection);
464 dump += StringPrintf(INDENT2 "updatePointerIcon: %s\n",
465 mLocked.updatePointerIcon ? "true" : "false");
466 dump += StringPrintf(INDENT2 "resourcesLoaded: %s\n",
467 mLocked.resourcesLoaded ? "true" : "false");
468 dump += StringPrintf(INDENT2 "requestedPointerType: %d\n", mLocked.requestedPointerType);
469 dump += StringPrintf(INDENT2 "resolvedPointerType: %d\n", mLocked.resolvedPointerType);
470 dump += StringPrintf(INDENT2 "skipScreenshot: %s\n", mLocked.skipScreenshot ? "true" : "false");
471 dump += StringPrintf(INDENT2 "animating: %s\n", mLocked.animating ? "true" : "false");
472 return dump;
473}
474
Liam Harringtonce637132020-08-14 04:00:11 +0000475bool MouseCursorController::doAnimations(nsecs_t timestamp) {
476 std::scoped_lock lock(mLock);
477 bool keepFading = doFadingAnimationLocked(timestamp);
478 bool keepBitmap = doBitmapAnimationLocked(timestamp);
479 bool keepAnimating = keepFading || keepBitmap;
480 if (!keepAnimating) {
481 /*
482 * We know that this callback will be removed before another
483 * is added. mLock in PointerAnimator will not be released
484 * until after this is removed, and adding another callback
485 * requires that lock. Thus it's safe to set mLocked.animating
486 * here.
487 */
488 mLocked.animating = false;
489 }
490 return keepAnimating;
491}
492
493void MouseCursorController::startAnimationLocked() REQUIRES(mLock) {
494 using namespace std::placeholders;
495
496 if (mLocked.animating) {
497 return;
498 }
499 mLocked.animating = true;
500
501 std::function<bool(nsecs_t)> func = std::bind(&MouseCursorController::doAnimations, this, _1);
502 /*
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700503 * Using ui::LogicalDisplayId::INVALID for displayId here to avoid removing the callback
Liam Harringtonce637132020-08-14 04:00:11 +0000504 * if a TouchSpotController with the same display is removed.
505 */
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700506 mContext.addAnimationCallback(ui::LogicalDisplayId::INVALID, func);
Liam Harringtonce637132020-08-14 04:00:11 +0000507}
508
Liam Harringtonc782be62020-07-17 19:48:24 +0000509} // namespace android