diff options
| author | Christian Meissl <meissl.christian@gmail.com> | 2024-10-18 16:00:40 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-18 14:00:40 +0000 |
| commit | 79fd309d6cf84163ff1c5c44f222e6a58dfa2872 (patch) | |
| tree | 00d53946221acc9fdb4f80253cd8c2178b8b4933 | |
| parent | dd8b2be044c6c67a1c9bf07f287b3967e958b8aa (diff) | |
| download | niri-79fd309d6cf84163ff1c5c44f222e6a58dfa2872.tar.gz niri-79fd309d6cf84163ff1c5c44f222e6a58dfa2872.tar.bz2 niri-79fd309d6cf84163ff1c5c44f222e6a58dfa2872.zip | |
support binding actions to switches (#747)
* support spawn action on switch events
this adds a new config section named `switch-events`
that allows to bind `spawn` action to certain switch
toggles.
* Expand docs
---------
Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
| -rw-r--r-- | niri-config/src/lib.rs | 43 | ||||
| -rw-r--r-- | src/input/mod.rs | 41 | ||||
| -rw-r--r-- | wiki/Configuration:-Overview.md | 1 | ||||
| -rw-r--r-- | wiki/Configuration:-Switch-Events.md | 45 | ||||
| -rw-r--r-- | wiki/_Sidebar.md | 1 |
5 files changed, 127 insertions, 4 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index c4452534..79bddc31 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -54,6 +54,8 @@ pub struct Config { #[knuffel(child, default)] pub binds: Binds, #[knuffel(child, default)] + pub switch_events: SwitchBinds, + #[knuffel(child, default)] pub debug: DebugConfig, #[knuffel(children(name = "workspace"))] pub workspaces: Vec<Workspace>, @@ -1088,6 +1090,24 @@ bitflags! { } } +#[derive(knuffel::Decode, Debug, Default, Clone, PartialEq)] +pub struct SwitchBinds { + #[knuffel(child)] + pub lid_open: Option<SwitchAction>, + #[knuffel(child)] + pub lid_close: Option<SwitchAction>, + #[knuffel(child)] + pub tablet_mode_on: Option<SwitchAction>, + #[knuffel(child)] + pub tablet_mode_off: Option<SwitchAction>, +} + +#[derive(knuffel::Decode, Debug, Clone, PartialEq)] +pub struct SwitchAction { + #[knuffel(child, unwrap(arguments))] + pub spawn: Vec<String>, +} + // Remember to add new actions to the CLI enum too. #[derive(knuffel::Decode, Debug, Clone, PartialEq)] pub enum Action { @@ -3079,6 +3099,11 @@ mod tests { Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; } } + switch-events { + tablet-mode-on { spawn "bash" "-c" "gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled true"; } + tablet-mode-off { spawn "bash" "-c" "gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled false"; } + } + debug { render-drm-device "/dev/dri/renderD129" } @@ -3426,6 +3451,24 @@ mod tests { allow_when_locked: false, }, ]), + switch_events: SwitchBinds { + lid_open: None, + lid_close: None, + tablet_mode_on: Some(SwitchAction { + spawn: vec![ + "bash".to_owned(), + "-c".to_owned(), + "gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled true".to_owned(), + ], + }), + tablet_mode_off: Some(SwitchAction { + spawn: vec![ + "bash".to_owned(), + "-c".to_owned(), + "gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled false".to_owned(), + ], + }), + }, debug: DebugConfig { render_drm_device: Some(PathBuf::from("/dev/dri/renderD129")), ..Default::default() diff --git a/src/input/mod.rs b/src/input/mod.rs index 92475d8e..3bccb714 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -6,14 +6,15 @@ use std::time::Duration; use calloop::timer::{TimeoutAction, Timer}; use input::event::gesture::GestureEventCoordinates as _; -use niri_config::{Action, Bind, Binds, Key, Modifiers, Trigger}; +use niri_config::{Action, Bind, Binds, Key, Modifiers, SwitchBinds, Trigger}; use niri_ipc::LayoutSwitchTarget; use smithay::backend::input::{ AbsolutePositionEvent, Axis, AxisSource, ButtonState, Device, DeviceCapability, Event, GestureBeginEvent, GestureEndEvent, GesturePinchUpdateEvent as _, GestureSwipeUpdateEvent as _, InputBackend, InputEvent, KeyState, KeyboardKeyEvent, Keycode, MouseButton, PointerAxisEvent, - PointerButtonEvent, PointerMotionEvent, ProximityState, TabletToolButtonEvent, TabletToolEvent, - TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TouchEvent, + PointerButtonEvent, PointerMotionEvent, ProximityState, Switch, SwitchState, SwitchToggleEvent, + TabletToolButtonEvent, TabletToolEvent, TabletToolProximityEvent, TabletToolTipEvent, + TabletToolTipState, TouchEvent, }; use smithay::backend::libinput::LibinputInputBackend; use smithay::input::keyboard::{keysyms, FilterResult, Keysym, ModifiersState}; @@ -127,7 +128,7 @@ impl State { TouchUp { event } => self.on_touch_up::<I>(event), TouchCancel { event } => self.on_touch_cancel::<I>(event), TouchFrame { event } => self.on_touch_frame::<I>(event), - SwitchToggle { .. } => (), + SwitchToggle { event } => self.on_switch_toggle::<I>(event), Special(_) => (), } @@ -2360,6 +2361,21 @@ impl State { }; handle.cancel(self); } + + fn on_switch_toggle<I: InputBackend>(&mut self, evt: I::SwitchToggleEvent) { + let Some(switch) = evt.switch() else { + return; + }; + + let action = { + let bindings = &self.niri.config.borrow().switch_events; + find_configured_switch_action(bindings, switch, evt.state()) + }; + + if let Some(action) = action { + self.do_action(action, true); + } + } } /// Check whether the key should be intercepted and mark intercepted @@ -2511,6 +2527,23 @@ fn find_configured_bind( None } +fn find_configured_switch_action( + bindings: &SwitchBinds, + switch: Switch, + state: SwitchState, +) -> Option<Action> { + let switch_action = match (switch, state) { + (Switch::Lid, SwitchState::Off) => &bindings.lid_open, + (Switch::Lid, SwitchState::On) => &bindings.lid_close, + (Switch::TabletMode, SwitchState::Off) => &bindings.tablet_mode_off, + (Switch::TabletMode, SwitchState::On) => &bindings.tablet_mode_on, + _ => unreachable!(), + }; + switch_action + .as_ref() + .map(|switch_action| Action::Spawn(switch_action.spawn.clone())) +} + fn modifiers_from_state(mods: ModifiersState) -> Modifiers { let mut modifiers = Modifiers::empty(); if mods.ctrl { diff --git a/wiki/Configuration:-Overview.md b/wiki/Configuration:-Overview.md index 5988ac7c..cf208504 100644 --- a/wiki/Configuration:-Overview.md +++ b/wiki/Configuration:-Overview.md @@ -5,6 +5,7 @@ You can find documentation for various sections of the config on these wiki page * [`input {}`](./Configuration:-Input.md) * [`output "eDP-1" {}`](./Configuration:-Outputs.md) * [`binds {}`](./Configuration:-Key-Bindings.md) +* [`switch-events {}`](./Configuration:-Switch-Events.md) * [`layout {}`](./Configuration:-Layout.md) * [top-level options](./Configuration:-Miscellaneous.md) * [`window-rule {}`](./Configuration:-Window-Rules.md) diff --git a/wiki/Configuration:-Switch-Events.md b/wiki/Configuration:-Switch-Events.md new file mode 100644 index 00000000..bb438a20 --- /dev/null +++ b/wiki/Configuration:-Switch-Events.md @@ -0,0 +1,45 @@ +### Overview + +Switch event bindings are declared in the `switch-events {}` section of the config. + +Here are all the events that you can bind at a glance: + +```kdl +switch-events { + lid-close { spawn "bash" "-c" "niri msg output \"eDP-1\" off"; } + lid-open { spawn "bash" "-c" "niri msg output \"eDP-1\" on"; } + tablet-mode-on { spawn "bash" "-c" "gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled true"; } + tablet-mode-off { spawn "bash" "-c" "gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled false"; } +} +``` + +The syntax is similar to key bindings. +Currently only the `spawn` action are supported. + +> [!NOTE] +> In contrast to key bindings, switch event bindings are *always* executed, even when the session is locked. + +### `lid-close`, `lid-open` + +These events correspond to closing and opening of the laptop lid. + +You could use them to turn the laptop internal monitor off and on (until niri gets this functionality built-in). + +```kdl +switch-events { + lid-close { spawn "bash" "-c" "niri msg output \"eDP-1\" off"; } + lid-open { spawn "bash" "-c" "niri msg output \"eDP-1\" on"; } +} +``` + +### `tablet-mode-on`, `tablet-mode-off` + +These events trigger when a convertible laptop goes into or out of tablet mode. +In tablet mode, the keyboard and mouse are usually inaccessible, so you can use these events to activate the on-screen keyboard. + +```kdl +switch-events { + tablet-mode-on { spawn "bash" "-c" "gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled true"; } + tablet-mode-off { spawn "bash" "-c" "gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled false"; } +} +``` diff --git a/wiki/_Sidebar.md b/wiki/_Sidebar.md index 0699ef89..6e821b85 100644 --- a/wiki/_Sidebar.md +++ b/wiki/_Sidebar.md @@ -14,6 +14,7 @@ * [Input](./Configuration:-Input.md) * [Outputs](./Configuration:-Outputs.md) * [Key Bindings](./Configuration:-Key-Bindings.md) +* [Switch Events](./Configuration:-Switch-Events.md) * [Layout](./Configuration:-Layout.md) * [Named Workspaces](./Configuration:-Named-Workspaces.md) * [Miscellaneous](./Configuration:-Miscellaneous.md) |
