gdk/
event.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4use libc::c_void;
5use std::fmt;
6use std::mem;
7use std::ptr;
8
9use crate::AxisUse;
10use crate::Device;
11use crate::DeviceTool;
12use crate::EventSequence;
13use crate::EventType;
14use crate::ModifierType;
15use crate::Screen;
16use crate::ScrollDirection;
17use crate::Seat;
18use crate::Window;
19
20glib::wrapper! {
21    /// A generic GDK event.
22    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
23    #[doc(alias = "GdkEvent")]
24    pub struct Event(Boxed<ffi::GdkEvent>);
25
26    match fn {
27        copy => |ptr| ffi::gdk_event_copy(ptr),
28        free => |ptr| ffi::gdk_event_free(ptr),
29        type_ => || ffi::gdk_event_get_type(),
30    }
31}
32
33impl Event {
34    /// Creates a new event.
35    #[doc(alias = "gdk_event_new")]
36    pub fn new(type_: EventType) -> Event {
37        assert_initialized_main_thread!();
38        unsafe { from_glib_none(ffi::gdk_event_new(type_.into_glib())) }
39    }
40
41    #[doc(alias = "gdk_event_get")]
42    pub fn get() -> Option<Event> {
43        assert_initialized_main_thread!();
44        unsafe { from_glib_none(ffi::gdk_event_get()) }
45    }
46
47    #[doc(alias = "gdk_event_put")]
48    pub fn put(&self) {
49        unsafe { ffi::gdk_event_put(self.to_glib_none().0) }
50    }
51
52    /// Set the event handler.
53    ///
54    /// The callback `handler` is called for each event. If `None`, event
55    /// handling is disabled.
56    #[doc(alias = "gdk_event_handler_set")]
57    pub fn set_handler<F: Fn(&mut Event) + 'static>(handler: Option<F>) {
58        assert_initialized_main_thread!();
59        unsafe extern "C" fn event_handler_trampoline<F: Fn(&mut Event) + 'static>(
60            event: *mut ffi::GdkEvent,
61            ptr: glib::ffi::gpointer,
62        ) {
63            if !ptr.is_null() {
64                let f: &F = &*(ptr as *mut _);
65                let mut event = from_glib_none(event);
66                f(&mut event)
67            }
68        }
69        unsafe extern "C" fn event_handler_destroy<F: Fn(&mut Event) + 'static>(
70            ptr: glib::ffi::gpointer,
71        ) {
72            if !ptr.is_null() {
73                // convert back to Box and free
74                let _boxed: Box<F> = Box::from_raw(ptr as *mut _);
75            }
76        }
77        if let Some(handler) = handler {
78            // allocate and convert to target type
79            // double box to reduce a fat pointer to a simple pointer
80            let boxed: Box<F> = Box::new(handler);
81            let ptr: *mut c_void = Box::into_raw(boxed) as *mut _;
82            unsafe {
83                ffi::gdk_event_handler_set(
84                    Some(event_handler_trampoline::<F>),
85                    ptr,
86                    Some(event_handler_destroy::<F>),
87                )
88            }
89        } else {
90            unsafe { ffi::gdk_event_handler_set(None, ptr::null_mut(), None) }
91        }
92    }
93
94    #[doc(alias = "gdk_event_get_axis")]
95    #[doc(alias = "get_axis")]
96    pub fn axis(&self, axis_use: AxisUse) -> Option<f64> {
97        let mut value = 0f64;
98        if unsafe {
99            from_glib(ffi::gdk_event_get_axis(
100                self.to_glib_none().0,
101                axis_use.into_glib(),
102                &mut value,
103            ))
104        } {
105            Some(value)
106        } else {
107            None
108        }
109    }
110
111    #[doc(alias = "gdk_event_get_button")]
112    #[doc(alias = "get_button")]
113    pub fn button(&self) -> Option<u32> {
114        let mut button = 0u32;
115        if unsafe {
116            from_glib(ffi::gdk_event_get_button(
117                self.to_glib_none().0,
118                &mut button,
119            ))
120        } {
121            Some(button)
122        } else {
123            None
124        }
125    }
126
127    #[doc(alias = "gdk_event_get_click_count")]
128    #[doc(alias = "get_click_count")]
129    pub fn click_count(&self) -> Option<u32> {
130        let mut click_count = 0u32;
131        if unsafe {
132            from_glib(ffi::gdk_event_get_click_count(
133                self.to_glib_none().0,
134                &mut click_count,
135            ))
136        } {
137            Some(click_count)
138        } else {
139            None
140        }
141    }
142
143    #[doc(alias = "gdk_event_get_coords")]
144    #[doc(alias = "get_coords")]
145    pub fn coords(&self) -> Option<(f64, f64)> {
146        let mut x_win = 0f64;
147        let mut y_win = 0f64;
148        if unsafe {
149            from_glib(ffi::gdk_event_get_coords(
150                self.to_glib_none().0,
151                &mut x_win,
152                &mut y_win,
153            ))
154        } {
155            Some((x_win, y_win))
156        } else {
157            None
158        }
159    }
160
161    #[doc(alias = "gdk_event_get_keycode")]
162    #[doc(alias = "get_keycode")]
163    pub fn keycode(&self) -> Option<u16> {
164        let mut keycode = 0u16;
165        if unsafe {
166            from_glib(ffi::gdk_event_get_keycode(
167                self.to_glib_none().0,
168                &mut keycode,
169            ))
170        } {
171            Some(keycode)
172        } else {
173            None
174        }
175    }
176
177    #[doc(alias = "gdk_event_get_keyval")]
178    #[doc(alias = "get_keyval")]
179    pub fn keyval(&self) -> Option<u32> {
180        let mut keyval = 0u32;
181        if unsafe {
182            from_glib(ffi::gdk_event_get_keyval(
183                self.to_glib_none().0,
184                &mut keyval,
185            ))
186        } {
187            Some(keyval)
188        } else {
189            None
190        }
191    }
192
193    #[doc(alias = "gdk_event_get_root_coords")]
194    #[doc(alias = "get_root_coords")]
195    pub fn root_coords(&self) -> Option<(f64, f64)> {
196        let mut x_root = 0f64;
197        let mut y_root = 0f64;
198        if unsafe {
199            from_glib(ffi::gdk_event_get_root_coords(
200                self.to_glib_none().0,
201                &mut x_root,
202                &mut y_root,
203            ))
204        } {
205            Some((x_root, y_root))
206        } else {
207            None
208        }
209    }
210
211    #[doc(alias = "gdk_event_get_scroll_direction")]
212    #[doc(alias = "get_scroll_direction")]
213    pub fn scroll_direction(&self) -> Option<ScrollDirection> {
214        unsafe {
215            let mut direction = mem::MaybeUninit::uninit();
216            if from_glib(ffi::gdk_event_get_scroll_direction(
217                self.to_glib_none().0,
218                direction.as_mut_ptr(),
219            )) {
220                Some(from_glib(direction.assume_init()))
221            } else {
222                None
223            }
224        }
225    }
226
227    #[doc(alias = "gdk_event_get_scroll_deltas")]
228    #[doc(alias = "get_scroll_deltas")]
229    pub fn scroll_deltas(&self) -> Option<(f64, f64)> {
230        let mut delta_x = 0f64;
231        let mut delta_y = 0f64;
232        if unsafe {
233            from_glib(ffi::gdk_event_get_scroll_deltas(
234                self.to_glib_none().0,
235                &mut delta_x,
236                &mut delta_y,
237            ))
238        } {
239            Some((delta_x, delta_y))
240        } else {
241            None
242        }
243    }
244
245    #[doc(alias = "gdk_event_is_scroll_stop_event")]
246    pub fn is_scroll_stop_event(&self) -> bool {
247        unsafe { from_glib(ffi::gdk_event_is_scroll_stop_event(self.to_glib_none().0)) }
248    }
249
250    #[doc(alias = "gdk_event_get_state")]
251    #[doc(alias = "get_state")]
252    pub fn state(&self) -> Option<ModifierType> {
253        unsafe {
254            let mut state = mem::MaybeUninit::uninit();
255            if from_glib(ffi::gdk_event_get_state(
256                self.to_glib_none().0,
257                state.as_mut_ptr(),
258            )) {
259                Some(from_glib(state.assume_init() as _))
260            } else {
261                None
262            }
263        }
264    }
265
266    #[doc(alias = "gdk_event_get_time")]
267    #[doc(alias = "get_time")]
268    pub fn time(&self) -> u32 {
269        unsafe { ffi::gdk_event_get_time(self.to_glib_none().0) }
270    }
271
272    /// Returns the associated `Window` if applicable.
273    #[doc(alias = "gdk_event_get_window")]
274    #[doc(alias = "get_window")]
275    pub fn window(&self) -> Option<Window> {
276        unsafe { from_glib_none(ffi::gdk_event_get_window(self.to_glib_none().0)) }
277    }
278
279    #[doc(alias = "gdk_event_get_event_sequence")]
280    #[doc(alias = "get_event_sequence")]
281    pub fn event_sequence(&self) -> Option<EventSequence> {
282        unsafe { from_glib_none(ffi::gdk_event_get_event_sequence(self.to_glib_none().0)) }
283    }
284
285    #[doc(alias = "gdk_event_triggers_context_menu")]
286    pub fn triggers_context_menu(&self) -> bool {
287        unsafe { from_glib(ffi::gdk_event_triggers_context_menu(self.to_glib_none().0)) }
288    }
289
290    #[doc(alias = "gdk_event_get_seat")]
291    #[doc(alias = "get_seat")]
292    pub fn seat(&self) -> Option<Seat> {
293        unsafe { from_glib_none(ffi::gdk_event_get_seat(self.to_glib_none().0)) }
294    }
295
296    #[doc(alias = "gdk_event_get_scancode")]
297    #[doc(alias = "get_scancode")]
298    pub fn scancode(&self) -> i32 {
299        unsafe { ffi::gdk_event_get_scancode(mut_override(self.to_glib_none().0)) }
300    }
301
302    #[doc(alias = "gdk_event_get_pointer_emulated")]
303    #[doc(alias = "get_pointer_emulated")]
304    pub fn is_pointer_emulated(&self) -> bool {
305        unsafe {
306            from_glib(ffi::gdk_event_get_pointer_emulated(mut_override(
307                self.to_glib_none().0,
308            )))
309        }
310    }
311
312    #[doc(alias = "gdk_event_set_screen")]
313    pub fn set_screen(&mut self, screen: Option<&Screen>) {
314        unsafe { ffi::gdk_event_set_screen(self.to_glib_none_mut().0, screen.to_glib_none().0) }
315    }
316
317    #[doc(alias = "gdk_event_get_screen")]
318    #[doc(alias = "get_screen")]
319    pub fn screen(&self) -> Option<Screen> {
320        unsafe { from_glib_none(ffi::gdk_event_get_screen(self.to_glib_none().0)) }
321    }
322
323    #[doc(alias = "gdk_event_set_device")]
324    pub fn set_device(&mut self, device: Option<&Device>) {
325        unsafe { ffi::gdk_event_set_device(self.to_glib_none_mut().0, device.to_glib_none().0) }
326    }
327
328    #[doc(alias = "gdk_event_get_device")]
329    #[doc(alias = "get_device")]
330    pub fn device(&self) -> Option<Device> {
331        unsafe { from_glib_none(ffi::gdk_event_get_device(self.to_glib_none().0)) }
332    }
333
334    #[doc(alias = "gdk_event_set_source_device")]
335    pub fn set_source_device(&mut self, device: Option<&Device>) {
336        unsafe {
337            ffi::gdk_event_set_source_device(self.to_glib_none_mut().0, device.to_glib_none().0)
338        }
339    }
340
341    #[doc(alias = "gdk_event_get_source_device")]
342    #[doc(alias = "get_source_device")]
343    pub fn source_device(&self) -> Option<Device> {
344        unsafe { from_glib_none(ffi::gdk_event_get_source_device(self.to_glib_none().0)) }
345    }
346
347    #[doc(alias = "gdk_event_set_device_tool")]
348    pub fn set_device_tool(&mut self, device: Option<&DeviceTool>) {
349        unsafe {
350            ffi::gdk_event_set_device_tool(self.to_glib_none_mut().0, device.to_glib_none().0)
351        }
352    }
353
354    #[doc(alias = "gdk_event_get_device_tool")]
355    #[doc(alias = "get_device_tool")]
356    pub fn device_tool(&self) -> Option<DeviceTool> {
357        unsafe { from_glib_none(ffi::gdk_event_get_device_tool(self.to_glib_none().0)) }
358    }
359
360    /// Returns the event type.
361    #[doc(alias = "get_event_type")]
362    pub fn event_type(&self) -> EventType {
363        unsafe { from_glib(self.as_ref().type_) }
364    }
365
366    /// Returns whether the event was sent explicitly.
367    #[allow(clippy::cast_lossless)]
368    #[doc(alias = "get_send_event")]
369    pub fn is_send_event(&self) -> bool {
370        unsafe { from_glib(self.as_ref().send_event as i32) }
371    }
372
373    /// Returns `true` if the event type matches `T`.
374    pub fn is<T: FromEvent>(&self) -> bool {
375        T::is(self)
376    }
377
378    /// Tries to downcast to a specific event type.
379    pub fn downcast<T: FromEvent>(self) -> Result<T, Self> {
380        T::from(self)
381    }
382
383    /// Tries to downcast to a specific event type.
384    pub fn downcast_ref<T: FromEvent>(&self) -> Option<&T> {
385        if T::is(self) {
386            unsafe { Some(&*(self as *const _ as *const _)) }
387        } else {
388            None
389        }
390    }
391
392    /// Tries to downcast to a specific event type.
393    pub fn downcast_mut<T: FromEvent>(&mut self) -> Option<&mut T> {
394        if T::is(self) {
395            unsafe { Some(&mut *(self as *mut _ as *mut _)) }
396        } else {
397            None
398        }
399    }
400}
401
402impl fmt::Debug for Event {
403    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
404        fmt.debug_struct("Event")
405            .field("inner", &self.inner)
406            .field("type", &self.event_type())
407            .finish()
408    }
409}
410
411/// A helper trait implemented by all event subtypes.
412pub unsafe trait FromEvent: Sized {
413    fn is(ev: &Event) -> bool;
414    fn from(ev: Event) -> Result<Self, Event>;
415}
416
417macro_rules! event_wrapper {
418    ($name:ident, $ffi_name:ident) => {
419        impl<'a> ToGlibPtr<'a, *const ::ffi::$ffi_name> for $name {
420            type Storage = &'a Self;
421
422            #[inline]
423            fn to_glib_none(&'a self) -> Stash<'a, *const ::ffi::$ffi_name, Self> {
424                let ptr =
425                    <$crate::Event as ToGlibPtr<*const ::ffi::GdkEvent>>::to_glib_none(&*self).0;
426                Stash(ptr as *const ::ffi::$ffi_name, self)
427            }
428        }
429
430        impl<'a> ToGlibPtrMut<'a, *mut ::ffi::$ffi_name> for $name {
431            type Storage = &'a mut Self;
432
433            #[inline]
434            fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ::ffi::$ffi_name, Self> {
435                let ptr = <$crate::Event as ToGlibPtrMut<*mut ::ffi::GdkEvent>>::to_glib_none_mut(
436                    &mut *self,
437                )
438                .0;
439                StashMut(ptr as *mut ::ffi::$ffi_name, self)
440            }
441        }
442
443        impl FromGlibPtrNone<*mut ::ffi::$ffi_name> for $name {
444            #[inline]
445            unsafe fn from_glib_none(ptr: *mut ::ffi::$ffi_name) -> Self {
446                <$name as crate::event::FromEvent>::from(from_glib_none(
447                    ptr as *mut ::ffi::GdkEvent,
448                ))
449                .unwrap()
450            }
451        }
452
453        impl FromGlibPtrBorrow<*mut ::ffi::$ffi_name> for $name {
454            #[inline]
455            unsafe fn from_glib_borrow(
456                ptr: *mut ::ffi::$ffi_name,
457            ) -> glib::translate::Borrowed<Self> {
458                glib::translate::Borrowed::new(
459                    <$name as crate::event::FromEvent>::from(
460                        crate::Event::from_glib_borrow(ptr as *mut ::ffi::GdkEvent).into_inner(),
461                    )
462                    .map_err(std::mem::forget)
463                    .unwrap(),
464                )
465            }
466        }
467
468        impl FromGlibPtrFull<*mut ::ffi::$ffi_name> for $name {
469            #[inline]
470            unsafe fn from_glib_full(ptr: *mut ::ffi::$ffi_name) -> Self {
471                <$name as crate::event::FromEvent>::from(from_glib_full(
472                    ptr as *mut ::ffi::GdkEvent,
473                ))
474                .unwrap()
475            }
476        }
477
478        impl AsRef<::ffi::$ffi_name> for $name {
479            #[inline]
480            fn as_ref(&self) -> &::ffi::$ffi_name {
481                unsafe {
482                    let ptr: *const ::ffi::$ffi_name = self.to_glib_none().0;
483                    &*ptr
484                }
485            }
486        }
487
488        impl AsMut<::ffi::$ffi_name> for $name {
489            #[inline]
490            fn as_mut(&mut self) -> &mut ::ffi::$ffi_name {
491                unsafe {
492                    let ptr: *mut ::ffi::$ffi_name = self.to_glib_none_mut().0;
493                    &mut *ptr
494                }
495            }
496        }
497    };
498}
499
500event_wrapper!(Event, GdkEventAny);
501
502macro_rules! event_subtype {
503    ($name:ident, $($ty:path)|+) => {
504        unsafe impl crate::event::FromEvent for $name {
505            #[inline]
506            fn is(ev: &crate::event::Event) -> bool {
507                skip_assert_initialized!();
508                matches!(ev.as_ref().type_, $($ty)|+)
509            }
510
511            #[inline]
512            fn from(ev: crate::event::Event) -> Result<Self, crate::event::Event> {
513                skip_assert_initialized!();
514                if Self::is(&ev) {
515                    Ok($name(ev))
516                } else {
517                    Err(ev)
518                }
519            }
520        }
521
522        impl ::std::ops::Deref for $name {
523            type Target = crate::event::Event;
524
525            fn deref(&self) -> &crate::event::Event {
526                &self.0
527            }
528        }
529
530        impl ::std::ops::DerefMut for $name {
531            fn deref_mut(&mut self) -> &mut crate::event::Event {
532                &mut self.0
533            }
534        }
535    };
536}
537
538unsafe impl FromEvent for Event {
539    #[inline]
540    fn is(_ev: &Event) -> bool {
541        skip_assert_initialized!();
542        true
543    }
544
545    #[inline]
546    fn from(ev: Event) -> Result<Self, Event> {
547        skip_assert_initialized!();
548        Ok(ev)
549    }
550}