Loading services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java +44 −20 Original line number Diff line number Diff line Loading @@ -138,8 +138,8 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation DIAGONAL_UP_LEFT_MOVE(KeyEvent.KEYCODE_7), UP_MOVE_OR_SCROLL(KeyEvent.KEYCODE_8), DIAGONAL_UP_RIGHT_MOVE(KeyEvent.KEYCODE_9), LEFT_MOVE(KeyEvent.KEYCODE_U), RIGHT_MOVE(KeyEvent.KEYCODE_O), LEFT_MOVE_OR_SCROLL(KeyEvent.KEYCODE_U), RIGHT_MOVE_OR_SCROLL(KeyEvent.KEYCODE_O), DIAGONAL_DOWN_LEFT_MOVE(KeyEvent.KEYCODE_J), DOWN_MOVE_OR_SCROLL(KeyEvent.KEYCODE_K), DIAGONAL_DOWN_RIGHT_MOVE(KeyEvent.KEYCODE_L), Loading Loading @@ -267,6 +267,16 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation ); } @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) private void sendVirtualMouseScrollEvent(float x, float y) { waitForVirtualMouseCreation(); mVirtualMouse.sendScrollEvent(new VirtualMouseScrollEvent.Builder() .setXAxisMovement(x) .setYAxisMovement(y) .build() ); } /** * Performs a mouse scroll action based on the provided key code. * The scroll action will only be performed if the scroll toggle is on. Loading @@ -284,19 +294,31 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation private void performMouseScrollAction(int keyCode) { MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from( keyCode, mActiveInputDeviceId, mDeviceKeyCodeMap); float y = switch (mouseKeyEvent) { case UP_MOVE_OR_SCROLL -> MOUSE_SCROLL_STEP; case DOWN_MOVE_OR_SCROLL -> -MOUSE_SCROLL_STEP; default -> 0.0f; }; waitForVirtualMouseCreation(); mVirtualMouse.sendScrollEvent(new VirtualMouseScrollEvent.Builder() .setYAxisMovement(y) .build() ); float x = 0f; float y = 0f; switch (mouseKeyEvent) { case UP_MOVE_OR_SCROLL -> { y = MOUSE_SCROLL_STEP; } case DOWN_MOVE_OR_SCROLL -> { y = -MOUSE_SCROLL_STEP; } case LEFT_MOVE_OR_SCROLL -> { x = MOUSE_SCROLL_STEP; } case RIGHT_MOVE_OR_SCROLL -> { x = -MOUSE_SCROLL_STEP; } default -> { x = 0.0f; y = 0.0f; } } sendVirtualMouseScrollEvent(x, y); if (DEBUG) { Slog.d(LOG_TAG, "Performed mouse key event: " + mouseKeyEvent.name() + " for scroll action with axis movement (y=" + y + ")"); + " for scroll action with axis movement (x=" + x + ", y=" + y + ")"); } } Loading Loading @@ -344,8 +366,8 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation * The method calculates the relative movement of the mouse pointer * and sends the corresponding event to the virtual mouse. * * The UP and DOWN pointer actions will only take place for their respective keys * if the scroll toggle is off. * The UP, DOWN, LEFT, RIGHT pointer actions will only take place for their * respective keys if the scroll toggle is off. * * @param keyCode The key code representing the direction or button press. * Supported keys are: Loading @@ -353,8 +375,8 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation * <li>{@link MouseKeysInterceptor.MouseKeyEvent#DIAGONAL_DOWN_LEFT_MOVE} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#DOWN_MOVE_OR_SCROLL} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#DIAGONAL_DOWN_RIGHT_MOVE} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#LEFT_MOVE} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#RIGHT_MOVE} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#LEFT_MOVE_OR_SCROLL} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#RIGHT_MOVE_OR_SCROLL} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#DIAGONAL_UP_LEFT_MOVE} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#UP_MOVE_OR_SCROLL} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#DIAGONAL_UP_RIGHT_MOVE} Loading @@ -381,10 +403,10 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation x = MOUSE_POINTER_MOVEMENT_STEP / sqrt(2); y = MOUSE_POINTER_MOVEMENT_STEP / sqrt(2); } case LEFT_MOVE -> { case LEFT_MOVE_OR_SCROLL -> { x = -MOUSE_POINTER_MOVEMENT_STEP; } case RIGHT_MOVE -> { case RIGHT_MOVE_OR_SCROLL -> { x = MOUSE_POINTER_MOVEMENT_STEP; } case DIAGONAL_UP_LEFT_MOVE -> { Loading Loading @@ -424,7 +446,9 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation private boolean isMouseScrollKey(int keyCode, InputDevice inputDevice) { return keyCode == MouseKeyEvent.UP_MOVE_OR_SCROLL.getKeyCode(inputDevice) || keyCode == MouseKeyEvent.DOWN_MOVE_OR_SCROLL.getKeyCode(inputDevice); || keyCode == MouseKeyEvent.DOWN_MOVE_OR_SCROLL.getKeyCode(inputDevice) || keyCode == MouseKeyEvent.LEFT_MOVE_OR_SCROLL.getKeyCode(inputDevice) || keyCode == MouseKeyEvent.RIGHT_MOVE_OR_SCROLL.getKeyCode(inputDevice); } /** Loading services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt +21 −0 Original line number Diff line number Diff line Loading @@ -235,6 +235,27 @@ class MouseKeysInterceptorTest { arrayOf<Float>(MouseKeysInterceptor.MOUSE_SCROLL_STEP)) } @Test fun whenScrollToggleOn_ScrollRightKeyIsPressed_scrollEventIsSent() { // There should be some delay between the downTime of the key event and calling onKeyEvent val downTime = clock.now() - KEYBOARD_POST_EVENT_DELAY_MILLIS val keyCodeScrollToggle = MouseKeysInterceptor.MouseKeyEvent.SCROLL_TOGGLE.keyCodeValue val keyCodeScroll = MouseKeysInterceptor.MouseKeyEvent.RIGHT_MOVE_OR_SCROLL.keyCodeValue val scrollToggleDownEvent = KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, keyCodeScrollToggle, 0, 0, DEVICE_ID, 0) val scrollDownEvent = KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, keyCodeScroll, 0, 0, DEVICE_ID, 0) mouseKeysInterceptor.onKeyEvent(scrollToggleDownEvent, 0) mouseKeysInterceptor.onKeyEvent(scrollDownEvent, 0) testLooper.dispatchAll() // Verify the sendScrollEvent method is called once and capture the arguments verifyScrollEvents(arrayOf<Float>(-MouseKeysInterceptor.MOUSE_SCROLL_STEP), arrayOf<Float>(0f)) } @Test fun whenScrollToggleOff_DirectionalUpKeyIsPressed_RelativeEventIsSent() { // There should be some delay between the downTime of the key event and calling onKeyEvent Loading Loading
services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java +44 −20 Original line number Diff line number Diff line Loading @@ -138,8 +138,8 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation DIAGONAL_UP_LEFT_MOVE(KeyEvent.KEYCODE_7), UP_MOVE_OR_SCROLL(KeyEvent.KEYCODE_8), DIAGONAL_UP_RIGHT_MOVE(KeyEvent.KEYCODE_9), LEFT_MOVE(KeyEvent.KEYCODE_U), RIGHT_MOVE(KeyEvent.KEYCODE_O), LEFT_MOVE_OR_SCROLL(KeyEvent.KEYCODE_U), RIGHT_MOVE_OR_SCROLL(KeyEvent.KEYCODE_O), DIAGONAL_DOWN_LEFT_MOVE(KeyEvent.KEYCODE_J), DOWN_MOVE_OR_SCROLL(KeyEvent.KEYCODE_K), DIAGONAL_DOWN_RIGHT_MOVE(KeyEvent.KEYCODE_L), Loading Loading @@ -267,6 +267,16 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation ); } @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) private void sendVirtualMouseScrollEvent(float x, float y) { waitForVirtualMouseCreation(); mVirtualMouse.sendScrollEvent(new VirtualMouseScrollEvent.Builder() .setXAxisMovement(x) .setYAxisMovement(y) .build() ); } /** * Performs a mouse scroll action based on the provided key code. * The scroll action will only be performed if the scroll toggle is on. Loading @@ -284,19 +294,31 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation private void performMouseScrollAction(int keyCode) { MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from( keyCode, mActiveInputDeviceId, mDeviceKeyCodeMap); float y = switch (mouseKeyEvent) { case UP_MOVE_OR_SCROLL -> MOUSE_SCROLL_STEP; case DOWN_MOVE_OR_SCROLL -> -MOUSE_SCROLL_STEP; default -> 0.0f; }; waitForVirtualMouseCreation(); mVirtualMouse.sendScrollEvent(new VirtualMouseScrollEvent.Builder() .setYAxisMovement(y) .build() ); float x = 0f; float y = 0f; switch (mouseKeyEvent) { case UP_MOVE_OR_SCROLL -> { y = MOUSE_SCROLL_STEP; } case DOWN_MOVE_OR_SCROLL -> { y = -MOUSE_SCROLL_STEP; } case LEFT_MOVE_OR_SCROLL -> { x = MOUSE_SCROLL_STEP; } case RIGHT_MOVE_OR_SCROLL -> { x = -MOUSE_SCROLL_STEP; } default -> { x = 0.0f; y = 0.0f; } } sendVirtualMouseScrollEvent(x, y); if (DEBUG) { Slog.d(LOG_TAG, "Performed mouse key event: " + mouseKeyEvent.name() + " for scroll action with axis movement (y=" + y + ")"); + " for scroll action with axis movement (x=" + x + ", y=" + y + ")"); } } Loading Loading @@ -344,8 +366,8 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation * The method calculates the relative movement of the mouse pointer * and sends the corresponding event to the virtual mouse. * * The UP and DOWN pointer actions will only take place for their respective keys * if the scroll toggle is off. * The UP, DOWN, LEFT, RIGHT pointer actions will only take place for their * respective keys if the scroll toggle is off. * * @param keyCode The key code representing the direction or button press. * Supported keys are: Loading @@ -353,8 +375,8 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation * <li>{@link MouseKeysInterceptor.MouseKeyEvent#DIAGONAL_DOWN_LEFT_MOVE} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#DOWN_MOVE_OR_SCROLL} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#DIAGONAL_DOWN_RIGHT_MOVE} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#LEFT_MOVE} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#RIGHT_MOVE} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#LEFT_MOVE_OR_SCROLL} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#RIGHT_MOVE_OR_SCROLL} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#DIAGONAL_UP_LEFT_MOVE} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#UP_MOVE_OR_SCROLL} * <li>{@link MouseKeysInterceptor.MouseKeyEvent#DIAGONAL_UP_RIGHT_MOVE} Loading @@ -381,10 +403,10 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation x = MOUSE_POINTER_MOVEMENT_STEP / sqrt(2); y = MOUSE_POINTER_MOVEMENT_STEP / sqrt(2); } case LEFT_MOVE -> { case LEFT_MOVE_OR_SCROLL -> { x = -MOUSE_POINTER_MOVEMENT_STEP; } case RIGHT_MOVE -> { case RIGHT_MOVE_OR_SCROLL -> { x = MOUSE_POINTER_MOVEMENT_STEP; } case DIAGONAL_UP_LEFT_MOVE -> { Loading Loading @@ -424,7 +446,9 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation private boolean isMouseScrollKey(int keyCode, InputDevice inputDevice) { return keyCode == MouseKeyEvent.UP_MOVE_OR_SCROLL.getKeyCode(inputDevice) || keyCode == MouseKeyEvent.DOWN_MOVE_OR_SCROLL.getKeyCode(inputDevice); || keyCode == MouseKeyEvent.DOWN_MOVE_OR_SCROLL.getKeyCode(inputDevice) || keyCode == MouseKeyEvent.LEFT_MOVE_OR_SCROLL.getKeyCode(inputDevice) || keyCode == MouseKeyEvent.RIGHT_MOVE_OR_SCROLL.getKeyCode(inputDevice); } /** Loading
services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt +21 −0 Original line number Diff line number Diff line Loading @@ -235,6 +235,27 @@ class MouseKeysInterceptorTest { arrayOf<Float>(MouseKeysInterceptor.MOUSE_SCROLL_STEP)) } @Test fun whenScrollToggleOn_ScrollRightKeyIsPressed_scrollEventIsSent() { // There should be some delay between the downTime of the key event and calling onKeyEvent val downTime = clock.now() - KEYBOARD_POST_EVENT_DELAY_MILLIS val keyCodeScrollToggle = MouseKeysInterceptor.MouseKeyEvent.SCROLL_TOGGLE.keyCodeValue val keyCodeScroll = MouseKeysInterceptor.MouseKeyEvent.RIGHT_MOVE_OR_SCROLL.keyCodeValue val scrollToggleDownEvent = KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, keyCodeScrollToggle, 0, 0, DEVICE_ID, 0) val scrollDownEvent = KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, keyCodeScroll, 0, 0, DEVICE_ID, 0) mouseKeysInterceptor.onKeyEvent(scrollToggleDownEvent, 0) mouseKeysInterceptor.onKeyEvent(scrollDownEvent, 0) testLooper.dispatchAll() // Verify the sendScrollEvent method is called once and capture the arguments verifyScrollEvents(arrayOf<Float>(-MouseKeysInterceptor.MOUSE_SCROLL_STEP), arrayOf<Float>(0f)) } @Test fun whenScrollToggleOff_DirectionalUpKeyIsPressed_RelativeEventIsSent() { // There should be some delay between the downTime of the key event and calling onKeyEvent Loading