mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
This commit is contained in:
@@ -1,3 +1,12 @@
|
||||
var last_key_time = 0;
|
||||
var keymap = {};
|
||||
for (var (k, v) in Event) {
|
||||
k = k + ""
|
||||
if (k[0] == "V" && k[1] == "K") {
|
||||
keymap[v] = k;
|
||||
}
|
||||
}
|
||||
|
||||
class Grid: Behavior {
|
||||
const TABLE_HEADER_CLICK = 0x81;
|
||||
const TABLE_ROW_CLICK = 0x82;
|
||||
@@ -144,7 +153,7 @@ class Grid: Behavior {
|
||||
|
||||
function onKey(evt)
|
||||
{
|
||||
|
||||
last_key_time = getTime();
|
||||
if (evt.type != Event.KEY_DOWN)
|
||||
return false;
|
||||
|
||||
|
||||
306
src/ui/remote.rs
306
src/ui/remote.rs
@@ -48,6 +48,10 @@ fn get_key_state(key: enigo::Key) -> bool {
|
||||
ENIGO.lock().unwrap().get_key_state(key)
|
||||
}
|
||||
|
||||
static mut IS_IN: bool = false;
|
||||
static mut KEYBOARD_HOOKED: bool = false;
|
||||
static mut KEYBOARD_ENABLED: bool = true;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct HandlerInner {
|
||||
element: Option<Element>,
|
||||
@@ -153,7 +157,8 @@ impl sciter::EventHandler for Handler {
|
||||
fn login(String, bool);
|
||||
fn new_rdp();
|
||||
fn send_mouse(i32, i32, i32, bool, bool, bool, bool);
|
||||
fn key_down_or_up(bool, String, i32, bool, bool, bool, bool, bool);
|
||||
fn enter();
|
||||
fn leave();
|
||||
fn ctrl_alt_del();
|
||||
fn transfer_file();
|
||||
fn tunnel();
|
||||
@@ -214,6 +219,130 @@ impl Handler {
|
||||
me
|
||||
}
|
||||
|
||||
fn start_keyboard_hook(&self) {
|
||||
if self.is_port_forward() || self.is_file_transfer() {
|
||||
return;
|
||||
}
|
||||
if unsafe { KEYBOARD_HOOKED } {
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
KEYBOARD_HOOKED = true;
|
||||
}
|
||||
log::info!("keyboard hooked");
|
||||
let mut me = self.clone();
|
||||
let peer = self.peer_platform();
|
||||
let is_win = peer == "Windows";
|
||||
std::thread::spawn(move || {
|
||||
// This will block.
|
||||
std::env::set_var("KEYBOARD_ONLY", "y"); // pass to rdev
|
||||
use rdev::{EventType::*, *};
|
||||
let func = move |evt: Event| {
|
||||
if unsafe { !IS_IN || !KEYBOARD_ENABLED } {
|
||||
return;
|
||||
}
|
||||
let (key, down) = match evt.event_type {
|
||||
KeyPress(k) => (k, 1),
|
||||
KeyRelease(k) => (k, 0),
|
||||
_ => return,
|
||||
};
|
||||
let alt = get_key_state(enigo::Key::Alt);
|
||||
let ctrl = get_key_state(enigo::Key::Control);
|
||||
let shift = get_key_state(enigo::Key::Shift);
|
||||
let command = get_key_state(enigo::Key::Meta);
|
||||
let control_key = match key {
|
||||
Key::Alt => Some(ControlKey::Alt),
|
||||
Key::AltGr => Some(ControlKey::RAlt),
|
||||
Key::Backspace => Some(ControlKey::Backspace),
|
||||
Key::ControlLeft => Some(ControlKey::Control),
|
||||
Key::ControlRight => Some(ControlKey::RControl),
|
||||
Key::DownArrow => Some(ControlKey::DownArrow),
|
||||
Key::Escape => Some(ControlKey::Escape),
|
||||
Key::F1 => Some(ControlKey::F1),
|
||||
Key::F10 => Some(ControlKey::F10),
|
||||
Key::F11 => Some(ControlKey::F11),
|
||||
Key::F12 => Some(ControlKey::F12),
|
||||
Key::F2 => Some(ControlKey::F2),
|
||||
Key::F3 => Some(ControlKey::F3),
|
||||
Key::F4 => Some(ControlKey::F4),
|
||||
Key::F5 => Some(ControlKey::F5),
|
||||
Key::F6 => Some(ControlKey::F6),
|
||||
Key::F7 => Some(ControlKey::F7),
|
||||
Key::F8 => Some(ControlKey::F8),
|
||||
Key::F9 => Some(ControlKey::F9),
|
||||
Key::LeftArrow => Some(ControlKey::LeftArrow),
|
||||
Key::MetaLeft => Some(ControlKey::Meta),
|
||||
Key::MetaRight => Some(ControlKey::RWin),
|
||||
Key::Return => Some(ControlKey::Return),
|
||||
Key::RightArrow => Some(ControlKey::RightArrow),
|
||||
Key::ShiftLeft => Some(ControlKey::Shift),
|
||||
Key::ShiftRight => Some(ControlKey::RShift),
|
||||
Key::Space => Some(ControlKey::Space),
|
||||
Key::Tab => Some(ControlKey::Tab),
|
||||
Key::UpArrow => Some(ControlKey::UpArrow),
|
||||
Key::Delete | Key::KpDelete => {
|
||||
if is_win && ctrl && alt {
|
||||
me.ctrl_alt_del();
|
||||
return;
|
||||
}
|
||||
Some(ControlKey::Delete)
|
||||
}
|
||||
Key::Apps => Some(ControlKey::Apps),
|
||||
Key::Cancel => Some(ControlKey::Cancel),
|
||||
Key::Clear => Some(ControlKey::Clear),
|
||||
Key::Kana => Some(ControlKey::Kana),
|
||||
Key::Hangul => Some(ControlKey::Hangul),
|
||||
Key::Junja => Some(ControlKey::Junja),
|
||||
Key::Final => Some(ControlKey::Final),
|
||||
Key::Hanja => Some(ControlKey::Hanja),
|
||||
Key::Hanji => Some(ControlKey::Hanja),
|
||||
Key::Convert => Some(ControlKey::Convert),
|
||||
Key::Print => Some(ControlKey::Print),
|
||||
Key::Select => Some(ControlKey::Select),
|
||||
Key::Execute => Some(ControlKey::Execute),
|
||||
Key::Snapshot => Some(ControlKey::Snapshot),
|
||||
Key::Help => Some(ControlKey::Help),
|
||||
Key::Sleep => Some(ControlKey::Sleep),
|
||||
Key::Separator => Some(ControlKey::Separator),
|
||||
Key::KpReturn => Some(ControlKey::NumpadEnter),
|
||||
Key::CapsLock | Key::NumLock | Key::ScrollLock => {
|
||||
return;
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
let mut key_event = KeyEvent::new();
|
||||
if let Some(k) = control_key {
|
||||
key_event.set_control_key(k);
|
||||
} else {
|
||||
let chr = match evt.name {
|
||||
Some(ref s) => {
|
||||
if s.len() == 1 {
|
||||
s.chars().next().unwrap()
|
||||
} else {
|
||||
'\0'
|
||||
}
|
||||
}
|
||||
_ => '\0',
|
||||
};
|
||||
if chr != '\0' {
|
||||
if chr == 'l' && is_win && command {
|
||||
me.lock_screen();
|
||||
return;
|
||||
}
|
||||
key_event.set_chr(chr as _);
|
||||
} else {
|
||||
log::error!("Unknown key {:?}", evt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
me.key_down_or_up(down, key_event, alt, ctrl, shift, command);
|
||||
};
|
||||
if let Err(error) = rdev::listen(func) {
|
||||
log::error!("rdev: {:?}", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn get_view_style(&mut self) -> String {
|
||||
return self.lc.read().unwrap().view_style.clone();
|
||||
}
|
||||
@@ -632,6 +761,18 @@ impl Handler {
|
||||
self.send(Data::NewRDP);
|
||||
}
|
||||
|
||||
fn enter(&mut self) {
|
||||
unsafe {
|
||||
IS_IN = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn leave(&mut self) {
|
||||
unsafe {
|
||||
IS_IN = false;
|
||||
}
|
||||
}
|
||||
|
||||
fn send_mouse(
|
||||
&mut self,
|
||||
mask: i32,
|
||||
@@ -814,18 +955,20 @@ impl Handler {
|
||||
|
||||
fn ctrl_alt_del(&mut self) {
|
||||
if self.peer_platform() == "Windows" {
|
||||
let del = "CTRL_ALT_DEL".to_owned();
|
||||
self.key_down_or_up(1, del, 0, false, false, false, false, false);
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.set_control_key(ControlKey::CtrlAltDel);
|
||||
self.key_down_or_up(1, key_event, false, false, false, false);
|
||||
} else {
|
||||
let del = "VK_DELETE".to_owned();
|
||||
self.key_down_or_up(1, del.clone(), 0, true, true, false, false, false);
|
||||
self.key_down_or_up(0, del, 0, true, true, false, false, false);
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.set_control_key(ControlKey::Delete);
|
||||
self.key_down_or_up(3, key_event, true, true, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
fn lock_screen(&mut self) {
|
||||
let lock = "LOCK_SCREEN".to_owned();
|
||||
self.key_down_or_up(1, lock, 0, false, false, false, false, false);
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.set_control_key(ControlKey::LockScreen);
|
||||
self.key_down_or_up(1, key_event, false, false, false, false);
|
||||
}
|
||||
|
||||
fn transfer_file(&mut self) {
|
||||
@@ -847,106 +990,61 @@ impl Handler {
|
||||
fn key_down_or_up(
|
||||
&mut self,
|
||||
down_or_up: i32,
|
||||
name: String,
|
||||
code: i32,
|
||||
evt: KeyEvent,
|
||||
alt: bool,
|
||||
ctrl: bool,
|
||||
shift: bool,
|
||||
command: bool,
|
||||
extended: bool,
|
||||
) {
|
||||
if self.peer_platform() == "Windows" {
|
||||
if ctrl && alt && name == "VK_DELETE" {
|
||||
self.ctrl_alt_del();
|
||||
return;
|
||||
}
|
||||
if command && name == "VK_L" {
|
||||
self.lock_screen();
|
||||
let mut key_event = evt;
|
||||
|
||||
if alt
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Alt)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RAlt)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Alt.into());
|
||||
}
|
||||
if shift
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Shift)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RShift)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Shift.into());
|
||||
}
|
||||
if ctrl
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Control)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RControl)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Control.into());
|
||||
}
|
||||
if command
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Meta)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RWin)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Meta.into());
|
||||
}
|
||||
/*
|
||||
if crate::is_control_key(&key_event, &ControlKey::CapsLock) {
|
||||
return;
|
||||
} else if get_key_state(enigo::Key::CapsLock) && common::valid_for_capslock(&key_event) {
|
||||
key_event.modifiers.push(ControlKey::CapsLock.into());
|
||||
}
|
||||
if self.peer_platform() != "Mac OS" {
|
||||
if crate::is_control_key(&key_event, &ControlKey::NumLock) {
|
||||
return;
|
||||
} else if get_key_state(enigo::Key::NumLock) && common::valid_for_numlock(&key_event) {
|
||||
key_event.modifiers.push(ControlKey::NumLock.into());
|
||||
}
|
||||
}
|
||||
|
||||
// extended: e.g. ctrl key on right side, https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-keybd_event
|
||||
// not found api of osx and xdo
|
||||
log::debug!(
|
||||
"{:?} {} {} {} {} {} {} {} {}",
|
||||
std::time::SystemTime::now(),
|
||||
down_or_up,
|
||||
name,
|
||||
code,
|
||||
alt,
|
||||
ctrl,
|
||||
shift,
|
||||
command,
|
||||
extended,
|
||||
);
|
||||
|
||||
let mut name = name;
|
||||
#[cfg(target_os = "linux")]
|
||||
if code == 65383 {
|
||||
// VK_MENU
|
||||
name = "Apps".to_owned();
|
||||
}
|
||||
|
||||
if extended {
|
||||
match name.as_ref() {
|
||||
"VK_CONTROL" => name = "RControl".to_owned(),
|
||||
"VK_MENU" => name = "RAlt".to_owned(),
|
||||
"VK_SHIFT" => name = "RShift".to_owned(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut key_event) = self.get_key_event(down_or_up, &name, code) {
|
||||
if alt
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Alt)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RAlt)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Alt.into());
|
||||
}
|
||||
if shift
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Shift)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RShift)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Shift.into());
|
||||
}
|
||||
if ctrl
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Control)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RControl)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Control.into());
|
||||
}
|
||||
if command
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Meta)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RWin)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Meta.into());
|
||||
}
|
||||
if crate::is_control_key(&key_event, &ControlKey::CapsLock) {
|
||||
return;
|
||||
} else if get_key_state(enigo::Key::CapsLock) && common::valid_for_capslock(&key_event)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::CapsLock.into());
|
||||
}
|
||||
if self.peer_platform() != "Mac OS" {
|
||||
if crate::is_control_key(&key_event, &ControlKey::NumLock) {
|
||||
return;
|
||||
} else if get_key_state(enigo::Key::NumLock)
|
||||
&& common::valid_for_numlock(&key_event)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::NumLock.into());
|
||||
}
|
||||
}
|
||||
if down_or_up == 1 {
|
||||
key_event.down = true;
|
||||
} else if down_or_up == 3 {
|
||||
key_event.press = true;
|
||||
}
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_key_event(key_event);
|
||||
log::debug!("{:?}", msg_out);
|
||||
self.send(Data::Message(msg_out));
|
||||
*/
|
||||
if down_or_up == 1 {
|
||||
key_event.down = true;
|
||||
} else if down_or_up == 3 {
|
||||
key_event.press = true;
|
||||
}
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_key_event(key_event);
|
||||
log::debug!("{:?}", msg_out);
|
||||
self.send(Data::Message(msg_out));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -1123,6 +1221,9 @@ impl Remote {
|
||||
};
|
||||
match Client::start(&self.handler.id, conn_type).await {
|
||||
Ok((mut peer, direct)) => {
|
||||
unsafe {
|
||||
KEYBOARD_ENABLED = true;
|
||||
}
|
||||
self.handler
|
||||
.call("setConnectionType", &make_args!(peer.is_secured(), direct));
|
||||
loop {
|
||||
@@ -1182,6 +1283,9 @@ impl Remote {
|
||||
if let Some(stop) = stop_clipboard {
|
||||
stop.send(()).ok();
|
||||
}
|
||||
unsafe {
|
||||
KEYBOARD_ENABLED = false;
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_job_status(&mut self, id: i32, file_num: i32, err: Option<String>) {
|
||||
@@ -1577,6 +1681,9 @@ impl Remote {
|
||||
log::info!("Change permission {:?} -> {}", p.permission, p.enabled);
|
||||
match p.permission.enum_value_or_default() {
|
||||
Permission::Keyboard => {
|
||||
unsafe {
|
||||
KEYBOARD_ENABLED = p.enabled;
|
||||
}
|
||||
self.handler
|
||||
.call("setPermission", &make_args!("keyboard", p.enabled));
|
||||
}
|
||||
@@ -1729,6 +1836,7 @@ impl Interface for Handler {
|
||||
crate::platform::windows::add_recent_document(&path);
|
||||
}
|
||||
}
|
||||
self.start_keyboard_hook();
|
||||
}
|
||||
|
||||
async fn handle_hash(&mut self, hash: Hash, peer: &mut Stream) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
var cursor_img = $(img#cursor);
|
||||
var last_key_time = 0;
|
||||
is_file_transfer = handler.is_file_transfer();
|
||||
var is_port_forward = handler.is_port_forward();
|
||||
var display_width = 0;
|
||||
@@ -72,46 +71,14 @@ function adaptDisplay() {
|
||||
// https://sciter.com/docs/content/sciter/Event.htm
|
||||
|
||||
var entered = false;
|
||||
|
||||
var keymap = {};
|
||||
for (var (k, v) in Event) {
|
||||
k = k + ""
|
||||
if (k[0] == "V" && k[1] == "K") {
|
||||
keymap[v] = k;
|
||||
if (!is_file_transfer && !is_port_forward) {
|
||||
self.onKey = function(evt) {
|
||||
if (!entered) return false;
|
||||
// so that arrow key not move scrollbar
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// VK_ENTER = VK_RETURN
|
||||
// somehow, handler.onKey and view.onKey not working
|
||||
function self.onKey(evt) {
|
||||
last_key_time = getTime();
|
||||
if (is_file_transfer || is_port_forward) return false;
|
||||
if (!entered) return false;
|
||||
if (!keyboard_enabled) return false;
|
||||
switch (evt.type) {
|
||||
case Event.KEY_DOWN:
|
||||
handler.key_down_or_up(1, keymap[evt.keyCode] || "", evt.keyCode, evt.altKey,
|
||||
evt.ctrlKey, evt.shiftKey, evt.commandKey, evt.extendedKey);
|
||||
if (is_osx && evt.commandKey) {
|
||||
handler.key_down_or_up(0, keymap[evt.keyCode] || "", evt.keyCode, evt.altKey,
|
||||
evt.ctrlKey, evt.shiftKey, evt.commandKey, evt.extendedKey);
|
||||
}
|
||||
break;
|
||||
case Event.KEY_UP:
|
||||
handler.key_down_or_up(0, keymap[evt.keyCode] || "", evt.keyCode, evt.altKey,
|
||||
evt.ctrlKey, evt.shiftKey, evt.commandKey, evt.extendedKey);
|
||||
break;
|
||||
case Event.KEY_CHAR:
|
||||
// the keypress event is fired when the element receives character value. Event.keyCode is a UNICODE code point of the character
|
||||
handler.key_down_or_up(2, "", evt.keyCode, evt.altKey,
|
||||
evt.ctrlKey, evt.shiftKey, evt.commandKey, evt.extendedKey);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var wait_window_toolbar = false;
|
||||
var last_mouse_mask;
|
||||
var acc_wheel_delta_x = 0;
|
||||
@@ -284,10 +251,12 @@ function handler.onMouse(evt)
|
||||
case Event.MOUSE_ENTER:
|
||||
entered = true;
|
||||
stdout.println("enter");
|
||||
handler.enter();
|
||||
return keyboard_enabled;
|
||||
case Event.MOUSE_LEAVE:
|
||||
entered = false;
|
||||
stdout.println("leave");
|
||||
handler.leave();
|
||||
return keyboard_enabled;
|
||||
default:
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user