Skip to content

Commit

Permalink
[GTK] Move the drawing monitor implementation from drawing area to th…
Browse files Browse the repository at this point in the history
…e web view

https://bugs.webkit.org/show_bug.cgi?id=264225

Reviewed by Alejandro G. Castro.

This way we can use the same implementation for GTK3 and GTK4.

* Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp:
(_WebKitWebViewBasePrivate::_WebKitWebViewBasePrivate):
(_WebKitWebViewBasePrivate::nextPresentationUpdateTimerFired):
(webkitWebViewBaseNextPresentationUpdateMonitorStart):
(webkitWebViewBaseNextPresentationUpdateMonitorStop):
(webkitWebViewBaseNextPresentationUpdateFrame):
(webkitWebViewBaseDispose):
(webkitWebViewBaseSnapshot):
(webkitWebViewBaseDraw):
(webkitWebViewBaseCallAfterNextPresentationUpdate):
* Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h:
* Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp:
(WebKit::DrawingAreaProxyCoordinatedGraphics::DrawingMonitor::DrawingMonitor):
(WebKit::DrawingAreaProxyCoordinatedGraphics::DrawingMonitor::start):
(WebKit::DrawingAreaProxyCoordinatedGraphics::DrawingMonitor::stop):
(WebKit::DrawingAreaProxyCoordinatedGraphics::DrawingMonitor::webViewDrawCallback): Deleted.
(WebKit::DrawingAreaProxyCoordinatedGraphics::DrawingMonitor::didDraw): Deleted.
* Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h:
* Source/WebKit/UIProcess/WebPageProxy.cpp:
* Source/WebKit/UIProcess/gtk/WebPageProxyGtk.cpp:
(WebKit::WebPageProxy::callAfterNextPresentationUpdate):

Canonical link: https://commits.webkit.org/270381@main
  • Loading branch information
