From 2e6d59b7b25573df07b56b65f31c8c9b66ed239e Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 5 Sep 2020 16:26:22 +0200 Subject: [PATCH] Clipboard: Add a key-value map alongside the clipboard storage A clipping now consists of three things: - The raw clip data - A MIME type - A key-value map (String, String) for anything you like --- Libraries/LibGUI/Clipboard.cpp | 12 +++++++++--- Libraries/LibGUI/Clipboard.h | 7 ++++++- Libraries/LibIPC/Dictionary.h | 7 ++++++- Services/Clipboard/ClientConnection.cpp | 4 ++-- Services/Clipboard/ClipboardServer.ipc | 4 ++-- Services/Clipboard/Storage.cpp | 6 +++++- Services/Clipboard/Storage.h | 5 ++++- 7 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Libraries/LibGUI/Clipboard.cpp b/Libraries/LibGUI/Clipboard.cpp index 8545febdaa..df96c01fa9 100644 --- a/Libraries/LibGUI/Clipboard.cpp +++ b/Libraries/LibGUI/Clipboard.cpp @@ -92,10 +92,11 @@ Clipboard::DataAndType Clipboard::data_and_type() const } auto data = ByteBuffer::copy(shared_buffer->data(), response->data_size()); auto type = response->mime_type(); - return { data, type }; + auto metadata = response->metadata().entries(); + return { data, type, metadata }; } -void Clipboard::set_data(ReadonlyBytes data, const String& type) +void Clipboard::set_data(ReadonlyBytes data, const String& type, const HashMap& metadata) { auto shared_buffer = SharedBuffer::create_with_size(data.size() + 1); if (!shared_buffer) { @@ -109,7 +110,7 @@ void Clipboard::set_data(ReadonlyBytes data, const String& type) shared_buffer->seal(); shared_buffer->share_with(connection().server_pid()); - connection().send_sync(shared_buffer->shbuf_id(), data.size(), type); + connection().send_sync(shared_buffer->shbuf_id(), data.size(), type, metadata); } void ClipboardServerConnection::handle(const Messages::ClipboardClient::ClipboardDataChanged& message) @@ -119,4 +120,9 @@ void ClipboardServerConnection::handle(const Messages::ClipboardClient::Clipboar clipboard.on_change(message.mime_type()); } +void Clipboard::set_bitmap(const Gfx::Bitmap& bitmap) +{ + (void) bitmap; +} + } diff --git a/Libraries/LibGUI/Clipboard.h b/Libraries/LibGUI/Clipboard.h index 96786baa2c..3f9a4033ac 100644 --- a/Libraries/LibGUI/Clipboard.h +++ b/Libraries/LibGUI/Clipboard.h @@ -27,8 +27,10 @@ #pragma once #include +#include #include #include +#include namespace GUI { @@ -38,16 +40,19 @@ public: ByteBuffer data() const { return data_and_type().data; } String mime_type() const { return data_and_type().mime_type; } - void set_data(ReadonlyBytes, const String& mime_type = "text/plain"); + void set_data(ReadonlyBytes, const String& mime_type = "text/plain", const HashMap& metadata = {}); void set_plain_text(const String& text) { set_data(text.bytes()); } + void set_bitmap(const Gfx::Bitmap&); + struct DataAndType { ByteBuffer data; String mime_type; + HashMap metadata; }; DataAndType data_and_type() const; diff --git a/Libraries/LibIPC/Dictionary.h b/Libraries/LibIPC/Dictionary.h index f272ec9165..34632a86e9 100644 --- a/Libraries/LibIPC/Dictionary.h +++ b/Libraries/LibIPC/Dictionary.h @@ -33,7 +33,12 @@ namespace IPC { class Dictionary { public: - Dictionary() {} + Dictionary() { } + + Dictionary(const HashMap& initial_entries) + : m_entries(initial_entries) + { + } bool is_empty() const { return m_entries.is_empty(); } size_t size() const { return m_entries.size(); } diff --git a/Services/Clipboard/ClientConnection.cpp b/Services/Clipboard/ClientConnection.cpp index 905a8f65b4..3e012e5aa5 100644 --- a/Services/Clipboard/ClientConnection.cpp +++ b/Services/Clipboard/ClientConnection.cpp @@ -68,7 +68,7 @@ OwnPtr ClientConnection::ha did_misbehave("SetClipboardData: Bad shared buffer ID"); return nullptr; } - Storage::the().set_data(*shared_buffer, message.data_size(), message.mime_type()); + Storage::the().set_data(*shared_buffer, message.data_size(), message.mime_type(), message.metadata().entries()); return make(); } @@ -92,7 +92,7 @@ OwnPtr ClientConnection::ha // After we respond to GetClipboardData, we have to wait for the client to ref the buffer on his side. m_last_sent_buffer = move(shared_buffer); } - return make(shbuf_id, storage.data_size(), storage.mime_type()); + return make(shbuf_id, storage.data_size(), storage.mime_type(), storage.metadata()); } void ClientConnection::notify_about_clipboard_change() diff --git a/Services/Clipboard/ClipboardServer.ipc b/Services/Clipboard/ClipboardServer.ipc index dc3dd4db28..c0c1fab8c8 100644 --- a/Services/Clipboard/ClipboardServer.ipc +++ b/Services/Clipboard/ClipboardServer.ipc @@ -2,6 +2,6 @@ endpoint ClipboardServer = 802 { Greet() => (i32 client_id) - GetClipboardData() => (i32 shbuf_id, i32 data_size, [UTF8] String mime_type) - SetClipboardData(i32 shbuf_id, i32 data_size, [UTF8] String mime_type) => () + GetClipboardData() => (i32 shbuf_id, i32 data_size, [UTF8] String mime_type, IPC::Dictionary metadata) + SetClipboardData(i32 shbuf_id, i32 data_size, [UTF8] String mime_type, IPC::Dictionary metadata) => () } diff --git a/Services/Clipboard/Storage.cpp b/Services/Clipboard/Storage.cpp index f64b5a4f70..e1788dbf39 100644 --- a/Services/Clipboard/Storage.cpp +++ b/Services/Clipboard/Storage.cpp @@ -44,12 +44,16 @@ Storage::~Storage() { } -void Storage::set_data(NonnullRefPtr data, size_t data_size, const String& mime_type) +void Storage::set_data(NonnullRefPtr data, size_t data_size, const String& mime_type, const HashMap& metadata) { dbg() << "Storage::set_data <- [" << mime_type << "] " << data->data() << " (" << data_size << " bytes)"; + for (auto& it : metadata) { + dbg() << " " << it.key << ": " << it.value; + } m_shared_buffer = move(data); m_data_size = data_size; m_mime_type = mime_type; + m_metadata = metadata; if (on_content_change) on_content_change(); diff --git a/Services/Clipboard/Storage.h b/Services/Clipboard/Storage.h index ba391d6f48..956377fa25 100644 --- a/Services/Clipboard/Storage.h +++ b/Services/Clipboard/Storage.h @@ -27,6 +27,7 @@ #pragma once #include +#include #include #include @@ -40,6 +41,7 @@ public: bool has_data() const { return m_shared_buffer; } const String& mime_type() const { return m_mime_type; } + const HashMap& metadata() const { return m_metadata; } const u8* data() const { @@ -55,7 +57,7 @@ public: return 0; } - void set_data(NonnullRefPtr, size_t data_size, const String& mime_type); + void set_data(NonnullRefPtr, size_t data_size, const String& mime_type, const HashMap& metadata); Function on_content_change; @@ -65,6 +67,7 @@ private: String m_mime_type; RefPtr m_shared_buffer; size_t m_data_size { 0 }; + HashMap m_metadata; }; }