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