cargo fmt
This commit is contained in:
parent
16c0826d3a
commit
801f8b6265
10 changed files with 887 additions and 818 deletions
|
@ -1,146 +1,173 @@
|
|||
use clap::Parser;
|
||||
use easymacros::x11_safe_wrapper::{Keysym, string_to_keysym, XDisplay};
|
||||
use easymacros::chartbl::CHARTBL;
|
||||
use easymacros::x11_safe_wrapper::{string_to_keysym, Keysym, XDisplay};
|
||||
use std::ffi::CString;
|
||||
use std::process::{Command, exit};
|
||||
use std::io::stdin;
|
||||
use std::process::{exit, Command};
|
||||
use std::time::Duration;
|
||||
use std::{fs, thread};
|
||||
use std::io::stdin;
|
||||
use x11::keysym::XK_Shift_L;
|
||||
use easymacros::chartbl::CHARTBL;
|
||||
|
||||
/// Macro player module for easymacros. It's compatible with xmacro macros.
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
/// The file that contains the macro to run.
|
||||
#[clap(value_parser, value_name = "input_file", value_hint = clap::ValueHint::FilePath)]
|
||||
input_file: Option<std::path::PathBuf>,
|
||||
/// Display to run the macro on. This uses the $DISPLAY environment variable by default.
|
||||
#[clap(short = 'D', long)]
|
||||
display: Option<String>,
|
||||
/// Delay for events to be sent.
|
||||
#[clap(short, long)]
|
||||
delay: Option<u64>,
|
||||
/// The file that contains the macro to run.
|
||||
#[clap(value_parser, value_name = "input_file", value_hint = clap::ValueHint::FilePath)]
|
||||
input_file: Option<std::path::PathBuf>,
|
||||
/// Display to run the macro on. This uses the $DISPLAY environment variable by default.
|
||||
#[clap(short = 'D', long)]
|
||||
display: Option<String>,
|
||||
/// Delay for events to be sent.
|
||||
#[clap(short, long)]
|
||||
delay: Option<u64>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
let args = Args::parse();
|
||||
|
||||
let display = get_remote(args.display);
|
||||
let delay = args.delay.unwrap_or(10);
|
||||
let display = get_remote(args.display);
|
||||
let delay = args.delay.unwrap_or(10);
|
||||
|
||||
if let Some(input_file_path) = args.input_file {
|
||||
let input_file_contents = fs::read_to_string(input_file_path).expect("Couldn't read macro file");
|
||||
if let Some(input_file_path) = args.input_file {
|
||||
let input_file_contents =
|
||||
fs::read_to_string(input_file_path).expect("Couldn't read macro file");
|
||||
|
||||
for instruction in input_file_contents.lines() {
|
||||
run_instruction(instruction, &display, delay);
|
||||
}
|
||||
} else {
|
||||
println!("No input file specified, reading from stdin.");
|
||||
let stdin = stdin();
|
||||
for instruction in input_file_contents.lines() {
|
||||
run_instruction(instruction, &display, delay);
|
||||
}
|
||||
} else {
|
||||
println!("No input file specified, reading from stdin.");
|
||||
let stdin = stdin();
|
||||
|
||||
loop {
|
||||
let mut line = String::new();
|
||||
stdin.read_line(&mut line).expect("Couldn't read line from stdin");
|
||||
// Without this it crashes because apparently it doesn't properly read the next input line?
|
||||
println!();
|
||||
line = line.trim().to_string();
|
||||
run_instruction(&*line, &display, delay);
|
||||
}
|
||||
}
|
||||
loop {
|
||||
let mut line = String::new();
|
||||
stdin
|
||||
.read_line(&mut line)
|
||||
.expect("Couldn't read line from stdin");
|
||||
// Without this it crashes because apparently it doesn't properly read the next input line?
|
||||
println!();
|
||||
line = line.trim().to_string();
|
||||
run_instruction(&*line, &display, delay);
|
||||
}
|
||||
}
|
||||
|
||||
display.close();
|
||||
display.close();
|
||||
}
|
||||
|
||||
fn get_remote(display_name: Option<String>) -> XDisplay {
|
||||
let display = XDisplay::open(display_name);
|
||||
let display = XDisplay::open(display_name);
|
||||
|
||||
if !display.has_xtest() {
|
||||
eprintln!("XTest not supported!");
|
||||
display.close();
|
||||
exit(1)
|
||||
}
|
||||
if !display.has_xtest() {
|
||||
eprintln!("XTest not supported!");
|
||||
display.close();
|
||||
exit(1)
|
||||
}
|
||||
|
||||
display.grab_control();
|
||||
display.sync();
|
||||
display.grab_control();
|
||||
display.sync();
|
||||
|
||||
display
|
||||
display
|
||||
}
|
||||
|
||||
fn run_instruction(instruction: &str, dpy: &XDisplay, delay: u64) {
|
||||
let instruction_split: Vec<&str> = instruction.split(' ').collect();
|
||||
let instruction_split: Vec<&str> = instruction.split(' ').collect();
|
||||
|
||||
match instruction_split[0] {
|
||||
"Delay" => thread::sleep(Duration::from_millis(instruction_split[1].parse().unwrap())),
|
||||
"ButtonPress" => dpy.send_fake_buttonpress(instruction_split[1].parse().unwrap(), delay),
|
||||
"ButtonRelease" => dpy.send_fake_buttonrelease(instruction_split[1].parse().unwrap(), delay),
|
||||
"MotionNotify" => dpy.send_fake_motion_event(instruction_split[1].parse().unwrap(), instruction_split[2].parse().unwrap(), delay),
|
||||
"KeyCodePress" => dpy.send_fake_keypress_from_code(instruction_split[1].parse().unwrap(), delay),
|
||||
"KeyCodeRelease" => dpy.send_fake_keyrelease_from_code(instruction_split[1].parse().unwrap(), delay),
|
||||
"KeySymPress" => dpy.send_fake_keypress_from_keysym(instruction_split[1].parse().unwrap(), delay),
|
||||
"KeySymRelease" => dpy.send_fake_keyrelease_from_keysym(instruction_split[1].parse().unwrap(), delay),
|
||||
match instruction_split[0] {
|
||||
"Delay" => thread::sleep(Duration::from_millis(instruction_split[1].parse().unwrap())),
|
||||
"ButtonPress" => dpy.send_fake_buttonpress(instruction_split[1].parse().unwrap(), delay),
|
||||
"ButtonRelease" => {
|
||||
dpy.send_fake_buttonrelease(instruction_split[1].parse().unwrap(), delay)
|
||||
}
|
||||
"MotionNotify" => dpy.send_fake_motion_event(
|
||||
instruction_split[1].parse().unwrap(),
|
||||
instruction_split[2].parse().unwrap(),
|
||||
delay,
|
||||
),
|
||||
"KeyCodePress" => {
|
||||
dpy.send_fake_keypress_from_code(instruction_split[1].parse().unwrap(), delay)
|
||||
}
|
||||
"KeyCodeRelease" => {
|
||||
dpy.send_fake_keyrelease_from_code(instruction_split[1].parse().unwrap(), delay)
|
||||
}
|
||||
"KeySymPress" => {
|
||||
dpy.send_fake_keypress_from_keysym(instruction_split[1].parse().unwrap(), delay)
|
||||
}
|
||||
"KeySymRelease" => {
|
||||
dpy.send_fake_keyrelease_from_keysym(instruction_split[1].parse().unwrap(), delay)
|
||||
}
|
||||
|
||||
"KeySym" => {
|
||||
let key: Keysym = instruction_split[1].parse().unwrap();
|
||||
dpy.send_fake_keypress_from_keysym(key, delay);
|
||||
dpy.send_fake_keyrelease_from_keysym(key, delay);
|
||||
}
|
||||
"KeyStrPress" => dpy.send_fake_keypress_from_string(CString::new(instruction_split[1]).unwrap().as_bytes(), delay),
|
||||
"KeyStrRelease" => dpy.send_fake_keyrelease_from_string(CString::new(instruction_split[1]).unwrap().as_bytes(), delay),
|
||||
"KeyStr" => {
|
||||
let keystring = CString::new(instruction_split[1]).unwrap();
|
||||
dpy.send_fake_keypress_from_string(keystring.as_bytes(), delay);
|
||||
dpy.send_fake_keyrelease_from_string(keystring.as_bytes(), delay);
|
||||
}
|
||||
"String" => {
|
||||
for c in instruction["String".len() + 1..].chars() {
|
||||
send_char(dpy, c, delay);
|
||||
}
|
||||
}
|
||||
"ExecBlock" | "ExecNoBlock" => {
|
||||
let mut command = Command::new(instruction_split[1]);
|
||||
for arg in &instruction_split[2..] {
|
||||
command.arg(arg);
|
||||
}
|
||||
if instruction_split[0] == "ExecBlock" {
|
||||
command.status().unwrap();
|
||||
} else {
|
||||
command.spawn().unwrap();
|
||||
}
|
||||
}
|
||||
c => panic!("Unknown command {:?}", instruction_split),
|
||||
}
|
||||
"KeySym" => {
|
||||
let key: Keysym = instruction_split[1].parse().unwrap();
|
||||
dpy.send_fake_keypress_from_keysym(key, delay);
|
||||
dpy.send_fake_keyrelease_from_keysym(key, delay);
|
||||
}
|
||||
"KeyStrPress" => dpy.send_fake_keypress_from_string(
|
||||
CString::new(instruction_split[1]).unwrap().as_bytes(),
|
||||
delay,
|
||||
),
|
||||
"KeyStrRelease" => dpy.send_fake_keyrelease_from_string(
|
||||
CString::new(instruction_split[1]).unwrap().as_bytes(),
|
||||
delay,
|
||||
),
|
||||
"KeyStr" => {
|
||||
let keystring = CString::new(instruction_split[1]).unwrap();
|
||||
dpy.send_fake_keypress_from_string(keystring.as_bytes(), delay);
|
||||
dpy.send_fake_keyrelease_from_string(keystring.as_bytes(), delay);
|
||||
}
|
||||
"String" => {
|
||||
for c in instruction["String".len() + 1..].chars() {
|
||||
send_char(dpy, c, delay);
|
||||
}
|
||||
}
|
||||
"ExecBlock" | "ExecNoBlock" => {
|
||||
let mut command = Command::new(instruction_split[1]);
|
||||
for arg in &instruction_split[2..] {
|
||||
command.arg(arg);
|
||||
}
|
||||
if instruction_split[0] == "ExecBlock" {
|
||||
command.status().unwrap();
|
||||
} else {
|
||||
command.spawn().unwrap();
|
||||
}
|
||||
}
|
||||
c => panic!("Unknown command {:?}", instruction_split),
|
||||
}
|
||||
}
|
||||
|
||||
fn send_char(dpy: &XDisplay, c: char, delay: u64) {
|
||||
// get keystring from character and turn it into a keysym
|
||||
let keysym = string_to_keysym(CHARTBL[c as usize].as_ref());
|
||||
let keycode = dpy.keysym_to_keycode(keysym);
|
||||
// get keystring from character and turn it into a keysym
|
||||
let keysym = string_to_keysym(CHARTBL[c as usize].as_ref());
|
||||
let keycode = dpy.keysym_to_keycode(keysym);
|
||||
|
||||
if keycode == 0 {
|
||||
eprintln!("No keycode found for character '{}'", c);
|
||||
return;
|
||||
}
|
||||
if keycode == 0 {
|
||||
eprintln!("No keycode found for character '{}'", c);
|
||||
return;
|
||||
}
|
||||
|
||||
let map_ks = dpy.get_keyboard_mapping(keycode, 1);
|
||||
if map_ks[0] == 0 {
|
||||
eprintln!("XGetKeyboardMapping failed (keycode: {})", keycode);
|
||||
return;
|
||||
}
|
||||
let map_ks = dpy.get_keyboard_mapping(keycode, 1);
|
||||
if map_ks[0] == 0 {
|
||||
eprintln!("XGetKeyboardMapping failed (keycode: {})", keycode);
|
||||
return;
|
||||
}
|
||||
|
||||
let (ks_lower, ks_upper) = dpy.convert_case(keysym);
|
||||
let (ks_lower, ks_upper) = dpy.convert_case(keysym);
|
||||
|
||||
// check if shift has to be pressed as well
|
||||
let mut shift_needed = true;
|
||||
if keysym == map_ks[0] && (keysym == ks_lower && keysym == ks_upper) {
|
||||
shift_needed = false;
|
||||
}
|
||||
if keysym == ks_lower && keysym != ks_upper {
|
||||
shift_needed = false;
|
||||
}
|
||||
// check if shift has to be pressed as well
|
||||
let mut shift_needed = true;
|
||||
if keysym == map_ks[0] && (keysym == ks_lower && keysym == ks_upper) {
|
||||
shift_needed = false;
|
||||
}
|
||||
if keysym == ks_lower && keysym != ks_upper {
|
||||
shift_needed = false;
|
||||
}
|
||||
|
||||
if shift_needed { dpy.send_fake_keypress_from_keysym(XK_Shift_L as Keysym, delay); }
|
||||
dpy.send_fake_keypress_from_code(keycode, delay);
|
||||
dpy.send_fake_keyrelease_from_code(keycode, delay);
|
||||
if shift_needed { dpy.send_fake_keyrelease_from_keysym(XK_Shift_L as Keysym, delay); }
|
||||
}
|
||||
if shift_needed {
|
||||
dpy.send_fake_keypress_from_keysym(XK_Shift_L as Keysym, delay);
|
||||
}
|
||||
dpy.send_fake_keypress_from_code(keycode, delay);
|
||||
dpy.send_fake_keyrelease_from_code(keycode, delay);
|
||||
if shift_needed {
|
||||
dpy.send_fake_keyrelease_from_keysym(XK_Shift_L as Keysym, delay);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,189 +1,198 @@
|
|||
extern crate core;
|
||||
|
||||
use std::ffi::c_void;
|
||||
use std::os::raw::{c_char};
|
||||
use std::process::{exit};
|
||||
use std::os::raw::c_char;
|
||||
use std::process::exit;
|
||||
use std::ptr::addr_of;
|
||||
|
||||
use clap::Parser;
|
||||
use x11::xlib::{CurrentTime, GrabModeAsync, GrabModeSync, GrabSuccess, KeyPressMask, SyncPointer, Time, XFree, XKeyEvent};
|
||||
use x11::xrecord::{XRecordAllocRange, XRecordEndOfData, XRecordFreeData, XRecordInterceptData, XRecordStartOfData};
|
||||
use x11::xlib::{
|
||||
CurrentTime, GrabModeAsync, GrabModeSync, GrabSuccess, KeyPressMask, SyncPointer, Time, XFree,
|
||||
XKeyEvent,
|
||||
};
|
||||
use x11::xrecord::{
|
||||
XRecordAllocRange, XRecordEndOfData, XRecordFreeData, XRecordInterceptData, XRecordStartOfData,
|
||||
};
|
||||
|
||||
use easymacros::{BUTTONPRESS_U8, BUTTONRELEASE_U8, Instructions, KEYPRESS_U8, KEYRELEASE_U8, MOTIONNOTIFY_U8, Position};
|
||||
use easymacros::ev_callback_data::EvCallbackData;
|
||||
use easymacros::macro_writer::MacroWriter;
|
||||
use easymacros::x11_safe_wrapper::{Keycode, XDisplay};
|
||||
use easymacros::{
|
||||
Instructions, Position, BUTTONPRESS_U8, BUTTONRELEASE_U8, KEYPRESS_U8, KEYRELEASE_U8,
|
||||
MOTIONNOTIFY_U8,
|
||||
};
|
||||
|
||||
/// Macro recording module for easymacros. Outputs are partially compatible with xmacro.
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
/// The file to record the macro to. Defaults to writing to stdout.
|
||||
#[clap(value_parser, value_name = "output_file", value_hint = clap::ValueHint::FilePath)]
|
||||
output_file: Option<std::path::PathBuf>,
|
||||
/// Display to run the macro on. This uses the $DISPLAY environment variable by default.
|
||||
#[clap(short = 'D', long)]
|
||||
display: Option<String>,
|
||||
/// Max Delay in milliseconds for macro delays
|
||||
#[clap(short, long)]
|
||||
max_delay: Option<u64>,
|
||||
/// Allow delay capturing in recording output. If this flag is set, the program will ignore the max_delay.
|
||||
#[clap(short, long)]
|
||||
ignore_delay_capturing: bool,
|
||||
/// The file to record the macro to. Defaults to writing to stdout.
|
||||
#[clap(value_parser, value_name = "output_file", value_hint = clap::ValueHint::FilePath)]
|
||||
output_file: Option<std::path::PathBuf>,
|
||||
/// Display to run the macro on. This uses the $DISPLAY environment variable by default.
|
||||
#[clap(short = 'D', long)]
|
||||
display: Option<String>,
|
||||
/// Max Delay in milliseconds for macro delays
|
||||
#[clap(short, long)]
|
||||
max_delay: Option<u64>,
|
||||
/// Allow delay capturing in recording output. If this flag is set, the program will ignore the max_delay.
|
||||
#[clap(short, long)]
|
||||
ignore_delay_capturing: bool,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
let args = Args::parse();
|
||||
|
||||
let display = XDisplay::open(args.display.clone());
|
||||
let recorded_display = XDisplay::open(args.display.clone());
|
||||
let stop_key = get_stop_key(display);
|
||||
let writer = MacroWriter::new(args.output_file, args.ignore_delay_capturing);
|
||||
let display = XDisplay::open(args.display.clone());
|
||||
let recorded_display = XDisplay::open(args.display.clone());
|
||||
let stop_key = get_stop_key(display);
|
||||
let writer = MacroWriter::new(args.output_file, args.ignore_delay_capturing);
|
||||
|
||||
event_loop(
|
||||
display,
|
||||
recorded_display,
|
||||
stop_key,
|
||||
writer,
|
||||
args.max_delay,
|
||||
);
|
||||
event_loop(display, recorded_display, stop_key, writer, args.max_delay);
|
||||
|
||||
display.close();
|
||||
display.close();
|
||||
}
|
||||
|
||||
fn get_stop_key(display: XDisplay) -> Keycode {
|
||||
let screen = display.get_default_screen();
|
||||
let screen = display.get_default_screen();
|
||||
|
||||
let root = display.get_root_window(screen);
|
||||
let potential_err = display.grab_keyboard(root, false, GrabModeSync, GrabModeAsync, CurrentTime);
|
||||
let root = display.get_root_window(screen);
|
||||
let potential_err =
|
||||
display.grab_keyboard(root, false, GrabModeSync, GrabModeAsync, CurrentTime);
|
||||
|
||||
if potential_err != GrabSuccess {
|
||||
eprintln!("Couldn't grab keyboard!");
|
||||
exit(1);
|
||||
}
|
||||
if potential_err != GrabSuccess {
|
||||
eprintln!("Couldn't grab keyboard!");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
println!("Press the key you want to use to stop recording the macro.");
|
||||
println!("Press the key you want to use to stop recording the macro.");
|
||||
|
||||
let stop_key;
|
||||
loop {
|
||||
display.allow_events(SyncPointer, CurrentTime);
|
||||
let ev = XKeyEvent::from(display.window_event(root, KeyPressMask));
|
||||
stop_key = ev.keycode;
|
||||
break;
|
||||
}
|
||||
let stop_key;
|
||||
loop {
|
||||
display.allow_events(SyncPointer, CurrentTime);
|
||||
let ev = XKeyEvent::from(display.window_event(root, KeyPressMask));
|
||||
stop_key = ev.keycode;
|
||||
break;
|
||||
}
|
||||
|
||||
display.ungrab_keyboard(CurrentTime);
|
||||
display.ungrab_pointer(CurrentTime);
|
||||
display.ungrab_keyboard(CurrentTime);
|
||||
display.ungrab_pointer(CurrentTime);
|
||||
|
||||
stop_key
|
||||
stop_key
|
||||
}
|
||||
|
||||
fn event_loop(
|
||||
xdpy: XDisplay,
|
||||
recdpy: XDisplay,
|
||||
stop_key: Keycode,
|
||||
mut writer: MacroWriter,
|
||||
max_delay: Option<Time>,
|
||||
xdpy: XDisplay,
|
||||
recdpy: XDisplay,
|
||||
stop_key: Keycode,
|
||||
mut writer: MacroWriter,
|
||||
max_delay: Option<Time>,
|
||||
) {
|
||||
let protocol_ranges = unsafe { XRecordAllocRange() };
|
||||
let protocol_ranges = unsafe { XRecordAllocRange() };
|
||||
|
||||
let pointer_pos: Position<i16> = Position::from(xdpy.query_pointer_pos());
|
||||
let pointer_pos: Position<i16> = Position::from(xdpy.query_pointer_pos());
|
||||
|
||||
if pointer_pos != Position(-1, -1) {
|
||||
writer.write(Instructions::MotionNotify(pointer_pos))
|
||||
}
|
||||
if pointer_pos != Position(-1, -1) {
|
||||
writer.write(Instructions::MotionNotify(pointer_pos))
|
||||
}
|
||||
|
||||
let ctx = recdpy.create_record_context(protocol_ranges);
|
||||
let ev_cb_data = EvCallbackData::new(writer, xdpy, recdpy, ctx, stop_key, pointer_pos, max_delay);
|
||||
let ctx = recdpy.create_record_context(protocol_ranges);
|
||||
let ev_cb_data =
|
||||
EvCallbackData::new(writer, xdpy, recdpy, ctx, stop_key, pointer_pos, max_delay);
|
||||
|
||||
if !recdpy.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 {
|
||||
recdpy.process_replies();
|
||||
}
|
||||
if !recdpy.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 {
|
||||
recdpy.process_replies();
|
||||
}
|
||||
|
||||
xdpy.disable_context(ctx);
|
||||
xdpy.free_context(ctx);
|
||||
unsafe { XFree(protocol_ranges as *mut c_void) };
|
||||
xdpy.disable_context(ctx);
|
||||
xdpy.free_context(ctx);
|
||||
unsafe { XFree(protocol_ranges as *mut c_void) };
|
||||
}
|
||||
|
||||
unsafe extern "C" fn ev_callback(closure: *mut c_char, intercept_data: *mut XRecordInterceptData) {
|
||||
let data = &mut *(closure as *mut EvCallbackData);
|
||||
let intercept_data = &mut *intercept_data;
|
||||
let data = &mut *(closure as *mut EvCallbackData);
|
||||
let intercept_data = &mut *intercept_data;
|
||||
|
||||
if intercept_data.category == XRecordStartOfData {
|
||||
println!("Got start of data!");
|
||||
data.last_event = intercept_data.server_time;
|
||||
XRecordFreeData(intercept_data);
|
||||
return;
|
||||
} else if intercept_data.category == XRecordEndOfData {
|
||||
println!("Got end of data!");
|
||||
XRecordFreeData(intercept_data);
|
||||
return;
|
||||
}
|
||||
if intercept_data.category == XRecordStartOfData {
|
||||
println!("Got start of data!");
|
||||
data.last_event = intercept_data.server_time;
|
||||
XRecordFreeData(intercept_data);
|
||||
return;
|
||||
} else if intercept_data.category == XRecordEndOfData {
|
||||
println!("Got end of data!");
|
||||
XRecordFreeData(intercept_data);
|
||||
return;
|
||||
}
|
||||
|
||||
let ev_type = *(intercept_data.data as *const u8);
|
||||
let ev_type = *(intercept_data.data as *const u8);
|
||||
|
||||
if data.pos.0 == 0 || data.pos.1 == -1 {
|
||||
if ev_type == MOTIONNOTIFY_U8 {
|
||||
data.update_pos(intercept_data);
|
||||
data.write_pos();
|
||||
} else {
|
||||
println!("Move your cursor so the macro can start with a fixed cursor position!
|
||||
Skipping event...");
|
||||
}
|
||||
} else if data.no_keypress_yet && ev_type == KEYRELEASE_U8 {
|
||||
println!("Skipping KeyRelease without recorded KeyPress...");
|
||||
} else {
|
||||
match ev_type {
|
||||
MOTIONNOTIFY_U8 => {
|
||||
data.update_pos(intercept_data);
|
||||
if data.pos.0 == 0 || data.pos.1 == -1 {
|
||||
if ev_type == MOTIONNOTIFY_U8 {
|
||||
data.update_pos(intercept_data);
|
||||
data.write_pos();
|
||||
} else {
|
||||
println!(
|
||||
"Move your cursor so the macro can start with a fixed cursor position!
|
||||
Skipping event..."
|
||||
);
|
||||
}
|
||||
} else if data.no_keypress_yet && ev_type == KEYRELEASE_U8 {
|
||||
println!("Skipping KeyRelease without recorded KeyPress...");
|
||||
} else {
|
||||
match ev_type {
|
||||
MOTIONNOTIFY_U8 => {
|
||||
data.update_pos(intercept_data);
|
||||
|
||||
if !data.moving {
|
||||
data.moving = true;
|
||||
}
|
||||
}
|
||||
KEYPRESS_U8 | KEYRELEASE_U8 => {
|
||||
let kc: u8 = *((intercept_data.data as usize + 1) as *const u8);
|
||||
let keyname = data.xdpy.keycode_to_string(kc as u32);
|
||||
if !data.moving {
|
||||
data.moving = true;
|
||||
}
|
||||
}
|
||||
KEYPRESS_U8 | KEYRELEASE_U8 => {
|
||||
let kc: u8 = *((intercept_data.data as usize + 1) as *const u8);
|
||||
let keyname = data.xdpy.keycode_to_string(kc as u32);
|
||||
|
||||
if ev_type == KEYPRESS_U8 && kc == data.stop_key as u8 {
|
||||
data.working = false;
|
||||
} else {
|
||||
if ev_type == KEYPRESS_U8 {
|
||||
data.no_keypress_yet = false;
|
||||
}
|
||||
if ev_type == KEYPRESS_U8 && kc == data.stop_key as u8 {
|
||||
data.working = false;
|
||||
} else {
|
||||
if ev_type == KEYPRESS_U8 {
|
||||
data.no_keypress_yet = false;
|
||||
}
|
||||
|
||||
data.maybe_write_delay(intercept_data.server_time);
|
||||
data.maybe_write_delay(intercept_data.server_time);
|
||||
|
||||
if data.ptr_is_moving() { data.write_pos(); }
|
||||
if data.ptr_is_moving() {
|
||||
data.write_pos();
|
||||
}
|
||||
|
||||
data.writer.write(if ev_type == KEYPRESS_U8 {
|
||||
Instructions::KeyStrPress(keyname)
|
||||
} else {
|
||||
Instructions::KeyStrRelease(keyname)
|
||||
});
|
||||
}
|
||||
}
|
||||
BUTTONPRESS_U8 | BUTTONRELEASE_U8 => {
|
||||
let bc: u8 = *((intercept_data.data as usize + 1) as *const u8);
|
||||
data.writer.write(if ev_type == KEYPRESS_U8 {
|
||||
Instructions::KeyStrPress(keyname)
|
||||
} else {
|
||||
Instructions::KeyStrRelease(keyname)
|
||||
});
|
||||
}
|
||||
}
|
||||
BUTTONPRESS_U8 | BUTTONRELEASE_U8 => {
|
||||
let bc: u8 = *((intercept_data.data as usize + 1) as *const u8);
|
||||
|
||||
data.maybe_write_delay(intercept_data.server_time);
|
||||
data.maybe_write_delay(intercept_data.server_time);
|
||||
|
||||
if data.ptr_is_moving() { data.write_pos(); }
|
||||
if data.ptr_is_moving() {
|
||||
data.write_pos();
|
||||
}
|
||||
|
||||
data.writer.write(if ev_type == BUTTONPRESS_U8 {
|
||||
Instructions::ButtonPress(bc)
|
||||
} else {
|
||||
Instructions::ButtonRelease(bc)
|
||||
});
|
||||
}
|
||||
_ => eprintln!("Unknown event type: {:?}", ev_type)
|
||||
}
|
||||
}
|
||||
data.writer.write(if ev_type == BUTTONPRESS_U8 {
|
||||
Instructions::ButtonPress(bc)
|
||||
} else {
|
||||
Instructions::ButtonRelease(bc)
|
||||
});
|
||||
}
|
||||
_ => eprintln!("Unknown event type: {:?}", ev_type),
|
||||
}
|
||||
}
|
||||
|
||||
data.ev_nr += 2;
|
||||
XRecordFreeData(intercept_data)
|
||||
data.ev_nr += 2;
|
||||
XRecordFreeData(intercept_data)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue