diff --git a/src/main.rs b/src/main.rs index c51370e..4bee4f8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,17 @@ mod wayland { pub const WAYLAND_WL_REGISTRY_EVENT_GLOBAL: u16 = 0; pub const WAYLAND_WL_DISPLAY_ERROR_EVENT: u16 = 0; pub const WAYLAND_XDG_BASE_EVENT_PING: u16 = 0; + pub const WAYLAND_WL_COMPOSITOR_CREATE_SURFACE_OPCODE: u16 = 0; pub const WAYLAND_XDG_SURFACE_EVENT_CONFIGURE: u16 = 0; + pub const WAYLAND_WL_SURFACE_COMMIT_OPCODE: u16 = 6; + pub const WAYLAND_XDG_WM_BASE_GET_XDG_SURFACE_OPCODE: u16 = 2; + pub const WAYLAND_XDG_SURFACE_GET_TOPLEVEL_OPCODE: u16 = 1; + pub const WAYLAND_XDG_WM_BASE_PONG_OPCODE: u16 = 3; + pub const WAYLAND_XDG_SURFACE_ACK_CONFIGURE_OPCODE: u16 = 4; + pub const WAYLAND_WL_SHM_POOL_CREATE_BUFFER_OPCODE: u16 = 0; + pub const WAYLAND_FORMAT_XRGB8888: u32 = 1; + pub const WAYLAND_WL_SURFACE_ATTACH_OPCODE: u16 = 1; + pub const WAYLAND_WL_SHM_CREATE_POOL_OPCODE: u16 = 0; pub fn write_string(buf: &mut Vec, src: &str) -> Result { let mut n_write = 0; @@ -35,6 +45,7 @@ mod wayland { let required_size = nearest_multiple_4(n_write as i32) as usize; while n_write < required_size { buf.push(0); + n_write += 1; } return Ok(n_write); @@ -78,15 +89,18 @@ mod wayland { } pub fn connect() -> Result { let xdg_runtime_dir = env::var("XDG_RUNTIME_DIR")?; + println!("Using xdg runtime dir: {}", xdg_runtime_dir); let wayland_display = env::var("WAYLAND_DISPLAY").unwrap_or("wayland-0".into()); - let wayland_path = xdg_runtime_dir + &wayland_display; + let wayland_path = xdg_runtime_dir + "/" + &wayland_display; + println!("Opening UnixStream: {wayland_path}"); let sock = UnixStream::connect(&wayland_path)?; Ok(Wayland { sock, - resource_counter: 2, + resource_counter: 1, }) } + #[derive(Debug)] struct RawWaylandMsg { resource_id: u32, opcode: u16, @@ -96,27 +110,103 @@ mod wayland { impl RawWaylandMsg { const HEADER_SIZE: u16 = (std::mem::size_of::() + (2 * std::mem::size_of::())) as u16; + pub fn new(resource_id: u32, opcode: u16, payload: Vec) -> Self { + RawWaylandMsg { + resource_id, + opcode, + size: Self::HEADER_SIZE + payload.len() as u16, + payload, + } + } } impl Wayland { pub fn wl_compositor_create_surface(&mut self, state: &mut State) -> Result { - todo!() + assert!(state.wl_compositor > 0); + let resource_id = state.wl_compositor; + let opcode = WAYLAND_WL_COMPOSITOR_CREATE_SURFACE_OPCODE; + + self.resource_counter += 1; + let object_id = self.resource_counter; + let mut payload = Vec::new(); + object_id.push_ne_into(&mut payload)?; + + let size = RawWaylandMsg::HEADER_SIZE + payload.len() as u16; + + let msg = RawWaylandMsg { + resource_id, + opcode, + size, + payload, + }; + println!( + "-> wl_compositor@{}.create_surface: wl_surface={}", + state.wl_compositor, object_id + ); + self.raw_send(msg)?; + Ok(object_id) } pub fn xdg_wm_base_get_xdg_surface(&mut self, state: &mut State) -> Result { - todo!() + assert!(state.xdg_wm_base > 0); + assert!(state.wl_surface > 0); + + self.resource_counter += 1; + let object_id = self.resource_counter; + let mut payload = object_id.to_ne_bytes().to_vec(); + state.wl_surface.push_ne_into(&mut payload)?; + let msg: RawWaylandMsg = RawWaylandMsg::new( + state.xdg_wm_base, + WAYLAND_XDG_WM_BASE_GET_XDG_SURFACE_OPCODE, + payload, + ); + println!( + "-> xdg_wm_base@{}.get_xdg_surface: xdg_surface={} wl_surface={}", + state.xdg_wm_base, object_id, state.wl_surface + ); + self.raw_send(msg)?; + Ok(object_id) } pub fn xdg_surface_get_toplevel(&mut self, state: &mut State) -> Result { - todo!() + assert!(state.xdg_surface > 0); + self.resource_counter += 1; + let payload = self.resource_counter.to_ne_bytes().to_vec(); + let msg = RawWaylandMsg::new( + state.xdg_surface, + WAYLAND_XDG_SURFACE_GET_TOPLEVEL_OPCODE, + payload, + ); + println!( + "-> xdg_surface@{}.get_toplevel: xdg_toplevel={}", + state.xdg_surface, self.resource_counter + ); + self.raw_send(msg)?; + Ok(self.resource_counter) } - pub fn wl_surface_commit(&mut self, state: &mut State) -> Result { - todo!() + pub fn wl_surface_commit(&mut self, state: &mut State) -> Result<()> { + assert!(state.wl_surface > 0); + let msg = + RawWaylandMsg::new(state.wl_surface, WAYLAND_WL_SURFACE_COMMIT_OPCODE, vec![]); + println!("-> wl_surface@{}.commit: ", state.wl_surface); + self.raw_send(msg)?; + Ok(()) } fn raw_send(&mut self, msg: RawWaylandMsg) -> Result<()> { + //println!("msg: {msg:?}"); let mut buffer = vec![]; msg.resource_id.push_ne_into(&mut buffer)?; msg.opcode.push_ne_into(&mut buffer)?; msg.size.push_ne_into(&mut buffer)?; buffer.push_vec(msg.payload)?; + + /* + println!("msg_size: {}", buffer.len()); + println!("msg_announced_size: {}", msg.size); + for i in buffer.iter() { + print!("{} ", *i); + } + println!(""); + */ + self.sock.write(&buffer)?; Ok(()) } @@ -133,6 +223,10 @@ mod wayland { payload, }; + println!( + "-> wl_display@{WAYLAND_DISPLAY_OBJECT_ID}.get_registry: wl_registry={}", + self.resource_counter + ); self.raw_send(msg)?; return Ok(self.resource_counter); @@ -170,24 +264,139 @@ mod wayland { return Ok(self.resource_counter); } - pub fn xdg_wm_base_pong(&self, state: &mut State, ping: u32) -> Result<()> { + pub fn xdg_wm_base_pong(&mut self, state: &mut State, ping: u32) -> Result<()> { + assert!(state.xdg_wm_base > 0); + assert!(state.wl_surface > 0); + + let msg = RawWaylandMsg::new( + state.xdg_wm_base, + WAYLAND_XDG_WM_BASE_PONG_OPCODE, + ping.to_ne_bytes().to_vec(), + ); + println!("-> xdg_wm_base@{}.pong: ping={}", state.xdg_wm_base, ping); + self.raw_send(msg)?; + Ok(()) + } + + pub fn xdg_surface_ack_configure( + &mut self, + state: &mut State, + configure: u32, + ) -> Result<()> { + assert!(state.xdg_surface > 0); + + let msg = RawWaylandMsg::new( + state.xdg_surface, + WAYLAND_XDG_SURFACE_ACK_CONFIGURE_OPCODE, + configure.to_ne_bytes().to_vec(), + ); + println!( + "-> xdg_surface@{}.ack_configure: configure={}", + state.xdg_surface, configure + ); + self.raw_send(msg)?; + Ok(()) + } + + pub fn wl_shm_create_pool(&mut self, state: &mut State) -> Result { + assert!(state.shm_pool_size > 0); + let _resource_id = state.wl_shm; + let _opcode = WAYLAND_WL_SHM_CREATE_POOL_OPCODE; + self.resource_counter += 1; + let _object_id = self.resource_counter; + /* + uint16_t msg_announced_size = wayland_header_size + + sizeof(wayland_current_id) + + sizeof(state->shm_pool_size); + + assert(roundup_4(msg_announced_size) == msg_announced_size); + buf_write_u16(msg, &msg_size, sizeof(msg), msg_announced_size); + + wayland_current_id++; + buf_write_u32(msg, &msg_size, sizeof(msg), wayland_current_id); + + buf_write_u32(msg, &msg_size, sizeof(msg), state->shm_pool_size); + + assert(roundup_4(msg_size) == msg_size); + + // Send the file descriptor as ancillary data. + // UNIX/Macros monstrosities ahead. + char buf[CMSG_SPACE(sizeof(state->shm_fd))] = ""; + + struct iovec io = {.iov_base = msg, .iov_len = msg_size}; + struct msghdr socket_msg = { + .msg_iov = &io, + .msg_iovlen = 1, + .msg_control = buf, + .msg_controllen = sizeof(buf), + }; + + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&socket_msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(state->shm_fd)); + + *((int *)CMSG_DATA(cmsg)) = state->shm_fd; + socket_msg.msg_controllen = CMSG_SPACE(sizeof(state->shm_fd)); + + if (sendmsg(fd, &socket_msg, 0) == -1) + exit(errno); + + printf("-> wl_shm@%u.create_pool: wl_shm_pool=%u\n", state->wl_shm, + wayland_current_id); + + return wayland_current_id; + */ + + // FIXME: + println!("-x wl_shm@{}.create_pool: NOT IMPLEMENTED", state.wl_shm); todo!() } - pub fn xdg_surface_ack_configure(&self, state: &mut State, configure: u32) -> Result<()> { - todo!() + pub fn wl_shm_pool_create_buffer(&mut self, state: &mut State) -> Result { + assert!(state.wl_shm_pool > 0); + let resource_id = state.wl_shm_pool; + let opcode = WAYLAND_WL_SHM_POOL_CREATE_BUFFER_OPCODE; + + self.resource_counter += 1; + let mut payload = self.resource_counter.to_ne_bytes().to_vec(); + 0_u32.push_ne_into(&mut payload)?; + state.w.push_ne_into(&mut payload)?; + state.h.push_ne_into(&mut payload)?; + state.stride.push_ne_into(&mut payload)?; + WAYLAND_FORMAT_XRGB8888.push_ne_into(&mut payload)?; + + let msg = RawWaylandMsg::new(resource_id, opcode, payload); + + println!( + "-> wl_shm_pool@{}.create_buffer: wl_buffer={}", + state.wl_shm_pool, self.resource_counter + ); + self.raw_send(msg)?; + Ok(self.resource_counter) } - pub fn wl_shm_create_pool(&self, state: &mut State) -> Result { - todo!() - } + pub fn wl_surface_attach(&mut self, state: &mut State) -> Result<()> { + assert!(state.wl_surface > 0); + assert!(state.wl_buffer > 0); - pub fn wl_shm_pool_create_buffer(&self, state: &mut State) -> Result { - todo!() - } + let resource_id = state.wl_surface; + let opcode = WAYLAND_WL_SURFACE_ATTACH_OPCODE; - pub(crate) fn wl_surface_attach(&self, state: &mut State) -> Result<()> { - todo!() + let mut payload = Vec::new(); + state.wl_buffer.push_ne_into(&mut payload)?; + let (x, y) = (0_u32, 0_u32); + x.push_ne_into(&mut payload)?; + y.push_ne_into(&mut payload)?; + + let msg = RawWaylandMsg::new(resource_id, opcode, payload); + println!( + "-> wl_surface@{}.attach: wl_buffer={}", + resource_id, state.wl_buffer + ); + self.raw_send(msg)?; + + Ok(()) } } } @@ -201,7 +410,7 @@ fn gen_rand_name(len: usize) -> String { let c: char = r as u8 as char; s.push(c); } - todo!() + return s; } fn wayland_handle_message( @@ -300,6 +509,7 @@ fn wayland_handle_message( fn main() -> anyhow::Result<()> { let mut display = wayland::connect()?; + println!("Connected to wayland display"); let reg = display.get_registry()?; let mut state = wayland::State::default();