From 0d2db8f288dcc3641074d5efa46326e889a28c8f Mon Sep 17 00:00:00 2001 From: chlorospingus Date: Wed, 23 Apr 2025 13:03:23 -0700 Subject: [PATCH 1/4] Move WlHeader trait and impl from main.rs to vec_utils.rs --- src/main.rs | 97 ++++----------------------------------- src/shm.rs | 116 +++++++++++++++++++++++------------------------ src/vec_utils.rs | 74 ++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 147 deletions(-) create mode 100644 src/vec_utils.rs diff --git a/src/main.rs b/src/main.rs index c3edaba..5ef0aa5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,22 @@ #![feature(unix_socket_ancillary_data)] use std::{env, error::Error, io::{Read, Write}, os::unix::net::{UnixStream, SocketAncillary}, u32}; -use shm::shm::ShmPool; mod shm; +mod vec_utils; +pub use vec_utils::WlMessage; + +struct WlHeader { + object: u32, + opcode: u16, + size: u16 +} struct WlClient { socket: UnixStream, current_id: u32, registry_id: Option, shm_id: Option, - shm_pool: Option + shm_pool: Option } impl WlClient { @@ -149,7 +156,7 @@ impl WlClient { fn wl_shm_create_pool(&mut self) -> Result<(), String> { self.current_id += 1; - self.shm_pool = Some(match ShmPool::new(4096, self.current_id) { + self.shm_pool = Some(match shm::ShmPool::new(4096, self.current_id) { Ok(val) => val, Err(err) => { return Err(err.to_string()); @@ -226,8 +233,6 @@ impl WlClient { request.write_u32(&stride, &mut offset); request.write_u32(&format, &mut offset); - println!("Creating wl_buffer: {:?}", request); - self.socket.write(&request)?; Ok(()) @@ -265,88 +270,6 @@ impl WlClient { } } -struct WlHeader { - object: u32, - opcode: u16, - size: u16 -} - -trait WlMessage { - /// Write a u32 to self at offset and increment offset by four - fn write_u32(&mut self, value: &u32, offset: &mut usize); - /// Write a u16 to self at offset and increment offset by four - fn write_u16(&mut self, value: &u16, offset: &mut usize); - /// Write a string to self at offset - /// and increment offset by string length rounded up to four bytes - fn write_string(&mut self, str: &String, offset: &mut usize); - /// Read a u32 from self at offset and increment offset by four - fn read_u32(&self, offset: &mut usize) -> u32; - /// Read a u16 from self at offset and increment offset by two - fn read_u16(&self, offset: &mut usize) -> u16; - /// Read a string from self at offset - /// and increment offset by string length rounded up to four bytes - fn read_string(&self, offset: &mut usize) -> String; -} - -impl WlMessage for Vec { - fn write_u32(&mut self, value: &u32, offset: &mut usize) { - self[*offset..*offset+4].copy_from_slice(&value.to_ne_bytes()); - *offset += 4; - } - - fn write_u16(&mut self, value: &u16, offset: &mut usize) { - self[*offset..*offset+2].copy_from_slice(&value.to_ne_bytes()); - *offset += 2; - } - - fn write_string(&mut self, str: &String, offset: &mut usize) { - let mut str = str.clone(); - str.push('\0'); - let rounded_len: u32 = (str.len()+3) as u32 & (u32::MAX-3); - self.write_u32(&rounded_len, offset); - self[*offset..*offset+str.len()].copy_from_slice(str.as_bytes()); - *offset += rounded_len as usize; - } - - fn read_u32(&self, offset: &mut usize) -> u32 { - let res = u32::from_ne_bytes( - self[*offset..*offset+4] - .try_into() - .expect("u32::from_ne_bytes failed in WlEvent::read_u32") - ); - *offset += 4; - res - } - - fn read_u16(&self, offset: &mut usize) -> u16 { - let res = u16::from_ne_bytes( - self[*offset..*offset+2] - .try_into() - .expect("u32::from_ne_bytes failed in WlEvent::read_u32") - ); - *offset += 2; - res - } - - fn read_string(&self, offset: &mut usize) -> String { - let str_len = u32::from_ne_bytes( - self[*offset..*offset+4] - .try_into() - .expect("u32::from_ne_bytes failed in WlEvent::read_string") - ); - *offset += 4; - let str = String::from_utf8( - self[*offset..*offset+((str_len-1) as usize)] - .to_vec()) - .expect("String::from_utf8 failed in WlEvent::read_string()" - ); - *offset += (str_len+3 & u32::MAX-3) as usize; - str - } -} - - - fn main() -> Result<(), Box> { let mut wl_client = WlClient::new()?; diff --git a/src/shm.rs b/src/shm.rs index 4ecd3e8..ff9dc4c 100644 --- a/src/shm.rs +++ b/src/shm.rs @@ -1,62 +1,58 @@ -pub mod shm { - - use libc::{c_void, ftruncate, mmap, munmap, shm_open, shm_unlink, MAP_FAILED, MAP_SHARED, O_CREAT, O_EXCL, O_RDWR, PROT_READ}; - - #[derive(Clone)] - pub struct ShmPool { - pub fd: i32, - pub id: u32, - pub addr: *mut c_void, - pub size: usize, - } - - impl ShmPool { - pub fn new(size: usize, id: u32) -> std::io::Result { - let shm_path: *const i8 = b"/chlorostart\0".as_ptr() as *const i8; - let fd = unsafe { shm_open(shm_path, O_RDWR | O_EXCL | O_CREAT, 0o600) }; - if fd == -1 { - eprint!("shm_open in ShmPool::new() failed: "); - return Err(std::io::Error::last_os_error()) - } - if unsafe { shm_unlink(shm_path) } == -1 { - eprint!("shm_unlink in ShmPool::new() failed: "); - return Err(std::io::Error::last_os_error()) - } - if unsafe { ftruncate(fd, size as i64) } == -1 { - eprint!("ftruncate in ShmPool::new() failed: "); - return Err(std::io::Error::last_os_error()) - } - let addr = unsafe { - mmap(std::ptr::null_mut(), size, PROT_READ | PROT_READ, MAP_SHARED, fd, 0) - }; - - if addr == MAP_FAILED { - eprint!("mmap in ShmPool::new() failed: "); - return Err(std::io::Error::last_os_error()) - } - - Ok(ShmPool { - fd, - id, - addr, - size - }) - } - - pub fn resize(&mut self, size: usize) -> std::io::Result<()> { - if unsafe { ftruncate(self.fd, size as i64) } == -1 { - return Err(std::io::Error::last_os_error()) - }; - self.size = size; - - Ok(()) - } - } - - impl Drop for ShmPool { - fn drop(&mut self) { - unsafe { munmap(self.addr, self.size); } - } - } +use libc::{c_void, ftruncate, mmap, munmap, shm_open, shm_unlink, MAP_FAILED, MAP_SHARED, O_CREAT, O_EXCL, O_RDWR, PROT_READ}; +#[derive(Clone)] +pub struct ShmPool { + pub fd: i32, + pub id: u32, + pub addr: *mut c_void, + pub size: usize, +} + +impl ShmPool { + pub fn new(size: usize, id: u32) -> std::io::Result { + let shm_path: *const i8 = b"/chlorostart\0".as_ptr() as *const i8; + let fd = unsafe { shm_open(shm_path, O_RDWR | O_EXCL | O_CREAT, 0o600) }; + if fd == -1 { + eprint!("shm_open in ShmPool::new() failed: "); + return Err(std::io::Error::last_os_error()) + } + if unsafe { shm_unlink(shm_path) } == -1 { + eprint!("shm_unlink in ShmPool::new() failed: "); + return Err(std::io::Error::last_os_error()) + } + if unsafe { ftruncate(fd, size as i64) } == -1 { + eprint!("ftruncate in ShmPool::new() failed: "); + return Err(std::io::Error::last_os_error()) + } + let addr = unsafe { + mmap(std::ptr::null_mut(), size, PROT_READ | PROT_READ, MAP_SHARED, fd, 0) + }; + + if addr == MAP_FAILED { + eprint!("mmap in ShmPool::new() failed: "); + return Err(std::io::Error::last_os_error()) + } + + Ok(ShmPool { + fd, + id, + addr, + size + }) + } + + pub fn resize(&mut self, size: usize) -> std::io::Result<()> { + if unsafe { ftruncate(self.fd, size as i64) } == -1 { + return Err(std::io::Error::last_os_error()) + }; + self.size = size; + + Ok(()) + } +} + +impl Drop for ShmPool { + fn drop(&mut self) { + unsafe { munmap(self.addr, self.size); } + } } diff --git a/src/vec_utils.rs b/src/vec_utils.rs new file mode 100644 index 0000000..336d197 --- /dev/null +++ b/src/vec_utils.rs @@ -0,0 +1,74 @@ + +pub trait WlMessage { + /// Write a u32 to self at offset and increment offset by four + fn write_u32(&mut self, value: &u32, offset: &mut usize); + /// Write a u16 to self at offset and increment offset by four + fn write_u16(&mut self, value: &u16, offset: &mut usize); + /// Write a string to self at offset + /// and increment offset by string length rounded up to four bytes + fn write_string(&mut self, str: &String, offset: &mut usize); + /// Read a u32 from self at offset and increment offset by four + fn read_u32(&self, offset: &mut usize) -> u32; + /// Read a u16 from self at offset and increment offset by two + fn read_u16(&self, offset: &mut usize) -> u16; + /// Read a string from self at offset + /// and increment offset by string length rounded up to four bytes + fn read_string(&self, offset: &mut usize) -> String; +} + +impl WlMessage for Vec { + fn write_u32(&mut self, value: &u32, offset: &mut usize) { + self[*offset..*offset+4].copy_from_slice(&value.to_ne_bytes()); + *offset += 4; + } + + fn write_u16(&mut self, value: &u16, offset: &mut usize) { + self[*offset..*offset+2].copy_from_slice(&value.to_ne_bytes()); + *offset += 2; + } + + fn write_string(&mut self, str: &String, offset: &mut usize) { + let mut str = str.clone(); + str.push('\0'); + let rounded_len: u32 = (str.len()+3) as u32 & (u32::MAX-3); + self.write_u32(&rounded_len, offset); + self[*offset..*offset+str.len()].copy_from_slice(str.as_bytes()); + *offset += rounded_len as usize; + } + + fn read_u32(&self, offset: &mut usize) -> u32 { + let res = u32::from_ne_bytes( + self[*offset..*offset+4] + .try_into() + .expect("u32::from_ne_bytes failed in WlEvent::read_u32") + ); + *offset += 4; + res + } + + fn read_u16(&self, offset: &mut usize) -> u16 { + let res = u16::from_ne_bytes( + self[*offset..*offset+2] + .try_into() + .expect("u32::from_ne_bytes failed in WlEvent::read_u32") + ); + *offset += 2; + res + } + + fn read_string(&self, offset: &mut usize) -> String { + let str_len = u32::from_ne_bytes( + self[*offset..*offset+4] + .try_into() + .expect("u32::from_ne_bytes failed in WlEvent::read_string") + ); + *offset += 4; + let str = String::from_utf8( + self[*offset..*offset+((str_len-1) as usize)] + .to_vec()) + .expect("String::from_utf8 failed in WlEvent::read_string()" + ); + *offset += (str_len+3 & u32::MAX-3) as usize; + str + } +} From b6b3cefd2d55d5224d37297a3ba2fbd3562fc6b6 Mon Sep 17 00:00:00 2001 From: chlorospingus Date: Wed, 23 Apr 2025 13:20:08 -0700 Subject: [PATCH 2/4] Move format, create_pool, and create_buffer to wl_shm.rs --- src/main.rs | 90 +--------------------------------------------- src/vec_utils.rs | 5 ++- src/wl_shm.rs | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 92 deletions(-) create mode 100644 src/wl_shm.rs diff --git a/src/main.rs b/src/main.rs index 5ef0aa5..096a5eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use std::{env, error::Error, io::{Read, Write}, os::unix::net::{UnixStream, SocketAncillary}, u32}; mod shm; +mod wl_shm; mod vec_utils; pub use vec_utils::WlMessage; @@ -149,95 +150,6 @@ impl WlClient { Ok(()) } - fn wl_shm_format(event: &Vec) { - let mut offset = 0; - println!("Received pixel format: {:x}", event.read_u32(&mut offset)); - } - - fn wl_shm_create_pool(&mut self) -> Result<(), String> { - self.current_id += 1; - self.shm_pool = Some(match shm::ShmPool::new(4096, self.current_id) { - Ok(val) => val, - Err(err) => { - return Err(err.to_string()); - } - }); - - let object = match self.shm_id { - Some(val) => val, - None => { - return Err("error in wl_shm_create_pool: shm_id not set!".to_string()); - } - }; - const OPCODE: u16 = 0; - const REQ_SIZE: u16 = 16; - let id = self.shm_pool.as_ref().unwrap().id; - let fds = [self.shm_pool.as_ref().unwrap().fd]; - let shm_size = self.shm_pool.as_ref().unwrap().size; - - let mut request = vec![0u8; REQ_SIZE as usize]; - let mut offset: usize = 0; - - // Request header - request.write_u32(&object, &mut offset); - request.write_u16(&OPCODE, &mut offset); - request.write_u16(&REQ_SIZE, &mut offset); - - // Id, size of shm pool - request.write_u32(&id, &mut offset); - request.write_u32(&(shm_size as u32), &mut offset); - - let mut ancillary_buf = [0u8; 32]; - let mut ancillary = SocketAncillary::new(&mut ancillary_buf[..]); - if !ancillary.add_fds(&fds[..]) { - return Err("Error in wl_shm_create_pool: ancillary.add_fds failed".to_string()); - } - - match self.socket.send_vectored_with_ancillary(&[std::io::IoSlice::new(&request)], &mut ancillary) { - Ok(bytes) => { - assert!(bytes == REQ_SIZE as usize); - } - Err(err) => { - return Err(err.to_string()); - } - }; - - Ok(()) - } - - fn wl_shm_pool_create_buffer( - &mut self, - shm_offset: u32, - width: u32, - height: u32 - ) -> Result<(), Box> { - let object: u32 = self.shm_pool.as_ref().unwrap().id; - const REQ_SIZE: u16 = 32; - const OPCODE: u16 = 0; - - let stride: u32 = width * 4; - self.current_id += 1; - let id = self.current_id; - let format = 0; - - let mut offset: usize = 0; - let mut request = vec![0u8; REQ_SIZE as usize]; - request.write_u32(&object, &mut offset); - request.write_u16(&OPCODE, &mut offset); - request.write_u16(&REQ_SIZE, &mut offset); - - request.write_u32(&id, &mut offset); - request.write_u32(&shm_offset, &mut offset); - request.write_u32(&width, &mut offset); - request.write_u32(&height, &mut offset); - request.write_u32(&stride, &mut offset); - request.write_u32(&format, &mut offset); - - self.socket.write(&request)?; - - Ok(()) - } - fn wl_registry_global(&mut self, event: &Vec) -> Result<(), Box> { let mut offset: usize = 0; diff --git a/src/vec_utils.rs b/src/vec_utils.rs index 336d197..8b97d66 100644 --- a/src/vec_utils.rs +++ b/src/vec_utils.rs @@ -65,9 +65,8 @@ impl WlMessage for Vec { *offset += 4; let str = String::from_utf8( self[*offset..*offset+((str_len-1) as usize)] - .to_vec()) - .expect("String::from_utf8 failed in WlEvent::read_string()" - ); + .to_vec() + ).expect("String::from_utf8 failed in WlEvent::read_string()"); *offset += (str_len+3 & u32::MAX-3) as usize; str } diff --git a/src/wl_shm.rs b/src/wl_shm.rs new file mode 100644 index 0000000..a419045 --- /dev/null +++ b/src/wl_shm.rs @@ -0,0 +1,94 @@ +use std::{io::Write, error::Error, os::unix::net::SocketAncillary}; +use crate::{WlClient, vec_utils::WlMessage, shm}; + +impl WlClient { + pub fn wl_shm_format(event: &Vec) { + let mut offset = 0; + println!("Received pixel format: {:x}", event.read_u32(&mut offset)); + } + + pub fn wl_shm_create_pool(&mut self) -> Result<(), String> { + self.current_id += 1; + self.shm_pool = Some(match shm::ShmPool::new(4096, self.current_id) { + Ok(val) => val, + Err(err) => { + return Err(err.to_string()); + } + }); + + let object = match self.shm_id { + Some(val) => val, + None => { + return Err("error in wl_shm_create_pool: shm_id not set!".to_string()); + } + }; + const OPCODE: u16 = 0; + const REQ_SIZE: u16 = 16; + let id = self.shm_pool.as_ref().unwrap().id; + let fds = [self.shm_pool.as_ref().unwrap().fd]; + let shm_size = self.shm_pool.as_ref().unwrap().size; + + let mut request = vec![0u8; REQ_SIZE as usize]; + let mut offset: usize = 0; + + // Request header + request.write_u32(&object, &mut offset); + request.write_u16(&OPCODE, &mut offset); + request.write_u16(&REQ_SIZE, &mut offset); + + // Id, size of shm pool + request.write_u32(&id, &mut offset); + request.write_u32(&(shm_size as u32), &mut offset); + + let mut ancillary_buf = [0u8; 32]; + let mut ancillary = SocketAncillary::new(&mut ancillary_buf[..]); + if !ancillary.add_fds(&fds[..]) { + return Err("Error in wl_shm_create_pool: ancillary.add_fds failed".to_string()); + } + + match self.socket.send_vectored_with_ancillary(&[std::io::IoSlice::new(&request)], &mut ancillary) { + Ok(bytes) => { + assert!(bytes == REQ_SIZE as usize); + } + Err(err) => { + return Err(err.to_string()); + } + }; + + Ok(()) + } + + pub fn wl_shm_pool_create_buffer( + &mut self, + shm_offset: u32, + width: u32, + height: u32 + ) -> Result<(), Box> { + let object: u32 = self.shm_pool.as_ref().unwrap().id; + const REQ_SIZE: u16 = 32; + const OPCODE: u16 = 0; + + let stride: u32 = width * 4; + self.current_id += 1; + let id = self.current_id; + let format = 0; + + let mut offset: usize = 0; + let mut request = vec![0u8; REQ_SIZE as usize]; + request.write_u32(&object, &mut offset); + request.write_u16(&OPCODE, &mut offset); + request.write_u16(&REQ_SIZE, &mut offset); + + request.write_u32(&id, &mut offset); + request.write_u32(&shm_offset, &mut offset); + request.write_u32(&width, &mut offset); + request.write_u32(&height, &mut offset); + request.write_u32(&stride, &mut offset); + request.write_u32(&format, &mut offset); + + self.socket.write(&request)?; + + Ok(()) + } + +} From eef2bfdc97beb926593b9cb3cfbecd3b66ae9022 Mon Sep 17 00:00:00 2001 From: chlorospingus Date: Wed, 23 Apr 2025 16:25:21 -0700 Subject: [PATCH 3/4] Move wl::{display, error}, wl_registry::{global, bind} from main.rs to wl_registry.rs --- src/main.rs | 119 +++------------------------------------------ src/wl_registry.rs | 105 +++++++++++++++++++++++++++++++++++++++ src/wl_shm.rs | 1 + 3 files changed, 113 insertions(+), 112 deletions(-) create mode 100644 src/wl_registry.rs diff --git a/src/main.rs b/src/main.rs index 096a5eb..d3fcadb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,9 @@ #![feature(unix_socket_ancillary_data)] -use std::{env, error::Error, io::{Read, Write}, os::unix::net::{UnixStream, SocketAncillary}, u32}; +use std::{env::var, error::Error, io::Read, os::unix::net::UnixStream, u32}; mod shm; mod wl_shm; +mod wl_registry; mod vec_utils; pub use vec_utils::WlMessage; @@ -22,7 +23,11 @@ struct WlClient { impl WlClient { fn new() -> Result> { - let sock = WlClient::connect()?; + let sock = UnixStream::connect(format!( + "{}/{}", + var("XDG_RUNTIME_DIR")?, + var("WAYLAND_DISPLAY")? + ))?; let res = WlClient { socket: sock, @@ -70,116 +75,6 @@ impl WlClient { Ok(()) } - - fn connect() -> Result> { - let wl_sock_path: String = format!( - "{}/{}", - env::var("XDG_RUNTIME_DIR")?, - env::var("WAYLAND_DISPLAY")? - ); - let sock = UnixStream::connect(wl_sock_path)?; - - Ok(sock) - } - - fn wl_display_error(event: &Vec) { - let mut offset: usize = 0; - eprintln!( - "Received error:\n\tObject: {}\n\tCode: {}\n\tMessage: {}", - event.read_u32(&mut offset), - event.read_u32(&mut offset), - event.read_string(&mut offset) - ); - } - - fn wl_display_get_registry(&mut self) -> Result<(), Box> { - const OBJECT: u32 = 1; - const OPCODE: u16 = 1; - const MSG_SIZE: u16 = 12; - - let mut request = [0u8; MSG_SIZE as usize]; - request[0..4].copy_from_slice(&OBJECT.to_ne_bytes()); - request[4..6].copy_from_slice(&OPCODE.to_ne_bytes()); - request[6..8].copy_from_slice(&MSG_SIZE.to_ne_bytes()); - - self.current_id += 1; - request[8..12].copy_from_slice(&self.current_id.to_ne_bytes()); - self.registry_id = Some(self.current_id); - - let written = self.socket.write(&request)?; - assert!(written == MSG_SIZE.into()); - - Ok(()) - } - - fn wl_registry_bind( - &mut self, - name: &u32, - interface: &String, - version: &u32, - id: &u32 - ) -> Result<(), String> { - let object: u32 = match self.registry_id { - Some(id) => id, - None => return Err(String::from("wl_registry_bind failed: wl_state.registry_id not set!")) - }; - const OPCODE: u16 = 0; - - let req_size: u16 = 24 + ((interface.len() as u16+3) & (u16::MAX-3)); - let mut request = vec![0u8; req_size as usize]; - let mut offset: usize = 0; - - request.write_u32 (&object, &mut offset); - request.write_u16 (&OPCODE, &mut offset); - request.write_u16 (&req_size, &mut offset); - - request.write_u32 (&name, &mut offset); - request.write_string (&interface, &mut offset); - request.write_u32 (&version, &mut offset); - request.write_u32 (&id, &mut offset); - - match self.socket.write(&request) { - Ok(bytes) => { - assert!(bytes == req_size as usize) - } - Err(err) => { - return Err(err.to_string()); - } - }; - - Ok(()) - } - - fn wl_registry_global(&mut self, event: &Vec) -> Result<(), Box> { - let mut offset: usize = 0; - - let name = event.read_u32(&mut offset); - let interface = event.read_string(&mut offset); - let version = event.read_u32(&mut offset); - - println!( - "Received global:\n\tName: {}\n\tInterface: {}\n\tVersion: {}", - name, - interface, - version, - ); - - if interface == "wl_shm" { - self.current_id += 1; - self.wl_registry_bind( - &name, - &interface, - &version, - &self.current_id.clone() - )?; - self.shm_id = Some(self.current_id); - - self.wl_shm_create_pool()?; - self.wl_shm_pool_create_buffer(0, 200, 200)?; - } - - Ok(()) - } } fn main() -> Result<(), Box> { diff --git a/src/wl_registry.rs b/src/wl_registry.rs new file mode 100644 index 0000000..0442512 --- /dev/null +++ b/src/wl_registry.rs @@ -0,0 +1,105 @@ +use crate::{WlClient, vec_utils::WlMessage}; +use std::{io::Write, error::Error}; + +impl WlClient { + pub fn wl_display_get_registry(&mut self) -> Result<(), Box> { + const OBJECT: u32 = 1; + const OPCODE: u16 = 1; + const MSG_SIZE: u16 = 12; + + let mut request = vec![0u8; MSG_SIZE as usize]; + let mut offset: usize = 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); + self.registry_id = Some(self.current_id); + + let written = self.socket.write(&request)?; + assert!(written == MSG_SIZE.into()); + + Ok(()) + } + + pub fn wl_registry_global(&mut self, event: &Vec) -> Result<(), Box> { + let mut offset: usize = 0; + + let name = event.read_u32(&mut offset); + let interface = event.read_string(&mut offset); + let version = event.read_u32(&mut offset); + + println!( + "Received global:\n\tName: {}\n\tInterface: {}\n\tVersion: {}", + name, + interface, + version, + ); + + if interface == "wl_shm" { + self.current_id += 1; + self.wl_registry_bind( + &name, + &interface, + &version, + &self.current_id.clone() + )?; + self.shm_id = Some(self.current_id); + + self.wl_shm_create_pool()?; + self.wl_shm_pool_create_buffer(0, 200, 200)?; + } + + Ok(()) + } + + pub fn wl_registry_bind( + &mut self, + name: &u32, + interface: &String, + version: &u32, + id: &u32 + ) -> Result<(), String> { + let object: u32 = match self.registry_id { + Some(id) => id, + None => return Err(String::from("wl_registry_bind failed: wl_state.registry_id not set!")) + }; + const OPCODE: u16 = 0; + + let req_size: u16 = 24 + ((interface.len() as u16+3) & (u16::MAX-3)); + let mut request = vec![0u8; req_size as usize]; + let mut offset: usize = 0; + + request.write_u32 (&object, &mut offset); + request.write_u16 (&OPCODE, &mut offset); + request.write_u16 (&req_size, &mut offset); + + request.write_u32 (&name, &mut offset); + request.write_string (&interface, &mut offset); + request.write_u32 (&version, &mut offset); + request.write_u32 (&id, &mut offset); + + match self.socket.write(&request) { + Ok(bytes) => { + assert!(bytes == req_size as usize) + } + Err(err) => { + return Err(err.to_string()); + } + }; + + Ok(()) + } + + pub fn wl_display_error(event: &Vec) { + let mut offset: usize = 0; + eprintln!( + "Received error:\n\tObject: {}\n\tCode: {}\n\tMessage: {}", + event.read_u32(&mut offset), + event.read_u32(&mut offset), + event.read_string(&mut offset) + ); + } +} diff --git a/src/wl_shm.rs b/src/wl_shm.rs index a419045..bb34f70 100644 --- a/src/wl_shm.rs +++ b/src/wl_shm.rs @@ -75,6 +75,7 @@ impl WlClient { let mut offset: usize = 0; let mut request = vec![0u8; REQ_SIZE as usize]; + request.write_u32(&object, &mut offset); request.write_u16(&OPCODE, &mut offset); request.write_u16(&REQ_SIZE, &mut offset); From 097a90c3dccdecb3dbfd2c90267f62910815071a Mon Sep 17 00:00:00 2001 From: chlorospingus Date: Wed, 23 Apr 2025 16:35:15 -0700 Subject: [PATCH 4/4] Move WlClient::{new, read_event} from main.rs to wl_client.rs --- src/main.rs | 79 +++--------------------------------------------- src/wl_client.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 74 deletions(-) create mode 100644 src/wl_client.rs diff --git a/src/main.rs b/src/main.rs index d3fcadb..b55dfaf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,81 +1,12 @@ #![feature(unix_socket_ancillary_data)] -use std::{env::var, error::Error, io::Read, os::unix::net::UnixStream, u32}; +use std::error::Error; -mod shm; -mod wl_shm; +mod wl_client; mod wl_registry; +mod wl_shm; mod vec_utils; -pub use vec_utils::WlMessage; - -struct WlHeader { - object: u32, - opcode: u16, - size: u16 -} - -struct WlClient { - socket: UnixStream, - current_id: u32, - registry_id: Option, - shm_id: Option, - shm_pool: Option -} - -impl WlClient { - fn new() -> Result> { - let sock = UnixStream::connect(format!( - "{}/{}", - var("XDG_RUNTIME_DIR")?, - var("WAYLAND_DISPLAY")? - ))?; - - let res = WlClient { - socket: sock, - current_id: 1, - registry_id: None, - shm_id: None, - shm_pool: None, - }; - - Ok(res) - } - - fn read_event(&mut self) -> Result<(), Box> { - // TODO: Don't realloc header and event - - let mut header = vec![0u8; 8]; - self.socket.read_exact(&mut header)?; - - let header = WlHeader { - object: u32::from_ne_bytes(header[0..4].try_into()?), - opcode: u16::from_ne_bytes(header[4..6].try_into()?), - size: u16::from_ne_bytes(header[6..8].try_into()?) - }; - - let mut event = vec![0u8; header.size as usize - 8]; - self.socket.read_exact(&mut event)?; - - if header.object == self.registry_id.unwrap() && header.opcode == 0 { // wl_registry::global - self.wl_registry_global(&event)?; - } - else if header.object == 1 && header.opcode == 0 { // wl_display::error - WlClient::wl_display_error(&event); - } - else if self.shm_id.is_some() && header.object == self.shm_id.unwrap() && header.opcode == 0 { // wl_shm::format - WlClient::wl_shm_format(&event); - } - else { - println!( - "Received event:\n\tObject: {}\n\tOpcode: {}\n\tSize: {}", - header.object, - header.opcode, - header.size - ); - } - - Ok(()) - } -} +mod shm; +use wl_client::WlClient; fn main() -> Result<(), Box> { let mut wl_client = WlClient::new()?; diff --git a/src/wl_client.rs b/src/wl_client.rs new file mode 100644 index 0000000..96ce870 --- /dev/null +++ b/src/wl_client.rs @@ -0,0 +1,74 @@ +use std::{env::var, error::Error, io::Read, os::unix::net::UnixStream, u32}; + +use crate::shm; + +struct WlHeader { + object: u32, + opcode: u16, + size: u16 +} + +pub struct WlClient { + pub socket: UnixStream, + pub current_id: u32, + pub registry_id: Option, + pub shm_id: Option, + pub shm_pool: Option +} + +impl WlClient { + pub fn new() -> Result> { + let sock = UnixStream::connect(format!( + "{}/{}", + var("XDG_RUNTIME_DIR")?, + var("WAYLAND_DISPLAY")? + ))?; + + let res = WlClient { + socket: sock, + current_id: 1, + registry_id: None, + shm_id: None, + shm_pool: None, + }; + + Ok(res) + } + + pub fn read_event(&mut self) -> Result<(), Box> { + // TODO: Don't realloc header and event + + let mut header = vec![0u8; 8]; + self.socket.read_exact(&mut header)?; + + let header = WlHeader { + object: u32::from_ne_bytes(header[0..4].try_into()?), + opcode: u16::from_ne_bytes(header[4..6].try_into()?), + size: u16::from_ne_bytes(header[6..8].try_into()?) + }; + + let mut event = vec![0u8; header.size as usize - 8]; + self.socket.read_exact(&mut event)?; + + if header.object == self.registry_id.unwrap() && header.opcode == 0 { // wl_registry::global + self.wl_registry_global(&event)?; + } + else if header.object == 1 && header.opcode == 0 { // wl_display::error + WlClient::wl_display_error(&event); + } + else if self.shm_id.is_some() && header.object == self.shm_id.unwrap() && header.opcode == 0 { // wl_shm::format + WlClient::wl_shm_format(&event); + } + else { + println!( + "Received event:\n\tObject: {}\n\tOpcode: {}\n\tSize: {}", + header.object, + header.opcode, + header.size + ); + } + + Ok(()) + } +} +