aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--niri-config/src/lib.rs43
-rw-r--r--src/input/mod.rs41
-rw-r--r--wiki/Configuration:-Overview.md1
-rw-r--r--wiki/Configuration:-Switch-Events.md45
-rw-r--r--wiki/_Sidebar.md1
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)