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

Commit 4af90265 authored by Ebru Kurnaz's avatar Ebru Kurnaz Committed by Android (Google) Code Review
Browse files

Merge "Update Size preference if the resolution has changed." into main

parents 67fe8825 99117069
Loading
Loading
Loading
Loading
+9 −79
Original line number Diff line number Diff line
@@ -29,10 +29,7 @@ import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.Choreographer;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;
import android.window.DesktopExperienceFlags;

@@ -46,13 +43,10 @@ import androidx.preference.PreferenceGroup;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragmentBase;
import com.android.settings.accessibility.AccessibilitySeekBarPreference;
import com.android.settings.accessibility.DisplaySizeData;
import com.android.settings.accessibility.TextReadingPreferenceFragment;
import com.android.settings.connecteddevice.display.ExternalDisplaySettingsConfiguration.DisplayListener;
import com.android.settings.connecteddevice.display.ExternalDisplaySettingsConfiguration.Injector;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.display.DisplayDensityUtils;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.IllustrationPreference;
import com.android.settingslib.widget.MainSwitchPreference;
@@ -352,38 +346,22 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
    }

    @NonNull
    private AccessibilitySeekBarPreference reuseSizePreference(Context context,
            PrefRefresh refresh, int displayId, int position) {
        AccessibilitySeekBarPreference pref =
    private ExternalDisplaySizePreference reuseSizePreference(Context context,
            PrefRefresh refresh, DisplayDevice display, int position) {
        ExternalDisplaySizePreference pref =
                refresh.findUnusedPreference(PrefBasics.EXTERNAL_DISPLAY_SIZE.keyForNth(position));
        if (pref == null) {
            pref = new AccessibilitySeekBarPreference(context, /* attrs= */ null);
            pref.setIconStart(R.drawable.ic_remove_24dp);
            pref.setIconStartContentDescription(R.string.screen_zoom_make_smaller_desc);
            pref.setIconEnd(R.drawable.ic_add_24dp);
            pref.setIconEndContentDescription(R.string.screen_zoom_make_larger_desc);
            pref = new ExternalDisplaySizePreference(context, /* attrs= */ null);
            PrefBasics.EXTERNAL_DISPLAY_SIZE.apply(pref, position);

            setStateForDisplaySizePreference(context, displayId, pref);
        }
        if (display.getMode() != null) {
            pref.setStateForPreference(display.getMode().getPhysicalWidth(),
                    display.getMode().getPhysicalHeight(), display.getId());
        }
        refresh.addPreference(pref);
        return pref;
    }

    private void setStateForDisplaySizePreference(Context context, int displayId,
            AccessibilitySeekBarPreference preference) {
        var displaySizeData = new DisplaySizeData(context,
                new DisplayDensityUtils(context, (info) -> info.displayId == displayId));
        ExternalDisplaySizePreferenceStateHandler seekBarChangeHandler =
                new ExternalDisplaySizePreferenceStateHandler(
                        displaySizeData, preference);

        preference.setMax(displaySizeData.getValues().size() - 1);
        preference.setProgress(displaySizeData.getInitialIndex());
        preference.setContinuousUpdates(false);
        preference.setOnSeekBarChangeListener(seekBarChangeHandler);
    }

    private void update() {
        final var screen = getPreferenceScreen();
        if (screen == null || mInjector == null || mInjector.getContext() == null) {
@@ -587,7 +565,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen

    private void addSizePreference(final Context context, PrefRefresh refresh,
            DisplayDevice display, int position) {
        var pref = reuseSizePreference(context, refresh, display.getId(), position);
        var pref = reuseSizePreference(context, refresh, display, position);
        pref.setSummary(EXTERNAL_DISPLAY_SIZE_SUMMARY_RESOURCE);
        pref.setOnPreferenceClickListener(
                (Preference p) -> {
@@ -637,54 +615,6 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
        }
    }

    private static class ExternalDisplaySizePreferenceStateHandler
            implements SeekBar.OnSeekBarChangeListener {
        private static final long MIN_COMMIT_INTERVAL_MS = 800;
        private static final long CHANGE_BY_BUTTON_DELAY_MS = 300;
        private final DisplaySizeData mDisplaySizeData;
        private int mLastDisplayProgress;
        private long mLastCommitTime;
        private final AccessibilitySeekBarPreference mPreference;
        ExternalDisplaySizePreferenceStateHandler(DisplaySizeData displaySizeData,
                AccessibilitySeekBarPreference preference) {
            mDisplaySizeData = displaySizeData;
            mPreference = preference;
        }

        final Choreographer.FrameCallback mCommit = this::tryCommitDisplaySizeConfig;

        private void tryCommitDisplaySizeConfig(long unusedFrameTimeNanos) {
            final int displayProgress = mPreference.getProgress();
            if (displayProgress != mLastDisplayProgress) {
                mDisplaySizeData.commit(displayProgress);
                mLastDisplayProgress = displayProgress;
            }
            mLastCommitTime = SystemClock.elapsedRealtime();
        }

        private void postCommitDelayed() {
            var commitDelayMs = CHANGE_BY_BUTTON_DELAY_MS;
            if (SystemClock.elapsedRealtime() - mLastCommitTime < MIN_COMMIT_INTERVAL_MS) {
                commitDelayMs += MIN_COMMIT_INTERVAL_MS;
            }

            final Choreographer choreographer = Choreographer.getInstance();
            choreographer.removeFrameCallback(mCommit);
            choreographer.postFrameCallbackDelayed(mCommit, commitDelayMs);
        }

        @Override
        public void onProgressChanged(@NonNull SeekBar seekBar, int i, boolean b) {
            postCommitDelayed();
        }

        @Override
        public void onStartTrackingTouch(@NonNull SeekBar seekBar) {}

        @Override
        public void onStopTrackingTouch(@NonNull SeekBar seekBar) {}
    }

    private static class PrefRefresh implements AutoCloseable {
        private final PreferenceGroup mScreen;
        private final HashMap<String, Preference> mUnusedPreferences = new HashMap<>();
+124 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

package com.android.settings.connecteddevice.display;

import android.content.Context;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.Choreographer;
import android.widget.SeekBar;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.settings.R;
import com.android.settings.accessibility.AccessibilitySeekBarPreference;
import com.android.settings.accessibility.DisplaySizeData;
import com.android.settingslib.display.DisplayDensityUtils;

/**
 * The display size preference setting used for External displays.
 */
public class ExternalDisplaySizePreference extends AccessibilitySeekBarPreference {
    private int mDisplayWidth;
    private int mDisplayHeight;
    private int mDisplayId;
    private Context mContext;

    public ExternalDisplaySizePreference(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        mDisplayId = -1;
        mDisplayWidth = 0;
        mDisplayHeight = 0;

        setIconStart(R.drawable.ic_remove_24dp);
        setIconStartContentDescription(R.string.screen_zoom_make_smaller_desc);
        setIconEnd(R.drawable.ic_add_24dp);
        setIconEndContentDescription(R.string.screen_zoom_make_larger_desc);
    }

    /** Sets the display width and height for this preference. */
    public void setStateForPreference(int displayWidth, int displayHeight, int displayId) {
        if (mDisplayWidth == displayWidth && mDisplayHeight == displayHeight
                && displayId == mDisplayId) return;
        mDisplayWidth = displayWidth;
        mDisplayHeight = displayHeight;
        mDisplayId = displayId;

        setStateForPreferenceInternal();
    }

    private void setStateForPreferenceInternal() {
        var displaySizeData = new DisplaySizeData(mContext,
                new DisplayDensityUtils(mContext, (info) -> info.displayId == mDisplayId));
        ExternalDisplaySizePreferenceStateHandler
                seekBarChangeHandler =
                new ExternalDisplaySizePreferenceStateHandler(
                        displaySizeData);

        setMax(displaySizeData.getValues().size() - 1);
        setProgress(displaySizeData.getInitialIndex());
        setContinuousUpdates(false);
        setOnSeekBarChangeListener(seekBarChangeHandler);
    }

    private class ExternalDisplaySizePreferenceStateHandler
            implements SeekBar.OnSeekBarChangeListener {
        private static final long MIN_COMMIT_INTERVAL_MS = 800;
        private static final long CHANGE_BY_BUTTON_DELAY_MS = 300;
        private final DisplaySizeData mDisplaySizeData;
        private int mLastDisplayProgress;
        private long mLastCommitTime;
        ExternalDisplaySizePreferenceStateHandler(DisplaySizeData displaySizeData) {
            mDisplaySizeData = displaySizeData;
        }

        final Choreographer.FrameCallback mCommit = this::tryCommitDisplaySizeConfig;

        private void tryCommitDisplaySizeConfig(long unusedFrameTimeNanos) {
            final int displayProgress = getProgress();
            if (displayProgress != mLastDisplayProgress) {
                mDisplaySizeData.commit(displayProgress);
                mLastDisplayProgress = displayProgress;
            }
            mLastCommitTime = SystemClock.elapsedRealtime();
        }

        private void postCommitDelayed() {
            var commitDelayMs = CHANGE_BY_BUTTON_DELAY_MS;
            if (SystemClock.elapsedRealtime() - mLastCommitTime < MIN_COMMIT_INTERVAL_MS) {
                commitDelayMs += MIN_COMMIT_INTERVAL_MS;
            }

            final Choreographer choreographer = Choreographer.getInstance();
            choreographer.removeFrameCallback(mCommit);
            choreographer.postFrameCallbackDelayed(mCommit, commitDelayMs);
        }

        @Override
        public void onProgressChanged(@NonNull SeekBar seekBar, int i, boolean b) {
            postCommitDelayed();
        }

        @Override
        public void onStartTrackingTouch(@NonNull SeekBar seekBar) {}

        @Override
        public void onStopTrackingTouch(@NonNull SeekBar seekBar) {}
    }
}