diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index b1f245610..0ffcee0d0 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -318,6 +318,7 @@ class _GeneralState extends State<_General> { hwcodec(), audio(context), record(context), + WaylandCard(), _Card(title: 'Language', children: [language()]), other() ], @@ -1855,14 +1856,80 @@ Widget _Radio(BuildContext context, ); } +class WaylandCard extends StatefulWidget { + const WaylandCard({Key? key}) : super(key: key); + + @override + State createState() => _WaylandCardState(); +} + +class _WaylandCardState extends State { + final restoreTokenKey = 'wayland-restore-token'; + + @override + Widget build(BuildContext context) { + return futureBuilder( + future: bind.mainHandleWaylandScreencastRestoreToken( + key: restoreTokenKey, value: "get"), + hasData: (restoreToken) { + final children = [ + if (restoreToken.isNotEmpty) + _buildClearScreenSelection(context, restoreToken), + ]; + return Offstage( + offstage: children.isEmpty, + child: _Card(title: 'Wayland', children: children), + ); + }, + ); + } + + Widget _buildClearScreenSelection(BuildContext context, String restoreToken) { + onConfirm() async { + final msg = await bind.mainHandleWaylandScreencastRestoreToken( + key: restoreTokenKey, value: "clear"); + gFFI.dialogManager.dismissAll(); + if (msg.isNotEmpty) { + msgBox(gFFI.sessionId, 'custom-nocancel', 'Error', msg, '', + gFFI.dialogManager); + } else { + setState(() {}); + } + } + + showConfirmMsgBox() => msgBoxCommon( + gFFI.dialogManager, + 'Confirmation', + Text( + translate('confirm_clear_Wayland_screen_selection_tip'), + ), + [ + dialogButton('OK', onPressed: onConfirm), + dialogButton('Cancel', + onPressed: () => gFFI.dialogManager.dismissAll()) + ]); + + return _Button( + 'Clear Wayland screen selection', + showConfirmMsgBox, + tip: 'clear_Wayland_screen_selection_tip', + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all( + Theme.of(context).colorScheme.error.withOpacity(0.75)), + ), + ); + } +} + // ignore: non_constant_identifier_names Widget _Button(String label, Function() onPressed, - {bool enabled = true, String? tip}) { + {bool enabled = true, String? tip, ButtonStyle? style}) { var button = ElevatedButton( onPressed: enabled ? onPressed : null, child: Text( translate(label), ).marginSymmetric(horizontal: 15), + style: style, ); StatefulWidget child; if (tip == null) { diff --git a/flutter/lib/web/bridge.dart b/flutter/lib/web/bridge.dart index 668b41268..7cf6aca3f 100644 --- a/flutter/lib/web/bridge.dart +++ b/flutter/lib/web/bridge.dart @@ -1605,5 +1605,10 @@ class RustdeskImpl { throw UnimplementedError(); } + Future mainHandleWaylandScreencastRestoreToken( + {required String key, required String value, dynamic hint}) { + throw UnimplementedError(); + } + void dispose() {} } diff --git a/libs/scrap/src/wayland/pipewire.rs b/libs/scrap/src/wayland/pipewire.rs index 76c8f838d..b946bd1e5 100644 --- a/libs/scrap/src/wayland/pipewire.rs +++ b/libs/scrap/src/wayland/pipewire.rs @@ -30,11 +30,36 @@ lazy_static! { pub static ref RDP_RESPONSE: Mutex> = Mutex::new(None); } +#[inline] +pub fn close_session() { + let _ = RDP_RESPONSE.lock().unwrap().take(); +} + +#[inline] +pub fn is_rdp_session_hold() -> bool { + RDP_RESPONSE.lock().unwrap().is_some() +} + +pub fn try_close_session() { + let mut rdp_res = RDP_RESPONSE.lock().unwrap(); + let mut close = false; + if let Some(rdp_res) = &*rdp_res { + // If is server running and restore token is supported, there's no need to keep the session. + if is_server_running() && rdp_res.is_support_restore_token { + close = true; + } + } + if close { + *rdp_res = None; + } +} + pub struct RdpResponse { pub conn: Arc, pub streams: Vec, pub fd: OwnedFd, pub session: dbus::Path<'static>, + pub is_support_restore_token: bool, } #[derive(Debug, Clone, Copy)] pub struct PwStreamInfo { @@ -476,6 +501,7 @@ pub fn request_remote_desktop() -> Result< OwnedFd, Vec, dbus::Path<'static>, + bool, ), Box, > { @@ -504,6 +530,14 @@ pub fn request_remote_desktop() -> Result< "handle_token".to_string(), Variant(Box::new("u1".to_string())), ); + + let mut is_support_restore_token = false; + if let Ok(version) = screencast_portal::version(&portal) { + if version >= 4 { + is_support_restore_token = true; + } + } + // The following code may be improved. // https://flatpak.github.io/xdg-desktop-portal/#:~:text=To%20avoid%20a%20race%20condition // To avoid a race condition @@ -524,6 +558,7 @@ pub fn request_remote_desktop() -> Result< streams.clone(), session.clone(), failure.clone(), + is_support_restore_token, ), failure_res.clone(), )?; @@ -547,7 +582,13 @@ pub fn request_remote_desktop() -> Result< if let Some(fd_res) = fd_res.clone() { if let Some(session) = session_res.clone() { if !streams_res.is_empty() { - return Ok((conn, fd_res, streams_res.clone(), session)); + return Ok(( + conn, + fd_res, + streams_res.clone(), + session, + is_support_restore_token, + )); } } } @@ -561,6 +602,7 @@ fn on_create_session_response( streams: Arc>>, session: Arc>>>, failure: Arc, + is_support_restore_token: bool, ) -> impl Fn( OrgFreedesktopPortalRequestResponse, &SyncConnection, @@ -591,15 +633,13 @@ fn on_create_session_response( let mut args: PropMap = HashMap::new(); // See `is_server_running()` to understand the following code. if is_server_running() { - if let Ok(version) = screencast_portal::version(&portal) { - if version >= 4 { - let restore_token = config::LocalConfig::get_option(RESTORE_TOKEN_CONF_KEY); - if !restore_token.is_empty() { - args.insert(RESTORE_TOKEN.to_string(), Variant(Box::new(restore_token))); - } - // persist_mode may be configured by the user. - args.insert("persist_mode".to_string(), Variant(Box::new(2u32))); + if is_support_restore_token { + let restore_token = config::LocalConfig::get_option(RESTORE_TOKEN_CONF_KEY); + if !restore_token.is_empty() { + args.insert(RESTORE_TOKEN.to_string(), Variant(Box::new(restore_token))); } + // persist_mode may be configured by the user. + args.insert("persist_mode".to_string(), Variant(Box::new(2u32))); } args.insert( "handle_token".to_string(), @@ -613,7 +653,13 @@ fn on_create_session_response( handle_response( c, path, - on_select_sources_response(fd.clone(), streams.clone(), failure.clone(), ses), + on_select_sources_response( + fd.clone(), + streams.clone(), + failure.clone(), + ses, + is_support_restore_token, + ), failure.clone(), )?; } else { @@ -627,7 +673,13 @@ fn on_create_session_response( handle_response( c, path, - on_select_devices_response(fd.clone(), streams.clone(), failure.clone(), ses), + on_select_devices_response( + fd.clone(), + streams.clone(), + failure.clone(), + ses, + is_support_restore_token, + ), failure.clone(), )?; } @@ -641,6 +693,7 @@ fn on_select_devices_response( streams: Arc>>, failure: Arc, session: dbus::Path<'static>, + is_support_restore_token: bool, ) -> impl Fn( OrgFreedesktopPortalRequestResponse, &SyncConnection, @@ -662,7 +715,13 @@ fn on_select_devices_response( handle_response( c, path, - on_select_sources_response(fd.clone(), streams.clone(), failure.clone(), session), + on_select_sources_response( + fd.clone(), + streams.clone(), + failure.clone(), + session, + is_support_restore_token, + ), failure.clone(), )?; @@ -675,6 +734,7 @@ fn on_select_sources_response( streams: Arc>>, failure: Arc, session: dbus::Path<'static>, + is_support_restore_token: bool, ) -> impl Fn( OrgFreedesktopPortalRequestResponse, &SyncConnection, @@ -696,7 +756,12 @@ fn on_select_sources_response( handle_response( c, path, - on_start_response(fd.clone(), streams.clone(), session.clone()), + on_start_response( + fd.clone(), + streams.clone(), + session.clone(), + is_support_restore_token, + ), failure.clone(), )?; @@ -708,6 +773,7 @@ fn on_start_response( fd: Arc>>, streams: Arc>>, session: dbus::Path<'static>, + is_support_restore_token: bool, ) -> impl Fn( OrgFreedesktopPortalRequestResponse, &SyncConnection, @@ -717,15 +783,13 @@ fn on_start_response( let portal = get_portal(c); // See `is_server_running()` to understand the following code. if is_server_running() { - if let Ok(version) = screencast_portal::version(&portal) { - if version >= 4 { - if let Some(restore_token) = r.results.get(RESTORE_TOKEN) { - if let Some(restore_token) = restore_token.as_str() { - config::LocalConfig::set_option( - RESTORE_TOKEN_CONF_KEY.to_owned(), - restore_token.to_owned(), - ); - } + if is_support_restore_token { + if let Some(restore_token) = r.results.get(RESTORE_TOKEN) { + if let Some(restore_token) = restore_token.as_str() { + config::LocalConfig::set_option( + RESTORE_TOKEN_CONF_KEY.to_owned(), + restore_token.to_owned(), + ); } } } @@ -752,7 +816,7 @@ pub fn get_capturables() -> Result, Box> { }; if rdp_connection.is_none() { - let (conn, fd, streams, session) = request_remote_desktop()?; + let (conn, fd, streams, session, is_support_restore_token) = request_remote_desktop()?; let conn = Arc::new(conn); let rdp_res = RdpResponse { @@ -760,6 +824,7 @@ pub fn get_capturables() -> Result, Box> { streams, fd, session, + is_support_restore_token, }; *rdp_connection = Some(rdp_res); } diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 6ac3570b2..7ec245b28 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -909,6 +909,39 @@ pub fn main_set_local_option(key: String, value: String) { set_local_option(key, value) } +// We do use use `main_get_local_option` and `main_set_local_option`. +// +// 1. For get, the value is stored in the server process. +// 2. For clear, we need to need to return the error mmsg from the server process to flutter. +#[cfg(target_os = "linux")] +pub fn main_handle_wayland_screencast_restore_token(key: String, value: String) -> String { + if value == "get" { + match crate::ipc::get_wayland_screencast_restore_token(key) { + Ok(v) => v, + Err(e) => { + log::error!("Failed to get wayland screencast restore token, {}", e); + "".to_owned() + } + } + } else if value == "clear" { + match crate::ipc::clear_wayland_screencast_restore_token(key.clone()) { + Ok(true) => { + set_local_option(key, "".to_owned()); + "".to_owned() + } + Ok(false) => "Failed to clear, please try again.".to_owned(), + Err(e) => format!("Failed to clear, {}", e), + } + } else { + "".to_owned() + } +} + +#[cfg(not(target_os = "linux"))] +pub fn main_handle_wayland_screencast_restore_token(_key: String, _value: String) -> String { + "".to_owned() +} + pub fn main_get_input_source() -> SyncReturn { #[cfg(not(any(target_os = "android", target_os = "ios")))] let input_source = get_cur_session_input_source(); diff --git a/src/ipc.rs b/src/ipc.rs index 1118f7ff8..bc88fe7f7 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -5,7 +5,10 @@ use std::{ #[cfg(not(windows))] use std::{fs::File, io::prelude::*}; -use crate::privacy_mode::PrivacyModeState; +use crate::{ + privacy_mode::PrivacyModeState, + ui_interface::{get_local_option, set_local_option}, +}; use bytes::Bytes; use parity_tokio_ipc::{ Connection as Conn, ConnectionClient as ConnClient, Endpoint, Incoming, SecurityAttributes, @@ -234,6 +237,8 @@ pub enum Data { CmErr(String), CheckHwcodec, VideoConnCount(Option), + // Although the key is not neccessary, it is used to avoid hardcoding the key. + WaylandScreencastRestoreToken((String, String)), } #[tokio::main(flavor = "current_thread")] @@ -526,6 +531,42 @@ async fn handle(data: Data, stream: &mut Connection) { scrap::hwcodec::start_check_process(true); } } + Data::WaylandScreencastRestoreToken((key, value)) => { + let v = if value == "get" { + let opt = get_local_option(key.clone()); + #[cfg(not(target_os = "linux"))] + { + Some(opt) + } + #[cfg(target_os = "linux")] + { + let v = if opt.is_empty() { + if scrap::wayland::pipewire::is_rdp_session_hold() { + "fake token".to_string() + } else { + "".to_owned() + } + } else { + opt + }; + Some(v) + } + } else if value == "clear" { + set_local_option(key.clone(), "".to_owned()); + #[cfg(target_os = "linux")] + scrap::wayland::pipewire::close_session(); + Some("".to_owned()) + } else { + None + }; + if let Some(v) = v { + allow_err!( + stream + .send(&Data::WaylandScreencastRestoreToken((key, v))) + .await + ); + } + } _ => {} } } @@ -959,6 +1000,35 @@ pub async fn notify_server_to_check_hwcodec() -> ResultType<()> { Ok(()) } +#[tokio::main(flavor = "current_thread")] +pub async fn get_wayland_screencast_restore_token(key: String) -> ResultType { + let v = handle_wayland_screencast_restore_token(key, "get".to_owned()).await?; + Ok(v.unwrap_or_default()) +} + +#[tokio::main(flavor = "current_thread")] +pub async fn clear_wayland_screencast_restore_token(key: String) -> ResultType { + if let Some(v) = handle_wayland_screencast_restore_token(key, "clear".to_owned()).await? { + return Ok(v.is_empty()); + } + return Ok(false); +} + +async fn handle_wayland_screencast_restore_token( + key: String, + value: String, +) -> ResultType> { + let ms_timeout = 1_000; + let mut c = connect(ms_timeout, "").await?; + c.send(&Data::WaylandScreencastRestoreToken((key, value))) + .await?; + if let Some(Data::WaylandScreencastRestoreToken((_key, v))) = c.next_timeout(ms_timeout).await? + { + return Ok(Some(v)); + } + return Ok(None); +} + #[cfg(test)] mod test { use super::*; diff --git a/src/lang/ar.rs b/src/lang/ar.rs index f0ec80aad..00bd3099b 100644 --- a/src/lang/ar.rs +++ b/src/lang/ar.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/bg.rs b/src/lang/bg.rs index 3c3025b8b..e1fa0ddf1 100644 --- a/src/lang/bg.rs +++ b/src/lang/bg.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ca.rs b/src/lang/ca.rs index c4b54b704..76ae6f4d6 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index a6311f0ed..9e0c42055 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", "未找到音频输入设备"), ("Incoming", "被控"), ("Outgoing", "主控"), + ("Clear Wayland screen selection", "清除 Wayland 的屏幕选择"), + ("clear_Wayland_screen_selection_tip", "清除 Wayland 的屏幕选择后,您可以重新选择分享的屏幕。"), + ("confirm_clear_Wayland_screen_selection_tip", "是否确认清除 Wayland 的分享屏幕选择?"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 887fe27e2..4c2cb089c 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", "Nebylo nalezeno žádné vstupní zvukové zařízení."), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 0916e06da..099264b1e 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index f52d7d514..31d1e5a28 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", "Kein Audio-Eingabegerät gefunden."), ("Incoming", "Eingehend"), ("Outgoing", "Ausgehend"), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index fb0a30075..0e196ac3c 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index 4439d9b25..239e85952 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -225,5 +225,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Follow remote window focus", ""), ("default_proxy_tip", "Default protocol and port are Socks5 and 1080"), ("no_audio_input_device_tip", "No audio input device found."), + ("clear_Wayland_screen_selection_tip", "After clearing the screen selection, you can reselect the screen to share."), + ("confirm_clear_Wayland_screen_selection_tip", "Are you sure to clear the Wayland screen selection?"), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 8bd0a24f1..2f26a586f 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 5e857834b..40b7251c5 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/et.rs b/src/lang/et.rs index aa438fb1f..5abe56715 100644 --- a/src/lang/et.rs +++ b/src/lang/et.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 794991f28..2785383b7 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index c9e076f4a..b67838f93 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/he.rs b/src/lang/he.rs index 4684bfd9a..9102a7c41 100644 --- a/src/lang/he.rs +++ b/src/lang/he.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hr.rs b/src/lang/hr.rs index 0601e0244..d2425c586 100644 --- a/src/lang/hr.rs +++ b/src/lang/hr.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 9b2352937..993ff961e 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 35ad2a088..f9b7e2d2b 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 564352091..019517bc2 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", "Nessun dispositivo input audio trovato."), ("Incoming", "In entrata"), ("Outgoing", "In uscita"), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index fa8105085..4bf5aa6df 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index b024506e1..e3c9779d8 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 0e4850921..0ac4fc72d 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lt.rs b/src/lang/lt.rs index c31c3726d..77c79297c 100644 --- a/src/lang/lt.rs +++ b/src/lang/lt.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lv.rs b/src/lang/lv.rs index a1a336acc..67d9bf87a 100644 --- a/src/lang/lv.rs +++ b/src/lang/lv.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", "Nav atrasta neviena audio ievades ierīce."), ("Incoming", "Ienākošie"), ("Outgoing", "Izejošie"), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nb.rs b/src/lang/nb.rs index 6cef742af..5a4bcb48d 100644 --- a/src/lang/nb.rs +++ b/src/lang/nb.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 119a4c8e0..6a0b2cd47 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index a7122431a..ada223be8 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 99bb9f46e..ca5b1beca 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 677b7f08c..764e49047 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 3eddf80d3..7811bf1b7 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index ec9d6bdbf..e738eba1f 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 9c099fa97..cd95c56d3 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", "Nenašlo sa žiadne vstupné zvukové zariadenie."), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 241ed6ca8..48f0028de 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index d323b924d..5497c6a21 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index bc4f9c6e9..e7303e0bf 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 7466d1a5e..d1b86e4b3 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 3e83d16c8..e40d12145 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index dc30f2431..130fb432d 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 20204388a..970aeb7d9 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 571d00261..fd23bfcbf 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index e21f48caf..9df9229d2 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 4628aa182..2354f46e3 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -609,5 +609,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("no_audio_input_device_tip", ""), ("Incoming", ""), ("Outgoing", ""), + ("Clear Wayland screen selection", ""), + ("clear_Wayland_screen_selection_tip", ""), + ("confirm_clear_Wayland_screen_selection_tip", ""), ].iter().cloned().collect(); } diff --git a/src/server/connection.rs b/src/server/connection.rs index 76436f061..1908b6bb4 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -3736,6 +3736,8 @@ mod raii { display_service::reset_resolutions(); #[cfg(windows)] let _ = virtual_display_manager::reset_all(); + #[cfg(target_os = "linux")] + scrap::wayland::pipewire::try_close_session(); } Self::check_wake_lock(); }