Move all wayland files into wayland namespace
This commit is contained in:
103
src/wayland/layer_shell.rs
Normal file
103
src/wayland/layer_shell.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
use std::{error::Error, io::Write};
|
||||
use crate::wayland::{vec_utils::WlMessage, wl_client::WlClient};
|
||||
|
||||
const NAMESPACE: &str = "chlorostart";
|
||||
const OVERLAY: u32 = 3;
|
||||
const EXCLUSIVE: u32 = 0; // exclusize keyboard focus
|
||||
|
||||
impl WlClient {
|
||||
pub fn layer_shell_get_layer_surface(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
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 output: u32 = 0;
|
||||
|
||||
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.layer_surface_id = Some(self.current_id);
|
||||
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(())
|
||||
}
|
||||
|
||||
pub fn layer_surface_configure(&mut self, event: &Vec<u8>) -> Result<(), Box<dyn Error>> {
|
||||
let mut offset: usize = 0;
|
||||
let serial = event.read_u32(&mut offset);
|
||||
let width = event.read_u32(&mut offset);
|
||||
let height = event.read_u32(&mut offset);
|
||||
|
||||
// TODO: Resize based on configure
|
||||
|
||||
// Ack configure
|
||||
let object = self.layer_surface_id.unwrap();
|
||||
const OPCODE: u16 = 6;
|
||||
const MSG_SIZE: u16 = 12;
|
||||
|
||||
let mut request = vec![0u8; MSG_SIZE as usize];
|
||||
offset = 0;
|
||||
|
||||
request.write_u32(&object, &mut offset);
|
||||
request.write_u16(&OPCODE, &mut offset);
|
||||
request.write_u16(&MSG_SIZE, &mut offset);
|
||||
|
||||
request.write_u32(&serial, &mut offset);
|
||||
|
||||
self.socket.write(&request)?;
|
||||
|
||||
self.wl_surface_attach()?;
|
||||
self.wl_surface_commit()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn layer_surface_set_size(&mut self, width: u32, height: u32) -> Result<(), Box<dyn Error>> {
|
||||
let object: u32 = self.layer_surface_id.unwrap();
|
||||
const OPCODE: u16 = 0;
|
||||
const MSG_SIZE: u16 = 20;
|
||||
|
||||
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);
|
||||
|
||||
request.write_u32(&width, &mut offset);
|
||||
request.write_u32(&height, &mut offset);
|
||||
|
||||
self.socket.write(&request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn layer_surface_set_keyboard_interactivity(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
let object: u32 = self.layer_surface_id.unwrap();
|
||||
const OPCODE: u16 = 4;
|
||||
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);
|
||||
|
||||
request.write_u32(&EXCLUSIVE, &mut offset);
|
||||
|
||||
self.socket.write(&request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
8
src/wayland/mod.rs
Normal file
8
src/wayland/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
pub mod layer_shell;
|
||||
pub mod surface;
|
||||
pub mod wl_client;
|
||||
pub mod wl_shm;
|
||||
pub mod vec_utils;
|
||||
pub mod shm;
|
||||
pub mod wl_registry;
|
||||
71
src/wayland/shm.rs
Normal file
71
src/wayland/shm.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
use libc::{c_void, ftruncate, mmap, munmap, shm_open, shm_unlink, MAP_FAILED, MAP_SHARED, O_CREAT, O_EXCL, O_RDWR, PROT_READ, PROT_WRITE};
|
||||
|
||||
#[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<ShmPool> {
|
||||
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_WRITE, 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(())
|
||||
}
|
||||
|
||||
pub fn write(&mut self, data: &Vec<u32>, offset: isize) -> std::io::Result<()> {
|
||||
// TODO: Bounds check
|
||||
unsafe {
|
||||
std::ptr::copy_nonoverlapping(
|
||||
data.as_ptr() as *const u32, // src: data as *const u32
|
||||
self.addr.offset(offset*4) as *mut u32, // dst: ShmPool address as *mut u32
|
||||
data.len()
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ShmPool {
|
||||
fn drop(&mut self) {
|
||||
unsafe { munmap(self.addr, self.size); }
|
||||
}
|
||||
}
|
||||
108
src/wayland/surface.rs
Normal file
108
src/wayland/surface.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
use std::{error::Error, io::Write};
|
||||
|
||||
use crate::wayland::{vec_utils::WlMessage, wl_client::WlClient};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UnsetErr (pub String);
|
||||
|
||||
impl Error for UnsetErr {}
|
||||
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<dyn Error>> {
|
||||
if self.compositor_id.is_none() {
|
||||
return Err(UnsetErr("compositor_id".to_string()).into());
|
||||
}
|
||||
|
||||
let object = self.compositor_id.unwrap();
|
||||
const OPCODE: u16 = 0;
|
||||
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.socket.write(&request)?;
|
||||
|
||||
self.surface_id = Some(self.current_id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wl_surface_attach(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
if self.surface_id.is_none() {
|
||||
return Err(Box::new(UnsetErr("surface_id".to_string())));
|
||||
}
|
||||
let object = self.surface_id.unwrap();
|
||||
const OPCODE: u16 = 1;
|
||||
const MSG_SIZE: u16 = 20;
|
||||
let buffer = self.buffer_id.unwrap();
|
||||
const X: u32 = 0;
|
||||
const Y: u32 = 0;
|
||||
|
||||
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);
|
||||
request.write_u32(&buffer, &mut offset);
|
||||
request.write_u32(&X, &mut offset);
|
||||
request.write_u32(&Y, &mut offset);
|
||||
|
||||
self.socket.write(&request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wl_surface_commit(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
let object = self.surface_id.unwrap();
|
||||
const OPCODE: u16 = 6;
|
||||
const MSG_SIZE: u16 = 8;
|
||||
|
||||
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.socket.write(&request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn xdg_wm_base_pong(&mut self, event: &Vec<u8>) -> Result<(), Box<dyn Error>> {
|
||||
if self.xdg_wm_base_id.is_none() {
|
||||
return Err(Box::new(UnsetErr("xdg_wm_base_id".to_string())));
|
||||
}
|
||||
let object = self.xdg_wm_base_id.unwrap();
|
||||
const OPCODE: u16 = 3;
|
||||
const MSG_SIZE: u16 = 12;
|
||||
let serial = u32::from_ne_bytes(event[0..4].try_into().unwrap());
|
||||
|
||||
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);
|
||||
request.write_u32(&serial, &mut offset);
|
||||
|
||||
self.socket.write(&request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
74
src/wayland/vec_utils.rs
Normal file
74
src/wayland/vec_utils.rs
Normal file
@@ -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<u8> {
|
||||
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) {
|
||||
// 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);
|
||||
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
|
||||
}
|
||||
}
|
||||
125
src/wayland/wl_client.rs
Normal file
125
src/wayland/wl_client.rs
Normal file
@@ -0,0 +1,125 @@
|
||||
use std::{env::var, error::Error, fmt::Debug, io::Read, os::unix::net::UnixStream, u32};
|
||||
|
||||
use crate::wayland::shm;
|
||||
|
||||
struct WlHeader {
|
||||
object: u32,
|
||||
opcode: u16,
|
||||
size: u16,
|
||||
}
|
||||
|
||||
pub struct WlClient {
|
||||
pub socket: UnixStream,
|
||||
pub current_id: u32,
|
||||
pub registry_id: Option<u32>,
|
||||
pub shm_id: Option<u32>,
|
||||
pub shm_pool: Option<shm::ShmPool>,
|
||||
pub buffer_id: Option<u32>,
|
||||
pub compositor_id: Option<u32>,
|
||||
pub surface_id: Option<u32>,
|
||||
pub xdg_wm_base_id: Option<u32>,
|
||||
pub layer_shell_id: Option<u32>,
|
||||
pub layer_surface_id: Option<u32>,
|
||||
}
|
||||
|
||||
impl WlClient {
|
||||
pub fn new() -> Result<Self, Box<dyn Error>> {
|
||||
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,
|
||||
buffer_id: None,
|
||||
compositor_id: None,
|
||||
surface_id: None,
|
||||
xdg_wm_base_id: None,
|
||||
layer_shell_id: None,
|
||||
layer_surface_id: None,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn read_event(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
// 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 if self.xdg_wm_base_id.is_some() && header.object == self.xdg_wm_base_id.unwrap() && header.opcode == 0 { // xdg_wm_base::ping
|
||||
self.xdg_wm_base_pong(&event)?;
|
||||
}
|
||||
else if Some(header.object) == self.layer_surface_id && header.opcode == 0 { // zwlr_layer_surface::configure
|
||||
self.layer_surface_configure(&event)?;
|
||||
}
|
||||
else if Some(header.object) == self.surface_id && header.opcode == 2 { // wl_surface::preferred_buffer_scale
|
||||
println!("Preferred buffer scale: {}", i32::from_ne_bytes(event[0..4].try_into().unwrap()));
|
||||
}
|
||||
else if Some(header.object) == self.surface_id && header.opcode == 3 { // wl_surface::preferred_buffer_transform
|
||||
println!("Preferred buffer transform: {}", i32::from_ne_bytes(event[0..4].try_into().unwrap()));
|
||||
dbg!(self);
|
||||
}
|
||||
else {
|
||||
println!(
|
||||
"Received event:\n\tObject: {}\n\tOpcode: {}\n\tSize: {}",
|
||||
header.object,
|
||||
header.opcode,
|
||||
header.size
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for WlClient {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f,
|
||||
"WlClient {{
|
||||
current_id: {},
|
||||
registry_id: {},
|
||||
shm_id: {},
|
||||
buffer_id: {},
|
||||
compositor_id: {},
|
||||
surface_id: {},
|
||||
xdg_wm_base_id: {},
|
||||
layer_shell_id: {},
|
||||
layer_surface_id: {},
|
||||
}}",
|
||||
self.current_id,
|
||||
self.registry_id.unwrap_or(0),
|
||||
self.shm_id.unwrap_or(0),
|
||||
self.buffer_id.unwrap_or(0),
|
||||
self.compositor_id.unwrap_or(0),
|
||||
self.surface_id.unwrap_or(0),
|
||||
self.xdg_wm_base_id.unwrap_or(0),
|
||||
self.layer_shell_id.unwrap_or(0),
|
||||
self.layer_surface_id.unwrap_or(0),
|
||||
)
|
||||
}
|
||||
}
|
||||
168
src/wayland/wl_registry.rs
Normal file
168
src/wayland/wl_registry.rs
Normal file
@@ -0,0 +1,168 @@
|
||||
use crate::wayland::{surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient};
|
||||
use std::{io::Write, error::Error};
|
||||
|
||||
impl WlClient {
|
||||
fn init_toplevel(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
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.layer_surface_set_size(800, 800)?;
|
||||
self.layer_surface_set_keyboard_interactivity()?;
|
||||
self.wl_surface_commit()?;
|
||||
|
||||
self.wl_shm_create_pool(800, 800)?;
|
||||
self.wl_shm_pool_create_buffer(0, 800, 800)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wl_display_get_registry(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
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<u8>) -> Result<(), Box<dyn Error>> {
|
||||
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,
|
||||
);
|
||||
|
||||
// TODO: Collapse these into one line (probably using a macro)
|
||||
|
||||
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.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)});
|
||||
}
|
||||
|
||||
if interface == "wl_compositor" {
|
||||
self.current_id += 1;
|
||||
self.wl_registry_bind(
|
||||
&name,
|
||||
&interface,
|
||||
&version,
|
||||
&self.current_id.clone()
|
||||
)?;
|
||||
self.compositor_id = Some(self.current_id);
|
||||
self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)});
|
||||
}
|
||||
|
||||
if interface == "xdg_wm_base" {
|
||||
self.current_id += 1;
|
||||
self.wl_registry_bind(
|
||||
&name,
|
||||
&interface,
|
||||
&version,
|
||||
&self.current_id.clone()
|
||||
)?;
|
||||
self.xdg_wm_base_id = Some(self.current_id);
|
||||
self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)});
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
|
||||
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<u8>) {
|
||||
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)
|
||||
);
|
||||
}
|
||||
}
|
||||
87
src/wayland/wl_shm.rs
Normal file
87
src/wayland/wl_shm.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
use std::{error::Error, io::Write, os::unix::net::SocketAncillary, u8};
|
||||
use crate::wayland::{shm, surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient};
|
||||
|
||||
const STRIDE: usize = 4;
|
||||
|
||||
impl WlClient {
|
||||
pub fn wl_shm_format(event: &Vec<u8>) {
|
||||
let mut offset = 0;
|
||||
println!("Received pixel format: {:x}", event.read_u32(&mut offset));
|
||||
}
|
||||
|
||||
pub fn wl_shm_create_pool(&mut self, width: usize, height: usize) -> Result<(), Box<dyn Error>> {
|
||||
self.current_id += 1;
|
||||
self.shm_pool = Some(shm::ShmPool::new(width * height * STRIDE, self.current_id)?);
|
||||
self.shm_pool.as_mut().unwrap().write(&vec![0xffff0000; width * height], 0)?;
|
||||
|
||||
let object = self.shm_id.ok_or(UnsetErr("shm_id".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(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"Failed to add FDs to ancillary data",
|
||||
).into());
|
||||
}
|
||||
|
||||
self.socket.send_vectored_with_ancillary(&[std::io::IoSlice::new(&request)], &mut ancillary)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wl_shm_pool_create_buffer(
|
||||
&mut self,
|
||||
shm_offset: u32,
|
||||
width: u32,
|
||||
height: u32
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
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)?;
|
||||
|
||||
self.buffer_id = Some(self.current_id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user