Commit 4727706757b9
tarball5 files changed+78-0
@@ -20,6 +20,7 @@ use smithay::wayland::image_capture_source::{
2020
ImageCaptureSourceState, OutputCaptureSourceState, ToplevelCaptureSourceState,2121
};2222
use smithay::wayland::image_copy_capture::ImageCopyCaptureState;23
+use smithay::wayland::keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState;2324
use smithay::wayland::output::OutputManagerState;2425
use smithay::wayland::pointer_constraints::PointerConstraintsState;2526
use smithay::wayland::presentation::PresentationState;@@ -62,6 +63,7 @@ pub struct Protocols {
6263
pub toplevel_list: ForeignToplevelListState,6364
pub xdg_foreign: XdgForeignState,6465
_xdg_dialog: XdgDialogState,66
+ pub shortcuts_inhibit: KeyboardShortcutsInhibitState,6567
_image_capture_source: ImageCaptureSourceState,6668
_idle_inhibit: IdleInhibitManagerState,6769
_xdg_decoration: XdgDecorationState,@@ -128,6 +130,7 @@ impl Protocols {
128130
toplevel_list: ForeignToplevelListState::new::<State>(dh),129131
xdg_foreign: XdgForeignState::new::<State>(dh),130132
_xdg_dialog: XdgDialogState::new::<State>(dh),133
+ shortcuts_inhibit: KeyboardShortcutsInhibitState::new::<State>(dh),131134
_image_capture_source: ImageCaptureSourceState::new(),132135
_idle_inhibit: IdleInhibitManagerState::new::<State>(dh),133136
_xdg_decoration: XdgDecorationState::new::<State>(dh),@@ -0,0 +1,68 @@
1
+//! Keyboard shortcut inhibitors. A client that asks gets its keys while it2
+//! has keyboard focus, with no prompt. Only binds that quit or reload still3
+//! fire, so a stuck inhibitor can always be walked out of, and VT switches4
+//! are never inhibited.5
+6
+use crate::focus::Focus;7
+use crate::state::State;8
+use monolith_ipc::Command;9
+use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;10
+use smithay::wayland::keyboard_shortcuts_inhibit::{11
+ KeyboardShortcutsInhibitHandler, KeyboardShortcutsInhibitState, KeyboardShortcutsInhibitor,12
+ KeyboardShortcutsInhibitorSeat,13
+};14
+use smithay::wayland::seat::WaylandFocus;15
+16
+pub fn escapes(cmd: &Command) -> bool {17
+ matches!(cmd, Command::Reload | Command::Quit)18
+}19
+20
+impl State {21
+ pub fn shortcuts_inhibited(&self) -> bool {22
+ self.input.inhibitor.as_ref().is_some_and(|i| i.is_active())23
+ }24
+25
+ /// Moves the active inhibitor to the new keyboard focus's, if it has one.26
+ pub fn follow_inhibitor(&mut self, focused: Option<&Focus>) {27
+ let surface = focused.and_then(|f| f.wl_surface());28
+ let next = surface29
+ .as_deref()30
+ .and_then(|s| self.input.seat.keyboard_shortcuts_inhibitor_for_surface(s));31
+ if self.input.inhibitor == next {32
+ return;33
+ }34
+ if let Some(old) = std::mem::replace(&mut self.input.inhibitor, next.clone()) {35
+ old.inactivate();36
+ }37
+ if let Some(next) = next {38
+ next.activate();39
+ }40
+ }41
+}42
+43
+impl KeyboardShortcutsInhibitHandler for State {44
+ fn keyboard_shortcuts_inhibit_state(&mut self) -> &mut KeyboardShortcutsInhibitState {45
+ &mut self.protocols.shortcuts_inhibit46
+ }47
+48
+ fn new_inhibitor(&mut self, inhibitor: KeyboardShortcutsInhibitor) {49
+ let focused = self50
+ .input51
+ .seat52
+ .get_keyboard()53
+ .and_then(|k| k.current_focus());54
+ if focused55
+ .and_then(|f| f.wl_surface().map(|s| s.into_owned()))56
+ .is_some_and(|s: WlSurface| &s == inhibitor.wl_surface())57
+ {58
+ inhibitor.activate();59
+ self.input.inhibitor = Some(inhibitor);60
+ }61
+ }62
+63
+ fn inhibitor_destroyed(&mut self, inhibitor: KeyboardShortcutsInhibitor) {64
+ if self.input.inhibitor.as_ref() == Some(&inhibitor) {65
+ self.input.inhibitor = None;66
+ }67
+ }68
+}@@ -210,6 +210,9 @@ impl State {
210210
Some(cmd) if state.services.lock.active() && !cmd.allowed_while_locked() => {211211
FilterResult::Forward212212
}213
+ Some(cmd) if state.shortcuts_inhibited() && !crate::inhibit::escapes(&cmd) => {214
+ FilterResult::Forward215
+ }213216
Some(cmd) => {214217
tracing::debug!(?cmd, "bind");215218
state.input.suppressed.push(code);@@ -13,6 +13,7 @@ mod frame;
1313
mod globals;1414
mod idle;1515
mod import;16
+mod inhibit;1617
mod input;1718
mod ipc;1819
mod launch;@@ -68,6 +68,7 @@ pub struct Input {
6868
/// Where the last absolute device event put the pointer, so the next6969
/// one yields a relative delta even while the pointer is held in place.7070
pub absolute: Option<Point<f64, Logical>>,71
+ pub inhibitor: Option<smithay::wayland::keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitor>,7172
}7273
7374
/// What needs doing after this batch of events.@@ -202,6 +203,7 @@ impl State {
202203
hover: None,203204
pointer_output: None,204205
absolute: None,206
+ inhibitor: None,205207
},206208
dirty: Dirty {207209
redraw: true,@@ -470,6 +472,7 @@ impl State {
470472
{471473
keyboard.set_focus(self, target.clone(), SERIAL_COUNTER.next_serial());472474
}475
+ self.follow_inhibitor(target.as_ref());473476
self.sync_pointer_constraint();474477
}