From cc1bed1f1f3e26a6a00b292ace94b6991c181ff9 Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Wed, 11 Nov 2026 09:25:10 -0700 Subject: now it's in two files Force-Push: yes Change-Id: I43fdbd0769fa61ef4e5d6ea053fa210175e47d6a --- src/main.rs | 371 ++++++++++++---------------------------------------------- src/xtypes.rs | 269 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 347 insertions(+), 293 deletions(-) create mode 100644 src/xtypes.rs (limited to 'src') diff --git a/src/main.rs b/src/main.rs index c80fdb8..436fcfa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,202 +1,18 @@ -use std::borrow::Borrow; +use crate::xtypes::*; + use std::sync::Arc; -use std::ops::Deref; use xcb::{ Xid }; use xcb::x::{ self, - Atom, - ChangeProperty, ClientMessageData, Cw, CreateWindow, EventMask, - InternAtom, - MapWindow, - PropMode, Screen, WindowClass }; - -struct Connection(xcb::Connection); - -struct Display { - connection: Connection, - screen_index: i32, - atoms: Atoms, -} - -struct Window { - display: Arc, - window_id: x::Window, -} - - -trait HasWindow { - fn window(&self) -> &Window; - - fn window_id(&self) -> x::Window { self.window().window_id } -} - -impl HasWindow for Window { - fn window(&self) -> &Window { self } -} - -impl> HasWindow for T { - fn window(&self) -> &Window { &*self } -} - - -trait HasConnection { - fn connection(&self) -> &Connection; -} - -impl HasConnection for Connection { - fn connection(&self) -> &Connection { self } -} - -impl HasConnection for T { - fn connection(&self) -> &Connection { &self.display().connection } -} - - -trait HasDisplay { - fn display(&self) -> &Display; - - fn atoms(&self) -> &Atoms { &self.display().atoms } -} - -impl HasDisplay for Display { - fn display(&self) -> &Display { self } -} - -impl HasDisplay for T { - fn display(&self) -> &Display { self.window().display.borrow() } -} - - -trait ConnectionExt: HasConnection { - fn get_atom(&self, name: &[u8]) -> xcb::Result { - let connection = self.connection(); - - let cookie = connection.0.send_request(&InternAtom { - only_if_exists: true, - name: name, - }); - - Ok(connection.0.wait_for_reply(cookie)?.atom()) - } - - fn get_atoms(&self) -> xcb::Result { - let wm_protocols = self.get_atom(b"WM_PROTOCOLS")?; - let wm_delete_window = self.get_atom(b"WM_DELETE_WINDOW")?; - - let wm_type = self.get_atom(b"_NET_WM_WINDOW_TYPE")?; - let wm_type_dock = self.get_atom(b"_NET_WM_WINDOW_TYPE_DOCK")?; - - let wm_strut = self.get_atom(b"_NET_WM_STRUT")?; - let wm_strut_partial = self.get_atom(b"_NET_WM_STRUT_PARTIAL")?; - - Ok(Atoms { - wm_protocols, wm_delete_window, - wm_type, wm_type_dock, - wm_strut, wm_strut_partial, - }) - } -} - -impl ConnectionExt for T { } - - -trait DisplayExt: HasDisplay + HasConnection { - fn screen(&self) -> &Screen { - let setup = self.connection().0.get_setup(); - let screen_index = self.display().screen_index as usize; - - &setup.roots().nth(screen_index).unwrap() - } -} - -impl DisplayExt for T { } - - -trait WindowExt: HasWindow + HasDisplay + HasConnection { - fn map_window(&self) -> xcb::Result<()> { - let display = self.display(); - - let cookie = display.connection.0.send_request_checked(&MapWindow { - window: self.window_id() - }); - display.connection.0.check_request(cookie)?; - - Ok(()) - } - - fn set_string_property(&self, property: &Atom, value: &[u8]) - -> xcb::Result<()> - { - let connection = self.connection(); - - let cookie = connection.0.send_request_checked(&ChangeProperty { - mode: PropMode::Replace, - window: self.window_id(), - property: *property, - r#type: x::ATOM_STRING, - data: value, - }); - connection.0.check_request(cookie)?; - - Ok(()) - } - - - fn set_atom_property(&self, property: &Atom, values: &[Atom]) - -> xcb::Result<()> - { - let connection = self.connection(); - - let cookie = connection.0.send_request_checked(&ChangeProperty { - mode: PropMode::Replace, - window: self.window_id(), - property: *property, - r#type: x::ATOM_ATOM, - data: values, - }); - connection.0.check_request(cookie)?; - - Ok(()) - } - - - fn set_cardinal_property(&self, property: &Atom, values: &[u32]) - -> xcb::Result<()> - { - let connection = self.connection(); - - let cookie = connection.0.send_request_checked(&ChangeProperty { - mode: PropMode::Replace, - window: self.window_id(), - property: *property, - r#type: x::ATOM_CARDINAL, - data: values, - }); - connection.0.check_request(cookie)?; - - Ok(()) - } -} - -impl WindowExt for T { } - - -struct Atoms { - wm_protocols: Atom, - wm_delete_window: Atom, - wm_type: Atom, - wm_type_dock: Atom, - wm_strut: Atom, - wm_strut_partial: Atom, -} +mod xtypes; #[derive(Clone, Copy, PartialEq, Eq)] @@ -226,35 +42,6 @@ struct Rectangle { } -impl Display { - fn new() -> xcb::Result { - let (connection, screen_index) = xcb::Connection::connect(None)?; - let connection = Connection(connection); - - let atoms = connection.get_atoms()?; - - Ok(Display { connection, screen_index, atoms }) - } -} - - -impl Window { - fn new(display: Arc, create_window: &mut CreateWindow) - -> xcb::Result - { - let display_ref: &Display = display.borrow(); - let connection: &Connection = &display_ref.connection; - - let window_id: x::Window = connection.0.generate_id(); - - create_window.wid = window_id; - let cookie = connection.0.send_request_checked(create_window); - connection.0.check_request(cookie)?; - - Ok(Window { display, window_id }) - } -} - fn main() -> xcb::Result<()> { let display = Arc::new(Display::new()?); @@ -265,14 +52,14 @@ fn main() -> xcb::Result<()> { })?; loop { - match display.connection.0.wait_for_event()? { + match display.wait_for_event()? { xcb::Event::X(x::Event::ButtonPress(event)) => { println!("click {:?}", event); } xcb::Event::X(x::Event::ClientMessage(event)) => { if let ClientMessageData::Data32([atom, ..]) = event.data() { - if atom == display.atoms.wm_delete_window.resource_id() { + if atom == display.atoms().wm_delete_window.resource_id() { break; } } @@ -292,7 +79,7 @@ impl Dock { { let screen = display.screen(); - let dock_bounds = compute_dock_bounds(&screen, &configuration); + let dock_bounds = Dock::compute_bounds(&screen, &configuration); let window = Window::new(Arc::clone(&display), &mut CreateWindow { depth: x::COPY_FROM_PARENT as u8, @@ -314,96 +101,94 @@ impl Dock { dock.set_string_property(&x::ATOM_WM_NAME, b"grass bar")?; - dock.set_atom_property(&display.atoms.wm_protocols, - &[display.atoms.wm_delete_window])?; + dock.set_atom_property(&display.atoms().wm_protocols, + &[display.atoms().wm_delete_window])?; - dock.set_atom_property(&display.atoms.wm_type, - &[display.atoms.wm_type_dock])?; + dock.set_atom_property(&display.atoms().wm_type, + &[display.atoms().wm_type_dock])?; - set_dock_strut_properties(&dock, &screen)?; + dock.set_strut_properties(&screen)?; dock.map_window()?; Ok(dock) } -} -fn compute_dock_bounds(screen: &Screen, configuration: &DockConfiguration) - -> Rectangle -{ - if configuration.side == ScreenSide::Top - || configuration.side == ScreenSide::Bottom - { - let left = 0; - let width = screen.width_in_pixels(); - let height = configuration.thickness; + fn set_strut_properties(&self, screen: &Screen) -> xcb::Result<()> { + let atoms = self.atoms(); - let top = if configuration.side == ScreenSide::Bottom { - screen.height_in_pixels() - height - } else { 0 }; + let thickness = self.configuration.thickness as u32; - Rectangle { left, top, width, height } - } else { - let top = 0; - let height = screen.height_in_pixels(); - let width = configuration.thickness; + let strut_values = match self.configuration.side { + ScreenSide::Left => &[thickness, 0 as u32, 0 as u32, 0 as u32], + ScreenSide::Right => &[0 as u32, thickness, 0 as u32, 0 as u32], + ScreenSide::Top => &[0 as u32, 0 as u32, thickness, 0 as u32], + ScreenSide::Bottom => &[0 as u32, 0 as u32, 0 as u32, thickness], + }; + self.set_cardinal_property(&atoms.wm_strut, strut_values)?; - let left = if configuration.side == ScreenSide::Right { - screen.width_in_pixels() - width - } else { 0 }; + let strut_partial_values = &[ + strut_values[0], + strut_values[1], + strut_values[2], + strut_values[3], - Rectangle { left, top, width, height } - } -} + 0 as u32, + if self.configuration.side == ScreenSide::Left { + screen.height_in_pixels() as u32 + } else { 0 as u32 }, + + 0 as u32, + if self.configuration.side == ScreenSide::Right { + screen.height_in_pixels() as u32 + } else { 0 as u32 }, + + 0 as u32, + if self.configuration.side == ScreenSide::Top { + screen.width_in_pixels() as u32 + } else { 0 as u32 }, + 0 as u32, + if self.configuration.side == ScreenSide::Bottom { + screen.width_in_pixels() as u32 + } else { 0 as u32 }, + ]; -fn set_dock_strut_properties(dock: &Dock, screen: &Screen) - -> xcb::Result<()> -{ - let window = dock.window(); - let atoms = dock.atoms(); - - let thickness = dock.configuration.thickness as u32; - - let strut_values = match dock.configuration.side { - ScreenSide::Left => &[thickness, 0 as u32, 0 as u32, 0 as u32], - ScreenSide::Right => &[0 as u32, thickness, 0 as u32, 0 as u32], - ScreenSide::Top => &[0 as u32, 0 as u32, thickness, 0 as u32], - ScreenSide::Bottom => &[0 as u32, 0 as u32, 0 as u32, thickness], - }; - window.set_cardinal_property(&atoms.wm_strut, strut_values)?; - - let strut_partial_values = &[ - strut_values[0], - strut_values[1], - strut_values[2], - strut_values[3], - - 0 as u32, - if dock.configuration.side == ScreenSide::Left { - screen.height_in_pixels() as u32 - } else { 0 as u32 }, - - 0 as u32, - if dock.configuration.side == ScreenSide::Right { - screen.height_in_pixels() as u32 - } else { 0 as u32 }, - - 0 as u32, - if dock.configuration.side == ScreenSide::Top { - screen.width_in_pixels() as u32 - } else { 0 as u32 }, - - 0 as u32, - if dock.configuration.side == ScreenSide::Bottom { - screen.width_in_pixels() as u32 - } else { 0 as u32 }, - ]; - - window.set_cardinal_property(&atoms.wm_strut_partial, + self.set_cardinal_property(&atoms.wm_strut_partial, strut_partial_values)?; - Ok(()) + Ok(()) + } + + + fn compute_bounds(screen: &Screen, configuration: &DockConfiguration) + -> Rectangle + { + if configuration.side == ScreenSide::Top + || configuration.side == ScreenSide::Bottom + { + let left = 0; + let width = screen.width_in_pixels(); + let height = configuration.thickness; + + let top = if configuration.side == ScreenSide::Bottom { + screen.height_in_pixels() - height + } else { 0 }; + + Rectangle { left, top, width, height } + } else { + let top = 0; + let height = screen.height_in_pixels(); + let width = configuration.thickness; + + let left = if configuration.side == ScreenSide::Right { + screen.width_in_pixels() - width + } else { 0 }; + + Rectangle { left, top, width, height } + } + } + } diff --git a/src/xtypes.rs b/src/xtypes.rs new file mode 100644 index 0000000..3f67e58 --- /dev/null +++ b/src/xtypes.rs @@ -0,0 +1,269 @@ +use std::borrow::Borrow; +use std::sync::Arc; +use std::ops::Deref; + +use xcb::x::{ + self, + Atom, + ChangeProperty, + CreateWindow, + InternAtom, + MapWindow, + PropMode, + Screen +}; + + +pub struct Atoms { + pub wm_protocols: Atom, + pub wm_delete_window: Atom, + pub wm_type: Atom, + pub wm_type_dock: Atom, + pub wm_strut: Atom, + pub wm_strut_partial: Atom, +} + + +pub struct Connection(xcb::Connection); + +pub struct Display { + connection: Connection, + screen_index: i32, + atoms: Atoms, +} + +pub struct Window { + display: Arc, + window_id: x::Window, +} + + +impl Connection { + pub fn connect(display_name: Option<&str>) + -> xcb::ConnResult<(Connection, i32)> + { + let (connection, screen_index) + = xcb::Connection::connect(display_name)?; + + Ok((Connection(connection), screen_index)) + } +} + + +impl Display { + pub fn new() -> xcb::Result { + let (connection, screen_index) = Connection::connect(None)?; + + let atoms = connection.get_atoms()?; + + Ok(Display { connection, screen_index, atoms }) + } + + pub fn screen_index(&self) -> i32 { + self.screen_index + } +} + + +impl Window { + pub fn new(display: Arc, create_window: &mut CreateWindow) + -> xcb::Result + { + let display_ref: &Display = display.borrow(); + let connection: &Connection = &display_ref.connection; + + let window_id: x::Window = connection.0.generate_id(); + + create_window.wid = window_id; + let cookie = connection.send_request_checked(create_window); + connection.check_request(cookie)?; + + Ok(Window { display, window_id }) + } +} + + +pub trait HasWindow { + fn window(&self) -> &Window; + + fn window_id(&self) -> x::Window { self.window().window_id } +} + +impl HasWindow for Window { + fn window(&self) -> &Window { self } +} + +impl> HasWindow for T { + fn window(&self) -> &Window { &*self } +} + + +pub trait HasConnection { + fn connection(&self) -> &Connection; + + fn get_setup(&self) -> &xcb::x::Setup { + self.connection().0.get_setup() + } + + fn send_request(&self, request: &R) -> R::Cookie { + self.connection().0.send_request(request) + } + + fn wait_for_reply(&self, cookie: C) + -> xcb::Result + { + self.connection().0.wait_for_reply(cookie) + } + + fn send_request_checked(&self, request: &R) + -> xcb::VoidCookieChecked + { + self.connection().0.send_request_checked(request) + } + + fn check_request(&self, cookie: xcb::VoidCookieChecked) + -> xcb::ProtocolResult<()> + { + self.connection().0.check_request(cookie) + } + + fn wait_for_event(&self) -> xcb::Result { + self.connection().0.wait_for_event() + } +} + +impl HasConnection for Connection { + fn connection(&self) -> &Connection { self } +} + +impl HasConnection for T { + fn connection(&self) -> &Connection { &self.display().connection } +} + + +pub trait HasDisplay { + fn display(&self) -> &Display; + + fn atoms(&self) -> &Atoms { &self.display().atoms } +} + +impl HasDisplay for Display { + fn display(&self) -> &Display { self } +} + +impl HasDisplay for T { + fn display(&self) -> &Display { self.window().display.borrow() } +} + + +pub trait ConnectionExt: HasConnection { + fn get_atom(&self, name: &[u8]) -> xcb::Result { + let connection = self.connection(); + + let cookie = connection.send_request(&InternAtom { + only_if_exists: true, + name: name, + }); + + Ok(connection.wait_for_reply(cookie)?.atom()) + } + + fn get_atoms(&self) -> xcb::Result { + let wm_protocols = self.get_atom(b"WM_PROTOCOLS")?; + let wm_delete_window = self.get_atom(b"WM_DELETE_WINDOW")?; + + let wm_type = self.get_atom(b"_NET_WM_WINDOW_TYPE")?; + let wm_type_dock = self.get_atom(b"_NET_WM_WINDOW_TYPE_DOCK")?; + + let wm_strut = self.get_atom(b"_NET_WM_STRUT")?; + let wm_strut_partial = self.get_atom(b"_NET_WM_STRUT_PARTIAL")?; + + Ok(Atoms { + wm_protocols, wm_delete_window, + wm_type, wm_type_dock, + wm_strut, wm_strut_partial, + }) + } +} + +impl ConnectionExt for T { } + + +pub trait DisplayExt: HasDisplay + HasConnection { + fn screen(&self) -> &Screen { + let setup = self.connection().get_setup(); + let screen_index = self.display().screen_index() as usize; + + &setup.roots().nth(screen_index).unwrap() + } +} + +impl DisplayExt for T { } + + +pub trait WindowExt: HasWindow + HasDisplay + HasConnection { + fn map_window(&self) -> xcb::Result<()> { + let cookie = self.send_request_checked(&MapWindow { + window: self.window_id() + }); + self.check_request(cookie)?; + + Ok(()) + } + + fn set_string_property(&self, property: &Atom, value: &[u8]) + -> xcb::Result<()> + { + let connection = self.connection(); + + let cookie = connection.send_request_checked(&ChangeProperty { + mode: PropMode::Replace, + window: self.window_id(), + property: *property, + r#type: x::ATOM_STRING, + data: value, + }); + connection.check_request(cookie)?; + + Ok(()) + } + + + fn set_atom_property(&self, property: &Atom, values: &[Atom]) + -> xcb::Result<()> + { + let connection = self.connection(); + + let cookie = connection.send_request_checked(&ChangeProperty { + mode: PropMode::Replace, + window: self.window_id(), + property: *property, + r#type: x::ATOM_ATOM, + data: values, + }); + connection.check_request(cookie)?; + + Ok(()) + } + + + fn set_cardinal_property(&self, property: &Atom, values: &[u32]) + -> xcb::Result<()> + { + let connection = self.connection(); + + let cookie = connection.send_request_checked(&ChangeProperty { + mode: PropMode::Replace, + window: self.window_id(), + property: *property, + r#type: x::ATOM_CARDINAL, + data: values, + }); + connection.check_request(cookie)?; + + Ok(()) + } +} + +impl WindowExt for T { } + -- cgit 1.4.1