summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibGUI
diff options
context:
space:
mode:
authorTheFightingCatfish <seekingblues@gmail.com>2021-07-27 03:19:56 +0800
committerAndreas Kling <kling@serenityos.org>2021-07-27 23:49:25 +0200
commit0c53c2dfa2a74c81b4cd675484defe38d2b9c5e4 (patch)
tree01949514cc7a350ec686e26528775acee75534c7 /Userland/Libraries/LibGUI
parent95f393ebcd750ec9a5f876dab09418c2aa913ab4 (diff)
downloadserenity-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.cpp87
-rw-r--r--Userland/Libraries/LibGUI/Clipboard.h44
-rw-r--r--Userland/Libraries/LibGUI/TextEditor.cpp9
-rw-r--r--Userland/Libraries/LibGUI/TextEditor.h8
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();