LibWeb+LibWebView+UI: Update the selection keyboard on selection changes

When the selected text on a page changes, update the system selection
clipboard on supported systems (if primary pasting is enabled).
This commit is contained in:
Timothy Flynn 2026-05-27 11:43:35 -04:00 committed by Tim Flynn
parent 082281da62
commit 793e7dd01b
11 changed files with 46 additions and 0 deletions

View file

@ -10,6 +10,8 @@
#include <LibWeb/DOM/Event.h>
#include <LibWeb/DOM/EventTarget.h>
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/HTML/Navigable.h>
#include <LibWeb/Page/Page.h>
namespace Web::DOM {
@ -56,6 +58,12 @@ void fire_a_selectionchange_event(T& target, Document& document)
auto event = DOM::Event::create(document.realm(), HTML::EventNames::selectionchange, event_init);
target.dispatch_event(event);
// AD-HOC: When the selection changes, inform the UI to update the primary pasteboard.
if (auto& page = document.page(); page.enable_primary_paste()) {
if (auto text = page.focused_navigable().selected_text(); !text.is_empty())
page.client().page_did_update_primary_selection(text);
}
}
}

View file

@ -514,6 +514,7 @@ public:
virtual void page_did_insert_clipboard_entry(Clipboard::SystemClipboardRepresentation const&, [[maybe_unused]] StringView presentation_style) { }
virtual void page_did_request_clipboard_entries([[maybe_unused]] u64 request_id) { }
virtual void page_did_request_primary_paste() { }
virtual void page_did_update_primary_selection(String const&) { }
virtual void page_did_change_audio_play_state(HTML::AudioPlayState) { }

View file

@ -1103,6 +1103,14 @@ Utf16String Application::clipboard_text(ClipboardType) const
return Utf16String::from_utf8(m_clipboard->data);
}
void Application::set_clipboard_text(String text, ClipboardType)
{
m_clipboard = Web::Clipboard::SystemClipboardRepresentation {
.data = text.to_byte_string(),
.mime_type = "text/plain"_string,
};
}
Vector<Web::Clipboard::SystemClipboardRepresentation> Application::clipboard_entries() const
{
if (!m_clipboard.has_value())

View file

@ -130,6 +130,7 @@ public:
};
virtual bool supports_clipboard_type(ClipboardType) const;
virtual Utf16String clipboard_text(ClipboardType = ClipboardType::Text) const;
virtual void set_clipboard_text(String, ClipboardType = ClipboardType::Text);
virtual Vector<Web::Clipboard::SystemClipboardRepresentation> clipboard_entries() const;
virtual void insert_clipboard_entry(Web::Clipboard::SystemClipboardRepresentation);

View file

@ -1166,6 +1166,12 @@ void WebContentClient::did_request_primary_paste(u64 page_id)
}
}
void WebContentClient::did_update_primary_selection(u64 page_id, String text)
{
if (auto view = view_for_page_id(page_id); view.has_value())
Application::the().set_clipboard_text(move(text), Application::ClipboardType::Selection);
}
void WebContentClient::did_change_audio_play_state(u64 page_id, Web::HTML::AudioPlayState play_state)
{
if (auto view = view_for_page_id(page_id); view.has_value())

View file

@ -185,6 +185,7 @@ private:
virtual void did_insert_clipboard_entry(u64 page_id, Web::Clipboard::SystemClipboardRepresentation, String presentation_style) override;
virtual void did_request_clipboard_entries(u64 page_id, u64 request_id) override;
virtual void did_request_primary_paste(u64 page_id) override;
virtual void did_update_primary_selection(u64 page_id, String) override;
virtual void did_change_audio_play_state(u64 page_id, Web::HTML::AudioPlayState) override;
virtual void did_update_navigation_buttons_state(u64 page_id, bool back_enabled, bool forward_enabled) override;
virtual Messages::WebContentClient::StartWorkerAgentResponse start_worker_agent(u64 page_id, Web::HTML::WorkerAgentStartRequest request) override;

View file

@ -783,6 +783,11 @@ void PageClient::page_did_request_primary_paste()
client().async_did_request_primary_paste(m_id);
}
void PageClient::page_did_update_primary_selection(String const& text)
{
client().async_did_update_primary_selection(m_id, text);
}
void PageClient::page_did_change_audio_play_state(Web::HTML::AudioPlayState play_state)
{
client().async_did_change_audio_play_state(m_id, play_state);

View file

@ -203,6 +203,7 @@ private:
virtual void page_did_insert_clipboard_entry(Web::Clipboard::SystemClipboardRepresentation const&, StringView presentation_style) override;
virtual void page_did_request_clipboard_entries(u64 request_id) override;
virtual void page_did_request_primary_paste() override;
virtual void page_did_update_primary_selection(String const&) override;
virtual void page_did_change_audio_play_state(Web::HTML::AudioPlayState) override;
virtual Web::HTML::WorkerAgentId start_worker_agent(Web::HTML::WorkerAgentStartRequest&&) override;
virtual void close_worker_agent(Web::HTML::WorkerAgentId, Web::HTML::WorkerAgentOwnerToken) override;

View file

@ -123,6 +123,7 @@ endpoint WebContentClient
did_insert_clipboard_entry(u64 page_id, Web::Clipboard::SystemClipboardRepresentation entry, String presentation_style) =|
did_request_clipboard_entries(u64 page_id, u64 request_id) =|
did_request_primary_paste(u64 page_id) =|
did_update_primary_selection(u64 page_id, String text) =|
did_update_navigation_buttons_state(u64 page_id, bool back_enabled, bool forward_enabled) =|

View file

@ -235,6 +235,19 @@ Utf16String Application::clipboard_text(ClipboardType type) const
return utf16_string_from_qstring(clipboard->text(mode));
}
void Application::set_clipboard_text(String text, ClipboardType type)
{
if (browser_options().headless_mode.has_value()) {
WebView::Application::set_clipboard_text(text, type);
return;
}
auto* clipboard = QGuiApplication::clipboard();
auto mode = clipboard_mode(*clipboard, type);
clipboard->setText(qstring_from_ak_string(text), mode);
}
Vector<Web::Clipboard::SystemClipboardRepresentation> Application::clipboard_entries() const
{
if (browser_options().headless_mode.has_value())

View file

@ -54,6 +54,7 @@ private:
virtual bool supports_clipboard_type(ClipboardType) const override;
virtual Utf16String clipboard_text(ClipboardType) const override;
virtual void set_clipboard_text(String, ClipboardType = ClipboardType::Text) override;
virtual Vector<Web::Clipboard::SystemClipboardRepresentation> clipboard_entries() const override;
virtual void insert_clipboard_entry(Web::Clipboard::SystemClipboardRepresentation) override;