SpiceAgent: Implement ClipboardGrab messages

This commit is contained in:
Caoimhe 2023-05-13 13:32:03 +01:00 committed by Andreas Kling
parent 79c73dd260
commit 8202f13169
Notes: sideshowbarker 2024-07-17 01:10:58 +09:00
3 changed files with 119 additions and 0 deletions

View file

@ -52,4 +52,37 @@ ErrorOr<String> AnnounceCapabilitiesMessage::debug_description()
return builder.to_string();
}
ErrorOr<ClipboardGrabMessage> ClipboardGrabMessage::read_from_stream(AK::Stream& 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));
}
return ClipboardGrabMessage(types);
}
ErrorOr<void> ClipboardGrabMessage::write_to_stream(AK::Stream& stream)
{
for (auto type : types()) {
TRY(stream.write_value(type));
}
return {};
}
ErrorOr<String> ClipboardGrabMessage::debug_description()
{
StringBuilder builder;
TRY(builder.try_append("ClipboardGrabMessage { "sv));
TRY(builder.try_appendff("types = {}", types()));
TRY(builder.try_append(" }"sv));
return builder.to_string();
}
}

View file

@ -6,6 +6,7 @@
#pragma once
#include <AK/Format.h>
#include <AK/Forward.h>
#include <AK/Vector.h>
@ -37,6 +38,17 @@ enum class Capability : u32 {
ClipboardGrabSerial
};
// Used to describe the type of data which is present on the user's clipboard.
enum class ClipboardDataType : u32 {
None = 0,
Text,
PNG,
BMP,
TIFF,
JPG,
__End
};
class Message {
public:
// The spice protocol headers contain a bit of documentation about these, but nothing major:
@ -98,4 +110,64 @@ private:
Vector<Capability> m_capabilities;
};
// Sent/received to tell the server/client that clipboard data is available.
class ClipboardGrabMessage : public Message {
public:
ClipboardGrabMessage(Vector<ClipboardDataType> const& types)
: Message(Type::ClipboardGrab)
, m_types(types)
{
}
static ErrorOr<ClipboardGrabMessage> read_from_stream(AK::Stream& stream);
ErrorOr<void> write_to_stream(AK::Stream& stream);
ErrorOr<String> debug_description() override;
Vector<ClipboardDataType> const& types() { return m_types; }
private:
Vector<ClipboardDataType> m_types;
};
}
namespace AK {
template<>
struct Formatter<SpiceAgent::ClipboardDataType> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, SpiceAgent::ClipboardDataType const& header)
{
auto string = "Unknown"sv;
switch (header) {
case SpiceAgent::ClipboardDataType::None:
string = "None"sv;
break;
case SpiceAgent::ClipboardDataType::Text:
string = "Text"sv;
break;
case SpiceAgent::ClipboardDataType::PNG:
string = "PNG"sv;
break;
case SpiceAgent::ClipboardDataType::BMP:
string = "BMP"sv;
break;
case SpiceAgent::ClipboardDataType::TIFF:
string = "TIFF"sv;
break;
case SpiceAgent::ClipboardDataType::JPG:
string = "JPG"sv;
break;
default:
break;
}
return Formatter<StringView>::format(builder, string);
}
};
}

View file

@ -64,6 +64,20 @@ ErrorOr<void> SpiceAgent::on_message_received()
break;
}
case Message::Type::ClipboardGrab: {
auto message = TRY(ClipboardGrabMessage::read_from_stream(stream));
if (message.types().is_empty())
break;
auto data_type = message.types().first();
if (data_type == ClipboardDataType::None)
break;
dbgln_if(SPICE_AGENT_DEBUG, "The spice server has notified us of new clipboard data of type: {}", data_type);
break;
}
// We ignore certain messages to prevent it from clogging up the logs.
case Message::Type::MonitorsConfig:
dbgln_if(SPICE_AGENT_DEBUG, "Ignored message: {}", header);