Merge branch 'master' of https://github.com/rustdesk/rustdesk into android_start_on_boot
This commit is contained in:
commit
761203e778
14
.github/workflows/flutter-ci.yml
vendored
14
.github/workflows/flutter-ci.yml
vendored
@ -18,7 +18,7 @@ on:
|
||||
|
||||
env:
|
||||
LLVM_VERSION: "15.0.6"
|
||||
FLUTTER_VERSION: "3.7.0"
|
||||
FLUTTER_VERSION: "3.7.5"
|
||||
# vcpkg version: 2022.05.10
|
||||
# for multiarch gcc compatibility
|
||||
VCPKG_COMMIT_ID: "14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44"
|
||||
@ -260,7 +260,7 @@ jobs:
|
||||
job:
|
||||
- {
|
||||
target: x86_64-unknown-linux-gnu,
|
||||
os: ubuntu-18.04,
|
||||
os: ubuntu-20.04,
|
||||
extra-build-args: "",
|
||||
}
|
||||
steps:
|
||||
@ -330,13 +330,13 @@ jobs:
|
||||
- {
|
||||
arch: x86_64,
|
||||
target: aarch64-linux-android,
|
||||
os: ubuntu-18.04,
|
||||
os: ubuntu-20.04,
|
||||
extra-build-features: "",
|
||||
}
|
||||
# - {
|
||||
# arch: x86_64,
|
||||
# target: armv7-linux-androideabi,
|
||||
# os: ubuntu-18.04,
|
||||
# os: ubuntu-20.04,
|
||||
# extra-build-features: "",
|
||||
# }
|
||||
steps:
|
||||
@ -907,19 +907,19 @@ jobs:
|
||||
- {
|
||||
arch: x86_64,
|
||||
target: x86_64-unknown-linux-gnu,
|
||||
os: ubuntu-18.04,
|
||||
os: ubuntu-20.04,
|
||||
extra-build-features: "",
|
||||
}
|
||||
- {
|
||||
arch: x86_64,
|
||||
target: x86_64-unknown-linux-gnu,
|
||||
os: ubuntu-18.04,
|
||||
os: ubuntu-20.04,
|
||||
extra-build-features: "flatpak",
|
||||
}
|
||||
- {
|
||||
arch: x86_64,
|
||||
target: x86_64-unknown-linux-gnu,
|
||||
os: ubuntu-18.04,
|
||||
os: ubuntu-20.04,
|
||||
extra-build-features: "appimage",
|
||||
}
|
||||
# - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
|
||||
|
6
.github/workflows/flutter-nightly.yml
vendored
6
.github/workflows/flutter-nightly.yml
vendored
@ -732,7 +732,7 @@ jobs:
|
||||
x86_64)
|
||||
# no need mock on x86_64
|
||||
export VCPKG_ROOT=/opt/artifacts/vcpkg
|
||||
cargo build --lib --features hwcodec,flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release
|
||||
cargo build --lib --features hwcodec,flutter,${{ matrix.job.extra-build-features }} --release
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -900,7 +900,7 @@ jobs:
|
||||
ln -s /usr/include /vcpkg/installed/arm64-linux/include
|
||||
export VCPKG_ROOT=/vcpkg
|
||||
# disable hwcodec for compilation
|
||||
cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release
|
||||
cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release
|
||||
;;
|
||||
armv7)
|
||||
cp -r /opt/artifacts/vcpkg/installed/lib/* /usr/lib/arm-linux-gnueabihf/
|
||||
@ -910,7 +910,7 @@ jobs:
|
||||
ln -s /usr/include /vcpkg/installed/arm-linux/include
|
||||
export VCPKG_ROOT=/vcpkg
|
||||
# disable hwcodec for compilation
|
||||
cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release
|
||||
cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release
|
||||
;;
|
||||
esac
|
||||
|
||||
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -4656,7 +4656,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rdev"
|
||||
version = "0.5.0-2"
|
||||
source = "git+https://github.com/fufesou/rdev#5b9fb5e42117f44e0ce0fe7cf2bddf270c75f1dc"
|
||||
source = "git+https://github.com/fufesou/rdev#25a99ce71ab42843ad253dd51e6a35e83e87a8a4"
|
||||
dependencies = [
|
||||
"cocoa",
|
||||
"core-foundation 0.9.3",
|
||||
|
5
build.py
5
build.py
@ -315,13 +315,10 @@ def build_flutter_dmg(version, features):
|
||||
# copy dylib
|
||||
system2(
|
||||
"cp target/release/liblibrustdesk.dylib target/release/librustdesk.dylib")
|
||||
# ffi_bindgen_function_refactor()
|
||||
# limitations from flutter rust bridge
|
||||
system2('sed -i "" "s/char \*\*rustdesk_core_main(int \*args_len);//" flutter/macos/Runner/bridge_generated.h')
|
||||
os.chdir('flutter')
|
||||
system2('flutter build macos --release')
|
||||
system2(
|
||||
"create-dmg rustdesk.dmg ./build/macos/Build/Products/Release/RustDesk.app")
|
||||
"create-dmg --volname \"RustDesk Installer\" --window-pos 200 120 --window-size 800 400 --icon-size 100 --app-drop-link 600 185 --icon RustDesk.app 200 190 --hide-extension RustDesk.app rustdesk.dmg ./build/macos/Build/Products/Release/RustDesk.app")
|
||||
os.rename("rustdesk.dmg", f"../rustdesk-{version}.dmg")
|
||||
os.chdir("..")
|
||||
|
||||
|
@ -217,6 +217,9 @@ class MyTheme {
|
||||
tabBarTheme: const TabBarTheme(
|
||||
labelColor: Colors.white70,
|
||||
),
|
||||
scrollbarTheme: ScrollbarThemeData(
|
||||
thumbColor: MaterialStateProperty.all(Colors.grey[500])
|
||||
),
|
||||
splashColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent,
|
||||
splashFactory: isDesktop ? NoSplash.splashFactory : null,
|
||||
|
@ -19,7 +19,7 @@ import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart';
|
||||
import '../../common/widgets/dialog.dart';
|
||||
import '../../common/widgets/login.dart';
|
||||
|
||||
const double _kTabWidth = 235;
|
||||
const double _kTabWidth = 200;
|
||||
const double _kTabHeight = 42;
|
||||
const double _kCardFixedWidth = 540;
|
||||
const double _kCardLeftMargin = 15;
|
||||
|
@ -920,6 +920,7 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
||||
disableClipboard(),
|
||||
lockAfterSessionEnd(),
|
||||
privacyMode(),
|
||||
swapKey(),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -953,12 +954,13 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
||||
|
||||
final canvasModel = widget.ffi.canvasModel;
|
||||
final width = (canvasModel.getDisplayWidth() * canvasModel.scale +
|
||||
canvasModel.windowBorderWidth * 2) *
|
||||
CanvasModel.leftToEdge +
|
||||
CanvasModel.rightToEdge) *
|
||||
scale +
|
||||
magicWidth;
|
||||
final height = (canvasModel.getDisplayHeight() * canvasModel.scale +
|
||||
canvasModel.tabBarHeight +
|
||||
canvasModel.windowBorderWidth * 2) *
|
||||
CanvasModel.topToEdge +
|
||||
CanvasModel.bottomToEdge) *
|
||||
scale +
|
||||
magicHeight;
|
||||
double left = wndRect.left + (wndRect.width - width) / 2;
|
||||
@ -1027,10 +1029,10 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
||||
final canvasModel = widget.ffi.canvasModel;
|
||||
final displayWidth = canvasModel.getDisplayWidth();
|
||||
final displayHeight = canvasModel.getDisplayHeight();
|
||||
final requiredWidth = displayWidth +
|
||||
(canvasModel.tabBarHeight + canvasModel.windowBorderWidth * 2);
|
||||
final requiredHeight = displayHeight +
|
||||
(canvasModel.tabBarHeight + canvasModel.windowBorderWidth * 2);
|
||||
final requiredWidth =
|
||||
CanvasModel.leftToEdge + displayWidth + CanvasModel.rightToEdge;
|
||||
final requiredHeight =
|
||||
CanvasModel.topToEdge + displayHeight + CanvasModel.bottomToEdge;
|
||||
return selfWidth > (requiredWidth * scale) &&
|
||||
selfHeight > (requiredHeight * scale);
|
||||
}
|
||||
@ -1527,6 +1529,23 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
||||
ffi: widget.ffi,
|
||||
child: Text(translate('Privacy mode')));
|
||||
}
|
||||
|
||||
swapKey() {
|
||||
final visible = perms['keyboard'] != false &&
|
||||
((Platform.isMacOS && pi.platform != kPeerPlatformMacOS) ||
|
||||
(!Platform.isMacOS && pi.platform == kPeerPlatformMacOS));
|
||||
if (!visible) return Offstage();
|
||||
final option = 'allow_swap_key';
|
||||
final value = bind.sessionGetToggleOptionSync(id: widget.id, arg: option);
|
||||
return _CheckboxMenuButton(
|
||||
value: value,
|
||||
onChanged: (value) {
|
||||
if (value == null) return;
|
||||
bind.sessionToggleOption(id: widget.id, value: option);
|
||||
},
|
||||
ffi: widget.ffi,
|
||||
child: Text(translate('Swap control-command key')));
|
||||
}
|
||||
}
|
||||
|
||||
class _KeyboardMenu extends StatelessWidget {
|
||||
|
@ -14,6 +14,7 @@ class DesktopScrollWrapper extends StatelessWidget {
|
||||
return ImprovedScrolling(
|
||||
scrollController: scrollController,
|
||||
enableCustomMouseWheelScrolling: true,
|
||||
// enableKeyboardScrolling: true, // strange behavior on mac
|
||||
customMouseWheelScrollConfig: CustomMouseWheelScrollConfig(
|
||||
scrollDuration: kDefaultScrollDuration,
|
||||
scrollCurve: Curves.linearToEaseOut,
|
||||
|
@ -458,10 +458,8 @@ class InputModel {
|
||||
return;
|
||||
}
|
||||
evt['type'] = type;
|
||||
if (isDesktop) {
|
||||
y = y - stateGlobal.tabBarHeight - stateGlobal.windowBorderWidth.value;
|
||||
x -= stateGlobal.windowBorderWidth.value;
|
||||
}
|
||||
y -= CanvasModel.topToEdge;
|
||||
x -= CanvasModel.leftToEdge;
|
||||
final canvasModel = parent.target!.canvasModel;
|
||||
final nearThr = 3;
|
||||
var nearRight = (canvasModel.size.width - x) < nearThr;
|
||||
|
@ -727,12 +727,25 @@ class CanvasModel with ChangeNotifier {
|
||||
double get scrollX => _scrollX;
|
||||
double get scrollY => _scrollY;
|
||||
|
||||
static double get leftToEdge => (isDesktop || isWebDesktop)
|
||||
? windowBorderWidth + kDragToResizeAreaPadding.left
|
||||
: 0;
|
||||
static double get rightToEdge => (isDesktop || isWebDesktop)
|
||||
? windowBorderWidth + kDragToResizeAreaPadding.right
|
||||
: 0;
|
||||
static double get topToEdge => (isDesktop || isWebDesktop)
|
||||
? tabBarHeight + windowBorderWidth + kDragToResizeAreaPadding.top
|
||||
: 0;
|
||||
static double get bottomToEdge => (isDesktop || isWebDesktop)
|
||||
? windowBorderWidth + kDragToResizeAreaPadding.bottom
|
||||
: 0;
|
||||
|
||||
updateViewStyle() async {
|
||||
Size getSize() {
|
||||
final size = MediaQueryData.fromWindow(ui.window).size;
|
||||
// If minimized, w or h may be negative here.
|
||||
double w = size.width - windowBorderWidth * 2;
|
||||
double h = size.height - tabBarHeight - windowBorderWidth * 2;
|
||||
double w = size.width - leftToEdge - rightToEdge;
|
||||
double h = size.height - topToEdge - bottomToEdge;
|
||||
return Size(w < 0 ? 0 : w, h < 0 ? 0 : h);
|
||||
}
|
||||
|
||||
@ -806,10 +819,14 @@ class CanvasModel with ChangeNotifier {
|
||||
return parent.target?.ffiModel.display.height ?? defaultHeight;
|
||||
}
|
||||
|
||||
double get windowBorderWidth => stateGlobal.windowBorderWidth.value;
|
||||
double get tabBarHeight => stateGlobal.tabBarHeight;
|
||||
static double get windowBorderWidth => stateGlobal.windowBorderWidth.value;
|
||||
static double get tabBarHeight => stateGlobal.tabBarHeight;
|
||||
|
||||
moveDesktopMouse(double x, double y) {
|
||||
if (size.width == 0 || size.height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// On mobile platforms, move the canvas with the cursor.
|
||||
final dw = getDisplayWidth() * _scale;
|
||||
final dh = getDisplayHeight() * _scale;
|
||||
|
@ -487,7 +487,7 @@
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
|
@ -217,6 +217,8 @@ pub struct PeerConfig {
|
||||
pub lock_after_session_end: LockAfterSessionEnd,
|
||||
#[serde(flatten)]
|
||||
pub privacy_mode: PrivacyMode,
|
||||
#[serde(flatten)]
|
||||
pub allow_swap_key: AllowSwapKey,
|
||||
#[serde(default)]
|
||||
pub port_forwards: Vec<(i32, String, i32)>,
|
||||
#[serde(default)]
|
||||
@ -1060,6 +1062,8 @@ serde_field_bool!(
|
||||
);
|
||||
serde_field_bool!(PrivacyMode, "privacy_mode", default_privacy_mode);
|
||||
|
||||
serde_field_bool!(AllowSwapKey, "allow_swap_key", default_swap_key);
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||
pub struct LocalConfig {
|
||||
#[serde(default)]
|
||||
|
@ -1230,6 +1230,8 @@ impl LoginConfigHandler {
|
||||
option.block_input = BoolOption::No.into();
|
||||
} else if name == "show-quality-monitor" {
|
||||
config.show_quality_monitor.v = !config.show_quality_monitor.v;
|
||||
} else if name == "allow_swap_key" {
|
||||
config.allow_swap_key.v = !config.allow_swap_key.v;
|
||||
} else {
|
||||
let is_set = self
|
||||
.options
|
||||
@ -1383,6 +1385,8 @@ impl LoginConfigHandler {
|
||||
self.config.disable_clipboard.v
|
||||
} else if name == "show-quality-monitor" {
|
||||
self.config.show_quality_monitor.v
|
||||
} else if name == "allow_swap_key" {
|
||||
self.config.allow_swap_key.v
|
||||
} else {
|
||||
!self.get_option(name).is_empty()
|
||||
}
|
||||
@ -1807,6 +1811,7 @@ pub fn send_mouse(
|
||||
if check_scroll_on_mac(mask, x, y) {
|
||||
mouse_event.modifiers.push(ControlKey::Scroll.into());
|
||||
}
|
||||
interface.swap_modifier_mouse(&mut mouse_event);
|
||||
msg_out.set_mouse_event(mouse_event);
|
||||
interface.send(Data::Message(msg_out));
|
||||
}
|
||||
@ -2033,6 +2038,7 @@ pub trait Interface: Send + Clone + 'static + Sized {
|
||||
fn is_force_relay(&self) -> bool {
|
||||
self.get_login_config_handler().read().unwrap().force_relay
|
||||
}
|
||||
fn swap_modifier_mouse(&self, _msg : &mut hbb_common::protos::message::MouseEvent) {}
|
||||
}
|
||||
|
||||
/// Data used by the client interface.
|
||||
|
@ -39,8 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("verification_tip", "A new device has been detected, and a verification code has been sent to the registered email address, enter the verification code to continue logging in."),
|
||||
("software_render_tip", "If you have an Nvidia graphics card and the remote window closes immediately after connecting, installing the nouveau driver and choosing to use software rendering may help. A software restart is required."),
|
||||
("config_input", "In order to control remote desktop with keyboard, you need to grant RustDesk \"Input Monitoring\" permissions."),
|
||||
("request_elevation_tip","You can also request elevation if there is someone on the remote side."),
|
||||
("wait_accept_uac_tip","Please wait for the remote user to accept the UAC dialog."),
|
||||
("request_elevation_tip", "You can also request elevation if there is someone on the remote side."),
|
||||
("wait_accept_uac_tip", "Please wait for the remote user to accept the UAC dialog."),
|
||||
("still_click_uac_tip", "Still requires the remote user to click OK on the UAC window of running RustDesk."),
|
||||
("config_microphone", "In order to speak remotely, you need to grant RustDesk \"Record Audio\" permissions."),
|
||||
("relay_hint_tip", "It may not be possible to connect directly, you can try to connect via relay. \nIn addition, if you want to use relay on your first try, you can add the \"/r\" suffix to the ID, or select the option \"Always connect via relay\" in the peer card."),
|
||||
|
@ -458,6 +458,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Reconnect", "Reconectar"),
|
||||
("Codec", "Códec"),
|
||||
("Resolution", "Resolución"),
|
||||
("No transfers in progress", ""),
|
||||
("No transfers in progress", "No hay transferencias en curso"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -456,8 +456,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Stop voice call", "توقف تماس صوتی"),
|
||||
("relay_hint_tip", " را به شناسه اضافه کنید یا گزینه \"همیشه از طریق رله متصل شوید\" را در کارت همتا انتخاب کنید. همچنین، اگر میخواهید فوراً از سرور رله استفاده کنید، میتوانید پسوند \"/r\".\n اتصال مستقیم ممکن است امکان پذیر نباشد. در این صورت می توانید سعی کنید از طریق سرور رله متصل شوید"),
|
||||
("Reconnect", "اتصال مجدد"),
|
||||
("Codec", ""),
|
||||
("Resolution", ""),
|
||||
("No transfers in progress", ""),
|
||||
("Codec", "کدک"),
|
||||
("Resolution", "وضوح"),
|
||||
("No transfers in progress", "هیچ انتقالی در حال انجام نیست"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -198,6 +198,7 @@ class Header: Reactor.Component {
|
||||
{keyboard_enabled && clipboard_enabled ? <li #disable-clipboard .toggle-option><span>{svg_checkmark}</span>{translate('Disable clipboard')}</li> : ""}
|
||||
{keyboard_enabled ? <li #lock-after-session-end .toggle-option><span>{svg_checkmark}</span>{translate('Lock after session end')}</li> : ""}
|
||||
{keyboard_enabled && pi.platform == "Windows" ? <li #privacy-mode><span>{svg_checkmark}</span>{translate('Privacy mode')}</li> : ""}
|
||||
{keyboard_enabled && ((is_osx && pi.platform != "Mac OS") || (!is_osx && pi.platform == "Mac OS")) ? <li #allow_swap_key .toggle-option><span>{svg_checkmark}</span>{translate('Swap control-command key')}</li> : ""}
|
||||
</menu>
|
||||
</popup>;
|
||||
}
|
||||
@ -440,7 +441,7 @@ function toggleMenuState() {
|
||||
for (var el in $$(menu#keyboard-options>li)) {
|
||||
el.attributes.toggleClass("selected", values.indexOf(el.id) >= 0);
|
||||
}
|
||||
for (var id in ["show-remote-cursor", "show-quality-monitor", "disable-audio", "enable-file-transfer", "disable-clipboard", "lock-after-session-end"]) {
|
||||
for (var id in ["show-remote-cursor", "show-quality-monitor", "disable-audio", "enable-file-transfer", "disable-clipboard", "lock-after-session-end", "allow_swap_key"]) {
|
||||
var el = self.select('#' + id);
|
||||
if (el) {
|
||||
var value = handler.get_toggle_option(id);
|
||||
|
@ -373,10 +373,87 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
return "".to_owned();
|
||||
}
|
||||
|
||||
pub fn swab_modifier_key(&self, msg: &mut KeyEvent) {
|
||||
|
||||
let allow_swap_key = self.get_toggle_option("allow_swap_key".to_string());
|
||||
if allow_swap_key {
|
||||
if let Some(key_event::Union::ControlKey(ck)) = msg.union {
|
||||
let ck = ck.enum_value_or_default();
|
||||
let ck = match ck {
|
||||
ControlKey::Control => ControlKey::Meta,
|
||||
ControlKey::Meta => ControlKey::Control,
|
||||
ControlKey::RControl => ControlKey::Meta,
|
||||
ControlKey::RWin => ControlKey::Control,
|
||||
_ => ck,
|
||||
};
|
||||
msg.set_control_key(ck);
|
||||
}
|
||||
msg.modifiers = msg.modifiers.iter().map(|ck| {
|
||||
let ck = ck.enum_value_or_default();
|
||||
let ck = match ck {
|
||||
ControlKey::Control => ControlKey::Meta,
|
||||
ControlKey::Meta => ControlKey::Control,
|
||||
ControlKey::RControl => ControlKey::Meta,
|
||||
ControlKey::RWin => ControlKey::Control,
|
||||
_ => ck,
|
||||
};
|
||||
hbb_common::protobuf::EnumOrUnknown::new(ck)
|
||||
}).collect();
|
||||
|
||||
|
||||
let code = msg.chr();
|
||||
if code != 0 {
|
||||
let mut peer = self.peer_platform().to_lowercase();
|
||||
peer.retain(|c| !c.is_whitespace());
|
||||
|
||||
let key = match peer.as_str() {
|
||||
"windows" => {
|
||||
let key = rdev::win_key_from_scancode(code);
|
||||
let key = match key {
|
||||
rdev::Key::ControlLeft => rdev::Key::MetaLeft,
|
||||
rdev::Key::MetaLeft => rdev::Key::ControlLeft,
|
||||
rdev::Key::ControlRight => rdev::Key::MetaLeft,
|
||||
rdev::Key::MetaRight => rdev::Key::ControlLeft,
|
||||
_ => key,
|
||||
};
|
||||
rdev::win_scancode_from_key(key).unwrap_or_default()
|
||||
}
|
||||
"macos" => {
|
||||
let key = rdev::macos_key_from_code(code);
|
||||
let key = match key {
|
||||
rdev::Key::ControlLeft => rdev::Key::MetaLeft,
|
||||
rdev::Key::MetaLeft => rdev::Key::ControlLeft,
|
||||
rdev::Key::ControlRight => rdev::Key::MetaLeft,
|
||||
rdev::Key::MetaRight => rdev::Key::ControlLeft,
|
||||
_ => key,
|
||||
};
|
||||
rdev::macos_keycode_from_key(key).unwrap_or_default()
|
||||
}
|
||||
_ => {
|
||||
let key = rdev::linux_key_from_code(code);
|
||||
let key = match key {
|
||||
rdev::Key::ControlLeft => rdev::Key::MetaLeft,
|
||||
rdev::Key::MetaLeft => rdev::Key::ControlLeft,
|
||||
rdev::Key::ControlRight => rdev::Key::MetaLeft,
|
||||
rdev::Key::MetaRight => rdev::Key::ControlLeft,
|
||||
_ => key,
|
||||
};
|
||||
rdev::linux_keycode_from_key(key).unwrap_or_default()
|
||||
}
|
||||
};
|
||||
msg.set_chr(key);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn send_key_event(&self, evt: &KeyEvent) {
|
||||
// mode: legacy(0), map(1), translate(2), auto(3)
|
||||
|
||||
let mut msg = evt.clone();
|
||||
self.swab_modifier_key(&mut msg);
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_key_event(evt.clone());
|
||||
msg_out.set_key_event(msg);
|
||||
self.send(Data::Message(msg_out));
|
||||
}
|
||||
|
||||
@ -934,6 +1011,23 @@ impl<T: InvokeUiSession> Interface for Session<T> {
|
||||
handle_test_delay(t, peer).await;
|
||||
}
|
||||
}
|
||||
|
||||
fn swap_modifier_mouse(&self, msg : &mut hbb_common::protos::message::MouseEvent) {
|
||||
let allow_swap_key = self.get_toggle_option("allow_swap_key".to_string());
|
||||
if allow_swap_key {
|
||||
msg.modifiers = msg.modifiers.iter().map(|ck| {
|
||||
let ck = ck.enum_value_or_default();
|
||||
let ck = match ck {
|
||||
ControlKey::Control => ControlKey::Meta,
|
||||
ControlKey::Meta => ControlKey::Control,
|
||||
ControlKey::RControl => ControlKey::Meta,
|
||||
ControlKey::RWin => ControlKey::Control,
|
||||
_ => ck,
|
||||
};
|
||||
hbb_common::protobuf::EnumOrUnknown::new(ck)
|
||||
}).collect();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InvokeUiSession> Session<T> {
|
||||
|
Loading…
Reference in New Issue
Block a user