blob: 4571ef4481c8aa535a8b0c3afb0b304f39acd4dd [file] [log] [blame]
Prabir Pradhanb56e92c2023-06-09 23:40:37 +00001/*
2 * Copyright 2023 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 "PointerChoreographer"
18
Byoungho Jungda10dd32023-10-06 17:03:45 +090019#include <android-base/logging.h>
20#include <input/PrintTools.h>
21
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000022#include "PointerChoreographer.h"
23
Byoungho Jungda10dd32023-10-06 17:03:45 +090024#define INDENT " "
25
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000026namespace android {
27
Byoungho Jungda10dd32023-10-06 17:03:45 +090028namespace {
29bool isFromMouse(const NotifyMotionArgs& args) {
30 return isFromSource(args.source, AINPUT_SOURCE_MOUSE) &&
31 args.pointerProperties[0].toolType == ToolType::MOUSE;
32}
33
Byoungho Jungee6268f2023-10-30 17:27:26 +090034bool isFromTouchpad(const NotifyMotionArgs& args) {
35 return isFromSource(args.source, AINPUT_SOURCE_MOUSE) &&
36 args.pointerProperties[0].toolType == ToolType::FINGER;
37}
38
Byoungho Jungd6fe27b2023-10-27 20:49:38 +090039bool isHoverAction(int32_t action) {
40 return action == AMOTION_EVENT_ACTION_HOVER_ENTER ||
41 action == AMOTION_EVENT_ACTION_HOVER_MOVE || action == AMOTION_EVENT_ACTION_HOVER_EXIT;
42}
43
44bool isStylusHoverEvent(const NotifyMotionArgs& args) {
45 return isStylusEvent(args.source, args.pointerProperties) && isHoverAction(args.action);
46}
Byoungho Jungda10dd32023-10-06 17:03:45 +090047} // namespace
48
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000049// --- PointerChoreographer ---
50
51PointerChoreographer::PointerChoreographer(InputListenerInterface& listener,
52 PointerChoreographerPolicyInterface& policy)
Prabir Pradhan16788792023-11-08 21:07:21 +000053 : mTouchControllerConstructor([this]() REQUIRES(mLock) {
54 return mPolicy.createPointerController(
55 PointerControllerInterface::ControllerType::TOUCH);
56 }),
57 mNextListener(listener),
Byoungho Jungda10dd32023-10-06 17:03:45 +090058 mPolicy(policy),
59 mDefaultMouseDisplayId(ADISPLAY_ID_DEFAULT),
Byoungho Jung6f5b16b2023-10-27 18:22:07 +090060 mNotifiedPointerDisplayId(ADISPLAY_ID_NONE),
Byoungho Jungd6fe27b2023-10-27 20:49:38 +090061 mShowTouchesEnabled(false),
62 mStylusPointerIconEnabled(false) {}
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000063
64void PointerChoreographer::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
Byoungho Jungda10dd32023-10-06 17:03:45 +090065 std::scoped_lock _l(mLock);
66
67 mInputDeviceInfos = args.inputDeviceInfos;
68 updatePointerControllersLocked();
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000069 mNextListener.notify(args);
70}
71
72void PointerChoreographer::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
73 mNextListener.notify(args);
74}
75
76void PointerChoreographer::notifyKey(const NotifyKeyArgs& args) {
77 mNextListener.notify(args);
78}
79
80void PointerChoreographer::notifyMotion(const NotifyMotionArgs& args) {
Byoungho Jungda10dd32023-10-06 17:03:45 +090081 NotifyMotionArgs newArgs = processMotion(args);
82
83 mNextListener.notify(newArgs);
84}
85
86NotifyMotionArgs PointerChoreographer::processMotion(const NotifyMotionArgs& args) {
87 std::scoped_lock _l(mLock);
88
89 if (isFromMouse(args)) {
90 return processMouseEventLocked(args);
Byoungho Jungee6268f2023-10-30 17:27:26 +090091 } else if (isFromTouchpad(args)) {
92 return processTouchpadEventLocked(args);
Byoungho Jungd6fe27b2023-10-27 20:49:38 +090093 } else if (mStylusPointerIconEnabled && isStylusHoverEvent(args)) {
94 processStylusHoverEventLocked(args);
Byoungho Jungda10dd32023-10-06 17:03:45 +090095 } else if (isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN)) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +090096 processTouchscreenAndStylusEventLocked(args);
Byoungho Jungda10dd32023-10-06 17:03:45 +090097 }
98 return args;
99}
100
101NotifyMotionArgs PointerChoreographer::processMouseEventLocked(const NotifyMotionArgs& args) {
102 if (args.getPointerCount() != 1) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000103 LOG(FATAL) << "Only mouse events with a single pointer are currently supported: "
104 << args.dump();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900105 }
106
Byoungho Jungee6268f2023-10-30 17:27:26 +0900107 auto [displayId, pc] = getDisplayIdAndMouseControllerLocked(args.displayId);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900108
109 const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
110 const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
111 pc.move(deltaX, deltaY);
112 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
113
114 const auto [x, y] = pc.getPosition();
115 NotifyMotionArgs newArgs(args);
116 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
117 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
118 newArgs.xCursorPosition = x;
119 newArgs.yCursorPosition = y;
120 newArgs.displayId = displayId;
121 return newArgs;
122}
123
Byoungho Jungee6268f2023-10-30 17:27:26 +0900124NotifyMotionArgs PointerChoreographer::processTouchpadEventLocked(const NotifyMotionArgs& args) {
125 auto [displayId, pc] = getDisplayIdAndMouseControllerLocked(args.displayId);
126
127 NotifyMotionArgs newArgs(args);
128 newArgs.displayId = displayId;
129 if (args.getPointerCount() == 1 && args.classification == MotionClassification::NONE) {
130 // This is a movement of the mouse pointer.
131 const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
132 const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
133 pc.move(deltaX, deltaY);
134 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
135
136 const auto [x, y] = pc.getPosition();
137 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
138 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
139 newArgs.xCursorPosition = x;
140 newArgs.yCursorPosition = y;
141 } else {
142 // This is a trackpad gesture with fake finger(s) that should not move the mouse pointer.
143 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
144
145 const auto [x, y] = pc.getPosition();
146 for (uint32_t i = 0; i < newArgs.getPointerCount(); i++) {
147 newArgs.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X,
148 args.pointerCoords[i].getX() + x);
149 newArgs.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y,
150 args.pointerCoords[i].getY() + y);
151 }
152 newArgs.xCursorPosition = x;
153 newArgs.yCursorPosition = y;
154 }
155 return newArgs;
156}
157
Byoungho Jungda10dd32023-10-06 17:03:45 +0900158/**
159 * When screen is touched, fade the mouse pointer on that display. We only call fade for
160 * ACTION_DOWN events.This would allow both mouse and touch to be used at the same time if the
161 * mouse device keeps moving and unfades the cursor.
162 * For touch events, we do not need to populate the cursor position.
163 */
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900164void PointerChoreographer::processTouchscreenAndStylusEventLocked(const NotifyMotionArgs& args) {
165 if (args.displayId == ADISPLAY_ID_NONE) {
166 return;
167 }
168
Byoungho Jungda10dd32023-10-06 17:03:45 +0900169 if (const auto it = mMousePointersByDisplay.find(args.displayId);
170 it != mMousePointersByDisplay.end() && args.action == AMOTION_EVENT_ACTION_DOWN) {
171 it->second->fade(PointerControllerInterface::Transition::GRADUAL);
172 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900173
174 if (!mShowTouchesEnabled) {
175 return;
176 }
177
178 // Get the touch pointer controller for the device, or create one if it doesn't exist.
Prabir Pradhan16788792023-11-08 21:07:21 +0000179 auto [it, _] = mTouchPointersByDevice.try_emplace(args.deviceId, mTouchControllerConstructor);
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900180
181 PointerControllerInterface& pc = *it->second;
182
183 const PointerCoords* coords = args.pointerCoords.data();
184 const int32_t maskedAction = MotionEvent::getActionMasked(args.action);
185 const uint8_t actionIndex = MotionEvent::getActionIndex(args.action);
186 std::array<uint32_t, MAX_POINTER_ID + 1> idToIndex;
187 BitSet32 idBits;
188 if (maskedAction != AMOTION_EVENT_ACTION_UP && maskedAction != AMOTION_EVENT_ACTION_CANCEL) {
189 for (size_t i = 0; i < args.getPointerCount(); i++) {
190 if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP && actionIndex == i) {
191 continue;
192 }
193 uint32_t id = args.pointerProperties[i].id;
194 idToIndex[id] = i;
195 idBits.markBit(id);
196 }
197 }
198 // The PointerController already handles setting spots per-display, so
199 // we do not need to manually manage display changes for touch spots for now.
200 pc.setSpots(coords, idToIndex.cbegin(), idBits, args.displayId);
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000201}
202
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900203void PointerChoreographer::processStylusHoverEventLocked(const NotifyMotionArgs& args) {
204 if (args.displayId == ADISPLAY_ID_NONE) {
205 return;
206 }
207
208 if (args.getPointerCount() != 1) {
209 LOG(WARNING) << "Only stylus hover events with a single pointer are currently supported: "
210 << args.dump();
211 }
212
213 // Get the stylus pointer controller for the device, or create one if it doesn't exist.
214 auto [it, _] =
215 mStylusPointersByDevice.try_emplace(args.deviceId,
216 getStylusControllerConstructor(args.displayId));
217
218 PointerControllerInterface& pc = *it->second;
219
220 const float x = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
221 const float y = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
222 pc.setPosition(x, y);
223 if (args.action == AMOTION_EVENT_ACTION_HOVER_EXIT) {
224 pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
Prabir Pradhan4b36db92024-01-03 20:56:57 +0000225 pc.updatePointerIcon(PointerIconStyle::TYPE_NOT_SPECIFIED);
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900226 } else {
227 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
228 }
229}
230
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000231void PointerChoreographer::notifySwitch(const NotifySwitchArgs& args) {
232 mNextListener.notify(args);
233}
234
235void PointerChoreographer::notifySensor(const NotifySensorArgs& args) {
236 mNextListener.notify(args);
237}
238
239void PointerChoreographer::notifyVibratorState(const NotifyVibratorStateArgs& args) {
240 mNextListener.notify(args);
241}
242
243void PointerChoreographer::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900244 processDeviceReset(args);
245
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000246 mNextListener.notify(args);
247}
248
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900249void PointerChoreographer::processDeviceReset(const NotifyDeviceResetArgs& args) {
250 std::scoped_lock _l(mLock);
Prabir Pradhan16788792023-11-08 21:07:21 +0000251 mTouchPointersByDevice.erase(args.deviceId);
252 mStylusPointersByDevice.erase(args.deviceId);
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900253}
254
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000255void PointerChoreographer::notifyPointerCaptureChanged(
256 const NotifyPointerCaptureChangedArgs& args) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900257 if (args.request.enable) {
258 std::scoped_lock _l(mLock);
259 for (const auto& [_, mousePointerController] : mMousePointersByDisplay) {
260 mousePointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
261 }
262 }
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000263 mNextListener.notify(args);
264}
265
266void PointerChoreographer::dump(std::string& dump) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900267 std::scoped_lock _l(mLock);
268
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000269 dump += "PointerChoreographer:\n";
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900270 dump += StringPrintf("show touches: %s\n", mShowTouchesEnabled ? "true" : "false");
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900271 dump += StringPrintf("stylus pointer icon enabled: %s\n",
272 mStylusPointerIconEnabled ? "true" : "false");
Byoungho Jungda10dd32023-10-06 17:03:45 +0900273
274 dump += INDENT "MousePointerControllers:\n";
275 for (const auto& [displayId, mousePointerController] : mMousePointersByDisplay) {
276 std::string pointerControllerDump = addLinePrefix(mousePointerController->dump(), INDENT);
277 dump += INDENT + std::to_string(displayId) + " : " + pointerControllerDump;
278 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900279 dump += INDENT "TouchPointerControllers:\n";
280 for (const auto& [deviceId, touchPointerController] : mTouchPointersByDevice) {
281 std::string pointerControllerDump = addLinePrefix(touchPointerController->dump(), INDENT);
282 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
283 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900284 dump += INDENT "StylusPointerControllers:\n";
285 for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
286 std::string pointerControllerDump = addLinePrefix(stylusPointerController->dump(), INDENT);
287 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
288 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900289 dump += "\n";
290}
291
292const DisplayViewport* PointerChoreographer::findViewportByIdLocked(int32_t displayId) const {
293 for (auto& viewport : mViewports) {
294 if (viewport.displayId == displayId) {
295 return &viewport;
296 }
297 }
298 return nullptr;
299}
300
301int32_t PointerChoreographer::getTargetMouseDisplayLocked(int32_t associatedDisplayId) const {
302 return associatedDisplayId == ADISPLAY_ID_NONE ? mDefaultMouseDisplayId : associatedDisplayId;
303}
304
Byoungho Jungee6268f2023-10-30 17:27:26 +0900305std::pair<int32_t, PointerControllerInterface&>
306PointerChoreographer::getDisplayIdAndMouseControllerLocked(int32_t associatedDisplayId) {
307 const int32_t displayId = getTargetMouseDisplayLocked(associatedDisplayId);
308
309 // Get the mouse pointer controller for the display, or create one if it doesn't exist.
310 auto [it, emplaced] =
311 mMousePointersByDisplay.try_emplace(displayId,
312 getMouseControllerConstructor(displayId));
313 if (emplaced) {
314 notifyPointerDisplayIdChangedLocked();
315 }
316
317 return {displayId, *it->second};
318}
319
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900320InputDeviceInfo* PointerChoreographer::findInputDeviceLocked(DeviceId deviceId) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000321 auto it = std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
322 [deviceId](const auto& info) { return info.getId() == deviceId; });
323 return it != mInputDeviceInfos.end() ? &(*it) : nullptr;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900324}
325
Byoungho Jungda10dd32023-10-06 17:03:45 +0900326void PointerChoreographer::updatePointerControllersLocked() {
327 std::set<int32_t /*displayId*/> mouseDisplaysToKeep;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900328 std::set<DeviceId> touchDevicesToKeep;
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900329 std::set<DeviceId> stylusDevicesToKeep;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900330
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000331 // Mark the displayIds or deviceIds of PointerControllers currently needed, and create
332 // new PointerControllers if necessary.
Byoungho Jungda10dd32023-10-06 17:03:45 +0900333 for (const auto& info : mInputDeviceInfos) {
334 const uint32_t sources = info.getSources();
335 if (isFromSource(sources, AINPUT_SOURCE_MOUSE) ||
336 isFromSource(sources, AINPUT_SOURCE_MOUSE_RELATIVE)) {
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000337 const int32_t displayId = getTargetMouseDisplayLocked(info.getAssociatedDisplayId());
338 mouseDisplaysToKeep.insert(displayId);
339 // For mice, show the cursor immediately when the device is first connected or
340 // when it moves to a new display.
341 auto [mousePointerIt, isNewMousePointer] =
342 mMousePointersByDisplay.try_emplace(displayId,
343 getMouseControllerConstructor(displayId));
344 auto [_, isNewMouseDevice] = mMouseDevices.emplace(info.getId());
345 if (isNewMouseDevice || isNewMousePointer) {
346 mousePointerIt->second->unfade(PointerControllerInterface::Transition::IMMEDIATE);
347 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900348 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900349 if (isFromSource(sources, AINPUT_SOURCE_TOUCHSCREEN) && mShowTouchesEnabled &&
350 info.getAssociatedDisplayId() != ADISPLAY_ID_NONE) {
351 touchDevicesToKeep.insert(info.getId());
352 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900353 if (isFromSource(sources, AINPUT_SOURCE_STYLUS) && mStylusPointerIconEnabled &&
354 info.getAssociatedDisplayId() != ADISPLAY_ID_NONE) {
355 stylusDevicesToKeep.insert(info.getId());
356 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900357 }
358
359 // Remove PointerControllers no longer needed.
Prabir Pradhan19767602023-11-03 16:53:31 +0000360 std::erase_if(mMousePointersByDisplay, [&mouseDisplaysToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000361 return mouseDisplaysToKeep.find(pair.first) == mouseDisplaysToKeep.end();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900362 });
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900363 std::erase_if(mTouchPointersByDevice, [&touchDevicesToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000364 return touchDevicesToKeep.find(pair.first) == touchDevicesToKeep.end();
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900365 });
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900366 std::erase_if(mStylusPointersByDevice, [&stylusDevicesToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000367 return stylusDevicesToKeep.find(pair.first) == stylusDevicesToKeep.end();
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900368 });
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000369 std::erase_if(mMouseDevices, [&](DeviceId id) REQUIRES(mLock) {
370 return std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
371 [id](const auto& info) { return info.getId() == id; }) ==
372 mInputDeviceInfos.end();
373 });
Byoungho Jungda10dd32023-10-06 17:03:45 +0900374
375 // Notify the policy if there's a change on the pointer display ID.
376 notifyPointerDisplayIdChangedLocked();
377}
378
379void PointerChoreographer::notifyPointerDisplayIdChangedLocked() {
380 int32_t displayIdToNotify = ADISPLAY_ID_NONE;
381 FloatPoint cursorPosition = {0, 0};
382 if (const auto it = mMousePointersByDisplay.find(mDefaultMouseDisplayId);
383 it != mMousePointersByDisplay.end()) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000384 const auto& pointerController = it->second;
385 // Use the displayId from the pointerController, because it accurately reflects whether
386 // the viewport has been added for that display. Otherwise, we would have to check if
387 // the viewport exists separately.
388 displayIdToNotify = pointerController->getDisplayId();
389 cursorPosition = pointerController->getPosition();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900390 }
391
392 if (mNotifiedPointerDisplayId == displayIdToNotify) {
393 return;
394 }
395 mPolicy.notifyPointerDisplayIdChanged(displayIdToNotify, cursorPosition);
396 mNotifiedPointerDisplayId = displayIdToNotify;
397}
398
399void PointerChoreographer::setDefaultMouseDisplayId(int32_t displayId) {
400 std::scoped_lock _l(mLock);
401
402 mDefaultMouseDisplayId = displayId;
403 updatePointerControllersLocked();
404}
405
406void PointerChoreographer::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
407 std::scoped_lock _l(mLock);
408 for (const auto& viewport : viewports) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900409 const int32_t displayId = viewport.displayId;
410 if (const auto it = mMousePointersByDisplay.find(displayId);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900411 it != mMousePointersByDisplay.end()) {
412 it->second->setDisplayViewport(viewport);
413 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900414 for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
415 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
416 if (info && info->getAssociatedDisplayId() == displayId) {
417 stylusPointerController->setDisplayViewport(viewport);
418 }
419 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900420 }
421 mViewports = viewports;
422 notifyPointerDisplayIdChangedLocked();
423}
424
425std::optional<DisplayViewport> PointerChoreographer::getViewportForPointerDevice(
426 int32_t associatedDisplayId) {
427 std::scoped_lock _l(mLock);
428 const int32_t resolvedDisplayId = getTargetMouseDisplayLocked(associatedDisplayId);
429 if (const auto viewport = findViewportByIdLocked(resolvedDisplayId); viewport) {
430 return *viewport;
431 }
432 return std::nullopt;
433}
434
435FloatPoint PointerChoreographer::getMouseCursorPosition(int32_t displayId) {
436 std::scoped_lock _l(mLock);
437 const int32_t resolvedDisplayId = getTargetMouseDisplayLocked(displayId);
438 if (auto it = mMousePointersByDisplay.find(resolvedDisplayId);
439 it != mMousePointersByDisplay.end()) {
440 return it->second->getPosition();
441 }
442 return {AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION};
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000443}
444
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900445void PointerChoreographer::setShowTouchesEnabled(bool enabled) {
446 std::scoped_lock _l(mLock);
447 if (mShowTouchesEnabled == enabled) {
448 return;
449 }
450 mShowTouchesEnabled = enabled;
451 updatePointerControllersLocked();
452}
453
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900454void PointerChoreographer::setStylusPointerIconEnabled(bool enabled) {
455 std::scoped_lock _l(mLock);
456 if (mStylusPointerIconEnabled == enabled) {
457 return;
458 }
459 mStylusPointerIconEnabled = enabled;
460 updatePointerControllersLocked();
461}
462
Byoungho Jung99326452023-11-03 20:19:17 +0900463bool PointerChoreographer::setPointerIcon(
464 std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon, int32_t displayId,
465 DeviceId deviceId) {
466 std::scoped_lock _l(mLock);
467 if (deviceId < 0) {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000468 LOG(WARNING) << "Invalid device id " << deviceId << ". Cannot set pointer icon.";
Byoungho Jung99326452023-11-03 20:19:17 +0900469 return false;
470 }
471 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
472 if (!info) {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000473 LOG(WARNING) << "No input device info found for id " << deviceId
474 << ". Cannot set pointer icon.";
Byoungho Jung99326452023-11-03 20:19:17 +0900475 return false;
476 }
477 const uint32_t sources = info->getSources();
478 const auto stylusPointerIt = mStylusPointersByDevice.find(deviceId);
479
480 if (isFromSource(sources, AINPUT_SOURCE_STYLUS) &&
481 stylusPointerIt != mStylusPointersByDevice.end()) {
482 if (std::holds_alternative<std::unique_ptr<SpriteIcon>>(icon)) {
483 if (std::get<std::unique_ptr<SpriteIcon>>(icon) == nullptr) {
484 LOG(FATAL) << "SpriteIcon should not be null";
485 }
486 stylusPointerIt->second->setCustomPointerIcon(
487 *std::get<std::unique_ptr<SpriteIcon>>(icon));
488 } else {
489 stylusPointerIt->second->updatePointerIcon(std::get<PointerIconStyle>(icon));
490 }
491 } else if (isFromSource(sources, AINPUT_SOURCE_MOUSE)) {
492 if (const auto mousePointerIt = mMousePointersByDisplay.find(displayId);
493 mousePointerIt != mMousePointersByDisplay.end()) {
494 if (std::holds_alternative<std::unique_ptr<SpriteIcon>>(icon)) {
495 if (std::get<std::unique_ptr<SpriteIcon>>(icon) == nullptr) {
496 LOG(FATAL) << "SpriteIcon should not be null";
497 }
498 mousePointerIt->second->setCustomPointerIcon(
499 *std::get<std::unique_ptr<SpriteIcon>>(icon));
500 } else {
501 mousePointerIt->second->updatePointerIcon(std::get<PointerIconStyle>(icon));
502 }
503 } else {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000504 LOG(WARNING) << "No mouse pointer controller found for display " << displayId
505 << ", device " << deviceId << ".";
Byoungho Jung99326452023-11-03 20:19:17 +0900506 return false;
507 }
508 } else {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000509 LOG(WARNING) << "Cannot set pointer icon for display " << displayId << ", device "
510 << deviceId << ".";
Byoungho Jung99326452023-11-03 20:19:17 +0900511 return false;
512 }
513 return true;
514}
515
Prabir Pradhan19767602023-11-03 16:53:31 +0000516PointerChoreographer::ControllerConstructor PointerChoreographer::getMouseControllerConstructor(
517 int32_t displayId) {
518 std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
519 [this, displayId]() REQUIRES(mLock) {
520 auto pc = mPolicy.createPointerController(
521 PointerControllerInterface::ControllerType::MOUSE);
522 if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
523 pc->setDisplayViewport(*viewport);
524 }
525 return pc;
526 };
527 return ConstructorDelegate(std::move(ctor));
528}
529
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900530PointerChoreographer::ControllerConstructor PointerChoreographer::getStylusControllerConstructor(
531 int32_t displayId) {
532 std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
533 [this, displayId]() REQUIRES(mLock) {
534 auto pc = mPolicy.createPointerController(
535 PointerControllerInterface::ControllerType::STYLUS);
536 if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
537 pc->setDisplayViewport(*viewport);
538 }
539 return pc;
540 };
541 return ConstructorDelegate(std::move(ctor));
542}
543
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000544} // namespace android