diff --git a/src/config/key_bindings.rs b/src/config/key_bindings.rs new file mode 100644 index 00000000..b74c240f --- /dev/null +++ b/src/config/key_bindings.rs @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: GPL-3.0-only + +use crate::shell::{ + focus::FocusDirection, grabs::ResizeEdge, layout::tiling::Direction, ResizeDirection, +}; +use serde::Deserialize; +use smithay::{ + backend::input::KeyState, + input::keyboard::{keysyms as KeySyms, xkb::keysym_get_name, ModifiersState}, +}; +use std::collections::HashMap; + +use super::{types::*, WorkspaceLayout}; + +#[derive(Debug, Clone, PartialEq, Eq, Deserialize)] +pub enum KeyModifier { + Ctrl, + Alt, + Shift, + Super, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] +pub struct KeyModifiers { + pub ctrl: bool, + pub alt: bool, + pub shift: bool, + pub logo: bool, +} + +impl PartialEq for KeyModifiers { + fn eq(&self, other: &ModifiersState) -> bool { + self.ctrl == other.ctrl + && self.alt == other.alt + && self.shift == other.shift + && self.logo == other.logo + } +} + +impl Into for ModifiersState { + fn into(self) -> KeyModifiers { + KeyModifiers { + ctrl: self.ctrl, + alt: self.alt, + shift: self.shift, + logo: self.logo, + } + } +} + +impl std::ops::AddAssign for KeyModifiers { + fn add_assign(&mut self, rhs: KeyModifier) { + match rhs { + KeyModifier::Ctrl => self.ctrl = true, + KeyModifier::Alt => self.alt = true, + KeyModifier::Shift => self.shift = true, + KeyModifier::Super => self.logo = true, + }; + } +} + +impl std::ops::BitOr for KeyModifier { + type Output = KeyModifiers; + + fn bitor(self, rhs: KeyModifier) -> Self::Output { + let mut modifiers = self.into(); + modifiers += rhs; + modifiers + } +} + +impl Into for KeyModifier { + fn into(self) -> KeyModifiers { + let mut modifiers = KeyModifiers { + ctrl: false, + alt: false, + shift: false, + logo: false, + }; + modifiers += self; + modifiers + } +} + +/// Describtion of a key combination that might be +/// handled by the compositor. +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Hash)] +#[serde(deny_unknown_fields)] +pub struct KeyPattern { + /// What modifiers are expected to be pressed alongside the key + #[serde(deserialize_with = "deserialize_KeyModifiers")] + pub modifiers: KeyModifiers, + /// The actual key, that was pressed + #[serde(deserialize_with = "deserialize_Keysym")] + pub key: u32, +} + +impl KeyPattern { + pub fn new(modifiers: impl Into, key: u32) -> KeyPattern { + KeyPattern { + modifiers: modifiers.into(), + key, + } + } +} + +impl ToString for KeyPattern { + fn to_string(&self) -> String { + let mut result = String::new(); + if self.modifiers.logo { + result += "Super+"; + } + if self.modifiers.ctrl { + result += "Ctrl+"; + } + if self.modifiers.alt { + result += "Alt+"; + } + if self.modifiers.shift { + result += "Shift+"; + } + result += &keysym_get_name(self.key); + result + } +} + +#[derive(Debug, Deserialize, Clone, PartialEq, Eq)] +pub enum Action { + Terminate, + Debug, + Close, + + Workspace(u8), + NextWorkspace, + PreviousWorkspace, + LastWorkspace, + MoveToWorkspace(u8), + MoveToNextWorkspace, + MoveToPreviousWorkspace, + MoveToLastWorkspace, + SendToWorkspace(u8), + SendToNextWorkspace, + SendToPreviousWorkspace, + SendToLastWorkspace, + + NextOutput, + PreviousOutput, + MoveToNextOutput, + MoveToPreviousOutput, + SendToNextOutput, + SendToPreviousOutput, + + Focus(FocusDirection), + Move(Direction), + + ToggleOrientation, + Orientation(crate::shell::layout::Orientation), + + ToggleStacking, + + ToggleTiling, + ToggleWindowFloating, + + Resizing(ResizeDirection), + #[serde(skip)] + _ResizingInternal(ResizeDirection, ResizeEdge, KeyState), + Maximize, + Spawn(String), +} + +fn insert_binding( + key_bindings: &mut HashMap, + modifiers: KeyModifiers, + keys: impl Iterator, + action: Action, +) { + if !key_bindings.values().any(|a| a == &action) { + for key in keys { + let pattern = KeyPattern { + modifiers: modifiers.clone(), + key, + }; + if !key_bindings.contains_key(&pattern) { + key_bindings.insert(pattern, action.clone()); + } + } + } +} + +pub fn add_default_bindings( + key_bindings: &mut HashMap, + workspace_layout: WorkspaceLayout, +) { + let (workspace_previous, workspace_next, output_previous, output_next) = match workspace_layout + { + WorkspaceLayout::Horizontal => ( + [KeySyms::KEY_Left, KeySyms::KEY_h], + [KeySyms::KEY_Right, KeySyms::KEY_j], + [KeySyms::KEY_Up, KeySyms::KEY_k], + [KeySyms::KEY_Down, KeySyms::KEY_j], + ), + WorkspaceLayout::Vertical => ( + [KeySyms::KEY_Up, KeySyms::KEY_k], + [KeySyms::KEY_Down, KeySyms::KEY_j], + [KeySyms::KEY_Left, KeySyms::KEY_h], + [KeySyms::KEY_Right, KeySyms::KEY_j], + ), + }; + + insert_binding( + key_bindings, + KeyModifiers { + logo: true, + ctrl: true, + ..Default::default() + }, + workspace_previous.iter().copied(), + Action::PreviousWorkspace, + ); + insert_binding( + key_bindings, + KeyModifiers { + logo: true, + ctrl: true, + ..Default::default() + }, + workspace_next.iter().copied(), + Action::NextWorkspace, + ); + insert_binding( + key_bindings, + KeyModifiers { + logo: true, + ctrl: true, + shift: true, + ..Default::default() + }, + workspace_previous.iter().copied(), + Action::MoveToPreviousWorkspace, + ); + insert_binding( + key_bindings, + KeyModifiers { + logo: true, + ctrl: true, + shift: true, + ..Default::default() + }, + workspace_next.iter().copied(), + Action::MoveToNextWorkspace, + ); + + insert_binding( + key_bindings, + KeyModifiers { + logo: true, + ctrl: true, + ..Default::default() + }, + output_previous.iter().copied(), + Action::PreviousOutput, + ); + insert_binding( + key_bindings, + KeyModifiers { + logo: true, + ctrl: true, + ..Default::default() + }, + output_next.iter().copied(), + Action::NextOutput, + ); + insert_binding( + key_bindings, + KeyModifiers { + logo: true, + ctrl: true, + shift: true, + ..Default::default() + }, + output_previous.iter().copied(), + Action::MoveToPreviousOutput, + ); + insert_binding( + key_bindings, + KeyModifiers { + logo: true, + ctrl: true, + shift: true, + ..Default::default() + }, + output_next.iter().copied(), + Action::MoveToNextOutput, + ); +} diff --git a/src/config/mod.rs b/src/config/mod.rs index 663b4e62..2a663ddd 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -2,14 +2,13 @@ use crate::{ shell::{ - focus::FocusDirection, grabs::ResizeEdge, layout::tiling::Direction, ResizeDirection, Shell, WorkspaceAmount, }, state::{BackendData, Data, State}, wayland::protocols::output_configuration::OutputConfigurationState, }; use serde::{Deserialize, Serialize}; -use smithay::input::{keyboard::xkb::keysym_get_name, Seat}; +use smithay::input::Seat; pub use smithay::{ backend::input::KeyState, input::keyboard::{keysyms as KeySyms, Keysym, ModifiersState}, @@ -26,6 +25,8 @@ pub use smithay::{ use std::{cell::RefCell, collections::HashMap, fs::OpenOptions, path::PathBuf}; use tracing::{debug, error, info, warn}; +mod key_bindings; +pub use key_bindings::{Action, KeyModifier, KeyModifiers, KeyPattern}; mod types; pub use self::types::*; @@ -37,7 +38,7 @@ pub struct Config { #[derive(Debug, Deserialize)] pub struct StaticConfig { - pub key_bindings: HashMap, + pub key_bindings: HashMap, pub workspace_mode: WorkspaceMode, pub workspace_amount: WorkspaceAmount, #[serde(default = "default_workspace_layout")] @@ -247,125 +248,9 @@ impl Config { ron::de::from_reader(OpenOptions::new().read(true).open(path).unwrap()) .expect("Malformed config file"); - let (workspace_previous, workspace_next, output_previous, output_next) = - match config.workspace_layout { - WorkspaceLayout::Horizontal => ( - [KeySyms::KEY_Left, KeySyms::KEY_h], - [KeySyms::KEY_Right, KeySyms::KEY_j], - [KeySyms::KEY_Up, KeySyms::KEY_k], - [KeySyms::KEY_Down, KeySyms::KEY_j], - ), - WorkspaceLayout::Vertical => ( - [KeySyms::KEY_Up, KeySyms::KEY_k], - [KeySyms::KEY_Down, KeySyms::KEY_j], - [KeySyms::KEY_Left, KeySyms::KEY_h], - [KeySyms::KEY_Right, KeySyms::KEY_j], - ), - }; - - fn insert_binding( - key_bindings: &mut HashMap, - modifiers: KeyModifiers, - keys: impl Iterator, - action: Action, - ) { - if !key_bindings.values().any(|a| a == &action) { - for key in keys { - let pattern = KeyPattern { - modifiers: modifiers.clone(), - key, - }; - if !key_bindings.contains_key(&pattern) { - key_bindings.insert(pattern, action.clone()); - } - } - } - } - - insert_binding( + key_bindings::add_default_bindings( &mut config.key_bindings, - KeyModifiers { - logo: true, - ctrl: true, - ..Default::default() - }, - workspace_previous.iter().copied(), - Action::PreviousWorkspace, - ); - insert_binding( - &mut config.key_bindings, - KeyModifiers { - logo: true, - ctrl: true, - ..Default::default() - }, - workspace_next.iter().copied(), - Action::NextWorkspace, - ); - insert_binding( - &mut config.key_bindings, - KeyModifiers { - logo: true, - ctrl: true, - shift: true, - ..Default::default() - }, - workspace_previous.iter().copied(), - Action::MoveToPreviousWorkspace, - ); - insert_binding( - &mut config.key_bindings, - KeyModifiers { - logo: true, - ctrl: true, - shift: true, - ..Default::default() - }, - workspace_next.iter().copied(), - Action::MoveToNextWorkspace, - ); - - insert_binding( - &mut config.key_bindings, - KeyModifiers { - logo: true, - ctrl: true, - ..Default::default() - }, - output_previous.iter().copied(), - Action::PreviousOutput, - ); - insert_binding( - &mut config.key_bindings, - KeyModifiers { - logo: true, - ctrl: true, - ..Default::default() - }, - output_next.iter().copied(), - Action::NextOutput, - ); - insert_binding( - &mut config.key_bindings, - KeyModifiers { - logo: true, - ctrl: true, - shift: true, - ..Default::default() - }, - output_previous.iter().copied(), - Action::MoveToPreviousOutput, - ); - insert_binding( - &mut config.key_bindings, - KeyModifiers { - logo: true, - ctrl: true, - shift: true, - ..Default::default() - }, - output_next.iter().copied(), - Action::MoveToNextOutput, + config.workspace_layout, ); return config; @@ -901,159 +786,3 @@ impl DynamicConfig { PersistenceGuard(self.inputs.0.clone(), &mut self.inputs.1) } } - -#[derive(Debug, Clone, PartialEq, Eq, Deserialize)] -pub enum KeyModifier { - Ctrl, - Alt, - Shift, - Super, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] -pub struct KeyModifiers { - pub ctrl: bool, - pub alt: bool, - pub shift: bool, - pub logo: bool, -} - -impl PartialEq for KeyModifiers { - fn eq(&self, other: &ModifiersState) -> bool { - self.ctrl == other.ctrl - && self.alt == other.alt - && self.shift == other.shift - && self.logo == other.logo - } -} - -impl Into for ModifiersState { - fn into(self) -> KeyModifiers { - KeyModifiers { - ctrl: self.ctrl, - alt: self.alt, - shift: self.shift, - logo: self.logo, - } - } -} - -impl std::ops::AddAssign for KeyModifiers { - fn add_assign(&mut self, rhs: KeyModifier) { - match rhs { - KeyModifier::Ctrl => self.ctrl = true, - KeyModifier::Alt => self.alt = true, - KeyModifier::Shift => self.shift = true, - KeyModifier::Super => self.logo = true, - }; - } -} - -impl std::ops::BitOr for KeyModifier { - type Output = KeyModifiers; - - fn bitor(self, rhs: KeyModifier) -> Self::Output { - let mut modifiers = self.into(); - modifiers += rhs; - modifiers - } -} - -impl Into for KeyModifier { - fn into(self) -> KeyModifiers { - let mut modifiers = KeyModifiers { - ctrl: false, - alt: false, - shift: false, - logo: false, - }; - modifiers += self; - modifiers - } -} - -/// Describtion of a key combination that might be -/// handled by the compositor. -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Hash)] -#[serde(deny_unknown_fields)] -pub struct KeyPattern { - /// What modifiers are expected to be pressed alongside the key - #[serde(deserialize_with = "deserialize_KeyModifiers")] - pub modifiers: KeyModifiers, - /// The actual key, that was pressed - #[serde(deserialize_with = "deserialize_Keysym")] - pub key: u32, -} - -impl KeyPattern { - pub fn new(modifiers: impl Into, key: u32) -> KeyPattern { - KeyPattern { - modifiers: modifiers.into(), - key, - } - } -} - -impl ToString for KeyPattern { - fn to_string(&self) -> String { - let mut result = String::new(); - if self.modifiers.logo { - result += "Super+"; - } - if self.modifiers.ctrl { - result += "Ctrl+"; - } - if self.modifiers.alt { - result += "Alt+"; - } - if self.modifiers.shift { - result += "Shift+"; - } - result += &keysym_get_name(self.key); - result - } -} - -#[derive(Debug, Deserialize, Clone, PartialEq, Eq)] -pub enum Action { - Terminate, - Debug, - Close, - - Workspace(u8), - NextWorkspace, - PreviousWorkspace, - LastWorkspace, - MoveToWorkspace(u8), - MoveToNextWorkspace, - MoveToPreviousWorkspace, - MoveToLastWorkspace, - SendToWorkspace(u8), - SendToNextWorkspace, - SendToPreviousWorkspace, - SendToLastWorkspace, - - NextOutput, - PreviousOutput, - MoveToNextOutput, - MoveToPreviousOutput, - SendToNextOutput, - SendToPreviousOutput, - - Focus(FocusDirection), - Move(Direction), - - ToggleOrientation, - Orientation(crate::shell::layout::Orientation), - - ToggleStacking, - - ToggleTiling, - ToggleWindowFloating, - - Resizing(ResizeDirection), - #[serde(skip)] - _ResizingInternal(ResizeDirection, ResizeEdge, KeyState), - Maximize, - Spawn(String), -}