| Differences between
and this patch
- a/Source/WebCore/ChangeLog +19 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2020-05-11  Carlos Garcia Campos  <cgarcia@igalia.com>
2
3
        [GTK] Rework drag and drop handling in preparation for GTK4
4
        https://bugs.webkit.org/show_bug.cgi?id=211723
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Remove PasteboardHelper that is no longer used and add conversion functions to GtkUtilities.
9
10
        * PlatformGTK.cmake:
11
        * SourcesGTK.txt:
12
        * platform/gtk/GtkUtilities.cpp:
13
        (WebCore::gdkDragActionToDragOperation):
14
        (WebCore::dragOperationToGdkDragActions):
15
        (WebCore::dragOperationToSingleGdkDragAction):
16
        * platform/gtk/GtkUtilities.h:
17
        * platform/gtk/PasteboardHelper.cpp: Removed.
18
        * platform/gtk/PasteboardHelper.h: Removed.
19
1
2020-05-06  Carlos Garcia Campos  <cgarcia@igalia.com>
20
2020-05-06  Carlos Garcia Campos  <cgarcia@igalia.com>
2
21
3
        [GTK] Rework clipboard handling in preparation for GTK4
22
        [GTK] Rework clipboard handling in preparation for GTK4
- a/Source/WebCore/PlatformGTK.cmake -1 lines
Lines 61-67 list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS a/Source/WebCore/PlatformGTK.cmake_sec1
61
    platform/gtk/GUniquePtrGtk.h
61
    platform/gtk/GUniquePtrGtk.h
62
    platform/gtk/GtkUtilities.h
62
    platform/gtk/GtkUtilities.h
63
    platform/gtk/GtkVersioning.h
63
    platform/gtk/GtkVersioning.h
64
    platform/gtk/PasteboardHelper.h
65
    platform/gtk/ScrollbarThemeGtk.h
64
    platform/gtk/ScrollbarThemeGtk.h
66
    platform/gtk/SelectionData.h
65
    platform/gtk/SelectionData.h
67
66
- a/Source/WebCore/SourcesGTK.txt -1 lines
Lines 109-115 platform/gtk/GRefPtrGtk.cpp a/Source/WebCore/SourcesGTK.txt_sec1
109
platform/gtk/GtkUtilities.cpp
109
platform/gtk/GtkUtilities.cpp
110
platform/gtk/LocalizedStringsGtk.cpp
110
platform/gtk/LocalizedStringsGtk.cpp
111
platform/gtk/PasteboardGtk.cpp
111
platform/gtk/PasteboardGtk.cpp
112
platform/gtk/PasteboardHelper.cpp
113
platform/gtk/PlatformKeyboardEventGtk.cpp
112
platform/gtk/PlatformKeyboardEventGtk.cpp
114
platform/gtk/PlatformScreenGtk.cpp
113
platform/gtk/PlatformScreenGtk.cpp
115
platform/gtk/PlatformWheelEventGtk.cpp
114
platform/gtk/PlatformWheelEventGtk.cpp
- a/Source/WebCore/platform/gtk/GtkUtilities.cpp +47 lines
Lines 102-105 unsigned stateModifierForGdkButton(unsigned button) a/Source/WebCore/platform/gtk/GtkUtilities.cpp_sec1
102
    return 1 << (8 + button - 1);
102
    return 1 << (8 + button - 1);
103
}
103
}
104
104
105
DragOperation gdkDragActionToDragOperation(GdkDragAction gdkAction)
106
{
107
    // We have no good way to detect DragOperationEvery other than
108
    // to use it when all applicable flags are on.
109
    if (gdkAction & GDK_ACTION_COPY
110
        && gdkAction & GDK_ACTION_MOVE
111
        && gdkAction & GDK_ACTION_LINK)
112
        return DragOperationEvery;
113
114
    unsigned action = DragOperationNone;
115
    if (gdkAction & GDK_ACTION_COPY)
116
        action |= DragOperationCopy;
117
    if (gdkAction & GDK_ACTION_MOVE)
118
        action |= DragOperationMove;
119
    if (gdkAction & GDK_ACTION_LINK)
120
        action |= DragOperationLink;
121
122
    return static_cast<DragOperation>(action);
123
}
124
125
GdkDragAction dragOperationToGdkDragActions(DragOperation coreAction)
126
{
127
    unsigned gdkAction = 0;
128
    if (coreAction == DragOperationNone)
129
        return static_cast<GdkDragAction>(gdkAction);
130
131
    if (coreAction & DragOperationCopy)
132
        gdkAction |= GDK_ACTION_COPY;
133
    if (coreAction & DragOperationMove)
134
        gdkAction |= GDK_ACTION_MOVE;
135
    if (coreAction & DragOperationLink)
136
        gdkAction |= GDK_ACTION_LINK;
137
138
    return static_cast<GdkDragAction>(gdkAction);
139
}
140
141
GdkDragAction dragOperationToSingleGdkDragAction(DragOperation coreAction)
142
{
143
    if (coreAction == DragOperationEvery || coreAction & DragOperationCopy)
144
        return GDK_ACTION_COPY;
145
    if (coreAction & DragOperationMove)
146
        return GDK_ACTION_MOVE;
147
    if (coreAction & DragOperationLink)
148
        return GDK_ACTION_LINK;
149
    return static_cast<GdkDragAction>(0);
150
}
151
105
} // namespace WebCore
152
} // namespace WebCore
- a/Source/WebCore/platform/gtk/GtkUtilities.h +5 lines
Lines 18-23 a/Source/WebCore/platform/gtk/GtkUtilities.h_sec1
18
18
19
#pragma once
19
#pragma once
20
20
21
#include "DragActions.h"
21
#include <gtk/gtk.h>
22
#include <gtk/gtk.h>
22
#include <wtf/MonotonicTime.h>
23
#include <wtf/MonotonicTime.h>
23
#include <wtf/WallTime.h>
24
#include <wtf/WallTime.h>
Lines 47-50 String defaultGtkSystemFont(); a/Source/WebCore/platform/gtk/GtkUtilities.h_sec2
47
48
48
WEBCORE_EXPORT unsigned stateModifierForGdkButton(unsigned button);
49
WEBCORE_EXPORT unsigned stateModifierForGdkButton(unsigned button);
49
50
51
WEBCORE_EXPORT DragOperation gdkDragActionToDragOperation(GdkDragAction);
52
WEBCORE_EXPORT GdkDragAction dragOperationToGdkDragActions(DragOperation);
53
WEBCORE_EXPORT GdkDragAction dragOperationToSingleGdkDragAction(DragOperation);
54
50
} // namespace WebCore
55
} // namespace WebCore
- a/Source/WebCore/platform/gtk/PasteboardHelper.cpp -235 lines
Lines 1-235 a/Source/WebCore/platform/gtk/PasteboardHelper.cpp_sec1
1
/*
2
 * Copyright (C) 2010 Martin Robinson <mrobinson@webkit.org>
3
 * Copyright (C) Igalia S.L.
4
 * Copyright (C) 2013 Collabora Ltd.
5
 * All rights reserved.
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Library General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Library General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Library General Public License
18
 * along with this library; see the file COPYING.LIB.  If not, write to
19
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20
 * Boston, MA 02110-1301, USA.
21
 *
22
 */
23
#include "config.h"
24
#include "PasteboardHelper.h"
25
26
#if !USE(GTK4)
27
28
#include "BitmapImage.h"
29
#include "SelectionData.h"
30
#include <gtk/gtk.h>
31
#include <wtf/glib/GUniquePtr.h>
32
#include <wtf/text/CString.h>
33
34
namespace WebCore {
35
36
static GdkAtom textPlainAtom;
37
static GdkAtom markupAtom;
38
static GdkAtom netscapeURLAtom;
39
static GdkAtom uriListAtom;
40
static GdkAtom smartPasteAtom;
41
static GdkAtom unknownAtom;
42
43
static const String& markupPrefix()
44
{
45
    static NeverDestroyed<const String> prefix(MAKE_STATIC_STRING_IMPL("<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">"));
46
    return prefix.get();
47
}
48
49
static void removeMarkupPrefix(String& markup)
50
{
51
    // The markup prefix is not harmful, but we remove it from the string anyway, so that
52
    // we can have consistent results with other ports during the layout tests.
53
    if (markup.startsWith(markupPrefix()))
54
        markup.remove(0, markupPrefix().length());
55
}
56
57
PasteboardHelper& PasteboardHelper::singleton()
58
{
59
    static PasteboardHelper helper;
60
    return helper;
61
}
62
63
PasteboardHelper::PasteboardHelper()
64
    : m_targetList(adoptGRef(gtk_target_list_new(nullptr, 0)))
65
{
66
    textPlainAtom = gdk_atom_intern_static_string("text/plain;charset=utf-8");
67
    markupAtom = gdk_atom_intern_static_string("text/html");
68
    netscapeURLAtom = gdk_atom_intern_static_string("_NETSCAPE_URL");
69
    uriListAtom = gdk_atom_intern_static_string("text/uri-list");
70
    smartPasteAtom = gdk_atom_intern_static_string("application/vnd.webkitgtk.smartpaste");
71
    unknownAtom = gdk_atom_intern_static_string("application/vnd.webkitgtk.unknown");
72
73
    gtk_target_list_add_text_targets(m_targetList.get(), PasteboardHelper::TargetTypeText);
74
    gtk_target_list_add(m_targetList.get(), markupAtom, 0, PasteboardHelper::TargetTypeMarkup);
75
    gtk_target_list_add_uri_targets(m_targetList.get(), PasteboardHelper::TargetTypeURIList);
76
    gtk_target_list_add(m_targetList.get(), netscapeURLAtom, 0, PasteboardHelper::TargetTypeNetscapeURL);
77
    gtk_target_list_add_image_targets(m_targetList.get(), PasteboardHelper::TargetTypeImage, TRUE);
78
    gtk_target_list_add(m_targetList.get(), unknownAtom, 0, PasteboardHelper::TargetTypeUnknown);
79
}
80
81
PasteboardHelper::~PasteboardHelper() = default;
82
83
GtkTargetList* PasteboardHelper::targetList() const
84
{
85
    return m_targetList.get();
86
}
87
88
static String selectionDataToUTF8String(GtkSelectionData* data)
89
{
90
    if (!gtk_selection_data_get_length(data))
91
        return String();
92
93
    // g_strndup guards against selection data that is not null-terminated.
94
    GUniquePtr<gchar> markupString(g_strndup(reinterpret_cast<const char*>(gtk_selection_data_get_data(data)), gtk_selection_data_get_length(data)));
95
    return String::fromUTF8(markupString.get());
96
}
97
98
GRefPtr<GtkTargetList> PasteboardHelper::targetListForSelectionData(const SelectionData& selection)
99
{
100
    GRefPtr<GtkTargetList> list = adoptGRef(gtk_target_list_new(nullptr, 0));
101
102
    if (selection.hasText())
103
        gtk_target_list_add_text_targets(list.get(), TargetTypeText);
104
105
    if (selection.hasMarkup())
106
        gtk_target_list_add(list.get(), markupAtom, 0, TargetTypeMarkup);
107
108
    if (selection.hasURIList()) {
109
        gtk_target_list_add_uri_targets(list.get(), TargetTypeURIList);
110
        gtk_target_list_add(list.get(), netscapeURLAtom, 0, TargetTypeNetscapeURL);
111
    }
112
113
    if (selection.hasImage())
114
        gtk_target_list_add_image_targets(list.get(), TargetTypeImage, TRUE);
115
116
    if (selection.hasUnknownTypeData())
117
        gtk_target_list_add(list.get(), unknownAtom, 0, TargetTypeUnknown);
118
119
    if (selection.canSmartReplace())
120
        gtk_target_list_add(list.get(), smartPasteAtom, 0, TargetTypeSmartPaste);
121
122
    return list;
123
}
124
125
void PasteboardHelper::fillSelectionData(const SelectionData& selection, unsigned info, GtkSelectionData* selectionData)
126
{
127
    if (info == TargetTypeText)
128
        gtk_selection_data_set_text(selectionData, selection.text().utf8().data(), -1);
129
130
    else if (info == TargetTypeMarkup) {
131
        // Some Linux applications refuse to accept pasted markup unless it is
132
        // prefixed by a content-type meta tag.
133
        CString markup = makeString(markupPrefix(), selection.markup()).utf8();
134
        gtk_selection_data_set(selectionData, markupAtom, 8, reinterpret_cast<const guchar*>(markup.data()), markup.length());
135
136
    } else if (info == TargetTypeURIList) {
137
        CString uriList = selection.uriList().utf8();
138
        gtk_selection_data_set(selectionData, uriListAtom, 8, reinterpret_cast<const guchar*>(uriList.data()), uriList.length());
139
140
    } else if (info == TargetTypeNetscapeURL && selection.hasURL()) {
141
        String url(selection.url());
142
        String result(url);
143
        result.append("\n");
144
145
        if (selection.hasText())
146
            result.append(selection.text());
147
        else
148
            result.append(url);
149
150
        GUniquePtr<gchar> resultData(g_strdup(result.utf8().data()));
151
        gtk_selection_data_set(selectionData, netscapeURLAtom, 8, reinterpret_cast<const guchar*>(resultData.get()), strlen(resultData.get()));
152
153
    } else if (info == TargetTypeImage && selection.hasImage()) {
154
        GRefPtr<GdkPixbuf> pixbuf = adoptGRef(selection.image()->getGdkPixbuf());
155
        gtk_selection_data_set_pixbuf(selectionData, pixbuf.get());
156
157
    } else if (info == TargetTypeSmartPaste)
158
        gtk_selection_data_set_text(selectionData, "", -1);
159
160
    else if (info == TargetTypeUnknown) {
161
        GVariantBuilder builder;
162
        g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
163
164
        for (auto& it : selection.unknownTypes()) {
165
            GUniquePtr<gchar> dictItem(g_strdup_printf("{'%s', '%s'}", it.key.utf8().data(), it.value.utf8().data()));
166
            g_variant_builder_add_parsed(&builder, dictItem.get());
167
        }
168
169
        GRefPtr<GVariant> variant = g_variant_builder_end(&builder);
170
        GUniquePtr<gchar> serializedVariant(g_variant_print(variant.get(), TRUE));
171
        gtk_selection_data_set(selectionData, unknownAtom, 1, reinterpret_cast<const guchar*>(serializedVariant.get()), strlen(serializedVariant.get()));
172
    }
173
}
174
175
void PasteboardHelper::fillSelectionData(GtkSelectionData* data, unsigned /* info */, SelectionData& selection)
176
{
177
    if (gtk_selection_data_get_length(data) < 0)
178
        return;
179
180
    GdkAtom target = gtk_selection_data_get_target(data);
181
    if (target == textPlainAtom)
182
        selection.setText(selectionDataToUTF8String(data));
183
    else if (target == markupAtom) {
184
        String markup(selectionDataToUTF8String(data));
185
        removeMarkupPrefix(markup);
186
        selection.setMarkup(markup);
187
    } else if (target == uriListAtom) {
188
        selection.setURIList(selectionDataToUTF8String(data));
189
    } else if (target == netscapeURLAtom) {
190
        String urlWithLabel(selectionDataToUTF8String(data));
191
        Vector<String> pieces = urlWithLabel.split('\n');
192
193
        // Give preference to text/uri-list here, as it can hold more
194
        // than one URI but still take  the label if there is one.
195
        if (!selection.hasURIList() && !pieces.isEmpty())
196
            selection.setURIList(pieces[0]);
197
        if (pieces.size() > 1)
198
            selection.setText(pieces[1]);
199
    } else if (target == unknownAtom && gtk_selection_data_get_length(data)) {
200
        GRefPtr<GVariant> variant = g_variant_new_parsed(reinterpret_cast<const char*>(gtk_selection_data_get_data(data)));
201
202
        GUniqueOutPtr<gchar> key;
203
        GUniqueOutPtr<gchar> value;
204
        GVariantIter iter;
205
206
        g_variant_iter_init(&iter, variant.get());
207
        while (g_variant_iter_next(&iter, "{ss}", &key.outPtr(), &value.outPtr()))
208
            selection.setUnknownTypeData(key.get(), value.get());
209
    }
210
}
211
212
Vector<GdkAtom> PasteboardHelper::dropAtomsForContext(GtkWidget* widget, GdkDragContext* context)
213
{
214
    // Always search for these common atoms.
215
    Vector<GdkAtom> dropAtoms;
216
    dropAtoms.append(textPlainAtom);
217
    dropAtoms.append(markupAtom);
218
    dropAtoms.append(uriListAtom);
219
    dropAtoms.append(netscapeURLAtom);
220
    dropAtoms.append(unknownAtom);
221
222
    // For images, try to find the most applicable image type.
223
    GRefPtr<GtkTargetList> list = adoptGRef(gtk_target_list_new(0, 0));
224
    gtk_target_list_add_image_targets(list.get(), TargetTypeImage, TRUE);
225
    GdkAtom atom = gtk_drag_dest_find_target(widget, context, list.get());
226
    if (atom != GDK_NONE)
227
        dropAtoms.append(atom);
228
229
    return dropAtoms;
230
}
231
232
} // namespace WebCore
233
234
#endif // !USE(GTK4)
235
- a/Source/WebCore/platform/gtk/PasteboardHelper.h -60 lines
Lines 1-60 a/Source/WebCore/platform/gtk/PasteboardHelper.h_sec1
1
/*
2
 * Copyright (C) 2007 Luca Bruno <lethalman88@gmail.com>
3
 * Copyright (C) 2009 Holger Hans Peter Freyther
4
 * Copyright (C) 2010 Martin Robinson <mrobinson@webkit.org>
5
 * Copyright (C) 2010 Igalia S.L.
6
 * All rights reserved.
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Library General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Library General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Library General Public License
19
 * along with this library; see the file COPYING.LIB.  If not, write to
20
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21
 * Boston, MA 02110-1301, USA.
22
 *
23
 */
24
25
#pragma once
26
27
#if !USE(GTK4)
28
29
#include "GRefPtrGtk.h"
30
#include <wtf/Function.h>
31
#include <wtf/Noncopyable.h>
32
#include <wtf/Vector.h>
33
34
namespace WebCore {
35
36
class SelectionData;
37
38
class PasteboardHelper {
39
    WTF_MAKE_NONCOPYABLE(PasteboardHelper);
40
public:
41
    static PasteboardHelper& singleton();
42
43
    GtkTargetList* targetList() const;
44
    GRefPtr<GtkTargetList> targetListForSelectionData(const SelectionData&);
45
    void fillSelectionData(const SelectionData&, unsigned, GtkSelectionData*);
46
    void fillSelectionData(GtkSelectionData*, unsigned, SelectionData&);
47
    Vector<GdkAtom> dropAtomsForContext(GtkWidget*, GdkDragContext*);
48
49
    enum PasteboardTargetType { TargetTypeMarkup, TargetTypeText, TargetTypeImage, TargetTypeURIList, TargetTypeNetscapeURL, TargetTypeSmartPaste, TargetTypeUnknown };
50
51
private:
52
    PasteboardHelper();
53
    ~PasteboardHelper();
54
55
    GRefPtr<GtkTargetList> m_targetList;
56
};
57
58
} // namespace WebCore
59
60
#endif // !USE(GTK4)
- a/Source/WebKit/ChangeLog +48 lines
Lines 1-3 a/Source/WebKit/ChangeLog_sec1
1
2020-05-11  Carlos Garcia Campos  <cgarcia@igalia.com>
2
3
        [GTK] Rework drag and drop handling in preparation for GTK4
4
        https://bugs.webkit.org/show_bug.cgi?id=211723
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Split DragAndDropHelper class into DragSource and DropTarget classes. This separates the source and destination
9
        parts making it easier to follow. This patch also adds PageClient::didPerformDragControllerAction() to notify
10
        back the view when an operation is done to update the result.
11
12
        * SourcesGTK.txt:
13
        * UIProcess/API/gtk/DragSource.h: Added.
14
        * UIProcess/API/gtk/DragSourceGtk3.cpp: Added.
15
        (WebKit::DragSource::DragSource):
16
        (WebKit::DragSource::~DragSource):
17
        (WebKit::DragSource::begin):
18
        * UIProcess/API/gtk/DropTarget.h: Added.
19
        * UIProcess/API/gtk/DropTargetGtk3.cpp: Added.
20
        (WebKit::DropTarget::DropTarget):
21
        (WebKit::DropTarget::~DropTarget):
22
        (WebKit::DropTarget::accept):
23
        (WebKit::DropTarget::enter):
24
        (WebKit::DropTarget::update):
25
        (WebKit::DropTarget::dataReceived):
26
        (WebKit::DropTarget::didPerformAction):
27
        (WebKit::DropTarget::leaveTimerFired):
28
        (WebKit::DropTarget::leave):
29
        (WebKit::DropTarget::drop):
30
        * UIProcess/API/gtk/PageClientImpl.cpp:
31
        (WebKit::PageClientImpl::startDrag):
32
        (WebKit::PageClientImpl::didPerformDragControllerAction):
33
        * UIProcess/API/gtk/PageClientImpl.h:
34
        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
35
        (webkitWebViewBaseConstructed):
36
        (webkit_web_view_base_class_init):
37
        (webkitWebViewBaseStartDrag):
38
        (webkitWebViewBaseDidPerformDragControllerAction):
39
        * UIProcess/API/gtk/WebKitWebViewBasePrivate.h:
40
        * UIProcess/PageClient.h:
41
        (WebKit::PageClient::didPerformDragControllerAction):
42
        * UIProcess/WebPageProxy.cpp:
43
        (WebKit::WebPageProxy::didPerformDragControllerAction):
44
        * UIProcess/gtk/DragAndDropHandler.cpp: Removed.
45
        * WebProcess/WebPage/WebPage.cpp:
46
        (WebKit::WebPage::performDragControllerAction):
47
        * WebProcess/WebPage/gtk/WebPageGtk.cpp:
48
1
2020-05-06  Carlos Garcia Campos  <cgarcia@igalia.com>
49
2020-05-06  Carlos Garcia Campos  <cgarcia@igalia.com>
2
50
3
        [GTK] Rework clipboard handling in preparation for GTK4
51
        [GTK] Rework clipboard handling in preparation for GTK4
- a/Source/WebKit/SourcesGTK.txt -1 / +4 lines
Lines 194-199 UIProcess/API/glib/WebKitWebsiteData.cpp @no-unify a/Source/WebKit/SourcesGTK.txt_sec1
194
UIProcess/API/glib/WebKitWebsiteDataManager.cpp @no-unify
194
UIProcess/API/glib/WebKitWebsiteDataManager.cpp @no-unify
195
UIProcess/API/glib/WebKitWindowProperties.cpp @no-unify
195
UIProcess/API/glib/WebKitWindowProperties.cpp @no-unify
196
196
197
UIProcess/API/gtk/DragSourceGtk3.cpp @no-unify
198
UIProcess/API/gtk/DragSourceGtk4.cpp @no-unify
199
UIProcess/API/gtk/DropTargetGtk3.cpp @no-unify
200
UIProcess/API/gtk/DropTargetGtk4.cpp @no-unify
197
UIProcess/API/gtk/InputMethodFilterGtk.cpp @no-unify
201
UIProcess/API/gtk/InputMethodFilterGtk.cpp @no-unify
198
UIProcess/API/gtk/PageClientImpl.cpp @no-unify
202
UIProcess/API/gtk/PageClientImpl.cpp @no-unify
199
UIProcess/API/gtk/WebKitAuthenticationDialog.cpp @no-unify
203
UIProcess/API/gtk/WebKitAuthenticationDialog.cpp @no-unify
Lines 256-262 UIProcess/gtk/AcceleratedBackingStoreX11.cpp @no-unify a/Source/WebKit/SourcesGTK.txt_sec2
256
UIProcess/gtk/Clipboard.cpp
260
UIProcess/gtk/Clipboard.cpp
257
UIProcess/gtk/ClipboardGtk3.cpp @no-unify
261
UIProcess/gtk/ClipboardGtk3.cpp @no-unify
258
UIProcess/gtk/ClipboardGtk4.cpp @no-unify
262
UIProcess/gtk/ClipboardGtk4.cpp @no-unify
259
UIProcess/gtk/DragAndDropHandler.cpp
260
UIProcess/gtk/GestureController.cpp
263
UIProcess/gtk/GestureController.cpp
261
UIProcess/gtk/HardwareAccelerationManager.cpp
264
UIProcess/gtk/HardwareAccelerationManager.cpp
262
UIProcess/gtk/KeyBindingTranslator.cpp
265
UIProcess/gtk/KeyBindingTranslator.cpp
- a/Source/WebKit/UIProcess/API/gtk/DragSource.h +68 lines
Line 0 a/Source/WebKit/UIProcess/API/gtk/DragSource.h_sec1
1
/*
2
 * Copyright (C) 2020 Igalia S.L.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#pragma once
27
28
#if ENABLE(DRAG_SUPPORT)
29
30
#include <WebCore/DragActions.h>
31
#include <wtf/Forward.h>
32
#include <wtf/Noncopyable.h>
33
#include <wtf/glib/GRefPtr.h>
34
35
typedef struct _GtkWidget GtkWidget;
36
37
#if !USE(GTK4)
38
typedef struct _GdkDragContext GdkDragContext;
39
#endif
40
41
namespace WebCore {
42
class SelectionData;
43
}
44
45
namespace WebKit {
46
47
class ShareableBitmap;
48
49
class DragSource {
50
    WTF_MAKE_NONCOPYABLE(DragSource); WTF_MAKE_FAST_ALLOCATED;
51
public:
52
53
    explicit DragSource(GtkWidget*);
54
    ~DragSource();
55
56
    void begin(Ref<WebCore::SelectionData>&&, WebCore::DragOperation, RefPtr<ShareableBitmap>&&);
57
58
private:
59
    GtkWidget* m_webView { nullptr };
60
#if !USE(GTK4)
61
    GRefPtr<GdkDragContext> m_drag;
62
#endif
63
    RefPtr<WebCore::SelectionData> m_selectionData;
64
};
65
66
} // namespace WebKit
67
68
#endif // ENABLE(DRAG_SUPPORT)
- a/Source/WebKit/UIProcess/API/gtk/DragSourceGtk3.cpp +144 lines
Line 0 a/Source/WebKit/UIProcess/API/gtk/DragSourceGtk3.cpp_sec1
1
/*
2
 * Copyright (C) 2020 Igalia S.L.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "config.h"
27
#include "DragSource.h"
28
29
#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
30
31
#include "WebKitWebViewBasePrivate.h"
32
#include <WebCore/GRefPtrGtk.h>
33
#include <WebCore/GtkUtilities.h>
34
#include <gtk/gtk.h>
35
36
namespace WebKit {
37
using namespace WebCore;
38
39
enum DragTargetType { Markup, Text, Image, URIList, NetscapeURL, SmartPaste };
40
41
DragSource::DragSource(GtkWidget* webView)
42
    : m_webView(webView)
43
{
44
    g_signal_connect(m_webView, "drag-data-get", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, GtkSelectionData* data, guint info, guint, gpointer userData) {
45
        auto& drag = *static_cast<DragSource*>(userData);
46
        if (drag.m_drag.get() != context)
47
            return;
48
49
        switch (info) {
50
        case DragTargetType::Text:
51
            gtk_selection_data_set_text(data, drag.m_selectionData->text().utf8().data(), -1);
52
            break;
53
        case DragTargetType::Markup: {
54
            CString markup = drag.m_selectionData->markup().utf8();
55
            gtk_selection_data_set(data, gdk_atom_intern_static_string("text/html"), 8, reinterpret_cast<const guchar*>(markup.data()), markup.length());
56
            break;
57
        }
58
        case DragTargetType::URIList: {
59
            CString uriList = drag.m_selectionData->uriList().utf8();
60
            gtk_selection_data_set(data, gdk_atom_intern_static_string("text/uri-list"), 8, reinterpret_cast<const guchar*>(uriList.data()), uriList.length());
61
            break;
62
        }
63
        case DragTargetType::NetscapeURL: {
64
            CString urlString = drag.m_selectionData->url().string().utf8();
65
            GUniquePtr<gchar> url(g_strdup_printf("%s\n%s", urlString.data(), drag.m_selectionData->hasText() ? drag.m_selectionData->text().utf8().data() : urlString.data()));
66
            gtk_selection_data_set(data, gdk_atom_intern_static_string("_NETSCAPE_URL"), 8, reinterpret_cast<const guchar*>(url.get()), strlen(url.get()));
67
            break;
68
        }
69
        case DragTargetType::Image: {
70
            GRefPtr<GdkPixbuf> pixbuf = adoptGRef(drag.m_selectionData->image()->getGdkPixbuf());
71
            gtk_selection_data_set_pixbuf(data, pixbuf.get());
72
            break;
73
        }
74
        case DragTargetType::SmartPaste:
75
            gtk_selection_data_set_text(data, "", -1);
76
            break;
77
        }
78
    }), this);
79
80
    g_signal_connect(m_webView, "drag-end", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, gpointer userData) {
81
        auto& drag = *static_cast<DragSource*>(userData);
82
        if (drag.m_drag.get() != context)
83
            return;
84
        if (!drag.m_selectionData)
85
            return;
86
87
        drag.m_selectionData = nullptr;
88
        drag.m_drag = nullptr;
89
90
        GdkDevice* device = gdk_drag_context_get_device(context);
91
        int x = 0;
92
        int y = 0;
93
        gdk_device_get_window_at_position(device, &x, &y);
94
        int xRoot = 0;
95
        int yRoot = 0;
96
        gdk_device_get_position(device, nullptr, &xRoot, &yRoot);
97
98
        auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(drag.m_webView));
99
        ASSERT(page);
100
        page->dragEnded({ x, y }, { xRoot, yRoot }, gdkDragActionToDragOperation(gdk_drag_context_get_selected_action(context)));
101
    }), this);
102
}
103
104
DragSource::~DragSource()
105
{
106
    g_signal_handlers_disconnect_by_data(m_webView, this);
107
}
108
109
void DragSource::begin(Ref<SelectionData>&& selectionData, DragOperation operation, RefPtr<ShareableBitmap>&& image)
110
{
111
    if (m_drag) {
112
        gtk_drag_cancel(m_drag.get());
113
        m_drag = nullptr;
114
    }
115
116
    m_selectionData = WTFMove(selectionData);
117
118
    GRefPtr<GtkTargetList> list = adoptGRef(gtk_target_list_new(nullptr, 0));
119
    if (m_selectionData->hasText())
120
        gtk_target_list_add_text_targets(list.get(), DragTargetType::Text);
121
    if (m_selectionData->hasMarkup())
122
        gtk_target_list_add(list.get(), gdk_atom_intern_static_string("text/html"), 0, DragTargetType::Markup);
123
    if (m_selectionData->hasURIList())
124
        gtk_target_list_add_uri_targets(list.get(), DragTargetType::URIList);
125
    if (m_selectionData->hasURL())
126
        gtk_target_list_add(list.get(), gdk_atom_intern_static_string("_NETSCAPE_URL"), 0, DragTargetType::NetscapeURL);
127
    if (m_selectionData->hasImage())
128
        gtk_target_list_add_image_targets(list.get(), DragTargetType::Image, TRUE);
129
    if (m_selectionData->canSmartReplace())
130
        gtk_target_list_add(list.get(), gdk_atom_intern_static_string("application/vnd.webkitgtk.smartpaste"), 0, DragTargetType::SmartPaste);
131
132
    m_drag = gtk_drag_begin_with_coordinates(m_webView, list.get(), dragOperationToGdkDragActions(operation), GDK_BUTTON_PRIMARY, nullptr, -1, -1);
133
    if (image) {
134
        RefPtr<cairo_surface_t> imageSurface(image->createCairoSurface());
135
        // Use the center of the drag image as hotspot.
136
        cairo_surface_set_device_offset(imageSurface.get(), -cairo_image_surface_get_width(imageSurface.get()) / 2, -cairo_image_surface_get_height(imageSurface.get()) / 2);
137
        gtk_drag_set_icon_surface(m_drag.get(), imageSurface.get());
138
    } else
139
        gtk_drag_set_icon_default(m_drag.get());
140
}
141
142
} // namespace WebKit
143
144
#endif // ENABLE(DRAG_SUPPORT) && !USE(GTK4)
- a/Source/WebKit/UIProcess/API/gtk/DropTarget.h +87 lines
Line 0 a/Source/WebKit/UIProcess/API/gtk/DropTarget.h_sec1
1
/*
2
 * Copyright (C) 2020 Igalia S.L.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#pragma once
27
28
#if ENABLE(DRAG_SUPPORT)
29
30
#include <WebCore/DragActions.h>
31
#include <WebCore/IntPoint.h>
32
#include <wtf/Forward.h>
33
#include <wtf/Noncopyable.h>
34
#include <wtf/RunLoop.h>
35
#include <wtf/glib/GRefPtr.h>
36
37
typedef struct _GtkWidget GtkWidget;
38
39
#if !USE(GTK4)
40
typedef struct _GdkDragContext GdkDragContext;
41
typedef struct _GtkSelectionData GtkSelectionData;
42
#endif
43
44
namespace WebCore {
45
class SelectionData;
46
}
47
48
namespace WebKit {
49
50
class ShareableBitmap;
51
52
class DropTarget {
53
    WTF_MAKE_NONCOPYABLE(DropTarget); WTF_MAKE_FAST_ALLOCATED;
54
public:
55
    explicit DropTarget(GtkWidget*);
56
    ~DropTarget();
57
58
    void didPerformAction();
59
60
private:
61
    void accept(unsigned = 0);
62
    void enter(WebCore::IntPoint&&, unsigned = 0);
63
    void update(WebCore::IntPoint&&, unsigned = 0);
64
    void leave();
65
    void drop(WebCore::IntPoint&&, unsigned = 0);
66
67
#if !USE(GTK4)
68
    void dataReceived(WebCore::IntPoint&&, GtkSelectionData*, unsigned, unsigned);
69
    void leaveTimerFired();
70
#endif
71
72
    GtkWidget* m_webView { nullptr };
73
#if !USE(GTK4)
74
    GRefPtr<GdkDragContext> m_drop;
75
#endif
76
    Optional<WebCore::IntPoint> m_position;
77
    unsigned m_dataRequestCount { 0 };
78
    RefPtr<WebCore::SelectionData> m_selectionData;
79
    WebCore::DragOperation m_operation { WebCore::DragOperationNone };
80
#if !USE(GTK4)
81
    RunLoop::Timer<DropTarget> m_leaveTimer;
82
#endif
83
};
84
85
} // namespace WebKit
86
87
#endif // ENABLE(DRAG_SUPPORT)
- a/Source/WebKit/UIProcess/API/gtk/DropTargetGtk3.cpp +270 lines
Line 0 a/Source/WebKit/UIProcess/API/gtk/DropTargetGtk3.cpp_sec1
1
/*
2
 * Copyright (C) 2020 Igalia S.L.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "config.h"
27
#include "DropTarget.h"
28
29
#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
30
31
#include "WebKitWebViewBasePrivate.h"
32
#include <WebCore/DragData.h>
33
#include <WebCore/GRefPtrGtk.h>
34
#include <WebCore/GtkUtilities.h>
35
#include <gtk/gtk.h>
36
#include <wtf/glib/GUniquePtr.h>
37
38
namespace WebKit {
39
using namespace WebCore;
40
41
enum DropTargetType { Markup, Text, URIList, NetscapeURL, SmartPaste };
42
43
DropTarget::DropTarget(GtkWidget* webView)
44
    : m_webView(webView)
45
    , m_leaveTimer(RunLoop::main(), this, &DropTarget::leaveTimerFired)
46
{
47
    GRefPtr<GtkTargetList> list = adoptGRef(gtk_target_list_new(nullptr, 0));
48
    gtk_target_list_add_text_targets(list.get(), DropTargetType::Text);
49
    gtk_target_list_add(list.get(), gdk_atom_intern_static_string("text/html"), 0, DropTargetType::Markup);
50
    gtk_target_list_add_uri_targets(list.get(), DropTargetType::URIList);
51
    gtk_target_list_add(list.get(), gdk_atom_intern_static_string("_NETSCAPE_URL"), 0, DropTargetType::NetscapeURL);
52
    gtk_target_list_add(list.get(), gdk_atom_intern_static_string("application/vnd.webkitgtk.smartpaste"), 0, DropTargetType::SmartPaste);
53
    gtk_drag_dest_set(m_webView, static_cast<GtkDestDefaults>(0), nullptr, 0,
54
        static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK));
55
    gtk_drag_dest_set_target_list(m_webView, list.get());
56
57
    g_signal_connect(m_webView, "drag-motion", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, gint x, gint y, guint time, gpointer userData) -> gboolean {
58
        auto& drop = *static_cast<DropTarget*>(userData);
59
        if (!drop.m_drop) {
60
            drop.m_drop = context;
61
            drop.m_position = IntPoint(x, y);
62
            drop.accept(time);
63
        } else if (drop.m_drop == context)
64
            drop.update({ x, y }, time);
65
        return TRUE;
66
    }), this);
67
68
    g_signal_connect(m_webView, "drag-leave", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, guint time, gpointer userData) {
69
        auto& drop = *static_cast<DropTarget*>(userData);
70
        if (drop.m_drop != context)
71
            return;
72
        drop.leave();
73
    }), this);
74
75
    g_signal_connect(m_webView, "drag-drop", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, gint x, gint y, guint time, gpointer userData) -> gboolean {
76
        auto& drop = *static_cast<DropTarget*>(userData);
77
        if (drop.m_drop != context) {
78
            gtk_drag_finish(context, FALSE, FALSE, time);
79
            return TRUE;
80
        }
81
        drop.drop({ x, y }, time);
82
        return TRUE;
83
    }), this);
84
85
    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) {
86
        auto& drop = *static_cast<DropTarget*>(userData);
87
        if (drop.m_drop != context)
88
            return;
89
        drop.dataReceived({ x, y }, data, info, time);
90
    }), this);
91
}
92
93
DropTarget::~DropTarget()
94
{
95
    g_signal_handlers_disconnect_by_data(m_webView, this);
96
}
97
98
void DropTarget::accept(unsigned time)
99
{
100
    if (m_leaveTimer.isActive()) {
101
        m_leaveTimer.stop();
102
        leaveTimerFired();
103
    }
104
105
    m_dataRequestCount = 0;
106
    m_selectionData = SelectionData::create();
107
108
    // WebCore needs the selection data to decide, so we need to preload the
109
    // data of targets we support. Once all data requests are done we start
110
    // notifying the web process about the DND events.
111
    auto* list = gdk_drag_context_list_targets(m_drop.get());
112
    static const char* const supportedTargets[] = {
113
        "text/plain;charset=utf-8",
114
        "text/html",
115
        "_NETSCAPE_URL",
116
        "text/uri-list",
117
        "application/vnd.webkitgtk.smartpaste"
118
    };
119
    Vector<GdkAtom, 4> targets;
120
    for (unsigned i = 0; i < G_N_ELEMENTS(supportedTargets); ++i) {
121
        GdkAtom atom = gdk_atom_intern_static_string(supportedTargets[i]);
122
        if (g_list_find(list, atom))
123
            targets.append(atom);
124
        else if (!i) {
125
            atom = gdk_atom_intern_static_string("text/plain");
126
            if (g_list_find(list, atom))
127
                targets.append(atom);
128
        }
129
    }
130
131
    m_dataRequestCount = targets.size();
132
    for (auto* atom : targets)
133
        gtk_drag_get_data(m_webView, m_drop.get(), atom, time);
134
}
135
136
void DropTarget::enter(IntPoint&& position, unsigned time)
137
{
138
    m_position = WTFMove(position);
139
140
    auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_webView));
141
    ASSERT(page);
142
    page->resetCurrentDragInformation();
143
144
    DragData dragData(m_selectionData.get(), *m_position, convertWidgetPointToScreenPoint(m_webView, *m_position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(m_drop.get())));
145
    page->dragEntered(dragData);
146
}
147
148
void DropTarget::update(IntPoint&& position, unsigned time)
149
{
150
    if (m_dataRequestCount || !m_selectionData)
151
        return;
152
153
    m_position = WTFMove(position);
154
155
    auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_webView));
156
    ASSERT(page);
157
158
    DragData dragData(m_selectionData.get(), *m_position, convertWidgetPointToScreenPoint(m_webView, *m_position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(m_drop.get())));
159
    page->dragUpdated(dragData);
160
}
161
162
void DropTarget::dataReceived(IntPoint&& position, GtkSelectionData* data, unsigned info, unsigned time)
163
{
164
    switch (info) {
165
    case DropTargetType::Text: {
166
        GUniquePtr<char> text(reinterpret_cast<char*>(gtk_selection_data_get_text(data)));
167
        m_selectionData->setText(String::fromUTF8(text.get()));
168
        break;
169
    }
170
    case DropTargetType::Markup: {
171
        gint length;
172
        const auto* markupData = gtk_selection_data_get_data_with_length(data, &length);
173
        if (length) {
174
            // If data starts with UTF-16 BOM assume it's UTF-16, otherwise assume UTF-8.
175
            if (length >= 2 && reinterpret_cast<const UChar*>(markupData)[0] == 0xFEFF)
176
                m_selectionData->setMarkup(String(reinterpret_cast<const UChar*>(markupData) + 1, (length / 2) - 1));
177
            else
178
                m_selectionData->setMarkup(String::fromUTF8(markupData, length));
179
        }
180
        break;
181
    }
182
    case DropTargetType::URIList: {
183
        gint length;
184
        const auto* uriListData = gtk_selection_data_get_data_with_length(data, &length);
185
        if (length)
186
            m_selectionData->setURIList(String::fromUTF8(uriListData, length));
187
        break;
188
    }
189
    case DropTargetType::NetscapeURL: {
190
        gint length;
191
        const auto* urlData = gtk_selection_data_get_data_with_length(data, &length);
192
        if (length) {
193
            Vector<String> tokens = String::fromUTF8(urlData, length).split('\n');
194
            URL url({ }, tokens[0]);
195
            if (url.isValid())
196
                m_selectionData->setURL(url, tokens.size() > 1 ? tokens[1] : String());
197
        }
198
        break;
199
    }
200
    case DropTargetType::SmartPaste:
201
        m_selectionData->setCanSmartReplace(true);
202
        break;
203
    }
204
205
    if (--m_dataRequestCount)
206
        return;
207
208
    enter(WTFMove(position), time);
209
}
210
211
void DropTarget::didPerformAction()
212
{
213
    if (!m_drop)
214
        return;
215
216
    auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_webView));
217
    ASSERT(page);
218
219
    auto operation = page->currentDragOperation();
220
    if (operation == m_operation)
221
        return;
222
223
    m_operation = operation;
224
    gdk_drag_status(m_drop.get(), dragOperationToSingleGdkDragAction(m_operation), GDK_CURRENT_TIME);
225
}
226
227
void DropTarget::leaveTimerFired()
228
{
229
    auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_webView));
230
    ASSERT(page);
231
232
    DragData dragData(m_selectionData.get(), *m_position, convertWidgetPointToScreenPoint(m_webView, *m_position), DragOperationNone);
233
    page->dragExited(dragData);
234
    page->resetCurrentDragInformation();
235
236
    m_drop = nullptr;
237
    m_position = WTF::nullopt;
238
    m_selectionData = nullptr;
239
}
240
241
void DropTarget::leave()
242
{
243
    // GTK emits drag-leave before drag-drop, but we need to know whether a drop
244
    // happened to notify the web process about the drag exit.
245
    m_leaveTimer.startOneShot(0_s);
246
}
247
248
void DropTarget::drop(IntPoint&& position, unsigned time)
249
{
250
    if (m_leaveTimer.isActive())
251
        m_leaveTimer.stop();
252
253
    auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_webView));
254
    ASSERT(page);
255
256
    uint32_t flags = 0;
257
    if (gdk_drag_context_get_selected_action(m_drop.get()) == GDK_ACTION_COPY)
258
        flags |= DragApplicationIsCopyKeyDown;
259
    DragData dragData(m_selectionData.get(), position, convertWidgetPointToScreenPoint(m_webView, position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(m_drop.get())), static_cast<DragApplicationFlags>(flags));
260
    page->performDragOperation(dragData, { }, { }, { });
261
    gtk_drag_finish(m_drop.get(), TRUE, FALSE, time);
262
263
    m_drop = nullptr;
264
    m_position = WTF::nullopt;
265
    m_selectionData = nullptr;
266
}
267
268
} // namespace WebKit
269
270
#endif // ENABLE(DRAG_SUPPORT) && !USE(GTK4)
- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp -7 / +5 lines
Lines 330-343 void PageClientImpl::didChangeContentSize(const IntSize& size) a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp_sec1
330
#if ENABLE(DRAG_SUPPORT)
330
#if ENABLE(DRAG_SUPPORT)
331
void PageClientImpl::startDrag(Ref<SelectionData>&& selection, DragOperation dragOperation, RefPtr<ShareableBitmap>&& dragImage)
331
void PageClientImpl::startDrag(Ref<SelectionData>&& selection, DragOperation dragOperation, RefPtr<ShareableBitmap>&& dragImage)
332
{
332
{
333
#if !USE(GTK4)
333
    webkitWebViewBaseStartDrag(WEBKIT_WEB_VIEW_BASE(m_viewWidget), WTFMove(selection), dragOperation, WTFMove(dragImage));
334
    WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(m_viewWidget);
334
}
335
    webkitWebViewBaseDragAndDropHandler(webView).startDrag(WTFMove(selection), dragOperation, WTFMove(dragImage));
336
335
337
    // A drag starting should prevent a double-click from happening. This might
336
void PageClientImpl::didPerformDragControllerAction()
338
    // happen if a drag is followed very quickly by another click (like in the WTR).
337
{
339
    webkitWebViewBaseResetClickCounter(webView);
338
    webkitWebViewBaseDidPerformDragControllerAction(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
340
#endif
341
}
339
}
342
#endif
340
#endif
343
341
- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h +1 lines
Lines 101-106 private: a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h_sec1
101
    RefPtr<ViewSnapshot> takeViewSnapshot(Optional<WebCore::IntRect>&&) override;
101
    RefPtr<ViewSnapshot> takeViewSnapshot(Optional<WebCore::IntRect>&&) override;
102
#if ENABLE(DRAG_SUPPORT)
102
#if ENABLE(DRAG_SUPPORT)
103
    void startDrag(Ref<WebCore::SelectionData>&&, WebCore::DragOperation, RefPtr<ShareableBitmap>&& dragImage) override;
103
    void startDrag(Ref<WebCore::SelectionData>&&, WebCore::DragOperation, RefPtr<ShareableBitmap>&& dragImage) override;
104
    void didPerformDragControllerAction() override;
104
#endif
105
#endif
105
106
106
    void enterAcceleratedCompositingMode(const LayerTreeContext&) override;
107
    void enterAcceleratedCompositingMode(const LayerTreeContext&) override;
- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp -63 / +24 lines
Lines 31-37 a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp_sec1
31
31
32
#include "APIPageConfiguration.h"
32
#include "APIPageConfiguration.h"
33
#include "AcceleratedBackingStore.h"
33
#include "AcceleratedBackingStore.h"
34
#include "DragSource.h"
34
#include "DrawingAreaProxyCoordinatedGraphics.h"
35
#include "DrawingAreaProxyCoordinatedGraphics.h"
36
#include "DropTarget.h"
35
#include "InputMethodFilter.h"
37
#include "InputMethodFilter.h"
36
#include "KeyBindingTranslator.h"
38
#include "KeyBindingTranslator.h"
37
#include "NativeWebKeyboardEvent.h"
39
#include "NativeWebKeyboardEvent.h"
Lines 58-64 a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp_sec2
58
#include <WebCore/GtkUtilities.h>
60
#include <WebCore/GtkUtilities.h>
59
#include <WebCore/GtkVersioning.h>
61
#include <WebCore/GtkVersioning.h>
60
#include <WebCore/NotImplemented.h>
62
#include <WebCore/NotImplemented.h>
61
#include <WebCore/PasteboardHelper.h>
62
#include <WebCore/PlatformDisplay.h>
63
#include <WebCore/PlatformDisplay.h>
63
#include <WebCore/RefPtrCairo.h>
64
#include <WebCore/RefPtrCairo.h>
64
#include <WebCore/Region.h>
65
#include <WebCore/Region.h>
Lines 219-226 struct _WebKitWebViewBasePrivate { a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp_sec3
219
220
220
    std::unique_ptr<AcceleratedBackingStore> acceleratedBackingStore;
221
    std::unique_ptr<AcceleratedBackingStore> acceleratedBackingStore;
221
222
222
#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
223
#if ENABLE(DRAG_SUPPORT)
223
    std::unique_ptr<DragAndDropHandler> dragAndDropHandler;
224
    std::unique_ptr<DragSource> dragSource;
225
    std::unique_ptr<DropTarget> dropTarget;
224
#endif
226
#endif
225
227
226
#if !USE(GTK4)
228
#if !USE(GTK4)
Lines 1554-1580 static gboolean webkitWebViewBaseQueryTooltip(GtkWidget* widget, gint /* x */, g a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp_sec4
1554
    return TRUE;
1556
    return TRUE;
1555
}
1557
}
1556
1558
1557
#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
1558
static void webkitWebViewBaseDragDataGet(GtkWidget* widget, GdkDragContext* context, GtkSelectionData* selectionData, guint info, guint /* time */)
1559
{
1560
    WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1561
    ASSERT(priv->dragAndDropHandler);
1562
    priv->dragAndDropHandler->fillDragData(context, selectionData, info);
1563
}
1564
1565
static void webkitWebViewBaseDragEnd(GtkWidget* widget, GdkDragContext* context)
1566
{
1567
    WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1568
    ASSERT(priv->dragAndDropHandler);
1569
    priv->dragAndDropHandler->finishDrag(context);
1570
}
1571
1572
static void webkitWebViewBaseDragDataReceived(GtkWidget* widget, GdkDragContext* context, gint /* x */, gint /* y */, GtkSelectionData* selectionData, guint info, guint time)
1573
{
1574
    webkitWebViewBaseDragAndDropHandler(WEBKIT_WEB_VIEW_BASE(widget)).dragEntered(context, selectionData, info, time);
1575
}
1576
#endif // ENABLE(DRAG_SUPPORT)
1577
1578
#if !USE(GTK4)
1559
#if !USE(GTK4)
1579
static gboolean webkitWebViewBaseEvent(GtkWidget* widget, GdkEvent* event)
1560
static gboolean webkitWebViewBaseEvent(GtkWidget* widget, GdkEvent* event)
1580
{
1561
{
Lines 1601-1628 static AtkObject* webkitWebViewBaseGetAccessible(GtkWidget* widget) a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp_sec5
1601
    return priv->accessible.get();
1582
    return priv->accessible.get();
1602
}
1583
}
1603
1584
1604
#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
1605
static gboolean webkitWebViewBaseDragMotion(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
1606
{
1607
    webkitWebViewBaseDragAndDropHandler(WEBKIT_WEB_VIEW_BASE(widget)).dragMotion(context, IntPoint(x, y), time);
1608
    return TRUE;
1609
}
1610
1611
static void webkitWebViewBaseDragLeave(GtkWidget* widget, GdkDragContext* context, guint /* time */)
1612
{
1613
    WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1614
    ASSERT(priv->dragAndDropHandler);
1615
    priv->dragAndDropHandler->dragLeave(context);
1616
}
1617
1618
static gboolean webkitWebViewBaseDragDrop(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
1619
{
1620
    WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1621
    ASSERT(priv->dragAndDropHandler);
1622
    return priv->dragAndDropHandler->drop(context, IntPoint(x, y), time);
1623
}
1624
#endif // ENABLE(DRAG_SUPPORT)
1625
1626
#if !USE(GTK4)
1585
#if !USE(GTK4)
1627
static void webkitWebViewBaseHierarchyChanged(GtkWidget* widget, GtkWidget* oldToplevel)
1586
static void webkitWebViewBaseHierarchyChanged(GtkWidget* widget, GtkWidget* oldToplevel)
1628
{
1587
{
Lines 1673-1682 static void webkitWebViewBaseConstructed(GObject* object) a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp_sec6
1673
    priv->pageClient = makeUnique<PageClientImpl>(viewWidget);
1632
    priv->pageClient = makeUnique<PageClientImpl>(viewWidget);
1674
    gtk_container_add(GTK_CONTAINER(viewWidget), priv->keyBindingTranslator.widget());
1633
    gtk_container_add(GTK_CONTAINER(viewWidget), priv->keyBindingTranslator.widget());
1675
1634
1676
#if !USE(GTK4)
1635
#if ENABLE(DRAG_SUPPORT)
1677
    gtk_drag_dest_set(viewWidget, static_cast<GtkDestDefaults>(0), nullptr, 0,
1636
    priv->dropTarget = makeUnique<DropTarget>(viewWidget);
1678
        static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
1679
    gtk_drag_dest_set_target_list(viewWidget, PasteboardHelper::singleton().targetList());
1680
#endif
1637
#endif
1681
1638
1682
#if USE(GTK4)
1639
#if USE(GTK4)
Lines 1747-1760 static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebVie a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp_sec7
1747
    widgetClass->touch_event = webkitWebViewBaseTouchEvent;
1704
    widgetClass->touch_event = webkitWebViewBaseTouchEvent;
1748
#endif
1705
#endif
1749
    widgetClass->query_tooltip = webkitWebViewBaseQueryTooltip;
1706
    widgetClass->query_tooltip = webkitWebViewBaseQueryTooltip;
1750
#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
1751
    widgetClass->drag_end = webkitWebViewBaseDragEnd;
1752
    widgetClass->drag_data_get = webkitWebViewBaseDragDataGet;
1753
    widgetClass->drag_motion = webkitWebViewBaseDragMotion;
1754
    widgetClass->drag_leave = webkitWebViewBaseDragLeave;
1755
    widgetClass->drag_drop = webkitWebViewBaseDragDrop;
1756
    widgetClass->drag_data_received = webkitWebViewBaseDragDataReceived;
1757
#endif // ENABLE(DRAG_SUPPORT)
1758
#if !USE(GTK4)
1707
#if !USE(GTK4)
1759
    widgetClass->event = webkitWebViewBaseEvent;
1708
    widgetClass->event = webkitWebViewBaseEvent;
1760
#endif
1709
#endif
Lines 1829-1841 void webkitWebViewBaseSetTooltipArea(WebKitWebViewBase* webViewBase, const IntRe a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp_sec8
1829
    webViewBase->priv->tooltipArea = tooltipArea;
1778
    webViewBase->priv->tooltipArea = tooltipArea;
1830
}
1779
}
1831
1780
1832
#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
1781
#if ENABLE(DRAG_SUPPORT)
1833
DragAndDropHandler& webkitWebViewBaseDragAndDropHandler(WebKitWebViewBase* webViewBase)
1782
void webkitWebViewBaseStartDrag(WebKitWebViewBase* webViewBase, Ref<SelectionData>&& selectionData, DragOperation dragOperation, RefPtr<ShareableBitmap>&& image)
1834
{
1783
{
1835
    WebKitWebViewBasePrivate* priv = webViewBase->priv;
1784
    WebKitWebViewBasePrivate* priv = webViewBase->priv;
1836
    if (!priv->dragAndDropHandler)
1785
    if (!priv->dragSource)
1837
        priv->dragAndDropHandler = makeUnique<DragAndDropHandler>(*priv->pageProxy);
1786
        priv->dragSource = makeUnique<DragSource>(GTK_WIDGET(webViewBase));
1838
    return *priv->dragAndDropHandler;
1787
1788
    priv->dragSource->begin(WTFMove(selectionData), dragOperation, WTFMove(image));
1789
1790
#if !USE(GTK4)
1791
    // A drag starting should prevent a double-click from happening. This might
1792
    // happen if a drag is followed very quickly by another click (like in the WTR).
1793
    priv->clickCounter.reset();
1794
#endif
1795
}
1796
1797
void webkitWebViewBaseDidPerformDragControllerAction(WebKitWebViewBase* webViewBase)
1798
{
1799
    webViewBase->priv->dropTarget->didPerformAction();
1839
}
1800
}
1840
#endif // ENABLE(DRAG_SUPPORT)
1801
#endif // ENABLE(DRAG_SUPPORT)
1841
1802
- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h -2 / +6 lines
Lines 32-37 a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h_sec1
32
#include "GestureController.h"
32
#include "GestureController.h"
33
#include "InputMethodState.h"
33
#include "InputMethodState.h"
34
#include "SameDocumentNavigationType.h"
34
#include "SameDocumentNavigationType.h"
35
#include "ShareableBitmap.h"
35
#include "ViewGestureController.h"
36
#include "ViewGestureController.h"
36
#include "ViewSnapshotStore.h"
37
#include "ViewSnapshotStore.h"
37
#include "WebContextMenuProxyGtk.h"
38
#include "WebContextMenuProxyGtk.h"
Lines 39-44 a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h_sec2
39
#include "WebKitInputMethodContext.h"
40
#include "WebKitInputMethodContext.h"
40
#include "WebKitWebViewBase.h"
41
#include "WebKitWebViewBase.h"
41
#include "WebPageProxy.h"
42
#include "WebPageProxy.h"
43
#include <WebCore/DragActions.h>
44
#include <WebCore/SelectionData.h>
42
#include <wtf/Optional.h>
45
#include <wtf/Optional.h>
43
46
44
WebKitWebViewBase* webkitWebViewBaseCreate(const API::PageConfiguration&);
47
WebKitWebViewBase* webkitWebViewBaseCreate(const API::PageConfiguration&);
Lines 78-85 void webkitWebViewBaseDidExitWebProcess(WebKitWebViewBase*); a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h_sec3
78
void webkitWebViewBaseDidRelaunchWebProcess(WebKitWebViewBase*);
81
void webkitWebViewBaseDidRelaunchWebProcess(WebKitWebViewBase*);
79
void webkitWebViewBasePageClosed(WebKitWebViewBase*);
82
void webkitWebViewBasePageClosed(WebKitWebViewBase*);
80
83
81
#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
84
#if ENABLE(DRAG_SUPPORT)
82
WebKit::DragAndDropHandler& webkitWebViewBaseDragAndDropHandler(WebKitWebViewBase*);
85
void webkitWebViewBaseStartDrag(WebKitWebViewBase*, Ref<WebCore::SelectionData>&&, WebCore::DragOperation, RefPtr<WebKit::ShareableBitmap>&&);
86
void webkitWebViewBaseDidPerformDragControllerAction(WebKitWebViewBase*);
83
#endif
87
#endif
84
88
85
#if !USE(GTK4)
89
#if !USE(GTK4)
- a/Source/WebKit/UIProcess/PageClient.h +1 lines
Lines 250-255 public: a/Source/WebKit/UIProcess/PageClient.h_sec1
250
    virtual void startDrag(const WebCore::DragItem&, const ShareableBitmap::Handle&) { }
250
    virtual void startDrag(const WebCore::DragItem&, const ShareableBitmap::Handle&) { }
251
#endif
251
#endif
252
    virtual void didPerformDragOperation(bool) { }
252
    virtual void didPerformDragOperation(bool) { }
253
    virtual void didPerformDragControllerAction() { }
253
#endif // ENABLE(DRAG_SUPPORT)
254
#endif // ENABLE(DRAG_SUPPORT)
254
255
255
    virtual void setCursor(const WebCore::Cursor&) = 0;
256
    virtual void setCursor(const WebCore::Cursor&) = 0;
- a/Source/WebKit/UIProcess/WebPageProxy.cpp +1 lines
Lines 2451-2456 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, WebCor a/Source/WebKit/UIProcess/WebPageProxy.cpp_sec1
2451
    m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
2451
    m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
2452
    m_currentDragCaretEditableElementRect = editableElementRect;
2452
    m_currentDragCaretEditableElementRect = editableElementRect;
2453
    setDragCaretRect(insertionRect);
2453
    setDragCaretRect(insertionRect);
2454
    pageClient().didPerformDragControllerAction();
2454
}
2455
}
2455
2456
2456
#if PLATFORM(GTK)
2457
#if PLATFORM(GTK)
- a/Source/WebKit/UIProcess/gtk/DragAndDropHandler.cpp -284 lines
Lines 1-284 a/Source/WebKit/UIProcess/gtk/DragAndDropHandler.cpp_sec1
1
/*
2
 * Copyright (C) 2014 Igalia S.L.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
 * THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "config.h"
27
#include "DragAndDropHandler.h"
28
29
#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)
30
31
#include "WebPageProxy.h"
32
#include <WebCore/DragData.h>
33
#include <WebCore/GRefPtrGtk.h>
34
#include <WebCore/GUniquePtrGtk.h>
35
#include <WebCore/GtkUtilities.h>
36
#include <WebCore/PasteboardHelper.h>
37
#include <wtf/RunLoop.h>
38
39
namespace WebKit {
40
using namespace WebCore;
41
42
DragAndDropHandler::DragAndDropHandler(WebPageProxy& page)
43
    : m_page(page)
44
{
45
}
46
47
DragAndDropHandler::DroppingContext::DroppingContext(GdkDragContext* gdkContext, const IntPoint& position)
48
    : gdkContext(gdkContext)
49
    , lastMotionPosition(position)
50
    , selectionData(SelectionData::create())
51
{
52
}
53
54
static inline GdkDragAction dragOperationToGdkDragActions(DragOperation coreAction)
55
{
56
    GdkDragAction gdkAction = static_cast<GdkDragAction>(0);
57
    if (coreAction == DragOperationNone)
58
        return gdkAction;
59
60
    if (coreAction & DragOperationCopy)
61
        gdkAction = static_cast<GdkDragAction>(GDK_ACTION_COPY | gdkAction);
62
    if (coreAction & DragOperationMove)
63
        gdkAction = static_cast<GdkDragAction>(GDK_ACTION_MOVE | gdkAction);
64
    if (coreAction & DragOperationLink)
65
        gdkAction = static_cast<GdkDragAction>(GDK_ACTION_LINK | gdkAction);
66
    if (coreAction & DragOperationPrivate)
67
        gdkAction = static_cast<GdkDragAction>(GDK_ACTION_PRIVATE | gdkAction);
68
69
    return gdkAction;
70
}
71
72
static inline GdkDragAction dragOperationToSingleGdkDragAction(DragOperation coreAction)
73
{
74
    if (coreAction == DragOperationEvery || coreAction & DragOperationCopy)
75
        return GDK_ACTION_COPY;
76
    if (coreAction & DragOperationMove)
77
        return GDK_ACTION_MOVE;
78
    if (coreAction & DragOperationLink)
79
        return GDK_ACTION_LINK;
80
    if (coreAction & DragOperationPrivate)
81
        return GDK_ACTION_PRIVATE;
82
    return static_cast<GdkDragAction>(0);
83
}
84
85
static inline DragOperation gdkDragActionToDragOperation(GdkDragAction gdkAction)
86
{
87
    // We have no good way to detect DragOperationEvery other than
88
    // to use it when all applicable flags are on.
89
    if (gdkAction & GDK_ACTION_COPY
90
        && gdkAction & GDK_ACTION_MOVE
91
        && gdkAction & GDK_ACTION_LINK
92
        && gdkAction & GDK_ACTION_PRIVATE)
93
        return DragOperationEvery;
94
95
    unsigned action = DragOperationNone;
96
    if (gdkAction & GDK_ACTION_COPY)
97
        action |= DragOperationCopy;
98
    if (gdkAction & GDK_ACTION_MOVE)
99
        action |= DragOperationMove;
100
    if (gdkAction & GDK_ACTION_LINK)
101
        action |= DragOperationLink;
102
    if (gdkAction & GDK_ACTION_PRIVATE)
103
        action |= DragOperationPrivate;
104
    return static_cast<DragOperation>(action);
105
}
106
107
void DragAndDropHandler::startDrag(Ref<SelectionData>&& selection, DragOperation dragOperation, RefPtr<ShareableBitmap>&& dragImage)
108
{
109
    // WebCore::EventHandler does not support more than one DnD operation at the same time for
110
    // a given page, so we should cancel any previous operation whose context we might have
111
    // stored, should we receive a new startDrag event before finishing a previous DnD operation.
112
    if (m_dragContext) {
113
        gtk_drag_cancel(m_dragContext.get());
114
        m_dragContext = nullptr;
115
    }
116
117
    m_draggingSelectionData = WTFMove(selection);
118
    GRefPtr<GtkTargetList> targetList = PasteboardHelper::singleton().targetListForSelectionData(*m_draggingSelectionData);
119
120
    GUniquePtr<GdkEvent> currentEvent(gtk_get_current_event());
121
    GdkDragContext* context = gtk_drag_begin_with_coordinates(m_page.viewWidget(), targetList.get(), dragOperationToGdkDragActions(dragOperation),
122
        GDK_BUTTON_PRIMARY, currentEvent.get(), -1, -1);
123
124
    m_dragContext = context;
125
126
    if (dragImage) {
127
        RefPtr<cairo_surface_t> image(dragImage->createCairoSurface());
128
        // Use the center of the drag image as hotspot.
129
        cairo_surface_set_device_offset(image.get(), -cairo_image_surface_get_width(image.get()) / 2, -cairo_image_surface_get_height(image.get()) / 2);
130
        gtk_drag_set_icon_surface(context, image.get());
131
    } else
132
        gtk_drag_set_icon_default(context);
133
}
134
135
void DragAndDropHandler::fillDragData(GdkDragContext* context, GtkSelectionData* selectionData, unsigned info)
136
{
137
    // This can happen when attempting to call finish drag from webkitWebViewBaseDragDataGet()
138
    // for a obsolete DnD operation that got previously cancelled in startDrag().
139
    if (m_dragContext.get() != context)
140
        return;
141
142
    ASSERT(m_draggingSelectionData);
143
    PasteboardHelper::singleton().fillSelectionData(*m_draggingSelectionData, info, selectionData);
144
}
145
146
void DragAndDropHandler::finishDrag(GdkDragContext* context)
147
{
148
    // This can happen when attempting to call finish drag from webkitWebViewBaseDragEnd()
149
    // for a obsolete DnD operation that got previously cancelled in startDrag().
150
    if (m_dragContext.get() != context)
151
        return;
152
153
    if (!m_draggingSelectionData)
154
        return;
155
156
    m_dragContext = nullptr;
157
    m_draggingSelectionData = nullptr;
158
159
    GdkDevice* device = gdk_drag_context_get_device(context);
160
    int x = 0, y = 0;
161
    gdk_device_get_window_at_position(device, &x, &y);
162
    int xRoot = 0, yRoot = 0;
163
    gdk_device_get_position(device, nullptr, &xRoot, &yRoot);
164
    m_page.dragEnded(IntPoint(x, y), IntPoint(xRoot, yRoot), gdkDragActionToDragOperation(gdk_drag_context_get_selected_action(context)));
165
}
166
167
SelectionData* DragAndDropHandler::dropDataSelection(GdkDragContext* context, GtkSelectionData* selectionData, unsigned info, IntPoint& position)
168
{
169
    DroppingContext* droppingContext = m_droppingContexts.get(context);
170
    if (!droppingContext)
171
        return nullptr;
172
173
    droppingContext->pendingDataRequests--;
174
    PasteboardHelper::singleton().fillSelectionData(selectionData, info, droppingContext->selectionData);
175
    if (droppingContext->pendingDataRequests)
176
        return nullptr;
177
178
    // The coordinates passed to drag-data-received signal are sometimes
179
    // inaccurate in WTR, so use the coordinates of the last motion event.
180
    position = droppingContext->lastMotionPosition;
181
182
    // If there are no more pending requests, start sending dragging data to WebCore.
183
    return droppingContext->selectionData.ptr();
184
}
185
186
void DragAndDropHandler::dragEntered(GdkDragContext* context, GtkSelectionData* selectionData, unsigned info, unsigned time)
187
{
188
    IntPoint position;
189
    auto* selection = dropDataSelection(context, selectionData, info, position);
190
    if (!selection)
191
        return;
192
193
    DragData dragData(selection, position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
194
    m_page.resetCurrentDragInformation();
195
    m_page.dragEntered(dragData);
196
    DragOperation operation = m_page.currentDragOperation();
197
    gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
198
}
199
200
SelectionData* DragAndDropHandler::dragDataSelection(GdkDragContext* context, const IntPoint& position, unsigned time)
201
{
202
    std::unique_ptr<DroppingContext>& droppingContext = m_droppingContexts.add(context, nullptr).iterator->value;
203
    if (!droppingContext) {
204
        GtkWidget* widget = m_page.viewWidget();
205
        droppingContext = makeUnique<DroppingContext>(context, position);
206
        Vector<GdkAtom> acceptableTargets(PasteboardHelper::singleton().dropAtomsForContext(widget, droppingContext->gdkContext));
207
        droppingContext->pendingDataRequests = acceptableTargets.size();
208
        for (auto& target : acceptableTargets)
209
            gtk_drag_get_data(widget, droppingContext->gdkContext, target, time);
210
    } else
211
        droppingContext->lastMotionPosition = position;
212
213
    // Don't send any drag information to WebCore until we've retrieved all the data for this drag operation.
214
    // Otherwise we'd have to block to wait for the drag's data.
215
    if (droppingContext->pendingDataRequests > 0)
216
        return nullptr;
217
218
    return droppingContext->selectionData.ptr();
219
}
220
221
void DragAndDropHandler::dragMotion(GdkDragContext* context, const IntPoint& position, unsigned time)
222
{
223
    auto* selection = dragDataSelection(context, position, time);
224
    if (!selection)
225
        return;
226
227
    DragData dragData(selection, position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
228
    m_page.dragUpdated(dragData);
229
    DragOperation operation = m_page.currentDragOperation();
230
    gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
231
}
232
233
void DragAndDropHandler::dragLeave(GdkDragContext* context)
234
{
235
    DroppingContext* droppingContext = m_droppingContexts.get(context);
236
    if (!droppingContext)
237
        return;
238
239
    // During a drop GTK+ will fire a drag-leave signal right before firing
240
    // the drag-drop signal. We want the actions for drag-leave to happen after
241
    // those for drag-drop, so schedule them to happen asynchronously here.
242
    RunLoop::main().dispatch([this, context, droppingContext]() {
243
        auto it = m_droppingContexts.find(context);
244
        if (it == m_droppingContexts.end())
245
            return;
246
247
        // If the view doesn't know about the drag yet (there are still pending data requests),
248
        // don't update it with information about the drag.
249
        if (droppingContext->pendingDataRequests)
250
            return;
251
252
        if (!droppingContext->dropHappened) {
253
            // Don't call dragExited if we have just received a drag-drop signal. This
254
            // happens in the case of a successful drop onto the view.
255
            const IntPoint& position = droppingContext->lastMotionPosition;
256
            DragData dragData(droppingContext->selectionData.ptr(), position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), DragOperationNone);
257
            m_page.dragExited(dragData);
258
            m_page.resetCurrentDragInformation();
259
        }
260
261
        m_droppingContexts.remove(it);
262
    });
263
}
264
265
bool DragAndDropHandler::drop(GdkDragContext* context, const IntPoint& position, unsigned time)
266
{
267
    DroppingContext* droppingContext = m_droppingContexts.get(context);
268
    if (!droppingContext)
269
        return false;
270
271
    droppingContext->dropHappened = true;
272
273
    uint32_t flags = 0;
274
    if (gdk_drag_context_get_selected_action(context) == GDK_ACTION_COPY)
275
        flags |= WebCore::DragApplicationIsCopyKeyDown;
276
    DragData dragData(droppingContext->selectionData.ptr(), position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)), static_cast<WebCore::DragApplicationFlags>(flags));
277
    m_page.performDragOperation(dragData, String(), { }, { });
278
    gtk_drag_finish(context, TRUE, FALSE, time);
279
    return true;
280
}
281
282
} // namespace WebKit
283
284
#endif // ENABLE(DRAG_SUPPORT)
- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp -1 / +1 lines
Lines 3947-3953 void WebPage::performDragControllerAction(DragControllerAction action, const Int a/Source/WebKit/WebProcess/WebPage/WebPage.cpp_sec1
3947
        return;
3947
        return;
3948
    }
3948
    }
3949
    case DragControllerAction::Updated: {
3949
    case DragControllerAction::Updated: {
3950
        DragOperation resolvedDragOperation = m_page->dragController().dragEntered(dragData);
3950
        DragOperation resolvedDragOperation = m_page->dragController().dragUpdated(dragData);
3951
        send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().dragHandlingMethod(), m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted(), { }, { }));
3951
        send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().dragHandlingMethod(), m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted(), { }, { }));
3952
        return;
3952
        return;
3953
    }
3953
    }
- a/Source/WebKit/WebProcess/WebPage/gtk/WebPageGtk.cpp -1 lines
Lines 42-48 a/Source/WebKit/WebProcess/WebPage/gtk/WebPageGtk.cpp_sec1
42
#include <WebCore/KeyboardEvent.h>
42
#include <WebCore/KeyboardEvent.h>
43
#include <WebCore/NotImplemented.h>
43
#include <WebCore/NotImplemented.h>
44
#include <WebCore/Page.h>
44
#include <WebCore/Page.h>
45
#include <WebCore/PasteboardHelper.h>
46
#include <WebCore/PlatformKeyboardEvent.h>
45
#include <WebCore/PlatformKeyboardEvent.h>
47
#include <WebCore/RenderTheme.h>
46
#include <WebCore/RenderTheme.h>
48
#include <WebCore/Settings.h>
47
#include <WebCore/Settings.h>

Return to Bug 211723