Compare commits

...

29 Commits

Author SHA1 Message Date
rustdesk
a054de744a fix hide-tray=Y causing The application “RustDesk.app” is not open anymore. https://github.com/rustdesk/rustdesk/discussions/10210 2026-01-23 19:06:03 +08:00
21pages
e4b06dadf5 auto retry on offline when already connected (#14124)
When controlled peer is reconnecting after signout/switch user, auto retry for 30s (matches server's peer offline threshold) instead of immediately showing "Remote desktop is offline" error.

Ref: https://github.com/rustdesk/rustdesk/discussions/14048

Signed-off-by: 21pages <sunboeasy@gmail.com>
2026-01-23 15:05:11 +08:00
Yavuz Selim YAZICI
087eb55299 Update tr.rs, Missing Turkish translations added (#14103)
* Update tr.rs

* Update tr.rs

---------

Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
2026-01-22 14:15:14 +08:00
bilimiyorum
341eb0c671 Updated tr.rs (#14100)
New string entries
Minor typo corrections
2026-01-22 14:13:38 +08:00
solokot
43b39102a4 Update ru.rs (#14099) 2026-01-22 14:12:26 +08:00
fufesou
be4bbd018d fix(install): linux xdo (#14096)
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-01-21 20:43:15 +08:00
RustDesk
21a7cef98a keep-awake-during-incoming-sessions (#14082)
* keep-awake-during-incoming-sessions

* Update flutter/lib/desktop/pages/desktop_setting_page.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update flutter/lib/common.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update flutter/lib/mobile/pages/settings_page.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update common.dart

* wakelock

Signed-off-by: 21pages <sunboeasy@gmail.com>

* fix build

Signed-off-by: 21pages <sunboeasy@gmail.com>

* Update server_model.dart

---------

Signed-off-by: 21pages <sunboeasy@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: 21pages <sunboeasy@gmail.com>
2026-01-21 16:25:57 +08:00
fufesou
a6724b1c07 fix: build (#14093)
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-01-20 22:53:18 +08:00
Cody Kim
7437593ee7 Update ko.rs (#14055)
* update: correct Korean translations (typo/grammar)

- typo: 인중 -> 인증
- grammar: 중 입니다 -> 중입니다

Signed-off-by: 0-Chan <kyc4421194@gmail.com>

* update: improve Korean translations

Signed-off-by: 0-Chan <kyc4421194@gmail.com>

---------

Signed-off-by: 0-Chan <kyc4421194@gmail.com>
2026-01-20 17:08:54 +08:00
VenusGirl❤
f21829b075 Update Korean (#14057) 2026-01-20 17:08:02 +08:00
hatterp
b4f60e6057 Update pl.rs (#14054)
improve Polish translation

Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
2026-01-19 13:41:10 +08:00
hatterp
b9ebddff0c Update pl.rs (#14053)
Add and improve Polish translation.
2026-01-18 19:34:26 +08:00
hatterp
a2243484a3 Update README-PL.md (#14052) 2026-01-17 18:31:41 +08:00
21pages
c4a9835ae5 change quick support filename detection (#14050)
Signed-off-by: 21pages <sunboeasy@gmail.com>
2026-01-15 13:47:39 +08:00
Alex Rijckaert
92ad279324 Dutch Translation up to date (#14033) 2026-01-14 13:05:01 +08:00
Kratos
7276025cf9 Update hu.rs (#14032)
Fix translated strings.
2026-01-13 11:00:29 +08:00
minh
9808d585cf Update vi.rs file (#14027) 2026-01-13 11:00:16 +08:00
John Fowler
dab9ed711c Update Hungarian translations in hu.rs (#14014)
Translation of new strings and some fixes.
John Fowler.
2026-01-12 20:57:05 +08:00
Mr-Update
b27a93fc77 Update de.rs (#14013) 2026-01-12 20:56:50 +08:00
Lynilia
e3f66973b7 Update fr.rs (#14012) 2026-01-12 20:56:35 +08:00
bilimiyorum
21529d6ca2 Current tr.rs (#14008)
New string entries
2026-01-12 20:56:19 +08:00
solokot
775b0a3c93 Update ru.rs (#14004) 2026-01-12 20:56:02 +08:00
Anatolij Vasilev
070d4d029f synchronized german translation with the current english readme (#14001) 2026-01-12 10:59:11 +08:00
bovirus
5355702e9c Italian language update (#13998) 2026-01-12 10:58:42 +08:00
VenusGirl❤
a97997952d Update Korean (#13996)
Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
2026-01-12 10:58:23 +08:00
Sunev
b0c12bd86b Update signing conditions for rustdesk files (#14010)
Now ```env.SIGN_BASE_URL``` would never be ```''```, yet could be ```'-2'``` while ```secrets.SIGN_BASE_URL``` was undefined.
2026-01-10 15:29:59 +08:00
fufesou
82fcab26b1 refact(sign): skip signed files (#14006)
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-01-10 02:01:32 +08:00
fufesou
f3bbcc4f55 refact(sign): skip signed files (#14005)
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-01-10 00:55:00 +08:00
21pages
98362eaca0 add Changelog link in update help card (#13997)
Signed-off-by: 21pages <sunboeasy@gmail.com>
2026-01-09 15:34:51 +08:00
79 changed files with 1611 additions and 801 deletions

View File

@@ -234,7 +234,7 @@ jobs:
path: rustdesk
- name: Sign rustdesk files
if: env.UPLOAD_ARTIFACT == 'true' && env.SIGN_BASE_URL != ''
if: env.UPLOAD_ARTIFACT == 'true' && env.SIGN_BASE_URL != '-2'
shell: bash
run: |
pip3 install requests argparse
@@ -266,7 +266,7 @@ jobs:
sha256sum ../../SignOutput/rustdesk-*.msi
- name: Sign rustdesk self-extracted file
if: env.UPLOAD_ARTIFACT == 'true' && env.SIGN_BASE_URL != ''
if: env.UPLOAD_ARTIFACT == 'true' && env.SIGN_BASE_URL != '-2'
shell: bash
run: |
BASE_URL=${{ env.SIGN_BASE_URL }} SECRET_KEY=${{ secrets.SIGN_SECRET_KEY }} python3 res/job.py sign_files ./SignOutput
@@ -400,7 +400,7 @@ jobs:
path: Release
- name: Sign rustdesk files
if: env.UPLOAD_ARTIFACT == 'true' && env.SIGN_BASE_URL != ''
if: env.UPLOAD_ARTIFACT == 'true' && env.SIGN_BASE_URL != '-2'
shell: bash
run: |
pip3 install requests argparse
@@ -418,7 +418,7 @@ jobs:
mv ./target/release/rustdesk-portable-packer.exe ./SignOutput/rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}-sciter.exe
- name: Sign rustdesk self-extracted file
if: env.UPLOAD_ARTIFACT == 'true' && env.SIGN_BASE_URL != ''
if: env.UPLOAD_ARTIFACT == 'true' && env.SIGN_BASE_URL != '-2'
shell: bash
run: |
BASE_URL=${{ env.SIGN_BASE_URL }} SECRET_KEY=${{ secrets.SIGN_SECRET_KEY }} python3 res/job.py sign_files ./SignOutput/

10
Cargo.lock generated
View File

@@ -2517,6 +2517,7 @@ version = "0.0.14"
dependencies = [
"core-graphics 0.22.3",
"hbb_common",
"libxdo-sys",
"log",
"objc",
"pkg-config",
@@ -3720,6 +3721,7 @@ dependencies = [
"httparse",
"lazy_static",
"libc",
"libloading 0.8.4",
"log",
"mac_address",
"machine-uid",
@@ -3755,6 +3757,7 @@ dependencies = [
"webrtc",
"whoami",
"winapi 0.3.9",
"x11 2.21.0",
"zstd 0.13.1",
]
@@ -4546,11 +4549,8 @@ dependencies = [
[[package]]
name = "libxdo-sys"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db23b9e7e2b7831bbd8aac0bbeeeb7b68cbebc162b227e7052e8e55829a09212"
dependencies = [
"libc",
"x11 2.21.0",
"hbb_common",
]
[[package]]
@@ -7181,9 +7181,9 @@ dependencies = [
"kcp-sys",
"keepawake",
"lazy_static",
"libloading 0.8.4",
"libpulse-binding",
"libpulse-simple-binding",
"libxdo-sys",
"mac_address",
"magnum-opus",
"nix 0.29.0",

View File

@@ -76,7 +76,6 @@ crossbeam-queue = "0.3"
hex = "0.4"
chrono = "0.4"
cidr-utils = "0.5"
libloading = "0.8"
fon = "0.6"
zip = "0.6"
shutdown_hooks = "0.1"
@@ -177,6 +176,7 @@ bytemuck = "1.23"
ttf-parser = "0.25"
[target.'cfg(target_os = "linux")'.dependencies]
libxdo-sys = "0.11"
psimple = { package = "libpulse-simple-binding", version = "2.27" }
pulse = { package = "libpulse-binding", version = "2.27" }
rust-pulsectl = { git = "https://github.com/rustdesk-org/pulsectl" }
@@ -207,6 +207,11 @@ android-wakelock = { git = "https://github.com/rustdesk-org/android-wakelock" }
members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/clipboard", "libs/virtual_display", "libs/virtual_display/dylib", "libs/portable", "libs/remote_printer"]
exclude = ["vdi/host", "examples/custom_plugin"]
# Patch libxdo-sys to use a stub implementation that doesn't require libxdo
# This allows building and running on systems without libxdo installed (e.g., Wayland-only)
[patch.crates-io]
libxdo-sys = { path = "libs/libxdo-sys-stub" }
[package.metadata.winres]
LegalCopyright = "Copyright © 2025 Purslane Ltd. All rights reserved."
ProductName = "RustDesk"

View File

@@ -1,15 +1,14 @@
<p align="center">
<img src="../res/logo-header.svg" alt="RustDesk - Your remote desktop"><br>
<a href="#freie-öffentliche-server">Server</a> •
<img src="../res/logo-header.svg" alt="RustDesk - Dein Remote-Desktop"><br>
<a href="#grobe-schritte-zum-kompilieren">Kompilieren</a> •
<a href="#auf-docker-kompilieren">Docker</a> •
<a href="#dateistruktur">Dateistruktur</a> •
<a href="#screenshots">Screenshots</a><br>
[<a href="../README.md">English</a>] | [<a href="README-UA.md">Українська</a>] | [<a href="README-CS.md">česky</a>] | [<a href="README-ZH.md">中文</a>] | [<a href="README-HU.md">Magyar</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>] | [<a href="README-VN.md">Tiếng Việt</a>] | [<a href="README-DA.md">Dansk</a>] | [<a href="README-GR.md">Ελληνικά</a>]<br>
[<a href="docs/README-UA.md">Українська</a>] | [<a href="docs/README-CS.md">česky</a>] | [<a href="docs/README-ZH.md">中文</a>] | [<a href="docs/README-HU.md">Magyar</a>] | [<a href="docs/README-ES.md">Español</a>] | [<a href="docs/README-FA.md">فارسی</a>] | [<a href="docs/README-FR.md">Français</a>] | [<a href="docs/README-DE.md">Deutsch</a>] | [<a href="docs/README-PL.md">Polski</a>] | [<a href="docs/README-ID.md">Indonesian</a>] | [<a href="docs/README-FI.md">Suomi</a>] | [<a href="docs/README-ML.md">മലയാളം</a>] | [<a href="docs/README-JP.md">日本語</a>] | [<a href="docs/README-NL.md">Nederlands</a>] | [<a href="docs/README-IT.md">Italiano</a>] | [<a href="docs/README-RU.md">Русский</a>] | [<a href="docs/README-PTBR.md">Português (Brasil)</a>] | [<a href="docs/README-EO.md">Esperanto</a>] | [<a href="docs/README-KR.md">한국어</a>] | [<a href="docs/README-AR.md">العربي</a>] | [<a href="docs/README-VN.md">Tiếng Việt</a>] | [<a href="docs/README-DA.md">Dansk</a>] | [<a href="docs/README-GR.md">Ελληνικά</a>] | [<a href="docs/README-TR.md">Türkçe</a>] | [<a href="docs/README-NO.md">Norsk</a>] | [<a href="docs/README-RO.md">Română</a>]<br>
<b>Wir brauchen Ihre Hilfe, um dieses README, die <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang">RustDesk-Benutzeroberfläche</a> und die <a href="https://github.com/rustdesk/doc.rustdesk.com">Dokumentation</a> in Ihre Muttersprache zu übersetzen.</b>
</p>
> [!Vorsicht]
> [!Caution]
> **Haftungsausschluss bei Missbrauch::** <br>
> Die Entwickler von RustDesk billigen oder unterstützen keine unethische oder illegale Nutzung dieser Software. Missbrauch, wie unbefugter Zugriff, unbefugte Kontrolle oder Verletzung der Privatsphäre, verstößt strikt gegen unsere Richtlinien. Die Autoren sind nicht verantwortlich für jeglichen Missbrauch der Anwendung.
@@ -28,11 +27,14 @@ RustDesk heißt jegliche Mitarbeit willkommen. Schauen Sie sich [CONTRIBUTING-DE
[**Programm herunterladen**](https://github.com/rustdesk/rustdesk/releases)
[**Nächtliche Erstellung**](https://github.com/rustdesk/rustdesk/releases/tag/nightly)
[**Nightly Builds**](https://github.com/rustdesk/rustdesk/releases/tag/nightly)
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
[<img src="https://f-droid.org/badge/get-it-on.png"
alt="Get it on F-Droid"
height="80">](https://f-droid.org/en/packages/com.carriez.flutter_hbb)
[<img src="https://flathub.org/api/badge?svg&locale=en"
alt="Get it on Flathub"
height="80">](https://flathub.org/apps/com.rustdesk.RustDesk)
## Abhängigkeiten
@@ -64,18 +66,19 @@ Bitte laden Sie die dynamische Bibliothek Sciter selbst herunter.
```sh
sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev \
libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make \
libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libpam0g-dev
```
### openSUSE Tumbleweed
```sh
sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel
sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel pam-devel
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel pam-devel
```
### Arch (Manjaro)
@@ -114,7 +117,7 @@ cd
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
git clone --recurse-submodules https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
@@ -129,6 +132,7 @@ Beginnen Sie damit, das Repository zu klonen und den Docker-Container zu bauen:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
git submodule update --init --recursive
docker build -t "rustdesk-builder" .
```
@@ -157,6 +161,7 @@ Bitte stellen Sie sicher, dass Sie diese Befehle im Stammverzeichnis des RustDes
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: Video-Codec, Konfiguration, TCP/UDP-Wrapper, Protokoll-Puffer, fs-Funktionen für Dateitransfer und ein paar andere nützliche Funktionen
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: Bildschirmaufnahme
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: Plattformspezifische Maus- und Tastatursteuerung
- **[libs/clipboard](https://github.com/rustdesk/rustdesk/tree/master/libs/clipboard)**: Datei kopieren und einfügen Implementierung für Windows, Linux, macOS.
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: Audio/Zwischenablage/Eingabe/Videodienste und Netzwerkverbindungen
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: Starten einer Peer-Verbindung
@@ -167,10 +172,11 @@ Bitte stellen Sie sicher, dass Sie diese Befehle im Stammverzeichnis des RustDes
## Screenshots
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![Verbindungsmanager](https://github.com/rustdesk/rustdesk/assets/28412477/db82d4e7-c4bc-4823-8e6f-6af7eadf7651)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![Verbunden zu einem Windows PC](https://github.com/rustdesk/rustdesk/assets/28412477/9baa91e9-3362-4d06-aa1a-7518edcbd7ea)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![Dateiübertragung](https://github.com/rustdesk/rustdesk/assets/28412477/39511ad3-aa9a-4f8c-8947-1cce286a46ad)
![TCP-Tunneling](https://github.com/rustdesk/rustdesk/assets/28412477/78e8708f-e87e-4570-8373-1360033ea6c5)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

View File

@@ -13,7 +13,9 @@ Porozmawiaj z nami na: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](http
[![RustDesk Server Pro](https://img.shields.io/badge/RustDesk%20Server%20Pro-Zaawansowane%20Funkcje-blue)](https://rustdesk.com/pricing.html)
Kolejny program do zdalnego pulpitu, napisany w Rust. Działa od samego początku, nie wymaga konfiguracji. Masz pełną kontrolę nad swoimi danymi, bez obaw o bezpieczeństwo. Możesz skorzystać z naszego darmowego serwera publicznego, [skonfigurować własny](https://rustdesk.com/server), lub [napisać własny serwer](https://github.com/rustdesk/rustdesk-server-demo).
## O projekcie
RustDesk to wieloplatformowe oprogramowanie do zdalnego pulpitu, napisane w języku Rust, zaprojektowane z myślą o prostocie wdrożenia, bezpieczeństwie i pełnej kontroli użytkownika nad danymi. Aplikacja działa od razu po uruchomieniu i nie wymaga skomplikowanej konfiguracji. Możesz skorzystać z naszego darmowego serwera publicznego, [skonfigurować własny](https://rustdesk.com/server), lub [napisać własny serwer](https://github.com/rustdesk/rustdesk-server-demo).
![image](https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png)
@@ -31,7 +33,7 @@ RustDesk zaprasza do współpracy każdego. Zobacz [`docs/CONTRIBUTING-PL.md`](C
## Zależności
Wersje desktopowe używają [sciter](https://sciter.com/) dla GUI, proszę pobrać samodzielnie bibliotekę sciter.
Wersje desktopowe korzystają z biblioteki [sciter](https://sciter.com/) jako silnika GUI. Bibliotekę Sciter należy pobrać i zainstalować samodzielnie.
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |

View File

@@ -1578,7 +1578,7 @@ bool option2bool(String option, String value) {
option == kOptionForceAlwaysRelay) {
res = value == "Y";
} else {
assert(false);
// "" is true
res = value != "N";
}
return res;
@@ -1596,9 +1596,6 @@ String bool2option(String option, bool b) {
option == kOptionForceAlwaysRelay) {
res = b ? 'Y' : defaultOptionNo;
} else {
if (option != kOptionEnableUdpPunch && option != kOptionEnableIpv6Punch) {
assert(false);
}
res = b ? 'Y' : 'N';
}
return res;
@@ -2684,20 +2681,44 @@ class SimpleWrapper<T> {
/// This manager handles multiple tabs within the same isolate.
class WakelockManager {
static final Set<UniqueKey> _enabledKeys = {};
// Don't use WakelockPlus.enabled, it causes error on Android:
// Unhandled Exception: FormatException: Message corrupted
//
// On Linux, multiple enable() calls create only one inhibit, but each disable()
// only releases if _cookie != null. So we need our own _enabled state to avoid
// calling disable() when not enabled.
// See: https://github.com/fluttercommunity/wakelock_plus/blob/0c74e5bbc6aefac57b6c96bb7ef987705ed559ec/wakelock_plus/lib/src/wakelock_plus_linux_plugin.dart#L48
static bool _enabled = false;
static void enable(UniqueKey key) {
if (isLinux) return;
_enabledKeys.add(key);
WakelockPlus.enable();
static void enable(UniqueKey key, {bool isServer = false}) {
// Check if we should keep awake during outgoing sessions
if (!isServer) {
final keepAwake =
mainGetLocalBoolOptionSync(kOptionKeepAwakeDuringOutgoingSessions);
if (!keepAwake) {
return; // Don't enable wakelock if user disabled keep awake
}
}
if (isDesktop) {
_enabledKeys.add(key);
}
if (!_enabled) {
_enabled = true;
WakelockPlus.enable();
}
}
static void disable(UniqueKey key) {
if (isLinux) return;
if (_enabledKeys.remove(key)) {
if (_enabledKeys.isEmpty) {
WakelockPlus.disable();
if (isDesktop) {
_enabledKeys.remove(key);
if (_enabledKeys.isNotEmpty) {
return;
}
}
if (_enabled) {
WakelockPlus.disable();
_enabled = false;
}
}
}

View File

@@ -194,6 +194,9 @@ const String kOptionDisableFloatingWindow = "disable-floating-window";
const String kOptionKeepScreenOn = "keep-screen-on";
const String kOptionKeepAwakeDuringIncomingSessions = "keep-awake-during-incoming-sessions";
const String kOptionKeepAwakeDuringOutgoingSessions = "keep-awake-during-outgoing-sessions";
const String kOptionShowMobileAction = "showMobileActions";
const String kUrlActionClose = "close";

View File

@@ -450,7 +450,11 @@ class _DesktopHomePageState extends State<DesktopHomePage>
"${translate("new-version-of-{${bind.mainGetAppNameSync()}}-tip")} (${bind.mainGetNewVersion()}).",
btnText,
onPressed,
closeButton: true);
closeButton: true,
help: isToUpdate ? 'Changelog' : null,
link: isToUpdate
? 'https://github.com/rustdesk/rustdesk/releases/tag/${bind.mainGetNewVersion()}'
: null);
}
if (systemError.isNotEmpty) {
return buildInstallCard("", systemError, "", () {});

View File

@@ -557,6 +557,17 @@ class _GeneralState extends State<_General> {
],
],
];
// Add client-side wakelock option for desktop platforms
if (!bind.isIncomingOnly()) {
children.add(_OptionCheckBox(
context,
'keep-awake-during-outgoing-sessions-label',
kOptionKeepAwakeDuringOutgoingSessions,
isServer: false,
));
}
if (!isWeb && bind.mainShowOption(key: kOptionAllowLinuxHeadless)) {
children.add(_OptionCheckBox(
context, 'Allow linux headless', kOptionAllowLinuxHeadless));
@@ -1219,6 +1230,9 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
...directIp(context),
whitelist(),
...autoDisconnect(context),
_OptionCheckBox(context, 'keep-awake-during-incoming-sessions-label',
kOptionKeepAwakeDuringIncomingSessions,
reverse: false, enabled: enabled),
if (bind.mainIsInstalled())
_OptionCheckBox(context, 'allow-only-conn-window-open-tip',
'allow-only-conn-window-open',

View File

@@ -5,7 +5,6 @@ import 'package:flutter_breadcrumb/flutter_breadcrumb.dart';
import 'package:flutter_hbb/models/file_model.dart';
import 'package:get/get.dart';
import 'package:toggle_switch/toggle_switch.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import '../../common.dart';
import '../../common/widgets/dialog.dart';
@@ -72,6 +71,7 @@ class _FileManagerPageState extends State<FileManagerPage> {
showLocal ? model.localController : model.remoteController;
FileDirectory get currentDir => currentFileController.directory.value;
DirectoryOptions get currentOptions => currentFileController.options.value;
final _uniqueKey = UniqueKey();
@override
void initState() {
@@ -86,7 +86,7 @@ class _FileManagerPageState extends State<FileManagerPage> {
.showLoading(translate('Connecting...'), onCancel: closeConnection);
});
gFFI.ffiModel.updateEventListener(gFFI.sessionId, widget.id);
WakelockPlus.enable();
WakelockManager.enable(_uniqueKey);
}
@override
@@ -94,7 +94,7 @@ class _FileManagerPageState extends State<FileManagerPage> {
model.close().whenComplete(() {
gFFI.close();
gFFI.dialogManager.dismissAll();
WakelockPlus.disable();
WakelockManager.disable(_uniqueKey);
});
model.jobController.clear();
super.dispose();

View File

@@ -14,7 +14,6 @@ import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart';
import 'package:provider/provider.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import '../../common.dart';
import '../../common/widgets/overlay.dart';
@@ -67,7 +66,7 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
String _value = '';
Orientation? _currentOrientation;
double _viewInsetsBottom = 0;
final _uniqueKey = UniqueKey();
Timer? _timerDidChangeMetrics;
final _blockableOverlayState = BlockableOverlayState();
@@ -105,9 +104,7 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
gFFI.dialogManager
.showLoading(translate('Connecting...'), onCancel: closeConnection);
});
if (!isWeb) {
WakelockPlus.enable();
}
WakelockManager.enable(_uniqueKey);
_physicalFocusNode.requestFocus();
gFFI.inputModel.listenToMouse(true);
gFFI.qualityMonitorModel.checkShowQualityMonitor(sessionId);
@@ -146,9 +143,7 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
gFFI.dialogManager.dismissAll();
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: SystemUiOverlay.values);
if (!isWeb) {
await WakelockPlus.disable();
}
WakelockManager.disable(_uniqueKey);
await keyboardSubscription.cancel();
removeSharedStates(widget.id);
// `on_voice_call_closed` should be called when the connection is ended.

View File

@@ -100,6 +100,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
var _enableIpv6Punch = false;
var _isUsingPublicServer = false;
var _allowAskForNoteAtEndOfConnection = false;
var _preventSleepWhileConnected = true;
_SettingsState() {
_enableAbr = option2bool(
@@ -140,6 +141,8 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
_enableIpv6Punch = mainGetLocalBoolOptionSync(kOptionEnableIpv6Punch);
_allowAskForNoteAtEndOfConnection =
mainGetLocalBoolOptionSync(kOptionAllowAskForNoteAtEndOfConnection);
_preventSleepWhileConnected =
mainGetLocalBoolOptionSync(kOptionKeepAwakeDuringOutgoingSessions);
_showTerminalExtraKeys =
mainGetLocalBoolOptionSync(kOptionEnableShowTerminalExtraKeys);
}
@@ -823,7 +826,18 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
_allowAskForNoteAtEndOfConnection = newValue;
});
},
)
),
if (!incomingOnly)
SettingsTile.switchTile(
title: Text(translate('keep-awake-during-outgoing-sessions-label')),
initialValue: _preventSleepWhileConnected,
onToggle: (v) async {
await mainSetLocalBoolOption(kOptionKeepAwakeDuringOutgoingSessions, v);
setState(() {
_preventSleepWhileConnected = v;
});
},
),
]),
if (isAndroid)
SettingsSection(title: Text(translate('Hardware Codec')), tiles: [

View File

@@ -11,7 +11,6 @@ import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart';
import 'package:provider/provider.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import '../../common.dart';
import '../../common/widgets/overlay.dart';
@@ -62,7 +61,7 @@ class _ViewCameraPageState extends State<ViewCameraPage>
bool _showGestureHelp = false;
Orientation? _currentOrientation;
double _viewInsetsBottom = 0;
final _uniqueKey = UniqueKey();
Timer? _timerDidChangeMetrics;
final _blockableOverlayState = BlockableOverlayState();
@@ -100,9 +99,7 @@ class _ViewCameraPageState extends State<ViewCameraPage>
gFFI.dialogManager
.showLoading(translate('Connecting...'), onCancel: closeConnection);
});
if (!isWeb) {
WakelockPlus.enable();
}
WakelockManager.enable(_uniqueKey);
_physicalFocusNode.requestFocus();
gFFI.inputModel.listenToMouse(true);
gFFI.qualityMonitorModel.checkShowQualityMonitor(sessionId);
@@ -139,9 +136,7 @@ class _ViewCameraPageState extends State<ViewCameraPage>
gFFI.dialogManager.dismissAll();
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: SystemUiOverlay.values);
if (!isWeb) {
await WakelockPlus.disable();
}
WakelockManager.disable(_uniqueKey);
removeSharedStates(widget.id);
// `on_voice_call_closed` should be called when the connection is ended.
// The inner logic of `on_voice_call_closed` will check if the voice call is active.

View File

@@ -120,6 +120,7 @@ class FfiModel with ChangeNotifier {
late VirtualMouseMode virtualMouseMode;
Timer? _timer;
var _reconnects = 1;
DateTime? _offlineReconnectStartTime;
bool _viewOnly = false;
bool _showMyCursor = false;
WeakReference<FFI> parent;
@@ -783,7 +784,8 @@ class FfiModel with ChangeNotifier {
}
}
Future<void> updateCurDisplay(SessionID sessionId, {updateCursorPos = false}) async {
Future<void> updateCurDisplay(SessionID sessionId,
{updateCursorPos = false}) async {
final newRect = displaysRect();
if (newRect == null) {
return;
@@ -939,11 +941,46 @@ class FfiModel with ChangeNotifier {
showPrivacyFailedDialog(
sessionId, type, title, text, link, hasRetry, dialogManager);
} else {
final hasRetry = evt['hasRetry'] == 'true';
var hasRetry = evt['hasRetry'] == 'true';
if (!hasRetry) {
hasRetry = shouldAutoRetryOnOffline(type, title, text);
}
showMsgBox(sessionId, type, title, text, link, hasRetry, dialogManager);
}
}
/// Auto-retry check for "Remote desktop is offline" error.
/// returns true to auto-retry, false otherwise.
bool shouldAutoRetryOnOffline(
String type,
String title,
String text,
) {
if (type == 'error' &&
title == 'Connection Error' &&
text == 'Remote desktop is offline' &&
_pi.isSet.isTrue) {
// Auto retry for ~30s (server's peer offline threshold) when controlled peer's account changes
// (e.g., signout, switch user, login into OS) causes temporary offline via websocket/tcp connection.
// The actual wait may exceed 30s (e.g., 20s elapsed + 16s next retry = 36s), which is acceptable
// since the controlled side reconnects quickly after account changes.
// Uses time-based check instead of _reconnects count because user can manually retry.
// https://github.com/rustdesk/rustdesk/discussions/14048
if (_offlineReconnectStartTime == null) {
// First offline, record time and start retry
_offlineReconnectStartTime = DateTime.now();
return true;
} else {
final elapsed =
DateTime.now().difference(_offlineReconnectStartTime!).inSeconds;
if (elapsed < 30) {
return true;
}
}
}
return false;
}
handleToast(Map<String, dynamic> evt, SessionID sessionId, String peerId) {
final type = evt['type'] ?? 'info';
final text = evt['text'] ?? '';
@@ -1001,6 +1038,7 @@ class FfiModel with ChangeNotifier {
_reconnects *= 2;
} else {
_reconnects = 1;
_offlineReconnectStartTime = null;
}
}
@@ -1323,6 +1361,7 @@ class FfiModel with ChangeNotifier {
}
if (displays.isNotEmpty) {
_reconnects = 1;
_offlineReconnectStartTime = null;
waitForFirstImage.value = true;
isRefreshing = false;
}

View File

@@ -8,7 +8,6 @@ import 'package:flutter_hbb/mobile/pages/settings_page.dart';
import 'package:flutter_hbb/models/chat_model.dart';
import 'package:flutter_hbb/models/platform_model.dart';
import 'package:get/get.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import 'package:window_manager/window_manager.dart';
import '../common.dart';
@@ -51,6 +50,8 @@ class ServerModel with ChangeNotifier {
Timer? cmHiddenTimer;
final _wakelockKey = UniqueKey();
bool get isStart => _isStart;
bool get mediaOk => _mediaOk;
@@ -466,10 +467,8 @@ class ServerModel with ChangeNotifier {
await parent.target?.invokeMethod("stop_service");
await bind.mainStopService();
notifyListeners();
if (!isLinux) {
// current linux is not supported
WakelockPlus.disable();
}
// for androidUpdatekeepScreenOn only
WakelockManager.disable(_wakelockKey);
}
Future<bool> setPermanentPassword(String newPW) async {
@@ -613,12 +612,12 @@ class ServerModel with ChangeNotifier {
void showLoginDialog(Client client) {
showClientDialog(
client,
client.isFileTransfer
? "Transfer file"
client.isFileTransfer
? "Transfer file"
: client.isViewCamera
? "View camera"
: client.isTerminal
? "Terminal"
: client.isTerminal
? "Terminal"
: "Share screen",
'Do you accept?',
'android_new_connection_tip',
@@ -797,12 +796,10 @@ class ServerModel with ChangeNotifier {
final on = ((keepScreenOn == KeepScreenOn.serviceOn) && _isStart) ||
(keepScreenOn == KeepScreenOn.duringControlled &&
_clients.map((e) => !e.disconnected).isNotEmpty);
if (on != await WakelockPlus.enabled) {
if (on) {
WakelockPlus.enable();
} else {
WakelockPlus.disable();
}
if (on) {
WakelockManager.enable(_wakelockKey, isServer: true);
} else {
WakelockManager.disable(_wakelockKey);
}
}
}

View File

@@ -37,5 +37,8 @@ core-graphics = "0.22"
objc = "0.2"
unicode-segmentation = "1.10"
[target.'cfg(target_os = "linux")'.dependencies]
libxdo-sys = "0.11"
[build-dependencies]
pkg-config = "0.3"

View File

@@ -1,50 +1,22 @@
//! XDO-based input emulation for Linux.
//!
//! This module uses libxdo-sys (patched to use dynamic loading stub) for input emulation.
//! The stub handles dynamic loading of libxdo, so we just call the functions directly.
//!
//! If libxdo is not available at runtime, all operations become no-ops.
use crate::{Key, KeyboardControllable, MouseButton, MouseControllable};
use hbb_common::libc::{c_char, c_int, c_void, useconds_t};
use std::{borrow::Cow, ffi::CString, ptr};
use hbb_common::libc::c_int;
use libxdo_sys::{self, xdo_t, CURRENTWINDOW};
use std::{borrow::Cow, ffi::CString};
const CURRENT_WINDOW: c_int = 0;
/// Default delay per keypress in microseconds.
/// This value is passed to libxdo functions and must fit in `useconds_t` (u32).
const DEFAULT_DELAY: u64 = 12000;
type Window = c_int;
type Xdo = *const c_void;
#[link(name = "xdo")]
extern "C" {
fn xdo_free(xdo: Xdo);
fn xdo_new(display: *const c_char) -> Xdo;
fn xdo_click_window(xdo: Xdo, window: Window, button: c_int) -> c_int;
fn xdo_mouse_down(xdo: Xdo, window: Window, button: c_int) -> c_int;
fn xdo_mouse_up(xdo: Xdo, window: Window, button: c_int) -> c_int;
fn xdo_move_mouse(xdo: Xdo, x: c_int, y: c_int, screen: c_int) -> c_int;
fn xdo_move_mouse_relative(xdo: Xdo, x: c_int, y: c_int) -> c_int;
fn xdo_enter_text_window(
xdo: Xdo,
window: Window,
string: *const c_char,
delay: useconds_t,
) -> c_int;
fn xdo_send_keysequence_window(
xdo: Xdo,
window: Window,
string: *const c_char,
delay: useconds_t,
) -> c_int;
fn xdo_send_keysequence_window_down(
xdo: Xdo,
window: Window,
string: *const c_char,
delay: useconds_t,
) -> c_int;
fn xdo_send_keysequence_window_up(
xdo: Xdo,
window: Window,
string: *const c_char,
delay: useconds_t,
) -> c_int;
fn xdo_get_input_state(xdo: Xdo) -> u32;
}
/// Maximum allowed delay value (u32::MAX as u64).
const MAX_DELAY: u64 = u32::MAX as u64;
fn mousebutton(button: MouseButton) -> c_int {
match button {
@@ -62,7 +34,7 @@ fn mousebutton(button: MouseButton) -> c_int {
/// The main struct for handling the event emitting
pub(super) struct EnigoXdo {
xdo: Xdo,
xdo: *mut xdo_t,
delay: u64,
}
// This is safe, we have a unique pointer.
@@ -70,37 +42,61 @@ pub(super) struct EnigoXdo {
unsafe impl Send for EnigoXdo {}
impl Default for EnigoXdo {
/// Create a new EnigoXdo instance
/// Create a new EnigoXdo instance.
///
/// If libxdo is not available, the xdo pointer will be null and all
/// input operations will be no-ops.
fn default() -> Self {
let xdo = unsafe { libxdo_sys::xdo_new(std::ptr::null()) };
if xdo.is_null() {
log::warn!("Failed to create xdo context, xdo functions will be disabled");
} else {
log::info!("xdo context created successfully");
}
Self {
xdo: unsafe { xdo_new(ptr::null()) },
xdo,
delay: DEFAULT_DELAY,
}
}
}
impl EnigoXdo {
/// Get the delay per keypress.
/// Default value is 12000.
/// This is Linux-specific.
/// Get the delay per keypress in microseconds.
///
/// Default value is 12000 (12ms). This is Linux-specific.
pub fn delay(&self) -> u64 {
self.delay
}
/// Set the delay per keypress.
/// This is Linux-specific.
/// Set the delay per keypress in microseconds.
///
/// This is Linux-specific. The value is clamped to `u32::MAX` (approximately
/// 4295 seconds) because libxdo uses `useconds_t` which is typically `u32`.
///
/// # Arguments
/// * `delay` - Delay in microseconds. Values exceeding `u32::MAX` will be clamped.
pub fn set_delay(&mut self, delay: u64) {
self.delay = delay;
self.delay = delay.min(MAX_DELAY);
if delay > MAX_DELAY {
log::warn!(
"delay value {} exceeds maximum {}, clamped",
delay,
MAX_DELAY
);
}
}
}
impl Drop for EnigoXdo {
fn drop(&mut self) {
if self.xdo.is_null() {
return;
}
unsafe {
xdo_free(self.xdo);
if !self.xdo.is_null() {
unsafe {
libxdo_sys::xdo_free(self.xdo);
}
}
}
}
impl MouseControllable for EnigoXdo {
fn as_any(&self) -> &dyn std::any::Any {
self
@@ -115,42 +111,47 @@ impl MouseControllable for EnigoXdo {
return;
}
unsafe {
xdo_move_mouse(self.xdo, x as c_int, y as c_int, 0);
libxdo_sys::xdo_move_mouse(self.xdo as *const _, x, y, 0);
}
}
fn mouse_move_relative(&mut self, x: i32, y: i32) {
if self.xdo.is_null() {
return;
}
unsafe {
xdo_move_mouse_relative(self.xdo, x as c_int, y as c_int);
libxdo_sys::xdo_move_mouse_relative(self.xdo as *const _, x, y);
}
}
fn mouse_down(&mut self, button: MouseButton) -> crate::ResultType {
if self.xdo.is_null() {
return Ok(());
}
unsafe {
xdo_mouse_down(self.xdo, CURRENT_WINDOW, mousebutton(button));
libxdo_sys::xdo_mouse_down(self.xdo as *const _, CURRENTWINDOW, mousebutton(button));
}
Ok(())
}
fn mouse_up(&mut self, button: MouseButton) {
if self.xdo.is_null() {
return;
}
unsafe {
xdo_mouse_up(self.xdo, CURRENT_WINDOW, mousebutton(button));
libxdo_sys::xdo_mouse_up(self.xdo as *const _, CURRENTWINDOW, mousebutton(button));
}
}
fn mouse_click(&mut self, button: MouseButton) {
if self.xdo.is_null() {
return;
}
unsafe {
xdo_click_window(self.xdo, CURRENT_WINDOW, mousebutton(button));
libxdo_sys::xdo_click_window(self.xdo as *const _, CURRENTWINDOW, mousebutton(button));
}
}
fn mouse_scroll_x(&mut self, length: i32) {
let button;
let mut length = length;
@@ -169,6 +170,7 @@ impl MouseControllable for EnigoXdo {
self.mouse_click(button);
}
}
fn mouse_scroll_y(&mut self, length: i32) {
let button;
let mut length = length;
@@ -188,6 +190,7 @@ impl MouseControllable for EnigoXdo {
}
}
}
fn keysequence<'a>(key: Key) -> Cow<'a, str> {
if let Key::Layout(c) = key {
return Cow::Owned(format!("U{:X}", c as u32));
@@ -284,6 +287,7 @@ fn keysequence<'a>(key: Key) -> Cow<'a, str> {
_ => "",
})
}
impl KeyboardControllable for EnigoXdo {
fn as_any(&self) -> &dyn std::any::Any {
self
@@ -314,7 +318,7 @@ impl KeyboardControllable for EnigoXdo {
let mod_alt = 1 << 3;
let mod_numlock = 1 << 4;
let mod_meta = 1 << 6;
let mask = unsafe { xdo_get_input_state(self.xdo) };
let mask = unsafe { libxdo_sys::xdo_get_input_state(self.xdo as *const _) };
match key {
Key::Shift => mask & mod_shift != 0,
Key::CapsLock => mask & mod_lock != 0,
@@ -332,56 +336,59 @@ impl KeyboardControllable for EnigoXdo {
}
if let Ok(string) = CString::new(sequence) {
unsafe {
xdo_enter_text_window(
self.xdo,
CURRENT_WINDOW,
libxdo_sys::xdo_enter_text_window(
self.xdo as *const _,
CURRENTWINDOW,
string.as_ptr(),
self.delay as useconds_t,
self.delay as libxdo_sys::useconds_t,
);
}
}
}
fn key_down(&mut self, key: Key) -> crate::ResultType {
if self.xdo.is_null() {
return Ok(());
}
let string = CString::new(&*keysequence(key))?;
unsafe {
xdo_send_keysequence_window_down(
self.xdo,
CURRENT_WINDOW,
libxdo_sys::xdo_send_keysequence_window_down(
self.xdo as *const _,
CURRENTWINDOW,
string.as_ptr(),
self.delay as useconds_t,
self.delay as libxdo_sys::useconds_t,
);
}
Ok(())
}
fn key_up(&mut self, key: Key) {
if self.xdo.is_null() {
return;
}
if let Ok(string) = CString::new(&*keysequence(key)) {
unsafe {
xdo_send_keysequence_window_up(
self.xdo,
CURRENT_WINDOW,
libxdo_sys::xdo_send_keysequence_window_up(
self.xdo as *const _,
CURRENTWINDOW,
string.as_ptr(),
self.delay as useconds_t,
self.delay as libxdo_sys::useconds_t,
);
}
}
}
fn key_click(&mut self, key: Key) {
if self.xdo.is_null() {
return;
}
if let Ok(string) = CString::new(&*keysequence(key)) {
unsafe {
xdo_send_keysequence_window(
self.xdo,
CURRENT_WINDOW,
libxdo_sys::xdo_send_keysequence_window(
self.xdo as *const _,
CURRENTWINDOW,
string.as_ptr(),
self.delay as useconds_t,
self.delay as libxdo_sys::useconds_t,
);
}
}

View File

@@ -0,0 +1,9 @@
[package]
name = "libxdo-sys"
version = "0.11.0"
edition = "2021"
publish = false
description = "Dynamic loading wrapper for libxdo-sys that doesn't require libxdo at compile/link time"
[dependencies]
hbb_common = { path = "../hbb_common" }

View File

@@ -0,0 +1,505 @@
//! Dynamic loading wrapper for libxdo.
//!
//! Provides the same API as libxdo-sys but loads libxdo at runtime,
//! allowing the program to run on systems without libxdo installed
//! (e.g., Wayland-only environments).
use hbb_common::{
libc::{c_char, c_int, c_uint},
libloading::{Library, Symbol},
log,
};
use std::sync::OnceLock;
pub use hbb_common::x11::xlib::{Display, Screen, Window};
#[repr(C)]
pub struct xdo_t {
_private: [u8; 0],
}
#[repr(C)]
pub struct charcodemap_t {
_private: [u8; 0],
}
#[repr(C)]
pub struct xdo_search_t {
_private: [u8; 0],
}
pub type useconds_t = c_uint;
pub const CURRENTWINDOW: Window = 0;
type FnXdoNew = unsafe extern "C" fn(*const c_char) -> *mut xdo_t;
type FnXdoNewWithOpenedDisplay =
unsafe extern "C" fn(*mut Display, *const c_char, c_int) -> *mut xdo_t;
type FnXdoFree = unsafe extern "C" fn(*mut xdo_t);
type FnXdoSendKeysequenceWindow =
unsafe extern "C" fn(*const xdo_t, Window, *const c_char, useconds_t) -> c_int;
type FnXdoSendKeysequenceWindowDown =
unsafe extern "C" fn(*const xdo_t, Window, *const c_char, useconds_t) -> c_int;
type FnXdoSendKeysequenceWindowUp =
unsafe extern "C" fn(*const xdo_t, Window, *const c_char, useconds_t) -> c_int;
type FnXdoEnterTextWindow =
unsafe extern "C" fn(*const xdo_t, Window, *const c_char, useconds_t) -> c_int;
type FnXdoClickWindow = unsafe extern "C" fn(*const xdo_t, Window, c_int) -> c_int;
type FnXdoMouseDown = unsafe extern "C" fn(*const xdo_t, Window, c_int) -> c_int;
type FnXdoMouseUp = unsafe extern "C" fn(*const xdo_t, Window, c_int) -> c_int;
type FnXdoMoveMouse = unsafe extern "C" fn(*const xdo_t, c_int, c_int, c_int) -> c_int;
type FnXdoMoveMouseRelative = unsafe extern "C" fn(*const xdo_t, c_int, c_int) -> c_int;
type FnXdoMoveMouseRelativeToWindow =
unsafe extern "C" fn(*const xdo_t, Window, c_int, c_int) -> c_int;
type FnXdoGetMouseLocation =
unsafe extern "C" fn(*const xdo_t, *mut c_int, *mut c_int, *mut c_int) -> c_int;
type FnXdoGetMouseLocation2 =
unsafe extern "C" fn(*const xdo_t, *mut c_int, *mut c_int, *mut c_int, *mut Window) -> c_int;
type FnXdoGetActiveWindow = unsafe extern "C" fn(*const xdo_t, *mut Window) -> c_int;
type FnXdoGetFocusedWindow = unsafe extern "C" fn(*const xdo_t, *mut Window) -> c_int;
type FnXdoGetFocusedWindowSane = unsafe extern "C" fn(*const xdo_t, *mut Window) -> c_int;
type FnXdoGetWindowLocation =
unsafe extern "C" fn(*const xdo_t, Window, *mut c_int, *mut c_int, *mut *mut Screen) -> c_int;
type FnXdoGetWindowSize =
unsafe extern "C" fn(*const xdo_t, Window, *mut c_uint, *mut c_uint) -> c_int;
type FnXdoGetInputState = unsafe extern "C" fn(*const xdo_t) -> c_uint;
type FnXdoActivateWindow = unsafe extern "C" fn(*const xdo_t, Window) -> c_int;
type FnXdoWaitForMouseMoveFrom = unsafe extern "C" fn(*const xdo_t, c_int, c_int) -> c_int;
type FnXdoWaitForMouseMoveTo = unsafe extern "C" fn(*const xdo_t, c_int, c_int) -> c_int;
type FnXdoSetWindowClass =
unsafe extern "C" fn(*const xdo_t, Window, *const c_char, *const c_char) -> c_int;
type FnXdoSearchWindows =
unsafe extern "C" fn(*const xdo_t, *const xdo_search_t, *mut *mut Window, *mut c_uint) -> c_int;
struct XdoLib {
_lib: Library,
xdo_new: FnXdoNew,
xdo_new_with_opened_display: Option<FnXdoNewWithOpenedDisplay>,
xdo_free: FnXdoFree,
xdo_send_keysequence_window: FnXdoSendKeysequenceWindow,
xdo_send_keysequence_window_down: Option<FnXdoSendKeysequenceWindowDown>,
xdo_send_keysequence_window_up: Option<FnXdoSendKeysequenceWindowUp>,
xdo_enter_text_window: Option<FnXdoEnterTextWindow>,
xdo_click_window: Option<FnXdoClickWindow>,
xdo_mouse_down: Option<FnXdoMouseDown>,
xdo_mouse_up: Option<FnXdoMouseUp>,
xdo_move_mouse: Option<FnXdoMoveMouse>,
xdo_move_mouse_relative: Option<FnXdoMoveMouseRelative>,
xdo_move_mouse_relative_to_window: Option<FnXdoMoveMouseRelativeToWindow>,
xdo_get_mouse_location: Option<FnXdoGetMouseLocation>,
xdo_get_mouse_location2: Option<FnXdoGetMouseLocation2>,
xdo_get_active_window: Option<FnXdoGetActiveWindow>,
xdo_get_focused_window: Option<FnXdoGetFocusedWindow>,
xdo_get_focused_window_sane: Option<FnXdoGetFocusedWindowSane>,
xdo_get_window_location: Option<FnXdoGetWindowLocation>,
xdo_get_window_size: Option<FnXdoGetWindowSize>,
xdo_get_input_state: Option<FnXdoGetInputState>,
xdo_activate_window: Option<FnXdoActivateWindow>,
xdo_wait_for_mouse_move_from: Option<FnXdoWaitForMouseMoveFrom>,
xdo_wait_for_mouse_move_to: Option<FnXdoWaitForMouseMoveTo>,
xdo_set_window_class: Option<FnXdoSetWindowClass>,
xdo_search_windows: Option<FnXdoSearchWindows>,
}
impl XdoLib {
fn load() -> Option<Self> {
// https://github.com/rustdesk/rustdesk/issues/13711
const LIB_NAMES: [&str; 3] = ["libxdo.so.4", "libxdo.so.3", "libxdo.so"];
unsafe {
let (lib, lib_name) = LIB_NAMES
.iter()
.find_map(|name| Library::new(name).ok().map(|lib| (lib, *name)))?;
log::info!("libxdo-sys Loaded {}", lib_name);
let xdo_new: FnXdoNew = *lib.get(b"xdo_new").ok()?;
let xdo_free: FnXdoFree = *lib.get(b"xdo_free").ok()?;
let xdo_send_keysequence_window: FnXdoSendKeysequenceWindow =
*lib.get(b"xdo_send_keysequence_window").ok()?;
let xdo_new_with_opened_display = lib
.get(b"xdo_new_with_opened_display")
.ok()
.map(|s: Symbol<FnXdoNewWithOpenedDisplay>| *s);
let xdo_send_keysequence_window_down = lib
.get(b"xdo_send_keysequence_window_down")
.ok()
.map(|s: Symbol<FnXdoSendKeysequenceWindowDown>| *s);
let xdo_send_keysequence_window_up = lib
.get(b"xdo_send_keysequence_window_up")
.ok()
.map(|s: Symbol<FnXdoSendKeysequenceWindowUp>| *s);
let xdo_enter_text_window = lib
.get(b"xdo_enter_text_window")
.ok()
.map(|s: Symbol<FnXdoEnterTextWindow>| *s);
let xdo_click_window = lib
.get(b"xdo_click_window")
.ok()
.map(|s: Symbol<FnXdoClickWindow>| *s);
let xdo_mouse_down = lib
.get(b"xdo_mouse_down")
.ok()
.map(|s: Symbol<FnXdoMouseDown>| *s);
let xdo_mouse_up = lib
.get(b"xdo_mouse_up")
.ok()
.map(|s: Symbol<FnXdoMouseUp>| *s);
let xdo_move_mouse = lib
.get(b"xdo_move_mouse")
.ok()
.map(|s: Symbol<FnXdoMoveMouse>| *s);
let xdo_move_mouse_relative = lib
.get(b"xdo_move_mouse_relative")
.ok()
.map(|s: Symbol<FnXdoMoveMouseRelative>| *s);
let xdo_move_mouse_relative_to_window = lib
.get(b"xdo_move_mouse_relative_to_window")
.ok()
.map(|s: Symbol<FnXdoMoveMouseRelativeToWindow>| *s);
let xdo_get_mouse_location = lib
.get(b"xdo_get_mouse_location")
.ok()
.map(|s: Symbol<FnXdoGetMouseLocation>| *s);
let xdo_get_mouse_location2 = lib
.get(b"xdo_get_mouse_location2")
.ok()
.map(|s: Symbol<FnXdoGetMouseLocation2>| *s);
let xdo_get_active_window = lib
.get(b"xdo_get_active_window")
.ok()
.map(|s: Symbol<FnXdoGetActiveWindow>| *s);
let xdo_get_focused_window = lib
.get(b"xdo_get_focused_window")
.ok()
.map(|s: Symbol<FnXdoGetFocusedWindow>| *s);
let xdo_get_focused_window_sane = lib
.get(b"xdo_get_focused_window_sane")
.ok()
.map(|s: Symbol<FnXdoGetFocusedWindowSane>| *s);
let xdo_get_window_location = lib
.get(b"xdo_get_window_location")
.ok()
.map(|s: Symbol<FnXdoGetWindowLocation>| *s);
let xdo_get_window_size = lib
.get(b"xdo_get_window_size")
.ok()
.map(|s: Symbol<FnXdoGetWindowSize>| *s);
let xdo_get_input_state = lib
.get(b"xdo_get_input_state")
.ok()
.map(|s: Symbol<FnXdoGetInputState>| *s);
let xdo_activate_window = lib
.get(b"xdo_activate_window")
.ok()
.map(|s: Symbol<FnXdoActivateWindow>| *s);
let xdo_wait_for_mouse_move_from = lib
.get(b"xdo_wait_for_mouse_move_from")
.ok()
.map(|s: Symbol<FnXdoWaitForMouseMoveFrom>| *s);
let xdo_wait_for_mouse_move_to = lib
.get(b"xdo_wait_for_mouse_move_to")
.ok()
.map(|s: Symbol<FnXdoWaitForMouseMoveTo>| *s);
let xdo_set_window_class = lib
.get(b"xdo_set_window_class")
.ok()
.map(|s: Symbol<FnXdoSetWindowClass>| *s);
let xdo_search_windows = lib
.get(b"xdo_search_windows")
.ok()
.map(|s: Symbol<FnXdoSearchWindows>| *s);
Some(Self {
_lib: lib,
xdo_new,
xdo_new_with_opened_display,
xdo_free,
xdo_send_keysequence_window,
xdo_send_keysequence_window_down,
xdo_send_keysequence_window_up,
xdo_enter_text_window,
xdo_click_window,
xdo_mouse_down,
xdo_mouse_up,
xdo_move_mouse,
xdo_move_mouse_relative,
xdo_move_mouse_relative_to_window,
xdo_get_mouse_location,
xdo_get_mouse_location2,
xdo_get_active_window,
xdo_get_focused_window,
xdo_get_focused_window_sane,
xdo_get_window_location,
xdo_get_window_size,
xdo_get_input_state,
xdo_activate_window,
xdo_wait_for_mouse_move_from,
xdo_wait_for_mouse_move_to,
xdo_set_window_class,
xdo_search_windows,
})
}
}
}
static XDO_LIB: OnceLock<Option<XdoLib>> = OnceLock::new();
fn get_lib() -> Option<&'static XdoLib> {
XDO_LIB
.get_or_init(|| {
let lib = XdoLib::load();
if lib.is_none() {
log::info!("libxdo-sys libxdo not found, xdo functions will be disabled");
}
lib
})
.as_ref()
}
pub unsafe extern "C" fn xdo_new(display: *const c_char) -> *mut xdo_t {
get_lib().map_or(std::ptr::null_mut(), |lib| (lib.xdo_new)(display))
}
pub unsafe extern "C" fn xdo_new_with_opened_display(
xdpy: *mut Display,
display: *const c_char,
close_display_when_freed: c_int,
) -> *mut xdo_t {
get_lib()
.and_then(|lib| lib.xdo_new_with_opened_display)
.map_or(std::ptr::null_mut(), |f| {
f(xdpy, display, close_display_when_freed)
})
}
pub unsafe extern "C" fn xdo_free(xdo: *mut xdo_t) {
if xdo.is_null() {
return;
}
if let Some(lib) = get_lib() {
(lib.xdo_free)(xdo);
}
}
pub unsafe extern "C" fn xdo_send_keysequence_window(
xdo: *const xdo_t,
window: Window,
keysequence: *const c_char,
delay: useconds_t,
) -> c_int {
get_lib().map_or(1, |lib| {
(lib.xdo_send_keysequence_window)(xdo, window, keysequence, delay)
})
}
pub unsafe extern "C" fn xdo_send_keysequence_window_down(
xdo: *const xdo_t,
window: Window,
keysequence: *const c_char,
delay: useconds_t,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_send_keysequence_window_down)
.map_or(1, |f| f(xdo, window, keysequence, delay))
}
pub unsafe extern "C" fn xdo_send_keysequence_window_up(
xdo: *const xdo_t,
window: Window,
keysequence: *const c_char,
delay: useconds_t,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_send_keysequence_window_up)
.map_or(1, |f| f(xdo, window, keysequence, delay))
}
pub unsafe extern "C" fn xdo_enter_text_window(
xdo: *const xdo_t,
window: Window,
string: *const c_char,
delay: useconds_t,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_enter_text_window)
.map_or(1, |f| f(xdo, window, string, delay))
}
pub unsafe extern "C" fn xdo_click_window(
xdo: *const xdo_t,
window: Window,
button: c_int,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_click_window)
.map_or(1, |f| f(xdo, window, button))
}
pub unsafe extern "C" fn xdo_mouse_down(xdo: *const xdo_t, window: Window, button: c_int) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_mouse_down)
.map_or(1, |f| f(xdo, window, button))
}
pub unsafe extern "C" fn xdo_mouse_up(xdo: *const xdo_t, window: Window, button: c_int) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_mouse_up)
.map_or(1, |f| f(xdo, window, button))
}
pub unsafe extern "C" fn xdo_move_mouse(
xdo: *const xdo_t,
x: c_int,
y: c_int,
screen: c_int,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_move_mouse)
.map_or(1, |f| f(xdo, x, y, screen))
}
pub unsafe extern "C" fn xdo_move_mouse_relative(xdo: *const xdo_t, x: c_int, y: c_int) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_move_mouse_relative)
.map_or(1, |f| f(xdo, x, y))
}
pub unsafe extern "C" fn xdo_move_mouse_relative_to_window(
xdo: *const xdo_t,
window: Window,
x: c_int,
y: c_int,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_move_mouse_relative_to_window)
.map_or(1, |f| f(xdo, window, x, y))
}
pub unsafe extern "C" fn xdo_get_mouse_location(
xdo: *const xdo_t,
x: *mut c_int,
y: *mut c_int,
screen_num: *mut c_int,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_get_mouse_location)
.map_or(1, |f| f(xdo, x, y, screen_num))
}
pub unsafe extern "C" fn xdo_get_mouse_location2(
xdo: *const xdo_t,
x: *mut c_int,
y: *mut c_int,
screen_num: *mut c_int,
window: *mut Window,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_get_mouse_location2)
.map_or(1, |f| f(xdo, x, y, screen_num, window))
}
pub unsafe extern "C" fn xdo_get_active_window(
xdo: *const xdo_t,
window_ret: *mut Window,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_get_active_window)
.map_or(1, |f| f(xdo, window_ret))
}
pub unsafe extern "C" fn xdo_get_focused_window(
xdo: *const xdo_t,
window_ret: *mut Window,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_get_focused_window)
.map_or(1, |f| f(xdo, window_ret))
}
pub unsafe extern "C" fn xdo_get_focused_window_sane(
xdo: *const xdo_t,
window_ret: *mut Window,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_get_focused_window_sane)
.map_or(1, |f| f(xdo, window_ret))
}
pub unsafe extern "C" fn xdo_get_window_location(
xdo: *const xdo_t,
window: Window,
x: *mut c_int,
y: *mut c_int,
screen_ret: *mut *mut Screen,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_get_window_location)
.map_or(1, |f| f(xdo, window, x, y, screen_ret))
}
pub unsafe extern "C" fn xdo_get_window_size(
xdo: *const xdo_t,
window: Window,
width: *mut c_uint,
height: *mut c_uint,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_get_window_size)
.map_or(1, |f| f(xdo, window, width, height))
}
pub unsafe extern "C" fn xdo_get_input_state(xdo: *const xdo_t) -> c_uint {
get_lib()
.and_then(|lib| lib.xdo_get_input_state)
.map_or(0, |f| f(xdo))
}
pub unsafe extern "C" fn xdo_activate_window(xdo: *const xdo_t, wid: Window) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_activate_window)
.map_or(1, |f| f(xdo, wid))
}
pub unsafe extern "C" fn xdo_wait_for_mouse_move_from(
xdo: *const xdo_t,
origin_x: c_int,
origin_y: c_int,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_wait_for_mouse_move_from)
.map_or(1, |f| f(xdo, origin_x, origin_y))
}
pub unsafe extern "C" fn xdo_wait_for_mouse_move_to(
xdo: *const xdo_t,
dest_x: c_int,
dest_y: c_int,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_wait_for_mouse_move_to)
.map_or(1, |f| f(xdo, dest_x, dest_y))
}
pub unsafe extern "C" fn xdo_set_window_class(
xdo: *const xdo_t,
wid: Window,
name: *const c_char,
class: *const c_char,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_set_window_class)
.map_or(1, |f| f(xdo, wid, name, class))
}
pub unsafe extern "C" fn xdo_search_windows(
xdo: *const xdo_t,
search: *const xdo_search_t,
windowlist_ret: *mut *mut Window,
nwindows_ret: *mut c_uint,
) -> c_int {
get_lib()
.and_then(|lib| lib.xdo_search_windows)
.map_or(1, |f| f(xdo, search, windowlist_ret, nwindows_ret))
}

View File

@@ -187,7 +187,10 @@ fn main() {
i += 1;
}
let click_setup = args.is_empty() && arg_exe.to_lowercase().ends_with("install.exe");
let quick_support = args.is_empty() && arg_exe.to_lowercase().ends_with("qs.exe");
#[cfg(windows)]
let quick_support = args.is_empty() && win::is_quick_support_exe(&arg_exe);
#[cfg(not(windows))]
let quick_support = false;
let mut ui = false;
let reader = BinaryReader::default();
@@ -234,4 +237,12 @@ mod win {
.output();
let _allow_err = std::fs::copy(src, &format!("{}\\{}", dir.to_string_lossy(), tgt));
}
/// Check if the executable is a Quick Support version.
/// Note: This function must be kept in sync with `src/core_main.rs`.
#[inline]
pub(super) fn is_quick_support_exe(exe: &str) -> bool {
let exe = exe.to_lowercase();
exe.contains("-qs-") || exe.contains("-qs.exe") || exe.contains("_qs.exe")
}
}

View File

@@ -205,9 +205,13 @@ def sign_files(dir_path, only_ext=None):
if not only_ext[i].startswith("."):
only_ext[i] = "." + only_ext[i]
for root, dirs, files in os.walk(dir_path):
is_signed_dir = "RustDeskPrinterDriver" in root or "usbmmidd_v2" in root
for file in files:
file_path = os.path.join(root, file)
_, ext = os.path.splitext(file_path)
# only sign the exe files in signed dirs
if is_signed_dir and ext not in [".exe"]:
continue
if only_ext and ext not in only_ext:
continue
if ext in SIGN_EXTENSIONS:

View File

@@ -5,8 +5,8 @@ Summary: RPM package
License: GPL-3.0
URL: https://rustdesk.com
Vendor: rustdesk <info@rustdesk.com>
Requires: gtk3 libxcb1 xdotool libXfixes3 alsa-utils libXtst6 libva2 pam gstreamer-plugins-base gstreamer-plugin-pipewire
Recommends: libayatana-appindicator3-1
Requires: gtk3 libxcb1 libXfixes3 alsa-utils libXtst6 libva2 pam gstreamer-plugins-base gstreamer-plugin-pipewire
Recommends: libayatana-appindicator3-1 xdotool
Provides: libdesktop_drop_plugin.so()(64bit), libdesktop_multi_window_plugin.so()(64bit), libfile_selector_linux_plugin.so()(64bit), libflutter_custom_cursor_plugin.so()(64bit), libflutter_linux_gtk.so()(64bit), libscreen_retriever_plugin.so()(64bit), libtray_manager_plugin.so()(64bit), liburl_launcher_linux_plugin.so()(64bit), libwindow_manager_plugin.so()(64bit), libwindow_size_plugin.so()(64bit), libtexture_rgba_renderer_plugin.so()(64bit)
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/

View File

@@ -5,8 +5,8 @@ Summary: RPM package
License: GPL-3.0
URL: https://rustdesk.com
Vendor: rustdesk <info@rustdesk.com>
Requires: gtk3 libxcb libxdo libXfixes alsa-lib libva pam gstreamer1-plugins-base
Recommends: libayatana-appindicator-gtk3
Requires: gtk3 libxcb libXfixes alsa-lib libva pam gstreamer1-plugins-base
Recommends: libayatana-appindicator-gtk3 libxdo
Provides: libdesktop_drop_plugin.so()(64bit), libdesktop_multi_window_plugin.so()(64bit), libfile_selector_linux_plugin.so()(64bit), libflutter_custom_cursor_plugin.so()(64bit), libflutter_linux_gtk.so()(64bit), libscreen_retriever_plugin.so()(64bit), libtray_manager_plugin.so()(64bit), liburl_launcher_linux_plugin.so()(64bit), libwindow_manager_plugin.so()(64bit), libwindow_size_plugin.so()(64bit), libtexture_rgba_renderer_plugin.so()(64bit)
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/

View File

@@ -3,8 +3,8 @@ Version: 1.1.9
Release: 0
Summary: RPM package
License: GPL-3.0
Requires: gtk3 libxcb1 xdotool libXfixes3 alsa-utils libXtst6 libva2 pam gstreamer-plugins-base gstreamer-plugin-pipewire
Recommends: libayatana-appindicator3-1
Requires: gtk3 libxcb1 libXfixes3 alsa-utils libXtst6 libva2 pam gstreamer-plugins-base gstreamer-plugin-pipewire
Recommends: libayatana-appindicator3-1 xdotool
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/

View File

@@ -5,8 +5,8 @@ Summary: RPM package
License: GPL-3.0
URL: https://rustdesk.com
Vendor: rustdesk <info@rustdesk.com>
Requires: gtk3 libxcb libxdo libXfixes alsa-lib libva2 pam gstreamer1-plugins-base
Recommends: libayatana-appindicator-gtk3
Requires: gtk3 libxcb libXfixes alsa-lib libva2 pam gstreamer1-plugins-base
Recommends: libayatana-appindicator-gtk3 libxdo
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/

View File

@@ -140,7 +140,7 @@ pub fn core_main() -> Option<Vec<String>> {
{
_is_quick_support |= !crate::platform::is_installed()
&& args.is_empty()
&& (arg_exe.to_lowercase().contains("-qs-")
&& (is_quick_support_exe(&arg_exe)
|| config::LocalConfig::get_option("pre-elevate-service") == "Y"
|| (!click_setup && crate::platform::is_elevated(None).unwrap_or(false)));
crate::portable_service::client::set_quick_support(_is_quick_support);
@@ -829,3 +829,12 @@ fn is_root() -> bool {
#[allow(unreachable_code)]
crate::platform::is_root()
}
/// Check if the executable is a Quick Support version.
/// Note: This function must be kept in sync with `libs/portable/src/main.rs`.
#[cfg(windows)]
#[inline]
fn is_quick_support_exe(exe: &str) -> bool {
let exe = exe.to_lowercase();
exe.contains("-qs-") || exe.contains("-qs.exe") || exe.contains("_qs.exe")
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", "无法锁定鼠标,相对鼠标模式已禁用"),
("rel-mouse-exit-{}-tip", "按下 {} 退出"),
("rel-mouse-permission-lost-tip", "键盘权限被撤销。相对鼠标模式已被禁用。"),
("Changelog", "更新日志"),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -730,11 +730,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("input note here", "Hier eine Notiz eingeben"),
("note-at-conn-end-tip", "Am Ende der Verbindung um eine Notiz bitten."),
("Show terminal extra keys", "Zusätzliche Tasten des Terminals anzeigen"),
("Relative mouse mode", ""),
("rel-mouse-not-supported-peer-tip", ""),
("rel-mouse-not-ready-tip", ""),
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Relative mouse mode", "Relativer Mausmodus"),
("rel-mouse-not-supported-peer-tip", "Der relative Mausmodus wird von der verbundenen Gegenstelle nicht unterstützt."),
("rel-mouse-not-ready-tip", "Der relative Mausmodus ist noch nicht bereit. Bitte versuchen Sie es erneut."),
("rel-mouse-lock-failed-tip", "Cursor konnte nicht gesperrt werden. Der relative Mausmodus wurde deaktiviert."),
("rel-mouse-exit-{}-tip", "Drücken Sie {} zum Beenden."),
("rel-mouse-permission-lost-tip", "Die Tastaturberechtigung wurde widerrufen. Der relative Mausmodus wurde deaktiviert."),
("Changelog", "Änderungsprotokoll"),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -267,5 +267,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", "Failed to lock cursor. Relative Mouse Mode has been disabled."),
("rel-mouse-exit-{}-tip", "Press {} to exit."),
("rel-mouse-permission-lost-tip", "Keyboard permission was revoked. Relative Mouse Mode has been disabled."),
("keep-awake-during-outgoing-sessions-label", "Keep screen awake during outgoing sessions"),
("keep-awake-during-incoming-sessions-label", "Keep screen awake during incoming sessions"),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -730,11 +730,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("input note here", "saisir la note ici"),
("note-at-conn-end-tip", "Proposer de rédiger une note une fois la connexion terminée"),
("Show terminal extra keys", "Afficher les touches supplémentaires du terminal"),
("Relative mouse mode", ""),
("rel-mouse-not-supported-peer-tip", ""),
("rel-mouse-not-ready-tip", ""),
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Relative mouse mode", "Mode souris relative"),
("rel-mouse-not-supported-peer-tip", "Le mode souris relative nest pas pris en charge par lappareil distant."),
("rel-mouse-not-ready-tip", "Le mode souris relative nest pas encore prêt ; veuillez réessayer."),
("rel-mouse-lock-failed-tip", "Échec du verrouillage du curseur. Le mode souris relative a été désactivé."),
("rel-mouse-exit-{}-tip", "Appuyez sur {} pour quitter."),
("rel-mouse-permission-lost-tip", "Lautorisation de contrôle du clavier a été révoquée. Le mode souris relative a été désactivé."),
("Changelog", "Journal des modifications"),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -727,14 +727,17 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Disable UDP", "UDP letiltása"),
("disable-udp-tip", "Meghatározza, hogy csak TCP-t használjon-e. Ha ez az beállítás engedélyezve van, a RustDesk nem fogja többé használni a 21116-os UDP-portot, helyette a 21116-os TCP-portot fogja használni."),
("server-oss-not-support-tip", "MEGJEGYZÉS: Az OSS RustDesk kiszolgáló nem támogatja ezt a funkciót."),
("input note here", "Megjegyzés bevitele"),
("note-at-conn-end-tip", "Megjegyzés a kapcsolat végén"),
("input note here", "Megjegyzés beírása"),
("note-at-conn-end-tip", "Kérjen megjegyzést a kapcsolat végén"),
("Show terminal extra keys", "További terminálgombok megjelenítése"),
("Relative mouse mode", ""),
("rel-mouse-not-supported-peer-tip", ""),
("rel-mouse-not-ready-tip", ""),
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Relative mouse mode", "Relatív egérmód"),
("rel-mouse-not-supported-peer-tip", "A kapcsolódott partner nem támogatja a relatív egérmódot."),
("rel-mouse-not-ready-tip", "A relatív egérmód még nem elérhető. Próbálja meg újra."),
("rel-mouse-lock-failed-tip", "Nem sikerült zárolni a kurzort. A relatív egérmód le lett tiltva."),
("rel-mouse-exit-{}-tip", "A kilépéshez nyomja meg a(z) {} gombot."),
("rel-mouse-permission-lost-tip", "A billentyűzet-hozzáférés vissza lett vonva. A relatív egérmód le lett tilva."),
("Changelog", "Változáslista"),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -730,11 +730,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("input note here", "Inserisci nota qui"),
("note-at-conn-end-tip", "Visualizza nota alla fine della connessione"),
("Show terminal extra keys", "Visualizza tasti aggiuntivi terminale"),
("Relative mouse mode", ""),
("rel-mouse-not-supported-peer-tip", ""),
("rel-mouse-not-ready-tip", ""),
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Relative mouse mode", "Modalità relativa mouse"),
("rel-mouse-not-supported-peer-tip", "La modalità mouse relativa non è supportata dal peer connesso."),
("rel-mouse-not-ready-tip", "La modalità mouse relativa non è ancora pronta. Riprova."),
("rel-mouse-lock-failed-tip", "Impossibile bloccare il cursore. La modalità mouse relativa è stata disabilitata."),
("rel-mouse-exit-{}-tip", "Premi {} per uscire."),
("rel-mouse-permission-lost-tip", "È stata revocato l'accesso alla tastiera. La modalità mouse relativa è stata disabilitata."),
("Changelog", "Novità programma"),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -3,30 +3,30 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
[
("Status", "상태"),
("Your Desktop", "내 데스크탑"),
("desk_tip", "이 ID와 비밀번호로 데스크에 액세스할 수 있습니다."),
("desk_tip", "이 ID와 비밀번호로 데스크에 액세스할 수 있습니다."),
("Password", "비밀번호"),
("Ready", "준비 완료"),
("Established", "연결됨"),
("connecting_status", "RustDesk 네트워크에 연결 중..."),
("Enable service", "서비스 활성화"),
("Start service", "서비스 시작"),
("Service is running", "서비스가 실행 중 입니다"),
("Service is running", "서비스가 실행 중입니다"),
("Service is not running", "서비스가 실행되지 않았습니다"),
("not_ready_status", "준비되지 않았습니다. 연결을 확인해 주세요"),
("Control Remote Desktop", "원격 데스크탑 제어"),
("Transfer file", "파일 전송"),
("Connect", "연결"),
("Recent sessions", "최근 세션"),
("Address book", "세션 주소록"),
("Address book", "주소록"),
("Confirmation", "확인"),
("TCP tunneling", "TCP 터널링"),
("Remove", "삭제"),
("Refresh random password", "임의의 비밀번호 새로 고침"),
("Set your own password", "자신만의 비밀번호 설정"),
("Enable keyboard/mouse", "키보드/마우스 사용함"),
("Enable clipboard", "클립보드 사용함"),
("Enable file transfer", "파일 전송 사용함"),
("Enable TCP tunneling", "TCP 터널링 사용함"),
("Enable keyboard/mouse", "키보드/마우스 허용"),
("Enable clipboard", "클립보드 허용"),
("Enable file transfer", "파일 전송 허용"),
("Enable TCP tunneling", "TCP 터널링 허용"),
("IP Whitelisting", "IP 화이트리스트"),
("ID/Relay Server", "ID/릴레이 서버"),
("Import server config", "서버 구성 가져오기"),
@@ -81,7 +81,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Please try 1 minute later", "1분 후에 다시 시도하세요"),
("Login Error", "로그인 오류"),
("Successful", "성공"),
("Connected, waiting for image...", "연결되었습니다, 이미지를 기다리는 중..."),
("Connected, waiting for image...", "연결됨, 화면을 기다리는 중..."),
("Name", "이름"),
("Type", "유형"),
("Modified", "수정 날짜"),
@@ -136,20 +136,20 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("ID does not exist", "ID가 존재하지 않습니다"),
("Failed to connect to rendezvous server", "랑데부 서버 연결에 실패했습니다"),
("Please try later", "나중에 시도해 주세요"),
("Remote desktop is offline", "원격 데스크이 오프라인입니다"),
("Remote desktop is offline", "원격 데스크이 오프라인입니다"),
("Key mismatch", "키가 일치하지 않습니다"),
("Timeout", "시간 초과"),
("Failed to connect to relay server", "릴레이 서버 연결에 실패했습니다"),
("Failed to connect via rendezvous server", "랑데부 서버를 통한 연결에 실패했습니다"),
("Failed to connect via relay server", "릴레이 서버를 통한 연결에 실패했습니다"),
("Failed to make direct connection to remote desktop", "원격 데스크톱에 직접 연결에 실패했습니다"),
("Failed to make direct connection to remote desktop", "원격 데스크 직접 연결에 실패했습니다"),
("Set Password", "비밀번호 설정"),
("OS Password", "OS 비밀번호"),
("install_tip", "UAC로 인해 경우에 따라 RustDesk가 원격 쪽에서 제대로 작동하지 않을 수 있습니다. UAC를 피하려면 아래 버튼을 클릭하여 시스템에 RustDesk를 설치하세요."),
("Click to upgrade", "업그레이드"),
("Configure", "구성"),
("config_acc", "데스크을 원격으로 제어하려면 RustDesk에 \"접근성\" 권한을 부여해야 합니다."),
("config_screen", "데스크에 원격으로 액세스하려면 RustDesk에 \"화면 녹화\" 권한을 부여해야 합니다."),
("config_acc", "데스크을 원격으로 제어하려면 RustDesk에 \"접근성\" 권한을 부여해야 합니다."),
("config_screen", "데스크에 원격으로 액세스하려면 RustDesk에 \"화면 녹화\" 권한을 부여해야 합니다."),
("Installing ...", "설치 중..."),
("Install", "설치하기"),
("Installation", "설치"),
@@ -162,7 +162,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Generating ...", "생성 중 ..."),
("Your installation is lower version.", "설치된 버전이 낮습니다."),
("not_close_tcp_tip", "터널을 사용하는 동안에는 이 창을 닫지 마세요"),
("Listening ...", "청취 중 ..."),
("Listening ...", "수신 대기 중 ..."),
("Remote Host", "원격 호스트"),
("Remote Port", "원격 포트"),
("Action", "동작"),
@@ -177,7 +177,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Accept", "수락"),
("Dismiss", "거부"),
("Disconnect", "연결 해제"),
("Enable file copy and paste", "파일 복사 및 붙여넣기 사용함"),
("Enable file copy and paste", "파일 복사 및 붙여넣기 허용"),
("Connected", "연결됨"),
("Direct and encrypted connection", "직접 및 암호화된 연결"),
("Relayed and encrypted connection", "릴레이 및 암호화된 연결"),
@@ -186,9 +186,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enter Remote ID", "원격 ID 입력"),
("Enter your password", "비밀번호 입력"),
("Logging in...", "로그인 중..."),
("Enable RDP session sharing", "RDP 세션 공유 사용함"),
("Enable RDP session sharing", "RDP 세션 공유 허용"),
("Auto Login", "자동 로그인"),
("Enable direct IP access", "직접 IP 액세스 사용함"),
("Enable direct IP access", "직접 IP 액세스 허용"),
("Rename", "이름 바꾸기"),
("Space", "공백"),
("Create desktop shortcut", "바탕 화면 바로가기 만들기"),
@@ -200,13 +200,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Login screen using Wayland is not supported", "Wayland를 사용한 로그인 화면은 지원되지 않습니다"),
("Reboot required", "재부팅이 필요합니다"),
("Unsupported display server", "지원하지 않는 디스플레이 서버"),
("x11 expected", "x11 예상"),
("x11 expected", "x11 환경이 필요합니다"),
("Port", "포트"),
("Settings", "설정"),
("Username", "사용자 이름"),
("Invalid port", "유효하지 않은 포트입니다"),
("Closed manually by the peer", "피어가 수동으로 닫았습니다"),
("Enable remote configuration modification", "원격 구성 수정 사용함"),
("Enable remote configuration modification", "원격 구성 수정 허용"),
("Run without install", "설치 없이 실행"),
("Connect via relay", "릴레이를 통해 연결"),
("Always connect via relay", "항상 릴레이를 통해 연결"),
@@ -214,7 +214,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Login", "로그인"),
("Verify", "확인"),
("Remember me", "기억하기"),
("Trust this device", "이 장치 신뢰"),
("Trust this device", "이 장치 신뢰"),
("Verification code", "인증 코드"),
("verification_tip", "등록한 이메일 주소로 인증 코드가 전송되었으니 인증 코드를 입력하여 로그인을 계속하세요."),
("Logout", "로그아웃"),
@@ -291,7 +291,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Help", "도움말"),
("Failed", "실패"),
("Succeeded", "성공"),
("Someone turns on privacy mode, exit", "누군가 개인정보 보호 모드를 니다, 종료합니다"),
("Someone turns on privacy mode, exit", "누군가 개인정보 보호 모드를 켰습니다, 연결을 종료합니다"),
("Unsupported", "지원되지 않음"),
("Peer denied", "연결 거부됨"),
("Please install plugins", "플러그인을 설치해주세요"),
@@ -311,7 +311,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Use permanent password", "영구 비밀번호 사용"),
("Use both passwords", "두 가지 비밀번호 모두 사용"),
("Set permanent password", "영구 비밀번호 설정"),
("Enable remote restart", "원격 재시작 사용함"),
("Enable remote restart", "원격 재시작 허용"),
("Restart remote device", "원격 장치 다시 시작"),
("Are you sure you want to restart", "다시 시작하시겠습니까"),
("Restarting remote device", "원격 장치를 다시 시작하는 중"),
@@ -344,7 +344,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Follow System", "시스템 설정 따름"),
("Enable hardware codec", "하드웨어 코덱 활성화"),
("Unlock Security Settings", "보안 설정 잠금 해제"),
("Enable audio", "오디오 사용함"),
("Enable audio", "오디오 허용"),
("Unlock Network Settings", "네트워크 설정 잠금 해제"),
("Server", "서버"),
("Direct IP Access", "직접 IP 연결"),
@@ -364,13 +364,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Change", "변경"),
("Start session recording", "세션 녹화 시작"),
("Stop session recording", "세션 녹화 중지"),
("Enable recording session", "세션 녹화 사용함"),
("Enable LAN discovery", "LAN 검색 사용함"),
("Enable recording session", "세션 녹화 허용"),
("Enable LAN discovery", "LAN 검색 허용"),
("Deny LAN discovery", "LAN 검색 거부"),
("Write a message", "메시지 쓰기"),
("Prompt", "프롬프트"),
("Please wait for confirmation of UAC...", "UAC 확인을 기다려주세요..."),
("elevated_foreground_window_tip", "원격 데스크의 현재 창을 작동하려면 더 높은 권한이 필요하므로 일시적으로 마우스와 키보드를 사용할 수 없습니다. 원격 사용자에게 현재 창을 최소화하도록 요청하거나 연결 관리 창에서 권한 상승 버튼을 클릭할 수 있습니다. 이 문제를 방지하려면 원격 장치에 소프트웨어를 설치하는 것이 좋습니다."),
("elevated_foreground_window_tip", "원격 데스크의 현재 창을 작동하려면 더 높은 권한이 필요하므로 일시적으로 마우스와 키보드를 사용할 수 없습니다. 원격 사용자에게 현재 창을 최소화하도록 요청하거나 연결 관리 창에서 권한 상승 버튼을 클릭할 수 있습니다. 이 문제를 방지하려면 원격 장치에 소프트웨어를 설치하는 것이 좋습니다."),
("Disconnected", "연결 끊김"),
("Other", "기타"),
("Confirm before closing multiple tabs", "여러 탭을 닫기 전에 확인"),
@@ -378,7 +378,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Full Access", "전체 액세스"),
("Screen Share", "화면 공유"),
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland는 Ubuntu 21.04 이상 버전이 필요합니다."),
("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland는 상위 버전의 Linux 배포판이 필요합니다. X11 데스크을 사용하거나 OS를 변경하세요."),
("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland는 상위 버전의 Linux 배포판이 필요합니다. X11 데스크을 사용하거나 OS를 변경하세요."),
("JumpLink", "점프 링크"),
("Please Select the screen to be shared(Operate on the peer side).", "공유할 화면을 선택하세요 (피어 측에서 작동)"),
("Show RustDesk", "RustDesk 표시"),
@@ -408,7 +408,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Select local keyboard type", "로컬 키보드 유형 선택"),
("software_render_tip", "Linux에서 Nvidia 그래픽 카드를 사용 중인데 원격 창이 연결 즉시 닫히는 경우 오픈 소스 Nouveau 드라이버로 전환하고 소프트웨어 렌더링을 사용하기로 선택하는 것이 도움이 될 수 있습니다. 소프트웨어를 재시작해야 합니다."),
("Always use software rendering", "항상 소프트웨어 렌더링 사용"),
("config_input", "키보드로 원격 데스크을 제어하려면 RustDesk에 \"입력 모니터링\" 권한을 부여해야 합니다."),
("config_input", "키보드로 원격 데스크을 제어하려면 RustDesk에 \"입력 모니터링\" 권한을 부여해야 합니다."),
("config_microphone", "원격으로 통화하려면 RustDesk에 \"오디오 녹음\" 권한을 부여해야 합니다."),
("request_elevation_tip", "원격 측에 사람이 있는 경우 권한 상승을 요청할 수도 있습니다."),
("Wait", "대기"),
@@ -428,7 +428,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Weak", "약함"),
("Medium", "보통"),
("Strong", "강력"),
("Switch Sides", "측면 전환"),
("Switch Sides", "역할 전환"),
("Please confirm if you want to share your desktop?", "데스크탑을 공유하시겠습니까?"),
("Display", "디스플레이"),
("Default View Style", "기본 보기 스타일"),
@@ -468,14 +468,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("login_linux_tip", "X 데스크탑을 활성화하려면 제어되는 터미널의 Linux 계정에 로그인하세요"),
("verify_rustdesk_password_tip", "RustDesk 비밀번호 확인"),
("remember_account_tip", "이 계정 기억하기"),
("os_account_desk_tip", "이 계정은 원격 OS에 로그인하고 헤드리스에서 데스크 세션을 활성화하는 데 사용됩니다."),
("os_account_desk_tip", "이 계정은 원격 OS에 로그인하고 헤드리스에서 데스크 세션을 활성화하는 데 사용됩니다."),
("OS Account", "OS 계정"),
("another_user_login_title_tip", "다른 사용자가 이미 로그인했습니다"),
("another_user_login_text_tip", "연결 끊기"),
("xorg_not_found_title_tip", "Xorg를 찾을 수 없습니다"),
("xorg_not_found_text_tip", "Xorg를 설치해 주세요"),
("no_desktop_title_tip", "사용 가능한 데스크 환경이 없습니다"),
("no_desktop_text_tip", "GNOME 데스크을 설치해 주세요"),
("no_desktop_title_tip", "사용 가능한 데스크 환경이 없습니다"),
("no_desktop_text_tip", "GNOME 데스크을 설치해 주세요"),
("No need to elevate", "권한 상승이 필요없습니다"),
("System Sound", "시스템 소리"),
("Default", "기본"),
@@ -488,7 +488,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Plugins", "플러그인"),
("Uninstall", "설치 제거"),
("Update", "업데이트"),
("Enable", "사용함"),
("Enable", "허용"),
("Disable", "사용 안 함"),
("Options", "옵션"),
("resolution_original_tip", "원본 해상도"),
@@ -558,7 +558,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Virtual display", "가상 디스플레이"),
("Plug out all", "모든 플러그를 뽑으세요"),
("True color (4:4:4)", "트루컬러 (4:4:4)"),
("Enable blocking user input", "사용자 입력 차단 사용함"),
("Enable blocking user input", "사용자 입력 차단 허용"),
("id_input_tip", "ID, 직접 IP 또는 포트가 있는 도메인 (<domain>:<port>)을 입력할 수 있습니다.\n다른 서버에 있는 장치에 액세스하려면 서버 주소 (<id>@<server_address>?key=<key_value>)를 추가하세요. 예를들어 \n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\n공용 서버의 장치에 액세스하려면 \"<id>@public\"을 입력하세요. 공용 서버에서는 키가 필요하지 않습니다.\n\n첫 번째 연결에서 릴레이 연결을 강제로 사용하려면 ID 끝에 \"/r\"을 추가합니다, 예를들면 \"9123456234/r\"."),
("privacy_mode_impl_mag_tip", "모드 1"),
("privacy_mode_impl_virtual_display_tip", "모드 2"),
@@ -571,8 +571,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("swap-left-right-mouse", "마우스 왼쪽 버튼과 오른쪽 버튼 교체"),
("2FA code", "이중 인증 코드"),
("More", "더 많은"),
("enable-2fa-title", "이중 인증 사용함"),
("enable-2fa-desc", "지금 인증앱을 설정해 주세요. 휴대폰이나 데스크에서 Authy, Microsoft 또는 Google 인증기와 같은 인증기 앱을 사용할 수 있습니다.\n\n앱으로 QR 코드를 스캔하고 앱에 표시된 코드를 입력하면 이중 인증이 가능합니다."),
("enable-2fa-title", "이중 인증 허용"),
("enable-2fa-desc", "지금 인증앱을 설정해 주세요. 휴대폰이나 데스크에서 Authy, Microsoft 또는 Google 인증기와 같은 인증기 앱을 사용할 수 있습니다.\n\n앱으로 QR 코드를 스캔하고 앱에 표시된 코드를 입력하면 이중 인증이 가능합니다."),
("wrong-2fa-code", "코드를 확인할 수 없습니다. 코드와 현지 시간 설정이 올바른지 확인합니다"),
("enter-2fa-title", "이중 인증"),
("Email verification code must be 6 characters.", "이메일 인증 코드는 6자여야 합니다."),
@@ -621,7 +621,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Volume down", "볼륨 낮추기"),
("Power", "전원"),
("Telegram bot", "Telegram 봇"),
("enable-bot-tip", "이 기능을 활성화하면 봇에서 이중 인 코드를 받을 수 있습니다. 또한 연결 알림 기능도 할 수 있습니다."),
("enable-bot-tip", "이 기능을 활성화하면 봇에서 이중 인 코드를 받을 수 있습니다. 또한 연결 알림 기능도 할 수 있습니다."),
("enable-bot-desc", "1. @BotFather와 채팅을 시작합니다.\n2. \"/newbot\" 명령을 보내주세요. 이 단계를 완료하면 토큰을 받게 됩니다.\n3. 새로 만든 봇과 채팅을 시작합니다. \"/hello\"와 같이 앞에 슬래시 (\"/\")로 시작하는 메시지를 보내 활성화합니다."),
("cancel-2fa-confirm-tip", "이중 인증을 취소하시겠습니까?"),
("cancel-bot-confirm-tip", "Telegram 봇을 취소하시겠습니까?"),
@@ -632,7 +632,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Requires at least {} characters", "최소 {}자 이상 필요합니다."),
("Wrong PIN", "잘못된 PIN"),
("Set PIN", "PIN 설정"),
("Enable trusted devices", "신뢰할 수 있는 장치 사용함"),
("Enable trusted devices", "신뢰할 수 있는 장치 허용"),
("Manage trusted devices", "신뢰할 수 있는 장치 관리"),
("Platform", "플랫폼"),
("Days remaining", "일 남음"),
@@ -678,7 +678,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("screenshot-action-tip", "스크린샷을 계속 진행할 방법을 선택해 주세요."),
("Save as", "다른 이름으로 저장"),
("Copy to clipboard", "클립보드에 복사"),
("Enable remote printer", "원격 프린터 사용함"),
("Enable remote printer", "원격 프린터 허용"),
("Downloading {}", "{} 다운로드 중"),
("{} Update", "{} 업데이트"),
("{}-to-update-tip", "{}가 지금 닫히고 새 버전을 설치합니다."),
@@ -693,11 +693,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable IPv6 P2P connection", "IPv6 P2P 연결 사용"),
("Enable UDP hole punching", "UDP 홀 펀칭 사용"),
("View camera", "카메라 보기"),
("Enable camera", "카메라 사용함"),
("Enable camera", "카메라 허용"),
("No cameras", "카메라 없음"),
("view_camera_unsupported_tip", "원격 장치가 카메라 보기를 지원하지 않습니다."),
("Terminal", "터미널"),
("Enable terminal", "터미널 사용함"),
("Enable terminal", "터미널 허용"),
("New tab", "새 탭"),
("Keep terminal sessions on disconnect", "연결이 끊어져도 터미널 세션 유지"),
("Terminal (Run as administrator)", "터미널 (관리자 권한으로 실행)"),
@@ -730,11 +730,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("input note here", "여기에 노트 입력"),
("note-at-conn-end-tip", "연결이 끝날 때 메모 요청"),
("Show terminal extra keys", "터미널 추가 키 표시"),
("Relative mouse mode", ""),
("rel-mouse-not-supported-peer-tip", ""),
("rel-mouse-not-ready-tip", ""),
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Relative mouse mode", "상대 마우스 모드"),
("rel-mouse-not-supported-peer-tip", "연결된 피어에서 상대 마우스 모드를 지원하지 않습니다."),
("rel-mouse-not-ready-tip", "상대 마우스 모드가 아직 준비되지 않았습니다. 다시 시도해 주세요."),
("rel-mouse-lock-failed-tip", "커서 잠금에 실패했습니다. 상대 마우스 모드가 비활성화되었습니다"),
("rel-mouse-exit-{}-tip", "종료하려면 {}을(를) 누르세요."),
("rel-mouse-permission-lost-tip", "키보드 권한이 취소되었습니다. 상대 마우스 모드가 비활성화되었습니다."),
("Changelog", "변경 기록"),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -730,11 +730,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("input note here", "voeg hier een opmerking toe"),
("note-at-conn-end-tip", "Vraag om een opmerking aan het einde van de verbinding"),
("Show terminal extra keys", "Toon extra toetsen voor terminal"),
("Relative mouse mode", ""),
("rel-mouse-not-supported-peer-tip", ""),
("rel-mouse-not-ready-tip", ""),
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Relative mouse mode", "Relatieve muismodus"),
("rel-mouse-not-supported-peer-tip", "De relatieve muismodus wordt niet ondersteund door het externe apparaat."),
("rel-mouse-not-ready-tip", "De relatieve muismodus was nog niet klaar, probeer het later opnieuw."),
("rel-mouse-lock-failed-tip", "Het vergrendelen van de cursor is mislukt. De relatieve muismodus is uitgeschakeld."),
("rel-mouse-exit-{}-tip", "Druk op {} om af te sluiten."),
("rel-mouse-permission-lost-tip", "De toetsenbordcontrole is uitgeschakeld. De relatieve muismodus is uitgeschakeld."),
("Changelog", "Wijzigingenlogboek"),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -13,7 +13,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Service is running", "Usługa uruchomiona"),
("Service is not running", "Usługa nie jest uruchomiona"),
("not_ready_status", "Brak gotowości"),
("Control Remote Desktop", "Połącz się z"),
("Control Remote Desktop", "Steruj pulpitem zdalnym"),
("Transfer file", "Transfer plików"),
("Connect", "Połącz"),
("Recent sessions", "Ostatnie sesje"),
@@ -75,7 +75,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Do you want to enter again?", "Czy chcesz wprowadzić ponownie?"),
("Connection Error", "Błąd połączenia"),
("Error", "Błąd"),
("Reset by the peer", "Połączenie zresetowanie przez zdalne urządzenie"),
("Reset by the peer", "Połączenie zresetowane przez zdalne urządzenie"),
("Connecting...", "Łączenie..."),
("Connection in progress. Please wait.", "Trwa łączenie. Proszę czekać."),
("Please try 1 minute later", "Spróbuj za minutę"),
@@ -120,7 +120,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Original", "Oryginalny"),
("Shrink", "Zmniejsz"),
("Stretch", "Rozciągnij"),
("Scrollbar", "Przewijanie ręczne"),
("Scrollbar", "Pasek przewijania"),
("ScrollAuto", "Przewijanie automatyczne"),
("Good image quality", "Wysoka jakość obrazu"),
("Balanced", "Tryb zbalansowany"),
@@ -161,7 +161,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("End-user license agreement", "Umowa licencyjna użytkownika końcowego"),
("Generating ...", "Trwa generowanie..."),
("Your installation is lower version.", "Twoja instalacja jest w niższej wersji"),
("not_close_tcp_tip", "Podczas korzystanie z tunelowania, nie zamykaj tego okna."),
("not_close_tcp_tip", "Podczas korzystania z tunelowania, nie zamykaj tego okna."),
("Listening ...", "Nasłuchiwanie..."),
("Remote Host", "Host zdalny"),
("Remote Port", "Port zdalny"),
@@ -198,7 +198,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Fix it", "Napraw to"),
("Warning", "Ostrzeżenie"),
("Login screen using Wayland is not supported", "Ekran logowania korzystający z Wayland nie jest obsługiwany"),
("Reboot required", "Wymagany ponowne uruchomienie"),
("Reboot required", "Wymagane ponowne uruchomienie"),
("Unsupported display server", "Nieobsługiwany serwer wyświetlania"),
("x11 expected", "Wymagany jest X11"),
("Port", "Port"),
@@ -225,7 +225,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Add Tag", "Dodaj Tag"),
("Unselect all tags", "Odznacz wszystkie tagi"),
("Network error", "Błąd sieci"),
("Username missed", "Nieprawidłowe nazwa użytkownika"),
("Username missed", "Nieprawidłowa nazwa użytkownika"),
("Password missed", "Nieprawidłowe hasło"),
("Wrong credentials", "Błędne dane uwierzytelniające"),
("The verification code is incorrect or has expired", "Kod weryfikacyjny jest niepoprawny lub wygasł"),
@@ -265,7 +265,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("No permission of file transfer", "Brak uprawnień na przesyłanie plików"),
("Note", "Notatka"),
("Connection", "Połączenie"),
("Share screen", "Udostępnij ekran"),
("Share screen", "Udostępnianie ekranu"),
("Chat", "Czat"),
("Total", "Łącznie"),
("items", "elementów"),
@@ -314,10 +314,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable remote restart", "Włącz zdalne restartowanie"),
("Restart remote device", "Zrestartuj zdalne urządzenie"),
("Are you sure you want to restart", "Czy na pewno uruchomić ponownie"),
("Restarting remote device", "Trwa restartowanie Zdalnego Urządzenia"),
("Restarting remote device", "Trwa restartowanie zdalnego urządzenia"),
("remote_restarting_tip", "Trwa ponownie uruchomienie zdalnego urządzenia, zamknij ten komunikat i ponownie nawiąż za chwilę połączenie używając hasła permanentnego"),
("Copied", "Skopiowano"),
("Exit Fullscreen", "Wyłącz tryb pełnoekranowy"),
("Exit Fullscreen", "Wyłącz tryb pełnoekranowy"),
("Fullscreen", "Tryb pełnoekranowy"),
("Mobile Actions", "Dostępne mobilne polecenia"),
("Select Monitor", "Wybierz ekran"),
@@ -379,7 +379,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Screen Share", "Udostępnianie ekranu"),
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland wymaga Ubuntu 21.04 lub nowszego."),
("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland wymaga nowszej dystrybucji Linuksa. Wypróbuj pulpit X11 lub zmień system operacyjny."),
("JumpLink", "View"),
("JumpLink", "Podgląd"),
("Please Select the screen to be shared(Operate on the peer side).", "Wybierz ekran do udostępnienia (działaj po zdalnego urządzenia)."),
("Show RustDesk", "Pokaż RustDesk"),
("This PC", "Ten komputer"),
@@ -403,13 +403,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Add to address book", "Dodaj do Książki Adresowej"),
("Group", "Grupy"),
("Search", "Szukaj"),
("Closed manually by web console", "Zakończone manualnie z konsoli Web"),
("Closed manually by web console", "Zakończone ręcznie z poziomu konsoli webowej"),
("Local keyboard type", "Lokalny typ klawiatury"),
("Select local keyboard type", "Wybierz lokalny typ klawiatury"),
("software_render_tip", "Jeżeli posiadasz kartę graficzną Nvidia i okno zamyka się natychmiast po nawiązaniu połączenia, instalacja sterownika nouveau i wybór renderowania programowego mogą pomóc. Restart aplikacji jest wymagany."),
("Always use software rendering", "Zawsze używaj renderowania programowego"),
("config_input", "By kontrolować zdalne urządzenie przy pomocy klawiatury, musisz udzielić aplikacji RustDesk uprawnień do \"Urządzeń Wejściowych\"."),
("config_microphone", "Aby umożliwić zdalne rozmowy należy przyznać RuskDesk uprawnienia do \"Nagrań audio\"."),
("config_microphone", "Aby umożliwić zdalne rozmowy należy przyznać RustDesk uprawnienia do \"Nagrań audio\"."),
("request_elevation_tip", "Możesz poprosić o podniesienie uprawnień jeżeli ktoś posiada dostęp do zdalnego urządzenia."),
("Wait", "Czekaj"),
("Elevation Error", "Błąd przy podnoszeniu uprawnień"),
@@ -459,8 +459,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("empty_favorite_tip", "Brak ulubionych?\nZnajdźmy kogoś, z kim możesz się połączyć i dodaj Go do ulubionych!"),
("empty_lan_tip", "Ojej, wygląda na to, że nie odkryliśmy żadnych urządzeń z RustDesk w Twojej sieci."),
("empty_address_book_tip", "Ojej, wygląda na to, że nie ma żadnych wpisów w Twojej książce adresowej."),
("Empty Username", "Pusty użytkownik"),
("Empty Password", "Puste hasło"),
("Empty Username", "Pole nazwy użytkownika jest puste"),
("Empty Password", "Pole hasła jest puste"),
("Me", "Ja"),
("identical_file_tip", "Ten plik jest identyczny z plikiem na drugim komputerze."),
("show_monitors_tip", "Pokaż monitory w zasobniku"),
@@ -729,12 +729,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("server-oss-not-support-tip", "UWAGA: Serwer OSS RustDesk nie obsługuje tej funkcji."),
("input note here", "Wstaw tutaj notatkę"),
("note-at-conn-end-tip", "Poproś o notatkę po zakończeniu połączenia."),
("Show terminal extra keys", ""),
("Relative mouse mode", ""),
("rel-mouse-not-supported-peer-tip", ""),
("rel-mouse-not-ready-tip", ""),
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Show terminal extra keys", "Pokaż dodatkowe klawisze terminala"),
("Relative mouse mode", "Tryb przechwytywania myszy"),
("rel-mouse-not-supported-peer-tip", "Zdalne urządzenie nie obsługuje trybu przechwytywania myszy"),
("rel-mouse-not-ready-tip", "Tryb przechwytywania myszy nie jest gotowy"),
("rel-mouse-lock-failed-tip", "Nie udało się przechwycić kursora myszy"),
("rel-mouse-exit-{}-tip", "Aby wyłączyć tryb przechwytywania myszy, naciśnij {}"),
("rel-mouse-permission-lost-tip", "Utracono uprawnienia do trybu przechwytywania myszy"),
("Changelog", "Dziennik zmian"),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -730,11 +730,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("input note here", "введите заметку"),
("note-at-conn-end-tip", "Запрашивать заметку в конце соединения"),
("Show terminal extra keys", "Показывать дополнительные кнопки терминала"),
("Relative mouse mode", ""),
("rel-mouse-not-supported-peer-tip", ""),
("rel-mouse-not-ready-tip", ""),
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Relative mouse mode", "Режим относительного перемещения мыши"),
("rel-mouse-not-supported-peer-tip", "Режим относительного перемещения мыши не поддерживается подключённым узлом."),
("rel-mouse-not-ready-tip", "Режим относительного перемещения мыши ещё не готов. Попробуйте снова."),
("rel-mouse-lock-failed-tip", "Невозможно заблокировать курсор. Режим относительного перемещения мыши отключён."),
("rel-mouse-exit-{}-tip", "Нажмите {} для выхода."),
("rel-mouse-permission-lost-tip", "Разрешение на использование клавиатуры отменено. Режим относительного перемещения мыши отключён."),
("Changelog", "Журнал изменений"),
("keep-awake-during-outgoing-sessions-label", "Не отключать экран во время исходящих сеансов"),
("keep-awake-during-incoming-sessions-label", "Не отключать экран во время входящих сеансов"),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -49,7 +49,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Mute", "Sustur"),
("Build Date", "Yapım Tarihi"),
("Version", "Sürüm"),
("Home", ""),
("Home", "Anasayfa"),
("Audio Input", "Ses Girişi"),
("Enhancements", "Geliştirmeler"),
("Hardware Codec", "Donanımsal Codec"),
@@ -309,7 +309,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Map mode", "Haritalama modu"),
("Translate mode", "Çeviri modu"),
("Use permanent password", "Kalıcı şifre kullan"),
("Use both passwords", "İki şifreyide kullan"),
("Use both passwords", "İki şifreyi de kullan"),
("Set permanent password", "Kalıcı şifre oluştur"),
("Enable remote restart", "Uzaktan yeniden başlatmayı aktif et"),
("Restart remote device", "Uzaktaki cihazı yeniden başlat"),
@@ -366,7 +366,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Stop session recording", "Oturum kaydını sonlandır"),
("Enable recording session", "Kayıt Oturumunu Aktif Et"),
("Enable LAN discovery", "Yerel Ağ Keşfine İzin Ver"),
("Deny LAN discovery", "Yerl Ağ Keşfine İzin Verme"),
("Deny LAN discovery", "Yerel Ağ Keşfine İzin Verme"),
("Write a message", "Bir mesaj yazın"),
("Prompt", "İstem"),
("Please wait for confirmation of UAC...", "UAC onayı için lütfen bekleyiniz..."),
@@ -568,7 +568,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("input_source_1_tip", "Giriş kaynağı 1"),
("input_source_2_tip", "Giriş kaynağı 2"),
("Swap control-command key", "Kontrol-komut tuşunu değiştir"),
("swap-left-right-mouse", "sol-sağ fareyi değiştir"),
("swap-left-right-mouse", "Sol-sağ fare tuşlarını değiştir"),
("2FA code", "2FA kodu"),
("More", "Daha"),
("enable-2fa-title", "İki faktörlü kimlik doğrulamayı etkinleştir"),
@@ -598,7 +598,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("no_need_privacy_mode_no_physical_displays_tip", "Fiziksel ekran yok, gizlilik modunu kullanmaya gerek yok."),
("Follow remote cursor", "Uzak imleci takip et"),
("Follow remote window focus", "Uzak pencere odağını takip et"),
("default_proxy_tip", ""),
("default_proxy_tip", "Varsayılan protokol ve port Socks5 ve 1080'dir."),
("no_audio_input_device_tip", "Varsayılan protokol ve port, Socks5 ve 1080'dir"),
("Incoming", "Gelen"),
("Outgoing", "Giden"),
@@ -696,8 +696,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable camera", "Kamerayı etkinleştir"),
("No cameras", "Kamera yok"),
("view_camera_unsupported_tip", "Uzak cihaz, kameranın görüntülenmesini desteklemiyor."),
("Terminal", ""),
("Enable terminal", ""),
("Terminal", "Terminal"),
("Enable terminal", "Terminali etkinleştir"),
("New tab", "Yeni sekme"),
("Keep terminal sessions on disconnect", "Bağlantı kesildiğinde terminal oturumlarınıık tut"),
("Terminal (Run as administrator)", "Terminal (Yönetici olarak çalıştır)"),
@@ -730,11 +730,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("input note here", "Notu buraya girin"),
("note-at-conn-end-tip", "Bağlantı bittiğinde not sorulsun"),
("Show terminal extra keys", "Terminal ek tuşlarını göster"),
("Relative mouse mode", ""),
("rel-mouse-not-supported-peer-tip", ""),
("rel-mouse-not-ready-tip", ""),
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Relative mouse mode", "Fareyi göreli modda kullan"),
("rel-mouse-not-supported-peer-tip", "Karşı taraf göreli fare modunu desteklemiyor"),
("rel-mouse-not-ready-tip", "Göreli fare modu henüz hazır değil"),
("rel-mouse-lock-failed-tip", "Göreli fare kilitlenemedi"),
("rel-mouse-exit-{}-tip", "Göreli fare modundan çıkmak için {}"),
("rel-mouse-permission-lost-tip", "Göreli fare izinleri geçerli değil"),
("Changelog", "Değişiklik Günlüğü"),
("keep-awake-during-outgoing-sessions-label", "Giden oturumlar süresince ekranıık tutun"),
("keep-awake-during-incoming-sessions-label", "Gelen oturumlar süresince ekranıık tutun"),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

View File

@@ -736,5 +736,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("rel-mouse-lock-failed-tip", ""),
("rel-mouse-exit-{}-tip", ""),
("rel-mouse-permission-lost-tip", ""),
("Changelog", ""),
("keep-awake-during-outgoing-sessions-label", ""),
("keep-awake-during-incoming-sessions-label", ""),
].iter().cloned().collect();
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,29 +6,26 @@ use hbb_common::{
anyhow::anyhow,
bail,
config::{keys::OPTION_ALLOW_LINUX_HEADLESS, Config},
libc::{c_char, c_int, c_long, c_void},
libc::{c_char, c_int, c_long, c_uint, c_void},
log,
message_proto::{DisplayInfo, Resolution},
regex::{Captures, Regex},
users::{get_user_by_name, os::unix::UserExt},
};
use libxdo_sys::{self, xdo_t, Window};
use std::{
cell::RefCell,
ffi::{OsStr, OsString},
path::{Path, PathBuf},
process::{Child, Command},
string::String,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
sync::atomic::{AtomicBool, Ordering},
sync::Arc,
time::{Duration, Instant},
};
use terminfo::{capability as cap, Database};
use wallpaper;
type Xdo = *const c_void;
pub const PA_SAMPLE_RATE: u32 = 48000;
static mut UNMODIFIED: bool = true;
@@ -86,35 +83,20 @@ lazy_static::lazy_static! {
}
thread_local! {
static XDO: RefCell<Xdo> = RefCell::new(unsafe { xdo_new(std::ptr::null()) });
// XDO context - created via libxdo-sys (which uses dynamic loading stub).
// If libxdo is not available, xdo will be null and xdo-based functions become no-ops.
static XDO: RefCell<*mut xdo_t> = RefCell::new({
let xdo = unsafe { libxdo_sys::xdo_new(std::ptr::null()) };
if xdo.is_null() {
log::warn!("Failed to create xdo context, xdo functions will be disabled");
} else {
log::info!("xdo context created successfully");
}
xdo
});
static DISPLAY: RefCell<*mut c_void> = RefCell::new(unsafe { XOpenDisplay(std::ptr::null())});
}
extern "C" {
fn xdo_get_mouse_location(
xdo: Xdo,
x: *mut c_int,
y: *mut c_int,
screen_num: *mut c_int,
) -> c_int;
fn xdo_move_mouse(xdo: Xdo, x: c_int, y: c_int, screen: c_int) -> c_int;
fn xdo_new(display: *const c_char) -> Xdo;
fn xdo_get_active_window(xdo: Xdo, window: *mut *mut c_void) -> c_int;
fn xdo_get_window_location(
xdo: Xdo,
window: *mut c_void,
x: *mut c_int,
y: *mut c_int,
screen_num: *mut c_int,
) -> c_int;
fn xdo_get_window_size(
xdo: Xdo,
window: *mut c_void,
width: *mut c_int,
height: *mut c_int,
) -> c_int;
}
#[link(name = "X11")]
extern "C" {
fn XOpenDisplay(display_name: *const c_char) -> *mut c_void;
@@ -160,14 +142,19 @@ fn sleep_millis(millis: u64) {
pub fn get_cursor_pos() -> Option<(i32, i32)> {
let mut res = None;
XDO.with(|xdo| {
if let Ok(xdo) = xdo.try_borrow_mut() {
if let Ok(xdo) = xdo.try_borrow() {
if xdo.is_null() {
return;
}
let mut x: c_int = 0;
let mut y: c_int = 0;
unsafe {
xdo_get_mouse_location(*xdo, &mut x as _, &mut y as _, std::ptr::null_mut());
libxdo_sys::xdo_get_mouse_location(
*xdo as *const _,
&mut x as _,
&mut y as _,
std::ptr::null_mut(),
);
}
res = Some((x, y));
}
@@ -178,14 +165,14 @@ pub fn get_cursor_pos() -> Option<(i32, i32)> {
pub fn set_cursor_pos(x: i32, y: i32) -> bool {
let mut res = false;
XDO.with(|xdo| {
match xdo.try_borrow_mut() {
match xdo.try_borrow() {
Ok(xdo) => {
if xdo.is_null() {
log::debug!("set_cursor_pos: xdo is null");
return;
}
unsafe {
let ret = xdo_move_mouse(*xdo, x, y, 0);
let ret = libxdo_sys::xdo_move_mouse(*xdo as *const _, x, y, 0);
if ret != 0 {
log::debug!(
"set_cursor_pos: xdo_move_mouse failed with code {} for coordinates ({}, {})",
@@ -230,22 +217,22 @@ pub fn reset_input_cache() {}
pub fn get_focused_display(displays: Vec<DisplayInfo>) -> Option<usize> {
let mut res = None;
XDO.with(|xdo| {
if let Ok(xdo) = xdo.try_borrow_mut() {
if let Ok(xdo) = xdo.try_borrow() {
if xdo.is_null() {
return;
}
let mut x: c_int = 0;
let mut y: c_int = 0;
let mut width: c_int = 0;
let mut height: c_int = 0;
let mut window: *mut c_void = std::ptr::null_mut();
let mut width: c_uint = 0;
let mut height: c_uint = 0;
let mut window: Window = 0;
unsafe {
if xdo_get_active_window(*xdo, &mut window) != 0 {
if libxdo_sys::xdo_get_active_window(*xdo as *const _, &mut window) != 0 {
return;
}
if xdo_get_window_location(
*xdo,
if libxdo_sys::xdo_get_window_location(
*xdo as *const _,
window,
&mut x as _,
&mut y as _,
@@ -254,11 +241,17 @@ pub fn get_focused_display(displays: Vec<DisplayInfo>) -> Option<usize> {
{
return;
}
if xdo_get_window_size(*xdo, window, &mut width as _, &mut height as _) != 0 {
if libxdo_sys::xdo_get_window_size(
*xdo as *const _,
window,
&mut width,
&mut height,
) != 0
{
return;
}
let center_x = x + width / 2;
let center_y = y + height / 2;
let center_x = x + (width / 2) as c_int;
let center_y = y + (height / 2) as c_int;
res = displays.iter().position(|d| {
center_x >= d.x
&& center_x < d.x + d.width
@@ -497,7 +490,10 @@ fn get_all_term_values(uid: &str) -> Vec<String> {
let Ok(cmdline) = std::fs::read(&cmdline_path) else {
continue;
};
let exe_end = cmdline.iter().position(|&b| b == 0).unwrap_or(cmdline.len());
let exe_end = cmdline
.iter()
.position(|&b| b == 0)
.unwrap_or(cmdline.len());
let exe_str = String::from_utf8_lossy(&cmdline[..exe_end]);
if !re.is_match(&exe_str) {
continue;

View File

@@ -74,6 +74,7 @@ lazy_static::lazy_static! {
pub static ref CONTROL_PERMISSIONS_ARRAY: Arc::<Mutex<Vec<(i32, ControlPermissions)>>> = Default::default();
static ref SWITCH_SIDES_UUID: Arc::<Mutex<HashMap<String, (Instant, uuid::Uuid)>>> = Default::default();
static ref WAKELOCK_SENDER: Arc::<Mutex<std::sync::mpsc::Sender<(usize, usize)>>> = Arc::new(Mutex::new(start_wakelock_thread()));
static ref WAKELOCK_KEEP_AWAKE_OPTION: Arc::<Mutex<Option<bool>>> = Default::default();
}
#[cfg(any(target_os = "windows", target_os = "linux"))]
@@ -906,6 +907,7 @@ impl Connection {
_ = second_timer.tick() => {
#[cfg(windows)]
conn.portable_check();
raii::AuthedConnID::check_wake_lock_on_setting_changed();
if let Some((instant, minute)) = conn.auto_disconnect_timer.as_ref() {
if instant.elapsed().as_secs() > minute * 60 {
conn.send_close_reason_no_retry("Connection failed due to inactivity").await;
@@ -5008,6 +5010,7 @@ impl FileRemoveLogControl {
}
fn start_wakelock_thread() -> std::sync::mpsc::Sender<(usize, usize)> {
// Check if we should keep awake during incoming sessions
use crate::platform::{get_wakelock, WakeLock};
let (tx, rx) = std::sync::mpsc::channel::<(usize, usize)>();
std::thread::spawn(move || {
@@ -5016,9 +5019,15 @@ fn start_wakelock_thread() -> std::sync::mpsc::Sender<(usize, usize)> {
loop {
match rx.recv() {
Ok((conn_count, remote_count)) => {
if conn_count == 0 {
wakelock = None;
log::info!("drop wakelock");
let keep_awake = config::Config::get_bool_option(
keys::OPTION_KEEP_AWAKE_DURING_INCOMING_SESSIONS,
);
*WAKELOCK_KEEP_AWAKE_OPTION.lock().unwrap() = Some(keep_awake);
if conn_count == 0 || !keep_awake {
if wakelock.is_some() {
wakelock = None;
log::info!("drop wakelock");
}
} else {
let mut display = remote_count > 0;
if let Some(_w) = wakelock.as_mut() {
@@ -5329,6 +5338,16 @@ mod raii {
.send((conn_count, remote_count)));
}
pub fn check_wake_lock_on_setting_changed() {
let current = config::Config::get_bool_option(
keys::OPTION_KEEP_AWAKE_DURING_INCOMING_SESSIONS,
);
let cached = *WAKELOCK_KEEP_AWAKE_OPTION.lock().unwrap();
if cached != Some(current) {
Self::check_wake_lock();
}
}
#[cfg(windows)]
pub fn non_port_forward_conn_count() -> usize {
AUTHED_CONNS

View File

@@ -10,12 +10,6 @@ use std::time::Duration;
pub fn start_tray() {
if crate::ui_interface::get_builtin_option(hbb_common::config::keys::OPTION_HIDE_TRAY) == "Y" {
#[cfg(target_os = "macos")]
{
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
}
}
#[cfg(not(target_os = "macos"))]
{
return;
@@ -129,6 +123,11 @@ fn make_tray() -> hbb_common::ResultType<()> {
);
if let tao::event::Event::NewEvents(tao::event::StartCause::Init) = event {
// for fixing https://github.com/rustdesk/rustdesk/discussions/10210#discussioncomment-14600745
// so we start tray, but not to show it
if crate::ui_interface::get_builtin_option(hbb_common::config::keys::OPTION_HIDE_TRAY) == "Y" {
return;
}
// We create the icon once the event loop is actually running
// to prevent issues like https://github.com/tauri-apps/tray-icon/issues/90
let tray = TrayIconBuilder::new()

View File

@@ -268,6 +268,7 @@ class Enhancements: Reactor.Component {
<li #enable-abr><span>{svg_checkmark}</span>{translate("Adaptive bitrate")} (beta)</li>
<li #screen-recording>{translate("Recording")}</li>
{support_remove_wallpaper ? <li #allow-remove-wallpaper><span>{svg_checkmark}</span>{translate("Remove wallpaper during incoming sessions")}</li> : ""}
<li #keep-awake-during-incoming-sessions><span>{svg_checkmark}</span>{translate("keep-awake-during-incoming-sessions-label")}</li>
</menu>
</li>;
}
@@ -288,6 +289,13 @@ class Enhancements: Reactor.Component {
if (is_opt_fixed) {
el.state.disabled = true;
}
} else if (el.id == "keep-awake-during-incoming-sessions") {
var enabled = handler.get_option(el.id) != "N";
el.attributes.toggleClass("selected", enabled);
var is_opt_fixed = handler.is_option_fixed(el.id);
if (is_opt_fixed) {
el.state.disabled = true;
}
}
}
@@ -304,6 +312,8 @@ class Enhancements: Reactor.Component {
}
} else if (v.indexOf("allow-") == 0) {
handler.set_option(v, handler.get_option(v) == 'Y' ? default_option_no : 'Y');
} else if (v == 'keep-awake-during-incoming-sessions') {
handler.set_option(v, handler.get_option(v) != 'N' ? 'N' : default_option_yes);
} else if (v == 'screen-recording') {
var show_root_dir = is_win && handler.is_installed();
var user_dir = handler.video_save_directory(false);