Merge pull request #2503 from fufesou/keyboard

Keyboard
This commit is contained in:
RustDesk 2022-12-10 10:00:37 +08:00 committed by GitHub
commit 1ce2c0487d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 99 additions and 96 deletions

View File

@ -324,6 +324,8 @@ impl InvokeUiSession for FlutterHandler {
); );
} }
fn on_connected(&self, _conn_type: ConnType) {}
fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str, retry: bool) { fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str, retry: bool) {
let has_retry = if retry { "true" } else { "" }; let has_retry = if retry { "true" } else { "" };
self.push_event( self.push_event(

View File

@ -17,8 +17,6 @@ use hbb_common::{
use crate::flutter::{self, SESSIONS}; use crate::flutter::{self, SESSIONS};
use crate::ui_interface::{self, *}; use crate::ui_interface::{self, *};
#[cfg(not(any(target_os = "android", target_os = "ios")))]
use crate::keyboard::CUR_SESSION;
use crate::{ use crate::{
client::file_trait::FileManager, client::file_trait::FileManager,
flutter::{make_fd_to_json, session_add, session_start_}, flutter::{make_fd_to_json, session_add, session_start_},
@ -293,7 +291,7 @@ pub fn session_enter_or_leave(id: String, enter: bool) {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
if let Some(session) = SESSIONS.read().unwrap().get(&id) { if let Some(session) = SESSIONS.read().unwrap().get(&id) {
if enter { if enter {
*CUR_SESSION.lock().unwrap() = Some(session.clone()); crate::keyboard::set_cur_session(session.clone());
session.enter(); session.enter();
} else { } else {
session.leave(); session.leave();

View File

@ -8,29 +8,26 @@ use crate::ui::remote::SciterHandler;
use crate::ui_session_interface::Session; use crate::ui_session_interface::Session;
use hbb_common::{log, message_proto::*}; use hbb_common::{log, message_proto::*};
use rdev::{Event, EventType, Key}; use rdev::{Event, EventType, Key};
use std::collections::{HashMap, HashSet}; use std::{
use std::sync::atomic::AtomicBool; collections::{HashMap, HashSet},
#[cfg(any(target_os = "windows", target_os = "macos"))] sync::{
use std::sync::atomic::Ordering; atomic::{AtomicBool, Ordering},
use std::sync::{mpsc, Arc, Mutex}; Arc, Mutex,
use std::thread; },
use std::time::SystemTime; time::SystemTime,
};
static mut IS_ALT_GR: bool = false; static mut IS_ALT_GR: bool = false;
pub static KEYBOARD_HOOKED: AtomicBool = AtomicBool::new(false); static KEYBOARD_HOOKED: AtomicBool = AtomicBool::new(false);
lazy_static::lazy_static! {
pub static ref GRAB_SENDER: Arc<Mutex<Option<mpsc::Sender<GrabState>>>> = Default::default();
}
#[cfg(feature = "flutter")] #[cfg(feature = "flutter")]
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref CUR_SESSION: Arc<Mutex<Option<Session<FlutterHandler>>>> = Default::default(); static ref CUR_SESSION: Arc<Mutex<Option<Session<FlutterHandler>>>> = Default::default();
} }
#[cfg(not(feature = "flutter"))] #[cfg(not(feature = "flutter"))]
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref CUR_SESSION: Arc<Mutex<Option<Session<SciterHandler>>>> = Default::default(); static ref CUR_SESSION: Arc<Mutex<Option<Session<SciterHandler>>>> = Default::default();
} }
lazy_static::lazy_static! { lazy_static::lazy_static! {
@ -47,7 +44,10 @@ lazy_static::lazy_static! {
m.insert(Key::MetaRight, false); m.insert(Key::MetaRight, false);
Mutex::new(m) Mutex::new(m)
}; };
}
pub fn set_cur_session(session: Session<SciterHandler>) {
*CUR_SESSION.lock().unwrap() = Some(session);
} }
pub mod client { pub mod client {
@ -62,20 +62,32 @@ pub mod client {
} }
pub fn start_grab_loop() { pub fn start_grab_loop() {
let (sender, receiver) = mpsc::channel::<GrabState>(); super::start_grab_loop();
grab_loop(receiver);
*GRAB_SENDER.lock().unwrap() = Some(sender);
change_grab_status(GrabState::Ready);
} }
pub fn change_grab_status(state: GrabState) { pub fn change_grab_status(state: GrabState) {
if GrabState::Wait == state { match state {
release_remote_keys(); GrabState::Ready => {}
GrabState::Run => {
#[cfg(any(target_os = "windows", target_os = "macos"))]
KEYBOARD_HOOKED.swap(true, Ordering::SeqCst);
#[cfg(target_os = "linux")]
rdev::enable_grab().ok();
}
GrabState::Wait => {
release_remote_keys();
#[cfg(any(target_os = "windows", target_os = "macos"))]
KEYBOARD_HOOKED.swap(false, Ordering::SeqCst);
#[cfg(target_os = "linux")]
rdev::disable_grab().ok();
}
GrabState::Exit => {
#[cfg(target_os = "linux")]
rdev::exit_grab_listen().ok();
} }
if let Some(sender) = &*GRAB_SENDER.lock().unwrap() {
sender.send(state).ok();
} }
} }
@ -166,11 +178,7 @@ pub mod client {
} }
} }
pub fn grab_loop(recv: mpsc::Receiver<GrabState>) { pub fn start_grab_loop() {
thread::spawn(move || loop {
if let Some(state) = recv.recv().ok() {
match state {
GrabState::Ready => {
#[cfg(any(target_os = "windows", target_os = "macos"))] #[cfg(any(target_os = "windows", target_os = "macos"))]
std::thread::spawn(move || { std::thread::spawn(move || {
let func = move |event: Event| match event.event_type { let func = move |event: Event| match event.event_type {
@ -206,28 +214,6 @@ pub fn grab_loop(recv: mpsc::Receiver<GrabState>) {
_ => Some(event), _ => Some(event),
}); });
} }
GrabState::Run => {
#[cfg(any(target_os = "windows", target_os = "macos"))]
KEYBOARD_HOOKED.swap(true, Ordering::SeqCst);
#[cfg(target_os = "linux")]
rdev::enable_grab().ok();
}
GrabState::Wait => {
#[cfg(any(target_os = "windows", target_os = "macos"))]
KEYBOARD_HOOKED.swap(false, Ordering::SeqCst);
#[cfg(target_os = "linux")]
rdev::disable_grab().ok();
}
GrabState::Exit => {
#[cfg(target_os = "linux")]
rdev::exit_grab_listen().ok();
}
}
}
});
}
pub fn is_long_press(event: &Event) -> bool { pub fn is_long_press(event: &Event) -> bool {
let keys = MODIFIERS_STATE.lock().unwrap(); let keys = MODIFIERS_STATE.lock().unwrap();
@ -246,10 +232,9 @@ pub fn is_long_press(event: &Event) -> bool {
pub fn release_remote_keys() { pub fn release_remote_keys() {
// todo!: client quit suddenly, how to release keys? // todo!: client quit suddenly, how to release keys?
let to_release = TO_RELEASE.lock().unwrap(); let to_release = TO_RELEASE.lock().unwrap().clone();
let keys = to_release.iter().map(|&key| key).collect::<Vec<Key>>(); TO_RELEASE.lock().unwrap().clear();
drop(to_release); for key in to_release {
for key in keys {
let event_type = EventType::KeyRelease(key); let event_type = EventType::KeyRelease(key);
let event = event_type_to_event(event_type); let event = event_type_to_event(event_type);
client::process_event(event); client::process_event(event);
@ -317,17 +302,15 @@ pub fn event_to_key_event(event: &Event) -> KeyEvent {
let mut key_event = KeyEvent::new(); let mut key_event = KeyEvent::new();
update_modifiers_state(event); update_modifiers_state(event);
let mut to_release = TO_RELEASE.lock().unwrap();
match event.event_type { match event.event_type {
EventType::KeyPress(key) => { EventType::KeyPress(key) => {
to_release.insert(key); TO_RELEASE.lock().unwrap().insert(key);
} }
EventType::KeyRelease(key) => { EventType::KeyRelease(key) => {
to_release.remove(&key); TO_RELEASE.lock().unwrap().remove(&key);
} }
_ => {} _ => {}
} }
drop(to_release);
let keyboard_mode = get_keyboard_mode_enum(); let keyboard_mode = get_keyboard_mode_enum();
key_event.mode = keyboard_mode.into(); key_event.mode = keyboard_mode.into();

View File

@ -124,12 +124,15 @@ pub fn start(args: &mut [String]) {
let args: Vec<String> = iter.map(|x| x.clone()).collect(); let args: Vec<String> = iter.map(|x| x.clone()).collect();
frame.set_title(&id); frame.set_title(&id);
frame.register_behavior("native-remote", move || { frame.register_behavior("native-remote", move || {
Box::new(remote::SciterSession::new( let handler = remote::SciterSession::new(
cmd.clone(), cmd.clone(),
id.clone(), id.clone(),
pass.clone(), pass.clone(),
args.clone(), args.clone(),
)) );
let inner = handler.inner();
crate::keyboard::set_cur_session(inner);
Box::new(handler)
}); });
page = "remote.html"; page = "remote.html";
} else { } else {

View File

@ -231,6 +231,17 @@ impl InvokeUiSession for SciterHandler {
self.call("updatePi", &make_args!(pi_sciter)); self.call("updatePi", &make_args!(pi_sciter));
} }
fn on_connected(&self, conn_type: ConnType) {
match conn_type {
ConnType::RDP => {},
ConnType::PORT_FORWARD => {},
ConnType::FILE_TRANSFER => {},
ConnType::DEFAULT_CONN => {
crate::keyboard::client::start_grab_loop();
},
}
}
fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str, retry: bool) { fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str, retry: bool) {
self.call2( self.call2(
"msgbox_retry", "msgbox_retry",
@ -434,6 +445,10 @@ impl SciterSession {
Self(session) Self(session)
} }
pub fn inner(&self) -> Session<SciterHandler> {
self.0.clone()
}
fn get_custom_image_quality(&mut self) -> Value { fn get_custom_image_quality(&mut self) -> Value {
let mut v = Value::array(0); let mut v = Value::array(0);
for x in self.lc.read().unwrap().custom_image_quality.iter() { for x in self.lc.read().unwrap().custom_image_quality.iter() {

View File

@ -5,6 +5,7 @@ use crate::client::{
QualityStatus, KEY_MAP, QualityStatus, KEY_MAP,
}; };
use crate::common::GrabState; use crate::common::GrabState;
use crate::keyboard;
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};
@ -12,12 +13,11 @@ use hbb_common::rendezvous_proto::ConnType;
use hbb_common::tokio::{self, sync::mpsc}; use hbb_common::tokio::{self, sync::mpsc};
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};
use rdev::{Event, EventType::*};
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use crate::keyboard;
use rdev::{Event, EventType::*};
pub static IS_IN: AtomicBool = AtomicBool::new(false); pub static IS_IN: AtomicBool = AtomicBool::new(false);
#[derive(Clone, Default)] #[derive(Clone, Default)]
@ -580,6 +580,7 @@ pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default {
fn set_display(&self, x: i32, y: i32, w: i32, h: i32, cursor_embeded: bool); fn set_display(&self, x: i32, y: i32, w: i32, h: i32, cursor_embeded: bool);
fn switch_display(&self, display: &SwitchDisplay); fn switch_display(&self, display: &SwitchDisplay);
fn set_peer_info(&self, peer_info: &PeerInfo); // flutter fn set_peer_info(&self, peer_info: &PeerInfo); // flutter
fn on_connected(&self, conn_type: ConnType);
fn update_privacy_mode(&self); fn update_privacy_mode(&self);
fn set_permission(&self, name: &str, value: bool); fn set_permission(&self, name: &str, value: bool);
fn close_success(&self); fn close_success(&self);
@ -712,6 +713,7 @@ impl<T: InvokeUiSession> Interface for Session<T> {
"", "",
); );
} }
self.on_connected(self.lc.read().unwrap().conn_type);
#[cfg(windows)] #[cfg(windows)]
{ {
let mut path = std::env::temp_dir(); let mut path = std::env::temp_dir();