pinnacle_api/
experimental.rs

1//! Experimental APIs.
2//!
3//! IMPORTANT: These are unstable and may change at any moment.
4
5#[cfg(feature = "snowcap")]
6pub use snowcap_api;
7
8/// Input grabbing.
9#[cfg(feature = "snowcap")]
10pub mod input_grab {
11    use snowcap_api::{
12        input::Modifiers,
13        layer::LayerHandle,
14        widget::{Program, row::Row},
15    };
16    use xkbcommon::xkb::Keysym;
17
18    struct InputGrab;
19
20    impl Program for InputGrab {
21        type Message = ();
22
23        fn update(&mut self, _msg: Self::Message) {}
24
25        fn view(&self) -> Option<snowcap_api::widget::WidgetDef<Self::Message>> {
26            Some(
27                Row::new()
28                    .width(snowcap_api::widget::Length::Fixed(1.0))
29                    .height(snowcap_api::widget::Length::Fixed(1.0))
30                    .into(),
31            )
32        }
33    }
34
35    /// A handle to an input grab.
36    pub struct InputGrabber(LayerHandle<()>);
37
38    impl InputGrabber {
39        /// Stops this input grab.
40        pub fn stop(&self) {
41            self.0.close();
42        }
43    }
44
45    /// Grabs keyboard input.
46    ///
47    /// All keyboard input will be redirected to this grabber (assuming another exclusive layer
48    /// surface doesn't open). Keybinds will still work.
49    ///
50    /// Don't forget to add a way to close the grabber, or else input will be grabbed forever!
51    ///
52    /// # Examples
53    ///
54    /// ```no_run
55    /// # use pinnacle_api::experimental::input_grab;
56    /// # use pinnacle_api::Keysym;
57    /// input_grab::grab_input(|grabber, key, mods| {
58    ///     if key == Keysym::e {
59    ///         println!("An `e` was pressed!");
60    ///     }
61    ///
62    ///     if key == Keysym::Escape {
63    ///         grabber.stop();
64    ///     }
65    /// });
66    /// ```
67    pub fn grab_input<F>(mut with_input: F)
68    where
69        F: FnMut(InputGrabber, Keysym, Modifiers) + Send + 'static,
70    {
71        let grabber = snowcap_api::layer::new_widget(
72            InputGrab,
73            None,
74            snowcap_api::layer::KeyboardInteractivity::Exclusive,
75            snowcap_api::layer::ExclusiveZone::Respect,
76            snowcap_api::layer::ZLayer::Overlay,
77        );
78
79        let grabber = match grabber {
80            Ok(grabber) => grabber,
81            Err(err) => {
82                println!("ERROR: failed to grab input: {err}");
83                return;
84            }
85        };
86
87        grabber.on_key_press(move |this, key, mods| {
88            with_input(InputGrabber(this), key, mods);
89        });
90    }
91}