diff --git a/Cargo.toml b/Cargo.toml index c13aa0e..a114ddc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ x11 = { version = "2.18" } thiserror = "1.0.20" log = "0.4.8" bitflags = "1.2.1" +derivative = "2.1.1" [build-dependencies] gl_generator = { version = "0.14.0", optional = true } diff --git a/src/lib.rs b/src/lib.rs index 42e5c4e..fa9f188 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,8 @@ #[macro_use] extern crate bitflags; #[macro_use] +extern crate derivative; +#[macro_use] extern crate thiserror; #[macro_use] extern crate log; diff --git a/src/xlib/colormap.rs b/src/xlib/colormap.rs new file mode 100644 index 0000000..29e74db --- /dev/null +++ b/src/xlib/colormap.rs @@ -0,0 +1,17 @@ +use x11::xlib; + +use crate::xlib::{Display, IntoInt}; + +#[derive(Derivative)] +#[derivative(Debug)] +pub struct Colormap<'a> { + #[derivative(Debug = "ignore")] + pub display: &'a Display, + pub inner: xlib::Colormap, +} + +impl<'a> IntoInt for Colormap<'a> { + fn into_int(&self) -> u64 { + self.inner + } +} diff --git a/src/xlib/cursor.rs b/src/xlib/cursor.rs index 2133c20..d9388ef 100644 --- a/src/xlib/cursor.rs +++ b/src/xlib/cursor.rs @@ -1,13 +1,24 @@ use x11::xlib; +use crate::xlib::{Display, IntoInt}; + /// Mouse pointer -pub struct Cursor { - pub(crate) display: *mut xlib::Display, - pub(crate) inner: xlib::Cursor, +#[derive(Derivative)] +#[derivative(Debug)] +pub struct Cursor<'a> { + #[derivative(Debug = "ignore")] + pub display: &'a Display, + pub inner: xlib::Cursor, } -impl Drop for Cursor { +impl<'a> Drop for Cursor<'a> { fn drop(&mut self) { - unsafe { xlib::XFreeCursor(self.display, self.inner) }; + unsafe { xlib::XFreeCursor(self.display.inner, self.inner) }; + } +} + +impl<'a> IntoInt for Cursor<'a> { + fn into_int(&self) -> u64 { + self.inner } } diff --git a/src/xlib/display.rs b/src/xlib/display.rs index 80415c1..861267f 100644 --- a/src/xlib/display.rs +++ b/src/xlib/display.rs @@ -62,7 +62,7 @@ impl Display { return Err(Error::CreateCursorError); } Ok(Cursor { - display: self.inner, + display: self, inner: cursor, }) } diff --git a/src/xlib/image.rs b/src/xlib/image.rs index 71c0c6a..b686d15 100644 --- a/src/xlib/image.rs +++ b/src/xlib/image.rs @@ -15,7 +15,7 @@ use crate::errors::{Error, Result}; /// /// Images consist of lines of longs in row-major form. pub struct Image { - pub(super) inner: *mut xlib::XImage, + pub inner: *mut xlib::XImage, } /// Image byte order @@ -28,26 +28,31 @@ pub enum ImageByteOrder { impl Image { /// Get the size (in bytes) of the data buffer. + #[inline] pub fn get_size(&self) -> usize { 4 * self.get_width() as usize * self.get_height() as usize } /// Get the image width + #[inline] pub fn get_width(&self) -> u32 { unsafe { (*self.inner).width as u32 } } /// Get the image height + #[inline] pub fn get_height(&self) -> u32 { unsafe { (*self.inner).height as u32 } } /// Get the image depth + #[inline] pub fn get_depth(&self) -> u32 { unsafe { (*self.inner).depth as u32 } } /// Get byte order (LSB or MSB) + #[inline] pub fn get_byte_order(&self) -> Result { let byte_order = unsafe { (*self.inner).byte_order }; match byte_order { @@ -109,6 +114,7 @@ impl<'a> PixBuffer<'a> { /// This uses XImage's get_pixel function to retrieve the pixel value, and then the various /// red/green/blue masks to actually perform the conversions, and fails (returns `None`) if the /// (x, y) coordinates given aren't actually in the image. + #[inline] pub fn get_pixel(&self, x: u32, y: u32) -> Option<(u8, u8, u8)> { let get_pixel = unsafe { (*self.image.inner).funcs.get_pixel }.unwrap(); let pixel = unsafe { get_pixel(self.image.inner, x as i32, y as i32) }; diff --git a/src/xlib/mod.rs b/src/xlib/mod.rs index ee1fa23..0d97e9f 100644 --- a/src/xlib/mod.rs +++ b/src/xlib/mod.rs @@ -2,6 +2,7 @@ mod atom; mod cursor; +mod colormap; mod display; mod drawable; mod event; @@ -10,12 +11,61 @@ mod pixmap; mod visual; mod window; +use x11::xlib; + pub use self::atom::Atom; pub use self::cursor::Cursor; pub use self::display::{Display, GetDisplay}; +pub use self::colormap::Colormap; pub use self::drawable::Drawable; pub use self::event::{Event, EventKind}; pub use self::image::{Image, ImageByteOrder, PixBuffer}; +pub use self::pixmap::Pixmap; pub use self::visual::{Visual, VisualInfo}; pub use self::window::{EventMask, SetWindowAttributes, Window, WindowAttributes}; -pub use self::pixmap::PixMap; + +#[derive(Debug)] +pub enum Inherit { + Value(T), + CopyFromParent, +} + +impl Default for Inherit { + fn default() -> Self { + Inherit::CopyFromParent + } +} + +pub trait IntoInt { + fn into_int(&self) -> u64; +} + +impl IntoInt for Inherit { + fn into_int(&self) -> u64 { + match self { + Inherit::Value(t) => t.into_int(), + Inherit::CopyFromParent => xlib::CopyFromParent as u64, + } + } +} + +#[derive(Debug)] +pub enum Noneable { + Value(T), + None, +} + +impl Default for Noneable { + fn default() -> Self { + Noneable::None + } +} + +impl IntoInt for Noneable { + fn into_int(&self) -> u64 { + match self { + Noneable::Value(t) => t.into_int(), + Noneable::None => 0, + } + } +} diff --git a/src/xlib/pixmap.rs b/src/xlib/pixmap.rs index cff4579..2f00f2c 100644 --- a/src/xlib/pixmap.rs +++ b/src/xlib/pixmap.rs @@ -1,5 +1,7 @@ use x11::xlib; +use crate::xlib::{Display, IntoInt}; + /// Pixmaps are off-screen resources that are used for various operations, for /// example, defining cursors as tiling patterns or as the source for certain /// raster operations @@ -7,14 +9,22 @@ use x11::xlib; /// Most graphics requests can operate either on a window or on a pixmap. A /// bitmap is a single bit-plane pixmap. Pixmaps can only be used on the screen /// on which they were created. -#[derive(Debug)] -pub struct PixMap { - pub(crate) display: *mut xlib::Display, +#[derive(Derivative)] +#[derivative(Debug)] +pub struct Pixmap<'a> { + #[derivative(Debug = "ignore")] + pub(crate) display: &'a Display, pub(crate) inner: xlib::Pixmap, } -impl Drop for PixMap { +impl<'a> Drop for Pixmap<'a> { fn drop(&mut self) { - unsafe { xlib::XFreePixmap(self.display, self.inner) }; + unsafe { xlib::XFreePixmap(self.display.inner, self.inner) }; + } +} + +impl<'a> IntoInt for Pixmap<'a> { + fn into_int(&self) -> u64 { + self.inner } } diff --git a/src/xlib/window.rs b/src/xlib/window.rs index eb1b3ea..75063d3 100644 --- a/src/xlib/window.rs +++ b/src/xlib/window.rs @@ -1,23 +1,17 @@ use std::mem; use std::os::raw::{c_long, c_ulong}; -use std::ptr; use x11::xlib; use crate::errors::{Error, Result}; use crate::rect::Rectangle; - -use super::atom::Atom; -use super::display::{Display, GetDisplay}; -use super::drawable::Drawable; -use super::image::Image; -use super::pixmap::PixMap; +use crate::xlib::{Colormap, Atom, Cursor, Display, Drawable, GetDisplay, Image, Inherit, IntoInt, Noneable, Pixmap}; /// A wrapper around a window handle. #[derive(Clone)] pub struct Window<'a> { - pub(crate) display: &'a Display, - pub(crate) inner: xlib::Window, + pub display: &'a Display, + pub inner: xlib::Window, } impl<'a> Window<'a> { @@ -219,38 +213,113 @@ bitflags! { } } -#[derive(Debug, Default)] -pub struct SetWindowAttributes { - pub background_pixmap: Option, +#[derive(Debug)] +pub struct SetWindowAttributes<'a> { + pub background_pixmap: BackgroundPixmap<'a>, pub background_pixel: c_ulong, - pub border_pixmap: Option, + pub border_pixmap: Inherit>, pub border_pixel: c_ulong, + pub bit_gravity: i32, + pub win_gravity: i32, + pub backing_store: BackingStore, + pub backing_planes: u64, + pub backing_pixel: u64, pub save_under: bool, pub event_mask: EventMask, pub do_not_propagate_mask: c_long, pub override_redirect: bool, + pub colormap: Inherit>, + pub cursor: Noneable>, } -impl SetWindowAttributes { +impl<'a> Default for SetWindowAttributes<'a> { + fn default() -> Self { + SetWindowAttributes { + background_pixmap: BackgroundPixmap::default(), + background_pixel: 0, + border_pixmap: Inherit::default(), + border_pixel: 0, + bit_gravity: xlib::ForgetGravity, + win_gravity: xlib::NorthWestGravity, + backing_store: BackingStore::default(), + backing_planes: 0xffffffff, + backing_pixel: 0, + save_under: false, + event_mask: EventMask::empty(), + do_not_propagate_mask: 0, + override_redirect: false, + colormap: Inherit::default(), + cursor: Noneable::default(), + } + } +} + +impl<'a> SetWindowAttributes<'a> { pub fn into_raw(self) -> *mut xlib::XSetWindowAttributes { let result = xlib::XSetWindowAttributes { - background_pixmap: unimplemented!(), + background_pixmap: self.background_pixmap.into_int(), background_pixel: self.background_pixel, - border_pixmap: unimplemented!(), - border_pixel: unimplemented!(), - bit_gravity: unimplemented!(), - win_gravity: unimplemented!(), - backing_store: unimplemented!(), - backing_planes: unimplemented!(), - backing_pixel: unimplemented!(), + border_pixmap: self.border_pixmap.into_int(), + border_pixel: self.border_pixel, + bit_gravity: self.bit_gravity, + win_gravity: self.win_gravity, + backing_store: self.backing_store.into_raw(), + backing_planes: self.backing_planes, + backing_pixel: self.backing_pixel, save_under: self.save_under.into(), event_mask: self.event_mask.bits() as i64, do_not_propagate_mask: self.do_not_propagate_mask, override_redirect: self.override_redirect.into(), - colormap: unimplemented!(), - cursor: unimplemented!(), + colormap: self.colormap.into_int(), + cursor: self.cursor.into_int(), }; Box::into_raw(Box::new(result)) } } + +#[derive(Debug)] +pub enum BackgroundPixmap<'a> { + Background(Pixmap<'a>), + None, + ParentRelative, +} + +impl<'a> Default for BackgroundPixmap<'a> { + fn default() -> Self { + BackgroundPixmap::None + } +} + +impl<'a> IntoInt for BackgroundPixmap<'a> { + fn into_int(&self) -> u64 { + match self { + BackgroundPixmap::Background(pixmap) => pixmap.inner, + BackgroundPixmap::None => 0, + BackgroundPixmap::ParentRelative => xlib::ParentRelative as u64, + } + } +} + +#[derive(Debug)] +pub enum BackingStore { + NotUseful, + WhenMapped, + Always, +} + +impl Default for BackingStore { + fn default() -> Self { + BackingStore::NotUseful + } +} + +impl BackingStore { + fn into_raw(self) -> i32 { + match self { + BackingStore::NotUseful => xlib::NotUseful, + BackingStore::WhenMapped => xlib::WhenMapped, + BackingStore::Always => xlib::Always, + } + } +}