From 89a6a257f89bba997e778160c53938be371ec6ac Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Wed, 11 Nov 2026 20:39:00 -0700 Subject: graphics contexts! with RAII! much trait refactoring the way forward to structure this cleanly is clear now, as well, but not implemented yet Force-Push: yes Change-Id: Ib3905edcfd49bf19d0fa7e4285f2edfed312d539 --- src/main.rs | 57 +++++++++++++++++++++++++++++++++++++++++++++++++-------- src/xcontext.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/xtypes.rs | 29 ++++++++++++++++++++--------- 3 files changed, 113 insertions(+), 17 deletions(-) create mode 100644 src/xcontext.rs (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 2c07e95..57eabf0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use crate::xtypes::*; use crate::xcolor::DisplayColorExt; +use crate::xcontext::GraphicContext; use std::sync::Arc; @@ -8,12 +9,16 @@ use xcb::x::{ self, ClientMessageData, Cw, CreateWindow, + CreateGc, FreeGc, + Drawable, EventMask, + PolyFillRectangle, Screen, WindowClass }; mod xcolor; +mod xcontext; mod xtypes; @@ -29,6 +34,7 @@ struct DockConfiguration { struct Dock { configuration: DockConfiguration, window: Window, + bounds: Arc>, } impl HasWindow for Dock { @@ -52,7 +58,7 @@ fn main() -> xcb::Result<()> { // #d4ffcc let background_pixel = display.allocate_color(54484, 65535, 52428)?; - let _dock = Dock::new(Arc::clone(&display), DockConfiguration { + let dock = Dock::new(Arc::clone(&display), DockConfiguration { thickness: 50, side: ScreenSide::Bottom, background_pixel, @@ -60,6 +66,10 @@ fn main() -> xcb::Result<()> { loop { match display.wait_for_event()? { + xcb::Event::X(x::Event::Expose(_event)) => { + let _ = dock.redraw(); // TODO + } + xcb::Event::X(x::Event::ButtonPress(event)) => { println!("click {:?}", event); } @@ -88,7 +98,6 @@ impl Dock { let dock_bounds = Dock::compute_bounds(&screen, &configuration); - println!("back pixel {:?}", configuration.background_pixel); let window = Window::new(Arc::clone(&display), &mut CreateWindow { depth: x::COPY_FROM_PARENT as u8, wid: x::Window::none(), @@ -105,15 +114,15 @@ impl Dock { Cw::EventMask(EventMask::EXPOSURE | EventMask::BUTTON_PRESS), ], })?; - let dock = Dock { window, configuration }; + let dock = Dock { window, configuration, bounds: Arc::new(dock_bounds) }; - dock.set_string_property(&x::ATOM_WM_NAME, b"grass bar")?; + dock.set_string_property(&x::ATOM_WM_NAME, b"sandbar")?; - dock.set_atom_property(&display.atoms().wm_protocols, - &[display.atoms().wm_delete_window])?; + dock.set_atom_property(&dock.atoms().wm_protocols, + &[dock.atoms().wm_delete_window])?; - dock.set_atom_property(&display.atoms().wm_type, - &[display.atoms().wm_type_dock])?; + dock.set_atom_property(&dock.atoms().wm_type, + &[dock.atoms().wm_type_dock])?; dock.set_strut_properties(&screen)?; @@ -197,5 +206,37 @@ impl Dock { Rectangle { left, top, width, height } } } + + + fn redraw(&self) -> xcb::Result<()> { + println!("redraw"); + + let drawable = Drawable::Window(self.window_id()); + let _context = GraphicContext::new(Arc::clone(self.display()), + drawable); + + /* + let black = self.screen().black_pixel(); + + let cookie = connection.send_request_checked(&PolyFillRectangle { + drawable: Drawable::Window(self.window_id()), + property: *property, + r#type: x::ATOM_CARDINAL, + data: values, + }); + connection.check_request(cookie)?; + */ + + Ok(()) + } +} + +impl HasDisplay for Dock { + fn display(&self) -> &Arc { self.window.display() } } +impl HasConnection for Dock { + fn connection(&self) -> &Connection { self.window.connection() } +} + + diff --git a/src/xcontext.rs b/src/xcontext.rs new file mode 100644 index 0000000..d9543f7 --- /dev/null +++ b/src/xcontext.rs @@ -0,0 +1,44 @@ +use crate::xtypes::*; + +use std::sync::Arc; + +use xcb::x::{ self, Drawable, CreateGc, FreeGc }; + + +pub struct GraphicContext { + display: Arc, + context_id: x::Gcontext, +} + + +impl GraphicContext { + pub fn new(display: Arc, drawable: Drawable) + -> xcb::Result + { + let context_id: x::Gcontext = display.generate_id(); + let cookie = display.send_request_checked(&CreateGc { + cid: context_id, + drawable, + value_list: &[], + }); + display.check_request(cookie)?; + + Ok(GraphicContext { display, context_id }) + } +} + +impl Drop for GraphicContext { + fn drop(&mut self) { + let cookie = self.send_request_checked(&FreeGc { gc: self.context_id }); + let _ = self.check_request(cookie); // TODO + } +} + +impl HasDisplay for GraphicContext { + fn display(&self) -> &Arc { &self.display } +} + +impl HasConnection for GraphicContext { + fn connection(&self) -> &Connection { self.display.connection() } +} + diff --git a/src/xtypes.rs b/src/xtypes.rs index 3f67e58..89bb622 100644 --- a/src/xtypes.rs +++ b/src/xtypes.rs @@ -2,6 +2,7 @@ use std::borrow::Borrow; use std::sync::Arc; use std::ops::Deref; +use xcb::XidNew; use xcb::x::{ self, Atom, @@ -10,7 +11,7 @@ use xcb::x::{ InternAtom, MapWindow, PropMode, - Screen + Screen, }; @@ -72,7 +73,7 @@ impl Window { let display_ref: &Display = display.borrow(); let connection: &Connection = &display_ref.connection; - let window_id: x::Window = connection.0.generate_id(); + let window_id: x::Window = connection.generate_id(); create_window.wid = window_id; let cookie = connection.send_request_checked(create_window); @@ -136,27 +137,37 @@ impl HasConnection for Connection { fn connection(&self) -> &Connection { self } } -impl HasConnection for T { - fn connection(&self) -> &Connection { &self.display().connection } +impl HasConnection for Arc { + fn connection(&self) -> &Connection { &self.connection } +} + +impl HasConnection for Window { + fn connection(&self) -> &Connection { &self.display.connection } } pub trait HasDisplay { - fn display(&self) -> &Display; + fn display(&self) -> &Arc; fn atoms(&self) -> &Atoms { &self.display().atoms } } -impl HasDisplay for Display { - fn display(&self) -> &Display { self } +impl HasDisplay for Arc { + fn display(&self) -> &Arc { self } } -impl HasDisplay for T { - fn display(&self) -> &Display { self.window().display.borrow() } +impl HasDisplay for Window { + fn display(&self) -> &Arc { &self.display } } pub trait ConnectionExt: HasConnection { + fn generate_id(&self) -> T { + let connection = self.connection(); + + connection.0.generate_id() + } + fn get_atom(&self, name: &[u8]) -> xcb::Result { let connection = self.connection(); -- cgit 1.4.1