Changeset 261555 in webkit
- Timestamp:
- May 12, 2020 8:22:11 AM (4 years ago)
- Location:
- trunk/Source/WebKit
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r261554 r261555 1 2020-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 1 22 2020-05-12 Carlos Garcia Campos <cgarcia@igalia.com> 2 23 -
trunk/Source/WebKit/UIProcess/gtk/Clipboard.h
r261554 r261555 29 29 #include <wtf/Forward.h> 30 30 31 #if !USE(GTK4) 31 #if USE(GTK4) 32 typedef struct _GdkClipboard GdkClipboard; 33 #else 32 34 typedef struct _GtkClipboard GtkClipboard; 33 35 #endif … … 59 61 60 62 private: 61 #if !USE(GTK4) 63 #if USE(GTK4) 64 GdkClipboard* m_clipboard { nullptr }; 65 #else 62 66 GtkClipboard* m_clipboard { nullptr }; 63 67 WebFrameProxy* m_frameWritingToClipboard { nullptr }; -
trunk/Source/WebKit/UIProcess/gtk/ClipboardGtk4.cpp
r261554 r261555 29 29 #if USE(GTK4) 30 30 31 #include "WebPasteboardProxy.h" 31 32 #include <WebCore/SelectionData.h> 32 33 #include <WebCore/SharedBuffer.h> 34 #include <gtk/gtk.h> 35 #include <wtf/glib/GRefPtr.h> 33 36 34 37 namespace WebKit { 35 38 36 Clipboard::Clipboard(Type) 39 Clipboard::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())) 37 41 { 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 } 38 48 } 39 49 40 50 Clipboard::Type Clipboard::type() const 41 51 { 42 return Type::Clipboard;52 return m_clipboard == gdk_display_get_primary_clipboard(gdk_display_get_default()) ? Type::Primary : Type::Clipboard; 43 53 } 44 54 45 55 void Clipboard::formats(CompletionHandler<void(Vector<String>&&)>&& completionHandler) 46 56 { 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)); 48 65 } 66 67 struct 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 }; 49 77 50 78 void Clipboard::readText(CompletionHandler<void(String&&)>&& completionHandler) 51 79 { 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))); 53 85 } 86 87 struct 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 }; 54 97 55 98 void Clipboard::readFilePaths(CompletionHandler<void(Vector<String>&&)>&& completionHandler) 56 99 { 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))); 58 117 } 118 119 struct 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 }; 59 129 60 130 void Clipboard::readBuffer(const char* format, CompletionHandler<void(Ref<WebCore::SharedBuffer>&&)>&& completionHandler) 61 131 { 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))); 63 156 } 64 157 65 void Clipboard::write( const WebCore::SelectionData&)158 void Clipboard::write(Ref<WebCore::SelectionData>&& selectionData) 66 159 { 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()); 67 187 } 68 188 69 189 void Clipboard::clear() 70 190 { 191 gdk_clipboard_set_content(m_clipboard, nullptr); 71 192 } 72 193
Note: See TracChangeset
for help on using the changeset viewer.