use std::convert::AsRef;
use std::convert::TryInto;
use std::io::{Seek, SeekFrom, Write};
use std::os::unix::io::IntoRawFd;
use std::time::{Duration, Instant};
use tempfile::tempfile;
use wayland_client::{protocol::wl_seat::WlSeat, EventQueue, Main};
use zwp_virtual_keyboard::virtual_keyboard_unstable_v1::zwp_virtual_keyboard_manager_v1::ZwpVirtualKeyboardManagerV1;
use zwp_virtual_keyboard::virtual_keyboard_unstable_v1::zwp_virtual_keyboard_v1::ZwpVirtualKeyboardV1;
mod keymap;
mod wayland;
type KeyCode = u32;
#[derive(Debug, Clone)]
pub enum SubmitError {
NotAlive,
}
#[derive(Debug, Clone, Copy)]
enum KeyState {
Pressed = 1,
Released = 0,
}
pub struct VKService {
event_queue: EventQueue, base_time: std::time::Instant,
shift_state: KeyState,
virtual_keyboard: Main<ZwpVirtualKeyboardV1>,
}
impl VKService {
pub fn new(
event_queue: EventQueue,
seat: &WlSeat,
vk_mgr: Main<ZwpVirtualKeyboardManagerV1>,
) -> VKService {
let base_time = Instant::now();
let shift_state = KeyState::Released;
let virtual_keyboard = vk_mgr.create_virtual_keyboard(&seat);
let vk_service = VKService {
event_queue,
base_time,
shift_state,
virtual_keyboard,
};
vk_service.init_virtual_keyboard();
vk_service
}
fn init_virtual_keyboard(&self) {
println!("keyboard initialized");
let src = keymap::KEYMAP;
let keymap_size = keymap::KEYMAP.len();
let keymap_size_u32: u32 = keymap_size.try_into().unwrap(); let keymap_size_u64: u64 = keymap_size.try_into().unwrap(); let mut keymap_file = tempfile().expect("Unable to create tempfile");
keymap_file.seek(SeekFrom::Start(keymap_size_u64)).unwrap();
keymap_file.write_all(&[0]).unwrap();
keymap_file.seek(SeekFrom::Start(0)).unwrap();
let mut data = unsafe {
memmap2::MmapOptions::new()
.map_mut(&keymap_file)
.expect("Could not access data from memory mapped file")
};
data[..src.len()].copy_from_slice(src.as_bytes());
let keymap_raw_fd = keymap_file.into_raw_fd();
self.virtual_keyboard
.keymap(1, keymap_raw_fd, keymap_size_u32);
}
fn get_duration(&mut self) -> u32 {
let duration = self.base_time.elapsed();
let duration = duration.as_millis();
if let Ok(duration) = duration.try_into() {
duration
} else {
self.base_time = Instant::now();
self.get_duration()
}
}
fn send_event(&mut self) {
self.event_queue
.sync_roundtrip(&mut (), |raw_event, _, _| {
println!("Unhandled Event: {:?}", raw_event)
})
.unwrap();
}
pub fn long_press_keycode(&mut self, keycode: KeyCode) -> Result<(), SubmitError> {
let press_result = self.send_key(keycode, KeyState::Pressed);
if press_result.is_ok() {
std::thread::sleep(Duration::from_millis(1000));
let result = self.send_key(keycode, KeyState::Released);
result
} else {
press_result
}
}
fn send_key(
&mut self,
keycode: KeyCode,
desired_key_state: KeyState,
) -> Result<(), SubmitError> {
let time = self.get_duration();
println!("time: {}, keycode: {}", time, keycode);
if self.virtual_keyboard.as_ref().is_alive() {
self.virtual_keyboard
.key(time, keycode, desired_key_state as u32);
self.send_event();
Ok(())
} else {
Err(SubmitError::NotAlive)
}
}
pub fn toggle_shift(&mut self) -> Result<(), SubmitError> {
let shift_flag = 0x1;
let mods_depressed;
let (_mods_latched, _mods_locked, group) = (0, 0, 0);
match self.shift_state {
KeyState::Pressed => {
self.shift_state = KeyState::Released;
mods_depressed = 0;
}
KeyState::Released => {
self.shift_state = KeyState::Pressed;
mods_depressed = shift_flag;
}
}
if self.virtual_keyboard.as_ref().is_alive() {
self.virtual_keyboard.modifiers(
mods_depressed, _mods_latched, _mods_locked, group, );
self.send_event();
Ok(())
} else {
Err(SubmitError::NotAlive)
}
}
}
fn main() {
println!("Start");
let (_, event_queue, seat, vk_mgr) = wayland::init_wayland();
let mut vk_service = VKService::new(event_queue, &seat, vk_mgr);
let key = input_event_codes::KEY_K!();
let submission_result = vk_service.long_press_keycode(key);
if submission_result.is_err() {
println!("Error: {:?}", submission_result);
};
println!("Long press done");
let key = input_event_codes::KEY_E!();
let submission_result = vk_service.toggle_shift();
if submission_result.is_err() {
println!("Error: {:?}", submission_result);
};
let submission_result = vk_service.long_press_keycode(key);
if submission_result.is_err() {
println!("Error: {:?}", submission_result);
};
println!("First toggle shift and long press x");
let key = input_event_codes::KEY_Y!();
let submission_result = vk_service.toggle_shift();
if submission_result.is_err() {
println!("Error: {:?}", submission_result);
};
let submission_result = vk_service.long_press_keycode(key);
if submission_result.is_err() {
println!("Error: {:?}", submission_result);
};
println!("Second toggle shift and long press x");
}