diff --git a/src/handlers.rs b/src/handlers.rs index 995fcfe..898207f 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -15,10 +15,11 @@ use smithay::{ renderer::utils::{self, with_renderer_surface_state}, }, delegate_compositor, delegate_cursor_shape, delegate_data_control, delegate_data_device, - delegate_fractional_scale, delegate_layer_shell, delegate_output, delegate_pointer_constraints, - delegate_presentation, delegate_primary_selection, delegate_relative_pointer, delegate_seat, + delegate_fractional_scale, delegate_keyboard_shortcuts_inhibit, delegate_layer_shell, + delegate_output, delegate_pointer_constraints, delegate_presentation, + delegate_primary_selection, delegate_relative_pointer, delegate_seat, delegate_security_context, delegate_shm, delegate_tablet_manager, delegate_viewporter, - delegate_xwayland_shell, + delegate_xwayland_keyboard_grab, delegate_xwayland_shell, desktop::{ self, find_popup_root_surface, get_popup_toplevel_coords, layer_map_for_output, PopupKind, PopupManager, WindowSurfaceType, @@ -48,6 +49,10 @@ use smithay::{ }, dmabuf, fractional_scale::{self, FractionalScaleHandler}, + keyboard_shortcuts_inhibit::{ + KeyboardShortcutsInhibitHandler, KeyboardShortcutsInhibitState, + KeyboardShortcutsInhibitor, + }, output::OutputHandler, pointer_constraints::{with_pointer_constraint, PointerConstraintsHandler}, seat::WaylandFocus, @@ -71,6 +76,7 @@ use smithay::{ }, shm::{ShmHandler, ShmState}, tablet_manager::TabletSeatHandler, + xwayland_keyboard_grab::XWaylandKeyboardGrabHandler, xwayland_shell::{XWaylandShellHandler, XWaylandShellState}, }, xwayland::XWaylandClientData, @@ -912,6 +918,27 @@ delegate_tablet_manager!(State); delegate_cursor_shape!(State); +impl KeyboardShortcutsInhibitHandler for State { + fn keyboard_shortcuts_inhibit_state(&mut self) -> &mut KeyboardShortcutsInhibitState { + &mut self.pinnacle.keyboard_shortcuts_inhibit_state + } + + fn new_inhibitor(&mut self, inhibitor: KeyboardShortcutsInhibitor) { + // TODO: Some way to not unconditionally activate the inhibitor + inhibitor.activate(); + } +} +delegate_keyboard_shortcuts_inhibit!(State); + +impl XWaylandKeyboardGrabHandler for State { + fn keyboard_focus_for_xsurface(&self, surface: &WlSurface) -> Option { + self.pinnacle + .window_for_surface(surface) + .map(KeyboardFocusTarget::from) + } +} +delegate_xwayland_keyboard_grab!(State); + impl Pinnacle { fn position_popup(&self, popup: &PopupSurface) { trace!("State::position_popup"); diff --git a/src/input.rs b/src/input.rs index 4b47b1c..83d323c 100644 --- a/src/input.rs +++ b/src/input.rs @@ -35,6 +35,7 @@ use smithay::{ utils::{Logical, Point, Rectangle, SERIAL_COUNTER}, wayland::{ compositor::{self, RegionAttributes, SurfaceAttributes}, + keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat, pointer_constraints::{with_pointer_constraint, PointerConstraint}, seat::WaylandFocus, shell::wlr_layer::{self, KeyboardInteractivity, LayerSurfaceCachedState}, @@ -487,6 +488,17 @@ impl State { } } + let shortcuts_inhibited = keyboard + .current_focus() + .and_then(|focus| { + focus.wl_surface().and_then(|surf| { + self.pinnacle + .seat + .keyboard_shortcuts_inhibitor_for_surface(&surf) + }) + }) + .is_some_and(|inhibitor| inhibitor.is_active()); + let action = keyboard.input( self, event.key_code(), @@ -510,36 +522,6 @@ impl State { let raw_sym = keysym.raw_syms().iter().next(); let mod_sym = keysym.modified_sym(); - if let Some(keybind_data) = state - .pinnacle - .input_state - .keybinds - .get(&(mod_mask, mod_sym)) - .or_else(|| { - raw_sym.and_then(|raw_sym| { - state - .pinnacle - .input_state - .keybinds - .get(&(mod_mask, *raw_sym)) - }) - }) - { - if state.pinnacle.lock_state.is_unlocked() { - return FilterResult::Intercept(KeyAction::CallCallback( - keybind_data.sender.clone(), - )); - } - } - - if kill_keybind == Some((mod_mask, mod_sym)) { - return FilterResult::Intercept(KeyAction::Quit); - } - - if reload_keybind == Some((mod_mask, mod_sym)) { - return FilterResult::Intercept(KeyAction::ReloadConfig); - } - if let mut vt @ keysyms::KEY_XF86Switch_VT_1..=keysyms::KEY_XF86Switch_VT_12 = keysym.modified_sym().raw() { @@ -547,6 +529,38 @@ impl State { tracing::info!("Switching to vt {vt}"); return FilterResult::Intercept(KeyAction::SwitchVt(vt as i32)); } + + if !shortcuts_inhibited { + if let Some(keybind_data) = state + .pinnacle + .input_state + .keybinds + .get(&(mod_mask, mod_sym)) + .or_else(|| { + raw_sym.and_then(|raw_sym| { + state + .pinnacle + .input_state + .keybinds + .get(&(mod_mask, *raw_sym)) + }) + }) + { + if state.pinnacle.lock_state.is_unlocked() { + return FilterResult::Intercept(KeyAction::CallCallback( + keybind_data.sender.clone(), + )); + } + } + + if kill_keybind == Some((mod_mask, mod_sym)) { + return FilterResult::Intercept(KeyAction::Quit); + } + + if reload_keybind == Some((mod_mask, mod_sym)) { + return FilterResult::Intercept(KeyAction::ReloadConfig); + } + } } FilterResult::Forward diff --git a/src/main.rs b/src/main.rs index 01cc1e1..bff0eb9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,6 @@ use pinnacle::{ util::increase_nofile_rlimit, }; use smithay::reexports::{calloop::EventLoop, rustix::process::geteuid}; -use tokio::sync::oneshot::error::TryRecvError; use tracing::{error, info, warn}; use tracing_appender::rolling::Rotation; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer}; @@ -177,6 +176,8 @@ async fn main() -> anyhow::Result<()> { #[cfg(feature = "snowcap")] { + use tokio::sync::oneshot::error::TryRecvError; + let (sender, mut recv) = tokio::sync::oneshot::channel(); let join_handle = tokio::task::spawn_blocking(move || { let _span = tracing::error_span!("snowcap"); diff --git a/src/state.rs b/src/state.rs index 4042f1c..28cead6 100644 --- a/src/state.rs +++ b/src/state.rs @@ -41,6 +41,7 @@ use smithay::{ dmabuf::DmabufFeedback, fractional_scale::FractionalScaleManagerState, idle_notify::IdleNotifierState, + keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState, output::OutputManagerState, pointer_constraints::PointerConstraintsState, relative_pointer::RelativePointerManagerState, @@ -55,6 +56,7 @@ use smithay::{ socket::ListeningSocketSource, tablet_manager::TabletManagerState, viewporter::ViewporterState, + xwayland_keyboard_grab::XWaylandKeyboardGrabState, xwayland_shell::XWaylandShellState, }, xwayland::{X11Wm, XWaylandClientData}, @@ -116,6 +118,8 @@ pub struct Pinnacle { pub output_management_manager_state: OutputManagementManagerState, pub output_power_management_state: OutputPowerManagementState, pub tablet_manager_state: TabletManagerState, + pub keyboard_shortcuts_inhibit_state: KeyboardShortcutsInhibitState, + pub xwayland_keyboard_grab_state: XWaylandKeyboardGrabState, pub lock_state: LockState, @@ -339,6 +343,10 @@ impl Pinnacle { filter_restricted_client, ), tablet_manager_state: TabletManagerState::new::(&display_handle), + keyboard_shortcuts_inhibit_state: KeyboardShortcutsInhibitState::new::( + &display_handle, + ), + xwayland_keyboard_grab_state: XWaylandKeyboardGrabState::new::(&display_handle), lock_state: LockState::default(),