fix: XRecordInterceptData layout and data_len check
- Fixed struct to match C: id_base(u64), server_time(u64), client_seq(u64), category(i32), client_swapped(i32), data(ptr), data_len(u64) - data_len is in 4-byte units, not bytes — keyboard events have data_len=1 - Added XRECORD_FROM_SERVER category check - Removed re-grab logic from event loop
This commit is contained in:
parent
d1a5f36606
commit
44d1b0a1d2
2 changed files with 19 additions and 18 deletions
|
|
@ -743,21 +743,12 @@ fn run_with_x11(
|
||||||
capture.focus_lost = false;
|
capture.focus_lost = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for events with 100ms timeout, then re-grab if needed
|
// Wait for events with 100ms timeout
|
||||||
let got_data = capture.wait_for_event(100);
|
let got_data = capture.wait_for_event(100);
|
||||||
let evt = capture.next_event();
|
let evt = capture.next_event();
|
||||||
if evt.is_none() {
|
if evt.is_none() {
|
||||||
static mut LOOP_COUNT: u64 = 0;
|
|
||||||
unsafe { LOOP_COUNT += 1; }
|
|
||||||
if got_data {
|
if got_data {
|
||||||
eprintln!("[vietc] DEBUG: select said data but no event in queue (loop={})", unsafe { LOOP_COUNT });
|
eprintln!("[vietc] DEBUG: select said data but no event in queue");
|
||||||
}
|
|
||||||
if unsafe { LOOP_COUNT } <= 3 || unsafe { LOOP_COUNT } % 50 == 0 {
|
|
||||||
eprintln!("[vietc] DEBUG: no event, grabbed={}, got_data={}", capture.is_grabbed(), got_data);
|
|
||||||
}
|
|
||||||
if !capture.is_grabbed() {
|
|
||||||
eprintln!("[vietc] Keyboard grab lost — re-grabbing");
|
|
||||||
capture.grab_keyboard();
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ const MOD4_MASK: c_int = 64;
|
||||||
// Grab modes
|
// Grab modes
|
||||||
const GRAB_MODE_ASYNC: c_int = 1;
|
const GRAB_MODE_ASYNC: c_int = 1;
|
||||||
|
|
||||||
|
// XRecord categories
|
||||||
|
const XRECORD_FROM_SERVER: c_int = 1;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn dlopen(filename: *const c_char, flag: c_int) -> *mut c_void;
|
fn dlopen(filename: *const c_char, flag: c_int) -> *mut c_void;
|
||||||
fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void;
|
fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void;
|
||||||
|
|
@ -56,14 +59,18 @@ struct XRecordRange {
|
||||||
|
|
||||||
type XRecordCallback = unsafe extern "C" fn(*mut c_void, *mut XRecordInterceptData);
|
type XRecordCallback = unsafe extern "C" fn(*mut c_void, *mut XRecordInterceptData);
|
||||||
|
|
||||||
|
// XRecordInterceptData: matches C layout exactly
|
||||||
|
// C: { XID id_base; Time server_time; unsigned long client_seq;
|
||||||
|
// int category; Bool client_swapped; unsigned char *data; unsigned long data_len; }
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct XRecordInterceptData {
|
struct XRecordInterceptData {
|
||||||
id: u64,
|
id_base: u64, // XID
|
||||||
server_time: u64,
|
server_time: u64, // Time
|
||||||
|
client_seq: u64, // unsigned long
|
||||||
|
category: c_int,
|
||||||
client_swapped: c_int,
|
client_swapped: c_int,
|
||||||
_pad: c_int,
|
|
||||||
data_len: c_int,
|
|
||||||
data: *mut u8,
|
data: *mut u8,
|
||||||
|
data_len: u64, // unsigned long
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -248,8 +255,11 @@ unsafe extern "C" fn record_callback(_closure: *mut c_void, data: *mut XRecordIn
|
||||||
if data.is_null() {
|
if data.is_null() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let data_len = (*data).data_len;
|
if (*data).category != XRECORD_FROM_SERVER {
|
||||||
if data_len < 2 {
|
return;
|
||||||
|
}
|
||||||
|
let data_len_bytes = (*data).data_len * 4; // data_len is in 4-byte units
|
||||||
|
if data_len_bytes < 2 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let data_bytes = (*data).data;
|
let data_bytes = (*data).data;
|
||||||
|
|
@ -264,7 +274,7 @@ unsafe extern "C" fn record_callback(_closure: *mut c_void, data: *mut XRecordIn
|
||||||
}
|
}
|
||||||
|
|
||||||
// XRecord data layout for keyboard events: type(1) + keycode(1) + state(2)
|
// XRecord data layout for keyboard events: type(1) + keycode(1) + state(2)
|
||||||
let state: c_int = if data_len >= 4 {
|
let state: c_int = if data_len_bytes >= 4 {
|
||||||
*(data_bytes.add(2) as *const u16) as c_int
|
*(data_bytes.add(2) as *const u16) as c_int
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue