config: Read/store zoom state

This commit is contained in:
Victoria Brekenfeld 2025-02-04 16:49:29 +01:00 committed by Victoria Brekenfeld
parent 7267c44116
commit 58f96e6f4a
2 changed files with 106 additions and 9 deletions

View file

@ -68,6 +68,7 @@ pub struct Config {
pub struct DynamicConfig {
outputs: (Option<PathBuf>, OutputsConfig),
numlock: (Option<PathBuf>, NumlockStateConfig),
accessibility_zoom: (Option<PathBuf>, ZoomState),
}
#[derive(Debug, Deserialize, Serialize)]
@ -176,6 +177,11 @@ impl OutputConfig {
}
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
pub struct ZoomState {
pub last_level: f64,
}
impl Config {
pub fn load(loop_handle: &LoopHandle<'_, State>) -> Config {
let config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap();
@ -314,7 +320,7 @@ impl Config {
};
Config {
dynamic_conf: Self::load_dynamic(xdg.as_ref()),
dynamic_conf: Self::load_dynamic(xdg.as_ref(), &cosmic_comp_config),
cosmic_conf: cosmic_comp_config,
cosmic_helper: config,
settings_context,
@ -324,7 +330,10 @@ impl Config {
}
}
fn load_dynamic(xdg: Option<&xdg::BaseDirectories>) -> DynamicConfig {
fn load_dynamic(
xdg: Option<&xdg::BaseDirectories>,
cosmic: &CosmicCompConfig,
) -> DynamicConfig {
let output_path =
xdg.and_then(|base| base.place_state_file("cosmic-comp/outputs.ron").ok());
let outputs = Self::load_outputs(&output_path);
@ -332,9 +341,14 @@ impl Config {
xdg.and_then(|base| base.place_state_file("cosmic-comp/numlock.ron").ok());
let numlock = Self::load_numlock(&numlock_path);
let zoom_path =
xdg.and_then(|base| base.place_state_file("cosmic-comp/a11y_zoom.ron").ok());
let zoom = Self::load_zoom_state(&zoom_path, cosmic);
DynamicConfig {
outputs: (output_path, outputs),
numlock: (numlock_path, numlock),
accessibility_zoom: (zoom_path, zoom),
}
}
@ -400,6 +414,35 @@ impl Config {
.unwrap_or_default()
}
fn load_zoom_state(path: &Option<PathBuf>, cosmic: &CosmicCompConfig) -> ZoomState {
if let Some(path) = path.as_ref() {
if path.exists() {
match ron::de::from_reader::<_, ZoomState>(
OpenOptions::new().read(true).open(path).unwrap(),
) {
Ok(mut config) => {
if config.last_level <= 1.0 {
warn!("Invalid level, resetting");
config.last_level =
1.0 + cosmic.accessibility_zoom.increment as f64 / 100.0;
}
return config;
}
Err(err) => {
warn!(?err, "Failed to read zoom_state, resetting..");
if let Err(err) = std::fs::remove_file(path) {
error!(?err, "Failed to remove zoom_state.");
}
}
};
}
}
ZoomState {
last_level: 1.0 + cosmic.accessibility_zoom.increment as f64 / 100.0,
}
}
pub fn shortcut_for_action(&self, action: &shortcuts::Action) -> Option<String> {
self.shortcuts.shortcut_for_action(action)
}
@ -674,6 +717,17 @@ impl DynamicConfig {
pub fn numlock_mut(&mut self) -> PersistenceGuard<'_, NumlockStateConfig> {
PersistenceGuard(self.numlock.0.clone(), &mut self.numlock.1)
}
pub fn zoom_state(&self) -> &ZoomState {
&self.accessibility_zoom.1
}
pub fn zoom_state_mut(&mut self) -> PersistenceGuard<'_, ZoomState> {
PersistenceGuard(
self.accessibility_zoom.0.clone(),
&mut self.accessibility_zoom.1,
)
}
}
fn get_config<T: Default + serde::de::DeserializeOwned>(
@ -855,6 +909,30 @@ fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut
"accessibility_zoom" => {
let new = get_config::<ZoomConfig>(&config, "accessibility_zoom");
if new != state.common.config.cosmic_conf.accessibility_zoom {
if new.start_on_login
&& !state
.common
.config
.cosmic_conf
.accessibility_zoom
.start_on_login
{
let level = state
.common
.shell
.read()
.unwrap()
.zoom_level(None)
.map_or(1., |(_, _, level)| level);
state.common.config.dynamic_conf.zoom_state_mut().last_level = if level
!= 1.
{
level
} else {
1. + state.common.config.cosmic_conf.accessibility_zoom.increment as f64
/ 100.
};
}
state.common.config.cosmic_conf.accessibility_zoom = new;
}
}

View file

@ -1032,20 +1032,39 @@ impl State {
.zoom_level(None)
.map(|(s, _, l)| (s, l))
.unwrap_or_else(|| (seat.clone(), 1.0));
if &zoom_seat == seat {
if current_level == 1. && matches!(x, Action::ZoomOut) {
return;
}
let new_level = if current_level == 1. && matches!(x, Action::ZoomIn) {
self.common.config.dynamic_conf.zoom_state().last_level
} else {
let increment =
self.common.config.cosmic_conf.accessibility_zoom.increment as f64 / 100.0;
match x {
Action::ZoomIn => current_level + increment,
Action::ZoomOut => (current_level - increment).max(1.0),
_ => unreachable!(),
}
};
if &zoom_seat == seat {
shell.trigger_zoom(
seat,
match x {
Action::ZoomIn => current_level + increment,
Action::ZoomOut => (current_level - increment).max(1.0),
_ => unreachable!(),
},
new_level,
self.common.config.cosmic_conf.accessibility_zoom.view_moves,
);
// TODO: persist state, if enable_on_startup
if new_level > 1.
&& self
.common
.config
.cosmic_conf
.accessibility_zoom
.start_on_login
{
self.common.config.dynamic_conf.zoom_state_mut().last_level = new_level;
}
}
}