Skip to content
This repository was archived by the owner on Apr 1, 2023. It is now read-only.

Commit fdcee04

Browse files
author
Asura
committed
grab: grab all keyboard
1 parent a5dfea8 commit fdcee04

File tree

2 files changed

+24
-62
lines changed

2 files changed

+24
-62
lines changed

examples/grab.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
use core::time::Duration;
22
use rdev::Event;
33
use rdev::EventType;
4-
use rdev::Key as RdevKey;
54
use rdev::{disable_grab, enable_grab, exit_grab_listen, start_grab_listen};
6-
use std::collections::HashSet;
75
use std::thread;
86

97
fn callback(event: Event) -> Option<Event> {
108
match event.event_type {
11-
EventType::KeyPress(RdevKey::ControlLeft) | EventType::KeyRelease(RdevKey::ControlLeft) => {
9+
EventType::KeyPress(_key) | EventType::KeyRelease(_key) => {
1210
/* */
1311
println!("{:?}", event.event_type);
1412
None
@@ -22,20 +20,18 @@ fn main() {
2220
let delay = Duration::from_secs(5);
2321

2422
println!("[*] starting grab listen...");
25-
let mut keys: HashSet<RdevKey> = HashSet::<RdevKey>::new();
26-
keys.insert(RdevKey::ControlLeft);
27-
start_grab_listen(callback, keys);
23+
start_grab_listen(callback);
2824

29-
enable_grab();
3025
println!("[*] grab keys(5s), try to press Ctrl+C, won't work on other applications");
26+
enable_grab();
3127
thread::sleep(delay);
3228

29+
println!("[*] ungrab keys(5s), try to press Ctrl+C");
3330
disable_grab();
34-
println!("[*] grab keys(5s), try to press Ctrl+C");
3531
thread::sleep(delay);
3632

37-
enable_grab();
3833
println!("[*] grab keys(5s), try to press Ctrl+C, won't work on other applications");
34+
enable_grab();
3935
thread::sleep(delay);
4036

4137
exit_grab_listen();

src/linux/grab.rs

Lines changed: 19 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,21 @@ use std::os::unix::prelude::AsRawFd;
99
use std::path::Path;
1010
use std::ptr;
1111
use std::thread;
12+
use std::time::Duration;
1213
use std::{
13-
collections::HashSet,
1414
mem::zeroed,
1515
os::raw::c_int,
1616
sync::{mpsc::Sender, Arc, Mutex},
1717
time::SystemTime,
1818
};
19-
use strum::IntoEnumIterator;
20-
use x11::xlib::{self, AnyModifier, Display, GrabModeAsync, KeyPressMask, XUngrabKey};
19+
use x11::xlib::{self, Display, GrabModeAsync, KeyPressMask, KeyReleaseMask};
2120

2221
#[derive(Debug)]
2322
pub struct MyDisplay(*mut xlib::Display);
2423
unsafe impl Sync for MyDisplay {}
2524
unsafe impl Send for MyDisplay {}
2625

2726
lazy_static::lazy_static! {
28-
pub static ref KEYS: Arc<Mutex<Option<HashSet<RdevKey>>>> = Arc::new(Mutex::new(None));
2927
pub static ref SENDER: Arc<Mutex<Option<Sender<GrabEvent>>>> = Arc::new(Mutex::new(None));
3028
}
3129

@@ -43,13 +41,6 @@ pub enum GrabEvent {
4341
KeyEvent(Event),
4442
}
4543

46-
pub fn init_keys(keys: HashSet<RdevKey>) {
47-
let mut global_keys = KEYS.lock().unwrap();
48-
if global_keys.is_none() {
49-
*global_keys = Some(keys);
50-
}
51-
}
52-
5344
fn convert_event(key: RdevKey, is_press: bool) -> Event {
5445
Event {
5546
event_type: if is_press {
@@ -64,56 +55,34 @@ fn convert_event(key: RdevKey, is_press: bool) -> Event {
6455
}
6556
}
6657

67-
fn is_key_grabed(key: RdevKey) -> bool {
68-
let global_keys = KEYS.lock().unwrap();
69-
if let Some(keys) = &*global_keys {
70-
keys.get(&key).is_some()
71-
} else {
72-
panic!("[-] grab error in rdev: Please init keys first");
73-
}
74-
}
75-
76-
fn grab_key(display: *mut Display, grab_window: u64, keycode: i32) {
58+
fn grab_keys(display: *mut Display, grab_window: u64) {
7759
unsafe {
78-
xlib::XGrabKey(
60+
xlib::XGrabKeyboard(
7961
display,
80-
keycode,
81-
AnyModifier,
8262
grab_window,
8363
c_int::from(true),
8464
GrabModeAsync,
8565
GrabModeAsync,
66+
xlib::CurrentTime,
8667
);
68+
xlib::XFlush(display);
69+
thread::sleep(Duration::from_millis(50));
8770
}
8871
}
8972

90-
fn grab_keys(display: *mut Display, grab_window: u64) {
91-
for key in RdevKey::iter() {
92-
let keycode: i32 = linux_keycode_from_key(key).unwrap_or_default() as _;
93-
if is_key_grabed(key) {
94-
grab_key(display, grab_window, keycode);
95-
}
96-
}
97-
}
98-
99-
fn ungrab_key(display: *mut Display, grab_window: u64, keycode: i32) {
73+
fn ungrab_keys(display: *mut Display) {
10074
unsafe {
101-
XUngrabKey(display, keycode, AnyModifier, grab_window);
102-
}
103-
}
104-
105-
fn ungrab_keys(display: *mut Display, grab_window: u64) {
106-
for key in RdevKey::iter() {
107-
let keycode: i32 = linux_keycode_from_key(key).unwrap_or_default() as _;
108-
if is_key_grabed(key) {
109-
ungrab_key(display, grab_window, keycode);
110-
}
75+
xlib::XUngrabKeyboard(display, xlib::CurrentTime);
76+
xlib::XFlush(display);
77+
thread::sleep(Duration::from_millis(50));
11178
}
11279
}
11380

11481
pub fn enable_grab() -> Result<(), GrabError> {
11582
if let Some(tx) = &*SENDER.lock().unwrap() {
11683
tx.send(GrabEvent::Grab).ok();
84+
/* if too fast: poll cannot perceive events */
85+
thread::sleep(Duration::from_millis(50));
11786
} else {
11887
return Err(GrabError::ListenError);
11988
};
@@ -123,21 +92,22 @@ pub fn enable_grab() -> Result<(), GrabError> {
12392
pub fn disable_grab() -> Result<(), GrabError> {
12493
if let Some(tx) = &*SENDER.lock().unwrap() {
12594
tx.send(GrabEvent::UnGrab).ok();
95+
thread::sleep(Duration::from_millis(50));
12696
} else {
12797
return Err(GrabError::ListenError);
12898
};
12999
Ok(())
130100
}
131101

132-
pub fn start_grab_listen<T>(callback: T, keys: HashSet<RdevKey>)
102+
pub fn start_grab_listen<T>(callback: T)
133103
where
134104
T: FnMut(Event) -> Option<Event> + 'static,
135105
{
136106
unsafe {
137107
GLOBAL_CALLBACK = Some(Box::new(callback));
138108
}
139-
init_keys(keys);
140109
start_grab_service();
110+
thread::sleep(Duration::from_millis(50));
141111
}
142112

143113
pub fn exit_grab_listen() -> Result<(), GrabError> {
@@ -215,10 +185,8 @@ fn start_grab_thread() {
215185
let grab_window = unsafe { xlib::XRootWindowOfScreen(screen) };
216186

217187
unsafe {
218-
xlib::XSelectInput(display, grab_window, KeyPressMask);
188+
xlib::XSelectInput(display, grab_window, KeyPressMask | KeyReleaseMask);
219189
}
220-
grab_keys(display, grab_window);
221-
unsafe { xlib::XFlush(display) };
222190

223191
let grab_fd = unsafe { xlib::XConnectionNumber(display) };
224192
unlink_socket(FILE_PATH);
@@ -264,13 +232,11 @@ fn start_grab_thread() {
264232
socket
265233
.recv(buf.as_mut_slice())
266234
.expect("recv function failed");
267-
// if recv "1": grab key
235+
// if recv "1": grab key
268236
if buf[0] == 49 {
269237
grab_keys(display, grab_window);
270-
unsafe { xlib::XFlush(display) };
271238
} else {
272-
ungrab_keys(display, grab_window);
273-
unsafe { xlib::XFlush(display) };
239+
ungrab_keys(display);
274240
}
275241
}
276242
GRAB_KEY => unsafe {

0 commit comments

Comments
 (0)