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