Merge branch 'master' into keyboard
This commit is contained in:
commit
47658667d6
4
.github/workflows/flutter-nightly.yml
vendored
4
.github/workflows/flutter-nightly.yml
vendored
@ -47,8 +47,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
flutter doctor -v
|
flutter doctor -v
|
||||||
flutter precache --windows
|
flutter precache --windows
|
||||||
Invoke-WebRequest -Uri https://github.com/Kingtous/engine/releases/download/v3.0.5-rustdesk/windows-x64-release-flutter.zip -OutFile windows-x64-release-flutter.zip
|
Invoke-WebRequest -Uri https://github.com/Kingtous/engine/releases/download/v3.0.5-rustdesk.2/windows-x64-flutter-release.zip -OutFile windows-x64-flutter-release.zip
|
||||||
Expand-Archive windows-x64-release-flutter.zip -DestinationPath engine
|
Expand-Archive windows-x64-flutter-release.zip -DestinationPath engine
|
||||||
mv -Force engine/* C:/hostedtoolcache/windows/flutter/stable-3.0.5-x64/bin/cache/artifacts/engine/windows-x64-release/
|
mv -Force engine/* C:/hostedtoolcache/windows/flutter/stable-3.0.5-x64/bin/cache/artifacts/engine/windows-x64-release/
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
|
408
Cargo.lock
generated
408
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -47,7 +47,7 @@ libc = "0.2"
|
|||||||
parity-tokio-ipc = { git = "https://github.com/open-trade/parity-tokio-ipc" }
|
parity-tokio-ipc = { git = "https://github.com/open-trade/parity-tokio-ipc" }
|
||||||
flexi_logger = { version = "0.22", features = ["async", "use_chrono_for_offset"] }
|
flexi_logger = { version = "0.22", features = ["async", "use_chrono_for_offset"] }
|
||||||
runas = "0.2"
|
runas = "0.2"
|
||||||
magnum-opus = { git = "https://github.com/SoLongAndThanksForAllThePizza/magnum-opus" }
|
magnum-opus = { git = "https://github.com/rustdesk/magnum-opus" }
|
||||||
dasp = { version = "0.11", features = ["signal", "interpolate-linear", "interpolate"], optional = true }
|
dasp = { version = "0.11", features = ["signal", "interpolate-linear", "interpolate"], optional = true }
|
||||||
rubato = { version = "0.12", optional = true }
|
rubato = { version = "0.12", optional = true }
|
||||||
samplerate = { version = "0.2", optional = true }
|
samplerate = { version = "0.2", optional = true }
|
||||||
@ -118,6 +118,7 @@ dbus = "0.9"
|
|||||||
dbus-crossroads = "0.5"
|
dbus-crossroads = "0.5"
|
||||||
gtk = "0.15"
|
gtk = "0.15"
|
||||||
libappindicator = "0.7"
|
libappindicator = "0.7"
|
||||||
|
glib = "0.16.5"
|
||||||
|
|
||||||
[target.'cfg(target_os = "android")'.dependencies]
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
android_logger = "0.11"
|
android_logger = "0.11"
|
||||||
|
@ -5,6 +5,8 @@ import 'dart:ui' as ui;
|
|||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_custom_cursor/cursor_manager.dart'
|
||||||
|
as custom_cursor_manager;
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:wakelock/wakelock.dart';
|
import 'package:wakelock/wakelock.dart';
|
||||||
@ -109,17 +111,17 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
id: widget.id, arg: 'show-remote-cursor');
|
id: widget.id, arg: 'show-remote-cursor');
|
||||||
_zoomCursor.value =
|
_zoomCursor.value =
|
||||||
bind.sessionGetToggleOptionSync(id: widget.id, arg: 'zoom-cursor');
|
bind.sessionGetToggleOptionSync(id: widget.id, arg: 'zoom-cursor');
|
||||||
if (!_isCustomCursorInited) {
|
// if (!_isCustomCursorInited) {
|
||||||
customCursorController.registerNeedUpdateCursorCallback(
|
// customCursorController.registerNeedUpdateCursorCallback(
|
||||||
(String? lastKey, String? currentKey) async {
|
// (String? lastKey, String? currentKey) async {
|
||||||
if (_firstEnterImage.value) {
|
// if (_firstEnterImage.value) {
|
||||||
_firstEnterImage.value = false;
|
// _firstEnterImage.value = false;
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
return lastKey == null || lastKey != currentKey;
|
// return lastKey == null || lastKey != currentKey;
|
||||||
});
|
// });
|
||||||
_isCustomCursorInited = true;
|
// _isCustomCursorInited = true;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -366,15 +368,23 @@ class _ImagePaintState extends State<ImagePaint> {
|
|||||||
return MouseCursor.defer;
|
return MouseCursor.defer;
|
||||||
} else {
|
} else {
|
||||||
final key = cache.updateGetKey(scale, zoomCursor.value);
|
final key = cache.updateGetKey(scale, zoomCursor.value);
|
||||||
cursor.addKey(key);
|
if (!cursor.cachedKeys.contains(key)) {
|
||||||
return FlutterCustomMemoryImageCursor(
|
debugPrint("Register custom cursor with key $key");
|
||||||
pixbuf: cache.data,
|
// [Safety]
|
||||||
key: key,
|
// It's ok to call async registerCursor in current synchronous context,
|
||||||
hotx: cache.hotx,
|
// because activating the cursor is also an async call and will always
|
||||||
hoty: cache.hoty,
|
// be executed after this.
|
||||||
imageWidth: (cache.width * cache.scale).toInt(),
|
custom_cursor_manager.CursorManager.instance
|
||||||
imageHeight: (cache.height * cache.scale).toInt(),
|
.registerCursor(custom_cursor_manager.CursorData()
|
||||||
);
|
..buffer = cache.data!
|
||||||
|
..height = (cache.height * cache.scale).toInt()
|
||||||
|
..width = (cache.width * cache.scale).toInt()
|
||||||
|
..hotX = cache.hotx
|
||||||
|
..hotY = cache.hoty
|
||||||
|
..name = key);
|
||||||
|
cursor.addKey(key);
|
||||||
|
}
|
||||||
|
return FlutterCustomMemoryImageCursor(key: key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import 'package:flutter_hbb/common/shared_state.dart';
|
|||||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
import 'package:image/image.dart' as img2;
|
import 'package:image/image.dart' as img2;
|
||||||
import 'package:flutter_custom_cursor/flutter_custom_cursor.dart';
|
import 'package:flutter_custom_cursor/cursor_manager.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
|
||||||
import '../common.dart';
|
import '../common.dart';
|
||||||
@ -1113,7 +1113,8 @@ class CursorModel with ChangeNotifier {
|
|||||||
_clearCache() {
|
_clearCache() {
|
||||||
final keys = {...cachedKeys};
|
final keys = {...cachedKeys};
|
||||||
for (var k in keys) {
|
for (var k in keys) {
|
||||||
customCursorController.freeCache(k);
|
debugPrint("deleting cursor with key $k");
|
||||||
|
CursorManager.instance.deleteCursor(k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ packages:
|
|||||||
name: _fe_analyzer_shared
|
name: _fe_analyzer_shared
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "49.0.0"
|
version: "50.0.0"
|
||||||
after_layout:
|
after_layout:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -21,7 +21,7 @@ packages:
|
|||||||
name: analyzer
|
name: analyzer
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.1.0"
|
version: "5.2.0"
|
||||||
animations:
|
animations:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -352,7 +352,7 @@ packages:
|
|||||||
name: file_picker
|
name: file_picker
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.2.1"
|
version: "5.2.3"
|
||||||
fixnum:
|
fixnum:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -389,12 +389,10 @@ packages:
|
|||||||
flutter_custom_cursor:
|
flutter_custom_cursor:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
name: flutter_custom_cursor
|
||||||
ref: "74b1b314142b6775c1243067a3503ac568ebc74b"
|
url: "https://pub.dartlang.org"
|
||||||
resolved-ref: "74b1b314142b6775c1243067a3503ac568ebc74b"
|
source: hosted
|
||||||
url: "https://github.com/Kingtous/rustdesk_flutter_custom_cursor"
|
version: "0.0.2"
|
||||||
source: git
|
|
||||||
version: "0.0.1"
|
|
||||||
flutter_improved_scrolling:
|
flutter_improved_scrolling:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -455,14 +453,14 @@ packages:
|
|||||||
name: freezed
|
name: freezed
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.3.2"
|
||||||
freezed_annotation:
|
freezed_annotation:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: freezed_annotation
|
name: freezed_annotation
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.2.0"
|
||||||
frontend_server_client:
|
frontend_server_client:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -637,7 +635,7 @@ packages:
|
|||||||
name: mime
|
name: mime
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.3"
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1106,7 +1104,7 @@ packages:
|
|||||||
name: video_player
|
name: video_player
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.7"
|
version: "2.4.9"
|
||||||
video_player_android:
|
video_player_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -65,10 +65,7 @@ dependencies:
|
|||||||
url: https://github.com/Kingtous/rustdesk_desktop_multi_window
|
url: https://github.com/Kingtous/rustdesk_desktop_multi_window
|
||||||
ref: 82f9eab81cb2c7bfb938def7a1b399a6279bbc75
|
ref: 82f9eab81cb2c7bfb938def7a1b399a6279bbc75
|
||||||
freezed_annotation: ^2.0.3
|
freezed_annotation: ^2.0.3
|
||||||
flutter_custom_cursor:
|
flutter_custom_cursor: ^0.0.2
|
||||||
git:
|
|
||||||
url: https://github.com/Kingtous/rustdesk_flutter_custom_cursor
|
|
||||||
ref: 74b1b314142b6775c1243067a3503ac568ebc74b
|
|
||||||
window_size:
|
window_size:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/google/flutter-desktop-embedding.git
|
url: https://github.com/google/flutter-desktop-embedding.git
|
||||||
|
@ -66,6 +66,21 @@ macro_rules! allow_err {
|
|||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
($e:expr, $($arg:tt)*) => {
|
||||||
|
if let Err(err) = $e {
|
||||||
|
log::debug!(
|
||||||
|
"{:?}, {}, {}:{}:{}:{}",
|
||||||
|
err,
|
||||||
|
format_args!($($arg)*),
|
||||||
|
module_path!(),
|
||||||
|
file!(),
|
||||||
|
line!(),
|
||||||
|
column!()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -250,4 +265,10 @@ mod tests {
|
|||||||
let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 16, 32), 21116));
|
let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 16, 32), 21116));
|
||||||
assert_eq!(addr, AddrMangle::decode(&AddrMangle::encode(addr)));
|
assert_eq!(addr, AddrMangle::decode(&AddrMangle::encode(addr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_allow_err() {
|
||||||
|
allow_err!(Err("test err") as Result<(), &str>);
|
||||||
|
allow_err!(Err("test err with msg") as Result<(), &str>, "prompt {}", "failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,7 @@ impl Encoder {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn current_hw_encoder_name() -> Option<String> {
|
pub fn current_hw_encoder_name() -> Option<String> {
|
||||||
#[cfg(feature = "hwcodec")]
|
#[cfg(feature = "hwcodec")]
|
||||||
if check_hwcodec_config() {
|
if enable_hwcodec_option() {
|
||||||
return HwEncoder::current_name().lock().unwrap().clone();
|
return HwEncoder::current_name().lock().unwrap().clone();
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
@ -229,7 +229,7 @@ impl Encoder {
|
|||||||
|
|
||||||
pub fn supported_encoding() -> (bool, bool) {
|
pub fn supported_encoding() -> (bool, bool) {
|
||||||
#[cfg(feature = "hwcodec")]
|
#[cfg(feature = "hwcodec")]
|
||||||
if check_hwcodec_config() {
|
if enable_hwcodec_option() {
|
||||||
let best = HwEncoder::best();
|
let best = HwEncoder::best();
|
||||||
(
|
(
|
||||||
best.h264.as_ref().map_or(false, |c| c.score > 0),
|
best.h264.as_ref().map_or(false, |c| c.score > 0),
|
||||||
@ -246,7 +246,7 @@ impl Encoder {
|
|||||||
impl Decoder {
|
impl Decoder {
|
||||||
pub fn video_codec_state(_id: &str) -> VideoCodecState {
|
pub fn video_codec_state(_id: &str) -> VideoCodecState {
|
||||||
#[cfg(feature = "hwcodec")]
|
#[cfg(feature = "hwcodec")]
|
||||||
if check_hwcodec_config() {
|
if enable_hwcodec_option() {
|
||||||
let best = HwDecoder::best();
|
let best = HwDecoder::best();
|
||||||
return VideoCodecState {
|
return VideoCodecState {
|
||||||
score_vpx: SCORE_VPX,
|
score_vpx: SCORE_VPX,
|
||||||
@ -257,7 +257,7 @@ impl Decoder {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mediacodec")]
|
#[cfg(feature = "mediacodec")]
|
||||||
if check_hwcodec_config() {
|
if enable_hwcodec_option() {
|
||||||
let score_h264 = if H264_DECODER_SUPPORT.load(std::sync::atomic::Ordering::SeqCst) {
|
let score_h264 = if H264_DECODER_SUPPORT.load(std::sync::atomic::Ordering::SeqCst) {
|
||||||
92
|
92
|
||||||
} else {
|
} else {
|
||||||
@ -287,11 +287,19 @@ impl Decoder {
|
|||||||
Decoder {
|
Decoder {
|
||||||
vpx,
|
vpx,
|
||||||
#[cfg(feature = "hwcodec")]
|
#[cfg(feature = "hwcodec")]
|
||||||
hw: HwDecoder::new_decoders(),
|
hw: if enable_hwcodec_option() {
|
||||||
|
HwDecoder::new_decoders()
|
||||||
|
} else {
|
||||||
|
HwDecoders::default()
|
||||||
|
},
|
||||||
#[cfg(feature = "hwcodec")]
|
#[cfg(feature = "hwcodec")]
|
||||||
i420: vec![],
|
i420: vec![],
|
||||||
#[cfg(feature = "mediacodec")]
|
#[cfg(feature = "mediacodec")]
|
||||||
media_codec: MediaCodecDecoder::new_decoders(),
|
media_codec: if enable_hwcodec_option() {
|
||||||
|
MediaCodecDecoder::new_decoders()
|
||||||
|
} else {
|
||||||
|
MediaCodecDecoders::default()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,7 +423,7 @@ impl Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "hwcodec", feature = "mediacodec"))]
|
#[cfg(any(feature = "hwcodec", feature = "mediacodec"))]
|
||||||
fn check_hwcodec_config() -> bool {
|
fn enable_hwcodec_option() -> bool {
|
||||||
if let Some(v) = Config2::get().options.get("enable-hwcodec") {
|
if let Some(v) = Config2::get().options.get("enable-hwcodec") {
|
||||||
return v != "N";
|
return v != "N";
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ impl EncoderApi for HwEncoder {
|
|||||||
frames.push(EncodedVideoFrame {
|
frames.push(EncodedVideoFrame {
|
||||||
data: Bytes::from(frame.data),
|
data: Bytes::from(frame.data),
|
||||||
pts: frame.pts as _,
|
pts: frame.pts as _,
|
||||||
key:frame.key == 1,
|
key: frame.key == 1,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -175,6 +175,7 @@ pub struct HwDecoder {
|
|||||||
pub info: CodecInfo,
|
pub info: CodecInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct HwDecoders {
|
pub struct HwDecoders {
|
||||||
pub h264: Option<HwDecoder>,
|
pub h264: Option<HwDecoder>,
|
||||||
pub h265: Option<HwDecoder>,
|
pub h265: Option<HwDecoder>,
|
||||||
|
@ -37,6 +37,7 @@ impl Deref for MediaCodecDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct MediaCodecDecoders {
|
pub struct MediaCodecDecoders {
|
||||||
pub h264: Option<MediaCodecDecoder>,
|
pub h264: Option<MediaCodecDecoder>,
|
||||||
pub h265: Option<MediaCodecDecoder>,
|
pub h265: Option<MediaCodecDecoder>,
|
||||||
|
@ -173,7 +173,7 @@ pub fn core_main() -> Option<Vec<String>> {
|
|||||||
crate::start_os_service();
|
crate::start_os_service();
|
||||||
return None;
|
return None;
|
||||||
} else if args[0] == "--server" {
|
} else if args[0] == "--server" {
|
||||||
log::info!("start --server");
|
log::info!("start --server with user {}", crate::username());
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
{
|
{
|
||||||
crate::start_server(true);
|
crate::start_server(true);
|
||||||
|
@ -56,7 +56,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Too frequent", "Zu häufig"),
|
("Too frequent", "Zu häufig"),
|
||||||
("Cancel", "Abbrechen"),
|
("Cancel", "Abbrechen"),
|
||||||
("Skip", "Überspringen"),
|
("Skip", "Überspringen"),
|
||||||
("Close", "Sitzung beenden"),
|
("Close", "Schließen"),
|
||||||
("Retry", "Erneut versuchen"),
|
("Retry", "Erneut versuchen"),
|
||||||
("OK", "OK"),
|
("OK", "OK"),
|
||||||
("Password Required", "Passwort erforderlich"),
|
("Password Required", "Passwort erforderlich"),
|
||||||
@ -358,7 +358,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Unpin menubar", "Menüleiste lösen"),
|
("Unpin menubar", "Menüleiste lösen"),
|
||||||
("Recording", "Aufnahme"),
|
("Recording", "Aufnahme"),
|
||||||
("Directory", "Verzeichnis"),
|
("Directory", "Verzeichnis"),
|
||||||
("Automatically record incoming sessions", "Automatische Aufzeichnung eingehender Sitzungen"),
|
("Automatically record incoming sessions", "Eingehende Sitzungen automatisch aufzeichnen"),
|
||||||
("Change", "Ändern"),
|
("Change", "Ändern"),
|
||||||
("Start session recording", "Sitzungsaufzeichnung starten"),
|
("Start session recording", "Sitzungsaufzeichnung starten"),
|
||||||
("Stop session recording", "Sitzungsaufzeichnung beenden"),
|
("Stop session recording", "Sitzungsaufzeichnung beenden"),
|
||||||
@ -398,7 +398,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Hide connection management window", "Fenster zur Verwaltung der Verbindung verstecken"),
|
("Hide connection management window", "Fenster zur Verwaltung der Verbindung verstecken"),
|
||||||
("hide_cm_tip", "Dies ist nur möglich, wenn der Zugriff nur über ein permanentes Passwort erfolgt."), // Sehr unklar. Muss noch angepasst werden. Original: Allow hiding only if accepting sessions via password and using pernament passw"),
|
("hide_cm_tip", "Dies ist nur möglich, wenn der Zugriff nur über ein permanentes Passwort erfolgt."), // Sehr unklar. Muss noch angepasst werden. Original: Allow hiding only if accepting sessions via password and using pernament passw"),
|
||||||
("wayland_experiment_tip", ""),
|
("wayland_experiment_tip", ""),
|
||||||
("Right click to select tabs", ""),
|
("Right click to select tabs", "Register mit rechtem Mausklick auswählen"),
|
||||||
("Add to Address Book", ""),
|
("Add to Address Book", "Zum Adressbuch hinzufügen"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Transfer File", "Transferir archivo"),
|
("Transfer File", "Transferir archivo"),
|
||||||
("Connect", "Conectar"),
|
("Connect", "Conectar"),
|
||||||
("Recent Sessions", "Sesiones recientes"),
|
("Recent Sessions", "Sesiones recientes"),
|
||||||
("Address Book", "Directorio"),
|
("Address Book", "Libreta de direcciones"),
|
||||||
("Confirmation", "Confirmación"),
|
("Confirmation", "Confirmación"),
|
||||||
("TCP Tunneling", "Túnel TCP"),
|
("TCP Tunneling", "Túnel TCP"),
|
||||||
("Remove", "Quitar"),
|
("Remove", "Quitar"),
|
||||||
|
@ -179,7 +179,8 @@ fn set_x11_env(uid: &str) {
|
|||||||
log::info!("uid of seat0: {}", uid);
|
log::info!("uid of seat0: {}", uid);
|
||||||
let gdm = format!("/run/user/{}/gdm/Xauthority", uid);
|
let gdm = format!("/run/user/{}/gdm/Xauthority", uid);
|
||||||
let mut auth = get_env_tries("XAUTHORITY", uid, 10);
|
let mut auth = get_env_tries("XAUTHORITY", uid, 10);
|
||||||
if auth.is_empty() {
|
// auth is another user's when uid = 0, https://github.com/rustdesk/rustdesk/issues/2468
|
||||||
|
if auth.is_empty() || uid == "0" {
|
||||||
auth = if std::path::Path::new(&gdm).exists() {
|
auth = if std::path::Path::new(&gdm).exists() {
|
||||||
gdm
|
gdm
|
||||||
} else {
|
} else {
|
||||||
|
@ -439,6 +439,7 @@ extern "C" {
|
|||||||
fn win32_disable_lowlevel_keyboard(hwnd: HWND);
|
fn win32_disable_lowlevel_keyboard(hwnd: HWND);
|
||||||
fn win_stop_system_key_propagate(v: BOOL);
|
fn win_stop_system_key_propagate(v: BOOL);
|
||||||
fn is_win_down() -> BOOL;
|
fn is_win_down() -> BOOL;
|
||||||
|
fn is_local_system() -> BOOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "system" {
|
extern "system" {
|
||||||
@ -718,10 +719,10 @@ pub fn set_share_rdp(enable: bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_active_username() -> String {
|
pub fn get_active_username() -> String {
|
||||||
let name = crate::username();
|
if !is_root() {
|
||||||
if name != "SYSTEM" {
|
return crate::username();
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn get_active_user(path: *mut u16, n: u32, rdp: BOOL) -> u32;
|
fn get_active_user(path: *mut u16, n: u32, rdp: BOOL) -> u32;
|
||||||
}
|
}
|
||||||
@ -757,7 +758,8 @@ pub fn is_prelogin() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_root() -> bool {
|
pub fn is_root() -> bool {
|
||||||
crate::username() == "SYSTEM"
|
// https://stackoverflow.com/questions/4023586/correct-way-to-find-out-if-a-service-is-running-as-the-system-user
|
||||||
|
unsafe { is_local_system() == TRUE }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lock_screen() {
|
pub fn lock_screen() {
|
||||||
|
@ -379,7 +379,9 @@ impl RendezvousMediator {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let local_addr = socket.local_addr();
|
let local_addr = socket.local_addr();
|
||||||
allow_err!(socket_client::connect_tcp(peer_addr, local_addr, 300).await);
|
// key important here for punch hole to tell my gateway incoming peer is safe.
|
||||||
|
// it can not be async here, because local_addr can not be reused, we must close the connection before use it again.
|
||||||
|
allow_err!(socket_client::connect_tcp(peer_addr, local_addr, 30).await);
|
||||||
socket
|
socket
|
||||||
};
|
};
|
||||||
let mut msg_out = Message::new();
|
let mut msg_out = Message::new();
|
||||||
|
42
src/tray.rs
42
src/tray.rs
@ -88,6 +88,9 @@ pub fn start_tray() {
|
|||||||
/// This function will block current execution, show the tray icon and handle events.
|
/// This function will block current execution, show the tray icon and handle events.
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub fn start_tray() {
|
pub fn start_tray() {
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use glib::{clone, Continue};
|
||||||
use gtk::traits::{GtkMenuItemExt, MenuShellExt, WidgetExt};
|
use gtk::traits::{GtkMenuItemExt, MenuShellExt, WidgetExt};
|
||||||
|
|
||||||
info!("configuring tray");
|
info!("configuring tray");
|
||||||
@ -106,9 +109,9 @@ pub fn start_tray() {
|
|||||||
crate::client::translate("Stop service".to_owned())
|
crate::client::translate("Stop service".to_owned())
|
||||||
};
|
};
|
||||||
let menu_item_service = gtk::MenuItem::with_label(label.as_str());
|
let menu_item_service = gtk::MenuItem::with_label(label.as_str());
|
||||||
menu_item_service.connect_activate(move |item| {
|
menu_item_service.connect_activate(move |_| {
|
||||||
let _lock = crate::ui_interface::SENDER.lock().unwrap();
|
let _lock = crate::ui_interface::SENDER.lock().unwrap();
|
||||||
update_tray_service_item(item);
|
change_service_state();
|
||||||
});
|
});
|
||||||
menu.append(&menu_item_service);
|
menu.append(&menu_item_service);
|
||||||
// show tray item
|
// show tray item
|
||||||
@ -116,6 +119,16 @@ pub fn start_tray() {
|
|||||||
appindicator.set_menu(&mut menu);
|
appindicator.set_menu(&mut menu);
|
||||||
// start event loop
|
// start event loop
|
||||||
info!("Setting tray event loop");
|
info!("Setting tray event loop");
|
||||||
|
// check the connection status for every second
|
||||||
|
glib::timeout_add_local(
|
||||||
|
Duration::from_secs(1),
|
||||||
|
clone!(@strong menu_item_service as item => move || {
|
||||||
|
let _lock = crate::ui_interface::SENDER.lock().unwrap();
|
||||||
|
update_tray_service_item(&item);
|
||||||
|
// continue to trigger the next status check
|
||||||
|
Continue(true)
|
||||||
|
}),
|
||||||
|
);
|
||||||
gtk::main();
|
gtk::main();
|
||||||
} else {
|
} else {
|
||||||
error!("Tray process exit now");
|
error!("Tray process exit now");
|
||||||
@ -123,17 +136,25 @@ pub fn start_tray() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
|
fn change_service_state() {
|
||||||
|
if is_service_stoped() {
|
||||||
|
debug!("Now try to start service");
|
||||||
|
crate::ipc::set_option("stop-service", "");
|
||||||
|
} else {
|
||||||
|
debug!("Now try to stop service");
|
||||||
|
crate::ipc::set_option("stop-service", "Y");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[inline]
|
||||||
fn update_tray_service_item(item: >k::MenuItem) {
|
fn update_tray_service_item(item: >k::MenuItem) {
|
||||||
use gtk::traits::GtkMenuItemExt;
|
use gtk::traits::GtkMenuItemExt;
|
||||||
|
|
||||||
if is_service_stoped() {
|
if is_service_stoped() {
|
||||||
debug!("Now try to start service");
|
|
||||||
item.set_label(&crate::client::translate("Stop service".to_owned()));
|
|
||||||
crate::ipc::set_option("stop-service", "");
|
|
||||||
} else {
|
|
||||||
debug!("Now try to stop service");
|
|
||||||
item.set_label(&crate::client::translate("Start Service".to_owned()));
|
item.set_label(&crate::client::translate("Start Service".to_owned()));
|
||||||
crate::ipc::set_option("stop-service", "Y");
|
} else {
|
||||||
|
item.set_label(&crate::client::translate("Stop service".to_owned()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,10 +210,10 @@ pub fn make_tray() {
|
|||||||
match mode {
|
match mode {
|
||||||
dark_light::Mode::Dark => {
|
dark_light::Mode::Dark => {
|
||||||
icon_path = "mac-tray-light.png";
|
icon_path = "mac-tray-light.png";
|
||||||
},
|
}
|
||||||
dark_light::Mode::Light => {
|
dark_light::Mode::Light => {
|
||||||
icon_path = "mac-tray-dark.png";
|
icon_path = "mac-tray-dark.png";
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
if let Ok(mut tray) = TrayItem::new(&crate::get_app_name(), icon_path) {
|
if let Ok(mut tray) = TrayItem::new(&crate::get_app_name(), icon_path) {
|
||||||
tray.add_label(&format!(
|
tray.add_label(&format!(
|
||||||
@ -211,4 +232,3 @@ pub fn make_tray() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,4 +588,44 @@ extern "C"
|
|||||||
stop_system_key_propagate = v;
|
stop_system_key_propagate = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/4023586/correct-way-to-find-out-if-a-service-is-running-as-the-system-user
|
||||||
|
BOOL is_local_system()
|
||||||
|
{
|
||||||
|
HANDLE hToken;
|
||||||
|
UCHAR bTokenUser[sizeof(TOKEN_USER) + 8 + 4 * SID_MAX_SUB_AUTHORITIES];
|
||||||
|
PTOKEN_USER pTokenUser = (PTOKEN_USER)bTokenUser;
|
||||||
|
ULONG cbTokenUser;
|
||||||
|
SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY;
|
||||||
|
PSID pSystemSid;
|
||||||
|
BOOL bSystem;
|
||||||
|
|
||||||
|
// open process token
|
||||||
|
if (!OpenProcessToken(GetCurrentProcess(),
|
||||||
|
TOKEN_QUERY,
|
||||||
|
&hToken))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// retrieve user SID
|
||||||
|
if (!GetTokenInformation(hToken, TokenUser, pTokenUser,
|
||||||
|
sizeof(bTokenUser), &cbTokenUser))
|
||||||
|
{
|
||||||
|
CloseHandle(hToken);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(hToken);
|
||||||
|
|
||||||
|
// allocate LocalSystem well-known SID
|
||||||
|
if (!AllocateAndInitializeSid(&siaNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, &pSystemSid))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// compare the user SID from the token with the LocalSystem SID
|
||||||
|
bSystem = EqualSid(pTokenUser->User.Sid, pSystemSid);
|
||||||
|
|
||||||
|
FreeSid(pSystemSid);
|
||||||
|
|
||||||
|
return bSystem;
|
||||||
|
}
|
||||||
|
|
||||||
} // end of extern "C"
|
} // end of extern "C"
|
Loading…
x
Reference in New Issue
Block a user