diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart
index 4b6cf2a62..67eb0234b 100644
--- a/flutter/lib/desktop/pages/desktop_setting_page.dart
+++ b/flutter/lib/desktop/pages/desktop_setting_page.dart
@@ -278,6 +278,8 @@ class _GeneralState extends State<_General> {
_OptionCheckBox(context, 'Confirm before closing multiple tabs',
'enable-confirm-closing-tabs'),
_OptionCheckBox(context, 'Adaptive Bitrate', 'enable-abr'),
+ if (Platform.isMacOS)
+ _OptionCheckBox(context, 'Swap control-command key', 'allow-swap-key'),
if (Platform.isLinux)
Tooltip(
message: translate('software_render_tip'),
diff --git a/memo.txt b/memo.txt
new file mode 100644
index 000000000..da23ae423
--- /dev/null
+++ b/memo.txt
@@ -0,0 +1,104 @@
+#windows
+python3 res/inline-sciter.py
+cargo build --release --features inline,with_rc --target=aarch64-pc-windows-msvc -vv
+
+Push-Location flutter ; flutter pub get ; Pop-Location
+~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart
+
+%comspec% /k "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsamd64_arm64.bat"
+rustup update
+rustup target add aarch64-pc-windows-msvc
+rustup target list
+
+reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug" /v Auto /t REG_DWORD /d 1 /f
+reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\rustdesk.exe" /v Debugger /t REG_SZ /d "vsjitdebugger.exe" /f
+
+#macos
+pushd flutter && flutter pub get && popd
+~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart
+./build.py --flutter
+codesign --force --options runtime -s "Developer ID Application" --deep ./flutter/build/macos/Build/Products/Release/RustDesk.app -v
+rm -r /Applications/RustDesk.app
+cp -r ./flutter/build/macos/Build/Products/Release/RustDesk.app /Applications/RustDesk.app
+open -n /Applications/RustDesk.app --args --server
+
+cargo bundle --release --features inline
+cp libsciter.dylib target/release/bundle/osx/RustDesk.app/Contents/MacOS
+mv target/release/bundle/osx/RustDesk.app/Contents/Resources/res/* target/release/bundle/osx/RustDesk.app/Contents/Resources
+rm -rf target/release/bundle/osx/RustDesk.app/Contents/Resources/res
+target/release/bundle/osx/RustDesk.app/Contents/Info.plist
+ LSUIElement
+ 1
+
+python3 res/inline-sciter.py
+cargo build --release --features inline
+cp target/release/rustdesk ../Documents/RustDesk.app/Contents/MacOS/rustdesk
+codesign -s "Developer ID Application" --force --options runtime ../Documents/RustDesk.app/Contents/MacOS/*
+codesign -s "Developer ID Application" --force --options runtime ../Documents/RustDesk.app
+rm -r /Applications/RustDesk.app
+cp -r ../Documents/RustDesk.app /Applications/RustDesk.app
+
+csrutil disable
+file target\release\rustdesk
+sudo lsof -i -n -P | grep rustdesk // netstat
+https://github.com/create-dmg/create-dmg
+security find-identity -p basic -v
+
+#android
+BINDGEN_EXTRA_CLANG_ARGS_aarch64_linux_android="--target=arm64-apple-macos --sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" RUST_LOG=debug cargo ndk --platform 21 --target aarch64-linux-android rustc --lib --features flutter --release
+cp target/aarch64-linux-android/release/liblibrustdesk.so flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so
+pushd flutter; flutter build apk --target-platform android-arm64 --release; popd
+adb install flutter/build/app/outputs/flutter-apk/app-release.apk
+
+sudo mount -t drvfs '\\192.168.111.10\Macintosh HD' /mnt/mac
+cp target/aarch64-linux-android/debug/liblibrustdesk.so /mnt/mac/Users/sjpark/rustdesk/flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so
+
+adb logcat | grep LOG_SERVICE
+adb emu kill
+
+sudo apt install build-essential
+sudo apt install gcc-multilib
+
+#ios
+flutter/ios/Runnder.xcworkspace/View/Navigators/Project/targets:Runner/Signing & Capability/Teams
+cargo build --target aarch64-apple-ios --features flutter --release
+pushd flutter; flutter build ios --release; popd
+xcode/Window/Devices and Simulators/INSTALLED APPS
+
+xcrun simctl list
+open -a Simulator --args -CurrentDeviceUDID 5D1C39DD-708B-41D3-B89A-3F0D9B8E42BF
+
+# rustdesk
+cd C:\Users\sjpark\Documents\rustdesk
+set VCPKG_ROOT=C:\Users\sjpark\Documents\vcpkg
+set LIBCLANG_PATH=C:\Program Files\LLVM\bin
+
+# ring
+set path=C:\Program Files\LLVM\bin;C:\Strawberry\perl\bin\;%path%;
+.\target\tools\windows\nasm\nasm.exe
+set RING_PREGENERATE_ASM=1
+
+#dependencies
+ring = { git = "https://github.com/sj6219/ring", branch = "0.16.20_alpha" }
+
+
+adb shell dumpsys package com.carriez.flutter_hbb
+objdump -T ~/rustdesk/target/aarch64-linux-android/release/liblibrustdesk.so
+
+cat /Users/sjpark/Library/Android/sdk/ndk/22.0.7026061/toolchains/llvm/prebuilt/darwin-x86_64/lib64/clang/11.0.5/lib/linux/aarch64/lldb-server | adb shell sh -c 'cat > /data/local/tmp/lldb-server && chmod 755 /data/local/tmp/lldb-server'
+adb shell run-as com.carriez.flutter_hbb mkdir -p /data/data/com.carriez.flutter_hbb/lldb/bin/
+adb shell "cat /data/local/tmp/lldb-server | run-as com.carriez.flutter_hbb sh -c 'cat > /data/data/com.carriez.flutter_hbb/lldb/bin/lldb-server && chmod 755 /data/data/com.carriez.flutter_hbb/lldb/bin/lldb-server'"
+
+adb shell ps -e -o PID -o NAME | grep com.carriez.flutter_hbb
+adb forward tcp:10086 tcp:10086
+adb shell run-as com.carriez.flutter_hbb /data/data/com.carriez.flutter_hbb/lldb/bin/lldb-server platform --listen "*:10086" --server
+
+/Users/sjpark/Library/Android/sdk/ndk/22.0.7026061/toolchains/llvm/prebuilt/darwin-x86_64/bin/lldb
+platform select remote-android
+platform connect connect://localhost:10086
+attach
+b connection.rs:624
+
+add-dsym /Users/sjpark/ndk-samples/hello-gl2/app/build/intermediates/merged_native_libs/debug/out/lib/arm64-v8a/libgl2jni.so
+b gl_code.cpp:151
+
diff --git a/src/flutter.rs b/src/flutter.rs
index 2d7d3fb86..bee585d93 100644
--- a/src/flutter.rs
+++ b/src/flutter.rs
@@ -428,8 +428,10 @@ pub fn session_add(
let session_id = get_session_id(id.to_owned());
LocalConfig::set_remote_id(&session_id);
+ let allow_swap_key = hbb_common::config::Config::get_option("allow-swap-key") == "Y";
let session: Session = Session {
id: session_id.clone(),
+ allow_swap_key,
..Default::default()
};
diff --git a/src/keyboard.rs b/src/keyboard.rs
index 91480ba30..2764a4408 100644
--- a/src/keyboard.rs
+++ b/src/keyboard.rs
@@ -210,6 +210,53 @@ pub fn start_grab_loop() {
if key == Key::CapsLock || key == Key::NumLock {
return Some(event);
}
+ #[cfg(target_os = "macos")]
+ let mut event = event;
+ #[cfg(target_os = "macos")] {
+ let mut allow_swap_key = false;
+ #[cfg(not(any(feature = "flutter", feature = "cli")))]
+ if let Some(session) = CUR_SESSION.lock().unwrap().as_ref() {
+ allow_swap_key = session.allow_swap_key;
+ }
+ #[cfg(feature = "flutter")]
+ if let Some(session) = SESSIONS
+ .read()
+ .unwrap()
+ .get(&*CUR_SESSION_ID.read().unwrap())
+ {
+ allow_swap_key = session.allow_swap_key;
+ }
+ if allow_swap_key {
+ match event.event_type {
+ EventType::KeyPress( key) => {
+ 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,
+ };
+ event.event_type = EventType::KeyPress(key);
+ event.scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default();
+ event.code = event.scan_code as _;
+ }
+ EventType::KeyRelease(key) => {
+ 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,
+ };
+ event.event_type = EventType::KeyRelease(key);
+ event.scan_code = rdev::macos_keycode_from_key(key).unwrap_or_default();
+ event.code = event.scan_code as _;
+ }
+ _ => {}
+ };
+ };
+ };
+
let mut _keyboard_mode = KeyboardMode::Map;
let scan_code = event.scan_code;
diff --git a/src/server/connection.rs b/src/server/connection.rs
index 9ce53c960..17d4e3768 100644
--- a/src/server/connection.rs
+++ b/src/server/connection.rs
@@ -539,6 +539,9 @@ impl Connection {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
fn handle_input(receiver: std_mpsc::Receiver, tx: Sender) {
+ #[cfg(target_os = "macos")]
+ let allow_swap_key = hbb_common::config::Config::get_option("allow-swap-key") == "Y";
+
let mut block_input_mode = false;
#[cfg(target_os = "windows")]
{
@@ -551,9 +554,66 @@ impl Connection {
match receiver.recv_timeout(std::time::Duration::from_millis(500)) {
Ok(v) => match v {
MessageInput::Mouse((msg, id)) => {
+ #[cfg(target_os = "macos")]
+ let msg = {
+ let mut msg = msg;
+ 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();
+ }
+ msg
+ };
+
handle_mouse(&msg, id);
}
MessageInput::Key((mut msg, press)) => {
+ #[cfg(target_os = "macos")]
+ 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 key = rdev::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,
+ };
+ msg.set_chr(rdev::macos_keycode_from_key(key).unwrap_or_default());
+ }
+ }
// todo: press and down have similar meanings.
if press && msg.mode.unwrap() == KeyboardMode::Legacy {
msg.down = true;
diff --git a/src/ui/index.tis b/src/ui/index.tis
index ec2e0a748..20228ea03 100644
--- a/src/ui/index.tis
+++ b/src/ui/index.tis
@@ -214,6 +214,7 @@ class Enhancements: Reactor.Component {
{has_hwcodec ? {svg_checkmark}{translate("Hardware Codec")} (beta) : ""}
{svg_checkmark}{translate("Adaptive Bitrate")} (beta)
{translate("Recording")}
+ {is_osx ? {svg_checkmark}{translate("Swap control-command key")} : "" }
;
}
diff --git a/src/ui/remote.rs b/src/ui/remote.rs
index 999b409e0..2d0d4d2c0 100644
--- a/src/ui/remote.rs
+++ b/src/ui/remote.rs
@@ -443,10 +443,12 @@ impl sciter::EventHandler for SciterSession {
impl SciterSession {
pub fn new(cmd: String, id: String, password: String, args: Vec) -> Self {
+ let allow_swap_key = hbb_common::config::Config::get_option("allow-swap-key") == "Y";
let session: Session = Session {
id: id.clone(),
password: password.clone(),
args,
+ allow_swap_key,
..Default::default()
};
diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs
index dc0e365ab..a0c4f06b0 100644
--- a/src/ui_session_interface.rs
+++ b/src/ui_session_interface.rs
@@ -36,6 +36,7 @@ pub struct Session {
pub sender: Arc>>>,
pub thread: Arc>>>,
pub ui_handler: T,
+ pub allow_swap_key: bool,
}
impl Session {
@@ -505,6 +506,15 @@ impl Session {
shift: bool,
command: bool,
) {
+ #[cfg(target_os = "macos")]
+ let (ctrl, command) =
+ if self.allow_swap_key {
+ (command, ctrl)
+ }
+ else {
+ (ctrl, command)
+ };
+
#[allow(unused_mut)]
let mut command = command;
#[cfg(windows)]