diff options
author | Caoimhe <caoimhebyrne06@gmail.com> | 2023-05-13 15:24:53 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-05-21 18:45:53 +0200 |
commit | 9f92e524648a9bf8451ba0f764a94a0a7e3f946b (patch) | |
tree | 6f989fe928429b6f469ef36d99ebe1a98ccc430d /Userland/Services/SpiceAgent | |
parent | 50a8db3922ebba08db60e357bb052dbb392e0e06 (diff) | |
download | serenity-9f92e524648a9bf8451ba0f764a94a0a7e3f946b.zip |
SpiceAgent: Add support for copying images to the clipboard
Diffstat (limited to 'Userland/Services/SpiceAgent')
-rw-r--r-- | Userland/Services/SpiceAgent/Message.cpp | 44 | ||||
-rw-r--r-- | Userland/Services/SpiceAgent/Message.h | 4 | ||||
-rw-r--r-- | Userland/Services/SpiceAgent/SpiceAgent.cpp | 25 | ||||
-rw-r--r-- | Userland/Services/SpiceAgent/SpiceAgent.h | 1 |
4 files changed, 63 insertions, 11 deletions
diff --git a/Userland/Services/SpiceAgent/Message.cpp b/Userland/Services/SpiceAgent/Message.cpp index f446125129..ffd5a0817d 100644 --- a/Userland/Services/SpiceAgent/Message.cpp +++ b/Userland/Services/SpiceAgent/Message.cpp @@ -11,6 +11,38 @@ namespace SpiceAgent { +ErrorOr<String> clipboard_data_type_to_mime_type(ClipboardDataType data_type) +{ + switch (data_type) { + case ClipboardDataType::Text: + return "text/plain"_string; + + case ClipboardDataType::PNG: + return "image/png"_string; + + case ClipboardDataType::BMP: + return "image/bitmap"_string; + + case ClipboardDataType::JPG: + return "image/jpeg"_string; + + case ClipboardDataType::TIFF: + return "image/tiff"_string; + + default: + return Error::from_string_literal("Unable to determine mime type!"); + } +} + +ErrorOr<ClipboardDataType> clipboard_data_type_from_raw_value(u32 value) +{ + if (value >= to_underlying(ClipboardDataType::__End)) { + return Error::from_string_literal("Unsupported clipboard type"); + } + + return static_cast<ClipboardDataType>(value); +} + ErrorOr<AnnounceCapabilitiesMessage> AnnounceCapabilitiesMessage::read_from_stream(AK::Stream& stream) { // If this message is a capabilities request, we don't have to parse anything else. @@ -57,11 +89,7 @@ ErrorOr<ClipboardGrabMessage> ClipboardGrabMessage::read_from_stream(AK::Stream& auto types = Vector<ClipboardDataType>(); while (!stream.is_eof()) { auto value = TRY(stream.read_value<u32>()); - if (value >= to_underlying(ClipboardDataType::__End)) { - return Error::from_string_literal("Unsupported clipboard type"); - } - - types.append(static_cast<ClipboardDataType>(value)); + types.append(TRY(clipboard_data_type_from_raw_value(value))); } return ClipboardGrabMessage(types); @@ -88,11 +116,7 @@ ErrorOr<String> ClipboardGrabMessage::debug_description() ErrorOr<ClipboardRequestMessage> ClipboardRequestMessage::read_from_stream(AK::Stream& stream) { auto value = TRY(stream.read_value<u32>()); - if (value >= to_underlying(ClipboardDataType::__End)) { - return Error::from_string_literal("Unsupported clipboard type"); - } - - auto type = static_cast<ClipboardDataType>(value); + auto type = TRY(clipboard_data_type_from_raw_value(value)); return ClipboardRequestMessage(type); } diff --git a/Userland/Services/SpiceAgent/Message.h b/Userland/Services/SpiceAgent/Message.h index 43799993a9..6a411b74d7 100644 --- a/Userland/Services/SpiceAgent/Message.h +++ b/Userland/Services/SpiceAgent/Message.h @@ -9,6 +9,7 @@ #include <AK/ByteBuffer.h> #include <AK/Format.h> #include <AK/Forward.h> +#include <AK/String.h> #include <AK/Vector.h> namespace SpiceAgent { @@ -50,6 +51,9 @@ enum class ClipboardDataType : u32 { __End }; +ErrorOr<String> clipboard_data_type_to_mime_type(ClipboardDataType type); +ErrorOr<ClipboardDataType> clipboard_data_type_from_raw_value(u32 value); + class Message { public: // The spice protocol headers contain a bit of documentation about these, but nothing major: diff --git a/Userland/Services/SpiceAgent/SpiceAgent.cpp b/Userland/Services/SpiceAgent/SpiceAgent.cpp index 33e0bf663f..f0e52268c4 100644 --- a/Userland/Services/SpiceAgent/SpiceAgent.cpp +++ b/Userland/Services/SpiceAgent/SpiceAgent.cpp @@ -8,6 +8,7 @@ #include "SpiceAgent.h" #include <AK/Debug.h> #include <LibGUI/Clipboard.h> +#include <LibGfx/ImageFormats/ImageDecoder.h> namespace SpiceAgent { @@ -111,11 +112,33 @@ ErrorOr<void> SpiceAgent::did_receive_clipboard_message(ClipboardMessage& messag case ClipboardDataType::Text: { // The default mime_type for set_data is `text/plain`. GUI::Clipboard::the().set_data(message.contents()); - return {}; + break; + } + + // For the image formats, let's try to find a decoder from LibGfx. + case ClipboardDataType::PNG: + case ClipboardDataType::BMP: + case ClipboardDataType::JPG: + case ClipboardDataType::TIFF: { + auto mime_type = TRY(clipboard_data_type_to_mime_type(message.data_type())); + + // FIXME: It should be trivial to make `try_create_for_raw_bytes` take a `StringView` instead of a direct `DeprecatedString`. + auto decoder = Gfx::ImageDecoder::try_create_for_raw_bytes(message.contents(), mime_type.to_deprecated_string()); + if (!decoder || (decoder->frame_count() == 0)) { + return Error::from_string_literal("Failed to find a suitable decoder for a pasted image!"); + } + + auto frame = TRY(decoder->frame(0)); + GUI::Clipboard::the().set_bitmap(*frame.image); + + break; } + default: return Error::from_string_literal("Unsupported clipboard data type!"); } + + return {}; } ErrorOr<ByteBuffer> SpiceAgent::read_message_buffer() diff --git a/Userland/Services/SpiceAgent/SpiceAgent.h b/Userland/Services/SpiceAgent/SpiceAgent.h index d877f55d4a..7eb9809f14 100644 --- a/Userland/Services/SpiceAgent/SpiceAgent.h +++ b/Userland/Services/SpiceAgent/SpiceAgent.h @@ -11,6 +11,7 @@ #include "Message.h" #include "MessageHeader.h" #include <AK/MemoryStream.h> +#include <AK/String.h> #include <AK/Vector.h> #include <LibCore/File.h> #include <LibCore/Notifier.h> |