From 3c2c92dd0d61cf72aaa59f81bfc24aba797af724 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Mon, 29 Jun 2020 00:22:13 -0500 Subject: [PATCH] window events --- Cargo.toml | 6 ++++-- src/glx/mod.rs | 15 +++++++++++++++ src/lib.rs | 5 +++++ src/xlib/display.rs | 9 +++++++-- src/xlib/event.rs | 11 ++--------- src/xlib/image.rs | 14 +++++++++++++- src/xlib/mod.rs | 8 +------- src/xlib/window.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 8 files changed, 88 insertions(+), 22 deletions(-) create mode 100644 src/glx/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 4b3406b..e679b8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,10 +13,11 @@ repository = "https://git.sr.ht/~iptq/safex11" all-features = true [features] -default = [] +default = ["xlib"] +glx = ["x11/glx", "xlib"] xlib = ["x11/xlib"] xrender = ["x11/xrender"] -xinerama = ["x11/xlib", "x11/xinerama"] +xinerama = ["x11/xinerama", "xlib"] xinput = ["x11/xinput"] [dependencies] @@ -24,3 +25,4 @@ libc = "0.2" x11 = { version = "2.18" } thiserror = "1.0.20" log = "0.4.8" +bitflags = "1.2.1" diff --git a/src/glx/mod.rs b/src/glx/mod.rs new file mode 100644 index 0000000..1de3256 --- /dev/null +++ b/src/glx/mod.rs @@ -0,0 +1,15 @@ +use x11::glx; + +use crate::errors::Result; +use crate::xlib::Display; + +pub trait GlxExtension { + fn query_glx_extension(&self) -> Result; +} + +impl GlxExtension for Display { + fn query_glx_extension(&self) -> Result { + let result = unsafe { glx::glXQueryExtension(self.inner, 0 as *mut _, 0 as *mut _) }; + Ok(result == 1) + } +} diff --git a/src/lib.rs b/src/lib.rs index f608330..a9fc641 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,7 @@ //! Higher level bindings to x11. +#[macro_use] +extern crate bitflags; #[macro_use] extern crate thiserror; #[macro_use] @@ -7,6 +9,9 @@ extern crate log; pub extern crate x11; +#[cfg(feature = "glx")] +pub mod glx; + #[cfg(feature = "xinput")] pub mod xinput; diff --git a/src/xlib/display.rs b/src/xlib/display.rs index 7ad88dd..a06ff2e 100644 --- a/src/xlib/display.rs +++ b/src/xlib/display.rs @@ -1,5 +1,6 @@ use std::ffi::CString; use std::os::raw::c_char; +use std::mem::MaybeUninit; use std::ptr; use x11::xlib; @@ -68,9 +69,13 @@ impl Display { /// Get the next event, blocks until an event is reached. pub fn next_event(&self) -> Result { - let event = ptr::null_mut(); - unsafe { xlib::XNextEvent(self.inner, event) }; + debug!("fishing for next event..."); + let mut event = MaybeUninit::uninit(); + let ptr = event.as_mut_ptr(); + unsafe { xlib::XNextEvent(self.inner, ptr) }; // TODO: check to make sure this isn't null + let mut event = unsafe{event.assume_init()}; + debug!("event: {:?}", event); unsafe { Event::from_raw(event) } } diff --git a/src/xlib/event.rs b/src/xlib/event.rs index 8bc6f45..bed1819 100644 --- a/src/xlib/event.rs +++ b/src/xlib/event.rs @@ -5,7 +5,7 @@ use crate::errors::{Error, Result}; /// An x11 Event #[derive(Debug)] pub struct Event { - inner: *mut xlib::XEvent, + inner: xlib::XEvent, kind: EventKind, } @@ -22,9 +22,8 @@ impl Event { &self.kind } - pub(super) unsafe fn from_raw(event: *mut xlib::XEvent) -> Result { + pub(super) unsafe fn from_raw(event: xlib::XEvent) -> Result { let inner = event; - let event = unsafe { *event }; debug!("event type: {:?}", event.type_); let kind = match event.type_ { xlib::KeyPress => EventKind::KeyPress(KeyEvent(event.key)), @@ -35,11 +34,5 @@ impl Event { } } -impl Drop for Event { - fn drop(&mut self) { - unsafe { libc::free(self.inner as *mut libc::c_void) }; - } -} - #[derive(Debug)] pub struct KeyEvent(xlib::XKeyEvent); diff --git a/src/xlib/image.rs b/src/xlib/image.rs index 227e902..15636aa 100644 --- a/src/xlib/image.rs +++ b/src/xlib/image.rs @@ -1,4 +1,16 @@ -use std::os::raw::c_ulong; +//! XImage +//! ====== +//! +//! Xlib provides some structures to perform operations on images. However, because there are +//! different in-memory representations, working with images is actually totally fucked. If you +//! want to maintain your sanity, do NOT pry into the raw data buffer of an Image. Instead, index +//! into the image using `PixBuffer::get_pixel` which already performs the conversion and returns a +//! tuple of RGB values. +//! +//! Peeking into the raw data buffer of an Image +//! -------------------------------------------- +//! +//! Images consist of lines of longs in row-major form. use x11::xlib; diff --git a/src/xlib/mod.rs b/src/xlib/mod.rs index e7d6f24..984653a 100644 --- a/src/xlib/mod.rs +++ b/src/xlib/mod.rs @@ -14,10 +14,4 @@ pub use self::drawable::Drawable; pub use self::event::{Event, EventKind}; pub use self::image::{Image, ImageByteOrder}; pub use self::visual::Visual; -pub use self::window::Window; - -pub const XC_crosshair: u32 = 34; -pub const XC_ll_angle: u32 = 76; -pub const XC_lr_angle: u32 = 78; -pub const XC_ul_angle: u32 = 144; -pub const XC_ur_angle: u32 = 148; +pub use self::window::{EventMask, Window}; diff --git a/src/xlib/window.rs b/src/xlib/window.rs index 80565b0..18ee13e 100644 --- a/src/xlib/window.rs +++ b/src/xlib/window.rs @@ -1,4 +1,5 @@ use std::mem; +use std::os::raw::c_ulong; use x11::xlib; @@ -112,10 +113,18 @@ impl Window { } } - /// Map to display + /// "Maps", or shows a window to a display. pub fn map(&self) { unsafe { xlib::XMapWindow(self.display, self.inner) }; } + + /// Requests for events from the server matching a particular event mask. + /// + /// If this function is not called, events will not be reported. + pub fn select_input(&self, event_mask: EventMask) { + debug!("event mask: {:?}", event_mask); + unsafe { xlib::XSelectInput(self.display, self.inner, event_mask.bits as i64) }; + } } impl GetDisplay for Window { @@ -183,3 +192,34 @@ impl Drop for WindowAttributes { unsafe { libc::free(self.inner as *mut libc::c_void) }; } } + +bitflags! { + pub struct EventMask: c_ulong { + const NO_EVENT_MASK = 0; + const KEY_PRESS_MASK = (1<<0); + const KEY_RELEASE_MASK = (1<<1); + const BUTTON_PRESS_MASK = (1<<2); + const BUTTON_RELEASE_MASK = (1<<3); + const ENTER_WINDOW_MASK = (1<<4); + const LEAVE_WINDOW_MASK = (1<<5); + const POINTER_MOTION_MASK = (1<<6); + const POINTER_MOTION_HINT_MASK = (1<<7); + const BUTTON_1_MOTION_MASK = (1<<8); + const BUTTON_2_MOTION_MASK = (1<<9); + const BUTTON_3_MOTION_MASK = (1<<10); + const BUTTON_4_MOTION_MASK = (1<<11); + const BUTTON_5_MOTION_MASK = (1<<12); + const BUTTON_MOTION_MASK = (1<<13); + const KEYMAP_STATE_MASK = (1<<14); + const EXPOSURE_MASK = (1<<15); + const VISIBILITY_CHANGE_MASK = (1<<16); + const STRUCTURE_NOTIFY_MASK = (1<<17); + const RESIZE_REDIRECT_MASK = (1<<18); + const SUBSTRUCTURE_NOTIFY_MASK = (1<<19); + const SUBSTRUCTURE_REDIRECT_MASK = (1<<20); + const FOCUS_CHANGE_MASK = (1<<21); + const PROPERTY_CHANGE_MASK = (1<<22); + const COLORMAP_CHANGE_MASK = (1<<23); + const OWNER_GRAB_BUTTON_MASK = (1<<24); + } +}