feat: take screenshot (#11591)

* feat: take screenshot

Signed-off-by: fufesou <linlong1266@gmail.com>

* screenshot, vram temp switch capturer

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix: misspelling

Signed-off-by: fufesou <linlong1266@gmail.com>

* screenshot, taking

Signed-off-by: fufesou <linlong1266@gmail.com>

* screenshot, rgba stride

Signed-off-by: fufesou <linlong1266@gmail.com>

* Bumps 1.4.0

Signed-off-by: fufesou <linlong1266@gmail.com>

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou 2025-04-30 17:23:35 +08:00 committed by GitHub
parent 2864e1984a
commit c626c2414d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
82 changed files with 948 additions and 96 deletions

View file

@ -38,7 +38,7 @@ env:
# https://github.com/rustdesk/rustdesk/actions/runs/14414119794/job/40427970174 # https://github.com/rustdesk/rustdesk/actions/runs/14414119794/job/40427970174
# 2. Update the `VCPKG_COMMIT_ID` in `ci.yml` and `playground.yml`. # 2. Update the `VCPKG_COMMIT_ID` in `ci.yml` and `playground.yml`.
VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
VERSION: "1.3.9" VERSION: "1.4.0"
NDK_VERSION: "r27c" NDK_VERSION: "r27c"
#signing keys env variable checks #signing keys env variable checks
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}" ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"

View file

@ -17,7 +17,7 @@ env:
TAG_NAME: "nightly" TAG_NAME: "nightly"
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite" VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
VERSION: "1.3.9" VERSION: "1.4.0"
NDK_VERSION: "r26d" NDK_VERSION: "r26d"
#signing keys env variable checks #signing keys env variable checks
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}" ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"

4
Cargo.lock generated
View file

@ -5857,7 +5857,7 @@ dependencies = [
[[package]] [[package]]
name = "rustdesk" name = "rustdesk"
version = "1.3.9" version = "1.4.0"
dependencies = [ dependencies = [
"android-wakelock", "android-wakelock",
"android_logger", "android_logger",
@ -5960,7 +5960,7 @@ dependencies = [
[[package]] [[package]]
name = "rustdesk-portable-packer" name = "rustdesk-portable-packer"
version = "1.3.9" version = "1.4.0"
dependencies = [ dependencies = [
"brotli", "brotli",
"dirs 5.0.1", "dirs 5.0.1",

View file

@ -1,6 +1,6 @@
[package] [package]
name = "rustdesk" name = "rustdesk"
version = "1.3.9" version = "1.4.0"
authors = ["rustdesk <info@rustdesk.com>"] authors = ["rustdesk <info@rustdesk.com>"]
edition = "2021" edition = "2021"
build= "build.rs" build= "build.rs"

View file

@ -18,7 +18,7 @@ AppDir:
id: rustdesk id: rustdesk
name: rustdesk name: rustdesk
icon: rustdesk icon: rustdesk
version: 1.3.9 version: 1.4.0
exec: usr/share/rustdesk/rustdesk exec: usr/share/rustdesk/rustdesk
exec_args: $@ exec_args: $@
apt: apt:

View file

@ -18,7 +18,7 @@ AppDir:
id: rustdesk id: rustdesk
name: rustdesk name: rustdesk
icon: rustdesk icon: rustdesk
version: 1.3.9 version: 1.4.0
exec: usr/share/rustdesk/rustdesk exec: usr/share/rustdesk/rustdesk
exec_args: $@ exec_args: $@
apt: apt:

View file

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -15,7 +16,7 @@ bool isEditOsPassword = false;
class TTextMenu { class TTextMenu {
final Widget child; final Widget child;
final VoidCallback onPressed; final VoidCallback? onPressed;
Widget? trailingIcon; Widget? trailingIcon;
bool divider; bool divider;
TTextMenu( TTextMenu(
@ -294,6 +295,41 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
), ),
onPressed: () => ffi.recordingModel.toggle())); onPressed: () => ffi.recordingModel.toggle()));
} }
// to-do:
// 1. Web desktop
// 2. Mobile, copy the image to the clipboard
if (isDesktop) {
final isScreenshotSupported = bind.sessionGetCommonSync(
sessionId: sessionId, key: 'is_screenshot_supported', param: '');
if ('true' == isScreenshotSupported) {
v.add(TTextMenu(
child: Text(ffi.ffiModel.timerScreenshot != null
? '${translate('Taking screenshot')} ...'
: translate('Take screenshot')),
onPressed: ffi.ffiModel.timerScreenshot != null
? null
: () {
if (pi.currentDisplay == kAllDisplayValue) {
msgBox(
sessionId,
'custom-nook-nocancel-hasclose-info',
'Take screenshot',
'screenshot-merged-screen-not-supported-tip',
'',
ffi.dialogManager);
} else {
bind.sessionTakeScreenshot(
sessionId: sessionId, display: pi.currentDisplay);
ffi.ffiModel.timerScreenshot =
Timer(Duration(seconds: 30), () {
ffi.ffiModel.timerScreenshot = null;
});
}
},
));
}
}
// fingerprint // fingerprint
if (!(isDesktop || isWebDesktop)) { if (!(isDesktop || isWebDesktop)) {
v.add(TTextMenu( v.add(TTextMenu(

View file

@ -220,7 +220,8 @@ const double kDefaultQuality = 50;
const double kMaxQuality = 100; const double kMaxQuality = 100;
const double kMaxMoreQuality = 2000; const double kMaxMoreQuality = 2000;
const String kKeyPrinterIncommingJobAction = 'printer-incomming-job-action'; // incomming (should be incoming) is kept, because change it will break the previous setting.
const String kKeyPrinterIncomingJobAction = 'printer-incomming-job-action';
const String kValuePrinterIncomingJobDismiss = 'dismiss'; const String kValuePrinterIncomingJobDismiss = 'dismiss';
const String kValuePrinterIncomingJobDefault = ''; const String kValuePrinterIncomingJobDefault = '';
const String kValuePrinterIncomingJobSelected = 'selected'; const String kValuePrinterIncomingJobSelected = 'selected';

View file

@ -1908,7 +1908,7 @@ class __PrinterState extends State<_Printer> {
final scrollController = ScrollController(); final scrollController = ScrollController();
return ListView(controller: scrollController, children: [ return ListView(controller: scrollController, children: [
outgoing(context), outgoing(context),
incomming(context), incoming(context),
]).marginOnly(bottom: _kListViewBottomMargin); ]).marginOnly(bottom: _kListViewBottomMargin);
} }
@ -1995,15 +1995,15 @@ class __PrinterState extends State<_Printer> {
return _Card(title: 'Outgoing Print Jobs', children: children); return _Card(title: 'Outgoing Print Jobs', children: children);
} }
Widget incomming(BuildContext context) { Widget incoming(BuildContext context) {
onRadioChanged(String value) async { onRadioChanged(String value) async {
await bind.mainSetLocalOption( await bind.mainSetLocalOption(
key: kKeyPrinterIncommingJobAction, value: value); key: kKeyPrinterIncomingJobAction, value: value);
setState(() {}); setState(() {});
} }
PrinterOptions printerOptions = PrinterOptions.load(); PrinterOptions printerOptions = PrinterOptions.load();
return _Card(title: 'Incomming Print Jobs', children: [ return _Card(title: 'Incoming Print Jobs', children: [
_Radio(context, _Radio(context,
value: kValuePrinterIncomingJobDismiss, value: kValuePrinterIncomingJobDismiss,
groupValue: printerOptions.action, groupValue: printerOptions.action,

View file

@ -695,9 +695,9 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
); );
if (index != null) { if (index != null) {
if (index < mobileActionMenus.length) { if (index < mobileActionMenus.length) {
mobileActionMenus[index].onPressed.call(); mobileActionMenus[index].onPressed?.call();
} else if (index < mobileActionMenus.length + more.length) { } else if (index < mobileActionMenus.length + more.length) {
menus[index - mobileActionMenus.length].onPressed.call(); menus[index - mobileActionMenus.length].onPressed?.call();
} }
} }
}(); }();
@ -770,7 +770,7 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
elevation: 8, elevation: 8,
); );
if (index != null && index < menus.length) { if (index != null && index < menus.length) {
menus[index].onPressed.call(); menus[index].onPressed?.call();
} }
}); });
} }
@ -1267,7 +1267,7 @@ void showOptions(
title: resolution.child, title: resolution.child,
onTap: () { onTap: () {
close(); close();
resolution.onPressed(); resolution.onPressed?.call();
}, },
)); ));
} }
@ -1279,7 +1279,7 @@ void showOptions(
title: virtualDisplayMenu.child, title: virtualDisplayMenu.child,
onTap: () { onTap: () {
close(); close();
virtualDisplayMenu.onPressed(); virtualDisplayMenu.onPressed?.call();
}, },
)); ));
} }

View file

