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 
5 use gdk_sys;
6 use glib::translate::*;
7 use glib_sys;
8 use libc::c_void;
9 use std::fmt;
10 use std::mem;
11 use std::ptr;
12 
13 use AxisUse;
14 use Device;
15 #[cfg(any(feature = "v3_22", feature = "dox"))]
16 use DeviceTool;
17 use EventSequence;
18 use EventType;
19 use ModifierType;
20 use Screen;
21 use ScrollDirection;
22 #[cfg(any(feature = "v3_20", feature = "dox"))]
23 use Seat;
24 use Window;
25 
26 glib_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 
38 impl Event {
39     /// Creates a new event.
new(type_: EventType) -> Event40     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 
get() -> Option<Event>45     pub fn get() -> Option<Event> {
46         assert_initialized_main_thread!();
47         unsafe { from_glib_none(gdk_sys::gdk_event_get()) }
48     }
49 
put(&self)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.
set_handler<F: Fn(&mut Event) + 'static>(handler: Option<F>)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 
get_axis(&self, axis_use: AxisUse) -> Option<f64>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 
get_button(&self) -> Option<u32>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 
get_click_count(&self) -> Option<u32>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 
get_coords(&self) -> Option<(f64, f64)>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 
get_keycode(&self) -> Option<u16>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 
get_keyval(&self) -> Option<u32>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 
get_root_coords(&self) -> Option<(f64, f64)>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 
get_scroll_direction(&self) -> Option<ScrollDirection>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 
get_scroll_deltas(&self) -> Option<(f64, f64)>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"))]
is_scroll_stop_event(&self) -> bool229     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 
get_state(&self) -> Option<ModifierType>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 
get_time(&self) -> u32251     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.
get_window(&self) -> Option<Window>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 
get_event_sequence(&self) -> Option<EventSequence>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 
triggers_context_menu(&self) -> bool264     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"))]
get_seat(&self) -> Option<Seat>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"))]
get_scancode(&mut self) -> i32278     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"))]
get_pointer_emulated(&mut self) -> bool283     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 
set_screen(&mut self, screen: Option<&Screen>)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 
get_screen(&self) -> Option<Screen>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 
set_device(&mut self, device: Option<&Device>)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 
get_device(&self) -> Option<Device>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 
set_source_device(&mut self, device: Option<&Device>)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 
get_source_device(&self) -> Option<Device>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"))]
set_device_tool(&mut self, device: Option<&DeviceTool>)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"))]
get_device_tool(&self) -> Option<DeviceTool>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.
get_event_type(&self) -> EventType330     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))]
get_send_event(&self) -> bool336     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`.
is<T: FromEvent>(&self) -> bool341     pub fn is<T: FromEvent>(&self) -> bool {
342         T::is(self)
343     }
344 
345     /// Tries to downcast to a specific event type.
downcast<T: FromEvent>(self) -> Result<T, Self>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.
downcast_ref<T: FromEvent>(&self) -> Option<&T>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.
downcast_mut<T: FromEvent>(&mut self) -> Option<&mut T>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 
369 impl fmt::Debug for Event {
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>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.
379 pub trait FromEvent: Sized {
is(ev: &Event) -> bool380     fn is(ev: &Event) -> bool;
from(ev: Event) -> Result<Self, Event>381     fn from(ev: Event) -> Result<Self, Event>;
382 }
383 
384 macro_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 
449 event_wrapper!(Event, GdkEventAny);
450 
451 macro_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 }
490