macos, use private CGEventSource
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
01ade73304
commit
94cecb1860
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -4305,7 +4305,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "rdev"
|
name = "rdev"
|
||||||
version = "0.5.0-2"
|
version = "0.5.0-2"
|
||||||
source = "git+https://github.com/fufesou/rdev#edddb71a88bd8a4737ef4216861b426490c49f2e"
|
source = "git+https://github.com/fufesou/rdev#196b589573f90703a601e6b105dd7c917fc388f9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cocoa",
|
"cocoa",
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3",
|
||||||
|
@ -523,6 +523,8 @@ impl Connection {
|
|||||||
rdev::set_dw_mouse_extra_info(enigo::ENIGO_INPUT_EXTRA_VALUE);
|
rdev::set_dw_mouse_extra_info(enigo::ENIGO_INPUT_EXTRA_VALUE);
|
||||||
rdev::set_dw_keyboard_extra_info(enigo::ENIGO_INPUT_EXTRA_VALUE);
|
rdev::set_dw_keyboard_extra_info(enigo::ENIGO_INPUT_EXTRA_VALUE);
|
||||||
}
|
}
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
reset_input_ondisconn();
|
||||||
loop {
|
loop {
|
||||||
match receiver.recv_timeout(std::time::Duration::from_millis(500)) {
|
match receiver.recv_timeout(std::time::Duration::from_millis(500)) {
|
||||||
Ok(v) => match v {
|
Ok(v) => match v {
|
||||||
|
@ -5,7 +5,9 @@ use crate::common::IS_X11;
|
|||||||
use dispatch::Queue;
|
use dispatch::Queue;
|
||||||
use enigo::{Enigo, Key, KeyboardControllable, MouseButton, MouseControllable};
|
use enigo::{Enigo, Key, KeyboardControllable, MouseButton, MouseControllable};
|
||||||
use hbb_common::{config::COMPRESS_LEVEL, get_time, protobuf::EnumOrUnknown};
|
use hbb_common::{config::COMPRESS_LEVEL, get_time, protobuf::EnumOrUnknown};
|
||||||
use rdev::{self, simulate, EventType, Key as RdevKey, RawKey};
|
use rdev::{self, EventType, Key as RdevKey, RawKey};
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
use rdev::{CGEventSourceStateID, CGEventTapLocation, VirtualInput};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
@ -221,6 +223,10 @@ lazy_static::lazy_static! {
|
|||||||
static ref IS_SERVER: bool = std::env::args().nth(1) == Some("--server".to_owned());
|
static ref IS_SERVER: bool = std::env::args().nth(1) == Some("--server".to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// virtual_input must be used in main thread.
|
||||||
|
// No need to wrap mutex.
|
||||||
|
static mut VIRTUAL_INPUT: Option<VirtualInput> = None;
|
||||||
|
|
||||||
// First call set_uinput() will create keyboard and mouse clients.
|
// First call set_uinput() will create keyboard and mouse clients.
|
||||||
// The clients are ipc connections that must live shorter than tokio runtime.
|
// The clients are ipc connections that must live shorter than tokio runtime.
|
||||||
// Thus this function must not be called in a temporary runtime.
|
// Thus this function must not be called in a temporary runtime.
|
||||||
@ -392,7 +398,9 @@ fn record_key_to_key(record_key: u64) -> Option<Key> {
|
|||||||
fn release_record_key(record_key: u64) {
|
fn release_record_key(record_key: u64) {
|
||||||
let func = move || {
|
let func = move || {
|
||||||
if record_key_is_rdev_layout(record_key) {
|
if record_key_is_rdev_layout(record_key) {
|
||||||
rdev_key_down_or_up(RdevKey::Unknown((record_key - KEY_RDEV_START) as _), false);
|
simulate_(&EventType::KeyRelease(RdevKey::Unknown(
|
||||||
|
(record_key - KEY_RDEV_START) as _,
|
||||||
|
)));
|
||||||
} else if let Some(key) = record_key_to_key(record_key) {
|
} else if let Some(key) = record_key_to_key(record_key) {
|
||||||
ENIGO.lock().unwrap().key_up(key);
|
ENIGO.lock().unwrap().key_up(key);
|
||||||
log::debug!("Fixed {:?} timeout", key);
|
log::debug!("Fixed {:?} timeout", key);
|
||||||
@ -687,7 +695,27 @@ pub fn handle_key(evt: &KeyEvent) {
|
|||||||
handle_key_(evt);
|
handle_key_(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sim_rdev_rawkey(code: u32, down_or_up: bool) {
|
#[inline]
|
||||||
|
fn reset_input() {
|
||||||
|
unsafe {
|
||||||
|
VIRTUAL_INPUT = VirtualInput::new(
|
||||||
|
CGEventSourceStateID::Private,
|
||||||
|
CGEventTapLocation::AnnotatedSession,
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
pub fn reset_input_ondisconn() {
|
||||||
|
if !*IS_SERVER {
|
||||||
|
QUEUE.exec_async(reset_input);
|
||||||
|
} else {
|
||||||
|
reset_input();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sim_rdev_rawkey(code: u32, keydown: bool) {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let rawkey = RawKey::ScanCode(code);
|
let rawkey = RawKey::ScanCode(code);
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
@ -698,22 +726,34 @@ fn sim_rdev_rawkey(code: u32, down_or_up: bool) {
|
|||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
let rawkey = RawKey::MacVirtualKeycode(code);
|
let rawkey = RawKey::MacVirtualKeycode(code);
|
||||||
|
|
||||||
rdev_key_down_or_up(RdevKey::RawKey(rawkey), down_or_up);
|
let event_type = if keydown {
|
||||||
|
EventType::KeyPress(RdevKey::RawKey(rawkey))
|
||||||
|
} else {
|
||||||
|
EventType::KeyRelease(RdevKey::RawKey(rawkey))
|
||||||
|
};
|
||||||
|
simulate_(&event_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rdev_key_down_or_up(key: RdevKey, down_or_up: bool) {
|
#[cfg(target_os = "macos")]
|
||||||
let event_type = match down_or_up {
|
#[inline]
|
||||||
true => EventType::KeyPress(key),
|
fn simulate_(event_type: &EventType) {
|
||||||
false => EventType::KeyRelease(key),
|
unsafe {
|
||||||
};
|
if let Some(virtual_input) = &VIRTUAL_INPUT {
|
||||||
match simulate(&event_type) {
|
let _ = virtual_input.simulate(&event_type);
|
||||||
|
std::thread::sleep(Duration::from_millis(20));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
#[inline]
|
||||||
|
fn simulate_(event_type: &EventType) {
|
||||||
|
match rdev::simulate(&event_type) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(_simulate_error) => {
|
Err(_simulate_error) => {
|
||||||
log::error!("Could not send {:?}", &event_type);
|
log::error!("Could not send {:?}", &event_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
std::thread::sleep(Duration::from_millis(20));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_modifier_in_key_event(control_key: ControlKey, key_event: &KeyEvent) -> bool {
|
fn is_modifier_in_key_event(control_key: ControlKey, key_event: &KeyEvent) -> bool {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user