Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7f09e7d6b2 | |||
| a50ef3ad8c | |||
| 1eff2cd4f7 | |||
| 3bcccb2e87 | |||
| 64fe7ec941 | |||
| 5b8475f1a3 | |||
| 9d0b9b97b5 | |||
| 7dcf3d80bb | |||
| a1aa3bc2eb | |||
| 1efb3f661b | |||
| a7c2956313 | |||
| bde60fff90 | |||
| 6cd5d1f256 | |||
| 9583a87f2f | |||
| 375b44beee |
48
src/graphics/circle.rs
Normal file
48
src/graphics/circle.rs
Normal file
@@ -0,0 +1,48 @@
|
||||
use crate::wayland::{shm::ShmPool, wl_shm::wl_buffer};
|
||||
use super::drawable::{Drawable, color_blend};
|
||||
|
||||
// x and y are center of circle
|
||||
pub struct Circle {
|
||||
x: usize,
|
||||
y: usize,
|
||||
radius: usize,
|
||||
color: u32,
|
||||
}
|
||||
|
||||
impl Circle {
|
||||
pub fn new(x: usize, y: usize, radius: usize, color: u32) -> Self {
|
||||
Circle { x, y, radius, color }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drawable for Circle {
|
||||
fn update(&mut self) {
|
||||
// self.x += 1;
|
||||
}
|
||||
|
||||
fn draw(&self, buffer: &wl_buffer, shm_pool: &mut ShmPool) {
|
||||
for l_row in 1..self.radius {
|
||||
let inner_diff = (((self.radius-1).pow(2) - l_row.pow(2)) as f64).sqrt();
|
||||
let outer_diff = ((self.radius.pow(2) - l_row.pow(2)) as f64).sqrt();
|
||||
shm_pool.write(self.color, (self.y-l_row)*buffer.width + self.x - inner_diff.floor() as usize + buffer.offset, 2*(inner_diff.floor() as usize));
|
||||
shm_pool.write(self.color, (self.y+l_row-1)*buffer.width + self.x - inner_diff.floor() as usize + buffer.offset, 2*(inner_diff.floor() as usize));
|
||||
for l_col in (inner_diff.floor() as usize+1)..(outer_diff.ceil() as usize) {
|
||||
let distance = ((l_row.pow(2) + l_col.pow(2)) as f64).sqrt();
|
||||
let offset = (self.y-l_row)*buffer.width + self.x - l_col + buffer.offset;
|
||||
shm_pool.write_pixel(color_blend(self.color, 0, distance.fract()), offset);
|
||||
let offset = (self.y-l_row)*buffer.width + self.x + l_col-1 + buffer.offset;
|
||||
shm_pool.write_pixel(color_blend(self.color, 0, distance.fract()), offset);
|
||||
let offset = (self.y+l_row-1)*buffer.width + self.x - l_col + buffer.offset;
|
||||
shm_pool.write_pixel(color_blend(self.color, 0, distance.fract()), offset);
|
||||
let offset = (self.y+l_row-1)*buffer.width + self.x + l_col-1 + buffer.offset;
|
||||
shm_pool.write_pixel(color_blend(self.color, 0, distance.fract()), offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Box<dyn Drawable>> for Circle {
|
||||
fn into(self) -> Box<dyn Drawable> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
54
src/graphics/drawable.rs
Normal file
54
src/graphics/drawable.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use crate::wayland::{shm::ShmPool, wl_shm::wl_buffer};
|
||||
|
||||
pub fn premultiply(color: u32) -> u32 {
|
||||
let a = (color & 0xff000000) >> 24;
|
||||
let r = (color & 0x00ff0000) >> 16;
|
||||
let g = (color & 0x0000ff00) >> 8;
|
||||
let b = (color & 0x000000ff) >> 0;
|
||||
let alpha = (a as f64 / 0xff as f64);
|
||||
(a << 24) +
|
||||
(((r as f64*alpha) as u32) << 16) +
|
||||
(((g as f64*alpha) as u32) << 8) +
|
||||
(((b as f64*alpha) as u32) << 0)
|
||||
}
|
||||
|
||||
pub fn color_blend(col1: u32, col2: u32, diff: f64) -> u32 {
|
||||
let a1 = (col1 & 0xff000000) >> 24;
|
||||
let r1 = (col1 & 0x00ff0000) >> 16;
|
||||
let g1 = (col1 & 0x0000ff00) >> 8;
|
||||
let b1 = (col1 & 0x000000ff) >> 0;
|
||||
let a2 = (col2 & 0xff000000) >> 24;
|
||||
let r2 = (col2 & 0x00ff0000) >> 16;
|
||||
let g2 = (col2 & 0x0000ff00) >> 8;
|
||||
let b2 = (col2 & 0x000000ff) >> 0;
|
||||
(((a1 as f64 + (a2 as f64 - a1 as f64) * diff).round() as u32) << 24) +
|
||||
(((r1 as f64 + (r2 as f64 - r1 as f64) * diff).round() as u32) << 16) +
|
||||
(((g1 as f64 + (b2 as f64 - g1 as f64) * diff).round() as u32) << 8 ) +
|
||||
(((b1 as f64 + (g2 as f64 - b1 as f64) * diff).round() as u32) << 0 )
|
||||
}
|
||||
|
||||
pub fn color_over(over: u32, under: u32) -> u32 {
|
||||
let a_over = (over & 0xff000000) >> 24;
|
||||
let a_under = (under & 0xff000000) >> 24;
|
||||
if a_over == 0xff || a_under == 0 {
|
||||
return over;
|
||||
}
|
||||
if a_over == 0 {
|
||||
return under;
|
||||
}
|
||||
let r_over = (over & 0x00ff0000) >> 16;
|
||||
let r_under = (under & 0x00ff0000) >> 16;
|
||||
let g_over = (over & 0x0000ff00) >> 8;
|
||||
let g_under = (under & 0x0000ff00) >> 8;
|
||||
let b_over = (over & 0x000000ff) >> 0;
|
||||
let b_under = (under & 0x000000ff) >> 0;
|
||||
((a_over + (a_under as f64 * (0xff - a_over) as f64 / 0xff as f64) as u32).min(0xff) << 24) +
|
||||
((r_over + (r_under as f64 * (0xff - a_over) as f64 / 0xff as f64) as u32).min(0xff) << 16) +
|
||||
((g_over + (g_under as f64 * (0xff - a_over) as f64 / 0xff as f64) as u32).min(0xff) << 8) +
|
||||
((b_over + (b_under as f64 * (0xff - a_over) as f64 / 0xff as f64) as u32).min(0xff) << 0)
|
||||
}
|
||||
|
||||
pub trait Drawable : Send {
|
||||
fn update(&mut self);
|
||||
fn draw(&self, buffer: &wl_buffer, shm_pool: &mut ShmPool);
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
|
||||
pub mod drawable;
|
||||
pub mod rectangle;
|
||||
pub mod circle;
|
||||
|
||||
@@ -1,94 +1,54 @@
|
||||
use std::usize;
|
||||
use crate::wayland::{shm::ShmPool, wl_shm::wl_buffer};
|
||||
use super::drawable::{Drawable, color_blend};
|
||||
|
||||
use crate::wayland::shm::ShmPool;
|
||||
|
||||
fn color_blend(col1: u32, col2: u32, diff: f64) -> u32 {
|
||||
// TODO: Account for alpha channel
|
||||
let r1 = (col1 & 0x00ff0000) >> 16;
|
||||
let g1 = (col1 & 0x0000ff00) >> 8;
|
||||
let b1 = col1 & 0x000000ff;
|
||||
let r2 = (col2 & 0x00ff0000) >> 16;
|
||||
let g2 = (col2 & 0x0000ff00) >> 8;
|
||||
let b2 = col2 & 0x000000ff;
|
||||
let r3 = if r1 < r2 {
|
||||
r1 + ((r2 - r1) as f64 * diff) as u32
|
||||
} else {
|
||||
r1 - ((r1 - r2) as f64 * diff) as u32
|
||||
};
|
||||
let g3 = if g1 < g2 {
|
||||
g1 + ((g2 - g1) as f64 * diff) as u32
|
||||
} else {
|
||||
g1 - ((g1 - g2) as f64 * diff) as u32
|
||||
};
|
||||
let b3 = if b1 < b2 {
|
||||
b1 + ((b2 - b1) as f64 * diff) as u32
|
||||
} else {
|
||||
b1 - ((b1 - b2) as f64 * diff) as u32
|
||||
};
|
||||
return 0xff000000 + (r3 << 16) + (g3 << 8) + b3;
|
||||
// x and y and topleft corner of rect
|
||||
pub struct Rectangle {
|
||||
x: usize,
|
||||
y: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
radius: usize,
|
||||
color: u32,
|
||||
}
|
||||
|
||||
// l_row means local row and g_row means global row
|
||||
impl ShmPool {
|
||||
impl Rectangle {
|
||||
pub fn new(x: usize, y: usize, width: usize, height: usize, radius: usize, color: u32) -> Self {
|
||||
Rectangle {x, y, width, height, radius, color}
|
||||
}
|
||||
}
|
||||
|
||||
// x and y are topleft corner of rect
|
||||
pub fn rectangle(&mut self, x: usize, y: usize, w: usize, h: usize, color: u32) {
|
||||
for g_row in y..y+h {
|
||||
self.write(&vec![color; w], g_row*self.width+x);
|
||||
}
|
||||
impl Drawable for Rectangle {
|
||||
fn update(&mut self) {
|
||||
// self.x += 1;
|
||||
}
|
||||
|
||||
// x and y and topleft corner of rect
|
||||
pub fn rounded_rectangle(
|
||||
&mut self,
|
||||
x: usize,
|
||||
y: usize,
|
||||
w: usize,
|
||||
h: usize,
|
||||
radius: usize,
|
||||
color: u32
|
||||
) {
|
||||
for l_row in 1..radius {
|
||||
let inner_diff = (((radius-1).pow(2) - l_row.pow(2)) as f64).sqrt();
|
||||
let outer_diff = ((radius.pow(2) - l_row.pow(2)) as f64).sqrt();
|
||||
self.write(&vec![color; w - (2*(radius - inner_diff.floor() as usize-1))], (y+radius-l_row)*self.width + x + radius - inner_diff.floor() as usize-1);
|
||||
self.write(&vec![color; w - (2*(radius - inner_diff.floor() as usize-1))], (y+h-radius+l_row)*self.width + x + radius - inner_diff.floor() as usize-1);
|
||||
fn draw(&self, buffer: &wl_buffer, shm_pool: &mut ShmPool) {
|
||||
for g_row in self.y+self.radius..self.y+self.height-self.radius+1 {
|
||||
shm_pool.write(self.color, g_row*buffer.width as usize+self.x + buffer.offset, self.width);
|
||||
}
|
||||
for l_row in 1..self.radius {
|
||||
let inner_diff = (((self.radius-1).pow(2) - l_row.pow(2)) as f64).sqrt();
|
||||
let outer_diff = ((self.radius.pow(2) - l_row.pow(2)) as f64).sqrt();
|
||||
shm_pool.write(self.color, (self.y+self.radius-l_row)*buffer.width as usize + self.x + self.radius - inner_diff.floor() as usize-1 + buffer.offset, self.width - (2*(self.radius - inner_diff.floor() as usize-1)));
|
||||
shm_pool.write(self.color, (self.y+self.height-self.radius+l_row)*buffer.width as usize + self.x + self.radius - inner_diff.floor() as usize-1 + buffer.offset, self.width - (2*(self.radius - inner_diff.floor() as usize-1)));
|
||||
for l_col in inner_diff.floor() as usize+1..outer_diff.ceil() as usize {
|
||||
// TODO: handle error from read_pixel
|
||||
let distance = ((l_row.pow(2) + l_col.pow(2)) as f64).sqrt();
|
||||
let offset = (y+radius-l_row)*self.width + x + radius - l_col - 1;
|
||||
self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize);
|
||||
let offset = (y+radius-l_row)*self.width + x + w - radius + l_col;
|
||||
self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize);
|
||||
let offset = (y+h-radius+l_row)*self.width + x + radius - l_col - 1;
|
||||
self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize);
|
||||
let offset = (y+h-radius+l_row)*self.width + x + w - radius + l_col;
|
||||
self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize);
|
||||
}
|
||||
}
|
||||
for g_row in y+radius..y+h-radius+1 {
|
||||
self.write(&vec![color; w], g_row*self.width+x);
|
||||
}
|
||||
}
|
||||
|
||||
// x and y are center of circle
|
||||
pub fn circle(&mut self, x: usize, y: usize, radius: usize, color: u32) {
|
||||
for l_row in 1..radius {
|
||||
let inner_diff = (((radius-1).pow(2) - l_row.pow(2)) as f64).sqrt();
|
||||
let outer_diff = ((radius.pow(2) - l_row.pow(2)) as f64).sqrt();
|
||||
let row: Vec<u32> = vec![color; 2*(inner_diff.floor() as usize)];
|
||||
self.write(&row, (y-l_row)*self.width + x - inner_diff.floor() as usize);
|
||||
self.write(&row, (y+l_row-1)*self.width + x - inner_diff.floor() as usize);
|
||||
for l_col in (inner_diff.floor() as usize+1)..(outer_diff.ceil() as usize) {
|
||||
let distance = ((l_row.pow(2) + l_col.pow(2)) as f64).sqrt();
|
||||
let offset = (y-l_row)*self.width + x - l_col;
|
||||
self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize);
|
||||
let offset = (y-l_row)*self.width + x + l_col-1;
|
||||
self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize);
|
||||
let offset = (y+l_row-1)*self.width + x - l_col;
|
||||
self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize);
|
||||
let offset = (y+l_row-1)*self.width + x + l_col-1;
|
||||
self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize);
|
||||
let offset = (self.y+self.radius-l_row)*buffer.width as usize + self.x + self.radius - l_col - 1 + buffer.offset;
|
||||
shm_pool.write_pixel(color_blend(self.color, 0, distance.fract()), offset);
|
||||
let offset = (self.y+self.radius-l_row)*buffer.width as usize + self.x + self.width - self.radius + l_col + buffer.offset;
|
||||
shm_pool.write_pixel(color_blend(self.color, 0, distance.fract()), offset);
|
||||
let offset = (self.y+self.height-self.radius+l_row)*buffer.width as usize + self.x + self.radius - l_col - 1 + buffer.offset;
|
||||
shm_pool.write_pixel(color_blend(self.color, 0, distance.fract()), offset);
|
||||
let offset = (self.y+self.height-self.radius+l_row)*buffer.width as usize + self.x + self.width - self.radius + l_col + buffer.offset;
|
||||
shm_pool.write_pixel(color_blend(self.color, 0, distance.fract()), offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Box<dyn Drawable>> for Rectangle {
|
||||
fn into(self) -> Box<dyn Drawable> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
16
src/main.rs
16
src/main.rs
@@ -1,22 +1,14 @@
|
||||
#![feature(unix_socket_ancillary_data)]
|
||||
use std::error::Error;
|
||||
#![feature(str_from_raw_parts)]
|
||||
|
||||
use std::{error::Error, thread, time::Duration};
|
||||
|
||||
mod wayland;
|
||||
use wayland::wl_client::WlClient;
|
||||
mod graphics;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut wl_client = WlClient::new()?;
|
||||
|
||||
wl_client.wl_display_get_registry()?;
|
||||
|
||||
loop {
|
||||
wl_client.read_event()?;
|
||||
|
||||
if false {
|
||||
break
|
||||
}
|
||||
}
|
||||
let mut wl_client = WlClient::run()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
use std::{error::Error, io::Write};
|
||||
use crate::wayland::{vec_utils::WlMessage, wl_client::WlClient};
|
||||
use std::{error::Error, io::Write, sync::atomic::Ordering, thread, time::Duration};
|
||||
use crate::wayland::{surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient};
|
||||
|
||||
const NAMESPACE: &str = "chlorostart";
|
||||
const OVERLAY: u32 = 3;
|
||||
const EXCLUSIVE: u32 = 0; // exclusize keyboard focus
|
||||
const EXCLUSIVE: u32 = 1; // 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();
|
||||
pub fn layer_shell_get_layer_surface(&self) -> Result<(), Box<dyn Error>> {
|
||||
// TODO: Make sure layer_surface_id isn't already set
|
||||
let object: u32 = self.layer_shell_id.load(Ordering::Relaxed);
|
||||
if object == 0 {
|
||||
return Err(UnsetErr("layer_shell_id".to_string()).into());
|
||||
}
|
||||
const OPCODE: u16 = 0;
|
||||
let msg_size: u16 = 28 + (NAMESPACE.len()+1).next_multiple_of(4) as u16;
|
||||
let output: u32 = 0;
|
||||
@@ -19,29 +23,44 @@ impl WlClient {
|
||||
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);
|
||||
let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
|
||||
request.write_u32(¤t_id, &mut offset);
|
||||
|
||||
let surface_id = self.surface_id.load(Ordering::Relaxed);
|
||||
if surface_id == 0 {
|
||||
return Err(UnsetErr("surface_id".to_string()).into());
|
||||
}
|
||||
|
||||
request.write_u32(&surface_id, &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)?;
|
||||
self.socket.lock().unwrap().write(&request)?;
|
||||
self.layer_surface_id.store(current_id, Ordering::Relaxed);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn layer_surface_configure(&mut self, event: &Vec<u8>) -> Result<(), Box<dyn Error>> {
|
||||
pub fn layer_surface_configure(&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);
|
||||
|
||||
println!(
|
||||
"Configure layer surface:\n\twidth: {}\n\theight: {}",
|
||||
width,
|
||||
height
|
||||
);
|
||||
|
||||
// TODO: Resize based on configure
|
||||
|
||||
// Ack configure
|
||||
let object = self.layer_surface_id.unwrap();
|
||||
let object = self.layer_surface_id.load(Ordering::Relaxed);
|
||||
if object == 0 {
|
||||
return Err(UnsetErr("layer_surface_id".to_string()).into());
|
||||
}
|
||||
const OPCODE: u16 = 6;
|
||||
const MSG_SIZE: u16 = 12;
|
||||
|
||||
@@ -54,16 +73,17 @@ impl WlClient {
|
||||
|
||||
request.write_u32(&serial, &mut offset);
|
||||
|
||||
self.socket.write(&request)?;
|
||||
|
||||
self.wl_surface_attach()?;
|
||||
self.wl_surface_commit()?;
|
||||
self.socket.lock().unwrap().write(&request)?;
|
||||
self.wl_surface_frame()?;
|
||||
|
||||
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();
|
||||
pub fn layer_surface_set_size(&self, width: u32, height: u32) -> Result<(), Box<dyn Error>> {
|
||||
let object: u32 = self.layer_surface_id.load(Ordering::Relaxed);
|
||||
if object == 0 {
|
||||
return Err(UnsetErr("layer_surface_id".to_string()).into());
|
||||
}
|
||||
const OPCODE: u16 = 0;
|
||||
const MSG_SIZE: u16 = 20;
|
||||
|
||||
@@ -77,13 +97,16 @@ impl WlClient {
|
||||
request.write_u32(&width, &mut offset);
|
||||
request.write_u32(&height, &mut offset);
|
||||
|
||||
self.socket.write(&request)?;
|
||||
self.socket.lock().unwrap().write(&request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn layer_surface_set_keyboard_interactivity(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
let object: u32 = self.layer_surface_id.unwrap();
|
||||
pub fn layer_surface_set_keyboard_interactivity(&self) -> Result<(), Box<dyn Error>> {
|
||||
let object: u32 = self.layer_surface_id.load(Ordering::Relaxed);
|
||||
if object == 0 {
|
||||
return Err(UnsetErr("layer_surface_id".to_string()).into());
|
||||
}
|
||||
const OPCODE: u16 = 4;
|
||||
const MSG_SIZE: u16 = 12;
|
||||
|
||||
@@ -96,7 +119,7 @@ impl WlClient {
|
||||
|
||||
request.write_u32(&EXCLUSIVE, &mut offset);
|
||||
|
||||
self.socket.write(&request)?;
|
||||
self.socket.lock().unwrap().write(&request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -6,3 +6,5 @@ pub mod wl_shm;
|
||||
pub mod vec_utils;
|
||||
pub mod shm;
|
||||
pub mod wl_registry;
|
||||
pub mod seat;
|
||||
pub mod xkb;
|
||||
|
||||
96
src/wayland/seat.rs
Normal file
96
src/wayland/seat.rs
Normal file
@@ -0,0 +1,96 @@
|
||||
#![feature(unix_socket_ancillary_data)]
|
||||
|
||||
use std::{error::Error, io::{IoSliceMut, Write}, os::unix::net::{AncillaryData, SocketAncillary}, sync::atomic::Ordering};
|
||||
|
||||
use crate::wayland::{shm, vec_utils::WlMessage, wl_client::WlClient, surface::UnsetErr};
|
||||
|
||||
use super::xkb;
|
||||
|
||||
|
||||
impl WlClient {
|
||||
pub fn wl_seat_capabilities(&self, event: &Vec<u8>) -> Result<(), Box<dyn Error>> {
|
||||
let mut offset: usize = 0;
|
||||
let capability = event.read_u32(&mut offset);
|
||||
println!(
|
||||
"Received seat capabilities:\n\tPointer: {}\n\tKeyboard: {}\n\tTouch: {}",
|
||||
(capability & 1) > 0,
|
||||
(capability & 2) > 0,
|
||||
(capability & 4) > 0,
|
||||
);
|
||||
if (capability & 2) > 0 {
|
||||
self.wl_seat_get_keyboard()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wl_seat_name(&self, event: &Vec<u8>) {
|
||||
let mut offset: usize = 0;
|
||||
let name = event.read_string(&mut offset);
|
||||
println!("Recieved seat name: {}", name);
|
||||
}
|
||||
|
||||
pub fn wl_seat_get_keyboard(&self) -> Result<(), Box<dyn Error>> {
|
||||
let object = self.seat_id.load(Ordering::Relaxed);
|
||||
if object == 0 {
|
||||
return Err(UnsetErr("keyboard_id".to_string()).into())
|
||||
}
|
||||
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);
|
||||
|
||||
let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
|
||||
self.keyboard_id.store(current_id, Ordering::Relaxed);
|
||||
request.write_u32(¤t_id, &mut offset);
|
||||
|
||||
self.socket.lock().unwrap().write(&request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wl_keyboard_keymap(&self, event: &Vec<u8>, fd: i32) -> Result<(), Box<dyn Error>>{
|
||||
let mut offset: usize = 0;
|
||||
let format = event.read_u32(&mut offset);
|
||||
let size = event.read_u32(&mut offset);
|
||||
|
||||
let mut keymap_fd = self.keymap_fd.lock().unwrap();
|
||||
*keymap_fd = Some(shm::ShmPool::from_fd(fd, size as usize)?);
|
||||
let mut keymap = self.keymap.write().unwrap();
|
||||
*keymap = xkb::gen_id_keysym_mapping(keymap_fd.as_ref().unwrap());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wl_keyboard_key(&self, event: &Vec<u8>) -> Result<(), Box<dyn Error>> {
|
||||
let mut offset: usize = 0;
|
||||
let serial = event.read_u32(&mut offset);
|
||||
let time = event.read_u32(&mut offset);
|
||||
let key = event.read_u32(&mut offset);
|
||||
let state = event.read_u32(&mut offset);
|
||||
|
||||
if let Some(keymap) = &*self.keymap.read().unwrap() {
|
||||
if let Some(keysym) = keymap.get(&(key + 8)) {
|
||||
if keysym[0] == "Escape" && state == 0 {
|
||||
self.exit();
|
||||
}
|
||||
println!("Received key:\n\t{} {}", keysym[0], if state == 0 {'↑'} else {'↓'});
|
||||
} else {
|
||||
eprintln!("Unrecognized key!");
|
||||
}
|
||||
} else {
|
||||
println!(
|
||||
"Received key:\n\tserial: {}\n\ttime: {}\n\tkey: {}\n\tstate: {}",
|
||||
serial,
|
||||
time,
|
||||
key,
|
||||
state
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,16 @@
|
||||
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};
|
||||
use libc::{c_void, ftruncate, mmap, munmap, shm_open, shm_unlink, MAP_FAILED, MAP_PRIVATE, MAP_SHARED, O_CREAT, O_EXCL, O_RDWR, PROT_READ, PROT_WRITE};
|
||||
|
||||
use crate::graphics::drawable::color_over;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ShmPool {
|
||||
pub fd: i32,
|
||||
pub id: u32,
|
||||
pub addr: *mut c_void,
|
||||
pub size: usize,
|
||||
pub width: usize,
|
||||
}
|
||||
|
||||
impl ShmPool {
|
||||
pub fn new(width: usize, height: usize, id: u32) -> std::io::Result<ShmPool> {
|
||||
let size = width * height * 4;
|
||||
|
||||
pub fn new(size: usize) -> 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 {
|
||||
@@ -38,13 +36,32 @@ impl ShmPool {
|
||||
|
||||
Ok(ShmPool {
|
||||
fd,
|
||||
id,
|
||||
addr,
|
||||
size,
|
||||
width,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_fd(fd: i32, size: usize) -> std::io::Result<ShmPool> {
|
||||
let addr = unsafe { mmap(std::ptr::null_mut(), size, PROT_READ, MAP_PRIVATE, fd, 0) };
|
||||
if addr == MAP_FAILED {
|
||||
eprint!("mmap in ShmPool::from_fd() failed with fd {}", fd);
|
||||
return Err(std::io::Error::last_os_error());
|
||||
}
|
||||
Ok(ShmPool {fd, addr, size})
|
||||
}
|
||||
|
||||
pub fn read_string(&self, offset: usize) -> std::io::Result<String> {
|
||||
let mut res: Vec<u8> = Vec::new();
|
||||
for i in offset..self.size {
|
||||
let byte = unsafe {*(self.addr.offset(i as isize) as *const u8)};
|
||||
if byte == 0 {
|
||||
break;
|
||||
}
|
||||
res.push(byte);
|
||||
};
|
||||
Ok(String::from_utf8(res).unwrap())
|
||||
}
|
||||
|
||||
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())
|
||||
@@ -54,36 +71,60 @@ impl ShmPool {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write(&mut self, data: &Vec<u32>, offset: usize) {
|
||||
if offset > self.size {
|
||||
pub fn write(&mut self, color: u32, offset: usize, len: usize) {
|
||||
if offset + len/4 >= self.size {
|
||||
return;
|
||||
}
|
||||
for i in offset..offset+len { unsafe {
|
||||
*((self.addr as *mut u32).offset(i as isize))
|
||||
= color_over(color, self.read_pixel(i).unwrap());
|
||||
}}
|
||||
}
|
||||
|
||||
pub fn write_raw(&mut self, color: u32, offset: usize, len: usize) {
|
||||
if offset + len/4 >= self.size {
|
||||
return;
|
||||
}
|
||||
for i in offset..offset+len { unsafe {
|
||||
*((self.addr as *mut u32).offset(i as isize)) = color;
|
||||
}}
|
||||
}
|
||||
|
||||
pub fn write_pixel(&mut self, color: u32, offset: usize) {
|
||||
// TODO: Return error if out of bounds
|
||||
if offset + 3 > self.size {
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
std::ptr::copy_nonoverlapping(
|
||||
data.as_ptr() as *const u32, // src: data as *const u32
|
||||
self.addr.offset(4*offset as isize) as *mut u32, // dst: ShmPool address as *mut u32
|
||||
if offset + data.len() * 4 <= self.size {
|
||||
data.len()
|
||||
} else {
|
||||
data.len() - offset
|
||||
}
|
||||
);
|
||||
*((self.addr as *mut u32).offset(offset as isize))
|
||||
= color_over(color, self.read_pixel(offset).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_pixel(&mut self, data: u32, offset: isize) {
|
||||
// TODO: Bounds check
|
||||
unsafe {*(self.addr.offset(offset*4) as *mut u32) = data;}
|
||||
pub fn write_pixel_raw(&mut self, color: u32, offset: usize) {
|
||||
// TODO: Return error if out of bounds
|
||||
if offset + 3 > self.size {
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
*((self.addr as *mut u32).offset(offset as isize)) = color;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_pixel(&self, offset: usize) -> u32 {
|
||||
// TODO: Bounds check
|
||||
return unsafe {*(self.addr.offset(4*offset as isize) as *const u32)};
|
||||
pub fn read_pixel(&self, offset: usize) -> Option<u32> {
|
||||
if offset + 3 > self.size {
|
||||
return None;
|
||||
}
|
||||
return Some(unsafe {*(self.addr.offset(4*offset as isize) as *const u32)});
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ShmPool {
|
||||
fn drop(&mut self) {
|
||||
println!("Dropping ShmPool!");
|
||||
unsafe { munmap(self.addr, self.size); }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for ShmPool {}
|
||||
unsafe impl Sync for ShmPool {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{error::Error, io::Write};
|
||||
use std::{error::Error, io::Write, sync::atomic::Ordering};
|
||||
|
||||
use crate::wayland::{vec_utils::WlMessage, wl_client::WlClient};
|
||||
use crate::wayland::{vec_utils::WlMessage, wl_client::WlClient, wl_shm::wl_buffer};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
@@ -15,12 +15,11 @@ impl fmt::Display for UnsetErr {
|
||||
}
|
||||
|
||||
impl WlClient {
|
||||
pub fn wl_compositor_create_surface(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
if self.compositor_id.is_none() {
|
||||
pub fn wl_compositor_create_surface(&self) -> Result<(), Box<dyn Error>> {
|
||||
let object = self.compositor_id.load(Ordering::Relaxed);
|
||||
if object == 0 {
|
||||
return Err(UnsetErr("compositor_id".to_string()).into());
|
||||
}
|
||||
|
||||
let object = self.compositor_id.unwrap();
|
||||
const OPCODE: u16 = 0;
|
||||
const MSG_SIZE: u16 = 12;
|
||||
|
||||
@@ -31,24 +30,26 @@ impl WlClient {
|
||||
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);
|
||||
let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
|
||||
request.write_u32(¤t_id, &mut offset);
|
||||
|
||||
self.socket.write(&request)?;
|
||||
self.socket.lock().unwrap().write(&request)?;
|
||||
|
||||
self.surface_id = Some(self.current_id);
|
||||
self.surface_id.store(current_id, Ordering::Relaxed);
|
||||
|
||||
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())));
|
||||
pub fn wl_surface_attach(&self, buffer: &wl_buffer) -> Result<(), Box<dyn Error + '_>> {
|
||||
|
||||
let id = buffer.id;
|
||||
|
||||
let object = self.surface_id.load(Ordering::Relaxed);
|
||||
if object == 0 {
|
||||
return Err(UnsetErr("surface_id".to_string()).into());
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -58,17 +59,20 @@ impl WlClient {
|
||||
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(&id, &mut offset);
|
||||
request.write_u32(&X, &mut offset);
|
||||
request.write_u32(&Y, &mut offset);
|
||||
|
||||
self.socket.write(&request)?;
|
||||
self.socket.lock()?.write(&request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wl_surface_commit(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
let object = self.surface_id.unwrap();
|
||||
pub fn wl_surface_commit(&self) -> Result<(), Box<dyn Error>> {
|
||||
let object = self.surface_id.load(Ordering::Relaxed);
|
||||
if object == 0 {
|
||||
return Err(UnsetErr("surface_id".to_string()).into());
|
||||
}
|
||||
const OPCODE: u16 = 6;
|
||||
const MSG_SIZE: u16 = 8;
|
||||
|
||||
@@ -79,16 +83,59 @@ impl WlClient {
|
||||
request.write_u16(&OPCODE, &mut offset);
|
||||
request.write_u16(&MSG_SIZE, &mut offset);
|
||||
|
||||
self.socket.write(&request)?;
|
||||
self.socket.lock().unwrap().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())));
|
||||
pub fn wl_surface_frame(&self) -> Result<(), Box<dyn Error + '_>> {
|
||||
let object = self.surface_id.load(Ordering::Relaxed);
|
||||
if object == 0 {
|
||||
return Err(UnsetErr("surface_id".to_string()).into());
|
||||
}
|
||||
const OPCODE: u16 = 3;
|
||||
const MSG_SIZE: u16 = 12;
|
||||
let id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
|
||||
|
||||
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(&id, &mut offset);
|
||||
self.socket.lock()?.write(&request)?;
|
||||
self.frame_hint_id.store(id, Ordering::Relaxed);
|
||||
|
||||
let buf_lock = if self.active_buffer.fetch_update(
|
||||
Ordering::Relaxed,
|
||||
Ordering::Relaxed,
|
||||
|b| { Some(!b) }
|
||||
).unwrap() {
|
||||
&self.buffer1
|
||||
} else {
|
||||
&self.buffer2
|
||||
}.lock()?;
|
||||
let buffer = buf_lock.as_ref().ok_or(UnsetErr("buffer".to_string()))?;
|
||||
|
||||
self.wl_surface_attach(buffer)?;
|
||||
let mut drawables = self.drawables.lock()?;
|
||||
let mut shm_pool = self.shm_pool.lock()?;
|
||||
shm_pool.write_raw(0, 0, 800 * 800 * 2);
|
||||
for drawable in &mut *drawables {
|
||||
drawable.update();
|
||||
drawable.draw(buffer, &mut *shm_pool);
|
||||
}
|
||||
self.wl_surface_commit()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn xdg_wm_base_pong(&self, event: &Vec<u8>) -> Result<(), Box<dyn Error>> {
|
||||
let object = self.xdg_wm_base_id.load(Ordering::Relaxed);
|
||||
if object == 0 {
|
||||
return Err(UnsetErr("xdg_wm_base_id".to_string()).into());
|
||||
}
|
||||
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());
|
||||
@@ -101,7 +148,7 @@ impl WlClient {
|
||||
request.write_u16(&MSG_SIZE, &mut offset);
|
||||
request.write_u32(&serial, &mut offset);
|
||||
|
||||
self.socket.write(&request)?;
|
||||
self.socket.lock().unwrap().write(&request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{env::var, error::Error, fmt::Debug, io::Read, os::unix::net::UnixStream, u32};
|
||||
use std::{collections::HashMap, env::var, error::Error, fmt::Debug, io::{IoSliceMut, Write}, os::unix::net::{AncillaryData, SocketAncillary, UnixStream}, sync::{atomic::{AtomicBool, AtomicU32, Ordering}, mpsc, Arc, Mutex, RwLock}, thread::{self}, u32};
|
||||
|
||||
use crate::wayland::shm;
|
||||
use crate::{graphics::{circle::Circle, drawable::{premultiply, Drawable}, rectangle::Rectangle}, wayland::{shm, surface::UnsetErr, vec_utils::WlMessage, wl_shm::wl_buffer}};
|
||||
|
||||
struct WlHeader {
|
||||
object: u32,
|
||||
@@ -9,49 +9,107 @@ struct WlHeader {
|
||||
}
|
||||
|
||||
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>,
|
||||
pub socket: Mutex<UnixStream>,
|
||||
pub current_id: AtomicU32,
|
||||
pub running: AtomicBool,
|
||||
pub shm_pool: Mutex<shm::ShmPool>,
|
||||
pub active_buffer: AtomicBool,
|
||||
pub buffer1: Mutex<Option<wl_buffer>>,
|
||||
pub buffer2: Mutex<Option<wl_buffer>>,
|
||||
pub keymap_fd: Mutex<Option<shm::ShmPool>>,
|
||||
pub keymap: RwLock<Option<HashMap<u32, Vec<String>>>>,
|
||||
pub drawables: Mutex<Vec<Box<dyn Drawable>>>,
|
||||
|
||||
pub registry_id: AtomicU32,
|
||||
pub shm_id: AtomicU32,
|
||||
pub shmpool_id: AtomicU32,
|
||||
pub seat_id: AtomicU32,
|
||||
pub keyboard_id: AtomicU32,
|
||||
pub compositor_id: AtomicU32,
|
||||
pub surface_id: AtomicU32,
|
||||
pub xdg_wm_base_id: AtomicU32,
|
||||
pub layer_shell_id: AtomicU32,
|
||||
pub layer_surface_id: AtomicU32,
|
||||
pub frame_hint_id: AtomicU32,
|
||||
}
|
||||
|
||||
impl WlClient {
|
||||
pub fn new() -> Result<Self, Box<dyn Error>> {
|
||||
pub fn run() -> Result<(), Box<dyn Error>> {
|
||||
let sock = UnixStream::connect(format!(
|
||||
"{}/{}",
|
||||
var("XDG_RUNTIME_DIR")?,
|
||||
var("WAYLAND_DISPLAY")?
|
||||
))?;
|
||||
sock.set_nonblocking(true)?;
|
||||
|
||||
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,
|
||||
};
|
||||
let mut arc_wl_client = Arc::new(WlClient {
|
||||
socket: Mutex::new(sock),
|
||||
running: AtomicBool::from(false),
|
||||
current_id: AtomicU32::from(1),
|
||||
registry_id: AtomicU32::from(0),
|
||||
shm_id: AtomicU32::from(0),
|
||||
shmpool_id: AtomicU32::from(0),
|
||||
shm_pool: Mutex::new(shm::ShmPool::new(800 * 800 * 4 * 2)?),
|
||||
active_buffer: AtomicBool::from(false),
|
||||
buffer1: Mutex::new(None),
|
||||
buffer2: Mutex::new(None),
|
||||
frame_hint_id: AtomicU32::from(0),
|
||||
compositor_id: AtomicU32::from(0),
|
||||
surface_id: AtomicU32::from(0),
|
||||
xdg_wm_base_id: AtomicU32::from(0),
|
||||
layer_shell_id: AtomicU32::from(0),
|
||||
layer_surface_id: AtomicU32::from(0),
|
||||
seat_id: AtomicU32::from(0),
|
||||
keyboard_id: AtomicU32::from(0),
|
||||
keymap: RwLock::new(None),
|
||||
keymap_fd: Mutex::new(None),
|
||||
drawables: Mutex::new(Vec::new()),
|
||||
});
|
||||
arc_wl_client.wl_display_get_registry();
|
||||
if let Ok(mut drawables) = arc_wl_client.drawables.lock() {
|
||||
drawables.push(Rectangle::new(50, 50, 300, 300, 16, 0xffff8800).into());
|
||||
drawables.push(Rectangle::new(350, 50, 300, 300, 16, premultiply(0x77aa22aa)).into());
|
||||
drawables.push(Circle::new(350, 80, 25, premultiply(0xff00ffff)).into());
|
||||
drawables.push(Circle::new(350, 160, 25, premultiply(0x8800ffff)).into());
|
||||
drawables.push(Circle::new(350, 240, 25, premultiply(0x0000ffff)).into());
|
||||
}
|
||||
arc_wl_client.running.store(true, Ordering::Relaxed);
|
||||
|
||||
Ok(res)
|
||||
let wl_client = arc_wl_client.clone();
|
||||
let readloop = thread::Builder::new().name("readloop".to_string()).spawn(move || {
|
||||
while wl_client.running.load(Ordering::Relaxed) {
|
||||
wl_client.read_event();
|
||||
}
|
||||
})?;
|
||||
|
||||
readloop.join();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_event(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
pub fn read_event(self: &Arc<Self>) -> Result<(), Box<dyn Error + '_>> {
|
||||
// TODO: Don't realloc header and event
|
||||
|
||||
// FIXME: Using fd like this is unreliable because fd could be before or after
|
||||
// event it was intended to be with
|
||||
let mut fd = 0;
|
||||
|
||||
let mut header = vec![0u8; 8];
|
||||
self.socket.read_exact(&mut header)?;
|
||||
let socket = self.socket.lock().unwrap();
|
||||
let mut ancillary_buf = [0; 128];
|
||||
let mut ancillary = SocketAncillary::new(&mut ancillary_buf);
|
||||
|
||||
socket.recv_vectored_with_ancillary(
|
||||
&mut [IoSliceMut::new(header.as_mut_slice())],
|
||||
&mut ancillary
|
||||
)?;
|
||||
for ancillary_result in ancillary.messages() {
|
||||
if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
|
||||
scm_rights.for_each(|received| {
|
||||
fd = received;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let header = WlHeader {
|
||||
object: u32::from_ne_bytes(header[0..4].try_into()?),
|
||||
@@ -60,29 +118,64 @@ impl WlClient {
|
||||
};
|
||||
|
||||
let mut event = vec![0u8; header.size as usize - 8];
|
||||
self.socket.read_exact(&mut event)?;
|
||||
socket.recv_vectored_with_ancillary(
|
||||
&mut [IoSliceMut::new(event.as_mut_slice())],
|
||||
&mut ancillary
|
||||
)?;
|
||||
for ancillary_result in ancillary.messages() {
|
||||
if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
|
||||
scm_rights.for_each(|received| {
|
||||
fd = received;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if header.object == self.registry_id.unwrap() && header.opcode == 0 { // wl_registry::global
|
||||
drop(socket);
|
||||
|
||||
if let Some(buffer) = self.buffer1.lock()?.as_mut() {
|
||||
if header.object == buffer.id && header.opcode == 0 { // wl_buffer::release
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if header.object == self.registry_id.load(Ordering::Relaxed) && 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
|
||||
else if header.object == self.shm_id.load(Ordering::Relaxed) && 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
|
||||
else if header.object == self.xdg_wm_base_id.load(Ordering::Relaxed) && 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
|
||||
else if header.object == self.layer_surface_id.load(Ordering::Relaxed) && 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 header.object == self.surface_id.load(Ordering::Relaxed) && 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 if header.object == self.surface_id.load(Ordering::Relaxed) && header.opcode == 3 { // wl_surface::preferred_buffer_transform
|
||||
// println!("Preferred buffer transform: {}", i32::from_ne_bytes(event[0..4].try_into().unwrap()));
|
||||
}
|
||||
else if header.object == self.seat_id.load(Ordering::Relaxed) && header.opcode == 0 { // wl_seat::capabilities
|
||||
self.wl_seat_capabilities(&event)?;
|
||||
}
|
||||
else if header.object == self.seat_id.load(Ordering::Relaxed) && header.opcode == 1 { // wl_seat::name
|
||||
self.wl_seat_name(&event);
|
||||
}
|
||||
else if header.object == self.keyboard_id.load(Ordering::Relaxed) && header.opcode == 0 { // wl_keyboard::keymap
|
||||
self.wl_keyboard_keymap(&event, fd)?;
|
||||
}
|
||||
else if header.object == self.keyboard_id.load(Ordering::Relaxed) && header.opcode == 3 { // wl_keyboard::key
|
||||
let wl_client = self.clone();
|
||||
thread::spawn(move || {
|
||||
wl_client.wl_keyboard_key(&event);
|
||||
});
|
||||
}
|
||||
else if header.object == self.frame_hint_id.load(Ordering::Relaxed) && header.opcode == 0 { // wl_callback<frame_hint>::done
|
||||
self.wl_surface_frame()?;
|
||||
}
|
||||
else {
|
||||
println!(
|
||||
@@ -95,31 +188,64 @@ impl WlClient {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn destroy_object(&self, id: u32, opcode: u16) {
|
||||
if id == 0 {
|
||||
return;
|
||||
}
|
||||
const REQ_SIZE: u16 = 8;
|
||||
|
||||
let mut request = vec![0; REQ_SIZE as usize];
|
||||
let mut offset = 0;
|
||||
|
||||
request.write_u32(&id, &mut offset);
|
||||
request.write_u16(&opcode, &mut offset);
|
||||
request.write_u16(&REQ_SIZE, &mut offset);
|
||||
|
||||
self.socket.lock().unwrap().write(&request);
|
||||
self.shmpool_id.store(0, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub fn exit(&self) -> Result<(), Box<dyn Error + '_>> {
|
||||
println!("Exiting!");
|
||||
self.destroy_object(self.layer_surface_id.load(Ordering::Relaxed), 7);
|
||||
self.destroy_object(self.buffer1.lock()?.as_ref().ok_or(UnsetErr("buffer1".to_string()))?.id, 0);
|
||||
self.keymap_fd.lock().unwrap().take();
|
||||
self.running.store(false, Ordering::Relaxed);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for WlClient {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f,
|
||||
"WlClient {{
|
||||
write!(f, "WlClient {{
|
||||
current_id: {},
|
||||
registry_id: {},
|
||||
shm_id: {},
|
||||
buffer_id: {},
|
||||
shmpool_id: {},
|
||||
buffer1: {:?},
|
||||
buffer2: {:?},
|
||||
compositor_id: {},
|
||||
surface_id: {},
|
||||
xdg_wm_base_id: {},
|
||||
layer_shell_id: {},
|
||||
layer_surface_id: {},
|
||||
seat_id: {},
|
||||
keyboard_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),
|
||||
self.current_id.load(Ordering::Relaxed),
|
||||
self.registry_id.load(Ordering::Relaxed),
|
||||
self.shm_id.load(Ordering::Relaxed),
|
||||
self.shmpool_id.load(Ordering::Relaxed),
|
||||
self.buffer1.lock().unwrap(),
|
||||
self.buffer2.lock().unwrap(),
|
||||
self.compositor_id.load(Ordering::Relaxed),
|
||||
self.surface_id.load(Ordering::Relaxed),
|
||||
self.xdg_wm_base_id.load(Ordering::Relaxed),
|
||||
self.layer_shell_id.load(Ordering::Relaxed),
|
||||
self.layer_surface_id.load(Ordering::Relaxed),
|
||||
self.seat_id.load(Ordering::Relaxed),
|
||||
self.keyboard_id.load(Ordering::Relaxed),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
use crate::wayland::{surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient};
|
||||
use std::{io::Write, error::Error};
|
||||
use crate::wayland::{surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient, wl_shm::wl_buffer};
|
||||
use std::{error::Error, io::Write, sync::{atomic::{AtomicU32, Ordering}, Arc}};
|
||||
|
||||
impl WlClient {
|
||||
fn init_toplevel(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
if self.shm_id.is_none() {
|
||||
fn init_toplevel(&self) -> Result<(), Box<dyn Error + '_>> {
|
||||
if self.shm_id.load(Ordering::Relaxed) == 0 {
|
||||
return Err(Box::new(UnsetErr("shm_id".to_string())));
|
||||
}
|
||||
if self.compositor_id.is_none() {
|
||||
if self.compositor_id.load(Ordering::Relaxed) == 0 {
|
||||
return Err(Box::new(UnsetErr("compositor_id".to_string())));
|
||||
}
|
||||
if self.xdg_wm_base_id.is_none() {
|
||||
if self.xdg_wm_base_id.load(Ordering::Relaxed) == 0 {
|
||||
return Err(Box::new(UnsetErr("xdg_wm_base_id".to_string())));
|
||||
}
|
||||
if self.layer_shell_id.is_none() {
|
||||
if self.layer_shell_id.load(Ordering::Relaxed) == 0 {
|
||||
return Err(UnsetErr("layer_shell_id".to_string()).into());
|
||||
}
|
||||
if self.seat_id.load(Ordering::Relaxed) == 0 {
|
||||
return Err(UnsetErr("seat_id".to_string()).into());
|
||||
}
|
||||
println!("Initializing toplevel!");
|
||||
self.wl_compositor_create_surface()?;
|
||||
self.layer_shell_get_layer_surface()?;
|
||||
@@ -23,13 +26,32 @@ impl WlClient {
|
||||
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)?;
|
||||
self.wl_shm_create_pool()?;
|
||||
|
||||
let current_id = self.current_id.fetch_add(2, Ordering::Relaxed);
|
||||
let mut buffer1 = self.buffer1.lock().unwrap();
|
||||
let mut buffer2 = self.buffer2.lock().unwrap();
|
||||
*buffer1 = Some(wl_buffer {
|
||||
id: current_id + 1,
|
||||
offset: 0,
|
||||
width: 800,
|
||||
height: 800,
|
||||
ready: true,
|
||||
});
|
||||
*buffer2 = Some(wl_buffer {
|
||||
id: current_id + 2,
|
||||
offset: 800 * 800, // pixel offset in pool
|
||||
width: 800,
|
||||
height: 800,
|
||||
ready: true,
|
||||
});
|
||||
self.wl_shm_pool_create_buffer(buffer1.as_ref().unwrap())?;
|
||||
self.wl_shm_pool_create_buffer(buffer2.as_ref().unwrap())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wl_display_get_registry(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
pub fn wl_display_get_registry(&self) -> Result<(), Box<dyn Error>> {
|
||||
const OBJECT: u32 = 1;
|
||||
const OPCODE: u16 = 1;
|
||||
const MSG_SIZE: u16 = 12;
|
||||
@@ -41,94 +63,68 @@ impl WlClient {
|
||||
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 current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
|
||||
request.write_u32(¤t_id, &mut offset);
|
||||
|
||||
let written = self.socket.write(&request)?;
|
||||
assert!(written == MSG_SIZE.into());
|
||||
self.socket.lock().unwrap().write(&request)?;
|
||||
self.registry_id.store(current_id, Ordering::Relaxed);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wl_registry_global(&mut self, event: &Vec<u8>) -> Result<(), Box<dyn Error>> {
|
||||
pub fn wl_registry_global(&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,
|
||||
);
|
||||
// println!(
|
||||
// "Received global:\n\tName: {}\n\tInterface: {}\n\tVersion: {}",
|
||||
// name,
|
||||
// interface,
|
||||
// version,
|
||||
// );
|
||||
|
||||
// TODO: Collapse these into one line (probably using a macro)
|
||||
macro_rules! bind_global {
|
||||
($global:tt) => {
|
||||
let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
|
||||
self.wl_registry_bind(&name, &interface, &version, ¤t_id)?;
|
||||
self.$global.store(current_id, Ordering::Relaxed);
|
||||
self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)});
|
||||
};
|
||||
}
|
||||
|
||||
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)});
|
||||
bind_global!(shm_id);
|
||||
}
|
||||
|
||||
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)});
|
||||
else if interface == "wl_compositor" {
|
||||
bind_global!(compositor_id);
|
||||
}
|
||||
|
||||
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)});
|
||||
else if interface == "xdg_wm_base" {
|
||||
bind_global!(xdg_wm_base_id);
|
||||
}
|
||||
|
||||
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)});
|
||||
else if interface == "zwlr_layer_shell_v1" {
|
||||
bind_global!(layer_shell_id);
|
||||
}
|
||||
else if interface == "wl_seat" {
|
||||
bind_global!(seat_id);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wl_registry_bind(
|
||||
&mut self,
|
||||
&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!"))
|
||||
};
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let object: u32 = self.registry_id.load(Ordering::Relaxed);
|
||||
if object == 0 {
|
||||
return Err(UnsetErr("registry_id".to_string()).into());
|
||||
}
|
||||
const OPCODE: u16 = 0;
|
||||
|
||||
let req_size: u16 = 24 + ((interface.len() as u16+3) & (u16::MAX-3));
|
||||
@@ -144,14 +140,7 @@ impl WlClient {
|
||||
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());
|
||||
}
|
||||
};
|
||||
self.socket.lock().unwrap().write(&request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,28 +1,38 @@
|
||||
use std::{error::Error, io::Write, os::unix::net::SocketAncillary, u8};
|
||||
use crate::wayland::{shm, surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient};
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::{error::Error, io::Write, os::unix::net::SocketAncillary, sync::atomic::Ordering, u8};
|
||||
use crate::wayland::{surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient};
|
||||
|
||||
const STRIDE: usize = 4;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct wl_buffer {
|
||||
pub id: u32,
|
||||
pub offset: usize,
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
pub ready: bool,
|
||||
}
|
||||
|
||||
impl WlClient {
|
||||
pub fn wl_shm_format(event: &Vec<u8>) {
|
||||
let mut offset = 0;
|
||||
println!("Received pixel format: {:x}", event.read_u32(&mut offset));
|
||||
// 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, self.current_id)?);
|
||||
self.shm_pool.as_mut().unwrap().write(&vec![0xffff0000; width * height], 0);
|
||||
self.shm_pool.as_mut().unwrap().rectangle(50, 50, 50, 50, 0xff00ff00);
|
||||
self.shm_pool.as_mut().unwrap().circle(300, 300, 200, 0xff0000ff);
|
||||
self.shm_pool.as_mut().unwrap().rounded_rectangle(450, 400, 60, 40, 16, 0xffffff00);
|
||||
pub fn wl_shm_create_pool(&self) -> Result<(), Box<dyn Error>> {
|
||||
let shm_pool = self.shm_pool.lock().unwrap();
|
||||
let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
|
||||
self.shmpool_id.store(current_id, Ordering::Relaxed);
|
||||
|
||||
let object = self.shm_id.ok_or(UnsetErr("shm_id".to_string()))?;
|
||||
let object = self.shm_id.load(Ordering::Relaxed);
|
||||
if object == 0 {
|
||||
return Err(UnsetErr("shm_id".to_string()).into());
|
||||
}
|
||||
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 id = self.shmpool_id.load(Ordering::Relaxed);
|
||||
let fds = [shm_pool.fd];
|
||||
let shm_size = shm_pool.size;
|
||||
|
||||
let mut request = vec![0u8; REQ_SIZE as usize];
|
||||
let mut offset: usize = 0;
|
||||
@@ -46,24 +56,24 @@ impl WlClient {
|
||||
).into());
|
||||
}
|
||||
|
||||
self.socket.send_vectored_with_ancillary(&[std::io::IoSlice::new(&request)], &mut ancillary)?;
|
||||
self.socket.lock().unwrap().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
|
||||
&self,
|
||||
buffer: &wl_buffer
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let object: u32 = self.shm_pool.as_ref().unwrap().id;
|
||||
let object: u32 = self.shmpool_id.load(Ordering::Relaxed);
|
||||
const REQ_SIZE: u16 = 32;
|
||||
const OPCODE: u16 = 0;
|
||||
|
||||
let byte_offset: u32 = buffer.offset as u32 * 4;
|
||||
let width: u32 = buffer.width as u32;
|
||||
let height: u32 = buffer.height as u32;
|
||||
let stride: u32 = width * 4;
|
||||
self.current_id += 1;
|
||||
let id = self.current_id;
|
||||
let id = buffer.id;
|
||||
let format = 0;
|
||||
|
||||
let mut offset: usize = 0;
|
||||
@@ -74,17 +84,14 @@ impl WlClient {
|
||||
request.write_u16(&REQ_SIZE, &mut offset);
|
||||
|
||||
request.write_u32(&id, &mut offset);
|
||||
request.write_u32(&shm_offset, &mut offset);
|
||||
request.write_u32(&byte_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);
|
||||
self.socket.lock().unwrap().write(&request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
167
src/wayland/xkb.rs
Normal file
167
src/wayland/xkb.rs
Normal file
@@ -0,0 +1,167 @@
|
||||
use core::str;
|
||||
use std::{collections::HashMap, fmt::{Debug, Display}, string::{self, ParseError}};
|
||||
|
||||
use super::shm::ShmPool;
|
||||
|
||||
enum Data<'a> {
|
||||
Block(&'a str, Vec<Data<'a>>),
|
||||
Statement(&'a str),
|
||||
}
|
||||
impl Debug for Data<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Block(header, data) => write!(f, "Block({}, {:#?})", header, data),
|
||||
Statement(str) => write!(f, "Statement({})", str),
|
||||
}
|
||||
}
|
||||
}
|
||||
use Data::*;
|
||||
|
||||
fn parse_block(map: &str) -> Vec<Data> {
|
||||
let mut begin = 0;
|
||||
let mut stack = 0;
|
||||
let mut is_statement = true;
|
||||
let mut datas = Vec::new();
|
||||
for (i, byte) in map.bytes().enumerate() {
|
||||
if stack == 0 {
|
||||
if byte == '{' as u8 {
|
||||
datas.push(Block(
|
||||
map.get(begin..i).unwrap(),
|
||||
parse_block(map.get(i+1..).unwrap())
|
||||
));
|
||||
is_statement = false;
|
||||
}
|
||||
else if byte == '}' as u8 {
|
||||
return datas;
|
||||
}
|
||||
else if byte == ';' as u8 || byte == ',' as u8 || byte == ']' as u8 {
|
||||
if is_statement {
|
||||
datas.push(Statement(map.get(begin..i).unwrap()));
|
||||
} else {
|
||||
is_statement = true;
|
||||
}
|
||||
begin = i+1;
|
||||
}
|
||||
else if byte == '[' as u8 {
|
||||
begin = i+1;
|
||||
}
|
||||
}
|
||||
|
||||
if byte == '{' as u8 {
|
||||
stack += 1;
|
||||
}
|
||||
else if byte == '}' as u8 {
|
||||
stack -= 1;
|
||||
}
|
||||
};
|
||||
|
||||
datas
|
||||
}
|
||||
|
||||
fn xkb_symbols(xkb_map: &Data) -> Result<HashMap<String, Vec<String>>, ()> {
|
||||
let mut map_symbols: Option<&Vec<Data>> = None;
|
||||
if let Block(header, subdata) = xkb_map {
|
||||
if header.find("xkb_keymap").is_some() {
|
||||
for subdata in subdata {
|
||||
if let Block(header, subdata) = subdata {
|
||||
if header.find("xkb_symbols").is_some() {
|
||||
map_symbols = Some(&subdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let map_symbols: &Vec<Data> = map_symbols.ok_or(())?;
|
||||
let mut res = HashMap::new();
|
||||
for map_symbols in map_symbols {
|
||||
if let Block(header, map_symbols) = map_symbols {
|
||||
if header.find("key").is_some() {
|
||||
let keysym = header.get(
|
||||
header.find('<').ok_or(())?+1..
|
||||
header.find('>').ok_or(())?
|
||||
).ok_or(())?.to_string();
|
||||
let mut symbols = Vec::new();
|
||||
for map_symbol in map_symbols {
|
||||
if let Statement(map_symbol) = &map_symbol {
|
||||
let mut symbol = String::new();
|
||||
for ch in map_symbol.chars() {
|
||||
if !ch.is_whitespace() {
|
||||
symbol.push(ch);
|
||||
}
|
||||
}
|
||||
symbols.push(symbol);
|
||||
}
|
||||
}
|
||||
res.insert(keysym, symbols);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn first_non_whitespace(s: &str) -> Option<char> {
|
||||
for ch in s.chars() {
|
||||
if !ch.is_whitespace() {
|
||||
return Some(ch);
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
fn xkb_keycodes(xkb_map: &Data) -> Result<HashMap<u32, String>, ()> {
|
||||
let mut keycodes: Option<&Vec<Data>> = None;
|
||||
if let Block(header, subdata) = xkb_map {
|
||||
if header.find("xkb_keymap").is_some() {
|
||||
for subdata in subdata {
|
||||
if let Block(header, subdata) = subdata {
|
||||
if header.find("xkb_keycodes").is_some() {
|
||||
keycodes = Some(&subdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut res = HashMap::new();
|
||||
let keycodes = keycodes.ok_or(())?;
|
||||
for map_keycode in keycodes {
|
||||
if let Statement(map_keycode) = map_keycode {
|
||||
if Some('<') != first_non_whitespace(map_keycode) {
|
||||
continue;
|
||||
}
|
||||
let keysym = map_keycode.get(
|
||||
map_keycode.find('<').ok_or(())?+1..
|
||||
map_keycode.find('>').ok_or(())?
|
||||
).ok_or(())?;
|
||||
let mut keycode = String::new();
|
||||
for ch in map_keycode.get(map_keycode.find('=').ok_or(())?..).ok_or(())?.chars() {
|
||||
if ch.is_digit(10) {
|
||||
keycode.push(ch);
|
||||
}
|
||||
}
|
||||
let keycode: u32 = keycode.parse().or(Err(()))?;
|
||||
res.insert(keycode, keysym.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn gen_id_keysym_mapping(xkb_map: &ShmPool) -> Option<HashMap<u32, Vec<String>>> {
|
||||
let xkb_map = unsafe {str::from_raw_parts(xkb_map.addr as *const u8, xkb_map.size)};
|
||||
let mut res = HashMap::new();
|
||||
let data = parse_block(xkb_map);
|
||||
let mut symbols = xkb_symbols(&data[0]).ok()?;
|
||||
let keycodes = xkb_keycodes(&data[0]).ok()?;
|
||||
for keycode in keycodes {
|
||||
let symbol = symbols.remove(&keycode.1);
|
||||
if let Some(symbol) = symbol {
|
||||
res.insert(keycode.0, symbol);
|
||||
}
|
||||
}
|
||||
|
||||
Some(res)
|
||||
}
|
||||
Reference in New Issue
Block a user