Parse keysyms from xkb config and interpret key in wl_keyboard.key

This commit is contained in:
2025-05-11 18:20:15 -07:00
parent a7c2956313
commit 1efb3f661b
6 changed files with 158 additions and 13 deletions

View File

@@ -1,4 +1,6 @@
#![feature(unix_socket_ancillary_data)] #![feature(unix_socket_ancillary_data)]
#![feature(str_from_raw_parts)]
use std::{error::Error, thread, time::Duration}; use std::{error::Error, thread, time::Duration};
mod wayland; mod wayland;

View File

@@ -7,3 +7,4 @@ pub mod vec_utils;
pub mod shm; pub mod shm;
pub mod wl_registry; pub mod wl_registry;
pub mod seat; pub mod seat;
pub mod xkb;

View File

@@ -4,6 +4,8 @@ use std::{error::Error, io::{IoSliceMut, Write}, os::unix::net::{AncillaryData,
use crate::wayland::{shm, vec_utils::WlMessage, wl_client::WlClient, surface::UnsetErr}; use crate::wayland::{shm, vec_utils::WlMessage, wl_client::WlClient, surface::UnsetErr};
use super::xkb;
impl WlClient { impl WlClient {
pub fn wl_seat_capabilities(&self, event: &Vec<u8>) -> Result<(), Box<dyn Error>> { pub fn wl_seat_capabilities(&self, event: &Vec<u8>) -> Result<(), Box<dyn Error>> {
@@ -56,23 +58,36 @@ impl WlClient {
let format = event.read_u32(&mut offset); let format = event.read_u32(&mut offset);
let size = event.read_u32(&mut offset); let size = event.read_u32(&mut offset);
*self.keymap.lock().unwrap() = Some(shm::ShmPool::from_fd(fd, size as usize)?); 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.lock().unwrap();
*keymap = xkb::gen_id_keysym_mapping(keymap_fd.as_ref().unwrap());
Ok(()) Ok(())
} }
pub fn wl_keyboard_key(&self, event: &Vec<u8>) { pub fn wl_keyboard_key(&self, event: &Vec<u8>) -> Result<(), Box<dyn Error>> {
let mut offset: usize = 0; let mut offset: usize = 0;
let serial = event.read_u32(&mut offset); let serial = event.read_u32(&mut offset);
let time = event.read_u32(&mut offset); let time = event.read_u32(&mut offset);
let key = event.read_u32(&mut offset); let key = event.read_u32(&mut offset);
let state = event.read_u32(&mut offset); let state = event.read_u32(&mut offset);
if let Some(keymap) = &*self.keymap.lock().unwrap() {
if let Some(keysym) = keymap.get(&(key + 8)) {
println!("Received key:\n\t{} {}", keysym, if state == 0 {'↑'} else {'↓'});
} else {
eprintln!("Unrecognized key!");
}
} else {
println!( println!(
"Received key:\n\tSerial: {}\n\tTime: {}\n\tKey: {}\n\tState: {}", "Received key:\n\tserial: {}\n\ttime: {}\n\tkey: {}\n\tstate: {}",
serial, serial,
time, time,
key, key,
state state
) );
}
Ok(())
} }
} }

View File

@@ -52,6 +52,18 @@ impl ShmPool {
Ok(ShmPool {fd, addr, size, width: 0}) Ok(ShmPool {fd, addr, size, width: 0})
} }
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<()> { pub fn resize(&mut self, size: usize) -> std::io::Result<()> {
if unsafe { ftruncate(self.fd, size as i64) } == -1 { if unsafe { ftruncate(self.fd, size as i64) } == -1 {
return Err(std::io::Error::last_os_error()) return Err(std::io::Error::last_os_error())

View File

@@ -1,6 +1,4 @@
#![feature(unix_socket_ancillary_data)] use std::{collections::HashMap, env::var, error::Error, fmt::Debug, io::IoSliceMut, os::unix::net::{AncillaryData, SocketAncillary, UnixStream}, sync::{atomic::{AtomicU32, Ordering}, Arc, Mutex}, thread::{self}, u32};
use std::{env::var, error::Error, fmt::Debug, io::{IoSliceMut, Read}, os::unix::net::{AncillaryData, SocketAncillary, UnixStream}, sync::{atomic::{AtomicU32, Ordering}, Arc, Mutex}, thread::{self, JoinHandle}, u32};
use crate::wayland::shm; use crate::wayland::shm;
@@ -25,7 +23,8 @@ pub struct WlClient {
pub layer_surface_id: AtomicU32, pub layer_surface_id: AtomicU32,
pub seat_id: AtomicU32, pub seat_id: AtomicU32,
pub keyboard_id: AtomicU32, pub keyboard_id: AtomicU32,
pub keymap: Mutex<Option<shm::ShmPool>>, pub keymap_fd: Mutex<Option<shm::ShmPool>>,
pub keymap: Mutex<Option<HashMap<u32, String>>>
} }
impl WlClient { impl WlClient {
@@ -52,6 +51,7 @@ impl WlClient {
seat_id: AtomicU32::from(0), seat_id: AtomicU32::from(0),
keyboard_id: AtomicU32::from(0), keyboard_id: AtomicU32::from(0),
keymap: Mutex::new(None), keymap: Mutex::new(None),
keymap_fd: Mutex::new(None),
}); });
let mut wl_client2 = wl_client.clone(); let mut wl_client2 = wl_client.clone();

115
src/wayland/xkb.rs Normal file
View File

@@ -0,0 +1,115 @@
use core::str;
use std::{collections::HashMap, string};
use super::shm::ShmPool;
#[derive(Debug)]
enum ParseMode {
Default,
Outer,
Inner,
Min,
Max,
Keysym,
Keycode,
}
use ParseMode::*;
pub fn gen_id_keysym_mapping(xkb_map: &ShmPool) -> Option<HashMap<u32, String>> {
let mut word = String::new();
let mut keycodes: bool = false;
let mut parse_mode = ParseMode::Default;
let mut max = 0;
let mut min = 0;
let mut keycode: String = String::new();
let mut keysym: String = String::new();
let mut res: HashMap<u32, String> = HashMap::new();
// TODO: Make this not a nightmare if else tree
for ch in unsafe {str::from_raw_parts(xkb_map.addr as *mut u8, xkb_map.size)}.chars() {
match parse_mode {
Default => {
if ch.is_whitespace() {
word.clear();
} else {
word.push(ch);
}
if word == "xkb_keycodes" {
parse_mode = Outer;
}
}
Outer => {
if ch == '{' {
parse_mode = Inner;
}
}
Inner => {
if ch.is_whitespace() {
word.clear();
} else {
word.push(ch);
}
if ch == '}' {
break;
} else if ch == '<' {
parse_mode = Keysym;
} else if ch == '=' {
parse_mode = Keycode;
}
if word == "minimum" {
parse_mode = Min;
}
else if word == "maximum" {
parse_mode = Max;
}
}
Min => {
if ch == ';' {
min = u32::from_str_radix(keycode.as_str(), 10).unwrap();
keycode.clear();
parse_mode = Inner;
} else if ch.is_digit(10) {
keycode.push(ch);
}
}
Max => {
if ch == ';' {
max = u32::from_str_radix(keycode.as_str(), 10).unwrap();
keycode.clear();
parse_mode = Inner;
} else if ch.is_digit(10) {
keycode.push(ch);
}
}
Keysym => {
if ch == '>' {
parse_mode = Inner;
} else {
keysym.push(ch);
}
}
Keycode => {
if ch == ';' {
let code = u32::from_str_radix(keycode.as_str(), 10).unwrap();
res.insert(code, keysym.clone());
if u32::from_str_radix(keycode.as_str(), 10).unwrap() >= max {
break;
}
keycode.clear();
keysym.clear();
parse_mode = Inner;
} else if ch.is_digit(10) {
keycode.push(ch);
}
}
}
}
Some(res)
}