1use super::{FlutterbugError, GenericDisplay, GenericInputContext, Window};
48use std::{
49 ffi::CString,
50 mem,
51 os::raw::{c_int, c_long, c_uchar, c_uint, c_ulong},
52 ptr::{self, NonNull},
53};
54use x11::xlib::{self, XID};
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub enum EventType {
59 KeyPress,
60 KeyRelease,
61 ButtonPress,
62 ButtonRelease,
63 MotionNotify,
64 EnterNotify,
65 LeaveNotify,
66 FocusIn,
67 FocusOut,
68 KeymapNotify,
69 Expose,
70 GraphicsExpose,
71 NoExpose,
72 CirculateRequest,
73 ConfigureRequest,
74 MapRequest,
75 ResizeRequest,
76 CirculateNotify,
77 ConfigureNotify,
78 CreateNotify,
79 DestroyNotify,
80 GravityNotify,
81 MapNotify,
82 MappingNotify,
83 ReparentNotify,
84 UnmapNotify,
85 VisibilityNotify,
86 ColormapEvent,
87 ClientMessage,
88 PropertyNotify,
89 SelectionClear,
90 SelectionNotify,
91 SelectionRequest,
92}
93
94impl EventType {
95 pub fn from_int(t: c_int) -> Option<Self> {
97 Some(match t {
98 xlib::KeyPress => Self::KeyPress,
99 xlib::KeyRelease => Self::KeyRelease,
100 xlib::ButtonPress => Self::ButtonPress,
101 xlib::ButtonRelease => Self::ButtonRelease,
102 xlib::MotionNotify => Self::MotionNotify,
103 xlib::EnterNotify => Self::EnterNotify,
104 xlib::LeaveNotify => Self::LeaveNotify,
105 xlib::FocusIn => Self::FocusIn,
106 xlib::FocusOut => Self::FocusOut,
107 xlib::KeymapNotify => Self::KeymapNotify,
108 xlib::Expose => Self::Expose,
109 xlib::GraphicsExpose => Self::GraphicsExpose,
110 xlib::NoExpose => Self::NoExpose,
111 xlib::CirculateRequest => Self::CirculateRequest,
112 xlib::ConfigureRequest => Self::ConfigureRequest,
113 xlib::MapRequest => Self::MapRequest,
114 xlib::ResizeRequest => Self::ResizeRequest,
115 xlib::CirculateNotify => Self::CirculateNotify,
116 xlib::ConfigureNotify => Self::ConfigureNotify,
117 xlib::CreateNotify => Self::CreateNotify,
118 xlib::DestroyNotify => Self::DestroyNotify,
119 xlib::GravityNotify => Self::GravityNotify,
120 xlib::MapNotify => Self::MapNotify,
121 xlib::MappingNotify => Self::MappingNotify,
122 xlib::ReparentNotify => Self::ReparentNotify,
123 xlib::UnmapNotify => Self::UnmapNotify,
124 xlib::VisibilityNotify => Self::VisibilityNotify,
125 xlib::ColormapNotify => Self::ColormapEvent,
126 xlib::ClientMessage => Self::ClientMessage,
127 xlib::PropertyNotify => Self::PropertyNotify,
128 xlib::SelectionClear => Self::SelectionClear,
129 xlib::SelectionNotify => Self::SelectionNotify,
130 xlib::SelectionRequest => Self::SelectionRequest,
131 _ => return None,
132 })
133 }
134
135 pub fn to_int(self) -> c_int {
137 match self {
138 Self::KeyPress => xlib::KeyPress,
139 Self::KeyRelease => xlib::KeyRelease,
140 Self::ButtonPress => xlib::ButtonPress,
141 Self::ButtonRelease => xlib::ButtonRelease,
142 Self::MotionNotify => xlib::MotionNotify,
143 Self::EnterNotify => xlib::EnterNotify,
144 Self::LeaveNotify => xlib::LeaveNotify,
145 Self::FocusIn => xlib::FocusIn,
146 Self::FocusOut => xlib::FocusOut,
147 Self::KeymapNotify => xlib::KeymapNotify,
148 Self::Expose => xlib::Expose,
149 Self::GraphicsExpose => xlib::GraphicsExpose,
150 Self::NoExpose => xlib::NoExpose,
151 Self::CirculateRequest => xlib::CirculateRequest,
152 Self::ConfigureRequest => xlib::ConfigureRequest,
153 Self::MapRequest => xlib::MapRequest,
154 Self::ResizeRequest => xlib::ResizeRequest,
155 Self::CirculateNotify => xlib::CirculateNotify,
156 Self::ConfigureNotify => xlib::ConfigureNotify,
157 Self::CreateNotify => xlib::CreateNotify,
158 Self::DestroyNotify => xlib::DestroyNotify,
159 Self::GravityNotify => xlib::GravityNotify,
160 Self::MapNotify => xlib::MapNotify,
161 Self::MappingNotify => xlib::MappingNotify,
162 Self::ReparentNotify => xlib::ReparentNotify,
163 Self::UnmapNotify => xlib::UnmapNotify,
164 Self::VisibilityNotify => xlib::VisibilityNotify,
165 Self::ColormapEvent => xlib::ColormapNotify,
166 Self::ClientMessage => xlib::ClientMessage,
167 Self::PropertyNotify => xlib::PropertyNotify,
168 Self::SelectionClear => xlib::SelectionClear,
169 Self::SelectionNotify => xlib::SelectionNotify,
170 Self::SelectionRequest => xlib::SelectionRequest,
171 }
172 }
173}
174
175bitflags::bitflags! {
176 #[doc = "The masks that can be applied to an event listener"]
177 pub struct EventMask : c_long {
178 const NO_EVENT_MASK = xlib::NoEventMask;
179 const KEY_PRESS_MASK = xlib::KeyPressMask;
180 const KEY_RELEASE_MASK = xlib::KeyReleaseMask;
181 const BUTTON_PRESS_MASK = xlib::ButtonPressMask;
182 const BUTTON_RELEASE_MASK = xlib::ButtonReleaseMask;
183 const ENTER_WINDOW_MASK = xlib::EnterWindowMask;
184 const LEAVE_WINDOW_MASK = xlib::LeaveWindowMask;
185 const POINTER_MOTION_MASK = xlib::PointerMotionMask;
186 const POINTER_MOTION_HINT_MASK = xlib::PointerMotionHintMask;
187 const BUTTON_1_MOTION_MASK = xlib::Button1MotionMask;
188 const BUTTON_2_MOTION_MASK = xlib::Button2MotionMask;
189 const BUTTON_3_MOTION_MASK = xlib::Button3MotionMask;
190 const BUTTON_4_MOTION_MASK = xlib::Button4MotionMask;
191 const BUTTON_5_MOTION_MASK = xlib::Button5MotionMask;
192 const BUTTON_MOTION_MASK = xlib::ButtonMotionMask;
193 const KEYMAP_STATE_MASK = xlib::KeymapStateMask;
194 const EXPOSURE_MASK = xlib::ExposureMask;
195 const VISIBILITY_CHANGE_MASK = xlib::VisibilityChangeMask;
196 const STRUCTURE_NOTIFY_MASK = xlib::StructureNotifyMask;
197 const RESIZE_REDIRECT_MASK = xlib::ResizeRedirectMask;
198 const SUBSTRUCTURE_NOTIFY_MASK = xlib::SubstructureNotifyMask;
199 const FOCUS_CHANGE_MASK = xlib::FocusChangeMask;
200 const PROPERTY_CHANGE_MASK = xlib::PropertyChangeMask;
201 const COLORMAP_CHANGE_MASK = xlib::ColormapChangeMask;
202 const OWNER_GRAB_BUTTON_MASK = xlib::OwnerGrabButtonMask;
203 }
204}
205
206pub trait DerivesAnEvent: Sized + Clone {
208 fn as_anyevent(&self) -> AnyEvent {
210 AnyEvent::from_raw(
211 self.kind(),
212 self.serial(),
213 unsafe { self.display() },
214 self.window(),
215 self.from_send_event(),
216 )
217 }
218 fn kind(&self) -> EventType;
220 fn serial(&self) -> c_ulong;
222 unsafe fn display(&self) -> NonNull<xlib::Display>;
229 fn window(&self) -> xlib::Window;
231 fn from_send_event(&self) -> bool;
233}
234
235pub trait DerivesEvent<EvStruct: Copy>: DerivesAnEvent {
237 fn from_evstruct(xev: EvStruct) -> Result<Self, FlutterbugError>
239 where
240 Self: Sized;
241
242 fn inner(&self) -> Result<EvStruct, FlutterbugError>;
244}
245
246#[derive(Debug, Clone)]
248pub struct AnyEvent {
249 kind: EventType,
250 serial: c_ulong,
251 display: NonNull<xlib::Display>,
252 window: xlib::Window,
253 from_send_event: bool,
254}
255
256impl AnyEvent {
257 #[inline]
259 pub(crate) fn from_raw(
260 kind: EventType,
261 serial: c_ulong,
262 display: NonNull<xlib::Display>,
263 window: xlib::Window,
264 fse: bool,
265 ) -> Self {
266 Self {
267 kind,
268 serial,
269 display,
270 window,
271 from_send_event: fse,
272 }
273 }
274}
275
276impl DerivesAnEvent for AnyEvent {
277 #[inline]
278 fn as_anyevent(&self) -> Self {
279 self.clone()
280 }
281 #[inline]
282 fn kind(&self) -> EventType {
283 self.kind
284 }
285 #[inline]
286 fn serial(&self) -> c_ulong {
287 self.serial
288 }
289 #[inline]
290 unsafe fn display(&self) -> NonNull<xlib::Display> {
291 self.display
292 }
293 #[inline]
294 fn window(&self) -> xlib::Window {
295 self.window
296 }
297 #[inline]
298 fn from_send_event(&self) -> bool {
299 self.from_send_event
300 }
301}
302
303macro_rules! anyev_impl {
305 ($xev: ty [ $winname: ident ]) => {
306 impl DerivesEvent<$xev> for AnyEvent {
307 #[inline]
308 fn from_evstruct(xev: $xev) -> Result<Self, FlutterbugError> {
309 Ok(Self {
310 kind: EventType::from_int(xev.type_)
311 .ok_or_else(|| FlutterbugError::InvalidEventType)?,
312 serial: xev.serial,
313 display: NonNull::new(xev.display)
314 .ok_or_else(|| FlutterbugError::DisplayFieldNull)?,
315 window: xev.$winname,
316 from_send_event: xev.send_event != 0,
317 })
318 }
319
320 #[inline]
321 fn inner(&self) -> Result<$xev, FlutterbugError> {
322 Err(FlutterbugError::InnerAnyEventInaccessible)
323 }
324 }
325 };
326 ($xev:ty) => {
327 anyev_impl! {$xev[window]}
328 };
329}
330
331impl DerivesEvent<xlib::XAnyEvent> for AnyEvent {
333 #[inline]
334 fn from_evstruct(xev: xlib::XAnyEvent) -> Result<Self, FlutterbugError> {
335 Ok(Self {
336 kind: EventType::from_int(xev.type_)
337 .ok_or_else(|| FlutterbugError::InvalidEventType)?,
338 serial: xev.serial,
339 display: NonNull::new(xev.display).ok_or_else(|| FlutterbugError::DisplayFieldNull)?,
340 window: xev.window,
341 from_send_event: xev.send_event != 0,
342 })
343 }
344
345 #[inline]
346 fn inner(&self) -> Result<xlib::XAnyEvent, FlutterbugError> {
347 Ok(xlib::XAnyEvent {
348 type_: self.kind.to_int(),
349 serial: self.serial,
350 display: self.display.as_ptr(),
351 window: self.window,
352 send_event: if self.from_send_event { 1 } else { 0 },
353 })
354 }
355}
356
357anyev_impl! {xlib::XKeyEvent}
358anyev_impl! {xlib::XButtonEvent}
359anyev_impl! {xlib::XMotionEvent}
360anyev_impl! {xlib::XCrossingEvent}
361anyev_impl! {xlib::XFocusChangeEvent}
362anyev_impl! {xlib::XExposeEvent}
363anyev_impl! {xlib::XGraphicsExposeEvent[drawable]}
364anyev_impl! {xlib::XNoExposeEvent[drawable]}
365anyev_impl! {xlib::XVisibilityEvent}
366anyev_impl! {xlib::XCreateWindowEvent[parent]}
367anyev_impl! {xlib::XDestroyWindowEvent}
368anyev_impl! {xlib::XUnmapEvent}
369anyev_impl! {xlib::XMapEvent}
370anyev_impl! {xlib::XMapRequestEvent}
371anyev_impl! {xlib::XReparentEvent}
372anyev_impl! {xlib::XConfigureEvent}
373anyev_impl! {xlib::XGravityEvent}
374anyev_impl! {xlib::XResizeRequestEvent}
375anyev_impl! {xlib::XConfigureRequestEvent}
376anyev_impl! {xlib::XCirculateEvent}
377anyev_impl! {xlib::XCirculateRequestEvent}
378anyev_impl! {xlib::XPropertyEvent}
379anyev_impl! {xlib::XSelectionClearEvent}
380anyev_impl! {xlib::XSelectionRequestEvent[owner]}
381anyev_impl! {xlib::XSelectionEvent[requestor]}
382anyev_impl! {xlib::XColormapEvent}
383anyev_impl! {xlib::XClientMessageEvent}
384anyev_impl! {xlib::XMappingEvent[event]}
385anyev_impl! {xlib::XKeymapEvent}
386
387macro_rules! event_type {
409 ($(#[$attr: meta])* $vis: vis struct $sname: ident : $bname: ty [ $winname: ident ] {
410 $($fvis: vis $fname: ident : $ftname: ty = $sfname: ident),*
411 $(,)?
412 }: $mname: ident) => {
413 $vis mod $mname {
414 #![allow(clippy::all)]
415 #![allow(unused_imports)]
416
417 use crate::{FlutterbugError, GenericDisplay, Window};
418 use super::{DerivesAnEvent, DerivesEvent, EventType};
419 use std::{convert::TryInto, os::raw::{c_char, c_uint, c_ulong, c_int}, ptr::NonNull};
420 use x11::xlib;
421
422 #[derive(Debug, Clone)]
423 $(#[$attr])*
424 pub struct $sname {
425 kind: EventType,
426 serial: c_ulong,
427 display: NonNull<xlib::Display>,
428 window: xlib::Window,
429 from_send_event: bool,
430 inner: $bname,
431 $($fvis $fname: $ftname),*
432 }
433
434 impl DerivesAnEvent for $sname {
435 #[inline]
436 fn kind(&self) -> EventType { self.kind }
437 #[inline]
438 fn serial(&self) -> c_ulong { self.serial }
439 #[inline]
440 unsafe fn display(&self) -> NonNull<xlib::Display> { self.display }
441 #[inline]
442 fn window(&self) -> xlib::Window { self.window }
443 #[inline]
444 fn from_send_event(&self) -> bool { self.from_send_event }
445 }
446
447 impl DerivesEvent<$bname> for $sname {
448 #[inline]
449 fn from_evstruct(ev: $bname) -> Result<Self, FlutterbugError> {
450 Ok(Self {
451 kind: EventType::from_int(ev.type_).ok_or_else(|| FlutterbugError::InvalidEventType)?,
452 serial: ev.serial,
453 display: NonNull::new(ev.display).ok_or_else(|| FlutterbugError::DisplayFieldNull)?,
454 window: ev.$winname,
455 from_send_event: ev.send_event != 0,
456 inner: ev,
457 $($fname: ev.$sfname.try_into().unwrap_or_else(|_|
458 panic!("Tried to convert {} and failed", stringify!($fname))
459 )),*
460 })
461 }
462
463 #[inline]
464 fn inner(&self) -> Result<$bname, FlutterbugError> { Ok(self.inner) }
465 }
466
467 type OurStruct = $bname;
468
469 impl $sname {
470 $(#[inline] pub fn $fname(&self) -> $ftname { self.$fname })*
471
472 #[inline]
473 pub fn new(
474 kind: EventType,
475 serial: c_ulong,
476 display: &dyn GenericDisplay,
477 sender_window: &Window,
478 fse: bool,
479 $($fname: $ftname),*
480 ) -> Result<Self, FlutterbugError> {
481 let inner = OurStruct {
482 type_: kind.to_int(),
483 serial,
484 display: display.raw()?.as_ptr(),
485 $winname: sender_window.window(),
486 send_event: if fse { 1 } else { 0 },
487 $($sfname: $fname.try_into().unwrap_or_else(|_|
488 panic!("Tried to convert {} and failed", stringify!($fname))
489 )),*
490 };
491
492 Ok(Self {
493 kind, serial, display: display.raw()?, window: sender_window.window(),
494 from_send_event: fse,
495 inner,
496 $($fname),*
497 })
498 }
499 }
500 }
501
502 $vis use $mname::*;
503 };
504 ($(#[$attr: meta])* $vis: vis struct $sname: ident : $bname: ty {
505 $($fvis: vis $fname: ident : $ftname: ty = $sfname: ident),*
506 $(,)?
507 }: $mname: ident) => {
508 event_type! {
509 $(#[$attr])*
510 $vis struct $sname : $bname [ window ] {
511 $($fvis $fname: $ftname = $sfname),*
512 } : $mname
513 }
514 };
515}
516
517event_type! {
518 pub struct KeyEvent : xlib::XKeyEvent {
519 root: xlib::Window = root,
520 subwindow: xlib::Window = subwindow,
521 time: xlib::Time = time,
522 x: i32 = x,
523 y: i32 = y,
524 x_root: u32 = x_root,
525 y_root: u32 = y_root,
526 pub state: c_uint = state,
527 keycode: c_uint = keycode,
528 same_screen: xlib::Bool = same_screen,
529 }: key_event
530}
531
532bitflags::bitflags! {
533 #[doc = "Represents function keys that can be depressed"]
534 pub struct FunctionKeys : c_uint {
535 const CONTROL = xlib::ControlMask;
536 const ALT = 8;
537 const SHIFT = xlib::ShiftMask;
538 const CAPS_LOCK = 2;
539 }
540}
541
542impl KeyEvent {
543 #[inline]
545 pub fn has_function(&self, f: FunctionKeys) -> bool {
546 (self.state & f.bits()) != 0
547 }
548
549 #[inline]
551 pub fn set_function(&mut self, f: FunctionKeys, is_in: bool) {
552 if !is_in {
553 self.state &= !f.bits();
554 } else {
555 self.state |= f.bits();
556 }
557 }
558
559 #[inline]
561 pub fn lookup(&self) -> Result<(xlib::KeySym, String), FlutterbugError> {
562 const BUFFER_SIZE: usize = 50;
563 let mut inner = self.inner()?;
564 let buffer = crate::cstring_buffer(BUFFER_SIZE);
565 let buffer = buffer.into_raw();
566 let mut ks = 0;
567
568 let _bsize = unsafe {
569 xlib::XLookupString(
570 &mut inner,
571 buffer,
572 BUFFER_SIZE as c_int - 1,
573 &mut ks,
574 ptr::null_mut(),
575 )
576 };
577 let res = unsafe { CString::from_raw(buffer) }.into_string()?;
578
579 Ok((ks, res))
580 }
581
582 #[inline]
584 pub fn lookup_utf8(
585 &self,
586 ic: &dyn GenericInputContext,
587 ) -> Result<(Option<xlib::KeySym>, Option<String>), FlutterbugError> {
588 const BUFFER_SIZE: usize = 50;
589 let mut inner = self.inner()?;
590 let buffer = crate::cstring_buffer(BUFFER_SIZE);
591 let buffer = buffer.into_raw();
592 let mut status = 0;
593 let mut ks = 0;
594
595 let _bsize = unsafe {
596 xlib::Xutf8LookupString(
597 ic.raw()?.as_mut(),
598 &mut inner,
599 buffer,
600 BUFFER_SIZE as c_int - 1,
601 &mut ks,
602 &mut status,
603 )
604 };
605
606 let mut res_str = None;
607 let mut res_ks = None;
608
609 match status {
610 xlib::XBufferOverflow => {
611 return Err(FlutterbugError::StaticMsg("Did not allocate enough memory"));
612 }
613 xlib::XLookupBoth | xlib::XLookupChars => {
614 res_str = Some(unsafe { CString::from_raw(buffer) }.into_string()?);
615 }
616 _ => { }
617 }
618
619 match status {
620 xlib::XLookupBoth | xlib::XLookupKeySym => {
621 res_ks = Some(ks);
622 }
623 _ => { }
624 }
625
626 Ok((res_ks, res_str))
627 }
628}
629
630event_type! {
631 pub struct ButtonEvent : xlib::XButtonEvent {
632 root: xlib::Window = root,
633 subwindow: xlib::Window = subwindow,
634 time: xlib::Time = time,
635 x: i32 = x,
636 y: i32 = y,
637 x_root: u32 = x_root,
638 y_root: u32 = y_root,
639 state: c_uint = state,
640 button: c_uint = button,
641 same_screen: xlib::Bool = same_screen,
642 }: button_event
643}
644
645event_type! {
646 pub struct MotionEvent : xlib::XMotionEvent {
647 root: xlib::Window = root,
648 subwindow: xlib::Window = subwindow,
649 time: xlib::Time = time,
650 x: i32 = x,
651 y: i32 = y,
652 x_root: u32 = x_root,
653 y_root: u32 = y_root,
654 state: c_uint = state,
655 is_hint: c_char = is_hint,
656 same_screen: xlib::Bool = same_screen,
657 }: motion_event
658}
659
660event_type! {
661 pub struct CrossingEvent : xlib::XCrossingEvent {
662 root: xlib::Window = root,
663 subwindow: xlib::Window = subwindow,
664 time: xlib::Time = time,
665 x: i32 = x,
666 y: i32 = y,
667 x_root: u32 = x_root,
668 y_root: u32 = y_root,
669 state: c_uint = state,
670 mode: c_int = mode,
671 detail: c_int = detail,
672 focus: xlib::Bool = focus,
673 same_screen: xlib::Bool = same_screen,
674 }: crossing_event
675}
676
677event_type! {
678 pub struct FocusChangeEvent : xlib::XFocusChangeEvent {
679 mode: c_int = mode,
680 detail: c_int = detail,
681 }: focus_change_event
682}
683
684event_type! {
685 pub struct ExposeEvent : xlib::XExposeEvent {
686 x: i32 = x,
687 y: i32 = y,
688 width: u32 = width,
689 height: u32 = height,
690 count: i32 = count,
691 }: expose_event
692}
693
694event_type! {
695 pub struct NoExposeEvent : xlib::XNoExposeEvent[drawable] {
696 major_code: c_int = major_code,
697 minor_code: c_int = minor_code,
698 }: no_expose_event
699}
700
701event_type! {
702 pub struct GraphicsExposeEvent : xlib::XGraphicsExposeEvent[drawable] {
703 x: i32 = x,
704 y: i32 = y,
705 width: u32 = width,
706 height: u32 = height,
707 count: i32 = count,
708 major_code: c_int = major_code,
709 minor_code: c_int = minor_code,
710 }: graphics_expose_event
711}
712
713event_type! {
714 pub struct ConfigureEvent : xlib::XConfigureEvent[event] {
715 child: xlib::Window = window,
716 x: i32 = x,
717 y: i32 = y,
718 width: u32 = width,
719 height: u32 = height,
720 border_width: u32 = border_width,
721 above: xlib::Window = above,
722 override_redirect: xlib::Bool = override_redirect,
723 }: configure_event
724}
725
726event_type! {
727 pub struct VisibilityEvent : xlib::XVisibilityEvent {
728 state: c_int = state,
729 }: visibility_event
730}
731
732event_type! {
733 pub struct CreateWindowEvent : xlib::XCreateWindowEvent[parent] {
734 child: xlib::Window = window,
735 x: i32 = x,
736 y: i32 = y,
737 width: u32 = width,
738 height: u32 = height,
739 border_width: u32 = border_width,
740 override_redirect: xlib::Bool = override_redirect,
741 }: create_window_event
742}
743
744event_type! {
745 pub struct DestroyWindowEvent : xlib::XDestroyWindowEvent[event] {
746 child: xlib::Window = window,
747 }: destroy_window_event
748}
749
750event_type! {
751 pub struct UnmapEvent : xlib::XUnmapEvent[event] {
752 child: xlib::Window = window,
753 from_configure: xlib::Bool = from_configure,
754 }: unmap_event
755}
756
757event_type! {
758 pub struct MapEvent : xlib::XMapEvent[event] {
759 child: xlib::Window = window,
760 override_redirect: xlib::Bool = override_redirect,
761 }: map_event
762}
763
764event_type! {
765 pub struct MapRequestEvent : xlib::XMapRequestEvent[parent] {
766 child: xlib::Window = window,
767 }: map_request_event
768}
769
770event_type! {
771 pub struct ReparentEvent : xlib::XReparentEvent[event] {
772 child: xlib::Window = window,
773 parent: xlib::Window = parent,
774 x: i32 = x,
775 y: i32 = y,
776 override_redirect: xlib::Bool = override_redirect,
777 }: reparent_event
778}
779
780event_type! {
781 pub struct GravityEvent : xlib::XGravityEvent[event] {
782 child: xlib::Window = window,
783 x: i32 = x,
784 y: i32 = y,
785 }: gravity_event
786}
787
788event_type! {
789 pub struct ResizeRequestEvent : xlib::XResizeRequestEvent {
790 width: u32 = width,
791 height: u32 = height,
792 }: resize_request_event
793}
794
795event_type! {
796 pub struct ConfigureRequestEvent : xlib::XConfigureRequestEvent {
797 parent: xlib::Window = parent,
798 x: i32 = x,
799 y: i32 = y,
800 width: u32 = width,
801 height: u32 = height,
802 border_width: u32 = border_width,
803 above: xlib::Window = above,
804 detail: c_int = detail,
805 value_mask: c_uint = value_mask,
806 }: configure_request_event
807}
808
809event_type! {
810 pub struct CirculateEvent : xlib::XCirculateEvent {
811 event: xlib::Window = event,
812 place: c_int = place,
813 }: circulate_event
814}
815
816event_type! {
817 pub struct CirculateRequestEvent : xlib::XCirculateRequestEvent {
818 parent: xlib::Window = parent,
819 place: c_int = place,
820 }: circulate_request_event
821}
822
823event_type! {
824 pub struct PropertyEvent : xlib::XPropertyEvent {
825 atom: xlib::Atom = atom,
826 time: xlib::Time = time,
827 state: c_int = state,
828 }: property_event
829}
830
831event_type! {
832 pub struct SelectionClearEvent : xlib::XSelectionClearEvent {
833 selection: xlib::Atom = selection,
834 time: xlib::Time = time,
835 }: selection_clear_event
836}
837
838event_type! {
839 pub struct SelectionRequestEvent : xlib::XSelectionRequestEvent[owner] {
840 requestor: xlib::Window = requestor,
841 selection: xlib::Atom = selection,
842 target: xlib::Atom = target,
843 property: xlib::Atom = property,
844 time: xlib::Time = time,
845 }: selection_request_event
846}
847
848event_type! {
849 pub struct SelectionEvent : xlib::XSelectionEvent[requestor] {
850 selection: xlib::Atom = selection,
851 target: xlib::Atom = target,
852 property: xlib::Atom = property,
853 time: xlib::Time = time,
854 }: selection_event
855}
856
857event_type! {
858 pub struct ColormapEvent : xlib::XColormapEvent {
859 colormap: xlib::Colormap = colormap,
860 state: c_int = state,
861 is_new_map: xlib::Bool = new,
862 }: colormap_event
863}
864
865event_type! {
866 pub struct ClientMessageEvent : xlib::XClientMessageEvent {
867 message_type: xlib::Atom = message_type,
868 format: c_int = format,
869 data: xlib::ClientMessageData = data,
870 }: client_message_event
871}
872
873event_type! {
874 pub struct MappingEvent : xlib::XMappingEvent[event] {
875 request: c_int = request,
876 first_keycode: c_int = first_keycode,
877 count: i32 = count,
878 }: mapping_event
879}
880
881event_type! {
882 pub struct KeymapEvent : xlib::XKeymapEvent {
883 keys: [c_char; 32] = key_vector
884 }: keymap_event
885}
886
887#[derive(Clone)]
889pub struct ErrorEvent {
890 kind: EventType,
891 display: NonNull<xlib::Display>,
892 resource_id: XID,
893 serial: c_ulong,
894 error_code: c_uchar,
895 minor_code: c_uchar,
896 request: c_uchar,
897 err_text: String,
898}
899
900impl DerivesAnEvent for ErrorEvent {
901 #[inline]
902 fn kind(&self) -> EventType {
903 self.kind
904 }
905 #[inline]
906 fn window(&self) -> xlib::Window {
907 self.resource_id
908 }
909 #[inline]
910 fn from_send_event(&self) -> bool {
911 false
912 }
913 #[inline]
914 unsafe fn display(&self) -> NonNull<xlib::Display> {
915 self.display
916 }
917 #[inline]
918 fn serial(&self) -> c_ulong {
919 self.serial
920 }
921}
922
923#[derive(Debug, Clone)]
925pub enum Event {
926 Any(AnyEvent),
927 Key(KeyEvent),
928 Button(ButtonEvent),
929 Motion(MotionEvent),
930 Crossing(CrossingEvent),
931 FocusChange(FocusChangeEvent),
932 Expose(ExposeEvent),
933 GraphicsExpose(GraphicsExposeEvent),
934 NoExpose(NoExposeEvent),
935 Visibility(VisibilityEvent),
936 CreateWindow(CreateWindowEvent),
937 DestroyWindow(DestroyWindowEvent),
938 Unmap(UnmapEvent),
939 Map(MapEvent),
940 MapRequest(MapRequestEvent),
941 Reparent(ReparentEvent),
942 Configure(ConfigureEvent),
943 Gravity(GravityEvent),
944 ResizeRequest(ResizeRequestEvent),
945 ConfigureRequest(ConfigureRequestEvent),
946 Circulate(CirculateEvent),
947 CirculateRequest(CirculateRequestEvent),
948 Property(PropertyEvent),
949 SelectionClear(SelectionClearEvent),
950 SelectionRequest(SelectionRequestEvent),
951 Selection(SelectionEvent),
952 Colormap(ColormapEvent),
953 ClientMessage(ClientMessageEvent),
954 Mapping(MappingEvent),
955 Keymap(KeymapEvent),
956}
957
958macro_rules! get_inner_property {
959 ($s: ident, $prop: ident) => {
960 match *$s {
961 Event::Any(ref a) => a.$prop(),
962 Event::Key(ref k) => k.$prop(),
963 Event::Button(ref b) => b.$prop(),
964 Event::Motion(ref m) => m.$prop(),
965 Event::Crossing(ref c) => c.$prop(),
966 Event::FocusChange(ref fc) => fc.$prop(),
967 Event::Expose(ref e) => e.$prop(),
968 Event::GraphicsExpose(ref ge) => ge.$prop(),
969 Event::NoExpose(ref ne) => ne.$prop(),
970 Event::Visibility(ref v) => v.$prop(),
971 Event::CreateWindow(ref cw) => cw.$prop(),
972 Event::DestroyWindow(ref dw) => dw.$prop(),
973 Event::Unmap(ref u) => u.$prop(),
974 Event::Map(ref m) => m.$prop(),
975 Event::MapRequest(ref mr) => mr.$prop(),
976 Event::Reparent(ref r) => r.$prop(),
977 Event::Configure(ref c) => c.$prop(),
978 Event::Gravity(ref g) => g.$prop(),
979 Event::ResizeRequest(ref rr) => rr.$prop(),
980 Event::ConfigureRequest(ref cr) => cr.$prop(),
981 Event::Circulate(ref c) => c.$prop(),
982 Event::CirculateRequest(ref cr) => cr.$prop(),
983 Event::Property(ref p) => p.$prop(),
984 Event::SelectionClear(ref sc) => sc.$prop(),
985 Event::SelectionRequest(ref sr) => sr.$prop(),
986 Event::Selection(ref s) => s.$prop(),
987 Event::Colormap(ref cm) => cm.$prop(),
988 Event::ClientMessage(ref cm) => cm.$prop(),
989 Event::Mapping(ref m) => m.$prop(),
990 Event::Keymap(ref k) => k.$prop(),
991 }
992 };
993}
994
995impl DerivesEvent<xlib::XEvent> for Event {
996 fn from_evstruct(x: xlib::XEvent) -> Result<Self, FlutterbugError> {
997 macro_rules! evt {
998 ($bname: ident, $sname: ty, $evfield: ident) => {
999 Ok(Event::$bname(<$sname>::from_evstruct(unsafe {
1000 x.$evfield
1001 })?))
1002 };
1003 }
1004
1005 let kind = unsafe { x.type_ };
1006 let kind = match EventType::from_int(kind) {
1007 Some(k) => k,
1008 None => return evt!(Any, AnyEvent, any),
1009 };
1010
1011 match kind {
1012 EventType::KeyPress | EventType::KeyRelease => evt!(Key, KeyEvent, key),
1013 EventType::ButtonPress | EventType::ButtonRelease => evt!(Button, ButtonEvent, button),
1014 EventType::MotionNotify => evt!(Motion, MotionEvent, motion),
1015 EventType::FocusIn | EventType::FocusOut => {
1016 evt!(FocusChange, FocusChangeEvent, focus_change)
1017 }
1018 EventType::EnterNotify | EventType::LeaveNotify => {
1019 evt!(Crossing, CrossingEvent, crossing)
1020 }
1021 EventType::KeymapNotify => evt!(Keymap, KeymapEvent, keymap),
1022 EventType::Expose => evt!(Expose, ExposeEvent, expose),
1023 EventType::GraphicsExpose => evt!(GraphicsExpose, GraphicsExposeEvent, graphics_expose),
1024 EventType::NoExpose => evt!(NoExpose, NoExposeEvent, no_expose),
1025 EventType::CirculateRequest => {
1026 evt!(CirculateRequest, CirculateRequestEvent, circulate_request)
1027 }
1028 EventType::ConfigureRequest => {
1029 evt!(ConfigureRequest, ConfigureRequestEvent, configure_request)
1030 }
1031 EventType::MapRequest => evt!(MapRequest, MapRequestEvent, map_request),
1032 EventType::ResizeRequest => evt!(ResizeRequest, ResizeRequestEvent, resize_request),
1033 EventType::CirculateNotify => evt!(Circulate, CirculateEvent, circulate),
1034 EventType::ConfigureNotify => evt!(Configure, ConfigureEvent, configure),
1035 EventType::CreateNotify => evt!(CreateWindow, CreateWindowEvent, create_window),
1036 EventType::DestroyNotify => evt!(DestroyWindow, DestroyWindowEvent, destroy_window),
1037 EventType::GravityNotify => evt!(Gravity, GravityEvent, gravity),
1038 EventType::MapNotify => evt!(Map, MapEvent, map),
1039 EventType::MappingNotify => evt!(Mapping, MappingEvent, mapping),
1040 EventType::ReparentNotify => evt!(Reparent, ReparentEvent, reparent),
1041 EventType::UnmapNotify => evt!(Unmap, UnmapEvent, unmap),
1042 EventType::VisibilityNotify => evt!(Visibility, VisibilityEvent, visibility),
1043 EventType::ColormapEvent => evt!(Colormap, ColormapEvent, colormap),
1044 EventType::ClientMessage => evt!(ClientMessage, ClientMessageEvent, client_message),
1045 EventType::PropertyNotify => evt!(Property, PropertyEvent, property),
1046 EventType::SelectionClear => evt!(SelectionClear, SelectionClearEvent, selection_clear),
1047 EventType::SelectionRequest => {
1048 evt!(SelectionRequest, SelectionRequestEvent, selection_request)
1049 }
1050 EventType::SelectionNotify => evt!(Selection, SelectionEvent, selection),
1051 }
1052 }
1053
1054 #[allow(unused_unsafe)]
1055 fn inner(&self) -> Result<xlib::XEvent, FlutterbugError> {
1056 let mut xev: xlib::XEvent = unsafe { mem::zeroed() };
1057
1058 macro_rules! set_evt {
1059 ($item: ident, $field: ident) => {
1060 unsafe { xev.$field = $item.inner()? }
1061 };
1062 }
1063
1064 match *self {
1065 Event::Any(ref a) => set_evt!(a, any),
1066 Event::Button(ref b) => set_evt!(b, button),
1067 Event::Key(ref k) => set_evt!(k, key),
1068 Event::Motion(ref m) => set_evt!(m, motion),
1069 Event::FocusChange(ref f) => set_evt!(f, focus_change),
1070 Event::Crossing(ref c) => set_evt!(c, crossing),
1071 Event::Keymap(ref km) => set_evt!(km, keymap),
1072 Event::Expose(ref e) => set_evt!(e, expose),
1073 Event::GraphicsExpose(ref ge) => set_evt!(ge, graphics_expose),
1074 Event::NoExpose(ref ne) => set_evt!(ne, no_expose),
1075 Event::CirculateRequest(ref ce) => set_evt!(ce, circulate_request),
1076 Event::ConfigureRequest(ref ce) => set_evt!(ce, configure_request),
1077 Event::MapRequest(ref me) => set_evt!(me, map_request),
1078 Event::ResizeRequest(ref rr) => set_evt!(rr, resize_request),
1079 Event::Circulate(ref cn) => set_evt!(cn, circulate),
1080 Event::Configure(ref cn) => set_evt!(cn, configure),
1081 Event::CreateWindow(ref cn) => set_evt!(cn, create_window),
1082 Event::DestroyWindow(ref dn) => set_evt!(dn, destroy_window),
1083 Event::Gravity(ref gn) => set_evt!(gn, gravity),
1084 Event::Map(ref m) => set_evt!(m, map),
1085 Event::Mapping(ref m) => set_evt!(m, mapping),
1086 Event::Reparent(ref r) => set_evt!(r, reparent),
1087 Event::Unmap(ref u) => set_evt!(u, unmap),
1088 Event::Visibility(ref v) => set_evt!(v, visibility),
1089 Event::Colormap(ref c) => set_evt!(c, colormap),
1090 Event::ClientMessage(ref cm) => set_evt!(cm, client_message),
1091 Event::Property(ref p) => set_evt!(p, property),
1092 Event::SelectionClear(ref sc) => set_evt!(sc, selection_clear),
1093 Event::SelectionRequest(ref sr) => set_evt!(sr, selection_request),
1094 Event::Selection(ref sn) => set_evt!(sn, selection),
1095 }
1096
1097 Ok(xev)
1098 }
1099}
1100
1101impl Event {
1102 pub fn next(dpy: &dyn GenericDisplay) -> Result<Event, FlutterbugError> {
1104 let mut xev: xlib::XEvent = unsafe { mem::zeroed() };
1105 unsafe { xlib::XNextEvent(dpy.raw()?.as_mut(), &mut xev) };
1106
1107 Self::from_evstruct(xev)
1108 }
1109
1110 #[inline]
1112 pub fn send(
1113 self,
1114 dpy: &dyn GenericDisplay,
1115 target: &Window,
1116 propogate: bool,
1117 mask: EventMask,
1118 ) -> Result<(), FlutterbugError> {
1119 let mut ev = self.inner()?;
1120 unsafe {
1121 xlib::XSendEvent(
1122 dpy.raw()?.as_mut(),
1123 target.window(),
1124 if propogate { 1 } else { 0 },
1125 mask.bits(),
1126 &mut ev,
1127 )
1128 };
1129 Ok(())
1130 }
1131
1132 #[inline]
1134 pub fn wait_for_map(display: &dyn GenericDisplay) -> Result<(), FlutterbugError> {
1135 'mapwait: loop {
1136 if let Self::Map(_m) = Self::next(display)? {
1137 break 'mapwait;
1138 }
1139 }
1140
1141 Ok(())
1142 }
1143
1144 #[inline]
1146 pub fn filter(&self, window: Option<&Window>) -> Result<bool, FlutterbugError> {
1147 let mut inner = self.inner()?;
1148 Ok(unsafe {
1149 xlib::XFilterEvent(
1150 &mut inner,
1151 match window {
1152 Some(w) => w.window(),
1153 None => 0,
1154 },
1155 )
1156 } != 0)
1157 }
1158}
1159
1160impl DerivesAnEvent for Event {
1161 fn kind(&self) -> EventType {
1162 get_inner_property!(self, kind)
1163 }
1164
1165 fn window(&self) -> xlib::Window {
1166 get_inner_property!(self, window)
1167 }
1168
1169 fn from_send_event(&self) -> bool {
1170 get_inner_property!(self, from_send_event)
1171 }
1172
1173 fn serial(&self) -> c_ulong {
1174 get_inner_property!(self, serial)
1175 }
1176 unsafe fn display(&self) -> NonNull<xlib::Display> {
1177 get_inner_property!(self, display)
1178 }
1179}