Skip to content

Commit 43a2bdf

Browse files
committed
feat: high contrast toggle
1 parent ba53a94 commit 43a2bdf

File tree

4 files changed

+110
-19
lines changed

4 files changed

+110
-19
lines changed

Cargo.lock

+17-17
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cosmic-settings/src/app.rs

+15
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,21 @@ impl cosmic::Application for SettingsApp {
800800
.dialog(self.active_page)
801801
.map(|e| e.map(Message::PageMessage))
802802
}
803+
804+
fn system_theme_update(
805+
&mut self,
806+
_keys: &[&'static str],
807+
new_theme: &cosmic::cosmic_theme::Theme,
808+
) -> Task<Self::Message> {
809+
if let Some(page) = self.pages.page_mut::<accessibility::Page>() {
810+
page.update(accessibility::Message::SystemTheme(Box::new(
811+
new_theme.clone(),
812+
)))
813+
.map(Into::into)
814+
} else {
815+
Task::none()
816+
}
817+
}
803818
}
804819

805820
impl SettingsApp {

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

+77-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use cosmic::{
2+
app,
3+
cosmic_theme::{CosmicPalette, ThemeBuilder},
24
iced_core::text::Wrapping,
3-
theme,
5+
theme::{self, CosmicTheme},
46
widget::{button, container, horizontal_space, icon, settings, text},
5-
Apply,
7+
Apply, Task,
68
};
79
pub use cosmic_comp_config::ZoomMovement;
10+
use cosmic_config::CosmicConfigEntry;
811
use cosmic_settings_page::{
912
self as page,
1013
section::{self, Section},
@@ -14,6 +17,7 @@ use slotmap::SlotMap;
1417

1518
pub mod magnifier;
1619
mod wayland;
20+
use tokio::task::spawn_blocking;
1721
pub use wayland::{AccessibilityEvent, AccessibilityRequest};
1822

1923
#[derive(Debug, Default)]
@@ -23,13 +27,17 @@ pub struct Page {
2327

2428
wayland_available: bool,
2529
wayland_thread: Option<wayland::Sender>,
30+
theme: Box<cosmic::cosmic_theme::Theme>,
31+
high_contrast: Option<bool>,
2632
}
2733

2834
#[derive(Debug, Clone)]
2935
pub enum Message {
3036
Event(wayland::AccessibilityEvent),
3137
ProtocolUnavailable,
3238
Return,
39+
HighContrast(bool),
40+
SystemTheme(Box<cosmic::cosmic_theme::Theme>),
3341
}
3442

3543
impl page::Page<crate::pages::Message> for Page {
@@ -110,6 +118,7 @@ pub fn vision() -> section::Section<crate::pages::Message> {
110118
on = fl!("accessibility", "on");
111119
off = fl!("accessibility", "off");
112120
unavailable = fl!("accessibility", "unavailable");
121+
high_contrast = fl!("accessibility", "high-contrast");
113122
});
114123

115124
Section::default()
@@ -154,6 +163,13 @@ pub fn vision() -> section::Section<crate::pages::Message> {
154163
.then_some(crate::pages::Message::Page(magnifier_entity)),
155164
)
156165
})
166+
.add(
167+
cosmic::Element::from(
168+
settings::item::builder(&descriptions[high_contrast])
169+
.toggler(page.theme.is_high_contrast, Message::HighContrast),
170+
)
171+
.map(crate::pages::Message::Accessibility),
172+
)
157173
.into()
158174
})
159175
}
@@ -170,6 +186,65 @@ impl Page {
170186
Message::Return => {
171187
return cosmic::iced::Task::done(crate::app::Message::Page(self.entity))
172188
}
189+
Message::SystemTheme(theme) => {
190+
self.theme = theme;
191+
}
192+
Message::HighContrast(enabled) => {
193+
if self.theme.is_high_contrast == enabled
194+
|| self.high_contrast.is_some_and(|hc| hc == enabled)
195+
{
196+
return Task::none();
197+
}
198+
self.high_contrast = Some(enabled);
199+
200+
_ = std::thread::spawn(move || {
201+
let set_hc = |is_dark: bool| {
202+
let builder_config = if is_dark {
203+
ThemeBuilder::dark_config()?
204+
} else {
205+
ThemeBuilder::light_config()?
206+
};
207+
let mut builder = match ThemeBuilder::get_entry(&builder_config) {
208+
Ok(b) => b,
209+
Err((errs, b)) => {
210+
tracing::warn!("{errs:?}");
211+
b
212+
}
213+
};
214+
215+
builder.palette = if is_dark {
216+
if enabled {
217+
CosmicPalette::HighContrastDark(builder.palette.inner())
218+
} else {
219+
CosmicPalette::Dark(builder.palette.inner())
220+
}
221+
} else if enabled {
222+
CosmicPalette::HighContrastLight(builder.palette.inner())
223+
} else {
224+
CosmicPalette::Light(builder.palette.inner())
225+
};
226+
builder.write_entry(&builder_config)?;
227+
228+
let new_theme = builder.build();
229+
230+
let theme_config = if is_dark {
231+
CosmicTheme::dark_config()?
232+
} else {
233+
CosmicTheme::light_config()?
234+
};
235+
236+
new_theme.write_entry(&theme_config)?;
237+
238+
Result::<(), cosmic_config::Error>::Ok(())
239+
};
240+
if let Err(err) = set_hc(true) {
241+
tracing::warn!("{err:?}");
242+
}
243+
if let Err(err) = set_hc(false) {
244+
tracing::warn!("{err:?}");
245+
}
246+
});
247+
}
173248
}
174249

175250
cosmic::iced::Task::none()

i18n/en/cosmic_settings.ftl

+1
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ accessibility = Accessibility
134134
.on = On
135135
.off = Off
136136
.unavailable = Unavailable
137+
.high-contrast = High contrast mode
137138
magnifier = Magnifier
138139
.controls = Or use these shortcuts: { $zoom_in ->
139140
[zero] {""}

0 commit comments

Comments
 (0)