commit
15296fd629
59
Cargo.lock
generated
59
Cargo.lock
generated
@ -1514,6 +1514,16 @@ dependencies = [
|
|||||||
"termcolor",
|
"termcolor",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "epoll"
|
||||||
|
version = "4.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "20df693c700404f7e19d4d6fae6b15215d2913c27955d2b9d6f2c0f537511cd0"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "err-derive"
|
name = "err-derive"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@ -2574,6 +2584,26 @@ dependencies = [
|
|||||||
"hashbrown 0.12.3",
|
"hashbrown 0.12.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inotify"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "abf888f9575c290197b2c948dc9e9ff10bd1a39ad1ea8585f734585fa6b9d3f9"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"inotify-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inotify-sys"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instant"
|
name = "instant"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
@ -4073,15 +4103,19 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "rdev"
|
name = "rdev"
|
||||||
version = "0.5.0-2"
|
version = "0.5.0-2"
|
||||||
source = "git+https://github.com/asur4s/rdev#bff57a29e3f14d032ab7441b2d6cf029df8adaca"
|
source = "git+https://github.com/asur4s/rdev#ea223720532f32652dab803db43f9ce437f2b019"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cocoa",
|
"cocoa",
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3",
|
||||||
"core-foundation-sys 0.8.3",
|
"core-foundation-sys 0.8.3",
|
||||||
"core-graphics 0.22.3",
|
"core-graphics 0.22.3",
|
||||||
"enum-map",
|
"enum-map",
|
||||||
|
"epoll",
|
||||||
|
"inotify",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
|
"strum 0.24.1",
|
||||||
|
"strum_macros 0.24.3",
|
||||||
"widestring 1.0.2",
|
"widestring 1.0.2",
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
"x11 2.20.0",
|
"x11 2.20.0",
|
||||||
@ -4899,6 +4933,12 @@ version = "0.18.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
|
checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.24.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strum_macros"
|
name = "strum_macros"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
@ -4911,6 +4951,19 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.24.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.4.0",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.99"
|
version = "1.0.99"
|
||||||
@ -4993,8 +5046,8 @@ checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.3.3",
|
"heck 0.3.3",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
"strum",
|
"strum 0.18.0",
|
||||||
"strum_macros",
|
"strum_macros 0.18.0",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"toml",
|
"toml",
|
||||||
"version-compare 0.0.10",
|
"version-compare 0.0.10",
|
||||||
|
@ -48,7 +48,7 @@ pub use super::lang::*;
|
|||||||
pub mod file_trait;
|
pub mod file_trait;
|
||||||
pub mod helper;
|
pub mod helper;
|
||||||
pub mod io_loop;
|
pub mod io_loop;
|
||||||
|
use crate::ui_session_interface::global_save_keyboard_mode;
|
||||||
pub static SERVER_KEYBOARD_ENABLED: AtomicBool = AtomicBool::new(true);
|
pub static SERVER_KEYBOARD_ENABLED: AtomicBool = AtomicBool::new(true);
|
||||||
pub static SERVER_FILE_TRANSFER_ENABLED: AtomicBool = AtomicBool::new(true);
|
pub static SERVER_FILE_TRANSFER_ENABLED: AtomicBool = AtomicBool::new(true);
|
||||||
pub static SERVER_CLIPBOARD_ENABLED: AtomicBool = AtomicBool::new(true);
|
pub static SERVER_CLIPBOARD_ENABLED: AtomicBool = AtomicBool::new(true);
|
||||||
@ -1294,6 +1294,9 @@ impl LoginConfigHandler {
|
|||||||
if !pi.version.is_empty() {
|
if !pi.version.is_empty() {
|
||||||
self.version = hbb_common::get_version_number(&pi.version);
|
self.version = hbb_common::get_version_number(&pi.version);
|
||||||
}
|
}
|
||||||
|
if hbb_common::get_version_number(&pi.version) < hbb_common::get_version_number("1.2.0") {
|
||||||
|
global_save_keyboard_mode("legacy".to_owned());
|
||||||
|
}
|
||||||
self.features = pi.features.clone().into_option();
|
self.features = pi.features.clone().into_option();
|
||||||
let serde = PeerInfoSerde {
|
let serde = PeerInfoSerde {
|
||||||
username: pi.username.clone(),
|
username: pi.username.clone(),
|
||||||
|
@ -6,6 +6,7 @@ use crate::client::{
|
|||||||
load_config, send_mouse, start_video_audio_threads, FileManager, Key, LoginConfigHandler,
|
load_config, send_mouse, start_video_audio_threads, FileManager, Key, LoginConfigHandler,
|
||||||
QualityStatus, KEY_MAP, SERVER_KEYBOARD_ENABLED,
|
QualityStatus, KEY_MAP, SERVER_KEYBOARD_ENABLED,
|
||||||
};
|
};
|
||||||
|
use crate::common::IS_X11;
|
||||||
use crate::{client::Data, client::Interface};
|
use crate::{client::Data, client::Interface};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use hbb_common::config::{Config, LocalConfig, PeerConfig};
|
use hbb_common::config::{Config, LocalConfig, PeerConfig};
|
||||||
@ -13,7 +14,7 @@ use hbb_common::rendezvous_proto::ConnType;
|
|||||||
use hbb_common::tokio::{self, sync::mpsc};
|
use hbb_common::tokio::{self, sync::mpsc};
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
use rdev::Keyboard as RdevKeyboard;
|
use rdev::Keyboard as RdevKeyboard;
|
||||||
use rdev::{Event, EventType::*, Key as RdevKey, KeyboardState};
|
use rdev::{Event, EventType, EventType::*, Key as RdevKey, KeyboardState};
|
||||||
|
|
||||||
use hbb_common::{allow_err, message_proto::*};
|
use hbb_common::{allow_err, message_proto::*};
|
||||||
use hbb_common::{fs, get_version_number, log, Stream};
|
use hbb_common::{fs, get_version_number, log, Stream};
|
||||||
@ -25,7 +26,9 @@ use std::sync::{Arc, Mutex, RwLock};
|
|||||||
/// IS_IN KEYBOARD_HOOKED sciter only
|
/// IS_IN KEYBOARD_HOOKED sciter only
|
||||||
pub static IS_IN: AtomicBool = AtomicBool::new(false);
|
pub static IS_IN: AtomicBool = AtomicBool::new(false);
|
||||||
pub static KEYBOARD_HOOKED: AtomicBool = AtomicBool::new(true);
|
pub static KEYBOARD_HOOKED: AtomicBool = AtomicBool::new(true);
|
||||||
|
pub static HOTKEY_HOOK_ENABLED: AtomicBool = AtomicBool::new(false);
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
use rdev::IS_GRAB;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
static mut IS_ALT_GR: bool = false;
|
static mut IS_ALT_GR: bool = false;
|
||||||
|
|
||||||
@ -38,6 +41,21 @@ lazy_static::lazy_static! {
|
|||||||
static ref KEYBOARD: Arc<Mutex<RdevKeyboard>> = Arc::new(Mutex::new(RdevKeyboard::new().unwrap()));
|
static ref KEYBOARD: Arc<Mutex<RdevKeyboard>> = Arc::new(Mutex::new(RdevKeyboard::new().unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
static ref MUTEX_SPECIAL_KEYS: Mutex<HashMap<RdevKey, bool>> = {
|
||||||
|
let mut m = HashMap::new();
|
||||||
|
m.insert(RdevKey::ShiftLeft, false);
|
||||||
|
m.insert(RdevKey::ShiftRight, false);
|
||||||
|
m.insert(RdevKey::ControlLeft, false);
|
||||||
|
m.insert(RdevKey::ControlRight, false);
|
||||||
|
m.insert(RdevKey::Alt, false);
|
||||||
|
m.insert(RdevKey::AltGr, false);
|
||||||
|
m.insert(RdevKey::MetaLeft, false);
|
||||||
|
m.insert(RdevKey::MetaRight, false);
|
||||||
|
Mutex::new(m)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct Session<T: InvokeUiSession> {
|
pub struct Session<T: InvokeUiSession> {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
@ -63,13 +81,11 @@ impl<T: InvokeUiSession> Session<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_keyboard_mode(&self) -> String {
|
pub fn get_keyboard_mode(&self) -> String {
|
||||||
return std::env::var("KEYBOARD_MODE")
|
global_get_keyboard_mode()
|
||||||
.unwrap_or(String::from("legacy"))
|
|
||||||
.to_lowercase();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_keyboard_mode(&self, value: String) {
|
pub fn save_keyboard_mode(&self, value: String) {
|
||||||
std::env::set_var("KEYBOARD_MODE", value);
|
global_save_keyboard_mode(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_view_style(&mut self, value: String) {
|
pub fn save_view_style(&mut self, value: String) {
|
||||||
@ -146,7 +162,12 @@ impl<T: InvokeUiSession> Session<T> {
|
|||||||
let decoder = scrap::codec::Decoder::video_codec_state(&self.id);
|
let decoder = scrap::codec::Decoder::video_codec_state(&self.id);
|
||||||
let mut h264 = decoder.score_h264 > 0;
|
let mut h264 = decoder.score_h264 > 0;
|
||||||
let mut h265 = decoder.score_h265 > 0;
|
let mut h265 = decoder.score_h265 > 0;
|
||||||
let (encoding_264, encoding_265) = self.lc.read().unwrap().supported_encoding.unwrap_or_default();
|
let (encoding_264, encoding_265) = self
|
||||||
|
.lc
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.supported_encoding
|
||||||
|
.unwrap_or_default();
|
||||||
h264 = h264 && encoding_264;
|
h264 = h264 && encoding_264;
|
||||||
h265 = h265 && encoding_265;
|
h265 = h265 && encoding_265;
|
||||||
return (h264, h265);
|
return (h264, h265);
|
||||||
@ -622,6 +643,7 @@ impl<T: InvokeUiSession> Session<T> {
|
|||||||
RdevKey::Quote => '\'',
|
RdevKey::Quote => '\'',
|
||||||
RdevKey::LeftBracket => '[',
|
RdevKey::LeftBracket => '[',
|
||||||
RdevKey::RightBracket => ']',
|
RdevKey::RightBracket => ']',
|
||||||
|
RdevKey::Slash => '/',
|
||||||
RdevKey::BackSlash => '\\',
|
RdevKey::BackSlash => '\\',
|
||||||
RdevKey::Minus => '-',
|
RdevKey::Minus => '-',
|
||||||
RdevKey::Equal => '=',
|
RdevKey::Equal => '=',
|
||||||
@ -746,12 +768,24 @@ impl<T: InvokeUiSession> Session<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn enter(&self) {
|
pub fn enter(&self) {
|
||||||
|
HOTKEY_HOOK_ENABLED.store(true, Ordering::SeqCst);
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
unsafe {
|
||||||
|
IS_GRAB.store(true, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
crate::platform::windows::stop_system_key_propagate(true);
|
crate::platform::windows::stop_system_key_propagate(true);
|
||||||
IS_IN.store(true, Ordering::SeqCst);
|
IS_IN.store(true, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn leave(&self) {
|
pub fn leave(&self) {
|
||||||
|
HOTKEY_HOOK_ENABLED.store(false, Ordering::SeqCst);
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
unsafe {
|
||||||
|
IS_GRAB.store(false, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
for key in TO_RELEASE.lock().unwrap().iter() {
|
for key in TO_RELEASE.lock().unwrap().iter() {
|
||||||
self.map_keyboard_mode(false, *key, None)
|
self.map_keyboard_mode(false, *key, None)
|
||||||
}
|
}
|
||||||
@ -865,27 +899,19 @@ impl<T: InvokeUiSession> Session<T> {
|
|||||||
ControlKey::Numpad9 => ControlKey::PageUp,
|
ControlKey::Numpad9 => ControlKey::PageUp,
|
||||||
_ => key,
|
_ => key,
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
key
|
key
|
||||||
};
|
};
|
||||||
key_event.set_control_key(key.clone());
|
key_event.set_control_key(key.clone());
|
||||||
}
|
}
|
||||||
Key::_Raw(raw) => {
|
Key::_Raw(raw) => {
|
||||||
if raw > 'z' as u32 || raw < 'a' as u32 {
|
key_event.set_chr(raw);
|
||||||
key_event.set_unicode(raw);
|
|
||||||
// TODO
|
|
||||||
// if down_or_up == 0 {
|
|
||||||
// // ignore up, avoiding trigger twice
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// down_or_up = 1; // if press, turn into down for avoiding trigger twice on server side
|
|
||||||
} else {
|
|
||||||
// to make ctrl+c works on windows
|
|
||||||
key_event.set_chr(raw);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
let (alt, ctrl, shift, command) = get_all_hotkey_state(alt, ctrl, shift, command);
|
||||||
|
|
||||||
self.legacy_modifiers(&mut key_event, alt, ctrl, shift, command);
|
self.legacy_modifiers(&mut key_event, alt, ctrl, shift, command);
|
||||||
if v == 1 {
|
if v == 1 {
|
||||||
key_event.down = true;
|
key_event.down = true;
|
||||||
@ -915,6 +941,9 @@ impl<T: InvokeUiSession> Session<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
let (alt, ctrl, shift, command) = get_all_hotkey_state(alt, ctrl, shift, command);
|
||||||
|
|
||||||
send_mouse(mask, x, y, alt, ctrl, shift, command, self);
|
send_mouse(mask, x, y, alt, ctrl, shift, command, self);
|
||||||
// on macos, ctrl + left button down = right button down, up won't emit, so we need to
|
// on macos, ctrl + left button down = right button down, up won't emit, so we need to
|
||||||
// emit up myself if peer is not macos
|
// emit up myself if peer is not macos
|
||||||
@ -1164,8 +1193,11 @@ impl<T: InvokeUiSession> Interface for Session<T> {
|
|||||||
crate::platform::windows::add_recent_document(&path);
|
crate::platform::windows::add_recent_document(&path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
self.start_keyboard_hook();
|
self.start_keyboard_hook();
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
self.start_hotkey_grab();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_hash(&mut self, pass: &str, hash: Hash, peer: &mut Stream) {
|
async fn handle_hash(&mut self, pass: &str, hash: Hash, peer: &mut Stream) {
|
||||||
@ -1208,6 +1240,93 @@ impl<T: InvokeUiSession> Interface for Session<T> {
|
|||||||
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
impl<T: InvokeUiSession> Session<T> {
|
impl<T: InvokeUiSession> Session<T> {
|
||||||
|
fn handle_hot_key_event(&self, event: Event) {
|
||||||
|
// keyboard long press
|
||||||
|
match event.event_type {
|
||||||
|
EventType::KeyPress(k) => {
|
||||||
|
if MUTEX_SPECIAL_KEYS.lock().unwrap().contains_key(&k) {
|
||||||
|
if *MUTEX_SPECIAL_KEYS.lock().unwrap().get(&k).unwrap() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MUTEX_SPECIAL_KEYS.lock().unwrap().insert(k, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EventType::KeyRelease(k) => {
|
||||||
|
if MUTEX_SPECIAL_KEYS.lock().unwrap().contains_key(&k) {
|
||||||
|
MUTEX_SPECIAL_KEYS.lock().unwrap().insert(k, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
// keyboard short press
|
||||||
|
match event.event_type {
|
||||||
|
EventType::KeyPress(key) => {
|
||||||
|
self.key_down_or_up(true, key, event);
|
||||||
|
}
|
||||||
|
EventType::KeyRelease(key) => {
|
||||||
|
self.key_down_or_up(false, key, event);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_hotkey_grab(&self) {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
if !*IS_X11.lock().unwrap() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if self.is_port_forward() || self.is_file_transfer() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let me = self.clone();
|
||||||
|
|
||||||
|
log::info!("hotkey grabing");
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
std::env::set_var("KEYBOARD_ONLY", "y");
|
||||||
|
|
||||||
|
let func = move |event: Event| {
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||||
|
if !HOTKEY_HOOK_ENABLED.load(Ordering::SeqCst) {
|
||||||
|
return Some(event);
|
||||||
|
};
|
||||||
|
match event.event_type {
|
||||||
|
EventType::KeyPress(_key) | EventType::KeyRelease(_key) => {
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||||
|
if MUTEX_SPECIAL_KEYS.lock().unwrap().contains_key(&_key) {
|
||||||
|
me.handle_hot_key_event(event);
|
||||||
|
return None;
|
||||||
|
} else {
|
||||||
|
return Some(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
me.handle_hot_key_event(event);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
_ => Some(event),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
use rdev::GRABED_KEYS;
|
||||||
|
GRABED_KEYS.lock().unwrap().insert(RdevKey::ShiftLeft);
|
||||||
|
GRABED_KEYS.lock().unwrap().insert(RdevKey::ShiftRight);
|
||||||
|
GRABED_KEYS.lock().unwrap().insert(RdevKey::ControlLeft);
|
||||||
|
GRABED_KEYS.lock().unwrap().insert(RdevKey::ControlRight);
|
||||||
|
GRABED_KEYS.lock().unwrap().insert(RdevKey::Alt);
|
||||||
|
GRABED_KEYS.lock().unwrap().insert(RdevKey::AltGr);
|
||||||
|
GRABED_KEYS.lock().unwrap().insert(RdevKey::MetaLeft);
|
||||||
|
GRABED_KEYS.lock().unwrap().insert(RdevKey::MetaRight);
|
||||||
|
}
|
||||||
|
if let Err(error) = rdev::grab(func) {
|
||||||
|
log::error!("Error: {:?}", error)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn start_keyboard_hook(&self) {
|
fn start_keyboard_hook(&self) {
|
||||||
if self.is_port_forward() || self.is_file_transfer() {
|
if self.is_port_forward() || self.is_file_transfer() {
|
||||||
return;
|
return;
|
||||||
@ -1215,6 +1334,11 @@ impl<T: InvokeUiSession> Session<T> {
|
|||||||
if !KEYBOARD_HOOKED.load(Ordering::SeqCst) {
|
if !KEYBOARD_HOOKED.load(Ordering::SeqCst) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// rdev::grab and rdev::listen use the same api on macOS
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
if HOTKEY_HOOK_ENABLED.load(Ordering::SeqCst) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
log::info!("keyboard hooked");
|
log::info!("keyboard hooked");
|
||||||
let me = self.clone();
|
let me = self.clone();
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@ -1222,20 +1346,6 @@ impl<T: InvokeUiSession> Session<T> {
|
|||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
// This will block.
|
// This will block.
|
||||||
std::env::set_var("KEYBOARD_ONLY", "y");
|
std::env::set_var("KEYBOARD_ONLY", "y");
|
||||||
lazy_static::lazy_static! {
|
|
||||||
static ref MUTEX_SPECIAL_KEYS: Mutex<HashMap<RdevKey, bool>> = {
|
|
||||||
let mut m = HashMap::new();
|
|
||||||
m.insert(RdevKey::ShiftLeft, false);
|
|
||||||
m.insert(RdevKey::ShiftRight, false);
|
|
||||||
m.insert(RdevKey::ControlLeft, false);
|
|
||||||
m.insert(RdevKey::ControlRight, false);
|
|
||||||
m.insert(RdevKey::Alt, false);
|
|
||||||
m.insert(RdevKey::AltGr, false);
|
|
||||||
m.insert(RdevKey::MetaLeft, false);
|
|
||||||
m.insert(RdevKey::MetaRight, false);
|
|
||||||
Mutex::new(m)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let func = move |evt: Event| {
|
let func = move |evt: Event| {
|
||||||
if !IS_IN.load(Ordering::SeqCst) || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst)
|
if !IS_IN.load(Ordering::SeqCst) || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst)
|
||||||
@ -1421,3 +1531,34 @@ async fn send_note(url: String, id: String, conn_id: i32, note: String) {
|
|||||||
let body = serde_json::json!({ "id": id, "Id": conn_id, "note": note });
|
let body = serde_json::json!({ "id": id, "Id": conn_id, "note": note });
|
||||||
allow_err!(crate::post_request(url, body.to_string(), "").await);
|
allow_err!(crate::post_request(url, body.to_string(), "").await);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_hotkey_state(key: RdevKey) -> bool {
|
||||||
|
*MUTEX_SPECIAL_KEYS.lock().unwrap().get(&key).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_all_hotkey_state(
|
||||||
|
alt: bool,
|
||||||
|
ctrl: bool,
|
||||||
|
shift: bool,
|
||||||
|
command: bool,
|
||||||
|
) -> (bool, bool, bool, bool) {
|
||||||
|
let ctrl =
|
||||||
|
get_hotkey_state(RdevKey::ControlLeft) || get_hotkey_state(RdevKey::ControlRight) || ctrl;
|
||||||
|
let shift =
|
||||||
|
get_hotkey_state(RdevKey::ShiftLeft) || get_hotkey_state(RdevKey::ShiftRight) || shift;
|
||||||
|
let command =
|
||||||
|
get_hotkey_state(RdevKey::MetaLeft) || get_hotkey_state(RdevKey::MetaRight) || command;
|
||||||
|
let alt = get_hotkey_state(RdevKey::Alt) || get_hotkey_state(RdevKey::AltGr) || alt;
|
||||||
|
|
||||||
|
(alt, ctrl, shift, command)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn global_get_keyboard_mode() -> String {
|
||||||
|
return std::env::var("KEYBOARD_MODE")
|
||||||
|
.unwrap_or(String::from("map"))
|
||||||
|
.to_lowercase();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn global_save_keyboard_mode(value: String) {
|
||||||
|
std::env::set_var("KEYBOARD_MODE", value);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user