carlosgcampos committed Nov 8, 2023
1 parent 699f679 commit 1dd5008
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 47 deletions.
54 changes: 54 additions & 0 deletions Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,12 @@ struct _WebKitWebViewBasePrivate {
#if GTK_CHECK_VERSION(3, 24, 0)
, releaseEmojiChooserTimer(RunLoop::main(), this, &_WebKitWebViewBasePrivate::releaseEmojiChooserTimerFired)
#endif
, nextPresentationUpdateTimer(RunLoop::main(), this, &_WebKitWebViewBasePrivate::nextPresentationUpdateTimerFired)
{
#if GTK_CHECK_VERSION(3, 24, 0)
releaseEmojiChooserTimer.setPriority(RunLoopSourcePriority::ReleaseUnusedResourcesTimer);
#endif
nextPresentationUpdateTimer.setPriority(GDK_PRIORITY_REDRAW - 10);
}

void updateActivityStateTimerFired()
Expand All @@ -272,6 +274,14 @@ struct _WebKitWebViewBasePrivate {
}
#endif

void nextPresentationUpdateTimerFired()
{
while (!nextPresentationUpdateCallbacks.isEmpty()) {
auto callback = nextPresentationUpdateCallbacks.takeLast();
callback();
}
}

#if !USE(GTK4)
WebKitWebViewChildrenMap children;
#endif
Expand Down Expand Up @@ -354,6 +364,10 @@ struct _WebKitWebViewBasePrivate {
bool pageGrabbedTouch;

std::unique_ptr<PointerLockManager> pointerLockManager;

Vector<CompletionHandler<void()>> nextPresentationUpdateCallbacks;
RunLoop::Timer nextPresentationUpdateTimer;
MonotonicTime nextPresentationUpdateStartTime;
};

/**
Expand Down Expand Up @@ -758,9 +772,40 @@ static void webkitWebViewBaseCompleteEmojiChooserRequest(WebKitWebViewBase* webV
}
#endif

static void webkitWebViewBaseNextPresentationUpdateMonitorStart(WebKitWebViewBase* webViewBase, CompletionHandler<void()>&& callback)
{
auto* priv = webViewBase->priv;
priv->nextPresentationUpdateCallbacks.insert(0, WTFMove(callback));
priv->nextPresentationUpdateStartTime = MonotonicTime::now();
priv->nextPresentationUpdateTimer.startOneShot(100_ms);
}

static void webkitWebViewBaseNextPresentationUpdateMonitorStop(WebKitWebViewBase* webViewBase)
{
auto* priv = webViewBase->priv;
priv->nextPresentationUpdateTimer.stop();
priv->nextPresentationUpdateTimerFired();
}

static void webkitWebViewBaseNextPresentationUpdateFrame(WebKitWebViewBase* webViewBase)
{
auto* priv = webViewBase->priv;
if (priv->nextPresentationUpdateCallbacks.isEmpty())
return;

// We wait up to 100 milliseconds for new frames. If there are several frames queued quickly,
// we want to wait until all of them have been processed, so after receiving a frame, we wait
// for the next frame (1 frame time and a half to make sure) or stop.
if (MonotonicTime::now() - priv->nextPresentationUpdateStartTime > 100_ms)
webkitWebViewBaseNextPresentationUpdateMonitorStop(webViewBase);
else
priv->nextPresentationUpdateTimer.startOneShot(24_ms);
}

static void webkitWebViewBaseDispose(GObject* gobject)
{
WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(gobject);
webkitWebViewBaseNextPresentationUpdateMonitorStop(webView);
#if USE(GTK4)
webkitWebViewBaseRemoveDialog(webView, webView->priv->dialog);
webkitWebViewBaseRemoveWebInspector(webView, webView->priv->inspectorView);
Expand Down Expand Up @@ -833,6 +878,8 @@ static void webkitWebViewBaseSnapshot(GtkWidget* widget, GtkSnapshot* snapshot)

if (webViewBase->priv->dialog)
gtk_widget_snapshot_child(widget, webViewBase->priv->dialog, snapshot);

webkitWebViewBaseNextPresentationUpdateFrame(webViewBase);
}
#else
static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr)
Expand Down Expand Up @@ -868,6 +915,8 @@ static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr)

GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->draw(widget, cr);

webkitWebViewBaseNextPresentationUpdateFrame(webViewBase);

return FALSE;
}
#endif
Expand Down Expand Up @@ -3362,3 +3411,8 @@ void webkitWebViewBaseSetShouldNotifyFocusEvents(WebKitWebViewBase* webViewBase,
{
webViewBase->priv->shouldNotifyFocusEvents = shouldNotifyFocusEvents;
}

void webkitWebViewBaseCallAfterNextPresentationUpdate(WebKitWebViewBase* webViewBase, CompletionHandler<void()>&& callback)
{
webkitWebViewBaseNextPresentationUpdateMonitorStart(webViewBase, WTFMove(callback));
}
2 changes: 2 additions & 0 deletions Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,5 @@ void webkitWebViewBaseSetShouldNotifyFocusEvents(WebKitWebViewBase*, bool);
void webkitWebViewBaseToplevelWindowIsActiveChanged(WebKitWebViewBase*, bool);
void webkitWebViewBaseToplevelWindowStateChanged(WebKitWebViewBase*, uint32_t, uint32_t);
void webkitWebViewBaseToplevelWindowMonitorChanged(WebKitWebViewBase*, GdkMonitor*);

void webkitWebViewBaseCallAfterNextPresentationUpdate(WebKitWebViewBase*, CompletionHandler<void()>&&);
Original file line number Diff line number Diff line change
Expand Up @@ -303,18 +303,10 @@ void DrawingAreaProxyCoordinatedGraphics::discardBackingStore()

DrawingAreaProxyCoordinatedGraphics::DrawingMonitor::DrawingMonitor(WebPageProxy& webPage)
: m_timer(RunLoop::main(), this, &DrawingMonitor::stop)
#if PLATFORM(GTK)
, m_webPage(webPage)
#endif
{
#if USE(GLIB_EVENT_LOOP)
#if PLATFORM(GTK)
// Give redraws more priority.
m_timer.setPriority(GDK_PRIORITY_REDRAW - 10);
#else
m_timer.setPriority(RunLoopSourcePriority::RunLoopDispatcher);
#endif
#endif
}

DrawingAreaProxyCoordinatedGraphics::DrawingMonitor::~DrawingMonitor()
Expand All @@ -324,51 +316,19 @@ DrawingAreaProxyCoordinatedGraphics::DrawingMonitor::~DrawingMonitor()
stop();
}

int DrawingAreaProxyCoordinatedGraphics::DrawingMonitor::webViewDrawCallback(DrawingAreaProxyCoordinatedGraphics::DrawingMonitor* monitor)
{
monitor->didDraw();
return false;
}

void DrawingAreaProxyCoordinatedGraphics::DrawingMonitor::start(CompletionHandler<void()>&& callback)
{
m_startTime = MonotonicTime::now();
m_callback = WTFMove(callback);
#if PLATFORM(GTK)
gtk_widget_queue_draw(m_webPage.viewWidget());
#if USE(GTK4)
m_timer.startOneShot(16_ms);
#else
g_signal_connect_swapped(m_webPage.viewWidget(), "draw", reinterpret_cast<GCallback>(webViewDrawCallback), this);
m_timer.startOneShot(100_ms);
#endif
#else
m_timer.startOneShot(0_s);
#endif
}

void DrawingAreaProxyCoordinatedGraphics::DrawingMonitor::stop()
{
m_timer.stop();
#if PLATFORM(GTK) && !USE(GTK4)
g_signal_handlers_disconnect_by_func(m_webPage.viewWidget(), reinterpret_cast<gpointer>(webViewDrawCallback), this);
#endif
m_startTime = MonotonicTime();
if (m_callback)
m_callback();
}

void DrawingAreaProxyCoordinatedGraphics::DrawingMonitor::didDraw()
{
// We wait up to 100 milliseconds for draw events. If there are several draw events queued quickly,
// we want to wait until all of them have been processed, so after receiving a draw, we wait
// for the next frame or stop.
if (MonotonicTime::now() - m_startTime > 100_ms)
stop();
else
m_timer.startOneShot(16_ms);
}

void DrawingAreaProxyCoordinatedGraphics::dispatchAfterEnsuringDrawing(CompletionHandler<void()>&& callbackFunction)
{
auto webPageProxy = protectedWebPageProxy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,10 @@ class DrawingAreaProxyCoordinatedGraphics final : public DrawingAreaProxy {
void start(CompletionHandler<void()>&&);

private:
static int webViewDrawCallback(DrawingMonitor*);

void stop();
void didDraw();

MonotonicTime m_startTime;
CompletionHandler<void()> m_callback;
RunLoop::Timer m_timer;
#if PLATFORM(GTK)
WebPageProxy& m_webPage;
#endif
};

// The current layer tree context.
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/UIProcess/WebPageProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11457,6 +11457,7 @@ void WebPageProxy::clearWheelEventTestMonitor()
send(Messages::WebPage::ClearWheelEventTestMonitor());
}

#if !PLATFORM(GTK)
void WebPageProxy::callAfterNextPresentationUpdate(CompletionHandler<void()>&& callback)
{
if (!hasRunningProcess() || !m_drawingArea)
Expand All @@ -11474,6 +11475,7 @@ void WebPageProxy::callAfterNextPresentationUpdate(CompletionHandler<void()>&& c
callback();
#endif
}
#endif

void WebPageProxy::setShouldScaleViewToFitDocument(bool shouldScaleViewToFitDocument)
{
Expand Down
10 changes: 10 additions & 0 deletions Source/WebKit/UIProcess/gtk/WebPageProxyGtk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,14 @@ OptionSet<WebCore::PlatformEvent::Modifier> WebPageProxy::currentStateOfModifier
return modifiers;
}

void WebPageProxy::callAfterNextPresentationUpdate(CompletionHandler<void()>&& callback)
{
if (!hasRunningProcess() || !m_drawingArea) {
callback();
return;
}

webkitWebViewBaseCallAfterNextPresentationUpdate(WEBKIT_WEB_VIEW_BASE(viewWidget()), WTFMove(callback));
}

} // namespace WebKit

0 comments on commit 1dd5008

Please sign in to comment.