[GTK] Configures but fails to link with ENABLE_OPENGL=OFF
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / gtk / WebKitWebViewBase.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Portions Copyright (c) 2010 Motorola Mobility, Inc.  All rights reserved.
4  * Copyright (C) 2011 Igalia S.L.
5  * Copyright (C) 2013 Gustavo Noronha Silva <gns@gnome.org>.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "WebKitWebViewBase.h"
31
32 #include "APIPageConfiguration.h"
33 #include "AcceleratedBackingStore.h"
34 #include "DrawingAreaProxyImpl.h"
35 #include "InputMethodFilter.h"
36 #include "KeyBindingTranslator.h"
37 #include "NativeWebKeyboardEvent.h"
38 #include "NativeWebMouseEvent.h"
39 #include "NativeWebWheelEvent.h"
40 #include "PageClientImpl.h"
41 #include "ViewState.h"
42 #include "WebEventFactory.h"
43 #include "WebFullScreenClientGtk.h"
44 #include "WebInspectorProxy.h"
45 #include "WebKit2Initialize.h"
46 #include "WebKitAuthenticationDialog.h"
47 #include "WebKitPrivate.h"
48 #include "WebKitWebViewBaseAccessible.h"
49 #include "WebKitWebViewBasePrivate.h"
50 #include "WebPageGroup.h"
51 #include "WebPageProxy.h"
52 #include "WebPreferences.h"
53 #include "WebProcessPool.h"
54 #include "WebUserContentControllerProxy.h"
55 #include <WebCore/CairoUtilities.h>
56 #include <WebCore/GUniquePtrGtk.h>
57 #include <WebCore/GtkUtilities.h>
58 #include <WebCore/GtkVersioning.h>
59 #include <WebCore/NotImplemented.h>
60 #include <WebCore/PasteboardHelper.h>
61 #include <WebCore/PlatformDisplay.h>
62 #include <WebCore/RefPtrCairo.h>
63 #include <WebCore/Region.h>
64 #include <gdk/gdk.h>
65 #include <gdk/gdkkeysyms.h>
66 #include <glib/gi18n-lib.h>
67 #include <memory>
68 #include <wtf/HashMap.h>
69 #include <wtf/glib/GRefPtr.h>
70 #include <wtf/text/CString.h>
71
72 #if ENABLE(FULLSCREEN_API)
73 #include "WebFullScreenManagerProxy.h"
74 #endif
75
76 #if PLATFORM(X11)
77 #include <gdk/gdkx.h>
78 #endif
79
80 // gtk_widget_get_scale_factor() appeared in GTK 3.10, but we also need
81 // to make sure we have cairo new enough to support cairo_surface_set_device_scale
82 #define HAVE_GTK_SCALE_FACTOR HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE && GTK_CHECK_VERSION(3, 10, 0)
83
84 using namespace WebKit;
85 using namespace WebCore;
86
87 struct ClickCounter {
88 public:
89     void reset()
90     {
91         currentClickCount = 0;
92         previousClickPoint = IntPoint();
93         previousClickTime = 0;
94         previousClickButton = 0;
95     }
96
97     int currentClickCountForGdkButtonEvent(GdkEventButton* buttonEvent)
98     {
99         GdkEvent* event = reinterpret_cast<GdkEvent*>(buttonEvent);
100         int doubleClickDistance = 250;
101         int doubleClickTime = 5;
102         g_object_get(gtk_settings_get_for_screen(gdk_event_get_screen(event)),
103             "gtk-double-click-distance", &doubleClickDistance, "gtk-double-click-time", &doubleClickTime, nullptr);
104
105         // GTK+ only counts up to triple clicks, but WebCore wants to know about
106         // quadruple clicks, quintuple clicks, ad infinitum. Here, we replicate the
107         // GDK logic for counting clicks.
108         guint32 eventTime = gdk_event_get_time(event);
109         if (!eventTime) {
110             // Real events always have a non-zero time, but events synthesized
111             // by the WTR do not and we must calculate a time manually. This time
112             // is not calculated in the WTR, because GTK+ does not work well with
113             // anything other than GDK_CURRENT_TIME on synthesized events.
114             GTimeVal timeValue;
115             g_get_current_time(&timeValue);
116             eventTime = (timeValue.tv_sec * 1000) + (timeValue.tv_usec / 1000);
117         }
118
119         if ((event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
120             || ((std::abs(buttonEvent->x - previousClickPoint.x()) < doubleClickDistance)
121                 && (std::abs(buttonEvent->y - previousClickPoint.y()) < doubleClickDistance)
122                 && (eventTime - previousClickTime < static_cast<unsigned>(doubleClickTime))
123                 && (buttonEvent->button == previousClickButton)))
124             currentClickCount++;
125         else
126             currentClickCount = 1;
127
128         double x, y;
129         gdk_event_get_coords(event, &x, &y);
130         previousClickPoint = IntPoint(x, y);
131         previousClickButton = buttonEvent->button;
132         previousClickTime = eventTime;
133
134         return currentClickCount;
135     }
136
137 private:
138     int currentClickCount;
139     IntPoint previousClickPoint;
140     unsigned previousClickButton;
141     int previousClickTime;
142 };
143
144 typedef HashMap<GtkWidget*, IntRect> WebKitWebViewChildrenMap;
145 typedef HashMap<uint32_t, GUniquePtr<GdkEvent>> TouchEventsMap;
146
147 struct _WebKitWebViewBasePrivate {
148     _WebKitWebViewBasePrivate()
149         : updateViewStateTimer(RunLoop::main(), this, &_WebKitWebViewBasePrivate::updateViewStateTimerFired)
150     {
151     }
152
153     void updateViewStateTimerFired()
154     {
155         if (!pageProxy)
156             return;
157         pageProxy->viewStateDidChange(viewStateFlagsToUpdate);
158         viewStateFlagsToUpdate = ViewState::NoFlags;
159     }
160
161     WebKitWebViewChildrenMap children;
162     std::unique_ptr<PageClientImpl> pageClient;
163     RefPtr<WebPageProxy> pageProxy;
164     bool shouldForwardNextKeyEvent;
165     bool shouldForwardNextWheelEvent;
166     ClickCounter clickCounter;
167     CString tooltipText;
168     IntRect tooltipArea;
169     GRefPtr<AtkObject> accessible;
170     GtkWidget* authenticationDialog;
171     GtkWidget* inspectorView;
172     AttachmentSide inspectorAttachmentSide;
173     unsigned inspectorViewSize;
174     GUniquePtr<GdkEvent> contextMenuEvent;
175     WebContextMenuProxyGtk* activeContextMenuProxy;
176     InputMethodFilter inputMethodFilter;
177     KeyBindingTranslator keyBindingTranslator;
178     TouchEventsMap touchEvents;
179     IntSize contentsSize;
180
181     GtkWindow* toplevelOnScreenWindow;
182     unsigned long toplevelFocusInEventID;
183     unsigned long toplevelFocusOutEventID;
184     unsigned long toplevelWindowStateEventID;
185     unsigned long toplevelWindowRealizedID;
186
187     // View State.
188     ViewState::Flags viewState;
189     ViewState::Flags viewStateFlagsToUpdate;
190     RunLoop::Timer<WebKitWebViewBasePrivate> updateViewStateTimer;
191
192     WebKitWebViewBaseDownloadRequestHandler downloadHandler;
193
194 #if ENABLE(FULLSCREEN_API)
195     bool fullScreenModeActive;
196     WebFullScreenClientGtk fullScreenClient;
197     GRefPtr<GDBusProxy> screenSaverProxy;
198     GRefPtr<GCancellable> screenSaverInhibitCancellable;
199     unsigned screenSaverCookie;
200 #endif
201
202     std::unique_ptr<AcceleratedBackingStore> acceleratedBackingStore;
203
204 #if ENABLE(DRAG_SUPPORT)
205     std::unique_ptr<DragAndDropHandler> dragAndDropHandler;
206 #endif
207
208 #if HAVE(GTK_GESTURES)
209     std::unique_ptr<GestureController> gestureController;
210 #endif
211 };
212
213 WEBKIT_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER)
214
215 static void webkitWebViewBaseScheduleUpdateViewState(WebKitWebViewBase* webViewBase, ViewState::Flags flagsToUpdate)
216 {
217     WebKitWebViewBasePrivate* priv = webViewBase->priv;
218     priv->viewStateFlagsToUpdate |= flagsToUpdate;
219     if (priv->updateViewStateTimer.isActive())
220         return;
221
222     priv->updateViewStateTimer.startOneShot(0);
223 }
224
225 static gboolean toplevelWindowFocusInEvent(GtkWidget* widget, GdkEventFocus*, WebKitWebViewBase* webViewBase)
226 {
227     // Spurious focus in events can occur when the window is hidden.
228     if (!gtk_widget_get_visible(widget))
229         return FALSE;
230
231     WebKitWebViewBasePrivate* priv = webViewBase->priv;
232     if (priv->viewState & ViewState::WindowIsActive)
233         return FALSE;
234
235     priv->viewState |= ViewState::WindowIsActive;
236     webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::WindowIsActive);
237
238     return FALSE;
239 }
240
241 static gboolean toplevelWindowFocusOutEvent(GtkWidget*, GdkEventFocus*, WebKitWebViewBase* webViewBase)
242 {
243     WebKitWebViewBasePrivate* priv = webViewBase->priv;
244     if (!(priv->viewState & ViewState::WindowIsActive))
245         return FALSE;
246
247     priv->viewState &= ~ViewState::WindowIsActive;
248     webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::WindowIsActive);
249
250     return FALSE;
251 }
252
253 static gboolean toplevelWindowStateEvent(GtkWidget*, GdkEventWindowState* event, WebKitWebViewBase* webViewBase)
254 {
255     WebKitWebViewBasePrivate* priv = webViewBase->priv;
256     if (!(event->changed_mask & GDK_WINDOW_STATE_ICONIFIED))
257         return FALSE;
258
259     bool visible = !(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED);
260     if ((visible && priv->viewState & ViewState::IsVisible) || (!visible && !(priv->viewState & ViewState::IsVisible)))
261         return FALSE;
262
263     if (visible)
264         priv->viewState |= ViewState::IsVisible;
265     else
266         priv->viewState &= ~ViewState::IsVisible;
267     webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::IsVisible);
268
269     return FALSE;
270 }
271
272 static void toplevelWindowRealized(WebKitWebViewBase* webViewBase)
273 {
274     gtk_widget_realize(GTK_WIDGET(webViewBase));
275
276     WebKitWebViewBasePrivate* priv = webViewBase->priv;
277     if (priv->toplevelWindowRealizedID) {
278         g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelWindowRealizedID);
279         priv->toplevelWindowRealizedID = 0;
280     }
281 }
282
283 static void webkitWebViewBaseSetToplevelOnScreenWindow(WebKitWebViewBase* webViewBase, GtkWindow* window)
284 {
285     WebKitWebViewBasePrivate* priv = webViewBase->priv;
286     if (priv->toplevelOnScreenWindow == window)
287         return;
288
289     if (priv->toplevelFocusInEventID) {
290         g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelFocusInEventID);
291         priv->toplevelFocusInEventID = 0;
292     }
293     if (priv->toplevelFocusOutEventID) {
294         g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelFocusOutEventID);
295         priv->toplevelFocusOutEventID = 0;
296     }
297     if (priv->toplevelWindowStateEventID) {
298         g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelWindowStateEventID);
299         priv->toplevelWindowStateEventID = 0;
300     }
301     if (priv->toplevelWindowRealizedID) {
302         g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelWindowRealizedID);
303         priv->toplevelWindowRealizedID = 0;
304     }
305
306     priv->toplevelOnScreenWindow = window;
307
308     if (!priv->toplevelOnScreenWindow) {
309         ViewState::Flags flagsToUpdate = 0;
310         if (priv->viewState & ViewState::IsInWindow) {
311             priv->viewState &= ~ViewState::IsInWindow;
312             flagsToUpdate |= ViewState::IsInWindow;
313         }
314         if (priv->viewState & ViewState::WindowIsActive) {
315             priv->viewState &= ~ViewState::WindowIsActive;
316             flagsToUpdate |= ViewState::IsInWindow;
317         }
318         if (flagsToUpdate)
319             webkitWebViewBaseScheduleUpdateViewState(webViewBase, flagsToUpdate);
320
321         return;
322     }
323
324     priv->toplevelFocusInEventID =
325         g_signal_connect(priv->toplevelOnScreenWindow, "focus-in-event",
326                          G_CALLBACK(toplevelWindowFocusInEvent), webViewBase);
327     priv->toplevelFocusOutEventID =
328         g_signal_connect(priv->toplevelOnScreenWindow, "focus-out-event",
329                          G_CALLBACK(toplevelWindowFocusOutEvent), webViewBase);
330     priv->toplevelWindowStateEventID =
331         g_signal_connect(priv->toplevelOnScreenWindow, "window-state-event", G_CALLBACK(toplevelWindowStateEvent), webViewBase);
332
333     if (gtk_widget_get_realized(GTK_WIDGET(window)))
334         gtk_widget_realize(GTK_WIDGET(webViewBase));
335     else
336         priv->toplevelWindowRealizedID = g_signal_connect_swapped(window, "realize", G_CALLBACK(toplevelWindowRealized), webViewBase);
337 }
338
339 static void webkitWebViewBaseRealize(GtkWidget* widget)
340 {
341     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(widget);
342     WebKitWebViewBasePrivate* priv = webView->priv;
343
344     gtk_widget_set_realized(widget, TRUE);
345
346     GtkAllocation allocation;
347     gtk_widget_get_allocation(widget, &allocation);
348
349     GdkWindowAttr attributes;
350     attributes.window_type = GDK_WINDOW_CHILD;
351     attributes.x = allocation.x;
352     attributes.y = allocation.y;
353     attributes.width = allocation.width;
354     attributes.height = allocation.height;
355     attributes.wclass = GDK_INPUT_OUTPUT;
356     attributes.visual = gtk_widget_get_visual(widget);
357     attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK
358         | GDK_EXPOSURE_MASK
359         | GDK_BUTTON_PRESS_MASK
360         | GDK_BUTTON_RELEASE_MASK
361         | GDK_SCROLL_MASK
362         | GDK_SMOOTH_SCROLL_MASK
363         | GDK_POINTER_MOTION_MASK
364         | GDK_ENTER_NOTIFY_MASK
365         | GDK_LEAVE_NOTIFY_MASK
366         | GDK_KEY_PRESS_MASK
367         | GDK_KEY_RELEASE_MASK
368         | GDK_BUTTON_MOTION_MASK
369         | GDK_BUTTON1_MOTION_MASK
370         | GDK_BUTTON2_MOTION_MASK
371         | GDK_BUTTON3_MOTION_MASK
372         | GDK_TOUCH_MASK;
373
374     gint attributesMask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
375
376     GdkWindow* window = gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, attributesMask);
377     gtk_widget_set_window(widget, window);
378     gdk_window_set_user_data(window, widget);
379
380 #if USE(TEXTURE_MAPPER_GL) && PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
381     if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11) {
382         if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea()))
383             drawingArea->setNativeSurfaceHandleForCompositing(GDK_WINDOW_XID(window));
384     }
385 #endif
386
387     gtk_style_context_set_background(gtk_widget_get_style_context(widget), window);
388
389     gtk_im_context_set_client_window(priv->inputMethodFilter.context(), window);
390 }
391
392 static void webkitWebViewBaseUnrealize(GtkWidget* widget)
393 {
394     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(widget);
395 #if USE(TEXTURE_MAPPER_GL) && PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
396     if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11) {
397         if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(webView->priv->pageProxy->drawingArea()))
398             drawingArea->destroyNativeSurfaceHandleForCompositing();
399     }
400 #endif
401     gtk_im_context_set_client_window(webView->priv->inputMethodFilter.context(), nullptr);
402
403     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->unrealize(widget);
404 }
405
406 static bool webkitWebViewChildIsInternalWidget(WebKitWebViewBase* webViewBase, GtkWidget* widget)
407 {
408     WebKitWebViewBasePrivate* priv = webViewBase->priv;
409     return widget == priv->inspectorView || widget == priv->authenticationDialog;
410 }
411
412 static void webkitWebViewBaseContainerAdd(GtkContainer* container, GtkWidget* widget)
413 {
414     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
415     WebKitWebViewBasePrivate* priv = webView->priv;
416
417     // Internal widgets like the web inspector and authentication dialog have custom
418     // allocations so we don't need to add them to our list of children.
419     if (!webkitWebViewChildIsInternalWidget(webView, widget)) {
420         GtkAllocation childAllocation;
421         gtk_widget_get_allocation(widget, &childAllocation);
422         priv->children.set(widget, childAllocation);
423     }
424
425     gtk_widget_set_parent(widget, GTK_WIDGET(container));
426 }
427
428 void webkitWebViewBaseAddAuthenticationDialog(WebKitWebViewBase* webViewBase, GtkWidget* dialog)
429 {
430     WebKitWebViewBasePrivate* priv = webViewBase->priv;
431     priv->authenticationDialog = dialog;
432     gtk_container_add(GTK_CONTAINER(webViewBase), dialog);
433     gtk_widget_show(dialog);
434
435     // We need to draw the shadow over the widget.
436     gtk_widget_queue_draw(GTK_WIDGET(webViewBase));
437 }
438
439 void webkitWebViewBaseAddWebInspector(WebKitWebViewBase* webViewBase, GtkWidget* inspector, AttachmentSide attachmentSide)
440 {
441     if (webViewBase->priv->inspectorView == inspector && webViewBase->priv->inspectorAttachmentSide == attachmentSide)
442         return;
443
444     webViewBase->priv->inspectorAttachmentSide = attachmentSide;
445
446     if (webViewBase->priv->inspectorView == inspector) {
447         gtk_widget_queue_resize(GTK_WIDGET(webViewBase));
448         return;
449     }
450
451     webViewBase->priv->inspectorView = inspector;
452     gtk_container_add(GTK_CONTAINER(webViewBase), inspector);
453 }
454
455 static void webkitWebViewBaseContainerRemove(GtkContainer* container, GtkWidget* widget)
456 {
457     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
458     WebKitWebViewBasePrivate* priv = webView->priv;
459     GtkWidget* widgetContainer = GTK_WIDGET(container);
460
461     gboolean wasVisible = gtk_widget_get_visible(widget);
462     gtk_widget_unparent(widget);
463
464     if (priv->inspectorView == widget) {
465         priv->inspectorView = 0;
466         priv->inspectorViewSize = 0;
467     } else if (priv->authenticationDialog == widget) {
468         priv->authenticationDialog = 0;
469     } else {
470         ASSERT(priv->children.contains(widget));
471         priv->children.remove(widget);
472     }
473     if (wasVisible && gtk_widget_get_visible(widgetContainer))
474         gtk_widget_queue_resize(widgetContainer);
475 }
476
477 static void webkitWebViewBaseContainerForall(GtkContainer* container, gboolean includeInternals, GtkCallback callback, gpointer callbackData)
478 {
479     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
480     WebKitWebViewBasePrivate* priv = webView->priv;
481
482     Vector<GtkWidget*> children;
483     copyKeysToVector(priv->children, children);
484     for (const auto& child : children) {
485         if (priv->children.contains(child))
486             (*callback)(child, callbackData);
487     }
488
489     if (includeInternals && priv->inspectorView)
490         (*callback)(priv->inspectorView, callbackData);
491
492     if (includeInternals && priv->authenticationDialog)
493         (*callback)(priv->authenticationDialog, callbackData);
494 }
495
496 void webkitWebViewBaseChildMoveResize(WebKitWebViewBase* webView, GtkWidget* child, const IntRect& childRect)
497 {
498     const IntRect& geometry = webView->priv->children.get(child);
499     if (geometry == childRect)
500         return;
501
502     webView->priv->children.set(child, childRect);
503     gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webView));
504 }
505
506 static void webkitWebViewBaseDispose(GObject* gobject)
507 {
508     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(gobject);
509     g_cancellable_cancel(webView->priv->screenSaverInhibitCancellable.get());
510     webkitWebViewBaseSetToplevelOnScreenWindow(webView, nullptr);
511     webView->priv->pageProxy->close();
512     webView->priv->acceleratedBackingStore = nullptr;
513     G_OBJECT_CLASS(webkit_web_view_base_parent_class)->dispose(gobject);
514 }
515
516 static void webkitWebViewBaseConstructed(GObject* object)
517 {
518     G_OBJECT_CLASS(webkit_web_view_base_parent_class)->constructed(object);
519
520     GtkWidget* viewWidget = GTK_WIDGET(object);
521     gtk_widget_set_can_focus(viewWidget, TRUE);
522     gtk_drag_dest_set(viewWidget, static_cast<GtkDestDefaults>(0), nullptr, 0,
523         static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
524     gtk_drag_dest_set_target_list(viewWidget, PasteboardHelper::singleton().targetList());
525
526     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(object)->priv;
527     priv->pageClient = std::make_unique<PageClientImpl>(viewWidget);
528     priv->authenticationDialog = 0;
529 }
530
531 static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr)
532 {
533     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
534     DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(webViewBase->priv->pageProxy->drawingArea());
535     if (!drawingArea)
536         return FALSE;
537
538     GdkRectangle clipRect;
539     if (!gdk_cairo_get_clip_rectangle(cr, &clipRect))
540         return FALSE;
541
542     if (webViewBase->priv->acceleratedBackingStore && drawingArea->isInAcceleratedCompositingMode())
543         webViewBase->priv->acceleratedBackingStore->paint(cr, clipRect);
544     else {
545         WebCore::Region unpaintedRegion; // This is simply unused.
546         drawingArea->paint(cr, clipRect, unpaintedRegion);
547     }
548
549     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->draw(widget, cr);
550
551     return FALSE;
552 }
553
554 static void webkitWebViewBaseChildAllocate(GtkWidget* child, gpointer userData)
555 {
556     if (!gtk_widget_get_visible(child))
557         return;
558
559     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(userData);
560     WebKitWebViewBasePrivate* priv = webViewBase->priv;
561     const IntRect& geometry = priv->children.get(child);
562     if (geometry.isEmpty())
563         return;
564
565     GtkAllocation childAllocation = geometry;
566     gtk_widget_size_allocate(child, &childAllocation);
567     priv->children.set(child, IntRect());
568 }
569
570 static void webkitWebViewBaseSizeAllocate(GtkWidget* widget, GtkAllocation* allocation)
571 {
572     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->size_allocate(widget, allocation);
573
574     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
575     gtk_container_foreach(GTK_CONTAINER(webViewBase), webkitWebViewBaseChildAllocate, webViewBase);
576
577     IntRect viewRect(allocation->x, allocation->y, allocation->width, allocation->height);
578     WebKitWebViewBasePrivate* priv = webViewBase->priv;
579     if (priv->inspectorView) {
580         GtkAllocation childAllocation = viewRect;
581
582         if (priv->inspectorAttachmentSide == AttachmentSide::Bottom) {
583             int inspectorViewHeight = std::min(static_cast<int>(priv->inspectorViewSize), allocation->height);
584             childAllocation.x = 0;
585             childAllocation.y = allocation->height - inspectorViewHeight;
586             childAllocation.height = inspectorViewHeight;
587             viewRect.setHeight(std::max(allocation->height - inspectorViewHeight, 1));
588         } else {
589             int inspectorViewWidth = std::min(static_cast<int>(priv->inspectorViewSize), allocation->width);
590             childAllocation.y = 0;
591             childAllocation.x = allocation->width - inspectorViewWidth;
592             childAllocation.width = inspectorViewWidth;
593             viewRect.setWidth(std::max(allocation->width - inspectorViewWidth, 1));
594         }
595
596         gtk_widget_size_allocate(priv->inspectorView, &childAllocation);
597     }
598
599     // The authentication dialog is centered in the view rect, which means that it
600     // never overlaps the web inspector. Thus, we need to calculate the allocation here
601     // after calculating the inspector allocation.
602     if (priv->authenticationDialog) {
603         GtkRequisition minimumSize;
604         gtk_widget_get_preferred_size(priv->authenticationDialog, &minimumSize, nullptr);
605
606         GtkAllocation childAllocation = { 0, 0, std::max(minimumSize.width, viewRect.width()), std::max(minimumSize.height, viewRect.height()) };
607         gtk_widget_size_allocate(priv->authenticationDialog, &childAllocation);
608     }
609
610     if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea()))
611         drawingArea->setSize(viewRect.size(), IntSize(), IntSize());
612 }
613
614 static void webkitWebViewBaseGetPreferredWidth(GtkWidget* widget, gint* minimumSize, gint* naturalSize)
615 {
616     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
617     *minimumSize = 0;
618     *naturalSize = priv->contentsSize.width();
619 }
620
621 static void webkitWebViewBaseGetPreferredHeight(GtkWidget* widget, gint* minimumSize, gint* naturalSize)
622 {
623     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
624     *minimumSize = 0;
625     *naturalSize = priv->contentsSize.height();
626 }
627
628 static void webkitWebViewBaseMap(GtkWidget* widget)
629 {
630     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->map(widget);
631
632     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
633     WebKitWebViewBasePrivate* priv = webViewBase->priv;
634     ViewState::Flags flagsToUpdate = 0;
635     if (!(priv->viewState & ViewState::IsVisible))
636         flagsToUpdate |= ViewState::IsVisible;
637     if (priv->toplevelOnScreenWindow) {
638         if (!(priv->viewState & ViewState::IsInWindow))
639             flagsToUpdate |= ViewState::IsInWindow;
640         if (gtk_window_is_active(GTK_WINDOW(priv->toplevelOnScreenWindow)) && !(priv->viewState & ViewState::WindowIsActive))
641             flagsToUpdate |= ViewState::WindowIsActive;
642     }
643     if (!flagsToUpdate)
644         return;
645
646     priv->viewState |= flagsToUpdate;
647     webkitWebViewBaseScheduleUpdateViewState(webViewBase, flagsToUpdate);
648 }
649
650 static void webkitWebViewBaseUnmap(GtkWidget* widget)
651 {
652     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->unmap(widget);
653
654     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
655     WebKitWebViewBasePrivate* priv = webViewBase->priv;
656     if (!(priv->viewState & ViewState::IsVisible))
657         return;
658
659     priv->viewState &= ~ViewState::IsVisible;
660     webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::IsVisible);
661 }
662
663 static gboolean webkitWebViewBaseFocusInEvent(GtkWidget* widget, GdkEventFocus* event)
664 {
665     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
666     webkitWebViewBaseSetFocus(webViewBase, true);
667     webViewBase->priv->inputMethodFilter.notifyFocusedIn();
668
669     return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus_in_event(widget, event);
670 }
671
672 static gboolean webkitWebViewBaseFocusOutEvent(GtkWidget* widget, GdkEventFocus* event)
673 {
674     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
675     webkitWebViewBaseSetFocus(webViewBase, false);
676     webViewBase->priv->inputMethodFilter.notifyFocusedOut();
677
678     return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus_out_event(widget, event);
679 }
680
681 static gboolean webkitWebViewBaseKeyPressEvent(GtkWidget* widget, GdkEventKey* keyEvent)
682 {
683     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
684     WebKitWebViewBasePrivate* priv = webViewBase->priv;
685
686     if (priv->authenticationDialog)
687         return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, keyEvent);
688
689 #if ENABLE(FULLSCREEN_API)
690     if (priv->fullScreenModeActive) {
691         switch (keyEvent->keyval) {
692         case GDK_KEY_Escape:
693         case GDK_KEY_f:
694         case GDK_KEY_F:
695             priv->pageProxy->fullScreenManager()->requestExitFullScreen();
696             return TRUE;
697         default:
698             break;
699         }
700     }
701 #endif
702
703     // Since WebProcess key event handling is not synchronous, handle the event in two passes.
704     // When WebProcess processes the input event, it will call PageClientImpl::doneWithKeyEvent
705     // with event handled status which determines whether to pass the input event to parent or not
706     // using gtk_main_do_event().
707     if (priv->shouldForwardNextKeyEvent) {
708         priv->shouldForwardNextKeyEvent = FALSE;
709         return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, keyEvent);
710     }
711
712     // We need to copy the event as otherwise it could be destroyed before we reach the lambda body.
713     GUniquePtr<GdkEvent> event(gdk_event_copy(reinterpret_cast<GdkEvent*>(keyEvent)));
714     priv->inputMethodFilter.filterKeyEvent(keyEvent, [priv, event = WTFMove(event)](const WebCore::CompositionResults& compositionResults, InputMethodFilter::EventFakedForComposition faked) {
715         priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(event.get(), compositionResults, faked,
716             !compositionResults.compositionUpdated() ? priv->keyBindingTranslator.commandsForKeyEvent(&event->key) : Vector<String>()));
717     });
718
719     return TRUE;
720 }
721
722 static gboolean webkitWebViewBaseKeyReleaseEvent(GtkWidget* widget, GdkEventKey* keyEvent)
723 {
724     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
725     WebKitWebViewBasePrivate* priv = webViewBase->priv;
726
727     if (priv->shouldForwardNextKeyEvent) {
728         priv->shouldForwardNextKeyEvent = FALSE;
729         return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_release_event(widget, keyEvent);
730     }
731
732     // We need to copy the event as otherwise it could be destroyed before we reach the lambda body.
733     GUniquePtr<GdkEvent> event(gdk_event_copy(reinterpret_cast<GdkEvent*>(keyEvent)));
734     priv->inputMethodFilter.filterKeyEvent(keyEvent, [priv, event = WTFMove(event)](const WebCore::CompositionResults& compositionResults, InputMethodFilter::EventFakedForComposition faked) {
735         priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(event.get(), compositionResults, faked, { }));
736     });
737
738     return TRUE;
739 }
740
741 static gboolean webkitWebViewBaseButtonPressEvent(GtkWidget* widget, GdkEventButton* buttonEvent)
742 {
743     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
744     WebKitWebViewBasePrivate* priv = webViewBase->priv;
745
746     if (priv->authenticationDialog)
747         return TRUE;
748
749     gtk_widget_grab_focus(widget);
750
751     priv->inputMethodFilter.notifyMouseButtonPress();
752
753     // For double and triple clicks GDK sends both a normal button press event
754     // and a specific type (like GDK_2BUTTON_PRESS). If we detect a special press
755     // coming up, ignore this event as it certainly generated the double or triple
756     // click. The consequence of not eating this event is two DOM button press events
757     // are generated.
758     GUniquePtr<GdkEvent> nextEvent(gdk_event_peek());
759     if (nextEvent && (nextEvent->any.type == GDK_2BUTTON_PRESS || nextEvent->any.type == GDK_3BUTTON_PRESS))
760         return TRUE;
761
762     // If it's a right click event save it as a possible context menu event.
763     if (buttonEvent->button == 3)
764         priv->contextMenuEvent.reset(gdk_event_copy(reinterpret_cast<GdkEvent*>(buttonEvent)));
765
766     priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(buttonEvent),
767         priv->clickCounter.currentClickCountForGdkButtonEvent(buttonEvent)));
768     return TRUE;
769 }
770
771 static gboolean webkitWebViewBaseButtonReleaseEvent(GtkWidget* widget, GdkEventButton* event)
772 {
773     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
774     WebKitWebViewBasePrivate* priv = webViewBase->priv;
775
776     if (priv->authenticationDialog)
777         return TRUE;
778
779     gtk_widget_grab_focus(widget);
780     priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(event), 0 /* currentClickCount */));
781
782     return TRUE;
783 }
784
785 static gboolean webkitWebViewBaseScrollEvent(GtkWidget* widget, GdkEventScroll* event)
786 {
787     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
788     WebKitWebViewBasePrivate* priv = webViewBase->priv;
789
790     if (std::exchange(priv->shouldForwardNextWheelEvent, false))
791         return FALSE;
792
793     if (priv->authenticationDialog)
794         return FALSE;
795
796     priv->pageProxy->handleWheelEvent(NativeWebWheelEvent(reinterpret_cast<GdkEvent*>(event)));
797
798     return TRUE;
799 }
800
801 static gboolean webkitWebViewBaseMotionNotifyEvent(GtkWidget* widget, GdkEventMotion* event)
802 {
803     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
804     WebKitWebViewBasePrivate* priv = webViewBase->priv;
805
806     if (priv->authenticationDialog) {
807         auto* widgetClass = GTK_WIDGET_CLASS(webkit_web_view_base_parent_class);
808         return widgetClass->motion_notify_event ? widgetClass->motion_notify_event(widget, event) : FALSE;
809     }
810
811     priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(event), 0 /* currentClickCount */));
812
813     return FALSE;
814 }
815
816 static gboolean webkitWebViewBaseCrossingNotifyEvent(GtkWidget* widget, GdkEventCrossing* crosssingEvent)
817 {
818     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
819     WebKitWebViewBasePrivate* priv = webViewBase->priv;
820
821     if (priv->authenticationDialog)
822         return FALSE;
823
824     // In the case of crossing events, it's very important the actual coordinates the WebProcess receives, because once the mouse leaves
825     // the web view, the WebProcess won't receive more events until the mouse enters again in the web view. So, if the coordinates of the leave
826     // event are not accurate, the WebProcess might not know the mouse left the view. This can happen because of double to integer conversion,
827     // if the coordinates of the leave event are for example (25.2, -0.9), the WebProcess will receive (25, 0) and any hit test will succeed
828     // because those coordinates are inside the web view.
829     GtkAllocation allocation;
830     gtk_widget_get_allocation(widget, &allocation);
831     double width = allocation.width;
832     double height = allocation.height;
833     double x = crosssingEvent->x;
834     double y = crosssingEvent->y;
835     if (x < 0 && x > -1)
836         x = -1;
837     else if (x >= width && x < width + 1)
838         x = width + 1;
839     if (y < 0 && y > -1)
840         y = -1;
841     else if (y >= height && y < height + 1)
842         y = height + 1;
843
844     GdkEvent* event = reinterpret_cast<GdkEvent*>(crosssingEvent);
845     GUniquePtr<GdkEvent> copiedEvent;
846     if (x != crosssingEvent->x || y != crosssingEvent->y) {
847         copiedEvent.reset(gdk_event_copy(event));
848         copiedEvent->crossing.x = x;
849         copiedEvent->crossing.y = y;
850     }
851
852     priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(copiedEvent ? copiedEvent.get() : event, 0 /* currentClickCount */));
853
854     return FALSE;
855 }
856
857 #if ENABLE(TOUCH_EVENTS)
858 static void appendTouchEvent(Vector<WebPlatformTouchPoint>& touchPoints, const GdkEvent* event, WebPlatformTouchPoint::TouchPointState state)
859 {
860     gdouble x, y;
861     gdk_event_get_coords(event, &x, &y);
862
863     gdouble xRoot, yRoot;
864     gdk_event_get_root_coords(event, &xRoot, &yRoot);
865
866     uint32_t identifier = GPOINTER_TO_UINT(gdk_event_get_event_sequence(event));
867     touchPoints.uncheckedAppend(WebPlatformTouchPoint(identifier, state, IntPoint(xRoot, yRoot), IntPoint(x, y)));
868 }
869
870 static inline WebPlatformTouchPoint::TouchPointState touchPointStateForEvents(const GdkEvent* current, const GdkEvent* event)
871 {
872     if (gdk_event_get_event_sequence(current) != gdk_event_get_event_sequence(event))
873         return WebPlatformTouchPoint::TouchStationary;
874
875     switch (current->type) {
876     case GDK_TOUCH_UPDATE:
877         return WebPlatformTouchPoint::TouchMoved;
878     case GDK_TOUCH_BEGIN:
879         return WebPlatformTouchPoint::TouchPressed;
880     case GDK_TOUCH_END:
881         return WebPlatformTouchPoint::TouchReleased;
882     default:
883         return WebPlatformTouchPoint::TouchStationary;
884     }
885 }
886
887 static void webkitWebViewBaseGetTouchPointsForEvent(WebKitWebViewBase* webViewBase, GdkEvent* event, Vector<WebPlatformTouchPoint>& touchPoints)
888 {
889     WebKitWebViewBasePrivate* priv = webViewBase->priv;
890     touchPoints.reserveInitialCapacity(event->type == GDK_TOUCH_END ? priv->touchEvents.size() + 1 : priv->touchEvents.size());
891
892     for (const auto& it : priv->touchEvents)
893         appendTouchEvent(touchPoints, it.value.get(), touchPointStateForEvents(it.value.get(), event));
894
895     // Touch was already removed from the TouchEventsMap, add it here.
896     if (event->type == GDK_TOUCH_END)
897         appendTouchEvent(touchPoints, event, WebPlatformTouchPoint::TouchReleased);
898 }
899
900 static gboolean webkitWebViewBaseTouchEvent(GtkWidget* widget, GdkEventTouch* event)
901 {
902     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
903     WebKitWebViewBasePrivate* priv = webViewBase->priv;
904
905     if (priv->authenticationDialog)
906         return TRUE;
907
908     GdkEvent* touchEvent = reinterpret_cast<GdkEvent*>(event);
909     uint32_t sequence = GPOINTER_TO_UINT(gdk_event_get_event_sequence(touchEvent));
910
911 #if HAVE(GTK_GESTURES)
912     GestureController& gestureController = webkitWebViewBaseGestureController(webViewBase);
913     if (gestureController.isProcessingGestures()) {
914         // If we are already processing gestures is because the WebProcess didn't handle the
915         // BEGIN touch event, so pass subsequent events to the GestureController.
916         gestureController.handleEvent(touchEvent);
917         // Remove the gesture event sequence from the handled touch events
918         // list to avoid the gesure sequence and a touch sequence of same
919         // ID to conflict.
920         priv->touchEvents.remove(sequence);
921         return TRUE;
922     }
923 #endif
924
925     switch (touchEvent->type) {
926     case GDK_TOUCH_BEGIN: {
927         ASSERT(!priv->touchEvents.contains(sequence));
928         GUniquePtr<GdkEvent> event(gdk_event_copy(touchEvent));
929         priv->touchEvents.add(sequence, WTFMove(event));
930         break;
931     }
932     case GDK_TOUCH_UPDATE: {
933         auto it = priv->touchEvents.find(sequence);
934         ASSERT(it != priv->touchEvents.end());
935         it->value.reset(gdk_event_copy(touchEvent));
936         break;
937     }
938     case GDK_TOUCH_END:
939         ASSERT(priv->touchEvents.contains(sequence));
940         priv->touchEvents.remove(sequence);
941         break;
942     default:
943         break;
944     }
945
946     Vector<WebPlatformTouchPoint> touchPoints;
947     webkitWebViewBaseGetTouchPointsForEvent(webViewBase, touchEvent, touchPoints);
948     priv->pageProxy->handleTouchEvent(NativeWebTouchEvent(reinterpret_cast<GdkEvent*>(event), WTFMove(touchPoints)));
949
950     return TRUE;
951 }
952 #endif // ENABLE(TOUCH_EVENTS)
953
954 #if HAVE(GTK_GESTURES)
955 GestureController& webkitWebViewBaseGestureController(WebKitWebViewBase* webViewBase)
956 {
957     WebKitWebViewBasePrivate* priv = webViewBase->priv;
958     if (!priv->gestureController)
959         priv->gestureController = std::make_unique<GestureController>(*priv->pageProxy);
960     return *priv->gestureController;
961 }
962 #endif
963
964 static gboolean webkitWebViewBaseQueryTooltip(GtkWidget* widget, gint /* x */, gint /* y */, gboolean keyboardMode, GtkTooltip* tooltip)
965 {
966     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
967
968     if (keyboardMode) {
969         // TODO: https://bugs.webkit.org/show_bug.cgi?id=61732.
970         notImplemented();
971         return FALSE;
972     }
973
974     if (priv->tooltipText.length() <= 0)
975         return FALSE;
976
977     if (!priv->tooltipArea.isEmpty()) {
978         GdkRectangle area = priv->tooltipArea;
979         gtk_tooltip_set_tip_area(tooltip, &area);
980     } else
981         gtk_tooltip_set_tip_area(tooltip, 0);
982     gtk_tooltip_set_text(tooltip, priv->tooltipText.data());
983
984     return TRUE;
985 }
986
987 #if ENABLE(DRAG_SUPPORT)
988 static void webkitWebViewBaseDragDataGet(GtkWidget* widget, GdkDragContext* context, GtkSelectionData* selectionData, guint info, guint /* time */)
989 {
990     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
991     ASSERT(priv->dragAndDropHandler);
992     priv->dragAndDropHandler->fillDragData(context, selectionData, info);
993 }
994
995 static void webkitWebViewBaseDragEnd(GtkWidget* widget, GdkDragContext* context)
996 {
997     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
998     ASSERT(priv->dragAndDropHandler);
999     priv->dragAndDropHandler->finishDrag(context);
1000 }
1001
1002 static void webkitWebViewBaseDragDataReceived(GtkWidget* widget, GdkDragContext* context, gint /* x */, gint /* y */, GtkSelectionData* selectionData, guint info, guint time)
1003 {
1004     webkitWebViewBaseDragAndDropHandler(WEBKIT_WEB_VIEW_BASE(widget)).dragEntered(context, selectionData, info, time);
1005 }
1006 #endif // ENABLE(DRAG_SUPPORT)
1007
1008 static AtkObject* webkitWebViewBaseGetAccessible(GtkWidget* widget)
1009 {
1010     // If the socket has already been created and embedded a plug ID, return it.
1011     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1012     if (priv->accessible && atk_socket_is_occupied(ATK_SOCKET(priv->accessible.get())))
1013         return priv->accessible.get();
1014
1015     // Create the accessible object and associate it to the widget.
1016     if (!priv->accessible) {
1017         priv->accessible = adoptGRef(ATK_OBJECT(webkitWebViewBaseAccessibleNew(widget)));
1018
1019         // Set the parent not to break bottom-up navigation.
1020         GtkWidget* parentWidget = gtk_widget_get_parent(widget);
1021         AtkObject* axParent = parentWidget ? gtk_widget_get_accessible(parentWidget) : 0;
1022         if (axParent)
1023             atk_object_set_parent(priv->accessible.get(), axParent);
1024     }
1025
1026     // Try to embed the plug in the socket, if posssible.
1027     String plugID = priv->pageProxy->accessibilityPlugID();
1028     if (plugID.isNull())
1029         return priv->accessible.get();
1030
1031     atk_socket_embed(ATK_SOCKET(priv->accessible.get()), const_cast<gchar*>(plugID.utf8().data()));
1032
1033     return priv->accessible.get();
1034 }
1035
1036 #if ENABLE(DRAG_SUPPORT)
1037 static gboolean webkitWebViewBaseDragMotion(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
1038 {
1039     webkitWebViewBaseDragAndDropHandler(WEBKIT_WEB_VIEW_BASE(widget)).dragMotion(context, IntPoint(x, y), time);
1040     return TRUE;
1041 }
1042
1043 static void webkitWebViewBaseDragLeave(GtkWidget* widget, GdkDragContext* context, guint /* time */)
1044 {
1045     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1046     ASSERT(priv->dragAndDropHandler);
1047     priv->dragAndDropHandler->dragLeave(context);
1048 }
1049
1050 static gboolean webkitWebViewBaseDragDrop(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
1051 {
1052     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1053     ASSERT(priv->dragAndDropHandler);
1054     return priv->dragAndDropHandler->drop(context, IntPoint(x, y), time);
1055 }
1056 #endif // ENABLE(DRAG_SUPPORT)
1057
1058 static void webkitWebViewBaseHierarchyChanged(GtkWidget* widget, GtkWidget* oldToplevel)
1059 {
1060     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1061     if (widgetIsOnscreenToplevelWindow(oldToplevel) && GTK_WINDOW(oldToplevel) == priv->toplevelOnScreenWindow) {
1062         webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), nullptr);
1063         return;
1064     }
1065
1066     if (!oldToplevel) {
1067         GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
1068         if (widgetIsOnscreenToplevelWindow(toplevel))
1069             webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), GTK_WINDOW(toplevel));
1070     }
1071 }
1072
1073 static gboolean webkitWebViewBaseFocus(GtkWidget* widget, GtkDirectionType direction)
1074 {
1075     // If the authentication dialog is active, we need to forward focus events there. This
1076     // ensures that you can tab between elements in the box.
1077     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1078     if (priv->authenticationDialog) {
1079         gboolean returnValue;
1080         g_signal_emit_by_name(priv->authenticationDialog, "focus", direction, &returnValue);
1081         return returnValue;
1082     }
1083
1084     return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus(widget, direction);
1085 }
1086
1087 static void webkitWebViewBaseDestroy(GtkWidget* widget)
1088 {
1089     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1090     if (priv->authenticationDialog)
1091         gtk_widget_destroy(priv->authenticationDialog);
1092
1093     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->destroy(widget);
1094 }
1095
1096 static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebViewBaseClass)
1097 {
1098     GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webkitWebViewBaseClass);
1099     widgetClass->realize = webkitWebViewBaseRealize;
1100     widgetClass->unrealize = webkitWebViewBaseUnrealize;
1101     widgetClass->draw = webkitWebViewBaseDraw;
1102     widgetClass->size_allocate = webkitWebViewBaseSizeAllocate;
1103     widgetClass->get_preferred_width = webkitWebViewBaseGetPreferredWidth;
1104     widgetClass->get_preferred_height = webkitWebViewBaseGetPreferredHeight;
1105     widgetClass->map = webkitWebViewBaseMap;
1106     widgetClass->unmap = webkitWebViewBaseUnmap;
1107     widgetClass->focus = webkitWebViewBaseFocus;
1108     widgetClass->focus_in_event = webkitWebViewBaseFocusInEvent;
1109     widgetClass->focus_out_event = webkitWebViewBaseFocusOutEvent;
1110     widgetClass->key_press_event = webkitWebViewBaseKeyPressEvent;
1111     widgetClass->key_release_event = webkitWebViewBaseKeyReleaseEvent;
1112     widgetClass->button_press_event = webkitWebViewBaseButtonPressEvent;
1113     widgetClass->button_release_event = webkitWebViewBaseButtonReleaseEvent;
1114     widgetClass->scroll_event = webkitWebViewBaseScrollEvent;
1115     widgetClass->motion_notify_event = webkitWebViewBaseMotionNotifyEvent;
1116     widgetClass->enter_notify_event = webkitWebViewBaseCrossingNotifyEvent;
1117     widgetClass->leave_notify_event = webkitWebViewBaseCrossingNotifyEvent;
1118 #if ENABLE(TOUCH_EVENTS)
1119     widgetClass->touch_event = webkitWebViewBaseTouchEvent;
1120 #endif
1121     widgetClass->query_tooltip = webkitWebViewBaseQueryTooltip;
1122 #if ENABLE(DRAG_SUPPORT)
1123     widgetClass->drag_end = webkitWebViewBaseDragEnd;
1124     widgetClass->drag_data_get = webkitWebViewBaseDragDataGet;
1125     widgetClass->drag_motion = webkitWebViewBaseDragMotion;
1126     widgetClass->drag_leave = webkitWebViewBaseDragLeave;
1127     widgetClass->drag_drop = webkitWebViewBaseDragDrop;
1128     widgetClass->drag_data_received = webkitWebViewBaseDragDataReceived;
1129 #endif // ENABLE(DRAG_SUPPORT)
1130     widgetClass->get_accessible = webkitWebViewBaseGetAccessible;
1131     widgetClass->hierarchy_changed = webkitWebViewBaseHierarchyChanged;
1132     widgetClass->destroy = webkitWebViewBaseDestroy;
1133
1134     GObjectClass* gobjectClass = G_OBJECT_CLASS(webkitWebViewBaseClass);
1135     gobjectClass->constructed = webkitWebViewBaseConstructed;
1136     gobjectClass->dispose = webkitWebViewBaseDispose;
1137
1138     GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webkitWebViewBaseClass);
1139     containerClass->add = webkitWebViewBaseContainerAdd;
1140     containerClass->remove = webkitWebViewBaseContainerRemove;
1141     containerClass->forall = webkitWebViewBaseContainerForall;
1142
1143     // Before creating a WebKitWebViewBasePriv we need to be sure that WebKit is started.
1144     // Usually starting a context triggers InitializeWebKit2, but in case
1145     // we create a view without asking before for a default_context we get a crash.
1146     WebKit::InitializeWebKit2();
1147 }
1148
1149 WebKitWebViewBase* webkitWebViewBaseCreate(const API::PageConfiguration& configuration)
1150 {
1151     WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(g_object_new(WEBKIT_TYPE_WEB_VIEW_BASE, nullptr));
1152     webkitWebViewBaseCreateWebPage(webkitWebViewBase, configuration.copy());
1153     return webkitWebViewBase;
1154 }
1155
1156 GtkIMContext* webkitWebViewBaseGetIMContext(WebKitWebViewBase* webkitWebViewBase)
1157 {
1158     return webkitWebViewBase->priv->inputMethodFilter.context();
1159 }
1160
1161 WebPageProxy* webkitWebViewBaseGetPage(WebKitWebViewBase* webkitWebViewBase)
1162 {
1163     return webkitWebViewBase->priv->pageProxy.get();
1164 }
1165
1166 #if HAVE(GTK_SCALE_FACTOR)
1167 static void deviceScaleFactorChanged(WebKitWebViewBase* webkitWebViewBase)
1168 {
1169     webkitWebViewBase->priv->pageProxy->setIntrinsicDeviceScaleFactor(gtk_widget_get_scale_factor(GTK_WIDGET(webkitWebViewBase)));
1170 }
1171 #endif // HAVE(GTK_SCALE_FACTOR)
1172
1173 void webkitWebViewBaseCreateWebPage(WebKitWebViewBase* webkitWebViewBase, Ref<API::PageConfiguration>&& configuration)
1174 {
1175     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1176     WebProcessPool* processPool = configuration->processPool();
1177     priv->pageProxy = processPool->createWebPage(*priv->pageClient, WTFMove(configuration));
1178     priv->pageProxy->initializeWebPage();
1179
1180     priv->acceleratedBackingStore = AcceleratedBackingStore::create(*priv->pageProxy);
1181
1182     priv->inputMethodFilter.setPage(priv->pageProxy.get());
1183
1184 #if HAVE(GTK_SCALE_FACTOR)
1185     // We attach this here, because changes in scale factor are passed directly to the page proxy.
1186     priv->pageProxy->setIntrinsicDeviceScaleFactor(gtk_widget_get_scale_factor(GTK_WIDGET(webkitWebViewBase)));
1187     g_signal_connect(webkitWebViewBase, "notify::scale-factor", G_CALLBACK(deviceScaleFactorChanged), nullptr);
1188 #endif
1189 }
1190
1191 void webkitWebViewBaseSetTooltipText(WebKitWebViewBase* webViewBase, const char* tooltip)
1192 {
1193     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1194     if (tooltip && tooltip[0] != '\0') {
1195         priv->tooltipText = tooltip;
1196         gtk_widget_set_has_tooltip(GTK_WIDGET(webViewBase), TRUE);
1197     } else {
1198         priv->tooltipText = "";
1199         gtk_widget_set_has_tooltip(GTK_WIDGET(webViewBase), FALSE);
1200     }
1201
1202     gtk_widget_trigger_tooltip_query(GTK_WIDGET(webViewBase));
1203 }
1204
1205 void webkitWebViewBaseSetTooltipArea(WebKitWebViewBase* webViewBase, const IntRect& tooltipArea)
1206 {
1207     webViewBase->priv->tooltipArea = tooltipArea;
1208 }
1209
1210 #if ENABLE(DRAG_SUPPORT)
1211 DragAndDropHandler& webkitWebViewBaseDragAndDropHandler(WebKitWebViewBase* webViewBase)
1212 {
1213     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1214     if (!priv->dragAndDropHandler)
1215         priv->dragAndDropHandler = std::make_unique<DragAndDropHandler>(*priv->pageProxy);
1216     return *priv->dragAndDropHandler;
1217 }
1218 #endif // ENABLE(DRAG_SUPPORT)
1219
1220 void webkitWebViewBaseForwardNextKeyEvent(WebKitWebViewBase* webkitWebViewBase)
1221 {
1222     webkitWebViewBase->priv->shouldForwardNextKeyEvent = TRUE;
1223 }
1224
1225 void webkitWebViewBaseForwardNextWheelEvent(WebKitWebViewBase* webkitWebViewBase)
1226 {
1227     webkitWebViewBase->priv->shouldForwardNextWheelEvent = true;
1228 }
1229
1230 #if ENABLE(FULLSCREEN_API)
1231 static void screenSaverInhibitedCallback(GDBusProxy* screenSaverProxy, GAsyncResult* result, WebKitWebViewBase* webViewBase)
1232 {
1233     GRefPtr<GVariant> returnValue = adoptGRef(g_dbus_proxy_call_finish(screenSaverProxy, result, nullptr));
1234     if (returnValue)
1235         g_variant_get(returnValue.get(), "(u)", &webViewBase->priv->screenSaverCookie);
1236     webViewBase->priv->screenSaverInhibitCancellable = nullptr;
1237 }
1238
1239 static void webkitWebViewBaseSendInhibitMessageToScreenSaver(WebKitWebViewBase* webViewBase)
1240 {
1241     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1242     ASSERT(priv->screenSaverProxy);
1243     priv->screenSaverCookie = 0;
1244     if (!priv->screenSaverInhibitCancellable)
1245         priv->screenSaverInhibitCancellable = adoptGRef(g_cancellable_new());
1246     g_dbus_proxy_call(priv->screenSaverProxy.get(), "Inhibit", g_variant_new("(ss)", g_get_prgname(), _("Website running in fullscreen mode")),
1247         G_DBUS_CALL_FLAGS_NONE, -1, priv->screenSaverInhibitCancellable.get(), reinterpret_cast<GAsyncReadyCallback>(screenSaverInhibitedCallback), webViewBase);
1248 }
1249
1250 static void screenSaverProxyCreatedCallback(GObject*, GAsyncResult* result, WebKitWebViewBase* webViewBase)
1251 {
1252     // WebKitWebViewBase cancels the proxy creation on dispose, which means this could be called
1253     // after the web view has been destroyed and g_dbus_proxy_new_for_bus_finish will return nullptr.
1254     // So, make sure we don't use the web view unless we have a valid proxy.
1255     // See https://bugs.webkit.org/show_bug.cgi?id=151653.
1256     GRefPtr<GDBusProxy> proxy = adoptGRef(g_dbus_proxy_new_for_bus_finish(result, nullptr));
1257     if (!proxy)
1258         return;
1259
1260     webViewBase->priv->screenSaverProxy = proxy;
1261     webkitWebViewBaseSendInhibitMessageToScreenSaver(webViewBase);
1262 }
1263
1264 static void webkitWebViewBaseInhibitScreenSaver(WebKitWebViewBase* webViewBase)
1265 {
1266     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1267     if (priv->screenSaverCookie) {
1268         // Already inhibited.
1269         return;
1270     }
1271
1272     if (priv->screenSaverProxy) {
1273         webkitWebViewBaseSendInhibitMessageToScreenSaver(webViewBase);
1274         return;
1275     }
1276
1277     priv->screenSaverInhibitCancellable = adoptGRef(g_cancellable_new());
1278     g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION, static_cast<GDBusProxyFlags>(G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS),
1279         nullptr, "org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver", priv->screenSaverInhibitCancellable.get(),
1280         reinterpret_cast<GAsyncReadyCallback>(screenSaverProxyCreatedCallback), webViewBase);
1281 }
1282
1283 static void webkitWebViewBaseUninhibitScreenSaver(WebKitWebViewBase* webViewBase)
1284 {
1285     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1286     if (!priv->screenSaverCookie) {
1287         // Not inhibited or it's being inhibited.
1288         g_cancellable_cancel(priv->screenSaverInhibitCancellable.get());
1289         return;
1290     }
1291
1292     // If we have a cookie we should have a proxy.
1293     ASSERT(priv->screenSaverProxy);
1294     g_dbus_proxy_call(priv->screenSaverProxy.get(), "UnInhibit", g_variant_new("(u)", priv->screenSaverCookie), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr, nullptr);
1295     priv->screenSaverCookie = 0;
1296 }
1297 #endif
1298
1299 void webkitWebViewBaseEnterFullScreen(WebKitWebViewBase* webkitWebViewBase)
1300 {
1301 #if ENABLE(FULLSCREEN_API)
1302     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1303     if (priv->fullScreenModeActive)
1304         return;
1305
1306     if (!priv->fullScreenClient.willEnterFullScreen())
1307         return;
1308
1309     WebFullScreenManagerProxy* fullScreenManagerProxy = priv->pageProxy->fullScreenManager();
1310     fullScreenManagerProxy->willEnterFullScreen();
1311
1312     GtkWidget* topLevelWindow = gtk_widget_get_toplevel(GTK_WIDGET(webkitWebViewBase));
1313     if (gtk_widget_is_toplevel(topLevelWindow))
1314         gtk_window_fullscreen(GTK_WINDOW(topLevelWindow));
1315     fullScreenManagerProxy->didEnterFullScreen();
1316     priv->fullScreenModeActive = true;
1317     webkitWebViewBaseInhibitScreenSaver(webkitWebViewBase);
1318 #endif
1319 }
1320
1321 void webkitWebViewBaseExitFullScreen(WebKitWebViewBase* webkitWebViewBase)
1322 {
1323 #if ENABLE(FULLSCREEN_API)
1324     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1325     if (!priv->fullScreenModeActive)
1326         return;
1327
1328     if (!priv->fullScreenClient.willExitFullScreen())
1329         return;
1330
1331     WebFullScreenManagerProxy* fullScreenManagerProxy = priv->pageProxy->fullScreenManager();
1332     fullScreenManagerProxy->willExitFullScreen();
1333
1334     GtkWidget* topLevelWindow = gtk_widget_get_toplevel(GTK_WIDGET(webkitWebViewBase));
1335     if (gtk_widget_is_toplevel(topLevelWindow))
1336         gtk_window_unfullscreen(GTK_WINDOW(topLevelWindow));
1337     fullScreenManagerProxy->didExitFullScreen();
1338     priv->fullScreenModeActive = false;
1339     webkitWebViewBaseUninhibitScreenSaver(webkitWebViewBase);
1340 #endif
1341 }
1342
1343 void webkitWebViewBaseInitializeFullScreenClient(WebKitWebViewBase* webkitWebViewBase, const WKFullScreenClientGtkBase* wkClient)
1344 {
1345     webkitWebViewBase->priv->fullScreenClient.initialize(wkClient);
1346 }
1347
1348 void webkitWebViewBaseSetInspectorViewSize(WebKitWebViewBase* webkitWebViewBase, unsigned size)
1349 {
1350     if (webkitWebViewBase->priv->inspectorViewSize == size)
1351         return;
1352     webkitWebViewBase->priv->inspectorViewSize = size;
1353     if (webkitWebViewBase->priv->inspectorView)
1354         gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webkitWebViewBase));
1355 }
1356
1357 static void activeContextMenuUnmapped(GtkMenu* menu, WebKitWebViewBase* webViewBase)
1358 {
1359     if (webViewBase->priv->activeContextMenuProxy && webViewBase->priv->activeContextMenuProxy->gtkMenu() == menu)
1360         webViewBase->priv->activeContextMenuProxy = nullptr;
1361 }
1362
1363 void webkitWebViewBaseSetActiveContextMenuProxy(WebKitWebViewBase* webkitWebViewBase, WebContextMenuProxyGtk* contextMenuProxy)
1364 {
1365     webkitWebViewBase->priv->activeContextMenuProxy = contextMenuProxy;
1366     g_signal_connect_object(contextMenuProxy->gtkMenu(), "unmap", G_CALLBACK(activeContextMenuUnmapped), webkitWebViewBase, static_cast<GConnectFlags>(0));
1367 }
1368
1369 WebContextMenuProxyGtk* webkitWebViewBaseGetActiveContextMenuProxy(WebKitWebViewBase* webkitWebViewBase)
1370 {
1371     return webkitWebViewBase->priv->activeContextMenuProxy;
1372 }
1373
1374 GdkEvent* webkitWebViewBaseTakeContextMenuEvent(WebKitWebViewBase* webkitWebViewBase)
1375 {
1376     return webkitWebViewBase->priv->contextMenuEvent.release();
1377 }
1378
1379 void webkitWebViewBaseSetFocus(WebKitWebViewBase* webViewBase, bool focused)
1380 {
1381     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1382     if ((focused && priv->viewState & ViewState::IsFocused) || (!focused && !(priv->viewState & ViewState::IsFocused)))
1383         return;
1384
1385     ViewState::Flags flagsToUpdate = ViewState::IsFocused;
1386     if (focused) {
1387         priv->viewState |= ViewState::IsFocused;
1388
1389         // If the view has received the focus and the window is not active
1390         // mark the current window as active now. This can happen if the
1391         // toplevel window is a GTK_WINDOW_POPUP and the focus has been
1392         // set programatically like WebKitTestRunner does, because POPUP
1393         // can't be focused.
1394         if (!(priv->viewState & ViewState::WindowIsActive)) {
1395             priv->viewState |= ViewState::WindowIsActive;
1396             flagsToUpdate |= ViewState::WindowIsActive;
1397         }
1398     } else
1399         priv->viewState &= ~ViewState::IsFocused;
1400
1401     webkitWebViewBaseScheduleUpdateViewState(webViewBase, flagsToUpdate);
1402 }
1403
1404 bool webkitWebViewBaseIsInWindowActive(WebKitWebViewBase* webViewBase)
1405 {
1406     return webViewBase->priv->viewState & ViewState::WindowIsActive;
1407 }
1408
1409 bool webkitWebViewBaseIsFocused(WebKitWebViewBase* webViewBase)
1410 {
1411     return webViewBase->priv->viewState & ViewState::IsFocused;
1412 }
1413
1414 bool webkitWebViewBaseIsVisible(WebKitWebViewBase* webViewBase)
1415 {
1416     return webViewBase->priv->viewState & ViewState::IsVisible;
1417 }
1418
1419 bool webkitWebViewBaseIsInWindow(WebKitWebViewBase* webViewBase)
1420 {
1421     return webViewBase->priv->viewState & ViewState::IsInWindow;
1422 }
1423
1424 void webkitWebViewBaseSetDownloadRequestHandler(WebKitWebViewBase* webViewBase, WebKitWebViewBaseDownloadRequestHandler downloadHandler)
1425 {
1426     webViewBase->priv->downloadHandler = downloadHandler;
1427 }
1428
1429 void webkitWebViewBaseHandleDownloadRequest(WebKitWebViewBase* webViewBase, DownloadProxy* download)
1430 {
1431     if (webViewBase->priv->downloadHandler)
1432         webViewBase->priv->downloadHandler(webViewBase, download);
1433 }
1434
1435 void webkitWebViewBaseSetInputMethodState(WebKitWebViewBase* webkitWebViewBase, bool enabled)
1436 {
1437     webkitWebViewBase->priv->inputMethodFilter.setEnabled(enabled);
1438 }
1439
1440 void webkitWebViewBaseUpdateTextInputState(WebKitWebViewBase* webkitWebViewBase)
1441 {
1442     const auto& editorState = webkitWebViewBase->priv->pageProxy->editorState();
1443     if (!editorState.isMissingPostLayoutData)
1444         webkitWebViewBase->priv->inputMethodFilter.setCursorRect(editorState.postLayoutData().caretRectAtStart);
1445 }
1446
1447 void webkitWebViewBaseSetContentsSize(WebKitWebViewBase* webkitWebViewBase, const IntSize& contentsSize)
1448 {
1449     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1450     if (priv->contentsSize == contentsSize)
1451         return;
1452     priv->contentsSize = contentsSize;
1453 }
1454
1455 void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase)
1456 {
1457     webkitWebViewBase->priv->clickCounter.reset();
1458 }
1459
1460 void webkitWebViewBaseEnterAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext)
1461 {
1462     if (webkitWebViewBase->priv->acceleratedBackingStore)
1463         webkitWebViewBase->priv->acceleratedBackingStore->update(layerTreeContext);
1464 }
1465
1466 void webkitWebViewBaseUpdateAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext)
1467 {
1468     if (webkitWebViewBase->priv->acceleratedBackingStore)
1469         webkitWebViewBase->priv->acceleratedBackingStore->update(layerTreeContext);
1470 }
1471
1472 void webkitWebViewBaseExitAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase)
1473 {
1474     if (webkitWebViewBase->priv->acceleratedBackingStore)
1475         webkitWebViewBase->priv->acceleratedBackingStore->update(LayerTreeContext());
1476 }
1477
1478 void webkitWebViewBaseDidRelaunchWebProcess(WebKitWebViewBase* webkitWebViewBase)
1479 {
1480     // Queue a resize to ensure the new DrawingAreaProxy is resized.
1481     gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webkitWebViewBase));
1482
1483 #if PLATFORM(X11) && USE(TEXTURE_MAPPER_GL) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
1484     if (PlatformDisplay::sharedDisplay().type() != PlatformDisplay::Type::X11)
1485         return;
1486
1487     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1488     DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea());
1489     ASSERT(drawingArea);
1490
1491     if (!gtk_widget_get_realized(GTK_WIDGET(webkitWebViewBase)))
1492         return;
1493
1494     uint64_t windowID = GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(webkitWebViewBase)));
1495     drawingArea->setNativeSurfaceHandleForCompositing(windowID);
1496 #else
1497     UNUSED_PARAM(webkitWebViewBase);
1498 #endif
1499 }
1500
1501 void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase)
1502 {
1503     if (webkitWebViewBase->priv->acceleratedBackingStore)
1504         webkitWebViewBase->priv->acceleratedBackingStore->update(LayerTreeContext());
1505 #if PLATFORM(X11) && USE(TEXTURE_MAPPER_GL) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
1506     if (PlatformDisplay::sharedDisplay().type() != PlatformDisplay::Type::X11)
1507         return;
1508
1509     if (!gtk_widget_get_realized(GTK_WIDGET(webkitWebViewBase)))
1510         return;
1511
1512     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1513     DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea());
1514     ASSERT(drawingArea);
1515     drawingArea->destroyNativeSurfaceHandleForCompositing();
1516 #endif
1517 }