Diff
Modified: trunk/Source/WebCore/ChangeLog (261569 => 261570)
--- trunk/Source/WebCore/ChangeLog 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebCore/ChangeLog 2020-05-12 19:27:48 UTC (rev 261570)
@@ -1,3 +1,22 @@
+2020-05-12 Carlos Garcia Campos <[email protected]>
+
+ [GTK] Rework drag and drop handling in preparation for GTK4
+ https://bugs.webkit.org/show_bug.cgi?id=211723
+
+ Reviewed by Adrian Perez de Castro.
+
+ Remove PasteboardHelper that is no longer used and add conversion functions to GtkUtilities.
+
+ * PlatformGTK.cmake:
+ * SourcesGTK.txt:
+ * platform/gtk/GtkUtilities.cpp:
+ (WebCore::gdkDragActionToDragOperation):
+ (WebCore::dragOperationToGdkDragActions):
+ (WebCore::dragOperationToSingleGdkDragAction):
+ * platform/gtk/GtkUtilities.h:
+ * platform/gtk/PasteboardHelper.cpp: Removed.
+ * platform/gtk/PasteboardHelper.h: Removed.
+
2020-05-12 Jacob Uphoff <[email protected]>
Unreviewed, reverting r261557.
Modified: trunk/Source/WebCore/PlatformGTK.cmake (261569 => 261570)
--- trunk/Source/WebCore/PlatformGTK.cmake 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebCore/PlatformGTK.cmake 2020-05-12 19:27:48 UTC (rev 261570)
@@ -61,7 +61,6 @@
platform/gtk/GUniquePtrGtk.h
platform/gtk/GtkUtilities.h
platform/gtk/GtkVersioning.h
- platform/gtk/PasteboardHelper.h
platform/gtk/ScrollbarThemeGtk.h
platform/gtk/SelectionData.h
Modified: trunk/Source/WebCore/SourcesGTK.txt (261569 => 261570)
--- trunk/Source/WebCore/SourcesGTK.txt 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebCore/SourcesGTK.txt 2020-05-12 19:27:48 UTC (rev 261570)
@@ -107,7 +107,6 @@
platform/gtk/GtkUtilities.cpp
platform/gtk/LocalizedStringsGtk.cpp
platform/gtk/PasteboardGtk.cpp
-platform/gtk/PasteboardHelper.cpp
platform/gtk/PlatformKeyboardEventGtk.cpp
platform/gtk/PlatformScreenGtk.cpp
platform/gtk/PlatformWheelEventGtk.cpp
Modified: trunk/Source/WebCore/platform/gtk/GtkUtilities.cpp (261569 => 261570)
--- trunk/Source/WebCore/platform/gtk/GtkUtilities.cpp 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebCore/platform/gtk/GtkUtilities.cpp 2020-05-12 19:27:48 UTC (rev 261570)
@@ -102,4 +102,51 @@
return 1 << (8 + button - 1);
}
+DragOperation gdkDragActionToDragOperation(GdkDragAction gdkAction)
+{
+ // We have no good way to detect DragOperationEvery other than
+ // to use it when all applicable flags are on.
+ if (gdkAction & GDK_ACTION_COPY
+ && gdkAction & GDK_ACTION_MOVE
+ && gdkAction & GDK_ACTION_LINK)
+ return DragOperationEvery;
+
+ unsigned action = ""
+ if (gdkAction & GDK_ACTION_COPY)
+ action |= DragOperationCopy;
+ if (gdkAction & GDK_ACTION_MOVE)
+ action |= DragOperationMove;
+ if (gdkAction & GDK_ACTION_LINK)
+ action |= DragOperationLink;
+
+ return static_cast<DragOperation>(action);
+}
+
+GdkDragAction dragOperationToGdkDragActions(DragOperation coreAction)
+{
+ unsigned gdkAction = 0;
+ if (coreAction == DragOperationNone)
+ return static_cast<GdkDragAction>(gdkAction);
+
+ if (coreAction & DragOperationCopy)
+ gdkAction |= GDK_ACTION_COPY;
+ if (coreAction & DragOperationMove)
+ gdkAction |= GDK_ACTION_MOVE;
+ if (coreAction & DragOperationLink)
+ gdkAction |= GDK_ACTION_LINK;
+
+ return static_cast<GdkDragAction>(gdkAction);
+}
+
+GdkDragAction dragOperationToSingleGdkDragAction(DragOperation coreAction)
+{
+ if (coreAction == DragOperationEvery || coreAction & DragOperationCopy)
+ return GDK_ACTION_COPY;
+ if (coreAction & DragOperationMove)
+ return GDK_ACTION_MOVE;
+ if (coreAction & DragOperationLink)
+ return GDK_ACTION_LINK;
+ return static_cast<GdkDragAction>(0);
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/gtk/GtkUtilities.h (261569 => 261570)
--- trunk/Source/WebCore/platform/gtk/GtkUtilities.h 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebCore/platform/gtk/GtkUtilities.h 2020-05-12 19:27:48 UTC (rev 261570)
@@ -18,6 +18,7 @@
#pragma once
+#include "DragActions.h"
#include <gtk/gtk.h>
#include <wtf/MonotonicTime.h>
#include <wtf/WallTime.h>
@@ -47,4 +48,8 @@
WEBCORE_EXPORT unsigned stateModifierForGdkButton(unsigned button);
+WEBCORE_EXPORT DragOperation gdkDragActionToDragOperation(GdkDragAction);
+WEBCORE_EXPORT GdkDragAction dragOperationToGdkDragActions(DragOperation);
+WEBCORE_EXPORT GdkDragAction dragOperationToSingleGdkDragAction(DragOperation);
+
} // namespace WebCore
Deleted: trunk/Source/WebCore/platform/gtk/PasteboardHelper.cpp (261569 => 261570)
--- trunk/Source/WebCore/platform/gtk/PasteboardHelper.cpp 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebCore/platform/gtk/PasteboardHelper.cpp 2020-05-12 19:27:48 UTC (rev 261570)
@@ -1,235 +0,0 @@
-/*
- * Copyright (C) 2010 Martin Robinson <[email protected]>
- * Copyright (C) Igalia S.L.
- * Copyright (C) 2013 Collabora Ltd.
- * All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#include "config.h"
-#include "PasteboardHelper.h"
-
-#if !USE(GTK4)
-
-#include "BitmapImage.h"
-#include "SelectionData.h"
-#include <gtk/gtk.h>
-#include <wtf/glib/GUniquePtr.h>
-#include <wtf/text/CString.h>
-
-namespace WebCore {
-
-static GdkAtom textPlainAtom;
-static GdkAtom markupAtom;
-static GdkAtom netscapeURLAtom;
-static GdkAtom uriListAtom;
-static GdkAtom smartPasteAtom;
-static GdkAtom unknownAtom;
-
-static const String& markupPrefix()
-{
- static NeverDestroyed<const String> prefix(MAKE_STATIC_STRING_IMPL("<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">"));
- return prefix.get();
-}
-
-static void removeMarkupPrefix(String& markup)
-{
- // The markup prefix is not harmful, but we remove it from the string anyway, so that
- // we can have consistent results with other ports during the layout tests.
- if (markup.startsWith(markupPrefix()))
- markup.remove(0, markupPrefix().length());
-}
-
-PasteboardHelper& PasteboardHelper::singleton()
-{
- static PasteboardHelper helper;
- return helper;
-}
-
-PasteboardHelper::PasteboardHelper()
- : m_targetList(adoptGRef(gtk_target_list_new(nullptr, 0)))
-{
- textPlainAtom = gdk_atom_intern_static_string("text/plain;charset=utf-8");
- markupAtom = gdk_atom_intern_static_string("text/html");
- netscapeURLAtom = gdk_atom_intern_static_string("_NETSCAPE_URL");
- uriListAtom = gdk_atom_intern_static_string("text/uri-list");
- smartPasteAtom = gdk_atom_intern_static_string("application/vnd.webkitgtk.smartpaste");
- unknownAtom = gdk_atom_intern_static_string("application/vnd.webkitgtk.unknown");
-
- gtk_target_list_add_text_targets(m_targetList.get(), PasteboardHelper::TargetTypeText);
- gtk_target_list_add(m_targetList.get(), markupAtom, 0, PasteboardHelper::TargetTypeMarkup);
- gtk_target_list_add_uri_targets(m_targetList.get(), PasteboardHelper::TargetTypeURIList);
- gtk_target_list_add(m_targetList.get(), netscapeURLAtom, 0, PasteboardHelper::TargetTypeNetscapeURL);
- gtk_target_list_add_image_targets(m_targetList.get(), PasteboardHelper::TargetTypeImage, TRUE);
- gtk_target_list_add(m_targetList.get(), unknownAtom, 0, PasteboardHelper::TargetTypeUnknown);
-}
-
-PasteboardHelper::~PasteboardHelper() = default;
-
-GtkTargetList* PasteboardHelper::targetList() const
-{
- return m_targetList.get();
-}
-
-static String selectionDataToUTF8String(GtkSelectionData* data)
-{
- if (!gtk_selection_data_get_length(data))
- return String();
-
- // g_strndup guards against selection data that is not null-terminated.
- GUniquePtr<gchar> markupString(g_strndup(reinterpret_cast<const char*>(gtk_selection_data_get_data(data)), gtk_selection_data_get_length(data)));
- return String::fromUTF8(markupString.get());
-}
-
-GRefPtr<GtkTargetList> PasteboardHelper::targetListForSelectionData(const SelectionData& selection)
-{
- GRefPtr<GtkTargetList> list = adoptGRef(gtk_target_list_new(nullptr, 0));
-
- if (selection.hasText())
- gtk_target_list_add_text_targets(list.get(), TargetTypeText);
-
- if (selection.hasMarkup())
- gtk_target_list_add(list.get(), markupAtom, 0, TargetTypeMarkup);
-
- if (selection.hasURIList()) {
- gtk_target_list_add_uri_targets(list.get(), TargetTypeURIList);
- gtk_target_list_add(list.get(), netscapeURLAtom, 0, TargetTypeNetscapeURL);
- }
-
- if (selection.hasImage())
- gtk_target_list_add_image_targets(list.get(), TargetTypeImage, TRUE);
-
- if (selection.hasUnknownTypeData())
- gtk_target_list_add(list.get(), unknownAtom, 0, TargetTypeUnknown);
-
- if (selection.canSmartReplace())
- gtk_target_list_add(list.get(), smartPasteAtom, 0, TargetTypeSmartPaste);
-
- return list;
-}
-
-void PasteboardHelper::fillSelectionData(const SelectionData& selection, unsigned info, GtkSelectionData* selectionData)
-{
- if (info == TargetTypeText)
- gtk_selection_data_set_text(selectionData, selection.text().utf8().data(), -1);
-
- else if (info == TargetTypeMarkup) {
- // Some Linux applications refuse to accept pasted markup unless it is
- // prefixed by a content-type meta tag.
- CString markup = makeString(markupPrefix(), selection.markup()).utf8();
- gtk_selection_data_set(selectionData, markupAtom, 8, reinterpret_cast<const guchar*>(markup.data()), markup.length());
-
- } else if (info == TargetTypeURIList) {
- CString uriList = selection.uriList().utf8();
- gtk_selection_data_set(selectionData, uriListAtom, 8, reinterpret_cast<const guchar*>(uriList.data()), uriList.length());
-
- } else if (info == TargetTypeNetscapeURL && selection.hasURL()) {
- String url(selection.url());
- String result(url);
- result.append("\n");
-
- if (selection.hasText())
- result.append(selection.text());
- else
- result.append(url);
-
- GUniquePtr<gchar> resultData(g_strdup(result.utf8().data()));
- gtk_selection_data_set(selectionData, netscapeURLAtom, 8, reinterpret_cast<const guchar*>(resultData.get()), strlen(resultData.get()));
-
- } else if (info == TargetTypeImage && selection.hasImage()) {
- GRefPtr<GdkPixbuf> pixbuf = adoptGRef(selection.image()->getGdkPixbuf());
- gtk_selection_data_set_pixbuf(selectionData, pixbuf.get());
-
- } else if (info == TargetTypeSmartPaste)
- gtk_selection_data_set_text(selectionData, "", -1);
-
- else if (info == TargetTypeUnknown) {
- GVariantBuilder builder;
- g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
-
- for (auto& it : selection.unknownTypes()) {
- GUniquePtr<gchar> dictItem(g_strdup_printf("{'%s', '%s'}", it.key.utf8().data(), it.value.utf8().data()));
- g_variant_builder_add_parsed(&builder, dictItem.get());
- }
-
- GRefPtr<GVariant> variant = g_variant_builder_end(&builder);
- GUniquePtr<gchar> serializedVariant(g_variant_print(variant.get(), TRUE));
- gtk_selection_data_set(selectionData, unknownAtom, 1, reinterpret_cast<const guchar*>(serializedVariant.get()), strlen(serializedVariant.get()));
- }
-}
-
-void PasteboardHelper::fillSelectionData(GtkSelectionData* data, unsigned /* info */, SelectionData& selection)
-{
- if (gtk_selection_data_get_length(data) < 0)
- return;
-
- GdkAtom target = gtk_selection_data_get_target(data);
- if (target == textPlainAtom)
- selection.setText(selectionDataToUTF8String(data));
- else if (target == markupAtom) {
- String markup(selectionDataToUTF8String(data));
- removeMarkupPrefix(markup);
- selection.setMarkup(markup);
- } else if (target == uriListAtom) {
- selection.setURIList(selectionDataToUTF8String(data));
- } else if (target == netscapeURLAtom) {
- String urlWithLabel(selectionDataToUTF8String(data));
- Vector<String> pieces = urlWithLabel.split('\n');
-
- // Give preference to text/uri-list here, as it can hold more
- // than one URI but still take the label if there is one.
- if (!selection.hasURIList() && !pieces.isEmpty())
- selection.setURIList(pieces[0]);
- if (pieces.size() > 1)
- selection.setText(pieces[1]);
- } else if (target == unknownAtom && gtk_selection_data_get_length(data)) {
- GRefPtr<GVariant> variant = g_variant_new_parsed(reinterpret_cast<const char*>(gtk_selection_data_get_data(data)));
-
- GUniqueOutPtr<gchar> key;
- GUniqueOutPtr<gchar> value;
- GVariantIter iter;
-
- g_variant_iter_init(&iter, variant.get());
- while (g_variant_iter_next(&iter, "{ss}", &key.outPtr(), &value.outPtr()))
- selection.setUnknownTypeData(key.get(), value.get());
- }
-}
-
-Vector<GdkAtom> PasteboardHelper::dropAtomsForContext(GtkWidget* widget, GdkDragContext* context)
-{
- // Always search for these common atoms.
- Vector<GdkAtom> dropAtoms;
- dropAtoms.append(textPlainAtom);
- dropAtoms.append(markupAtom);
- dropAtoms.append(uriListAtom);
- dropAtoms.append(netscapeURLAtom);
- dropAtoms.append(unknownAtom);
-
- // For images, try to find the most applicable image type.
- GRefPtr<GtkTargetList> list = adoptGRef(gtk_target_list_new(0, 0));
- gtk_target_list_add_image_targets(list.get(), TargetTypeImage, TRUE);
- GdkAtom atom = gtk_drag_dest_find_target(widget, context, list.get());
- if (atom != GDK_NONE)
- dropAtoms.append(atom);
-
- return dropAtoms;
-}
-
-} // namespace WebCore
-
-#endif // !USE(GTK4)
-
Deleted: trunk/Source/WebCore/platform/gtk/PasteboardHelper.h (261569 => 261570)
--- trunk/Source/WebCore/platform/gtk/PasteboardHelper.h 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebCore/platform/gtk/PasteboardHelper.h 2020-05-12 19:27:48 UTC (rev 261570)
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2007 Luca Bruno <[email protected]>
- * Copyright (C) 2009 Holger Hans Peter Freyther
- * Copyright (C) 2010 Martin Robinson <[email protected]>
- * Copyright (C) 2010 Igalia S.L.
- * All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#pragma once
-
-#if !USE(GTK4)
-
-#include "GRefPtrGtk.h"
-#include <wtf/Function.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-class SelectionData;
-
-class PasteboardHelper {
- WTF_MAKE_NONCOPYABLE(PasteboardHelper);
-public:
- static PasteboardHelper& singleton();
-
- GtkTargetList* targetList() const;
- GRefPtr<GtkTargetList> targetListForSelectionData(const SelectionData&);
- void fillSelectionData(const SelectionData&, unsigned, GtkSelectionData*);
- void fillSelectionData(GtkSelectionData*, unsigned, SelectionData&);
- Vector<GdkAtom> dropAtomsForContext(GtkWidget*, GdkDragContext*);
-
- enum PasteboardTargetType { TargetTypeMarkup, TargetTypeText, TargetTypeImage, TargetTypeURIList, TargetTypeNetscapeURL, TargetTypeSmartPaste, TargetTypeUnknown };
-
-private:
- PasteboardHelper();
- ~PasteboardHelper();
-
- GRefPtr<GtkTargetList> m_targetList;
-};
-
-} // namespace WebCore
-
-#endif // !USE(GTK4)
Modified: trunk/Source/WebKit/ChangeLog (261569 => 261570)
--- trunk/Source/WebKit/ChangeLog 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebKit/ChangeLog 2020-05-12 19:27:48 UTC (rev 261570)
@@ -1,3 +1,51 @@
+2020-05-12 Carlos Garcia Campos <[email protected]>
+
+ [GTK] Rework drag and drop handling in preparation for GTK4
+ https://bugs.webkit.org/show_bug.cgi?id=211723
+
+ Reviewed by Adrian Perez de Castro.
+
+ Split DragAndDropHelper class into DragSource and DropTarget classes. This separates the source and destination
+ parts making it easier to follow. This patch also adds PageClient::didPerformDragControllerAction() to notify
+ back the view when an operation is done to update the result.
+
+ * SourcesGTK.txt:
+ * UIProcess/API/gtk/DragSource.h: Added.
+ * UIProcess/API/gtk/DragSourceGtk3.cpp: Added.
+ (WebKit::DragSource::DragSource):
+ (WebKit::DragSource::~DragSource):
+ (WebKit::DragSource::begin):
+ * UIProcess/API/gtk/DropTarget.h: Added.
+ * UIProcess/API/gtk/DropTargetGtk3.cpp: Added.
+ (WebKit::DropTarget::DropTarget):
+ (WebKit::DropTarget::~DropTarget):
+ (WebKit::DropTarget::accept):
+ (WebKit::DropTarget::enter):
+ (WebKit::DropTarget::update):
+ (WebKit::DropTarget::dataReceived):
+ (WebKit::DropTarget::didPerformAction):
+ (WebKit::DropTarget::leaveTimerFired):
+ (WebKit::DropTarget::leave):
+ (WebKit::DropTarget::drop):
+ * UIProcess/API/gtk/PageClientImpl.cpp:
+ (WebKit::PageClientImpl::startDrag):
+ (WebKit::PageClientImpl::didPerformDragControllerAction):
+ * UIProcess/API/gtk/PageClientImpl.h:
+ * UIProcess/API/gtk/WebKitWebViewBase.cpp:
+ (webkitWebViewBaseConstructed):
+ (webkit_web_view_base_class_init):
+ (webkitWebViewBaseStartDrag):
+ (webkitWebViewBaseDidPerformDragControllerAction):
+ * UIProcess/API/gtk/WebKitWebViewBasePrivate.h:
+ * UIProcess/PageClient.h:
+ (WebKit::PageClient::didPerformDragControllerAction):
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::didPerformDragControllerAction):
+ * UIProcess/gtk/DragAndDropHandler.cpp: Removed.
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::performDragControllerAction):
+ * WebProcess/WebPage/gtk/WebPageGtk.cpp:
+
2020-05-12 Jacob Uphoff <[email protected]>
Unreviewed, reverting r261557.
Modified: trunk/Source/WebKit/SourcesGTK.txt (261569 => 261570)
--- trunk/Source/WebKit/SourcesGTK.txt 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebKit/SourcesGTK.txt 2020-05-12 19:27:48 UTC (rev 261570)
@@ -194,6 +194,10 @@
UIProcess/API/glib/WebKitWebsiteDataManager.cpp @no-unify
UIProcess/API/glib/WebKitWindowProperties.cpp @no-unify
+UIProcess/API/gtk/DragSourceGtk3.cpp @no-unify
+UIProcess/API/gtk/DragSourceGtk4.cpp @no-unify
+UIProcess/API/gtk/DropTargetGtk3.cpp @no-unify
+UIProcess/API/gtk/DropTargetGtk4.cpp @no-unify
UIProcess/API/gtk/InputMethodFilterGtk.cpp @no-unify
UIProcess/API/gtk/PageClientImpl.cpp @no-unify
UIProcess/API/gtk/WebKitAuthenticationDialog.cpp @no-unify
@@ -256,7 +260,6 @@
UIProcess/gtk/Clipboard.cpp
UIProcess/gtk/ClipboardGtk3.cpp @no-unify
UIProcess/gtk/ClipboardGtk4.cpp @no-unify
-UIProcess/gtk/DragAndDropHandler.cpp
UIProcess/gtk/GestureController.cpp
UIProcess/gtk/HardwareAccelerationManager.cpp
UIProcess/gtk/KeyBindingTranslator.cpp
Added: trunk/Source/WebKit/UIProcess/API/gtk/DragSource.h (0 => 261570)
--- trunk/Source/WebKit/UIProcess/API/gtk/DragSource.h (rev 0)
+++ trunk/Source/WebKit/UIProcess/API/gtk/DragSource.h 2020-05-12 19:27:48 UTC (rev 261570)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(DRAG_SUPPORT)
+
+#include <WebCore/DragActions.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/glib/GRefPtr.h>
+
+typedef struct _GtkWidget GtkWidget;
+
+#if !USE(GTK4)
+typedef struct _GdkDragContext GdkDragContext;
+#endif
+
+namespace WebCore {
+class SelectionData;
+}
+
+namespace WebKit {
+
+class ShareableBitmap;
+
+class DragSource {
+ WTF_MAKE_NONCOPYABLE(DragSource); WTF_MAKE_FAST_ALLOCATED;
+public:
+
+ explicit DragSource(GtkWidget*);
+ ~DragSource();
+
+ void begin(Ref<WebCore::SelectionData>&&, WebCore::DragOperation, RefPtr<ShareableBitmap>&&);
+
+private:
+ GtkWidget* m_webView { nullptr };
+#if !USE(GTK4)
+ GRefPtr<GdkDragContext> m_drag;
+#endif
+ RefPtr<WebCore::SelectionData> m_selectionData;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(DRAG_SUPPORT)
Added: trunk/Source/WebKit/UIProcess/API/gtk/DragSourceGtk3.cpp (0 => 261570)
--- trunk/Source/WebKit/UIProcess/API/gtk/DragSourceGtk3.cpp (rev 0)
+++ trunk/Source/WebKit/UIProcess/API/gtk/DragSourceGtk3.cpp 2020-05-12 19:27:48 UTC (rev 261570)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2020 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DragSource.h"
+
+#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
+
+#include "WebKitWebViewBasePrivate.h"
+#include <WebCore/GRefPtrGtk.h>
+#include <WebCore/GtkUtilities.h>
+#include <gtk/gtk.h>
+
+namespace WebKit {
+using namespace WebCore;
+
+enum DragTargetType { Markup, Text, Image, URIList, NetscapeURL, SmartPaste };
+
+DragSource::DragSource(GtkWidget* webView)
+ : m_webView(webView)
+{
+ g_signal_connect(m_webView, "drag-data-get", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, GtkSelectionData* data, guint info, guint, gpointer userData) {
+ auto& drag = *static_cast<DragSource*>(userData);
+ if (drag.m_drag.get() != context)
+ return;
+
+ switch (info) {
+ case DragTargetType::Text:
+ gtk_selection_data_set_text(data, drag.m_selectionData->text().utf8().data(), -1);
+ break;
+ case DragTargetType::Markup: {
+ CString markup = drag.m_selectionData->markup().utf8();
+ gtk_selection_data_set(data, gdk_atom_intern_static_string("text/html"), 8, reinterpret_cast<const guchar*>(markup.data()), markup.length());
+ break;
+ }
+ case DragTargetType::URIList: {
+ CString uriList = drag.m_selectionData->uriList().utf8();
+ gtk_selection_data_set(data, gdk_atom_intern_static_string("text/uri-list"), 8, reinterpret_cast<const guchar*>(uriList.data()), uriList.length());
+ break;
+ }
+ case DragTargetType::NetscapeURL: {
+ CString urlString = drag.m_selectionData->url().string().utf8();
+ GUniquePtr<gchar> url(g_strdup_printf("%s\n%s", urlString.data(), drag.m_selectionData->hasText() ? drag.m_selectionData->text().utf8().data() : urlString.data()));
+ gtk_selection_data_set(data, gdk_atom_intern_static_string("_NETSCAPE_URL"), 8, reinterpret_cast<const guchar*>(url.get()), strlen(url.get()));
+ break;
+ }
+ case DragTargetType::Image: {
+ GRefPtr<GdkPixbuf> pixbuf = adoptGRef(drag.m_selectionData->image()->getGdkPixbuf());
+ gtk_selection_data_set_pixbuf(data, pixbuf.get());
+ break;
+ }
+ case DragTargetType::SmartPaste:
+ gtk_selection_data_set_text(data, "", -1);
+ break;
+ }
+ }), this);
+
+ g_signal_connect(m_webView, "drag-end", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, gpointer userData) {
+ auto& drag = *static_cast<DragSource*>(userData);
+ if (drag.m_drag.get() != context)
+ return;
+ if (!drag.m_selectionData)
+ return;
+
+ drag.m_selectionData = nullptr;
+ drag.m_drag = nullptr;
+
+ GdkDevice* device = gdk_drag_context_get_device(context);
+ int x = 0;
+ int y = 0;
+ gdk_device_get_window_at_position(device, &x, &y);
+ int xRoot = 0;
+ int yRoot = 0;
+ gdk_device_get_position(device, nullptr, &xRoot, &yRoot);
+
+ auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(drag.m_webView));
+ ASSERT(page);
+ page->dragEnded({ x, y }, { xRoot, yRoot }, gdkDragActionToDragOperation(gdk_drag_context_get_selected_action(context)));
+ }), this);
+}
+
+DragSource::~DragSource()
+{
+ g_signal_handlers_disconnect_by_data(m_webView, this);
+}
+
+void DragSource::begin(Ref<SelectionData>&& selectionData, DragOperation operation, RefPtr<ShareableBitmap>&& image)
+{
+ if (m_drag) {
+ gtk_drag_cancel(m_drag.get());
+ m_drag = nullptr;
+ }
+
+ m_selectionData = WTFMove(selectionData);
+
+ GRefPtr<GtkTargetList> list = adoptGRef(gtk_target_list_new(nullptr, 0));
+ if (m_selectionData->hasText())
+ gtk_target_list_add_text_targets(list.get(), DragTargetType::Text);
+ if (m_selectionData->hasMarkup())
+ gtk_target_list_add(list.get(), gdk_atom_intern_static_string("text/html"), 0, DragTargetType::Markup);
+ if (m_selectionData->hasURIList())
+ gtk_target_list_add_uri_targets(list.get(), DragTargetType::URIList);
+ if (m_selectionData->hasURL())
+ gtk_target_list_add(list.get(), gdk_atom_intern_static_string("_NETSCAPE_URL"), 0, DragTargetType::NetscapeURL);
+ if (m_selectionData->hasImage())
+ gtk_target_list_add_image_targets(list.get(), DragTargetType::Image, TRUE);
+ if (m_selectionData->canSmartReplace())
+ gtk_target_list_add(list.get(), gdk_atom_intern_static_string("application/vnd.webkitgtk.smartpaste"), 0, DragTargetType::SmartPaste);
+
+ m_drag = gtk_drag_begin_with_coordinates(m_webView, list.get(), dragOperationToGdkDragActions(operation), GDK_BUTTON_PRIMARY, nullptr, -1, -1);
+ if (image) {
+ RefPtr<cairo_surface_t> imageSurface(image->createCairoSurface());
+ // Use the center of the drag image as hotspot.
+ cairo_surface_set_device_offset(imageSurface.get(), -cairo_image_surface_get_width(imageSurface.get()) / 2, -cairo_image_surface_get_height(imageSurface.get()) / 2);
+ gtk_drag_set_icon_surface(m_drag.get(), imageSurface.get());
+ } else
+ gtk_drag_set_icon_default(m_drag.get());
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(DRAG_SUPPORT) && !USE(GTK4)
Added: trunk/Source/WebKit/UIProcess/API/gtk/DragSourceGtk4.cpp (0 => 261570)
--- trunk/Source/WebKit/UIProcess/API/gtk/DragSourceGtk4.cpp (rev 0)
+++ trunk/Source/WebKit/UIProcess/API/gtk/DragSourceGtk4.cpp 2020-05-12 19:27:48 UTC (rev 261570)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DragSource.h"
+
+#if ENABLE(DRAG_SUPPORT) && USE(GTK4)
+
+#include "WebKitWebViewBasePrivate.h"
+#include <WebCore/GtkUtilities.h>
+#include <gtk/gtk.h>
+
+namespace WebKit {
+using namespace WebCore;
+
+DragSource::DragSource(GtkWidget* webView)
+ : m_webView(webView)
+{
+}
+
+DragSource::~DragSource()
+{
+}
+
+void DragSource::begin(Ref<SelectionData>&&, DragOperation, RefPtr<ShareableBitmap>&&)
+{
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(DRAG_SUPPORT) && USE(GTK4)
Added: trunk/Source/WebKit/UIProcess/API/gtk/DropTarget.h (0 => 261570)
--- trunk/Source/WebKit/UIProcess/API/gtk/DropTarget.h (rev 0)
+++ trunk/Source/WebKit/UIProcess/API/gtk/DropTarget.h 2020-05-12 19:27:48 UTC (rev 261570)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(DRAG_SUPPORT)
+
+#include <WebCore/DragActions.h>
+#include <WebCore/IntPoint.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/RunLoop.h>
+#include <wtf/glib/GRefPtr.h>
+
+typedef struct _GtkWidget GtkWidget;
+
+#if !USE(GTK4)
+typedef struct _GdkDragContext GdkDragContext;
+typedef struct _GtkSelectionData GtkSelectionData;
+#endif
+
+namespace WebCore {
+class SelectionData;
+}
+
+namespace WebKit {
+
+class ShareableBitmap;
+
+class DropTarget {
+ WTF_MAKE_NONCOPYABLE(DropTarget); WTF_MAKE_FAST_ALLOCATED;
+public:
+ explicit DropTarget(GtkWidget*);
+ ~DropTarget();
+
+ void didPerformAction();
+
+private:
+ void accept(unsigned = 0);
+ void enter(WebCore::IntPoint&&, unsigned = 0);
+ void update(WebCore::IntPoint&&, unsigned = 0);
+ void leave();
+ void drop(WebCore::IntPoint&&, unsigned = 0);
+
+#if !USE(GTK4)
+ void dataReceived(WebCore::IntPoint&&, GtkSelectionData*, unsigned, unsigned);
+ void leaveTimerFired();
+#endif
+
+ GtkWidget* m_webView { nullptr };
+#if !USE(GTK4)
+ GRefPtr<GdkDragContext> m_drop;
+#endif
+ Optional<WebCore::IntPoint> m_position;
+ unsigned m_dataRequestCount { 0 };
+ RefPtr<WebCore::SelectionData> m_selectionData;
+ WebCore::DragOperation m_operation { WebCore::DragOperationNone };
+#if !USE(GTK4)
+ RunLoop::Timer<DropTarget> m_leaveTimer;
+#endif
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(DRAG_SUPPORT)
Added: trunk/Source/WebKit/UIProcess/API/gtk/DropTargetGtk3.cpp (0 => 261570)
--- trunk/Source/WebKit/UIProcess/API/gtk/DropTargetGtk3.cpp (rev 0)
+++ trunk/Source/WebKit/UIProcess/API/gtk/DropTargetGtk3.cpp 2020-05-12 19:27:48 UTC (rev 261570)
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2020 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DropTarget.h"
+
+#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
+
+#include "WebKitWebViewBasePrivate.h"
+#include <WebCore/DragData.h>
+#include <WebCore/GRefPtrGtk.h>
+#include <WebCore/GtkUtilities.h>
+#include <gtk/gtk.h>
+#include <wtf/glib/GUniquePtr.h>
+
+namespace WebKit {
+using namespace WebCore;
+
+enum DropTargetType { Markup, Text, URIList, NetscapeURL, SmartPaste };
+
+DropTarget::DropTarget(GtkWidget* webView)
+ : m_webView(webView)
+ , m_leaveTimer(RunLoop::main(), this, &DropTarget::leaveTimerFired)
+{
+ GRefPtr<GtkTargetList> list = adoptGRef(gtk_target_list_new(nullptr, 0));
+ gtk_target_list_add_text_targets(list.get(), DropTargetType::Text);
+ gtk_target_list_add(list.get(), gdk_atom_intern_static_string("text/html"), 0, DropTargetType::Markup);
+ gtk_target_list_add_uri_targets(list.get(), DropTargetType::URIList);
+ gtk_target_list_add(list.get(), gdk_atom_intern_static_string("_NETSCAPE_URL"), 0, DropTargetType::NetscapeURL);
+ gtk_target_list_add(list.get(), gdk_atom_intern_static_string("application/vnd.webkitgtk.smartpaste"), 0, DropTargetType::SmartPaste);
+ gtk_drag_dest_set(m_webView, static_cast<GtkDestDefaults>(0), nullptr, 0,
+ static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK));
+ gtk_drag_dest_set_target_list(m_webView, list.get());
+
+ g_signal_connect(m_webView, "drag-motion", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, gint x, gint y, guint time, gpointer userData) -> gboolean {
+ auto& drop = *static_cast<DropTarget*>(userData);
+ if (!drop.m_drop) {
+ drop.m_drop = context;
+ drop.m_position = IntPoint(x, y);
+ drop.accept(time);
+ } else if (drop.m_drop == context)
+ drop.update({ x, y }, time);
+ return TRUE;
+ }), this);
+
+ g_signal_connect(m_webView, "drag-leave", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, guint time, gpointer userData) {
+ auto& drop = *static_cast<DropTarget*>(userData);
+ if (drop.m_drop != context)
+ return;
+ drop.leave();
+ }), this);
+
+ g_signal_connect(m_webView, "drag-drop", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, gint x, gint y, guint time, gpointer userData) -> gboolean {
+ auto& drop = *static_cast<DropTarget*>(userData);
+ if (drop.m_drop != context) {
+ gtk_drag_finish(context, FALSE, FALSE, time);
+ return TRUE;
+ }
+ drop.drop({ x, y }, time);
+ return TRUE;
+ }), this);
+
+ g_signal_connect(m_webView, "drag-data-received", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, gint x, gint y, GtkSelectionData* data, guint info, guint time, gpointer userData) {
+ auto& drop = *static_cast<DropTarget*>(userData);
+ if (drop.m_drop != context)
+ return;
+ drop.dataReceived({ x, y }, data, info, time);
+ }), this);
+}
+
+DropTarget::~DropTarget()
+{
+ g_signal_handlers_disconnect_by_data(m_webView, this);
+}
+
+void DropTarget::accept(unsigned time)
+{
+ if (m_leaveTimer.isActive()) {
+ m_leaveTimer.stop();
+ leaveTimerFired();
+ }
+
+ m_dataRequestCount = 0;
+ m_selectionData = SelectionData::create();
+
+ // WebCore needs the selection data to decide, so we need to preload the
+ // data of targets we support. Once all data requests are done we start
+ // notifying the web process about the DND events.
+ auto* list = gdk_drag_context_list_targets(m_drop.get());
+ static const char* const supportedTargets[] = {
+ "text/plain;charset=utf-8",
+ "text/html",
+ "_NETSCAPE_URL",
+ "text/uri-list",
+ "application/vnd.webkitgtk.smartpaste"
+ };
+ Vector<GdkAtom, 4> targets;
+ for (unsigned i = 0; i < G_N_ELEMENTS(supportedTargets); ++i) {
+ GdkAtom atom = gdk_atom_intern_static_string(supportedTargets[i]);
+ if (g_list_find(list, atom))
+ targets.append(atom);
+ else if (!i) {
+ atom = gdk_atom_intern_static_string("text/plain");
+ if (g_list_find(list, atom))
+ targets.append(atom);
+ }
+ }
+
+ m_dataRequestCount = targets.size();
+ for (auto* atom : targets)
+ gtk_drag_get_data(m_webView, m_drop.get(), atom, time);
+}
+
+void DropTarget::enter(IntPoint&& position, unsigned time)
+{
+ m_position = WTFMove(position);
+
+ auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_webView));
+ ASSERT(page);
+ page->resetCurrentDragInformation();
+
+ DragData dragData(m_selectionData.get(), *m_position, convertWidgetPointToScreenPoint(m_webView, *m_position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(m_drop.get())));
+ page->dragEntered(dragData);
+}
+
+void DropTarget::update(IntPoint&& position, unsigned time)
+{
+ if (m_dataRequestCount || !m_selectionData)
+ return;
+
+ m_position = WTFMove(position);
+
+ auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_webView));
+ ASSERT(page);
+
+ DragData dragData(m_selectionData.get(), *m_position, convertWidgetPointToScreenPoint(m_webView, *m_position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(m_drop.get())));
+ page->dragUpdated(dragData);
+}
+
+void DropTarget::dataReceived(IntPoint&& position, GtkSelectionData* data, unsigned info, unsigned time)
+{
+ switch (info) {
+ case DropTargetType::Text: {
+ GUniquePtr<char> text(reinterpret_cast<char*>(gtk_selection_data_get_text(data)));
+ m_selectionData->setText(String::fromUTF8(text.get()));
+ break;
+ }
+ case DropTargetType::Markup: {
+ gint length;
+ const auto* markupData = gtk_selection_data_get_data_with_length(data, &length);
+ if (length) {
+ // If data starts with UTF-16 BOM assume it's UTF-16, otherwise assume UTF-8.
+ if (length >= 2 && reinterpret_cast<const UChar*>(markupData)[0] == 0xFEFF)
+ m_selectionData->setMarkup(String(reinterpret_cast<const UChar*>(markupData) + 1, (length / 2) - 1));
+ else
+ m_selectionData->setMarkup(String::fromUTF8(markupData, length));
+ }
+ break;
+ }
+ case DropTargetType::URIList: {
+ gint length;
+ const auto* uriListData = gtk_selection_data_get_data_with_length(data, &length);
+ if (length)
+ m_selectionData->setURIList(String::fromUTF8(uriListData, length));
+ break;
+ }
+ case DropTargetType::NetscapeURL: {
+ gint length;
+ const auto* urlData = gtk_selection_data_get_data_with_length(data, &length);
+ if (length) {
+ Vector<String> tokens = String::fromUTF8(urlData, length).split('\n');
+ URL url({ }, tokens[0]);
+ if (url.isValid())
+ m_selectionData->setURL(url, tokens.size() > 1 ? tokens[1] : String());
+ }
+ break;
+ }
+ case DropTargetType::SmartPaste:
+ m_selectionData->setCanSmartReplace(true);
+ break;
+ }
+
+ if (--m_dataRequestCount)
+ return;
+
+ enter(WTFMove(position), time);
+}
+
+void DropTarget::didPerformAction()
+{
+ if (!m_drop)
+ return;
+
+ auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_webView));
+ ASSERT(page);
+
+ auto operation = page->currentDragOperation();
+ if (operation == m_operation)
+ return;
+
+ m_operation = operation;
+ gdk_drag_status(m_drop.get(), dragOperationToSingleGdkDragAction(m_operation), GDK_CURRENT_TIME);
+}
+
+void DropTarget::leaveTimerFired()
+{
+ auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_webView));
+ ASSERT(page);
+
+ DragData dragData(m_selectionData.get(), *m_position, convertWidgetPointToScreenPoint(m_webView, *m_position), DragOperationNone);
+ page->dragExited(dragData);
+ page->resetCurrentDragInformation();
+
+ m_drop = nullptr;
+ m_position = WTF::nullopt;
+ m_selectionData = nullptr;
+}
+
+void DropTarget::leave()
+{
+ // GTK emits drag-leave before drag-drop, but we need to know whether a drop
+ // happened to notify the web process about the drag exit.
+ m_leaveTimer.startOneShot(0_s);
+}
+
+void DropTarget::drop(IntPoint&& position, unsigned time)
+{
+ if (m_leaveTimer.isActive())
+ m_leaveTimer.stop();
+
+ auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_webView));
+ ASSERT(page);
+
+ uint32_t flags = 0;
+ if (gdk_drag_context_get_selected_action(m_drop.get()) == GDK_ACTION_COPY)
+ flags |= DragApplicationIsCopyKeyDown;
+ DragData dragData(m_selectionData.get(), position, convertWidgetPointToScreenPoint(m_webView, position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(m_drop.get())), static_cast<DragApplicationFlags>(flags));
+ page->performDragOperation(dragData, { }, { }, { });
+ gtk_drag_finish(m_drop.get(), TRUE, FALSE, time);
+
+ m_drop = nullptr;
+ m_position = WTF::nullopt;
+ m_selectionData = nullptr;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(DRAG_SUPPORT) && !USE(GTK4)
Added: trunk/Source/WebKit/UIProcess/API/gtk/DropTargetGtk4.cpp (0 => 261570)
--- trunk/Source/WebKit/UIProcess/API/gtk/DropTargetGtk4.cpp (rev 0)
+++ trunk/Source/WebKit/UIProcess/API/gtk/DropTargetGtk4.cpp 2020-05-12 19:27:48 UTC (rev 261570)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DropTarget.h"
+
+#if ENABLE(DRAG_SUPPORT) && USE(GTK4)
+
+#include "WebKitWebViewBasePrivate.h"
+#include <WebCore/DragData.h>
+#include <WebCore/GtkUtilities.h>
+#include <gtk/gtk.h>
+#include <wtf/glib/GUniquePtr.h>
+
+namespace WebKit {
+using namespace WebCore;
+
+DropTarget::DropTarget(GtkWidget* webView)
+ : m_webView(webView)
+{
+}
+
+DropTarget::~DropTarget()
+{
+}
+
+void DropTarget::accept(unsigned)
+{
+}
+
+void DropTarget::loadData(const char*, CompletionHandler<void(GRefPtr<GBytes>&&)>&&)
+{
+}
+
+void DropTarget::didLoadData()
+{
+}
+
+void DropTarget::enter(IntPoint&&, unsigned)
+{
+}
+
+void DropTarget::update(IntPoint&&, unsigned)
+{
+}
+
+void DropTarget::didPerformAction()
+{
+}
+
+void DropTarget::leave()
+{
+}
+
+void DropTarget::drop(IntPoint&&, unsigned)
+{
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(DRAG_SUPPORT) && USE(GTK4)
Modified: trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp (261569 => 261570)
--- trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp 2020-05-12 19:27:48 UTC (rev 261570)
@@ -330,14 +330,12 @@
#if ENABLE(DRAG_SUPPORT)
void PageClientImpl::startDrag(Ref<SelectionData>&& selection, DragOperation dragOperation, RefPtr<ShareableBitmap>&& dragImage)
{
-#if !USE(GTK4)
- WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(m_viewWidget);
- webkitWebViewBaseDragAndDropHandler(webView).startDrag(WTFMove(selection), dragOperation, WTFMove(dragImage));
+ webkitWebViewBaseStartDrag(WEBKIT_WEB_VIEW_BASE(m_viewWidget), WTFMove(selection), dragOperation, WTFMove(dragImage));
+}
- // A drag starting should prevent a double-click from happening. This might
- // happen if a drag is followed very quickly by another click (like in the WTR).
- webkitWebViewBaseResetClickCounter(webView);
-#endif
+void PageClientImpl::didPerformDragControllerAction()
+{
+ webkitWebViewBaseDidPerformDragControllerAction(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
}
#endif
Modified: trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h (261569 => 261570)
--- trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h 2020-05-12 19:27:48 UTC (rev 261570)
@@ -101,6 +101,7 @@
RefPtr<ViewSnapshot> takeViewSnapshot(Optional<WebCore::IntRect>&&) override;
#if ENABLE(DRAG_SUPPORT)
void startDrag(Ref<WebCore::SelectionData>&&, WebCore::DragOperation, RefPtr<ShareableBitmap>&& dragImage) override;
+ void didPerformDragControllerAction() override;
#endif
void enterAcceleratedCompositingMode(const LayerTreeContext&) override;
Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp (261569 => 261570)
--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp 2020-05-12 19:27:48 UTC (rev 261570)
@@ -31,7 +31,9 @@
#include "APIPageConfiguration.h"
#include "AcceleratedBackingStore.h"
+#include "DragSource.h"
#include "DrawingAreaProxyCoordinatedGraphics.h"
+#include "DropTarget.h"
#include "InputMethodFilter.h"
#include "KeyBindingTranslator.h"
#include "NativeWebKeyboardEvent.h"
@@ -58,7 +60,6 @@
#include <WebCore/GtkUtilities.h>
#include <WebCore/GtkVersioning.h>
#include <WebCore/NotImplemented.h>
-#include <WebCore/PasteboardHelper.h>
#include <WebCore/PlatformDisplay.h>
#include <WebCore/RefPtrCairo.h>
#include <WebCore/Region.h>
@@ -219,8 +220,9 @@
std::unique_ptr<AcceleratedBackingStore> acceleratedBackingStore;
-#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
- std::unique_ptr<DragAndDropHandler> dragAndDropHandler;
+#if ENABLE(DRAG_SUPPORT)
+ std::unique_ptr<DragSource> dragSource;
+ std::unique_ptr<DropTarget> dropTarget;
#endif
#if !USE(GTK4)
@@ -1554,27 +1556,6 @@
return TRUE;
}
-#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
-static void webkitWebViewBaseDragDataGet(GtkWidget* widget, GdkDragContext* context, GtkSelectionData* selectionData, guint info, guint /* time */)
-{
- WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
- ASSERT(priv->dragAndDropHandler);
- priv->dragAndDropHandler->fillDragData(context, selectionData, info);
-}
-
-static void webkitWebViewBaseDragEnd(GtkWidget* widget, GdkDragContext* context)
-{
- WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
- ASSERT(priv->dragAndDropHandler);
- priv->dragAndDropHandler->finishDrag(context);
-}
-
-static void webkitWebViewBaseDragDataReceived(GtkWidget* widget, GdkDragContext* context, gint /* x */, gint /* y */, GtkSelectionData* selectionData, guint info, guint time)
-{
- webkitWebViewBaseDragAndDropHandler(WEBKIT_WEB_VIEW_BASE(widget)).dragEntered(context, selectionData, info, time);
-}
-#endif // ENABLE(DRAG_SUPPORT)
-
#if !USE(GTK4)
static gboolean webkitWebViewBaseEvent(GtkWidget* widget, GdkEvent* event)
{
@@ -1601,28 +1582,6 @@
return priv->accessible.get();
}
-#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
-static gboolean webkitWebViewBaseDragMotion(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
-{
- webkitWebViewBaseDragAndDropHandler(WEBKIT_WEB_VIEW_BASE(widget)).dragMotion(context, IntPoint(x, y), time);
- return TRUE;
-}
-
-static void webkitWebViewBaseDragLeave(GtkWidget* widget, GdkDragContext* context, guint /* time */)
-{
- WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
- ASSERT(priv->dragAndDropHandler);
- priv->dragAndDropHandler->dragLeave(context);
-}
-
-static gboolean webkitWebViewBaseDragDrop(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
-{
- WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
- ASSERT(priv->dragAndDropHandler);
- return priv->dragAndDropHandler->drop(context, IntPoint(x, y), time);
-}
-#endif // ENABLE(DRAG_SUPPORT)
-
#if !USE(GTK4)
static void webkitWebViewBaseHierarchyChanged(GtkWidget* widget, GtkWidget* oldToplevel)
{
@@ -1673,10 +1632,8 @@
priv->pageClient = makeUnique<PageClientImpl>(viewWidget);
gtk_container_add(GTK_CONTAINER(viewWidget), priv->keyBindingTranslator.widget());
-#if !USE(GTK4)
- gtk_drag_dest_set(viewWidget, static_cast<GtkDestDefaults>(0), nullptr, 0,
- static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
- gtk_drag_dest_set_target_list(viewWidget, PasteboardHelper::singleton().targetList());
+#if ENABLE(DRAG_SUPPORT)
+ priv->dropTarget = makeUnique<DropTarget>(viewWidget);
#endif
#if USE(GTK4)
@@ -1747,14 +1704,6 @@
widgetClass->touch_event = webkitWebViewBaseTouchEvent;
#endif
widgetClass->query_tooltip = webkitWebViewBaseQueryTooltip;
-#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
- widgetClass->drag_end = webkitWebViewBaseDragEnd;
- widgetClass->drag_data_get = webkitWebViewBaseDragDataGet;
- widgetClass->drag_motion = webkitWebViewBaseDragMotion;
- widgetClass->drag_leave = webkitWebViewBaseDragLeave;
- widgetClass->drag_drop = webkitWebViewBaseDragDrop;
- widgetClass->drag_data_received = webkitWebViewBaseDragDataReceived;
-#endif // ENABLE(DRAG_SUPPORT)
#if !USE(GTK4)
widgetClass->event = webkitWebViewBaseEvent;
#endif
@@ -1829,14 +1778,26 @@
webViewBase->priv->tooltipArea = tooltipArea;
}
-#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
-DragAndDropHandler& webkitWebViewBaseDragAndDropHandler(WebKitWebViewBase* webViewBase)
+#if ENABLE(DRAG_SUPPORT)
+void webkitWebViewBaseStartDrag(WebKitWebViewBase* webViewBase, Ref<SelectionData>&& selectionData, DragOperation dragOperation, RefPtr<ShareableBitmap>&& image)
{
WebKitWebViewBasePrivate* priv = webViewBase->priv;
- if (!priv->dragAndDropHandler)
- priv->dragAndDropHandler = makeUnique<DragAndDropHandler>(*priv->pageProxy);
- return *priv->dragAndDropHandler;
+ if (!priv->dragSource)
+ priv->dragSource = makeUnique<DragSource>(GTK_WIDGET(webViewBase));
+
+ priv->dragSource->begin(WTFMove(selectionData), dragOperation, WTFMove(image));
+
+#if !USE(GTK4)
+ // A drag starting should prevent a double-click from happening. This might
+ // happen if a drag is followed very quickly by another click (like in the WTR).
+ priv->clickCounter.reset();
+#endif
}
+
+void webkitWebViewBaseDidPerformDragControllerAction(WebKitWebViewBase* webViewBase)
+{
+ webViewBase->priv->dropTarget->didPerformAction();
+}
#endif // ENABLE(DRAG_SUPPORT)
void webkitWebViewBaseForwardNextKeyEvent(WebKitWebViewBase* webkitWebViewBase)
Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h (261569 => 261570)
--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h 2020-05-12 19:27:48 UTC (rev 261570)
@@ -32,6 +32,7 @@
#include "GestureController.h"
#include "InputMethodState.h"
#include "SameDocumentNavigationType.h"
+#include "ShareableBitmap.h"
#include "ViewGestureController.h"
#include "ViewSnapshotStore.h"
#include "WebContextMenuProxyGtk.h"
@@ -39,6 +40,8 @@
#include "WebKitInputMethodContext.h"
#include "WebKitWebViewBase.h"
#include "WebPageProxy.h"
+#include <WebCore/DragActions.h>
+#include <WebCore/SelectionData.h>
#include <wtf/Optional.h>
WebKitWebViewBase* webkitWebViewBaseCreate(const API::PageConfiguration&);
@@ -78,8 +81,9 @@
void webkitWebViewBaseDidRelaunchWebProcess(WebKitWebViewBase*);
void webkitWebViewBasePageClosed(WebKitWebViewBase*);
-#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
-WebKit::DragAndDropHandler& webkitWebViewBaseDragAndDropHandler(WebKitWebViewBase*);
+#if ENABLE(DRAG_SUPPORT)
+void webkitWebViewBaseStartDrag(WebKitWebViewBase*, Ref<WebCore::SelectionData>&&, WebCore::DragOperation, RefPtr<WebKit::ShareableBitmap>&&);
+void webkitWebViewBaseDidPerformDragControllerAction(WebKitWebViewBase*);
#endif
#if !USE(GTK4)
Modified: trunk/Source/WebKit/UIProcess/PageClient.h (261569 => 261570)
--- trunk/Source/WebKit/UIProcess/PageClient.h 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebKit/UIProcess/PageClient.h 2020-05-12 19:27:48 UTC (rev 261570)
@@ -250,6 +250,7 @@
virtual void startDrag(const WebCore::DragItem&, const ShareableBitmap::Handle&) { }
#endif
virtual void didPerformDragOperation(bool) { }
+ virtual void didPerformDragControllerAction() { }
#endif // ENABLE(DRAG_SUPPORT)
virtual void setCursor(const WebCore::Cursor&) = 0;
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (261569 => 261570)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2020-05-12 19:27:48 UTC (rev 261570)
@@ -2424,6 +2424,7 @@
m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
m_currentDragCaretEditableElementRect = editableElementRect;
setDragCaretRect(insertionRect);
+ pageClient().didPerformDragControllerAction();
}
#if PLATFORM(GTK)
Deleted: trunk/Source/WebKit/UIProcess/gtk/DragAndDropHandler.cpp (261569 => 261570)
--- trunk/Source/WebKit/UIProcess/gtk/DragAndDropHandler.cpp 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebKit/UIProcess/gtk/DragAndDropHandler.cpp 2020-05-12 19:27:48 UTC (rev 261570)
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2014 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "DragAndDropHandler.h"
-
-#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
-
-#include "WebPageProxy.h"
-#include <WebCore/DragData.h>
-#include <WebCore/GRefPtrGtk.h>
-#include <WebCore/GUniquePtrGtk.h>
-#include <WebCore/GtkUtilities.h>
-#include <WebCore/PasteboardHelper.h>
-#include <wtf/RunLoop.h>
-
-namespace WebKit {
-using namespace WebCore;
-
-DragAndDropHandler::DragAndDropHandler(WebPageProxy& page)
- : m_page(page)
-{
-}
-
-DragAndDropHandler::DroppingContext::DroppingContext(GdkDragContext* gdkContext, const IntPoint& position)
- : gdkContext(gdkContext)
- , lastMotionPosition(position)
- , selectionData(SelectionData::create())
-{
-}
-
-static inline GdkDragAction dragOperationToGdkDragActions(DragOperation coreAction)
-{
- GdkDragAction gdkAction = static_cast<GdkDragAction>(0);
- if (coreAction == DragOperationNone)
- return gdkAction;
-
- if (coreAction & DragOperationCopy)
- gdkAction = static_cast<GdkDragAction>(GDK_ACTION_COPY | gdkAction);
- if (coreAction & DragOperationMove)
- gdkAction = static_cast<GdkDragAction>(GDK_ACTION_MOVE | gdkAction);
- if (coreAction & DragOperationLink)
- gdkAction = static_cast<GdkDragAction>(GDK_ACTION_LINK | gdkAction);
- if (coreAction & DragOperationPrivate)
- gdkAction = static_cast<GdkDragAction>(GDK_ACTION_PRIVATE | gdkAction);
-
- return gdkAction;
-}
-
-static inline GdkDragAction dragOperationToSingleGdkDragAction(DragOperation coreAction)
-{
- if (coreAction == DragOperationEvery || coreAction & DragOperationCopy)
- return GDK_ACTION_COPY;
- if (coreAction & DragOperationMove)
- return GDK_ACTION_MOVE;
- if (coreAction & DragOperationLink)
- return GDK_ACTION_LINK;
- if (coreAction & DragOperationPrivate)
- return GDK_ACTION_PRIVATE;
- return static_cast<GdkDragAction>(0);
-}
-
-static inline DragOperation gdkDragActionToDragOperation(GdkDragAction gdkAction)
-{
- // We have no good way to detect DragOperationEvery other than
- // to use it when all applicable flags are on.
- if (gdkAction & GDK_ACTION_COPY
- && gdkAction & GDK_ACTION_MOVE
- && gdkAction & GDK_ACTION_LINK
- && gdkAction & GDK_ACTION_PRIVATE)
- return DragOperationEvery;
-
- unsigned action = ""
- if (gdkAction & GDK_ACTION_COPY)
- action |= DragOperationCopy;
- if (gdkAction & GDK_ACTION_MOVE)
- action |= DragOperationMove;
- if (gdkAction & GDK_ACTION_LINK)
- action |= DragOperationLink;
- if (gdkAction & GDK_ACTION_PRIVATE)
- action |= DragOperationPrivate;
- return static_cast<DragOperation>(action);
-}
-
-void DragAndDropHandler::startDrag(Ref<SelectionData>&& selection, DragOperation dragOperation, RefPtr<ShareableBitmap>&& dragImage)
-{
- // WebCore::EventHandler does not support more than one DnD operation at the same time for
- // a given page, so we should cancel any previous operation whose context we might have
- // stored, should we receive a new startDrag event before finishing a previous DnD operation.
- if (m_dragContext) {
- gtk_drag_cancel(m_dragContext.get());
- m_dragContext = nullptr;
- }
-
- m_draggingSelectionData = WTFMove(selection);
- GRefPtr<GtkTargetList> targetList = PasteboardHelper::singleton().targetListForSelectionData(*m_draggingSelectionData);
-
- GUniquePtr<GdkEvent> currentEvent(gtk_get_current_event());
- GdkDragContext* context = gtk_drag_begin_with_coordinates(m_page.viewWidget(), targetList.get(), dragOperationToGdkDragActions(dragOperation),
- GDK_BUTTON_PRIMARY, currentEvent.get(), -1, -1);
-
- m_dragContext = context;
-
- if (dragImage) {
- RefPtr<cairo_surface_t> image(dragImage->createCairoSurface());
- // Use the center of the drag image as hotspot.
- cairo_surface_set_device_offset(image.get(), -cairo_image_surface_get_width(image.get()) / 2, -cairo_image_surface_get_height(image.get()) / 2);
- gtk_drag_set_icon_surface(context, image.get());
- } else
- gtk_drag_set_icon_default(context);
-}
-
-void DragAndDropHandler::fillDragData(GdkDragContext* context, GtkSelectionData* selectionData, unsigned info)
-{
- // This can happen when attempting to call finish drag from webkitWebViewBaseDragDataGet()
- // for a obsolete DnD operation that got previously cancelled in startDrag().
- if (m_dragContext.get() != context)
- return;
-
- ASSERT(m_draggingSelectionData);
- PasteboardHelper::singleton().fillSelectionData(*m_draggingSelectionData, info, selectionData);
-}
-
-void DragAndDropHandler::finishDrag(GdkDragContext* context)
-{
- // This can happen when attempting to call finish drag from webkitWebViewBaseDragEnd()
- // for a obsolete DnD operation that got previously cancelled in startDrag().
- if (m_dragContext.get() != context)
- return;
-
- if (!m_draggingSelectionData)
- return;
-
- m_dragContext = nullptr;
- m_draggingSelectionData = nullptr;
-
- GdkDevice* device = gdk_drag_context_get_device(context);
- int x = 0, y = 0;
- gdk_device_get_window_at_position(device, &x, &y);
- int xRoot = 0, yRoot = 0;
- gdk_device_get_position(device, nullptr, &xRoot, &yRoot);
- m_page.dragEnded(IntPoint(x, y), IntPoint(xRoot, yRoot), gdkDragActionToDragOperation(gdk_drag_context_get_selected_action(context)));
-}
-
-SelectionData* DragAndDropHandler::dropDataSelection(GdkDragContext* context, GtkSelectionData* selectionData, unsigned info, IntPoint& position)
-{
- DroppingContext* droppingContext = m_droppingContexts.get(context);
- if (!droppingContext)
- return nullptr;
-
- droppingContext->pendingDataRequests--;
- PasteboardHelper::singleton().fillSelectionData(selectionData, info, droppingContext->selectionData);
- if (droppingContext->pendingDataRequests)
- return nullptr;
-
- // The coordinates passed to drag-data-received signal are sometimes
- // inaccurate in WTR, so use the coordinates of the last motion event.
- position = droppingContext->lastMotionPosition;
-
- // If there are no more pending requests, start sending dragging data to WebCore.
- return droppingContext->selectionData.ptr();
-}
-
-void DragAndDropHandler::dragEntered(GdkDragContext* context, GtkSelectionData* selectionData, unsigned info, unsigned time)
-{
- IntPoint position;
- auto* selection = dropDataSelection(context, selectionData, info, position);
- if (!selection)
- return;
-
- DragData dragData(selection, position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
- m_page.resetCurrentDragInformation();
- m_page.dragEntered(dragData);
- DragOperation operation = m_page.currentDragOperation();
- gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
-}
-
-SelectionData* DragAndDropHandler::dragDataSelection(GdkDragContext* context, const IntPoint& position, unsigned time)
-{
- std::unique_ptr<DroppingContext>& droppingContext = m_droppingContexts.add(context, nullptr).iterator->value;
- if (!droppingContext) {
- GtkWidget* widget = m_page.viewWidget();
- droppingContext = makeUnique<DroppingContext>(context, position);
- Vector<GdkAtom> acceptableTargets(PasteboardHelper::singleton().dropAtomsForContext(widget, droppingContext->gdkContext));
- droppingContext->pendingDataRequests = acceptableTargets.size();
- for (auto& target : acceptableTargets)
- gtk_drag_get_data(widget, droppingContext->gdkContext, target, time);
- } else
- droppingContext->lastMotionPosition = position;
-
- // Don't send any drag information to WebCore until we've retrieved all the data for this drag operation.
- // Otherwise we'd have to block to wait for the drag's data.
- if (droppingContext->pendingDataRequests > 0)
- return nullptr;
-
- return droppingContext->selectionData.ptr();
-}
-
-void DragAndDropHandler::dragMotion(GdkDragContext* context, const IntPoint& position, unsigned time)
-{
- auto* selection = dragDataSelection(context, position, time);
- if (!selection)
- return;
-
- DragData dragData(selection, position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
- m_page.dragUpdated(dragData);
- DragOperation operation = m_page.currentDragOperation();
- gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
-}
-
-void DragAndDropHandler::dragLeave(GdkDragContext* context)
-{
- DroppingContext* droppingContext = m_droppingContexts.get(context);
- if (!droppingContext)
- return;
-
- // During a drop GTK+ will fire a drag-leave signal right before firing
- // the drag-drop signal. We want the actions for drag-leave to happen after
- // those for drag-drop, so schedule them to happen asynchronously here.
- RunLoop::main().dispatch([this, context, droppingContext]() {
- auto it = m_droppingContexts.find(context);
- if (it == m_droppingContexts.end())
- return;
-
- // If the view doesn't know about the drag yet (there are still pending data requests),
- // don't update it with information about the drag.
- if (droppingContext->pendingDataRequests)
- return;
-
- if (!droppingContext->dropHappened) {
- // Don't call dragExited if we have just received a drag-drop signal. This
- // happens in the case of a successful drop onto the view.
- const IntPoint& position = droppingContext->lastMotionPosition;
- DragData dragData(droppingContext->selectionData.ptr(), position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), DragOperationNone);
- m_page.dragExited(dragData);
- m_page.resetCurrentDragInformation();
- }
-
- m_droppingContexts.remove(it);
- });
-}
-
-bool DragAndDropHandler::drop(GdkDragContext* context, const IntPoint& position, unsigned time)
-{
- DroppingContext* droppingContext = m_droppingContexts.get(context);
- if (!droppingContext)
- return false;
-
- droppingContext->dropHappened = true;
-
- uint32_t flags = 0;
- if (gdk_drag_context_get_selected_action(context) == GDK_ACTION_COPY)
- flags |= WebCore::DragApplicationIsCopyKeyDown;
- DragData dragData(droppingContext->selectionData.ptr(), position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)), static_cast<WebCore::DragApplicationFlags>(flags));
- m_page.performDragOperation(dragData, String(), { }, { });
- gtk_drag_finish(context, TRUE, FALSE, time);
- return true;
-}
-
-} // namespace WebKit
-
-#endif // ENABLE(DRAG_SUPPORT)
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (261569 => 261570)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2020-05-12 19:27:48 UTC (rev 261570)
@@ -3943,7 +3943,7 @@
return;
}
case DragControllerAction::Updated: {
- DragOperation resolvedDragOperation = m_page->dragController().dragEntered(dragData);
+ DragOperation resolvedDragOperation = m_page->dragController().dragUpdated(dragData);
send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().dragHandlingMethod(), m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted(), { }, { }));
return;
}
Modified: trunk/Source/WebKit/WebProcess/WebPage/gtk/WebPageGtk.cpp (261569 => 261570)
--- trunk/Source/WebKit/WebProcess/WebPage/gtk/WebPageGtk.cpp 2020-05-12 19:13:18 UTC (rev 261569)
+++ trunk/Source/WebKit/WebProcess/WebPage/gtk/WebPageGtk.cpp 2020-05-12 19:27:48 UTC (rev 261570)
@@ -42,7 +42,6 @@
#include <WebCore/KeyboardEvent.h>
#include <WebCore/NotImplemented.h>
#include <WebCore/Page.h>
-#include <WebCore/PasteboardHelper.h>
#include <WebCore/PlatformKeyboardEvent.h>
#include <WebCore/RenderTheme.h>
#include <WebCore/Settings.h>