diff --git a/src/seat/keyboard_filter.rs b/src/seat/keyboard_filter.rs new file mode 100644 index 000000000..69cfd2490 --- /dev/null +++ b/src/seat/keyboard_filter.rs @@ -0,0 +1,141 @@ +/*! This implements support for the experimental xx-keyboard-filter-v1 protocol. + */ + +pub use protocol::xx_keyboard_filter_manager_v1::XxKeyboardFilterManagerV1; +pub use protocol::xx_keyboard_filter_v1::XxKeyboardFilterV1; +use wayland_client::globals::{BindError, GlobalList}; +use wayland_client::protocol::wl_keyboard::WlKeyboard; +use wayland_client::protocol::wl_surface::WlSurface; +use wayland_client::{Connection, Dispatch, QueueHandle}; +use wayland_protocols_experimental::keyboard_filter::v3::client::{ + self as protocol, xx_keyboard_filter_manager_v1, xx_keyboard_filter_v1, +}; + +use crate::globals::GlobalData; + +#[derive(Debug)] +pub struct KeyboardFilterManager { + manager: XxKeyboardFilterManagerV1, +} + +impl KeyboardFilterManager { + /// Bind the input_method global, if it exists + pub fn bind(globals: &GlobalList, qh: &QueueHandle) -> Result + where + D: Dispatch + 'static, + { + let manager = globals.bind(qh, 1..=1, GlobalData)?; + Ok(Self { manager }) + } + + /// Request a new keyboard_filter object associated with a given + /// keyboard, input method, and surface. + /// + /// Surface can be any surface, even a dummy one. + /// + /// May cause a protocol error if there's a bound keyboard already. + pub fn bind_to_input_method( + &self, + qh: &QueueHandle, + keyboard: &WlKeyboard, + input_method: &super::input_method_v3::XxInputMethodV1, + surface: &WlSurface, + ) -> KeyboardFilter + where + D: Dispatch + 'static, + { + KeyboardFilter(self.manager.bind_to_input_method(keyboard, input_method, surface, qh, ())) + } +} + +impl Dispatch for KeyboardFilterManager +where + D: Dispatch, +{ + fn event( + _data: &mut D, + _manager: &XxKeyboardFilterManagerV1, + _event: xx_keyboard_filter_manager_v1::Event, + _: &GlobalData, + _conn: &Connection, + _qh: &QueueHandle, + ) { + unreachable!("Filter manager receives no events") + } +} + +#[derive(Debug)] +pub struct KeyboardFilter(XxKeyboardFilterV1); + +impl KeyboardFilter { + /// May cause a protocol error if there's no bound keyboard. + pub fn unbind(&self) { + self.0.unbind(); + } + + /// May cause a protocol error on invalid serial. + pub fn filter(&self, serial: u32, action: xx_keyboard_filter_v1::FilterAction) { + self.0.filter(serial, action); + } +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct KeyboardVersion(pub u32); + +impl Dispatch for KeyboardFilter +where + D: Dispatch, +{ + fn event( + _data: &mut D, + _keyboard: &XxKeyboardFilterV1, + _event: xx_keyboard_filter_v1::Event, + _: &(), + _conn: &Connection, + _qh: &QueueHandle, + ) { + unreachable!("Filter receives no events") + } +} + +#[macro_export] +macro_rules! delegate_keyboard_filter_v1 { + ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { + $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + $crate::reexports::protocols_experimental::keyboard_filter::v3::client::xx_keyboard_filter_manager_v1::XxKeyboardFilterManagerV1: $crate::globals::GlobalData + ] => $crate::seat::keyboard_filter::KeyboardFilterManager); + $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + $crate::reexports::protocols_experimental::keyboard_filter::v3::client::xx_keyboard_filter_v1::XxKeyboardFilterV1: () + ] => $crate::seat::keyboard_filter::KeyboardFilter); + }; +} + +#[cfg(test)] +mod test { + use super::*; + + struct Handler {} + + delegate_keyboard_filter_v1!(Handler); + + fn assert_is_manager_delegate() + where + T: wayland_client::Dispatch< + protocol::xx_keyboard_filter_manager_v1::XxKeyboardFilterManagerV1, + crate::globals::GlobalData, + >, + { + } + + fn assert_is_delegate() + where + T: wayland_client::Dispatch, + { + } + + #[test] + fn test_valid_assignment() { + assert_is_manager_delegate::(); + assert_is_delegate::(); + } +} diff --git a/src/seat/mod.rs b/src/seat/mod.rs index 4c94b9061..82764025c 100644 --- a/src/seat/mod.rs +++ b/src/seat/mod.rs @@ -24,6 +24,7 @@ pub mod input_method; pub mod input_method_v3; #[cfg(feature = "xkbcommon")] pub mod keyboard; +pub mod keyboard_filter; pub mod pointer; pub mod pointer_constraints; pub mod relative_pointer;