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