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>.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
30 #include "WebKitWebViewBase.h"
32 #include "APIPageConfiguration.h"
33 #include "AcceleratedBackingStore.h"
34 #include "DrawingAreaProxyCoordinatedGraphics.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 "ViewGestureController.h"
42 #include "WebEventFactory.h"
43 #include "WebInspectorProxy.h"
44 #include "WebKit2Initialize.h"
45 #include "WebKitWebViewBaseAccessible.h"
46 #include "WebKitWebViewBasePrivate.h"
47 #include "WebPageGroup.h"
48 #include "WebPageProxy.h"
49 #include "WebPreferences.h"
50 #include "WebProcessPool.h"
51 #include "WebUserContentControllerProxy.h"
52 #include <WebCore/ActivityState.h>
53 #include <WebCore/CairoUtilities.h>
54 #include <WebCore/GUniquePtrGtk.h>
55 #include <WebCore/GtkUtilities.h>
56 #include <WebCore/GtkVersioning.h>
57 #include <WebCore/NotImplemented.h>
58 #include <WebCore/PasteboardHelper.h>
59 #include <WebCore/PlatformDisplay.h>
60 #include <WebCore/RefPtrCairo.h>
61 #include <WebCore/Region.h>
63 #include <gdk/gdkkeysyms.h>
64 #include <glib/gi18n-lib.h>
66 #include <pal/system/SleepDisabler.h>
67 #include <wtf/Compiler.h>
68 #include <wtf/HashMap.h>
69 #include <wtf/glib/GRefPtr.h>
70 #include <wtf/glib/WTFGType.h>
71 #include <wtf/text/CString.h>
73 #if ENABLE(FULLSCREEN_API)
74 #include "WebFullScreenManagerProxy.h"
81 // gtk_widget_get_scale_factor() appeared in GTK 3.10, but we also need
82 // to make sure we have cairo new enough to support cairo_surface_set_device_scale
83 #define HAVE_GTK_SCALE_FACTOR HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE && GTK_CHECK_VERSION(3, 10, 0)
85 using namespace WebKit;
86 using namespace WebCore;
92 currentClickCount = 0;
93 previousClickPoint = IntPoint();
94 previousClickTime = 0;
95 previousClickButton = 0;
98 int currentClickCountForGdkButtonEvent(GdkEvent* event)
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);
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);
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.
115 g_get_current_time(&timeValue);
116 eventTime = (timeValue.tv_sec * 1000) + (timeValue.tv_usec / 1000);
119 if ((event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
120 || ((std::abs(event->button.x - previousClickPoint.x()) < doubleClickDistance)
121 && (std::abs(event->button.y - previousClickPoint.y()) < doubleClickDistance)
122 && (eventTime - previousClickTime < static_cast<unsigned>(doubleClickTime))
123 && (event->button.button == previousClickButton)))
126 currentClickCount = 1;
129 gdk_event_get_coords(event, &x, &y);
130 previousClickPoint = IntPoint(x, y);
131 previousClickButton = event->button.button;
132 previousClickTime = eventTime;
134 return currentClickCount;
138 int currentClickCount;
139 IntPoint previousClickPoint;
140 unsigned previousClickButton;
141 int previousClickTime;
144 typedef HashMap<GtkWidget*, IntRect> WebKitWebViewChildrenMap;
145 typedef HashMap<uint32_t, GUniquePtr<GdkEvent>> TouchEventsMap;
147 struct _WebKitWebViewBasePrivate {
148 _WebKitWebViewBasePrivate()
149 : updateActivityStateTimer(RunLoop::main(), this, &_WebKitWebViewBasePrivate::updateActivityStateTimerFired)
153 void updateActivityStateTimerFired()
157 pageProxy->activityStateDidChange(activityStateFlagsToUpdate);
158 activityStateFlagsToUpdate = { };
161 WebKitWebViewChildrenMap children;
162 std::unique_ptr<PageClientImpl> pageClient;
163 RefPtr<WebPageProxy> pageProxy;
164 bool shouldForwardNextKeyEvent { false };
165 bool shouldForwardNextWheelEvent { false };
166 ClickCounter clickCounter;
169 GRefPtr<AtkObject> accessible;
170 GtkWidget* dialog { nullptr };
171 GtkWidget* inspectorView { nullptr };
172 AttachmentSide inspectorAttachmentSide { AttachmentSide::Bottom };
173 unsigned inspectorViewSize { 0 };
174 GUniquePtr<GdkEvent> contextMenuEvent;
175 WebContextMenuProxyGtk* activeContextMenuProxy { nullptr };
176 InputMethodFilter inputMethodFilter;
177 KeyBindingTranslator keyBindingTranslator;
178 TouchEventsMap touchEvents;
179 IntSize contentsSize;
181 GtkWindow* toplevelOnScreenWindow { nullptr };
182 unsigned long toplevelFocusInEventID { 0 };
183 unsigned long toplevelFocusOutEventID { 0 };
184 unsigned long toplevelWindowStateEventID { 0 };
185 unsigned long toplevelWindowRealizedID { 0 };
186 unsigned long themeChangedID { 0 };
187 unsigned long applicationPreferDarkThemeID { 0 };
190 OptionSet<ActivityState::Flag> activityState;
191 OptionSet<ActivityState::Flag> activityStateFlagsToUpdate;
192 RunLoop::Timer<WebKitWebViewBasePrivate> updateActivityStateTimer;
194 #if ENABLE(FULLSCREEN_API)
195 bool fullScreenModeActive { false };
196 std::unique_ptr<PAL::SleepDisabler> sleepDisabler;
199 std::unique_ptr<AcceleratedBackingStore> acceleratedBackingStore;
201 #if ENABLE(DRAG_SUPPORT)
202 std::unique_ptr<DragAndDropHandler> dragAndDropHandler;
205 #if HAVE(GTK_GESTURES)
206 std::unique_ptr<GestureController> gestureController;
208 std::unique_ptr<ViewGestureController> viewGestureController;
211 WEBKIT_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER)
213 static void webkitWebViewBaseScheduleUpdateActivityState(WebKitWebViewBase* webViewBase, OptionSet<ActivityState::Flag> flagsToUpdate)
215 WebKitWebViewBasePrivate* priv = webViewBase->priv;
216 priv->activityStateFlagsToUpdate.add(flagsToUpdate);
217 if (priv->updateActivityStateTimer.isActive())
220 priv->updateActivityStateTimer.startOneShot(0_s);
223 static gboolean toplevelWindowFocusInEvent(GtkWidget* widget, GdkEventFocus*, WebKitWebViewBase* webViewBase)
225 // Spurious focus in events can occur when the window is hidden.
226 if (!gtk_widget_get_visible(widget))
229 WebKitWebViewBasePrivate* priv = webViewBase->priv;
230 if (priv->activityState & ActivityState::WindowIsActive)
233 priv->activityState.add(ActivityState::WindowIsActive);
234 webkitWebViewBaseScheduleUpdateActivityState(webViewBase, ActivityState::WindowIsActive);
239 static gboolean toplevelWindowFocusOutEvent(GtkWidget*, GdkEventFocus*, WebKitWebViewBase* webViewBase)
241 WebKitWebViewBasePrivate* priv = webViewBase->priv;
242 if (!(priv->activityState & ActivityState::WindowIsActive))
245 priv->activityState.remove(ActivityState::WindowIsActive);
246 webkitWebViewBaseScheduleUpdateActivityState(webViewBase, ActivityState::WindowIsActive);
251 static gboolean toplevelWindowStateEvent(GtkWidget*, GdkEventWindowState* event, WebKitWebViewBase* webViewBase)
253 WebKitWebViewBasePrivate* priv = webViewBase->priv;
254 if (!(event->changed_mask & GDK_WINDOW_STATE_ICONIFIED))
257 bool visible = !(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED);
258 if ((visible && priv->activityState & ActivityState::IsVisible) || (!visible && !(priv->activityState & ActivityState::IsVisible)))
262 priv->activityState.add(ActivityState::IsVisible);
264 priv->activityState.remove(ActivityState::IsVisible);
265 webkitWebViewBaseScheduleUpdateActivityState(webViewBase, ActivityState::IsVisible);
270 static void themeChanged(WebKitWebViewBase* webViewBase)
272 webViewBase->priv->pageProxy->effectiveAppearanceDidChange();
275 static void toplevelWindowRealized(WebKitWebViewBase* webViewBase)
277 gtk_widget_realize(GTK_WIDGET(webViewBase));
279 WebKitWebViewBasePrivate* priv = webViewBase->priv;
280 if (priv->toplevelWindowRealizedID) {
281 g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelWindowRealizedID);
282 priv->toplevelWindowRealizedID = 0;
286 static void webkitWebViewBaseSetToplevelOnScreenWindow(WebKitWebViewBase* webViewBase, GtkWindow* window)
288 WebKitWebViewBasePrivate* priv = webViewBase->priv;
289 if (priv->toplevelOnScreenWindow == window)
292 if (priv->toplevelFocusInEventID) {
293 g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelFocusInEventID);
294 priv->toplevelFocusInEventID = 0;
296 if (priv->toplevelFocusOutEventID) {
297 g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelFocusOutEventID);
298 priv->toplevelFocusOutEventID = 0;
300 if (priv->toplevelWindowStateEventID) {
301 g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelWindowStateEventID);
302 priv->toplevelWindowStateEventID = 0;
304 if (priv->toplevelWindowRealizedID) {
305 g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelWindowRealizedID);
306 priv->toplevelWindowRealizedID = 0;
308 if (priv->themeChangedID || priv->applicationPreferDarkThemeID) {
309 auto* settings = gtk_widget_get_settings(GTK_WIDGET(priv->toplevelOnScreenWindow));
310 if (priv->themeChangedID) {
311 g_signal_handler_disconnect(settings, priv->themeChangedID);
312 priv->themeChangedID = 0;
314 if (priv->applicationPreferDarkThemeID) {
315 g_signal_handler_disconnect(settings, priv->applicationPreferDarkThemeID);
316 priv->applicationPreferDarkThemeID = 0;
320 priv->toplevelOnScreenWindow = window;
322 if (!priv->toplevelOnScreenWindow) {
323 OptionSet<ActivityState::Flag> flagsToUpdate;
324 if (priv->activityState & ActivityState::IsInWindow) {
325 priv->activityState.remove(ActivityState::IsInWindow);
326 flagsToUpdate.add(ActivityState::IsInWindow);
328 if (priv->activityState & ActivityState::WindowIsActive) {
329 priv->activityState.remove(ActivityState::WindowIsActive);
330 flagsToUpdate.add(ActivityState::IsInWindow);
333 webkitWebViewBaseScheduleUpdateActivityState(webViewBase, flagsToUpdate);
338 priv->toplevelFocusInEventID =
339 g_signal_connect(priv->toplevelOnScreenWindow, "focus-in-event",
340 G_CALLBACK(toplevelWindowFocusInEvent), webViewBase);
341 priv->toplevelFocusOutEventID =
342 g_signal_connect(priv->toplevelOnScreenWindow, "focus-out-event",
343 G_CALLBACK(toplevelWindowFocusOutEvent), webViewBase);
344 priv->toplevelWindowStateEventID =
345 g_signal_connect(priv->toplevelOnScreenWindow, "window-state-event", G_CALLBACK(toplevelWindowStateEvent), webViewBase);
347 auto* settings = gtk_widget_get_settings(GTK_WIDGET(priv->toplevelOnScreenWindow));
348 priv->themeChangedID =
349 g_signal_connect_swapped(settings, "notify::gtk-theme-name", G_CALLBACK(themeChanged), webViewBase);
350 priv->applicationPreferDarkThemeID =
351 g_signal_connect_swapped(settings, "notify::gtk-application-prefer-dark-theme", G_CALLBACK(themeChanged), webViewBase);
353 if (gtk_widget_get_realized(GTK_WIDGET(window)))
354 gtk_widget_realize(GTK_WIDGET(webViewBase));
356 priv->toplevelWindowRealizedID = g_signal_connect_swapped(window, "realize", G_CALLBACK(toplevelWindowRealized), webViewBase);
359 static void webkitWebViewBaseRealize(GtkWidget* widget)
361 WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(widget);
362 WebKitWebViewBasePrivate* priv = webView->priv;
364 gtk_widget_set_realized(widget, TRUE);
366 GtkAllocation allocation;
367 gtk_widget_get_allocation(widget, &allocation);
369 GdkWindowAttr attributes;
370 attributes.window_type = GDK_WINDOW_CHILD;
371 attributes.x = allocation.x;
372 attributes.y = allocation.y;
373 attributes.width = allocation.width;
374 attributes.height = allocation.height;
375 attributes.wclass = GDK_INPUT_OUTPUT;
376 attributes.visual = gtk_widget_get_visual(widget);
377 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK
379 | GDK_BUTTON_PRESS_MASK
380 | GDK_BUTTON_RELEASE_MASK
382 | GDK_SMOOTH_SCROLL_MASK
383 | GDK_POINTER_MOTION_MASK
384 | GDK_ENTER_NOTIFY_MASK
385 | GDK_LEAVE_NOTIFY_MASK
387 | GDK_KEY_RELEASE_MASK
388 | GDK_BUTTON_MOTION_MASK
389 | GDK_BUTTON1_MOTION_MASK
390 | GDK_BUTTON2_MOTION_MASK
391 | GDK_BUTTON3_MOTION_MASK
393 #if HAVE(GTK_GESTURES)
394 attributes.event_mask |= GDK_TOUCHPAD_GESTURE_MASK;
397 gint attributesMask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
399 GdkWindow* window = gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, attributesMask);
400 gtk_widget_set_window(widget, window);
401 gdk_window_set_user_data(window, widget);
403 #if USE(TEXTURE_MAPPER_GL) && PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
404 if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11) {
405 if (auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(priv->pageProxy->drawingArea()))
406 drawingArea->setNativeSurfaceHandleForCompositing(GDK_WINDOW_XID(window));
410 gtk_im_context_set_client_window(priv->inputMethodFilter.context(), window);
413 static void webkitWebViewBaseUnrealize(GtkWidget* widget)
415 WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(widget);
416 #if USE(TEXTURE_MAPPER_GL) && PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
417 if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11) {
418 if (auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(webView->priv->pageProxy->drawingArea()))
419 drawingArea->destroyNativeSurfaceHandleForCompositing();
422 gtk_im_context_set_client_window(webView->priv->inputMethodFilter.context(), nullptr);
424 GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->unrealize(widget);
427 static bool webkitWebViewChildIsInternalWidget(WebKitWebViewBase* webViewBase, GtkWidget* widget)
429 WebKitWebViewBasePrivate* priv = webViewBase->priv;
430 return widget == priv->inspectorView || widget == priv->dialog;
433 static void webkitWebViewBaseContainerAdd(GtkContainer* container, GtkWidget* widget)
435 WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
436 WebKitWebViewBasePrivate* priv = webView->priv;
438 // Internal widgets like the web inspector and authentication dialog have custom
439 // allocations so we don't need to add them to our list of children.
440 if (!webkitWebViewChildIsInternalWidget(webView, widget)) {
441 GtkAllocation childAllocation;
442 gtk_widget_get_allocation(widget, &childAllocation);
443 priv->children.set(widget, childAllocation);
446 gtk_widget_set_parent(widget, GTK_WIDGET(container));
449 void webkitWebViewBaseAddDialog(WebKitWebViewBase* webViewBase, GtkWidget* dialog)
451 WebKitWebViewBasePrivate* priv = webViewBase->priv;
452 priv->dialog = dialog;
453 gtk_container_add(GTK_CONTAINER(webViewBase), dialog);
454 gtk_widget_show(dialog);
456 // We need to draw the shadow over the widget.
457 gtk_widget_queue_draw(GTK_WIDGET(webViewBase));
460 void webkitWebViewBaseAddWebInspector(WebKitWebViewBase* webViewBase, GtkWidget* inspector, AttachmentSide attachmentSide)
462 if (webViewBase->priv->inspectorView == inspector && webViewBase->priv->inspectorAttachmentSide == attachmentSide)
465 webViewBase->priv->inspectorAttachmentSide = attachmentSide;
467 if (webViewBase->priv->inspectorView == inspector) {
468 gtk_widget_queue_resize(GTK_WIDGET(webViewBase));
472 webViewBase->priv->inspectorView = inspector;
473 gtk_container_add(GTK_CONTAINER(webViewBase), inspector);
476 static void webkitWebViewBaseContainerRemove(GtkContainer* container, GtkWidget* widget)
478 WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
479 WebKitWebViewBasePrivate* priv = webView->priv;
480 GtkWidget* widgetContainer = GTK_WIDGET(container);
482 gboolean wasVisible = gtk_widget_get_visible(widget);
483 gtk_widget_unparent(widget);
485 if (priv->inspectorView == widget) {
486 priv->inspectorView = 0;
487 priv->inspectorViewSize = 0;
488 } else if (priv->dialog == widget) {
489 priv->dialog = nullptr;
490 if (gtk_widget_get_visible(widgetContainer))
491 gtk_widget_grab_focus(widgetContainer);
493 ASSERT(priv->children.contains(widget));
494 priv->children.remove(widget);
496 if (wasVisible && gtk_widget_get_visible(widgetContainer))
497 gtk_widget_queue_resize(widgetContainer);
500 static void webkitWebViewBaseContainerForall(GtkContainer* container, gboolean includeInternals, GtkCallback callback, gpointer callbackData)
502 WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
503 WebKitWebViewBasePrivate* priv = webView->priv;
505 for (const auto& child : copyToVector(priv->children.keys())) {
506 if (priv->children.contains(child))
507 (*callback)(child, callbackData);
510 if (includeInternals && priv->inspectorView)
511 (*callback)(priv->inspectorView, callbackData);
513 if (includeInternals && priv->dialog)
514 (*callback)(priv->dialog, callbackData);
517 void webkitWebViewBaseChildMoveResize(WebKitWebViewBase* webView, GtkWidget* child, const IntRect& childRect)
519 const IntRect& geometry = webView->priv->children.get(child);
520 if (geometry == childRect)
523 webView->priv->children.set(child, childRect);
524 gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webView));
527 static void webkitWebViewBaseDispose(GObject* gobject)
529 WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(gobject);
530 webkitWebViewBaseSetToplevelOnScreenWindow(webView, nullptr);
531 webView->priv->pageProxy->close();
532 webView->priv->acceleratedBackingStore = nullptr;
533 webView->priv->sleepDisabler = nullptr;
534 G_OBJECT_CLASS(webkit_web_view_base_parent_class)->dispose(gobject);
537 static void webkitWebViewBaseConstructed(GObject* object)
539 G_OBJECT_CLASS(webkit_web_view_base_parent_class)->constructed(object);
541 GtkWidget* viewWidget = GTK_WIDGET(object);
542 gtk_widget_set_can_focus(viewWidget, TRUE);
543 gtk_drag_dest_set(viewWidget, static_cast<GtkDestDefaults>(0), nullptr, 0,
544 static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
545 gtk_drag_dest_set_target_list(viewWidget, PasteboardHelper::singleton().targetList());
547 WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(object)->priv;
548 priv->pageClient = std::make_unique<PageClientImpl>(viewWidget);
549 priv->dialog = nullptr;
552 static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr)
554 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
555 auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(webViewBase->priv->pageProxy->drawingArea());
559 GdkRectangle clipRect;
560 if (!gdk_cairo_get_clip_rectangle(cr, &clipRect))
563 bool showingNavigationSnapshot = webViewBase->priv->pageProxy->isShowingNavigationGestureSnapshot();
564 if (showingNavigationSnapshot)
565 cairo_push_group(cr);
567 if (webViewBase->priv->acceleratedBackingStore && drawingArea->isInAcceleratedCompositingMode())
568 webViewBase->priv->acceleratedBackingStore->paint(cr, clipRect);
570 WebCore::Region unpaintedRegion; // This is simply unused.
571 drawingArea->paint(cr, clipRect, unpaintedRegion);
574 if (showingNavigationSnapshot) {
575 ViewGestureController& controller = webkitWebViewBaseViewGestureController(webViewBase);
576 RefPtr<cairo_pattern_t> group = adoptRef(cairo_pop_group(cr));
577 controller.draw(cr, group.get());
580 GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->draw(widget, cr);
585 static void webkitWebViewBaseChildAllocate(GtkWidget* child, gpointer userData)
587 if (!gtk_widget_get_visible(child))
590 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(userData);
591 WebKitWebViewBasePrivate* priv = webViewBase->priv;
592 const IntRect& geometry = priv->children.get(child);
593 if (geometry.isEmpty())
596 GtkAllocation childAllocation = geometry;
597 gtk_widget_size_allocate(child, &childAllocation);
598 priv->children.set(child, IntRect());
601 static void webkitWebViewBaseSizeAllocate(GtkWidget* widget, GtkAllocation* allocation)
603 GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->size_allocate(widget, allocation);
605 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
606 gtk_container_foreach(GTK_CONTAINER(webViewBase), webkitWebViewBaseChildAllocate, webViewBase);
608 IntRect viewRect(allocation->x, allocation->y, allocation->width, allocation->height);
609 WebKitWebViewBasePrivate* priv = webViewBase->priv;
610 if (priv->inspectorView) {
611 GtkAllocation childAllocation = viewRect;
613 if (priv->inspectorAttachmentSide == AttachmentSide::Bottom) {
614 int inspectorViewHeight = std::min(static_cast<int>(priv->inspectorViewSize), allocation->height);
615 childAllocation.x = 0;
616 childAllocation.y = allocation->height - inspectorViewHeight;
617 childAllocation.height = inspectorViewHeight;
618 viewRect.setHeight(std::max(allocation->height - inspectorViewHeight, 1));
620 int inspectorViewWidth = std::min(static_cast<int>(priv->inspectorViewSize), allocation->width);
621 childAllocation.y = 0;
622 childAllocation.x = allocation->width - inspectorViewWidth;
623 childAllocation.width = inspectorViewWidth;
624 viewRect.setWidth(std::max(allocation->width - inspectorViewWidth, 1));
627 gtk_widget_size_allocate(priv->inspectorView, &childAllocation);
630 // The dialogs are centered in the view rect, which means that it
631 // never overlaps the web inspector. Thus, we need to calculate the allocation here
632 // after calculating the inspector allocation.
634 GtkRequisition minimumSize;
635 gtk_widget_get_preferred_size(priv->dialog, &minimumSize, nullptr);
637 GtkAllocation childAllocation = { 0, 0, std::max(minimumSize.width, viewRect.width()), std::max(minimumSize.height, viewRect.height()) };
638 gtk_widget_size_allocate(priv->dialog, &childAllocation);
641 if (auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(priv->pageProxy->drawingArea()))
642 drawingArea->setSize(viewRect.size());
645 static void webkitWebViewBaseGetPreferredWidth(GtkWidget* widget, gint* minimumSize, gint* naturalSize)
647 WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
649 *naturalSize = priv->contentsSize.width();
652 static void webkitWebViewBaseGetPreferredHeight(GtkWidget* widget, gint* minimumSize, gint* naturalSize)
654 WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
656 *naturalSize = priv->contentsSize.height();
659 static void webkitWebViewBaseMap(GtkWidget* widget)
661 GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->map(widget);
663 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
664 WebKitWebViewBasePrivate* priv = webViewBase->priv;
665 OptionSet<ActivityState::Flag> flagsToUpdate;
666 if (!(priv->activityState & ActivityState::IsVisible))
667 flagsToUpdate.add(ActivityState::IsVisible);
668 if (priv->toplevelOnScreenWindow) {
669 if (!(priv->activityState & ActivityState::IsInWindow))
670 flagsToUpdate.add(ActivityState::IsInWindow);
671 if (gtk_window_is_active(GTK_WINDOW(priv->toplevelOnScreenWindow)) && !(priv->activityState & ActivityState::WindowIsActive))
672 flagsToUpdate.add(ActivityState::WindowIsActive);
677 priv->activityState.add(flagsToUpdate);
678 webkitWebViewBaseScheduleUpdateActivityState(webViewBase, flagsToUpdate);
681 static void webkitWebViewBaseUnmap(GtkWidget* widget)
683 GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->unmap(widget);
685 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
686 WebKitWebViewBasePrivate* priv = webViewBase->priv;
687 if (!(priv->activityState & ActivityState::IsVisible))
690 priv->activityState.remove(ActivityState::IsVisible);
691 webkitWebViewBaseScheduleUpdateActivityState(webViewBase, ActivityState::IsVisible);
694 static gboolean webkitWebViewBaseFocusInEvent(GtkWidget* widget, GdkEventFocus* event)
696 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
697 webkitWebViewBaseSetFocus(webViewBase, true);
698 webViewBase->priv->inputMethodFilter.notifyFocusedIn();
700 return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus_in_event(widget, event);
703 static gboolean webkitWebViewBaseFocusOutEvent(GtkWidget* widget, GdkEventFocus* event)
705 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
706 webkitWebViewBaseSetFocus(webViewBase, false);
707 webViewBase->priv->inputMethodFilter.notifyFocusedOut();
709 return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus_out_event(widget, event);
712 static gboolean webkitWebViewBaseKeyPressEvent(GtkWidget* widget, GdkEventKey* keyEvent)
714 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
715 WebKitWebViewBasePrivate* priv = webViewBase->priv;
717 #if ENABLE(DEVELOPER_MODE) && OS(LINUX)
718 if ((keyEvent->state & GDK_CONTROL_MASK) && (keyEvent->state & GDK_SHIFT_MASK) && keyEvent->keyval == GDK_KEY_G) {
719 auto& preferences = priv->pageProxy->preferences();
720 preferences.setResourceUsageOverlayVisible(!preferences.resourceUsageOverlayVisible());
721 priv->shouldForwardNextKeyEvent = FALSE;
722 return GDK_EVENT_STOP;
727 return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, keyEvent);
729 #if ENABLE(FULLSCREEN_API)
730 if (priv->fullScreenModeActive) {
731 switch (keyEvent->keyval) {
735 priv->pageProxy->fullScreenManager()->requestExitFullScreen();
736 return GDK_EVENT_STOP;
743 // Since WebProcess key event handling is not synchronous, handle the event in two passes.
744 // When WebProcess processes the input event, it will call PageClientImpl::doneWithKeyEvent
745 // with event handled status which determines whether to pass the input event to parent or not
746 // using gtk_main_do_event().
747 if (priv->shouldForwardNextKeyEvent) {
748 priv->shouldForwardNextKeyEvent = FALSE;
749 return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, keyEvent);
752 // We need to copy the event as otherwise it could be destroyed before we reach the lambda body.
753 GUniquePtr<GdkEvent> event(gdk_event_copy(reinterpret_cast<GdkEvent*>(keyEvent)));
754 priv->inputMethodFilter.filterKeyEvent(keyEvent, [priv, event = WTFMove(event)](const WebCore::CompositionResults& compositionResults, InputMethodFilter::EventFakedForComposition faked) {
755 priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(event.get(), compositionResults, faked,
756 !compositionResults.compositionUpdated() ? priv->keyBindingTranslator.commandsForKeyEvent(&event->key) : Vector<String>()));
759 return GDK_EVENT_STOP;
762 static gboolean webkitWebViewBaseKeyReleaseEvent(GtkWidget* widget, GdkEventKey* keyEvent)
764 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
765 WebKitWebViewBasePrivate* priv = webViewBase->priv;
767 if (priv->shouldForwardNextKeyEvent) {
768 priv->shouldForwardNextKeyEvent = FALSE;
769 return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_release_event(widget, keyEvent);
772 // We need to copy the event as otherwise it could be destroyed before we reach the lambda body.
773 GUniquePtr<GdkEvent> event(gdk_event_copy(reinterpret_cast<GdkEvent*>(keyEvent)));
774 priv->inputMethodFilter.filterKeyEvent(keyEvent, [priv, event = WTFMove(event)](const WebCore::CompositionResults& compositionResults, InputMethodFilter::EventFakedForComposition faked) {
775 priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(event.get(), compositionResults, faked, { }));
778 return GDK_EVENT_STOP;
781 static void webkitWebViewBaseHandleMouseEvent(WebKitWebViewBase* webViewBase, GdkEvent* event)
783 WebKitWebViewBasePrivate* priv = webViewBase->priv;
784 ASSERT(!priv->dialog);
788 switch (event->type) {
789 case GDK_BUTTON_PRESS:
790 case GDK_2BUTTON_PRESS:
791 case GDK_3BUTTON_PRESS: {
792 // For double and triple clicks GDK sends both a normal button press event
793 // and a specific type (like GDK_2BUTTON_PRESS). If we detect a special press
794 // coming up, ignore this event as it certainly generated the double or triple
795 // click. The consequence of not eating this event is two DOM button press events
797 GUniquePtr<GdkEvent> nextEvent(gdk_event_peek());
798 if (nextEvent && (nextEvent->any.type == GDK_2BUTTON_PRESS || nextEvent->any.type == GDK_3BUTTON_PRESS))
801 priv->inputMethodFilter.notifyMouseButtonPress();
803 // If it's a right click event save it as a possible context menu event.
804 if (event->button.button == GDK_BUTTON_SECONDARY)
805 priv->contextMenuEvent.reset(gdk_event_copy(event));
807 clickCount = priv->clickCounter.currentClickCountForGdkButtonEvent(event);
810 case GDK_BUTTON_RELEASE:
811 gtk_widget_grab_focus(GTK_WIDGET(webViewBase));
813 case GDK_MOTION_NOTIFY:
814 case GDK_ENTER_NOTIFY:
815 case GDK_LEAVE_NOTIFY:
818 ASSERT_NOT_REACHED();
821 priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(event, clickCount));
824 static gboolean webkitWebViewBaseButtonPressEvent(GtkWidget* widget, GdkEventButton* event)
826 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
827 WebKitWebViewBasePrivate* priv = webViewBase->priv;
830 return GDK_EVENT_STOP;
832 webkitWebViewBaseHandleMouseEvent(webViewBase, reinterpret_cast<GdkEvent*>(event));
834 return GDK_EVENT_STOP;
837 static gboolean webkitWebViewBaseButtonReleaseEvent(GtkWidget* widget, GdkEventButton* event)
839 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
840 WebKitWebViewBasePrivate* priv = webViewBase->priv;
843 return GDK_EVENT_STOP;
845 webkitWebViewBaseHandleMouseEvent(webViewBase, reinterpret_cast<GdkEvent*>(event));
847 return GDK_EVENT_STOP;
850 static void webkitWebViewBaseHandleWheelEvent(WebKitWebViewBase* webViewBase, GdkEvent* event, Optional<WebWheelEvent::Phase> phase = WTF::nullopt, Optional<WebWheelEvent::Phase> momentum = WTF::nullopt)
852 WebKitWebViewBasePrivate* priv = webViewBase->priv;
853 ASSERT(!priv->dialog);
855 priv->pageProxy->handleWheelEvent(NativeWebWheelEvent(event, phase.value(), momentum.valueOr(WebWheelEvent::Phase::PhaseNone)));
857 priv->pageProxy->handleWheelEvent(NativeWebWheelEvent(event));
860 static gboolean webkitWebViewBaseScrollEvent(GtkWidget* widget, GdkEventScroll* event)
862 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
863 WebKitWebViewBasePrivate* priv = webViewBase->priv;
865 if (std::exchange(priv->shouldForwardNextWheelEvent, false))
866 return GDK_EVENT_PROPAGATE;
869 return GDK_EVENT_PROPAGATE;
871 // Shift+Wheel scrolls in the perpendicular direction.
872 if (event->state & GDK_SHIFT_MASK) {
873 switch (event->direction) {
875 event->direction = GDK_SCROLL_LEFT;
877 case GDK_SCROLL_LEFT:
878 event->direction = GDK_SCROLL_UP;
880 case GDK_SCROLL_DOWN:
881 event->direction = GDK_SCROLL_RIGHT;
883 case GDK_SCROLL_RIGHT:
884 event->direction = GDK_SCROLL_DOWN;
886 case GDK_SCROLL_SMOOTH:
887 std::swap(event->delta_x, event->delta_y);
892 ViewGestureController& controller = webkitWebViewBaseViewGestureController(webViewBase);
893 if (controller.isSwipeGestureEnabled() && controller.handleScrollWheelEvent(event))
894 return GDK_EVENT_STOP;
896 webkitWebViewBaseHandleWheelEvent(webViewBase, reinterpret_cast<GdkEvent*>(event));
898 return GDK_EVENT_STOP;
901 static gboolean webkitWebViewBasePopupMenu(GtkWidget* widget)
903 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
904 WebKitWebViewBasePrivate* priv = webViewBase->priv;
906 GdkEvent* currentEvent = gtk_get_current_event();
908 currentEvent = gdk_event_new(GDK_NOTHING);
909 priv->contextMenuEvent.reset(currentEvent);
910 priv->pageProxy->handleContextMenuKeyEvent();
915 static gboolean webkitWebViewBaseMotionNotifyEvent(GtkWidget* widget, GdkEventMotion* event)
917 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
918 WebKitWebViewBasePrivate* priv = webViewBase->priv;
921 auto* widgetClass = GTK_WIDGET_CLASS(webkit_web_view_base_parent_class);
922 return widgetClass->motion_notify_event ? widgetClass->motion_notify_event(widget, event) : GDK_EVENT_PROPAGATE;
925 webkitWebViewBaseHandleMouseEvent(webViewBase, reinterpret_cast<GdkEvent*>(event));
927 return GDK_EVENT_PROPAGATE;
930 static gboolean webkitWebViewBaseCrossingNotifyEvent(GtkWidget* widget, GdkEventCrossing* crossingEvent)
932 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
933 WebKitWebViewBasePrivate* priv = webViewBase->priv;
936 return GDK_EVENT_PROPAGATE;
938 #if ENABLE(DEVELOPER_MODE)
939 // Do not send mouse move events to the WebProcess for crossing events during testing.
940 // WTR never generates crossing events and they can confuse tests.
941 // https://bugs.webkit.org/show_bug.cgi?id=185072.
942 if (UNLIKELY(priv->pageProxy->process().processPool().configuration().fullySynchronousModeIsAllowedForTesting()))
943 return GDK_EVENT_PROPAGATE;
946 // In the case of crossing events, it's very important the actual coordinates the WebProcess receives, because once the mouse leaves
947 // 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
948 // event are not accurate, the WebProcess might not know the mouse left the view. This can happen because of double to integer conversion,
949 // 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
950 // because those coordinates are inside the web view.
951 GtkAllocation allocation;
952 gtk_widget_get_allocation(widget, &allocation);
953 double width = allocation.width;
954 double height = allocation.height;
955 double x = crossingEvent->x;
956 double y = crossingEvent->y;
959 else if (x >= width && x < width + 1)
963 else if (y >= height && y < height + 1)
966 GdkEvent* event = reinterpret_cast<GdkEvent*>(crossingEvent);
967 GUniquePtr<GdkEvent> copiedEvent;
968 if (x != crossingEvent->x || y != crossingEvent->y) {
969 copiedEvent.reset(gdk_event_copy(event));
970 copiedEvent->crossing.x = x;
971 copiedEvent->crossing.y = y;
974 webkitWebViewBaseHandleMouseEvent(webViewBase, copiedEvent ? copiedEvent.get() : event);
976 return GDK_EVENT_PROPAGATE;
979 #if ENABLE(TOUCH_EVENTS)
980 static void appendTouchEvent(Vector<WebPlatformTouchPoint>& touchPoints, const GdkEvent* event, WebPlatformTouchPoint::TouchPointState state)
983 gdk_event_get_coords(event, &x, &y);
985 gdouble xRoot, yRoot;
986 gdk_event_get_root_coords(event, &xRoot, &yRoot);
988 uint32_t identifier = GPOINTER_TO_UINT(gdk_event_get_event_sequence(event));
989 touchPoints.uncheckedAppend(WebPlatformTouchPoint(identifier, state, IntPoint(xRoot, yRoot), IntPoint(x, y)));
992 static inline WebPlatformTouchPoint::TouchPointState touchPointStateForEvents(const GdkEvent* current, const GdkEvent* event)
994 if (gdk_event_get_event_sequence(current) != gdk_event_get_event_sequence(event))
995 return WebPlatformTouchPoint::TouchStationary;
997 switch (current->type) {
998 case GDK_TOUCH_UPDATE:
999 return WebPlatformTouchPoint::TouchMoved;
1000 case GDK_TOUCH_BEGIN:
1001 return WebPlatformTouchPoint::TouchPressed;
1003 return WebPlatformTouchPoint::TouchReleased;
1004 case GDK_TOUCH_CANCEL:
1005 return WebPlatformTouchPoint::TouchCancelled;
1007 return WebPlatformTouchPoint::TouchStationary;
1011 static void webkitWebViewBaseGetTouchPointsForEvent(WebKitWebViewBase* webViewBase, GdkEvent* event, Vector<WebPlatformTouchPoint>& touchPoints)
1013 WebKitWebViewBasePrivate* priv = webViewBase->priv;
1014 bool touchEnd = (event->type == GDK_TOUCH_END) || (event->type == GDK_TOUCH_CANCEL);
1015 touchPoints.reserveInitialCapacity(touchEnd ? priv->touchEvents.size() + 1 : priv->touchEvents.size());
1017 for (const auto& it : priv->touchEvents)
1018 appendTouchEvent(touchPoints, it.value.get(), touchPointStateForEvents(it.value.get(), event));
1020 // Touch was already removed from the TouchEventsMap, add it here.
1022 appendTouchEvent(touchPoints, event, WebPlatformTouchPoint::TouchReleased);
1025 static gboolean webkitWebViewBaseTouchEvent(GtkWidget* widget, GdkEventTouch* event)
1027 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
1028 WebKitWebViewBasePrivate* priv = webViewBase->priv;
1031 return GDK_EVENT_STOP;
1033 GdkEvent* touchEvent = reinterpret_cast<GdkEvent*>(event);
1034 uint32_t sequence = GPOINTER_TO_UINT(gdk_event_get_event_sequence(touchEvent));
1036 switch (touchEvent->type) {
1037 case GDK_TOUCH_BEGIN: {
1038 ASSERT(!priv->touchEvents.contains(sequence));
1039 GUniquePtr<GdkEvent> event(gdk_event_copy(touchEvent));
1040 priv->touchEvents.add(sequence, WTFMove(event));
1043 case GDK_TOUCH_UPDATE: {
1044 auto it = priv->touchEvents.find(sequence);
1045 ASSERT(it != priv->touchEvents.end());
1046 it->value.reset(gdk_event_copy(touchEvent));
1049 case GDK_TOUCH_CANCEL:
1052 ASSERT(priv->touchEvents.contains(sequence));
1053 priv->touchEvents.remove(sequence);
1059 Vector<WebPlatformTouchPoint> touchPoints;
1060 webkitWebViewBaseGetTouchPointsForEvent(webViewBase, touchEvent, touchPoints);
1061 priv->pageProxy->handleTouchEvent(NativeWebTouchEvent(reinterpret_cast<GdkEvent*>(event), WTFMove(touchPoints)));
1063 return GDK_EVENT_STOP;
1065 #endif // ENABLE(TOUCH_EVENTS)
1067 #if HAVE(GTK_GESTURES)
1068 class TouchGestureController final : public GestureControllerClient {
1069 WTF_MAKE_FAST_ALLOCATED;
1072 explicit TouchGestureController(WebKitWebViewBase* webViewBase)
1073 : m_webView(webViewBase)
1078 static GUniquePtr<GdkEvent> createScrollEvent(GdkEventTouch* event, const FloatPoint& point, const FloatPoint& delta, bool isStop = false)
1080 GUniquePtr<GdkEvent> scrollEvent(gdk_event_new(GDK_SCROLL));
1081 scrollEvent->scroll.time = event->time;
1082 scrollEvent->scroll.x = point.x();
1083 scrollEvent->scroll.y = point.y();
1084 scrollEvent->scroll.x_root = event->x_root;
1085 scrollEvent->scroll.y_root = event->y_root;
1086 scrollEvent->scroll.direction = GDK_SCROLL_SMOOTH;
1087 scrollEvent->scroll.delta_x = delta.x();
1088 scrollEvent->scroll.delta_y = delta.y();
1089 scrollEvent->scroll.state = event->state;
1090 #if GTK_CHECK_VERSION(3, 20, 0)
1091 scrollEvent->scroll.is_stop = isStop;
1093 UNUSED_PARAM(isStop);
1095 scrollEvent->scroll.window = event->window ? GDK_WINDOW(g_object_ref(event->window)) : nullptr;
1096 auto* touchEvent = reinterpret_cast<GdkEvent*>(event);
1097 gdk_event_set_screen(scrollEvent.get(), gdk_event_get_screen(touchEvent));
1098 gdk_event_set_device(scrollEvent.get(), gdk_event_get_device(touchEvent));
1099 gdk_event_set_source_device(scrollEvent.get(), gdk_event_get_source_device(touchEvent));
1103 void simulateMouseClick(GdkEventTouch* event, unsigned button)
1105 GUniquePtr<GdkEvent> pointerEvent(gdk_event_new(GDK_MOTION_NOTIFY));
1106 pointerEvent->motion.time = event->time;
1107 pointerEvent->motion.x = event->x;
1108 pointerEvent->motion.y = event->y;
1109 pointerEvent->motion.x_root = event->x_root;
1110 pointerEvent->motion.y_root = event->y_root;
1111 pointerEvent->motion.state = event->state;
1112 pointerEvent->motion.window = event->window ? GDK_WINDOW(g_object_ref(event->window)) : nullptr;
1113 auto* touchEvent = reinterpret_cast<GdkEvent*>(event);
1114 gdk_event_set_screen(pointerEvent.get(), gdk_event_get_screen(touchEvent));
1115 gdk_event_set_device(pointerEvent.get(), gdk_event_get_device(touchEvent));
1116 gdk_event_set_source_device(pointerEvent.get(), gdk_event_get_source_device(touchEvent));
1117 webkitWebViewBaseHandleMouseEvent(m_webView, pointerEvent.get());
1119 pointerEvent.reset(gdk_event_new(GDK_BUTTON_PRESS));
1120 pointerEvent->button.button = button;
1121 pointerEvent->button.time = event->time;
1122 pointerEvent->button.x = event->x;
1123 pointerEvent->button.y = event->y;
1124 pointerEvent->button.x_root = event->x_root;
1125 pointerEvent->button.y_root = event->y_root;
1126 pointerEvent->button.window = event->window ? GDK_WINDOW(g_object_ref(event->window)) : nullptr;
1127 gdk_event_set_screen(pointerEvent.get(), gdk_event_get_screen(touchEvent));
1128 gdk_event_set_device(pointerEvent.get(), gdk_event_get_device(touchEvent));
1129 gdk_event_set_source_device(pointerEvent.get(), gdk_event_get_source_device(touchEvent));
1130 webkitWebViewBaseHandleMouseEvent(m_webView, pointerEvent.get());
1132 pointerEvent->type = GDK_BUTTON_RELEASE;
1133 webkitWebViewBaseHandleMouseEvent(m_webView, pointerEvent.get());
1136 void tap(GdkEventTouch* event) final
1138 simulateMouseClick(event, GDK_BUTTON_PRIMARY);
1141 void startDrag(GdkEventTouch* event, const FloatPoint& startPoint) final
1143 GUniquePtr<GdkEvent> scrollEvent = createScrollEvent(event, startPoint, { });
1144 webkitWebViewBaseHandleWheelEvent(m_webView, scrollEvent.get(), WebWheelEvent::Phase::PhaseBegan);
1147 void drag(GdkEventTouch* event, const FloatPoint& point, const FloatPoint& delta) final
1149 GUniquePtr<GdkEvent> scrollEvent = createScrollEvent(event, point, delta);
1150 webkitWebViewBaseHandleWheelEvent(m_webView, scrollEvent.get(), WebWheelEvent::Phase::PhaseChanged);
1153 void swipe(GdkEventTouch* event, const FloatPoint& velocity) final
1155 GUniquePtr<GdkEvent> scrollEvent = createScrollEvent(event, FloatPoint::narrowPrecision(event->x, event->y), velocity, true);
1156 webkitWebViewBaseHandleWheelEvent(m_webView, scrollEvent.get(), WebWheelEvent::Phase::PhaseNone, WebWheelEvent::Phase::PhaseBegan);
1159 void startZoom(const IntPoint& center, double& initialScale, IntPoint& initialPoint) final
1161 auto* page = m_webView->priv->pageProxy.get();
1163 initialScale = page->pageScaleFactor();
1164 page->getCenterForZoomGesture(center, initialPoint);
1167 void zoom(double scale, const IntPoint& origin) final
1169 auto* page = m_webView->priv->pageProxy.get();
1172 page->scalePage(scale, origin);
1175 void longPress(GdkEventTouch* event) final
1177 simulateMouseClick(event, GDK_BUTTON_SECONDARY);
1180 WebKitWebViewBase* m_webView;
1183 GestureController& webkitWebViewBaseGestureController(WebKitWebViewBase* webViewBase)
1185 WebKitWebViewBasePrivate* priv = webViewBase->priv;
1186 if (!priv->gestureController)
1187 priv->gestureController = std::make_unique<GestureController>(GTK_WIDGET(webViewBase), std::make_unique<TouchGestureController>(webViewBase));
1188 return *priv->gestureController;
1192 ViewGestureController& webkitWebViewBaseViewGestureController(WebKitWebViewBase* webViewBase)
1194 return *webViewBase->priv->viewGestureController;
1197 static gboolean webkitWebViewBaseQueryTooltip(GtkWidget* widget, gint /* x */, gint /* y */, gboolean keyboardMode, GtkTooltip* tooltip)
1199 WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1202 // TODO: https://bugs.webkit.org/show_bug.cgi?id=61732.
1207 if (priv->tooltipText.length() <= 0)
1210 if (!priv->tooltipArea.isEmpty()) {
1211 GdkRectangle area = priv->tooltipArea;
1212 gtk_tooltip_set_tip_area(tooltip, &area);
1214 gtk_tooltip_set_tip_area(tooltip, 0);
1215 gtk_tooltip_set_text(tooltip, priv->tooltipText.data());
1220 #if ENABLE(DRAG_SUPPORT)
1221 static void webkitWebViewBaseDragDataGet(GtkWidget* widget, GdkDragContext* context, GtkSelectionData* selectionData, guint info, guint /* time */)
1223 WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1224 ASSERT(priv->dragAndDropHandler);
1225 priv->dragAndDropHandler->fillDragData(context, selectionData, info);
1228 static void webkitWebViewBaseDragEnd(GtkWidget* widget, GdkDragContext* context)
1230 WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1231 ASSERT(priv->dragAndDropHandler);
1232 priv->dragAndDropHandler->finishDrag(context);
1235 static void webkitWebViewBaseDragDataReceived(GtkWidget* widget, GdkDragContext* context, gint /* x */, gint /* y */, GtkSelectionData* selectionData, guint info, guint time)
1237 webkitWebViewBaseDragAndDropHandler(WEBKIT_WEB_VIEW_BASE(widget)).dragEntered(context, selectionData, info, time);
1239 #endif // ENABLE(DRAG_SUPPORT)
1241 static gboolean webkitWebViewBaseEvent(GtkWidget* widget, GdkEvent* event)
1243 #if HAVE(GTK_GESTURES)
1244 if (event->type == GDK_TOUCHPAD_PINCH)
1245 webkitWebViewBaseGestureController(WEBKIT_WEB_VIEW_BASE(widget)).handleEvent(event);
1248 return GDK_EVENT_PROPAGATE;
1251 static AtkObject* webkitWebViewBaseGetAccessible(GtkWidget* widget)
1253 WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1254 if (!priv->accessible) {
1255 // Create the accessible object and associate it to the widget.
1256 priv->accessible = adoptGRef(ATK_OBJECT(webkitWebViewBaseAccessibleNew(widget)));
1258 // Set the parent to not break bottom-up navigation.
1259 if (auto* parentWidget = gtk_widget_get_parent(widget)) {
1260 if (auto* axParent = gtk_widget_get_accessible(parentWidget))
1261 atk_object_set_parent(priv->accessible.get(), axParent);
1265 return priv->accessible.get();
1268 #if ENABLE(DRAG_SUPPORT)
1269 static gboolean webkitWebViewBaseDragMotion(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
1271 webkitWebViewBaseDragAndDropHandler(WEBKIT_WEB_VIEW_BASE(widget)).dragMotion(context, IntPoint(x, y), time);
1275 static void webkitWebViewBaseDragLeave(GtkWidget* widget, GdkDragContext* context, guint /* time */)
1277 WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1278 ASSERT(priv->dragAndDropHandler);
1279 priv->dragAndDropHandler->dragLeave(context);
1282 static gboolean webkitWebViewBaseDragDrop(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
1284 WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1285 ASSERT(priv->dragAndDropHandler);
1286 return priv->dragAndDropHandler->drop(context, IntPoint(x, y), time);
1288 #endif // ENABLE(DRAG_SUPPORT)
1290 static void webkitWebViewBaseHierarchyChanged(GtkWidget* widget, GtkWidget* oldToplevel)
1292 WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1293 if (widgetIsOnscreenToplevelWindow(oldToplevel) && GTK_WINDOW(oldToplevel) == priv->toplevelOnScreenWindow) {
1294 webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), nullptr);
1299 GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
1300 if (widgetIsOnscreenToplevelWindow(toplevel))
1301 webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), GTK_WINDOW(toplevel));
1305 static gboolean webkitWebViewBaseFocus(GtkWidget* widget, GtkDirectionType direction)
1307 // If a dialog is active, we need to forward focus events there. This
1308 // ensures that you can tab between elements in the box.
1309 WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1311 gboolean returnValue;
1312 g_signal_emit_by_name(priv->dialog, "focus", direction, &returnValue);
1316 return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus(widget, direction);
1319 static void webkitWebViewBaseDestroy(GtkWidget* widget)
1321 WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
1323 gtk_widget_destroy(priv->dialog);
1325 GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->destroy(widget);
1328 static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebViewBaseClass)
1330 GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webkitWebViewBaseClass);
1331 widgetClass->realize = webkitWebViewBaseRealize;
1332 widgetClass->unrealize = webkitWebViewBaseUnrealize;
1333 widgetClass->draw = webkitWebViewBaseDraw;
1334 widgetClass->size_allocate = webkitWebViewBaseSizeAllocate;
1335 widgetClass->get_preferred_width = webkitWebViewBaseGetPreferredWidth;
1336 widgetClass->get_preferred_height = webkitWebViewBaseGetPreferredHeight;
1337 widgetClass->map = webkitWebViewBaseMap;
1338 widgetClass->unmap = webkitWebViewBaseUnmap;
1339 widgetClass->focus = webkitWebViewBaseFocus;
1340 widgetClass->focus_in_event = webkitWebViewBaseFocusInEvent;
1341 widgetClass->focus_out_event = webkitWebViewBaseFocusOutEvent;
1342 widgetClass->key_press_event = webkitWebViewBaseKeyPressEvent;
1343 widgetClass->key_release_event = webkitWebViewBaseKeyReleaseEvent;
1344 widgetClass->button_press_event = webkitWebViewBaseButtonPressEvent;
1345 widgetClass->button_release_event = webkitWebViewBaseButtonReleaseEvent;
1346 widgetClass->scroll_event = webkitWebViewBaseScrollEvent;
1347 widgetClass->popup_menu = webkitWebViewBasePopupMenu;
1348 widgetClass->motion_notify_event = webkitWebViewBaseMotionNotifyEvent;
1349 widgetClass->enter_notify_event = webkitWebViewBaseCrossingNotifyEvent;
1350 widgetClass->leave_notify_event = webkitWebViewBaseCrossingNotifyEvent;
1351 #if ENABLE(TOUCH_EVENTS)
1352 widgetClass->touch_event = webkitWebViewBaseTouchEvent;
1354 widgetClass->query_tooltip = webkitWebViewBaseQueryTooltip;
1355 #if ENABLE(DRAG_SUPPORT)
1356 widgetClass->drag_end = webkitWebViewBaseDragEnd;
1357 widgetClass->drag_data_get = webkitWebViewBaseDragDataGet;
1358 widgetClass->drag_motion = webkitWebViewBaseDragMotion;
1359 widgetClass->drag_leave = webkitWebViewBaseDragLeave;
1360 widgetClass->drag_drop = webkitWebViewBaseDragDrop;
1361 widgetClass->drag_data_received = webkitWebViewBaseDragDataReceived;
1362 #endif // ENABLE(DRAG_SUPPORT)
1363 widgetClass->event = webkitWebViewBaseEvent;
1364 widgetClass->get_accessible = webkitWebViewBaseGetAccessible;
1365 widgetClass->hierarchy_changed = webkitWebViewBaseHierarchyChanged;
1366 widgetClass->destroy = webkitWebViewBaseDestroy;
1368 GObjectClass* gobjectClass = G_OBJECT_CLASS(webkitWebViewBaseClass);
1369 gobjectClass->constructed = webkitWebViewBaseConstructed;
1370 gobjectClass->dispose = webkitWebViewBaseDispose;
1372 GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webkitWebViewBaseClass);
1373 containerClass->add = webkitWebViewBaseContainerAdd;
1374 containerClass->remove = webkitWebViewBaseContainerRemove;
1375 containerClass->forall = webkitWebViewBaseContainerForall;
1377 // Before creating a WebKitWebViewBasePriv we need to be sure that WebKit is started.
1378 // Usually starting a context triggers InitializeWebKit2, but in case
1379 // we create a view without asking before for a default_context we get a crash.
1380 WebKit::InitializeWebKit2();
1383 WebKitWebViewBase* webkitWebViewBaseCreate(const API::PageConfiguration& configuration)
1385 WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(g_object_new(WEBKIT_TYPE_WEB_VIEW_BASE, nullptr));
1386 webkitWebViewBaseCreateWebPage(webkitWebViewBase, configuration.copy());
1387 return webkitWebViewBase;
1390 GtkIMContext* webkitWebViewBaseGetIMContext(WebKitWebViewBase* webkitWebViewBase)
1392 return webkitWebViewBase->priv->inputMethodFilter.context();
1395 WebPageProxy* webkitWebViewBaseGetPage(WebKitWebViewBase* webkitWebViewBase)
1397 return webkitWebViewBase->priv->pageProxy.get();
1400 #if HAVE(GTK_SCALE_FACTOR)
1401 static void deviceScaleFactorChanged(WebKitWebViewBase* webkitWebViewBase)
1403 webkitWebViewBase->priv->pageProxy->setIntrinsicDeviceScaleFactor(gtk_widget_get_scale_factor(GTK_WIDGET(webkitWebViewBase)));
1405 #endif // HAVE(GTK_SCALE_FACTOR)
1407 void webkitWebViewBaseCreateWebPage(WebKitWebViewBase* webkitWebViewBase, Ref<API::PageConfiguration>&& configuration)
1409 WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1410 WebProcessPool* processPool = configuration->processPool();
1411 priv->pageProxy = processPool->createWebPage(*priv->pageClient, WTFMove(configuration));
1412 priv->pageProxy->initializeWebPage();
1414 priv->acceleratedBackingStore = AcceleratedBackingStore::create(*priv->pageProxy);
1416 priv->inputMethodFilter.setPage(priv->pageProxy.get());
1418 #if HAVE(GTK_SCALE_FACTOR)
1419 // We attach this here, because changes in scale factor are passed directly to the page proxy.
1420 priv->pageProxy->setIntrinsicDeviceScaleFactor(gtk_widget_get_scale_factor(GTK_WIDGET(webkitWebViewBase)));
1421 g_signal_connect(webkitWebViewBase, "notify::scale-factor", G_CALLBACK(deviceScaleFactorChanged), nullptr);
1424 priv->viewGestureController = std::make_unique<WebKit::ViewGestureController>(*priv->pageProxy);
1427 void webkitWebViewBaseSetTooltipText(WebKitWebViewBase* webViewBase, const char* tooltip)
1429 WebKitWebViewBasePrivate* priv = webViewBase->priv;
1430 if (tooltip && tooltip[0] != '\0') {
1431 priv->tooltipText = tooltip;
1432 gtk_widget_set_has_tooltip(GTK_WIDGET(webViewBase), TRUE);
1434 priv->tooltipText = "";
1435 gtk_widget_set_has_tooltip(GTK_WIDGET(webViewBase), FALSE);
1438 gtk_widget_trigger_tooltip_query(GTK_WIDGET(webViewBase));
1441 void webkitWebViewBaseSetTooltipArea(WebKitWebViewBase* webViewBase, const IntRect& tooltipArea)
1443 webViewBase->priv->tooltipArea = tooltipArea;
1446 #if ENABLE(DRAG_SUPPORT)
1447 DragAndDropHandler& webkitWebViewBaseDragAndDropHandler(WebKitWebViewBase* webViewBase)
1449 WebKitWebViewBasePrivate* priv = webViewBase->priv;
1450 if (!priv->dragAndDropHandler)
1451 priv->dragAndDropHandler = std::make_unique<DragAndDropHandler>(*priv->pageProxy);
1452 return *priv->dragAndDropHandler;
1454 #endif // ENABLE(DRAG_SUPPORT)
1456 void webkitWebViewBaseForwardNextKeyEvent(WebKitWebViewBase* webkitWebViewBase)
1458 webkitWebViewBase->priv->shouldForwardNextKeyEvent = TRUE;
1461 void webkitWebViewBaseForwardNextWheelEvent(WebKitWebViewBase* webkitWebViewBase)
1463 webkitWebViewBase->priv->shouldForwardNextWheelEvent = true;
1466 void webkitWebViewBaseEnterFullScreen(WebKitWebViewBase* webkitWebViewBase)
1468 #if ENABLE(FULLSCREEN_API)
1469 WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1470 ASSERT(!priv->fullScreenModeActive);
1472 WebFullScreenManagerProxy* fullScreenManagerProxy = priv->pageProxy->fullScreenManager();
1473 fullScreenManagerProxy->willEnterFullScreen();
1475 GtkWidget* topLevelWindow = gtk_widget_get_toplevel(GTK_WIDGET(webkitWebViewBase));
1476 if (gtk_widget_is_toplevel(topLevelWindow))
1477 gtk_window_fullscreen(GTK_WINDOW(topLevelWindow));
1478 fullScreenManagerProxy->didEnterFullScreen();
1479 priv->fullScreenModeActive = true;
1480 priv->sleepDisabler = PAL::SleepDisabler::create(_("Website running in fullscreen mode"), PAL::SleepDisabler::Type::Display);
1484 void webkitWebViewBaseExitFullScreen(WebKitWebViewBase* webkitWebViewBase)
1486 #if ENABLE(FULLSCREEN_API)
1487 WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1488 ASSERT(priv->fullScreenModeActive);
1490 WebFullScreenManagerProxy* fullScreenManagerProxy = priv->pageProxy->fullScreenManager();
1491 fullScreenManagerProxy->willExitFullScreen();
1493 GtkWidget* topLevelWindow = gtk_widget_get_toplevel(GTK_WIDGET(webkitWebViewBase));
1494 if (gtk_widget_is_toplevel(topLevelWindow))
1495 gtk_window_unfullscreen(GTK_WINDOW(topLevelWindow));
1496 fullScreenManagerProxy->didExitFullScreen();
1497 priv->fullScreenModeActive = false;
1498 priv->sleepDisabler = nullptr;
1502 bool webkitWebViewBaseIsFullScreen(WebKitWebViewBase* webkitWebViewBase)
1504 #if ENABLE(FULLSCREEN_API)
1505 return webkitWebViewBase->priv->fullScreenModeActive;
1511 void webkitWebViewBaseSetInspectorViewSize(WebKitWebViewBase* webkitWebViewBase, unsigned size)
1513 if (webkitWebViewBase->priv->inspectorViewSize == size)
1515 webkitWebViewBase->priv->inspectorViewSize = size;
1516 if (webkitWebViewBase->priv->inspectorView)
1517 gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webkitWebViewBase));
1520 static void activeContextMenuUnmapped(GtkMenu* menu, WebKitWebViewBase* webViewBase)
1522 if (webViewBase->priv->activeContextMenuProxy && webViewBase->priv->activeContextMenuProxy->gtkMenu() == menu)
1523 webViewBase->priv->activeContextMenuProxy = nullptr;
1526 void webkitWebViewBaseSetActiveContextMenuProxy(WebKitWebViewBase* webkitWebViewBase, WebContextMenuProxyGtk* contextMenuProxy)
1528 webkitWebViewBase->priv->activeContextMenuProxy = contextMenuProxy;
1529 g_signal_connect_object(contextMenuProxy->gtkMenu(), "unmap", G_CALLBACK(activeContextMenuUnmapped), webkitWebViewBase, static_cast<GConnectFlags>(0));
1532 WebContextMenuProxyGtk* webkitWebViewBaseGetActiveContextMenuProxy(WebKitWebViewBase* webkitWebViewBase)
1534 return webkitWebViewBase->priv->activeContextMenuProxy;
1537 GdkEvent* webkitWebViewBaseTakeContextMenuEvent(WebKitWebViewBase* webkitWebViewBase)
1539 return webkitWebViewBase->priv->contextMenuEvent.release();
1542 void webkitWebViewBaseSetFocus(WebKitWebViewBase* webViewBase, bool focused)
1544 WebKitWebViewBasePrivate* priv = webViewBase->priv;
1545 if ((focused && priv->activityState & ActivityState::IsFocused) || (!focused && !(priv->activityState & ActivityState::IsFocused)))
1548 OptionSet<ActivityState::Flag> flagsToUpdate { ActivityState::IsFocused };
1550 priv->activityState.add(ActivityState::IsFocused);
1552 // If the view has received the focus and the window is not active
1553 // mark the current window as active now. This can happen if the
1554 // toplevel window is a GTK_WINDOW_POPUP and the focus has been
1555 // set programatically like WebKitTestRunner does, because POPUP
1556 // can't be focused.
1557 if (!(priv->activityState & ActivityState::WindowIsActive)) {
1558 priv->activityState.add(ActivityState::WindowIsActive);
1559 flagsToUpdate.add(ActivityState::WindowIsActive);
1562 priv->activityState.remove(ActivityState::IsFocused);
1564 webkitWebViewBaseScheduleUpdateActivityState(webViewBase, flagsToUpdate);
1567 bool webkitWebViewBaseIsInWindowActive(WebKitWebViewBase* webViewBase)
1569 return webViewBase->priv->activityState.contains(ActivityState::WindowIsActive);
1572 bool webkitWebViewBaseIsFocused(WebKitWebViewBase* webViewBase)
1574 return webViewBase->priv->activityState.contains(ActivityState::IsFocused);
1577 bool webkitWebViewBaseIsVisible(WebKitWebViewBase* webViewBase)
1579 return webViewBase->priv->activityState.contains(ActivityState::IsVisible);
1582 bool webkitWebViewBaseIsInWindow(WebKitWebViewBase* webViewBase)
1584 return webViewBase->priv->activityState.contains(ActivityState::IsInWindow);
1587 void webkitWebViewBaseSetInputMethodState(WebKitWebViewBase* webkitWebViewBase, bool enabled)
1589 webkitWebViewBase->priv->inputMethodFilter.setEnabled(enabled);
1592 void webkitWebViewBaseUpdateTextInputState(WebKitWebViewBase* webkitWebViewBase)
1594 const auto& editorState = webkitWebViewBase->priv->pageProxy->editorState();
1595 if (!editorState.isMissingPostLayoutData)
1596 webkitWebViewBase->priv->inputMethodFilter.setCursorRect(editorState.postLayoutData().caretRectAtStart);
1599 void webkitWebViewBaseSetContentsSize(WebKitWebViewBase* webkitWebViewBase, const IntSize& contentsSize)
1601 WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1602 if (priv->contentsSize == contentsSize)
1604 priv->contentsSize = contentsSize;
1607 void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase)
1609 webkitWebViewBase->priv->clickCounter.reset();
1612 void webkitWebViewBaseEnterAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext)
1614 if (webkitWebViewBase->priv->acceleratedBackingStore)
1615 webkitWebViewBase->priv->acceleratedBackingStore->update(layerTreeContext);
1618 void webkitWebViewBaseUpdateAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext)
1620 if (webkitWebViewBase->priv->acceleratedBackingStore)
1621 webkitWebViewBase->priv->acceleratedBackingStore->update(layerTreeContext);
1624 void webkitWebViewBaseExitAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase)
1626 if (webkitWebViewBase->priv->acceleratedBackingStore)
1627 webkitWebViewBase->priv->acceleratedBackingStore->update(LayerTreeContext());
1630 bool webkitWebViewBaseMakeGLContextCurrent(WebKitWebViewBase* webkitWebViewBase)
1632 if (webkitWebViewBase->priv->acceleratedBackingStore)
1633 return webkitWebViewBase->priv->acceleratedBackingStore->makeContextCurrent();
1637 void webkitWebViewBaseDidRelaunchWebProcess(WebKitWebViewBase* webkitWebViewBase)
1639 // Queue a resize to ensure the new DrawingAreaProxy is resized.
1640 gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webkitWebViewBase));
1642 #if PLATFORM(X11) && USE(TEXTURE_MAPPER_GL) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
1643 if (PlatformDisplay::sharedDisplay().type() != PlatformDisplay::Type::X11)
1646 WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1647 auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(priv->pageProxy->drawingArea());
1648 ASSERT(drawingArea);
1650 if (!gtk_widget_get_realized(GTK_WIDGET(webkitWebViewBase)))
1653 uint64_t windowID = GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(webkitWebViewBase)));
1654 drawingArea->setNativeSurfaceHandleForCompositing(windowID);
1656 UNUSED_PARAM(webkitWebViewBase);
1660 void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase)
1662 if (webkitWebViewBase->priv->acceleratedBackingStore)
1663 webkitWebViewBase->priv->acceleratedBackingStore->update(LayerTreeContext());
1664 #if PLATFORM(X11) && USE(TEXTURE_MAPPER_GL) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
1665 if (PlatformDisplay::sharedDisplay().type() != PlatformDisplay::Type::X11)
1668 if (!gtk_widget_get_realized(GTK_WIDGET(webkitWebViewBase)))
1671 WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1672 auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(priv->pageProxy->drawingArea());
1673 ASSERT(drawingArea);
1674 drawingArea->destroyNativeSurfaceHandleForCompositing();
1678 RefPtr<WebKit::ViewSnapshot> webkitWebViewBaseTakeViewSnapshot(WebKitWebViewBase* webkitWebViewBase)
1680 WebPageProxy* page = webkitWebViewBase->priv->pageProxy.get();
1682 IntSize size = page->viewSize();
1684 #if HAVE_GTK_SCALE_FACTOR
1685 float deviceScale = page->deviceScaleFactor();
1686 size.scale(deviceScale);
1689 RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_RGB24, size.width(), size.height()));
1691 #if HAVE_GTK_SCALE_FACTOR
1692 cairoSurfaceSetDeviceScale(surface.get(), deviceScale, deviceScale);
1695 RefPtr<cairo_t> cr = adoptRef(cairo_create(surface.get()));
1696 webkitWebViewBaseDraw(GTK_WIDGET(webkitWebViewBase), cr.get());
1698 return ViewSnapshot::create(WTFMove(surface));
1701 void webkitWebViewBaseDidStartProvisionalLoadForMainFrame(WebKitWebViewBase* webkitWebViewBase)
1703 if (webkitWebViewBase->priv->viewGestureController->isSwipeGestureEnabled())
1704 webkitWebViewBase->priv->viewGestureController->didStartProvisionalLoadForMainFrame();
1707 void webkitWebViewBaseDidFirstVisuallyNonEmptyLayoutForMainFrame(WebKitWebViewBase* webkitWebViewBase)
1709 if (webkitWebViewBase->priv->viewGestureController->isSwipeGestureEnabled())
1710 webkitWebViewBase->priv->viewGestureController->didFirstVisuallyNonEmptyLayoutForMainFrame();
1713 void webkitWebViewBaseDidFinishLoadForMainFrame(WebKitWebViewBase* webkitWebViewBase)
1715 if (webkitWebViewBase->priv->viewGestureController->isSwipeGestureEnabled())
1716 webkitWebViewBase->priv->viewGestureController->didFinishLoadForMainFrame();
1719 void webkitWebViewBaseDidFailLoadForMainFrame(WebKitWebViewBase* webkitWebViewBase)
1721 if (webkitWebViewBase->priv->viewGestureController->isSwipeGestureEnabled())
1722 webkitWebViewBase->priv->viewGestureController->didFailLoadForMainFrame();
1725 void webkitWebViewBaseDidSameDocumentNavigationForMainFrame(WebKitWebViewBase* webkitWebViewBase, SameDocumentNavigationType type)
1727 if (webkitWebViewBase->priv->viewGestureController->isSwipeGestureEnabled())
1728 webkitWebViewBase->priv->viewGestureController->didSameDocumentNavigationForMainFrame(type);
1731 void webkitWebViewBaseDidRestoreScrollPosition(WebKitWebViewBase* webkitWebViewBase)
1733 if (webkitWebViewBase->priv->viewGestureController->isSwipeGestureEnabled())
1734 webkitWebViewBase->priv->viewGestureController->didRestoreScrollPosition();