basically work, but AltGr not handle well, because confused with Alt_R,
and no idea how to get AltGr state. And on Windows, AltGr (some keyboard, like br) trigger two key down: Left Control and Alt, how to handle?
This commit is contained in:
parent
1758aa0f1e
commit
ab1805281f
@ -60,11 +60,16 @@ fn mousebutton(button: MouseButton) -> c_int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum PyMsg {
|
||||||
|
Char(char),
|
||||||
|
Str(&'static str),
|
||||||
|
}
|
||||||
|
|
||||||
/// The main struct for handling the event emitting
|
/// The main struct for handling the event emitting
|
||||||
pub struct Enigo {
|
pub struct Enigo {
|
||||||
xdo: Xdo,
|
xdo: Xdo,
|
||||||
delay: u64,
|
delay: u64,
|
||||||
tx: mpsc::Sender<(char, bool)>,
|
tx: mpsc::Sender<(PyMsg, bool)>,
|
||||||
}
|
}
|
||||||
// This is safe, we have a unique pointer.
|
// This is safe, we have a unique pointer.
|
||||||
// TODO: use Unique<c_char> once stable.
|
// TODO: use Unique<c_char> once stable.
|
||||||
@ -74,7 +79,7 @@ impl Default for Enigo {
|
|||||||
/// Create a new Enigo instance
|
/// Create a new Enigo instance
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
// start_pynput_service(rx);
|
start_pynput_service(rx);
|
||||||
Self {
|
Self {
|
||||||
xdo: unsafe { xdo_new(ptr::null()) },
|
xdo: unsafe { xdo_new(ptr::null()) },
|
||||||
delay: DEFAULT_DELAY,
|
delay: DEFAULT_DELAY,
|
||||||
@ -94,15 +99,98 @@ impl Enigo {
|
|||||||
pub fn set_delay(&mut self, delay: u64) {
|
pub fn set_delay(&mut self, delay: u64) {
|
||||||
self.delay = delay;
|
self.delay = delay;
|
||||||
}
|
}
|
||||||
|
///
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.tx.send((PyMsg::Char('\0'), true)).ok();
|
||||||
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn send_pynput(&mut self, key: &Key, is_press: bool) -> bool {
|
fn send_pynput(&mut self, key: &Key, is_press: bool) -> bool {
|
||||||
if unsafe { PYNPUT_EXIT || !PYNPUT_REDAY } {
|
if unsafe { PYNPUT_EXIT || !PYNPUT_REDAY } {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if let Key::Layout(c) = key {
|
if let Key::Layout(c) = key {
|
||||||
return self.tx.send((*c, is_press)).is_ok();
|
return self.tx.send((PyMsg::Char(*c), is_press)).is_ok();
|
||||||
}
|
}
|
||||||
false
|
if let Key::Raw(_) = key {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#[allow(deprecated)]
|
||||||
|
let s = match key {
|
||||||
|
Key::Alt => "Alt_L",
|
||||||
|
Key::Backspace => "BackSpace",
|
||||||
|
Key::CapsLock => "Caps_Lock",
|
||||||
|
Key::Control => "Control_L",
|
||||||
|
Key::Delete => "Delete",
|
||||||
|
Key::DownArrow => "Down",
|
||||||
|
Key::End => "End",
|
||||||
|
Key::Escape => "Escape",
|
||||||
|
Key::F1 => "F1",
|
||||||
|
Key::F10 => "F10",
|
||||||
|
Key::F11 => "F11",
|
||||||
|
Key::F12 => "F12",
|
||||||
|
Key::F2 => "F2",
|
||||||
|
Key::F3 => "F3",
|
||||||
|
Key::F4 => "F4",
|
||||||
|
Key::F5 => "F5",
|
||||||
|
Key::F6 => "F6",
|
||||||
|
Key::F7 => "F7",
|
||||||
|
Key::F8 => "F8",
|
||||||
|
Key::F9 => "F9",
|
||||||
|
Key::Home => "Home",
|
||||||
|
Key::LeftArrow => "Left",
|
||||||
|
Key::Option => "Option",
|
||||||
|
Key::PageDown => "Page_Down",
|
||||||
|
Key::PageUp => "Page_Up",
|
||||||
|
Key::Return => "Return",
|
||||||
|
Key::RightArrow => "Right",
|
||||||
|
Key::Shift => "Shift_L",
|
||||||
|
Key::Space => "space",
|
||||||
|
Key::Tab => "Tab",
|
||||||
|
Key::UpArrow => "Up",
|
||||||
|
Key::Numpad0 => "0",
|
||||||
|
Key::Numpad1 => "1",
|
||||||
|
Key::Numpad2 => "2",
|
||||||
|
Key::Numpad3 => "3",
|
||||||
|
Key::Numpad4 => "4",
|
||||||
|
Key::Numpad5 => "5",
|
||||||
|
Key::Numpad6 => "6",
|
||||||
|
Key::Numpad7 => "7",
|
||||||
|
Key::Numpad8 => "8",
|
||||||
|
Key::Numpad9 => "9",
|
||||||
|
Key::Decimal => "KP_Decimal",
|
||||||
|
Key::Cancel => "Cancel",
|
||||||
|
Key::Clear => "Clear",
|
||||||
|
Key::Pause => "Pause",
|
||||||
|
Key::Kana => "Kana",
|
||||||
|
Key::Hangul => "Hangul",
|
||||||
|
Key::Hanja => "Hanja",
|
||||||
|
Key::Kanji => "Kanji",
|
||||||
|
Key::Select => "Select",
|
||||||
|
Key::Print => "Print",
|
||||||
|
Key::Execute => "Execute",
|
||||||
|
Key::Snapshot => "3270_PrintScreen",
|
||||||
|
Key::Insert => "Insert",
|
||||||
|
Key::Help => "Help",
|
||||||
|
Key::Separator => "KP_Separator",
|
||||||
|
Key::Scroll => "Scroll_Lock",
|
||||||
|
Key::NumLock => "Num_Lock",
|
||||||
|
Key::RWin => "Super_R",
|
||||||
|
Key::Apps => "Menu",
|
||||||
|
Key::Multiply => "KP_Multiply",
|
||||||
|
Key::Add => "KP_Add",
|
||||||
|
Key::Subtract => "KP_Subtract",
|
||||||
|
Key::Divide => "KP_Divide",
|
||||||
|
Key::Equals => "KP_Equal",
|
||||||
|
Key::NumpadEnter => "KP_Enter",
|
||||||
|
Key::RightShift => "Shift_R",
|
||||||
|
Key::RightControl => "Control_R",
|
||||||
|
Key::RightAlt => "Mode_switch",
|
||||||
|
Key::Command | Key::Super | Key::Windows | Key::Meta => "Super_L",
|
||||||
|
_ => {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return self.tx.send((PyMsg::Str(s), is_press)).is_ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Drop for Enigo {
|
impl Drop for Enigo {
|
||||||
@ -385,7 +473,7 @@ static mut PYNPUT_EXIT: bool = false;
|
|||||||
static mut PYNPUT_REDAY: bool = false;
|
static mut PYNPUT_REDAY: bool = false;
|
||||||
static IPC_FILE: &'static str = "/tmp/RustDesk/pynput_service";
|
static IPC_FILE: &'static str = "/tmp/RustDesk/pynput_service";
|
||||||
|
|
||||||
fn start_pynput_service(rx: mpsc::Receiver<(char, bool)>) {
|
fn start_pynput_service(rx: mpsc::Receiver<(PyMsg, bool)>) {
|
||||||
let mut py = "./pynput_service.py".to_owned();
|
let mut py = "./pynput_service.py".to_owned();
|
||||||
if !std::path::Path::new(&py).exists() {
|
if !std::path::Path::new(&py).exists() {
|
||||||
py = "/usr/share/rustdesk/files/pynput_service.py".to_owned();
|
py = "/usr/share/rustdesk/files/pynput_service.py".to_owned();
|
||||||
@ -421,15 +509,20 @@ fn start_pynput_service(rx: mpsc::Receiver<(char, bool)>) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let d = std::time::Duration::from_millis(30);
|
let d = std::time::Duration::from_millis(30);
|
||||||
unsafe { PYNPUT_REDAY = true; }
|
unsafe {
|
||||||
let mut buf = [0u8; 10];
|
PYNPUT_REDAY = true;
|
||||||
|
}
|
||||||
|
let mut buf = [0u8; 1024];
|
||||||
loop {
|
loop {
|
||||||
if unsafe { PYNPUT_EXIT } {
|
if unsafe { PYNPUT_EXIT } {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
match rx.recv_timeout(d) {
|
match rx.recv_timeout(d) {
|
||||||
Ok((chr, is_press)) => {
|
Ok((msg, is_press)) => {
|
||||||
let msg = format!("{}{}", if is_press { 'p' } else { 'r' }, chr);
|
let msg = match msg {
|
||||||
|
PyMsg::Char(chr) => format!("{}{}", if is_press { 'p' } else { 'r' }, chr),
|
||||||
|
PyMsg::Str(s) => format!("{}{}", if is_press { 'p' } else { 'r' }, s),
|
||||||
|
};
|
||||||
let n = msg.len();
|
let n = msg.len();
|
||||||
buf[0] = n as _;
|
buf[0] = n as _;
|
||||||
buf[1..(n + 1)].copy_from_slice(msg.as_bytes());
|
buf[1..(n + 1)].copy_from_slice(msg.as_bytes());
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
from pynput.keyboard import Controller
|
from pynput.keyboard import Key, Controller
|
||||||
|
from pynput.keyboard._xorg import KeyCode
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
|
INVALID = KeyCode._from_symbol("\0") # test
|
||||||
|
|
||||||
keyboard = Controller()
|
keyboard = Controller()
|
||||||
|
|
||||||
server_address = sys.argv[1]
|
server_address = sys.argv[1]
|
||||||
@ -20,6 +23,10 @@ server.bind(server_address)
|
|||||||
server.listen(1)
|
server.listen(1)
|
||||||
clientsocket, address = server.accept()
|
clientsocket, address = server.accept()
|
||||||
print("Got pynput connection")
|
print("Got pynput connection")
|
||||||
|
|
||||||
|
|
||||||
|
def loop():
|
||||||
|
global keyboard
|
||||||
buf = []
|
buf = []
|
||||||
while True:
|
while True:
|
||||||
data = clientsocket.recv(1024)
|
data = clientsocket.recv(1024)
|
||||||
@ -27,17 +34,33 @@ while True:
|
|||||||
print("Connection broken")
|
print("Connection broken")
|
||||||
break
|
break
|
||||||
buf.extend(data)
|
buf.extend(data)
|
||||||
|
while buf:
|
||||||
n = buf[0]
|
n = buf[0]
|
||||||
n = n + 1
|
n = n + 1
|
||||||
if len(buf) >= n:
|
if len(buf) < n:
|
||||||
msg = bytearray(buf[1:n]).decode("utf-8")
|
|
||||||
if len(msg) != 2:
|
|
||||||
print("Wrong message")
|
|
||||||
break
|
break
|
||||||
if msg[0] == "p":
|
msg = bytearray(buf[1:n]).decode("utf-8")
|
||||||
keyboard.press(msg[1])
|
|
||||||
else:
|
|
||||||
keyboard.release(msg[1])
|
|
||||||
buf = buf[n:]
|
buf = buf[n:]
|
||||||
|
if len(msg) < 2:
|
||||||
|
continue
|
||||||
|
if msg[1] == "\0":
|
||||||
|
keyboard = Controller()
|
||||||
|
print("Keyboard reset")
|
||||||
|
continue
|
||||||
|
print(msg)
|
||||||
|
if len(msg) == 2:
|
||||||
|
name = msg[1]
|
||||||
|
else:
|
||||||
|
name = KeyCode._from_symbol(msg[1:])
|
||||||
|
print(name)
|
||||||
|
if name == INVALID:
|
||||||
|
continue
|
||||||
|
if msg[0] == "p":
|
||||||
|
keyboard.press(name)
|
||||||
|
else:
|
||||||
|
keyboard.release(name)
|
||||||
|
|
||||||
|
|
||||||
|
loop()
|
||||||
clientsocket.close()
|
clientsocket.close()
|
||||||
server.close()
|
server.close()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user