@ -243,7 +243,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
Widget build(BuildContext context) { Widget build(BuildContext context) {
Provider.of<FfiModel>(context); Provider.of<FfiModel>(context);
final outgoingOnly = bind.isOutgoingOnly(); final outgoingOnly = bind.isOutgoingOnly();
final incommingOnly = bind.isIncomingOnly(); final incomingOnly = bind.isIncomingOnly();
final customClientSection = CustomSettingsSection( final customClientSection = CustomSettingsSection(
child: Column( child: Column(
children: [ children: [
@ -728,7 +728,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
}); });
}, },
), ),
if (!incommingOnly) if (!incomingOnly)
SettingsTile.switchTile( SettingsTile.switchTile(
title: title:
Text(translate('Automatically record outgoing sessions')), Text(translate('Automatically record outgoing sessions')),

View file

@ -478,9 +478,9 @@ class _ViewCameraPageState extends State<ViewCameraPage>
); );
if (index != null) { if (index != null) {
if (index < mobileActionMenus.length) { if (index < mobileActionMenus.length) {
mobileActionMenus[index].onPressed.call(); mobileActionMenus[index].onPressed?.call();
} else if (index < mobileActionMenus.length + more.length) { } else if (index < mobileActionMenus.length + more.length) {
menus[index - mobileActionMenus.length].onPressed.call(); menus[index - mobileActionMenus.length].onPressed?.call();
} }
} }
}(); }();
@ -553,7 +553,7 @@ class _ViewCameraPageState extends State<ViewCameraPage>
elevation: 8, elevation: 8,
); );
if (index != null && index < menus.length) { if (index != null && index < menus.length) {
menus[index].onPressed.call(); menus[index].onPressed?.call();
} }
}); });
} }

View file

