aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-08-27 10:06:41 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-08-27 10:43:57 +0300
commitab52bb9521faa897727d5eff278fc4310390ff07 (patch)
tree839dc03cab640fd396a628a63898d8fac3c34ec5
parentda5e33775cbb7a4e64189360b4eb00eab6dbb1b3 (diff)
downloadniri-ab52bb9521faa897727d5eff278fc4310390ff07.tar.gz
niri-ab52bb9521faa897727d5eff278fc4310390ff07.tar.bz2
niri-ab52bb9521faa897727d5eff278fc4310390ff07.zip
config: Extract input
-rw-r--r--niri-config/src/input.rs487
-rw-r--r--niri-config/src/lib.rs478
2 files changed, 490 insertions, 475 deletions
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<WarpMouseToFocus>,
+ #[knuffel(child)]
+ pub focus_follows_mouse: Option<FocusFollowsMouse>,
+ #[knuffel(child)]
+ pub workspace_auto_back_and_forth: bool,
+ #[knuffel(child, unwrap(argument, str))]
+ pub mod_key: Option<ModKey>,
+ #[knuffel(child, unwrap(argument, str))]
+ pub mod_key_nested: Option<ModKey>,
+}
+
+#[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<String>,
+ #[knuffel(child, unwrap(argument))]
+ pub file: Option<String>,
+}
+
+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<FloatOrInt<0, 100>>,
+ #[knuffel(property)]
+ pub horizontal: Option<FloatOrInt<-100, 100>>,
+ #[knuffel(property)]
+ pub vertical: Option<FloatOrInt<-100, 100>>,
+}
+
+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<bool>,
+ #[knuffel(child)]
+ pub drag_lock: bool,
+ #[knuffel(child)]
+ pub natural_scroll: bool,
+ #[knuffel(child, unwrap(argument, str))]
+ pub click_method: Option<ClickMethod>,
+ #[knuffel(child, unwrap(argument), default)]
+ pub accel_speed: FloatOrInt<-1, 1>,
+ #[knuffel(child, unwrap(argument, str))]
+ pub accel_profile: Option<AccelProfile>,
+ #[knuffel(child, unwrap(argument, str))]
+ pub scroll_method: Option<ScrollMethod>,
+ #[knuffel(child, unwrap(argument))]
+ pub scroll_button: Option<u32>,
+ #[knuffel(child)]
+ pub scroll_button_lock: bool,
+ #[knuffel(child, unwrap(argument, str))]
+ pub tap_button_map: Option<TapButtonMap>,
+ #[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<ScrollFactor>,
+}
+
+#[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<AccelProfile>,
+ #[knuffel(child, unwrap(argument, str))]
+ pub scroll_method: Option<ScrollMethod>,
+ #[knuffel(child, unwrap(argument))]
+ pub scroll_button: Option<u32>,
+ #[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<ScrollFactor>,
+}
+
+#[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<AccelProfile>,
+ #[knuffel(child, unwrap(argument, str))]
+ pub scroll_method: Option<ScrollMethod>,
+ #[knuffel(child, unwrap(argument))]
+ pub scroll_button: Option<u32>,
+ #[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<AccelProfile>,
+ #[knuffel(child, unwrap(argument, str))]
+ pub scroll_method: Option<ScrollMethod>,
+ #[knuffel(child, unwrap(argument))]
+ pub scroll_button: Option<u32>,
+ #[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<ClickMethod> 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<AccelProfile> 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<ScrollMethod> 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<TapButtonMap> 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<Vec<f32>>,
+ #[knuffel(child, unwrap(argument))]
+ pub map_to_output: Option<String>,
+ #[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<String>,
+}
+
+#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)]
+pub struct FocusFollowsMouse {
+ #[knuffel(property, str)]
+ pub max_scroll_amount: Option<Percent>,
+}
+
+#[derive(knuffel::Decode, Debug, PartialEq, Eq, Clone, Copy)]
+pub struct WarpMouseToFocus {
+ #[knuffel(property, str)]
+ pub mode: Option<WarpMouseToFocusMode>,
+}
+
+#[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<Self, Self::Err> {
+ 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<Self, Self::Err> {
+ 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<Self, Self::Err> {
+ 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<Self, Self::Err> {
+ 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<Self, Self::Err> {
+ 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<Self, Self::Err> {
+ 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<Workspace>,
}
-#[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<WarpMouseToFocus>,
- #[knuffel(child)]
- pub focus_follows_mouse: Option<FocusFollowsMouse>,
- #[knuffel(child)]
- pub workspace_auto_back_and_forth: bool,
- #[knuffel(child, unwrap(argument, str))]
- pub mod_key: Option<ModKey>,
- #[knuffel(child, unwrap(argument, str))]
- pub mod_key_nested: Option<ModKey>,
-}
-
-#[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<String>,
- #[knuffel(child, unwrap(argument))]
- pub file: Option<String>,
-}
-
-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<FloatOrInt<0, 100>>,
- #[knuffel(property)]
- pub horizontal: Option<FloatOrInt<-100, 100>>,
- #[knuffel(property)]
- pub vertical: Option<FloatOrInt<-100, 100>>,
-}
-
-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<bool>,
- #[knuffel(child)]
- pub drag_lock: bool,
- #[knuffel(child)]
- pub natural_scroll: bool,
- #[knuffel(child, unwrap(argument, str))]
- pub click_method: Option<ClickMethod>,
- #[knuffel(child, unwrap(argument), default)]
- pub accel_speed: FloatOrInt<-1, 1>,
- #[knuffel(child, unwrap(argument, str))]
- pub accel_profile: Option<AccelProfile>,
- #[knuffel(child, unwrap(argument, str))]
- pub scroll_method: Option<ScrollMethod>,
- #[knuffel(child, unwrap(argument))]
- pub scroll_button: Option<u32>,
- #[knuffel(child)]
- pub scroll_button_lock: bool,
- #[knuffel(child, unwrap(argument, str))]
- pub tap_button_map: Option<TapButtonMap>,
- #[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<ScrollFactor>,
-}
-
-#[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<AccelProfile>,
- #[knuffel(child, unwrap(argument, str))]
- pub scroll_method: Option<ScrollMethod>,
- #[knuffel(child, unwrap(argument))]
- pub scroll_button: Option<u32>,
- #[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<ScrollFactor>,
-}
-
-#[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<AccelProfile>,
- #[knuffel(child, unwrap(argument, str))]
- pub scroll_method: Option<ScrollMethod>,
- #[knuffel(child, unwrap(argument))]
- pub scroll_button: Option<u32>,
- #[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<AccelProfile>,
- #[knuffel(child, unwrap(argument, str))]
- pub scroll_method: Option<ScrollMethod>,
- #[knuffel(child, unwrap(argument))]
- pub scroll_button: Option<u32>,
- #[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<ClickMethod> 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<AccelProfile> 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<ScrollMethod> 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<TapButtonMap> 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<Vec<f32>>,
- #[knuffel(child, unwrap(argument))]
- pub map_to_output: Option<String>,
- #[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<String>,
-}
-
-#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)]
-pub struct FocusFollowsMouse {
- #[knuffel(property, str)]
- pub max_scroll_amount: Option<Percent>,
-}
-
-#[derive(knuffel::Decode, Debug, PartialEq, Eq, Clone, Copy)]
-pub struct WarpMouseToFocus {
- #[knuffel(property, str)]
- pub mode: Option<WarpMouseToFocusMode>,
-}
-
-#[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<Self, Self::Err> {
- 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<Output>);
@@ -3172,22 +2813,6 @@ where
}
}
-impl FromStr for ModKey {
- type Err = miette::Error;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- 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<Self, Self::Err> {
- 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<Self, Self::Err> {
- 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<Self, Self::Err> {
- 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<Self, Self::Err> {
- 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;
@@ -3543,45 +3110,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(
r##"