mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-07-10 17:25:09 +03:00
Compare commits
3 Commits
a7c55db9ac
...
cd2fff0655
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd2fff0655 | ||
|
|
10f61ffdc2 | ||
|
|
d72952bf93 |
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "إعادة تعيين اختيار إدخال لوحة المفاتيح"),
|
||||
("remember-wayland-keyboard-choice-tip", "لا تسأل مرة أخرى لهذا الكمبيوتر البعيد"),
|
||||
("Why this happens", "سبب حدوث ذلك"),
|
||||
("Switch display", "تبديل الشاشة"),
|
||||
("Show monitor switch button on the main toolbar", "إظهار زر تبديل الشاشة على شريط الأدوات الرئيسي"),
|
||||
("Show on the minimized toolbar", "الإظهار على شريط الأدوات المُصغّر"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Скінуць выбар уводу з клавіятуры"),
|
||||
("remember-wayland-keyboard-choice-tip", "Не пытацца зноў для гэтага аддаленага кампутара"),
|
||||
("Why this happens", "Чаму гэта адбываецца"),
|
||||
("Switch display", "Пераключыць дысплэй"),
|
||||
("Show monitor switch button on the main toolbar", "Паказваць кнопку пераключэння манітора на галоўнай панэлі інструментаў"),
|
||||
("Show on the minimized toolbar", "Паказваць на згорнутай панэлі інструментаў"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Нулиране на избора за въвеждане от клавиатура"),
|
||||
("remember-wayland-keyboard-choice-tip", "Не питай отново за този отдалечен компютър"),
|
||||
("Why this happens", "Защо се случва това"),
|
||||
("Switch display", "Превключване на дисплея"),
|
||||
("Show monitor switch button on the main toolbar", "Показване на бутона за превключване на монитора в главната лента с инструменти"),
|
||||
("Show on the minimized toolbar", "Показване в минимизираната лента с инструменти"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Restableix l'opció d'entrada de teclat"),
|
||||
("remember-wayland-keyboard-choice-tip", "No tornis a preguntar-ho per a aquest equip remot"),
|
||||
("Why this happens", "Per què passa això"),
|
||||
("Switch display", "Canvia de pantalla"),
|
||||
("Show monitor switch button on the main toolbar", "Mostra el botó de canvi de monitor a la barra d’eines principal"),
|
||||
("Show on the minimized toolbar", "Mostra a la barra d’eines minimitzada"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "重置键盘输入选择"),
|
||||
("remember-wayland-keyboard-choice-tip", "以后对这台远程电脑不再询问"),
|
||||
("Why this happens", "了解原因"),
|
||||
("Switch display", "切换显示器"),
|
||||
("Show monitor switch button on the main toolbar", "在主工具栏上显示显示器切换按钮"),
|
||||
("Show on the minimized toolbar", "在最小化工具栏上显示"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Resetovat volbu vstupu z klávesnice"),
|
||||
("remember-wayland-keyboard-choice-tip", "Pro tento vzdálený počítač se již neptat"),
|
||||
("Why this happens", "Proč k tomu dochází"),
|
||||
("Switch display", "Přepnout obrazovku"),
|
||||
("Show monitor switch button on the main toolbar", "Zobrazit tlačítko přepnutí monitoru na hlavním panelu nástrojů"),
|
||||
("Show on the minimized toolbar", "Zobrazit na minimalizovaném panelu nástrojů"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Nulstil valg for tastaturinput"),
|
||||
("remember-wayland-keyboard-choice-tip", "Spørg ikke igen for denne fjerncomputer"),
|
||||
("Why this happens", "Hvorfor dette sker"),
|
||||
("Switch display", "Skift skærm"),
|
||||
("Show monitor switch button on the main toolbar", "Vis knap til skærmskift på hovedværktøjslinjen"),
|
||||
("Show on the minimized toolbar", "Vis på den minimerede værktøjslinje"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Auswahl der Tastatureingabe zurücksetzen"),
|
||||
("remember-wayland-keyboard-choice-tip", "Für diesen entfernten Computer nicht erneut fragen"),
|
||||
("Why this happens", "Warum dies passiert"),
|
||||
("Switch display", "Anzeige wechseln"),
|
||||
("Show monitor switch button on the main toolbar", "Schaltfläche zum Monitorwechsel in der Haupt-Symbolleiste anzeigen"),
|
||||
("Show on the minimized toolbar", "In der minimierten Symbolleiste anzeigen"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Επαναφορά επιλογής εισαγωγής από πληκτρολόγιο"),
|
||||
("remember-wayland-keyboard-choice-tip", "Να μην ερωτηθώ ξανά για αυτόν τον απομακρυσμένο υπολογιστή"),
|
||||
("Why this happens", "Γιατί συμβαίνει αυτό"),
|
||||
("Switch display", "Εναλλαγή οθόνης"),
|
||||
("Show monitor switch button on the main toolbar", "Εμφάνιση κουμπιού εναλλαγής οθόνης στην κύρια γραμμή εργαλείων"),
|
||||
("Show on the minimized toolbar", "Εμφάνιση στην ελαχιστοποιημένη γραμμή εργαλείων"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Restarigi la elekton de klavara enigo"),
|
||||
("remember-wayland-keyboard-choice-tip", "Ne demandi denove por ĉi tiu fora komputilo"),
|
||||
("Why this happens", "Kial ĉi tio okazas"),
|
||||
("Switch display", "Ŝalti ekranon"),
|
||||
("Show monitor switch button on the main toolbar", "Montri ekran-ŝaltan butonon en la ĉefa ilobreto"),
|
||||
("Show on the minimized toolbar", "Montri en la minimumigita ilobreto"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Restablecer la opción de entrada del teclado"),
|
||||
("remember-wayland-keyboard-choice-tip", "No volver a preguntar para este equipo remoto"),
|
||||
("Why this happens", "Por qué ocurre esto"),
|
||||
("Switch display", "Cambiar de pantalla"),
|
||||
("Show monitor switch button on the main toolbar", "Mostrar el botón de cambio de monitor en la barra de herramientas principal"),
|
||||
("Show on the minimized toolbar", "Mostrar en la barra de herramientas minimizada"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Lähtesta klaviatuurisisestuse valik"),
|
||||
("remember-wayland-keyboard-choice-tip", "Ära küsi selle kaugarvuti puhul uuesti"),
|
||||
("Why this happens", "Miks see juhtub"),
|
||||
("Switch display", "Vaheta kuva"),
|
||||
("Show monitor switch button on the main toolbar", "Näita monitori vahetamise nuppu peamisel tööriistaribal"),
|
||||
("Show on the minimized toolbar", "Näita minimeeritud tööriistaribal"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Berrezarri teklatuko sarreraren aukera"),
|
||||
("remember-wayland-keyboard-choice-tip", "Ez galdetu berriro urruneko ordenagailu honetarako"),
|
||||
("Why this happens", "Zergatik gertatzen den hau"),
|
||||
("Switch display", "Aldatu pantaila"),
|
||||
("Show monitor switch button on the main toolbar", "Erakutsi monitorea aldatzeko botoia tresna-barra nagusian"),
|
||||
("Show on the minimized toolbar", "Erakutsi minimizatutako tresna-barran"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "بازنشانی انتخاب ورودی صفحه کلید"),
|
||||
("remember-wayland-keyboard-choice-tip", "برای این رایانه از راه دور دوباره نپرس"),
|
||||
("Why this happens", "چرا این اتفاق میافتد"),
|
||||
("Switch display", "تعویض نمایشگر"),
|
||||
("Show monitor switch button on the main toolbar", "نمایش دکمه تعویض نمایشگر در نوار ابزار اصلی"),
|
||||
("Show on the minimized toolbar", "نمایش در نوار ابزار کوچکشده"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Nollaa näppäimistösyötteen valinta"),
|
||||
("remember-wayland-keyboard-choice-tip", "Älä kysy uudelleen tältä etätietokoneelta"),
|
||||
("Why this happens", "Miksi näin tapahtuu"),
|
||||
("Switch display", "Vaihda näyttöä"),
|
||||
("Show monitor switch button on the main toolbar", "Näytä näytön vaihtopainike päätyökalurivillä"),
|
||||
("Show on the minimized toolbar", "Näytä pienennetyssä työkalurivissä"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Réinitialiser le choix de la saisie au clavier"),
|
||||
("remember-wayland-keyboard-choice-tip", "Ne plus demander pour cet appareil distant"),
|
||||
("Why this happens", "Pourquoi cela se produit"),
|
||||
("Switch display", "Changer d’écran"),
|
||||
("Show monitor switch button on the main toolbar", "Afficher le bouton de changement d’écran dans la barre d’outils principale"),
|
||||
("Show on the minimized toolbar", "Afficher dans la barre d’outils réduite"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "კლავიატურის შეყვანის არჩევანის ჩამოყრა"),
|
||||
("remember-wayland-keyboard-choice-tip", "აღარ მკითხო ამ დისტანციური კომპიუტერისთვის"),
|
||||
("Why this happens", "რატომ ხდება ეს"),
|
||||
("Switch display", "ეკრანის გადართვა"),
|
||||
("Show monitor switch button on the main toolbar", "მონიტორის გადართვის ღილაკის ჩვენება მთავარ ხელსაწყოთა ზოლზე"),
|
||||
("Show on the minimized toolbar", "ჩვენება ჩაკეცილ ხელსაწყოთა ზოლზე"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "કીબોર્ડ ઇનપુટ પસંદગી રિસેટ કરો"),
|
||||
("remember-wayland-keyboard-choice-tip", "આ રિમોટ કમ્પ્યુટર માટે ફરીથી પૂછશો નહીં"),
|
||||
("Why this happens", "આવું શા માટે થાય છે"),
|
||||
("Switch display", "ડિસ્પ્લે બદલો"),
|
||||
("Show monitor switch button on the main toolbar", "મુખ્ય ટૂલબાર પર મોનિટર સ્વિચ બટન બતાવો"),
|
||||
("Show on the minimized toolbar", "ન્યૂનતમ કરેલા ટૂલબાર પર બતાવો"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "אפס את בחירת קלט המקלדת"),
|
||||
("remember-wayland-keyboard-choice-tip", "אל תשאל שוב עבור מחשב מרוחק זה"),
|
||||
("Why this happens", "מדוע זה קורה"),
|
||||
("Switch display", "החלפת צג"),
|
||||
("Show monitor switch button on the main toolbar", "הצגת לחצן החלפת צג בסרגל הכלים הראשי"),
|
||||
("Show on the minimized toolbar", "הצגה בסרגל הכלים הממוזער"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "कीबोर्ड इनपुट चयन रीसेट करें"),
|
||||
("remember-wayland-keyboard-choice-tip", "इस रिमोट कंप्यूटर के लिए दोबारा न पूछें"),
|
||||
("Why this happens", "ऐसा क्यों होता है"),
|
||||
("Switch display", "डिस्प्ले बदलें"),
|
||||
("Show monitor switch button on the main toolbar", "मुख्य टूलबार पर मॉनिटर स्विच बटन दिखाएं"),
|
||||
("Show on the minimized toolbar", "न्यूनतम किए गए टूलबार पर दिखाएं"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Poništi izbor unosa tipkovnicom"),
|
||||
("remember-wayland-keyboard-choice-tip", "Ne pitaj ponovno za ovo udaljeno računalo"),
|
||||
("Why this happens", "Zašto se ovo događa"),
|
||||
("Switch display", "Promijeni zaslon"),
|
||||
("Show monitor switch button on the main toolbar", "Prikaži gumb za prebacivanje monitora na glavnoj alatnoj traci"),
|
||||
("Show on the minimized toolbar", "Prikaži na minimiziranoj alatnoj traci"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Billentyűzetbevitel választásának visszaállítása"),
|
||||
("remember-wayland-keyboard-choice-tip", "Ne kérdezze meg újra ennél a távoli számítógépnél"),
|
||||
("Why this happens", "Miért történik ez"),
|
||||
("Switch display", "Kijelző váltása"),
|
||||
("Show monitor switch button on the main toolbar", "Monitorváltó gomb megjelenítése a fő eszköztáron"),
|
||||
("Show on the minimized toolbar", "Megjelenítés a kis méretű eszköztáron"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Setel ulang pilihan masukan keyboard"),
|
||||
("remember-wayland-keyboard-choice-tip", "Jangan tanya lagi untuk komputer jarak jauh ini"),
|
||||
("Why this happens", "Mengapa ini terjadi"),
|
||||
("Switch display", "Ganti tampilan"),
|
||||
("Show monitor switch button on the main toolbar", "Tampilkan tombol pengalih monitor di bilah alat utama"),
|
||||
("Show on the minimized toolbar", "Tampilkan di bilah alat yang diperkecil"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Ripristina scelta input da tastiera"),
|
||||
("remember-wayland-keyboard-choice-tip", "Non chiedere più per questo computer remoto"),
|
||||
("Why this happens", "Perché accade questo"),
|
||||
("Switch display", "Cambia schermo"),
|
||||
("Show monitor switch button on the main toolbar", "Mostra il pulsante di cambio monitor nella barra degli strumenti principale"),
|
||||
("Show on the minimized toolbar", "Mostra nella barra degli strumenti ridotta a icona"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "キーボード入力の選択をリセット"),
|
||||
("remember-wayland-keyboard-choice-tip", "このリモートコンピューターでは今後確認しない"),
|
||||
("Why this happens", "この問題が起こる理由"),
|
||||
("Switch display", "ディスプレイを切り替え"),
|
||||
("Show monitor switch button on the main toolbar", "メインツールバーにモニター切り替えボタンを表示"),
|
||||
("Show on the minimized toolbar", "最小化したツールバーに表示"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "키보드 입력 선택 초기화"),
|
||||
("remember-wayland-keyboard-choice-tip", "이 원격 컴퓨터에 대해 다시 묻지 않기"),
|
||||
("Why this happens", "이런 현상이 발생하는 이유"),
|
||||
("Switch display", "디스플레이 전환"),
|
||||
("Show monitor switch button on the main toolbar", "기본 도구 모음에 모니터 전환 버튼 표시"),
|
||||
("Show on the minimized toolbar", "최소화된 도구 모음에 표시"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Пернетақта еңгізу таңдауын қалпына келтіру"),
|
||||
("remember-wayland-keyboard-choice-tip", "Осы қашықтағы компьютер үшін қайта сұрамау"),
|
||||
("Why this happens", "Бұл неге болады"),
|
||||
("Switch display", "Дисплейді ауыстыру"),
|
||||
("Show monitor switch button on the main toolbar", "Негізгі құралдар тақтасында мониторды ауыстыру түймесін көрсету"),
|
||||
("Show on the minimized toolbar", "Кішірейтілген құралдар тақтасында көрсету"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Atstatyti klaviatūros įvesties pasirinkimą"),
|
||||
("remember-wayland-keyboard-choice-tip", "Daugiau neklausti dėl šio nuotolinio kompiuterio"),
|
||||
("Why this happens", "Kodėl taip nutinka"),
|
||||
("Switch display", "Perjungti ekraną"),
|
||||
("Show monitor switch button on the main toolbar", "Rodyti monitoriaus perjungimo mygtuką pagrindinėje įrankių juostoje"),
|
||||
("Show on the minimized toolbar", "Rodyti sumažintoje įrankių juostoje"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Atiestatīt tastatūras ievades izvēli"),
|
||||
("remember-wayland-keyboard-choice-tip", "Vairs nejautāt par šo attālo datoru"),
|
||||
("Why this happens", "Kāpēc tas notiek"),
|
||||
("Switch display", "Pārslēgt displeju"),
|
||||
("Show monitor switch button on the main toolbar", "Rādīt monitora pārslēgšanas pogu galvenajā rīkjoslā"),
|
||||
("Show on the minimized toolbar", "Rādīt minimizētajā rīkjoslā"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "കീബോർഡ് ഇൻപുട്ട് തിരഞ്ഞെടുപ്പ് റീസെറ്റ് ചെയ്യുക"),
|
||||
("remember-wayland-keyboard-choice-tip", "ഈ റിമോട്ട് കമ്പ്യൂട്ടറിനായി ഇനി ചോദിക്കരുത്"),
|
||||
("Why this happens", "ഇത് എന്തുകൊണ്ട് സംഭവിക്കുന്നു"),
|
||||
("Switch display", "ഡിസ്പ്ലേ മാറ്റുക"),
|
||||
("Show monitor switch button on the main toolbar", "പ്രധാന ടൂൾബാറിൽ മോണിറ്റർ സ്വിച്ച് ബട്ടൺ കാണിക്കുക"),
|
||||
("Show on the minimized toolbar", "ചെറുതാക്കിയ ടൂൾബാറിൽ കാണിക്കുക"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Tilbakestill valg for tastaturinndata"),
|
||||
("remember-wayland-keyboard-choice-tip", "Ikke spør igjen for denne eksterne datamaskinen"),
|
||||
("Why this happens", "Hvorfor dette skjer"),
|
||||
("Switch display", "Bytt skjerm"),
|
||||
("Show monitor switch button on the main toolbar", "Vis knapp for skjermbytte på hovedverktøylinjen"),
|
||||
("Show on the minimized toolbar", "Vis på den minimerte verktøylinjen"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Keuze voor toetsenbordinvoer opnieuw instellen"),
|
||||
("remember-wayland-keyboard-choice-tip", "Niet meer vragen voor deze externe computer"),
|
||||
("Why this happens", "Waarom dit gebeurt"),
|
||||
("Switch display", "Beeldscherm wisselen"),
|
||||
("Show monitor switch button on the main toolbar", "Knop voor monitorwisseling weergeven op de hoofdwerkbalk"),
|
||||
("Show on the minimized toolbar", "Weergeven op de geminimaliseerde werkbalk"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Zresetuj wybór dotyczący wprowadzania z klawiatury"),
|
||||
("remember-wayland-keyboard-choice-tip", "Nie pytaj ponownie dla tego zdalnego komputera"),
|
||||
("Why this happens", "Dlaczego tak się dzieje"),
|
||||
("Switch display", "Przełącz ekran"),
|
||||
("Show monitor switch button on the main toolbar", "Pokaż przycisk przełączania monitora na głównym pasku narzędzi"),
|
||||
("Show on the minimized toolbar", "Pokaż na zminimalizowanym pasku narzędzi"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Repor escolha de entrada de teclado"),
|
||||
("remember-wayland-keyboard-choice-tip", "Não voltar a perguntar para este computador remoto"),
|
||||
("Why this happens", "Porque é que isto acontece"),
|
||||
("Switch display", "Trocar de ecrã"),
|
||||
("Show monitor switch button on the main toolbar", "Mostrar o botão de troca de monitor na barra de ferramentas principal"),
|
||||
("Show on the minimized toolbar", "Mostrar na barra de ferramentas minimizada"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Redefinir escolha de entrada do teclado"),
|
||||
("remember-wayland-keyboard-choice-tip", "Não perguntar novamente para este computador remoto"),
|
||||
("Why this happens", "Por que isso acontece"),
|
||||
("Switch display", "Trocar de tela"),
|
||||
("Show monitor switch button on the main toolbar", "Mostrar o botão de troca de monitor na barra de ferramentas principal"),
|
||||
("Show on the minimized toolbar", "Mostrar na barra de ferramentas minimizada"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Resetează alegerea pentru introducerea de la tastatură"),
|
||||
("remember-wayland-keyboard-choice-tip", "Nu mai întreba pentru acest computer la distanță"),
|
||||
("Why this happens", "De ce se întâmplă acest lucru"),
|
||||
("Switch display", "Comută afișajul"),
|
||||
("Show monitor switch button on the main toolbar", "Afișează butonul de comutare a monitorului în bara de instrumente principală"),
|
||||
("Show on the minimized toolbar", "Afișează în bara de instrumente minimizată"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Сбросить выбор для ввода с клавиатуры"),
|
||||
("remember-wayland-keyboard-choice-tip", "Больше не спрашивать для этого удалённого компьютера"),
|
||||
("Why this happens", "Почему это происходит"),
|
||||
("Switch display", "Переключить дисплей"),
|
||||
("Show monitor switch button on the main toolbar", "Показывать кнопку переключения монитора на главной панели инструментов"),
|
||||
("Show on the minimized toolbar", "Показывать на свёрнутой панели инструментов"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Reseta s'isseberada de s'insertada cun su tecladu"),
|
||||
("remember-wayland-keyboard-choice-tip", "No torres a preguntare pro custu elaboradore remotu"),
|
||||
("Why this happens", "Pro ite custu càpitat"),
|
||||
("Switch display", "Càmbia ischermu"),
|
||||
("Show monitor switch button on the main toolbar", "Mustra su butone de càmbiu de monitor in sa barra de aina printzipale"),
|
||||
("Show on the minimized toolbar", "Mustra in sa barra de aina minimizada"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Obnoviť voľbu vstupu z klávesnice"),
|
||||
("remember-wayland-keyboard-choice-tip", "Nepýtať sa znova pre tento vzdialený počítač"),
|
||||
("Why this happens", "Prečo sa to deje"),
|
||||
("Switch display", "Prepnúť obrazovku"),
|
||||
("Show monitor switch button on the main toolbar", "Zobraziť tlačidlo prepnutia monitora na hlavnom paneli nástrojov"),
|
||||
("Show on the minimized toolbar", "Zobraziť na minimalizovanom paneli nástrojov"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Ponastavi izbiro vnosa s tipkovnice"),
|
||||
("remember-wayland-keyboard-choice-tip", "Za ta oddaljeni računalnik ne vprašaj več"),
|
||||
("Why this happens", "Zakaj se to dogaja"),
|
||||
("Switch display", "Preklopi zaslon"),
|
||||
("Show monitor switch button on the main toolbar", "Pokaži gumb za preklop monitorja v glavni orodni vrstici"),
|
||||
("Show on the minimized toolbar", "Pokaži v pomanjšani orodni vrstici"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Rivendos zgjedhjen e hyrjes nga tastiera"),
|
||||
("remember-wayland-keyboard-choice-tip", "Mos pyet më për këtë kompjuter në distancë"),
|
||||
("Why this happens", "Pse ndodh kjo"),
|
||||
("Switch display", "Ndërro ekranin"),
|
||||
("Show monitor switch button on the main toolbar", "Shfaq butonin e ndërrimit të monitorit te shiriti kryesor i veglave"),
|
||||
("Show on the minimized toolbar", "Shfaq te shiriti i minimizuar i veglave"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Resetuj izbor unosa sa tastature"),
|
||||
("remember-wayland-keyboard-choice-tip", "Ne pitaj ponovo za ovaj udaljeni računar"),
|
||||
("Why this happens", "Zašto se ovo dešava"),
|
||||
("Switch display", "Промени екран"),
|
||||
("Show monitor switch button on the main toolbar", "Прикажи дугме за пребацивање монитора на главној траци са алаткама"),
|
||||
("Show on the minimized toolbar", "Прикажи на умањеној траци са алаткама"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Återställ val av tangentbordsinmatning"),
|
||||
("remember-wayland-keyboard-choice-tip", "Fråga inte igen för den här fjärrdatorn"),
|
||||
("Why this happens", "Varför detta händer"),
|
||||
("Switch display", "Växla skärm"),
|
||||
("Show monitor switch button on the main toolbar", "Visa knapp för skärmväxling i huvudverktygsfältet"),
|
||||
("Show on the minimized toolbar", "Visa i det minimerade verktygsfältet"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "விசைப்பலகை உள்ளீட்டுத் தேர்வை மீட்டமை"),
|
||||
("remember-wayland-keyboard-choice-tip", "இந்தத் தொலை கணினிக்கு மீண்டும் கேட்க வேண்டாம்"),
|
||||
("Why this happens", "இது ஏன் நிகழ்கிறது"),
|
||||
("Switch display", "திரையை மாற்று"),
|
||||
("Show monitor switch button on the main toolbar", "முதன்மை கருவிப்பட்டையில் திரை மாற்று பொத்தானைக் காட்டு"),
|
||||
("Show on the minimized toolbar", "சிறிதாக்கப்பட்ட கருவிப்பட்டையில் காட்டு"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", ""),
|
||||
("remember-wayland-keyboard-choice-tip", ""),
|
||||
("Why this happens", ""),
|
||||
("Switch display", ""),
|
||||
("Show monitor switch button on the main toolbar", ""),
|
||||
("Show on the minimized toolbar", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "รีเซ็ตตัวเลือกการป้อนข้อมูลจากคีย์บอร์ด"),
|
||||
("remember-wayland-keyboard-choice-tip", "ไม่ต้องถามอีกสำหรับคอมพิวเตอร์ปลายทางนี้"),
|
||||
("Why this happens", "เหตุใดจึงเกิดขึ้น"),
|
||||
("Switch display", "สลับจอแสดงผล"),
|
||||
("Show monitor switch button on the main toolbar", "แสดงปุ่มสลับจอภาพบนแถบเครื่องมือหลัก"),
|
||||
("Show on the minimized toolbar", "แสดงบนแถบเครื่องมือที่ย่อเล็กสุด"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Klavye girişi seçimini sıfırla"),
|
||||
("remember-wayland-keyboard-choice-tip", "Bu uzak bilgisayar için bir daha sorma"),
|
||||
("Why this happens", "Bunun nedeni"),
|
||||
("Switch display", "Ekranı değiştir"),
|
||||
("Show monitor switch button on the main toolbar", "Ana araç çubuğunda monitör değiştirme düğmesini göster"),
|
||||
("Show on the minimized toolbar", "Simge durumuna küçültülmüş araç çubuğunda göster"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "重設鍵盤輸入選擇"),
|
||||
("remember-wayland-keyboard-choice-tip", "不要再為此遠端電腦詢問"),
|
||||
("Why this happens", "發生原因"),
|
||||
("Switch display", "切換螢幕"),
|
||||
("Show monitor switch button on the main toolbar", "在主工具列上顯示螢幕切換按鈕"),
|
||||
("Show on the minimized toolbar", "在最小化工具列上顯示"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Скинути вибір щодо введення з клавіатури"),
|
||||
("remember-wayland-keyboard-choice-tip", "Більше не запитувати для цього віддаленого комп'ютера"),
|
||||
("Why this happens", "Чому це відбувається"),
|
||||
("Switch display", "Перемкнути дисплей"),
|
||||
("Show monitor switch button on the main toolbar", "Показувати кнопку перемикання монітора на головній панелі інструментів"),
|
||||
("Show on the minimized toolbar", "Показувати на згорнутій панелі інструментів"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -758,5 +758,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wayland-keyboard-input-reset-choice-tip", "Đặt lại lựa chọn nhập bàn phím"),
|
||||
("remember-wayland-keyboard-choice-tip", "Không hỏi lại cho máy tính từ xa này"),
|
||||
("Why this happens", "Tại sao điều này xảy ra"),
|
||||
("Switch display", "Chuyển màn hình"),
|
||||
("Show monitor switch button on the main toolbar", "Hiển thị nút chuyển đổi màn hình trên thanh công cụ chính"),
|
||||
("Show on the minimized toolbar", "Hiển thị trên thanh công cụ thu nhỏ"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -462,10 +462,14 @@ impl DesktopManager {
|
||||
let (child_xorg, child_wm) = Self::start_x11(uid, gid, username, display_num, &envs)?;
|
||||
is_child_running.store(true, Ordering::SeqCst);
|
||||
|
||||
// capture the logind session scope (from a live child) for teardown, see
|
||||
// reap_session_scope.
|
||||
let scope_dir = Self::session_scope_dir(child_xorg.id());
|
||||
|
||||
log::info!("Start xorg and wm done, notify and wait xtop x11");
|
||||
allow_err!(tx_res.send("".to_owned()));
|
||||
|
||||
Self::wait_stop_x11(child_xorg, child_wm);
|
||||
Self::wait_stop_x11(child_xorg, child_wm, scope_dir, display_num);
|
||||
log::info!("Wait x11 stop done");
|
||||
Ok(())
|
||||
}
|
||||
@@ -665,7 +669,222 @@ impl DesktopManager {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_wait_stop_x11(child_xorg: &mut Child, child_wm: &mut Child) -> bool {
|
||||
// resolve the "session-<id>.scope" directory pam_systemd put the x session in, read
|
||||
// from a live child pid. cgroup v2 mounts every cgroup under /sys/fs/cgroup, v1/hybrid
|
||||
// keeps the scope under the systemd controller mount; pick by the controller field and
|
||||
// confirm the cgroup is real. empty if there is no such scope (e.g. no logind).
|
||||
fn session_scope_dir(pid: u32) -> String {
|
||||
let path = format!("/proc/{}/cgroup", pid);
|
||||
let content = match std::fs::read_to_string(&path) {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
log::warn!("Failed to read {} to find session scope: {}", path, e);
|
||||
return "".to_owned();
|
||||
}
|
||||
};
|
||||
for line in content.lines() {
|
||||
// "<hierarchy>:<controllers>:<path>"; v2 unified is "0::<path>", the v1
|
||||
// systemd hierarchy is "<n>:name=systemd:<path>".
|
||||
let mut fields = line.splitn(3, ':');
|
||||
let (controllers, cgroup) = match (fields.next(), fields.next(), fields.next()) {
|
||||
(Some(_), Some(c), Some(p)) => (c, p),
|
||||
_ => continue,
|
||||
};
|
||||
let scope = match Self::session_scope(cgroup) {
|
||||
Some(s) => s,
|
||||
None => continue,
|
||||
};
|
||||
let mount = if controllers.is_empty() {
|
||||
"/sys/fs/cgroup"
|
||||
} else if controllers.split(',').any(|c| c == "name=systemd") {
|
||||
"/sys/fs/cgroup/systemd"
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
let dir = format!("{}{}", mount, scope);
|
||||
if Path::new(&format!("{}/cgroup.procs", dir)).exists() {
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
"".to_owned()
|
||||
}
|
||||
|
||||
// the "/.../session-<id>.scope" prefix of a cgroup path, dropping any nested child
|
||||
// cgroup below it so a descendant scope does not get mistaken for the session.
|
||||
fn session_scope(cgroup: &str) -> Option<String> {
|
||||
let mut scope = String::new();
|
||||
for comp in cgroup.split('/').filter(|c| !c.is_empty()) {
|
||||
scope.push('/');
|
||||
scope.push_str(comp);
|
||||
if comp.starts_with("session-") && comp.ends_with(".scope") {
|
||||
return Some(scope);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// on teardown reap the whole session scope subtree, not just the xorg + wm pids:
|
||||
// the per-session pipewire and other desktop children otherwise outlive them and
|
||||
// hold the logind session in "closing", leaking sockets + displays on reconnect
|
||||
// (rustdesk/rustdesk#15183). SIGTERM first so pipewire unlinks its sockets, then
|
||||
// SIGKILL stragglers; skip our own pid (pam put the service in the scope too).
|
||||
fn reap_session_scope(scope_dir: &str) {
|
||||
if scope_dir.is_empty() {
|
||||
return;
|
||||
}
|
||||
let me = std::process::id();
|
||||
// spare the --server's own children and any descendants of them sharing this scope
|
||||
// (see pid_is_spared); only the desktop session's leftovers are reaped.
|
||||
let spared: Vec<u32> = crate::server::CHILD_PROCESS
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|c| c.id())
|
||||
.collect();
|
||||
for sig in [hbb_common::libc::SIGTERM, hbb_common::libc::SIGKILL] {
|
||||
let mut pids = Vec::new();
|
||||
Self::collect_scope_pids(Path::new(scope_dir), &mut pids);
|
||||
let mut any = false;
|
||||
for pid in pids {
|
||||
if pid == me || Self::pid_is_spared(pid, &spared, me) {
|
||||
continue;
|
||||
}
|
||||
any = true;
|
||||
log::info!("Reaping leftover session process {} (signal {})", pid, sig);
|
||||
unsafe {
|
||||
if hbb_common::libc::kill(pid as hbb_common::libc::pid_t, sig) != 0 {
|
||||
let err = std::io::Error::last_os_error();
|
||||
// ESRCH = it already exited (or did between snapshot and now).
|
||||
if err.raw_os_error() != Some(hbb_common::libc::ESRCH) {
|
||||
log::warn!("Failed to signal session process {}: {}", pid, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !any {
|
||||
break;
|
||||
}
|
||||
if sig == hbb_common::libc::SIGTERM {
|
||||
std::thread::sleep(Duration::from_millis(300));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a tracked --server child (the sudo wrapper run_as_user spawns) or any descendant of
|
||||
// one: with use_pty sudo runs --cm-no-ui under a monitor with its own pid, so walk the
|
||||
// parent chain (stopping at the --server) to spare the worker, not just the wrapper.
|
||||
fn pid_is_spared(pid: u32, spared: &[u32], me: u32) -> bool {
|
||||
let mut cur = pid;
|
||||
for _ in 0..32 {
|
||||
if spared.contains(&cur) {
|
||||
return true;
|
||||
}
|
||||
if cur <= 1 || cur == me {
|
||||
return false;
|
||||
}
|
||||
match Self::parent_pid(cur) {
|
||||
Some(ppid) => cur = ppid,
|
||||
None => return false,
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn parent_pid(pid: u32) -> Option<u32> {
|
||||
// /proc/<pid>/stat is "pid (comm) state ppid ..."; comm can contain spaces and ')',
|
||||
// so read the fields after the last ')'.
|
||||
let stat = std::fs::read_to_string(format!("/proc/{}/stat", pid)).ok()?;
|
||||
stat.rsplit_once(')')?
|
||||
.1
|
||||
.split_whitespace()
|
||||
.nth(1)?
|
||||
.parse()
|
||||
.ok()
|
||||
}
|
||||
|
||||
// collect every pid in the cgroup subtree rooted at dir. "cgroup.procs" lists only
|
||||
// the procs directly in a cgroup, so recurse into child cgroup directories to catch
|
||||
// processes the desktop session moved into descendant scopes.
|
||||
fn collect_scope_pids(dir: &Path, out: &mut Vec<u32>) {
|
||||
let procs = dir.join("cgroup.procs");
|
||||
match std::fs::read_to_string(&procs) {
|
||||
Ok(content) => {
|
||||
out.extend(content.lines().filter_map(|l| l.trim().parse::<u32>().ok()));
|
||||
}
|
||||
Err(e) if e.kind() != std::io::ErrorKind::NotFound => {
|
||||
log::warn!("Failed to read {}: {}", procs.display(), e);
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
let entries = match std::fs::read_dir(dir) {
|
||||
Ok(e) => e,
|
||||
Err(e) if e.kind() != std::io::ErrorKind::NotFound => {
|
||||
log::warn!("Failed to list cgroup dir {}: {}", dir.display(), e);
|
||||
return;
|
||||
}
|
||||
Err(_) => return,
|
||||
};
|
||||
for entry in entries {
|
||||
let entry = match entry {
|
||||
Ok(entry) => entry,
|
||||
Err(e) => {
|
||||
log::warn!("Failed to read entry under {}: {}", dir.display(), e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
match entry.file_type() {
|
||||
Ok(t) if t.is_dir() => Self::collect_scope_pids(&entry.path(), out),
|
||||
Ok(_) => {}
|
||||
Err(e) if e.kind() != std::io::ErrorKind::NotFound => {
|
||||
log::warn!("Failed to stat {}: {}", entry.path().display(), e);
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a SIGKILL'd Xorg (how wait_x11_children_exit ends it) leaves "/tmp/.X<n>-lock" and
|
||||
// "/tmp/.X11-unix/X<n>" behind, and get_avail_display() treats either file as "display
|
||||
// in use", so the number is never reused and climbs until none are free
|
||||
// (rustdesk/rustdesk#15183). a clean exit would remove them; do the same on teardown,
|
||||
// but skip it if a live process still holds the lock: another server could have taken
|
||||
// the number in the gap, and removing its files would break that display.
|
||||
fn cleanup_x_display_files(display_num: u32) {
|
||||
let lock = format!("/tmp/.X{}-lock", display_num);
|
||||
if let Ok(content) = std::fs::read_to_string(&lock) {
|
||||
if let Ok(pid) = content.trim().parse::<i32>() {
|
||||
if Self::pid_alive(pid) {
|
||||
log::info!("X display {} still held by pid {}, leaving its files", display_num, pid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for path in [lock, format!("/tmp/.X11-unix/X{}", display_num)] {
|
||||
if let Err(e) = std::fs::remove_file(&path) {
|
||||
if e.kind() != std::io::ErrorKind::NotFound {
|
||||
log::warn!("Failed to remove stale X file {}: {}", path, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// signal-0 probe: the pid exists if kill succeeds or fails with EPERM (alive but not
|
||||
// ours); only ESRCH means it is gone.
|
||||
fn pid_alive(pid: i32) -> bool {
|
||||
unsafe {
|
||||
if hbb_common::libc::kill(pid as hbb_common::libc::pid_t, 0) == 0 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
std::io::Error::last_os_error().raw_os_error() == Some(hbb_common::libc::EPERM)
|
||||
}
|
||||
|
||||
fn try_wait_stop_x11(
|
||||
child_xorg: &mut Child,
|
||||
child_wm: &mut Child,
|
||||
scope_dir: &str,
|
||||
display_num: u32,
|
||||
) -> bool {
|
||||
let mut desktop_manager = DESKTOP_MANAGER.lock().unwrap();
|
||||
let mut exited = true;
|
||||
if let Some(desktop_manager) = &mut (*desktop_manager) {
|
||||
@@ -677,6 +896,8 @@ impl DesktopManager {
|
||||
if exited {
|
||||
log::debug!("Wait x11 children exiting");
|
||||
Self::wait_x11_children_exit(child_xorg, child_wm);
|
||||
Self::reap_session_scope(scope_dir);
|
||||
Self::cleanup_x_display_files(display_num);
|
||||
desktop_manager
|
||||
.is_child_running
|
||||
.store(false, Ordering::SeqCst);
|
||||
@@ -686,9 +907,14 @@ impl DesktopManager {
|
||||
exited
|
||||
}
|
||||
|
||||
fn wait_stop_x11(mut child_xorg: Child, mut child_wm: Child) {
|
||||
fn wait_stop_x11(
|
||||
mut child_xorg: Child,
|
||||
mut child_wm: Child,
|
||||
scope_dir: String,
|
||||
display_num: u32,
|
||||
) {
|
||||
loop {
|
||||
if Self::try_wait_stop_x11(&mut child_xorg, &mut child_wm) {
|
||||
if Self::try_wait_stop_x11(&mut child_xorg, &mut child_wm, &scope_dir, display_num) {
|
||||
break;
|
||||
}
|
||||
std::thread::sleep(Duration::from_millis(super::SERVICE_INTERVAL));
|
||||
@@ -806,3 +1032,54 @@ fn pam_get_service_name() -> String {
|
||||
"gdm".to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn session_scope_truncates_at_first_scope() {
|
||||
assert_eq!(
|
||||
DesktopManager::session_scope("/user.slice/user-1000.slice/session-3.scope").as_deref(),
|
||||
Some("/user.slice/user-1000.slice/session-3.scope")
|
||||
);
|
||||
// a nested child scope must not be mistaken for the session
|
||||
assert_eq!(
|
||||
DesktopManager::session_scope(
|
||||
"/user.slice/user-1000.slice/session-3.scope/app-foo.scope"
|
||||
)
|
||||
.as_deref(),
|
||||
Some("/user.slice/user-1000.slice/session-3.scope")
|
||||
);
|
||||
assert_eq!(
|
||||
DesktopManager::session_scope(
|
||||
"/user.slice/user-1000.slice/user@1000.service/app.slice/x.service"
|
||||
),
|
||||
None
|
||||
);
|
||||
assert_eq!(DesktopManager::session_scope("/"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collect_scope_pids_walks_descendant_cgroups() {
|
||||
// regression for #15183: pids in descendant cgroups must be collected too
|
||||
let base = std::env::temp_dir().join(format!("rustdesk-cgtest-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&base);
|
||||
let scope = base.join("session-3.scope");
|
||||
let child = scope.join("app-foo.scope");
|
||||
let nested = child.join("deeper.scope");
|
||||
std::fs::create_dir_all(&nested).unwrap();
|
||||
std::fs::create_dir_all(scope.join("empty.scope")).unwrap();
|
||||
std::fs::write(scope.join("cgroup.procs"), "100\n101\n").unwrap();
|
||||
std::fs::write(scope.join("cgroup.controllers"), "memory pids\n").unwrap();
|
||||
std::fs::write(child.join("cgroup.procs"), "200\n").unwrap();
|
||||
std::fs::write(nested.join("cgroup.procs"), "300\n").unwrap();
|
||||
|
||||
let mut pids = Vec::new();
|
||||
DesktopManager::collect_scope_pids(&scope, &mut pids);
|
||||
pids.sort();
|
||||
let _ = std::fs::remove_dir_all(&base);
|
||||
|
||||
assert_eq!(pids, vec![100, 101, 200, 300]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user