fix wayland input

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2023-01-10 14:11:49 +08:00
parent 367de991f6
commit 00867276ed
10 changed files with 75 additions and 21 deletions

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hbb/models/state_model.dart';
import '../../models/input_model.dart'; import '../../models/input_model.dart';
@ -25,7 +26,8 @@ class RawKeyFocusScope extends StatelessWidget {
canRequestFocus: true, canRequestFocus: true,
focusNode: focusNode, focusNode: focusNode,
onFocusChange: onFocusChange, onFocusChange: onFocusChange,
onKey: inputModel.handleRawKeyEvent, onKey:
stateGlobal.grabKeyboard ? inputModel.handleRawKeyEvent : null,
child: child)); child: child));
} }
} }

View File

@ -3,6 +3,7 @@ import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/desktop/pages/remote_tab_page.dart'; import 'package:flutter_hbb/desktop/pages/remote_tab_page.dart';
import 'package:flutter_hbb/models/platform_model.dart'; import 'package:flutter_hbb/models/platform_model.dart';
import 'package:flutter_hbb/desktop/widgets/refresh_wrapper.dart'; import 'package:flutter_hbb/desktop/widgets/refresh_wrapper.dart';
import 'package:flutter_hbb/models/state_model.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
/// multi-tab desktop remote screen /// multi-tab desktop remote screen
@ -10,7 +11,9 @@ class DesktopRemoteScreen extends StatelessWidget {
final Map<String, dynamic> params; final Map<String, dynamic> params;
DesktopRemoteScreen({Key? key, required this.params}) : super(key: key) { DesktopRemoteScreen({Key? key, required this.params}) : super(key: key) {
bind.mainStartGrabKeyboard(); if (!bind.mainStartGrabKeyboard()) {
stateGlobal.grabKeyboard = true;
}
} }
@override @override

View File

@ -119,8 +119,11 @@ class InputModel {
keyCode = newData.keyCode; keyCode = newData.keyCode;
} else if (e.data is RawKeyEventDataLinux) { } else if (e.data is RawKeyEventDataLinux) {
RawKeyEventDataLinux newData = e.data as RawKeyEventDataLinux; RawKeyEventDataLinux newData = e.data as RawKeyEventDataLinux;
scanCode = newData.scanCode; // scanCode and keyCode of RawKeyEventDataLinux are incorrect.
keyCode = newData.keyCode; // 1. scanCode means keycode
// 2. keyCode means keysym
scanCode = 0;
keyCode = newData.scanCode;
} else if (e.data is RawKeyEventDataAndroid) { } else if (e.data is RawKeyEventDataAndroid) {
RawKeyEventDataAndroid newData = e.data as RawKeyEventDataAndroid; RawKeyEventDataAndroid newData = e.data as RawKeyEventDataAndroid;
scanCode = newData.scanCode + 8; scanCode = newData.scanCode + 8;
@ -135,16 +138,33 @@ class InputModel {
} else { } else {
down = false; down = false;
} }
inputRawKey(e.character ?? "", keyCode, scanCode, down); inputRawKey(e.character ?? '', keyCode, scanCode, down);
} }
/// Send raw Key Event /// Send raw Key Event
void inputRawKey(String name, int keyCode, int scanCode, bool down) { void inputRawKey(String name, int keyCode, int scanCode, bool down) {
const capslock = 1;
const numlock = 2;
const scrolllock = 3;
int lockModes = 0;
if (HardwareKeyboard.instance.lockModesEnabled
.contains(KeyboardLockMode.capsLock)) {
lockModes |= (1 << capslock);
}
if (HardwareKeyboard.instance.lockModesEnabled
.contains(KeyboardLockMode.numLock)) {
lockModes |= (1 << numlock);
}
if (HardwareKeyboard.instance.lockModesEnabled
.contains(KeyboardLockMode.scrollLock)) {
lockModes |= (1 << scrolllock);
}
bind.sessionHandleFlutterKeyEvent( bind.sessionHandleFlutterKeyEvent(
id: id, id: id,
name: name, name: name,
keycode: keyCode, keycode: keyCode,
scancode: scanCode, scancode: scanCode,
lockModes: lockModes,
downOrUp: down); downOrUp: down);
} }

