Skip to main content

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