Skip to content

Commit

Permalink
[GTK] Mark the view as not visible when left the last monitor
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=262954

Reviewed by Michael Catanzaro.

In GTK4 under wayland we receive the leave-monitor signal when the
window is minimized, or hidden in other ways like moving to a different
workspace. In those cases, we can mark the view as not visible to avoid
doing rendering updates.

* Source/WebKit/UIProcess/API/gtk/ToplevelWindow.cpp:
(WebKit::ToplevelWindow::isMinimized const):
(WebKit::ToplevelWindow::isInMonitor const):
(WebKit::ToplevelWindow::connectSurfaceSignals):
* Source/WebKit/UIProcess/API/gtk/ToplevelWindow.h:
* Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp:
(webkitWebViewBaseToplevelWindowStateChanged):
(webkitWebViewBaseToplevelWindowMonitorChanged):

Canonical link: https://commits.webkit.org/269137@main
  • Loading branch information
carlosgcampos committed Oct 10, 2023
1 parent c4614fd commit 1a71158
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 3 deletions.
33 changes: 31 additions & 2 deletions Source/WebKit/UIProcess/API/gtk/ToplevelWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,18 @@ bool ToplevelWindow::isFullscreen() const
return false;
}

bool ToplevelWindow::isMinimized() const
{
#if USE(GTK4)
if (auto* surface = gtk_native_get_surface(GTK_NATIVE(m_window)))
return gdk_toplevel_get_state(GDK_TOPLEVEL(surface)) & GDK_TOPLEVEL_STATE_MINIMIZED;
#else
if (auto* window = gtk_widget_get_window(GTK_WIDGET(m_window)))
return gdk_window_get_state(window) & GDK_WINDOW_STATE_ICONIFIED;
#endif
return false;
}

GdkMonitor* ToplevelWindow::monitor() const
{
auto* display = gtk_widget_get_display(GTK_WIDGET(m_window));
Expand All @@ -115,6 +127,18 @@ GdkMonitor* ToplevelWindow::monitor() const
return nullptr;
}

bool ToplevelWindow::isInMonitor() const
{
#if USE(GTK4)
// GTK4 always returns a valid monitor from gdk_display_get_monitor_at_surface() even after monitor-leave signal is emitted,
// so we keep track of the monitors.
return !m_monitors.isEmpty();
#else
auto* widget = GTK_WIDGET(m_window);
return gtk_widget_get_realized(widget) && gdk_display_get_monitor_at_window(gtk_widget_get_display(widget), gtk_widget_get_window(widget));
#endif
}

void ToplevelWindow::connectSignals()
{
#if USE(GTK4)
Expand Down Expand Up @@ -182,11 +206,16 @@ void ToplevelWindow::connectSurfaceSignals()
toplevelWindow->m_state = state;
toplevelWindow->notifyState(changedMask, state);
}), this);
notifyMonitorChanged(monitor());
if (auto* monitor = gdk_display_get_monitor_at_surface(gtk_widget_get_display(GTK_WIDGET(m_window)), surface)) {
m_monitors.add(monitor);
notifyMonitorChanged(monitor);
}
g_signal_connect(surface, "enter-monitor", G_CALLBACK(+[](GdkSurface* surface, GdkMonitor* monitor, ToplevelWindow* toplevelWindow) {
toplevelWindow->m_monitors.add(monitor);
toplevelWindow->notifyMonitorChanged(monitor);
}), this);
g_signal_connect(surface, "leave-monitor", G_CALLBACK(+[](GdkSurface* surface, GdkMonitor*, ToplevelWindow* toplevelWindow) {
g_signal_connect(surface, "leave-monitor", G_CALLBACK(+[](GdkSurface* surface, GdkMonitor* monitor, ToplevelWindow* toplevelWindow) {
toplevelWindow->m_monitors.remove(monitor);
toplevelWindow->notifyMonitorChanged(toplevelWindow->monitor());
}), this);
}
Expand Down
3 changes: 3 additions & 0 deletions Source/WebKit/UIProcess/API/gtk/ToplevelWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ class ToplevelWindow {
GtkWindow* window() const { return m_window; }
bool isActive() const;
bool isFullscreen() const;
bool isMinimized() const;
GdkMonitor* monitor() const;
bool isInMonitor() const;

private:
void connectSignals();
Expand All @@ -65,6 +67,7 @@ class ToplevelWindow {
HashSet<WebKitWebViewBase*> m_webViews;
#if USE(GTK4)
GdkToplevelState m_state { static_cast<GdkToplevelState>(0) };
HashSet<GdkMonitor*> m_monitors;
#endif
};

Expand Down
14 changes: 13 additions & 1 deletion Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ void webkitWebViewBaseToplevelWindowStateChanged(WebKitWebViewBase* webViewBase,
return;

if (visible) {
if (priv->activityState & ActivityState::IsVisible || !gtk_widget_get_mapped(GTK_WIDGET(webViewBase)))
if (priv->activityState & ActivityState::IsVisible || !gtk_widget_get_mapped(GTK_WIDGET(webViewBase)) || !priv->toplevelOnScreenWindow->isInMonitor())
return;
priv->activityState.add(ActivityState::IsVisible);
} else {
Expand All @@ -474,6 +474,18 @@ void webkitWebViewBaseToplevelWindowStateChanged(WebKitWebViewBase* webViewBase,

void webkitWebViewBaseToplevelWindowMonitorChanged(WebKitWebViewBase* webViewBase, GdkMonitor* monitor)
{
WebKitWebViewBasePrivate* priv = webViewBase->priv;
if (priv->toplevelOnScreenWindow->isInMonitor()) {
if (!(priv->activityState & ActivityState::IsVisible) && gtk_widget_get_mapped(GTK_WIDGET(webViewBase)) && !priv->toplevelOnScreenWindow->isMinimized()) {
priv->activityState.add(ActivityState::IsVisible);
webkitWebViewBaseScheduleUpdateActivityState(webViewBase, ActivityState::IsVisible);
}
} else {
if (priv->activityState & ActivityState::IsVisible) {
priv->activityState.remove(ActivityState::IsVisible);
webkitWebViewBaseScheduleUpdateActivityState(webViewBase, ActivityState::IsVisible);
}
}
webkitWebViewBaseUpdateDisplayID(webViewBase, monitor);
}

Expand Down

0 comments on commit 1a71158

Please sign in to comment.