Skip to content

Commit a5744e8

Browse files
authored
feat(displays): add X11 scaling settings
1 parent 47c6329 commit a5744e8

File tree

2 files changed

+104
-17
lines changed

2 files changed

+104
-17
lines changed

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

Lines changed: 98 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@ use cosmic::iced::{time, Alignment, Length};
1010
use cosmic::iced_widget::scrollable::{Direction, Properties, RelativeOffset};
1111
use cosmic::prelude::CollectionWidget;
1212
use cosmic::widget::{
13-
self, column, container, dropdown, list_column, segmented_button, tab_bar, toggler,
13+
self, column, container, dropdown, list_column, segmented_button, tab_bar, text, toggler,
1414
};
1515
use cosmic::{command, Apply, Command, Element};
16+
use cosmic_config::{ConfigGet, ConfigSet};
1617
use cosmic_randr_shell::{List, Output, OutputKey, Transform};
1718
use cosmic_settings_page::{self as page, section, Section};
1819
use once_cell::sync::Lazy;
1920
use slab::Slab;
2021
use slotmap::{Key, SecondaryMap, SlotMap};
2122
use std::{collections::BTreeMap, process::ExitStatus, sync::Arc};
23+
use tracing::error;
2224

2325
static DPI_SCALES: &[u32] = &[50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300];
2426
static DPI_SCALE_LABELS: Lazy<Vec<String>> =
@@ -98,6 +100,7 @@ pub enum Message {
98100
/// Available outputs from cosmic-randr.
99101
randr: Arc<Result<List, cosmic_randr_shell::Error>>,
100102
},
103+
SetXwaylandDescaling(bool),
101104
}
102105

103106
impl From<Message> for app::Message {
@@ -137,10 +140,22 @@ pub struct Page {
137140
/// the instant the setting was changed.
138141
dialog_countdown: usize,
139142
show_display_options: bool,
143+
comp_config: cosmic_config::Config,
144+
comp_config_descale_xwayland: bool,
140145
}
141146

142147
impl Default for Page {
143148
fn default() -> Self {
149+
let comp_config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap();
150+
let comp_config_descale_xwayland =
151+
comp_config.get("descale_xwayland").unwrap_or_else(|err| {
152+
if !matches!(err, cosmic_config::Error::NoConfigDirectory) {
153+
error!(?err, "Failed to read config 'descale_xwayland'");
154+
}
155+
156+
false
157+
});
158+
144159
Self {
145160
list: List::default(),
146161
display_tabs: segmented_button::SingleSelectModel::default(),
@@ -156,6 +171,8 @@ impl Default for Page {
156171
dialog: None,
157172
dialog_countdown: 0,
158173
show_display_options: true,
174+
comp_config,
175+
comp_config_descale_xwayland,
159176
}
160177
}
161178
}
@@ -204,6 +221,8 @@ impl page::Page<crate::pages::Message> for Page {
204221
sections.insert(display_arrangement()),
205222
// Display configuration
206223
sections.insert(display_configuration()),
224+
// Xwayland scaling options
225+
sections.insert(legacy_applications()),
207226
])
208227
}
209228

@@ -470,6 +489,16 @@ impl Page {
470489
fl!("orientation", "rotate-270"),
471490
];
472491
}
492+
493+
Message::SetXwaylandDescaling(descale) => {
494+
self.comp_config_descale_xwayland = descale;
495+
if let Err(err) = self
496+
.comp_config
497+
.set("descale_xwayland", &self.comp_config_descale_xwayland)
498+
{
499+
error!(?err, "Failed to set config 'descale_xwayland'");
500+
}
501+
}
473502
}
474503

475504
self.last_pan = 0.5;
@@ -1018,28 +1047,28 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
10181047
let active_output = &page.list.outputs[active_id];
10191048

10201049
let display_options = (page.show_display_options && active_output.enabled).then(|| {
1021-
list_column()
1022-
.add(widget::settings::item(
1050+
vec![
1051+
widget::settings::item(
10231052
&descriptions[resolution],
10241053
dropdown(
10251054
&page.cache.resolutions,
10261055
page.cache.resolution_selected,
10271056
Message::Resolution,
10281057
),
1029-
))
1030-
.add(widget::settings::item(
1058+
),
1059+
widget::settings::item(
10311060
&descriptions[refresh_rate],
10321061
dropdown(
10331062
&page.cache.refresh_rates,
10341063
page.cache.refresh_rate_selected,
10351064
Message::RefreshRate,
10361065
),
1037-
))
1038-
.add(widget::settings::item(
1066+
),
1067+
widget::settings::item(
10391068
&descriptions[scale],
10401069
dropdown(&DPI_SCALE_LABELS, page.cache.scale_selected, Message::Scale),
1041-
))
1042-
.add(widget::settings::item(
1070+
),
1071+
widget::settings::item(
10431072
&descriptions[orientation],
10441073
dropdown(
10451074
&page.cache.orientations,
@@ -1053,10 +1082,11 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
10531082
})
10541083
},
10551084
),
1056-
))
1085+
),
1086+
]
10571087
});
10581088

