From 0f8ad128b65869d683253753a477c0ccafca9bf2 Mon Sep 17 00:00:00 2001 From: JJ Liebig Date: Thu, 3 Sep 2026 15:30:04 +0200 Subject: fix: read Windows clipboard images in WSL (#3572) refs #3376 --- src/platform/linux.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'src/platform') diff --git a/src/platform/linux.rs b/src/platform/linux.rs index f3ba0429..8efe7357 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -478,6 +478,13 @@ pub fn open_url(url: &str) -> std::io::Result> { } pub fn read_clipboard_image() -> Option { + if running_inside_wsl() { + if let Some(image) = read_wsl_clipboard_image_with_command(|program| Command::new(program)) + { + return Some(image); + } + } + for (mime, extension) in [ ("image/png", "png"), ("image/jpeg", "jpg"), @@ -508,6 +515,24 @@ pub fn read_clipboard_image() -> Option { None } +fn read_wsl_clipboard_image_with_command( + mut command: impl FnMut(&str) -> Command, +) -> Option { + let mut command = command("powershell.exe"); + command.args([ + "-NoProfile", + "-NonInteractive", + "-STA", + "-Command", + "$ErrorActionPreference='Stop'; Add-Type -AssemblyName System.Windows.Forms; Add-Type -AssemblyName System.Drawing; $image=[System.Windows.Forms.Clipboard]::GetImage(); if ($null -eq $image) { exit 1 }; $stream=[System.IO.MemoryStream]::new(); try { $image.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png); [Console]::OpenStandardOutput().Write($stream.GetBuffer(), 0, [int]$stream.Length) } finally { $stream.Dispose(); $image.Dispose() }", + ]); + let bytes = read_clipboard_image_with_spawned_command(command)?; + bytes_match_image_signature("png", &bytes).then_some(ClipboardImage { + bytes, + extension: "png", + }) +} + fn read_validated_clipboard_image( program: &str, args: &[&str], @@ -1494,6 +1519,24 @@ mod tests { ); } + #[test] + fn read_wsl_clipboard_image_accepts_png_from_windows_command() { + assert_eq!( + read_wsl_clipboard_image_with_command(|program| { + assert_eq!(program, "powershell.exe"); + let mut command = Command::new("sh"); + command + .arg("-c") + .arg("printf '\\211PNG\\r\\n\\032\\nrest-of-image'"); + command + }), + Some(ClipboardImage { + bytes: b"\x89PNG\r\n\x1a\nrest-of-image".to_vec(), + extension: "png", + }) + ); + } + #[test] fn image_signatures_match_only_their_format() { assert!(bytes_match_image_signature("png", b"\x89PNG\r\n\x1a\n...")); -- cgit v1.2.3