fix wayland input
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
367de991f6
commit
00867276ed
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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",
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -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 {
|
||||||
|
@ -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> {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user