From 0f726cf16b1d5a7a96fce10b43e4662503953c75 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Fri, 9 Sep 2022 20:17:40 -0700 Subject: [PATCH] Implement keyboard shortcut inhibit protocol TODO: restrict what apps can call this in some way. --- src/input/mod.rs | 41 +++++++++++++++---- src/state.rs | 7 +++- .../handlers/keyboard_shortcuts_inhibit.rs | 22 ++++++++++ src/wayland/handlers/mod.rs | 1 + 4 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 src/wayland/handlers/keyboard_shortcuts_inhibit.rs diff --git a/src/input/mod.rs b/src/input/mod.rs index 0c20143b..abd75c23 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -20,7 +20,10 @@ use smithay::{ output::Output, reexports::wayland_server::{protocol::wl_surface::WlSurface, DisplayHandle}, utils::{Buffer, Logical, Point, Rectangle, Size, SERIAL_COUNTER}, - wayland::shell::wlr_layer::Layer as WlrLayer, + wayland::{ + keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat, + shell::wlr_layer::Layer as WlrLayer, + }, }; use std::{cell::RefCell, collections::HashMap}; @@ -173,6 +176,19 @@ impl State { let device = event.device(); for seat in self.common.seats.clone().iter() { + let current_output = active_output(seat, &self.common); + let workspace = self.common.shell.active_space_mut(¤t_output); + let shortcuts_inhibited = workspace + .focus_stack(seat) + .last() + .and_then(|window| { + seat.keyboard_shortcuts_inhibitor_for_surface( + &window.toplevel().wl_surface(), + ) + }) + .map(|inhibitor| inhibitor.is_active()) + .unwrap_or(false); + let userdata = seat.user_data(); let devices = userdata.get::().unwrap(); if devices.has_device(&device) { @@ -249,15 +265,22 @@ impl State { } // here we can handle global shortcuts and the like - for (binding, action) in - data.common.config.static_conf.key_bindings.iter() - { - if state == KeyState::Pressed - && binding.modifiers == *modifiers - && handle.raw_syms().contains(&binding.key) + if !shortcuts_inhibited { + for (binding, action) in + data.common.config.static_conf.key_bindings.iter() { - userdata.get::().unwrap().add(&handle); - return FilterResult::Intercept(Some(action.clone())); + if state == KeyState::Pressed + && binding.modifiers == *modifiers + && handle.raw_syms().contains(&binding.key) + { + userdata + .get::() + .unwrap() + .add(&handle); + return FilterResult::Intercept(Some( + action.clone(), + )); + } } } diff --git a/src/state.rs b/src/state.rs index a2cd9c00..3eaf3bbe 100644 --- a/src/state.rs +++ b/src/state.rs @@ -25,8 +25,8 @@ use smithay::{ utils::{Buffer, Size}, wayland::{ compositor::CompositorState, data_device::DataDeviceState, dmabuf::DmabufState, - output::OutputManagerState, primary_selection::PrimarySelectionState, shm::ShmState, - viewporter::ViewporterState, + keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState, output::OutputManagerState, + primary_selection::PrimarySelectionState, shm::ShmState, viewporter::ViewporterState, }, }; @@ -86,6 +86,7 @@ pub struct Common { pub data_device_state: DataDeviceState, pub dmabuf_state: DmabufState, pub export_dmabuf_state: ExportDmabufState, + pub keyboard_shortcuts_inhibit_state: KeyboardShortcutsInhibitState, pub output_state: OutputManagerState, pub output_configuration_state: OutputConfigurationState, pub primary_selection_state: PrimarySelectionState, @@ -301,6 +302,7 @@ impl State { //|client| client.get_data::().unwrap().privileged, |_| true, ); + let keyboard_shortcuts_inhibit_state = KeyboardShortcutsInhibitState::new::(dh); let output_state = OutputManagerState::new_with_xdg_output::(dh); let output_configuration_state = OutputConfigurationState::new(dh, |_| true); let primary_selection_state = PrimarySelectionState::new::(dh, None); @@ -355,6 +357,7 @@ impl State { export_dmabuf_state, shm_state, seat_state, + keyboard_shortcuts_inhibit_state, output_state, output_configuration_state, primary_selection_state, diff --git a/src/wayland/handlers/keyboard_shortcuts_inhibit.rs b/src/wayland/handlers/keyboard_shortcuts_inhibit.rs new file mode 100644 index 00000000..e1a2978d --- /dev/null +++ b/src/wayland/handlers/keyboard_shortcuts_inhibit.rs @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-3.0-only + +use crate::state::State; +use smithay::{ + delegate_keyboard_shortcuts_inhibit, + wayland::keyboard_shortcuts_inhibit::{ + KeyboardShortcutsInhibitHandler, KeyboardShortcutsInhibitState, KeyboardShortcutsInhibitor, + }, +}; + +impl KeyboardShortcutsInhibitHandler for State { + fn keyboard_shortcuts_inhibit_state(&mut self) -> &mut KeyboardShortcutsInhibitState { + &mut self.common.keyboard_shortcuts_inhibit_state + } + + fn new_inhibitor(&mut self, inhibitor: KeyboardShortcutsInhibitor) { + // TODO: Restrict what apps can inhibit shortcuts + inhibitor.activate(); + } +} + +delegate_keyboard_shortcuts_inhibit!(State); diff --git a/src/wayland/handlers/mod.rs b/src/wayland/handlers/mod.rs index 91c80de5..06590066 100644 --- a/src/wayland/handlers/mod.rs +++ b/src/wayland/handlers/mod.rs @@ -5,6 +5,7 @@ pub mod compositor; pub mod data_device; pub mod dmabuf; pub mod export_dmabuf; +pub mod keyboard_shortcuts_inhibit; pub mod layer_shell; pub mod output; pub mod output_configuration;