Add Settings for vector-specific PointerIcon stroke colors.
Bug: 305193969 Test: PointerIconLoadingTest Flag: android.view.flags.enable_vector_cursor_a11y_settings Change-Id: I72213e8806fed451a0edb16d497406ffae5c1a44
This commit is contained in:
60
res/layout/pointer_icon_stroke_style_layout.xml
Normal file
60
res/layout/pointer_icon_stroke_style_layout.xml
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Copyright 2024 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="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
||||
android:orientation="vertical"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/pointer_stroke_style_padding"
|
||||
android:text="@string/pointer_stroke_style"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/button_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="@dimen/pointer_stroke_style_padding"
|
||||
android:layout_marginBottom="@dimen/pointer_stroke_style_padding"
|
||||
android:padding="@dimen/pointer_stroke_style_padding">
|
||||
<RadioButton android:id="@+id/stroke_style_white"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/pointer_stroke_style_padding"
|
||||
android:text="@string/pointer_stroke_style_name_white"/>
|
||||
<RadioButton android:id="@+id/stroke_style_black"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/pointer_stroke_style_padding"
|
||||
android:text="@string/pointer_stroke_style_name_black"/>
|
||||
<RadioButton android:id="@+id/stroke_style_none"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/pointer_stroke_style_padding"
|
||||
android:text="@string/pointer_stroke_style_name_none"/>
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
@@ -179,6 +179,7 @@
|
||||
<dimen name="pointer_fill_style_circle_padding">8dp</dimen>
|
||||
<dimen name="pointer_fill_style_shape_default_stroke">1dp</dimen>
|
||||
<dimen name="pointer_fill_style_shape_hovered_stroke">3dp</dimen>
|
||||
<dimen name="pointer_stroke_style_padding">8dp</dimen>
|
||||
<dimen name="pointer_scale_padding">8dp</dimen>
|
||||
<item name="pointer_scale_size_start" format="float" type="dimen">1.0</item>
|
||||
<item name="pointer_scale_size_end" format="float" type="dimen">2.5</item>
|
||||
|
@@ -4501,6 +4501,14 @@
|
||||
<string name="pointer_fill_style_pink_button">Change pointer fill style to pink</string>
|
||||
<!-- Content description for blue pointer fill style. [CHAR LIMIT=60] -->
|
||||
<string name="pointer_fill_style_blue_button">Change pointer fill style to blue</string>
|
||||
<!-- Title text for mouse pointer stroke style. [CHAR LIMIT=35] -->
|
||||
<string name="pointer_stroke_style">Pointer stroke style</string>
|
||||
<!-- White value for pointer stroke style. [CHAR LIMIT=35] -->
|
||||
<string name="pointer_stroke_style_name_white">White</string>
|
||||
<!-- Black value pointer stroke style. [CHAR LIMIT=35] -->
|
||||
<string name="pointer_stroke_style_name_black">Black</string>
|
||||
<!-- None value for pointer stroke style. [CHAR LIMIT=35] -->
|
||||
<string name="pointer_stroke_style_name_none">None</string>
|
||||
<!-- Title for the button to trigger the 'touch gesture' education. [CHAR LIMIT=35] -->
|
||||
<string name="trackpad_touch_gesture">Learn touchpad gestures</string>
|
||||
<!-- Search keywords for "touchpad" -->
|
||||
|
@@ -68,6 +68,12 @@
|
||||
android:order="50"
|
||||
settings:controller="com.android.settings.inputmethod.PointerFillStylePreferenceController"/>
|
||||
|
||||
<com.android.settings.inputmethod.PointerStrokeStylePreference
|
||||
android:key="pointer_stroke_style"
|
||||
android:title="@string/pointer_stroke_style"
|
||||
android:order="60"
|
||||
settings:controller="com.android.settings.inputmethod.PointerStrokeStylePreferenceController"/>
|
||||
|
||||
<com.android.settings.widget.LabeledSeekBarPreference
|
||||
android:key="pointer_scale"
|
||||
android:title="@string/pointer_scale"
|
||||
|
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2024 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.
|
||||
*/
|
||||
package com.android.settings.inputmethod;
|
||||
|
||||
import static android.view.PointerIcon.POINTER_ICON_VECTOR_STYLE_STROKE_BLACK;
|
||||
import static android.view.PointerIcon.POINTER_ICON_VECTOR_STYLE_STROKE_NONE;
|
||||
import static android.view.PointerIcon.POINTER_ICON_VECTOR_STYLE_STROKE_WHITE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.PointerIcon;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
public class PointerStrokeStylePreference extends Preference {
|
||||
|
||||
public PointerStrokeStylePreference(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setLayoutResource(R.layout.pointer_icon_stroke_style_layout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
|
||||
LinearLayout buttonHolder = (LinearLayout) holder.findViewById(R.id.button_holder);
|
||||
// Intercept hover events so setting row does not highlight when hovering buttons.
|
||||
buttonHolder.setOnHoverListener((v, e) -> true);
|
||||
|
||||
int currentStroke = getPreferenceDataStore().getInt(Settings.System.POINTER_STROKE_STYLE,
|
||||
POINTER_ICON_VECTOR_STYLE_STROKE_WHITE);
|
||||
initRadioButton(holder, R.id.stroke_style_white, POINTER_ICON_VECTOR_STYLE_STROKE_WHITE,
|
||||
currentStroke);
|
||||
initRadioButton(holder, R.id.stroke_style_black, POINTER_ICON_VECTOR_STYLE_STROKE_BLACK,
|
||||
currentStroke);
|
||||
initRadioButton(holder, R.id.stroke_style_none, POINTER_ICON_VECTOR_STYLE_STROKE_NONE,
|
||||
currentStroke);
|
||||
}
|
||||
|
||||
private void initRadioButton(@NonNull PreferenceViewHolder holder, int id, int strokeStyle,
|
||||
int currentStroke) {
|
||||
RadioButton radioButton = (RadioButton) holder.findViewById(id);
|
||||
if (radioButton == null) {
|
||||
return;
|
||||
}
|
||||
radioButton.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
if (isChecked) {
|
||||
getPreferenceDataStore().putInt(Settings.System.POINTER_STROKE_STYLE, strokeStyle);
|
||||
}
|
||||
});
|
||||
radioButton.setChecked(currentStroke == strokeStyle);
|
||||
radioButton.setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_ARROW));
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2024 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.
|
||||
*/
|
||||
|
||||
package com.android.settings.inputmethod;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
public class PointerStrokeStylePreferenceController extends BasePreferenceController {
|
||||
|
||||
@VisibleForTesting
|
||||
static final String KEY_POINTER_STROKE_STYLE = "pointer_stroke_style";
|
||||
|
||||
public PointerStrokeStylePreferenceController(@NonNull Context context) {
|
||||
super(context, KEY_POINTER_STROKE_STYLE);
|
||||
}
|
||||
|
||||
@AvailabilityStatus
|
||||
public int getAvailabilityStatus() {
|
||||
return android.view.flags.Flags.enableVectorCursorA11ySettings() ? AVAILABLE
|
||||
: CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(@NonNull PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
Preference pointerStrokeStylePreference = screen.findPreference(KEY_POINTER_STROKE_STYLE);
|
||||
if (pointerStrokeStylePreference == null) {
|
||||
return;
|
||||
}
|
||||
pointerStrokeStylePreference.setPreferenceDataStore(new PreferenceDataStore() {
|
||||
@Override
|
||||
public void putInt(@NonNull String key, int value) {
|
||||
Settings.System.putIntForUser(mContext.getContentResolver(), key, value,
|
||||
UserHandle.USER_CURRENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(@NonNull String key, int defValue) {
|
||||
return Settings.System.getIntForUser(mContext.getContentResolver(), key, defValue,
|
||||
UserHandle.USER_CURRENT);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2024 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.
|
||||
*/
|
||||
|
||||
package com.android.settings.inputmethod;
|
||||
|
||||
import static android.view.flags.Flags.enableVectorCursorA11ySettings;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.inputmethod.PointerStrokeStylePreferenceController.KEY_POINTER_STROKE_STYLE;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/** Tests for {@link PointerStrokeStylePreferenceController} */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class PointerStrokeStylePreferenceControllerTest {
|
||||
@Rule
|
||||
public MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
@Mock
|
||||
PreferenceScreen mPreferenceScreen;
|
||||
|
||||
private Context mContext;
|
||||
private PointerStrokeStylePreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mController = new PointerStrokeStylePreferenceController(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_initializeDataStore() {
|
||||
Preference strokePreference = new Preference(mContext);
|
||||
strokePreference.setKey(KEY_POINTER_STROKE_STYLE);
|
||||
when(mPreferenceScreen.findPreference(eq(KEY_POINTER_STROKE_STYLE))).thenReturn(
|
||||
strokePreference);
|
||||
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
|
||||
assertNotNull(strokePreference.getPreferenceDataStore());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_flagEnabled() {
|
||||
assumeTrue(enableVectorCursorA11ySettings());
|
||||
|
||||
assertEquals(mController.getAvailabilityStatus(), AVAILABLE);
|
||||
}
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2024 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.
|
||||
*/
|
||||
|
||||
package com.android.settings.inputmethod;
|
||||
|
||||
import static android.view.PointerIcon.POINTER_ICON_VECTOR_STYLE_STROKE_BLACK;
|
||||
import static android.view.PointerIcon.POINTER_ICON_VECTOR_STYLE_STROKE_WHITE;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.view.View;
|
||||
import android.widget.RadioButton;
|
||||
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/** Tests for {@link PointerStrokeStylePreference} */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class PointerStrokeStylePreferenceTest {
|
||||
@Rule
|
||||
public MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
@Mock
|
||||
PreferenceDataStore mPreferenceDataStore;
|
||||
|
||||
private Context mContext;
|
||||
private PreferenceViewHolder mViewHolder;
|
||||
private PointerStrokeStylePreference mPreference;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mPreference = new PointerStrokeStylePreference(mContext, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_getCurrentStrokeStyleFromDataStore() {
|
||||
final View view = spy(View.inflate(mContext, mPreference.getLayoutResource(), null));
|
||||
mViewHolder = PreferenceViewHolder.createInstanceForTests(view);
|
||||
mPreference.setPreferenceDataStore(mPreferenceDataStore);
|
||||
|
||||
mPreference.onBindViewHolder(mViewHolder);
|
||||
|
||||
verify(mPreferenceDataStore).getInt(Settings.System.POINTER_STROKE_STYLE,
|
||||
POINTER_ICON_VECTOR_STYLE_STROKE_WHITE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_radioButtonUpdatesDataStore() {
|
||||
final View view = spy(View.inflate(mContext, mPreference.getLayoutResource(), null));
|
||||
mViewHolder = PreferenceViewHolder.createInstanceForTests(view);
|
||||
mPreference.setPreferenceDataStore(mPreferenceDataStore);
|
||||
RadioButton radioButton = (RadioButton) view.findViewById(R.id.stroke_style_black);
|
||||
mPreference.onBindViewHolder(mViewHolder);
|
||||
|
||||
radioButton.setChecked(true);
|
||||
|
||||
verify(mPreferenceDataStore).getInt(Settings.System.POINTER_STROKE_STYLE,
|
||||
POINTER_ICON_VECTOR_STYLE_STROKE_WHITE);
|
||||
verify(mPreferenceDataStore).putInt(Settings.System.POINTER_STROKE_STYLE,
|
||||
POINTER_ICON_VECTOR_STYLE_STROKE_BLACK);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user