From 970c59edee837356ef9c709f0ed938bef41d4b81 Mon Sep 17 00:00:00 2001 From: chlorospingus Date: Thu, 24 Apr 2025 22:38:25 -0700 Subject: [PATCH] Bind wlr layer shell global and get layer surface --- src/layer_shell.rs | 31 +++++++++++++++++++++++++++++++ src/main.rs | 1 + src/surface.rs | 12 +++++++----- src/vec_utils.rs | 1 + src/wl_client.rs | 38 ++++++++++++++++++++------------------ src/wl_registry.rs | 46 ++++++++++++++++++++++++++++++++-------------- 6 files changed, 92 insertions(+), 37 deletions(-) create mode 100644 src/layer_shell.rs diff --git a/src/layer_shell.rs b/src/layer_shell.rs new file mode 100644 index 0000000..50c8f13 --- /dev/null +++ b/src/layer_shell.rs @@ -0,0 +1,31 @@ +use std::{error::Error, io::Write}; +use crate::{surface::UnsetErr, vec_utils::WlMessage, WlClient}; + +const NAMESPACE: &str = "chlorostart"; +const OVERLAY: u32 = 3; + +impl WlClient { + pub fn layer_shell_get_layer_surface(&mut self) -> Result<(), Box> { + let object: u32 = self.layer_shell_id.unwrap(); + const OPCODE: u16 = 0; + let msg_size: u16 = 28 + (NAMESPACE.len()+1).next_multiple_of(4) as u16; + let mut request = vec![0u8; msg_size as usize]; + let mut offset: usize = 0; + let output: u32 = 0; + + request.write_u32(&object, &mut offset); + request.write_u16(&OPCODE, &mut offset); + request.write_u16(&msg_size, &mut offset); + + self.current_id += 1; + request.write_u32(&self.current_id, &mut offset); + request.write_u32(&self.surface_id.unwrap(), &mut offset); + request.write_u32(&output, &mut offset); + request.write_u32(&OVERLAY, &mut offset); + request.write_string(&NAMESPACE.to_string(), &mut offset); + + self.socket.write(&request)?; + + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index 9aa9f8d..101f7c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ mod wl_shm; mod vec_utils; mod shm; mod surface; +mod layer_shell; use wl_client::WlClient; fn main() -> Result<(), Box> { diff --git a/src/surface.rs b/src/surface.rs index c28163b..2ab7ade 100644 --- a/src/surface.rs +++ b/src/surface.rs @@ -2,20 +2,22 @@ use std::{error::Error, io::Write}; use crate::{vec_utils::WlMessage, WlClient}; +use std::fmt; + #[derive(Debug)] -pub struct UnsetErr (String); +pub struct UnsetErr (pub String); impl Error for UnsetErr {} -impl std::fmt::Display for UnsetErr { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{} not set!", self.0) +impl fmt::Display for UnsetErr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{} is not set!", self.0) } } impl WlClient { pub fn wl_compositor_create_surface(&mut self) -> Result<(), Box> { if self.compositor_id.is_none() { - return Err(Box::new(UnsetErr("compositor_id".to_string()))); + return Err(UnsetErr("compositor_id".to_string()).into()); } let object = self.compositor_id.unwrap(); diff --git a/src/vec_utils.rs b/src/vec_utils.rs index 8b97d66..dbb6695 100644 --- a/src/vec_utils.rs +++ b/src/vec_utils.rs @@ -28,6 +28,7 @@ impl WlMessage for Vec { } fn write_string(&mut self, str: &String, offset: &mut usize) { + // TODO: Don't clone str, use &str instead of &String let mut str = str.clone(); str.push('\0'); let rounded_len: u32 = (str.len()+3) as u32 & (u32::MAX-3); diff --git a/src/wl_client.rs b/src/wl_client.rs index 9cf812f..8b7a73d 100644 --- a/src/wl_client.rs +++ b/src/wl_client.rs @@ -9,15 +9,16 @@ struct WlHeader { } pub struct WlClient { - pub socket: UnixStream, - pub current_id: u32, - pub registry_id: Option, - pub shm_id: Option, - pub shm_pool: Option, - pub buffer_id: Option, - pub compositor_id: Option, - pub surface_id: Option, - pub xdg_wm_base_id: Option, + pub socket: UnixStream, + pub current_id: u32, + pub registry_id: Option, + pub shm_id: Option, + pub shm_pool: Option, + pub buffer_id: Option, + pub compositor_id: Option, + pub surface_id: Option, + pub xdg_wm_base_id: Option, + pub layer_shell_id: Option, } impl WlClient { @@ -29,15 +30,16 @@ impl WlClient { ))?; let res = WlClient { - socket: sock, - current_id: 1, - registry_id: None, - shm_id: None, - shm_pool: None, - buffer_id: None, - compositor_id: None, - surface_id: None, - xdg_wm_base_id: None, + socket: sock, + current_id: 1, + registry_id: None, + shm_id: None, + shm_pool: None, + buffer_id: None, + compositor_id: None, + surface_id: None, + xdg_wm_base_id: None, + layer_shell_id: None, }; Ok(res) diff --git a/src/wl_registry.rs b/src/wl_registry.rs index bc6fae8..c9655f3 100644 --- a/src/wl_registry.rs +++ b/src/wl_registry.rs @@ -1,15 +1,27 @@ -use crate::{WlClient, vec_utils::WlMessage}; +use crate::{surface::UnsetErr, vec_utils::WlMessage, WlClient}; use std::{io::Write, error::Error}; impl WlClient { fn init_toplevel(&mut self) -> Result<(), Box> { - println!("----> shm and compositor found!"); + if self.shm_id.is_none() { + return Err(Box::new(UnsetErr("shm_id".to_string()))); + } + if self.compositor_id.is_none() { + return Err(Box::new(UnsetErr("compositor_id".to_string()))); + } + if self.xdg_wm_base_id.is_none() { + return Err(Box::new(UnsetErr("xdg_wm_base_id".to_string()))); + } + if self.layer_shell_id.is_none() { + return Err(UnsetErr("layer_shell_id".to_string()).into()); + } + println!("Initializing toplevel!"); + self.wl_compositor_create_surface()?; + self.layer_shell_get_layer_surface()?; self.wl_shm_create_pool()?; self.wl_shm_pool_create_buffer(0, 200, 200)?; - self.wl_compositor_create_surface()?; self.wl_surface_attach()?; - Ok(()) } @@ -49,6 +61,8 @@ impl WlClient { version, ); + // TODO: Collapse these into one line (probably using a macro) + if interface == "wl_shm" { self.current_id += 1; self.wl_registry_bind( @@ -58,9 +72,7 @@ impl WlClient { &self.current_id.clone() )?; self.shm_id = Some(self.current_id); - if self.compositor_id.is_some() && self.xdg_wm_base_id.is_some() { - self.init_toplevel()?; - } + self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)}); } if interface == "wl_compositor" { @@ -72,10 +84,7 @@ impl WlClient { &self.current_id.clone() )?; self.compositor_id = Some(self.current_id); - - if self.shm_id.is_some() && self.xdg_wm_base_id.is_some() { - self.init_toplevel()?; - } + self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)}); } if interface == "xdg_wm_base" { @@ -87,10 +96,19 @@ impl WlClient { &self.current_id.clone() )?; self.xdg_wm_base_id = Some(self.current_id); + self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)}); + } - if self.shm_id.is_some() && self.compositor_id.is_some() { - self.init_toplevel()?; - } + if interface == "zwlr_layer_shell_v1" { + self.current_id += 1; + self.wl_registry_bind( + &name, + &interface, + &version, + &self.current_id.clone() + )?; + self.layer_shell_id = Some(self.current_id); + self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)}); } Ok(())