mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-03 08:08:43 +00:00
LibWeb+LibWebVew+WebContent+UI: Add IPC to retrieve the system clipboard
We currently have a single IPC to set clipboard data. We will also need an IPC to retrieve that data from the UI. This defines system clipboard data in LibWeb to handle this transfer, and adds the IPC to provide it.
This commit is contained in:
parent
5fb5066e89
commit
61c0f67c8c
Notes:
github-actions[bot]
2025-05-02 21:47:42 +00:00
Author: https://github.com/trflynn89
Commit: 61c0f67c8c
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4548
Reviewed-by: https://github.com/shannonbooth
23 changed files with 255 additions and 28 deletions
|
@ -34,6 +34,7 @@ set(SOURCES
|
|||
Clipboard/Clipboard.cpp
|
||||
Clipboard/ClipboardEvent.cpp
|
||||
Clipboard/ClipboardItem.cpp
|
||||
Clipboard/SystemClipboard.cpp
|
||||
Compression/CompressionStream.cpp
|
||||
Compression/DecompressionStream.cpp
|
||||
ContentSecurityPolicy/Directives/Directive.cpp
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <LibTextCodec/Decoder.h>
|
||||
#include <LibWeb/Bindings/ClipboardPrototype.h>
|
||||
#include <LibWeb/Clipboard/Clipboard.h>
|
||||
#include <LibWeb/Clipboard/SystemClipboard.h>
|
||||
#include <LibWeb/FileAPI/Blob.h>
|
||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
||||
|
@ -40,43 +41,43 @@ void Clipboard::initialize(JS::Realm& realm)
|
|||
}
|
||||
|
||||
// https://w3c.github.io/clipboard-apis/#os-specific-well-known-format
|
||||
static StringView os_specific_well_known_format(StringView mime_type_string)
|
||||
static String os_specific_well_known_format(StringView mime_type_string)
|
||||
{
|
||||
// NOTE: Here we always takes the Linux case, and defer to the browser process to handle OS specific implementations.
|
||||
auto mime_type = MimeSniff::MimeType::parse(mime_type_string);
|
||||
|
||||
// 1. Let wellKnownFormat be an empty string.
|
||||
StringView well_known_format {};
|
||||
String well_known_format {};
|
||||
|
||||
// 2. If mimeType’s essence is "text/plain", then
|
||||
if (mime_type->essence() == "text/plain"sv) {
|
||||
if (auto const& essence = mime_type->essence(); essence == "text/plain"sv) {
|
||||
// On Windows, follow the convention described below:
|
||||
// Assign CF_UNICODETEXT to wellKnownFormat.
|
||||
// On MacOS, follow the convention described below:
|
||||
// Assign NSPasteboardTypeString to wellKnownFormat.
|
||||
// On Linux, ChromeOS, and Android, follow the convention described below:
|
||||
// Assign "text/plain" to wellKnownFormat.
|
||||
well_known_format = "text/plain"sv;
|
||||
well_known_format = essence;
|
||||
}
|
||||
// 3. Else, if mimeType’s essence is "text/html", then
|
||||
if (mime_type->essence() == "text/html"sv) {
|
||||
else if (essence == "text/html"sv) {
|
||||
// On Windows, follow the convention described below:
|
||||
// Assign CF_HTML to wellKnownFormat.
|
||||
// On MacOS, follow the convention described below:
|
||||
// Assign NSHTMLPboardType to wellKnownFormat.
|
||||
// On Linux, ChromeOS, and Android, follow the convention described below:
|
||||
// Assign "text/html" to wellKnownFormat.
|
||||
well_known_format = "text/html"sv;
|
||||
well_known_format = essence;
|
||||
}
|
||||
// 4. Else, if mimeType’s essence is "image/png", then
|
||||
if (mime_type->essence() == "image/png"sv) {
|
||||
else if (essence == "image/png"sv) {
|
||||
// On Windows, follow the convention described below:
|
||||
// Assign "PNG" to wellKnownFormat.
|
||||
// On MacOS, follow the convention described below:
|
||||
// Assign NSPasteboardTypePNG to wellKnownFormat.
|
||||
// On Linux, ChromeOS, and Android, follow the convention described below:
|
||||
// Assign "image/png" to wellKnownFormat.
|
||||
well_known_format = "image/png"sv;
|
||||
well_known_format = essence;
|
||||
}
|
||||
|
||||
// 5. Return wellKnownFormat.
|
||||
|
@ -113,7 +114,7 @@ static void write_blobs_and_option_to_clipboard(JS::Realm& realm, ReadonlySpan<G
|
|||
auto payload = MUST(TextCodec::convert_input_to_utf8_using_given_decoder_unless_there_is_a_byte_order_mark(*decoder, item->raw_bytes()));
|
||||
|
||||
// 4. Insert payload and presentationStyle into the system clipboard using formatString as the native clipboard format.
|
||||
window.page().client().page_did_insert_clipboard_entry(payload, presentation_style, format_string);
|
||||
window.page().client().page_did_insert_clipboard_entry({ payload.to_byte_string(), move(format_string) }, presentation_style);
|
||||
}
|
||||
|
||||
// FIXME: 3. Write web custom formats given webCustomFormats.
|
||||
|
|
41
Libraries/LibWeb/Clipboard/SystemClipboard.cpp
Normal file
41
Libraries/LibWeb/Clipboard/SystemClipboard.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Tim Flynn <trflynn89@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibIPC/Decoder.h>
|
||||
#include <LibIPC/Encoder.h>
|
||||
#include <LibWeb/Clipboard/SystemClipboard.h>
|
||||
|
||||
template<>
|
||||
ErrorOr<void> IPC::encode(Encoder& encoder, Web::Clipboard::SystemClipboardRepresentation const& output)
|
||||
{
|
||||
TRY(encoder.encode(output.data));
|
||||
TRY(encoder.encode(output.mime_type));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<>
|
||||
ErrorOr<Web::Clipboard::SystemClipboardRepresentation> IPC::decode(Decoder& decoder)
|
||||
{
|
||||
auto data = TRY(decoder.decode<ByteString>());
|
||||
auto mime_type = TRY(decoder.decode<String>());
|
||||
|
||||
return Web::Clipboard::SystemClipboardRepresentation { move(data), move(mime_type) };
|
||||
}
|
||||
|
||||
template<>
|
||||
ErrorOr<void> IPC::encode(Encoder& encoder, Web::Clipboard::SystemClipboardItem const& output)
|
||||
{
|
||||
TRY(encoder.encode(output.system_clipboard_representations));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<>
|
||||
ErrorOr<Web::Clipboard::SystemClipboardItem> IPC::decode(Decoder& decoder)
|
||||
{
|
||||
auto system_clipboard_representation = TRY(decoder.decode<Vector<Web::Clipboard::SystemClipboardRepresentation>>());
|
||||
|
||||
return Web::Clipboard::SystemClipboardItem { move(system_clipboard_representation) };
|
||||
}
|
43
Libraries/LibWeb/Clipboard/SystemClipboard.h
Normal file
43
Libraries/LibWeb/Clipboard/SystemClipboard.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Tim Flynn <trflynn89@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibIPC/Forward.h>
|
||||
|
||||
namespace Web::Clipboard {
|
||||
|
||||
// https://w3c.github.io/clipboard-apis/#system-clipboard-representation
|
||||
struct SystemClipboardRepresentation {
|
||||
ByteString data;
|
||||
String mime_type;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/clipboard-apis/#system-clipboard-item
|
||||
struct SystemClipboardItem {
|
||||
Vector<SystemClipboardRepresentation> system_clipboard_representations;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<>
|
||||
ErrorOr<void> encode(Encoder&, Web::Clipboard::SystemClipboardRepresentation const&);
|
||||
|
||||
template<>
|
||||
ErrorOr<Web::Clipboard::SystemClipboardRepresentation> decode(Decoder&);
|
||||
|
||||
template<>
|
||||
ErrorOr<void> encode(Encoder&, Web::Clipboard::SystemClipboardItem const&);
|
||||
|
||||
template<>
|
||||
ErrorOr<Web::Clipboard::SystemClipboardItem> decode(Decoder&);
|
||||
|
||||
}
|
|
@ -92,6 +92,9 @@ enum class XMLHttpRequestResponseType : u8;
|
|||
namespace Web::Clipboard {
|
||||
class Clipboard;
|
||||
class ClipboardItem;
|
||||
|
||||
struct SystemClipboardItem;
|
||||
struct SystemClipboardRepresentation;
|
||||
}
|
||||
|
||||
namespace Web::Compression {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <LibIPC/Decoder.h>
|
||||
#include <LibIPC/Encoder.h>
|
||||
#include <LibWeb/CSS/StyleComputer.h>
|
||||
#include <LibWeb/Clipboard/SystemClipboard.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/Range.h>
|
||||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
|
@ -49,6 +50,7 @@ void Page::visit_edges(JS::Cell::Visitor& visitor)
|
|||
visitor.visit(m_client);
|
||||
visitor.visit(m_window_rect_observer);
|
||||
visitor.visit(m_on_pending_dialog_closed);
|
||||
visitor.visit(m_pending_clipboard_requests);
|
||||
}
|
||||
|
||||
HTML::Navigable& Page::focused_navigable()
|
||||
|
@ -454,6 +456,20 @@ void Page::select_dropdown_closed(Optional<u32> const& selected_item_id)
|
|||
}
|
||||
}
|
||||
|
||||
void Page::request_clipboard_entries(ClipboardRequest request)
|
||||
{
|
||||
auto request_id = m_next_clipboard_request_id++;
|
||||
m_pending_clipboard_requests.set(request_id, request);
|
||||
|
||||
client().page_did_request_clipboard_entries(request_id);
|
||||
}
|
||||
|
||||
void Page::retrieved_clipboard_entries(u64 request_id, Vector<Clipboard::SystemClipboardItem> items)
|
||||
{
|
||||
if (auto request = m_pending_clipboard_requests.take(request_id); request.has_value())
|
||||
(*request)->function()(move(items));
|
||||
}
|
||||
|
||||
void Page::register_media_element(Badge<HTML::HTMLMediaElement>, UniqueNodeID media_id)
|
||||
{
|
||||
m_media_elements.append(media_id);
|
||||
|
|
|
@ -164,6 +164,10 @@ public:
|
|||
void did_request_select_dropdown(WeakPtr<HTML::HTMLSelectElement> target, Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items);
|
||||
void select_dropdown_closed(Optional<u32> const& selected_item_id);
|
||||
|
||||
using ClipboardRequest = GC::Ref<GC::Function<void(Vector<Clipboard::SystemClipboardItem>)>>;
|
||||
void request_clipboard_entries(ClipboardRequest);
|
||||
void retrieved_clipboard_entries(u64 request_id, Vector<Clipboard::SystemClipboardItem>);
|
||||
|
||||
enum class PendingNonBlockingDialog {
|
||||
None,
|
||||
ColorPicker,
|
||||
|
@ -272,6 +276,9 @@ private:
|
|||
PendingNonBlockingDialog m_pending_non_blocking_dialog { PendingNonBlockingDialog::None };
|
||||
WeakPtr<HTML::HTMLElement> m_pending_non_blocking_dialog_target;
|
||||
|
||||
HashMap<u64, ClipboardRequest> m_pending_clipboard_requests;
|
||||
u64 m_next_clipboard_request_id { 0 };
|
||||
|
||||
Vector<UniqueNodeID> m_media_elements;
|
||||
Optional<UniqueNodeID> m_media_context_menu_element_id;
|
||||
|
||||
|
@ -393,7 +400,8 @@ public:
|
|||
|
||||
virtual void page_did_change_theme_color(Gfx::Color) { }
|
||||
|
||||
virtual void page_did_insert_clipboard_entry([[maybe_unused]] StringView data, [[maybe_unused]] StringView presentation_style, [[maybe_unused]] StringView mime_type) { }
|
||||
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_change_audio_play_state(HTML::AudioPlayState) { }
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue