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(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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
println!(
|
|
||||||
"Received key:\n\tSerial: {}\n\tTime: {}\n\tKey: {}\n\tState: {}",
|
if let Some(keymap) = &*self.keymap.lock().unwrap() {
|
||||||
serial,
|
if let Some(keysym) = keymap.get(&(key + 8)) {
|
||||||
time,
|
println!("Received key:\n\t{} {}", keysym, if state == 0 {'↑'} else {'↓'});
|
||||||
key,
|
} else {
|
||||||
state
|
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})
|
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())
|
||||||
|
|||||||
@@ -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
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