2019-09-07 11:35:45 +00:00
|
|
|
use std::{thread};
|
2019-09-01 12:58:39 +00:00
|
|
|
use std::sync::mpsc;
|
2019-09-07 11:35:45 +00:00
|
|
|
use std::os::raw::{c_char, c_void};
|
2019-09-01 14:50:20 +00:00
|
|
|
use std::ffi::CString;
|
2019-09-06 20:19:28 +00:00
|
|
|
use crate::keyboard::{KeyEvent, KeyModifier};
|
|
|
|
use crate::keyboard::KeyModifier::*;
|
2019-09-01 12:58:39 +00:00
|
|
|
|
2019-09-07 11:35:45 +00:00
|
|
|
use crate::bridge::linux::*;
|
|
|
|
|
2019-09-01 12:58:39 +00:00
|
|
|
#[repr(C)]
|
|
|
|
pub struct LinuxKeyboardInterceptor {
|
2019-09-05 17:18:55 +00:00
|
|
|
pub sender: mpsc::Sender<KeyEvent>
|
2019-09-01 12:58:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl super::KeyboardInterceptor for LinuxKeyboardInterceptor {
|
|
|
|
fn initialize(&self) {
|
|
|
|
unsafe {
|
2019-09-07 11:35:45 +00:00
|
|
|
let self_ptr = self as *const LinuxKeyboardInterceptor as *const c_void;
|
|
|
|
register_keypress_callback( self_ptr,keypress_callback);
|
2019-09-06 20:19:28 +00:00
|
|
|
initialize(); // TODO: check initialization return codes
|
2019-09-01 12:58:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn start(&self) {
|
2019-09-06 20:19:28 +00:00
|
|
|
unsafe {
|
|
|
|
eventloop();
|
|
|
|
}
|
2019-09-01 12:58:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-01 18:46:46 +00:00
|
|
|
impl Drop for LinuxKeyboardInterceptor {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe { cleanup(); }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-01 12:58:39 +00:00
|
|
|
pub struct LinuxKeyboardSender {
|
|
|
|
}
|
|
|
|
|
|
|
|
impl super::KeyboardSender for LinuxKeyboardSender {
|
|
|
|
fn send_string(&self, s: &str) {
|
2019-09-01 14:50:20 +00:00
|
|
|
let res = CString::new(s);
|
|
|
|
match res {
|
|
|
|
Ok(cstr) => unsafe { send_string(cstr.as_ptr()); }
|
|
|
|
Err(e) => panic!(e.to_string())
|
|
|
|
}
|
2019-09-01 12:58:39 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 20:19:28 +00:00
|
|
|
fn send_enter(&self) {
|
|
|
|
// On linux this is not needed, so NOOP
|
|
|
|
}
|
|
|
|
|
2019-09-06 22:38:13 +00:00
|
|
|
fn trigger_paste(&self) {
|
|
|
|
unsafe { trigger_paste(); }
|
|
|
|
|
|
|
|
// TODO: detect when in terminal and use trigger_terminal_paste() instead
|
|
|
|
}
|
|
|
|
|
2019-09-01 12:58:39 +00:00
|
|
|
fn delete_string(&self, count: i32) {
|
2019-09-01 14:50:20 +00:00
|
|
|
unsafe {delete_string(count)}
|
2019-09-01 12:58:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Native bridge code
|
|
|
|
|
2019-09-07 11:35:45 +00:00
|
|
|
extern fn keypress_callback(_self: *mut c_void, raw_buffer: *const u8, len: i32,
|
2019-09-06 20:38:21 +00:00
|
|
|
is_modifier: i32, key_code: i32) {
|
2019-09-01 12:58:39 +00:00
|
|
|
unsafe {
|
2019-09-07 11:35:45 +00:00
|
|
|
let _self = _self as *mut LinuxKeyboardInterceptor;
|
|
|
|
|
2019-09-06 20:38:21 +00:00
|
|
|
if is_modifier == 0 { // Char event
|
2019-09-06 20:19:28 +00:00
|
|
|
// Convert the received buffer to a character
|
|
|
|
let buffer = std::slice::from_raw_parts(raw_buffer, len as usize);
|
|
|
|
let r = String::from_utf8_lossy(buffer).chars().nth(0);
|
|
|
|
|
|
|
|
// Send the char through the channel
|
|
|
|
if let Some(c) = r {
|
|
|
|
(*_self).sender.send(KeyEvent::Char(c)).unwrap();
|
|
|
|
}
|
|
|
|
}else{ // Modifier event
|
|
|
|
let modifier: Option<KeyModifier> = match key_code {
|
2019-09-06 20:38:21 +00:00
|
|
|
133 => Some(META),
|
|
|
|
50 => Some(SHIFT),
|
|
|
|
64 => Some(ALT),
|
|
|
|
37 => Some(CTRL),
|
|
|
|
22 => Some(BACKSPACE),
|
2019-09-06 20:19:28 +00:00
|
|
|
_ => None,
|
|
|
|
};
|
2019-09-01 12:58:39 +00:00
|
|
|
|
2019-09-06 20:19:28 +00:00
|
|
|
if let Some(modifier) = modifier {
|
|
|
|
(*_self).sender.send(KeyEvent::Modifier(modifier)).unwrap();
|
|
|
|
}
|
2019-09-01 12:58:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|