@ -34,6 +34,7 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';
import 'package:file_picker/file_picker.dart';
import '../common.dart'; import '../common.dart';
import '../utils/image.dart' as img; import '../utils/image.dart' as img;
@ -119,6 +120,8 @@ class FfiModel with ChangeNotifier {
RxBool waitForFirstImage = true.obs; RxBool waitForFirstImage = true.obs;
bool isRefreshing = false; bool isRefreshing = false;
Timer? timerScreenshot;
Rect? get rect => _rect; Rect? get rect => _rect;
bool get isOriginalResolutionSet => bool get isOriginalResolutionSet =>
_pi.tryGetDisplayIfNotAllDisplay()?.isOriginalResolutionSet ?? false; _pi.tryGetDisplayIfNotAllDisplay()?.isOriginalResolutionSet ?? false;
@ -216,6 +219,7 @@ class FfiModel with ChangeNotifier {
_timer = null; _timer = null;
clearPermissions(); clearPermissions();
waitForImageTimer?.cancel(); waitForImageTimer?.cancel();
timerScreenshot?.cancel();
} }
setConnectionType(String peerId, bool secure, bool direct) { setConnectionType(String peerId, bool secure, bool direct) {
@ -414,12 +418,82 @@ class FfiModel with ChangeNotifier {
} }
} else if (name == "printer_request") { } else if (name == "printer_request") {
_handlePrinterRequest(evt, sessionId, peerId); _handlePrinterRequest(evt, sessionId, peerId);
} else if (name == 'screenshot') {
_handleScreenshot(evt, sessionId, peerId);
} else { } else {
debugPrint('Event is not handled in the fixed branch: $name'); debugPrint('Event is not handled in the fixed branch: $name');
} }
}; };
} }
_handleScreenshot(
Map<String, dynamic> evt, SessionID sessionId, String peerId) {
timerScreenshot?.cancel();
timerScreenshot = null;
final msg = evt['msg'] ?? '';
final msgBoxType = 'custom-nook-nocancel-hasclose';
final msgBoxTitle = 'Take screenshot';
final dialogManager = parent.target!.dialogManager;
if (msg.isNotEmpty) {
msgBox(sessionId, msgBoxType, msgBoxTitle, msg, '', dialogManager);
} else {
final msgBoxText = 'screenshot-action-tip';
close() {
dialogManager.dismissAll();
}
saveAs() {
close();
Future.delayed(Duration.zero, () async {
final ts = DateTime.now().millisecondsSinceEpoch ~/ 1000;
String? outputFile = await FilePicker.platform.saveFile(
dialogTitle: '${translate('Save as')}...',
fileName: 'screenshot_$ts.png',
allowedExtensions: ['png'],
type: FileType.custom,
);
if (outputFile == null) {
bind.sessionHandleScreenshot(sessionId: sessionId, action: '2');
} else {
final res = await bind.sessionHandleScreenshot(
sessionId: sessionId, action: '0:$outputFile');
if (res.isNotEmpty) {
msgBox(sessionId, 'custom-nook-nocancel-hasclose-error',
'Take screenshot', res, '', dialogManager);
}
}
});
}
copyToClipboard() {
bind.sessionHandleScreenshot(sessionId: sessionId, action: '1');
close();
}
cancel() {
bind.sessionHandleScreenshot(sessionId: sessionId, action: '2');
close();
}
final List<Widget> buttons = [
dialogButton('${translate('Save as')}...', onPressed: saveAs),
dialogButton('Copy to clipboard', onPressed: copyToClipboard),
dialogButton('Cancel', onPressed: cancel),
];
dialogManager.dismissAll();
dialogManager.show(
(setState, close, context) => CustomAlertDialog(
title: null,
content: SelectionArea(
child: msgboxContent(msgBoxType, msgBoxTitle, msgBoxText)),
actions: buttons,
),
tag: '$msgBoxType-$msgBoxTitle-$msgBoxTitle',
);
}
}
_handlePrinterRequest( _handlePrinterRequest(
Map<String, dynamic> evt, SessionID sessionId, String peerId) { Map<String, dynamic> evt, SessionID sessionId, String peerId) {
final id = evt['id']; final id = evt['id'];
@ -451,7 +525,7 @@ class FfiModel with ChangeNotifier {
if (saveSettings.value || dontShowAgain.value) { if (saveSettings.value || dontShowAgain.value) {
bind.mainSetLocalOption(key: kKeyPrinterSelected, value: printerName); bind.mainSetLocalOption(key: kKeyPrinterSelected, value: printerName);
bind.mainSetLocalOption( bind.mainSetLocalOption(
key: kKeyPrinterIncommingJobAction, key: kKeyPrinterIncomingJobAction,
value: defaultOrSelectedGroupValue.value); value: defaultOrSelectedGroupValue.value);
} }
if (dontShowAgain.value) { if (dontShowAgain.value) {
@ -463,7 +537,7 @@ class FfiModel with ChangeNotifier {
onCancel() { onCancel() {
if (dontShowAgain.value) { if (dontShowAgain.value) {
bind.mainSetLocalOption( bind.mainSetLocalOption(
key: kKeyPrinterIncommingJobAction, key: kKeyPrinterIncomingJobAction,
value: kValuePrinterIncomingJobDismiss); value: kValuePrinterIncomingJobDismiss);
} }
close(); close();

View file

@ -13,7 +13,7 @@ class PrinterOptions {
required this.printerName}); required this.printerName});
static PrinterOptions load() { static PrinterOptions load() {
var action = bind.mainGetLocalOption(key: kKeyPrinterIncommingJobAction); var action = bind.mainGetLocalOption(key: kKeyPrinterIncomingJobAction);
if (![ if (![
kValuePrinterIncomingJobDismiss, kValuePrinterIncomingJobDismiss,
kValuePrinterIncomingJobDefault, kValuePrinterIncomingJobDefault,
@ -28,7 +28,7 @@ class PrinterOptions {
if (action == kValuePrinterIncomingJobSelected) { if (action == kValuePrinterIncomingJobSelected) {
action = kValuePrinterIncomingJobDefault; action = kValuePrinterIncomingJobDefault;
bind.mainSetLocalOption( bind.mainSetLocalOption(
key: kKeyPrinterIncommingJobAction, key: kKeyPrinterIncomingJobAction,
value: kValuePrinterIncomingJobDefault); value: kValuePrinterIncomingJobDefault);
if (printerNames.isEmpty) { if (printerNames.isEmpty) {
selectedPrinterName = ''; selectedPrinterName = '';

View file

@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# 1.1.9-1 works for android, but for ios it becomes 1.1.91, need to set it to 1.1.9-a.1 for iOS, will get 1.1.9.1, but iOS store not allow 4 numbers # 1.1.9-1 works for android, but for ios it becomes 1.1.91, need to set it to 1.1.9-a.1 for iOS, will get 1.1.9.1, but iOS store not allow 4 numbers
version: 1.3.9+57 version: 1.4.0+58
environment: environment:
sdk: '^3.1.0' sdk: '^3.1.0'

@ -1 +1 @@
Subproject commit 3afaf6494475ef58dcaaae6b4e6d2303cc3d632b Subproject commit 42aad01a517d4de7420ddcb7e99c29bd9f6d2b5a

View file

@ -1,6 +1,6 @@
[package] [package]
name = "rustdesk-portable-packer" name = "rustdesk-portable-packer"
version = "1.3.9" version = "1.4.0"
edition = "2021" edition = "2021"
description = "RustDesk Remote Desktop" description = "RustDesk Remote Desktop"

View file

@ -197,3 +197,40 @@ pub fn convert_to_yuv(
} }
Ok(()) Ok(())
} }
#[cfg(not(target_os = "ios"))]
pub fn convert(captured: &PixelBuffer, pixfmt: crate::Pixfmt, dst: &mut Vec<u8>) -> ResultType<()> {
if captured.pixfmt() == pixfmt {
dst.extend_from_slice(captured.data());
return Ok(());
}
let src = captured.data();
let src_stride = captured.stride();
let src_pixfmt = captured.pixfmt();
let src_width = captured.width();
let src_height = captured.height();
let unsupported = format!(
"unsupported pixfmt conversion: {src_pixfmt:?} -> {:?}",
pixfmt
);
match (src_pixfmt, pixfmt) {
(crate::Pixfmt::BGRA, crate::Pixfmt::RGBA) | (crate::Pixfmt::RGBA, crate::Pixfmt::BGRA) => {
dst.resize(src.len(), 0);
call_yuv!(ABGRToARGB(
src.as_ptr(),
src_stride[0] as _,
dst.as_mut_ptr(),
src_stride[0] as _,
src_width as _,
src_height as _,
));
}
_ => {
bail!(unsupported);
}
}
Ok(())
}

View file

@ -63,6 +63,7 @@ pub enum ImageFormat {
} }
#[repr(C)] #[repr(C)]
#[derive(Clone)]
pub struct ImageRgb { pub struct ImageRgb {
pub raw: Vec<u8>, pub raw: Vec<u8>,
pub w: usize, pub w: usize,

View file

@ -1,5 +1,5 @@
pkgname=rustdesk pkgname=rustdesk
pkgver=1.3.9 pkgver=1.4.0
pkgrel=0 pkgrel=0
epoch= epoch=
pkgdesc="" pkgdesc=""

View file

@ -1,5 +1,5 @@
Name: rustdesk Name: rustdesk
Version: 1.3.9 Version: 1.4.0
Release: 0 Release: 0
Summary: RPM package Summary: RPM package
License: GPL-3.0 License: GPL-3.0

View file

@ -1,5 +1,5 @@
Name: rustdesk Name: rustdesk
Version: 1.3.9 Version: 1.4.0
Release: 0 Release: 0
Summary: RPM package Summary: RPM package
License: GPL-3.0 License: GPL-3.0

View file

@ -1,5 +1,5 @@
Name: rustdesk Name: rustdesk
Version: 1.3.9 Version: 1.4.0
Release: 0 Release: 0
Summary: RPM package Summary: RPM package
License: GPL-3.0 License: GPL-3.0

View file

@ -85,6 +85,7 @@ pub use super::lang::*;
pub mod file_trait; pub mod file_trait;
pub mod helper; pub mod helper;
pub mod io_loop; pub mod io_loop;
pub mod screenshot;
pub const MILLI1: Duration = Duration::from_millis(1); pub const MILLI1: Duration = Duration::from_millis(1);
pub const SEC30: Duration = Duration::from_secs(30); pub const SEC30: Duration = Duration::from_secs(30);
@ -3336,6 +3337,7 @@ pub enum Data {
CloseVoiceCall, CloseVoiceCall,
ResetDecoder(Option<usize>), ResetDecoder(Option<usize>),
RenameFile((i32, String, String, bool)), RenameFile((i32, String, String, bool)),
TakeScreenshot((i32, String)),
} }
/// Keycode for key events. /// Keycode for key events.

View file

@ -962,6 +962,15 @@ impl<T: InvokeUiSession> Remote<T> {
} }
} }
}, },
Data::TakeScreenshot((display, sid)) => {
let mut msg = Message::new();
msg.set_screenshot_request(ScreenshotRequest {
display,
sid,
..Default::default()
});
allow_err!(peer.send(&msg).await);
}
_ => {} _ => {}
} }
true true
@ -1909,6 +1918,11 @@ impl<T: InvokeUiSession> Remote<T> {
self.handler.set_displays(&pi.displays); self.handler.set_displays(&pi.displays);
self.handler.set_platform_additions(&pi.platform_additions); self.handler.set_platform_additions(&pi.platform_additions);
} }
Some(message::Union::ScreenshotResponse(response)) => {
crate::client::screenshot::set_screenshot(response.data);
self.handler
.handle_screenshot_resp(response.sid, response.msg);
}
_ => {} _ => {}
} }
} }

99
src/client/screenshot.rs Normal file
View file

@ -0,0 +1,99 @@
#[cfg(not(any(target_os = "android", target_os = "ios")))]
use crate::clipboard::{update_clipboard, ClipboardSide};
use hbb_common::{message_proto::*, ResultType};
use std::sync::Mutex;
lazy_static::lazy_static! {
static ref SCREENSHOT: Mutex<Screenshot> = Default::default();
}
pub enum ScreenshotAction {
SaveAs(String),
CopyToClipboard,
Discard,
}
impl Default for ScreenshotAction {
fn default() -> Self {
Self::Discard
}
}
impl From<&str> for ScreenshotAction {
fn from(value: &str) -> Self {
match value.chars().next() {
Some('0') => {
if let Some((pos, _)) = value.char_indices().nth(2) {
let substring = &value[pos..];
Self::SaveAs(substring.to_string())
} else {
Self::default()
}
}
Some('1') => Self::CopyToClipboard,
Some('2') => Self::default(),
_ => Self::default(),
}
}
}
impl Into<String> for ScreenshotAction {
fn into(self) -> String {
match self {
Self::SaveAs(p) => format!("0:{p}"),
Self::CopyToClipboard => "1".to_owned(),
Self::Discard => "2".to_owned(),
}
}
}
#[derive(Default)]
pub struct Screenshot {
data: Option<bytes::Bytes>,
}
impl Screenshot {
fn set_screenshot(&mut self, data: bytes::Bytes) {
self.data.replace(data);
}
fn handle_screenshot(&mut self, action: String) -> String {
let Some(data) = self.data.take() else {
return "No cached screenshot".to_owned();
};
match Self::handle_screenshot_(data, action) {
Ok(()) => "".to_owned(),
Err(e) => e.to_string(),
}
}
fn handle_screenshot_(data: bytes::Bytes, action: String) -> ResultType<()> {
match ScreenshotAction::from(&action as &str) {
ScreenshotAction::SaveAs(p) => {
std::fs::write(p, data)?;
}
ScreenshotAction::CopyToClipboard => {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
{
let clips = vec![Clipboard {
compress: false,
content: data,
format: ClipboardFormat::ImagePng.into(),
..Default::default()
}];
update_clipboard(clips, ClipboardSide::Client);
}
}
ScreenshotAction::Discard => {}
}
Ok(())
}
}
pub fn set_screenshot(data: bytes::Bytes) {
SCREENSHOT.lock().unwrap().set_screenshot(data);
}
pub fn handle_screenshot(action: String) -> String {
SCREENSHOT.lock().unwrap().handle_screenshot(action)
}

View file

@ -147,6 +147,16 @@ pub fn is_support_file_paste_if_macos(ver: &str) -> bool {
hbb_common::get_version_number(ver) >= hbb_common::get_version_number("1.3.9") hbb_common::get_version_number(ver) >= hbb_common::get_version_number("1.3.9")
} }
#[inline]
pub fn is_support_screenshot(ver: &str) -> bool {
is_support_multi_ui_session_num(hbb_common::get_version_number(ver))
}
#[inline]
pub fn is_support_screenshot_num(ver: i64) -> bool {
ver >= hbb_common::get_version_number("1.4.0")
}
// is server process, with "--server" args // is server process, with "--server" args
#[inline] #[inline]
pub fn is_server() -> bool { pub fn is_server() -> bool {

View file

@ -543,6 +543,25 @@ impl FlutterHandler {
pub fn push_event<V>(&self, name: &str, event: &[(&str, V)], excludes: &[&SessionID]) pub fn push_event<V>(&self, name: &str, event: &[(&str, V)], excludes: &[&SessionID])
where where
V: Sized + Serialize + Clone, V: Sized + Serialize + Clone,
{
self.push_event_(name, event, &[], excludes);
}
pub fn push_event_to<V>(&self, name: &str, event: &[(&str, V)], include: &[&SessionID])
where
V: Sized + Serialize + Clone,
{
self.push_event_(name, event, include, &[]);
}
pub fn push_event_<V>(
&self,
name: &str,
event: &[(&str, V)],
includes: &[&SessionID],
excludes: &[&SessionID],
) where
V: Sized + Serialize + Clone,
{ {
let mut h: HashMap<&str, serde_json::Value> = let mut h: HashMap<&str, serde_json::Value> =
event.iter().map(|(k, v)| (*k, json!(*v))).collect(); event.iter().map(|(k, v)| (*k, json!(*v))).collect();
@ -550,11 +569,20 @@ impl FlutterHandler {
h.insert("name", json!(name)); h.insert("name", json!(name));
let out = serde_json::ser::to_string(&h).unwrap_or("".to_owned()); let out = serde_json::ser::to_string(&h).unwrap_or("".to_owned());
for (sid, session) in self.session_handlers.read().unwrap().iter() { for (sid, session) in self.session_handlers.read().unwrap().iter() {
if excludes.contains(&sid) { let mut push = false;
continue; if includes.is_empty() {
if !excludes.contains(&sid) {
push = true;
}
} else {
if includes.contains(&sid) {
push = true;
}
} }
if let Some(stream) = &session.event_stream { if push {
stream.add(EventToUI::Event(out.clone())); if let Some(stream) = &session.event_stream {
stream.add(EventToUI::Event(out.clone()));
}
} }
} }
} }
@ -1067,6 +1095,16 @@ impl InvokeUiSession for FlutterHandler {
&[], &[],
); );
} }
fn handle_screenshot_resp(&self, sid: String, msg: String) {
match SessionID::from_str(&sid) {
Ok(sid) => self.push_event_to("screenshot", &[("msg", json!(msg))], &[&sid]),
Err(e) => {
// Unreachable!
log::error!("Failed to parse sid \"{}\", {}", sid, e);
}
}
}
} }
impl FlutterHandler { impl FlutterHandler {

View file

@ -250,6 +250,16 @@ pub fn session_refresh(session_id: SessionID, display: usize) {
} }
} }
pub fn session_take_screenshot(session_id: SessionID, display: usize) {
if let Some(s) = sessions::get_session_by_session_id(&session_id) {
s.take_screenshot(display as _, session_id.to_string());
}
}
pub fn session_handle_screenshot(session_id: SessionID, action: String) -> String {
crate::client::screenshot::handle_screenshot(action)
}
pub fn session_is_multi_ui_session(session_id: SessionID) -> SyncReturn<bool> { pub fn session_is_multi_ui_session(session_id: SessionID) -> SyncReturn<bool> {
if let Some(session) = sessions::get_session_by_session_id(&session_id) { if let Some(session) = sessions::get_session_by_session_id(&session_id) {
SyncReturn(session.is_multi_ui_session()) SyncReturn(session.is_multi_ui_session())
@ -2461,6 +2471,27 @@ pub fn main_set_common(_key: String, _value: String) {
} }
} }
pub fn session_get_common_sync(
session_id: SessionID,
key: String,
param: String,
) -> SyncReturn<Option<String>> {
SyncReturn(session_get_common(session_id, key, param))
}
pub fn session_get_common(session_id: SessionID, key: String, param: String) -> Option<String> {
if let Some(s) = sessions::get_session_by_session_id(&session_id) {
let v = if key == "is_screenshot_supported" {
s.is_screenshot_supported().to_string()
} else {
"".to_owned()
};
Some(v)
} else {
None
}
}
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
pub mod server_side { pub mod server_side {
use hbb_common::{config, log}; use hbb_common::{config, log};

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "الطابعة {} جاهزة"), ("printer-{}-ready-tip", "الطابعة {} جاهزة"),
("Install {} Printer", "تثبيت طابعة {}"), ("Install {} Printer", "تثبيت طابعة {}"),
("Outgoing Print Jobs", "وظائف الطباعة الصادرة"), ("Outgoing Print Jobs", "وظائف الطباعة الصادرة"),
("Incomming Print Jobs", "وظائف الطباعة الواردة"), ("Incoming Print Jobs", "وظائف الطباعة الواردة"),
("Incoming Print Job", "وظيفة طباعة واردة"), ("Incoming Print Job", "وظيفة طباعة واردة"),
("use-the-default-printer-tip", "استخدم الطابعة الافتراضية"), ("use-the-default-printer-tip", "استخدم الطابعة الافتراضية"),
("use-the-selected-printer-tip", "استخدم الطابعة المحددة"), ("use-the-selected-printer-tip", "استخدم الطابعة المحددة"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "الطباعة عن بُعد غير مسموح بها على هذا الجهاز"), ("remote-printing-disallowed-text-tip", "الطباعة عن بُعد غير مسموح بها على هذا الجهاز"),
("save-settings-tip", "حفظ الإعدادات"), ("save-settings-tip", "حفظ الإعدادات"),
("dont-show-again-tip", "لا تظهر هذا مرة أخرى"), ("dont-show-again-tip", "لا تظهر هذا مرة أخرى"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -653,7 +653,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Upload folder", "上传文件夹"), ("Upload folder", "上传文件夹"),
("Upload files", "上传文件"), ("Upload files", "上传文件"),
("Clipboard is synchronized", "剪贴板已同步"), ("Clipboard is synchronized", "剪贴板已同步"),
("Update client clipboard", "更新客户端的贴板"), ("Update client clipboard", "更新客户端的贴板"),
("Untagged", "无标签"), ("Untagged", "无标签"),
("new-version-of-{}-tip", "{} 版本更新"), ("new-version-of-{}-tip", "{} 版本更新"),
("Accessible devices", "可访问的设备"), ("Accessible devices", "可访问的设备"),
@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "{} 打印机已安装,您可以使用打印功能了。"), ("printer-{}-ready-tip", "{} 打印机已安装,您可以使用打印功能了。"),
("Install {} Printer", "安装 {} 打印机"), ("Install {} Printer", "安装 {} 打印机"),
("Outgoing Print Jobs", "传出的打印任务"), ("Outgoing Print Jobs", "传出的打印任务"),
("Incomming Print Jobs", "传入的打印任务"), ("Incoming Print Jobs", "传入的打印任务"),
("Incoming Print Job", "传入的打印任务"), ("Incoming Print Job", "传入的打印任务"),
("use-the-default-printer-tip", "使用默认的打印机执行"), ("use-the-default-printer-tip", "使用默认的打印机执行"),
("use-the-selected-printer-tip", "使用选择的打印机执行"), ("use-the-selected-printer-tip", "使用选择的打印机执行"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "被控端的权限设置拒绝了远程打印。"), ("remote-printing-disallowed-text-tip", "被控端的权限设置拒绝了远程打印。"),
("save-settings-tip", "保存设置"), ("save-settings-tip", "保存设置"),
("dont-show-again-tip", "不再显示此信息"), ("dont-show-again-tip", "不再显示此信息"),
("Take screenshot", "截屏"),
("Taking screenshot", "正在截屏"),
("screenshot-merged-screen-not-supported-tip", "当前不支持多个屏幕的合并截屏,请切换到单个屏幕重试。"),
("screenshot-action-tip", "请选择如何继续截屏。"),
("Save as", "另存为"),
("Copy to clipboard", "复制到剪贴板"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "Der Drucker {} ist installiert und einsatzbereit."), ("printer-{}-ready-tip", "Der Drucker {} ist installiert und einsatzbereit."),
("Install {} Printer", "Drucker {} installieren"), ("Install {} Printer", "Drucker {} installieren"),
("Outgoing Print Jobs", "Ausgehende Druckaufträge"), ("Outgoing Print Jobs", "Ausgehende Druckaufträge"),
("Incomming Print Jobs", "Eingehende Druckaufträge"), ("Incoming Print Jobs", "Eingehende Druckaufträge"),
("Incoming Print Job", "Eingehender Druckauftrag"), ("Incoming Print Job", "Eingehender Druckauftrag"),
("use-the-default-printer-tip", "Standarddrucker verwenden"), ("use-the-default-printer-tip", "Standarddrucker verwenden"),
("use-the-selected-printer-tip", "Ausgewählten Drucker verwenden"), ("use-the-selected-printer-tip", "Ausgewählten Drucker verwenden"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "Die Berechtigungseinstellungen der kontrollierten Seite verweigern den entfernten Druck."), ("remote-printing-disallowed-text-tip", "Die Berechtigungseinstellungen der kontrollierten Seite verweigern den entfernten Druck."),
("save-settings-tip", "Einstellungen speichern"), ("save-settings-tip", "Einstellungen speichern"),
("dont-show-again-tip", "Nicht mehr anzeigen"), ("dont-show-again-tip", "Nicht mehr anzeigen"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -253,5 +253,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "The permission settings of the controlled side deny Remote Printing."), ("remote-printing-disallowed-text-tip", "The permission settings of the controlled side deny Remote Printing."),
("save-settings-tip", "Save settings"), ("save-settings-tip", "Save settings"),
("dont-show-again-tip", "Don't show this again"), ("dont-show-again-tip", "Don't show this again"),
("screenshot-merged-screen-not-supported-tip", "Merging screenshots of multiple displays is currently not supported. Please switch to a single display and try again."),
("screenshot-action-tip", "Please select how to continue with the screenshot."),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "La impresora {} está instalada y lista para usar."), ("printer-{}-ready-tip", "La impresora {} está instalada y lista para usar."),
("Install {} Printer", "Instalar la impresora {}"), ("Install {} Printer", "Instalar la impresora {}"),
("Outgoing Print Jobs", "Tareas salientes de impresión"), ("Outgoing Print Jobs", "Tareas salientes de impresión"),
("Incomming Print Jobs", "Tareas entrantes de impresión"), ("Incoming Print Jobs", "Tareas entrantes de impresión"),
("Incoming Print Job", "Trabajo entrante de impresión"), ("Incoming Print Job", "Trabajo entrante de impresión"),
("use-the-default-printer-tip", "Usar la impresora predeterminada"), ("use-the-default-printer-tip", "Usar la impresora predeterminada"),
("use-the-selected-printer-tip", "Usar la impresora seleccionada"), ("use-the-selected-printer-tip", "Usar la impresora seleccionada"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "Los ajustes de permisos del lado controlado no permiten la impresión remota."), ("remote-printing-disallowed-text-tip", "Los ajustes de permisos del lado controlado no permiten la impresión remota."),
("save-settings-tip", "Guardar ajustes"), ("save-settings-tip", "Guardar ajustes"),
("dont-show-again-tip", "No volver a mostrar"), ("dont-show-again-tip", "No volver a mostrar"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "چاپگر {} آماده است"), ("printer-{}-ready-tip", "چاپگر {} آماده است"),
("Install {} Printer", "نصب چاپگر {}"), ("Install {} Printer", "نصب چاپگر {}"),
("Outgoing Print Jobs", "وظایف چاپ خروجی"), ("Outgoing Print Jobs", "وظایف چاپ خروجی"),
("Incomming Print Jobs", "وظایف چاپ ورودی"), ("Incoming Print Jobs", "وظایف چاپ ورودی"),
("Incoming Print Job", "وظیفه چاپ ورودی"), ("Incoming Print Job", "وظیفه چاپ ورودی"),
("use-the-default-printer-tip", "از چاپگر پیش‌فرض استفاده کنید"), ("use-the-default-printer-tip", "از چاپگر پیش‌فرض استفاده کنید"),
("use-the-selected-printer-tip", "از چاپگر انتخاب‌شده استفاده کنید"), ("use-the-selected-printer-tip", "از چاپگر انتخاب‌شده استفاده کنید"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "شما مجوز لازم برای چاپ از راه دور را ندارید"), ("remote-printing-disallowed-text-tip", "شما مجوز لازم برای چاپ از راه دور را ندارید"),
("save-settings-tip", "تنظیمات را ذخیره کنید"), ("save-settings-tip", "تنظیمات را ذخیره کنید"),
("dont-show-again-tip", "دیگر نمایش داده نشود"), ("dont-show-again-tip", "دیگر نمایش داده نشود"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "Limprimante {} est installée et opérationnelle."), ("printer-{}-ready-tip", "Limprimante {} est installée et opérationnelle."),
("Install {} Printer", "Installer limprimante {}"), ("Install {} Printer", "Installer limprimante {}"),
("Outgoing Print Jobs", "Impressions sortantes"), ("Outgoing Print Jobs", "Impressions sortantes"),
("Incomming Print Jobs", "Impressions entrantes"), ("Incoming Print Jobs", "Impressions entrantes"),
("Incoming Print Job", "Impression entrante"), ("Incoming Print Job", "Impression entrante"),
("use-the-default-printer-tip", "Utiliser limprimante par défaut"), ("use-the-default-printer-tip", "Utiliser limprimante par défaut"),
("use-the-selected-printer-tip", "Utiliser limprimante sélectionnée"), ("use-the-selected-printer-tip", "Utiliser limprimante sélectionnée"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "Les paramètres de lappareil contrôlé nautorisent pas limpression à distance."), ("remote-printing-disallowed-text-tip", "Les paramètres de lappareil contrôlé nautorisent pas limpression à distance."),
("save-settings-tip", "Enregistrer les paramètres"), ("save-settings-tip", "Enregistrer les paramètres"),
("dont-show-again-tip", "Ne plus afficher"), ("dont-show-again-tip", "Ne plus afficher"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -239,7 +239,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Empty", "ცარიელი"), ("Empty", "ცარიელი"),
("Invalid folder name", "არასწორი საქაღალდის სახელი"), ("Invalid folder name", "არასწორი საქაღალდის სახელი"),
("Socks5 Proxy", "SOCKS5-პროქსი"), ("Socks5 Proxy", "SOCKS5-პროქსი"),
("Proxy", "პროქსი"), ("Socks5/Http(s) Proxy", ""),
("Discovered", "ნაპოვნია"), ("Discovered", "ნაპოვნია"),
("install_daemon_tip", "ჩატვირთვისას გასაშვებად საჭიროა სისტემური სერვისის დაყენება"), ("install_daemon_tip", "ჩატვირთვისას გასაშვებად საჭიროა სისტემური სერვისის დაყენება"),
("Remote ID", "დაშორებული ID"), ("Remote ID", "დაშორებული ID"),
@ -567,7 +567,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("id_input_tip", "შეგიძლიათ შეიყვანოთ იდენტიფიკატორი, პირდაპირი IP მისამართი ან დომენი პორტით (<დომენი>:<პორტი>).\nთუ გჭირდებათ წვდომა მოწყობილობაზე სხვა სერვერზე, დაამატეთ სერვერის მისამართი (<id>@<სერვერის_მისამართი>?key=<გასაღების_მნიშვნელობა>), მაგალითად:\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nთუ გჭირდებათ წვდომა მოწყობილობაზე საჯარო სერვერზე, შეიყვანეთ \"<id>@public\", გასაღები საჯარო სერვერისთვის არ არის საჭირო."), ("id_input_tip", "შეგიძლიათ შეიყვანოთ იდენტიფიკატორი, პირდაპირი IP მისამართი ან დომენი პორტით (<დომენი>:<პორტი>).\nთუ გჭირდებათ წვდომა მოწყობილობაზე სხვა სერვერზე, დაამატეთ სერვერის მისამართი (<id>@<სერვერის_მისამართი>?key=<გასაღების_მნიშვნელობა>), მაგალითად:\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nთუ გჭირდებათ წვდომა მოწყობილობაზე საჯარო სერვერზე, შეიყვანეთ \"<id>@public\", გასაღები საჯარო სერვერისთვის არ არის საჭირო."),
("privacy_mode_impl_mag_tip", "რეჟიმი 1"), ("privacy_mode_impl_mag_tip", "რეჟიმი 1"),
("privacy_mode_impl_virtual_display_tip", "რეჟიმი 2"), ("privacy_mode_impl_virtual_display_tip", "რეჟიმი 2"),
("privacy_mode_impl_virtual_display_tip", "რეჟიმი 2"),
("Enter privacy mode", "კონფიდენციალურობის რეჟიმის ჩართვა"), ("Enter privacy mode", "კონფიდენციალურობის რეჟიმის ჩართვა"),
("Exit privacy mode", "კონფიდენციალურობის რეჟიმის გამორთვა"), ("Exit privacy mode", "კონფიდენციალურობის რეჟიმის გამორთვა"),
("idd_not_support_under_win10_2004_tip", "არაპირდაპირი ჩვენების დრაივერი არ არის მხარდაჭერილი. საჭიროა Windows 10 ვერსია 2004 ან უფრო ახალი."), ("idd_not_support_under_win10_2004_tip", "არაპირდაპირი ჩვენების დრაივერი არ არის მხარდაჭერილი. საჭიროა Windows 10 ვერსია 2004 ან უფრო ახალი."),
@ -659,7 +658,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("new-version-of-{}-tip", "ხელმისაწვდომია ახალი ვერსია {}"), ("new-version-of-{}-tip", "ხელმისაწვდომია ახალი ვერსია {}"),
("Accessible devices", "ხელმისაწვდომი მოწყობილობები"), ("Accessible devices", "ხელმისაწვდომი მოწყობილობები"),
("View camera", "კამერის ნახვა"), ("View camera", "კამერის ნახვა"),
("upgrade_remote_rustdesk_client_to{}_tip", "განაახლეთ RustDesk კლიენტი ვერსიამდე {} ან უფრო ახალი დისტანციურ მხარეზე!"), ("upgrade_remote_rustdesk_client_to_{}_tip", ""),
("view_camera_unsupported_tip", "დისტანციური მოწყობილობა არ უჭერს მხარს კამერის ნახვას."), ("view_camera_unsupported_tip", "დისტანციური მოწყობილობა არ უჭერს მხარს კამერის ნახვას."),
("Enable camera", "კამერის ჩართვა"), ("Enable camera", "კამერის ჩართვა"),
("No cameras", "კამერა არ არის"), ("No cameras", "კამერა არ არის"),
@ -672,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "პრინტერი {} დაინსტალირებულია და მზად არის გამოსაყენებლად."), ("printer-{}-ready-tip", "პრინტერი {} დაინსტალირებულია და მზად არის გამოსაყენებლად."),
("Install {} Printer", "დააინსტალირეთ პრინტერი {}"), ("Install {} Printer", "დააინსტალირეთ პრინტერი {}"),
("Outgoing Print Jobs", "გამავალი ბეჭდვის დავალება"), ("Outgoing Print Jobs", "გამავალი ბეჭდვის დავალება"),
("Incomming Print Jobs", "შემომავალი ბეჭდვის დავალება"), ("Incoming Print Jobs", "შემომავალი ბეჭდვის დავალება"),
("Incoming Print Job", "შემომავალი ბეჭდვის დავალება"), ("Incoming Print Job", "შემომავალი ბეჭდვის დავალება"),
("use-the-default-printer-tip", "ნაგულისხმევი პრინტერის გამოყენება"), ("use-the-default-printer-tip", "ნაგულისხმევი პრინტერის გამოყენება"),
("use-the-selected-printer-tip", "არჩეული პრინტერის გამოყენება"), ("use-the-selected-printer-tip", "არჩეული პრინტერის გამოყენება"),
@ -682,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "მართულ მხარეზე უფლებების პარამეტრები კრძალავს დისტანციურ ბეჭდვას."), ("remote-printing-disallowed-text-tip", "მართულ მხარეზე უფლებების პარამეტრები კრძალავს დისტანციურ ბეჭდვას."),
("save-settings-tip", "პარამეტრების შენახვა"), ("save-settings-tip", "პარამეტრების შენახვა"),
("dont-show-again-tip", "აღარ აჩვენოთ"), ("dont-show-again-tip", "აღარ აჩვენოთ"),
].iter().cloned().collect(); ("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "A(z) {} nyomtató készen áll"), ("printer-{}-ready-tip", "A(z) {} nyomtató készen áll"),
("Install {} Printer", "A(z) {} nyomtató nyomtató telepítése"), ("Install {} Printer", "A(z) {} nyomtató nyomtató telepítése"),
("Outgoing Print Jobs", "Kimenő nyomtatási feladatok"), ("Outgoing Print Jobs", "Kimenő nyomtatási feladatok"),
("Incomming Print Jobs", "Bejövő nyomtatási feladatok"), ("Incoming Print Jobs", "Bejövő nyomtatási feladatok"),
("Incoming Print Job", "Bejövő nyomtatási feladat"), ("Incoming Print Job", "Bejövő nyomtatási feladat"),
("use-the-default-printer-tip", "Alapértelmezett nyomtató használata"), ("use-the-default-printer-tip", "Alapértelmezett nyomtató használata"),
("use-the-selected-printer-tip", "Kiválasztott nyomtató használata"), ("use-the-selected-printer-tip", "Kiválasztott nyomtató használata"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "A távoli nyomtatás nincs engedélyezve"), ("remote-printing-disallowed-text-tip", "A távoli nyomtatás nincs engedélyezve"),
("save-settings-tip", "Beállítások mentése"), ("save-settings-tip", "Beállítások mentése"),
("dont-show-again-tip", "Ne jelenítse meg újra"), ("dont-show-again-tip", "Ne jelenítse meg újra"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "La stampante {} è installata e pronta all'uso."), ("printer-{}-ready-tip", "La stampante {} è installata e pronta all'uso."),
("Install {} Printer", "Installa la stampante {}"), ("Install {} Printer", "Installa la stampante {}"),
("Outgoing Print Jobs", "Lavori di stampa in uscita"), ("Outgoing Print Jobs", "Lavori di stampa in uscita"),
("Incomming Print Jobs", "Lavori di stampa in entrata"), ("Incoming Print Jobs", "Lavori di stampa in entrata"),
("Incoming Print Job", "Lavoro di stampa in entrata"), ("Incoming Print Job", "Lavoro di stampa in entrata"),
("use-the-default-printer-tip", "Usa la stampante predefinita"), ("use-the-default-printer-tip", "Usa la stampante predefinita"),
("use-the-selected-printer-tip", "Usa la stampante selezionata"), ("use-the-selected-printer-tip", "Usa la stampante selezionata"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "Le impostazioni di autorizzazione del lato controllato negano la stampa remota."), ("remote-printing-disallowed-text-tip", "Le impostazioni di autorizzazione del lato controllato negano la stampa remota."),
("save-settings-tip", "Salva impostazioni"), ("save-settings-tip", "Salva impostazioni"),
("dont-show-again-tip", "Non visualizzare più questo messaggio"), ("dont-show-again-tip", "Non visualizzare più questo messaggio"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "Printeris {} ir instalēts un gatavs lietošanai."), ("printer-{}-ready-tip", "Printeris {} ir instalēts un gatavs lietošanai."),
("Install {} Printer", "Instalēt {} printeri"), ("Install {} Printer", "Instalēt {} printeri"),
("Outgoing Print Jobs", "Izejošie drukas darbi"), ("Outgoing Print Jobs", "Izejošie drukas darbi"),
("Incomming Print Jobs", "Ienākošie drukas darbi"), ("Incoming Print Jobs", "Ienākošie drukas darbi"),
("Incoming Print Job", "Ienākošais drukas darbs"), ("Incoming Print Job", "Ienākošais drukas darbs"),
("use-the-default-printer-tip", "Izmantot noklusējuma printeri"), ("use-the-default-printer-tip", "Izmantot noklusējuma printeri"),
("use-the-selected-printer-tip", "Izmantot atlasīto printeri"), ("use-the-selected-printer-tip", "Izmantot atlasīto printeri"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "Kontrolētās puses atļauju iestatījumi liedz attālo drukāšanu."), ("remote-printing-disallowed-text-tip", "Kontrolētās puses atļauju iestatījumi liedz attālo drukāšanu."),
("save-settings-tip", "Saglabāt iestatījumus"), ("save-settings-tip", "Saglabāt iestatījumus"),
("dont-show-again-tip", "Nerādīt šo vēlreiz"), ("dont-show-again-tip", "Nerādīt šo vēlreiz"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "De printer {} is geïnstalleerd en klaar voor gebruik."), ("printer-{}-ready-tip", "De printer {} is geïnstalleerd en klaar voor gebruik."),
("Install {} Printer", "Installeer {} Printer"), ("Install {} Printer", "Installeer {} Printer"),
("Outgoing Print Jobs", "Uitgaande Afdruktaken"), ("Outgoing Print Jobs", "Uitgaande Afdruktaken"),
("Incomming Print Jobs", "Inkomende Afdruktaken"), ("Incoming Print Jobs", "Inkomende Afdruktaken"),
("Incoming Print Job", "Inkomende Afdruktaak"), ("Incoming Print Job", "Inkomende Afdruktaak"),
("use-the-default-printer-tip", "Gebruik de standaard printer"), ("use-the-default-printer-tip", "Gebruik de standaard printer"),
("use-the-selected-printer-tip", "Gebruik de geselecteerde printer"), ("use-the-selected-printer-tip", "Gebruik de geselecteerde printer"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "Machtigingsinstellingen aan beheerde zijde verhinderen afdrukken op afstand."), ("remote-printing-disallowed-text-tip", "Machtigingsinstellingen aan beheerde zijde verhinderen afdrukken op afstand."),
("save-settings-tip", "Instellingen opslaan"), ("save-settings-tip", "Instellingen opslaan"),
("dont-show-again-tip", "Dit bericht wordt niet meer weergegeven"), ("dont-show-again-tip", "Dit bericht wordt niet meer weergegeven"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "Drukarka {} jest zainstalowana i gotowa do użycia."), ("printer-{}-ready-tip", "Drukarka {} jest zainstalowana i gotowa do użycia."),
("Install {} Printer", "Zainstaluj drukarkę {}"), ("Install {} Printer", "Zainstaluj drukarkę {}"),
("Outgoing Print Jobs", "Wychodzące zadania drukowania"), ("Outgoing Print Jobs", "Wychodzące zadania drukowania"),
("Incomming Print Jobs", "Przychodzące zadania drukowania"), ("Incoming Print Jobs", "Przychodzące zadania drukowania"),
("Incoming Print Job", "Przychodzące zadanie drukowania"), ("Incoming Print Job", "Przychodzące zadanie drukowania"),
("use-the-default-printer-tip", "Użyj domyślnej drukarki"), ("use-the-default-printer-tip", "Użyj domyślnej drukarki"),
("use-the-selected-printer-tip", "Użyj wybranej drukarki"), ("use-the-selected-printer-tip", "Użyj wybranej drukarki"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "Ustawienia uprawnień po zdalnej stronie uniemożliwiają zdalne drukowanie."), ("remote-printing-disallowed-text-tip", "Ustawienia uprawnień po zdalnej stronie uniemożliwiają zdalne drukowanie."),
("save-settings-tip", "Zapisz ustawienia"), ("save-settings-tip", "Zapisz ustawienia"),
("dont-show-again-tip", "Nie pokazuj więcej"), ("dont-show-again-tip", "Nie pokazuj więcej"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "A impressora {} está instalada e operacional."), ("printer-{}-ready-tip", "A impressora {} está instalada e operacional."),
("Install {} Printer", "Instalar impressora {}"), ("Install {} Printer", "Instalar impressora {}"),
("Outgoing Print Jobs", "Trabalhos de impressão enviados"), ("Outgoing Print Jobs", "Trabalhos de impressão enviados"),
("Incomming Print Jobs", "Trabalhos de impressão recebidos"), ("Incoming Print Jobs", "Trabalhos de impressão recebidos"),
("Incoming Print Job", "Impressão recebida"), ("Incoming Print Job", "Impressão recebida"),
("use-the-default-printer-tip", "Usar impressora padrão"), ("use-the-default-printer-tip", "Usar impressora padrão"),
("use-the-selected-printer-tip", "Usar impressora selecionada"), ("use-the-selected-printer-tip", "Usar impressora selecionada"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "As configurações do dispositivo controlado não permitem impressão remota."), ("remote-printing-disallowed-text-tip", "As configurações do dispositivo controlado não permitem impressão remota."),
("save-settings-tip", "Salvar configurações"), ("save-settings-tip", "Salvar configurações"),
("dont-show-again-tip", "Não mostrar novamente"), ("dont-show-again-tip", "Não mostrar novamente"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "Принтер {} установлен и готов к использованию."), ("printer-{}-ready-tip", "Принтер {} установлен и готов к использованию."),
("Install {} Printer", "Установить принтер {}"), ("Install {} Printer", "Установить принтер {}"),
("Outgoing Print Jobs", "Исходящее задание печати"), ("Outgoing Print Jobs", "Исходящее задание печати"),
("Incomming Print Jobs", "Входящее задание печати"), ("Incoming Print Jobs", "Входящее задание печати"),
("Incoming Print Job", "Входящее задание печати"), ("Incoming Print Job", "Входящее задание печати"),
("use-the-default-printer-tip", "Использовать принтер по умолчанию"), ("use-the-default-printer-tip", "Использовать принтер по умолчанию"),
("use-the-selected-printer-tip", "Использовать выбранный принтер"), ("use-the-selected-printer-tip", "Использовать выбранный принтер"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "Настройки разрешений на управляемой стороне запрещают удалённую печать."), ("remote-printing-disallowed-text-tip", "Настройки разрешений на управляемой стороне запрещают удалённую печать."),
("save-settings-tip", "Сохранить настройки"), ("save-settings-tip", "Сохранить настройки"),
("dont-show-again-tip", "Больше не показывать"), ("dont-show-again-tip", "Больше не показывать"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "S'imprentadora {} est installada e pronta pro s'impreu."), ("printer-{}-ready-tip", "S'imprentadora {} est installada e pronta pro s'impreu."),
("Install {} Printer", "Installa s'imprentadora {}"), ("Install {} Printer", "Installa s'imprentadora {}"),
("Outgoing Print Jobs", "Traballos de imprenta in essida"), ("Outgoing Print Jobs", "Traballos de imprenta in essida"),
("Incomming Print Jobs", "Traballos de imprenta in intrada"), ("Incoming Print Jobs", "Traballos de imprenta in intrada"),
("Incoming Print Job", "Traballu de imprenta in intrada"), ("Incoming Print Job", "Traballu de imprenta in intrada"),
("use-the-default-printer-tip", "Imprea s'imprentadora predefinida"), ("use-the-default-printer-tip", "Imprea s'imprentadora predefinida"),
("use-the-selected-printer-tip", "Imprea s'imprentadora seletzionada"), ("use-the-selected-printer-tip", "Imprea s'imprentadora seletzionada"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "Sas impostatziones de sos permissos de s'ala controllada negant s'imprenta remota."), ("remote-printing-disallowed-text-tip", "Sas impostatziones de sos permissos de s'ala controllada negant s'imprenta remota."),
("save-settings-tip", "Sarva sas impostatziones"), ("save-settings-tip", "Sarva sas impostatziones"),
("dont-show-again-tip", "Non mustres prus custu messàgiu"), ("dont-show-again-tip", "Non mustres prus custu messàgiu"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", "{} 印表機已安裝,您可以使用列印功能了。"), ("printer-{}-ready-tip", "{} 印表機已安裝,您可以使用列印功能了。"),
("Install {} Printer", "安裝 {} 印表機"), ("Install {} Printer", "安裝 {} 印表機"),
("Outgoing Print Jobs", "傳出的列印任務"), ("Outgoing Print Jobs", "傳出的列印任務"),
("Incomming Print Jobs", "傳入的列印任務"), ("Incoming Print Jobs", "傳入的列印任務"),
("Incoming Print Job", "傳入的列印任務"), ("Incoming Print Job", "傳入的列印任務"),
("use-the-default-printer-tip", "使用預設的印表機"), ("use-the-default-printer-tip", "使用預設的印表機"),
("use-the-selected-printer-tip", "使用選取的印表機"), ("use-the-selected-printer-tip", "使用選取的印表機"),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", "被控端的權限設置拒絕了遠端列印。"), ("remote-printing-disallowed-text-tip", "被控端的權限設置拒絕了遠端列印。"),
("save-settings-tip", "儲存設定"), ("save-settings-tip", "儲存設定"),
("dont-show-again-tip", "不再顯示此訊息"), ("dont-show-again-tip", "不再顯示此訊息"),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -671,7 +671,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("printer-{}-ready-tip", ""), ("printer-{}-ready-tip", ""),
("Install {} Printer", ""), ("Install {} Printer", ""),
("Outgoing Print Jobs", ""), ("Outgoing Print Jobs", ""),
("Incomming Print Jobs", ""), ("Incoming Print Jobs", ""),
("Incoming Print Job", ""), ("Incoming Print Job", ""),
("use-the-default-printer-tip", ""), ("use-the-default-printer-tip", ""),
("use-the-selected-printer-tip", ""), ("use-the-selected-printer-tip", ""),
@ -681,5 +681,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("remote-printing-disallowed-text-tip", ""), ("remote-printing-disallowed-text-tip", ""),
("save-settings-tip", ""), ("save-settings-tip", ""),
("dont-show-again-tip", ""), ("dont-show-again-tip", ""),
("Take screenshot", ""),
("Taking screenshot", ""),
("screenshot-merged-screen-not-supported-tip", ""),
("screenshot-action-tip", ""),
("Save as", ""),
("Copy to clipboard", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -2819,6 +2819,16 @@ impl Connection {
Some(message::Union::VoiceCallResponse(_response)) => { Some(message::Union::VoiceCallResponse(_response)) => {
// TODO: Maybe we can do a voice call from cm directly. // TODO: Maybe we can do a voice call from cm directly.
} }
Some(message::Union::ScreenshotRequest(request)) => {
if let Some(tx) = self.inner.tx.clone() {
crate::video_service::set_take_screenshot(
request.display as _,
request.sid.clone(),
tx,
);
self.refresh_video_display(Some(request.display as usize));
}
}
_ => {} _ => {}
} }
} }

View file

@ -49,7 +49,7 @@ use scrap::{
codec::{Encoder, EncoderCfg}, codec::{Encoder, EncoderCfg},
record::{Recorder, RecorderContext}, record::{Recorder, RecorderContext},
vpxcodec::{VpxEncoderConfig, VpxVideoCodecId}, vpxcodec::{VpxEncoderConfig, VpxVideoCodecId},
CodecFormat, Display, EncodeInput, TraitCapturer, CodecFormat, Display, EncodeInput, TraitCapturer, TraitPixelBuffer,
}; };
#[cfg(windows)] #[cfg(windows)]
use std::sync::Once; use std::sync::Once;
@ -70,6 +70,13 @@ lazy_static::lazy_static! {
pub static ref VIDEO_QOS: Arc<Mutex<VideoQoS>> = Default::default(); pub static ref VIDEO_QOS: Arc<Mutex<VideoQoS>> = Default::default();
pub static ref IS_UAC_RUNNING: Arc<Mutex<bool>> = Default::default(); pub static ref IS_UAC_RUNNING: Arc<Mutex<bool>> = Default::default();
pub static ref IS_FOREGROUND_WINDOW_ELEVATED: Arc<Mutex<bool>> = Default::default(); pub static ref IS_FOREGROUND_WINDOW_ELEVATED: Arc<Mutex<bool>> = Default::default();
static ref SCREENSHOTS: Mutex<HashMap<usize, Screenshot>> = Default::default();
}
struct Screenshot {
sid: String,
tx: Sender,
restore_vram: bool,
} }
#[inline] #[inline]
@ -457,7 +464,7 @@ fn get_capturer(
} }
fn run(vs: VideoService) -> ResultType<()> { fn run(vs: VideoService) -> ResultType<()> {
let _raii = Raii::new(vs.sp.name()); let mut _raii = Raii::new(vs.sp.name());
// Wayland only support one video capturer for now. It is ok to call ensure_inited() here. // Wayland only support one video capturer for now. It is ok to call ensure_inited() here.
// //
// ensure_inited() is needed because clear() may be called. // ensure_inited() is needed because clear() may be called.
@ -639,6 +646,49 @@ fn run(vs: VideoService) -> ResultType<()> {
Ok(frame) => { Ok(frame) => {
repeat_encode_counter = 0; repeat_encode_counter = 0;
if frame.valid() { if frame.valid() {
let screenshot = SCREENSHOTS.lock().unwrap().remove(&display_idx);
if let Some(mut screenshot) = screenshot {
let restore_vram = screenshot.restore_vram;
let (msg, w, h, data) = match &frame {
scrap::Frame::PixelBuffer(f) => match get_rgba_from_pixelbuf(f) {
Ok(rgba) => ("".to_owned(), f.width(), f.height(), rgba),
Err(e) => {
let serr = e.to_string();
log::error!(
"Failed to convert the pix format into rgba, {}",
&serr
);
(format!("Convert pixfmt: {}", serr), 0, 0, vec![])
}
},
scrap::Frame::Texture(_) => {
if restore_vram {
// Already set one time, just ignore to break infinite loop.
// Though it's unreachable, this branch is kept to avoid infinite loop.
(
"Please change codec and try again.".to_owned(),
0,
0,
vec![],
)
} else {
#[cfg(all(windows, feature = "vram"))]
VRamEncoder::set_not_use(sp.name(), true);
screenshot.restore_vram = true;
SCREENSHOTS.lock().unwrap().insert(display_idx, screenshot);
_raii.try_vram = false;
bail!("SWITCH");
}
}
};
std::thread::spawn(move || {
handle_screenshot(screenshot, msg, w, h, data);
});
if restore_vram {
bail!("SWITCH");
}
}
let frame = frame.to(encoder.yuvfmt(), &mut yuv, &mut mid_data)?; let frame = frame.to(encoder.yuvfmt(), &mut yuv, &mut mid_data)?;
let send_conn_ids = handle_one_frame( let send_conn_ids = handle_one_frame(
display_idx, display_idx,
@ -764,24 +814,32 @@ fn run(vs: VideoService) -> ResultType<()> {
Ok(()) Ok(())
} }
struct Raii(String); struct Raii {
name: String,
try_vram: bool,
}
impl Raii { impl Raii {
fn new(name: String) -> Self { fn new(name: String) -> Self {
log::info!("new video service: {}", name); log::info!("new video service: {}", name);
VIDEO_QOS.lock().unwrap().new_display(name.clone()); VIDEO_QOS.lock().unwrap().new_display(name.clone());
Raii(name) Raii {
name,
try_vram: true,
}
} }
} }
impl Drop for Raii { impl Drop for Raii {
fn drop(&mut self) { fn drop(&mut self) {
log::info!("stop video service: {}", self.0); log::info!("stop video service: {}", self.name);
#[cfg(feature = "vram")] #[cfg(feature = "vram")]
VRamEncoder::set_not_use(self.0.clone(), false); if self.try_vram {
VRamEncoder::set_not_use(self.name.clone(), false);
}
#[cfg(feature = "vram")] #[cfg(feature = "vram")]
Encoder::update(scrap::codec::EncodingUpdate::Check); Encoder::update(scrap::codec::EncodingUpdate::Check);
VIDEO_QOS.lock().unwrap().remove_display(&self.0); VIDEO_QOS.lock().unwrap().remove_display(&self.name);
} }
} }
@ -1206,3 +1264,77 @@ fn check_qos(
drop(video_qos); drop(video_qos);
Ok(()) Ok(())
} }
pub fn set_take_screenshot(display_idx: usize, sid: String, tx: Sender) {
SCREENSHOTS.lock().unwrap().insert(
display_idx,
Screenshot {
sid,
tx,
restore_vram: false,
},
);
}
// We need to this function, because the `stride` may be larger than `width * 4`.
fn get_rgba_from_pixelbuf<'a>(pixbuf: &scrap::PixelBuffer<'a>) -> ResultType<Vec<u8>> {
let w = pixbuf.width();
let h = pixbuf.height();
let stride = pixbuf.stride();
let Some(s) = stride.get(0) else {
bail!("Invalid pixel buf stride.")
};
if *s == w * 4 {
let mut rgba = vec![];
scrap::convert(pixbuf, scrap::Pixfmt::RGBA, &mut rgba)?;
Ok(rgba)
} else {
let bgra = pixbuf.data();
let mut bit_flipped = Vec::with_capacity(w * h * 4);
for y in 0..h {
for x in 0..w {
let i = s * y + 4 * x;
bit_flipped.extend_from_slice(&[bgra[i + 2], bgra[i + 1], bgra[i], bgra[i + 3]]);
}
}
Ok(bit_flipped)
}
}
fn handle_screenshot(screenshot: Screenshot, msg: String, w: usize, h: usize, data: Vec<u8>) {
let mut response = ScreenshotResponse::new();
response.sid = screenshot.sid;
if msg.is_empty() {
if data.is_empty() {
response.msg = "Failed to take screenshot, please try again later.".to_owned();
} else {
fn encode_png(width: usize, height: usize, rgba: Vec<u8>) -> ResultType<Vec<u8>> {
let mut png = Vec::new();
let mut encoder =
repng::Options::smallest(width as _, height as _).build(&mut png)?;
encoder.write(&rgba)?;
encoder.finish()?;
Ok(png)
}
match encode_png(w as _, h as _, data) {
Ok(png) => {
response.data = png.into();
}
Err(e) => {
response.msg = format!("Error encoding png: {}", e);
}
}
}
} else {
response.msg = msg;
}
let mut msg_out = Message::new();
msg_out.set_screenshot_response(response);
if let Err(e) = screenshot
.tx
.send((hbb_common::tokio::time::Instant::now(), Arc::new(msg_out)))
{
log::error!("Failed to send screenshot, {}", e);
}
}

View file

@ -230,6 +230,7 @@ class Header: Reactor.Component {
{restart_enabled && (pi.platform == "Linux" || pi.platform == "Windows" || pi.platform == "Mac OS") ? <li #restart_remote_device>{translate('Restart remote device')}</li> : ""} {restart_enabled && (pi.platform == "Linux" || pi.platform == "Windows" || pi.platform == "Mac OS") ? <li #restart_remote_device>{translate('Restart remote device')}</li> : ""}
{keyboard_enabled ? <li #lock-screen>{translate('Insert Lock')}</li> : ""} {keyboard_enabled ? <li #lock-screen>{translate('Insert Lock')}</li> : ""}
{keyboard_enabled && pi.platform == "Windows" && pi.sas_enabled ? <li #block-input>{translate("Block user input")}</li> : ""} {keyboard_enabled && pi.platform == "Windows" && pi.sas_enabled ? <li #block-input>{translate("Block user input")}</li> : ""}
{handler.is_screenshot_supported() ? <li #take-screenshot>{translate('Take screenshot')}</li> : "" }
<li #refresh>{translate('Refresh')}</li> <li #refresh>{translate('Refresh')}</li>
</menu> </menu>
</popup>; </popup>;
@ -377,6 +378,10 @@ class Header: Reactor.Component {
handler.lock_screen(); handler.lock_screen();
} }
event click $(#take-screenshot) {
handler.take_screenshot(pi.current_display, "");
}
event click $(#refresh) { event click $(#refresh) {
// 0 is just a dummy value. It will be ignored by the handler. // 0 is just a dummy value. It will be ignored by the handler.
handler.refresh_video(0); handler.refresh_video(0);
@ -546,6 +551,26 @@ handler.setCurrentDisplay = function(v) {
} }
} }
handler.screenshot = function(msg) {
if (msg) {
msgbox(
"custom-nocancel-nook-hasclose-error",
translate("Take screenshot"),
msg,
"",
function() {}
);
} else {
msgbox(
"custom-take-screenshot-nocancel-nook",
translate("Take screenshot"),
translate("screenshot-action-tip"),
"",
function() {}
);
}
}
function updatePrivacyMode() { function updatePrivacyMode() {
var el = $(li#privacy-mode); var el = $(li#privacy-mode);
if (el) { if (el) {

View file

@ -132,6 +132,17 @@ class MsgboxComponent: Reactor.Component {
return this.type.indexOf("skip") >= 0; return this.type.indexOf("skip") >= 0;
} }
function getScreenshotButtons() {
var isScreenshot = this.type.indexOf("take-screenshot") >= 0;
return isScreenshot
? <div>
<button .button #screenshotSaveAs .outline>{translate('Save as')}...</button>
<button .button #screenshotCopyToClip .outline>{translate('Copy to clipboard')}</button>
<button .button #screenshotCancel .outline>{translate('Cancel')}</button>
</div>
: "";
}
function render() { function render() {
this.set_outline_focus(); this.set_outline_focus();
var color = this.getColor(); var color = this.getColor();
@ -170,6 +181,7 @@ class MsgboxComponent: Reactor.Component {
{hasOk || this.hasRetry ? <button .button #submit>{translate(this.hasRetry ? "Retry" : "OK")}</button> : ""} {hasOk || this.hasRetry ? <button .button #submit>{translate(this.hasRetry ? "Retry" : "OK")}</button> : ""}
{hasLink ? <button .button #jumplink .outline>{translate('JumpLink')}</button> : ""} {hasLink ? <button .button #jumplink .outline>{translate('JumpLink')}</button> : ""}
{hasClose ? <button .button #cancel .outline>{translate('Close')}</button> : ""} {hasClose ? <button .button #cancel .outline>{translate('Close')}</button> : ""}
{this.getScreenshotButtons()}
</div> </div>
</div> </div>
</div> </div>
@ -246,6 +258,39 @@ class MsgboxComponent: Reactor.Component {
} }
} }
event click $(button#screenshotSaveAs) {
this.close();
handler.leave(handler.get_keyboard_mode());
const filter = "Png file (*.png)";
const defaultExt = "png";
const initialPath = System.path(#USER_DOCUMENTS, "screenshot");
const caption = "Save as";
var url = view.selectFile(#save, filter, defaultExt, initialPath, caption);
handler.enter(handler.get_keyboard_mode());
if(url) {
var res = handler.handle_screenshot("0:" + URL.toPath(url));
if (res) {
msgbox("custom-error-nocancel-nook-hasclose", "Take screenshot", res, "", function() {});
}
} else {
handler.handle_screenshot("2");
}
}
event click $(button#screenshotCopyToClip) {
this.close();
var res = handler.handle_screenshot("1");
if (res) {
msgbox("custom-error-nocancel-nook-hasclose", "Take screenshot", res, "", function() {});
}
}
event click $(button#screenshotCancel) {
this.close();
handler.handle_screenshot("2");
}
event keydown (evt) { event keydown (evt) {
if (!evt.shortcutKey) { if (!evt.shortcutKey) {
if (isEnterKey(evt)) { if (isEnterKey(evt)) {

View file

@ -383,6 +383,10 @@ impl InvokeUiSession for SciterHandler {
fn printer_request(&self, id: i32, path: String) { fn printer_request(&self, id: i32, path: String) {
self.call("printerRequest", &make_args!(id, path)); self.call("printerRequest", &make_args!(id, path));
} }
fn handle_screenshot_resp(&self, _sid: String, msg: String) {
self.call("screenshot", &make_args!(msg));
}
} }
pub struct SciterSession(Session<SciterHandler>); pub struct SciterSession(Session<SciterHandler>);
@ -529,6 +533,9 @@ impl sciter::EventHandler for SciterSession {
fn save_custom_image_quality(i32); fn save_custom_image_quality(i32);
fn refresh_video(i32); fn refresh_video(i32);
fn record_screen(bool); fn record_screen(bool);
fn is_screenshot_supported();
fn take_screenshot(i32, String);
fn handle_screenshot(String);
fn get_toggle_option(String); fn get_toggle_option(String);
fn is_privacy_mode_supported(); fn is_privacy_mode_supported();
fn toggle_option(String); fn toggle_option(String);
@ -866,6 +873,10 @@ impl SciterSession {
fn on_printer_selected(&self, id: i32, path: String, printer_name: String) { fn on_printer_selected(&self, id: i32, path: String, printer_name: String) {
self.printer_response(id, path, printer_name); self.printer_response(id, path, printer_name);
} }
fn handle_screenshot(&self, action: String) -> String {
crate::client::screenshot::handle_screenshot(action)
}
} }
pub fn make_fd(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> Value { pub fn make_fd(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> Value {

View file

@ -412,6 +412,14 @@ impl<T: InvokeUiSession> Session<T> {
self.send(Data::RecordScreen(start)); self.send(Data::RecordScreen(start));
} }
pub fn is_screenshot_supported(&self) -> bool {
crate::common::is_support_screenshot_num(self.lc.read().unwrap().version)
}
pub fn take_screenshot(&self, display: i32, sid: String) {
self.send(Data::TakeScreenshot((display, sid)));
}
pub fn is_recording(&self) -> bool { pub fn is_recording(&self) -> bool {
self.lc.read().unwrap().record_state self.lc.read().unwrap().record_state
} }
@ -1586,6 +1594,7 @@ pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default {
fn update_record_status(&self, start: bool); fn update_record_status(&self, start: bool);
fn update_empty_dirs(&self, _res: ReadEmptyDirsResponse) {} fn update_empty_dirs(&self, _res: ReadEmptyDirsResponse) {}
fn printer_request(&self, id: i32, path: String); fn printer_request(&self, id: i32, path: String);
fn handle_screenshot_resp(&self, sid: String, msg: String);
} }
impl<T: InvokeUiSession> Deref for Session<T> { impl<T: InvokeUiSession> Deref for Session<T> {