1 | use std::ffi::c_int; |
2 | use std::sync::Arc; |
3 | |
4 | use x11_dl::xlib::{self, XEvent, XGenericEventCookie}; |
5 | |
6 | use crate::platform_impl::x11::XConnection; |
7 | |
8 | /// XEvents of type GenericEvent store their actual data in an XGenericEventCookie data structure. |
9 | /// This is a wrapper to extract the cookie from a GenericEvent XEvent and release the cookie data |
10 | /// once it has been processed |
11 | pub struct GenericEventCookie { |
12 | cookie: XGenericEventCookie, |
13 | xconn: Arc<XConnection>, |
14 | } |
15 | |
16 | impl GenericEventCookie { |
17 | pub fn from_event(xconn: Arc<XConnection>, event: XEvent) -> Option<GenericEventCookie> { |
18 | unsafe { |
19 | let mut cookie: XGenericEventCookie = From::from(event); |
20 | if (xconn.xlib.XGetEventData)(xconn.display, &mut cookie) == xlib::True { |
21 | Some(GenericEventCookie { cookie, xconn }) |
22 | } else { |
23 | None |
24 | } |
25 | } |
26 | } |
27 | |
28 | #[inline ] |
29 | pub fn extension(&self) -> u8 { |
30 | self.cookie.extension as u8 |
31 | } |
32 | |
33 | #[inline ] |
34 | pub fn evtype(&self) -> c_int { |
35 | self.cookie.evtype |
36 | } |
37 | |
38 | /// Borrow inner event data as `&T`. |
39 | /// |
40 | /// ## SAFETY |
41 | /// |
42 | /// The caller must ensure that the event has the `T` inside of it. |
43 | #[inline ] |
44 | pub unsafe fn as_event<T>(&self) -> &T { |
45 | unsafe { &*(self.cookie.data as *const _) } |
46 | } |
47 | } |
48 | |
49 | impl Drop for GenericEventCookie { |
50 | fn drop(&mut self) { |
51 | unsafe { |
52 | (self.xconn.xlib.XFreeEventData)(self.xconn.display, &mut self.cookie); |
53 | } |
54 | } |
55 | } |
56 | |