winit/platform_impl/linux/wayland/seat/keyboard/
mod.rs

1//! Wayland keyboard handling.
2
3use std::cell::RefCell;
4use std::rc::Rc;
5
6use sctk::reexports::client::protocol::wl_keyboard::WlKeyboard;
7use sctk::reexports::client::protocol::wl_seat::WlSeat;
8use sctk::reexports::client::Attached;
9
10use sctk::reexports::calloop::{LoopHandle, Source};
11
12use sctk::seat::keyboard::{self, RepeatSource};
13
14use crate::event::ModifiersState;
15use crate::platform_impl::wayland::event_loop::WinitState;
16use crate::platform_impl::wayland::WindowId;
17
18mod handlers;
19mod keymap;
20
21pub(crate) struct Keyboard {
22    pub keyboard: WlKeyboard,
23
24    /// The source for repeat keys.
25    pub repeat_source: Option<Source<RepeatSource>>,
26
27    /// LoopHandle to drop `RepeatSource`, when dropping the keyboard.
28    pub loop_handle: LoopHandle<WinitState>,
29}
30
31impl Keyboard {
32    pub fn new(
33        seat: &Attached<WlSeat>,
34        loop_handle: LoopHandle<WinitState>,
35        modifiers_state: Rc<RefCell<ModifiersState>>,
36    ) -> Option<Self> {
37        let mut inner = KeyboardInner::new(modifiers_state);
38        let keyboard_data = keyboard::map_keyboard_repeat(
39            loop_handle.clone(),
40            &seat,
41            None,
42            keyboard::RepeatKind::System,
43            move |event, _, mut dispatch_data| {
44                let winit_state = dispatch_data.get::<WinitState>().unwrap();
45                handlers::handle_keyboard(event, &mut inner, winit_state);
46            },
47        );
48
49        let (keyboard, repeat_source) = keyboard_data.ok()?;
50
51        Some(Self {
52            keyboard,
53            loop_handle,
54            repeat_source: Some(repeat_source),
55        })
56    }
57}
58
59impl Drop for Keyboard {
60    fn drop(&mut self) {
61        if self.keyboard.as_ref().version() >= 3 {
62            self.keyboard.release();
63        }
64
65        if let Some(repeat_source) = self.repeat_source.take() {
66            self.loop_handle.remove(repeat_source);
67        }
68    }
69}
70
71struct KeyboardInner {
72    /// Currently focused surface.
73    target_window_id: Option<WindowId>,
74
75    /// A pending state of modifiers.
76    ///
77    /// This state is getting set if we've got a modifiers update
78    /// before `Enter` event, which shouldn't happen in general, however
79    /// some compositors are still doing so.
80    pending_modifers_state: Option<ModifiersState>,
81
82    /// Current state of modifiers keys.
83    modifiers_state: Rc<RefCell<ModifiersState>>,
84}
85
86impl KeyboardInner {
87    fn new(modifiers_state: Rc<RefCell<ModifiersState>>) -> Self {
88        Self {
89            target_window_id: None,
90            pending_modifers_state: None,
91            modifiers_state,
92        }
93    }
94}
95
96impl From<keyboard::ModifiersState> for ModifiersState {
97    fn from(mods: keyboard::ModifiersState) -> ModifiersState {
98        let mut wl_mods = ModifiersState::empty();
99        wl_mods.set(ModifiersState::SHIFT, mods.shift);
100        wl_mods.set(ModifiersState::CTRL, mods.ctrl);
101        wl_mods.set(ModifiersState::ALT, mods.alt);
102        wl_mods.set(ModifiersState::LOGO, mods.logo);
103        wl_mods
104    }
105}