Parse keysyms from xkb config and interpret key in wl_keyboard.key
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
#![feature(unix_socket_ancillary_data)]
|
||||
#![feature(str_from_raw_parts)]
|
||||
|
||||
use std::{error::Error, thread, time::Duration};
|
||||
|
||||
mod wayland;
|
||||
|
||||
@@ -7,3 +7,4 @@ pub mod vec_utils;
|
||||
pub mod shm;
|
||||
pub mod wl_registry;
|
||||
pub mod seat;
|
||||
pub mod xkb;
|
||||
|
||||
@@ -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 super::xkb;
|
||||
|
||||
|
||||
impl WlClient {
|
||||
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 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(())
|
||||
}
|
||||
|
||||
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 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);
|
||||
println!(
|
||||
"Received key:\n\tSerial: {}\n\tTime: {}\n\tKey: {}\n\tState: {}",
|
||||
serial,
|
||||
time,
|
||||
key,
|
||||
state
|
||||
)
|
||||
|
||||
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!(
|
||||
"Received key:\n\tserial: {}\n\ttime: {}\n\tkey: {}\n\tstate: {}",
|
||||
serial,
|
||||
time,
|
||||
key,
|
||||
state
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,18 @@ impl ShmPool {
|
||||
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<()> {
|
||||
if unsafe { ftruncate(self.fd, size as i64) } == -1 {
|
||||
return Err(std::io::Error::last_os_error())
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#![feature(unix_socket_ancillary_data)]
|
||||
|
||||
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 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 crate::wayland::shm;
|
||||
|
||||
@@ -25,7 +23,8 @@ pub struct WlClient {
|
||||
pub layer_surface_id: AtomicU32,
|
||||
pub seat_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 {
|
||||
@@ -52,6 +51,7 @@ impl WlClient {
|
||||
seat_id: AtomicU32::from(0),
|
||||
keyboard_id: AtomicU32::from(0),
|
||||
keymap: Mutex::new(None),
|
||||
keymap_fd: Mutex::new(None),
|
||||
});
|
||||
|
||||
let mut wl_client2 = wl_client.clone();
|
||||
|
||||
115
src/wayland/xkb.rs
Normal file
115
src/wayland/xkb.rs
Normal 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)
|
||||
}
|
||||
Reference in New Issue
Block a user