mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-12-11 09:49:11 +08:00
Merge pull request #6561 from fufesou/feat/input_source
Feat/input source
This commit is contained in:
commit
db158e1ffe
30
Cargo.lock
generated
30
Cargo.lock
generated
@ -1806,7 +1806,7 @@ dependencies = [
|
||||
"log",
|
||||
"objc",
|
||||
"pkg-config",
|
||||
"rdev 0.5.0-2 (git+https://github.com/fufesou/rdev)",
|
||||
"rdev",
|
||||
"serde 1.0.190",
|
||||
"serde_derive",
|
||||
"tfc",
|
||||
@ -4894,31 +4894,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rdev"
|
||||
version = "0.5.0-2"
|
||||
source = "git+https://github.com/fufesou/rdev?branch=master#339b2a334ba273afebb7e27fb76984e620fc76e5"
|
||||
dependencies = [
|
||||
"cocoa",
|
||||
"core-foundation 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation-sys 0.8.4",
|
||||
"core-graphics 0.22.3",
|
||||
"dispatch",
|
||||
"enum-map",
|
||||
"epoll",
|
||||
"inotify",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"mio",
|
||||
"strum 0.24.1",
|
||||
"strum_macros 0.24.3",
|
||||
"widestring",
|
||||
"winapi 0.3.9",
|
||||
"x11 2.21.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rdev"
|
||||
version = "0.5.0-2"
|
||||
source = "git+https://github.com/fufesou/rdev#339b2a334ba273afebb7e27fb76984e620fc76e5"
|
||||
source = "git+https://github.com/fufesou/rdev#b3434caee84c92412b45a2f655a15ac5dad33488"
|
||||
dependencies = [
|
||||
"cocoa",
|
||||
"core-foundation 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -5261,7 +5237,7 @@ dependencies = [
|
||||
"pam",
|
||||
"parity-tokio-ipc",
|
||||
"percent-encoding",
|
||||
"rdev 0.5.0-2 (git+https://github.com/fufesou/rdev?branch=master)",
|
||||
"rdev",
|
||||
"repng",
|
||||
"reqwest",
|
||||
"ringbuf",
|
||||
|
@ -71,7 +71,7 @@ default-net = "0.14"
|
||||
wol-rs = "1.0"
|
||||
flutter_rust_bridge = { version = "=1.80", features = ["uuid"], optional = true}
|
||||
errno = "0.3"
|
||||
rdev = { git = "https://github.com/fufesou/rdev", branch = "master" }
|
||||
rdev = { git = "https://github.com/fufesou/rdev" }
|
||||
url = { version = "2.3", features = ["serde"] }
|
||||
crossbeam-queue = "0.3"
|
||||
hex = "0.4"
|
||||
|
@ -959,7 +959,6 @@ class CustomAlertDialog extends StatelessWidget {
|
||||
void msgBox(SessionID sessionId, String type, String title, String text,
|
||||
String link, OverlayDialogManager dialogManager,
|
||||
{bool? hasCancel, ReconnectHandle? reconnect, int? reconnectTimeout}) {
|
||||
|
||||
dialogManager.dismissAll();
|
||||
List<Widget> buttons = [];
|
||||
bool hasOk = false;
|
||||
@ -2766,6 +2765,8 @@ parseParamScreenRect(Map<String, dynamic> params) {
|
||||
return screenRect;
|
||||
}
|
||||
|
||||
get isInputSourceFlutter => stateGlobal.getInputSource() == "Input source 2";
|
||||
|
||||
class _ReconnectCountDownButton extends StatefulWidget {
|
||||
_ReconnectCountDownButton({
|
||||
Key? key,
|
||||
|
@ -34,7 +34,8 @@ class RawKeyFocusScope extends StatelessWidget {
|
||||
canRequestFocus: true,
|
||||
focusNode: focusNode,
|
||||
onFocusChange: onFocusChange,
|
||||
onKey: inputModel.handleRawKeyEvent,
|
||||
onKey: (FocusNode data, RawKeyEvent e) =>
|
||||
inputModel.handleRawKeyEvent(e),
|
||||
child: child));
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ const String kAppTypeDesktopPortForward = "port forward";
|
||||
const String kWindowMainWindowOnTop = "main_window_on_top";
|
||||
const String kWindowGetWindowInfo = "get_window_info";
|
||||
const String kWindowGetScreenList = "get_screen_list";
|
||||
// This method is not used, maybe it can be removed.
|
||||
const String kWindowDisableGrabKeyboard = "disable_grab_keyboard";
|
||||
const String kWindowActionRebuild = "rebuild";
|
||||
const String kWindowEventHide = "hide";
|
||||
|
@ -156,7 +156,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||
),
|
||||
));
|
||||
} else if (call.method == kWindowDisableGrabKeyboard) {
|
||||
stateGlobal.grabKeyboard = false;
|
||||
// ???
|
||||
} else if (call.method == "onDestroy") {
|
||||
tabController.clear();
|
||||
} else if (call.method == kWindowActionRebuild) {
|
||||
|
@ -12,9 +12,8 @@ class DesktopRemoteScreen extends StatelessWidget {
|
||||
final Map<String, dynamic> params;
|
||||
|
||||
DesktopRemoteScreen({Key? key, required this.params}) : super(key: key) {
|
||||
if (!bind.mainStartGrabKeyboard()) {
|
||||
stateGlobal.grabKeyboard = true;
|
||||
}
|
||||
bind.mainInitInputSource();
|
||||
stateGlobal.getInputSource(force: true);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1585,7 +1585,7 @@ class _KeyboardMenu extends StatelessWidget {
|
||||
// If use flutter to grab keys, we can only use one mode.
|
||||
// Map mode and Legacy mode, at least one of them is supported.
|
||||
String? modeOnly;
|
||||
if (stateGlobal.grabKeyboard) {
|
||||
if (isInputSourceFlutter) {
|
||||
if (bind.sessionIsKeyboardModeSupported(
|
||||
sessionId: ffi.sessionId, mode: kKeyMapMode)) {
|
||||
modeOnly = kKeyMapMode;
|
||||
@ -1603,6 +1603,7 @@ class _KeyboardMenu extends StatelessWidget {
|
||||
menuChildren: [
|
||||
keyboardMode(modeOnly),
|
||||
localKeyboardType(),
|
||||
inputSource(),
|
||||
Divider(),
|
||||
viewMode(),
|
||||
Divider(),
|
||||
@ -1627,6 +1628,7 @@ class _KeyboardMenu extends StatelessWidget {
|
||||
if (value == null) return;
|
||||
await bind.sessionSetKeyboardMode(
|
||||
sessionId: ffi.sessionId, value: value);
|
||||
await ffi.inputModel.updateKeyboardMode();
|
||||
}
|
||||
|
||||
for (InputModeMenu mode in modes) {
|
||||
@ -1678,6 +1680,41 @@ class _KeyboardMenu extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
inputSource() {
|
||||
final supportedInputSource = bind.mainSupportedInputSource();
|
||||
if (supportedInputSource.isEmpty) return Offstage();
|
||||
late final List<dynamic> supportedInputSourceList;
|
||||
try {
|
||||
supportedInputSourceList = jsonDecode(supportedInputSource);
|
||||
} catch (e) {
|
||||
debugPrint('Failed to decode $supportedInputSource, $e');
|
||||
return;
|
||||
}
|
||||
if (supportedInputSourceList.length < 2) return Offstage();
|
||||
final inputSource = stateGlobal.getInputSource();
|
||||
final enabled = !ffi.ffiModel.viewOnly;
|
||||
final children = <Widget>[Divider()];
|
||||
children.addAll(supportedInputSourceList.map((e) {
|
||||
final d = e as List<dynamic>;
|
||||
return RdoMenuButton<String>(
|
||||
child: Text(translate(d[1] as String)),
|
||||
value: d[0] as String,
|
||||
groupValue: inputSource,
|
||||
onChanged: enabled
|
||||
? (v) async {
|
||||
if (v != null) {
|
||||
await stateGlobal.setInputSource(ffi.sessionId, v);
|
||||
await ffi.ffiModel.checkDesktopKeyboardMode();
|
||||
await ffi.inputModel.updateKeyboardMode();
|
||||
}
|
||||
}
|
||||
: null,
|
||||
ffi: ffi,
|
||||
);
|
||||
}));
|
||||
return Column(children: children);
|
||||
}
|
||||
|
||||
viewMode() {
|
||||
final ffiModel = ffi.ffiModel;
|
||||
final enabled = versionCmp(pi.version, '1.2.0') >= 0 && ffiModel.keyboard;
|
||||
|
@ -13,7 +13,6 @@ import '../../models/model.dart';
|
||||
import '../../models/platform_model.dart';
|
||||
import '../common.dart';
|
||||
import '../consts.dart';
|
||||
import './state_model.dart';
|
||||
|
||||
/// Mouse button enum.
|
||||
enum MouseButtons { left, right, wheel }
|
||||
@ -53,9 +52,114 @@ class PointerEventToRust {
|
||||
}
|
||||
}
|
||||
|
||||
class ToReleaseKeys {
|
||||
RawKeyEvent? lastLShiftKeyEvent;
|
||||
RawKeyEvent? lastRShiftKeyEvent;
|
||||
RawKeyEvent? lastLCtrlKeyEvent;
|
||||
RawKeyEvent? lastRCtrlKeyEvent;
|
||||
RawKeyEvent? lastLAltKeyEvent;
|
||||
RawKeyEvent? lastRAltKeyEvent;
|
||||
RawKeyEvent? lastLCommandKeyEvent;
|
||||
RawKeyEvent? lastRCommandKeyEvent;
|
||||
RawKeyEvent? lastSuperKeyEvent;
|
||||
|
||||
reset() {
|
||||
lastLShiftKeyEvent = null;
|
||||
lastRShiftKeyEvent = null;
|
||||
lastLCtrlKeyEvent = null;
|
||||
lastRCtrlKeyEvent = null;
|
||||
lastLAltKeyEvent = null;
|
||||
lastRAltKeyEvent = null;
|
||||
lastLCommandKeyEvent = null;
|
||||
lastRCommandKeyEvent = null;
|
||||
lastSuperKeyEvent = null;
|
||||
}
|
||||
|
||||
updateKeyDown(LogicalKeyboardKey logicKey, RawKeyDownEvent e) {
|
||||
if (e.isAltPressed) {
|
||||
if (logicKey == LogicalKeyboardKey.altLeft) {
|
||||
lastLAltKeyEvent = e;
|
||||
} else if (logicKey == LogicalKeyboardKey.altRight) {
|
||||
lastRAltKeyEvent = e;
|
||||
}
|
||||
} else if (e.isControlPressed) {
|
||||
if (logicKey == LogicalKeyboardKey.controlLeft) {
|
||||
lastLCtrlKeyEvent = e;
|
||||
} else if (logicKey == LogicalKeyboardKey.controlRight) {
|
||||
lastRCtrlKeyEvent = e;
|
||||
}
|
||||
} else if (e.isShiftPressed) {
|
||||
if (logicKey == LogicalKeyboardKey.shiftLeft) {
|
||||
lastLShiftKeyEvent = e;
|
||||
} else if (logicKey == LogicalKeyboardKey.shiftRight) {
|
||||
lastRShiftKeyEvent = e;
|
||||
}
|
||||
} else if (e.isMetaPressed) {
|
||||
if (logicKey == LogicalKeyboardKey.metaLeft) {
|
||||
lastLCommandKeyEvent = e;
|
||||
} else if (logicKey == LogicalKeyboardKey.metaRight) {
|
||||
lastRCommandKeyEvent = e;
|
||||
} else if (logicKey == LogicalKeyboardKey.superKey) {
|
||||
lastSuperKeyEvent = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateKeyUp(LogicalKeyboardKey logicKey, RawKeyUpEvent e) {
|
||||
if (e.isAltPressed) {
|
||||
if (logicKey == LogicalKeyboardKey.altLeft) {
|
||||
lastLAltKeyEvent = null;
|
||||
} else if (logicKey == LogicalKeyboardKey.altRight) {
|
||||
lastRAltKeyEvent = null;
|
||||
}
|
||||
} else if (e.isControlPressed) {
|
||||
if (logicKey == LogicalKeyboardKey.controlLeft) {
|
||||
lastLCtrlKeyEvent = null;
|
||||
} else if (logicKey == LogicalKeyboardKey.controlRight) {
|
||||
lastRCtrlKeyEvent = null;
|
||||
}
|
||||
} else if (e.isShiftPressed) {
|
||||
if (logicKey == LogicalKeyboardKey.shiftLeft) {
|
||||
lastLShiftKeyEvent = null;
|
||||
} else if (logicKey == LogicalKeyboardKey.shiftRight) {
|
||||
lastRShiftKeyEvent = null;
|
||||
}
|
||||
} else if (e.isMetaPressed) {
|
||||
if (logicKey == LogicalKeyboardKey.metaLeft) {
|
||||
lastLCommandKeyEvent = null;
|
||||
} else if (logicKey == LogicalKeyboardKey.metaRight) {
|
||||
lastRCommandKeyEvent = null;
|
||||
} else if (logicKey == LogicalKeyboardKey.superKey) {
|
||||
lastSuperKeyEvent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
release(KeyEventResult Function(RawKeyEvent e) handleRawKeyEvent) {
|
||||
for (final key in [
|
||||
lastLShiftKeyEvent,
|
||||
lastRShiftKeyEvent,
|
||||
lastLCtrlKeyEvent,
|
||||
lastRCtrlKeyEvent,
|
||||
lastLAltKeyEvent,
|
||||
lastRAltKeyEvent,
|
||||
lastLCommandKeyEvent,
|
||||
lastRCommandKeyEvent,
|
||||
lastSuperKeyEvent,
|
||||
]) {
|
||||
if (key != null) {
|
||||
handleRawKeyEvent(RawKeyUpEvent(
|
||||
data: key.data,
|
||||
character: key.character,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class InputModel {
|
||||
final WeakReference<FFI> parent;
|
||||
String keyboardMode = "legacy";
|
||||
String keyboardMode = '';
|
||||
|
||||
// keyboard
|
||||
var shift = false;
|
||||
@ -63,6 +167,8 @@ class InputModel {
|
||||
var alt = false;
|
||||
var command = false;
|
||||
|
||||
final ToReleaseKeys toReleaseKeys = ToReleaseKeys();
|
||||
|
||||
// trackpad
|
||||
var _trackpadLastDelta = Offset.zero;
|
||||
var _stopFling = true;
|
||||
@ -88,18 +194,29 @@ class InputModel {
|
||||
|
||||
InputModel(this.parent) {
|
||||
sessionId = parent.target!.sessionId;
|
||||
|
||||
// It is ok to call updateKeyboardMode() directly.
|
||||
// Because `bind` is initialized in `PlatformFFI.init()` which is called very early.
|
||||
// But we still wrap it in a Future.delayed() to make it more clear.
|
||||
Future.delayed(Duration(milliseconds: 100), () {
|
||||
updateKeyboardMode();
|
||||
});
|
||||
}
|
||||
|
||||
KeyEventResult handleRawKeyEvent(FocusNode data, RawKeyEvent e) {
|
||||
if (isDesktop && !stateGlobal.grabKeyboard) {
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
|
||||
updateKeyboardMode() async {
|
||||
// * Currently mobile does not enable map mode
|
||||
if (isDesktop) {
|
||||
bind.sessionGetKeyboardMode(sessionId: sessionId).then((result) {
|
||||
keyboardMode = result.toString();
|
||||
});
|
||||
if (keyboardMode.isEmpty) {
|
||||
keyboardMode =
|
||||
await bind.sessionGetKeyboardMode(sessionId: sessionId) ??
|
||||
kKeyLegacyMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KeyEventResult handleRawKeyEvent(RawKeyEvent e) {
|
||||
if (isDesktop && !isInputSourceFlutter) {
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
|
||||
final key = e.logicalKey;
|
||||
@ -115,6 +232,7 @@ class InputModel {
|
||||
command = true;
|
||||
}
|
||||
}
|
||||
toReleaseKeys.updateKeyDown(key, e);
|
||||
}
|
||||
if (e is RawKeyUpEvent) {
|
||||
if (key == LogicalKeyboardKey.altLeft ||
|
||||
@ -131,6 +249,8 @@ class InputModel {
|
||||
key == LogicalKeyboardKey.superKey) {
|
||||
command = false;
|
||||
}
|
||||
|
||||
toReleaseKeys.updateKeyUp(key, e);
|
||||
}
|
||||
|
||||
// * Currently mobile does not enable map mode
|
||||
@ -320,12 +440,16 @@ class InputModel {
|
||||
}
|
||||
|
||||
void enterOrLeave(bool enter) {
|
||||
toReleaseKeys.release(handleRawKeyEvent);
|
||||
|
||||
// Fix status
|
||||
if (!enter) {
|
||||
resetModifiers();
|
||||
}
|
||||
_flingTimer?.cancel();
|
||||
bind.sessionEnterOrLeave(sessionId: sessionId, enter: enter);
|
||||
if (!isInputSourceFlutter) {
|
||||
bind.sessionEnterOrLeave(sessionId: sessionId, enter: enter);
|
||||
}
|
||||
}
|
||||
|
||||
/// Send mouse movement event with distance in [x] and [y].
|
||||
@ -396,7 +520,8 @@ class InputModel {
|
||||
}
|
||||
if (x != 0 || y != 0) {
|
||||
if (peerPlatform == kPeerPlatformAndroid) {
|
||||
handlePointerEvent('touch', 'pan_update', Offset(x.toDouble(), y.toDouble()));
|
||||
handlePointerEvent(
|
||||
'touch', 'pan_update', Offset(x.toDouble(), y.toDouble()));
|
||||
} else {
|
||||
bind.sessionSendMouse(
|
||||
sessionId: sessionId,
|
||||
|
@ -735,17 +735,9 @@ class FfiModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
checkDesktopKeyboardMode() async {
|
||||
final curMode = await bind.sessionGetKeyboardMode(sessionId: sessionId);
|
||||
if (curMode != null) {
|
||||
if (bind.sessionIsKeyboardModeSupported(
|
||||
sessionId: sessionId, mode: curMode)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If current keyboard mode is not supported, change to another one.
|
||||
|
||||
if (stateGlobal.grabKeyboard) {
|
||||
if (isInputSourceFlutter) {
|
||||
// Local side, flutter keyboard input source
|
||||
// Currently only map mode is supported, legacy mode is used for compatibility.
|
||||
for (final mode in [kKeyMapMode, kKeyLegacyMode]) {
|
||||
if (bind.sessionIsKeyboardModeSupported(
|
||||
sessionId: sessionId, mode: mode)) {
|
||||
@ -754,6 +746,15 @@ class FfiModel with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final curMode = await bind.sessionGetKeyboardMode(sessionId: sessionId);
|
||||
if (curMode != null) {
|
||||
if (bind.sessionIsKeyboardModeSupported(
|
||||
sessionId: sessionId, mode: curMode)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If current keyboard mode is not supported, change to another one.
|
||||
for (final mode in [kKeyMapMode, kKeyTranslateMode, kKeyLegacyMode]) {
|
||||
if (bind.sessionIsKeyboardModeSupported(
|
||||
sessionId: sessionId, mode: mode)) {
|
||||
|
@ -153,10 +153,10 @@ class PlatformFFI {
|
||||
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
||||
name = '${androidInfo.brand}-${androidInfo.model}';
|
||||
id = androidInfo.id.hashCode.toString();
|
||||
androidVersion = androidInfo.version.sdkInt ?? 0;
|
||||
androidVersion = androidInfo.version.sdkInt;
|
||||
} else if (Platform.isIOS) {
|
||||
IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
|
||||
name = iosInfo.utsname.machine ?? '';
|
||||
name = iosInfo.utsname.machine;
|
||||
id = iosInfo.identifierForVendor.hashCode.toString();
|
||||
} else if (Platform.isLinux) {
|
||||
LinuxDeviceInfo linuxInfo = await deviceInfo.linuxInfo;
|
||||
|
@ -2,15 +2,16 @@ import 'dart:io';
|
||||
|
||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hbb/common.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../consts.dart';
|
||||
import './platform_model.dart';
|
||||
|
||||
enum SvcStatus { notReady, connecting, ready }
|
||||
|
||||
class StateGlobal {
|
||||
int _windowId = -1;
|
||||
bool grabKeyboard = false;
|
||||
final RxBool _fullscreen = false.obs;
|
||||
bool _isMinimized = false;
|
||||
final RxBool isMaximized = false.obs;
|
||||
@ -22,6 +23,8 @@ class StateGlobal {
|
||||
// Only used for macOS
|
||||
bool? closeOnFullscreen;
|
||||
|
||||
String _inputSource = '';
|
||||
|
||||
// Use for desktop -> remote toolbar -> resolution
|
||||
final Map<String, Map<int, String?>> _lastResolutionGroupValues = {};
|
||||
|
||||
@ -94,6 +97,18 @@ class StateGlobal {
|
||||
}
|
||||
}
|
||||
|
||||
String getInputSource({bool force = false}) {
|
||||
if (force || _inputSource.isEmpty) {
|
||||
_inputSource = bind.mainGetInputSource();
|
||||
}
|
||||
return _inputSource;
|
||||
}
|
||||
|
||||
setInputSource(SessionID sessionId, String v) async {
|
||||
await bind.mainSetInputSource(sessionId: sessionId, value: v);
|
||||
_inputSource = bind.mainGetInputSource();
|
||||
}
|
||||
|
||||
StateGlobal._();
|
||||
|
||||
static final StateGlobal instance = StateGlobal._();
|
||||
|
@ -1,5 +1,3 @@
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::common::get_default_sound_input;
|
||||
use crate::{
|
||||
client::file_trait::FileManager,
|
||||
common::is_keyboard_mode_supported,
|
||||
@ -8,6 +6,11 @@ use crate::{
|
||||
input::*,
|
||||
ui_interface::{self, *},
|
||||
};
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::{
|
||||
common::get_default_sound_input,
|
||||
keyboard::input_source::{change_input_source, get_cur_session_input_source},
|
||||
};
|
||||
use flutter_rust_bridge::{StreamSink, SyncReturn};
|
||||
#[cfg(feature = "plugin_framework")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
@ -857,6 +860,19 @@ pub fn main_set_local_option(key: String, value: String) {
|
||||
set_local_option(key, value)
|
||||
}
|
||||
|
||||
pub fn main_get_input_source() -> SyncReturn<String> {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
let input_source = get_cur_session_input_source();
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
let input_source = "".to_owned();
|
||||
SyncReturn(input_source)
|
||||
}
|
||||
|
||||
pub fn main_set_input_source(session_id: SessionID, value: String) {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
change_input_source(session_id, value);
|
||||
}
|
||||
|
||||
pub fn main_get_my_id() -> String {
|
||||
get_id()
|
||||
}
|
||||
@ -1593,16 +1609,10 @@ pub fn main_is_installed() -> SyncReturn<bool> {
|
||||
SyncReturn(is_installed())
|
||||
}
|
||||
|
||||
pub fn main_start_grab_keyboard() -> SyncReturn<bool> {
|
||||
#[cfg(target_os = "linux")]
|
||||
if !crate::platform::linux::is_x11() {
|
||||
return SyncReturn(false);
|
||||
}
|
||||
crate::keyboard::client::start_grab_loop();
|
||||
if !is_can_input_monitoring(false) {
|
||||
return SyncReturn(false);
|
||||
}
|
||||
SyncReturn(true)
|
||||
pub fn main_init_input_source() -> SyncReturn<()> {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
crate::keyboard::input_source::init_input_source();
|
||||
SyncReturn(())
|
||||
}
|
||||
|
||||
pub fn main_is_installed_lower_version() -> SyncReturn<bool> {
|
||||
@ -1979,6 +1989,20 @@ pub fn main_supported_privacy_mode_impls() -> SyncReturn<String> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn main_supported_input_source() -> SyncReturn<String> {
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
{
|
||||
SyncReturn("".to_owned())
|
||||
}
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
{
|
||||
SyncReturn(
|
||||
serde_json::to_string(&crate::keyboard::input_source::get_supported_input_source())
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub mod server_side {
|
||||
use hbb_common::{config, log};
|
||||
|
127
src/keyboard.rs
127
src/keyboard.rs
@ -12,7 +12,7 @@ use hbb_common::message_proto::*;
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
use rdev::KeyCode;
|
||||
use rdev::{Event, EventType, Key};
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
@ -34,6 +34,9 @@ const OS_LOWER_ANDROID: &str = "android";
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
static KEYBOARD_HOOKED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
static IS_RDEV_ENABLED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref TO_RELEASE: Arc<Mutex<HashMap<Key, Event>>> = Arc::new(Mutex::new(HashMap::new()));
|
||||
static ref MODIFIERS_STATE: Mutex<HashMap<Key, bool>> = {
|
||||
@ -52,6 +55,7 @@ lazy_static::lazy_static! {
|
||||
|
||||
pub mod client {
|
||||
use super::*;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref IS_GRAB_STARTED: Arc<Mutex<bool>> = Arc::new(Mutex::new(false));
|
||||
}
|
||||
@ -67,6 +71,9 @@ pub mod client {
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub fn change_grab_status(state: GrabState, keyboard_mode: &str) {
|
||||
if !IS_RDEV_ENABLED.load(Ordering::SeqCst) {
|
||||
return;
|
||||
}
|
||||
match state {
|
||||
GrabState::Ready => {}
|
||||
GrabState::Run => {
|
||||
@ -90,10 +97,7 @@ pub mod client {
|
||||
#[cfg(target_os = "linux")]
|
||||
rdev::disable_grab();
|
||||
}
|
||||
GrabState::Exit => {
|
||||
#[cfg(target_os = "linux")]
|
||||
rdev::exit_grab_listen();
|
||||
}
|
||||
GrabState::Exit => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,7 +247,7 @@ fn get_keyboard_mode() -> String {
|
||||
"legacy".to_string()
|
||||
}
|
||||
|
||||
pub fn start_grab_loop() {
|
||||
fn start_grab_loop() {
|
||||
std::env::set_var("KEYBOARD_ONLY", "y");
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
std::thread::spawn(move || {
|
||||
@ -327,6 +331,16 @@ pub fn start_grab_loop() {
|
||||
};
|
||||
}
|
||||
|
||||
// #[allow(dead_code)] is ok here. No need to stop grabbing loop.
|
||||
#[allow(dead_code)]
|
||||
fn stop_grab_loop() -> Result<(), rdev::GrabError> {
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
rdev::exit_grab()?;
|
||||
#[cfg(target_os = "linux")]
|
||||
rdev::exit_grab_listen();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_long_press(event: &Event) -> bool {
|
||||
let keys = MODIFIERS_STATE.lock().unwrap();
|
||||
match event.event_type {
|
||||
@ -1076,3 +1090,104 @@ pub fn keycode_to_rdev_key(keycode: u32) -> Key {
|
||||
#[cfg(target_os = "macos")]
|
||||
return rdev::macos_key_from_code(keycode.try_into().unwrap_or_default());
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub mod input_source {
|
||||
#[cfg(target_os = "macos")]
|
||||
use hbb_common::log;
|
||||
use hbb_common::SessionID;
|
||||
|
||||
use crate::ui_interface::{get_local_option, set_local_option};
|
||||
|
||||
pub const CONFIG_OPTION_INPUT_SOURCE: &str = "input-source";
|
||||
// rdev grab mode
|
||||
pub const CONFIG_INPUT_SOURCE_1: &str = "Input source 1";
|
||||
pub const CONFIG_INPUT_SOURCE_1_TIP: &str = "input_source_1_tip";
|
||||
// flutter grab mode
|
||||
pub const CONFIG_INPUT_SOURCE_2: &str = "Input source 2";
|
||||
pub const CONFIG_INPUT_SOURCE_2_TIP: &str = "input_source_2_tip";
|
||||
|
||||
pub const CONFIG_INPUT_SOURCE_DEFAULT: &str = CONFIG_INPUT_SOURCE_1;
|
||||
|
||||
pub fn init_input_source() {
|
||||
#[cfg(target_os = "linux")]
|
||||
if !crate::platform::linux::is_x11() {
|
||||
// If switching from X11 to Wayland, the grab loop will not be started.
|
||||
// Do not change the config here.
|
||||
return;
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
if !crate::platform::macos::is_can_input_monitoring(false) {
|
||||
log::error!("init_input_source, is_can_input_monitoring() false");
|
||||
set_local_option(
|
||||
CONFIG_OPTION_INPUT_SOURCE.to_string(),
|
||||
CONFIG_INPUT_SOURCE_2.to_string(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
let cur_input_source = get_cur_session_input_source();
|
||||
if cur_input_source == CONFIG_INPUT_SOURCE_1 {
|
||||
super::IS_RDEV_ENABLED.store(true, super::Ordering::SeqCst);
|
||||
}
|
||||
super::client::start_grab_loop();
|
||||
}
|
||||
|
||||
pub fn change_input_source(session_id: SessionID, input_source: String) {
|
||||
let cur_input_source = get_cur_session_input_source();
|
||||
if cur_input_source == input_source {
|
||||
return;
|
||||
}
|
||||
if input_source == CONFIG_INPUT_SOURCE_1 {
|
||||
#[cfg(target_os = "macos")]
|
||||
if !crate::platform::macos::is_can_input_monitoring(false) {
|
||||
log::error!("change_input_source, is_can_input_monitoring() false");
|
||||
return;
|
||||
}
|
||||
// It is ok to start grab loop multiple times.
|
||||
super::client::start_grab_loop();
|
||||
super::IS_RDEV_ENABLED.store(true, super::Ordering::SeqCst);
|
||||
crate::flutter_ffi::session_enter_or_leave(session_id, true);
|
||||
} else if input_source == CONFIG_INPUT_SOURCE_2 {
|
||||
// No need to stop grab loop.
|
||||
crate::flutter_ffi::session_enter_or_leave(session_id, false);
|
||||
super::IS_RDEV_ENABLED.store(false, super::Ordering::SeqCst);
|
||||
}
|
||||
set_local_option(CONFIG_OPTION_INPUT_SOURCE.to_string(), input_source);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_cur_session_input_source() -> String {
|
||||
#[cfg(target_os = "linux")]
|
||||
if !crate::platform::linux::is_x11() {
|
||||
return CONFIG_INPUT_SOURCE_2.to_string();
|
||||
}
|
||||
let input_source = get_local_option(CONFIG_OPTION_INPUT_SOURCE.to_string());
|
||||
if input_source.is_empty() {
|
||||
CONFIG_INPUT_SOURCE_DEFAULT.to_string()
|
||||
} else {
|
||||
input_source
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_supported_input_source() -> Vec<(String, String)> {
|
||||
#[cfg(target_os = "linux")]
|
||||
if !crate::platform::linux::is_x11() {
|
||||
return vec![(
|
||||
CONFIG_INPUT_SOURCE_2.to_string(),
|
||||
CONFIG_INPUT_SOURCE_2_TIP.to_string(),
|
||||
)];
|
||||
}
|
||||
vec![
|
||||
(
|
||||
CONFIG_INPUT_SOURCE_1.to_string(),
|
||||
CONFIG_INPUT_SOURCE_1_TIP.to_string(),
|
||||
),
|
||||
(
|
||||
CONFIG_INPUT_SOURCE_2.to_string(),
|
||||
CONFIG_INPUT_SOURCE_2_TIP.to_string(),
|
||||
),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", "进入隐私模式"),
|
||||
("Exit privacy mode", "退出隐私模式"),
|
||||
("idd_not_support_under_win10_2004_tip", "不支持 Indirect display driver 。需要 windows 10, version 2004 及更高的版本。"),
|
||||
("input_source_1_tip", "输入源 1"),
|
||||
("input_source_2_tip", "输入源 2"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", "Vstup do režimu soukromí"),
|
||||
("Exit privacy mode", "Ukončit režim soukromí"),
|
||||
("idd_not_support_under_win10_2004_tip", "Ovladač nepřímého zobrazení není podporován. Je vyžadován systém Windows 10, verze 2004 nebo novější."),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", "Datenschutzmodus aktivieren"),
|
||||
("Exit privacy mode", "Datenschutzmodus beenden"),
|
||||
("idd_not_support_under_win10_2004_tip", "Indirekter Grafiktreiber wird nicht unterstützt. Windows 10, Version 2004 oder neuer ist erforderlich."),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -206,5 +206,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("privacy_mode_impl_mag_tip", "Mode 1"),
|
||||
("privacy_mode_impl_virtual_display_tip", "Mode 2"),
|
||||
("idd_not_support_under_win10_2004_tip", "Indirect display driver is not supported. Windows 10, version 2004 or newer is required."),
|
||||
("input_source_1_tip", "Input source 1"),
|
||||
("input_source_2_tip", "Input source 2"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", "Entrar al modo privado"),
|
||||
("Exit privacy mode", "Salir del modo privado"),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", "Masuk mode privasi"),
|
||||
("Exit privacy mode", "Keluar mode privasi"),
|
||||
("idd_not_support_under_win10_2004_tip", "Driver grafis yang Anda gunakan tidak kompatibel dengan versi Windows Anda dan memerlukan Windows 10 versi 2004 atau yang lebih baru"),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", "Entra in modalità privacy"),
|
||||
("Exit privacy mode", "Esci dalla modalità privacy"),
|
||||
("idd_not_support_under_win10_2004_tip", "Il driver video indiretto non è supportato. È richiesto Windows 10, versione 2004 o successiva."),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", "개인정보 보호 모드 사용"),
|
||||
("Exit privacy mode", "개인정보 보호 모드 종료"),
|
||||
("idd_not_support_under_win10_2004_tip", "간접 디스플레이 드라이버는 지원되지 않습니다. Windows 10 버전 2004 이상이 필요합니다."),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", "Ieiet privātuma režīmā"),
|
||||
("Exit privacy mode", "Iziet no privātuma režīma"),
|
||||
("idd_not_support_under_win10_2004_tip", "Netiešā displeja draiveris netiek atbalstīts. Nepieciešama operētājsistēma Windows 10, versija 2004 vai jaunāka."),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", "Wejdź w tryb prywatności"),
|
||||
("Exit privacy mode", "Wyjdź z trybu prywatności"),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", "Включить режим конфиденциальности"),
|
||||
("Exit privacy mode", "Отключить режим конфиденциальности"),
|
||||
("idd_not_support_under_win10_2004_tip", "Драйвер непрямого отображения не поддерживается. Требуется Windows 10 версии 2004 или новее."),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", "Vstup do režimu súkromia"),
|
||||
("Exit privacy mode", "Ukončiť režim súkromia"),
|
||||
("idd_not_support_under_win10_2004_tip", "Ovládač nepriameho zobrazenia nie je podporovaný. Vyžaduje sa systém Windows 10, verzia 2004 alebo novšia."),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", "Увійти в режим конфіденційності"),
|
||||
("Exit privacy mode", "Вийти з режиму конфіденційності"),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter privacy mode", ""),
|
||||
("Exit privacy mode", ""),
|
||||
("idd_not_support_under_win10_2004_tip", ""),
|
||||
("input_source_1_tip", ""),
|
||||
("input_source_2_tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -5,8 +5,6 @@ use crate::{
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use rdev::{Event, EventType::*, KeyCode};
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ops::{Deref, DerefMut},
|
||||
@ -43,9 +41,6 @@ use crate::common::GrabState;
|
||||
use crate::keyboard;
|
||||
use crate::{client::Data, client::Interface};
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub static IS_IN: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
const CHANGE_RESOLUTION_VALID_TIMEOUT_SECS: u64 = 15;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
@ -725,13 +720,11 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub fn enter(&self, keyboard_mode: String) {
|
||||
IS_IN.store(true, Ordering::SeqCst);
|
||||
keyboard::client::change_grab_status(GrabState::Run, &keyboard_mode);
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub fn leave(&self, keyboard_mode: String) {
|
||||
IS_IN.store(false, Ordering::SeqCst);
|
||||
keyboard::client::change_grab_status(GrabState::Wait, &keyboard_mode);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user