From ab52bb9521faa897727d5eff278fc4310390ff07 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Wed, 27 Aug 2025 10:06:41 +0300 Subject: config: Extract input --- niri-config/src/input.rs | 487 +++++++++++++++++++++++++++++++++++++++++++++++ niri-config/src/lib.rs | 478 +--------------------------------------------- 2 files changed, 490 insertions(+), 475 deletions(-) create mode 100644 niri-config/src/input.rs diff --git a/niri-config/src/input.rs b/niri-config/src/input.rs new file mode 100644 index 00000000..a5b546df --- /dev/null +++ b/niri-config/src/input.rs @@ -0,0 +1,487 @@ +use std::str::FromStr; + +use miette::miette; +use smithay::input::keyboard::XkbConfig; +use smithay::reexports::input; + +use crate::{FloatOrInt, Modifiers, Percent}; + +#[derive(knuffel::Decode, Debug, Default, PartialEq)] +pub struct Input { + #[knuffel(child, default)] + pub keyboard: Keyboard, + #[knuffel(child, default)] + pub touchpad: Touchpad, + #[knuffel(child, default)] + pub mouse: Mouse, + #[knuffel(child, default)] + pub trackpoint: Trackpoint, + #[knuffel(child, default)] + pub trackball: Trackball, + #[knuffel(child, default)] + pub tablet: Tablet, + #[knuffel(child, default)] + pub touch: Touch, + #[knuffel(child)] + pub disable_power_key_handling: bool, + #[knuffel(child)] + pub warp_mouse_to_focus: Option, + #[knuffel(child)] + pub focus_follows_mouse: Option, + #[knuffel(child)] + pub workspace_auto_back_and_forth: bool, + #[knuffel(child, unwrap(argument, str))] + pub mod_key: Option, + #[knuffel(child, unwrap(argument, str))] + pub mod_key_nested: Option, +} + +#[derive(knuffel::Decode, Debug, PartialEq, Eq)] +pub struct Keyboard { + #[knuffel(child, default)] + pub xkb: Xkb, + // The defaults were chosen to match wlroots and sway. + #[knuffel(child, unwrap(argument), default = Self::default().repeat_delay)] + pub repeat_delay: u16, + #[knuffel(child, unwrap(argument), default = Self::default().repeat_rate)] + pub repeat_rate: u8, + #[knuffel(child, unwrap(argument), default)] + pub track_layout: TrackLayout, + #[knuffel(child)] + pub numlock: bool, +} + +impl Default for Keyboard { + fn default() -> Self { + Self { + xkb: Default::default(), + repeat_delay: 600, + repeat_rate: 25, + track_layout: Default::default(), + numlock: Default::default(), + } + } +} + +#[derive(knuffel::Decode, Debug, Default, PartialEq, Eq, Clone)] +pub struct Xkb { + #[knuffel(child, unwrap(argument), default)] + pub rules: String, + #[knuffel(child, unwrap(argument), default)] + pub model: String, + #[knuffel(child, unwrap(argument), default)] + pub layout: String, + #[knuffel(child, unwrap(argument), default)] + pub variant: String, + #[knuffel(child, unwrap(argument))] + pub options: Option, + #[knuffel(child, unwrap(argument))] + pub file: Option, +} + +impl Xkb { + pub fn to_xkb_config(&self) -> XkbConfig<'_> { + XkbConfig { + rules: &self.rules, + model: &self.model, + layout: &self.layout, + variant: &self.variant, + options: self.options.clone(), + } + } +} + +#[derive(knuffel::DecodeScalar, Debug, Default, PartialEq, Eq)] +pub enum TrackLayout { + /// The layout change is global. + #[default] + Global, + /// The layout change is window local. + Window, +} + +#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq)] +pub struct ScrollFactor { + #[knuffel(argument)] + pub base: Option>, + #[knuffel(property)] + pub horizontal: Option>, + #[knuffel(property)] + pub vertical: Option>, +} + +impl ScrollFactor { + pub fn h_v_factors(&self) -> (f64, f64) { + let base_value = self.base.map(|f| f.0).unwrap_or(1.0); + let h = self.horizontal.map(|f| f.0).unwrap_or(base_value); + let v = self.vertical.map(|f| f.0).unwrap_or(base_value); + (h, v) + } +} + +#[derive(knuffel::Decode, Debug, Default, PartialEq)] +pub struct Touchpad { + #[knuffel(child)] + pub off: bool, + #[knuffel(child)] + pub tap: bool, + #[knuffel(child)] + pub dwt: bool, + #[knuffel(child)] + pub dwtp: bool, + #[knuffel(child, unwrap(argument))] + pub drag: Option, + #[knuffel(child)] + pub drag_lock: bool, + #[knuffel(child)] + pub natural_scroll: bool, + #[knuffel(child, unwrap(argument, str))] + pub click_method: Option, + #[knuffel(child, unwrap(argument), default)] + pub accel_speed: FloatOrInt<-1, 1>, + #[knuffel(child, unwrap(argument, str))] + pub accel_profile: Option, + #[knuffel(child, unwrap(argument, str))] + pub scroll_method: Option, + #[knuffel(child, unwrap(argument))] + pub scroll_button: Option, + #[knuffel(child)] + pub scroll_button_lock: bool, + #[knuffel(child, unwrap(argument, str))] + pub tap_button_map: Option, + #[knuffel(child)] + pub left_handed: bool, + #[knuffel(child)] + pub disabled_on_external_mouse: bool, + #[knuffel(child)] + pub middle_emulation: bool, + #[knuffel(child)] + pub scroll_factor: Option, +} + +#[derive(knuffel::Decode, Debug, Default, PartialEq)] +pub struct Mouse { + #[knuffel(child)] + pub off: bool, + #[knuffel(child)] + pub natural_scroll: bool, + #[knuffel(child, unwrap(argument), default)] + pub accel_speed: FloatOrInt<-1, 1>, + #[knuffel(child, unwrap(argument, str))] + pub accel_profile: Option, + #[knuffel(child, unwrap(argument, str))] + pub scroll_method: Option, + #[knuffel(child, unwrap(argument))] + pub scroll_button: Option, + #[knuffel(child)] + pub scroll_button_lock: bool, + #[knuffel(child)] + pub left_handed: bool, + #[knuffel(child)] + pub middle_emulation: bool, + #[knuffel(child)] + pub scroll_factor: Option, +} + +#[derive(knuffel::Decode, Debug, Default, PartialEq)] +pub struct Trackpoint { + #[knuffel(child)] + pub off: bool, + #[knuffel(child)] + pub natural_scroll: bool, + #[knuffel(child, unwrap(argument), default)] + pub accel_speed: FloatOrInt<-1, 1>, + #[knuffel(child, unwrap(argument, str))] + pub accel_profile: Option, + #[knuffel(child, unwrap(argument, str))] + pub scroll_method: Option, + #[knuffel(child, unwrap(argument))] + pub scroll_button: Option, + #[knuffel(child)] + pub scroll_button_lock: bool, + #[knuffel(child)] + pub left_handed: bool, + #[knuffel(child)] + pub middle_emulation: bool, +} + +#[derive(knuffel::Decode, Debug, Default, PartialEq)] +pub struct Trackball { + #[knuffel(child)] + pub off: bool, + #[knuffel(child)] + pub natural_scroll: bool, + #[knuffel(child, unwrap(argument), default)] + pub accel_speed: FloatOrInt<-1, 1>, + #[knuffel(child, unwrap(argument, str))] + pub accel_profile: Option, + #[knuffel(child, unwrap(argument, str))] + pub scroll_method: Option, + #[knuffel(child, unwrap(argument))] + pub scroll_button: Option, + #[knuffel(child)] + pub scroll_button_lock: bool, + #[knuffel(child)] + pub left_handed: bool, + #[knuffel(child)] + pub middle_emulation: bool, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ClickMethod { + Clickfinger, + ButtonAreas, +} + +impl From for input::ClickMethod { + fn from(value: ClickMethod) -> Self { + match value { + ClickMethod::Clickfinger => Self::Clickfinger, + ClickMethod::ButtonAreas => Self::ButtonAreas, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum AccelProfile { + Adaptive, + Flat, +} + +impl From for input::AccelProfile { + fn from(value: AccelProfile) -> Self { + match value { + AccelProfile::Adaptive => Self::Adaptive, + AccelProfile::Flat => Self::Flat, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ScrollMethod { + NoScroll, + TwoFinger, + Edge, + OnButtonDown, +} + +impl From for input::ScrollMethod { + fn from(value: ScrollMethod) -> Self { + match value { + ScrollMethod::NoScroll => Self::NoScroll, + ScrollMethod::TwoFinger => Self::TwoFinger, + ScrollMethod::Edge => Self::Edge, + ScrollMethod::OnButtonDown => Self::OnButtonDown, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TapButtonMap { + LeftRightMiddle, + LeftMiddleRight, +} + +impl From for input::TapButtonMap { + fn from(value: TapButtonMap) -> Self { + match value { + TapButtonMap::LeftRightMiddle => Self::LeftRightMiddle, + TapButtonMap::LeftMiddleRight => Self::LeftMiddleRight, + } + } +} + +#[derive(knuffel::Decode, Debug, Default, PartialEq)] +pub struct Tablet { + #[knuffel(child)] + pub off: bool, + #[knuffel(child, unwrap(arguments))] + pub calibration_matrix: Option>, + #[knuffel(child, unwrap(argument))] + pub map_to_output: Option, + #[knuffel(child)] + pub left_handed: bool, +} + +#[derive(knuffel::Decode, Debug, Default, PartialEq)] +pub struct Touch { + #[knuffel(child)] + pub off: bool, + #[knuffel(child, unwrap(argument))] + pub map_to_output: Option, +} + +#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] +pub struct FocusFollowsMouse { + #[knuffel(property, str)] + pub max_scroll_amount: Option, +} + +#[derive(knuffel::Decode, Debug, PartialEq, Eq, Clone, Copy)] +pub struct WarpMouseToFocus { + #[knuffel(property, str)] + pub mode: Option, +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum WarpMouseToFocusMode { + CenterXy, + CenterXyAlways, +} + +impl FromStr for WarpMouseToFocusMode { + type Err = miette::Error; + + fn from_str(s: &str) -> Result { + match s { + "center-xy" => Ok(Self::CenterXy), + "center-xy-always" => Ok(Self::CenterXyAlways), + _ => Err(miette!( + r#"invalid mode for warp-mouse-to-focus, can be "center-xy" or "center-xy-always" (or leave unset for separate centering)"# + )), + } + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum ModKey { + Ctrl, + Shift, + Alt, + Super, + IsoLevel3Shift, + IsoLevel5Shift, +} + +impl ModKey { + pub fn to_modifiers(&self) -> Modifiers { + match self { + ModKey::Ctrl => Modifiers::CTRL, + ModKey::Shift => Modifiers::SHIFT, + ModKey::Alt => Modifiers::ALT, + ModKey::Super => Modifiers::SUPER, + ModKey::IsoLevel3Shift => Modifiers::ISO_LEVEL3_SHIFT, + ModKey::IsoLevel5Shift => Modifiers::ISO_LEVEL5_SHIFT, + } + } +} + +impl FromStr for ModKey { + type Err = miette::Error; + + fn from_str(s: &str) -> Result { + match &*s.to_ascii_lowercase() { + "ctrl" | "control" => Ok(Self::Ctrl), + "shift" => Ok(Self::Shift), + "alt" => Ok(Self::Alt), + "super" | "win" => Ok(Self::Super), + "iso_level3_shift" | "mod5" => Ok(Self::IsoLevel3Shift), + "iso_level5_shift" | "mod3" => Ok(Self::IsoLevel5Shift), + _ => Err(miette!("invalid Mod key: {s}")), + } + } +} + +impl FromStr for ClickMethod { + type Err = miette::Error; + + fn from_str(s: &str) -> Result { + match s { + "clickfinger" => Ok(Self::Clickfinger), + "button-areas" => Ok(Self::ButtonAreas), + _ => Err(miette!( + r#"invalid click method, can be "button-areas" or "clickfinger""# + )), + } + } +} + +impl FromStr for AccelProfile { + type Err = miette::Error; + + fn from_str(s: &str) -> Result { + match s { + "adaptive" => Ok(Self::Adaptive), + "flat" => Ok(Self::Flat), + _ => Err(miette!( + r#"invalid accel profile, can be "adaptive" or "flat""# + )), + } + } +} + +impl FromStr for ScrollMethod { + type Err = miette::Error; + + fn from_str(s: &str) -> Result { + match s { + "no-scroll" => Ok(Self::NoScroll), + "two-finger" => Ok(Self::TwoFinger), + "edge" => Ok(Self::Edge), + "on-button-down" => Ok(Self::OnButtonDown), + _ => Err(miette!( + r#"invalid scroll method, can be "no-scroll", "two-finger", "edge", or "on-button-down""# + )), + } + } +} + +impl FromStr for TapButtonMap { + type Err = miette::Error; + + fn from_str(s: &str) -> Result { + match s { + "left-right-middle" => Ok(Self::LeftRightMiddle), + "left-middle-right" => Ok(Self::LeftMiddleRight), + _ => Err(miette!( + r#"invalid tap button map, can be "left-right-middle" or "left-middle-right""# + )), + } + } +} + +#[cfg(test)] +mod tests { + use insta::assert_debug_snapshot; + + use super::*; + + #[test] + fn scroll_factor_h_v_factors() { + let sf = ScrollFactor { + base: Some(FloatOrInt(2.0)), + horizontal: None, + vertical: None, + }; + assert_debug_snapshot!(sf.h_v_factors(), @r#" + ( + 2.0, + 2.0, + ) + "#); + + let sf = ScrollFactor { + base: None, + horizontal: Some(FloatOrInt(3.0)), + vertical: Some(FloatOrInt(-1.0)), + }; + assert_debug_snapshot!(sf.h_v_factors(), @r#" + ( + 3.0, + -1.0, + ) + "#); + + let sf = ScrollFactor { + base: Some(FloatOrInt(2.0)), + horizontal: Some(FloatOrInt(1.0)), + vertical: None, + }; + assert_debug_snapshot!(sf.h_v_factors(), @r" + ( + 1.0, + 2.0, + ) + "); + } +} diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index f5aa3e1a..c33fe372 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -20,13 +20,13 @@ use niri_ipc::{ use smithay::backend::renderer::Color32F; use smithay::input::keyboard::keysyms::KEY_NoSymbol; use smithay::input::keyboard::xkb::{keysym_from_name, KEYSYM_CASE_INSENSITIVE}; -use smithay::input::keyboard::{Keysym, XkbConfig}; -use smithay::reexports::input; +use smithay::input::keyboard::Keysym; pub const DEFAULT_BACKGROUND_COLOR: Color = Color::from_array_unpremul([0.25, 0.25, 0.25, 1.]); pub const DEFAULT_BACKDROP_COLOR: Color = Color::from_array_unpremul([0.15, 0.15, 0.15, 1.]); pub mod animations; +pub mod input; pub mod layer_rule; pub mod utils; pub mod window_rule; @@ -34,6 +34,7 @@ pub mod window_rule; pub use crate::animations::{ Animation, AnimationCurve, AnimationKind, Animations, EasingParams, SpringParams, }; +pub use crate::input::{Input, ModKey, ScrollMethod, TrackLayout, WarpMouseToFocusMode, Xkb}; pub use crate::layer_rule::LayerRule; pub use crate::window_rule::{FloatingPosition, RelativeTo, WindowRule}; @@ -91,91 +92,6 @@ pub struct Config { pub workspaces: Vec, } -#[derive(knuffel::Decode, Debug, Default, PartialEq)] -pub struct Input { - #[knuffel(child, default)] - pub keyboard: Keyboard, - #[knuffel(child, default)] - pub touchpad: Touchpad, - #[knuffel(child, default)] - pub mouse: Mouse, - #[knuffel(child, default)] - pub trackpoint: Trackpoint, - #[knuffel(child, default)] - pub trackball: Trackball, - #[knuffel(child, default)] - pub tablet: Tablet, - #[knuffel(child, default)] - pub touch: Touch, - #[knuffel(child)] - pub disable_power_key_handling: bool, - #[knuffel(child)] - pub warp_mouse_to_focus: Option, - #[knuffel(child)] - pub focus_follows_mouse: Option, - #[knuffel(child)] - pub workspace_auto_back_and_forth: bool, - #[knuffel(child, unwrap(argument, str))] - pub mod_key: Option, - #[knuffel(child, unwrap(argument, str))] - pub mod_key_nested: Option, -} - -#[derive(knuffel::Decode, Debug, PartialEq, Eq)] -pub struct Keyboard { - #[knuffel(child, default)] - pub xkb: Xkb, - // The defaults were chosen to match wlroots and sway. - #[knuffel(child, unwrap(argument), default = Self::default().repeat_delay)] - pub repeat_delay: u16, - #[knuffel(child, unwrap(argument), default = Self::default().repeat_rate)] - pub repeat_rate: u8, - #[knuffel(child, unwrap(argument), default)] - pub track_layout: TrackLayout, - #[knuffel(child)] - pub numlock: bool, -} - -impl Default for Keyboard { - fn default() -> Self { - Self { - xkb: Default::default(), - repeat_delay: 600, - repeat_rate: 25, - track_layout: Default::default(), - numlock: Default::default(), - } - } -} - -#[derive(knuffel::Decode, Debug, Default, PartialEq, Eq, Clone)] -pub struct Xkb { - #[knuffel(child, unwrap(argument), default)] - pub rules: String, - #[knuffel(child, unwrap(argument), default)] - pub model: String, - #[knuffel(child, unwrap(argument), default)] - pub layout: String, - #[knuffel(child, unwrap(argument), default)] - pub variant: String, - #[knuffel(child, unwrap(argument))] - pub options: Option, - #[knuffel(child, unwrap(argument))] - pub file: Option, -} - -impl Xkb { - pub fn to_xkb_config(&self) -> XkbConfig<'_> { - XkbConfig { - rules: &self.rules, - model: &self.model, - layout: &self.layout, - variant: &self.variant, - options: self.options.clone(), - } - } -} - #[derive(knuffel::DecodeScalar, Debug, Default, PartialEq, Eq, Clone, Copy)] pub enum CenterFocusedColumn { /// Focusing a column will not center the column. @@ -188,284 +104,9 @@ pub enum CenterFocusedColumn { OnOverflow, } -#[derive(knuffel::DecodeScalar, Debug, Default, PartialEq, Eq)] -pub enum TrackLayout { - /// The layout change is global. - #[default] - Global, - /// The layout change is window local. - Window, -} - -#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq)] -pub struct ScrollFactor { - #[knuffel(argument)] - pub base: Option>, - #[knuffel(property)] - pub horizontal: Option>, - #[knuffel(property)] - pub vertical: Option>, -} - -impl ScrollFactor { - pub fn h_v_factors(&self) -> (f64, f64) { - let base_value = self.base.map(|f| f.0).unwrap_or(1.0); - let h = self.horizontal.map(|f| f.0).unwrap_or(base_value); - let v = self.vertical.map(|f| f.0).unwrap_or(base_value); - (h, v) - } -} - -#[derive(knuffel::Decode, Debug, Default, PartialEq)] -pub struct Touchpad { - #[knuffel(child)] - pub off: bool, - #[knuffel(child)] - pub tap: bool, - #[knuffel(child)] - pub dwt: bool, - #[knuffel(child)] - pub dwtp: bool, - #[knuffel(child, unwrap(argument))] - pub drag: Option, - #[knuffel(child)] - pub drag_lock: bool, - #[knuffel(child)] - pub natural_scroll: bool, - #[knuffel(child, unwrap(argument, str))] - pub click_method: Option, - #[knuffel(child, unwrap(argument), default)] - pub accel_speed: FloatOrInt<-1, 1>, - #[knuffel(child, unwrap(argument, str))] - pub accel_profile: Option, - #[knuffel(child, unwrap(argument, str))] - pub scroll_method: Option, - #[knuffel(child, unwrap(argument))] - pub scroll_button: Option, - #[knuffel(child)] - pub scroll_button_lock: bool, - #[knuffel(child, unwrap(argument, str))] - pub tap_button_map: Option, - #[knuffel(child)] - pub left_handed: bool, - #[knuffel(child)] - pub disabled_on_external_mouse: bool, - #[knuffel(child)] - pub middle_emulation: bool, - #[knuffel(child)] - pub scroll_factor: Option, -} - -#[derive(knuffel::Decode, Debug, Default, PartialEq)] -pub struct Mouse { - #[knuffel(child)] - pub off: bool, - #[knuffel(child)] - pub natural_scroll: bool, - #[knuffel(child, unwrap(argument), default)] - pub accel_speed: FloatOrInt<-1, 1>, - #[knuffel(child, unwrap(argument, str))] - pub accel_profile: Option, - #[knuffel(child, unwrap(argument, str))] - pub scroll_method: Option, - #[knuffel(child, unwrap(argument))] - pub scroll_button: Option, - #[knuffel(child)] - pub scroll_button_lock: bool, - #[knuffel(child)] - pub left_handed: bool, - #[knuffel(child)] - pub middle_emulation: bool, - #[knuffel(child)] - pub scroll_factor: Option, -} - -#[derive(knuffel::Decode, Debug, Default, PartialEq)] -pub struct Trackpoint { - #[knuffel(child)] - pub off: bool, - #[knuffel(child)] - pub natural_scroll: bool, - #[knuffel(child, unwrap(argument), default)] - pub accel_speed: FloatOrInt<-1, 1>, - #[knuffel(child, unwrap(argument, str))] - pub accel_profile: Option, - #[knuffel(child, unwrap(argument, str))] - pub scroll_method: Option, - #[knuffel(child, unwrap(argument))] - pub scroll_button: Option, - #[knuffel(child)] - pub scroll_button_lock: bool, - #[knuffel(child)] - pub left_handed: bool, - #[knuffel(child)] - pub middle_emulation: bool, -} - -#[derive(knuffel::Decode, Debug, Default, PartialEq)] -pub struct Trackball { - #[knuffel(child)] - pub off: bool, - #[knuffel(child)] - pub natural_scroll: bool, - #[knuffel(child, unwrap(argument), default)] - pub accel_speed: FloatOrInt<-1, 1>, - #[knuffel(child, unwrap(argument, str))] - pub accel_profile: Option, - #[knuffel(child, unwrap(argument, str))] - pub scroll_method: Option, - #[knuffel(child, unwrap(argument))] - pub scroll_button: Option, - #[knuffel(child)] - pub scroll_button_lock: bool, - #[knuffel(child)] - pub left_handed: bool, - #[knuffel(child)] - pub middle_emulation: bool, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ClickMethod { - Clickfinger, - ButtonAreas, -} - -impl From for input::ClickMethod { - fn from(value: ClickMethod) -> Self { - match value { - ClickMethod::Clickfinger => Self::Clickfinger, - ClickMethod::ButtonAreas => Self::ButtonAreas, - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum AccelProfile { - Adaptive, - Flat, -} - -impl From for input::AccelProfile { - fn from(value: AccelProfile) -> Self { - match value { - AccelProfile::Adaptive => Self::Adaptive, - AccelProfile::Flat => Self::Flat, - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ScrollMethod { - NoScroll, - TwoFinger, - Edge, - OnButtonDown, -} - -impl From for input::ScrollMethod { - fn from(value: ScrollMethod) -> Self { - match value { - ScrollMethod::NoScroll => Self::NoScroll, - ScrollMethod::TwoFinger => Self::TwoFinger, - ScrollMethod::Edge => Self::Edge, - ScrollMethod::OnButtonDown => Self::OnButtonDown, - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum TapButtonMap { - LeftRightMiddle, - LeftMiddleRight, -} - -impl From for input::TapButtonMap { - fn from(value: TapButtonMap) -> Self { - match value { - TapButtonMap::LeftRightMiddle => Self::LeftRightMiddle, - TapButtonMap::LeftMiddleRight => Self::LeftMiddleRight, - } - } -} - -#[derive(knuffel::Decode, Debug, Default, PartialEq)] -pub struct Tablet { - #[knuffel(child)] - pub off: bool, - #[knuffel(child, unwrap(arguments))] - pub calibration_matrix: Option>, - #[knuffel(child, unwrap(argument))] - pub map_to_output: Option, - #[knuffel(child)] - pub left_handed: bool, -} - -#[derive(knuffel::Decode, Debug, Default, PartialEq)] -pub struct Touch { - #[knuffel(child)] - pub off: bool, - #[knuffel(child, unwrap(argument))] - pub map_to_output: Option, -} - -#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] -pub struct FocusFollowsMouse { - #[knuffel(property, str)] - pub max_scroll_amount: Option, -} - -#[derive(knuffel::Decode, Debug, PartialEq, Eq, Clone, Copy)] -pub struct WarpMouseToFocus { - #[knuffel(property, str)] - pub mode: Option, -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum WarpMouseToFocusMode { - CenterXy, - CenterXyAlways, -} - -impl FromStr for WarpMouseToFocusMode { - type Err = miette::Error; - - fn from_str(s: &str) -> Result { - match s { - "center-xy" => Ok(Self::CenterXy), - "center-xy-always" => Ok(Self::CenterXyAlways), - _ => Err(miette!( - r#"invalid mode for warp-mouse-to-focus, can be "center-xy" or "center-xy-always" (or leave unset for separate centering)"# - )), - } - } -} - #[derive(Debug, Clone, Copy, PartialEq)] pub struct Percent(pub f64); -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum ModKey { - Ctrl, - Shift, - Alt, - Super, - IsoLevel3Shift, - IsoLevel5Shift, -} - -impl ModKey { - pub fn to_modifiers(&self) -> Modifiers { - match self { - ModKey::Ctrl => Modifiers::CTRL, - ModKey::Shift => Modifiers::SHIFT, - ModKey::Alt => Modifiers::ALT, - ModKey::Super => Modifiers::SUPER, - ModKey::IsoLevel3Shift => Modifiers::ISO_LEVEL3_SHIFT, - ModKey::IsoLevel5Shift => Modifiers::ISO_LEVEL5_SHIFT, - } - } -} - #[derive(Debug, Default, Clone, PartialEq)] pub struct Outputs(pub Vec); @@ -3172,22 +2813,6 @@ where } } -impl FromStr for ModKey { - type Err = miette::Error; - - fn from_str(s: &str) -> Result { - match &*s.to_ascii_lowercase() { - "ctrl" | "control" => Ok(Self::Ctrl), - "shift" => Ok(Self::Shift), - "alt" => Ok(Self::Alt), - "super" | "win" => Ok(Self::Super), - "iso_level3_shift" | "mod5" => Ok(Self::IsoLevel3Shift), - "iso_level5_shift" | "mod3" => Ok(Self::IsoLevel5Shift), - _ => Err(miette!("invalid Mod key: {s}")), - } - } -} - impl FromStr for Key { type Err = miette::Error; @@ -3260,64 +2885,6 @@ impl FromStr for Key { } } -impl FromStr for ClickMethod { - type Err = miette::Error; - - fn from_str(s: &str) -> Result { - match s { - "clickfinger" => Ok(Self::Clickfinger), - "button-areas" => Ok(Self::ButtonAreas), - _ => Err(miette!( - r#"invalid click method, can be "button-areas" or "clickfinger""# - )), - } - } -} - -impl FromStr for AccelProfile { - type Err = miette::Error; - - fn from_str(s: &str) -> Result { - match s { - "adaptive" => Ok(Self::Adaptive), - "flat" => Ok(Self::Flat), - _ => Err(miette!( - r#"invalid accel profile, can be "adaptive" or "flat""# - )), - } - } -} - -impl FromStr for ScrollMethod { - type Err = miette::Error; - - fn from_str(s: &str) -> Result { - match s { - "no-scroll" => Ok(Self::NoScroll), - "two-finger" => Ok(Self::TwoFinger), - "edge" => Ok(Self::Edge), - "on-button-down" => Ok(Self::OnButtonDown), - _ => Err(miette!( - r#"invalid scroll method, can be "no-scroll", "two-finger", "edge", or "on-button-down""# - )), - } - } -} - -impl FromStr for TapButtonMap { - type Err = miette::Error; - - fn from_str(s: &str) -> Result { - match s { - "left-right-middle" => Ok(Self::LeftRightMiddle), - "left-middle-right" => Ok(Self::LeftMiddleRight), - _ => Err(miette!( - r#"invalid tap button map, can be "left-right-middle" or "left-middle-right""# - )), - } - } -} - impl FromStr for Percent { type Err = miette::Error; @@ -3542,45 +3109,6 @@ mod tests { "#); } - #[test] - fn scroll_factor_h_v_factors() { - let sf = ScrollFactor { - base: Some(FloatOrInt(2.0)), - horizontal: None, - vertical: None, - }; - assert_debug_snapshot!(sf.h_v_factors(), @r#" - ( - 2.0, - 2.0, - ) - "#); - - let sf = ScrollFactor { - base: None, - horizontal: Some(FloatOrInt(3.0)), - vertical: Some(FloatOrInt(-1.0)), - }; - assert_debug_snapshot!(sf.h_v_factors(), @r#" - ( - 3.0, - -1.0, - ) - "#); - - let sf = ScrollFactor { - base: Some(FloatOrInt(2.0)), - horizontal: Some(FloatOrInt(1.0)), - vertical: None, - }; - assert_debug_snapshot!(sf.h_v_factors(), @r" - ( - 1.0, - 2.0, - ) - "); - } - #[test] fn parse() { let parsed = do_parse( -- cgit