diff options
author | TheFightingCatfish <seekingblues@gmail.com> | 2021-07-27 03:19:56 +0800 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-27 23:49:25 +0200 |
commit | 0c53c2dfa2a74c81b4cd675484defe38d2b9c5e4 (patch) | |
tree | 01949514cc7a350ec686e26528775acee75534c7 /Userland/Libraries/LibGUI | |
parent | 95f393ebcd750ec9a5f876dab09418c2aa913ab4 (diff) | |
download | serenity-0c53c2dfa2a74c81b4cd675484defe38d2b9c5e4.zip |
LibGUI: Add a ClipboardClient for GUI::Clipboard
Anyone who inherits from `GUI::Clipboard::ClipboardClient` will receive
clipboard notifications via `clipboard_content_did_change()`.
Update ClipboardHistoryModel, TextEditor and TerminalWidget to inherit
from this class.
Diffstat (limited to 'Userland/Libraries/LibGUI')
-rw-r--r-- | Userland/Libraries/LibGUI/Clipboard.cpp | 87 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/Clipboard.h | 44 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/TextEditor.cpp | 9 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/TextEditor.h | 8 |
4 files changed, 90 insertions, 58 deletions
diff --git a/Userland/Libraries/LibGUI/Clipboard.cpp b/Userland/Libraries/LibGUI/Clipboard.cpp index b41a435d98..360afb2d21 100644 --- a/Userland/Libraries/LibGUI/Clipboard.cpp +++ b/Userland/Libraries/LibGUI/Clipboard.cpp @@ -1,10 +1,10 @@ /* * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ -#include <AK/Badge.h> #include <Clipboard/ClipboardClientEndpoint.h> #include <Clipboard/ClipboardServerEndpoint.h> #include <LibGUI/Clipboard.h> @@ -23,18 +23,14 @@ private: : IPC::ServerConnection<ClipboardClientEndpoint, ClipboardServerEndpoint>(*this, "/tmp/portal/clipboard") { } - virtual void clipboard_data_changed(String const& mime_type) override; -}; -Clipboard& Clipboard::the() -{ - static Clipboard* s_the; - if (!s_the) - s_the = new Clipboard; - return *s_the; -} + virtual void clipboard_data_changed(String const& mime_type) override + { + Clipboard::the().clipboard_data_changed({}, mime_type); + } +}; -ClipboardServerConnection* s_connection; +static ClipboardServerConnection* s_connection; static ClipboardServerConnection& connection() { @@ -46,8 +42,12 @@ void Clipboard::initialize(Badge<Application>) s_connection = &ClipboardServerConnection::construct().leak_ref(); } -Clipboard::Clipboard() +Clipboard& Clipboard::the() { + static Clipboard* s_the; + if (!s_the) + s_the = new Clipboard; + return *s_the; } Clipboard::DataAndType Clipboard::data_and_type() const @@ -61,31 +61,6 @@ Clipboard::DataAndType Clipboard::data_and_type() const return { data, type, metadata }; } -void Clipboard::set_data(ReadonlyBytes data, const String& type, const HashMap<String, String>& metadata) -{ - auto buffer = Core::AnonymousBuffer::create_with_size(data.size()); - if (!buffer.is_valid()) { - dbgln("GUI::Clipboard::set_data() failed to create a buffer"); - return; - } - if (!data.is_empty()) - memcpy(buffer.data<void>(), data.data(), data.size()); - - connection().async_set_clipboard_data(move(buffer), type, metadata); -} - -void Clipboard::clear() -{ - connection().async_set_clipboard_data({}, {}, {}); -} - -void ClipboardServerConnection::clipboard_data_changed(String const& mime_type) -{ - auto& clipboard = Clipboard::the(); - if (clipboard.on_change) - clipboard.on_change(mime_type); -} - RefPtr<Gfx::Bitmap> Clipboard::bitmap() const { auto clipping = data_and_type(); @@ -126,7 +101,20 @@ RefPtr<Gfx::Bitmap> Clipboard::bitmap() const return bitmap; } -void Clipboard::set_bitmap(const Gfx::Bitmap& bitmap) +void Clipboard::set_data(ReadonlyBytes const& data, String const& type, HashMap<String, String> const& metadata) +{ + auto buffer = Core::AnonymousBuffer::create_with_size(data.size()); + if (!buffer.is_valid()) { + dbgln("GUI::Clipboard::set_data() failed to create a buffer"); + return; + } + if (!data.is_empty()) + memcpy(buffer.data<void>(), data.data(), data.size()); + + connection().async_set_clipboard_data(move(buffer), type, metadata); +} + +void Clipboard::set_bitmap(Gfx::Bitmap const& bitmap) { HashMap<String, String> metadata; metadata.set("width", String::number(bitmap.width())); @@ -137,4 +125,27 @@ void Clipboard::set_bitmap(const Gfx::Bitmap& bitmap) set_data({ bitmap.scanline(0), bitmap.size_in_bytes() }, "image/x-serenityos", metadata); } +void Clipboard::clear() +{ + connection().async_set_clipboard_data({}, {}, {}); +} + +void Clipboard::clipboard_data_changed(Badge<ClipboardServerConnection>, String const& mime_type) +{ + if (on_change) + on_change(mime_type); + for (auto* client : m_clients) + client->clipboard_content_did_change(mime_type); +} + +Clipboard::ClipboardClient::ClipboardClient() +{ + Clipboard::the().register_client({}, *this); +} + +Clipboard::ClipboardClient::~ClipboardClient() +{ + Clipboard::the().unregister_client({}, *this); +} + } diff --git a/Userland/Libraries/LibGUI/Clipboard.h b/Userland/Libraries/LibGUI/Clipboard.h index 47627cd84c..b5cc02d9b8 100644 --- a/Userland/Libraries/LibGUI/Clipboard.h +++ b/Userland/Libraries/LibGUI/Clipboard.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ @@ -15,22 +16,17 @@ namespace GUI { +class ClipboardServerConnection; + class Clipboard { public: - static Clipboard& the(); - - 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", const HashMap<String, String>& metadata = {}); - void clear(); - - void set_plain_text(const String& text) - { - set_data(text.bytes()); - } + class ClipboardClient { + public: + ClipboardClient(); + virtual ~ClipboardClient(); - void set_bitmap(const Gfx::Bitmap&); - RefPtr<Gfx::Bitmap> bitmap() const; + virtual void clipboard_content_did_change(String const& mime_type) = 0; + }; struct DataAndType { ByteBuffer data; @@ -38,14 +34,30 @@ public: HashMap<String, String> metadata; }; + static void initialize(Badge<Application>); + static Clipboard& the(); + DataAndType data_and_type() const; + ByteBuffer data() const { return data_and_type().data; } + String mime_type() const { return data_and_type().mime_type; } + RefPtr<Gfx::Bitmap> bitmap() const; - Function<void(const String& mime_type)> on_change; + void set_data(ReadonlyBytes const& data, String const& mime_type = "text/plain", HashMap<String, String> const& metadata = {}); + void set_plain_text(String const& text) { set_data(text.bytes()); } + void set_bitmap(Gfx::Bitmap const&); + void clear(); - static void initialize(Badge<Application>); + void clipboard_data_changed(Badge<ClipboardServerConnection>, String const& mime_type); + + void register_client(Badge<ClipboardClient>, ClipboardClient& client) { m_clients.set(&client); } + void unregister_client(Badge<ClipboardClient>, ClipboardClient& client) { m_clients.remove(&client); } + + Function<void(String const& mime_type)> on_change; private: - Clipboard(); + Clipboard() = default; + + HashTable<ClipboardClient*> m_clients; }; } diff --git a/Userland/Libraries/LibGUI/TextEditor.cpp b/Userland/Libraries/LibGUI/TextEditor.cpp index f7c9c55a63..68cba0725f 100644 --- a/Userland/Libraries/LibGUI/TextEditor.cpp +++ b/Userland/Libraries/LibGUI/TextEditor.cpp @@ -83,6 +83,7 @@ void TextEditor::create_actions() m_cut_action->set_enabled(false); m_copy_action->set_enabled(false); m_paste_action = CommonActions::make_paste_action([&](auto&) { paste(); }, this); + m_paste_action->set_enabled(is_editable() && Clipboard::the().mime_type().starts_with("text/") && !Clipboard::the().data().is_empty()); m_delete_action = CommonActions::make_delete_action([&](auto&) { do_delete(); }, this); if (is_multi_line()) { m_go_to_line_action = Action::create( @@ -98,9 +99,6 @@ void TextEditor::create_actions() this); } m_select_all_action = CommonActions::make_select_all_action([this](auto&) { select_all(); }, this); - Clipboard::the().on_change = [this](auto const& mime_type) { - m_paste_action->set_enabled(is_editable() && mime_type.starts_with("text/") && !Clipboard::the().data().is_empty()); - }; } void TextEditor::set_text(StringView const& text) @@ -1801,6 +1799,11 @@ void TextEditor::document_did_set_cursor(TextPosition const& position) set_cursor(position); } +void TextEditor::clipboard_content_did_change(String const& mime_type) +{ + m_paste_action->set_enabled(is_editable() && mime_type.starts_with("text/") && !Clipboard::the().data().is_empty()); +} + void TextEditor::set_document(TextDocument& document) { if (m_document.ptr() == &document) diff --git a/Userland/Libraries/LibGUI/TextEditor.h b/Userland/Libraries/LibGUI/TextEditor.h index cea1c30f25..4ee1ebdfa6 100644 --- a/Userland/Libraries/LibGUI/TextEditor.h +++ b/Userland/Libraries/LibGUI/TextEditor.h @@ -12,6 +12,8 @@ #include <LibCore/ElapsedTimer.h> #include <LibCore/Timer.h> #include <LibGUI/AbstractScrollableWidget.h> +#include <LibGUI/Action.h> +#include <LibGUI/Clipboard.h> #include <LibGUI/Forward.h> #include <LibGUI/TextDocument.h> #include <LibGUI/TextRange.h> @@ -24,7 +26,8 @@ namespace GUI { class TextEditor : public AbstractScrollableWidget , public TextDocument::Client - , public Syntax::HighlighterClient { + , public Syntax::HighlighterClient + , public Clipboard::ClipboardClient { C_OBJECT(TextEditor); public: @@ -252,6 +255,9 @@ private: virtual GUI::TextDocument& highlighter_did_request_document() final { return document(); } virtual GUI::TextPosition highlighter_did_request_cursor() const final { return m_cursor; } + // ^Clipboard::ClipboardClient + virtual void clipboard_content_did_change(String const& mime_type) override; + void create_actions(); void paint_ruler(Painter&); void update_content_size(); |