From 0a294d9ff318e9c9ea3ceda6820c686d664ec800 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sun, 9 Jan 2022 19:56:24 +0800 Subject: [PATCH] https://github.com/rustdesk/rustdesk/issues/292 --- Cargo.lock | 121 ++++++++--- Cargo.toml | 5 +- libs/hbb_common/protos/message.proto | 1 + src/ui/grid.tis | 11 +- src/ui/remote.rs | 306 ++++++++++++++++++--------- src/ui/remote.tis | 45 +--- 6 files changed, 325 insertions(+), 164 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc1244525..b66313127 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,7 +94,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d76e1fe0171b6d0857afca5671db12a44e71e80823db13ab39f776fb09ad079" dependencies = [ "clipboard-win", - "core-graphics", + "core-graphics 0.22.3", "image", "log", "objc", @@ -416,6 +416,21 @@ dependencies = [ "cc", ] +[[package]] +name = "cocoa" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "667fdc068627a2816b9ff831201dd9864249d6ee8d190b9532357f1fc0f61ea7" +dependencies = [ + "bitflags", + "block", + "core-foundation 0.9.2", + "core-graphics 0.21.0", + "foreign-types", + "libc", + "objc", +] + [[package]] name = "cocoa" version = "0.24.0" @@ -425,8 +440,8 @@ dependencies = [ "bitflags", "block", "cocoa-foundation", - "core-foundation", - "core-graphics", + "core-foundation 0.9.2", + "core-graphics 0.22.3", "foreign-types", "libc", "objc", @@ -440,7 +455,7 @@ checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" dependencies = [ "bitflags", "block", - "core-foundation", + "core-foundation 0.9.2", "core-graphics-types", "foreign-types", "libc", @@ -473,22 +488,62 @@ dependencies = [ "toml", ] +[[package]] +name = "core-foundation" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +dependencies = [ + "core-foundation-sys 0.7.0", + "libc", +] + [[package]] name = "core-foundation" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" dependencies = [ - "core-foundation-sys", + "core-foundation-sys 0.8.3", "libc", ] +[[package]] +name = "core-foundation-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" + [[package]] name = "core-foundation-sys" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "core-graphics" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" +dependencies = [ + "bitflags", + "core-foundation 0.7.0", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a67c4378cf203eace8fb6567847eb641fd6ff933c1145a115c6ee820ebb978" +dependencies = [ + "bitflags", + "core-foundation 0.9.2", + "foreign-types", + "libc", +] + [[package]] name = "core-graphics" version = "0.22.3" @@ -496,7 +551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ "bitflags", - "core-foundation", + "core-foundation 0.9.2", "core-graphics-types", "foreign-types", "libc", @@ -509,7 +564,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" dependencies = [ "bitflags", - "core-foundation", + "core-foundation 0.9.2", "foreign-types", "libc", ] @@ -539,7 +594,7 @@ version = "0.13.4" source = "git+https://github.com/open-trade/cpal#3a30569687271c2d5d67279c4883d63f4003d34c" dependencies = [ "alsa", - "core-foundation-sys", + "core-foundation-sys 0.8.3", "coreaudio-rs", "jni", "js-sys", @@ -922,7 +977,7 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" name = "enigo" version = "0.0.14" dependencies = [ - "core-graphics", + "core-graphics 0.22.3", "libc", "log", "objc", @@ -2891,6 +2946,21 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "rdev" +version = "0.5.0" +source = "git+https://github.com/open-trade/rdev#faeef84bf2edfa457e9e32c0c96b63f44e494fff" +dependencies = [ + "cocoa 0.22.0", + "core-foundation 0.7.0", + "core-foundation-sys 0.7.0", + "core-graphics 0.19.2", + "lazy_static", + "libc", + "winapi 0.3.9", + "x11", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -3055,9 +3125,9 @@ dependencies = [ "cfg-if 1.0.0", "clap", "clipboard-master", - "cocoa", - "core-foundation", - "core-graphics", + "cocoa 0.24.0", + "core-foundation 0.9.2", + "core-graphics 0.22.3", "cpal", "crc32fast", "ctrlc", @@ -3077,6 +3147,7 @@ dependencies = [ "objc", "parity-tokio-ipc", "psutil", + "rdev", "repng", "rpassword 5.0.1", "rubato", @@ -3091,7 +3162,6 @@ dependencies = [ "sha2", "sys-locale", "systray", - "tigervnc", "uuid", "whoami", "winapi 0.3.9", @@ -3243,8 +3313,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" dependencies = [ "bitflags", - "core-foundation", - "core-foundation-sys", + "core-foundation 0.9.2", + "core-foundation-sys 0.8.3", "libc", "security-framework-sys", ] @@ -3255,7 +3325,7 @@ version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" dependencies = [ - "core-foundation-sys", + "core-foundation-sys 0.8.3", "libc", ] @@ -3604,15 +3674,6 @@ dependencies = [ "weezl", ] -[[package]] -name = "tigervnc" -version = "1.0.1" -source = "git+https://github.com/open-trade/tigervnc#254ad243c5a22887ddf0e79def58b8251b108d08" -dependencies = [ - "cc", - "cfg-if 1.0.0", -] - [[package]] name = "time" version = "0.3.5" @@ -4126,6 +4187,16 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "x11" +version = "2.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd0565fa8bfba8c5efe02725b14dff114c866724eff2cfd44d76cea74bcd87a" +dependencies = [ + "libc", + "pkg-config", +] + [[package]] name = "x11-clipboard" version = "0.5.3" diff --git a/Cargo.toml b/Cargo.toml index 69b3673ab..db0133937 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,10 @@ sciter-rs = { git = "https://github.com/open-trade/rust-sciter", branch = "dyn" ctrlc = "3.2" arboard = "2.0" clipboard-master = "3.1" -tigervnc = { git = "https://github.com/open-trade/tigervnc" } +#tigervnc = { path = "../tigervnc" } +#tigervnc = { git = "https://github.com/open-trade/tigervnc" } +#rdev = { path = "../rdev" } +rdev = { git = "https://github.com/open-trade/rdev" } [target.'cfg(target_os = "windows")'.dependencies] systray = { git = "https://github.com/liyue201/systray-rs" } diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 47c526dd1..d436fe128 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -83,6 +83,7 @@ message MouseEvent { } enum ControlKey { + Unknown = 0; Alt = 1; Backspace = 2; CapsLock = 3; diff --git a/src/ui/grid.tis b/src/ui/grid.tis index f33b4ef35..cf7cf3a38 100644 --- a/src/ui/grid.tis +++ b/src/ui/grid.tis @@ -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; diff --git a/src/ui/remote.rs b/src/ui/remote.rs index d4fde3f38..e732bcbb3 100644 --- a/src/ui/remote.rs +++ b/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, @@ -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) { @@ -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) { diff --git a/src/ui/remote.tis b/src/ui/remote.tis index af936e112..0afbe13f3 100644 --- a/src/ui/remote.tis +++ b/src/ui/remote.tis @@ -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;