mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-11-27 14:59:02 +08:00
fix: wayland delete restore token (#7988)
* fix: wayland delete restore token Signed-off-by: fufesou <shuanglongchen@yeah.net> * Wayland close session when clearing restore token Signed-off-by: fufesou <shuanglongchen@yeah.net> * fix build Signed-off-by: fufesou <shuanglongchen@yeah.net> * Refact Wayland option Signed-off-by: fufesou <shuanglongchen@yeah.net> * Wayland clear screen selection, fake token Signed-off-by: fufesou <shuanglongchen@yeah.net> * fix build web Signed-off-by: fufesou <shuanglongchen@yeah.net> * fix: build Signed-off-by: fufesou <shuanglongchen@yeah.net> * chore Signed-off-by: fufesou <shuanglongchen@yeah.net> --------- Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
a31a68ba17
commit
bbe9017318
@ -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<T>(BuildContext context,
|
||||
);
|
||||
}
|
||||
|
||||
class WaylandCard extends StatefulWidget {
|
||||
const WaylandCard({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<WaylandCard> createState() => _WaylandCardState();
|
||||
}
|
||||
|
||||
class _WaylandCardState extends State<WaylandCard> {
|
||||
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<Color>(
|
||||
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) {
|
||||
|
@ -1605,5 +1605,10 @@ class RustdeskImpl {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
Future<String> mainHandleWaylandScreencastRestoreToken(
|
||||
{required String key, required String value, dynamic hint}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
void dispose() {}
|
||||
}
|
||||
|
@ -30,11 +30,36 @@ lazy_static! {
|
||||
pub static ref RDP_RESPONSE: Mutex<Option<RdpResponse>> = 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<SyncConnection>,
|
||||
pub streams: Vec<PwStreamInfo>,
|
||||
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<PwStreamInfo>,
|
||||
dbus::Path<'static>,
|
||||
bool,
|
||||
),
|
||||
Box<dyn Error>,
|
||||
> {
|
||||
@ -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<Mutex<Vec<PwStreamInfo>>>,
|
||||
session: Arc<Mutex<Option<dbus::Path<'static>>>>,
|
||||
failure: Arc<AtomicBool>,
|
||||
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<Mutex<Vec<PwStreamInfo>>>,
|
||||
failure: Arc<AtomicBool>,
|
||||
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<Mutex<Vec<PwStreamInfo>>>,
|
||||
failure: Arc<AtomicBool>,
|
||||
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<Mutex<Option<OwnedFd>>>,
|
||||
streams: Arc<Mutex<Vec<PwStreamInfo>>>,
|
||||
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<Vec<PipeWireCapturable>, Box<dyn Error>> {
|
||||
};
|
||||
|
||||
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<Vec<PipeWireCapturable>, Box<dyn Error>> {
|
||||
streams,
|
||||
fd,
|
||||
session,
|
||||
is_support_restore_token,
|
||||
};
|
||||
*rdp_connection = Some(rdp_res);
|
||||
}
|
||||
|
@ -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<String> {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
let input_source = get_cur_session_input_source();
|
||||
|
72
src/ipc.rs
72
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<usize>),
|
||||
// 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<String> {
|
||||
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<bool> {
|
||||
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<Option<String>> {
|
||||
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::*;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user