Properly understand keys pressed and unpressed

This commit is contained in:
2025-05-14 22:05:31 -07:00
parent 9d0b9b97b5
commit 5b8475f1a3
4 changed files with 158 additions and 106 deletions

View File

@@ -60,7 +60,7 @@ impl WlClient {
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();
let mut keymap = self.keymap.write().unwrap();
*keymap = xkb::gen_id_keysym_mapping(keymap_fd.as_ref().unwrap());
Ok(())
@@ -73,12 +73,12 @@ impl WlClient {
let key = event.read_u32(&mut offset);
let state = event.read_u32(&mut offset);
if let Some(keymap) = &*self.keymap.lock().unwrap() {
if let Some(keymap) = &*self.keymap.read().unwrap() {
if let Some(keysym) = keymap.get(&(key + 8)) {
if keysym == "ESC" && state == 0 {
if keysym[0] == "Escape" && state == 0 {
self.exit();
}
println!("Received key:\n\t{} {}", keysym, if state == 0 {'↑'} else {'↓'});
println!("Received key:\n\t{} {}", keysym[0], if state == 0 {'↑'} else {'↓'});
} else {
eprintln!("Unrecognized key!");
}

View File

@@ -1,4 +1,4 @@
use std::{collections::HashMap, env::var, error::Error, fmt::Debug, io::{IoSliceMut, Write}, os::unix::net::{AncillaryData, SocketAncillary, UnixStream}, sync::{atomic::{AtomicU32, AtomicBool, Ordering}, mpsc, Arc, Mutex}, thread::{self}, time::Duration, 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}, time::Duration, u32};
use crate::wayland::{shm, vec_utils::WlMessage};
@@ -31,7 +31,7 @@ pub struct WlClient {
pub seat_id: AtomicU32,
pub keyboard_id: AtomicU32,
pub keymap_fd: Mutex<Option<shm::ShmPool>>,
pub keymap: Mutex<Option<HashMap<u32, String>>>
pub keymap: RwLock<Option<HashMap<u32, Vec<String>>>>
}
impl WlClient {
@@ -62,7 +62,7 @@ impl WlClient {
layer_surface_id: AtomicU32::from(0),
seat_id: AtomicU32::from(0),
keyboard_id: AtomicU32::from(0),
keymap: Mutex::new(None),
keymap: RwLock::new(None),
keymap_fd: Mutex::new(None),
});
arc_wl_client.wl_display_get_registry();

View File

@@ -16,11 +16,11 @@ impl WlClient {
let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
self.shmpool_id.store(current_id, Ordering::Relaxed);
shm_pool.write(&vec![0xffff0000; width * height], 0);
let rect = Rectangle::new(100, 100, 200, 50, 25, 0xffffff);
// shm_pool.write(&vec![0xffff0000; width * height], 0);
let rect = Rectangle::new(100, 100, 200, 50, 20, 0xffffff);
rect.draw(&mut shm_pool);
let circle = Circle::new(250, 150, 20, 0xff00ffff);
circle.draw(&mut shm_pool);
// let circle = Circle::new(250, 150, 20, 0xff00ffff);
// circle.draw(&mut shm_pool);
let object = self.shm_id.load(Ordering::Relaxed);
if object == 0 {

View File

@@ -1,115 +1,167 @@
use core::str;
use std::{collections::HashMap, string};
use std::{collections::HashMap, fmt::{Debug, Display}, string::{self, ParseError}};
use super::shm::ShmPool;
#[derive(Debug)]
enum ParseMode {
Default,
Outer,
Inner,
Min,
Max,
Keysym,
Keycode,
enum Data<'a> {
Block(&'a str, Vec<Data<'a>>),
Statement(&'a str),
}
use ParseMode::*;
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::*;
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();
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 {
word.push(ch);
}
if word == "xkb_keycodes" {
parse_mode = Outer;
is_statement = true;
}
begin = i+1;
}
Outer => {
if ch == '{' {
parse_mode = Inner;
}
else if byte == '[' as u8 {
begin = i+1;
}
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 byte == '{' as u8 {
stack += 1;
}
else if byte == '}' as u8 {
stack -= 1;
}
};
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;
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);
}
keycode.clear();
keysym.clear();
parse_mode = Inner;
} else if ch.is_digit(10) {
keycode.push(ch);
}
}
}
}
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)
}