From 316d95d490a9a15e84e73540d09832175a1fe16c Mon Sep 17 00:00:00 2001 From: Ryan Brue Date: Sun, 22 Dec 2024 23:38:54 -0600 Subject: [PATCH] gestures: Implement configurable gestures using new cosmic-settings-daemon config This commit adds very very simple configurable touchpad gestures, starting with next and previous workspace. We need to add support for more actions at some point, but this is a good start. Signed-off-by: Ryan Brue --- Cargo.lock | 6 ++-- Cargo.toml | 3 +- src/config/gestures.rs | 24 +++++++++++++++ src/config/mod.rs | 22 ++++++++++++-- src/input/actions.rs | 8 ++--- src/input/gestures/mod.rs | 10 ++----- src/input/mod.rs | 63 +++++++-------------------------------- 7 files changed, 65 insertions(+), 71 deletions(-) create mode 100644 src/config/gestures.rs diff --git a/Cargo.lock b/Cargo.lock index 7fcf9c27..67ab55e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "ab_glyph" @@ -903,7 +903,7 @@ dependencies = [ [[package]] name = "cosmic-settings-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-settings-daemon#747e482ca197497ee3bc5f6e9dcd23c73e592e47" +source = "git+https://github.com/ryanabx-contrib/cosmic-settings-daemon?branch=gestures#23542a85f799b49b4a6dec39bdebdd8e01e37eaa" dependencies = [ "cosmic-config", "serde", @@ -2472,7 +2472,7 @@ dependencies = [ [[package]] name = "id_tree" version = "1.8.0" -source = "git+https://github.com/Drakulix/id-tree.git?branch=feature/copy_clone#632a57d6d49160e18d7300fa7edae52281ec5482" +source = "git+https://github.com/Drakulix/id-tree.git?branch=feature%2Fcopy_clone#632a57d6d49160e18d7300fa7edae52281ec5482" dependencies = [ "snowflake", ] diff --git a/Cargo.toml b/Cargo.toml index 6b8e669d..741bfcbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,8 @@ calloop = {version = "0.14.1", features = ["executor"]} cosmic-comp-config = {path = "cosmic-comp-config"} cosmic-config = {git = "https://github.com/pop-os/libcosmic/", features = ["calloop", "macro"]} cosmic-protocols = {git = "https://github.com/pop-os/cosmic-protocols", branch = "main", default-features = false, features = ["server"]} -cosmic-settings-config = { git = "https://github.com/pop-os/cosmic-settings-daemon" } +# cosmic-settings-config = { git = "https://github.com/pop-os/cosmic-settings-daemon" } +cosmic-settings-config = { git = "https://github.com/ryanabx-contrib/cosmic-settings-daemon", branch = "gestures" } edid-rs = {version = "0.1"} egui = {version = "0.29.0", optional = true} egui_plot = {version = "0.29.0", optional = true} diff --git a/src/config/gestures.rs b/src/config/gestures.rs new file mode 100644 index 00000000..7fa487c3 --- /dev/null +++ b/src/config/gestures.rs @@ -0,0 +1,24 @@ +use cosmic_comp_config::workspace::WorkspaceLayout; +use cosmic_settings_config::shortcuts::{self, action::Direction, Gestures}; + +pub fn add_default_gestures(gestures: &mut Gestures, workspace_layout: WorkspaceLayout) { + // TODO: Do we take into account natural scroll? + let (workspace_forward, workspace_backward) = match workspace_layout { + WorkspaceLayout::Vertical => (Direction::Up, Direction::Down), + WorkspaceLayout::Horizontal => (Direction::Left, Direction::Right), + }; + + gestures.insert_default_gesture( + 4 as u32, + workspace_forward.clone(), + shortcuts::Action::NextWorkspace, + ); + + gestures.insert_default_gesture( + 4 as u32, + workspace_backward.clone(), + shortcuts::Action::PreviousWorkspace, + ); + + // TODO: More default gestures? +} diff --git a/src/config/mod.rs b/src/config/mod.rs index f8bd9a2f..dba5bc1c 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -8,7 +8,7 @@ use crate::{ }, }; use cosmic_config::{ConfigGet, CosmicConfigEntry}; -use cosmic_settings_config::window_rules::ApplicationException; +use cosmic_settings_config::{shortcuts::Gestures, window_rules::ApplicationException}; use cosmic_settings_config::{shortcuts, window_rules, Shortcuts}; use serde::{Deserialize, Serialize}; use smithay::wayland::xdg_activation::XdgActivationState; @@ -37,6 +37,7 @@ use tracing::{error, warn}; mod input_config; pub mod key_bindings; pub use key_bindings::{Action, PrivateAction}; +pub mod gestures; mod types; pub use self::types::*; use cosmic::config::CosmicTk; @@ -54,6 +55,8 @@ pub struct Config { pub settings_context: cosmic_config::Config, /// Key bindings from `com.system76.CosmicSettings.Shortcuts` pub shortcuts: Shortcuts, + /// Gestures from `com.system76.CosmicSettings.Shortcuts` + pub gestures: Gestures, // Tiling exceptions from `com.system76.CosmicSettings.WindowRules` pub tiling_exceptions: Vec, /// System actions from `com.system76.CosmicSettings.Shortcuts` @@ -226,9 +229,15 @@ impl Config { let settings_context = shortcuts::context().expect("Failed to load shortcuts config"); let system_actions = shortcuts::system_actions(&config); let mut shortcuts = shortcuts::shortcuts(&settings_context); - + // Add any missing default shortcuts recommended by the compositor. key_bindings::add_default_bindings(&mut shortcuts, workspace.workspace_layout); + + // Source gestures + let mut gestures = shortcuts::gestures(&settings_context); + + // Add any missing default gestures recommended by the compositor. + gestures::add_default_gestures(&mut gestures, workspace.workspace_layout); // Listen for updates to the keybindings config. match cosmic_config::calloop::ConfigWatchSource::new(&settings_context) { @@ -245,6 +254,14 @@ impl Config { state.common.config.shortcuts = shortcuts; } + "custom_gestures" | "default_gestures" => { + let mut gestures = shortcuts::gestures(&config); + let layout = get_config::(&config, "workspaces") + .workspace_layout; + gestures::add_default_gestures(&mut gestures, layout); + state.common.config.gestures = gestures; + } + "system_actions" => { state.common.config.system_actions = shortcuts::system_actions(&config); @@ -309,6 +326,7 @@ impl Config { cosmic_helper: config, settings_context, shortcuts, + gestures, system_actions, tiling_exceptions, } diff --git a/src/input/actions.rs b/src/input/actions.rs index a85cf8a0..5426c6c4 100644 --- a/src/input/actions.rs +++ b/src/input/actions.rs @@ -92,11 +92,10 @@ impl State { } } - pub fn handle_swipe_action(&mut self, action: gestures::SwipeAction, seat: &Seat) { - use gestures::SwipeAction; + pub fn handle_swipe_action(&mut self, action: shortcuts::Action, seat: &Seat) { match action { - SwipeAction::NextWorkspace => { + shortcuts::Action::NextWorkspace => { let _ = to_next_workspace( &mut *self.common.shell.write().unwrap(), &seat, @@ -104,7 +103,7 @@ impl State { &mut self.common.workspace_state.update(), ); } - SwipeAction::PrevWorkspace => { + shortcuts::Action::PreviousWorkspace => { let _ = to_previous_workspace( &mut *self.common.shell.write().unwrap(), &seat, @@ -112,6 +111,7 @@ impl State { &mut self.common.workspace_state.update(), ); } + _ => {} // TODO: Handle more actions } } diff --git a/src/input/gestures/mod.rs b/src/input/gestures/mod.rs index 996d19cf..9d4479ee 100644 --- a/src/input/gestures/mod.rs +++ b/src/input/gestures/mod.rs @@ -1,4 +1,4 @@ -use cosmic_settings_config::shortcuts::action::Direction; +use cosmic_settings_config::{shortcuts::action::Direction, Action}; use smithay::utils::{Logical, Point}; use std::{collections::VecDeque, time::Duration}; use tracing::trace; @@ -12,17 +12,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 8b40908e..0d8682ff 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -9,7 +9,7 @@ use crate::{ }, Action, Config, PrivateAction, }, - input::gestures::{GestureState, SwipeAction}, + input::gestures::GestureState, shell::{ focus::{ render_input_order, @@ -34,7 +34,7 @@ use calloop::{ RegistrationToken, }; use cosmic_comp_config::workspace::WorkspaceLayout; -use cosmic_settings_config::shortcuts; +use cosmic_settings_config::shortcuts::{self, Gesture}; use cosmic_settings_config::shortcuts::action::{Direction, ResizeDirection}; use smithay::{ backend::input::{ @@ -880,7 +880,7 @@ impl State { .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&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(), @@ -896,63 +896,20 @@ impl State { natural_scroll = natural; } } - 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) => { - if natural_scroll { - Some(SwipeAction::NextWorkspace) - } else { - Some(SwipeAction::PrevWorkspace) - } - } - Some(Direction::Right) => { - if natural_scroll { - Some(SwipeAction::PrevWorkspace) - } else { - Some(SwipeAction::NextWorkspace) - } - } - _ => None, // TODO: Other actions - } - } else { - match gesture_state.direction { - Some(Direction::Up) => { - if natural_scroll { - Some(SwipeAction::NextWorkspace) - } else { - Some(SwipeAction::PrevWorkspace) - } - } - Some(Direction::Down) => { - if natural_scroll { - Some(SwipeAction::PrevWorkspace) - } else { - Some(SwipeAction::NextWorkspace) - } - } - _ => None, // TODO: Other actions - } - } - } - _ => None, - }; - - gesture_state.action = activate_action; + activate_action = self.common.config.gestures.0.iter().find(|(gesture, action)| { + gesture.fingers == gesture_state.fingers && Some(gesture.direction) == gesture_state.direction + }).map(|(_, action)| action).cloned(); + gesture_state.action = activate_action.clone(); } match gesture_state.action { - Some(SwipeAction::NextWorkspace) | Some(SwipeAction::PrevWorkspace) => { + Some(shortcuts::Action::NextWorkspace) | Some(shortcuts::Action::PreviousWorkspace) => { self.common.shell.write().unwrap().update_workspace_delta( &seat.active_output(), gesture_state.delta, ) } - _ => {} + _ => {} // TODO: Other actions } } else { let pointer = seat.get_pointer().unwrap(); @@ -983,7 +940,7 @@ impl State { self.common.idle_notifier_state.notify_activity(&seat); if let Some(ref gesture_state) = self.common.gesture_state { match gesture_state.action { - Some(SwipeAction::NextWorkspace) | Some(SwipeAction::PrevWorkspace) => { + Some(shortcuts::Action::NextWorkspace) | Some(shortcuts::Action::PreviousWorkspace) => { let velocity = gesture_state.velocity(); let norm_velocity = if self.common.config.cosmic_conf.workspaces.workspace_layout