diff --git a/Cargo.lock b/Cargo.lock index e2f242b..5893362 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -793,6 +793,7 @@ dependencies = [ "i18n-embed", "i18n-embed-fl", "image", + "itertools 0.11.0", "libcosmic", "log", "notify", @@ -2208,7 +2209,7 @@ dependencies = [ "iced_graphics", "iced_runtime", "iced_style", - "itertools", + "itertools 0.10.5", "raw-window-handle 0.5.2", "smithay-client-toolkit 0.17.0", "smithay-clipboard", @@ -2506,6 +2507,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "jni-sys" version = "0.3.0" diff --git a/app/Cargo.toml b/app/Cargo.toml index d33ed06..5aefca9 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -18,6 +18,7 @@ derive_setters = "0.1.6" dirs = "5.0.1" generator = "0.7.4" i18n-embed-fl = "0.6.7" +itertools = "0.11.0" libcosmic = {workspace = true} once_cell = "1.17.2" regex = "1.8.3" diff --git a/app/src/pages/input/keyboard/mod.rs b/app/src/pages/input/keyboard/mod.rs index 8409ec8..91e9803 100644 --- a/app/src/pages/input/keyboard/mod.rs +++ b/app/src/pages/input/keyboard/mod.rs @@ -158,10 +158,11 @@ impl super::Page { }; let prefix = special_key.prefix(); let current = self - .xkb_options + .xkb + .options .iter() - .find(|x| x.starts_with(prefix)) - .map(String::as_str); + .flat_map(|x| x.split(',')) + .find(|x| x.starts_with(prefix)); // TODO description, layout default diff --git a/app/src/pages/input/mod.rs b/app/src/pages/input/mod.rs index 8c072b3..5b11862 100644 --- a/app/src/pages/input/mod.rs +++ b/app/src/pages/input/mod.rs @@ -1,15 +1,18 @@ use crate::app; use cosmic::{ + cosmic_config::{self, ConfigGet, ConfigSet}, iced::{self, wayland::actions::window::SctkWindowSettings, window}, iced_sctk::commands, iced_widget::core::layout, }; use cosmic_settings_page as page; +use itertools::Itertools; +use tracing::error; pub mod keyboard; mod mouse; -#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +#[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)] pub struct XkbConfig { pub rules: String, pub model: String, @@ -34,13 +37,10 @@ pub enum Message { SpecialCharacterSelect(Option<&'static str>), } -#[derive(derivative::Derivative)] -#[derivative(Default)] pub struct Page { - // cosmic_config::Config + config: cosmic_config::Config, // Mouse - #[derivative(Default(value = "mouse::default_primary_button()"))] primary_button: cosmic::widget::segmented_button::SingleSelectModel, acceleration: bool, natural_scroll: bool, @@ -50,10 +50,44 @@ pub struct Page { // Keyboard expanded_source_popover: Option, - #[derivative(Default(value = "keyboard::default_input_sources()"))] sources: Vec, special_character_dialog: Option, - xkb_options: Vec, + xkb: XkbConfig, +} + +fn get_config( + config: &cosmic_config::Config, + key: &str, +) -> T { + config.get(key).unwrap_or_else(|err| { + error!(?err, "Failed to read config '{}'", key); + T::default() + }) +} + +impl Default for Page { + fn default() -> Self { + let config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap(); + let xkb = get_config(&config, "xkb-config"); + + Self { + config, + + // Mouse + primary_button: mouse::default_primary_button(), + acceleration: false, + natural_scroll: false, + double_click_speed: 0, + scroll_speed: 0, + mouse_speed: 0, + + // Keyboard + expanded_source_popover: None, + sources: keyboard::default_input_sources(), + special_character_dialog: None, + xkb, + } + } } impl Page { @@ -107,14 +141,17 @@ impl Page { } Message::SpecialCharacterSelect(id) => { if let Some(special_key) = self.special_character_dialog { + let options = self.xkb.options.as_deref().unwrap_or(""); let prefix = special_key.prefix(); - if let Some(idx) = self.xkb_options.iter().position(|x| x.starts_with(prefix)) { - self.xkb_options.remove(idx); + let new_options = options + .split(',') + .filter(|x| !x.starts_with(prefix)) + .chain(id.into_iter()) + .join(","); + self.xkb.options = Some(new_options).filter(|x| !x.is_empty()); + if let Err(err) = self.config.set("xkb-config", &self.xkb) { + error!(?err, "Failed to set config 'xkb-config'"); } - if let Some(id) = id { - self.xkb_options.push(id.to_string()); - } - // TODO set in cosmic-config } } Message::OpenKeyboardShortcuts => {}