feat(displays): add X11 scaling settings

This commit is contained in:
Victoria Brekenfeld 2024-09-03 14:29:14 +02:00 committed by GitHub
parent 47c6329645
commit a5744e8bdb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 104 additions and 17 deletions

View file

@ -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<Vec<String>> =
@ -98,6 +100,7 @@ pub enum Message {
/// Available outputs from cosmic-randr.
randr: Arc<Result<List, cosmic_randr_shell::Error>>,
},
SetXwaylandDescaling(bool),
}
impl From<Message> 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<crate::pages::Message> 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<crate::pages::Message> {
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<crate::pages::Message> {
})
},
),
))
),
]
});
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<crate::pages::Message> {
> 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<crate::pages::Message> {
&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<crate::pages::Message> {
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::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
widget::settings::view_section(&section.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)
})
}

View file

@ -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