From 43a2bdfd68d85276f8ead77eb6cd9c01beeaab34 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Mon, 10 Mar 2025 14:41:40 -0400 Subject: [PATCH] feat: high contrast toggle --- Cargo.lock | 34 ++++---- cosmic-settings/src/app.rs | 15 ++++ .../src/pages/accessibility/mod.rs | 79 ++++++++++++++++++- i18n/en/cosmic_settings.ftl | 1 + 4 files changed, 110 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4513b39..480cbbcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1519,7 +1519,7 @@ dependencies = [ [[package]] name = "cosmic-config" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "atomicwrites", "cosmic-config-derive", @@ -1541,7 +1541,7 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "quote", "syn 1.0.109", @@ -1822,8 +1822,8 @@ dependencies = [ [[package]] name = "cosmic-text" -version = "0.12.1" -source = "git+https://github.com/pop-os/cosmic-text.git#974ddaed96b334f560b606ebe5d2ca2d2f9f23ef" +version = "0.13.1" +source = "git+https://github.com/pop-os/cosmic-text.git#60f2c2b0c2e7cf8734b3ad0fc94ef7bce94f649b" dependencies = [ "bitflags 2.8.0", "fontdb 0.16.2", @@ -1845,7 +1845,7 @@ dependencies = [ [[package]] name = "cosmic-theme" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "almost", "cosmic-config", @@ -3216,7 +3216,7 @@ dependencies = [ [[package]] name = "iced" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "dnd", "iced_accessibility", @@ -3234,7 +3234,7 @@ dependencies = [ [[package]] name = "iced_accessibility" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "accesskit", "accesskit_winit", @@ -3243,7 +3243,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "bitflags 2.8.0", "bytes", @@ -3268,7 +3268,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "futures", "iced_core", @@ -3294,7 +3294,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "bitflags 2.8.0", "bytemuck", @@ -3316,7 +3316,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -3328,7 +3328,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "bytes", "cosmic-client-toolkit", @@ -3344,7 +3344,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "bytemuck", "cosmic-text", @@ -3360,7 +3360,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "as-raw-xcb-connection", "bitflags 2.8.0", @@ -3391,7 +3391,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "cosmic-client-toolkit", "dnd", @@ -3410,7 +3410,7 @@ dependencies = [ [[package]] name = "iced_winit" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "cosmic-client-toolkit", "dnd", @@ -4416,7 +4416,7 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libcosmic" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#50d2104485649bdddf1247f63ec3cf2eb81c5817" +source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" dependencies = [ "apply", "ashpd 0.9.2", diff --git a/cosmic-settings/src/app.rs b/cosmic-settings/src/app.rs index ce70ff6a..11f736bb 100644 --- a/cosmic-settings/src/app.rs +++ b/cosmic-settings/src/app.rs @@ -800,6 +800,21 @@ impl cosmic::Application for SettingsApp { .dialog(self.active_page) .map(|e| e.map(Message::PageMessage)) } + + fn system_theme_update( + &mut self, + _keys: &[&'static str], + new_theme: &cosmic::cosmic_theme::Theme, + ) -> Task { + if let Some(page) = self.pages.page_mut::() { + page.update(accessibility::Message::SystemTheme(Box::new( + new_theme.clone(), + ))) + .map(Into::into) + } else { + Task::none() + } + } } impl SettingsApp { diff --git a/cosmic-settings/src/pages/accessibility/mod.rs b/cosmic-settings/src/pages/accessibility/mod.rs index 313a0721..51cee650 100644 --- a/cosmic-settings/src/pages/accessibility/mod.rs +++ b/cosmic-settings/src/pages/accessibility/mod.rs @@ -1,10 +1,13 @@ use cosmic::{ + app, + cosmic_theme::{CosmicPalette, ThemeBuilder}, iced_core::text::Wrapping, - theme, + theme::{self, CosmicTheme}, widget::{button, container, horizontal_space, icon, settings, text}, - Apply, + Apply, Task, }; pub use cosmic_comp_config::ZoomMovement; +use cosmic_config::CosmicConfigEntry; use cosmic_settings_page::{ self as page, section::{self, Section}, @@ -14,6 +17,7 @@ use slotmap::SlotMap; pub mod magnifier; mod wayland; +use tokio::task::spawn_blocking; pub use wayland::{AccessibilityEvent, AccessibilityRequest}; #[derive(Debug, Default)] @@ -23,6 +27,8 @@ pub struct Page { wayland_available: bool, wayland_thread: Option, + theme: Box, + high_contrast: Option, } #[derive(Debug, Clone)] @@ -30,6 +36,8 @@ pub enum Message { Event(wayland::AccessibilityEvent), ProtocolUnavailable, Return, + HighContrast(bool), + SystemTheme(Box), } impl page::Page for Page { @@ -110,6 +118,7 @@ pub fn vision() -> section::Section { on = fl!("accessibility", "on"); off = fl!("accessibility", "off"); unavailable = fl!("accessibility", "unavailable"); + high_contrast = fl!("accessibility", "high-contrast"); }); Section::default() @@ -154,6 +163,13 @@ pub fn vision() -> section::Section { .then_some(crate::pages::Message::Page(magnifier_entity)), ) }) + .add( + cosmic::Element::from( + settings::item::builder(&descriptions[high_contrast]) + .toggler(page.theme.is_high_contrast, Message::HighContrast), + ) + .map(crate::pages::Message::Accessibility), + ) .into() }) } @@ -170,6 +186,65 @@ impl Page { Message::Return => { return cosmic::iced::Task::done(crate::app::Message::Page(self.entity)) } + Message::SystemTheme(theme) => { + self.theme = theme; + } + Message::HighContrast(enabled) => { + if self.theme.is_high_contrast == enabled + || self.high_contrast.is_some_and(|hc| hc == enabled) + { + return Task::none(); + } + self.high_contrast = Some(enabled); + + _ = std::thread::spawn(move || { + let set_hc = |is_dark: bool| { + let builder_config = if is_dark { + ThemeBuilder::dark_config()? + } else { + ThemeBuilder::light_config()? + }; + let mut builder = match ThemeBuilder::get_entry(&builder_config) { + Ok(b) => b, + Err((errs, b)) => { + tracing::warn!("{errs:?}"); + b + } + }; + + builder.palette = if is_dark { + if enabled { + CosmicPalette::HighContrastDark(builder.palette.inner()) + } else { + CosmicPalette::Dark(builder.palette.inner()) + } + } else if enabled { + CosmicPalette::HighContrastLight(builder.palette.inner()) + } else { + CosmicPalette::Light(builder.palette.inner()) + }; + builder.write_entry(&builder_config)?; + + let new_theme = builder.build(); + + let theme_config = if is_dark { + CosmicTheme::dark_config()? + } else { + CosmicTheme::light_config()? + }; + + new_theme.write_entry(&theme_config)?; + + Result::<(), cosmic_config::Error>::Ok(()) + }; + if let Err(err) = set_hc(true) { + tracing::warn!("{err:?}"); + } + if let Err(err) = set_hc(false) { + tracing::warn!("{err:?}"); + } + }); + } } cosmic::iced::Task::none() diff --git a/i18n/en/cosmic_settings.ftl b/i18n/en/cosmic_settings.ftl index f5d39d3c..676f51d4 100644 --- a/i18n/en/cosmic_settings.ftl +++ b/i18n/en/cosmic_settings.ftl @@ -134,6 +134,7 @@ accessibility = Accessibility .on = On .off = Off .unavailable = Unavailable + .high-contrast = High contrast mode magnifier = Magnifier .controls = Or use these shortcuts: { $zoom_in -> [zero] {""}