diff --git a/.gitignore b/.gitignore index 088ba6b..22d3516 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,8 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk + + +# Added by cargo + +/target diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e96d63c --- /dev/null +++ b/src/main.rs @@ -0,0 +1,78 @@ +use std::sync::{Arc, mpsc, Mutex}; +use std::sync::mpsc::Receiver; +use std::thread; +use evdev::{Device, enumerate, InputEvent}; +use crate::modifiers::ModifierStates; +use crate::virt_kb::VirtKb; + +mod modifiers; +mod virt_kb; + +fn main() { + let devices = enumerate(); + let kb_name = "py-evdev-uinput"; + + let mut kbs = { + let mut r = Vec::new(); + + for dev in devices { + if let Some(keyboard) = dev.name() { + if keyboard == kb_name { + r.push(dev); + } + } + } + + r + }; + + + let virt_kb = VirtKb::new(&kbs); + let mod_states = ModifierStates::new(); + + let reader = KeyReader::new(kbs); + let event_receiver = reader.init(); + + +} + +struct KeyReader { + keyboards: Arc>>, +} + +impl KeyReader { + pub fn new(kbs: Vec) -> Self { + let mut kbs = kbs; + + for kb in kbs.iter_mut() { + match kb.grab() { + Ok(_) => println!("Keyboard {} grabbed!", kb.name().get_or_insert("[Unnamed]")), + Err(_) => println!("Failed to grab keyboard {}.", kb.name().get_or_insert("[Unnamed]")), + } + } + + Self { keyboards: Arc::new(Mutex::new(kbs)) } + } + + pub fn init(&self) -> Receiver>{ + let (tx, rx) = mpsc::channel(); + + let keyboards = self.keyboards.clone(); + thread::spawn(move || { + let mut kbs_locked = keyboards.lock().unwrap(); + loop { + for kb in kbs_locked.iter_mut() { + let mut events = kb + .fetch_events() + .unwrap() + .collect::>(); + + tx.send(events) + .expect("Couldn't send keyboard events from reader to main thread."); + } + } + }); + + rx + } +} \ No newline at end of file diff --git a/src/modifiers.rs b/src/modifiers.rs new file mode 100644 index 0000000..a99fd02 --- /dev/null +++ b/src/modifiers.rs @@ -0,0 +1,57 @@ +use evdev::{InputEvent, Key}; + +#[derive(Debug)] +pub struct ModifierStates { + ctrl: bool, + alt: bool, + shift: bool, + meta: bool, +} + +impl ModifierStates { + pub fn new() -> Self { + ModifierStates { + ctrl: false, + alt: false, + shift: false, + meta: false + } + } + pub fn update(&mut self, event: InputEvent) { + let code = event.code(); + let val = event.value(); + + self.update_ctrl(code, val); + self.update_alt(code, val); + self.update_shift(code, val); + self.update_meta(code, val); + } + pub fn mod_pressed(&self) -> bool { + self.ctrl || self.alt || self.shift || self.meta + } + + fn update_ctrl(&mut self, code: u16, val: i32) { + if code == Key::KEY_LEFTCTRL.code() || code == Key::KEY_RIGHTCTRL.code() { + self.ctrl = val != 0; + } + } + + fn update_alt(&mut self, code: u16, val: i32) { + if code == Key::KEY_LEFTALT.code() || code == Key::KEY_RIGHTALT.code() { + self.ctrl = val != 0; + } + } + + fn update_shift(&mut self, code: u16, val: i32) { + if code == Key::KEY_LEFTSHIFT.code() || code == Key::KEY_RIGHTSHIFT.code() { + self.ctrl = val != 0; + } + } + + fn update_meta(&mut self, code: u16, val: i32) { + if code == Key::KEY_LEFTMETA.code() || code == Key::KEY_RIGHTMETA.code() { + self.ctrl = val != 0; + } + } +} + diff --git a/src/virt_kb.rs b/src/virt_kb.rs new file mode 100644 index 0000000..46d0996 --- /dev/null +++ b/src/virt_kb.rs @@ -0,0 +1,37 @@ +use std::sync::mpsc; +use std::sync::mpsc::{Sender, SendError}; +use std::thread; +use evdev::{Device, InputEvent}; +use evdev::uinput::VirtualDeviceBuilder; + +pub struct VirtKb { + tx: Sender>, +} + +impl VirtKb { + pub fn new(physical_kbs: &Vec) -> Self { + let (tx, rx) = mpsc::channel::>(); + + let mut virt_kb_builder = VirtualDeviceBuilder::new() + .expect("Failed to create UInput device") + .name("EasyMacros"); + + for phys_kb in physical_kbs { + virt_kb_builder = virt_kb_builder.with_keys(phys_kb.supported_keys().unwrap()).unwrap(); + } + + let mut virt_kb = virt_kb_builder.build().expect("Failed to build virt_kb"); + + thread::spawn(move || { + for received in rx { + virt_kb.emit(&received).expect("Virtual keyboard failed to send events"); + } + }); + + Self { tx } + } + + pub fn send_events(&self, events: Vec) -> Result<(), SendError>> { + self.tx.send(events) + } +} \ No newline at end of file