Skip to content

Commit 6aa692e

Browse files
committed
implement additional scale options
Signed-off-by: Dusan <[email protected]>
1 parent a90d7fb commit 6aa692e

File tree

2 files changed

+107
-11
lines changed

2 files changed

+107
-11
lines changed

cosmic-settings/src/pages/display/mod.rs

+106-11
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ use std::{collections::BTreeMap, process::ExitStatus, sync::Arc};
2424
use tokio::sync::oneshot;
2525
use tracing::error;
2626

27-
static DPI_SCALES: &[u32] = &[50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300];
27+
static DPI_SCALES: &[f64] = &[
28+
50.0, 75.0, 100.0, 125.0, 150.0, 175.0, 200.0, 225.0, 250.0, 275.0, 300.0,
29+
];
2830
static DPI_SCALE_LABELS: Lazy<Vec<String>> =
2931
Lazy::new(|| DPI_SCALES.iter().map(|scale| format!("{scale}%")).collect());
3032

@@ -100,6 +102,8 @@ pub enum Message {
100102
Resolution(usize),
101103
/// Set the preferred scale for a display.
102104
Scale(usize),
105+
SliderChangeScale(f64),
106+
SliderApplyScale,
103107
/// Refreshes display outputs.
104108
Update {
105109
/// Available outputs from cosmic-randr.
@@ -148,6 +152,7 @@ pub struct Page {
148152
show_display_options: bool,
149153
comp_config: cosmic_config::Config,
150154
comp_config_descale_xwayland: bool,
155+
slider_scale: Option<f64>,
151156
}
152157

153158
impl Default for Page {
@@ -177,6 +182,7 @@ impl Default for Page {
177182
dialog: None,
178183
dialog_countdown: 0,
179184
show_display_options: true,
185+
slider_scale: None,
180186
comp_config,
181187
comp_config_descale_xwayland,
182188
}
@@ -193,6 +199,13 @@ struct Config {
193199
scale: u32,
194200
}
195201

202+
#[derive(Default)]
203+
struct ScaleOptionsViewCache {
204+
scale_selected: Option<usize>,
205+
scale_values: Vec<f64>,
206+
scale_labels: Vec<String>,
207+
}
208+
196209
/// Cached view content for widgets.
197210
#[derive(Default)]
198211
struct ViewCache {
@@ -205,7 +218,18 @@ struct ViewCache {
205218
refresh_rate_selected: Option<usize>,
206219
vrr_selected: Option<usize>,
207220
resolution_selected: Option<usize>,
208-
scale_selected: Option<usize>,
221+
scale_options: ScaleOptionsViewCache,
222+
}
223+
224+
impl ScaleOptionsViewCache {
225+
fn scale_selected_as_value(&self) -> f64 {
226+
let selected = self.scale_selected;
227+
if let Some(selected) = selected {
228+
return *self.scale_values.get(selected).unwrap_or(DPI_SCALES.last().unwrap());
229+
}
230+
231+
*DPI_SCALES.last().unwrap()
232+
}
209233
}
210234

211235
impl page::AutoBind<crate::pages::Message> for Page {}
@@ -515,8 +539,15 @@ impl Page {
515539

516540
Message::Resolution(option) => return self.set_resolution(option),
517541

518-
Message::Scale(scale) => return self.set_scale(scale),
519-
542+
Message::Scale(option) => return self.set_scale_option(option),
543+
Message::SliderChangeScale(scale) => {
544+
self.slider_scale = Some(scale);
545+
}
546+
Message::SliderApplyScale => {
547+
if let Some(value) = self.slider_scale {
548+
return self.set_scale_value(value);
549+
}
550+
}
520551
Message::Update { randr } => {
521552
match Arc::into_inner(randr) {
522553
Some(Ok(outputs)) => self.update_displays(outputs),
@@ -664,10 +695,14 @@ impl Page {
664695
self.cache.refresh_rate_selected = None;
665696
self.cache.vrr_selected = None;
666697

667-
self.cache.scale_selected = Some(
668-
DPI_SCALES
698+
self.cache.scale_options.scale_labels = get_sorted_scale_labels(self.config.scale.try_into().unwrap());
699+
self.cache.scale_options.scale_values = get_sorted_scales(self.config.scale.try_into().unwrap());
700+
self.cache.scale_options.scale_selected = Some(
701+
self.cache
702+
.scale_options
703+
.scale_values
669704
.iter()
670-
.position(|scale| self.config.scale <= *scale)
705+
.position(|scale| self.config.scale <= scale.floor() as u32)
671706
.unwrap_or(DPI_SCALES.len() - 1),
672707
);
673708

@@ -913,20 +948,40 @@ impl Page {
913948
Task::batch(tasks)
914949
}
915950

951+
pub fn set_scale_option(&mut self, option: usize) -> Task<app::Message> {
952+
let value = self.cache
953+
.scale_options
954+
.scale_values
955+
.get(option)
956+
.unwrap_or(self.cache.scale_options.scale_values.last().unwrap());
957+
958+
self.set_scale_value(*value)
959+
}
960+
916961
/// Set the scale of the active display.
917-
pub fn set_scale(&mut self, option: usize) -> Task<app::Message> {
962+
pub fn set_scale_value(&mut self, value: f64) -> Task<app::Message> {
918963
let mut tasks = Vec::with_capacity(2);
919964

920965
let Some(output) = self.list.outputs.get(self.active_display) else {
921966
return Task::none();
922967
};
923968

924-
let scale = (option * 25 + 50) as u32;
969+
let scale = value.floor() as u32;
925970

926971
let request = Randr::Scale(scale);
927972
let revert_request = Randr::Scale(self.config.scale);
928973

929-
self.cache.scale_selected = Some(option);
974+
self.cache.scale_options.scale_labels = get_sorted_scale_labels(value);
975+
self.cache.scale_options.scale_values = get_sorted_scales(value);
976+
self.cache.scale_options.scale_selected = Some(
977+
self.cache
978+
.scale_options
979+
.scale_values
980+
.iter()
981+
.position(|scale| value <= *scale)
982+
.unwrap_or(self.cache.scale_options.scale_values.len() - 1),
983+
);
984+
930985
self.config.scale = scale;
931986
tasks.push(self.exec_randr(output, Randr::Scale(scale)));
932987
tasks.push(self.set_dialog(revert_request, &request));
@@ -1078,6 +1133,29 @@ impl Page {
10781133
}
10791134
}
10801135

1136+
fn get_sorted_scales(current_value: f64) -> Vec<f64> {
1137+
if DPI_SCALES.contains(&current_value ) {
1138+
return DPI_SCALES.to_vec();
1139+
}
1140+
1141+
let mut scales: Vec<f64> = DPI_SCALES.iter().copied().collect();
1142+
scales.push(current_value);
1143+
scales.sort_by(|a, b| a.partial_cmp(b).unwrap());
1144+
1145+
scales
1146+
}
1147+
1148+
fn get_sorted_scale_labels(current_value: f64) -> Vec<String> {
1149+
if DPI_SCALES.contains(&current_value) {
1150+
return DPI_SCALE_LABELS.to_vec();
1151+
}
1152+
1153+
return get_sorted_scales(current_value)
1154+
.iter()
1155+
.map(|v| format!("{v}%"))
1156+
.collect();
1157+
}
1158+
10811159
/// View for the display arrangement section.
10821160
pub fn display_arrangement() -> Section<crate::pages::Message> {
10831161
let mut descriptions = Slab::new();
@@ -1132,6 +1210,7 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
11321210
let vrr = descriptions.insert(fl!("vrr"));
11331211
let resolution = descriptions.insert(fl!("display", "resolution"));
11341212
let scale = descriptions.insert(fl!("display", "scale"));
1213+
let additional_scale_options = descriptions.insert(fl!("display", "additional-scale-options"));
11351214
let orientation = descriptions.insert(fl!("orientation"));
11361215
let enable_label = descriptions.insert(fl!("display", "enable"));
11371216
let options_label = descriptions.insert(fl!("display", "options"));
@@ -1183,7 +1262,23 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
11831262
items.extend(vec![
11841263
widget::settings::item(
11851264
&descriptions[scale],
1186-
dropdown(&DPI_SCALE_LABELS, page.cache.scale_selected, Message::Scale),
1265+
dropdown(
1266+
&page.cache.scale_options.scale_labels,
1267+
page.cache.scale_options.scale_selected,
1268+
Message::Scale,
1269+
),
1270+
),
1271+
widget::settings::item(
1272+
&descriptions[additional_scale_options],
1273+
widget::slider(
1274+
50.0..=300.0,
1275+
page.slider_scale.unwrap_or(
1276+
page.cache.scale_options.scale_selected_as_value()
1277+
),
1278+
Message::SliderChangeScale,
1279+
)
1280+
.on_release(Message::SliderApplyScale)
1281+
.breakpoints(DPI_SCALES),
11871282
),
11881283
widget::settings::item(
11891284
&descriptions[orientation],

i18n/en/cosmic_settings.ftl

+1
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ display = Displays
359359
.refresh-rate = Refresh rate
360360
.resolution = Resolution
361361
.scale = Scale
362+
.additional-scale-options = Additional scale options
362363
363364
mirroring = Mirroring
364365
.id = Mirroring { $id }

0 commit comments

Comments
 (0)