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

Commit 1f8d924a authored by Katie Dektar's avatar Katie Dektar
Browse files

[A11y] Fix bug where magnification jumps between zoom levels

Fullscreen magnification would get into a state where it continuously
jumped between zoom levels when a pinch zoom or keyboard shortcut
zoom came in at the same time as the window magnification settings
panel was opened. This can be fixed by passing in 'fromUser',
which indicates that the user did not initiate the change and it
can be ignored.

Tested manually with TalkBack to ensure that TalkBack changes to
the progress bar (using the swipe up/down gestures) still cause
magnification scale changes. TalkBack interacting with the +/-
buttons also still cause scale changes.

Bug: 392946442
Test: atest SeekBarWithIconButtonsViewTest
Test: atest WindowMagnificationSettingsTest
Test: Manual with TalkBack
Flag: EXEMPT bugfix
Change-Id: I0d0b925bb00562fa7bec187e59702c28429b4e07
parent c533272a
Loading
Loading
Loading
Loading
+23 −2
Original line number Diff line number Diff line
@@ -130,12 +130,17 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
    @Test
    public void setProgress_onProgressChangedAndOnUserInteractionFinalized() {
        reset(mOnSeekBarChangeListener);
        mIconDiscreteSliderLinearLayout.setProgress(1);

        // Trigger the progress changed listener with fromUser but without clicking.
        // This is similar to what would happen if an accessibility service changed the
        // progress.
        mIconDiscreteSliderLinearLayout.getSeekBarChangeListener().onProgressChanged(
                mIconDiscreteSliderLinearLayout.getSeekbar(), 1, /*fromUser=*/ true);

        // If users are changing seekbar progress without touching the seekbar or clicking the
        // buttons, trigger onUserInteractionFinalized.
        verify(mOnSeekBarChangeListener).onProgressChanged(
                eq(mSeekbar), /* progress= */ eq(1), /* fromUser= */ eq(false));
                eq(mSeekbar), /* progress= */ eq(1), /* fromUser= */ eq(true));
        verify(mOnSeekBarChangeListener, never()).onStartTrackingTouch(/* seekBar= */ any());
        verify(mOnSeekBarChangeListener, never()).onStopTrackingTouch(/* seekBar= */ any());
        verify(mOnSeekBarChangeListener).onUserInteractionFinalized(
@@ -143,6 +148,22 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
                eq(OnSeekBarWithIconButtonsChangeListener.ControlUnitType.SLIDER));
    }

    @Test
    public void setProgress_onProgressChangedWithoutUserInteractionFinalized() {
        reset(mOnSeekBarChangeListener);
        mIconDiscreteSliderLinearLayout.setProgress(1);

        // If seekbar progress changes due to a non-user event, without touching the seekbar or
        // clicking the buttons, do not trigger onUserInteractionFinalized.
        verify(mOnSeekBarChangeListener).onProgressChanged(
                eq(mSeekbar), /* progress= */ eq(1), /* fromUser= */ eq(false));
        verify(mOnSeekBarChangeListener, never()).onStartTrackingTouch(/* seekBar= */ any());
        verify(mOnSeekBarChangeListener, never()).onStopTrackingTouch(/* seekBar= */ any());
        verify(mOnSeekBarChangeListener, never()).onUserInteractionFinalized(
                /* seekBar= */ any(),
                eq(OnSeekBarWithIconButtonsChangeListener.ControlUnitType.SLIDER));
    }

    @Test
    public void setProgressToSeekBarByTouch_onUserInteractionFinalizedAfterTouchEnds() {
        reset(mOnSeekBarChangeListener);
+8 −7
Original line number Diff line number Diff line
@@ -174,14 +174,15 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            // Notify the service to update the magnifier scale only when the progress changed is
            // triggered by user interaction on seekbar
            if (fromUser) {
            // triggered by user interaction on seekbar.
            if (!fromUser) {
                return;
            }
            final float scale = transformProgressToScale(progress);
            // We don't need to update the persisted scale when the seekbar progress is
            // changing. The update should be triggered when the changing is ended.
            mCallback.onMagnifierScale(scale, /* updatePersistence= */ false);
        }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
@@ -195,7 +196,7 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest

        @Override
        public void onUserInteractionFinalized(SeekBar seekBar, @ControlUnitType int control) {
            // Update the Settings persisted scale only when user interaction with seekbar ends
            // Update the Settings persisted scale only when user interaction with seekbar ends.
            final int progress = seekBar.getProgress();
            final float scale = transformProgressToScale(progress);
            mCallback.onMagnifierScale(scale, /* updatePersistence= */ true);
+7 −7
Original line number Diff line number Diff line
@@ -88,7 +88,7 @@ constructor(
        dialog.setPositiveButton(
            R.string.quick_settings_done,
            /* onClick = */ null,
            /* dismissOnClick = */ true
            /* dismissOnClick = */ true,
        )
    }

@@ -102,7 +102,7 @@ constructor(
            labelArray[i] =
                context.resources.getString(
                    com.android.settingslib.R.string.font_scale_percentage,
                    (strEntryValues[i].toFloat() * 100).roundToInt()
                    (strEntryValues[i].toFloat() * 100).roundToInt(),
                )
        }
        seekBarWithIconButtonsView.setProgressStateLabels(labelArray)
@@ -132,7 +132,7 @@ constructor(

                override fun onUserInteractionFinalized(
                    seekBar: SeekBar,
                    @ControlUnitType control: Int
                    @ControlUnitType control: Int,
                ) {
                    if (control == ControlUnitType.BUTTON) {
                        // The seekbar progress is changed by icon buttons
@@ -216,7 +216,7 @@ constructor(
            !systemSettings.putStringForUser(
                Settings.System.FONT_SCALE,
                strEntryValues[lastProgress.get()],
                userTracker.userId
                userTracker.userId,
            )
        ) {
            title.post { doneButton.isEnabled = true }
@@ -228,13 +228,13 @@ constructor(
        if (
            secureSettings.getStringForUser(
                Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED,
                userTracker.userId
                userTracker.userId,
            ) != ON
        ) {
            secureSettings.putStringForUser(
                Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED,
                ON,
                userTracker.userId
                userTracker.userId,
            )
        }
    }
@@ -249,7 +249,7 @@ constructor(

        title.setTextSize(
            TypedValue.COMPLEX_UNIT_PX,
            previewConfigContext.resources.getDimension(R.dimen.dialog_title_text_size)
            previewConfigContext.resources.getDimension(R.dimen.dialog_title_text_size),
        )
    }

+9 −4
Original line number Diff line number Diff line
@@ -286,7 +286,8 @@ public class SeekBarWithIconButtonsView extends LinearLayout {

        /**
         * Notification that the user interaction with SeekBarWithIconButtonsView is finalized. This
         * would be triggered after user ends dragging on the slider or clicks icon buttons.
         * would be triggered after user ends dragging on the slider or clicks icon buttons. This is
         * not called if the progress change was not initiated by the user.
         *
         * @param seekBar The SeekBar in which the user ends interaction with
         * @param control The last user interacted control unit. It would be
@@ -318,10 +319,14 @@ public class SeekBarWithIconButtonsView extends LinearLayout {
                            seekBar, OnSeekBarWithIconButtonsChangeListener.ControlUnitType.BUTTON);
                } else {
                    mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
                    if (!mSeekByTouch) {
                    if (!mSeekByTouch && fromUser) {
                        // Accessibility users could change the progress of the seekbar without
                        // touching the seekbar or clicking the buttons. We will consider the
                        // interaction has finished in this case.
                        // touching the seekbar or clicking the buttons. In this, {@code fromUser}
                        // will be true, and we will consider the interaction to be finished.
                        // The seekbar progress could be changed when {@code fromUser} is false
                        // when magnification scale is set by pinch-to-zoom, keyboard control, or
                        // other services. In this case, we don't need to take finalized actions
                        // for the progress change.
                        mOnSeekBarChangeListener.onUserInteractionFinalized(
                                seekBar,
                                OnSeekBarWithIconButtonsChangeListener.ControlUnitType.SLIDER);
+12 −1
Original line number Diff line number Diff line
@@ -552,11 +552,22 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase {
                mockSeekBar,
                OnSeekBarWithIconButtonsChangeListener.ControlUnitType.SLIDER);

        // should trigger callback to update magnifier scale and persist the scale
        // Should trigger callback to update magnifier scale and persist the scale.
        verify(mWindowMagnificationSettingsCallback)
                .onMagnifierScale(/* scale= */ eq(4f), /* updatePersistence= */ eq(true));
    }

    @Test
    public void onSeekbarUserInteractionFinalized_notFromUser_persistedScaleNotUpdated() {
        OnSeekBarWithIconButtonsChangeListener onChangeListener =
                mZoomSeekbar.getOnSeekBarWithIconButtonsChangeListener();
        onChangeListener.onProgressChanged(mZoomSeekbar.getSeekbar(), 30, false);

        // Should not trigger callback to update magnifier scale and persist the scale.
        verify(mWindowMagnificationSettingsCallback, never())
                .onMagnifierScale(/* scale= */ anyFloat(), /* updatePersistence= */ eq(true));
    }

    @Test
    public void seekbarProgress_scaleUpdatedAfterSettingPanelOpened_progressAlsoUpdated() {
        setupMagnificationCapabilityAndMode(