gdk4/
event.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4
5use crate::{ffi, prelude::*, Event, EventType};
6
7impl Event {
8    #[inline]
9    pub fn is<T: EventKind>(&self) -> bool {
10        T::event_types().contains(&self.event_type())
11    }
12
13    #[inline]
14    pub fn type_(&self) -> glib::Type {
15        unsafe {
16            let ptr = self.as_ptr();
17            from_glib((*(*(ptr as *mut glib::gobject_ffi::GTypeInstance)).g_class).g_type)
18        }
19    }
20
21    #[inline]
22    pub fn downcast<T: EventKind>(self) -> Result<T, Event> {
23        unsafe {
24            if self.is::<T>() {
25                Ok(from_glib_full(self.into_glib_ptr()))
26            } else {
27                Err(self)
28            }
29        }
30    }
31
32    #[inline]
33    pub fn downcast_ref<T: EventKind>(&self) -> Option<&T> {
34        unsafe {
35            if self.is::<T>() {
36                Some(&*(self as *const Event as *const T))
37            } else {
38                None
39            }
40        }
41    }
42
43    /// Returns the relative angle from @event1 to @event2.
44    ///
45    /// The relative angle is the angle between the X axis and the line
46    /// through both events' positions. The rotation direction for positive
47    /// angles is from the positive X axis towards the positive Y axis.
48    ///
49    /// This assumes that both events have X/Y information.
50    /// If not, this function returns [`false`].
51    /// ## `event1`
52    /// first [`Event`][crate::Event]
53    /// ## `event2`
54    /// second [`Event`][crate::Event]
55    ///
56    /// # Returns
57    ///
58    /// [`true`] if the angle could be calculated.
59    ///
60    /// ## `angle`
61    /// return location for the relative angle between both events
62    #[doc(alias = "gdk_events_get_angle")]
63    #[doc(alias = "get_angle")]
64    pub fn angle(&self, event: impl AsRef<Event>) -> Option<f64> {
65        skip_assert_initialized!();
66        unsafe {
67            let mut angle = std::mem::MaybeUninit::uninit();
68            let ret = from_glib(ffi::gdk_events_get_angle(
69                self.to_glib_none().0,
70                event.as_ref().to_glib_none().0,
71                angle.as_mut_ptr(),
72            ));
73            if ret {
74                let angle = angle.assume_init();
75                Some(angle)
76            } else {
77                None
78            }
79        }
80    }
81
82    /// Returns the point halfway between the events' positions.
83    ///
84    /// This assumes that both events have X/Y information.
85    /// If not, this function returns [`false`].
86    /// ## `event1`
87    /// first [`Event`][crate::Event]
88    /// ## `event2`
89    /// second [`Event`][crate::Event]
90    ///
91    /// # Returns
92    ///
93    /// [`true`] if the center could be calculated.
94    ///
95    /// ## `x`
96    /// return location for the X coordinate of the center
97    ///
98    /// ## `y`
99    /// return location for the Y coordinate of the center
100    #[doc(alias = "gdk_events_get_center")]
101    #[doc(alias = "get_center")]
102    pub fn center(&self, event: impl AsRef<Event>) -> Option<(f64, f64)> {
103        skip_assert_initialized!();
104        unsafe {
105            let mut x = std::mem::MaybeUninit::uninit();
106            let mut y = std::mem::MaybeUninit::uninit();
107            let ret = from_glib(ffi::gdk_events_get_center(
108                self.to_glib_none().0,
109                event.as_ref().to_glib_none().0,
110                x.as_mut_ptr(),
111                y.as_mut_ptr(),
112            ));
113            if ret {
114                let x = x.assume_init();
115                let y = y.assume_init();
116                Some((x, y))
117            } else {
118                None
119            }
120        }
121    }
122
123    /// Returns the distance between the event locations.
124    ///
125    /// This assumes that both events have X/Y information.
126    /// If not, this function returns [`false`].
127    /// ## `event1`
128    /// first [`Event`][crate::Event]
129    /// ## `event2`
130    /// second [`Event`][crate::Event]
131    ///
132    /// # Returns
133    ///
134    /// [`true`] if the distance could be calculated.
135    ///
136    /// ## `distance`
137    /// return location for the distance
138    #[doc(alias = "gdk_events_get_distance")]
139    #[doc(alias = "get_distance")]
140    pub fn distance(&self, event: impl AsRef<Event>) -> Option<f64> {
141        skip_assert_initialized!();
142        unsafe {
143            let mut distance = std::mem::MaybeUninit::uninit();
144            let ret = from_glib(ffi::gdk_events_get_distance(
145                self.to_glib_none().0,
146                event.as_ref().to_glib_none().0,
147                distance.as_mut_ptr(),
148            ));
149            if ret {
150                let distance = distance.assume_init();
151                Some(distance)
152            } else {
153                None
154            }
155        }
156    }
157}
158
159impl std::fmt::Debug for Event {
160    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
161        f.debug_struct("Event")
162            .field("event_type", &self.event_type())
163            .field("history", &self.history())
164            .field("modifier_state", &self.modifier_state())
165            .field("pointer_emulated", &self.is_pointer_emulated())
166            .field("position", &self.position())
167            .field("time", &self.time())
168            .field("triggers_context_menu", &self.triggers_context_menu())
169            .finish()
170    }
171}
172
173#[doc(hidden)]
174impl AsRef<Event> for Event {
175    #[inline]
176    fn as_ref(&self) -> &Self {
177        self
178    }
179}
180
181// rustdoc-stripper-ignore-next
182/// A common trait implemented by the various [`Event`](crate::Event) types.
183///
184/// # Safety
185///
186/// The user is not supposed to implement this trait.
187pub unsafe trait EventKind:
188    StaticType + FromGlibPtrFull<*mut ffi::GdkEvent> + 'static
189{
190    fn event_types() -> &'static [EventType];
191}
192
193macro_rules! define_event {
194    ($rust_type:ident, $ffi_type:path,$event_event_types:expr) => {
195        unsafe impl crate::event::EventKind for $rust_type {
196            #[inline]
197            fn event_types() -> &'static [crate::EventType] {
198                $event_event_types
199            }
200        }
201
202        impl std::ops::Deref for $rust_type {
203            type Target = crate::Event;
204
205            #[inline]
206            fn deref(&self) -> &Self::Target {
207                unsafe { &*(self as *const $rust_type as *const crate::Event) }
208            }
209        }
210
211        impl AsRef<crate::Event> for $rust_type {
212            #[inline]
213            fn as_ref(&self) -> &crate::Event {
214                self.upcast_ref()
215            }
216        }
217
218        #[doc(hidden)]
219        impl glib::translate::FromGlibPtrFull<*mut crate::ffi::GdkEvent> for $rust_type {
220            #[inline]
221            unsafe fn from_glib_full(ptr: *mut crate::ffi::GdkEvent) -> Self {
222                glib::translate::FromGlibPtrFull::from_glib_full(ptr as *mut $ffi_type)
223            }
224        }
225
226        impl $rust_type {
227            #[inline]
228            pub fn upcast(self) -> crate::Event {
229                unsafe { std::mem::transmute(self) }
230            }
231
232            #[inline]
233            pub fn upcast_ref(&self) -> &crate::Event {
234                self
235            }
236        }
237    };
238}