From 38898bfda30925e6d7025b26a098f8d55783f13a Mon Sep 17 00:00:00 2001 From: Ryan Brue Date: Sun, 31 Mar 2024 18:57:30 -0500 Subject: [PATCH] feat: touchpad gesture configuration --- cosmic-comp-config/src/input.rs | 37 +++++++++++ cosmic-comp-config/src/lib.rs | 2 + src/config/mod.rs | 7 +- src/input/gestures/mod.rs | 9 +-- src/input/mod.rs | 109 +++++++++++++++++++++++--------- 5 files changed, 125 insertions(+), 39 deletions(-) diff --git a/cosmic-comp-config/src/input.rs b/cosmic-comp-config/src/input.rs index 5ac4889eb..93d72ac50 100644 --- a/cosmic-comp-config/src/input.rs +++ b/cosmic-comp-config/src/input.rs @@ -46,6 +46,43 @@ pub struct ScrollConfig { pub scroll_button: Option, pub scroll_factor: Option, } +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +pub struct TouchpadGestureConfig { + pub three_finger: Option, + pub four_finger: Option, + pub five_finger: Option, +} +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum GestureConfig { + WorkspaceDependent(RelativeGestureConfig), + Directional(AbsoluteGestureConfig), +} +#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)] +pub struct RelativeGestureConfig { + pub action_forward: Option, + pub action_backward: Option, + pub action_side_1: Option, + pub action_side_2: Option, +} +#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)] +pub struct AbsoluteGestureConfig { + pub action_up: Option, + pub action_down: Option, + pub action_left: Option, + pub action_right: Option, +} +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum GestureCommand { + WorkspaceForward, + WorkspaceBackward, + WorkspaceOverviewEnable, + WorkspaceOverviewDisable, + WindowUp, + WindowDown, + WindowLeft, + WindowRight, + Custom(String), +} #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum DeviceState { diff --git a/cosmic-comp-config/src/lib.rs b/cosmic-comp-config/src/lib.rs index 32dbd3f41..9cd832a5b 100644 --- a/cosmic-comp-config/src/lib.rs +++ b/cosmic-comp-config/src/lib.rs @@ -13,6 +13,7 @@ pub struct CosmicCompConfig { pub workspaces: workspace::WorkspaceConfig, pub input_default: input::InputConfig, pub input_touchpad: input::InputConfig, + pub input_touchpad_gestures: input::TouchpadGestureConfig, pub input_devices: HashMap, pub xkb_config: XkbConfig, /// Autotiling enabled @@ -31,6 +32,7 @@ impl Default for CosmicCompConfig { workspaces: Default::default(), input_default: Default::default(), input_touchpad: Default::default(), + input_touchpad_gestures: Default::default(), input_devices: Default::default(), xkb_config: Default::default(), autotile: Default::default(), diff --git a/src/config/mod.rs b/src/config/mod.rs index 3637f5c4f..b1ac2fa60 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -32,7 +32,7 @@ pub use key_bindings::{Action, KeyModifier, KeyModifiers, KeyPattern}; mod types; pub use self::types::*; use cosmic_comp_config::{ - input::InputConfig, + input::{InputConfig, TouchpadGestureConfig}, workspace::{WorkspaceConfig, WorkspaceLayout}, CosmicCompConfig, TileBehavior, XkbConfig, }; @@ -567,6 +567,11 @@ fn config_changed(config: cosmic_config::Config, keys: Vec, state: &mut state.common.config.cosmic_conf.input_touchpad = value; update_input(state); } + "input_touchpad_gestures" => { + let value = get_config::(&config, "input_touchpad_gestures"); + state.common.config.cosmic_conf.input_touchpad_gestures = value; + update_input(state); + } "input_devices" => { let value = get_config::>(&config, "input_devices"); state.common.config.cosmic_conf.input_devices = value; diff --git a/src/input/gestures/mod.rs b/src/input/gestures/mod.rs index 2998615a9..70dceca49 100644 --- a/src/input/gestures/mod.rs +++ b/src/input/gestures/mod.rs @@ -1,3 +1,4 @@ +use cosmic_comp_config::input::GestureCommand; use smithay::utils::{Logical, Point}; use std::{collections::VecDeque, time::Duration}; use tracing::trace; @@ -13,17 +14,11 @@ pub struct SwipeEvent { timestamp: Duration, } -#[derive(Debug, Clone, Copy)] -pub enum SwipeAction { - NextWorkspace, - PrevWorkspace, -} - #[derive(Debug, Clone)] pub struct GestureState { pub fingers: u32, pub direction: Option, - pub action: Option, + pub action: Option, pub delta: f64, // Delta tracking inspired by Niri (GPL-3.0) https://github.com/YaLTeR/niri/tree/v0.1.3 pub history: VecDeque, diff --git a/src/input/mod.rs b/src/input/mod.rs index 9dd124c1f..2979d6b55 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -2,7 +2,7 @@ use crate::{ config::{Action, Config, KeyModifiers, KeyPattern}, - input::gestures::{GestureState, SwipeAction}, + input::gestures::GestureState, shell::{ focus::{ target::{KeyboardFocusTarget, PointerFocusTarget}, @@ -26,7 +26,11 @@ use crate::{ }, }; use calloop::{timer::Timer, RegistrationToken}; -use cosmic_comp_config::{workspace::WorkspaceLayout, TileBehavior}; +use cosmic_comp_config::{ + input::{GestureCommand, GestureConfig}, + workspace::WorkspaceLayout, + TileBehavior, +}; use cosmic_config::ConfigSet; use smithay::{ backend::input::{ @@ -1091,7 +1095,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { - let mut activate_action: Option = None; + let mut activate_action: Option = None; if let Some(ref mut gesture_state) = self.common.gesture_state { let first_update = gesture_state.update( event.delta(), @@ -1099,39 +1103,81 @@ impl State { ); // Decide on action if first update if first_update { - activate_action = match gesture_state.fingers { - 3 => None, // TODO: 3 finger gestures - 4 => { - if self.common.config.cosmic_conf.workspaces.workspace_layout - == WorkspaceLayout::Horizontal - { - match gesture_state.direction { - Some(Direction::Left) => { - Some(SwipeAction::NextWorkspace) - } - Some(Direction::Right) => { - Some(SwipeAction::PrevWorkspace) - } - _ => None, // TODO: Other actions + let target_config = match gesture_state.fingers { + 3 => self + .common + .config + .cosmic_conf + .input_touchpad_gestures + .three_finger + .clone(), + 4 => self + .common + .config + .cosmic_conf + .input_touchpad_gestures + .four_finger + .clone(), + 5 => self + .common + .config + .cosmic_conf + .input_touchpad_gestures + .five_finger + .clone(), + _ => None, + }; + + activate_action = match target_config { + Some(GestureConfig::WorkspaceDependent(config)) => { + match ( + self.common.config.cosmic_conf.workspaces.workspace_layout, + gesture_state.direction, + ) { + (WorkspaceLayout::Vertical, Some(Direction::Down)) => { + config.action_forward.clone() } - } else { - match gesture_state.direction { - Some(Direction::Up) => Some(SwipeAction::NextWorkspace), - Some(Direction::Down) => { - Some(SwipeAction::PrevWorkspace) - } - _ => None, // TODO: Other actions + (WorkspaceLayout::Vertical, Some(Direction::Up)) => { + config.action_backward.clone() } + (WorkspaceLayout::Vertical, Some(Direction::Right)) => { + config.action_side_1.clone() + } + (WorkspaceLayout::Vertical, Some(Direction::Left)) => { + config.action_side_2.clone() + } + (WorkspaceLayout::Horizontal, Some(Direction::Down)) => { + config.action_side_1.clone() + } + (WorkspaceLayout::Horizontal, Some(Direction::Up)) => { + config.action_side_2.clone() + } + (WorkspaceLayout::Horizontal, Some(Direction::Right)) => { + config.action_forward.clone() + } + (WorkspaceLayout::Horizontal, Some(Direction::Left)) => { + config.action_backward.clone() + } + _ => None, } } - _ => None, + Some(GestureConfig::Directional(config)) => { + match gesture_state.direction { + Some(Direction::Up) => config.action_up.clone(), + Some(Direction::Down) => config.action_down.clone(), + Some(Direction::Right) => config.action_right.clone(), + Some(Direction::Left) => config.action_left.clone(), + None => None, + } + } + None => None, }; - - gesture_state.action = activate_action; + gesture_state.action = activate_action.clone(); } match gesture_state.action { - Some(SwipeAction::NextWorkspace) | Some(SwipeAction::PrevWorkspace) => { + Some(GestureCommand::WorkspaceForward) + | Some(GestureCommand::WorkspaceBackward) => { self.common.shell.write().unwrap().update_workspace_delta( &seat.active_output(), gesture_state.delta, @@ -1150,7 +1196,7 @@ impl State { ); } match activate_action { - Some(SwipeAction::NextWorkspace) => { + Some(GestureCommand::WorkspaceForward) => { let _ = to_next_workspace( &mut *self.common.shell.write().unwrap(), &seat, @@ -1158,7 +1204,7 @@ impl State { &mut self.common.workspace_state.update(), ); } - Some(SwipeAction::PrevWorkspace) => { + Some(GestureCommand::WorkspaceBackward) => { let _ = to_previous_workspace( &mut *self.common.shell.write().unwrap(), &seat, @@ -1182,7 +1228,8 @@ impl State { if let Some(seat) = maybe_seat { if let Some(ref gesture_state) = self.common.gesture_state { match gesture_state.action { - Some(SwipeAction::NextWorkspace) | Some(SwipeAction::PrevWorkspace) => { + Some(GestureCommand::WorkspaceForward) + | Some(GestureCommand::WorkspaceBackward) => { let velocity = gesture_state.velocity(); let norm_velocity = if self.common.config.cosmic_conf.workspaces.workspace_layout