@@ -7,6 +7,7 @@ pub mod arrangement;
7
7
use crate :: { app, pages} ;
8
8
use arrangement:: Arrangement ;
9
9
use cosmic:: iced:: { time, Alignment , Length } ;
10
+ use cosmic:: iced_widget:: row;
10
11
use cosmic:: iced_widget:: scrollable:: { Direction , RelativeOffset , Scrollbar } ;
11
12
use cosmic:: widget:: {
12
13
self , column, container, dropdown, list_column, segmented_button, tab_bar, text, toggler,
@@ -18,18 +19,32 @@ use cosmic_randr_shell::{
18
19
} ;
19
20
use cosmic_settings_page:: { self as page, section, Section } ;
20
21
use futures:: pin_mut;
21
- use once_cell:: sync:: Lazy ;
22
22
use slab:: Slab ;
23
23
use slotmap:: { Key , SecondaryMap , SlotMap } ;
24
24
use std:: sync:: atomic:: { AtomicBool , Ordering } ;
25
25
use std:: { collections:: BTreeMap , process:: ExitStatus , sync:: Arc } ;
26
26
use tokio:: sync:: oneshot;
27
27
use tracing:: error;
28
28
29
- static DPI_SCALES : & [ u32 ] = & [ 50 , 75 , 100 , 125 , 150 , 175 , 200 , 225 , 250 , 275 , 300 ] ;
30
-
31
- static DPI_SCALE_LABELS : Lazy < Vec < String > > =
32
- Lazy :: new ( || DPI_SCALES . iter ( ) . map ( |scale| format ! ( "{scale}%" ) ) . collect ( ) ) ;
29
+ static DPI_SCALES : & [ ScaleValue ] = & [
30
+ ScaleValue :: Custom ,
31
+ ScaleValue :: Preset ( 50 ) ,
32
+ ScaleValue :: Preset ( 75 ) ,
33
+ ScaleValue :: Preset ( 100 ) ,
34
+ ScaleValue :: Preset ( 125 ) ,
35
+ ScaleValue :: Preset ( 150 ) ,
36
+ ScaleValue :: Preset ( 175 ) ,
37
+ ScaleValue :: Preset ( 200 ) ,
38
+ ScaleValue :: Preset ( 225 ) ,
39
+ ScaleValue :: Preset ( 250 ) ,
40
+ ScaleValue :: Preset ( 275 ) ,
41
+ ScaleValue :: Preset ( 300 ) ,
42
+ ] ;
43
+ fn scale_is_custom ( idx : usize ) -> bool {
44
+ idx == 0
45
+ }
46
+ static DPI_CUSTOM_SCALE_BREAKPOINTS : & [ u32 ] = & [ 50 , 100 , 150 , 200 , 250 , 300 ] ;
47
+ static DPI_CUSTOM_SCALE_RANGE : std:: ops:: RangeInclusive < u32 > = 50 ..=300 ;
33
48
34
49
/// Display color depth options
35
50
#[ allow( dead_code) ]
@@ -50,6 +65,11 @@ pub enum Mirroring {
50
65
Mirror ( OutputKey ) ,
51
66
}
52
67
68
+ pub enum ScaleValue {
69
+ Custom ,
70
+ Preset ( u32 ) ,
71
+ }
72
+
53
73
/// Night light preferences
54
74
// #[derive(Clone, Copy, Debug)]
55
75
// pub enum NightLight {
@@ -101,8 +121,10 @@ pub enum Message {
101
121
Resolution ( usize ) ,
102
122
/// Set the preferred scale for a display.
103
123
Scale ( usize ) ,
104
- /// Adjust the display scale.
105
- AdjustScale ( u32 ) ,
124
+ /// Set the displayed value for the custom scale.
125
+ CustomScaleDrag ( u32 ) ,
126
+ /// Confirm the custom scale change for a display.
127
+ CustomScale ,
106
128
/// Refreshes display outputs.
107
129
Update {
108
130
/// Available outputs from cosmic-randr.
@@ -153,7 +175,7 @@ pub struct Page {
153
175
show_display_options : bool ,
154
176
comp_config : cosmic_config:: Config ,
155
177
comp_config_descale_xwayland : bool ,
156
- adjusted_scale : u32 ,
178
+ custom_scale : Option < u32 > ,
157
179
}
158
180
159
181
impl Default for Page {
@@ -184,9 +206,9 @@ impl Default for Page {
184
206
dialog : None ,
185
207
dialog_countdown : 0 ,
186
208
show_display_options : true ,
187
- adjusted_scale : 0 ,
188
209
comp_config,
189
210
comp_config_descale_xwayland,
211
+ custom_scale : None ,
190
212
}
191
213
}
192
214
}
@@ -214,6 +236,7 @@ struct ViewCache {
214
236
vrr_selected : Option < usize > ,
215
237
resolution_selected : Option < usize > ,
216
238
scale_selected : Option < usize > ,
239
+ scales : Vec < String > ,
217
240
}
218
241
219
242
impl page:: AutoBind < crate :: pages:: Message > for Page { }
@@ -515,18 +538,15 @@ impl Page {
515
538
Message :: Resolution ( option) => return self . set_resolution ( option) ,
516
539
517
540
Message :: Scale ( option) => {
518
- self . adjusted_scale = 0 ;
519
- return self . set_scale ( option) ;
541
+ return self . set_scale_preset ( option) ;
520
542
}
521
543
522
- Message :: AdjustScale ( scale) => {
523
- if self . adjusted_scale != scale {
524
- self . adjusted_scale = scale ;
544
+ Message :: CustomScaleDrag ( scale) => {
545
+ self . custom_scale = Some ( scale) ;
546
+ }
525
547
526
- if let Some ( option) = self . cache . scale_selected {
527
- return self . set_scale ( option) ;
528
- }
529
- }
548
+ Message :: CustomScale => {
549
+ return self . set_scale ( self . custom_scale . unwrap ( ) ) ;
530
550
}
531
551
532
552
Message :: Update { randr } => {
@@ -673,18 +693,28 @@ impl Page {
673
693
self . cache . refresh_rate_selected = None ;
674
694
self . cache . vrr_selected = None ;
675
695
696
+ self . cache . scales = DPI_SCALES
697
+ . iter ( )
698
+ . map ( |s| match s {
699
+ ScaleValue :: Custom => fl ! ( "display" , "custom-scale-option" ) ,
700
+ ScaleValue :: Preset ( v) => format ! ( "{v}%" ) ,
701
+ } )
702
+ . collect ( ) ;
676
703
let selected_scale = DPI_SCALES
677
704
. iter ( )
678
- . position ( |scale| self . config . scale <= * scale)
679
- . unwrap_or ( DPI_SCALES . len ( ) - 1 ) ;
680
-
681
- self . adjusted_scale = ( ( self . config . scale % 25 ) . min ( 20 ) as f32 / 5.0 ) . round ( ) as u32 * 5 ;
682
- self . cache . scale_selected = Some ( if self . adjusted_scale != 0 && selected_scale > 0 {
683
- selected_scale - 1
684
- } else {
685
- selected_scale
686
- } ) ;
705
+ . position ( |s| matches ! ( s, ScaleValue :: Preset ( s) if * s == self . config. scale) )
706
+ . unwrap_or ( 0 ) ;
687
707
708
+ // If we are using a non-preset scale
709
+ if scale_is_custom ( selected_scale) {
710
+ self . custom_scale = Some ( self . config . scale ) ;
711
+ }
712
+ // If the previous state of the page had a custom scale but it coincides with a preset scale, we are still using a custom scale
713
+ if let Some ( v) = & mut self . custom_scale {
714
+ * v = self . config . scale ;
715
+ }
716
+
717
+ self . cache . scale_selected = Some ( selected_scale) ;
688
718
if let Some ( current_mode_id) = output. current {
689
719
for ( mode_id, mode) in output
690
720
. modes
@@ -927,20 +957,30 @@ impl Page {
927
957
Task :: batch ( tasks)
928
958
}
929
959
960
+ /// Set the scale preset of the active display.
961
+ pub fn set_scale_preset ( & mut self , option : usize ) -> Task < app:: Message > {
962
+ self . custom_scale = scale_is_custom ( option) . then_some ( self . config . scale ) ;
963
+ let scale = match DPI_SCALES [ option] {
964
+ ScaleValue :: Custom => self . custom_scale . unwrap ( ) ,
965
+ ScaleValue :: Preset ( value) => value,
966
+ } ;
967
+
968
+ self . cache . scale_selected = Some ( option) ;
969
+ self . set_scale ( scale)
970
+ }
971
+
930
972
/// Set the scale of the active display.
931
- pub fn set_scale ( & mut self , option : usize ) -> Task < app:: Message > {
973
+ pub fn set_scale ( & mut self , scale : u32 ) -> Task < app:: Message > {
932
974
let Some ( output) = self . list . outputs . get ( self . active_display ) else {
933
975
return Task :: none ( ) ;
934
976
} ;
935
977
936
- let mut tasks = Vec :: with_capacity ( 2 ) ;
937
-
938
- let scale = ( option * 25 + 50 ) as u32 + self . adjusted_scale . min ( 20 ) ;
939
-
940
- self . cache . scale_selected = Some ( option) ;
941
978
self . config . scale = scale;
942
- tasks. push ( self . exec_randr ( output, Randr :: Scale ( scale) ) ) ;
943
- Task :: batch ( tasks)
979
+ if let Some ( s) = & mut self . custom_scale {
980
+ * s = scale;
981
+ }
982
+
983
+ self . exec_randr ( output, Randr :: Scale ( scale) )
944
984
}
945
985
946
986
/// Enables or disables the active display.
@@ -1132,7 +1172,7 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
1132
1172
let vrr = descriptions. insert ( fl ! ( "vrr" ) ) ;
1133
1173
let resolution = descriptions. insert ( fl ! ( "display" , "resolution" ) ) ;
1134
1174
let scale = descriptions. insert ( fl ! ( "display" , "scale" ) ) ;
1135
- let additional_scale_options = descriptions. insert ( fl ! ( "display" , "additional -scale-options " ) ) ;
1175
+ let custom_scale = descriptions. insert ( fl ! ( "display" , "custom -scale" ) ) ;
1136
1176
let orientation = descriptions. insert ( fl ! ( "orientation" ) ) ;
1137
1177
let enable_label = descriptions. insert ( fl ! ( "display" , "enable" ) ) ;
1138
1178
let options_label = descriptions. insert ( fl ! ( "display" , "options" ) ) ;
@@ -1181,38 +1221,50 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
1181
1221
) ) ;
1182
1222
}
1183
1223
1184
- items. extend ( vec ! [
1185
- widget:: settings:: item(
1186
- & descriptions[ scale] ,
1187
- dropdown( & DPI_SCALE_LABELS , page. cache. scale_selected, Message :: Scale ) ,
1188
- ) ,
1189
- widget:: settings:: item(
1190
- & descriptions[ additional_scale_options] ,
1191
- widget:: spin_button(
1192
- format!( "{}%" , page. adjusted_scale) ,
1193
- page. adjusted_scale,
1194
- 5 ,
1195
- 0 ,
1196
- 20 ,
1197
- Message :: AdjustScale ,
1198
- ) ,
1224
+ items. push ( widget:: settings:: item (
1225
+ & descriptions[ scale] ,
1226
+ dropdown (
1227
+ & page. cache . scales ,
1228
+ page. cache . scale_selected ,
1229
+ Message :: Scale ,
1199
1230
) ,
1200
- widget:: settings:: item(
1201
- & descriptions[ orientation] ,
1202
- dropdown(
1203
- & page. cache. orientations,
1204
- page. cache. orientation_selected,
1205
- |id| {
1206
- Message :: Orientation ( match id {
1207
- 0 => Transform :: Normal ,
1208
- 1 => Transform :: Rotate90 ,
1209
- 2 => Transform :: Rotate180 ,
1210
- _ => Transform :: Rotate270 ,
1211
- } )
1212
- } ,
1213
- ) ,
1231
+ ) ) ;
1232
+
1233
+ if let Some ( s) = page. custom_scale {
1234
+ items. push ( widget:: settings:: item (
1235
+ & descriptions[ custom_scale] ,
1236
+ row ! [
1237
+ widget:: text:: body( format!( "{}%" , s) )
1238
+ . width( Length :: Fixed ( 22.0 ) )
1239
+ . align_x( Alignment :: Center ) ,
1240
+ widget:: horizontal_space( ) . width( 12 ) ,
1241
+ widget:: slider(
1242
+ DPI_CUSTOM_SCALE_RANGE . clone( ) ,
1243
+ s,
1244
+ Message :: CustomScaleDrag
1245
+ )
1246
+ . on_release( Message :: CustomScale )
1247
+ . breakpoints( DPI_CUSTOM_SCALE_BREAKPOINTS )
1248
+ . step( 5u32 )
1249
+ ] ,
1250
+ ) ) ;
1251
+ }
1252
+
1253
+ items. push ( widget:: settings:: item (
1254
+ & descriptions[ orientation] ,
1255
+ dropdown (
1256
+ & page. cache . orientations ,
1257
+ page. cache . orientation_selected ,
1258
+ |id| {
1259
+ Message :: Orientation ( match id {
1260
+ 0 => Transform :: Normal ,
1261
+ 1 => Transform :: Rotate90 ,
1262
+ 2 => Transform :: Rotate180 ,
1263
+ _ => Transform :: Rotate270 ,
1264
+ } )
1265
+ } ,
1214
1266
) ,
1215
- ] ) ;
1267
+ ) ) ;
1216
1268
1217
1269
items
1218
1270
} ) ;
0 commit comments