blob: 28d96e3e5bb1d3f280624f0546ef194a7d9a4d30 [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 Singh64a70882024-10-25 21:08:08 +000031namespace android {
32
Liam Harringtonc782be62020-07-17 19:48:24 +000033namespace {
Arpit Singh64a70882024-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 Singh64a70882024-10-25 21:08:08 +000038} // namespace
Liana Kazanova (xWF)a1d4fe02024-11-18 19:14:42 +000039
Liam Harringtonc782be62020-07-17 19:48:24 +000040// --- 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 Singh64a70882024-10-25 21:08:08 +000069FloatPoint 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 Singh64a70882024-10-25 21:08:08 +000074 return {0, 0};
Liam Harringtonc782be62020-07-17 19:48:24 +000075 }
76
Arpit Singh64a70882024-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 Singh64a70882024-10-25 21:08:08 +000081 const FloatPoint position{mLocked.pointerX + deltaX, mLocked.pointerY + deltaY};
82 setPositionLocked(position.x, position.y);
83 // The amount of the delta that was not consumed as a result of the cursor
84 // hitting the edge of the display.
85 return {position.x - mLocked.pointerX, position.y - mLocked.pointerY};
Liam Harringtonc782be62020-07-17 19:48:24 +000086}
87
Liam Harringtonc782be62020-07-17 19:48:24 +000088void MouseCursorController::setPosition(float x, float y) {
89#if DEBUG_MOUSE_CURSOR_UPDATES
90 ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
91#endif
92 std::scoped_lock lock(mLock);
93 setPositionLocked(x, y);
94}
95
Arpit Singh64a70882024-10-25 21:08:08 +000096FloatRect MouseCursorController::getBoundsLocked() REQUIRES(mLock) {
Prabir Pradhaneb0c5072024-09-09 19:53:06 +000097 // The valid bounds for a mouse cursor. Since the right and bottom edges are considered outside
98 // the display, clip the bounds by one pixel instead of letting the cursor get arbitrarily
99 // close to the outside edge.
Arpit Singh64a70882024-10-25 21:08:08 +0000100 return FloatRect{
Prabir Pradhaneb0c5072024-09-09 19:53:06 +0000101 static_cast<float>(mLocked.viewport.logicalLeft),
102 static_cast<float>(mLocked.viewport.logicalTop),
103 static_cast<float>(mLocked.viewport.logicalRight - 1),
104 static_cast<float>(mLocked.viewport.logicalBottom - 1),
105 };
Arpit Singh64a70882024-10-25 21:08:08 +0000106}
107
108void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) {
109 const auto& v = mLocked.viewport;
110 if (!v.isValid()) return;
111
112 const FloatRect bounds = getBoundsLocked();
Prabir Pradhaneb0c5072024-09-09 19:53:06 +0000113 mLocked.pointerX = std::max(bounds.left, std::min(bounds.right, x));
114 mLocked.pointerY = std::max(bounds.top, std::min(bounds.bottom, y));
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000115
116 updatePointerLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000117}
118
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000119FloatPoint MouseCursorController::getPosition() const {
Liam Harringtonc782be62020-07-17 19:48:24 +0000120 std::scoped_lock lock(mLock);
121
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000122 return {mLocked.pointerX, mLocked.pointerY};
Liam Harringtonc782be62020-07-17 19:48:24 +0000123}
124
Linnan Li0defadf2024-05-05 19:17:05 +0800125ui::LogicalDisplayId MouseCursorController::getDisplayId() const {
Liam Harringtonc782be62020-07-17 19:48:24 +0000126 std::scoped_lock lock(mLock);
127 return mLocked.viewport.displayId;
128}
129
130void MouseCursorController::fade(PointerControllerInterface::Transition transition) {
131 std::scoped_lock lock(mLock);
132
133 // Remove the inactivity timeout, since we are fading now.
134 mContext.removeInactivityTimeout();
135
136 // Start fading.
137 if (transition == PointerControllerInterface::Transition::IMMEDIATE) {
138 mLocked.pointerFadeDirection = 0;
139 mLocked.pointerAlpha = 0.0f;
140 updatePointerLocked();
141 } else {
142 mLocked.pointerFadeDirection = -1;
Liam Harringtonce637132020-08-14 04:00:11 +0000143 startAnimationLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000144 }
145}
146
147void MouseCursorController::unfade(PointerControllerInterface::Transition transition) {
148 std::scoped_lock lock(mLock);
149
150 // Always reset the inactivity timer.
151 mContext.resetInactivityTimeout();
152
153 // Start unfading.
154 if (transition == PointerControllerInterface::Transition::IMMEDIATE) {
155 mLocked.pointerFadeDirection = 0;
156 mLocked.pointerAlpha = 1.0f;
157 updatePointerLocked();
158 } else {
159 mLocked.pointerFadeDirection = 1;
Liam Harringtonce637132020-08-14 04:00:11 +0000160 startAnimationLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000161 }
162}
163
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900164void MouseCursorController::setStylusHoverMode(bool stylusHoverMode) {
165 std::scoped_lock lock(mLock);
166
167 if (mLocked.stylusHoverMode != stylusHoverMode) {
168 mLocked.stylusHoverMode = stylusHoverMode;
169 mLocked.updatePointerIcon = true;
170 }
171}
172
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000173void MouseCursorController::setSkipScreenshot(bool skip) {
174 std::scoped_lock lock(mLock);
175 if (mLocked.skipScreenshot == skip) {
176 return;
177 }
178 mLocked.skipScreenshot = skip;
179 updatePointerLocked();
180}
181
Liam Harringtonc782be62020-07-17 19:48:24 +0000182void MouseCursorController::reloadPointerResources(bool getAdditionalMouseResources) {
183 std::scoped_lock lock(mLock);
184
185 loadResourcesLocked(getAdditionalMouseResources);
186 updatePointerLocked();
187}
188
189/**
190 * The viewport values for deviceHeight and deviceWidth have already been adjusted for rotation,
191 * so here we are getting the dimensions in the original, unrotated orientation (orientation 0).
192 */
193static void getNonRotatedSize(const DisplayViewport& viewport, int32_t& width, int32_t& height) {
194 width = viewport.deviceWidth;
195 height = viewport.deviceHeight;
196
Michael Wrightecde4d02022-11-25 00:20:19 +0000197 if (viewport.orientation == ui::ROTATION_90 || viewport.orientation == ui::ROTATION_270) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000198 std::swap(width, height);
199 }
200}
201
202void MouseCursorController::setDisplayViewport(const DisplayViewport& viewport,
203 bool getAdditionalMouseResources) {
204 std::scoped_lock lock(mLock);
205
206 if (viewport == mLocked.viewport) {
207 return;
208 }
209
210 const DisplayViewport oldViewport = mLocked.viewport;
211 mLocked.viewport = viewport;
212
213 int32_t oldDisplayWidth, oldDisplayHeight;
214 getNonRotatedSize(oldViewport, oldDisplayWidth, oldDisplayHeight);
215 int32_t newDisplayWidth, newDisplayHeight;
216 getNonRotatedSize(viewport, newDisplayWidth, newDisplayHeight);
217
218 // Reset cursor position to center if size or display changed.
219 if (oldViewport.displayId != viewport.displayId || oldDisplayWidth != newDisplayWidth ||
220 oldDisplayHeight != newDisplayHeight) {
Prabir Pradhaneb0c5072024-09-09 19:53:06 +0000221 if (viewport.isValid()) {
222 // Use integer coordinates as the starting point for the cursor location.
223 // We usually expect display sizes to be even numbers, so the flooring is precautionary.
224 mLocked.pointerX = std::floor((viewport.logicalLeft + viewport.logicalRight) / 2);
225 mLocked.pointerY = std::floor((viewport.logicalTop + viewport.logicalBottom) / 2);
Liam Harringtonc782be62020-07-17 19:48:24 +0000226 // Reload icon resources for density may be changed.
227 loadResourcesLocked(getAdditionalMouseResources);
228 } else {
229 mLocked.pointerX = 0;
230 mLocked.pointerY = 0;
231 }
232 } else if (oldViewport.orientation != viewport.orientation) {
233 // Apply offsets to convert from the pixel top-left corner position to the pixel center.
234 // This creates an invariant frame of reference that we can easily rotate when
235 // taking into account that the pointer may be located at fractional pixel offsets.
236 float x = mLocked.pointerX + 0.5f;
237 float y = mLocked.pointerY + 0.5f;
238 float temp;
239
240 // Undo the previous rotation.
241 switch (oldViewport.orientation) {
Michael Wrightecde4d02022-11-25 00:20:19 +0000242 case ui::ROTATION_90:
Liam Harringtonc782be62020-07-17 19:48:24 +0000243 temp = x;
244 x = oldViewport.deviceHeight - y;
245 y = temp;
246 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000247 case ui::ROTATION_180:
Liam Harringtonc782be62020-07-17 19:48:24 +0000248 x = oldViewport.deviceWidth - x;
249 y = oldViewport.deviceHeight - y;
250 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000251 case ui::ROTATION_270:
Liam Harringtonc782be62020-07-17 19:48:24 +0000252 temp = x;
253 x = y;
254 y = oldViewport.deviceWidth - temp;
255 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000256 case ui::ROTATION_0:
257 break;
Liam Harringtonc782be62020-07-17 19:48:24 +0000258 }
259
260 // Perform the new rotation.
261 switch (viewport.orientation) {
Michael Wrightecde4d02022-11-25 00:20:19 +0000262 case ui::ROTATION_90:
Liam Harringtonc782be62020-07-17 19:48:24 +0000263 temp = x;
264 x = y;
265 y = viewport.deviceHeight - temp;
266 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000267 case ui::ROTATION_180:
Liam Harringtonc782be62020-07-17 19:48:24 +0000268 x = viewport.deviceWidth - x;
269 y = viewport.deviceHeight - y;
270 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000271 case ui::ROTATION_270:
Liam Harringtonc782be62020-07-17 19:48:24 +0000272 temp = x;
273 x = viewport.deviceWidth - y;
274 y = temp;
275 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000276 case ui::ROTATION_0:
277 break;
Liam Harringtonc782be62020-07-17 19:48:24 +0000278 }
279
280 // Apply offsets to convert from the pixel center to the pixel top-left corner position
281 // and save the results.
282 mLocked.pointerX = x - 0.5f;
283 mLocked.pointerY = y - 0.5f;
284 }
285
286 updatePointerLocked();
287}
288
Brandon Pollack015f5d92022-06-02 06:59:33 +0000289void MouseCursorController::updatePointerIcon(PointerIconStyle iconId) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000290 std::scoped_lock lock(mLock);
291
292 if (mLocked.requestedPointerType != iconId) {
293 mLocked.requestedPointerType = iconId;
294 mLocked.updatePointerIcon = true;
295 updatePointerLocked();
296 }
297}
298
299void MouseCursorController::setCustomPointerIcon(const SpriteIcon& icon) {
300 std::scoped_lock lock(mLock);
301
Brandon Pollack015f5d92022-06-02 06:59:33 +0000302 const PointerIconStyle iconId = mContext.getPolicy()->getCustomPointerIconId();
Liam Harringtonc782be62020-07-17 19:48:24 +0000303 mLocked.additionalMouseResources[iconId] = icon;
304 mLocked.requestedPointerType = iconId;
305 mLocked.updatePointerIcon = true;
306 updatePointerLocked();
307}
308
Liam Harringtonce637132020-08-14 04:00:11 +0000309bool MouseCursorController::doFadingAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000310 nsecs_t frameDelay = timestamp - mContext.getAnimationTime();
Liam Harringtonce637132020-08-14 04:00:11 +0000311 bool keepAnimating = false;
Liam Harringtonc782be62020-07-17 19:48:24 +0000312
313 // Animate pointer fade.
314 if (mLocked.pointerFadeDirection < 0) {
315 mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
316 if (mLocked.pointerAlpha <= 0.0f) {
317 mLocked.pointerAlpha = 0.0f;
318 mLocked.pointerFadeDirection = 0;
319 } else {
320 keepAnimating = true;
321 }
322 updatePointerLocked();
323 } else if (mLocked.pointerFadeDirection > 0) {
324 mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
325 if (mLocked.pointerAlpha >= 1.0f) {
326 mLocked.pointerAlpha = 1.0f;
327 mLocked.pointerFadeDirection = 0;
328 } else {
329 keepAnimating = true;
330 }
331 updatePointerLocked();
332 }
Liam Harringtonc782be62020-07-17 19:48:24 +0000333 return keepAnimating;
334}
335
Liam Harringtonce637132020-08-14 04:00:11 +0000336bool MouseCursorController::doBitmapAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000337 std::map<PointerIconStyle, PointerAnimation>::const_iterator iter =
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900338 mLocked.animationResources.find(mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000339 if (iter == mLocked.animationResources.end()) {
340 return false;
341 }
342
343 if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000344 auto& spriteController = mContext.getSpriteController();
345 spriteController.openTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000346
347 int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
348 mLocked.animationFrameIndex += incr;
349 mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
350 while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
351 mLocked.animationFrameIndex -= iter->second.animationFrames.size();
352 }
353 mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
354
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000355 spriteController.closeTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000356 }
Liam Harringtonc782be62020-07-17 19:48:24 +0000357 // Keep animating.
358 return true;
359}
360
361void MouseCursorController::updatePointerLocked() REQUIRES(mLock) {
362 if (!mLocked.viewport.isValid()) {
363 return;
364 }
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000365 auto& spriteController = mContext.getSpriteController();
366 spriteController.openTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000367
368 mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
369 mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
370 mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000371 mLocked.pointerSprite->setSkipScreenshot(mLocked.skipScreenshot);
Liam Harringtonc782be62020-07-17 19:48:24 +0000372
373 if (mLocked.pointerAlpha > 0) {
374 mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
375 mLocked.pointerSprite->setVisible(true);
376 } else {
377 mLocked.pointerSprite->setVisible(false);
378 }
379
380 if (mLocked.updatePointerIcon) {
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900381 mLocked.resolvedPointerType = mLocked.requestedPointerType;
382 const PointerIconStyle defaultPointerIconId =
383 mContext.getPolicy()->getDefaultPointerIconId();
384 if (mLocked.resolvedPointerType == PointerIconStyle::TYPE_NOT_SPECIFIED) {
385 mLocked.resolvedPointerType = mLocked.stylusHoverMode
386 ? mContext.getPolicy()->getDefaultStylusIconId()
387 : defaultPointerIconId;
388 }
389
390 if (mLocked.resolvedPointerType == defaultPointerIconId) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000391 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
392 } else {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000393 std::map<PointerIconStyle, SpriteIcon>::const_iterator iter =
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900394 mLocked.additionalMouseResources.find(mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000395 if (iter != mLocked.additionalMouseResources.end()) {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000396 std::map<PointerIconStyle, PointerAnimation>::const_iterator anim_iter =
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900397 mLocked.animationResources.find(mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000398 if (anim_iter != mLocked.animationResources.end()) {
399 mLocked.animationFrameIndex = 0;
400 mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
Liam Harringtonce637132020-08-14 04:00:11 +0000401 startAnimationLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000402 }
403 mLocked.pointerSprite->setIcon(iter->second);
404 } else {
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900405 ALOGW("Can't find the resource for icon id %d", mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000406 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
407 }
408 }
409 mLocked.updatePointerIcon = false;
410 }
411
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000412 spriteController.closeTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000413}
414
415void MouseCursorController::loadResourcesLocked(bool getAdditionalMouseResources) REQUIRES(mLock) {
416 if (!mLocked.viewport.isValid()) {
417 return;
418 }
419
420 if (!mLocked.resourcesLoaded) mLocked.resourcesLoaded = true;
421
422 sp<PointerControllerPolicyInterface> policy = mContext.getPolicy();
423 policy->loadPointerResources(&mResources, mLocked.viewport.displayId);
424 policy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
425
426 mLocked.additionalMouseResources.clear();
427 mLocked.animationResources.clear();
428 if (getAdditionalMouseResources) {
429 policy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
430 &mLocked.animationResources,
431 mLocked.viewport.displayId);
432 }
433
434 mLocked.updatePointerIcon = true;
435}
436
437bool MouseCursorController::isViewportValid() {
438 std::scoped_lock lock(mLock);
439 return mLocked.viewport.isValid();
440}
441
442void MouseCursorController::getAdditionalMouseResources() {
443 std::scoped_lock lock(mLock);
444
445 if (mLocked.additionalMouseResources.empty()) {
446 mContext.getPolicy()->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
447 &mLocked.animationResources,
448 mLocked.viewport.displayId);
449 }
450 mLocked.updatePointerIcon = true;
451 updatePointerLocked();
452}
453
454bool MouseCursorController::resourcesLoaded() {
455 std::scoped_lock lock(mLock);
456 return mLocked.resourcesLoaded;
457}
458
Arpit Singh05215af2024-08-25 17:49:32 +0000459std::string MouseCursorController::dump() const {
460 std::string dump = INDENT "MouseCursorController:\n";
461 std::scoped_lock lock(mLock);
462 dump += StringPrintf(INDENT2 "viewport: %s\n", mLocked.viewport.toString().c_str());
463 dump += StringPrintf(INDENT2 "stylusHoverMode: %s\n",
464 mLocked.stylusHoverMode ? "true" : "false");
465 dump += StringPrintf(INDENT2 "pointerFadeDirection: %d\n", mLocked.pointerFadeDirection);
466 dump += StringPrintf(INDENT2 "updatePointerIcon: %s\n",
467 mLocked.updatePointerIcon ? "true" : "false");
468 dump += StringPrintf(INDENT2 "resourcesLoaded: %s\n",
469 mLocked.resourcesLoaded ? "true" : "false");
470 dump += StringPrintf(INDENT2 "requestedPointerType: %d\n", mLocked.requestedPointerType);
471 dump += StringPrintf(INDENT2 "resolvedPointerType: %d\n", mLocked.resolvedPointerType);
472 dump += StringPrintf(INDENT2 "skipScreenshot: %s\n", mLocked.skipScreenshot ? "true" : "false");
473 dump += StringPrintf(INDENT2 "animating: %s\n", mLocked.animating ? "true" : "false");
474 return dump;
475}
476
Liam Harringtonce637132020-08-14 04:00:11 +0000477bool MouseCursorController::doAnimations(nsecs_t timestamp) {
478 std::scoped_lock lock(mLock);
479 bool keepFading = doFadingAnimationLocked(timestamp);
480 bool keepBitmap = doBitmapAnimationLocked(timestamp);
481 bool keepAnimating = keepFading || keepBitmap;
482 if (!keepAnimating) {
483 /*
484 * We know that this callback will be removed before another
485 * is added. mLock in PointerAnimator will not be released
486 * until after this is removed, and adding another callback
487 * requires that lock. Thus it's safe to set mLocked.animating
488 * here.
489 */
490 mLocked.animating = false;
491 }
492 return keepAnimating;
493}
494
495void MouseCursorController::startAnimationLocked() REQUIRES(mLock) {
496 using namespace std::placeholders;
497
498 if (mLocked.animating) {
499 return;
500 }
501 mLocked.animating = true;
502
503 std::function<bool(nsecs_t)> func = std::bind(&MouseCursorController::doAnimations, this, _1);
504 /*
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700505 * Using ui::LogicalDisplayId::INVALID for displayId here to avoid removing the callback
Liam Harringtonce637132020-08-14 04:00:11 +0000506 * if a TouchSpotController with the same display is removed.
507 */
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700508 mContext.addAnimationCallback(ui::LogicalDisplayId::INVALID, func);
Liam Harringtonce637132020-08-14 04:00:11 +0000509}
510
Liam Harringtonc782be62020-07-17 19:48:24 +0000511} // namespace android