Properly understand keys pressed and unpressed
This commit is contained in:
@@ -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!");
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user