674021692bd6bde44665dc0ff9e30d1c6dc4f225
[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) && PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
381     if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea()))
382         drawingArea->setNativeSurfaceHandleForCompositing(GDK_WINDOW_XID(window));
383 #endif
384
385     gtk_style_context_set_background(gtk_widget_get_style_context(widget), window);
386
387     gtk_im_context_set_client_window(priv->inputMethodFilter.context(), window);
388 }
389
390 static void webkitWebViewBaseUnrealize(GtkWidget* widget)
391 {
392     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(widget);
393 #if USE(TEXTURE_MAPPER) && PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
394     if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(webView->priv->pageProxy->drawingArea()))
395         drawingArea->destroyNativeSurfaceHandleForCompositing();
396 #endif
397     gtk_im_context_set_client_window(webView->priv->inputMethodFilter.context(), nullptr);
398
399     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->unrealize(widget);
400 }
401
402 static bool webkitWebViewChildIsInternalWidget(WebKitWebViewBase* webViewBase, GtkWidget* widget)
403 {
404     WebKitWebViewBasePrivate* priv = webViewBase->priv;
405     return widget == priv->inspectorView || widget == priv->authenticationDialog;
406 }
407
408 static void webkitWebViewBaseContainerAdd(GtkContainer* container, GtkWidget* widget)
409 {
410     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
411     WebKitWebViewBasePrivate* priv = webView->priv;
412
413     // Internal widgets like the web inspector and authentication dialog have custom
414     // allocations so we don't need to add them to our list of children.
415     if (!webkitWebViewChildIsInternalWidget(webView, widget)) {
416         GtkAllocation childAllocation;
417         gtk_widget_get_allocation(widget, &childAllocation);
418         priv->children.set(widget, childAllocation);
419     }
420
421     gtk_widget_set_parent(widget, GTK_WIDGET(container));
422 }
423
424 void webkitWebViewBaseAddAuthenticationDialog(WebKitWebViewBase* webViewBase, GtkWidget* dialog)
425 {
426     WebKitWebViewBasePrivate* priv = webViewBase->priv;
427     priv->authenticationDialog = dialog;
428     gtk_container_add(GTK_CONTAINER(webViewBase), dialog);
429     gtk_widget_show(dialog);
430
431     // We need to draw the shadow over the widget.
432     gtk_widget_queue_draw(GTK_WIDGET(webViewBase));
433 }
434
435 void webkitWebViewBaseAddWebInspector(WebKitWebViewBase* webViewBase, GtkWidget* inspector, AttachmentSide attachmentSide)
436 {
437     if (webViewBase->priv->inspectorView == inspector && webViewBase->priv->inspectorAttachmentSide == attachmentSide)
438         return;
439
440     webViewBase->priv->inspectorAttachmentSide = attachmentSide;
441
442     if (webViewBase->priv->inspectorView == inspector) {
443         gtk_widget_queue_resize(GTK_WIDGET(webViewBase));
444         return;
445     }
446
447     webViewBase->priv->inspectorView = inspector;
448     gtk_container_add(GTK_CONTAINER(webViewBase), inspector);
449 }
450
451 static void webkitWebViewBaseContainerRemove(GtkContainer* container, GtkWidget* widget)
452 {
453     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
454     WebKitWebViewBasePrivate* priv = webView->priv;
455     GtkWidget* widgetContainer = GTK_WIDGET(container);
456
457     gboolean wasVisible = gtk_widget_get_visible(widget);
458     gtk_widget_unparent(widget);
459
460     if (priv->inspectorView == widget) {
461         priv->inspectorView = 0;
462         priv->inspectorViewSize = 0;
463     } else if (priv->authenticationDialog == widget) {
464         priv->authenticationDialog = 0;
465     } else {
466         ASSERT(priv->children.contains(widget));
467         priv->children.remove(widget);
468     }
469     if (wasVisible && gtk_widget_get_visible(widgetContainer))
470         gtk_widget_queue_resize(widgetContainer);
471 }
472
473 static void webkitWebViewBaseContainerForall(GtkContainer* container, gboolean includeInternals, GtkCallback callback, gpointer callbackData)
474 {
475     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
476     WebKitWebViewBasePrivate* priv = webView->priv;
477
478     Vector<GtkWidget*> children;
479     copyKeysToVector(priv->children, children);
480     for (const auto& child : children) {
481         if (priv->children.contains(child))
482             (*callback)(child, callbackData);
483     }
484
485     if (includeInternals && priv->inspectorView)
486         (*callback)(priv->inspectorView, callbackData);
487
488     if (includeInternals && priv->authenticationDialog)
489         (*callback)(priv->authenticationDialog, callbackData);
490 }
491
492 void webkitWebViewBaseChildMoveResize(WebKitWebViewBase* webView, GtkWidget* child, const IntRect& childRect)
493 {
494     const IntRect& geometry = webView->priv->children.get(child);
495     if (geometry == childRect)
496         return;
497
498     webView->priv->children.set(child, childRect);
499     gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webView));
500 }
501
502 static void webkitWebViewBaseDispose(GObject* gobject)
503 {
504     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(gobject);
505     g_cancellable_cancel(webView->priv->screenSaverInhibitCancellable.get());
506     webkitWebViewBaseSetToplevelOnScreenWindow(webView, nullptr);
507     webView->priv->pageProxy->close();
508     webView->priv->acceleratedBackingStore = nullptr;
509     G_OBJECT_CLASS(webkit_web_view_base_parent_class)->dispose(gobject);
510 }
511
512 static void webkitWebViewBaseConstructed(GObject* object)
513 {
514     G_OBJECT_CLASS(webkit_web_view_base_parent_class)->constructed(object);
515
516     GtkWidget* viewWidget = GTK_WIDGET(object);
517     gtk_widget_set_can_focus(viewWidget, TRUE);
518     gtk_drag_dest_set(viewWidget, static_cast<GtkDestDefaults>(0), nullptr, 0,
519         static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
520     gtk_drag_dest_set_target_list(viewWidget, PasteboardHelper::singleton().targetList());
521
522     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(object)->priv;
523     priv->pageClient = std::make_unique<PageClientImpl>(viewWidget);
524     priv->authenticationDialog = 0;
525 }
526
527 static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr)
528 {
529     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
530     DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(webViewBase->priv->pageProxy->drawingArea());
531     if (!drawingArea)
532         return FALSE;
533
534     GdkRectangle clipRect;
535     if (!gdk_cairo_get_clip_rectangle(cr, &clipRect))
536         return FALSE;
537
538     if (webViewBase->priv->acceleratedBackingStore && drawingArea->isInAcceleratedCompositingMode())
539         webViewBase->priv->acceleratedBackingStore->paint(cr, clipRect);
540     else {
541         WebCore::Region unpaintedRegion; // This is simply unused.
542         drawingArea->paint(cr, clipRect, unpaintedRegion);
543     }
544
545     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->draw(widget, cr);
546
547     return FALSE;
548 }
549
550 static void webkitWebViewBaseChildAllocate(GtkWidget* child, gpointer userData)
551 {
552     if (!gtk_widget_get_visible(child))
553         return;
554
555     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(userData);
556     WebKitWebViewBasePrivate* priv = webViewBase->priv;
557     const IntRect& geometry = priv->children.get(child);
558     if (geometry.isEmpty())
559         return;
560
561     GtkAllocation childAllocation = geometry;
562     gtk_widget_size_allocate(child, &childAllocation);
563     priv->children.set(child, IntRect());
564 }
565
566 static void webkitWebViewBaseSizeAllocate(GtkWidget* widget, GtkAllocation* allocation)
567 {
568     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->size_allocate(widget, allocation);
569
570     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
571     gtk_container_foreach(GTK_CONTAINER(webViewBase), webkitWebViewBaseChildAllocate, webViewBase);
572
573     IntRect viewRect(allocation->x, allocation->y, allocation->width, allocation->height);
574     WebKitWebViewBasePrivate* priv = webViewBase->priv;
575     if (priv->inspectorView) {
576         GtkAllocation childAllocation = viewRect;
577
578         if (priv->inspectorAttachmentSide == AttachmentSide::Bottom) {
579             int inspectorViewHeight = std::min(static_cast<int>(priv->inspectorViewSize), allocation->height);
580             childAllocation.x = 0;
581             childAllocation.y = allocation->height - inspectorViewHeight;
582             childAllocation.height = inspectorViewHeight;
583             viewRect.setHeight(std::max(allocation->height - inspectorViewHeight, 1));
584         } else {
585             int inspectorViewWidth = std::min(static_cast<int>(priv->inspectorViewSize), allocation->width);
586             childAllocation.y = 0;
587             childAllocation.x = allocation->width - inspectorViewWidth;
588             childAllocation.width = inspectorViewWidth;
589             viewRect.setWidth(std::max(allocation->width - inspectorViewWidth, 1));
590         }
591
592         gtk_widget_size_allocate(priv->inspectorView, &childAllocation);
593     }
594
595     // The authentication dialog is centered in the view rect, which means that it
596     // never overlaps the web inspector. Thus, we need to calculate the allocation here
597     // after calculating the inspector allocation.
598     if (priv->authenticationDialog) {
599         GtkRequisition minimumSize;
600         gtk_widget_get_preferred_size(priv->authenticationDialog, &minimumSize, nullptr);
601
602         GtkAllocation childAllocation = { 0, 0, std::max(minimumSize.width, viewRect.width()), std::max(minimumSize.height, viewRect.height()) };
603         gtk_widget_size_allocate(priv->authenticationDialog, &childAllocation);
604     }
605
606     if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea()))
607         drawingArea->setSize(viewRect.size(), IntSize(), IntSize());
608 }
609
610 static void webkitWebViewBaseGetPreferredWidth(GtkWidget* widget, gint* minimumSize, gint* naturalSize)
611 {
612     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
613     *minimumSize = 0;
614     *naturalSize = priv->contentsSize.width();
615 }
616
617 static void webkitWebViewBaseGetPreferredHeight(GtkWidget* widget, gint* minimumSize, gint* naturalSize)
618 {
619     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
620     *minimumSize = 0;
621     *naturalSize = priv->contentsSize.height();
622 }
623
624 static void webkitWebViewBaseMap(GtkWidget* widget)
625 {
626     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->map(widget);
627
628     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
629     WebKitWebViewBasePrivate* priv = webViewBase->priv;
630     ViewState::Flags flagsToUpdate = 0;
631     if (!(priv->viewState & ViewState::IsVisible))
632         flagsToUpdate |= ViewState::IsVisible;
633     if (priv->toplevelOnScreenWindow) {
634         if (!(priv->viewState & ViewState::IsInWindow))
635             flagsToUpdate |= ViewState::IsInWindow;
636         if (gtk_window_is_active(GTK_WINDOW(priv->toplevelOnScreenWindow)) && !(priv->viewState & ViewState::WindowIsActive))
637             flagsToUpdate |= ViewState::WindowIsActive;
638     }
639     if (!flagsToUpdate)
640         return;
641
642     priv->viewState |= flagsToUpdate;
643     webkitWebViewBaseScheduleUpdateViewState(webViewBase, flagsToUpdate);
644 }
645
646 static void webkitWebViewBaseUnmap(GtkWidget* widget)
647 {
648     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->unmap(widget);
649
650     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
651     WebKitWebViewBasePrivate* priv = webViewBase->priv;
652     if (!(priv->viewState & ViewState::IsVisible))
653         return;
654
655     priv->viewState &= ~ViewState::IsVisible;
656     webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::IsVisible);
657 }
658
659 static gboolean webkitWebViewBaseFocusInEvent(GtkWidget* widget, GdkEventFocus* event)
660 {
661     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
662     webkitWebViewBaseSetFocus(webViewBase, true);
663     webViewBase->priv->inputMethodFilter.notifyFocusedIn();
664
665     return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus_in_event(widget, event);
666 }
667
668 static gboolean webkitWebViewBaseFocusOutEvent(GtkWidget* widget, GdkEventFocus* event)
669 {
670     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
671     webkitWebViewBaseSetFocus(webViewBase, false);
672     webViewBase->priv->inputMethodFilter.notifyFocusedOut();
673
674     return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus_out_event(widget, event);
675 }
676
677 static gboolean webkitWebViewBaseKeyPressEvent(GtkWidget* widget, GdkEventKey* keyEvent)
678 {
679     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
680     WebKitWebViewBasePrivate* priv = webViewBase->priv;
681
682     if (priv->authenticationDialog)
683         return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, keyEvent);
684
685 #if ENABLE(FULLSCREEN_API)
686     if (priv->fullScreenModeActive) {
687         switch (keyEvent->keyval) {
688         case GDK_KEY_Escape:
689         case GDK_KEY_f:
690         case GDK_KEY_F:
691             priv->pageProxy->fullScreenManager()->requestExitFullScreen();
692             return TRUE;
693         default:
694             break;
695         }
696     }
697 #endif
698
699     // Since WebProcess key event handling is not synchronous, handle the event in two passes.
700     // When WebProcess processes the input event, it will call PageClientImpl::doneWithKeyEvent
701     // with event handled status which determines whether to pass the input event to parent or not
702     // using gtk_main_do_event().
703     if (priv->shouldForwardNextKeyEvent) {
704         priv->shouldForwardNextKeyEvent = FALSE;
705         return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, keyEvent);
706     }
707
708     // We need to copy the event as otherwise it could be destroyed before we reach the lambda body.
709     GUniquePtr<GdkEvent> event(gdk_event_copy(reinterpret_cast<GdkEvent*>(keyEvent)));
710     priv->inputMethodFilter.filterKeyEvent(keyEvent, [priv, event = WTFMove(event)](const WebCore::CompositionResults& compositionResults, InputMethodFilter::EventFakedForComposition faked) {
711         priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(event.get(), compositionResults, faked,
712             !compositionResults.compositionUpdated() ? priv->keyBindingTranslator.commandsForKeyEvent(&event->key) : Vector<String>()));
713     });
714
715     return TRUE;
716 }
717
718 static gboolean webkitWebViewBaseKeyReleaseEvent(GtkWidget* widget, GdkEventKey* keyEvent)
719 {
720     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
721     WebKitWebViewBasePrivate* priv = webViewBase->priv;
722
723     if (priv->shouldForwardNextKeyEvent) {
724         priv->shouldForwardNextKeyEvent = FALSE;
725         return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_release_event(widget, keyEvent);
726     }
727
728     // We need to copy the event as otherwise it could be destroyed before we reach the lambda body.
729     GUniquePtr<GdkEvent> event(gdk_event_copy(reinterpret_cast<GdkEvent*>(keyEvent)));
730     priv->inputMethodFilter.filterKeyEvent(keyEvent, [priv, event = WTFMove(event)](const WebCore::CompositionResults& compositionResults, InputMethodFilter::EventFakedForComposition faked) {
731         priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(event.get(), compositionResults, faked, { }));
732     });
733
734     return TRUE;
735 }
736
737 static gboolean webkitWebViewBaseButtonPressEvent(GtkWidget* widget, GdkEventButton* buttonEvent)
738 {
739     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
740     WebKitWebViewBasePrivate* priv = webViewBase->priv;
741
742     if (priv->authenticationDialog)
743         return TRUE;
744
745     gtk_widget_grab_focus(widget);
746
747     priv->inputMethodFilter.notifyMouseButtonPress();
748
749     // For double and triple clicks GDK sends both a normal button press event
750     // and a specific type (like GDK_2BUTTON_PRESS). If we detect a special press
751     // coming up, ignore this event as it certainly generated the double or triple
752     // click. The consequence of not eating this event is two DOM button press events
753     // are generated.
754     GUniquePtr<GdkEvent> nextEvent(gdk_event_peek());
755     if (nextEvent && (nextEvent->any.type == GDK_2BUTTON_PRESS || nextEvent->any.type == GDK_3BUTTON_PRESS))
756         return TRUE;
757
758     // If it's a right click event save it as a possible context menu event.
759     if (buttonEvent->button == 3)
760         priv->contextMenuEvent.reset(gdk_event_copy(reinterpret_cast<GdkEvent*>(buttonEvent)));
761
762     priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(buttonEvent),
763         priv->clickCounter.currentClickCountForGdkButtonEvent(buttonEvent)));
764     return TRUE;
765 }
766
767 static gboolean webkitWebViewBaseButtonReleaseEvent(GtkWidget* widget, GdkEventButton* event)
768 {
769     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
770     WebKitWebViewBasePrivate* priv = webViewBase->priv;
771
772     if (priv->authenticationDialog)
773         return TRUE;
774
775     gtk_widget_grab_focus(widget);
776     priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(event), 0 /* currentClickCount */));
777
778     return TRUE;
779 }
780
781 static gboolean webkitWebViewBaseScrollEvent(GtkWidget* widget, GdkEventScroll* event)
782 {
783     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
784     WebKitWebViewBasePrivate* priv = webViewBase->priv;
785
786     if (std::exchange(priv->shouldForwardNextWheelEvent, false))
787         return FALSE;
788
789     if (priv->authenticationDialog)
790         return FALSE;
791
792     priv->pageProxy->handleWheelEvent(NativeWebWheelEvent(reinterpret_cast<GdkEvent*>(event)));
793
794     return TRUE;
795 }
796
797 static gboolean webkitWebViewBaseMotionNotifyEvent(GtkWidget* widget, GdkEventMotion* event)
798 {
799     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
800     WebKitWebViewBasePrivate* priv = webViewBase->priv;
801
802     if (priv->authenticationDialog) {
803         auto* widgetClass = GTK_WIDGET_CLASS(webkit_web_view_base_parent_class);
804         return widgetClass->motion_notify_event ? widgetClass->motion_notify_event(widget, event) : FALSE;
805     }
806
807     priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(event), 0 /* currentClickCount */));
808
809     return FALSE;
810 }
811
812 static gboolean webkitWebViewBaseCrossingNotifyEvent(GtkWidget* widget, GdkEventCrossing* crosssingEvent)
813 {
814     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
815     WebKitWebViewBasePrivate* priv = webViewBase->priv;
816
817     if (priv->authenticationDialog)
818         return FALSE;
819
820     // In the case of crossing events, it's very important the actual coordinates the WebProcess receives, because once the mouse leaves
821     // 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
822     // event are not accurate, the WebProcess might not know the mouse left the view. This can happen because of double to integer conversion,
823     // 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
824     // because those coordinates are inside the web view.
825     GtkAllocation allocation;
826     gtk_widget_get_allocation(widget, &allocation);
827     double width = allocation.width;
828     double height = allocation.height;
829     double x = crosssingEvent->x;
830     double y = crosssingEvent->y;
831     if (x < 0 && x > -1)
832         x = -1;
833     else if (x >= width && x < width + 1)
834         x = width + 1;
835     if (y < 0 && y > -1)
836         y = -1;
837     else if (y >= height && y < height + 1)
838         y = height + 1;
839
840     GdkEvent* event = reinterpret_cast<GdkEvent*>(crosssingEvent);
841     GUniquePtr<GdkEvent> copiedEvent;
842     if (x != crosssingEvent->x || y != crosssingEvent->y) {
843         copiedEvent.reset(gdk_event_copy(event));
844         copiedEvent->crossing.x = x;
845         copiedEvent->crossing.y = y;
846     }
847
848     priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(copiedEvent ? copiedEvent.get() : event, 0 /* currentClickCount */));
849
850     return FALSE;
851 }
852
853 #if ENABLE(TOUCH_EVENTS)
854 static void appendTouchEvent(Vector<WebPlatformTouchPoint>& touchPoints, const GdkEvent* event, WebPlatformTouchPoint::TouchPointState state)
855 {
856     gdouble x, y;
857     gdk_event_get_coords(event, &x, &y);
858
859     gdouble xRoot, yRoot;
860     gdk_event_get_root_coords(event, &xRoot, &yRoot);
861
862     uint32_t identifier = GPOINTER_TO_UINT(gdk_event_get_event_sequence(event));
863     touchPoints.uncheckedAppend(WebPlatformTouchPoint(identifier, state, IntPoint(xRoot, yRoot), IntPoint(x, y)));
864 }
865
866 static inline WebPlatformTouchPoint::TouchPointState touchPointStateForEvents(const GdkEvent* current, const GdkEvent* event)
867 {
868     if (gdk_event_get_event_sequence(current) != gdk_event_get_event_sequence(event))
869         return WebPlatformTouchPoint::TouchStationary;
870
871     switch (current->type) {
872     case GDK_TOUCH_UPDATE:
873         return WebPlatformTouchPoint::TouchMoved;
874     case GDK_TOUCH_BEGIN:
875         return WebPlatformTouchPoint::TouchPressed;
876     case GDK_TOUCH_END:
877         return WebPlatformTouchPoint::TouchReleased;
878     default:
879         return WebPlatformTouchPoint::TouchStationary;
880     }
881 }
882
883 static void webkitWebViewBaseGetTouchPointsForEvent(WebKitWebViewBase* webViewBase, GdkEvent* event, Vector<WebPlatformTouchPoint>& touchPoints)
884 {
885     WebKitWebViewBasePrivate* priv = webViewBase->priv;
886     touchPoints.reserveInitialCapacity(event->type == GDK_TOUCH_END ? priv->touchEvents.size() + 1 : priv->touchEvents.size());
887
888     for (const auto& it : priv->touchEvents)
889         appendTouchEvent(touchPoints, it.value.get(), touchPointStateForEvents(it.value.get(), event));
890
891     // Touch was already removed from the TouchEventsMap, add it here.
892     if (event->type == GDK_TOUCH_END)
893         appendTouchEvent(touchPoints, event, WebPlatformTouchPoint::TouchReleased);
894 }
895
896 static gboolean webkitWebViewBaseTouchEvent(GtkWidget* widget, GdkEventTouch* event)
897 {
898     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
899     WebKitWebViewBasePrivate* priv = webViewBase->priv;
900
901     if (priv->authenticationDialog)
902         return TRUE;
903
904     GdkEvent* touchEvent = reinterpret_cast<GdkEvent*>(event);
905     uint32_t sequence = GPOINTER_TO_UINT(gdk_event_get_event_sequence(touchEvent));
906
907 #if HAVE(GTK_GESTURES)
908     GestureController& gestureController = webkitWebViewBaseGestureController(webViewBase);
909     if (gestureController.isProcessingGestures()) {
910         // If we are already processing gestures is because the WebProcess didn't handle the
911         // BEGIN touch event, so pass subsequent events to the GestureController.
912         gestureController.handleEvent(touchEvent);
913         // Remove the gesture event sequence from the handled touch events
914         // list to avoid the gesure sequence and a touch sequence of same
915         // ID to conflict.
916         priv->touchEvents.remove(sequence);
917         return TRUE;
918     }
919 #endif
920
921     switch (touchEvent->type) {
922     case GDK_TOUCH_BEGIN: {
923         ASSERT(!priv->touchEvents.contains(sequence));
924         GUniquePtr<GdkEvent> event(gdk_event_copy(touchEvent));
925         priv->touchEvents.add(sequence, WTFMove(event));
926         break;
927     }
928     case GDK_TOUCH_UPDATE: {
929         auto it = priv->touchEvents.find(sequence);
930         ASSERT(it != priv->touchEvents.end());
931         it->value.reset(gdk_event_copy(touchEvent));
932         break;
933     }
934     case GDK_TOUCH_END:
935         ASSERT(priv->touchEvents.contains(sequence));
936         priv->touchEvents.remove(sequence);
937         break;
938     default:
939         break;
940     }
941
942     Vector<WebPlatformTouchPoint> touchPoints;
943     webkitWebViewBaseGetTouchPointsForEvent(webViewBase, touchEvent, touchPoints);
944     priv->pageProxy->handleTouchEvent(NativeWebTouchEvent(reinterpret_cast<GdkEvent*>(event), WTFMove(touchPoints)));
945
946     return TRUE;
947 }
948 #endif // ENABLE(TOUCH_EVENTS)
949
950 #if HAVE(GTK_GESTURES)
951 GestureController& webkitWebViewBaseGestureController(WebKitWebViewBase* webViewBase)
952 {
953     WebKitWebViewBasePrivate* priv = webViewBase->priv;
954     if (!priv->gestureController)
955         priv->gestureController = std::make_unique<GestureController>(*priv->pageProxy);
956     return *priv->gestureController;
957 }
958 #endif
959
960 static gboolean webkitWebViewBaseQueryTooltip(GtkWidget* widget, gint /* x */, gint /* y */, gboolean keyboardMode, GtkTooltip* tooltip)
961 {
962     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
963
964     if (keyboardMode) {
965         // TODO: https://bugs.webkit.org/show_bug.cgi?id=61732.
966         notImplemented();
967         return FALSE;
968     }
969
970     if (priv->tooltipText.length() <= 0)
971         return FALSE;
972
973     if (!priv->tooltipArea.isEmpty()) {
974         GdkRectangle area = priv->tooltipArea;
975         gtk_tooltip_set_tip_area(tooltip, &area);
976     } else
977         gtk_tooltip_set_tip_area(tooltip, 0);
978     gtk_tooltip_set_text(tooltip, priv->tooltipText.data());
979
980     return TRUE;
981 }
982
983 #if ENABLE(DRAG_SUPPORT)
984 static void webkitWebViewBaseDragDataGet(GtkWidget* widget, GdkDragContext* context, GtkSelectionData* selectionData, guint info, guint /* time */)
985 {
986     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
987     ASSERT(priv->dragAndDropHandler);
988     priv->dragAndDropHandler->fillDragData(context, selectionData, info);
989 }
990
991 static void webkitWebViewBaseDragEnd(GtkWidget* widget, GdkDragContext* context)
992 {
993     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
994     ASSERT(priv->dragAndDropHandler);
995     priv->dragAndDropHandler->finishDrag(context);
996 }
997
998 static void webkitWebViewBaseDragDataReceived(GtkWidget* widget, GdkDragContext* context, gint /* x */, gint /* y */, GtkSelectionData* selectionData, guint info, guint time)
999 {
1000     webkitWebViewBaseDragAndDropHandler(WEBKIT_WEB_VIEW_BASE(widget)).dragEntered(context, selectionData, info, time);
1001 }
1002 #endif // ENABLE(DRAG_SUPPORT)
1003
1004 static AtkObject* webkitWebViewBaseGetAccessible(GtkWidget* widget)
1005 {
1006     // If the socket has already been created and embedded a plug ID, return it.
1007     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1008     if (priv->accessible && atk_socket_is_occupied(ATK_SOCKET(priv->accessible.get())))
1009         return priv->accessible.get();
1010
1011     // Create the accessible object and associate it to the widget.
1012     if (!priv->accessible) {
1013         priv->accessible = adoptGRef(ATK_OBJECT(webkitWebViewBaseAccessibleNew(widget)));
1014
1015         // Set the parent not to break bottom-up navigation.
1016         GtkWidget* parentWidget = gtk_widget_get_parent(widget);
1017         AtkObject* axParent = parentWidget ? gtk_widget_get_accessible(parentWidget) : 0;
1018         if (axParent)
1019             atk_object_set_parent(priv->accessible.get(), axParent);
1020     }
1021
1022     // Try to embed the plug in the socket, if posssible.
1023     String plugID = priv->pageProxy->accessibilityPlugID();
1024     if (plugID.isNull())
1025         return priv->accessible.get();
1026
1027     atk_socket_embed(ATK_SOCKET(priv->accessible.get()), const_cast<gchar*>(plugID.utf8().data()));
1028
1029     return priv->accessible.get();
1030 }
1031
1032 #if ENABLE(DRAG_SUPPORT)
1033 static gboolean webkitWebViewBaseDragMotion(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
1034 {
1035     webkitWebViewBaseDragAndDropHandler(WEBKIT_WEB_VIEW_BASE(widget)).dragMotion(context, IntPoint(x, y), time);
1036     return TRUE;
1037 }
1038
1039 static void webkitWebViewBaseDragLeave(GtkWidget* widget, GdkDragContext* context, guint /* time */)
1040 {
1041     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1042     ASSERT(priv->dragAndDropHandler);
1043     priv->dragAndDropHandler->dragLeave(context);
1044 }
1045
1046 static gboolean webkitWebViewBaseDragDrop(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
1047 {
1048     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1049     ASSERT(priv->dragAndDropHandler);
1050     return priv->dragAndDropHandler->drop(context, IntPoint(x, y), time);
1051 }
1052 #endif // ENABLE(DRAG_SUPPORT)
1053
1054 static void webkitWebViewBaseHierarchyChanged(GtkWidget* widget, GtkWidget* oldToplevel)
1055 {
1056     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1057     if (widgetIsOnscreenToplevelWindow(oldToplevel) && GTK_WINDOW(oldToplevel) == priv->toplevelOnScreenWindow) {
1058         webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), nullptr);
1059         return;
1060     }
1061
1062     if (!oldToplevel) {
1063         GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
1064         if (widgetIsOnscreenToplevelWindow(toplevel))
1065             webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), GTK_WINDOW(toplevel));
1066     }
1067 }
1068
1069 static gboolean webkitWebViewBaseFocus(GtkWidget* widget, GtkDirectionType direction)
1070 {
1071     // If the authentication dialog is active, we need to forward focus events there. This
1072     // ensures that you can tab between elements in the box.
1073     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1074     if (priv->authenticationDialog) {
1075         gboolean returnValue;
1076         g_signal_emit_by_name(priv->authenticationDialog, "focus", direction, &returnValue);
1077         return returnValue;
1078     }
1079
1080     return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus(widget, direction);
1081 }
1082
1083 static void webkitWebViewBaseDestroy(GtkWidget* widget)
1084 {
1085     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1086     if (priv->authenticationDialog)
1087         gtk_widget_destroy(priv->authenticationDialog);
1088
1089     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->destroy(widget);
1090 }
1091
1092 static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebViewBaseClass)
1093 {
1094     GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webkitWebViewBaseClass);
1095     widgetClass->realize = webkitWebViewBaseRealize;
1096     widgetClass->unrealize = webkitWebViewBaseUnrealize;
1097     widgetClass->draw = webkitWebViewBaseDraw;
1098     widgetClass->size_allocate = webkitWebViewBaseSizeAllocate;
1099     widgetClass->get_preferred_width = webkitWebViewBaseGetPreferredWidth;
1100     widgetClass->get_preferred_height = webkitWebViewBaseGetPreferredHeight;
1101     widgetClass->map = webkitWebViewBaseMap;
1102     widgetClass->unmap = webkitWebViewBaseUnmap;
1103     widgetClass->focus = webkitWebViewBaseFocus;
1104     widgetClass->focus_in_event = webkitWebViewBaseFocusInEvent;
1105     widgetClass->focus_out_event = webkitWebViewBaseFocusOutEvent;
1106     widgetClass->key_press_event = webkitWebViewBaseKeyPressEvent;
1107     widgetClass->key_release_event = webkitWebViewBaseKeyReleaseEvent;
1108     widgetClass->button_press_event = webkitWebViewBaseButtonPressEvent;
1109     widgetClass->button_release_event = webkitWebViewBaseButtonReleaseEvent;
1110     widgetClass->scroll_event = webkitWebViewBaseScrollEvent;
1111     widgetClass->motion_notify_event = webkitWebViewBaseMotionNotifyEvent;
1112     widgetClass->enter_notify_event = webkitWebViewBaseCrossingNotifyEvent;
1113     widgetClass->leave_notify_event = webkitWebViewBaseCrossingNotifyEvent;
1114 #if ENABLE(TOUCH_EVENTS)
1115     widgetClass->touch_event = webkitWebViewBaseTouchEvent;
1116 #endif
1117     widgetClass->query_tooltip = webkitWebViewBaseQueryTooltip;
1118 #if ENABLE(DRAG_SUPPORT)
1119     widgetClass->drag_end = webkitWebViewBaseDragEnd;
1120     widgetClass->drag_data_get = webkitWebViewBaseDragDataGet;
1121     widgetClass->drag_motion = webkitWebViewBaseDragMotion;
1122     widgetClass->drag_leave = webkitWebViewBaseDragLeave;
1123     widgetClass->drag_drop = webkitWebViewBaseDragDrop;
1124     widgetClass->drag_data_received = webkitWebViewBaseDragDataReceived;
1125 #endif // ENABLE(DRAG_SUPPORT)
1126     widgetClass->get_accessible = webkitWebViewBaseGetAccessible;
1127     widgetClass->hierarchy_changed = webkitWebViewBaseHierarchyChanged;
1128     widgetClass->destroy = webkitWebViewBaseDestroy;
1129
1130     GObjectClass* gobjectClass = G_OBJECT_CLASS(webkitWebViewBaseClass);
1131     gobjectClass->constructed = webkitWebViewBaseConstructed;
1132     gobjectClass->dispose = webkitWebViewBaseDispose;
1133
1134     GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webkitWebViewBaseClass);
1135     containerClass->add = webkitWebViewBaseContainerAdd;
1136     containerClass->remove = webkitWebViewBaseContainerRemove;
1137     containerClass->forall = webkitWebViewBaseContainerForall;
1138
1139     // Before creating a WebKitWebViewBasePriv we need to be sure that WebKit is started.
1140     // Usually starting a context triggers InitializeWebKit2, but in case
1141     // we create a view without asking before for a default_context we get a crash.
1142     WebKit::InitializeWebKit2();
1143 }
1144
1145 WebKitWebViewBase* webkitWebViewBaseCreate(const API::PageConfiguration& configuration)
1146 {
1147     WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(g_object_new(WEBKIT_TYPE_WEB_VIEW_BASE, nullptr));
1148     webkitWebViewBaseCreateWebPage(webkitWebViewBase, configuration.copy());
1149     return webkitWebViewBase;
1150 }
1151
1152 GtkIMContext* webkitWebViewBaseGetIMContext(WebKitWebViewBase* webkitWebViewBase)
1153 {
1154     return webkitWebViewBase->priv->inputMethodFilter.context();
1155 }
1156
1157 WebPageProxy* webkitWebViewBaseGetPage(WebKitWebViewBase* webkitWebViewBase)
1158 {
1159     return webkitWebViewBase->priv->pageProxy.get();
1160 }
1161
1162 #if HAVE(GTK_SCALE_FACTOR)
1163 static void deviceScaleFactorChanged(WebKitWebViewBase* webkitWebViewBase)
1164 {
1165     webkitWebViewBase->priv->pageProxy->setIntrinsicDeviceScaleFactor(gtk_widget_get_scale_factor(GTK_WIDGET(webkitWebViewBase)));
1166 }
1167 #endif // HAVE(GTK_SCALE_FACTOR)
1168
1169 void webkitWebViewBaseCreateWebPage(WebKitWebViewBase* webkitWebViewBase, Ref<API::PageConfiguration>&& configuration)
1170 {
1171     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1172     WebProcessPool* processPool = configuration->processPool();
1173     priv->pageProxy = processPool->createWebPage(*priv->pageClient, WTFMove(configuration));
1174     priv->pageProxy->initializeWebPage();
1175
1176     priv->acceleratedBackingStore = AcceleratedBackingStore::create(*priv->pageProxy);
1177
1178     priv->inputMethodFilter.setPage(priv->pageProxy.get());
1179
1180 #if HAVE(GTK_SCALE_FACTOR)
1181     // We attach this here, because changes in scale factor are passed directly to the page proxy.
1182     priv->pageProxy->setIntrinsicDeviceScaleFactor(gtk_widget_get_scale_factor(GTK_WIDGET(webkitWebViewBase)));
1183     g_signal_connect(webkitWebViewBase, "notify::scale-factor", G_CALLBACK(deviceScaleFactorChanged), nullptr);
1184 #endif
1185 }
1186
1187 void webkitWebViewBaseSetTooltipText(WebKitWebViewBase* webViewBase, const char* tooltip)
1188 {
1189     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1190     if (tooltip && tooltip[0] != '\0') {
1191         priv->tooltipText = tooltip;
1192         gtk_widget_set_has_tooltip(GTK_WIDGET(webViewBase), TRUE);
1193     } else {
1194         priv->tooltipText = "";
1195         gtk_widget_set_has_tooltip(GTK_WIDGET(webViewBase), FALSE);
1196     }
1197
1198     gtk_widget_trigger_tooltip_query(GTK_WIDGET(webViewBase));
1199 }
1200
1201 void webkitWebViewBaseSetTooltipArea(WebKitWebViewBase* webViewBase, const IntRect& tooltipArea)
1202 {
1203     webViewBase->priv->tooltipArea = tooltipArea;
1204 }
1205
1206 #if ENABLE(DRAG_SUPPORT)
1207 DragAndDropHandler& webkitWebViewBaseDragAndDropHandler(WebKitWebViewBase* webViewBase)
1208 {
1209     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1210     if (!priv->dragAndDropHandler)
1211         priv->dragAndDropHandler = std::make_unique<DragAndDropHandler>(*priv->pageProxy);
1212     return *priv->dragAndDropHandler;
1213 }
1214 #endif // ENABLE(DRAG_SUPPORT)
1215
1216 void webkitWebViewBaseForwardNextKeyEvent(WebKitWebViewBase* webkitWebViewBase)
1217 {
1218     webkitWebViewBase->priv->shouldForwardNextKeyEvent = TRUE;
1219 }
1220
1221 void webkitWebViewBaseForwardNextWheelEvent(WebKitWebViewBase* webkitWebViewBase)
1222 {
1223     webkitWebViewBase->priv->shouldForwardNextWheelEvent = true;
1224 }
1225
1226 #if ENABLE(FULLSCREEN_API)
1227 static void screenSaverInhibitedCallback(GDBusProxy* screenSaverProxy, GAsyncResult* result, WebKitWebViewBase* webViewBase)
1228 {
1229     GRefPtr<GVariant> returnValue = adoptGRef(g_dbus_proxy_call_finish(screenSaverProxy, result, nullptr));
1230     if (returnValue)
1231         g_variant_get(returnValue.get(), "(u)", &webViewBase->priv->screenSaverCookie);
1232     webViewBase->priv->screenSaverInhibitCancellable = nullptr;
1233 }
1234
1235 static void webkitWebViewBaseSendInhibitMessageToScreenSaver(WebKitWebViewBase* webViewBase)
1236 {
1237     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1238     ASSERT(priv->screenSaverProxy);
1239     priv->screenSaverCookie = 0;
1240     if (!priv->screenSaverInhibitCancellable)
1241         priv->screenSaverInhibitCancellable = adoptGRef(g_cancellable_new());
1242     g_dbus_proxy_call(priv->screenSaverProxy.get(), "Inhibit", g_variant_new("(ss)", g_get_prgname(), _("Website running in fullscreen mode")),
1243         G_DBUS_CALL_FLAGS_NONE, -1, priv->screenSaverInhibitCancellable.get(), reinterpret_cast<GAsyncReadyCallback>(screenSaverInhibitedCallback), webViewBase);
1244 }
1245
1246 static void screenSaverProxyCreatedCallback(GObject*, GAsyncResult* result, WebKitWebViewBase* webViewBase)
1247 {
1248     // WebKitWebViewBase cancels the proxy creation on dispose, which means this could be called
1249     // after the web view has been destroyed and g_dbus_proxy_new_for_bus_finish will return nullptr.
1250     // So, make sure we don't use the web view unless we have a valid proxy.
1251     // See https://bugs.webkit.org/show_bug.cgi?id=151653.
1252     GRefPtr<GDBusProxy> proxy = adoptGRef(g_dbus_proxy_new_for_bus_finish(result, nullptr));
1253     if (!proxy)
1254         return;
1255
1256     webViewBase->priv->screenSaverProxy = proxy;
1257     webkitWebViewBaseSendInhibitMessageToScreenSaver(webViewBase);
1258 }
1259
1260 static void webkitWebViewBaseInhibitScreenSaver(WebKitWebViewBase* webViewBase)
1261 {
1262     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1263     if (priv->screenSaverCookie) {
1264         // Already inhibited.
1265         return;
1266     }
1267
1268     if (priv->screenSaverProxy) {
1269         webkitWebViewBaseSendInhibitMessageToScreenSaver(webViewBase);
1270         return;
1271     }
1272
1273     priv->screenSaverInhibitCancellable = adoptGRef(g_cancellable_new());
1274     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),
1275         nullptr, "org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver", priv->screenSaverInhibitCancellable.get(),
1276         reinterpret_cast<GAsyncReadyCallback>(screenSaverProxyCreatedCallback), webViewBase);
1277 }
1278
1279 static void webkitWebViewBaseUninhibitScreenSaver(WebKitWebViewBase* webViewBase)
1280 {
1281     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1282     if (!priv->screenSaverCookie) {
1283         // Not inhibited or it's being inhibited.
1284         g_cancellable_cancel(priv->screenSaverInhibitCancellable.get());
1285         return;
1286     }
1287
1288     // If we have a cookie we should have a proxy.
1289     ASSERT(priv->screenSaverProxy);
1290     g_dbus_proxy_call(priv->screenSaverProxy.get(), "UnInhibit", g_variant_new("(u)", priv->screenSaverCookie), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr, nullptr);
1291     priv->screenSaverCookie = 0;
1292 }
1293 #endif
1294
1295 void webkitWebViewBaseEnterFullScreen(WebKitWebViewBase* webkitWebViewBase)
1296 {
1297 #if ENABLE(FULLSCREEN_API)
1298     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1299     if (priv->fullScreenModeActive)
1300         return;
1301
1302     if (!priv->fullScreenClient.willEnterFullScreen())
1303         return;
1304
1305     WebFullScreenManagerProxy* fullScreenManagerProxy = priv->pageProxy->fullScreenManager();
1306     fullScreenManagerProxy->willEnterFullScreen();
1307
1308     GtkWidget* topLevelWindow = gtk_widget_get_toplevel(GTK_WIDGET(webkitWebViewBase));
1309     if (gtk_widget_is_toplevel(topLevelWindow))
1310         gtk_window_fullscreen(GTK_WINDOW(topLevelWindow));
1311     fullScreenManagerProxy->didEnterFullScreen();
1312     priv->fullScreenModeActive = true;
1313     webkitWebViewBaseInhibitScreenSaver(webkitWebViewBase);
1314 #endif
1315 }
1316
1317 void webkitWebViewBaseExitFullScreen(WebKitWebViewBase* webkitWebViewBase)
1318 {
1319 #if ENABLE(FULLSCREEN_API)
1320     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1321     if (!priv->fullScreenModeActive)
1322         return;
1323
1324     if (!priv->fullScreenClient.willExitFullScreen())
1325         return;
1326
1327     WebFullScreenManagerProxy* fullScreenManagerProxy = priv->pageProxy->fullScreenManager();
1328     fullScreenManagerProxy->willExitFullScreen();
1329
1330     GtkWidget* topLevelWindow = gtk_widget_get_toplevel(GTK_WIDGET(webkitWebViewBase));
1331     if (gtk_widget_is_toplevel(topLevelWindow))
1332         gtk_window_unfullscreen(GTK_WINDOW(topLevelWindow));
1333     fullScreenManagerProxy->didExitFullScreen();
1334     priv->fullScreenModeActive = false;
1335     webkitWebViewBaseUninhibitScreenSaver(webkitWebViewBase);
1336 #endif
1337 }
1338
1339 void webkitWebViewBaseInitializeFullScreenClient(WebKitWebViewBase* webkitWebViewBase, const WKFullScreenClientGtkBase* wkClient)
1340 {
1341     webkitWebViewBase->priv->fullScreenClient.initialize(wkClient);
1342 }
1343
1344 void webkitWebViewBaseSetInspectorViewSize(WebKitWebViewBase* webkitWebViewBase, unsigned size)
1345 {
1346     if (webkitWebViewBase->priv->inspectorViewSize == size)
1347         return;
1348     webkitWebViewBase->priv->inspectorViewSize = size;
1349     if (webkitWebViewBase->priv->inspectorView)
1350         gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webkitWebViewBase));
1351 }
1352
1353 static void activeContextMenuUnmapped(GtkMenu* menu, WebKitWebViewBase* webViewBase)
1354 {
1355     if (webViewBase->priv->activeContextMenuProxy && webViewBase->priv->activeContextMenuProxy->gtkMenu() == menu)
1356         webViewBase->priv->activeContextMenuProxy = nullptr;
1357 }
1358
1359 void webkitWebViewBaseSetActiveContextMenuProxy(WebKitWebViewBase* webkitWebViewBase, WebContextMenuProxyGtk* contextMenuProxy)
1360 {
1361     webkitWebViewBase->priv->activeContextMenuProxy = contextMenuProxy;
1362     g_signal_connect_object(contextMenuProxy->gtkMenu(), "unmap", G_CALLBACK(activeContextMenuUnmapped), webkitWebViewBase, static_cast<GConnectFlags>(0));
1363 }
1364
1365 WebContextMenuProxyGtk* webkitWebViewBaseGetActiveContextMenuProxy(WebKitWebViewBase* webkitWebViewBase)
1366 {
1367     return webkitWebViewBase->priv->activeContextMenuProxy;
1368 }
1369
1370 GdkEvent* webkitWebViewBaseTakeContextMenuEvent(WebKitWebViewBase* webkitWebViewBase)
1371 {
1372     return webkitWebViewBase->priv->contextMenuEvent.release();
1373 }
1374
1375 void webkitWebViewBaseSetFocus(WebKitWebViewBase* webViewBase, bool focused)
1376 {
1377     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1378     if ((focused && priv->viewState & ViewState::IsFocused) || (!focused && !(priv->viewState & ViewState::IsFocused)))
1379         return;
1380
1381     ViewState::Flags flagsToUpdate = ViewState::IsFocused;
1382     if (focused) {
1383         priv->viewState |= ViewState::IsFocused;
1384
1385         // If the view has received the focus and the window is not active
1386         // mark the current window as active now. This can happen if the
1387         // toplevel window is a GTK_WINDOW_POPUP and the focus has been
1388         // set programatically like WebKitTestRunner does, because POPUP
1389         // can't be focused.
1390         if (!(priv->viewState & ViewState::WindowIsActive)) {
1391             priv->viewState |= ViewState::WindowIsActive;
1392             flagsToUpdate |= ViewState::WindowIsActive;
1393         }
1394     } else
1395         priv->viewState &= ~ViewState::IsFocused;
1396
1397     webkitWebViewBaseScheduleUpdateViewState(webViewBase, flagsToUpdate);
1398 }
1399
1400 bool webkitWebViewBaseIsInWindowActive(WebKitWebViewBase* webViewBase)
1401 {
1402     return webViewBase->priv->viewState & ViewState::WindowIsActive;
1403 }
1404
1405 bool webkitWebViewBaseIsFocused(WebKitWebViewBase* webViewBase)
1406 {
1407     return webViewBase->priv->viewState & ViewState::IsFocused;
1408 }
1409
1410 bool webkitWebViewBaseIsVisible(WebKitWebViewBase* webViewBase)
1411 {
1412     return webViewBase->priv->viewState & ViewState::IsVisible;
1413 }
1414
1415 bool webkitWebViewBaseIsInWindow(WebKitWebViewBase* webViewBase)
1416 {
1417     return webViewBase->priv->viewState & ViewState::IsInWindow;
1418 }
1419
1420 void webkitWebViewBaseSetDownloadRequestHandler(WebKitWebViewBase* webViewBase, WebKitWebViewBaseDownloadRequestHandler downloadHandler)
1421 {
1422     webViewBase->priv->downloadHandler = downloadHandler;
1423 }
1424
1425 void webkitWebViewBaseHandleDownloadRequest(WebKitWebViewBase* webViewBase, DownloadProxy* download)
1426 {
1427     if (webViewBase->priv->downloadHandler)
1428         webViewBase->priv->downloadHandler(webViewBase, download);
1429 }
1430
1431 void webkitWebViewBaseSetInputMethodState(WebKitWebViewBase* webkitWebViewBase, bool enabled)
1432 {
1433     webkitWebViewBase->priv->inputMethodFilter.setEnabled(enabled);
1434 }
1435
1436 void webkitWebViewBaseUpdateTextInputState(WebKitWebViewBase* webkitWebViewBase)
1437 {
1438     const auto& editorState = webkitWebViewBase->priv->pageProxy->editorState();
1439     if (!editorState.isMissingPostLayoutData)
1440         webkitWebViewBase->priv->inputMethodFilter.setCursorRect(editorState.postLayoutData().caretRectAtStart);
1441 }
1442
1443 void webkitWebViewBaseSetContentsSize(WebKitWebViewBase* webkitWebViewBase, const IntSize& contentsSize)
1444 {
1445     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1446     if (priv->contentsSize == contentsSize)
1447         return;
1448     priv->contentsSize = contentsSize;
1449 }
1450
1451 void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase)
1452 {
1453     webkitWebViewBase->priv->clickCounter.reset();
1454 }
1455
1456 void webkitWebViewBaseEnterAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext)
1457 {
1458     if (webkitWebViewBase->priv->acceleratedBackingStore)
1459         webkitWebViewBase->priv->acceleratedBackingStore->update(layerTreeContext);
1460 }
1461
1462 void webkitWebViewBaseUpdateAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext)
1463 {
1464     if (webkitWebViewBase->priv->acceleratedBackingStore)
1465         webkitWebViewBase->priv->acceleratedBackingStore->update(layerTreeContext);
1466 }
1467
1468 void webkitWebViewBaseExitAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase)
1469 {
1470     if (webkitWebViewBase->priv->acceleratedBackingStore)
1471         webkitWebViewBase->priv->acceleratedBackingStore->update(LayerTreeContext());
1472 }
1473
1474 void webkitWebViewBaseDidRelaunchWebProcess(WebKitWebViewBase* webkitWebViewBase)
1475 {
1476     // Queue a resize to ensure the new DrawingAreaProxy is resized.
1477     gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webkitWebViewBase));
1478
1479 #if PLATFORM(X11) && USE(TEXTURE_MAPPER) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
1480     if (PlatformDisplay::sharedDisplay().type() != PlatformDisplay::Type::X11)
1481         return;
1482
1483     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1484     DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea());
1485     ASSERT(drawingArea);
1486
1487     if (!gtk_widget_get_realized(GTK_WIDGET(webkitWebViewBase)))
1488         return;
1489
1490     uint64_t windowID = GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(webkitWebViewBase)));
1491     drawingArea->setNativeSurfaceHandleForCompositing(windowID);
1492 #else
1493     UNUSED_PARAM(webkitWebViewBase);
1494 #endif
1495 }
1496
1497 void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase)
1498 {
1499     if (webkitWebViewBase->priv->acceleratedBackingStore)
1500         webkitWebViewBase->priv->acceleratedBackingStore->update(LayerTreeContext());
1501 #if PLATFORM(X11) && USE(TEXTURE_MAPPER) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
1502     if (PlatformDisplay::sharedDisplay().type() != PlatformDisplay::Type::X11)
1503         return;
1504
1505     if (!gtk_widget_get_realized(GTK_WIDGET(webkitWebViewBase)))
1506         return;
1507
1508     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1509     DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea());
1510     ASSERT(drawingArea);
1511     drawingArea->destroyNativeSurfaceHandleForCompositing();
1512 #endif
1513 }