blob: 0be4c327b70af3e141c0d037ba4caa0c0b0ae478 [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);
225 } else {
226 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
227 }
228}
229
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000230void PointerChoreographer::notifySwitch(const NotifySwitchArgs& args) {
231 mNextListener.notify(args);
232}
233
234void PointerChoreographer::notifySensor(const NotifySensorArgs& args) {
235 mNextListener.notify(args);
236}
237
238void PointerChoreographer::notifyVibratorState(const NotifyVibratorStateArgs& args) {
239 mNextListener.notify(args);
240}
241
242void PointerChoreographer::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900243 processDeviceReset(args);
244
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000245 mNextListener.notify(args);
246}
247
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900248void PointerChoreographer::processDeviceReset(const NotifyDeviceResetArgs& args) {
249 std::scoped_lock _l(mLock);
Prabir Pradhan16788792023-11-08 21:07:21 +0000250 mTouchPointersByDevice.erase(args.deviceId);
251 mStylusPointersByDevice.erase(args.deviceId);
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900252}
253
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000254void PointerChoreographer::notifyPointerCaptureChanged(
255 const NotifyPointerCaptureChangedArgs& args) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900256 if (args.request.enable) {
257 std::scoped_lock _l(mLock);
258 for (const auto& [_, mousePointerController] : mMousePointersByDisplay) {
259 mousePointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
260 }
261 }
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000262 mNextListener.notify(args);
263}
264
265void PointerChoreographer::dump(std::string& dump) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900266 std::scoped_lock _l(mLock);
267
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000268 dump += "PointerChoreographer:\n";
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900269 dump += StringPrintf("show touches: %s\n", mShowTouchesEnabled ? "true" : "false");
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900270 dump += StringPrintf("stylus pointer icon enabled: %s\n",
271 mStylusPointerIconEnabled ? "true" : "false");
Byoungho Jungda10dd32023-10-06 17:03:45 +0900272
273 dump += INDENT "MousePointerControllers:\n";
274 for (const auto& [displayId, mousePointerController] : mMousePointersByDisplay) {
275 std::string pointerControllerDump = addLinePrefix(mousePointerController->dump(), INDENT);
276 dump += INDENT + std::to_string(displayId) + " : " + pointerControllerDump;
277 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900278 dump += INDENT "TouchPointerControllers:\n";
279 for (const auto& [deviceId, touchPointerController] : mTouchPointersByDevice) {
280 std::string pointerControllerDump = addLinePrefix(touchPointerController->dump(), INDENT);
281 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
282 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900283 dump += INDENT "StylusPointerControllers:\n";
284 for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
285 std::string pointerControllerDump = addLinePrefix(stylusPointerController->dump(), INDENT);
286 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
287 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900288 dump += "\n";
289}
290
291const DisplayViewport* PointerChoreographer::findViewportByIdLocked(int32_t displayId) const {
292 for (auto& viewport : mViewports) {
293 if (viewport.displayId == displayId) {
294 return &viewport;
295 }
296 }
297 return nullptr;
298}
299
300int32_t PointerChoreographer::getTargetMouseDisplayLocked(int32_t associatedDisplayId) const {
301 return associatedDisplayId == ADISPLAY_ID_NONE ? mDefaultMouseDisplayId : associatedDisplayId;
302}
303
Byoungho Jungee6268f2023-10-30 17:27:26 +0900304std::pair<int32_t, PointerControllerInterface&>
305PointerChoreographer::getDisplayIdAndMouseControllerLocked(int32_t associatedDisplayId) {
306 const int32_t displayId = getTargetMouseDisplayLocked(associatedDisplayId);
307
308 // Get the mouse pointer controller for the display, or create one if it doesn't exist.
309 auto [it, emplaced] =
310 mMousePointersByDisplay.try_emplace(displayId,
311 getMouseControllerConstructor(displayId));
312 if (emplaced) {
313 notifyPointerDisplayIdChangedLocked();
314 }
315
316 return {displayId, *it->second};
317}
318
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900319InputDeviceInfo* PointerChoreographer::findInputDeviceLocked(DeviceId deviceId) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000320 auto it = std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
321 [deviceId](const auto& info) { return info.getId() == deviceId; });
322 return it != mInputDeviceInfos.end() ? &(*it) : nullptr;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900323}
324
Byoungho Jungda10dd32023-10-06 17:03:45 +0900325void PointerChoreographer::updatePointerControllersLocked() {
326 std::set<int32_t /*displayId*/> mouseDisplaysToKeep;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900327 std::set<DeviceId> touchDevicesToKeep;
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900328 std::set<DeviceId> stylusDevicesToKeep;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900329
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000330 // Mark the displayIds or deviceIds of PointerControllers currently needed, and create
331 // new PointerControllers if necessary.
Byoungho Jungda10dd32023-10-06 17:03:45 +0900332 for (const auto& info : mInputDeviceInfos) {
333 const uint32_t sources = info.getSources();
334 if (isFromSource(sources, AINPUT_SOURCE_MOUSE) ||
335 isFromSource(sources, AINPUT_SOURCE_MOUSE_RELATIVE)) {
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000336 const int32_t displayId = getTargetMouseDisplayLocked(info.getAssociatedDisplayId());
337 mouseDisplaysToKeep.insert(displayId);
338 // For mice, show the cursor immediately when the device is first connected or
339 // when it moves to a new display.
340 auto [mousePointerIt, isNewMousePointer] =
341 mMousePointersByDisplay.try_emplace(displayId,
342 getMouseControllerConstructor(displayId));
343 auto [_, isNewMouseDevice] = mMouseDevices.emplace(info.getId());
344 if (isNewMouseDevice || isNewMousePointer) {
345 mousePointerIt->second->unfade(PointerControllerInterface::Transition::IMMEDIATE);
346 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900347 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900348 if (isFromSource(sources, AINPUT_SOURCE_TOUCHSCREEN) && mShowTouchesEnabled &&
349 info.getAssociatedDisplayId() != ADISPLAY_ID_NONE) {
350 touchDevicesToKeep.insert(info.getId());
351 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900352 if (isFromSource(sources, AINPUT_SOURCE_STYLUS) && mStylusPointerIconEnabled &&
353 info.getAssociatedDisplayId() != ADISPLAY_ID_NONE) {
354 stylusDevicesToKeep.insert(info.getId());
355 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900356 }
357
358 // Remove PointerControllers no longer needed.
Prabir Pradhan19767602023-11-03 16:53:31 +0000359 std::erase_if(mMousePointersByDisplay, [&mouseDisplaysToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000360 return mouseDisplaysToKeep.find(pair.first) == mouseDisplaysToKeep.end();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900361 });
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900362 std::erase_if(mTouchPointersByDevice, [&touchDevicesToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000363 return touchDevicesToKeep.find(pair.first) == touchDevicesToKeep.end();
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900364 });
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900365 std::erase_if(mStylusPointersByDevice, [&stylusDevicesToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000366 return stylusDevicesToKeep.find(pair.first) == stylusDevicesToKeep.end();
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900367 });
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000368 std::erase_if(mMouseDevices, [&](DeviceId id) REQUIRES(mLock) {
369 return std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
370 [id](const auto& info) { return info.getId() == id; }) ==
371 mInputDeviceInfos.end();
372 });
Byoungho Jungda10dd32023-10-06 17:03:45 +0900373
374 // Notify the policy if there's a change on the pointer display ID.
375 notifyPointerDisplayIdChangedLocked();
376}
377
378void PointerChoreographer::notifyPointerDisplayIdChangedLocked() {
379 int32_t displayIdToNotify = ADISPLAY_ID_NONE;
380 FloatPoint cursorPosition = {0, 0};
381 if (const auto it = mMousePointersByDisplay.find(mDefaultMouseDisplayId);
382 it != mMousePointersByDisplay.end()) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000383 const auto& pointerController = it->second;
384 // Use the displayId from the pointerController, because it accurately reflects whether
385 // the viewport has been added for that display. Otherwise, we would have to check if
386 // the viewport exists separately.
387 displayIdToNotify = pointerController->getDisplayId();
388 cursorPosition = pointerController->getPosition();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900389 }
390
391 if (mNotifiedPointerDisplayId == displayIdToNotify) {
392 return;
393 }
394 mPolicy.notifyPointerDisplayIdChanged(displayIdToNotify, cursorPosition);
395 mNotifiedPointerDisplayId = displayIdToNotify;
396}
397
398void PointerChoreographer::setDefaultMouseDisplayId(int32_t displayId) {
399 std::scoped_lock _l(mLock);
400
401 mDefaultMouseDisplayId = displayId;
402 updatePointerControllersLocked();
403}
404
405void PointerChoreographer::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
406 std::scoped_lock _l(mLock);
407 for (const auto& viewport : viewports) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900408 const int32_t displayId = viewport.displayId;
409 if (const auto it = mMousePointersByDisplay.find(displayId);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900410 it != mMousePointersByDisplay.end()) {
411 it->second->setDisplayViewport(viewport);
412 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900413 for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
414 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
415 if (info && info->getAssociatedDisplayId() == displayId) {
416 stylusPointerController->setDisplayViewport(viewport);
417 }
418 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900419 }
420 mViewports = viewports;
421 notifyPointerDisplayIdChangedLocked();
422}
423
424std::optional<DisplayViewport> PointerChoreographer::getViewportForPointerDevice(
425 int32_t associatedDisplayId) {
426 std::scoped_lock _l(mLock);
427 const int32_t resolvedDisplayId = getTargetMouseDisplayLocked(associatedDisplayId);
428 if (const auto viewport = findViewportByIdLocked(resolvedDisplayId); viewport) {
429 return *viewport;
430 }
431 return std::nullopt;
432}
433
434FloatPoint PointerChoreographer::getMouseCursorPosition(int32_t displayId) {
435 std::scoped_lock _l(mLock);
436 const int32_t resolvedDisplayId = getTargetMouseDisplayLocked(displayId);
437 if (auto it = mMousePointersByDisplay.find(resolvedDisplayId);
438 it != mMousePointersByDisplay.end()) {
439 return it->second->getPosition();
440 }
441 return {AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION};
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000442}
443
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900444void PointerChoreographer::setShowTouchesEnabled(bool enabled) {
445 std::scoped_lock _l(mLock);
446 if (mShowTouchesEnabled == enabled) {
447 return;
448 }
449 mShowTouchesEnabled = enabled;
450 updatePointerControllersLocked();
451}
452
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900453void PointerChoreographer::setStylusPointerIconEnabled(bool enabled) {
454 std::scoped_lock _l(mLock);
455 if (mStylusPointerIconEnabled == enabled) {
456 return;
457 }
458 mStylusPointerIconEnabled = enabled;
459 updatePointerControllersLocked();
460}
461
Byoungho Jung99326452023-11-03 20:19:17 +0900462bool PointerChoreographer::setPointerIcon(
463 std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon, int32_t displayId,
464 DeviceId deviceId) {
465 std::scoped_lock _l(mLock);
466 if (deviceId < 0) {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000467 LOG(WARNING) << "Invalid device id " << deviceId << ". Cannot set pointer icon.";
Byoungho Jung99326452023-11-03 20:19:17 +0900468 return false;
469 }
470 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
471 if (!info) {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000472 LOG(WARNING) << "No input device info found for id " << deviceId
473 << ". Cannot set pointer icon.";
Byoungho Jung99326452023-11-03 20:19:17 +0900474 return false;
475 }
476 const uint32_t sources = info->getSources();
477 const auto stylusPointerIt = mStylusPointersByDevice.find(deviceId);
478
479 if (isFromSource(sources, AINPUT_SOURCE_STYLUS) &&
480 stylusPointerIt != mStylusPointersByDevice.end()) {
481 if (std::holds_alternative<std::unique_ptr<SpriteIcon>>(icon)) {
482 if (std::get<std::unique_ptr<SpriteIcon>>(icon) == nullptr) {
483 LOG(FATAL) << "SpriteIcon should not be null";
484 }
485 stylusPointerIt->second->setCustomPointerIcon(
486 *std::get<std::unique_ptr<SpriteIcon>>(icon));
487 } else {
488 stylusPointerIt->second->updatePointerIcon(std::get<PointerIconStyle>(icon));
489 }
490 } else if (isFromSource(sources, AINPUT_SOURCE_MOUSE)) {
491 if (const auto mousePointerIt = mMousePointersByDisplay.find(displayId);
492 mousePointerIt != mMousePointersByDisplay.end()) {
493 if (std::holds_alternative<std::unique_ptr<SpriteIcon>>(icon)) {
494 if (std::get<std::unique_ptr<SpriteIcon>>(icon) == nullptr) {
495 LOG(FATAL) << "SpriteIcon should not be null";
496 }
497 mousePointerIt->second->setCustomPointerIcon(
498 *std::get<std::unique_ptr<SpriteIcon>>(icon));
499 } else {
500 mousePointerIt->second->updatePointerIcon(std::get<PointerIconStyle>(icon));
501 }
502 } else {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000503 LOG(WARNING) << "No mouse pointer controller found for display " << displayId
504 << ", device " << deviceId << ".";
Byoungho Jung99326452023-11-03 20:19:17 +0900505 return false;
506 }
507 } else {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000508 LOG(WARNING) << "Cannot set pointer icon for display " << displayId << ", device "
509 << deviceId << ".";
Byoungho Jung99326452023-11-03 20:19:17 +0900510 return false;
511 }
512 return true;
513}
514
Prabir Pradhan19767602023-11-03 16:53:31 +0000515PointerChoreographer::ControllerConstructor PointerChoreographer::getMouseControllerConstructor(
516 int32_t displayId) {
517 std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
518 [this, displayId]() REQUIRES(mLock) {
519 auto pc = mPolicy.createPointerController(
520 PointerControllerInterface::ControllerType::MOUSE);
521 if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
522 pc->setDisplayViewport(*viewport);
523 }
524 return pc;
525 };
526 return ConstructorDelegate(std::move(ctor));
527}
528
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900529PointerChoreographer::ControllerConstructor PointerChoreographer::getStylusControllerConstructor(
530 int32_t displayId) {
531 std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
532 [this, displayId]() REQUIRES(mLock) {
533 auto pc = mPolicy.createPointerController(
534 PointerControllerInterface::ControllerType::STYLUS);
535 if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
536 pc->setDisplayViewport(*viewport);
537 }
538 return pc;
539 };
540 return ConstructorDelegate(std::move(ctor));
541}
542
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000543} // namespace android