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