Merge branch 'master' into keyboard

This commit is contained in:
fufesou 2022-12-14 11:12:55 +08:00
commit 47658667d6
19 changed files with 424 additions and 233 deletions

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -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);
} }
} }

View File

@ -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);
} }
} }
} }

View File

@ -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:

View File

@ -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

View File

@ -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");
}
} }

View File

@ -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";
} }

View File

@ -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>,

View File

@ -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>,

View File

@ -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);

View File

@ -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();
} }

View File

@ -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"),

View File

@ -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 {

View File

@ -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() {

View File

@ -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();

View File

@ -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: &gtk::MenuItem) { fn update_tray_service_item(item: &gtk::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() {
} }
} }
} }

View File

@ -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"