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) -> snowcap_api::widget::WidgetDef<Self::Message> {
26            Row::new()
27                .width(snowcap_api::widget::Length::Fixed(1.0))
28                .height(snowcap_api::widget::Length::Fixed(1.0))
29                .into()
30        }
31    }
32
33    /// A handle to an input grab.
34    pub struct InputGrabber(LayerHandle<()>);
35
36    impl InputGrabber {
37        /// Stops this input grab.
38        pub fn stop(&self) {
39            self.0.close();
40        }
41    }
42
43    /// Grabs keyboard input.
44    ///
45    /// All keyboard input will be redirected to this grabber (assuming another exclusive layer
46    /// surface doesn't open). Keybinds will still work.
47    ///
48    /// Don't forget to add a way to close the grabber, or else input will be grabbed forever!
49    ///
50    /// # Examples
51    ///
52    /// ```no_run
53    /// # use pinnacle_api::experimental::input_grab;
54    /// # use pinnacle_api::Keysym;
55    /// input_grab::grab_input(|grabber, key, mods| {
56    ///     if key == Keysym::e {
57    ///         println!("An `e` was pressed!");
58    ///     }
59    ///
60    ///     if key == Keysym::Escape {
61    ///         grabber.stop();
62    ///     }
63    /// });
64    /// ```
65    pub fn grab_input<F>(mut with_input: F)
66    where
67        F: FnMut(InputGrabber, Keysym, Modifiers) + Send + 'static,
68    {
69        let grabber = snowcap_api::layer::new_widget(
70            InputGrab,
71            None,
72            snowcap_api::layer::KeyboardInteractivity::Exclusive,
73            snowcap_api::layer::ExclusiveZone::Respect,
74            snowcap_api::layer::ZLayer::Overlay,
75        );
76
77        let grabber = match grabber {
78            Ok(grabber) => grabber,
79            Err(err) => {
80                println!("ERROR: failed to grab input: {err}");
81                return;
82            }
83        };
84
85        grabber.on_key_press(move |this, key, mods| {
86            with_input(InputGrabber(this), key, mods);
87        });
88    }
89}