1use std::collections::HashMap;
2use std::ffi::CStr;
3use x11::xlib::{
4 Display, KeyCode, KeySym, XCloseDisplay, XDisplayKeycodes, XFree, XGetKeyboardMapping,
5 XKeysymToString, XOpenDisplay,
6};
7
8pub type XmodmapPke = HashMap<u8, Vec<String>>;
9
10pub fn xmodmap_pke() -> Result<XmodmapPke, String> {
13 let dpy: *mut Display = unsafe { XOpenDisplay(std::ptr::null::<libc::c_char>()) };
14 let mut xmodmap_pke_table: XmodmapPke = HashMap::new();
15 let mut min_keycode = 0;
16 let mut max_keycode = 0;
17 let mut keysyms_per_keycode = 0;
18 let mut keymap: *mut KeySym;
19 let origkeymap: *mut KeySym;
20 unsafe {
21 XDisplayKeycodes(dpy, &mut min_keycode, &mut max_keycode);
22 }
23 origkeymap = unsafe {
24 XGetKeyboardMapping(
25 dpy,
26 min_keycode as KeyCode,
27 max_keycode - min_keycode + 1_i32,
28 &mut keysyms_per_keycode,
29 )
30 };
31 if origkeymap.is_null() {
32 return Err("unable to get keyboard mapping table.".to_string());
33 }
34 keymap = origkeymap;
35 for i in min_keycode..=max_keycode {
36 let mut max = keysyms_per_keycode - 1;
37 while max >= 0 && unsafe { *keymap.offset(max as isize) } == 0_u64 {
38 max -= 1
39 }
40 let mut ksyms: Vec<String> = Vec::new();
41 for j in 0..=max {
42 let ks: KeySym = unsafe { *keymap.offset(j as isize) };
43 let s = if ks == 0_u64 {
44 "NoSymbol"
45 } else {
46 unsafe { CStr::from_ptr(XKeysymToString(ks)) }
47 .to_str()
48 .unwrap()
49 };
50 if s.is_empty() {
51 ksyms.push(format!("{:0>4x}", ks));
52 } else {
53 ksyms.push(s.to_string());
54 }
55 }
56 keymap = unsafe { keymap.offset(keysyms_per_keycode as isize) };
57 xmodmap_pke_table.insert(i as u8, ksyms);
58 }
59 unsafe {
60 XFree(origkeymap.cast::<i8>().cast::<libc::c_void>());
61 XCloseDisplay(dpy);
62 }
63 Ok(xmodmap_pke_table)
64}