summaryrefslogtreecommitdiff
path: root/Userland/Services/SpiceAgent
diff options
context:
space:
mode:
authorCaoimhe <caoimhebyrne06@gmail.com>2023-05-13 15:24:53 +0100
committerAndreas Kling <kling@serenityos.org>2023-05-21 18:45:53 +0200
commit9f92e524648a9bf8451ba0f764a94a0a7e3f946b (patch)
tree6f989fe928429b6f469ef36d99ebe1a98ccc430d /Userland/Services/SpiceAgent
parent50a8db3922ebba08db60e357bb052dbb392e0e06 (diff)
downloadserenity-9f92e524648a9bf8451ba0f764a94a0a7e3f946b.zip
SpiceAgent: Add support for copying images to the clipboard
Diffstat (limited to 'Userland/Services/SpiceAgent')
-rw-r--r--Userland/Services/SpiceAgent/Message.cpp44
-rw-r--r--Userland/Services/SpiceAgent/Message.h4
-rw-r--r--Userland/Services/SpiceAgent/SpiceAgent.cpp25
-rw-r--r--Userland/Services/SpiceAgent/SpiceAgent.h1
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>