gdk/toplevel: Make gdk_toplevel_present() async

The plan is to concencrate size computations as part of the frame clock
dispatch, meaning we shouldn't do it synchronously in the present()
function.

Still, in Wayland, and maybe elsewhere, it is done in the present()
function, e.g. when no state change was made, but this will eventually
be changed.
This commit is contained in:
Jonas Ådahl 2020-11-20 16:56:36 +01:00
parent 528ec4dded
commit 641915974b
6 changed files with 72 additions and 70 deletions

View File

@ -1524,7 +1524,7 @@ show_surface (GdkSurface *surface)
gdk_surface_invalidate_rect (surface, NULL);
}
static gboolean
static void
gdk_broadway_toplevel_present (GdkToplevel *toplevel,
GdkToplevelLayout *layout)
{
@ -1583,8 +1583,6 @@ gdk_broadway_toplevel_present (GdkToplevel *toplevel,
gdk_broadway_surface_unmaximize (surface);
show_surface (surface);
return TRUE;
}
static gboolean

View File

@ -51,11 +51,10 @@ enum
static guint signals[N_SIGNALS] = { 0 };
static gboolean
static void
gdk_toplevel_default_present (GdkToplevel *toplevel,
GdkToplevelLayout *layout)
{
return FALSE;
}
static gboolean
@ -239,18 +238,17 @@ gdk_toplevel_install_properties (GObjectClass *object_class,
* compute the preferred size of the toplevel surface. See
* #GdkToplevel::compute-size for details.
*
* Presenting may fail.
*
* Returns: %FALSE if @toplevel failed to be presented, otherwise %TRUE.
* Presenting is asynchronous and the specified layout parameters are not
* guaranteed to be respected.
*/
gboolean
void
gdk_toplevel_present (GdkToplevel *toplevel,
GdkToplevelLayout *layout)
{
g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
g_return_val_if_fail (layout != NULL, FALSE);
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_return_if_fail (layout != NULL);
return GDK_TOPLEVEL_GET_IFACE (toplevel)->present (toplevel, layout);
GDK_TOPLEVEL_GET_IFACE (toplevel)->present (toplevel, layout);
}
/**

View File

@ -129,7 +129,7 @@ GDK_AVAILABLE_IN_ALL
G_DECLARE_INTERFACE (GdkToplevel, gdk_toplevel, GDK, TOPLEVEL, GObject)
GDK_AVAILABLE_IN_ALL
gboolean gdk_toplevel_present (GdkToplevel *toplevel,
void gdk_toplevel_present (GdkToplevel *toplevel,
GdkToplevelLayout *layout);
GDK_AVAILABLE_IN_ALL

View File

@ -13,7 +13,7 @@ struct _GdkToplevelInterface
{
GTypeInterface g_iface;
gboolean (* present) (GdkToplevel *toplevel,
void (* present) (GdkToplevel *toplevel,
GdkToplevelLayout *layout);
gboolean (* minimize) (GdkToplevel *toplevel);
gboolean (* lower) (GdkToplevel *toplevel);

View File

@ -4756,79 +4756,87 @@ gdk_wayland_toplevel_class_init (GdkWaylandToplevelClass *class)
gdk_toplevel_install_properties (object_class, 1);
}
static void
reconfigure_callback (void *data,
struct wl_callback *callback,
uint32_t time)
static gboolean
did_maximize_layout_change (GdkToplevel *toplevel,
GdkToplevelLayout *layout)
{
gboolean *done = (gboolean *) data;
GdkSurface *surface = GDK_SURFACE (toplevel);
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
*done = TRUE;
if (!impl->toplevel.layout)
return TRUE;
if (gdk_toplevel_layout_get_maximized (impl->toplevel.layout) !=
gdk_toplevel_layout_get_maximized (layout))
return TRUE;
return FALSE;
}
static const struct wl_callback_listener reconfigure_listener = {
reconfigure_callback
};
static gboolean
did_fullscreen_layout_change (GdkToplevel *toplevel,
GdkToplevelLayout *layout)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
if (!impl->toplevel.layout)
return TRUE;
if (gdk_toplevel_layout_get_fullscreen (impl->toplevel.layout) !=
gdk_toplevel_layout_get_fullscreen (layout))
return TRUE;
if (gdk_toplevel_layout_get_fullscreen_monitor (impl->toplevel.layout) !=
gdk_toplevel_layout_get_fullscreen_monitor (layout))
return TRUE;
return FALSE;
}
static void
gdk_wayland_toplevel_present (GdkToplevel *toplevel,
GdkToplevelLayout *layout)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
GdkWaylandDisplay *display_wayland;
struct wl_callback *callback;
gboolean done = FALSE;
int last_configure_serial = impl->last_configure_serial;
gboolean needs_reconfigure = TRUE;
gboolean pending_configure = FALSE;
if (gdk_toplevel_layout_get_maximized (layout))
if (did_maximize_layout_change (toplevel, layout))
{
gdk_wayland_surface_maximize (surface);
needs_reconfigure = FALSE;
}
else
{
gdk_wayland_surface_unmaximize (surface);
}
if (gdk_toplevel_layout_get_fullscreen (layout))
{
GdkMonitor *monitor = gdk_toplevel_layout_get_fullscreen_monitor (layout);
if (monitor)
gdk_wayland_surface_fullscreen_on_monitor (surface, monitor);
if (gdk_toplevel_layout_get_maximized (layout))
gdk_wayland_surface_maximize (surface);
else
gdk_wayland_surface_fullscreen (surface);
needs_reconfigure = FALSE;
gdk_wayland_surface_unmaximize (surface);
pending_configure = TRUE;
}
if (did_fullscreen_layout_change (toplevel, layout))
{
if (gdk_toplevel_layout_get_fullscreen (layout))
{
GdkMonitor *monitor;
monitor = gdk_toplevel_layout_get_fullscreen_monitor (layout);
if (monitor)
gdk_wayland_surface_fullscreen_on_monitor (surface, monitor);
else
gdk_wayland_surface_fullscreen (surface);
}
else
{
gdk_wayland_surface_unfullscreen (surface);
}
pending_configure = TRUE;
}
else
gdk_wayland_surface_unfullscreen (surface);
g_clear_pointer (&impl->toplevel.layout, gdk_toplevel_layout_unref);
impl->toplevel.layout = gdk_toplevel_layout_copy (layout);
gdk_wayland_surface_show (surface, FALSE);
display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
callback = wl_display_sync (display_wayland->wl_display);
wl_proxy_set_queue ((struct wl_proxy *) callback, impl->event_queue);
wl_callback_add_listener (callback,
&reconfigure_listener,
&done);
while (is_realized_toplevel (impl) &&
(!impl->initial_configure_received || !done))
wl_display_dispatch_queue (display_wayland->wl_display, impl->event_queue);
wl_callback_destroy (callback);
if (needs_reconfigure &&
last_configure_serial == impl->last_configure_serial &&
!(surface->state & (GDK_TOPLEVEL_STATE_MAXIMIZED |
GDK_TOPLEVEL_STATE_FULLSCREEN |
GDK_TOPLEVEL_STATE_TILED)))
if (!pending_configure)
configure_surface_geometry (surface);
return TRUE;
}
static gboolean

View File

@ -4849,7 +4849,7 @@ gdk_x11_toplevel_class_init (GdkX11ToplevelClass *class)
gdk_toplevel_install_properties (object_class, LAST_PROP);
}
static gboolean
static void
gdk_x11_toplevel_present (GdkToplevel *toplevel,
GdkToplevelLayout *layout)
{
@ -4922,7 +4922,7 @@ gdk_x11_toplevel_present (GdkToplevel *toplevel,
gdk_x11_surface_unfullscreen (surface);
if (surface->destroyed)
return TRUE;
return;
was_mapped = GDK_SURFACE_IS_MAPPED (surface);
@ -4933,8 +4933,6 @@ gdk_x11_toplevel_present (GdkToplevel *toplevel,
if (!was_mapped)
gdk_surface_invalidate_rect (surface, NULL);
return TRUE;
}
static gboolean