1059-
let mut content = column().spacing(theme.cosmic().space_m());
1089+
let mut content = column().spacing(theme.cosmic().space_xs());
10601090

10611091
if page.list.outputs.len() > 1 {
10621092
let display_switcher = tab_bar::horizontal(&page.display_tabs)
@@ -1073,7 +1103,7 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
10731103
> 1
10741104
|| !active_output.enabled)
10751105
.then(|| {
1076-
list_column()
1106+
let mut column = list_column()
10771107
.add(widget::settings::item(
10781108
&descriptions[enable_label],
10791109
toggler(None, active_output.enabled, Message::DisplayToggle),
@@ -1084,17 +1114,68 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
10841114
&page.mirror_menu,
10851115
Message::Mirroring,
10861116
),
1087-
))
1117+
));
1118+
1119+
if let Some(items) = display_options {
1120+
for item in items {
1121+
column = column.add(item);
1122+
}
1123+
}
1124+
1125+
column
10881126
});
10891127

10901128
content = content.push(display_switcher).push_maybe(display_enable);
1129+
} else {
1130+
content = content
1131+
.push(widget::text::heading(&descriptions[options_label]))
1132+
.push_maybe(display_options.map(|items| {
1133+
let mut column = list_column();
1134+
for item in items {
1135+
column = column.add(item);
1136+
}
1137+
column
1138+
}));
10911139
}
10921140

1093-
content
1094-
.push(widget::text::heading(&descriptions[options_label]))
1095-
.push_maybe(display_options)
1141+
content.apply(Element::from).map(pages::Message::Displays)
1142+
})
1143+
}
1144+
1145+
pub fn legacy_applications() -> Section<crate::pages::Message> {
1146+
let mut descriptions = Slab::new();
1147+
1148+
let system = descriptions.insert(fl!("legacy-applications", "scaled-by-system"));
1149+
let system_desc = descriptions.insert(fl!("legacy-applications", "system-description"));
1150+
let native = descriptions.insert(fl!("legacy-applications", "scaled-natively"));
1151+
let native_desc = descriptions.insert(fl!("legacy-applications", "native-description"));
1152+
1153+
Section::default()
1154+
.title(fl!("legacy-applications"))
1155+
.descriptions(descriptions)
1156+
.view::<Page>(move |_binder, page, section| {
1157+
let descriptions = &section.descriptions;
1158+
widget::settings::view_section(&section.title)
1159+
.add(widget::settings::item_row(vec![widget::radio(
1160+
widget::column()
1161+
.push(text::body(&descriptions[system]))
1162+
.push(text::caption(&descriptions[system_desc])),
1163+
false,
1164+
Some(page.comp_config_descale_xwayland),
1165+
Message::SetXwaylandDescaling,
1166+
)
1167+
.into()]))
1168+
.add(widget::settings::item_row(vec![widget::radio(
1169+
widget::column()
1170+
.push(text::body(&descriptions[native]))
1171+
.push(text::caption(&descriptions[native_desc])),
1172+
true,
1173+
Some(page.comp_config_descale_xwayland),
1174+
Message::SetXwaylandDescaling,
1175+
)
1176+
.into()]))
10961177
.apply(Element::from)
1097-
.map(pages::Message::Displays)
1178+
.map(crate::pages::Message::Displays)
10981179
})
10991180
}
11001181

i18n/en/cosmic_settings.ftl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,12 @@ dialog = Dialog
262262
.change-prompt = Settings changes will automatically revert in { $time } seconds.
263263
.revert-settings = Revert Settings
264264
265+
legacy-applications = X11 Window System Application Scaling
266+
.scaled-by-system = Scale all X11 Applications
267+
.system-description = X11 applications will appear blurry on HiDPI screens.
268+
.scaled-natively = Render X11 Applications at native resolution
269+
.native-description = X11 applications that don't support scaling will be small when HiDPI displays are in use. Enable for games to utilize the full monitor resolution.
270+
265271
## Sound
266272

267273
sound = Sound

0 commit comments

Comments
 (0)