1 /*
2 * Copyright (C) 2019 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 // clang-format off
18 #include "../Macros.h"
19 // clang-format on
20
21 #include "CursorInputMapper.h"
22
23 #include <optional>
24
25 #include <com_android_input_flags.h>
26 #include <ftl/enum.h>
27 #include <input/AccelerationCurve.h>
28
29 #include "CursorButtonAccumulator.h"
30 #include "CursorScrollAccumulator.h"
31 #include "PointerControllerInterface.h"
32 #include "TouchCursorInputMapperCommon.h"
33
34 #include "input/PrintTools.h"
35
36 namespace input_flags = com::android::input::flags;
37
38 namespace android {
39
40 // The default velocity control parameters that has no effect.
41 static const VelocityControlParameters FLAT_VELOCITY_CONTROL_PARAMS{};
42
43 // --- CursorMotionAccumulator ---
44
CursorMotionAccumulator()45 CursorMotionAccumulator::CursorMotionAccumulator() {
46 clearRelativeAxes();
47 }
48
reset(InputDeviceContext & deviceContext)49 void CursorMotionAccumulator::reset(InputDeviceContext& deviceContext) {
50 clearRelativeAxes();
51 }
52
clearRelativeAxes()53 void CursorMotionAccumulator::clearRelativeAxes() {
54 mRelX = 0;
55 mRelY = 0;
56 }
57
process(const RawEvent & rawEvent)58 void CursorMotionAccumulator::process(const RawEvent& rawEvent) {
59 if (rawEvent.type == EV_REL) {
60 switch (rawEvent.code) {
61 case REL_X:
62 mRelX = rawEvent.value;
63 break;
64 case REL_Y:
65 mRelY = rawEvent.value;
66 break;
67 }
68 }
69 }
70
finishSync()71 void CursorMotionAccumulator::finishSync() {
72 clearRelativeAxes();
73 }
74
75 // --- CursorInputMapper ---
76
CursorInputMapper(InputDeviceContext & deviceContext,const InputReaderConfiguration & readerConfig)77 CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext,
78 const InputReaderConfiguration& readerConfig)
79 : InputMapper(deviceContext, readerConfig),
80 mLastEventTime(std::numeric_limits<nsecs_t>::min()),
81 mEnableNewMousePointerBallistics(input_flags::enable_new_mouse_pointer_ballistics()) {}
82
getSources() const83 uint32_t CursorInputMapper::getSources() const {
84 return mSource;
85 }
86
populateDeviceInfo(InputDeviceInfo & info)87 void CursorInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
88 InputMapper::populateDeviceInfo(info);
89
90 if (mParameters.mode == Parameters::Mode::POINTER) {
91 if (!mBoundsInLogicalDisplay.isEmpty()) {
92 info.addMotionRange(AMOTION_EVENT_AXIS_X, mSource, mBoundsInLogicalDisplay.left,
93 mBoundsInLogicalDisplay.right, 0.0f, 0.0f, 0.0f);
94 info.addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, mBoundsInLogicalDisplay.top,
95 mBoundsInLogicalDisplay.bottom, 0.0f, 0.0f, 0.0f);
96 }
97 } else {
98 info.addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
99 info.addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
100 info.addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, mSource, -1.0f, 1.0f, 0.0f, mXScale,
101 0.0f);
102 info.addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale,
103 0.0f);
104 }
105 info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
106
107 if (mCursorScrollAccumulator.haveRelativeVWheel()) {
108 info.addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
109 }
110 if (mCursorScrollAccumulator.haveRelativeHWheel()) {
111 info.addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
112 }
113 }
114
dump(std::string & dump)115 void CursorInputMapper::dump(std::string& dump) {
116 dump += INDENT2 "Cursor Input Mapper:\n";
117 dumpParameters(dump);
118 dump += StringPrintf(INDENT3 "XScale: %0.3f\n", mXScale);
119 dump += StringPrintf(INDENT3 "YScale: %0.3f\n", mYScale);
120 dump += StringPrintf(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
121 dump += StringPrintf(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
122 dump += StringPrintf(INDENT3 "HaveVWheel: %s\n",
123 toString(mCursorScrollAccumulator.haveRelativeVWheel()));
124 dump += StringPrintf(INDENT3 "HaveHWheel: %s\n",
125 toString(mCursorScrollAccumulator.haveRelativeHWheel()));
126 dump += StringPrintf(INDENT3 "WheelYVelocityControlParameters: %s",
127 mWheelYVelocityControl.getParameters().dump().c_str());
128 dump += StringPrintf(INDENT3 "WheelXVelocityControlParameters: %s",
129 mWheelXVelocityControl.getParameters().dump().c_str());
130 dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
131 dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
132 dump += StringPrintf(INDENT3 "DisplayId: %s\n",
133 toString(mDisplayId, streamableToString).c_str());
134 dump += StringPrintf(INDENT3 "Orientation: %s\n", ftl::enum_string(mOrientation).c_str());
135 dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
136 dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
137 dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
138 }
139
reconfigure(nsecs_t when,const InputReaderConfiguration & readerConfig,ConfigurationChanges changes)140 std::list<NotifyArgs> CursorInputMapper::reconfigure(nsecs_t when,
141 const InputReaderConfiguration& readerConfig,
142 ConfigurationChanges changes) {
143 std::list<NotifyArgs> out = InputMapper::reconfigure(when, readerConfig, changes);
144
145 if (!changes.any()) { // first time only
146 configureBasicParams();
147 }
148
149 const bool configurePointerCapture = !changes.any() ||
150 (mParameters.mode != Parameters::Mode::NAVIGATION &&
151 changes.test(InputReaderConfiguration::Change::POINTER_CAPTURE));
152 if (configurePointerCapture) {
153 configureOnPointerCapture(readerConfig);
154 out.push_back(NotifyDeviceResetArgs(getContext()->getNextId(), when, getDeviceId()));
155 }
156
157 if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO) ||
158 configurePointerCapture) {
159 configureOnChangeDisplayInfo(readerConfig);
160 }
161
162 // Pointer speed settings depend on display settings.
163 if (!changes.any() || changes.test(InputReaderConfiguration::Change::POINTER_SPEED) ||
164 changes.test(InputReaderConfiguration::Change::DISPLAY_INFO) || configurePointerCapture) {
165 configureOnChangePointerSpeed(readerConfig);
166 }
167 return out;
168 }
169
computeParameters(const InputDeviceContext & deviceContext)170 CursorInputMapper::Parameters CursorInputMapper::computeParameters(
171 const InputDeviceContext& deviceContext) {
172 Parameters parameters;
173 parameters.mode = Parameters::Mode::POINTER;
174 const PropertyMap& config = deviceContext.getConfiguration();
175 std::optional<std::string> cursorModeString = config.getString("cursor.mode");
176 if (cursorModeString.has_value()) {
177 if (*cursorModeString == "navigation") {
178 parameters.mode = Parameters::Mode::NAVIGATION;
179 } else if (*cursorModeString != "pointer" && *cursorModeString != "default") {
180 ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString->c_str());
181 }
182 }
183
184 parameters.orientationAware = config.getBool("cursor.orientationAware").value_or(false);
185
186 parameters.hasAssociatedDisplay = false;
187 if (parameters.mode == Parameters::Mode::POINTER || parameters.orientationAware) {
188 parameters.hasAssociatedDisplay = true;
189 }
190 return parameters;
191 }
192
dumpParameters(std::string & dump)193 void CursorInputMapper::dumpParameters(std::string& dump) {
194 dump += INDENT3 "Parameters:\n";
195 dump += StringPrintf(INDENT4 "HasAssociatedDisplay: %s\n",
196 toString(mParameters.hasAssociatedDisplay));
197 dump += StringPrintf(INDENT4 "Mode: %s\n", ftl::enum_string(mParameters.mode).c_str());
198 dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
199 }
200
reset(nsecs_t when)201 std::list<NotifyArgs> CursorInputMapper::reset(nsecs_t when) {
202 mButtonState = 0;
203 mDownTime = 0;
204 mLastEventTime = std::numeric_limits<nsecs_t>::min();
205
206 mOldPointerVelocityControl.reset();
207 mNewPointerVelocityControl.reset();
208 mWheelXVelocityControl.reset();
209 mWheelYVelocityControl.reset();
210
211 mCursorButtonAccumulator.reset(getDeviceContext());
212 mCursorMotionAccumulator.reset(getDeviceContext());
213 mCursorScrollAccumulator.reset(getDeviceContext());
214
215 return InputMapper::reset(when);
216 }
217
process(const RawEvent & rawEvent)218 std::list<NotifyArgs> CursorInputMapper::process(const RawEvent& rawEvent) {
219 std::list<NotifyArgs> out;
220 mCursorButtonAccumulator.process(rawEvent);
221 mCursorMotionAccumulator.process(rawEvent);
222 mCursorScrollAccumulator.process(rawEvent);
223
224 if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) {
225 const auto [eventTime, readTime] =
226 applyBluetoothTimestampSmoothening(getDeviceContext().getDeviceIdentifier(),
227 rawEvent.when, rawEvent.readTime,
228 mLastEventTime);
229 out += sync(eventTime, readTime);
230 mLastEventTime = eventTime;
231 }
232 return out;
233 }
234
sync(nsecs_t when,nsecs_t readTime)235 std::list<NotifyArgs> CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
236 std::list<NotifyArgs> out;
237 if (!mDisplayId) {
238 // Ignore events when there is no target display configured.
239 return out;
240 }
241
242 int32_t lastButtonState = mButtonState;
243 int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
244 mButtonState = currentButtonState;
245
246 bool wasDown = isPointerDown(lastButtonState);
247 bool down = isPointerDown(currentButtonState);
248 bool downChanged;
249 if (!wasDown && down) {
250 mDownTime = when;
251 downChanged = true;
252 } else if (wasDown && !down) {
253 downChanged = true;
254 } else {
255 downChanged = false;
256 }
257 nsecs_t downTime = mDownTime;
258 bool buttonsChanged = currentButtonState != lastButtonState;
259 int32_t buttonsPressed = currentButtonState & ~lastButtonState;
260 int32_t buttonsReleased = lastButtonState & ~currentButtonState;
261
262 float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
263 float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
264 bool moved = deltaX != 0 || deltaY != 0;
265
266 // Rotate delta according to orientation.
267 rotateDelta(mOrientation, &deltaX, &deltaY);
268
269 // Move the pointer.
270 PointerProperties pointerProperties;
271 pointerProperties.clear();
272 pointerProperties.id = 0;
273 pointerProperties.toolType = ToolType::MOUSE;
274
275 PointerCoords pointerCoords;
276 pointerCoords.clear();
277
278 float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
279 float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
280 bool scrolled = vscroll != 0 || hscroll != 0;
281
282 mWheelYVelocityControl.move(when, nullptr, &vscroll);
283 mWheelXVelocityControl.move(when, &hscroll, nullptr);
284
285 if (mEnableNewMousePointerBallistics) {
286 mNewPointerVelocityControl.move(when, &deltaX, &deltaY);
287 } else {
288 mOldPointerVelocityControl.move(when, &deltaX, &deltaY);
289 }
290
291 float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
292 float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
293 if (mSource == AINPUT_SOURCE_MOUSE) {
294 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
295 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
296 } else {
297 // Pointer capture and navigation modes
298 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
299 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
300 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
301 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
302 }
303
304 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
305
306 // Moving an external trackball or mouse should wake the device.
307 // We don't do this for internal cursor devices to prevent them from waking up
308 // the device in your pocket.
309 // TODO: Use the input device configuration to control this behavior more finely.
310 uint32_t policyFlags = 0;
311 if ((buttonsPressed || moved || scrolled) && getDeviceContext().isExternal()) {
312 policyFlags |= POLICY_FLAG_WAKE;
313 }
314
315 // Synthesize key down from buttons if needed.
316 out += synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, readTime, getDeviceId(),
317 mSource, *mDisplayId, policyFlags, lastButtonState,
318 currentButtonState);
319
320 // Send motion event.
321 if (downChanged || moved || scrolled || buttonsChanged) {
322 int32_t metaState = getContext()->getGlobalMetaState();
323 int32_t buttonState = lastButtonState;
324 int32_t motionEventAction;
325 if (downChanged) {
326 motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
327 } else if (down || (mSource != AINPUT_SOURCE_MOUSE)) {
328 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
329 } else {
330 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
331 }
332
333 if (buttonsReleased) {
334 BitSet32 released(buttonsReleased);
335 while (!released.isEmpty()) {
336 int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
337 buttonState &= ~actionButton;
338 out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime,
339 getDeviceId(), mSource, *mDisplayId, policyFlags,
340 AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
341 metaState, buttonState, MotionClassification::NONE,
342 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
343 &pointerCoords, mXPrecision, mYPrecision,
344 xCursorPosition, yCursorPosition, downTime,
345 /*videoFrames=*/{}));
346 }
347 }
348
349 out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
350 mSource, *mDisplayId, policyFlags, motionEventAction, 0, 0,
351 metaState, currentButtonState, MotionClassification::NONE,
352 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
353 &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
354 yCursorPosition, downTime,
355 /*videoFrames=*/{}));
356
357 if (buttonsPressed) {
358 BitSet32 pressed(buttonsPressed);
359 while (!pressed.isEmpty()) {
360 int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
361 buttonState |= actionButton;
362 out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime,
363 getDeviceId(), mSource, *mDisplayId, policyFlags,
364 AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
365 metaState, buttonState, MotionClassification::NONE,
366 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
367 &pointerCoords, mXPrecision, mYPrecision,
368 xCursorPosition, yCursorPosition, downTime,
369 /*videoFrames=*/{}));
370 }
371 }
372
373 ALOG_ASSERT(buttonState == currentButtonState);
374
375 // Send hover move after UP to tell the application that the mouse is hovering now.
376 if (motionEventAction == AMOTION_EVENT_ACTION_UP && (mSource == AINPUT_SOURCE_MOUSE)) {
377 out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
378 mSource, *mDisplayId, policyFlags,
379 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
380 currentButtonState, MotionClassification::NONE,
381 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
382 &pointerCoords, mXPrecision, mYPrecision,
383 xCursorPosition, yCursorPosition, downTime,
384 /*videoFrames=*/{}));
385 }
386
387 // Send scroll events.
388 if (scrolled) {
389 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
390 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
391
392 out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
393 mSource, *mDisplayId, policyFlags,
394 AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
395 currentButtonState, MotionClassification::NONE,
396 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
397 &pointerCoords, mXPrecision, mYPrecision,
398 xCursorPosition, yCursorPosition, downTime,
399 /*videoFrames=*/{}));
400 }
401 }
402
403 // Synthesize key up from buttons if needed.
404 out += synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, readTime, getDeviceId(),
405 mSource, *mDisplayId, policyFlags, lastButtonState,
406 currentButtonState);
407
408 mCursorMotionAccumulator.finishSync();
409 mCursorScrollAccumulator.finishSync();
410 return out;
411 }
412
getScanCodeState(uint32_t sourceMask,int32_t scanCode)413 int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
414 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
415 return getDeviceContext().getScanCodeState(scanCode);
416 } else {
417 return AKEY_STATE_UNKNOWN;
418 }
419 }
420
getAssociatedDisplayId()421 std::optional<ui::LogicalDisplayId> CursorInputMapper::getAssociatedDisplayId() {
422 return mDisplayId;
423 }
424
configureBasicParams()425 void CursorInputMapper::configureBasicParams() {
426 mCursorScrollAccumulator.configure(getDeviceContext());
427
428 // Configure basic parameters.
429 mParameters = computeParameters(getDeviceContext());
430
431 // Configure device mode.
432 switch (mParameters.mode) {
433 case Parameters::Mode::POINTER_RELATIVE:
434 // Should not happen during first time configuration.
435 ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER");
436 mParameters.mode = Parameters::Mode::POINTER;
437 [[fallthrough]];
438 case Parameters::Mode::POINTER:
439 mSource = AINPUT_SOURCE_MOUSE;
440 mXPrecision = 1.0f;
441 mYPrecision = 1.0f;
442 mXScale = 1.0f;
443 mYScale = 1.0f;
444 break;
445 case Parameters::Mode::NAVIGATION:
446 mSource = AINPUT_SOURCE_TRACKBALL;
447 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
448 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
449 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
450 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
451 break;
452 }
453
454 mVWheelScale = 1.0f;
455 mHWheelScale = 1.0f;
456 }
457
configureOnPointerCapture(const InputReaderConfiguration & config)458 void CursorInputMapper::configureOnPointerCapture(const InputReaderConfiguration& config) {
459 if (config.pointerCaptureRequest.isEnable()) {
460 if (mParameters.mode == Parameters::Mode::POINTER) {
461 mParameters.mode = Parameters::Mode::POINTER_RELATIVE;
462 mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
463 } else {
464 ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
465 }
466 } else {
467 if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) {
468 mParameters.mode = Parameters::Mode::POINTER;
469 mSource = AINPUT_SOURCE_MOUSE;
470 } else {
471 ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE");
472 }
473 }
474 bumpGeneration();
475 }
476
configureOnChangePointerSpeed(const InputReaderConfiguration & config)477 void CursorInputMapper::configureOnChangePointerSpeed(const InputReaderConfiguration& config) {
478 if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) {
479 // Disable any acceleration or scaling for the pointer when Pointer Capture is enabled.
480 if (mEnableNewMousePointerBallistics) {
481 mNewPointerVelocityControl.setAccelerationEnabled(false);
482 } else {
483 mOldPointerVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
484 }
485 mWheelXVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
486 mWheelYVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
487 } else {
488 if (mEnableNewMousePointerBallistics) {
489 mNewPointerVelocityControl.setAccelerationEnabled(
490 config.displaysWithMousePointerAccelerationDisabled.count(
491 mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) == 0);
492 mNewPointerVelocityControl.setCurve(
493 createAccelerationCurveForPointerSensitivity(config.mousePointerSpeed));
494 } else {
495 mOldPointerVelocityControl.setParameters(
496 (config.displaysWithMousePointerAccelerationDisabled.count(
497 mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) == 0)
498 ? config.pointerVelocityControlParameters
499 : FLAT_VELOCITY_CONTROL_PARAMS);
500 }
501 mWheelXVelocityControl.setParameters(config.wheelVelocityControlParameters);
502 mWheelYVelocityControl.setParameters(config.wheelVelocityControlParameters);
503 }
504 }
505
configureOnChangeDisplayInfo(const InputReaderConfiguration & config)506 void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfiguration& config) {
507 const bool isPointer = mParameters.mode == Parameters::Mode::POINTER;
508
509 mDisplayId = ui::LogicalDisplayId::INVALID;
510 std::optional<DisplayViewport> resolvedViewport;
511 if (auto assocViewport = mDeviceContext.getAssociatedViewport(); assocViewport) {
512 // This InputDevice is associated with a viewport.
513 // Only generate events for the associated display.
514 mDisplayId = assocViewport->displayId;
515 resolvedViewport = *assocViewport;
516 } else if (isPointer) {
517 // The InputDevice is not associated with a viewport, but it controls the mouse pointer.
518 // Always use DISPLAY_ID_NONE for mouse events.
519 // PointerChoreographer will make it target the correct the displayId later.
520 resolvedViewport = getContext()->getPolicy()->getPointerViewportForAssociatedDisplay();
521 mDisplayId =
522 resolvedViewport ? std::make_optional(ui::LogicalDisplayId::INVALID) : std::nullopt;
523 }
524
525 mOrientation = (mParameters.orientationAware && mParameters.hasAssociatedDisplay) ||
526 mParameters.mode == Parameters::Mode::POINTER_RELATIVE || !resolvedViewport
527 ? ui::ROTATION_0
528 : getInverseRotation(resolvedViewport->orientation);
529
530 mBoundsInLogicalDisplay = resolvedViewport
531 ? FloatRect{static_cast<float>(resolvedViewport->logicalLeft),
532 static_cast<float>(resolvedViewport->logicalTop),
533 static_cast<float>(resolvedViewport->logicalRight - 1),
534 static_cast<float>(resolvedViewport->logicalBottom - 1)}
535 : FloatRect{0, 0, 0, 0};
536
537 bumpGeneration();
538 }
539
540 } // namespace android
541