Skip to main content

gtk4/
event_controller_key.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{boxed::Box as Box_, mem::transmute};
4
5use gdk::Key;
6use glib::{SignalHandlerId, signal::connect_raw, translate::*};
7
8use crate::{EventControllerKey, ffi, prelude::*};
9
10impl EventControllerKey {
11    /// Emitted whenever a key is pressed.
12    /// ## `keyval`
13    /// the pressed key.
14    /// ## `keycode`
15    /// the raw code of the pressed key.
16    /// ## `state`
17    /// the bitmask, representing the state of modifier keys and pointer buttons.
18    ///
19    /// # Returns
20    ///
21    /// [`true`] if the key press was handled, [`false`] otherwise.
22    pub fn connect_key_pressed<
23        F: Fn(&EventControllerKey, Key, u32, gdk::ModifierType) -> glib::Propagation + 'static,
24    >(
25        &self,
26        f: F,
27    ) -> SignalHandlerId {
28        unsafe extern "C" fn key_pressed_trampoline<
29            F: Fn(&EventControllerKey, Key, u32, gdk::ModifierType) -> glib::Propagation + 'static,
30        >(
31            this: *mut ffi::GtkEventControllerKey,
32            keyval: libc::c_uint,
33            keycode: libc::c_uint,
34            state: gdk::ffi::GdkModifierType,
35            f: glib::ffi::gpointer,
36        ) -> glib::ffi::gboolean {
37            unsafe {
38                let f: &F = &*(f as *const F);
39                f(
40                    &from_glib_borrow(this),
41                    from_glib(keyval),
42                    keycode,
43                    from_glib(state),
44                )
45                .into_glib()
46            }
47        }
48        unsafe {
49            let f: Box_<F> = Box_::new(f);
50            connect_raw(
51                self.as_ptr() as *mut _,
52                c"key-pressed".as_ptr() as *const _,
53                Some(transmute::<*const (), unsafe extern "C" fn()>(
54                    key_pressed_trampoline::<F> as *const (),
55                )),
56                Box_::into_raw(f),
57            )
58        }
59    }
60
61    /// Emitted whenever a key is released.
62    /// ## `keyval`
63    /// the released key.
64    /// ## `keycode`
65    /// the raw code of the released key.
66    /// ## `state`
67    /// the bitmask, representing the state of modifier keys and pointer buttons.
68    pub fn connect_key_released<
69        F: Fn(&EventControllerKey, Key, u32, gdk::ModifierType) + 'static,
70    >(
71        &self,
72        f: F,
73    ) -> SignalHandlerId {
74        unsafe extern "C" fn key_released_trampoline<
75            F: Fn(&EventControllerKey, Key, u32, gdk::ModifierType) + 'static,
76        >(
77            this: *mut ffi::GtkEventControllerKey,
78            keyval: libc::c_uint,
79            keycode: libc::c_uint,
80            state: gdk::ffi::GdkModifierType,
81            f: glib::ffi::gpointer,
82        ) {
83            unsafe {
84                let f: &F = &*(f as *const F);
85                f(
86                    &from_glib_borrow(this),
87                    from_glib(keyval),
88                    keycode,
89                    from_glib(state),
90                )
91            }
92        }
93        unsafe {
94            let f: Box_<F> = Box_::new(f);
95            connect_raw(
96                self.as_ptr() as *mut _,
97                c"key-released".as_ptr() as *const _,
98                Some(transmute::<*const (), unsafe extern "C" fn()>(
99                    key_released_trampoline::<F> as *const (),
100                )),
101                Box_::into_raw(f),
102            )
103        }
104    }
105}