config: Add screen-filter configuration and persistent state
This commit is contained in:
parent
c10d400d70
commit
ea09334ff7
2 changed files with 85 additions and 1 deletions
|
|
@ -69,6 +69,7 @@ pub struct DynamicConfig {
|
|||
outputs: (Option<PathBuf>, OutputsConfig),
|
||||
numlock: (Option<PathBuf>, NumlockStateConfig),
|
||||
pub accessibility_zoom: (Option<PathBuf>, ZoomState),
|
||||
accessibility_filter: (Option<PathBuf>, ScreenFilter),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
|
|
@ -182,6 +183,29 @@ pub struct ZoomState {
|
|||
pub last_level: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq)]
|
||||
pub struct ScreenFilter {
|
||||
pub inverted: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub color_filter: Option<ColorFilter>,
|
||||
}
|
||||
|
||||
impl ScreenFilter {
|
||||
pub fn is_noop(&self) -> bool {
|
||||
self.inverted == false && self.color_filter.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[repr(u8)]
|
||||
// these values need to match with offscreen.frag
|
||||
pub enum ColorFilter {
|
||||
Greyscale = 1,
|
||||
Protanopia = 2,
|
||||
Deuteranopia = 3,
|
||||
Tritanopia = 4,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn load(loop_handle: &LoopHandle<'_, State>) -> Config {
|
||||
let config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap();
|
||||
|
|
@ -311,6 +335,18 @@ impl Config {
|
|||
),
|
||||
};
|
||||
|
||||
let _ = loop_handle.insert_idle(|state| {
|
||||
let filter_conf = state.common.config.dynamic_conf.screen_filter();
|
||||
state
|
||||
.common
|
||||
.a11y_state
|
||||
.set_screen_inverted(filter_conf.inverted);
|
||||
state
|
||||
.common
|
||||
.a11y_state
|
||||
.set_screen_filter(filter_conf.color_filter);
|
||||
});
|
||||
|
||||
Config {
|
||||
dynamic_conf: Self::load_dynamic(xdg.as_ref(), &cosmic_comp_config),
|
||||
cosmic_conf: cosmic_comp_config,
|
||||
|
|
@ -337,10 +373,17 @@ impl Config {
|
|||
xdg.and_then(|base| base.place_state_file("cosmic-comp/a11y_zoom.ron").ok());
|
||||
let zoom = Self::load_zoom_state(&zoom_path, cosmic);
|
||||
|
||||
let filter_path = xdg.and_then(|base| {
|
||||
base.place_state_file("cosmic-comp/a11y_screen_filter.ron")
|
||||
.ok()
|
||||
});
|
||||
let filter = Self::load_filter_state(&filter_path);
|
||||
|
||||
DynamicConfig {
|
||||
outputs: (output_path, outputs),
|
||||
numlock: (numlock_path, numlock),
|
||||
accessibility_zoom: (zoom_path, zoom),
|
||||
accessibility_filter: (filter_path, filter),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -435,6 +478,29 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
fn load_filter_state(path: &Option<PathBuf>) -> ScreenFilter {
|
||||
if let Some(path) = path.as_ref() {
|
||||
if path.exists() {
|
||||
match ron::de::from_reader::<_, ScreenFilter>(
|
||||
OpenOptions::new().read(true).open(path).unwrap(),
|
||||
) {
|
||||
Ok(config) => return config,
|
||||
Err(err) => {
|
||||
warn!(?err, "Failed to read screen_filter state, resetting..");
|
||||
if let Err(err) = std::fs::remove_file(path) {
|
||||
error!(?err, "Failed to remove screen_filter state.");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ScreenFilter {
|
||||
inverted: false,
|
||||
color_filter: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shortcut_for_action(&self, action: &shortcuts::Action) -> Option<String> {
|
||||
self.shortcuts.shortcut_for_action(action)
|
||||
}
|
||||
|
|
@ -486,6 +552,7 @@ impl Config {
|
|||
if let Err(err) = backend.apply_config_for_outputs(
|
||||
false,
|
||||
loop_handle,
|
||||
self.dynamic_conf.screen_filter(),
|
||||
shell.clone(),
|
||||
workspace_state,
|
||||
xdg_activation_state,
|
||||
|
|
@ -511,6 +578,7 @@ impl Config {
|
|||
if let Err(err) = backend.apply_config_for_outputs(
|
||||
false,
|
||||
loop_handle,
|
||||
self.dynamic_conf.screen_filter(),
|
||||
shell.clone(),
|
||||
workspace_state,
|
||||
xdg_activation_state,
|
||||
|
|
@ -553,6 +621,7 @@ impl Config {
|
|||
if let Err(err) = backend.apply_config_for_outputs(
|
||||
false,
|
||||
loop_handle,
|
||||
self.dynamic_conf.screen_filter(),
|
||||
shell.clone(),
|
||||
workspace_state,
|
||||
xdg_activation_state,
|
||||
|
|
@ -720,6 +789,17 @@ impl DynamicConfig {
|
|||
&mut self.accessibility_zoom.1,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn screen_filter(&self) -> &ScreenFilter {
|
||||
&self.accessibility_filter.1
|
||||
}
|
||||
|
||||
pub fn screen_filter_mut(&mut self) -> PersistenceGuard<'_, ScreenFilter> {
|
||||
PersistenceGuard(
|
||||
self.accessibility_filter.0.clone(),
|
||||
&mut self.accessibility_filter.1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_config<T: Default + serde::de::DeserializeOwned>(
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
winit::WinitState,
|
||||
x11::X11State,
|
||||
},
|
||||
config::{Config, OutputConfig, OutputState},
|
||||
config::{Config, OutputConfig, OutputState, ScreenFilter},
|
||||
input::{gestures::GestureState, PointerFocusState},
|
||||
shell::{grabs::SeatMoveGrabState, CosmicSurface, SeatExt, Shell},
|
||||
utils::prelude::OutputExt,
|
||||
|
|
@ -451,6 +451,10 @@ impl BackendData {
|
|||
_ => unreachable!("No backend set when getting offscreen renderer"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_screen_filter(&mut self, screen_filter: &ScreenFilter) -> anyhow::Result<()> {
|
||||
let _ = screen_filter; // TODO
|
||||
}
|
||||
}
|
||||
|
||||
pub struct KmsNodes {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue