feat: enforce focused shortcut inhibition
This commit is contained in:
1 parent
bab371dc97
commit
6dc2a5300e
3 files changed
+84
-2
No files matched your search
@@ -15,6 +15,10 @@ use smithay::{
|
|||||||
fractional_scale::{FractionalScaleHandler, with_fractional_scale},
|
fractional_scale::{FractionalScaleHandler, with_fractional_scale},
|
||||||
idle_inhibit::IdleInhibitHandler,
|
idle_inhibit::IdleInhibitHandler,
|
||||||
idle_notify::{IdleNotifierHandler, IdleNotifierState},
|
idle_notify::{IdleNotifierHandler, IdleNotifierState},
|
||||||
|
keyboard_shortcuts_inhibit::{
|
||||||
|
KeyboardShortcutsInhibitHandler, KeyboardShortcutsInhibitState,
|
||||||
|
KeyboardShortcutsInhibitor, KeyboardShortcutsInhibitorSeat,
|
||||||
|
},
|
||||||
output::OutputHandler,
|
output::OutputHandler,
|
||||||
pointer_constraints::{
|
pointer_constraints::{
|
||||||
PointerConstraint, PointerConstraintsHandler, with_pointer_constraint,
|
PointerConstraint, PointerConstraintsHandler, with_pointer_constraint,
|
||||||
@@ -56,6 +60,18 @@ impl SeatHandler for Ferese {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&WlSurface>) {
|
fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&WlSurface>) {
|
||||||
|
if let Some(inhibitor) = self.active_shortcuts_inhibitor.take()
|
||||||
|
&& inhibitor.is_active()
|
||||||
|
{
|
||||||
|
inhibitor.inactivate();
|
||||||
|
}
|
||||||
|
if let Some(inhibitor) =
|
||||||
|
focused.and_then(|surface| seat.keyboard_shortcuts_inhibitor_for_surface(surface))
|
||||||
|
{
|
||||||
|
inhibitor.activate();
|
||||||
|
self.active_shortcuts_inhibitor = Some(inhibitor);
|
||||||
|
}
|
||||||
|
|
||||||
let client = focused.and_then(|surface| self.display_handle.get_client(surface.id()).ok());
|
let client = focused.and_then(|surface| self.display_handle.get_client(surface.id()).ok());
|
||||||
set_data_device_focus(&self.display_handle, seat, client.clone());
|
set_data_device_focus(&self.display_handle, seat, client.clone());
|
||||||
set_primary_focus(&self.display_handle, seat, client);
|
set_primary_focus(&self.display_handle, seat, client);
|
||||||
@@ -106,6 +122,30 @@ impl IdleInhibitHandler for Ferese {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl KeyboardShortcutsInhibitHandler for Ferese {
|
||||||
|
fn keyboard_shortcuts_inhibit_state(&mut self) -> &mut KeyboardShortcutsInhibitState {
|
||||||
|
&mut self.keyboard_shortcuts_inhibit_state
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_inhibitor(&mut self, inhibitor: KeyboardShortcutsInhibitor) {
|
||||||
|
let focused = self
|
||||||
|
.seat
|
||||||
|
.get_keyboard()
|
||||||
|
.and_then(|keyboard| keyboard.current_focus());
|
||||||
|
|
||||||
|
if focused.as_ref() == Some(inhibitor.wl_surface()) {
|
||||||
|
inhibitor.activate();
|
||||||
|
self.active_shortcuts_inhibitor = Some(inhibitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inhibitor_destroyed(&mut self, inhibitor: KeyboardShortcutsInhibitor) {
|
||||||
|
if self.active_shortcuts_inhibitor.as_ref() == Some(&inhibitor) {
|
||||||
|
self.active_shortcuts_inhibitor = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Ferese {
|
impl Ferese {
|
||||||
pub fn update_fractional_scale(&self, scale: f64) {
|
pub fn update_fractional_scale(&self, scale: f64) {
|
||||||
for window in self.space.elements() {
|
for window in self.space.elements() {
|
||||||
@@ -197,6 +237,7 @@ smithay::delegate_data_device!(Ferese);
|
|||||||
smithay::delegate_fractional_scale!(Ferese);
|
smithay::delegate_fractional_scale!(Ferese);
|
||||||
smithay::delegate_idle_inhibit!(Ferese);
|
smithay::delegate_idle_inhibit!(Ferese);
|
||||||
smithay::delegate_idle_notify!(Ferese);
|
smithay::delegate_idle_notify!(Ferese);
|
||||||
|
smithay::delegate_keyboard_shortcuts_inhibit!(Ferese);
|
||||||
smithay::delegate_layer_shell!(Ferese);
|
smithay::delegate_layer_shell!(Ferese);
|
||||||
smithay::delegate_output!(Ferese);
|
smithay::delegate_output!(Ferese);
|
||||||
smithay::delegate_pointer_constraints!(Ferese);
|
smithay::delegate_pointer_constraints!(Ferese);
|
||||||
|
|||||||
+32
-2
@@ -9,7 +9,10 @@ use smithay::{
|
|||||||
},
|
},
|
||||||
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||||
utils::{Logical, Point, SERIAL_COUNTER, Serial},
|
utils::{Logical, Point, SERIAL_COUNTER, Serial},
|
||||||
wayland::pointer_constraints::{PointerConstraint, with_pointer_constraint},
|
wayland::{
|
||||||
|
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat,
|
||||||
|
pointer_constraints::{PointerConstraint, with_pointer_constraint},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Ferese;
|
use crate::Ferese;
|
||||||
@@ -38,6 +41,22 @@ impl Ferese {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let symbol = keysym.modified_sym().raw();
|
let symbol = keysym.modified_sym().raw();
|
||||||
|
if emergency_shortcut_escape(symbol, modifiers.ctrl, modifiers.alt) {
|
||||||
|
if state == KeyState::Pressed {
|
||||||
|
data.intercepted_keys.insert(keycode);
|
||||||
|
|
||||||
|
if let Some(inhibitor) = data.active_shortcuts_inhibitor.take() {
|
||||||
|
inhibitor.inactivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FilterResult::Intercept(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.seat.keyboard_shortcuts_inhibited() {
|
||||||
|
return FilterResult::Forward;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(vt) = virtual_terminal(
|
if let Some(vt) = virtual_terminal(
|
||||||
symbol,
|
symbol,
|
||||||
modifiers.ctrl,
|
modifiers.ctrl,
|
||||||
@@ -383,9 +402,20 @@ fn virtual_terminal(symbol: u32, ctrl: bool, alt: bool, direct: bool) -> Option<
|
|||||||
.then_some((symbol - keysyms::KEY_F1 + 1) as i32)
|
.then_some((symbol - keysyms::KEY_F1 + 1) as i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emergency_shortcut_escape(symbol: u32, ctrl: bool, alt: bool) -> bool {
|
||||||
|
ctrl && alt && symbol == keysyms::KEY_Escape
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::virtual_terminal;
|
use super::{emergency_shortcut_escape, virtual_terminal};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn emergency_escape_requires_control_alt_escape() {
|
||||||
|
assert!(emergency_shortcut_escape(keysyms::KEY_Escape, true, true));
|
||||||
|
assert!(!emergency_shortcut_escape(keysyms::KEY_Escape, true, false));
|
||||||
|
assert!(!emergency_shortcut_escape(keysyms::KEY_q, true, true));
|
||||||
|
}
|
||||||
use smithay::input::keyboard::keysyms;
|
use smithay::input::keyboard::keysyms;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ use smithay::{
|
|||||||
fractional_scale::FractionalScaleManagerState,
|
fractional_scale::FractionalScaleManagerState,
|
||||||
idle_inhibit::IdleInhibitManagerState,
|
idle_inhibit::IdleInhibitManagerState,
|
||||||
idle_notify::IdleNotifierState,
|
idle_notify::IdleNotifierState,
|
||||||
|
keyboard_shortcuts_inhibit::{KeyboardShortcutsInhibitState, KeyboardShortcutsInhibitor},
|
||||||
output::OutputManagerState,
|
output::OutputManagerState,
|
||||||
pointer_constraints::PointerConstraintsState,
|
pointer_constraints::PointerConstraintsState,
|
||||||
presentation::PresentationState,
|
presentation::PresentationState,
|
||||||
@@ -70,6 +71,7 @@ pub struct Ferese {
|
|||||||
pub(crate) named_cursors: HashMap<CursorIcon, crate::cursor::NamedCursor>,
|
pub(crate) named_cursors: HashMap<CursorIcon, crate::cursor::NamedCursor>,
|
||||||
pub intercepted_keys: HashSet<smithay::input::keyboard::Keycode>,
|
pub intercepted_keys: HashSet<smithay::input::keyboard::Keycode>,
|
||||||
pub idle_inhibitors: HashMap<WlSurface, usize>,
|
pub idle_inhibitors: HashMap<WlSurface, usize>,
|
||||||
|
pub active_shortcuts_inhibitor: Option<KeyboardShortcutsInhibitor>,
|
||||||
pub direct_backend: Option<crate::backends::direct::DirectBackendState>,
|
pub direct_backend: Option<crate::backends::direct::DirectBackendState>,
|
||||||
next_window_id: u64,
|
next_window_id: u64,
|
||||||
last_animation_tick: Instant,
|
last_animation_tick: Instant,
|
||||||
@@ -82,6 +84,7 @@ pub struct Ferese {
|
|||||||
pub fractional_scale_state: FractionalScaleManagerState,
|
pub fractional_scale_state: FractionalScaleManagerState,
|
||||||
pub idle_inhibit_state: IdleInhibitManagerState,
|
pub idle_inhibit_state: IdleInhibitManagerState,
|
||||||
pub idle_notifier_state: IdleNotifierState<Self>,
|
pub idle_notifier_state: IdleNotifierState<Self>,
|
||||||
|
pub keyboard_shortcuts_inhibit_state: KeyboardShortcutsInhibitState,
|
||||||
pub output_manager_state: OutputManagerState,
|
pub output_manager_state: OutputManagerState,
|
||||||
pub pointer_constraints_state: PointerConstraintsState,
|
pub pointer_constraints_state: PointerConstraintsState,
|
||||||
pub presentation_state: PresentationState,
|
pub presentation_state: PresentationState,
|
||||||
@@ -110,6 +113,8 @@ impl Ferese {
|
|||||||
let fractional_scale_state = FractionalScaleManagerState::new::<Self>(&display_handle);
|
let fractional_scale_state = FractionalScaleManagerState::new::<Self>(&display_handle);
|
||||||
let idle_inhibit_state = IdleInhibitManagerState::new::<Self>(&display_handle);
|
let idle_inhibit_state = IdleInhibitManagerState::new::<Self>(&display_handle);
|
||||||
let idle_notifier_state = IdleNotifierState::new(&display_handle, event_loop.handle());
|
let idle_notifier_state = IdleNotifierState::new(&display_handle, event_loop.handle());
|
||||||
|
let keyboard_shortcuts_inhibit_state =
|
||||||
|
KeyboardShortcutsInhibitState::new::<Self>(&display_handle);
|
||||||
let shm_state = ShmState::new::<Self>(&display_handle, Vec::new());
|
let shm_state = ShmState::new::<Self>(&display_handle, Vec::new());
|
||||||
let single_pixel_buffer_state = SinglePixelBufferState::new::<Self>(&display_handle);
|
let single_pixel_buffer_state = SinglePixelBufferState::new::<Self>(&display_handle);
|
||||||
let output_manager_state = OutputManagerState::new_with_xdg_output::<Self>(&display_handle);
|
let output_manager_state = OutputManagerState::new_with_xdg_output::<Self>(&display_handle);
|
||||||
@@ -149,6 +154,7 @@ impl Ferese {
|
|||||||
named_cursors,
|
named_cursors,
|
||||||
intercepted_keys: HashSet::new(),
|
intercepted_keys: HashSet::new(),
|
||||||
idle_inhibitors: HashMap::new(),
|
idle_inhibitors: HashMap::new(),
|
||||||
|
active_shortcuts_inhibitor: None,
|
||||||
direct_backend: None,
|
direct_backend: None,
|
||||||
next_window_id: 1,
|
next_window_id: 1,
|
||||||
last_animation_tick: start_time,
|
last_animation_tick: start_time,
|
||||||
@@ -161,6 +167,7 @@ impl Ferese {
|
|||||||
fractional_scale_state,
|
fractional_scale_state,
|
||||||
idle_inhibit_state,
|
idle_inhibit_state,
|
||||||
idle_notifier_state,
|
idle_notifier_state,
|
||||||
|
keyboard_shortcuts_inhibit_state,
|
||||||
output_manager_state,
|
output_manager_state,
|
||||||
pointer_constraints_state,
|
pointer_constraints_state,
|
||||||
presentation_state,
|
presentation_state,
|
||||||
@@ -346,6 +353,10 @@ impl Ferese {
|
|||||||
}
|
}
|
||||||
self.space.map_element(window, (0, 0), focus_new_window);
|
self.space.map_element(window, (0, 0), focus_new_window);
|
||||||
self.relayout();
|
self.relayout();
|
||||||
|
|
||||||
|
if focus_new_window {
|
||||||
|
self.restore_keyboard_focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_transient_window(&mut self, window: Window, parent: WindowId) {
|
pub fn add_transient_window(&mut self, window: Window, parent: WindowId) {
|
||||||
|
|||||||
Reference in new issue
Block a user