View File

@ -9,6 +9,7 @@ import '../consts.dart';
class StateGlobal { class StateGlobal {
int _windowId = -1; int _windowId = -1;
bool _fullscreen = false; bool _fullscreen = false;
bool grabKeyboard = false;
final RxBool _showTabBar = true.obs; final RxBool _showTabBar = true.obs;
final RxDouble _resizeEdgeSize = RxDouble(kWindowEdgeSize); final RxDouble _resizeEdgeSize = RxDouble(kWindowEdgeSize);
final RxDouble _windowBorderWidth = RxDouble(kWindowBorderWidth); final RxDouble _windowBorderWidth = RxDouble(kWindowBorderWidth);

View File

@ -183,6 +183,7 @@ impl MouseControllable for Enigo {
fn get_led_state(key: Key) -> bool { fn get_led_state(key: Key) -> bool {
let led_file = match key { let led_file = match key {
// FIXME: the file may be /sys/class/leds/input2 or input5 ...
Key::CapsLock => "/sys/class/leds/input1::capslock/brightness", Key::CapsLock => "/sys/class/leds/input1::capslock/brightness",
Key::NumLock => "/sys/class/leds/input1::numlock/brightness", Key::NumLock => "/sys/class/leds/input1::numlock/brightness",
_ => { _ => {

View File

@ -51,7 +51,7 @@ lazy_static::lazy_static! {
pub fn global_init() -> bool { pub fn global_init() -> bool {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
{ {
if !scrap::is_x11() { if !*IS_X11 {
crate::server::wayland::set_wayland_scrap_map_err(); crate::server::wayland::set_wayland_scrap_map_err();
} }
} }
@ -660,13 +660,13 @@ pub fn make_privacy_mode_msg(state: back_notification::PrivacyModeState) -> Mess
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref IS_X11: Mutex<bool> = Mutex::new(false); pub static ref IS_X11: bool = false;
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref IS_X11: Mutex<bool> = Mutex::new("x11" == hbb_common::platform::linux::get_display_server()); pub static ref IS_X11: bool = "x11" == hbb_common::platform::linux::get_display_server();
} }
pub fn make_fd_to_json(id: i32, path: String, entries: &Vec<FileEntry>) -> String { pub fn make_fd_to_json(id: i32, path: String, entries: &Vec<FileEntry>) -> String {

View File

@ -289,10 +289,11 @@ pub fn session_handle_flutter_key_event(
name: String, name: String,
keycode: i32, keycode: i32,
scancode: i32, scancode: i32,
lock_modes: i32,
down_or_up: bool, down_or_up: bool,
) { ) {
if let Some(session) = SESSIONS.read().unwrap().get(&id) { if let Some(session) = SESSIONS.read().unwrap().get(&id) {
session.handle_flutter_key_event(&name, keycode, scancode, down_or_up); session.handle_flutter_key_event(&name, keycode, scancode, lock_modes, down_or_up);
} }
} }
@ -1093,8 +1094,13 @@ pub fn main_is_installed() -> SyncReturn<bool> {
SyncReturn(is_installed()) SyncReturn(is_installed())
} }
pub fn main_start_grab_keyboard() { pub fn main_start_grab_keyboard() -> SyncReturn<bool> {
#[cfg(target_os = "linux")]
if !*crate::common::IS_X11 {
return SyncReturn(false);
}
crate::keyboard::client::start_grab_loop(); crate::keyboard::client::start_grab_loop();
SyncReturn(true)
} }
pub fn main_is_installed_lower_version() -> SyncReturn<bool> { pub fn main_is_installed_lower_version() -> SyncReturn<bool> {

View File

@ -99,11 +99,11 @@ pub mod client {
} }
} }
pub fn process_event(event: &Event) { pub fn process_event(event: &Event, lock_modes: Option<i32>) {
if is_long_press(&event) { if is_long_press(&event) {
return; return;
} }
if let Some(key_event) = event_to_key_event(&event) { if let Some(key_event) = event_to_key_event(&event, lock_modes) {
send_key_event(&key_event); send_key_event(&key_event);
} }
} }
@ -196,7 +196,7 @@ pub fn start_grab_loop() {
return Some(event); return Some(event);
} }
if KEYBOARD_HOOKED.load(Ordering::SeqCst) { if KEYBOARD_HOOKED.load(Ordering::SeqCst) {
client::process_event(&event); client::process_event(&event, None);
if is_press { if is_press {
return None; return None;
} else { } else {
@ -222,7 +222,7 @@ pub fn start_grab_loop() {
if let Key::Unknown(keycode) = key { if let Key::Unknown(keycode) = key {
log::error!("rdev get unknown key, keycode is : {:?}", keycode); log::error!("rdev get unknown key, keycode is : {:?}", keycode);
} else { } else {
client::process_event(&event); client::process_event(&event, None);
} }
None None
} }
@ -254,7 +254,7 @@ pub fn release_remote_keys() {
for key in to_release { for key in to_release {
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, None);
} }
} }
@ -267,7 +267,23 @@ pub fn get_keyboard_mode_enum() -> KeyboardMode {
} }
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
pub fn add_numlock_capslock_status(key_event: &mut KeyEvent) { fn add_numlock_capslock_with_lock_modes(key_event: &mut KeyEvent, lock_modes: i32) {
const CAPS_LOCK: i32 = 1;
const NUM_LOCK: i32 = 2;
// const SCROLL_LOCK: i32 = 3;
if lock_modes & (1 << CAPS_LOCK) != 0 {
key_event.modifiers.push(ControlKey::CapsLock.into());
}
if lock_modes & (1 << NUM_LOCK) != 0 {
key_event.modifiers.push(ControlKey::NumLock.into());
}
// if lock_modes & (1 << SCROLL_LOCK) != 0 {
// key_event.modifiers.push(ControlKey::ScrollLock.into());
// }
}
#[cfg(not(any(target_os = "android", target_os = "ios")))]
fn add_numlock_capslock_status(key_event: &mut KeyEvent) {
if get_key_state(enigo::Key::CapsLock) { if get_key_state(enigo::Key::CapsLock) {
key_event.modifiers.push(ControlKey::CapsLock.into()); key_event.modifiers.push(ControlKey::CapsLock.into());
} }
@ -315,7 +331,7 @@ fn update_modifiers_state(event: &Event) {
}; };
} }
pub fn event_to_key_event(event: &Event) -> Option<KeyEvent> { pub fn event_to_key_event(event: &Event, lock_modes: Option<i32>) -> Option<KeyEvent> {
let mut key_event = KeyEvent::new(); let mut key_event = KeyEvent::new();
update_modifiers_state(event); update_modifiers_state(event);
@ -345,8 +361,12 @@ pub fn event_to_key_event(event: &Event) -> Option<KeyEvent> {
} }
} }
}; };
#[cfg(not(any(target_os = "android", target_os = "ios")))] if let Some(lock_modes) = lock_modes {
add_numlock_capslock_status(&mut key_event); add_numlock_capslock_with_lock_modes(&mut key_event, lock_modes);
} else {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
add_numlock_capslock_status(&mut key_event);
}
return Some(key_event); return Some(key_event);
} }

View File

@ -882,7 +882,7 @@ fn map_keyboard_mode(evt: &KeyEvent) {
// Wayland // Wayland
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
if !*IS_X11.lock().unwrap() { if !*IS_X11 {
let mut en = ENIGO.lock().unwrap(); let mut en = ENIGO.lock().unwrap();
let code = evt.chr() as u16; let code = evt.chr() as u16;

View File

@ -394,6 +394,7 @@ impl<T: InvokeUiSession> Session<T> {
name: &str, name: &str,
keycode: i32, keycode: i32,
scancode: i32, scancode: i32,
lock_modes: i32,
down_or_up: bool, down_or_up: bool,
) { ) {
if scancode < 0 || keycode < 0 { if scancode < 0 || keycode < 0 {
@ -420,7 +421,7 @@ impl<T: InvokeUiSession> Session<T> {
scan_code: scancode as _, scan_code: scancode as _,
event_type: event_type, event_type: event_type,
}; };
keyboard::client::process_event(&event); keyboard::client::process_event(&event, Some(lock_modes));
} }
// flutter only TODO new input // flutter only TODO new input