From a5744e8bdbc57d1b2bf7e354dd66f474efcd6560 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld <4404502+Drakulix@users.noreply.github.com> Date: Tue, 3 Sep 2024 14:29:14 +0200 Subject: [PATCH] feat(displays): add X11 scaling settings --- cosmic-settings/src/pages/display/mod.rs | 115 +++++++++++++++++++---- i18n/en/cosmic_settings.ftl | 6 ++ 2 files changed, 104 insertions(+), 17 deletions(-) diff --git a/cosmic-settings/src/pages/display/mod.rs b/cosmic-settings/src/pages/display/mod.rs index cc5d797..2adb5b0 100644 --- a/cosmic-settings/src/pages/display/mod.rs +++ b/cosmic-settings/src/pages/display/mod.rs @@ -10,15 +10,17 @@ use cosmic::iced::{time, Alignment, Length}; use cosmic::iced_widget::scrollable::{Direction, Properties, RelativeOffset}; use cosmic::prelude::CollectionWidget; use cosmic::widget::{ - self, column, container, dropdown, list_column, segmented_button, tab_bar, toggler, + self, column, container, dropdown, list_column, segmented_button, tab_bar, text, toggler, }; use cosmic::{command, Apply, Command, Element}; +use cosmic_config::{ConfigGet, ConfigSet}; use cosmic_randr_shell::{List, Output, OutputKey, Transform}; use cosmic_settings_page::{self as page, section, Section}; use once_cell::sync::Lazy; use slab::Slab; use slotmap::{Key, SecondaryMap, SlotMap}; use std::{collections::BTreeMap, process::ExitStatus, sync::Arc}; +use tracing::error; static DPI_SCALES: &[u32] = &[50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300]; static DPI_SCALE_LABELS: Lazy> = @@ -98,6 +100,7 @@ pub enum Message { /// Available outputs from cosmic-randr. randr: Arc>, }, + SetXwaylandDescaling(bool), } impl From for app::Message { @@ -137,10 +140,22 @@ pub struct Page { /// the instant the setting was changed. dialog_countdown: usize, show_display_options: bool, + comp_config: cosmic_config::Config, + comp_config_descale_xwayland: bool, } impl Default for Page { fn default() -> Self { + let comp_config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap(); + let comp_config_descale_xwayland = + comp_config.get("descale_xwayland").unwrap_or_else(|err| { + if !matches!(err, cosmic_config::Error::NoConfigDirectory) { + error!(?err, "Failed to read config 'descale_xwayland'"); + } + + false + }); + Self { list: List::default(), display_tabs: segmented_button::SingleSelectModel::default(), @@ -156,6 +171,8 @@ impl Default for Page { dialog: None, dialog_countdown: 0, show_display_options: true, + comp_config, + comp_config_descale_xwayland, } } } @@ -204,6 +221,8 @@ impl page::Page for Page { sections.insert(display_arrangement()), // Display configuration sections.insert(display_configuration()), + // Xwayland scaling options + sections.insert(legacy_applications()), ]) } @@ -470,6 +489,16 @@ impl Page { fl!("orientation", "rotate-270"), ]; } + + Message::SetXwaylandDescaling(descale) => { + self.comp_config_descale_xwayland = descale; + if let Err(err) = self + .comp_config + .set("descale_xwayland", &self.comp_config_descale_xwayland) + { + error!(?err, "Failed to set config 'descale_xwayland'"); + } + } } self.last_pan = 0.5; @@ -1018,28 +1047,28 @@ pub fn display_configuration() -> Section { let active_output = &page.list.outputs[active_id]; let display_options = (page.show_display_options && active_output.enabled).then(|| { - list_column() - .add(widget::settings::item( + vec![ + widget::settings::item( &descriptions[resolution], dropdown( &page.cache.resolutions, page.cache.resolution_selected, Message::Resolution, ), - )) - .add(widget::settings::item( + ), + widget::settings::item( &descriptions[refresh_rate], dropdown( &page.cache.refresh_rates, page.cache.refresh_rate_selected, Message::RefreshRate, ), - )) - .add(widget::settings::item( + ), + widget::settings::item( &descriptions[scale], dropdown(&DPI_SCALE_LABELS, page.cache.scale_selected, Message::Scale), - )) - .add(widget::settings::item( + ), + widget::settings::item( &descriptions[orientation], dropdown( &page.cache.orientations, @@ -1053,10 +1082,11 @@ pub fn display_configuration() -> Section { }) }, ), - )) + ), + ] }); - let mut content = column().spacing(theme.cosmic().space_m()); + let mut content = column().spacing(theme.cosmic().space_xs()); if page.list.outputs.len() > 1 { let display_switcher = tab_bar::horizontal(&page.display_tabs) @@ -1073,7 +1103,7 @@ pub fn display_configuration() -> Section { > 1 || !active_output.enabled) .then(|| { - list_column() + let mut column = list_column() .add(widget::settings::item( &descriptions[enable_label], toggler(None, active_output.enabled, Message::DisplayToggle), @@ -1084,17 +1114,68 @@ pub fn display_configuration() -> Section { &page.mirror_menu, Message::Mirroring, ), - )) + )); + + if let Some(items) = display_options { + for item in items { + column = column.add(item); + } + } + + column }); content = content.push(display_switcher).push_maybe(display_enable); + } else { + content = content + .push(widget::text::heading(&descriptions[options_label])) + .push_maybe(display_options.map(|items| { + let mut column = list_column(); + for item in items { + column = column.add(item); + } + column + })); } - content - .push(widget::text::heading(&descriptions[options_label])) - .push_maybe(display_options) + content.apply(Element::from).map(pages::Message::Displays) + }) +} + +pub fn legacy_applications() -> Section { + let mut descriptions = Slab::new(); + + let system = descriptions.insert(fl!("legacy-applications", "scaled-by-system")); + let system_desc = descriptions.insert(fl!("legacy-applications", "system-description")); + let native = descriptions.insert(fl!("legacy-applications", "scaled-natively")); + let native_desc = descriptions.insert(fl!("legacy-applications", "native-description")); + + Section::default() + .title(fl!("legacy-applications")) + .descriptions(descriptions) + .view::(move |_binder, page, section| { + let descriptions = §ion.descriptions; + widget::settings::view_section(§ion.title) + .add(widget::settings::item_row(vec![widget::radio( + widget::column() + .push(text::body(&descriptions[system])) + .push(text::caption(&descriptions[system_desc])), + false, + Some(page.comp_config_descale_xwayland), + Message::SetXwaylandDescaling, + ) + .into()])) + .add(widget::settings::item_row(vec![widget::radio( + widget::column() + .push(text::body(&descriptions[native])) + .push(text::caption(&descriptions[native_desc])), + true, + Some(page.comp_config_descale_xwayland), + Message::SetXwaylandDescaling, + ) + .into()])) .apply(Element::from) - .map(pages::Message::Displays) + .map(crate::pages::Message::Displays) }) } diff --git a/i18n/en/cosmic_settings.ftl b/i18n/en/cosmic_settings.ftl index d706683..ea1c402 100644 --- a/i18n/en/cosmic_settings.ftl +++ b/i18n/en/cosmic_settings.ftl @@ -262,6 +262,12 @@ dialog = Dialog .change-prompt = Settings changes will automatically revert in { $time } seconds. .revert-settings = Revert Settings +legacy-applications = X11 Window System Application Scaling + .scaled-by-system = Scale all X11 Applications + .system-description = X11 applications will appear blurry on HiDPI screens. + .scaled-natively = Render X11 Applications at native resolution + .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. + ## Sound sound = Sound