wayland: Request frame callbacks on subsurfaces

We need this for the case when the subsurface completely covers
up the main surface. Without it, we just stop updating.
This commit is contained in:
Matthias Clasen 2023-11-10 14:26:10 +01:00
parent 59dbfb0843
commit ca054bfdc9
4 changed files with 74 additions and 8 deletions

View File

@ -25,6 +25,8 @@ struct _GdkWaylandSubsurface
struct wl_region *opaque_region;
struct wl_callback *frame_callback;
gboolean above_parent;
};
@ -34,3 +36,6 @@ struct _GdkWaylandSubsurfaceClass
};
GType gdk_wayland_subsurface_get_type (void) G_GNUC_CONST;
void gdk_wayland_subsurface_request_frame (GdkSubsurface *subsurface);
void gdk_wayland_subsurface_clear_frame_callback (GdkSubsurface *subsurface);

View File

@ -41,6 +41,7 @@ gdk_wayland_subsurface_finalize (GObject *object)
GdkWaylandSubsurface *self = GDK_WAYLAND_SUBSURFACE (object);
g_clear_object (&self->texture);
g_clear_pointer (&self->frame_callback, wl_callback_destroy);
g_clear_pointer (&self->opaque_region, wl_region_destroy);
g_clear_pointer (&self->viewport, wp_viewport_destroy);
g_clear_pointer (&self->subsurface, wl_subsurface_destroy);
@ -337,3 +338,39 @@ gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class)
subsurface_class->place_below = gdk_wayland_subsurface_place_below;
subsurface_class->is_above_parent = gdk_wayland_subsurface_is_above_parent;
};
static void
frame_callback (void *data,
struct wl_callback *callback,
uint32_t time)
{
GdkSubsurface *sub = data;
g_assert (((GdkWaylandSubsurface *)sub)->frame_callback == callback);
g_assert (!GDK_SURFACE_DESTROYED (sub->parent));
gdk_wayland_surface_frame_callback (sub->parent, time);
}
static const struct wl_callback_listener frame_listener = {
frame_callback
};
void
gdk_wayland_subsurface_request_frame (GdkSubsurface *sub)
{
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
self->frame_callback = wl_surface_frame (self->surface);
wl_proxy_set_queue ((struct wl_proxy *) self->frame_callback, NULL);
wl_callback_add_listener (self->frame_callback, &frame_listener, self);
wl_surface_commit (self->surface);
}
void
gdk_wayland_subsurface_clear_frame_callback (GdkSubsurface *sub)
{
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
g_clear_pointer (&self->frame_callback, wl_callback_destroy);
}

View File

@ -123,6 +123,9 @@ void gdk_wayland_surface_get_window_geometry (GdkSurface *surface,
void gdk_wayland_surface_freeze_state (GdkSurface *surface);
void gdk_wayland_surface_thaw_state (GdkSurface *surface);
void gdk_wayland_surface_frame_callback (GdkSurface *surface,
uint32_t time);
#define GDK_TYPE_WAYLAND_DRAG_SURFACE (gdk_wayland_drag_surface_get_type ())
GType gdk_wayland_drag_surface_get_type (void) G_GNUC_CONST;

View File

@ -264,12 +264,10 @@ gdk_wayland_surface_update_size (GdkSurface *surface,
_gdk_surface_update_size (surface);
}
static void
frame_callback (void *data,
struct wl_callback *callback,
void
gdk_wayland_surface_frame_callback (GdkSurface *surface,
uint32_t time)
{
GdkSurface *surface = data;
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
GdkWaylandDisplay *display_wayland =
GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
@ -279,11 +277,14 @@ frame_callback (void *data,
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "wayland", "frame event");
GDK_DISPLAY_DEBUG (GDK_DISPLAY (display_wayland), EVENTS, "frame %p", surface);
g_assert (impl->frame_callback == callback);
g_assert (!GDK_SURFACE_DESTROYED (surface));
g_clear_pointer (&impl->frame_callback, wl_callback_destroy);
for (gsize i = 0; i < gdk_surface_get_n_subsurfaces (surface); i++)
{
GdkSubsurface *subsurface = gdk_surface_get_subsurface (surface, i);
gdk_wayland_subsurface_clear_frame_callback (subsurface);
}
GDK_WAYLAND_SURFACE_GET_CLASS (impl)->handle_frame (impl);
if (impl->awaiting_frame_frozen)
@ -321,6 +322,19 @@ frame_callback (void *data,
_gdk_frame_clock_add_timings_to_profiler (clock, timings);
}
static void
frame_callback (void *data,
struct wl_callback *callback,
uint32_t time)
{
GdkSurface *surface = data;
g_assert (GDK_WAYLAND_SURFACE (surface)->frame_callback == callback);
g_assert (!GDK_SURFACE_DESTROYED (surface));
gdk_wayland_surface_frame_callback (surface, time);
}
static const struct wl_callback_listener frame_listener = {
frame_callback
};
@ -382,6 +396,13 @@ gdk_wayland_surface_request_frame (GdkSurface *surface)
self->frame_callback = wl_surface_frame (self->display_server.wl_surface);
wl_proxy_set_queue ((struct wl_proxy *) self->frame_callback, NULL);
wl_callback_add_listener (self->frame_callback, &frame_listener, surface);
for (gsize i = 0; i < gdk_surface_get_n_subsurfaces (surface); i++)
{
GdkSubsurface *subsurface = gdk_surface_get_subsurface (surface, i);
gdk_wayland_subsurface_request_frame (subsurface);
}
self->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
}