gdk/
event.rs

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