Changeset 261555 in webkit


Ignore:
Timestamp:
May 12, 2020 8:22:11 AM (4 years ago)
Author:
Carlos Garcia Campos
Message:

[GTK4] Add support for clipboard operations
https://bugs.webkit.org/show_bug.cgi?id=211561

Reviewed by Adrian Perez de Castro.

  • UIProcess/gtk/Clipboard.h:
  • UIProcess/gtk/ClipboardGtk4.cpp:

(WebKit::Clipboard::Clipboard):
(WebKit::Clipboard::type const):
(WebKit::Clipboard::formats):
(WebKit::ReadTextAsyncData::ReadTextAsyncData):
(WebKit::Clipboard::readText):
(WebKit::ReadFilePathsAsyncData::ReadFilePathsAsyncData):
(WebKit::Clipboard::readFilePaths):
(WebKit::ReadBufferAsyncData::ReadBufferAsyncData):
(WebKit::Clipboard::readBuffer):
(WebKit::Clipboard::write):
(WebKit::Clipboard::clear):

Location:
trunk/Source/WebKit
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r261554 r261555  
     12020-05-12  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [GTK4] Add support for clipboard operations
     4        https://bugs.webkit.org/show_bug.cgi?id=211561
     5
     6        Reviewed by Adrian Perez de Castro.
     7
     8        * UIProcess/gtk/Clipboard.h:
     9        * UIProcess/gtk/ClipboardGtk4.cpp:
     10        (WebKit::Clipboard::Clipboard):
     11        (WebKit::Clipboard::type const):
     12        (WebKit::Clipboard::formats):
     13        (WebKit::ReadTextAsyncData::ReadTextAsyncData):
     14        (WebKit::Clipboard::readText):
     15        (WebKit::ReadFilePathsAsyncData::ReadFilePathsAsyncData):
     16        (WebKit::Clipboard::readFilePaths):
     17        (WebKit::ReadBufferAsyncData::ReadBufferAsyncData):
     18        (WebKit::Clipboard::readBuffer):
     19        (WebKit::Clipboard::write):
     20        (WebKit::Clipboard::clear):
     21
    1222020-05-12  Carlos Garcia Campos  <cgarcia@igalia.com>
    223
  • trunk/Source/WebKit/UIProcess/gtk/Clipboard.h

    r261554 r261555  
    2929#include <wtf/Forward.h>
    3030
    31 #if !USE(GTK4)
     31#if USE(GTK4)
     32typedef struct _GdkClipboard GdkClipboard;
     33#else
    3234typedef struct _GtkClipboard GtkClipboard;
    3335#endif
     
    5961
    6062private:
    61 #if !USE(GTK4)
     63#if USE(GTK4)
     64    GdkClipboard* m_clipboard { nullptr };
     65#else
    6266    GtkClipboard* m_clipboard { nullptr };
    6367    WebFrameProxy* m_frameWritingToClipboard { nullptr };
  • trunk/Source/WebKit/UIProcess/gtk/ClipboardGtk4.cpp

    r261554 r261555  
    2929#if USE(GTK4)
    3030
     31#include "WebPasteboardProxy.h"
    3132#include <WebCore/SelectionData.h>
    3233#include <WebCore/SharedBuffer.h>
     34#include <gtk/gtk.h>
     35#include <wtf/glib/GRefPtr.h>
    3336
    3437namespace WebKit {
    3538
    36 Clipboard::Clipboard(Type)
     39Clipboard::Clipboard(Type type)
     40    : m_clipboard(type == Type::Clipboard ? gdk_display_get_clipboard(gdk_display_get_default()) : gdk_display_get_primary_clipboard(gdk_display_get_default()))
    3741{
     42    if (type == Type::Primary) {
     43        g_signal_connect(m_clipboard, "notify::local", G_CALLBACK(+[](GdkClipboard* clipboard, GParamSpec*, gpointer) {
     44            if (!gdk_clipboard_is_local(clipboard))
     45                WebPasteboardProxy::singleton().setPrimarySelectionOwner(nullptr);
     46        }), nullptr);
     47    }
    3848}
    3949
    4050Clipboard::Type Clipboard::type() const
    4151{
    42     return Type::Clipboard;
     52    return m_clipboard == gdk_display_get_primary_clipboard(gdk_display_get_default()) ? Type::Primary : Type::Clipboard;
    4353}
    4454
    4555void Clipboard::formats(CompletionHandler<void(Vector<String>&&)>&& completionHandler)
    4656{
    47     completionHandler({ });
     57    gsize mimeTypesCount;
     58    const char* const* mimeTypes = gdk_content_formats_get_mime_types(gdk_clipboard_get_formats(m_clipboard), &mimeTypesCount);
     59
     60    Vector<String> result;
     61    result.reserveInitialCapacity(mimeTypesCount);
     62    for (size_t i = 0; i < mimeTypesCount; ++i)
     63        result.uncheckedAppend(String::fromUTF8(mimeTypes[i]));
     64    completionHandler(WTFMove(result));
    4865}
     66
     67struct ReadTextAsyncData {
     68    WTF_MAKE_STRUCT_FAST_ALLOCATED;
     69
     70    explicit ReadTextAsyncData(CompletionHandler<void(String&&)>&& handler)
     71        : completionHandler(WTFMove(handler))
     72    {
     73    }
     74
     75    CompletionHandler<void(String&&)> completionHandler;
     76};
    4977
    5078void Clipboard::readText(CompletionHandler<void(String&&)>&& completionHandler)
    5179{
    52     completionHandler({ });
     80    gdk_clipboard_read_text_async(m_clipboard, nullptr, [](GObject* clipboard, GAsyncResult* result, gpointer userData) {
     81        std::unique_ptr<ReadTextAsyncData> data(static_cast<ReadTextAsyncData*>(userData));
     82        GUniquePtr<char> text(gdk_clipboard_read_text_finish(GDK_CLIPBOARD(clipboard), result, nullptr));
     83        data->completionHandler(String::fromUTF8(text.get()));
     84    }, new ReadTextAsyncData(WTFMove(completionHandler)));
    5385}
     86
     87struct ReadFilePathsAsyncData {
     88    WTF_MAKE_STRUCT_FAST_ALLOCATED;
     89
     90    explicit ReadFilePathsAsyncData(CompletionHandler<void(Vector<String>&&)>&& handler)
     91        : completionHandler(WTFMove(handler))
     92    {
     93    }
     94
     95    CompletionHandler<void(Vector<String>&&)> completionHandler;
     96};
    5497
    5598void Clipboard::readFilePaths(CompletionHandler<void(Vector<String>&&)>&& completionHandler)
    5699{
    57     completionHandler({ });
     100    gdk_clipboard_read_value_async(m_clipboard, GDK_TYPE_FILE_LIST, G_PRIORITY_DEFAULT, nullptr, [](GObject* clipboard, GAsyncResult* result, gpointer userData) {
     101        std::unique_ptr<ReadFilePathsAsyncData> data(static_cast<ReadFilePathsAsyncData*>(userData));
     102        Vector<String> filePaths;
     103        if (const GValue* value = gdk_clipboard_read_value_finish(GDK_CLIPBOARD(clipboard), result, nullptr)) {
     104            auto* list = static_cast<GSList*>(g_value_get_boxed(value));
     105            for (auto* l = list; l && l->data; l = g_slist_next(l)) {
     106                auto* file = G_FILE(l->data);
     107                if (!g_file_is_native(file))
     108                    continue;
     109
     110                GUniquePtr<gchar> filename(g_file_get_path(file));
     111                if (filename)
     112                    filePaths.append(String::fromUTF8(filename.get()));
     113            }
     114        }
     115        data->completionHandler(WTFMove(filePaths));
     116    }, new ReadFilePathsAsyncData(WTFMove(completionHandler)));
    58117}
     118
     119struct ReadBufferAsyncData {
     120    WTF_MAKE_STRUCT_FAST_ALLOCATED;
     121
     122    explicit ReadBufferAsyncData(CompletionHandler<void(Ref<WebCore::SharedBuffer>&&)>&& handler)
     123        : completionHandler(WTFMove(handler))
     124    {
     125    }
     126
     127    CompletionHandler<void(Ref<WebCore::SharedBuffer>&&)> completionHandler;
     128};
    59129
    60130void Clipboard::readBuffer(const char* format, CompletionHandler<void(Ref<WebCore::SharedBuffer>&&)>&& completionHandler)
    61131{
    62     completionHandler(WebCore::SharedBuffer::create());
     132    const char* mimeTypes[] = { format, nullptr };
     133    gdk_clipboard_read_async(m_clipboard, mimeTypes, G_PRIORITY_DEFAULT, nullptr, [](GObject* clipboard, GAsyncResult* result, gpointer userData) {
     134        std::unique_ptr<ReadBufferAsyncData> data(static_cast<ReadBufferAsyncData*>(userData));
     135        GRefPtr<GInputStream> inputStream = adoptGRef(gdk_clipboard_read_finish(GDK_CLIPBOARD(clipboard), result, nullptr, nullptr));
     136        if (!inputStream) {
     137            data->completionHandler(WebCore::SharedBuffer::create());
     138            return;
     139        }
     140
     141        GRefPtr<GOutputStream> outputStream = adoptGRef(g_memory_output_stream_new_resizable());
     142        g_output_stream_splice_async(outputStream.get(), inputStream.get(),
     143            static_cast<GOutputStreamSpliceFlags>(G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET),
     144            G_PRIORITY_DEFAULT, nullptr, [](GObject* stream, GAsyncResult* result, gpointer userData) {
     145                std::unique_ptr<ReadBufferAsyncData> data(static_cast<ReadBufferAsyncData*>(userData));
     146                gssize writtenBytes = g_output_stream_splice_finish(G_OUTPUT_STREAM(stream), result, nullptr);
     147                if (writtenBytes <= 0) {
     148                    data->completionHandler(WebCore::SharedBuffer::create());
     149                    return;
     150                }
     151
     152                GRefPtr<GBytes> bytes = adoptGRef(g_memory_output_stream_steal_as_bytes(G_MEMORY_OUTPUT_STREAM(stream)));
     153                data->completionHandler(WebCore::SharedBuffer::create(bytes.get()));
     154            }, data.release());
     155    }, new ReadBufferAsyncData(WTFMove(completionHandler)));
    63156}
    64157
    65 void Clipboard::write(const WebCore::SelectionData&)
     158void Clipboard::write(Ref<WebCore::SelectionData>&& selectionData)
    66159{
     160    Vector<GdkContentProvider*> providers;
     161    if (selectionData->hasMarkup()) {
     162        CString markup = selectionData->markup().utf8();
     163        GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new(markup.data(), markup.length()));
     164        providers.append(gdk_content_provider_new_for_bytes("text/html", bytes.get()));
     165    }
     166
     167    if (selectionData->hasImage()) {
     168        GRefPtr<GdkPixbuf> pixbuf = adoptGRef(selectionData->image()->getGdkPixbuf());
     169        providers.append(gdk_content_provider_new_typed(GDK_TYPE_PIXBUF, pixbuf.get()));
     170    }
     171
     172    if (selectionData->hasText())
     173        providers.append(gdk_content_provider_new_typed(G_TYPE_STRING, selectionData->text().utf8().data()));
     174
     175    if (selectionData->canSmartReplace()) {
     176        GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new(nullptr, 0));
     177        providers.append(gdk_content_provider_new_for_bytes("application/vnd.webkitgtk.smartpaste", bytes.get()));
     178    }
     179
     180    if (providers.isEmpty()) {
     181        clear();
     182        return;
     183    }
     184
     185    GRefPtr<GdkContentProvider> provider = adoptGRef(gdk_content_provider_new_union(providers.data(), providers.size()));
     186    gdk_clipboard_set_content(m_clipboard, provider.get());
    67187}
    68188
    69189void Clipboard::clear()
    70190{
     191    gdk_clipboard_set_content(m_clipboard, nullptr);
    71192}
    72193
Note: See TracChangeset for help on using the changeset viewer.