Files
rustdesk/src/client/screenshot.rs
fufesou c626c2414d 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>
2025-04-30 17:23:35 +08:00

100 lines
2.8 KiB
Rust

#[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)
}