mirror of
https://github.com/YaLTeR/niri.git
synced 2025-10-06 00:23:14 +02:00
config: Extract input
This commit is contained in:
487
niri-config/src/input.rs
Normal file
487
niri-config/src/input.rs
Normal file
@@ -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,
|
||||
)
|
||||
");
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
Reference in New Issue
Block a user