From 8a20bb2d25b27f0e09028a5b12a44f803f3bc65b Mon Sep 17 00:00:00 2001 From: Gabriel <68819302+obsidianical@users.noreply.github.com> Date: Wed, 29 Jun 2022 14:34:15 +0200 Subject: [PATCH] painful segfault apparently! :,) --- src/bin/easymacrorec.rs | 74 +++++++++++++++++++++++++++-------------- src/x11_safe_wrapper.rs | 41 +++++++++++++++++------ 2 files changed, 79 insertions(+), 36 deletions(-) diff --git a/src/bin/easymacrorec.rs b/src/bin/easymacrorec.rs index 211110a..e5acdbb 100644 --- a/src/bin/easymacrorec.rs +++ b/src/bin/easymacrorec.rs @@ -1,12 +1,15 @@ +extern crate core; + use std::os::raw::{c_char, c_uchar, c_uint}; use std::process::{exit, ExitCode}; use std::ptr::{addr_of, slice_from_raw_parts}; use std::{slice, thread}; +use std::ffi::c_void; use clap::Parser; use x11::keysym::XK_Escape; use x11::xinput2::XIGrabModeSync; -use x11::xlib::{CurrentTime, GrabModeAsync, GrabModeSync, GrabSuccess, KeyCode, KeyPress, KeyPressMask, SyncPointer, XEvent, XFree, XKeyEvent, XKeyPressedEvent, XPointer}; -use x11::xrecord::{XRecordContext, XRecordCreateContext, XRecordDisableContext, XRecordEndOfData, XRecordFreeData, XRecordInterceptData, XRecordStartOfData}; +use x11::xlib::{ButtonPress, ButtonRelease, CurrentTime, GrabModeAsync, GrabModeSync, GrabSuccess, KeyCode, KeyPress, KeyPressMask, KeyRelease, MotionNotify, SyncPointer, XEvent, XFree, XKeyEvent, XKeyPressedEvent, XPointer}; +use x11::xrecord::{XRecordAllocRange, XRecordContext, XRecordCreateContext, XRecordDisableContext, XRecordEndOfData, XRecordFreeData, XRecordInterceptData, XRecordStartOfData}; use easymacros::x11_safe_wrapper::{Keycode, XDisplay}; /// Macro recording module for easymacros. Outputs are partially compatible with xmacro. @@ -70,8 +73,9 @@ fn get_stop_key(display: XDisplay) -> Keycode { fn ev_loop(display: XDisplay, recordeddpy: XDisplay, screen: i32, stop_key: Keycode) { let root = display.get_root_window(screen); + let protocol_ranges = unsafe { XRecordAllocRange() }; - let ctx = recordeddpy.create_record_context(); + let ctx = recordeddpy.create_record_context(protocol_ranges); let ev_cb_data = EvCallbackData { xdpy: display, recdpy: recordeddpy, @@ -81,13 +85,16 @@ fn ev_loop(display: XDisplay, recordeddpy: XDisplay, screen: i32, stop_key: Keyc working: true }; - recordeddpy.enable_context_async(ctx, Some(ev_callback), addr_of!(ev_cb_data) as *mut c_char); + if !recordeddpy.enable_context_async(ctx, Some(ev_callback), addr_of!(ev_cb_data) as *mut c_char) { + panic!("Failed to enable record context") + } while ev_cb_data.working { recordeddpy.process_replies(); } display.disable_context(ctx); display.free_context(ctx); + unsafe { XFree(protocol_ranges as *mut c_void) }; } #[derive(Debug)] @@ -105,10 +112,12 @@ pub struct EvCallbackData { unsafe extern "C" fn ev_callback(closure: *mut c_char, intercept_data: *mut XRecordInterceptData) { - println!("Got event!!!"); - + dbg!(intercept_data); + dbg!(closure); let data = &mut *(closure as *mut EvCallbackData); let intercept_data = &mut *intercept_data; + dbg!(&intercept_data); + dbg!(&data); if intercept_data.category == XRecordStartOfData { println!("Got start of data!"); @@ -118,26 +127,41 @@ unsafe extern "C" fn ev_callback(closure: *mut c_char, intercept_data: *mut XRec return; } data.nr_evs += 1; - println!("nr: {:?}, len: {:?}", data, intercept_data.len); - let s: &[i32] = unsafe { - slice::from_raw_parts(intercept_data.data as *const i32, 4) - }; - let ev = unsafe { slice::from_raw_parts(intercept_data.data as *const u8, 2) }; - println!("data: {:?}", s); - let x: XKeyPressedEvent; + // println!("nr: {:?}, len: {:?}", data, intercept_data.data_len); - if ev[0] == KeyPress { - if ev[1] == data.stop_key as i32 { - println!("stop key detected!"); - // if !data.xdpy.disable_context() { - // println!("failed to disable context"); - // } - // let res = data.xdpy.disable_context(data.ctx); - // println!("disabling context: {:?}", res); - data.working = false; - return; + dbg!(intercept_data.data); + let ev_type = *(intercept_data.data as *const u8); + match ev_type { + KEYPRESS_U8 => { + let kc = *((intercept_data.data as usize + 1) as *const u8); + let stop = kc == data.stop_key as u8; + if stop { + println!("stop key detected!"); + data.working = false; + XRecordFreeData(intercept_data) + } else { + // let keyname = data.xdpy.keycode_to_string(kc as u32); + let keyname = data.xdpy.keycode_to_string(44); + let rstring = format!("KeyPress {}", &keyname.to_str().unwrap()); + // let rstring = format!("KeyPress {}", kc); + // dbg!(kc); + dbg!(&rstring); + std::mem::forget(keyname); + // XRecordFreeData(intercept_data) + } } + KEYRELEASE_U8 => {} + BUTTONPRESS_U8 => {} + BUTTONRELEASE_U8 => {} + MOTIONNOTIFY_U8 => {} + _ => eprintln!("Unknown event type: {:?}", ev_type) } - XRecordFreeData(intercept_data) -} \ No newline at end of file +} + +const KEYPRESS_U8: u8 = KeyPress as u8; +const KEYRELEASE_U8: u8 = KeyRelease as u8; +const BUTTONPRESS_U8: u8 = ButtonPress as u8; +const BUTTONRELEASE_U8: u8 = ButtonRelease as u8; +const MOTIONNOTIFY_U8: u8 = MotionNotify as u8; + diff --git a/src/x11_safe_wrapper.rs b/src/x11_safe_wrapper.rs index 5354b85..d6f57fe 100644 --- a/src/x11_safe_wrapper.rs +++ b/src/x11_safe_wrapper.rs @@ -2,8 +2,8 @@ use std::cell::{Ref, RefCell}; use std::env; use std::ffi::CString; use std::os::raw::{c_char, c_int, c_uchar, c_uint, c_ulong}; -use x11::xlib::{Display, GenericEvent, KeyPress, MotionNotify, Time, Window, XAllowEvents, XAnyEvent, XCloseDisplay, XDefaultScreen, XEvent, XFlush, XGrabKeyboard, XKeyEvent, XKeysymToKeycode, XOpenDisplay, XRootWindow, XStringToKeysym, XSync, XUngrabKeyboard, XUngrabPointer, XWindowEvent}; -use x11::xrecord::{XRecordAllClients, XRecordAllocRange, XRecordClientInfo, XRecordClientSpec, XRecordContext, XRecordCreateContext, XRecordDisableContext, XRecordEnableContext, XRecordEnableContextAsync, XRecordFreeContext, XRecordInterceptData, XRecordProcessReplies, XRecordQueryVersion}; +use x11::xlib::{Display, GenericEvent, KeyCode, KeyPress, MotionNotify, Status, Time, Window, XAllowEvents, XAnyEvent, XCloseDisplay, XDefaultScreen, XEvent, XFlush, XGrabKeyboard, XKeycodeToKeysym, XKeyEvent, XKeysymToKeycode, XKeysymToString, XOpenDisplay, XRootWindow, XStringToKeysym, XSync, XUngrabKeyboard, XUngrabPointer, XWindowEvent}; +use x11::xrecord::{XRecordAllClients, XRecordAllocRange, XRecordClientInfo, XRecordClientSpec, XRecordContext, XRecordCreateContext, XRecordDisableContext, XRecordEnableContext, XRecordEnableContextAsync, XRecordFreeContext, XRecordInterceptData, XRecordProcessReplies, XRecordQueryVersion, XRecordRange}; use x11::xtest::{ XTestFakeButtonEvent, XTestFakeKeyEvent, XTestFakeMotionEvent, XTestGrabControl, XTestQueryExtension, @@ -57,7 +57,7 @@ impl XDisplay { unsafe { XRootWindow(self.ptr, screen_nr) } } - pub fn keysym_to_keycode(&self, keysym: c_ulong) -> Keycode { + pub fn keysym_to_keycode(&self, keysym: Keysym) -> Keycode { unsafe { XKeysymToKeycode(self.ptr, keysym) as Keycode } } @@ -65,6 +65,16 @@ impl XDisplay { self.keysym_to_keycode(string_to_keysym(string)) } + pub fn keycode_to_keysym(&self, keycode: Keycode) -> Keysym { + unsafe { + XKeycodeToKeysym(self.ptr, keycode as c_uchar, 0) + } + } + + pub fn keycode_to_string(&self, keycode: Keycode) -> CString { + keysym_to_string(self.keycode_to_keysym(keycode)) + } + // XTest stuff pub fn has_xtest(&self) -> bool { let mut vals: (c_int, c_int, c_int, c_int) = (0, 0, 0, 0); @@ -159,8 +169,7 @@ impl XDisplay { xrec_res == 0 } - pub fn create_record_context(&self) -> XRecordContext { - let mut protocol_ranges = unsafe { XRecordAllocRange() }; + pub fn create_record_context(&self, mut protocol_ranges: *mut XRecordRange) -> XRecordContext { unsafe { (*protocol_ranges).device_events.first = KeyPress as c_uchar; (*protocol_ranges).device_events.last = MotionNotify as c_uchar; @@ -184,19 +193,19 @@ impl XDisplay { ctx: XRecordContext, cb:Option, closure: *mut c_char - ) { + ) -> bool { unsafe { - XRecordEnableContext( self.ptr, ctx, cb, closure as *mut c_char ); + XRecordEnableContext( self.ptr, ctx, cb, closure as *mut c_char ) != 0 } } pub fn enable_context_async(&self, ctx: XRecordContext, - cb: Option, - closure: *mut c_char, - ) { + cb: Option, + closure: *mut c_char, + ) -> bool { unsafe { - XRecordEnableContextAsync( self.ptr, ctx, cb, closure as *mut c_char ); + XRecordEnableContextAsync( self.ptr, ctx, cb, closure as *mut c_char ) != 0 } } @@ -221,3 +230,13 @@ impl XDisplay { pub fn string_to_keysym(string: &[u8]) -> Keysym { unsafe { XStringToKeysym(string.as_ptr() as *const c_char) } } +pub fn keysym_to_string(keysym: Keysym) -> CString { + unsafe { + let raw = XKeysymToString(keysym); + dbg!(raw); + let r = CString::from_raw(raw); + r + } + // .into_string() + // .expect("failed to convert CString into Rust String") +}