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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use std::collections::HashMap;
use std::mem;
use std::os::raw::c_ulong;
use std::ptr;
use x11_dl::xlib;
pub mod modifiers {
use x11_dl::xlib;
pub const ALT: u32 = xlib::Mod1Mask;
pub const CONTROL: u32 = xlib::ControlMask;
pub const SHIFT: u32 = xlib::ShiftMask;
pub const SUPER: u32 = xlib::Mod4Mask;
}
pub type ListenerID = (i32, u32);
pub struct Listener {
display: *mut xlib::Display,
root: c_ulong,
xlib: xlib::Xlib,
handlers: HashMap<ListenerID, Box<dyn Fn()>>,
}
impl Listener {
pub fn new() -> Listener {
let xlib = xlib::Xlib::open().unwrap();
unsafe {
let display = (xlib.XOpenDisplay)(ptr::null());
let mut supported_rtrn: i32 = mem::MaybeUninit::uninit().assume_init();
(xlib.XkbSetDetectableAutoRepeat)(display, 1, &mut supported_rtrn);
Listener {
display: display,
root: (xlib.XDefaultRootWindow)(display),
xlib,
handlers: HashMap::new(),
}
}
}
pub fn register_hotkey<CB: 'static + Fn()>(
&mut self,
modifiers: u32,
key: u32,
handler: CB,
) -> Result<ListenerID, String> {
unsafe {
let keycode = (self.xlib.XKeysymToKeycode)(self.display, key as u64) as i32;
let result = (self.xlib.XGrabKey)(
self.display,
keycode,
modifiers,
self.root,
0,
xlib::GrabModeAsync,
xlib::GrabModeAsync,
);
if result == 0 {
return Err("Failed to register hotkey".to_string());
}
let id = (keycode, modifiers);
self.handlers.insert(id, Box::new(handler));
Ok(id)
}
}
pub fn listen(self) {
unsafe {
(self.xlib.XSelectInput)(self.display, self.root, xlib::KeyReleaseMask);
let mut event: xlib::XEvent = mem::MaybeUninit::uninit().assume_init();
loop {
(self.xlib.XNextEvent)(self.display, &mut event);
match event.get_type() {
xlib::KeyRelease => {
if let Some(handler) = self
.handlers
.get(&(event.key.keycode as i32, event.key.state))
{
handler();
}
}
_ => (),
}
}
}
}
}