Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b968400c authored by Yuhan Yang's avatar Yuhan Yang Committed by Android (Google) Code Review
Browse files

Merge "Add Autoclick cursor area size settings dialog" into main

parents faa7bc84 7630d396
Loading
Loading
Loading
Loading
+78 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  Copyright 2025 The Android Open Source Project

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:gravity="center_horizontal"
              android:orientation="vertical">

    <TextView
        android:id="@+id/autoclick_cursor_area_size_dialog_title"
        android:text="@string/autoclick_cursor_area_size_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginHorizontal="26dp"
        android:textSize="20sp"
        android:textColor="?android:attr/textColorPrimary"
        android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
    />

    <TextView
        android:id="@+id/autoclick_cursor_area_size_dialog_subtitle"
        android:text="@string/autoclick_cursor_area_size_summary"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="26dp"
        android:layout_marginTop="8dp"
        android:textSize="16sp"
        android:textColor="?android:attr/textColorSecondary"
    />

    <RadioGroup
        android:id="@+id/autoclick_cursor_area_size_value_group"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginTop="16dp">

        <RadioButton
            android:id="@+id/autoclick_cursor_area_size_value_extra_small"
            android:text="@string/autoclick_cursor_area_size_dialog_option_extra_small"
            style="@style/AutoclickDialogRadioButton"/>
        <RadioButton
            android:id="@+id/autoclick_cursor_area_size_value_small"
            android:text="@string/autoclick_cursor_area_size_dialog_option_small"
            style="@style/AutoclickDialogRadioButton"/>
        <RadioButton
            android:id="@+id/autoclick_cursor_area_size_value_default"
            android:text="@string/autoclick_cursor_area_size_dialog_option_default"
            style="@style/AutoclickDialogRadioButton"/>

        <RadioButton
            android:id="@+id/autoclick_cursor_area_size_value_large"
            android:text="@string/autoclick_cursor_area_size_dialog_option_large"
            style="@style/AutoclickDialogRadioButton"/>

        <RadioButton
            android:id="@+id/autoclick_cursor_area_size_value_extra_large"
            android:text="@string/autoclick_cursor_area_size_dialog_option_extra_large"
            style="@style/AutoclickDialogRadioButton"/>
    </RadioGroup>

</LinearLayout>
 No newline at end of file
+21 −6
Original line number Diff line number Diff line
@@ -5643,12 +5643,27 @@
    <string name="accessibility_autoclick_longer_desc">Longer</string>
    <!-- Description for the seekbar that adjust auto click time. [CHAR_LIMIT=NONE] -->
    <string name="accessibility_autoclick_seekbar_desc">Auto click time</string>
    <!-- Title for the seekbar that adjust auto click cursor area size. [CHAR_LIMIT=NONE] -->
    <!-- TODO(b/383901288): Update string to translatable once approved by UXW. -->
    <string name="autoclick_cursor_area_size_title" translatable="false">Cursor area size</string>
    <!-- Summary for the seekbar that adjust auto click cursor area size. [CHAR_LIMIT=NONE] -->
    <!-- TODO(b/383901288): Update string to translatable once approved by UXW. -->
    <string name="autoclick_cursor_area_size_summary" translatable="false">Adjust the autoclick ring indicator area size</string>
    <!-- Title for the alert dialog that adjust auto click cursor area size. [CHAR_LIMIT=NONE] -->
    <!-- TODO(b/394683600): Update string to translatable once approved by UXW. -->
    <string name="autoclick_cursor_area_size_title" translatable="false">Click area</string>
    <!-- Summary for the alert dialog that adjust auto click cursor area size. [CHAR_LIMIT=NONE] -->
    <!-- TODO(b/394683600): Update string to translatable once approved by UXW. -->
    <string name="autoclick_cursor_area_size_summary" translatable="false">The area where the cursor can move freely without canceling the click once the countdown starts</string>
    <!-- Option for the autoclick area dialog that adjust auto click cursor area size to extra large. [CHAR_LIMIT=NONE] -->
    <!-- TODO(b/394683600): Update string to translatable once approved by UXW. -->
    <string name="autoclick_cursor_area_size_dialog_option_extra_large" translatable="false">Extra large</string>
    <!-- Option for the autoclick area dialog that adjust auto click cursor area size to large. [CHAR_LIMIT=NONE] -->
    <!-- TODO(b/394683600): Update string to translatable once approved by UXW. -->
    <string name="autoclick_cursor_area_size_dialog_option_large" translatable="false">Large</string>
    <!-- Option for the autoclick area dialog that adjust auto click cursor area size to Medium(Default). [CHAR_LIMIT=NONE] -->
    <!-- TODO(b/394683600): Update string to translatable once approved by UXW. -->
    <string name="autoclick_cursor_area_size_dialog_option_default" translatable="false">Default</string>
    <!-- Option for the autoclick area dialog that adjust auto click cursor area size to small. [CHAR_LIMIT=NONE] -->
    <!-- TODO(b/394683600): Update string to translatable once approved by UXW. -->
    <string name="autoclick_cursor_area_size_dialog_option_small" translatable="false">Small</string>
    <!-- Option for the autoclick area dialog that adjust auto click cursor area size to extra small. [CHAR_LIMIT=NONE] -->
    <!-- TODO(b/394683600): Update string to translatable once approved by UXW. -->
    <string name="autoclick_cursor_area_size_dialog_option_extra_small" translatable="false">Extra small</string>
    <!-- Title for the toggle button that turns on/off the autoclick setting of ignoring minor cursor movement. [CHAR_LIMIT=NONE] -->
    <!-- TODO(b/388845718): Update string to translatable once approved by UXW. -->
    <string name="autoclick_ignore_minor_cursor_movement_title" translatable="false">Ignore minor cursor movement</string>
