Last active
November 11, 2024 07:26
-
-
Save taoky/c344472cd9c878a56f2b845bb85bbc14 to your computer and use it in GitHub Desktop.
Simulate keyboard input in GNOME/KDE Wayland
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "keyboardsim" | |
version = "0.1.0" | |
edition = "2021" | |
[dependencies] | |
ashpd = "0.10.2" | |
keycode = "0.4.0" | |
tokio = { version = "1.41.1", features = ["full"] } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// [dependencies] | |
// ashpd = "0.10.2" | |
// xkbcommon = "0.8.0" | |
// tokio = { version = "1.41.1", features = ["full"] } | |
use std::{fs::File, io::Read, process::exit, time::Duration}; | |
use ashpd::desktop::{ | |
remote_desktop::{DeviceType, KeyState, RemoteDesktop}, | |
PersistMode, Session, | |
}; | |
use xkbcommon::xkb::{ | |
keysyms::{KEY_Escape, KEY_Return, KEY_Tab}, | |
utf32_to_keysym, | |
}; | |
async fn press_key( | |
proxy: &RemoteDesktop<'_>, | |
session: &Session<'_, RemoteDesktop<'_>>, | |
ch: char, | |
) -> ashpd::Result<()> { | |
let keysym = match ch { | |
'\n' => KEY_Return, | |
'\t' => KEY_Tab, | |
'\x1b' => KEY_Escape, | |
_ => utf32_to_keysym(ch as u32).into(), | |
}; | |
proxy | |
.notify_keyboard_keysym(session, keysym as i32, KeyState::Pressed) | |
.await?; | |
proxy | |
.notify_keyboard_keysym(session, keysym as i32, KeyState::Released) | |
.await?; | |
Ok(()) | |
} | |
async fn run(buffer: Vec<u8>) -> ashpd::Result<()> { | |
let proxy = RemoteDesktop::new().await?; | |
let session = proxy.create_session().await?; | |
proxy | |
.select_devices( | |
&session, | |
DeviceType::Keyboard.into(), | |
None, | |
PersistMode::DoNot, | |
) | |
.await?; | |
let response = proxy.start(&session, None).await?.response()?; | |
println!("{:#?}", response.devices()); | |
println!("Wait 2s for you to focus..."); | |
std::thread::sleep(Duration::new(2, 0)); | |
for i in buffer { | |
press_key(&proxy, &session, i as char).await?; | |
} | |
Ok(()) | |
} | |
#[tokio::main] | |
async fn main() { | |
let argv: Vec<_> = std::env::args().collect(); | |
if argv.len() <= 1 { | |
println!("Usage: {} [filename]", argv[0]); | |
exit(1); | |
} | |
let filename = &argv[1]; | |
let mut file = File::open(filename).unwrap(); | |
let mut buffer = Vec::new(); | |
file.read_to_end(&mut buffer).unwrap(); | |
run(buffer).await.unwrap(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment