added macro playing delay!!!!!!!!1

This commit is contained in:
Schrottkatze 2022-07-25 17:14:00 +02:00
parent b9770f43f1
commit f52e2914d7
2 changed files with 125 additions and 130 deletions

View file

@ -12,140 +12,135 @@ use easymacros::chartbl::CHARTBL;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)] #[clap(author, version, about, long_about = None)]
struct Args { struct Args {
/// The file that contains the macro to run. /// The file that contains the macro to run.
#[clap(value_parser, value_name = "input_file", value_hint = clap::ValueHint::FilePath)] #[clap(value_parser, value_name = "input_file", value_hint = clap::ValueHint::FilePath)]
input_file: Option<std::path::PathBuf>, input_file: Option<std::path::PathBuf>,
/// Display to run the macro on. This uses the $DISPLAY environment variable by default. /// Display to run the macro on. This uses the $DISPLAY environment variable by default.
#[clap(short = "D", long)] #[clap(short = 'D', long)]
display: Option<String>, display: Option<String>,
// Delay for events to be sent. /// Delay for events to be sent.
// #[clap(short, long)] #[clap(short, long)]
// event_delay: Option<u16>, delay: Option<u64>,
} }
fn main() { fn main() {
let args = Args::parse(); let args = Args::parse();
let display = get_remote(args.display); let display = get_remote(args.display);
let delay = args.delay.unwrap_or(10);
if let Some(input_file_path) = args.input_file { if let Some(input_file_path) = args.input_file {
let input_file_contents = fs::read_to_string(input_file_path) let input_file_contents = fs::read_to_string(input_file_path).expect("Couldn't read macro file");
.expect("Couldn't read macro file");
for instruction in input_file_contents.lines() { for instruction in input_file_contents.lines() {
run_instruction(instruction, &display); run_instruction(instruction, &display, delay);
} }
} else { } else {
println!("No input file specified, reading from stdin."); println!("No input file specified, reading from stdin.");
let stdin = stdin(); let stdin = stdin();
loop { loop {
let mut line = String::new(); let mut line = String::new();
stdin.read_line(&mut line).expect("Couldn't read line from stdin"); 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? // Without this it crashes because apparently it doesn't properly read the next input line?
println!(); println!();
line = line.trim().to_string(); line = line.trim().to_string();
run_instruction(&*line, &display); run_instruction(&*line, &display, delay);
} }
} }
display.close(); display.close();
} }
fn get_remote(display_name: Option<String>) -> XDisplay { fn get_remote(display_name: Option<String>) -> XDisplay {
let display = XDisplay::open(display_name); let display = XDisplay::open(display_name);
if !display.has_xtest() { if !display.has_xtest() {
eprintln!("XTest not supported!"); eprintln!("XTest not supported!");
display.close(); display.close();
exit(1) exit(1)
} }
display.grab_control(); display.grab_control();
display.sync(); display.sync();
display display
} }
fn run_instruction(instruction: &str, dpy: &XDisplay) { 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] { match instruction_split[0] {
"Delay" => thread::sleep(Duration::from_millis(instruction_split[1].parse().unwrap())), "Delay" => thread::sleep(Duration::from_millis(instruction_split[1].parse().unwrap())),
"ButtonPress" => dpy.send_fake_buttonpress(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()), "ButtonRelease" => dpy.send_fake_buttonrelease(instruction_split[1].parse().unwrap(), delay),
"MotionNotify" => dpy "MotionNotify" => dpy.send_fake_motion_event(instruction_split[1].parse().unwrap(), instruction_split[2].parse().unwrap(), delay),
.send_fake_motion_event(instruction_split[1].parse().unwrap(), instruction_split[2].parse().unwrap()), "KeyCodePress" => dpy.send_fake_keypress_from_code(instruction_split[1].parse().unwrap(), delay),
"KeyCodePress" => dpy.send_fake_keypress_from_code(instruction_split[1].parse().unwrap()), "KeyCodeRelease" => dpy.send_fake_keyrelease_from_code(instruction_split[1].parse().unwrap(), delay),
"KeyCodeRelease" => dpy.send_fake_keyrelease_from_code(instruction_split[1].parse().unwrap()), "KeySymPress" => dpy.send_fake_keypress_from_keysym(instruction_split[1].parse().unwrap(), delay),
"KeySymPress" => dpy.send_fake_keypress_from_keysym(instruction_split[1].parse().unwrap()), "KeySymRelease" => dpy.send_fake_keyrelease_from_keysym(instruction_split[1].parse().unwrap(), delay),
"KeySymRelease" => {
dpy.send_fake_keyrelease_from_keysym(instruction_split[1].parse().unwrap()) "KeySym" => {
} let key: Keysym = instruction_split[1].parse().unwrap();
"KeySym" => { dpy.send_fake_keypress_from_keysym(key, delay);
let key: Keysym = instruction_split[1].parse().unwrap(); dpy.send_fake_keyrelease_from_keysym(key, delay);
dpy.send_fake_keypress_from_keysym(key); }
dpy.send_fake_keyrelease_from_keysym(key); "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),
"KeyStrPress" => { "KeyStr" => {
dpy.send_fake_keypress_from_string(CString::new(instruction_split[1]).unwrap().as_bytes()) let keystring = CString::new(instruction_split[1]).unwrap();
} dpy.send_fake_keypress_from_string(keystring.as_bytes(), delay);
"KeyStrRelease" => dpy dpy.send_fake_keyrelease_from_string(keystring.as_bytes(), delay);
.send_fake_keyrelease_from_string(CString::new(instruction_split[1]).unwrap().as_bytes()), }
"KeyStr" => { "String" => {
let keystring = CString::new(instruction_split[1]).unwrap(); for c in instruction["String".len() + 1..].chars() {
dpy.send_fake_keypress_from_string(keystring.as_bytes()); send_char(dpy, c, delay);
dpy.send_fake_keyrelease_from_string(keystring.as_bytes()); }
} }
"String" => { "ExecBlock" | "ExecNoBlock" => {
for c in instruction["String".len()+1..].chars() { let mut command = Command::new(instruction_split[1]);
send_char(dpy, c); for arg in &instruction_split[2..] {
} command.arg(arg);
} }
"ExecBlock" | "ExecNoBlock" => { if instruction_split[0] == "ExecBlock" {
let mut command = Command::new(instruction_split[1]); command.status().unwrap();
for arg in &instruction_split[2..] { } else {
command.arg(arg); command.spawn().unwrap();
} }
if instruction_split[0] == "ExecBlock" { }
command.status().unwrap(); c => panic!("Unknown command {:?}", instruction_split),
} else { }
command.spawn().unwrap();
}
}
c => panic!("Unknown command {:?}", instruction_split),
}
} }
fn send_char(dpy: &XDisplay, c: char) { fn send_char(dpy: &XDisplay, c: char, delay: u64) {
// get keystring from character and turn it into a keysym // get keystring from character and turn it into a keysym
let keysym = string_to_keysym(CHARTBL[c as usize].as_ref()); let keysym = string_to_keysym(CHARTBL[c as usize].as_ref());
let keycode = dpy.keysym_to_keycode(keysym); let keycode = dpy.keysym_to_keycode(keysym);
if keycode == 0 { if keycode == 0 {
eprintln!("No keycode found for character '{}'", c); eprintln!("No keycode found for character '{}'", c);
return; return;
} }
let map_ks = dpy.get_keyboard_mapping(keycode, 1); let map_ks = dpy.get_keyboard_mapping(keycode, 1);
if map_ks[0] == 0 { if map_ks[0] == 0 {
eprintln!("XGetKeyboardMapping failed (keycode: {})", keycode); eprintln!("XGetKeyboardMapping failed (keycode: {})", keycode);
return; 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 // check if shift has to be pressed as well
let mut shift_needed = true; let mut shift_needed = true;
if keysym == map_ks[0] && (keysym == ks_lower && keysym == ks_upper) { if keysym == map_ks[0] && (keysym == ks_lower && keysym == ks_upper) {
shift_needed = false; shift_needed = false;
} }
if keysym == ks_lower && keysym != ks_upper { if keysym == ks_lower && keysym != ks_upper {
shift_needed = false; shift_needed = false;
} }
if shift_needed { dpy.send_fake_keypress_from_keysym(XK_Shift_L as Keysym); } if shift_needed { dpy.send_fake_keypress_from_keysym(XK_Shift_L as Keysym, delay); }
dpy.send_fake_keypress_from_code(keycode); dpy.send_fake_keypress_from_code(keycode, delay);
dpy.send_fake_keyrelease_from_code(keycode); dpy.send_fake_keyrelease_from_code(keycode, delay);
if shift_needed { dpy.send_fake_keyrelease_from_keysym(XK_Shift_L as Keysym); } if shift_needed { dpy.send_fake_keyrelease_from_keysym(XK_Shift_L as Keysym, delay); }
} }

View file

@ -133,42 +133,42 @@ impl XDisplay {
has_extension != 0 has_extension != 0
} }
pub fn send_fake_keypress_from_string(&self, string: &[u8]) { pub fn send_fake_keypress_from_string(&self, string: &[u8], delay: u64) {
self.send_fake_keypress_from_keysym(string_to_keysym(string)) self.send_fake_keypress_from_keysym(string_to_keysym(string), delay)
} }
pub fn send_fake_keypress_from_keysym(&self, ks: Keysym) { pub fn send_fake_keypress_from_keysym(&self, ks: Keysym, delay: u64) {
self.send_fake_keypress_from_code(self.keysym_to_keycode(ks)) self.send_fake_keypress_from_code(self.keysym_to_keycode(ks), delay)
} }
pub fn send_fake_keypress_from_code(&self, code: Keycode) { pub fn send_fake_keypress_from_code(&self, code: Keycode, delay: u64) {
unsafe { XTestFakeKeyEvent(self.ptr, code, TRUE_C, 10) }; unsafe { XTestFakeKeyEvent(self.ptr, code, TRUE_C, delay) };
self.flush(); self.flush();
} }
pub fn send_fake_buttonpress(&self, button: u32) { pub fn send_fake_buttonpress(&self, button: u32, delay: u64) {
unsafe { XTestFakeButtonEvent(self.ptr, button, TRUE_C, 10) }; unsafe { XTestFakeButtonEvent(self.ptr, button, TRUE_C, delay) };
} }
pub fn send_fake_buttonrelease(&self, button: u32) { pub fn send_fake_buttonrelease(&self, button: u32, delay: u64) {
unsafe { XTestFakeButtonEvent(self.ptr, button, FALSE_C, 10) }; unsafe { XTestFakeButtonEvent(self.ptr, button, FALSE_C, delay) };
} }
pub fn send_fake_keyrelease_from_string(&self, string: &[u8]) { pub fn send_fake_keyrelease_from_string(&self, string: &[u8], delay: u64) {
self.send_fake_keyrelease_from_keysym(string_to_keysym(string)) self.send_fake_keyrelease_from_keysym(string_to_keysym(string), delay)
} }
pub fn send_fake_keyrelease_from_keysym(&self, ks: Keysym) { pub fn send_fake_keyrelease_from_keysym(&self, ks: Keysym, delay: u64) {
self.send_fake_keyrelease_from_code(self.keysym_to_keycode(ks)) self.send_fake_keyrelease_from_code(self.keysym_to_keycode(ks), delay)
} }
pub fn send_fake_keyrelease_from_code(&self, code: Keycode) { pub fn send_fake_keyrelease_from_code(&self, code: Keycode, delay: u64) {
unsafe { XTestFakeKeyEvent(self.ptr, code, FALSE_C, 10) }; unsafe { XTestFakeKeyEvent(self.ptr, code, FALSE_C, delay) };
self.flush(); self.flush();
} }
pub fn send_fake_motion_event(&self, x: i32, y: i32) { pub fn send_fake_motion_event(&self, x: i32, y: i32, delay: u64) {
unsafe { XTestFakeMotionEvent(self.ptr, -1, x, y, 10) }; unsafe { XTestFakeMotionEvent(self.ptr, -1, x, y, delay) };
self.flush(); self.flush();
} }