+8 −0
Original line number Diff line number Diff line
@@ -710,6 +710,14 @@
        <item name="android:textSize">14sp</item>
    </style>

    <style name="AutoclickDialogRadioButton">
        <item name="android:paddingStart">12dp</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">48dp</item>
        <item name="android:layout_gravity">start|center_vertical</item>
        <item name="android:background">@null</item>
    </style>

    <style name="Widget.PopupWindow.Settings"
           parent="@android:style/Widget.DeviceDefault.PopupWindow">
        <item name="android:clipToPadding">true</item>
+4 −5
Original line number Diff line number Diff line
@@ -76,12 +76,11 @@
        settings:searchable="false"
        settings:controller="com.android.settings.accessibility.ToggleAutoclickCustomSeekbarController"/>

    <com.android.settingslib.widget.SliderPreference
    <Preference
        android:key="accessibility_control_autoclick_cursor_area_size"
        android:title="@string/autoclick_cursor_area_size_title"
        android:summary="@string/autoclick_cursor_area_size_summary"
        android:selectable="false"
        android:persistent="false"
        settings:searchable="false"
        android:title="@string/autoclick_cursor_area_size_title"
        settings:controller="com.android.settings.accessibility.ToggleAutoclickCursorAreaSizeController" />

    <SwitchPreferenceCompat
+65 −37
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.settings.accessibility;

import static android.content.Context.MODE_PRIVATE;
import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_INCREMENT_SIZE;
import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_MAX;
import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_MIN;

@@ -25,35 +24,49 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.accessibility.AccessibilityManager;
import android.widget.RadioGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.PreferenceScreen;
import androidx.preference.Preference;

import com.android.server.accessibility.Flags;
import com.android.settings.core.SliderPreferenceController;
import com.android.settingslib.widget.SliderPreference;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;

import com.google.common.collect.ImmutableBiMap;

/** Controller class that controls accessibility autoclick cursor area size settings. */
public class ToggleAutoclickCursorAreaSizeController extends SliderPreferenceController
public class ToggleAutoclickCursorAreaSizeController extends BasePreferenceController
        implements LifecycleObserver, SharedPreferences.OnSharedPreferenceChangeListener {

    public static final String TAG = ToggleAutoclickCursorAreaSizeController.class.getSimpleName();

    public final ImmutableBiMap<Integer, Integer> RADIO_BUTTON_ID_TO_CURSOR_SIZE =
            new ImmutableBiMap.Builder<Integer, Integer>()
                .put(R.id.autoclick_cursor_area_size_value_extra_large, 100)
                .put(R.id.autoclick_cursor_area_size_value_large, 80)
                .put(R.id.autoclick_cursor_area_size_value_default, 60)
                .put(R.id.autoclick_cursor_area_size_value_small, 40)
                .put(R.id.autoclick_cursor_area_size_value_extra_small, 20)
                .buildOrThrow();

    private final ContentResolver mContentResolver;
    private final SharedPreferences mSharedPreferences;
    private SliderPreference mPreference;
    protected AlertDialog mAlertDialog;

    public ToggleAutoclickCursorAreaSizeController(@NonNull Context context,
            @NonNull String preferenceKey) {
        super(context, preferenceKey);

        mContentResolver = context.getContentResolver();
        mSharedPreferences = context.getSharedPreferences(context.getPackageName(), MODE_PRIVATE);
        constructDialog(context);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
@@ -70,53 +83,68 @@ public class ToggleAutoclickCursorAreaSizeController extends SliderPreferenceCon
        }
    }

    @Override
    public void displayPreference(@NonNull PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreference = screen.findPreference(getPreferenceKey());
        if (mPreference != null) {
            mPreference.setMin(getMin());
            mPreference.setMax(getMax());
            mPreference.setSliderIncrement(AUTOCLICK_CURSOR_AREA_INCREMENT_SIZE);
            mPreference.setValue(getSliderPosition());
    protected void constructDialog(Context context) {
        mAlertDialog = new AlertDialog.Builder(context)
                .setView(R.layout.dialog_autoclick_cursor_area_size)
                .setPositiveButton(android.R.string.ok,
                        (dialog, which) -> {
                            RadioGroup radioGroup =
                                    mAlertDialog.findViewById(
                                            R.id.autoclick_cursor_area_size_value_group);
                            int checkedRadioButtonId = radioGroup.getCheckedRadioButtonId();
                            int size = RADIO_BUTTON_ID_TO_CURSOR_SIZE.get(checkedRadioButtonId);
                            updateAutoclickCursorAreaSize(size);
                        })
                .setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.dismiss())
                .create();
        mAlertDialog.setOnShowListener(dialog -> {
            initStateBasedOnSize();
        });
    }

    private void initStateBasedOnSize() {
        RadioGroup cannedValueRadioGroup = mAlertDialog.findViewById(
                    R.id.autoclick_cursor_area_size_value_group);
        int autoclickCursordefaultSize = validateSize(Settings.Secure.getInt(mContentResolver,
                Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE,
                AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT));

        int radioButtonId = RADIO_BUTTON_ID_TO_CURSOR_SIZE.inverse()
                .get(autoclickCursordefaultSize);

        cannedValueRadioGroup.check(radioButtonId);
    }

    @Override
    public int getAvailabilityStatus() {
        return Flags.enableAutoclickIndicator() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
    public boolean handlePreferenceTreeClick(@NonNull Preference preference) {
        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
            return false;
        }

    @Override
    public void onSharedPreferenceChanged(
            @NonNull SharedPreferences sharedPreferences, @Nullable String key) {
        // TODO(b/383901288): Update slider if interested preference has changed.
        if (mAlertDialog != null) {
            mAlertDialog.show();
        }

    @Override
    public boolean setSliderPosition(int position) {
        int size = validateSize(position);
        Settings.Secure.putInt(
                mContentResolver, Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE, size);
        return true;
    }

    @Override
    public int getSliderPosition() {
        int size = Settings.Secure.getInt(mContentResolver,
                Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE,
                AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT);
        return validateSize(size);
    public int getAvailabilityStatus() {
        return Flags.enableAutoclickIndicator() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
    }

    @Override
    public int getMax() {
        return AUTOCLICK_CURSOR_AREA_SIZE_MAX;
    public void onSharedPreferenceChanged(
            @NonNull SharedPreferences sharedPreferences, @Nullable String key) {
        // TODO(b/383901288): Update slider if interested preference has changed.
    }

    @Override
    public int getMin() {
        return AUTOCLICK_CURSOR_AREA_SIZE_MIN;
    /** Updates autoclick cursor area size. */
    public void updateAutoclickCursorAreaSize(int size) {
        Settings.Secure.putInt(
                mContentResolver,
                Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE,
                validateSize(size));
    }

    private int validateSize(int size) {
Loading