mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
config: Extract input
This commit is contained in:
@@ -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,
|
||||||
|
)
|
||||||
|
");
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-475
@@ -20,13 +20,13 @@ use niri_ipc::{
|
|||||||
use smithay::backend::renderer::Color32F;
|
use smithay::backend::renderer::Color32F;
|
||||||
use smithay::input::keyboard::keysyms::KEY_NoSymbol;
|
use smithay::input::keyboard::keysyms::KEY_NoSymbol;
|
||||||
use smithay::input::keyboard::xkb::{keysym_from_name, KEYSYM_CASE_INSENSITIVE};
|
use smithay::input::keyboard::xkb::{keysym_from_name, KEYSYM_CASE_INSENSITIVE};
|
||||||
use smithay::input::keyboard::{Keysym, XkbConfig};
|
use smithay::input::keyboard::Keysym;
|
||||||
use smithay::reexports::input;
|
|
||||||
|
|
||||||
pub const DEFAULT_BACKGROUND_COLOR: Color = Color::from_array_unpremul([0.25, 0.25, 0.25, 1.]);
|
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 const DEFAULT_BACKDROP_COLOR: Color = Color::from_array_unpremul([0.15, 0.15, 0.15, 1.]);
|
||||||
|
|
||||||
pub mod animations;
|
pub mod animations;
|
||||||
|
pub mod input;
|
||||||
pub mod layer_rule;
|
pub mod layer_rule;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
pub mod window_rule;
|
pub mod window_rule;
|
||||||
@@ -34,6 +34,7 @@ pub mod window_rule;
|
|||||||
pub use crate::animations::{
|
pub use crate::animations::{
|
||||||
Animation, AnimationCurve, AnimationKind, Animations, EasingParams, SpringParams,
|
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::layer_rule::LayerRule;
|
||||||
pub use crate::window_rule::{FloatingPosition, RelativeTo, WindowRule};
|
pub use crate::window_rule::{FloatingPosition, RelativeTo, WindowRule};
|
||||||
|
|
||||||
@@ -91,91 +92,6 @@ pub struct Config {
|
|||||||
pub workspaces: Vec<Workspace>,
|
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)]
|
#[derive(knuffel::DecodeScalar, Debug, Default, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum CenterFocusedColumn {
|
pub enum CenterFocusedColumn {
|
||||||
/// Focusing a column will not center the column.
|
/// Focusing a column will not center the column.
|
||||||
@@ -188,284 +104,9 @@ pub enum CenterFocusedColumn {
|
|||||||
OnOverflow,
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct Percent(pub f64);
|
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)]
|
#[derive(Debug, Default, Clone, PartialEq)]
|
||||||
pub struct Outputs(pub Vec<Output>);
|
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 {
|
impl FromStr for Key {
|
||||||
type Err = miette::Error;
|
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 {
|
impl FromStr for Percent {
|
||||||
type Err = miette::Error;
|
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]
|
#[test]
|
||||||
fn parse() {
|
fn parse() {
|
||||||
let parsed = do_parse(
|
let parsed = do_parse(
|
||||||
|
|||||||
Reference in New Issue
Block a user