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:
|
env:
|
||||||
LLVM_VERSION: "15.0.6"
|
LLVM_VERSION: "15.0.6"
|
||||||
FLUTTER_VERSION: "3.7.0"
|
FLUTTER_VERSION: "3.7.5"
|
||||||
# vcpkg version: 2022.05.10
|
# vcpkg version: 2022.05.10
|
||||||
# for multiarch gcc compatibility
|
# for multiarch gcc compatibility
|
||||||
VCPKG_COMMIT_ID: "14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44"
|
VCPKG_COMMIT_ID: "14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44"
|
||||||
@ -260,7 +260,7 @@ jobs:
|
|||||||
job:
|
job:
|
||||||
- {
|
- {
|
||||||
target: x86_64-unknown-linux-gnu,
|
target: x86_64-unknown-linux-gnu,
|
||||||
os: ubuntu-18.04,
|
os: ubuntu-20.04,
|
||||||
extra-build-args: "",
|
extra-build-args: "",
|
||||||
}
|
}
|
||||||
steps:
|
steps:
|
||||||
@ -330,13 +330,13 @@ jobs:
|
|||||||
- {
|
- {
|
||||||
arch: x86_64,
|
arch: x86_64,
|
||||||
target: aarch64-linux-android,
|
target: aarch64-linux-android,
|
||||||
os: ubuntu-18.04,
|
os: ubuntu-20.04,
|
||||||
extra-build-features: "",
|
extra-build-features: "",
|
||||||
}
|
}
|
||||||
# - {
|
# - {
|
||||||
# arch: x86_64,
|
# arch: x86_64,
|
||||||
# target: armv7-linux-androideabi,
|
# target: armv7-linux-androideabi,
|
||||||
# os: ubuntu-18.04,
|
# os: ubuntu-20.04,
|
||||||
# extra-build-features: "",
|
# extra-build-features: "",
|
||||||
# }
|
# }
|
||||||
steps:
|
steps:
|
||||||
@ -907,19 +907,19 @@ jobs:
|
|||||||
- {
|
- {
|
||||||
arch: x86_64,
|
arch: x86_64,
|
||||||
target: x86_64-unknown-linux-gnu,
|
target: x86_64-unknown-linux-gnu,
|
||||||
os: ubuntu-18.04,
|
os: ubuntu-20.04,
|
||||||
extra-build-features: "",
|
extra-build-features: "",
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
arch: x86_64,
|
arch: x86_64,
|
||||||
target: x86_64-unknown-linux-gnu,
|
target: x86_64-unknown-linux-gnu,
|
||||||
os: ubuntu-18.04,
|
os: ubuntu-20.04,
|
||||||
extra-build-features: "flatpak",
|
extra-build-features: "flatpak",
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
arch: x86_64,
|
arch: x86_64,
|
||||||
target: x86_64-unknown-linux-gnu,
|
target: x86_64-unknown-linux-gnu,
|
||||||
os: ubuntu-18.04,
|
os: ubuntu-20.04,
|
||||||
extra-build-features: "appimage",
|
extra-build-features: "appimage",
|
||||||
}
|
}
|
||||||
# - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
|
# - { 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)
|
x86_64)
|
||||||
# no need mock on x86_64
|
# no need mock on x86_64
|
||||||
export VCPKG_ROOT=/opt/artifacts/vcpkg
|
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
|
esac
|
||||||
|
|
||||||
@ -900,7 +900,7 @@ jobs:
|
|||||||
ln -s /usr/include /vcpkg/installed/arm64-linux/include
|
ln -s /usr/include /vcpkg/installed/arm64-linux/include
|
||||||
export VCPKG_ROOT=/vcpkg
|
export VCPKG_ROOT=/vcpkg
|
||||||
# disable hwcodec for compilation
|
# 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)
|
armv7)
|
||||||
cp -r /opt/artifacts/vcpkg/installed/lib/* /usr/lib/arm-linux-gnueabihf/
|
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
|
ln -s /usr/include /vcpkg/installed/arm-linux/include
|
||||||
export VCPKG_ROOT=/vcpkg
|
export VCPKG_ROOT=/vcpkg
|
||||||
# disable hwcodec for compilation
|
# 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
|
esac
|
||||||
|
|
||||||
|
|||||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -4656,7 +4656,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "rdev"
|
name = "rdev"
|
||||||
version = "0.5.0-2"
|
version = "0.5.0-2"
|
||||||
source = "git+https://github.com/fufesou/rdev#5b9fb5e42117f44e0ce0fe7cf2bddf270c75f1dc"
|
source = "git+https://github.com/fufesou/rdev#25a99ce71ab42843ad253dd51e6a35e83e87a8a4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cocoa",
|
"cocoa",
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3",
|
||||||
|
|||||||
5
build.py
5
build.py
@ -315,13 +315,10 @@ def build_flutter_dmg(version, features):
|
|||||||
# copy dylib
|
# copy dylib
|
||||||
system2(
|
system2(
|
||||||
"cp target/release/liblibrustdesk.dylib target/release/librustdesk.dylib")
|
"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')
|
os.chdir('flutter')
|
||||||
system2('flutter build macos --release')
|
system2('flutter build macos --release')
|
||||||
system2(
|
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.rename("rustdesk.dmg", f"../rustdesk-{version}.dmg")
|
||||||
os.chdir("..")
|
os.chdir("..")
|
||||||
|
|
||||||
|
|||||||
@ -217,6 +217,9 @@ class MyTheme {
|
|||||||
tabBarTheme: const TabBarTheme(
|
tabBarTheme: const TabBarTheme(
|
||||||
labelColor: Colors.white70,
|
labelColor: Colors.white70,
|
||||||
),
|
),
|
||||||
|
scrollbarTheme: ScrollbarThemeData(
|
||||||
|
thumbColor: MaterialStateProperty.all(Colors.grey[500])
|
||||||
|
),
|
||||||
splashColor: Colors.transparent,
|
splashColor: Colors.transparent,
|
||||||
highlightColor: Colors.transparent,
|
highlightColor: Colors.transparent,
|
||||||
splashFactory: isDesktop ? NoSplash.splashFactory : null,
|
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/dialog.dart';
|
||||||
import '../../common/widgets/login.dart';
|
import '../../common/widgets/login.dart';
|
||||||
|
|
||||||
const double _kTabWidth = 235;
|
const double _kTabWidth = 200;
|
||||||
const double _kTabHeight = 42;
|
const double _kTabHeight = 42;
|
||||||
const double _kCardFixedWidth = 540;
|
const double _kCardFixedWidth = 540;
|
||||||
const double _kCardLeftMargin = 15;
|
const double _kCardLeftMargin = 15;
|
||||||
|
|||||||
@ -920,6 +920,7 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
|||||||
disableClipboard(),
|
disableClipboard(),
|
||||||
lockAfterSessionEnd(),
|
lockAfterSessionEnd(),
|
||||||
privacyMode(),
|
privacyMode(),
|
||||||
|
swapKey(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -953,12 +954,13 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
|||||||
|
|
||||||
final canvasModel = widget.ffi.canvasModel;
|
final canvasModel = widget.ffi.canvasModel;
|
||||||
final width = (canvasModel.getDisplayWidth() * canvasModel.scale +
|
final width = (canvasModel.getDisplayWidth() * canvasModel.scale +
|
||||||
canvasModel.windowBorderWidth * 2) *
|
CanvasModel.leftToEdge +
|
||||||
|
CanvasModel.rightToEdge) *
|
||||||
scale +
|
scale +
|
||||||
magicWidth;
|
magicWidth;
|
||||||
final height = (canvasModel.getDisplayHeight() * canvasModel.scale +
|
final height = (canvasModel.getDisplayHeight() * canvasModel.scale +
|
||||||
canvasModel.tabBarHeight +
|
CanvasModel.topToEdge +
|
||||||
canvasModel.windowBorderWidth * 2) *
|
CanvasModel.bottomToEdge) *
|
||||||
scale +
|
scale +
|
||||||
magicHeight;
|
magicHeight;
|
||||||
double left = wndRect.left + (wndRect.width - width) / 2;
|
double left = wndRect.left + (wndRect.width - width) / 2;
|
||||||
@ -1027,10 +1029,10 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
|||||||
final canvasModel = widget.ffi.canvasModel;
|
final canvasModel = widget.ffi.canvasModel;
|
||||||
final displayWidth = canvasModel.getDisplayWidth();
|
final displayWidth = canvasModel.getDisplayWidth();
|
||||||
final displayHeight = canvasModel.getDisplayHeight();
|
final displayHeight = canvasModel.getDisplayHeight();
|
||||||
final requiredWidth = displayWidth +
|
final requiredWidth =
|
||||||
(canvasModel.tabBarHeight + canvasModel.windowBorderWidth * 2);
|
CanvasModel.leftToEdge + displayWidth + CanvasModel.rightToEdge;
|
||||||
final requiredHeight = displayHeight +
|
final requiredHeight =
|
||||||
(canvasModel.tabBarHeight + canvasModel.windowBorderWidth * 2);
|
CanvasModel.topToEdge + displayHeight + CanvasModel.bottomToEdge;
|
||||||
return selfWidth > (requiredWidth * scale) &&
|
return selfWidth > (requiredWidth * scale) &&
|
||||||
selfHeight > (requiredHeight * scale);
|
selfHeight > (requiredHeight * scale);
|
||||||
}
|
}
|
||||||
@ -1527,6 +1529,23 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
|||||||
ffi: widget.ffi,
|
ffi: widget.ffi,
|
||||||
child: Text(translate('Privacy mode')));
|
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 {
|
class _KeyboardMenu extends StatelessWidget {
|
||||||
|
|||||||
@ -14,6 +14,7 @@ class DesktopScrollWrapper extends StatelessWidget {
|
|||||||
return ImprovedScrolling(
|
return ImprovedScrolling(
|
||||||
scrollController: scrollController,
|
scrollController: scrollController,
|
||||||
enableCustomMouseWheelScrolling: true,
|
enableCustomMouseWheelScrolling: true,
|
||||||
|
// enableKeyboardScrolling: true, // strange behavior on mac
|
||||||
customMouseWheelScrollConfig: CustomMouseWheelScrollConfig(
|
customMouseWheelScrollConfig: CustomMouseWheelScrollConfig(
|
||||||
scrollDuration: kDefaultScrollDuration,
|
scrollDuration: kDefaultScrollDuration,
|
||||||
scrollCurve: Curves.linearToEaseOut,
|
scrollCurve: Curves.linearToEaseOut,
|
||||||
|
|||||||
@ -458,10 +458,8 @@ class InputModel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
evt['type'] = type;
|
evt['type'] = type;
|
||||||
if (isDesktop) {
|
y -= CanvasModel.topToEdge;
|
||||||
y = y - stateGlobal.tabBarHeight - stateGlobal.windowBorderWidth.value;
|
x -= CanvasModel.leftToEdge;
|
||||||
x -= stateGlobal.windowBorderWidth.value;
|
|
||||||
}
|
|
||||||
final canvasModel = parent.target!.canvasModel;
|
final canvasModel = parent.target!.canvasModel;
|
||||||
final nearThr = 3;
|
final nearThr = 3;
|
||||||
var nearRight = (canvasModel.size.width - x) < nearThr;
|
var nearRight = (canvasModel.size.width - x) < nearThr;
|
||||||
|
|||||||
@ -727,12 +727,25 @@ class CanvasModel with ChangeNotifier {
|
|||||||
double get scrollX => _scrollX;
|
double get scrollX => _scrollX;
|
||||||
double get scrollY => _scrollY;
|
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 {
|
updateViewStyle() async {
|
||||||
Size getSize() {
|
Size getSize() {
|
||||||
final size = MediaQueryData.fromWindow(ui.window).size;
|
final size = MediaQueryData.fromWindow(ui.window).size;
|
||||||
// If minimized, w or h may be negative here.
|
// If minimized, w or h may be negative here.
|
||||||
double w = size.width - windowBorderWidth * 2;
|
double w = size.width - leftToEdge - rightToEdge;
|
||||||
double h = size.height - tabBarHeight - windowBorderWidth * 2;
|
double h = size.height - topToEdge - bottomToEdge;
|
||||||
return Size(w < 0 ? 0 : w, h < 0 ? 0 : h);
|
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;
|
return parent.target?.ffiModel.display.height ?? defaultHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
double get windowBorderWidth => stateGlobal.windowBorderWidth.value;
|
static double get windowBorderWidth => stateGlobal.windowBorderWidth.value;
|
||||||
double get tabBarHeight => stateGlobal.tabBarHeight;
|
static double get tabBarHeight => stateGlobal.tabBarHeight;
|
||||||
|
|
||||||
moveDesktopMouse(double x, double y) {
|
moveDesktopMouse(double x, double y) {
|
||||||
|
if (size.width == 0 || size.height == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// On mobile platforms, move the canvas with the cursor.
|
// On mobile platforms, move the canvas with the cursor.
|
||||||
final dw = getDisplayWidth() * _scale;
|
final dw = getDisplayWidth() * _scale;
|
||||||
final dh = getDisplayHeight() * _scale;
|
final dh = getDisplayHeight() * _scale;
|
||||||
|
|||||||
@ -487,7 +487,7 @@
|
|||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CODE_SIGN_IDENTITY = "-";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
|||||||
@ -217,6 +217,8 @@ pub struct PeerConfig {
|
|||||||
pub lock_after_session_end: LockAfterSessionEnd,
|
pub lock_after_session_end: LockAfterSessionEnd,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub privacy_mode: PrivacyMode,
|
pub privacy_mode: PrivacyMode,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub allow_swap_key: AllowSwapKey,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub port_forwards: Vec<(i32, String, i32)>,
|
pub port_forwards: Vec<(i32, String, i32)>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -1060,6 +1062,8 @@ serde_field_bool!(
|
|||||||
);
|
);
|
||||||
serde_field_bool!(PrivacyMode, "privacy_mode", default_privacy_mode);
|
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)]
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||||
pub struct LocalConfig {
|
pub struct LocalConfig {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|||||||
@ -1230,6 +1230,8 @@ impl LoginConfigHandler {
|
|||||||
option.block_input = BoolOption::No.into();
|
option.block_input = BoolOption::No.into();
|
||||||
} else if name == "show-quality-monitor" {
|
} else if name == "show-quality-monitor" {
|
||||||
config.show_quality_monitor.v = !config.show_quality_monitor.v;
|
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 {
|
} else {
|
||||||
let is_set = self
|
let is_set = self
|
||||||
.options
|
.options
|
||||||
@ -1383,6 +1385,8 @@ impl LoginConfigHandler {
|
|||||||
self.config.disable_clipboard.v
|
self.config.disable_clipboard.v
|
||||||
} else if name == "show-quality-monitor" {
|
} else if name == "show-quality-monitor" {
|
||||||
self.config.show_quality_monitor.v
|
self.config.show_quality_monitor.v
|
||||||
|
} else if name == "allow_swap_key" {
|
||||||
|
self.config.allow_swap_key.v
|
||||||
} else {
|
} else {
|
||||||
!self.get_option(name).is_empty()
|
!self.get_option(name).is_empty()
|
||||||
}
|
}
|
||||||
@ -1807,6 +1811,7 @@ pub fn send_mouse(
|
|||||||
if check_scroll_on_mac(mask, x, y) {
|
if check_scroll_on_mac(mask, x, y) {
|
||||||
mouse_event.modifiers.push(ControlKey::Scroll.into());
|
mouse_event.modifiers.push(ControlKey::Scroll.into());
|
||||||
}
|
}
|
||||||
|
interface.swap_modifier_mouse(&mut mouse_event);
|
||||||
msg_out.set_mouse_event(mouse_event);
|
msg_out.set_mouse_event(mouse_event);
|
||||||
interface.send(Data::Message(msg_out));
|
interface.send(Data::Message(msg_out));
|
||||||
}
|
}
|
||||||
@ -2033,6 +2038,7 @@ pub trait Interface: Send + Clone + 'static + Sized {
|
|||||||
fn is_force_relay(&self) -> bool {
|
fn is_force_relay(&self) -> bool {
|
||||||
self.get_login_config_handler().read().unwrap().force_relay
|
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.
|
/// Data used by the client interface.
|
||||||
|
|||||||
@ -458,6 +458,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Reconnect", "Reconectar"),
|
("Reconnect", "Reconectar"),
|
||||||
("Codec", "Códec"),
|
("Codec", "Códec"),
|
||||||
("Resolution", "Resolución"),
|
("Resolution", "Resolución"),
|
||||||
("No transfers in progress", ""),
|
("No transfers in progress", "No hay transferencias en curso"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -456,8 +456,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Stop voice call", "توقف تماس صوتی"),
|
("Stop voice call", "توقف تماس صوتی"),
|
||||||
("relay_hint_tip", " را به شناسه اضافه کنید یا گزینه \"همیشه از طریق رله متصل شوید\" را در کارت همتا انتخاب کنید. همچنین، اگر میخواهید فوراً از سرور رله استفاده کنید، میتوانید پسوند \"/r\".\n اتصال مستقیم ممکن است امکان پذیر نباشد. در این صورت می توانید سعی کنید از طریق سرور رله متصل شوید"),
|
("relay_hint_tip", " را به شناسه اضافه کنید یا گزینه \"همیشه از طریق رله متصل شوید\" را در کارت همتا انتخاب کنید. همچنین، اگر میخواهید فوراً از سرور رله استفاده کنید، میتوانید پسوند \"/r\".\n اتصال مستقیم ممکن است امکان پذیر نباشد. در این صورت می توانید سعی کنید از طریق سرور رله متصل شوید"),
|
||||||
("Reconnect", "اتصال مجدد"),
|
("Reconnect", "اتصال مجدد"),
|
||||||
("Codec", ""),
|
("Codec", "کدک"),
|
||||||
("Resolution", ""),
|
("Resolution", "وضوح"),
|
||||||
("No transfers in progress", ""),
|
("No transfers in progress", "هیچ انتقالی در حال انجام نیست"),
|
||||||
].iter().cloned().collect();
|
].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 && 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 ? <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 && 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>
|
</menu>
|
||||||
</popup>;
|
</popup>;
|
||||||
}
|
}
|
||||||
@ -440,7 +441,7 @@ function toggleMenuState() {
|
|||||||
for (var el in $$(menu#keyboard-options>li)) {
|
for (var el in $$(menu#keyboard-options>li)) {
|
||||||
el.attributes.toggleClass("selected", values.indexOf(el.id) >= 0);
|
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);
|
var el = self.select('#' + id);
|
||||||
if (el) {
|
if (el) {
|
||||||
var value = handler.get_toggle_option(id);
|
var value = handler.get_toggle_option(id);
|
||||||
|
|||||||
@ -373,10 +373,87 @@ impl<T: InvokeUiSession> Session<T> {
|
|||||||
return "".to_owned();
|
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) {
|
pub fn send_key_event(&self, evt: &KeyEvent) {
|
||||||
// mode: legacy(0), map(1), translate(2), auto(3)
|
// 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();
|
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));
|
self.send(Data::Message(msg_out));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -934,6 +1011,23 @@ impl<T: InvokeUiSession> Interface for Session<T> {
|
|||||||
handle_test_delay(t, peer).await;
|
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> {
|
impl<T: InvokeUiSession> Session<T> {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user