summaryrefslogtreecommitdiff
path: root/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp')
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp1059
1 files changed, 688 insertions, 371 deletions
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp
index b22c71fa1..b057a5a44 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp
@@ -29,15 +29,20 @@
#include "config.h"
#include "WebKitWebViewBase.h"
+#include "APIPageConfiguration.h"
+#include "AcceleratedBackingStore.h"
+#include "ActivityState.h"
#include "DrawingAreaProxyImpl.h"
+#include "InputMethodFilter.h"
+#include "KeyBindingTranslator.h"
+#include "NativeWebKeyboardEvent.h"
#include "NativeWebMouseEvent.h"
#include "NativeWebWheelEvent.h"
#include "PageClientImpl.h"
-#include "ViewState.h"
-#include "WebContext.h"
#include "WebEventFactory.h"
#include "WebFullScreenClientGtk.h"
#include "WebInspectorProxy.h"
+#include "WebKit2Initialize.h"
#include "WebKitAuthenticationDialog.h"
#include "WebKitPrivate.h"
#include "WebKitWebViewBaseAccessible.h"
@@ -45,37 +50,31 @@
#include "WebPageGroup.h"
#include "WebPageProxy.h"
#include "WebPreferences.h"
-#include "WebViewBaseInputMethodFilter.h"
+#include "WebProcessPool.h"
+#include "WebUserContentControllerProxy.h"
#include <WebCore/CairoUtilities.h>
-#include <WebCore/ClipboardUtilitiesGtk.h>
-#include <WebCore/DataObjectGtk.h>
-#include <WebCore/DragData.h>
-#include <WebCore/DragIcon.h>
#include <WebCore/GUniquePtrGtk.h>
-#include <WebCore/GtkClickCounter.h>
-#include <WebCore/GtkDragAndDropHelper.h>
-#include <WebCore/GtkTouchContextHelper.h>
#include <WebCore/GtkUtilities.h>
#include <WebCore/GtkVersioning.h>
#include <WebCore/NotImplemented.h>
#include <WebCore/PasteboardHelper.h>
+#include <WebCore/PlatformDisplay.h>
#include <WebCore/RefPtrCairo.h>
#include <WebCore/Region.h>
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
-#ifdef GDK_WINDOWING_X11
-#include <gdk/gdkx.h>
-#endif
+#include <glib/gi18n-lib.h>
+#include <memory>
#include <wtf/HashMap.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/CString.h>
#if ENABLE(FULLSCREEN_API)
#include "WebFullScreenManagerProxy.h"
#endif
-#if USE(TEXTURE_MAPPER_GL) && defined(GDK_WINDOWING_X11)
-#include <WebCore/RedirectedXCompositeWindow.h>
+#if PLATFORM(X11)
+#include <gdk/gdkx.h>
#endif
// gtk_widget_get_scale_factor() appeared in GTK 3.10, but we also need
@@ -85,130 +84,200 @@
using namespace WebKit;
using namespace WebCore;
-typedef HashMap<GtkWidget*, IntRect> WebKitWebViewChildrenMap;
+struct ClickCounter {
+public:
+ void reset()
+ {
+ currentClickCount = 0;
+ previousClickPoint = IntPoint();
+ previousClickTime = 0;
+ previousClickButton = 0;
+ }
-#if USE(TEXTURE_MAPPER_GL)
-void redirectedWindowDamagedCallback(void* data);
-#endif
+ int currentClickCountForGdkButtonEvent(GdkEventButton* buttonEvent)
+ {
+ GdkEvent* event = reinterpret_cast<GdkEvent*>(buttonEvent);
+ int doubleClickDistance = 250;
+ int doubleClickTime = 5;
+ g_object_get(gtk_settings_get_for_screen(gdk_event_get_screen(event)),
+ "gtk-double-click-distance", &doubleClickDistance, "gtk-double-click-time", &doubleClickTime, nullptr);
+
+ // GTK+ only counts up to triple clicks, but WebCore wants to know about
+ // quadruple clicks, quintuple clicks, ad infinitum. Here, we replicate the
+ // GDK logic for counting clicks.
+ guint32 eventTime = gdk_event_get_time(event);
+ if (!eventTime) {
+ // Real events always have a non-zero time, but events synthesized
+ // by the WTR do not and we must calculate a time manually. This time
+ // is not calculated in the WTR, because GTK+ does not work well with
+ // anything other than GDK_CURRENT_TIME on synthesized events.
+ GTimeVal timeValue;
+ g_get_current_time(&timeValue);
+ eventTime = (timeValue.tv_sec * 1000) + (timeValue.tv_usec / 1000);
+ }
+
+ if ((event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
+ || ((std::abs(buttonEvent->x - previousClickPoint.x()) < doubleClickDistance)
+ && (std::abs(buttonEvent->y - previousClickPoint.y()) < doubleClickDistance)
+ && (eventTime - previousClickTime < static_cast<unsigned>(doubleClickTime))
+ && (buttonEvent->button == previousClickButton)))
+ currentClickCount++;
+ else
+ currentClickCount = 1;
+
+ double x, y;
+ gdk_event_get_coords(event, &x, &y);
+ previousClickPoint = IntPoint(x, y);
+ previousClickButton = buttonEvent->button;
+ previousClickTime = eventTime;
+
+ return currentClickCount;
+ }
+
+private:
+ int currentClickCount;
+ IntPoint previousClickPoint;
+ unsigned previousClickButton;
+ int previousClickTime;
+};
+
+typedef HashMap<GtkWidget*, IntRect> WebKitWebViewChildrenMap;
+typedef HashMap<uint32_t, GUniquePtr<GdkEvent>> TouchEventsMap;
struct _WebKitWebViewBasePrivate {
+ _WebKitWebViewBasePrivate()
+ : updateActivityStateTimer(RunLoop::main(), this, &_WebKitWebViewBasePrivate::updateActivityStateTimerFired)
+ {
+ }
+
+ void updateActivityStateTimerFired()
+ {
+ if (!pageProxy)
+ return;
+ pageProxy->activityStateDidChange(activityStateFlagsToUpdate);
+ activityStateFlagsToUpdate = ActivityState::NoFlags;
+ }
+
WebKitWebViewChildrenMap children;
- OwnPtr<PageClientImpl> pageClient;
+ std::unique_ptr<PageClientImpl> pageClient;
RefPtr<WebPageProxy> pageProxy;
bool shouldForwardNextKeyEvent;
- GtkClickCounter clickCounter;
+ bool shouldForwardNextWheelEvent;
+ ClickCounter clickCounter;
CString tooltipText;
IntRect tooltipArea;
-#if ENABLE(DRAG_SUPPORT)
- GtkDragAndDropHelper dragAndDropHelper;
-#endif
- DragIcon dragIcon;
-#if !GTK_CHECK_VERSION(3, 13, 4)
- IntSize resizerSize;
-#endif
GRefPtr<AtkObject> accessible;
- bool needsResizeOnMap;
GtkWidget* authenticationDialog;
GtkWidget* inspectorView;
AttachmentSide inspectorAttachmentSide;
unsigned inspectorViewSize;
GUniquePtr<GdkEvent> contextMenuEvent;
WebContextMenuProxyGtk* activeContextMenuProxy;
- WebViewBaseInputMethodFilter inputMethodFilter;
- GtkTouchContextHelper touchContext;
+ InputMethodFilter inputMethodFilter;
+ KeyBindingTranslator keyBindingTranslator;
+ TouchEventsMap touchEvents;
+ IntSize contentsSize;
GtkWindow* toplevelOnScreenWindow;
-#if !GTK_CHECK_VERSION(3, 13, 4)
- unsigned long toplevelResizeGripVisibilityID;
-#endif
unsigned long toplevelFocusInEventID;
unsigned long toplevelFocusOutEventID;
- unsigned long toplevelVisibilityEventID;
+ unsigned long toplevelWindowStateEventID;
+ unsigned long toplevelWindowRealizedID;
// View State.
- bool isInWindowActive : 1;
- bool isFocused : 1;
- bool isVisible : 1;
- bool isWindowVisible : 1;
+ ActivityState::Flags activityState;
+ ActivityState::Flags activityStateFlagsToUpdate;
+ RunLoop::Timer<WebKitWebViewBasePrivate> updateActivityStateTimer;
WebKitWebViewBaseDownloadRequestHandler downloadHandler;
#if ENABLE(FULLSCREEN_API)
bool fullScreenModeActive;
WebFullScreenClientGtk fullScreenClient;
+ GRefPtr<GDBusProxy> screenSaverProxy;
+ GRefPtr<GCancellable> screenSaverInhibitCancellable;
+ unsigned screenSaverCookie;
+#endif
+
+ std::unique_ptr<AcceleratedBackingStore> acceleratedBackingStore;
+
+#if ENABLE(DRAG_SUPPORT)
+ std::unique_ptr<DragAndDropHandler> dragAndDropHandler;
#endif
-#if USE(TEXTURE_MAPPER_GL)
- OwnPtr<RedirectedXCompositeWindow> redirectedWindow;
+#if HAVE(GTK_GESTURES)
+ std::unique_ptr<GestureController> gestureController;
#endif
};
WEBKIT_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER)
-#if !GTK_CHECK_VERSION(3, 13, 4)
-static void webkitWebViewBaseNotifyResizerSize(WebKitWebViewBase* webViewBase)
+static void webkitWebViewBaseScheduleUpdateActivityState(WebKitWebViewBase* webViewBase, ActivityState::Flags flagsToUpdate)
{
WebKitWebViewBasePrivate* priv = webViewBase->priv;
- if (!priv->toplevelOnScreenWindow)
+ priv->activityStateFlagsToUpdate |= flagsToUpdate;
+ if (priv->updateActivityStateTimer.isActive())
return;
- gboolean resizerVisible;
- g_object_get(G_OBJECT(priv->toplevelOnScreenWindow), "resize-grip-visible", &resizerVisible, NULL);
-
- IntSize resizerSize;
- if (resizerVisible) {
- GdkRectangle resizerRect;
- gtk_window_get_resize_grip_area(priv->toplevelOnScreenWindow, &resizerRect);
- GdkRectangle allocation;
- gtk_widget_get_allocation(GTK_WIDGET(webViewBase), &allocation);
- if (gdk_rectangle_intersect(&resizerRect, &allocation, 0))
- resizerSize = IntSize(resizerRect.width, resizerRect.height);
- }
-
- if (resizerSize != priv->resizerSize) {
- priv->resizerSize = resizerSize;
- priv->pageProxy->setWindowResizerSize(resizerSize);
- }
+ priv->updateActivityStateTimer.startOneShot(0);
}
-static void toplevelWindowResizeGripVisibilityChanged(GObject*, GParamSpec*, WebKitWebViewBase* webViewBase)
+static gboolean toplevelWindowFocusInEvent(GtkWidget* widget, GdkEventFocus*, WebKitWebViewBase* webViewBase)
{
- webkitWebViewBaseNotifyResizerSize(webViewBase);
+ // Spurious focus in events can occur when the window is hidden.
+ if (!gtk_widget_get_visible(widget))
+ return FALSE;
+
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ if (priv->activityState & ActivityState::WindowIsActive)
+ return FALSE;
+
+ priv->activityState |= ActivityState::WindowIsActive;
+ webkitWebViewBaseScheduleUpdateActivityState(webViewBase, ActivityState::WindowIsActive);
+
+ return FALSE;
}
-#endif
-static gboolean toplevelWindowFocusInEvent(GtkWidget* widget, GdkEventFocus*, WebKitWebViewBase* webViewBase)
+static gboolean toplevelWindowFocusOutEvent(GtkWidget*, GdkEventFocus*, WebKitWebViewBase* webViewBase)
{
WebKitWebViewBasePrivate* priv = webViewBase->priv;
- if (!priv->isInWindowActive) {
- priv->isInWindowActive = true;
- priv->pageProxy->viewStateDidChange(ViewState::WindowIsActive);
- }
+ if (!(priv->activityState & ActivityState::WindowIsActive))
+ return FALSE;
+
+ priv->activityState &= ~ActivityState::WindowIsActive;
+ webkitWebViewBaseScheduleUpdateActivityState(webViewBase, ActivityState::WindowIsActive);
return FALSE;
}
-static gboolean toplevelWindowFocusOutEvent(GtkWidget* widget, GdkEventFocus*, WebKitWebViewBase* webViewBase)
+static gboolean toplevelWindowStateEvent(GtkWidget*, GdkEventWindowState* event, WebKitWebViewBase* webViewBase)
{
WebKitWebViewBasePrivate* priv = webViewBase->priv;
- if (priv->isInWindowActive) {
- priv->isInWindowActive = false;
- priv->pageProxy->viewStateDidChange(ViewState::WindowIsActive);
- }
+ if (!(event->changed_mask & GDK_WINDOW_STATE_ICONIFIED))
+ return FALSE;
+
+ bool visible = !(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED);
+ if ((visible && priv->activityState & ActivityState::IsVisible) || (!visible && !(priv->activityState & ActivityState::IsVisible)))
+ return FALSE;
+
+ if (visible)
+ priv->activityState |= ActivityState::IsVisible;
+ else
+ priv->activityState &= ~ActivityState::IsVisible;
+ webkitWebViewBaseScheduleUpdateActivityState(webViewBase, ActivityState::IsVisible);
return FALSE;
}
-static gboolean toplevelWindowVisibilityEvent(GtkWidget*, GdkEventVisibility* visibilityEvent, WebKitWebViewBase* webViewBase)
+static void toplevelWindowRealized(WebKitWebViewBase* webViewBase)
{
+ gtk_widget_realize(GTK_WIDGET(webViewBase));
+
WebKitWebViewBasePrivate* priv = webViewBase->priv;
- bool isWindowVisible = visibilityEvent->state != GDK_VISIBILITY_FULLY_OBSCURED;
- if (priv->isWindowVisible != isWindowVisible) {
- priv->isWindowVisible = isWindowVisible;
- priv->pageProxy->viewStateDidChange(ViewState::IsVisible);
+ if (priv->toplevelWindowRealizedID) {
+ g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelWindowRealizedID);
+ priv->toplevelWindowRealizedID = 0;
}
-
- return FALSE;
}
static void webkitWebViewBaseSetToplevelOnScreenWindow(WebKitWebViewBase* webViewBase, GtkWindow* window)
@@ -217,12 +286,6 @@ static void webkitWebViewBaseSetToplevelOnScreenWindow(WebKitWebViewBase* webVie
if (priv->toplevelOnScreenWindow == window)
return;
-#if !GTK_CHECK_VERSION(3, 13, 4)
- if (priv->toplevelResizeGripVisibilityID) {
- g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelResizeGripVisibilityID);
- priv->toplevelResizeGripVisibilityID = 0;
- }
-#endif
if (priv->toplevelFocusInEventID) {
g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelFocusInEventID);
priv->toplevelFocusInEventID = 0;
@@ -231,36 +294,53 @@ static void webkitWebViewBaseSetToplevelOnScreenWindow(WebKitWebViewBase* webVie
g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelFocusOutEventID);
priv->toplevelFocusOutEventID = 0;
}
- if (priv->toplevelVisibilityEventID) {
- g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelVisibilityEventID);
- priv->toplevelVisibilityEventID = 0;
+ if (priv->toplevelWindowStateEventID) {
+ g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelWindowStateEventID);
+ priv->toplevelWindowStateEventID = 0;
+ }
+ if (priv->toplevelWindowRealizedID) {
+ g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelWindowRealizedID);
+ priv->toplevelWindowRealizedID = 0;
}
priv->toplevelOnScreenWindow = window;
- priv->pageProxy->viewStateDidChange(ViewState::IsInWindow);
- if (!priv->toplevelOnScreenWindow)
- return;
-#if !GTK_CHECK_VERSION(3, 13, 4)
- webkitWebViewBaseNotifyResizerSize(webViewBase);
+ if (!priv->toplevelOnScreenWindow) {
+ ActivityState::Flags flagsToUpdate = 0;
+ if (priv->activityState & ActivityState::IsInWindow) {
+ priv->activityState &= ~ActivityState::IsInWindow;
+ flagsToUpdate |= ActivityState::IsInWindow;
+ }
+ if (priv->activityState & ActivityState::WindowIsActive) {
+ priv->activityState &= ~ActivityState::WindowIsActive;
+ flagsToUpdate |= ActivityState::IsInWindow;
+ }
+ if (flagsToUpdate)
+ webkitWebViewBaseScheduleUpdateActivityState(webViewBase, flagsToUpdate);
+
+ return;
+ }
- priv->toplevelResizeGripVisibilityID =
- g_signal_connect(priv->toplevelOnScreenWindow, "notify::resize-grip-visible",
- G_CALLBACK(toplevelWindowResizeGripVisibilityChanged), webViewBase);
-#endif
priv->toplevelFocusInEventID =
g_signal_connect(priv->toplevelOnScreenWindow, "focus-in-event",
G_CALLBACK(toplevelWindowFocusInEvent), webViewBase);
priv->toplevelFocusOutEventID =
g_signal_connect(priv->toplevelOnScreenWindow, "focus-out-event",
G_CALLBACK(toplevelWindowFocusOutEvent), webViewBase);
- priv->toplevelVisibilityEventID =
- g_signal_connect(priv->toplevelOnScreenWindow, "visibility-notify-event",
- G_CALLBACK(toplevelWindowVisibilityEvent), webViewBase);
+ priv->toplevelWindowStateEventID =
+ g_signal_connect(priv->toplevelOnScreenWindow, "window-state-event", G_CALLBACK(toplevelWindowStateEvent), webViewBase);
+
+ if (gtk_widget_get_realized(GTK_WIDGET(window)))
+ gtk_widget_realize(GTK_WIDGET(webViewBase));
+ else
+ priv->toplevelWindowRealizedID = g_signal_connect_swapped(window, "realize", G_CALLBACK(toplevelWindowRealized), webViewBase);
}
static void webkitWebViewBaseRealize(GtkWidget* widget)
{
+ WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(widget);
+ WebKitWebViewBasePrivate* priv = webView->priv;
+
gtk_widget_set_realized(widget, TRUE);
GtkAllocation allocation;
@@ -281,6 +361,8 @@ static void webkitWebViewBaseRealize(GtkWidget* widget)
| GDK_SCROLL_MASK
| GDK_SMOOTH_SCROLL_MASK
| GDK_POINTER_MOTION_MASK
+ | GDK_ENTER_NOTIFY_MASK
+ | GDK_LEAVE_NOTIFY_MASK
| GDK_KEY_PRESS_MASK
| GDK_KEY_RELEASE_MASK
| GDK_BUTTON_MOTION_MASK
@@ -295,12 +377,30 @@ static void webkitWebViewBaseRealize(GtkWidget* widget)
gtk_widget_set_window(widget, window);
gdk_window_set_user_data(window, widget);
+#if USE(TEXTURE_MAPPER_GL) && PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
+ if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11) {
+ if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea()))
+ drawingArea->setNativeSurfaceHandleForCompositing(GDK_WINDOW_XID(window));
+ }
+#endif
+
gtk_style_context_set_background(gtk_widget_get_style_context(widget), window);
+ gtk_im_context_set_client_window(priv->inputMethodFilter.context(), window);
+}
+
+static void webkitWebViewBaseUnrealize(GtkWidget* widget)
+{
WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(widget);
- GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
- if (widgetIsOnscreenToplevelWindow(toplevel))
- webkitWebViewBaseSetToplevelOnScreenWindow(webView, GTK_WINDOW(toplevel));
+#if USE(TEXTURE_MAPPER_GL) && PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
+ if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11) {
+ if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(webView->priv->pageProxy->drawingArea()))
+ drawingArea->destroyNativeSurfaceHandleForCompositing();
+ }
+#endif
+ gtk_im_context_set_client_window(webView->priv->inputMethodFilter.context(), nullptr);
+
+ GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->unrealize(widget);
}
static bool webkitWebViewChildIsInternalWidget(WebKitWebViewBase* webViewBase, GtkWidget* widget)
@@ -406,8 +506,10 @@ void webkitWebViewBaseChildMoveResize(WebKitWebViewBase* webView, GtkWidget* chi
static void webkitWebViewBaseDispose(GObject* gobject)
{
WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(gobject);
+ g_cancellable_cancel(webView->priv->screenSaverInhibitCancellable.get());
webkitWebViewBaseSetToplevelOnScreenWindow(webView, nullptr);
webView->priv->pageProxy->close();
+ webView->priv->acceleratedBackingStore = nullptr;
G_OBJECT_CLASS(webkit_web_view_base_parent_class)->dispose(gobject);
}
@@ -417,48 +519,15 @@ static void webkitWebViewBaseConstructed(GObject* object)
GtkWidget* viewWidget = GTK_WIDGET(object);
gtk_widget_set_can_focus(viewWidget, TRUE);
- gtk_drag_dest_set(viewWidget, static_cast<GtkDestDefaults>(0), 0, 0,
- static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
- gtk_drag_dest_set_target_list(viewWidget, PasteboardHelper::defaultPasteboardHelper()->targetList());
+ gtk_drag_dest_set(viewWidget, static_cast<GtkDestDefaults>(0), nullptr, 0,
+ static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
+ gtk_drag_dest_set_target_list(viewWidget, PasteboardHelper::singleton().targetList());
WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(object)->priv;
- priv->pageClient = PageClientImpl::create(viewWidget);
-#if ENABLE(DRAG_SUPPORT)
- priv->dragAndDropHelper.setWidget(viewWidget);
-#endif
-
-#if USE(TEXTURE_MAPPER_GL) && defined(GDK_WINDOWING_X11)
- GdkDisplay* display = gdk_display_manager_get_default_display(gdk_display_manager_get());
- if (GDK_IS_X11_DISPLAY(display)) {
- priv->redirectedWindow = RedirectedXCompositeWindow::create(IntSize(1, 1), RedirectedXCompositeWindow::DoNotCreateGLContext);
- if (priv->redirectedWindow)
- priv->redirectedWindow->setDamageNotifyCallback(redirectedWindowDamagedCallback, object);
- }
-#endif
-
+ priv->pageClient = std::make_unique<PageClientImpl>(viewWidget);
priv->authenticationDialog = 0;
}
-#if USE(TEXTURE_MAPPER_GL)
-static bool webkitWebViewRenderAcceleratedCompositingResults(WebKitWebViewBase* webViewBase, DrawingAreaProxyImpl* drawingArea, cairo_t* cr, GdkRectangle* clipRect)
-{
- if (!drawingArea->isInAcceleratedCompositingMode())
- return false;
-
- // To avoid flashes when initializing accelerated compositing for the first
- // time, we wait until we know there's a frame ready before rendering.
- WebKitWebViewBasePrivate* priv = webViewBase->priv;
- if (!priv->redirectedWindow)
- return false;
-
- cairo_rectangle(cr, clipRect->x, clipRect->y, clipRect->width, clipRect->height);
- cairo_surface_t* surface = priv->redirectedWindow->cairoSurfaceForWidget(GTK_WIDGET(webViewBase));
- cairo_set_source_surface(cr, surface, 0, 0);
- cairo_fill(cr);
- return true;
-}
-#endif
-
static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
@@ -470,18 +539,11 @@ static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr)
if (!gdk_cairo_get_clip_rectangle(cr, &clipRect))
return FALSE;
-#if USE(TEXTURE_MAPPER_GL)
- if (webkitWebViewRenderAcceleratedCompositingResults(webViewBase, drawingArea, cr, &clipRect))
- return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->draw(widget, cr);
-#endif
-
- WebCore::Region unpaintedRegion; // This is simply unused.
- drawingArea->paint(cr, clipRect, unpaintedRegion);
-
- if (webViewBase->priv->authenticationDialog) {
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- cairo_set_source_rgba(cr, 0, 0, 0, 0.5);
- cairo_paint(cr);
+ if (webViewBase->priv->acceleratedBackingStore && drawingArea->isInAcceleratedCompositingMode())
+ webViewBase->priv->acceleratedBackingStore->paint(cr, clipRect);
+ else {
+ WebCore::Region unpaintedRegion; // This is simply unused.
+ drawingArea->paint(cr, clipRect, unpaintedRegion);
}
GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->draw(widget, cr);
@@ -505,8 +567,11 @@ static void webkitWebViewBaseChildAllocate(GtkWidget* child, gpointer userData)
priv->children.set(child, IntRect());
}
-static void resizeWebKitWebViewBaseFromAllocation(WebKitWebViewBase* webViewBase, GtkAllocation* allocation, bool sizeChanged)
+static void webkitWebViewBaseSizeAllocate(GtkWidget* widget, GtkAllocation* allocation)
{
+ GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->size_allocate(widget, allocation);
+
+ WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
gtk_container_foreach(GTK_CONTAINER(webViewBase), webkitWebViewBaseChildAllocate, webViewBase);
IntRect viewRect(allocation->x, allocation->y, allocation->width, allocation->height);
@@ -514,7 +579,7 @@ static void resizeWebKitWebViewBaseFromAllocation(WebKitWebViewBase* webViewBase
if (priv->inspectorView) {
GtkAllocation childAllocation = viewRect;
- if (priv->inspectorAttachmentSide == AttachmentSideBottom) {
+ if (priv->inspectorAttachmentSide == AttachmentSide::Bottom) {
int inspectorViewHeight = std::min(static_cast<int>(priv->inspectorViewSize), allocation->height);
childAllocation.x = 0;
childAllocation.y = allocation->height - inspectorViewHeight;
@@ -535,45 +600,29 @@ static void resizeWebKitWebViewBaseFromAllocation(WebKitWebViewBase* webViewBase
// never overlaps the web inspector. Thus, we need to calculate the allocation here
// after calculating the inspector allocation.
if (priv->authenticationDialog) {
- GtkRequisition naturalSize;
- gtk_widget_get_preferred_size(priv->authenticationDialog, 0, &naturalSize);
-
- GtkAllocation childAllocation = {
- (viewRect.width() - naturalSize.width) / 2,
- (viewRect.height() - naturalSize.height) / 2,
- naturalSize.width,
- naturalSize.height
- };
+ GtkRequisition minimumSize;
+ gtk_widget_get_preferred_size(priv->authenticationDialog, &minimumSize, nullptr);
+
+ GtkAllocation childAllocation = { 0, 0, std::max(minimumSize.width, viewRect.width()), std::max(minimumSize.height, viewRect.height()) };
gtk_widget_size_allocate(priv->authenticationDialog, &childAllocation);
}
-#if USE(TEXTURE_MAPPER_GL)
- if (sizeChanged && webViewBase->priv->redirectedWindow)
- webViewBase->priv->redirectedWindow->resize(viewRect.size());
-#endif
-
- if (priv->pageProxy->drawingArea())
- priv->pageProxy->drawingArea()->setSize(viewRect.size(), IntSize(), IntSize());
-
-#if !GTK_CHECK_VERSION(3, 13, 4)
- webkitWebViewBaseNotifyResizerSize(webViewBase);
-#endif
+ if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea()))
+ drawingArea->setSize(viewRect.size(), IntSize(), IntSize());
}
-static void webkitWebViewBaseSizeAllocate(GtkWidget* widget, GtkAllocation* allocation)
+static void webkitWebViewBaseGetPreferredWidth(GtkWidget* widget, gint* minimumSize, gint* naturalSize)
{
- bool sizeChanged = gtk_widget_get_allocated_width(widget) != allocation->width
- || gtk_widget_get_allocated_height(widget) != allocation->height;
-
- GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->size_allocate(widget, allocation);
-
- WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
- if (sizeChanged && !gtk_widget_get_mapped(widget)) {
- webViewBase->priv->needsResizeOnMap = true;
- return;
- }
+ WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
+ *minimumSize = 0;
+ *naturalSize = priv->contentsSize.width();
+}
- resizeWebKitWebViewBaseFromAllocation(webViewBase, allocation, sizeChanged);
+static void webkitWebViewBaseGetPreferredHeight(GtkWidget* widget, gint* minimumSize, gint* naturalSize)
+{
+ WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
+ *minimumSize = 0;
+ *naturalSize = priv->contentsSize.height();
}
static void webkitWebViewBaseMap(GtkWidget* widget)
@@ -582,29 +631,33 @@ static void webkitWebViewBaseMap(GtkWidget* widget)
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
- if (!priv->isVisible) {
- priv->isVisible = true;
- priv->pageProxy->viewStateDidChange(ViewState::IsVisible);
+ ActivityState::Flags flagsToUpdate = 0;
+ if (!(priv->activityState & ActivityState::IsVisible))
+ flagsToUpdate |= ActivityState::IsVisible;
+ if (priv->toplevelOnScreenWindow) {
+ if (!(priv->activityState & ActivityState::IsInWindow))
+ flagsToUpdate |= ActivityState::IsInWindow;
+ if (gtk_window_is_active(GTK_WINDOW(priv->toplevelOnScreenWindow)) && !(priv->activityState & ActivityState::WindowIsActive))
+ flagsToUpdate |= ActivityState::WindowIsActive;
}
-
- if (!priv->needsResizeOnMap)
+ if (!flagsToUpdate)
return;
- GtkAllocation allocation;
- gtk_widget_get_allocation(widget, &allocation);
- resizeWebKitWebViewBaseFromAllocation(webViewBase, &allocation, true /* sizeChanged */);
- priv->needsResizeOnMap = false;
+ priv->activityState |= flagsToUpdate;
+ webkitWebViewBaseScheduleUpdateActivityState(webViewBase, flagsToUpdate);
}
static void webkitWebViewBaseUnmap(GtkWidget* widget)
{
GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->unmap(widget);
- WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
- if (priv->isVisible) {
- priv->isVisible = false;
- priv->pageProxy->viewStateDidChange(ViewState::IsVisible);
- }
+ WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ if (!(priv->activityState & ActivityState::IsVisible))
+ return;
+
+ priv->activityState &= ~ActivityState::IsVisible;
+ webkitWebViewBaseScheduleUpdateActivityState(webViewBase, ActivityState::IsVisible);
}
static gboolean webkitWebViewBaseFocusInEvent(GtkWidget* widget, GdkEventFocus* event)
@@ -625,17 +678,26 @@ static gboolean webkitWebViewBaseFocusOutEvent(GtkWidget* widget, GdkEventFocus*
return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus_out_event(widget, event);
}
-static gboolean webkitWebViewBaseKeyPressEvent(GtkWidget* widget, GdkEventKey* event)
+static gboolean webkitWebViewBaseKeyPressEvent(GtkWidget* widget, GdkEventKey* keyEvent)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
+#if ENABLE(DEVELOPER_MODE) && OS(LINUX)
+ if ((keyEvent->state & GDK_CONTROL_MASK) && (keyEvent->state & GDK_SHIFT_MASK) && keyEvent->keyval == GDK_KEY_G) {
+ auto& preferences = priv->pageProxy->preferences();
+ preferences.setResourceUsageOverlayVisible(!preferences.resourceUsageOverlayVisible());
+ priv->shouldForwardNextKeyEvent = FALSE;
+ return TRUE;
+ }
+#endif
+
if (priv->authenticationDialog)
- return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, event);
+ return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, keyEvent);
#if ENABLE(FULLSCREEN_API)
if (priv->fullScreenModeActive) {
- switch (event->keyval) {
+ switch (keyEvent->keyval) {
case GDK_KEY_Escape:
case GDK_KEY_f:
case GDK_KEY_F:
@@ -653,22 +715,35 @@ static gboolean webkitWebViewBaseKeyPressEvent(GtkWidget* widget, GdkEventKey* e
// using gtk_main_do_event().
if (priv->shouldForwardNextKeyEvent) {
priv->shouldForwardNextKeyEvent = FALSE;
- return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, event);
+ return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, keyEvent);
}
- priv->inputMethodFilter.filterKeyEvent(event);
+
+ // We need to copy the event as otherwise it could be destroyed before we reach the lambda body.
+ GUniquePtr<GdkEvent> event(gdk_event_copy(reinterpret_cast<GdkEvent*>(keyEvent)));
+ priv->inputMethodFilter.filterKeyEvent(keyEvent, [priv, event = WTFMove(event)](const WebCore::CompositionResults& compositionResults, InputMethodFilter::EventFakedForComposition faked) {
+ priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(event.get(), compositionResults, faked,
+ !compositionResults.compositionUpdated() ? priv->keyBindingTranslator.commandsForKeyEvent(&event->key) : Vector<String>()));
+ });
+
return TRUE;
}
-static gboolean webkitWebViewBaseKeyReleaseEvent(GtkWidget* widget, GdkEventKey* event)
+static gboolean webkitWebViewBaseKeyReleaseEvent(GtkWidget* widget, GdkEventKey* keyEvent)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
if (priv->shouldForwardNextKeyEvent) {
priv->shouldForwardNextKeyEvent = FALSE;
- return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_release_event(widget, event);
+ return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_release_event(widget, keyEvent);
}
- priv->inputMethodFilter.filterKeyEvent(event);
+
+ // We need to copy the event as otherwise it could be destroyed before we reach the lambda body.
+ GUniquePtr<GdkEvent> event(gdk_event_copy(reinterpret_cast<GdkEvent*>(keyEvent)));
+ priv->inputMethodFilter.filterKeyEvent(keyEvent, [priv, event = WTFMove(event)](const WebCore::CompositionResults& compositionResults, InputMethodFilter::EventFakedForComposition faked) {
+ priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(event.get(), compositionResults, faked, { }));
+ });
+
return TRUE;
}
@@ -684,14 +759,21 @@ static gboolean webkitWebViewBaseButtonPressEvent(GtkWidget* widget, GdkEventBut
priv->inputMethodFilter.notifyMouseButtonPress();
- if (!priv->clickCounter.shouldProcessButtonEvent(buttonEvent))
+ // For double and triple clicks GDK sends both a normal button press event
+ // and a specific type (like GDK_2BUTTON_PRESS). If we detect a special press
+ // coming up, ignore this event as it certainly generated the double or triple
+ // click. The consequence of not eating this event is two DOM button press events
+ // are generated.
+ GUniquePtr<GdkEvent> nextEvent(gdk_event_peek());
+ if (nextEvent && (nextEvent->any.type == GDK_2BUTTON_PRESS || nextEvent->any.type == GDK_3BUTTON_PRESS))
return TRUE;
// If it's a right click event save it as a possible context menu event.
if (buttonEvent->button == 3)
priv->contextMenuEvent.reset(gdk_event_copy(reinterpret_cast<GdkEvent*>(buttonEvent)));
+
priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(buttonEvent),
- priv->clickCounter.clickCountForGdkButtonEvent(widget, buttonEvent)));
+ priv->clickCounter.currentClickCountForGdkButtonEvent(buttonEvent)));
return TRUE;
}
@@ -714,41 +796,195 @@ static gboolean webkitWebViewBaseScrollEvent(GtkWidget* widget, GdkEventScroll*
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ if (std::exchange(priv->shouldForwardNextWheelEvent, false))
+ return FALSE;
+
if (priv->authenticationDialog)
- return TRUE;
+ return FALSE;
priv->pageProxy->handleWheelEvent(NativeWebWheelEvent(reinterpret_cast<GdkEvent*>(event)));
return TRUE;
}
+static gboolean webkitWebViewBasePopupMenu(GtkWidget* widget)
+{
+ WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+
+ GdkEvent* currentEvent = gtk_get_current_event();
+ if (!currentEvent)
+ currentEvent = gdk_event_new(GDK_NOTHING);
+ priv->contextMenuEvent.reset(currentEvent);
+ priv->pageProxy->handleContextMenuKeyEvent();
+
+ return TRUE;
+}
+
static gboolean webkitWebViewBaseMotionNotifyEvent(GtkWidget* widget, GdkEventMotion* event)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
- if (priv->authenticationDialog)
- return TRUE;
+ if (priv->authenticationDialog) {
+ auto* widgetClass = GTK_WIDGET_CLASS(webkit_web_view_base_parent_class);
+ return widgetClass->motion_notify_event ? widgetClass->motion_notify_event(widget, event) : FALSE;
+ }
priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(event), 0 /* currentClickCount */));
- return TRUE;
+ return FALSE;
+}
+
+static gboolean webkitWebViewBaseCrossingNotifyEvent(GtkWidget* widget, GdkEventCrossing* crosssingEvent)
+{
+ WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+
+ if (priv->authenticationDialog)
+ return FALSE;
+
+ // In the case of crossing events, it's very important the actual coordinates the WebProcess receives, because once the mouse leaves
+ // 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
+ // event are not accurate, the WebProcess might not know the mouse left the view. This can happen because of double to integer conversion,
+ // 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
+ // because those coordinates are inside the web view.
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(widget, &allocation);
+ double width = allocation.width;
+ double height = allocation.height;
+ double x = crosssingEvent->x;
+ double y = crosssingEvent->y;
+ if (x < 0 && x > -1)
+ x = -1;
+ else if (x >= width && x < width + 1)
+ x = width + 1;
+ if (y < 0 && y > -1)
+ y = -1;
+ else if (y >= height && y < height + 1)
+ y = height + 1;
+
+ GdkEvent* event = reinterpret_cast<GdkEvent*>(crosssingEvent);
+ GUniquePtr<GdkEvent> copiedEvent;
+ if (x != crosssingEvent->x || y != crosssingEvent->y) {
+ copiedEvent.reset(gdk_event_copy(event));
+ copiedEvent->crossing.x = x;
+ copiedEvent->crossing.y = y;
+ }
+
+ priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(copiedEvent ? copiedEvent.get() : event, 0 /* currentClickCount */));
+
+ return FALSE;
+}
+
+#if ENABLE(TOUCH_EVENTS)
+static void appendTouchEvent(Vector<WebPlatformTouchPoint>& touchPoints, const GdkEvent* event, WebPlatformTouchPoint::TouchPointState state)
+{
+ gdouble x, y;
+ gdk_event_get_coords(event, &x, &y);
+
+ gdouble xRoot, yRoot;
+ gdk_event_get_root_coords(event, &xRoot, &yRoot);
+
+ uint32_t identifier = GPOINTER_TO_UINT(gdk_event_get_event_sequence(event));
+ touchPoints.uncheckedAppend(WebPlatformTouchPoint(identifier, state, IntPoint(xRoot, yRoot), IntPoint(x, y)));
+}
+
+static inline WebPlatformTouchPoint::TouchPointState touchPointStateForEvents(const GdkEvent* current, const GdkEvent* event)
+{
+ if (gdk_event_get_event_sequence(current) != gdk_event_get_event_sequence(event))
+ return WebPlatformTouchPoint::TouchStationary;
+
+ switch (current->type) {
+ case GDK_TOUCH_UPDATE:
+ return WebPlatformTouchPoint::TouchMoved;
+ case GDK_TOUCH_BEGIN:
+ return WebPlatformTouchPoint::TouchPressed;
+ case GDK_TOUCH_END:
+ return WebPlatformTouchPoint::TouchReleased;
+ default:
+ return WebPlatformTouchPoint::TouchStationary;
+ }
+}
+
+static void webkitWebViewBaseGetTouchPointsForEvent(WebKitWebViewBase* webViewBase, GdkEvent* event, Vector<WebPlatformTouchPoint>& touchPoints)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ touchPoints.reserveInitialCapacity(event->type == GDK_TOUCH_END ? priv->touchEvents.size() + 1 : priv->touchEvents.size());
+
+ for (const auto& it : priv->touchEvents)
+ appendTouchEvent(touchPoints, it.value.get(), touchPointStateForEvents(it.value.get(), event));
+
+ // Touch was already removed from the TouchEventsMap, add it here.
+ if (event->type == GDK_TOUCH_END)
+ appendTouchEvent(touchPoints, event, WebPlatformTouchPoint::TouchReleased);
}
static gboolean webkitWebViewBaseTouchEvent(GtkWidget* widget, GdkEventTouch* event)
{
- WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
+ WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
if (priv->authenticationDialog)
return TRUE;
- priv->touchContext.handleEvent(reinterpret_cast<GdkEvent*>(event));
- priv->pageProxy->handleTouchEvent(NativeWebTouchEvent(reinterpret_cast<GdkEvent*>(event), priv->touchContext));
+ GdkEvent* touchEvent = reinterpret_cast<GdkEvent*>(event);
+ uint32_t sequence = GPOINTER_TO_UINT(gdk_event_get_event_sequence(touchEvent));
+
+#if HAVE(GTK_GESTURES)
+ GestureController& gestureController = webkitWebViewBaseGestureController(webViewBase);
+ if (gestureController.isProcessingGestures()) {
+ // If we are already processing gestures is because the WebProcess didn't handle the
+ // BEGIN touch event, so pass subsequent events to the GestureController.
+ gestureController.handleEvent(touchEvent);
+ // Remove the gesture event sequence from the handled touch events
+ // list to avoid the gesure sequence and a touch sequence of same
+ // ID to conflict.
+ priv->touchEvents.remove(sequence);
+ return TRUE;
+ }
+#endif
+
+ switch (touchEvent->type) {
+ case GDK_TOUCH_BEGIN: {
+ ASSERT(!priv->touchEvents.contains(sequence));
+ GUniquePtr<GdkEvent> event(gdk_event_copy(touchEvent));
+ priv->touchEvents.add(sequence, WTFMove(event));
+ break;
+ }
+ case GDK_TOUCH_UPDATE: {
+ auto it = priv->touchEvents.find(sequence);
+ ASSERT(it != priv->touchEvents.end());
+ it->value.reset(gdk_event_copy(touchEvent));
+ break;
+ }
+ case GDK_TOUCH_END:
+ ASSERT(priv->touchEvents.contains(sequence));
+ priv->touchEvents.remove(sequence);
+ break;
+ default:
+ break;
+ }
+
+ Vector<WebPlatformTouchPoint> touchPoints;
+ webkitWebViewBaseGetTouchPointsForEvent(webViewBase, touchEvent, touchPoints);
+ priv->pageProxy->handleTouchEvent(NativeWebTouchEvent(reinterpret_cast<GdkEvent*>(event), WTFMove(touchPoints)));
return TRUE;
}
+#endif // ENABLE(TOUCH_EVENTS)
+
+#if HAVE(GTK_GESTURES)
+GestureController& webkitWebViewBaseGestureController(WebKitWebViewBase* webViewBase)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ if (!priv->gestureController)
+ priv->gestureController = std::make_unique<GestureController>(*priv->pageProxy);
+ return *priv->gestureController;
+}
+#endif
-static gboolean webkitWebViewBaseQueryTooltip(GtkWidget* widget, gint x, gint y, gboolean keyboardMode, GtkTooltip* tooltip)
+static gboolean webkitWebViewBaseQueryTooltip(GtkWidget* widget, gint /* x */, gint /* y */, gboolean keyboardMode, GtkTooltip* tooltip)
{
WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
@@ -772,39 +1008,23 @@ static gboolean webkitWebViewBaseQueryTooltip(GtkWidget* widget, gint x, gint y,
}
#if ENABLE(DRAG_SUPPORT)
-static void webkitWebViewBaseDragDataGet(GtkWidget* widget, GdkDragContext* context, GtkSelectionData* selectionData, guint info, guint time)
+static void webkitWebViewBaseDragDataGet(GtkWidget* widget, GdkDragContext* context, GtkSelectionData* selectionData, guint info, guint /* time */)
{
- WEBKIT_WEB_VIEW_BASE(widget)->priv->dragAndDropHelper.handleGetDragData(context, selectionData, info);
+ WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
+ ASSERT(priv->dragAndDropHandler);
+ priv->dragAndDropHandler->fillDragData(context, selectionData, info);
}
static void webkitWebViewBaseDragEnd(GtkWidget* widget, GdkDragContext* context)
{
- WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
- if (!webViewBase->priv->dragAndDropHelper.handleDragEnd(context))
- return;
-
- GdkDevice* device = gdk_drag_context_get_device(context);
- int x = 0, y = 0;
- gdk_device_get_window_at_position(device, &x, &y);
- int xRoot = 0, yRoot = 0;
- gdk_device_get_position(device, 0, &xRoot, &yRoot);
- webViewBase->priv->pageProxy->dragEnded(IntPoint(x, y), IntPoint(xRoot, yRoot),
- gdkDragActionToDragOperation(gdk_drag_context_get_selected_action(context)));
+ WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
+ ASSERT(priv->dragAndDropHandler);
+ priv->dragAndDropHandler->finishDrag(context);
}
-static void webkitWebViewBaseDragDataReceived(GtkWidget* widget, GdkDragContext* context, gint x, gint y, GtkSelectionData* selectionData, guint info, guint time)
+static void webkitWebViewBaseDragDataReceived(GtkWidget* widget, GdkDragContext* context, gint /* x */, gint /* y */, GtkSelectionData* selectionData, guint info, guint time)
{
- WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
- IntPoint position;
- DataObjectGtk* dataObject = webViewBase->priv->dragAndDropHelper.handleDragDataReceived(context, selectionData, info, position);
- if (!dataObject)
- return;
-
- DragData dragData(dataObject, position, convertWidgetPointToScreenPoint(widget, position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
- webViewBase->priv->pageProxy->resetDragOperation();
- webViewBase->priv->pageProxy->dragEntered(dragData);
- DragOperation operation = webViewBase->priv->pageProxy->dragSession().operation;
- gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
+ webkitWebViewBaseDragAndDropHandler(WEBKIT_WEB_VIEW_BASE(widget)).dragEntered(context, selectionData, info, time);
}
#endif // ENABLE(DRAG_SUPPORT)
@@ -839,57 +1059,38 @@ static AtkObject* webkitWebViewBaseGetAccessible(GtkWidget* widget)
#if ENABLE(DRAG_SUPPORT)
static gboolean webkitWebViewBaseDragMotion(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
{
- WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
- IntPoint position(x, y);
- DataObjectGtk* dataObject = webViewBase->priv->dragAndDropHelper.handleDragMotion(context, position, time);
- if (!dataObject)
- return TRUE;
-
- DragData dragData(dataObject, position, convertWidgetPointToScreenPoint(widget, position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
- webViewBase->priv->pageProxy->dragUpdated(dragData);
- DragOperation operation = webViewBase->priv->pageProxy->dragSession().operation;
- gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
+ webkitWebViewBaseDragAndDropHandler(WEBKIT_WEB_VIEW_BASE(widget)).dragMotion(context, IntPoint(x, y), time);
return TRUE;
}
-static void dragExitedCallback(GtkWidget* widget, DragData& dragData, bool dropHappened)
-{
- // Don't call dragExited if we have just received a drag-drop signal. This
- // happens in the case of a successful drop onto the view.
- if (dropHappened)
- return;
-
- WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
- webViewBase->priv->pageProxy->dragExited(dragData);
- webViewBase->priv->pageProxy->resetDragOperation();
-}
-
-static void webkitWebViewBaseDragLeave(GtkWidget* widget, GdkDragContext* context, guint time)
+static void webkitWebViewBaseDragLeave(GtkWidget* widget, GdkDragContext* context, guint /* time */)
{
- WEBKIT_WEB_VIEW_BASE(widget)->priv->dragAndDropHelper.handleDragLeave(context, dragExitedCallback);
+ WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
+ ASSERT(priv->dragAndDropHandler);
+ priv->dragAndDropHandler->dragLeave(context);
}
static gboolean webkitWebViewBaseDragDrop(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
{
- WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
- DataObjectGtk* dataObject = webViewBase->priv->dragAndDropHelper.handleDragDrop(context);
- if (!dataObject)
- return FALSE;
-
- IntPoint position(x, y);
- DragData dragData(dataObject, position, convertWidgetPointToScreenPoint(widget, position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
- SandboxExtension::Handle handle;
- SandboxExtension::HandleArray sandboxExtensionForUpload;
- webViewBase->priv->pageProxy->performDrag(dragData, String(), handle, sandboxExtensionForUpload);
- gtk_drag_finish(context, TRUE, FALSE, time);
- return TRUE;
+ WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
+ ASSERT(priv->dragAndDropHandler);
+ return priv->dragAndDropHandler->drop(context, IntPoint(x, y), time);
}
#endif // ENABLE(DRAG_SUPPORT)
-static void webkitWebViewBaseParentSet(GtkWidget* widget, GtkWidget* oldParent)
+static void webkitWebViewBaseHierarchyChanged(GtkWidget* widget, GtkWidget* oldToplevel)
{
- if (!gtk_widget_get_parent(widget))
- webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), 0);
+ WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
+ if (widgetIsOnscreenToplevelWindow(oldToplevel) && GTK_WINDOW(oldToplevel) == priv->toplevelOnScreenWindow) {
+ webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), nullptr);
+ return;
+ }
+
+ if (!oldToplevel) {
+ GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
+ if (widgetIsOnscreenToplevelWindow(toplevel))
+ webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), GTK_WINDOW(toplevel));
+ }
}
static gboolean webkitWebViewBaseFocus(GtkWidget* widget, GtkDirectionType direction)
@@ -919,8 +1120,11 @@ static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebVie
{
GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webkitWebViewBaseClass);
widgetClass->realize = webkitWebViewBaseRealize;
+ widgetClass->unrealize = webkitWebViewBaseUnrealize;
widgetClass->draw = webkitWebViewBaseDraw;
widgetClass->size_allocate = webkitWebViewBaseSizeAllocate;
+ widgetClass->get_preferred_width = webkitWebViewBaseGetPreferredWidth;
+ widgetClass->get_preferred_height = webkitWebViewBaseGetPreferredHeight;
widgetClass->map = webkitWebViewBaseMap;
widgetClass->unmap = webkitWebViewBaseUnmap;
widgetClass->focus = webkitWebViewBaseFocus;
@@ -931,8 +1135,13 @@ static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebVie
widgetClass->button_press_event = webkitWebViewBaseButtonPressEvent;
widgetClass->button_release_event = webkitWebViewBaseButtonReleaseEvent;
widgetClass->scroll_event = webkitWebViewBaseScrollEvent;
+ widgetClass->popup_menu = webkitWebViewBasePopupMenu;
widgetClass->motion_notify_event = webkitWebViewBaseMotionNotifyEvent;
+ widgetClass->enter_notify_event = webkitWebViewBaseCrossingNotifyEvent;
+ widgetClass->leave_notify_event = webkitWebViewBaseCrossingNotifyEvent;
+#if ENABLE(TOUCH_EVENTS)
widgetClass->touch_event = webkitWebViewBaseTouchEvent;
+#endif
widgetClass->query_tooltip = webkitWebViewBaseQueryTooltip;
#if ENABLE(DRAG_SUPPORT)
widgetClass->drag_end = webkitWebViewBaseDragEnd;
@@ -943,7 +1152,7 @@ static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebVie
widgetClass->drag_data_received = webkitWebViewBaseDragDataReceived;
#endif // ENABLE(DRAG_SUPPORT)
widgetClass->get_accessible = webkitWebViewBaseGetAccessible;
- widgetClass->parent_set = webkitWebViewBaseParentSet;
+ widgetClass->hierarchy_changed = webkitWebViewBaseHierarchyChanged;
widgetClass->destroy = webkitWebViewBaseDestroy;
GObjectClass* gobjectClass = G_OBJECT_CLASS(webkitWebViewBaseClass);
@@ -954,12 +1163,17 @@ static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebVie
containerClass->add = webkitWebViewBaseContainerAdd;
containerClass->remove = webkitWebViewBaseContainerRemove;
containerClass->forall = webkitWebViewBaseContainerForall;
+
+ // Before creating a WebKitWebViewBasePriv we need to be sure that WebKit is started.
+ // Usually starting a context triggers InitializeWebKit2, but in case
+ // we create a view without asking before for a default_context we get a crash.
+ WebKit::InitializeWebKit2();
}
-WebKitWebViewBase* webkitWebViewBaseCreate(WebContext* context, WebPageGroup* pageGroup, WebPageProxy* relatedPage)
+WebKitWebViewBase* webkitWebViewBaseCreate(const API::PageConfiguration& configuration)
{
- WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(g_object_new(WEBKIT_TYPE_WEB_VIEW_BASE, NULL));
- webkitWebViewBaseCreateWebPage(webkitWebViewBase, context, pageGroup, relatedPage);
+ WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(g_object_new(WEBKIT_TYPE_WEB_VIEW_BASE, nullptr));
+ webkitWebViewBaseCreateWebPage(webkitWebViewBase, configuration.copy());
return webkitWebViewBase;
}
@@ -973,18 +1187,6 @@ WebPageProxy* webkitWebViewBaseGetPage(WebKitWebViewBase* webkitWebViewBase)
return webkitWebViewBase->priv->pageProxy.get();
}
-void webkitWebViewBaseUpdatePreferences(WebKitWebViewBase* webkitWebViewBase)
-{
- WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
-
-#if USE(TEXTURE_MAPPER_GL)
- if (priv->redirectedWindow)
- return;
-#endif
-
- priv->pageProxy->pageGroup().preferences()->setAcceleratedCompositingEnabled(false);
-}
-
#if HAVE(GTK_SCALE_FACTOR)
static void deviceScaleFactorChanged(WebKitWebViewBase* webkitWebViewBase)
{
@@ -992,32 +1194,22 @@ static void deviceScaleFactorChanged(WebKitWebViewBase* webkitWebViewBase)
}
#endif // HAVE(GTK_SCALE_FACTOR)
-void webkitWebViewBaseCreateWebPage(WebKitWebViewBase* webkitWebViewBase, WebContext* context, WebPageGroup* pageGroup, WebPageProxy* relatedPage)
+void webkitWebViewBaseCreateWebPage(WebKitWebViewBase* webkitWebViewBase, Ref<API::PageConfiguration>&& configuration)
{
WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
-
- WebPageConfiguration webPageConfiguration;
- webPageConfiguration.pageGroup = pageGroup;
- webPageConfiguration.relatedPage = relatedPage;
- priv->pageProxy = context->createWebPage(*priv->pageClient, std::move(webPageConfiguration));
+ WebProcessPool* processPool = configuration->processPool();
+ priv->pageProxy = processPool->createWebPage(*priv->pageClient, WTFMove(configuration));
priv->pageProxy->initializeWebPage();
-#if USE(TEXTURE_MAPPER_GL)
- if (priv->redirectedWindow)
- priv->pageProxy->setAcceleratedCompositingWindowId(priv->redirectedWindow->windowId());
-#endif
+ priv->acceleratedBackingStore = AcceleratedBackingStore::create(*priv->pageProxy);
+
+ priv->inputMethodFilter.setPage(priv->pageProxy.get());
#if HAVE(GTK_SCALE_FACTOR)
// We attach this here, because changes in scale factor are passed directly to the page proxy.
priv->pageProxy->setIntrinsicDeviceScaleFactor(gtk_widget_get_scale_factor(GTK_WIDGET(webkitWebViewBase)));
g_signal_connect(webkitWebViewBase, "notify::scale-factor", G_CALLBACK(deviceScaleFactorChanged), nullptr);
#endif
-
- webkitWebViewBaseUpdatePreferences(webkitWebViewBase);
-
- // This must happen here instead of the instance initializer, because the input method
- // filter must have access to the page.
- priv->inputMethodFilter.setWebView(webkitWebViewBase);
}
void webkitWebViewBaseSetTooltipText(WebKitWebViewBase* webViewBase, const char* tooltip)
@@ -1040,31 +1232,12 @@ void webkitWebViewBaseSetTooltipArea(WebKitWebViewBase* webViewBase, const IntRe
}
#if ENABLE(DRAG_SUPPORT)
-void webkitWebViewBaseStartDrag(WebKitWebViewBase* webViewBase, const DragData& dragData, PassRefPtr<ShareableBitmap> dragImage)
+DragAndDropHandler& webkitWebViewBaseDragAndDropHandler(WebKitWebViewBase* webViewBase)
{
WebKitWebViewBasePrivate* priv = webViewBase->priv;
-
- RefPtr<DataObjectGtk> dataObject = adoptRef(dragData.platformData());
- GRefPtr<GtkTargetList> targetList = adoptGRef(PasteboardHelper::defaultPasteboardHelper()->targetListForDataObject(dataObject.get()));
- GUniquePtr<GdkEvent> currentEvent(gtk_get_current_event());
- GdkDragContext* context = gtk_drag_begin(GTK_WIDGET(webViewBase),
- targetList.get(),
- dragOperationToGdkDragActions(dragData.draggingSourceOperationMask()),
- 1, /* button */
- currentEvent.get());
- priv->dragAndDropHelper.startedDrag(context, dataObject.get());
-
-
- // A drag starting should prevent a double-click from happening. This might
- // happen if a drag is followed very quickly by another click (like in the DRT).
- priv->clickCounter.reset();
-
- if (dragImage) {
- RefPtr<cairo_surface_t> image(dragImage->createCairoSurface());
- priv->dragIcon.setImage(image.get());
- priv->dragIcon.useForDrag(context);
- } else
- gtk_drag_set_icon_default(context);
+ if (!priv->dragAndDropHandler)
+ priv->dragAndDropHandler = std::make_unique<DragAndDropHandler>(*priv->pageProxy);
+ return *priv->dragAndDropHandler;
}
#endif // ENABLE(DRAG_SUPPORT)
@@ -1073,6 +1246,80 @@ void webkitWebViewBaseForwardNextKeyEvent(WebKitWebViewBase* webkitWebViewBase)
webkitWebViewBase->priv->shouldForwardNextKeyEvent = TRUE;
}
+void webkitWebViewBaseForwardNextWheelEvent(WebKitWebViewBase* webkitWebViewBase)
+{
+ webkitWebViewBase->priv->shouldForwardNextWheelEvent = true;
+}
+
+#if ENABLE(FULLSCREEN_API)
+static void screenSaverInhibitedCallback(GDBusProxy* screenSaverProxy, GAsyncResult* result, WebKitWebViewBase* webViewBase)
+{
+ GRefPtr<GVariant> returnValue = adoptGRef(g_dbus_proxy_call_finish(screenSaverProxy, result, nullptr));
+ if (returnValue)
+ g_variant_get(returnValue.get(), "(u)", &webViewBase->priv->screenSaverCookie);
+ webViewBase->priv->screenSaverInhibitCancellable = nullptr;
+}
+
+static void webkitWebViewBaseSendInhibitMessageToScreenSaver(WebKitWebViewBase* webViewBase)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ ASSERT(priv->screenSaverProxy);
+ priv->screenSaverCookie = 0;
+ if (!priv->screenSaverInhibitCancellable)
+ priv->screenSaverInhibitCancellable = adoptGRef(g_cancellable_new());
+ g_dbus_proxy_call(priv->screenSaverProxy.get(), "Inhibit", g_variant_new("(ss)", g_get_prgname(), _("Website running in fullscreen mode")),
+ G_DBUS_CALL_FLAGS_NONE, -1, priv->screenSaverInhibitCancellable.get(), reinterpret_cast<GAsyncReadyCallback>(screenSaverInhibitedCallback), webViewBase);
+}
+
+static void screenSaverProxyCreatedCallback(GObject*, GAsyncResult* result, WebKitWebViewBase* webViewBase)
+{
+ // WebKitWebViewBase cancels the proxy creation on dispose, which means this could be called
+ // after the web view has been destroyed and g_dbus_proxy_new_for_bus_finish will return nullptr.
+ // So, make sure we don't use the web view unless we have a valid proxy.
+ // See https://bugs.webkit.org/show_bug.cgi?id=151653.
+ GRefPtr<GDBusProxy> proxy = adoptGRef(g_dbus_proxy_new_for_bus_finish(result, nullptr));
+ if (!proxy)
+ return;
+
+ webViewBase->priv->screenSaverProxy = proxy;
+ webkitWebViewBaseSendInhibitMessageToScreenSaver(webViewBase);
+}
+
+static void webkitWebViewBaseInhibitScreenSaver(WebKitWebViewBase* webViewBase)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ if (priv->screenSaverCookie) {
+ // Already inhibited.
+ return;
+ }
+
+ if (priv->screenSaverProxy) {
+ webkitWebViewBaseSendInhibitMessageToScreenSaver(webViewBase);
+ return;
+ }
+
+ priv->screenSaverInhibitCancellable = adoptGRef(g_cancellable_new());
+ 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),
+ nullptr, "org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver", priv->screenSaverInhibitCancellable.get(),
+ reinterpret_cast<GAsyncReadyCallback>(screenSaverProxyCreatedCallback), webViewBase);
+}
+
+static void webkitWebViewBaseUninhibitScreenSaver(WebKitWebViewBase* webViewBase)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ if (!priv->screenSaverCookie) {
+ // Not inhibited or it's being inhibited.
+ g_cancellable_cancel(priv->screenSaverInhibitCancellable.get());
+ return;
+ }
+
+ // If we have a cookie we should have a proxy.
+ ASSERT(priv->screenSaverProxy);
+ g_dbus_proxy_call(priv->screenSaverProxy.get(), "UnInhibit", g_variant_new("(u)", priv->screenSaverCookie), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr, nullptr);
+ priv->screenSaverCookie = 0;
+}
+#endif
+
void webkitWebViewBaseEnterFullScreen(WebKitWebViewBase* webkitWebViewBase)
{
#if ENABLE(FULLSCREEN_API)
@@ -1091,6 +1338,7 @@ void webkitWebViewBaseEnterFullScreen(WebKitWebViewBase* webkitWebViewBase)
gtk_window_fullscreen(GTK_WINDOW(topLevelWindow));
fullScreenManagerProxy->didEnterFullScreen();
priv->fullScreenModeActive = true;
+ webkitWebViewBaseInhibitScreenSaver(webkitWebViewBase);
#endif
}
@@ -1112,6 +1360,7 @@ void webkitWebViewBaseExitFullScreen(WebKitWebViewBase* webkitWebViewBase)
gtk_window_unfullscreen(GTK_WINDOW(topLevelWindow));
fullScreenManagerProxy->didExitFullScreen();
priv->fullScreenModeActive = false;
+ webkitWebViewBaseUninhibitScreenSaver(webkitWebViewBase);
#endif
}
@@ -1129,9 +1378,16 @@ void webkitWebViewBaseSetInspectorViewSize(WebKitWebViewBase* webkitWebViewBase,
gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webkitWebViewBase));
}
+static void activeContextMenuUnmapped(GtkMenu* menu, WebKitWebViewBase* webViewBase)
+{
+ if (webViewBase->priv->activeContextMenuProxy && webViewBase->priv->activeContextMenuProxy->gtkMenu() == menu)
+ webViewBase->priv->activeContextMenuProxy = nullptr;
+}
+
void webkitWebViewBaseSetActiveContextMenuProxy(WebKitWebViewBase* webkitWebViewBase, WebContextMenuProxyGtk* contextMenuProxy)
{
webkitWebViewBase->priv->activeContextMenuProxy = contextMenuProxy;
+ g_signal_connect_object(contextMenuProxy->gtkMenu(), "unmap", G_CALLBACK(activeContextMenuUnmapped), webkitWebViewBase, static_cast<GConnectFlags>(0));
}
WebContextMenuProxyGtk* webkitWebViewBaseGetActiveContextMenuProxy(WebKitWebViewBase* webkitWebViewBase)
@@ -1144,57 +1400,49 @@ GdkEvent* webkitWebViewBaseTakeContextMenuEvent(WebKitWebViewBase* webkitWebView
return webkitWebViewBase->priv->contextMenuEvent.release();
}
-#if USE(TEXTURE_MAPPER_GL)
-void redirectedWindowDamagedCallback(void* data)
-{
- gtk_widget_queue_draw(GTK_WIDGET(data));
-}
-#endif
-
void webkitWebViewBaseSetFocus(WebKitWebViewBase* webViewBase, bool focused)
{
WebKitWebViewBasePrivate* priv = webViewBase->priv;
- if (priv->isFocused == focused)
+ if ((focused && priv->activityState & ActivityState::IsFocused) || (!focused && !(priv->activityState & ActivityState::IsFocused)))
return;
- unsigned viewStateFlags = ViewState::IsFocused;
- priv->isFocused = focused;
-
- // If the view has received the focus and the window is not active
- // mark the current window as active now. This can happen if the
- // toplevel window is a GTK_WINDOW_POPUP and the focus has been
- // set programatically like WebKitTestRunner does, because POPUP
- // can't be focused.
- if (priv->isFocused && !priv->isInWindowActive) {
- priv->isInWindowActive = true;
- viewStateFlags |= ViewState::WindowIsActive;
- }
- priv->pageProxy->viewStateDidChange(viewStateFlags);
+ ActivityState::Flags flagsToUpdate = ActivityState::IsFocused;
+ if (focused) {
+ priv->activityState |= ActivityState::IsFocused;
+
+ // If the view has received the focus and the window is not active
+ // mark the current window as active now. This can happen if the
+ // toplevel window is a GTK_WINDOW_POPUP and the focus has been
+ // set programatically like WebKitTestRunner does, because POPUP
+ // can't be focused.
+ if (!(priv->activityState & ActivityState::WindowIsActive)) {
+ priv->activityState |= ActivityState::WindowIsActive;
+ flagsToUpdate |= ActivityState::WindowIsActive;
+ }
+ } else
+ priv->activityState &= ~ActivityState::IsFocused;
+
+ webkitWebViewBaseScheduleUpdateActivityState(webViewBase, flagsToUpdate);
}
bool webkitWebViewBaseIsInWindowActive(WebKitWebViewBase* webViewBase)
{
- return webViewBase->priv->isInWindowActive;
+ return webViewBase->priv->activityState & ActivityState::WindowIsActive;
}
bool webkitWebViewBaseIsFocused(WebKitWebViewBase* webViewBase)
{
- return webViewBase->priv->isFocused;
+ return webViewBase->priv->activityState & ActivityState::IsFocused;
}
bool webkitWebViewBaseIsVisible(WebKitWebViewBase* webViewBase)
{
- return webViewBase->priv->isVisible;
+ return webViewBase->priv->activityState & ActivityState::IsVisible;
}
bool webkitWebViewBaseIsInWindow(WebKitWebViewBase* webViewBase)
{
- return webViewBase->priv->toplevelOnScreenWindow;
-}
-
-bool webkitWebViewBaseIsWindowVisible(WebKitWebViewBase* webViewBase)
-{
- return webViewBase->priv->isWindowVisible;
+ return webViewBase->priv->activityState & ActivityState::IsInWindow;
}
void webkitWebViewBaseSetDownloadRequestHandler(WebKitWebViewBase* webViewBase, WebKitWebViewBaseDownloadRequestHandler downloadHandler)
@@ -1215,10 +1463,79 @@ void webkitWebViewBaseSetInputMethodState(WebKitWebViewBase* webkitWebViewBase,
void webkitWebViewBaseUpdateTextInputState(WebKitWebViewBase* webkitWebViewBase)
{
- webkitWebViewBase->priv->inputMethodFilter.setCursorRect(webkitWebViewBase->priv->pageProxy->editorState().cursorRect);
+ const auto& editorState = webkitWebViewBase->priv->pageProxy->editorState();
+ if (!editorState.isMissingPostLayoutData)
+ webkitWebViewBase->priv->inputMethodFilter.setCursorRect(editorState.postLayoutData().caretRectAtStart);
+}
+
+void webkitWebViewBaseSetContentsSize(WebKitWebViewBase* webkitWebViewBase, const IntSize& contentsSize)
+{
+ WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
+ if (priv->contentsSize == contentsSize)
+ return;
+ priv->contentsSize = contentsSize;
}
void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase)
{
webkitWebViewBase->priv->clickCounter.reset();
}
+
+void webkitWebViewBaseEnterAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext)
+{
+ if (webkitWebViewBase->priv->acceleratedBackingStore)
+ webkitWebViewBase->priv->acceleratedBackingStore->update(layerTreeContext);
+}
+
+void webkitWebViewBaseUpdateAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext)
+{
+ if (webkitWebViewBase->priv->acceleratedBackingStore)
+ webkitWebViewBase->priv->acceleratedBackingStore->update(layerTreeContext);
+}
+
+void webkitWebViewBaseExitAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase)
+{
+ if (webkitWebViewBase->priv->acceleratedBackingStore)
+ webkitWebViewBase->priv->acceleratedBackingStore->update(LayerTreeContext());
+}
+
+void webkitWebViewBaseDidRelaunchWebProcess(WebKitWebViewBase* webkitWebViewBase)
+{
+ // Queue a resize to ensure the new DrawingAreaProxy is resized.
+ gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webkitWebViewBase));
+
+#if PLATFORM(X11) && USE(TEXTURE_MAPPER_GL) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
+ if (PlatformDisplay::sharedDisplay().type() != PlatformDisplay::Type::X11)
+ return;
+
+ WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
+ DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea());
+ ASSERT(drawingArea);
+
+ if (!gtk_widget_get_realized(GTK_WIDGET(webkitWebViewBase)))
+ return;
+
+ uint64_t windowID = GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(webkitWebViewBase)));
+ drawingArea->setNativeSurfaceHandleForCompositing(windowID);
+#else
+ UNUSED_PARAM(webkitWebViewBase);
+#endif
+}
+
+void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase)
+{
+ if (webkitWebViewBase->priv->acceleratedBackingStore)
+ webkitWebViewBase->priv->acceleratedBackingStore->update(LayerTreeContext());
+#if PLATFORM(X11) && USE(TEXTURE_MAPPER_GL) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
+ if (PlatformDisplay::sharedDisplay().type() != PlatformDisplay::Type::X11)
+ return;
+
+ if (!gtk_widget_get_realized(GTK_WIDGET(webkitWebViewBase)))
+ return;
+
+ WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
+ DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea());
+ ASSERT(drawingArea);
+ drawingArea->destroyNativeSurfaceHandleForCompositing();
+#endif
+}