diff options
8 files changed, 104 insertions, 0 deletions
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java index 061b5859a989..897ce4a7b022 100644 --- a/core/java/android/hardware/input/InputSettings.java +++ b/core/java/android/hardware/input/InputSettings.java @@ -25,6 +25,7 @@ import static com.android.hardware.input.Flags.keyboardA11ySlowKeysFlag; import static com.android.hardware.input.Flags.keyboardA11yStickyKeysFlag; import static com.android.hardware.input.Flags.keyboardA11yMouseKeys; import static com.android.hardware.input.Flags.mouseReverseVerticalScrolling; +import static com.android.hardware.input.Flags.mouseSwapPrimaryButton; import static com.android.hardware.input.Flags.touchpadTapDragging; import static com.android.hardware.input.Flags.touchpadVisualizer; import static com.android.input.flags.Flags.enableInputFilterRustImpl; @@ -372,6 +373,14 @@ public class InputSettings { } /** + * Returns true if the feature flag for mouse swap primary button is enabled. + * @hide + */ + public static boolean isMouseSwapPrimaryButtonFeatureFlagEnabled() { + return mouseSwapPrimaryButton(); + } + + /** * Returns true if the touchpad visualizer is allowed to appear. * * @param context The application context. @@ -549,6 +558,47 @@ public class InputSettings { } /** + * Whether the primary mouse button is swapped on connected mice. + * + * @param context The application context. + * @return Whether mice will have their primary buttons swapped, so that left clicking will + * perform the secondary action (e.g. show menu) and right clicking will perform the primary + * action. + * + * @hide + */ + public static boolean isMouseSwapPrimaryButtonEnabled(@NonNull Context context) { + if (!isMouseSwapPrimaryButtonFeatureFlagEnabled()) { + return false; + } + + return Settings.System.getIntForUser(context.getContentResolver(), + Settings.System.MOUSE_SWAP_PRIMARY_BUTTON, 0, UserHandle.USER_CURRENT) + != 0; + } + + /** + * Sets whether mice will have their primary buttons swapped between left and right + * clicks. + * + * @param context The application context. + * @param swapPrimaryButton Whether swapping the primary button is enabled. + * + * @hide + */ + @RequiresPermission(Manifest.permission.WRITE_SETTINGS) + public static void setMouseSwapPrimaryButton(@NonNull Context context, + boolean swapPrimaryButton) { + if (!isMouseSwapPrimaryButtonFeatureFlagEnabled()) { + return; + } + + Settings.System.putIntForUser(context.getContentResolver(), + Settings.System.MOUSE_SWAP_PRIMARY_BUTTON, swapPrimaryButton ? 1 : 0, + UserHandle.USER_CURRENT); + } + + /** * Whether Accessibility bounce keys feature is enabled. * * <p> diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 46bb8e2c2454..594005c3ebd6 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6219,6 +6219,16 @@ public final class Settings { "mouse_reverse_vertical_scrolling"; /** + * Whether to enable swapping the primary button for connected mice. + * + * When enabled, right clicking will be the primary button and left clicking will be the + * secondary button (e.g. show menu). + * @hide + */ + public static final String MOUSE_SWAP_PRIMARY_BUTTON = + "mouse_swap_primary_button"; + + /** * Pointer fill style, specified by * {@link android.view.PointerIcon.PointerIconVectorStyleFill} constants. * @@ -6457,6 +6467,7 @@ public final class Settings { PRIVATE_SETTINGS.add(SCREEN_FLASH_NOTIFICATION_COLOR); PRIVATE_SETTINGS.add(DEFAULT_DEVICE_FONT_SCALE); PRIVATE_SETTINGS.add(MOUSE_REVERSE_VERTICAL_SCROLLING); + PRIVATE_SETTINGS.add(MOUSE_SWAP_PRIMARY_BUTTON); } /** diff --git a/core/proto/android/providers/settings/system.proto b/core/proto/android/providers/settings/system.proto index 3865ae44e56e..9779dc0e00b8 100644 --- a/core/proto/android/providers/settings/system.proto +++ b/core/proto/android/providers/settings/system.proto @@ -224,6 +224,7 @@ message SystemSettingsProto { option (android.msg_privacy).dest = DEST_EXPLICIT; optional SettingProto reverse_vertical_scrolling = 1 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto swap_primary_button = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional Mouse mouse = 38; diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java index e1b967b1b6a8..3530e0f5f9de 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java @@ -107,6 +107,7 @@ public class SystemSettings { Settings.System.AUTO_LAUNCH_MEDIA_CONTROLS, Settings.System.LOCALE_PREFERENCES, Settings.System.MOUSE_REVERSE_VERTICAL_SCROLLING, + Settings.System.MOUSE_SWAP_PRIMARY_BUTTON, Settings.System.TOUCHPAD_POINTER_SPEED, Settings.System.TOUCHPAD_NATURAL_SCROLLING, Settings.System.TOUCHPAD_TAP_TO_CLICK, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java index 1f51e1a8523e..509b88b257fe 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java @@ -222,6 +222,7 @@ public class SystemSettingsValidators { VALIDATORS.put(System.POINTER_SCALE, new InclusiveFloatRangeValidator(DEFAULT_POINTER_SCALE, LARGE_POINTER_SCALE)); VALIDATORS.put(System.MOUSE_REVERSE_VERTICAL_SCROLLING, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.MOUSE_SWAP_PRIMARY_BUTTON, BOOLEAN_VALIDATOR); VALIDATORS.put(System.TOUCHPAD_POINTER_SPEED, new InclusiveIntegerRangeValidator(-7, 7)); VALIDATORS.put(System.TOUCHPAD_NATURAL_SCROLLING, BOOLEAN_VALIDATOR); VALIDATORS.put(System.TOUCHPAD_TAP_TO_CLICK, BOOLEAN_VALIDATOR); diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java index 9df2cb4d8e65..d1a6d3b9bb00 100644 --- a/services/core/java/com/android/server/input/InputSettingsObserver.java +++ b/services/core/java/com/android/server/input/InputSettingsObserver.java @@ -66,6 +66,9 @@ class InputSettingsObserver extends ContentObserver { Map.entry(Settings.System.getUriFor( Settings.System.MOUSE_REVERSE_VERTICAL_SCROLLING), (reason) -> updateMouseReverseVerticalScrolling()), + Map.entry(Settings.System.getUriFor( + Settings.System.MOUSE_SWAP_PRIMARY_BUTTON), + (reason) -> updateMouseSwapPrimaryButton()), Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_POINTER_SPEED), (reason) -> updateTouchpadPointerSpeed()), Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_NATURAL_SCROLLING), @@ -171,6 +174,11 @@ class InputSettingsObserver extends ContentObserver { InputSettings.isMouseReverseVerticalScrollingEnabled(mContext)); } + private void updateMouseSwapPrimaryButton() { + mNative.setMouseSwapPrimaryButtonEnabled( + InputSettings.isMouseSwapPrimaryButtonEnabled(mContext)); + } + private void updateTouchpadPointerSpeed() { mNative.setTouchpadPointerSpeed( constrainPointerSpeedValue(InputSettings.getTouchpadPointerSpeed(mContext))); diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java index 1f04dd9e2dbf..21e8bccd2883 100644 --- a/services/core/java/com/android/server/input/NativeInputManagerService.java +++ b/services/core/java/com/android/server/input/NativeInputManagerService.java @@ -129,6 +129,8 @@ interface NativeInputManagerService { void setMouseReverseVerticalScrollingEnabled(boolean enabled); + void setMouseSwapPrimaryButtonEnabled(boolean enabled); + void setTouchpadPointerSpeed(int speed); void setTouchpadNaturalScrollingEnabled(boolean enabled); @@ -393,6 +395,9 @@ interface NativeInputManagerService { public native void setMouseReverseVerticalScrollingEnabled(boolean enabled); @Override + public native void setMouseSwapPrimaryButtonEnabled(boolean enabled); + + @Override public native void setTouchpadPointerSpeed(int speed); @Override diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index f36e6806ceec..248ed1a58b75 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -338,6 +338,7 @@ public: void setPointerSpeed(int32_t speed); void setMousePointerAccelerationEnabled(ui::LogicalDisplayId displayId, bool enabled); void setMouseReverseVerticalScrollingEnabled(bool enabled); + void setMouseSwapPrimaryButtonEnabled(bool enabled); void setTouchpadPointerSpeed(int32_t speed); void setTouchpadNaturalScrollingEnabled(bool enabled); void setTouchpadTapToClickEnabled(bool enabled); @@ -486,6 +487,9 @@ private: // True if mouse vertical scrolling is reversed. bool mouseReverseVerticalScrollingEnabled{false}; + // True if the mouse primary button is swapped (left/right buttons). + bool mouseSwapPrimaryButtonEnabled{false}; + // The touchpad pointer speed, as a number from -7 (slowest) to 7 (fastest). int32_t touchpadPointerSpeed{0}; @@ -768,6 +772,7 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon outConfig->mouseReverseVerticalScrollingEnabled = mLocked.mouseReverseVerticalScrollingEnabled; + outConfig->mouseSwapPrimaryButtonEnabled = mLocked.mouseSwapPrimaryButtonEnabled; outConfig->touchpadPointerSpeed = mLocked.touchpadPointerSpeed; outConfig->touchpadNaturalScrollingEnabled = mLocked.touchpadNaturalScrollingEnabled; @@ -1339,6 +1344,21 @@ void NativeInputManager::setMouseReverseVerticalScrollingEnabled(bool enabled) { InputReaderConfiguration::Change::MOUSE_SETTINGS); } +void NativeInputManager::setMouseSwapPrimaryButtonEnabled(bool enabled) { + { // acquire lock + std::scoped_lock _l(mLock); + + if (mLocked.mouseSwapPrimaryButtonEnabled == enabled) { + return; + } + + mLocked.mouseSwapPrimaryButtonEnabled = enabled; + } // release lock + + mInputManager->getReader().requestRefreshConfiguration( + InputReaderConfiguration::Change::MOUSE_SETTINGS); +} + void NativeInputManager::setPointerSpeed(int32_t speed) { { // acquire lock std::scoped_lock _l(mLock); @@ -3030,6 +3050,12 @@ static void nativeSetMouseReverseVerticalScrollingEnabled(JNIEnv* env, jobject n im->setMouseReverseVerticalScrollingEnabled(enabled); } +static void nativeSetMouseSwapPrimaryButtonEnabled(JNIEnv* env, jobject nativeImplObj, + bool enabled) { + NativeInputManager* im = getNativeInputManager(env, nativeImplObj); + im->setMouseSwapPrimaryButtonEnabled(enabled); +} + // ---------------------------------------------------------------------------- static const JNINativeMethod gInputManagerMethods[] = { @@ -3078,6 +3104,7 @@ static const JNINativeMethod gInputManagerMethods[] = { (void*)nativeSetMousePointerAccelerationEnabled}, {"setMouseReverseVerticalScrollingEnabled", "(Z)V", (void*)nativeSetMouseReverseVerticalScrollingEnabled}, + {"setMouseSwapPrimaryButtonEnabled", "(Z)V", (void*)nativeSetMouseSwapPrimaryButtonEnabled}, {"setTouchpadPointerSpeed", "(I)V", (void*)nativeSetTouchpadPointerSpeed}, {"setTouchpadNaturalScrollingEnabled", "(Z)V", (void*)nativeSetTouchpadNaturalScrollingEnabled}, |