c9052e
From 4232f2056cd31811d047104d1223f3e5ced4b107 Mon Sep 17 00:00:00 2001
c9052e
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
c9052e
Date: Thu, 16 Apr 2020 19:42:03 +0200
c9052e
Subject: [PATCH 1/5] clutter/stage: Make clutter_stage_schedule_update()
c9052e
 always schedule
c9052e
c9052e
We could call clutter_stage_schedule_update() and it wouldn't actually
c9052e
schedule anything, as the master frame clock only tries to reschedule if
c9052e
1) there is an active timeline, 2) there are pending relayouts, 3) there
c9052e
are pending redraws, or 4) there are pending events. Thus, a call to
c9052e
clutter_stage_schedule_update() didn't have any effect if it was called
c9052e
at the wrong time.
c9052e
c9052e
Fix this by adding a boolean state "needs_update" to the stage, set on
c9052e
clutter_stage_schedule_update() and cleared on
c9052e
_clutter_stage_do_update(), that will make the master clock reschedule
c9052e
an update if it is TRUE.
c9052e
c9052e
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1218
c9052e
(cherry picked from commit b8003807b0772e97354302b5cc2825e0b22c6c83)
c9052e
---
c9052e
 clutter/clutter/clutter-stage.c | 10 +++++++++-
c9052e
 1 file changed, 9 insertions(+), 1 deletion(-)
c9052e
c9052e
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
c9052e
index aaa77d9ede..5a914a3d0b 100644
c9052e
--- a/clutter/clutter/clutter-stage.c
c9052e
+++ b/clutter/clutter/clutter-stage.c
c9052e
@@ -152,6 +152,8 @@ struct _ClutterStagePrivate
c9052e
 
c9052e
   int update_freeze_count;
c9052e
 
c9052e
+  gboolean needs_update;
c9052e
+
c9052e
   guint relayout_pending       : 1;
c9052e
   guint redraw_pending         : 1;
c9052e
   guint is_fullscreen          : 1;
c9052e
@@ -1074,7 +1076,9 @@ _clutter_stage_needs_update (ClutterStage *stage)
c9052e
 
c9052e
   priv = stage->priv;
c9052e
 
c9052e
-  return priv->relayout_pending || priv->redraw_pending;
c9052e
+  return priv->relayout_pending ||
c9052e
+         priv->needs_update ||
c9052e
+         priv->redraw_pending;
c9052e
 }
c9052e
 
c9052e
 void
c9052e
@@ -1232,6 +1236,8 @@ _clutter_stage_do_update (ClutterStage *stage)
c9052e
 
c9052e
   priv->stage_was_relayout = FALSE;
c9052e
 
c9052e
+  priv->needs_update = FALSE;
c9052e
+
c9052e
   /* if the stage is being destroyed, or if the destruction already
c9052e
    * happened and we don't have an StageWindow any more, then we
c9052e
    * should bail out
c9052e
@@ -4080,6 +4086,8 @@ _clutter_stage_schedule_update (ClutterStage *stage)
c9052e
   if (stage_window == NULL)
c9052e
     return;
c9052e
 
c9052e
+  stage->priv->needs_update = TRUE;
c9052e
+
c9052e
   return _clutter_stage_window_schedule_update (stage_window,
c9052e
                                                 stage->priv->sync_delay);
c9052e
 }
c9052e
-- 
c9052e
2.31.1
c9052e
c9052e
c9052e
From 2d4453cfdcaf0c6a9f492d2c2395dbfc8cf833db Mon Sep 17 00:00:00 2001
c9052e
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
c9052e
Date: Thu, 16 Apr 2020 19:11:37 +0200
c9052e
Subject: [PATCH 2/5] clutter/stage: Make clutter_stage_schedule_update()
c9052e
 public API
c9052e
c9052e
It's effectively used by mutter by abusing a ClutterTimeline to scedule
c9052e
updates.  Timelines are not really suited in places that is done, as it
c9052e
is really just about getting a single new update scheduled whenever
c9052e
suitable, so expose the API so we can use it directly.
c9052e
c9052e
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1218
c9052e
(cherry picked from commit 99c9a14bc8058830232cd4e07c7bb897e84a8c9c)
c9052e
---
c9052e
 clutter/clutter/clutter-master-clock-default.c |  4 ++--
c9052e
 clutter/clutter/clutter-stage-private.h        |  1 -
c9052e
 clutter/clutter/clutter-stage.c                | 16 ++++++++--------
c9052e
 clutter/clutter/clutter-stage.h                |  3 +++
c9052e
 4 files changed, 13 insertions(+), 11 deletions(-)
c9052e
c9052e
diff --git a/clutter/clutter/clutter-master-clock-default.c b/clutter/clutter/clutter-master-clock-default.c
c9052e
index 0647c3a7fd..de7a1e2f4d 100644
c9052e
--- a/clutter/clutter/clutter-master-clock-default.c
c9052e
+++ b/clutter/clutter/clutter-master-clock-default.c
c9052e
@@ -206,7 +206,7 @@ master_clock_schedule_stage_updates (ClutterMasterClockDefault *master_clock)
c9052e
   stages = clutter_stage_manager_peek_stages (stage_manager);
c9052e
 
c9052e
   for (l = stages; l != NULL; l = l->next)
c9052e
-    _clutter_stage_schedule_update (l->data);
c9052e
+    clutter_stage_schedule_update (l->data);
c9052e
 }
c9052e
 
c9052e
 static GSList *
c9052e
@@ -259,7 +259,7 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
c9052e
       if (master_clock->timelines ||
c9052e
           _clutter_stage_has_queued_events (l->data) ||
c9052e
           _clutter_stage_needs_update (l->data))
c9052e
-        _clutter_stage_schedule_update (l->data);
c9052e
+        clutter_stage_schedule_update (l->data);
c9052e
     }
c9052e
 }
c9052e
 
c9052e
diff --git a/clutter/clutter/clutter-stage-private.h b/clutter/clutter/clutter-stage-private.h
c9052e
index 42474687ad..ea0ce5ec72 100644
c9052e
--- a/clutter/clutter/clutter-stage-private.h
c9052e
+++ b/clutter/clutter/clutter-stage-private.h
c9052e
@@ -70,7 +70,6 @@ void     _clutter_stage_queue_event                       (ClutterStage *stage,
c9052e
 gboolean _clutter_stage_has_queued_events                 (ClutterStage *stage);
c9052e
 void     _clutter_stage_process_queued_events             (ClutterStage *stage);
c9052e
 void     _clutter_stage_update_input_devices              (ClutterStage *stage);
c9052e
-void     _clutter_stage_schedule_update                   (ClutterStage *stage);
c9052e
 gint64    _clutter_stage_get_update_time                  (ClutterStage *stage);
c9052e
 void     _clutter_stage_clear_update_time                 (ClutterStage *stage);
c9052e
 gboolean _clutter_stage_has_full_redraw_queued            (ClutterStage *stage);
c9052e
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
c9052e
index 5a914a3d0b..74ff8b1337 100644
c9052e
--- a/clutter/clutter/clutter-stage.c
c9052e
+++ b/clutter/clutter/clutter-stage.c
c9052e
@@ -921,7 +921,7 @@ _clutter_stage_queue_event (ClutterStage *stage,
c9052e
     {
c9052e
       ClutterMasterClock *master_clock = _clutter_master_clock_get_default ();
c9052e
       _clutter_master_clock_start_running (master_clock);
c9052e
-      _clutter_stage_schedule_update (stage);
c9052e
+      clutter_stage_schedule_update (stage);
c9052e
     }
c9052e
 
c9052e
   /* if needed, update the state of the input device of the event.
c9052e
@@ -1295,7 +1295,7 @@ clutter_stage_real_queue_relayout (ClutterActor *self)
c9052e
 
c9052e
   if (!priv->relayout_pending)
c9052e
     {
c9052e
-      _clutter_stage_schedule_update (stage);
c9052e
+      clutter_stage_schedule_update (stage);
c9052e
       priv->relayout_pending = TRUE;
c9052e
     }
c9052e
 
c9052e
@@ -3788,7 +3788,7 @@ clutter_stage_ensure_redraw (ClutterStage *stage)
c9052e
   priv = stage->priv;
c9052e
 
c9052e
   if (!priv->relayout_pending && !priv->redraw_pending)
c9052e
-    _clutter_stage_schedule_update (stage);
c9052e
+    clutter_stage_schedule_update (stage);
c9052e
 
c9052e
   priv->relayout_pending = TRUE;
c9052e
   priv->redraw_pending = TRUE;
c9052e
@@ -4069,13 +4069,13 @@ clutter_stage_get_minimum_size (ClutterStage *stage,
c9052e
 }
c9052e
 
c9052e
 /**
c9052e
- * _clutter_stage_schedule_update:
c9052e
- * @window: a #ClutterStage actor
c9052e
+ * clutter_stage_schedule_update:
c9052e
+ * @stage: a #ClutterStage actor
c9052e
  *
c9052e
  * Schedules a redraw of the #ClutterStage at the next optimal timestamp.
c9052e
  */
c9052e
 void
c9052e
-_clutter_stage_schedule_update (ClutterStage *stage)
c9052e
+clutter_stage_schedule_update (ClutterStage *stage)
c9052e
 {
c9052e
   ClutterStageWindow *stage_window;
c9052e
 
c9052e
@@ -4097,7 +4097,7 @@ _clutter_stage_schedule_update (ClutterStage *stage)
c9052e
  * @stage: a #ClutterStage actor
c9052e
  *
c9052e
  * Returns the earliest time in which the stage is ready to update. The update
c9052e
- * time is set when _clutter_stage_schedule_update() is called. This can then
c9052e
+ * time is set when clutter_stage_schedule_update() is called. This can then
c9052e
  * be used by e.g. the #ClutterMasterClock to know when the stage needs to be
c9052e
  * redrawn.
c9052e
  *
c9052e
@@ -4267,7 +4267,7 @@ _clutter_stage_queue_actor_redraw (ClutterStage                 *stage,
c9052e
 
c9052e
       CLUTTER_NOTE (PAINT, "First redraw request");
c9052e
 
c9052e
-      _clutter_stage_schedule_update (stage);
c9052e
+      clutter_stage_schedule_update (stage);
c9052e
       priv->redraw_pending = TRUE;
c9052e
 
c9052e
       master_clock = _clutter_master_clock_get_default ();
c9052e
diff --git a/clutter/clutter/clutter-stage.h b/clutter/clutter/clutter-stage.h
c9052e
index 9da63d211d..53e37ae3bc 100644
c9052e
--- a/clutter/clutter/clutter-stage.h
c9052e
+++ b/clutter/clutter/clutter-stage.h
c9052e
@@ -265,6 +265,9 @@ CLUTTER_EXPORT
c9052e
 void            clutter_stage_skip_sync_delay                   (ClutterStage          *stage);
c9052e
 #endif
c9052e
 
c9052e
+CLUTTER_EXPORT
c9052e
+void clutter_stage_schedule_update (ClutterStage *stage);
c9052e
+
c9052e
 CLUTTER_EXPORT
c9052e
 gboolean clutter_stage_get_capture_final_size (ClutterStage          *stage,
c9052e
                                                cairo_rectangle_int_t *rect,
c9052e
-- 
c9052e
2.31.1
c9052e
c9052e
c9052e
From 1c4db591b6bb2ae9d649e8157eae24b875e7a22b Mon Sep 17 00:00:00 2001
c9052e
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
c9052e
Date: Mon, 28 Oct 2019 18:20:31 +0100
c9052e
Subject: [PATCH 3/5] wayland/actor-surface: Always store away frame callbacks
c9052e
 on commit
c9052e
c9052e
We're expected by MetaWaylandSurface to always pick the frame callbacks
c9052e
out from the pending state when committing (applying) so that no frame
c9052e
callbacks are unaccounted for. We failed to do this if our actor for
c9052e
some reason (e.g. associated window was unmanaged) was destroyed. To
c9052e
handle this situation better, store away the frame callbacks until we
c9052e
some later point in time need to pass them on forward.
c9052e
c9052e
https://gitlab.gnome.org/GNOME/mutter/merge_requests/893
c9052e
---
c9052e
 src/wayland/meta-wayland-actor-surface.c | 25 +++++++++++++++++++++++-
c9052e
 1 file changed, 24 insertions(+), 1 deletion(-)
c9052e
c9052e
diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c
c9052e
index 2471de0a92..264565c575 100644
c9052e
--- a/src/wayland/meta-wayland-actor-surface.c
c9052e
+++ b/src/wayland/meta-wayland-actor-surface.c
c9052e
@@ -35,6 +35,8 @@ typedef struct _MetaWaylandActorSurfacePrivate MetaWaylandActorSurfacePrivate;
c9052e
 struct _MetaWaylandActorSurfacePrivate
c9052e
 {
c9052e
   MetaSurfaceActor *actor;
c9052e
+
c9052e
+  struct wl_list frame_callback_list;
c9052e
 };
c9052e
 
c9052e
 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandActorSurface,
c9052e
@@ -56,6 +58,7 @@ meta_wayland_actor_surface_dispose (GObject *object)
c9052e
     meta_wayland_actor_surface_get_instance_private (META_WAYLAND_ACTOR_SURFACE (object));
c9052e
   MetaWaylandSurface *surface =
c9052e
     meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (object));
c9052e
+  MetaWaylandFrameCallback *cb, *next;
c9052e
 
c9052e
   if (priv->actor)
c9052e
     {
c9052e
@@ -66,6 +69,9 @@ meta_wayland_actor_surface_dispose (GObject *object)
c9052e
       g_clear_object (&priv->actor);
c9052e
     }
c9052e
 
c9052e
+  wl_list_for_each_safe (cb, next, &priv->frame_callback_list, link)
c9052e
+    wl_resource_destroy (cb->resource);
c9052e
+
c9052e
   G_OBJECT_CLASS (meta_wayland_actor_surface_parent_class)->dispose (object);
c9052e
 }
c9052e
 
c9052e
@@ -99,6 +105,9 @@ meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor
c9052e
   MetaSurfaceActorWayland *surface_actor_wayland =
c9052e
     META_SURFACE_ACTOR_WAYLAND (priv->actor);
c9052e
 
c9052e
+  meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland,
c9052e
+                                                  &priv->frame_callback_list);
c9052e
+  wl_list_init (&priv->frame_callback_list);
c9052e
   meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland,
c9052e
                                                   &pending->frame_callback_list);
c9052e
   wl_list_init (&pending->frame_callback_list);
c9052e
@@ -253,10 +262,20 @@ meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole  *surface_role,
c9052e
 {
c9052e
   MetaWaylandActorSurface *actor_surface =
c9052e
     META_WAYLAND_ACTOR_SURFACE (surface_role);
c9052e
+  MetaWaylandActorSurfacePrivate *priv =
c9052e
+    meta_wayland_actor_surface_get_instance_private (actor_surface);
c9052e
   MetaWaylandSurface *surface =
c9052e
     meta_wayland_surface_role_get_surface (surface_role);
c9052e
   MetaWaylandSurface *toplevel_surface;
c9052e
 
c9052e
+  if (!priv->actor)
c9052e
+    {
c9052e
+      wl_list_insert_list (&priv->frame_callback_list,
c9052e
+                           &pending->frame_callback_list);
c9052e
+      wl_list_init (&pending->frame_callback_list);
c9052e
+      return;
c9052e
+    }
c9052e
+
c9052e
   meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending);
c9052e
 
c9052e
   toplevel_surface = meta_wayland_surface_get_toplevel (surface);
c9052e
@@ -307,8 +326,12 @@ meta_wayland_actor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *surfac
c9052e
 }
c9052e
 
c9052e
 static void
c9052e
-meta_wayland_actor_surface_init (MetaWaylandActorSurface *role)
c9052e
+meta_wayland_actor_surface_init (MetaWaylandActorSurface *actor_surface)
c9052e
 {
c9052e
+  MetaWaylandActorSurfacePrivate *priv =
c9052e
+    meta_wayland_actor_surface_get_instance_private (actor_surface);
c9052e
+
c9052e
+  wl_list_init (&priv->frame_callback_list);
c9052e
 }
c9052e
 
c9052e
 static void
c9052e
-- 
c9052e
2.31.1
c9052e
c9052e
c9052e
From 54e5cee1a8d1a94fb19b438a3c80fe72179a3c80 Mon Sep 17 00:00:00 2001
c9052e
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
c9052e
Date: Fri, 6 Aug 2021 19:09:24 +0200
c9052e
Subject: [PATCH 4/5] wayland/actor-surface: Always store away frame callbacks
c9052e
 on commit
c9052e
c9052e
We're expected by MetaWaylandSurface to always pick the frame callbacks
c9052e
out from the pending state when committing (applying) so that no frame
c9052e
callbacks are unaccounted for. We failed to do this if our actor for
c9052e
some reason (e.g. associated window was unmanaged) was destroyed. To
c9052e
handle this situation better, store away the frame callbacks until we
c9052e
some later point in time need to pass them on forward.
c9052e
c9052e
https://gitlab.gnome.org/GNOME/mutter/merge_requests/893
c9052e
---
c9052e
 src/compositor/meta-surface-actor-wayland.c | 29 ---------
c9052e
 src/wayland/meta-wayland-actor-surface.c    | 65 ++++++++++++++++-----
c9052e
 src/wayland/meta-wayland-actor-surface.h    |  3 +
c9052e
 src/wayland/meta-wayland-cursor-surface.c   |  4 +-
c9052e
 src/wayland/meta-wayland-dnd-surface.c      | 11 +++-
c9052e
 src/wayland/meta-wayland-legacy-xdg-shell.c |  8 +--
c9052e
 src/wayland/meta-wayland-private.h          |  2 +-
c9052e
 src/wayland/meta-wayland-subsurface.c       |  2 -
c9052e
 src/wayland/meta-wayland-surface.c          | 38 +++---------
c9052e
 src/wayland/meta-wayland-surface.h          |  9 +--
c9052e
 src/wayland/meta-wayland-wl-shell.c         |  3 -
c9052e
 src/wayland/meta-wayland-xdg-shell.c        | 15 ++---
c9052e
 src/wayland/meta-wayland.c                  | 56 +++++++++++++-----
c9052e
 src/wayland/meta-wayland.h                  |  8 ++-
c9052e
 src/wayland/meta-xwayland.c                 | 45 --------------
c9052e
 15 files changed, 127 insertions(+), 171 deletions(-)
c9052e
c9052e
diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c
c9052e
index a75c4dd096..480b51c61a 100644
c9052e
--- a/src/compositor/meta-surface-actor-wayland.c
c9052e
+++ b/src/compositor/meta-surface-actor-wayland.c
c9052e
@@ -42,7 +42,6 @@ struct _MetaSurfaceActorWayland
c9052e
   MetaSurfaceActor parent;
c9052e
 
c9052e
   MetaWaylandSurface *surface;
c9052e
-  struct wl_list frame_callback_list;
c9052e
 };
c9052e
 
c9052e
 G_DEFINE_TYPE (MetaSurfaceActorWayland,
c9052e
@@ -91,13 +90,6 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
c9052e
   return FALSE;
c9052e
 }
c9052e
 
c9052e
-void
c9052e
-meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self,
c9052e
-                                                struct wl_list *frame_callbacks)
c9052e
-{
c9052e
-  wl_list_insert_list (&self->frame_callback_list, frame_callbacks);
c9052e
-}
c9052e
-
c9052e
 static MetaWindow *
c9052e
 meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
c9052e
 {
c9052e
@@ -158,22 +150,6 @@ meta_surface_actor_wayland_get_preferred_height  (ClutterActor *actor,
c9052e
     *natural_height_p *= scale;
c9052e
 }
c9052e
 
c9052e
-static void
c9052e
-meta_surface_actor_wayland_paint (ClutterActor *actor)
c9052e
-{
c9052e
-  MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
c9052e
-
c9052e
-  if (self->surface)
c9052e
-    {
c9052e
-      MetaWaylandCompositor *compositor = self->surface->compositor;
c9052e
-
c9052e
-      wl_list_insert_list (&compositor->frame_callbacks, &self->frame_callback_list);
c9052e
-      wl_list_init (&self->frame_callback_list);
c9052e
-    }
c9052e
-
c9052e
-  CLUTTER_ACTOR_CLASS (meta_surface_actor_wayland_parent_class)->paint (actor);
c9052e
-}
c9052e
-
c9052e
 static void
c9052e
 meta_surface_actor_wayland_dispose (GObject *object)
c9052e
 {
c9052e
@@ -190,9 +166,6 @@ meta_surface_actor_wayland_dispose (GObject *object)
c9052e
       self->surface = NULL;
c9052e
     }
c9052e
 
c9052e
-  wl_list_for_each_safe (cb, next, &self->frame_callback_list, link)
c9052e
-    wl_resource_destroy (cb->resource);
c9052e
-
c9052e
   G_OBJECT_CLASS (meta_surface_actor_wayland_parent_class)->dispose (object);
c9052e
 }
c9052e
 
c9052e
@@ -205,7 +178,6 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
c9052e
 
c9052e
   actor_class->get_preferred_width = meta_surface_actor_wayland_get_preferred_width;
c9052e
   actor_class->get_preferred_height = meta_surface_actor_wayland_get_preferred_height;
c9052e
-  actor_class->paint = meta_surface_actor_wayland_paint;
c9052e
 
c9052e
   surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
c9052e
   surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
c9052e
@@ -232,7 +204,6 @@ meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
c9052e
 
c9052e
   g_assert (meta_is_wayland_compositor ());
c9052e
 
c9052e
-  wl_list_init (&self->frame_callback_list);
c9052e
   self->surface = surface;
c9052e
   g_object_add_weak_pointer (G_OBJECT (self->surface),
c9052e
                              (gpointer *) &self->surface);
c9052e
diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c
c9052e
index 264565c575..037dd901ab 100644
c9052e
--- a/src/wayland/meta-wayland-actor-surface.c
c9052e
+++ b/src/wayland/meta-wayland-actor-surface.c
c9052e
@@ -84,16 +84,22 @@ meta_wayland_actor_surface_assigned (MetaWaylandSurfaceRole *surface_role)
c9052e
     meta_wayland_surface_role_get_surface (surface_role);
c9052e
   GList *l;
c9052e
 
c9052e
-  meta_surface_actor_wayland_add_frame_callbacks (META_SURFACE_ACTOR_WAYLAND (priv->actor),
c9052e
-                                                  &surface->pending_frame_callback_list);
c9052e
-  wl_list_init (&surface->pending_frame_callback_list);
c9052e
-
c9052e
   for (l = surface->subsurfaces; l; l = l->next)
c9052e
     {
c9052e
       ClutterActor *subsurface_actor =
c9052e
         CLUTTER_ACTOR (meta_wayland_surface_get_actor (l->data));
c9052e
       clutter_actor_add_child (CLUTTER_ACTOR (priv->actor), subsurface_actor);
c9052e
     }
c9052e
+
c9052e
+  if (wl_list_empty (&surface->unassigned.pending_frame_callback_list))
c9052e
+    return;
c9052e
+
c9052e
+  wl_list_insert_list (priv->frame_callback_list.prev,
c9052e
+                       &surface->unassigned.pending_frame_callback_list);
c9052e
+  wl_list_init (&surface->unassigned.pending_frame_callback_list);
c9052e
+
c9052e
+  meta_wayland_compositor_add_frame_callback_surface (surface->compositor,
c9052e
+                                                      surface);
c9052e
 }
c9052e
 
c9052e
 void
c9052e
@@ -102,15 +108,40 @@ meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor
c9052e
 {
c9052e
   MetaWaylandActorSurfacePrivate *priv =
c9052e
     meta_wayland_actor_surface_get_instance_private (actor_surface);
c9052e
-  MetaSurfaceActorWayland *surface_actor_wayland =
c9052e
-    META_SURFACE_ACTOR_WAYLAND (priv->actor);
c9052e
+  MetaWaylandSurfaceRole *surface_role =
c9052e
+    META_WAYLAND_SURFACE_ROLE (actor_surface);
c9052e
+  MetaWaylandSurface *surface =
c9052e
+    meta_wayland_surface_role_get_surface (surface_role);
c9052e
 
c9052e
-  meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland,
c9052e
-                                                  &priv->frame_callback_list);
c9052e
-  wl_list_init (&priv->frame_callback_list);
c9052e
-  meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland,
c9052e
-                                                  &pending->frame_callback_list);
c9052e
+  if (!priv->actor)
c9052e
+    return;
c9052e
+
c9052e
+  if (wl_list_empty (&pending->frame_callback_list))
c9052e
+    return;
c9052e
+
c9052e
+  wl_list_insert_list (priv->frame_callback_list.prev,
c9052e
+                       &pending->frame_callback_list);
c9052e
   wl_list_init (&pending->frame_callback_list);
c9052e
+
c9052e
+  meta_wayland_compositor_add_frame_callback_surface (surface->compositor,
c9052e
+                                                      surface);
c9052e
+}
c9052e
+
c9052e
+void
c9052e
+meta_wayland_actor_surface_emit_frame_callbacks (MetaWaylandActorSurface *actor_surface,
c9052e
+                                                 uint32_t                 timestamp_ms)
c9052e
+{
c9052e
+  MetaWaylandActorSurfacePrivate *priv =
c9052e
+    meta_wayland_actor_surface_get_instance_private (actor_surface);
c9052e
+
c9052e
+  while (!wl_list_empty (&priv->frame_callback_list))
c9052e
+    {
c9052e
+      MetaWaylandFrameCallback *callback =
c9052e
+        wl_container_of (priv->frame_callback_list.next, callback, link);
c9052e
+
c9052e
+      wl_callback_send_done (callback->resource, timestamp_ms);
c9052e
+      wl_resource_destroy (callback->resource);
c9052e
+    }
c9052e
 }
c9052e
 
c9052e
 static double
c9052e
@@ -268,12 +299,14 @@ meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole  *surface_role,
c9052e
     meta_wayland_surface_role_get_surface (surface_role);
c9052e
   MetaWaylandSurface *toplevel_surface;
c9052e
 
c9052e
-  if (!priv->actor)
c9052e
+  if (!wl_list_empty (&pending->frame_callback_list) &&
c9052e
+      priv->actor &&
c9052e
+      !meta_surface_actor_is_obscured (priv->actor))
c9052e
     {
c9052e
-      wl_list_insert_list (&priv->frame_callback_list,
c9052e
-                           &pending->frame_callback_list);
c9052e
-      wl_list_init (&pending->frame_callback_list);
c9052e
-      return;
c9052e
+      MetaBackend *backend = meta_get_backend ();
c9052e
+      ClutterActor *stage = meta_backend_get_stage (backend);
c9052e
+
c9052e
+      clutter_stage_schedule_update (CLUTTER_STAGE (stage));
c9052e
     }
c9052e
 
c9052e
   meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending);
c9052e
diff --git a/src/wayland/meta-wayland-actor-surface.h b/src/wayland/meta-wayland-actor-surface.h
c9052e
index 444b3b1785..e79f1caff5 100644
c9052e
--- a/src/wayland/meta-wayland-actor-surface.h
c9052e
+++ b/src/wayland/meta-wayland-actor-surface.h
c9052e
@@ -46,4 +46,7 @@ void meta_wayland_actor_surface_reset_actor (MetaWaylandActorSurface *actor_surf
c9052e
 void meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor_surface,
c9052e
                                                        MetaWaylandPendingState *pending);
c9052e
 
c9052e
+void meta_wayland_actor_surface_emit_frame_callbacks (MetaWaylandActorSurface *actor_surface,
c9052e
+                                                      uint32_t                 timestamp_ms);
c9052e
+
c9052e
 #endif /* META_WAYLAND_ACTOR_SURFACE_H */
c9052e
diff --git a/src/wayland/meta-wayland-cursor-surface.c b/src/wayland/meta-wayland-cursor-surface.c
c9052e
index d46b3511fa..6b791eb378 100644
c9052e
--- a/src/wayland/meta-wayland-cursor-surface.c
c9052e
+++ b/src/wayland/meta-wayland-cursor-surface.c
c9052e
@@ -124,8 +124,8 @@ meta_wayland_cursor_surface_assigned (MetaWaylandSurfaceRole *surface_role)
c9052e
     meta_wayland_cursor_surface_get_instance_private (cursor_surface);
c9052e
 
c9052e
   wl_list_insert_list (&priv->frame_callbacks,
c9052e
-                       &surface->pending_frame_callback_list);
c9052e
-  wl_list_init (&surface->pending_frame_callback_list);
c9052e
+                       &surface->unassigned.pending_frame_callback_list);
c9052e
+  wl_list_init (&surface->unassigned.pending_frame_callback_list);
c9052e
 }
c9052e
 
c9052e
 static void
c9052e
diff --git a/src/wayland/meta-wayland-dnd-surface.c b/src/wayland/meta-wayland-dnd-surface.c
c9052e
index 2aad6dcd5d..8ddeb2a7bd 100644
c9052e
--- a/src/wayland/meta-wayland-dnd-surface.c
c9052e
+++ b/src/wayland/meta-wayland-dnd-surface.c
c9052e
@@ -21,6 +21,8 @@
c9052e
 
c9052e
 #include "wayland/meta-wayland-dnd-surface.h"
c9052e
 
c9052e
+#include "wayland/meta-wayland.h"
c9052e
+
c9052e
 struct _MetaWaylandSurfaceRoleDND
c9052e
 {
c9052e
   MetaWaylandActorSurface parent;
c9052e
@@ -36,7 +38,11 @@ dnd_surface_assigned (MetaWaylandSurfaceRole *surface_role)
c9052e
   MetaWaylandSurface *surface =
c9052e
     meta_wayland_surface_role_get_surface (surface_role);
c9052e
 
c9052e
-  meta_wayland_surface_queue_pending_frame_callbacks (surface);
c9052e
+  if (wl_list_empty (&surface->unassigned.pending_frame_callback_list))
c9052e
+    return;
c9052e
+
c9052e
+  meta_wayland_compositor_add_frame_callback_surface (surface->compositor,
c9052e
+                                                      surface);
c9052e
 }
c9052e
 
c9052e
 static void
c9052e
@@ -46,7 +52,8 @@ dnd_surface_commit (MetaWaylandSurfaceRole  *surface_role,
c9052e
   MetaWaylandSurface *surface =
c9052e
     meta_wayland_surface_role_get_surface (surface_role);
c9052e
 
c9052e
-  meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
c9052e
+  meta_wayland_compositor_add_frame_callback_surface (surface->compositor,
c9052e
+                                                      surface);
c9052e
 }
c9052e
 
c9052e
 static void
c9052e
diff --git a/src/wayland/meta-wayland-legacy-xdg-shell.c b/src/wayland/meta-wayland-legacy-xdg-shell.c
c9052e
index 8230641770..b78552f31b 100644
c9052e
--- a/src/wayland/meta-wayland-legacy-xdg-shell.c
c9052e
+++ b/src/wayland/meta-wayland-legacy-xdg-shell.c
c9052e
@@ -659,6 +659,8 @@ meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole  *surface_role,
c9052e
     META_WAYLAND_ZXDG_SURFACE_V6 (xdg_toplevel);
c9052e
   MetaWaylandZxdgSurfaceV6Private *xdg_surface_priv =
c9052e
     meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface);
c9052e
+  MetaWaylandActorSurface *actor_surface =
c9052e
+    META_WAYLAND_ACTOR_SURFACE (xdg_surface);
c9052e
   MetaWaylandSurfaceRoleClass *surface_role_class;
c9052e
   MetaWaylandSurface *surface =
c9052e
     meta_wayland_surface_role_get_surface (surface_role);
c9052e
@@ -670,7 +672,7 @@ meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole  *surface_role,
c9052e
   window = surface->window;
c9052e
   if (!window)
c9052e
     {
c9052e
-      meta_wayland_surface_cache_pending_frame_callbacks (surface, pending);
c9052e
+      meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending);
c9052e
       return;
c9052e
     }
c9052e
 
c9052e
@@ -1220,14 +1222,10 @@ meta_wayland_zxdg_surface_v6_send_configure (MetaWaylandZxdgSurfaceV6 *xdg_surfa
c9052e
 static void
c9052e
 zxdg_surface_v6_destructor (struct wl_resource *resource)
c9052e
 {
c9052e
-  MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
c9052e
   MetaWaylandZxdgSurfaceV6 *xdg_surface = wl_resource_get_user_data (resource);
c9052e
   MetaWaylandZxdgSurfaceV6Private *priv =
c9052e
     meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface);
c9052e
 
c9052e
-  meta_wayland_compositor_destroy_frame_callbacks (surface->compositor,
c9052e
-                                                   surface);
c9052e
-
c9052e
   priv->shell_client->surfaces = g_list_remove (priv->shell_client->surfaces,
c9052e
                                                 xdg_surface);
c9052e
 
c9052e
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
c9052e
index 5bcb0ea4f9..215d0967f6 100644
c9052e
--- a/src/wayland/meta-wayland-private.h
c9052e
+++ b/src/wayland/meta-wayland-private.h
c9052e
@@ -67,7 +67,7 @@ struct _MetaWaylandCompositor
c9052e
   struct wl_display *wayland_display;
c9052e
   char *display_name;
c9052e
   GHashTable *outputs;
c9052e
-  struct wl_list frame_callbacks;
c9052e
+  GList *frame_callback_surfaces;
c9052e
 
c9052e
   MetaXWaylandManager xwayland_manager;
c9052e
 
c9052e
diff --git a/src/wayland/meta-wayland-subsurface.c b/src/wayland/meta-wayland-subsurface.c
c9052e
index e0fa0a48b2..c7059b99a2 100644
c9052e
--- a/src/wayland/meta-wayland-subsurface.c
c9052e
+++ b/src/wayland/meta-wayland-subsurface.c
c9052e
@@ -239,8 +239,6 @@ wl_subsurface_destructor (struct wl_resource *resource)
c9052e
 {
c9052e
   MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
c9052e
 
c9052e
-  meta_wayland_compositor_destroy_frame_callbacks (surface->compositor,
c9052e
-                                                   surface);
c9052e
   if (surface->sub.parent)
c9052e
     {
c9052e
       wl_list_remove (&surface->sub.parent_destroy_listener.link);
c9052e
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
c9052e
index 6ffcd6a7fb..a76ab28c24 100644
c9052e
--- a/src/wayland/meta-wayland-surface.c
c9052e
+++ b/src/wayland/meta-wayland-surface.c
c9052e
@@ -358,15 +358,6 @@ surface_process_damage (MetaWaylandSurface *surface,
c9052e
   cairo_region_destroy (transformed_region);
c9052e
 }
c9052e
 
c9052e
-void
c9052e
-meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface      *surface,
c9052e
-                                                          MetaWaylandPendingState *pending)
c9052e
-{
c9052e
-  wl_list_insert_list (&surface->compositor->frame_callbacks,
c9052e
-                       &pending->frame_callback_list);
c9052e
-  wl_list_init (&pending->frame_callback_list);
c9052e
-}
c9052e
-
c9052e
 void
c9052e
 meta_wayland_surface_destroy_window (MetaWaylandSurface *surface)
c9052e
 {
c9052e
@@ -656,15 +647,6 @@ parent_surface_state_applied (gpointer data,
c9052e
   meta_wayland_subsurface_parent_state_applied (subsurface);
c9052e
 }
c9052e
 
c9052e
-void
c9052e
-meta_wayland_surface_cache_pending_frame_callbacks (MetaWaylandSurface      *surface,
c9052e
-                                                    MetaWaylandPendingState *pending)
c9052e
-{
c9052e
-  wl_list_insert_list (&surface->pending_frame_callback_list,
c9052e
-                       &pending->frame_callback_list);
c9052e
-  wl_list_init (&pending->frame_callback_list);
c9052e
-}
c9052e
-
c9052e
 void
c9052e
 meta_wayland_surface_apply_pending_state (MetaWaylandSurface      *surface,
c9052e
                                           MetaWaylandPendingState *pending)
c9052e
@@ -810,7 +792,9 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface      *surface,
c9052e
     }
c9052e
   else
c9052e
     {
c9052e
-      meta_wayland_surface_cache_pending_frame_callbacks (surface, pending);
c9052e
+      wl_list_insert_list (surface->unassigned.pending_frame_callback_list.prev,
c9052e
+                           &pending->frame_callback_list);
c9052e
+      wl_list_init (&pending->frame_callback_list);
c9052e
 
c9052e
       if (pending->newly_attached)
c9052e
         {
c9052e
@@ -1352,12 +1336,14 @@ wl_surface_destructor (struct wl_resource *resource)
c9052e
   if (surface->input_region)
c9052e
     cairo_region_destroy (surface->input_region);
c9052e
 
c9052e
-  meta_wayland_compositor_destroy_frame_callbacks (compositor, surface);
c9052e
+  meta_wayland_compositor_remove_frame_callback_surface (compositor, surface);
c9052e
 
c9052e
   g_hash_table_foreach (surface->outputs_to_destroy_notify_id, surface_output_disconnect_signal, surface);
c9052e
   g_hash_table_unref (surface->outputs_to_destroy_notify_id);
c9052e
 
c9052e
-  wl_list_for_each_safe (cb, next, &surface->pending_frame_callback_list, link)
c9052e
+  wl_list_for_each_safe (cb, next,
c9052e
+                         &surface->unassigned.pending_frame_callback_list,
c9052e
+                         link)
c9052e
     wl_resource_destroy (cb->resource);
c9052e
 
c9052e
   if (surface->resource)
c9052e
@@ -1401,7 +1387,7 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
c9052e
   surface->resource = wl_resource_create (client, &wl_surface_interface, wl_resource_get_version (compositor_resource), id);
c9052e
   wl_resource_set_implementation (surface->resource, &meta_wayland_wl_surface_interface, surface, wl_surface_destructor);
c9052e
 
c9052e
-  wl_list_init (&surface->pending_frame_callback_list);
c9052e
+  wl_list_init (&surface->unassigned.pending_frame_callback_list);
c9052e
 
c9052e
   sync_drag_dest_funcs (surface);
c9052e
 
c9052e
@@ -1809,14 +1795,6 @@ meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRole *role)
c9052e
   return priv->surface;
c9052e
 }
c9052e
 
c9052e
-void
c9052e
-meta_wayland_surface_queue_pending_frame_callbacks (MetaWaylandSurface *surface)
c9052e
-{
c9052e
-  wl_list_insert_list (&surface->compositor->frame_callbacks,
c9052e
-                       &surface->pending_frame_callback_list);
c9052e
-  wl_list_init (&surface->pending_frame_callback_list);
c9052e
-}
c9052e
-
c9052e
 cairo_region_t *
c9052e
 meta_wayland_surface_calculate_input_region (MetaWaylandSurface *surface)
c9052e
 {
c9052e
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
c9052e
index e244a3fdf7..776431fca2 100644
c9052e
--- a/src/wayland/meta-wayland-surface.h
c9052e
+++ b/src/wayland/meta-wayland-surface.h
c9052e
@@ -160,13 +160,9 @@ struct _MetaWaylandSurface
c9052e
   /* Buffer renderer state. */
c9052e
   gboolean buffer_held;
c9052e
 
c9052e
-  /* List of pending frame callbacks that needs to stay queued longer than one
c9052e
-   * commit sequence, such as when it has not yet been assigned a role.
c9052e
-   */
c9052e
-  struct wl_list pending_frame_callback_list;
c9052e
-
c9052e
   /* Intermediate state for when no role has been assigned. */
c9052e
   struct {
c9052e
+    struct wl_list pending_frame_callback_list;
c9052e
     MetaWaylandBuffer *buffer;
c9052e
   } unassigned;
c9052e
 
c9052e
@@ -274,9 +270,6 @@ MetaWaylandSurface *meta_wayland_surface_get_toplevel (MetaWaylandSurface *surfa
c9052e
 
c9052e
 MetaWindow *        meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface);
c9052e
 
c9052e
-void                meta_wayland_surface_cache_pending_frame_callbacks (MetaWaylandSurface      *surface,
c9052e
-                                                                        MetaWaylandPendingState *pending);
c9052e
-
c9052e
 void                meta_wayland_surface_queue_pending_frame_callbacks (MetaWaylandSurface *surface);
c9052e
 
c9052e
 void                meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface      *surface,
c9052e
diff --git a/src/wayland/meta-wayland-wl-shell.c b/src/wayland/meta-wayland-wl-shell.c
c9052e
index 539fb9858e..e80db17e78 100644
c9052e
--- a/src/wayland/meta-wayland-wl-shell.c
c9052e
+++ b/src/wayland/meta-wayland-wl-shell.c
c9052e
@@ -100,9 +100,6 @@ wl_shell_surface_destructor (struct wl_resource *resource)
c9052e
     surface_from_wl_shell_surface_resource (resource);
c9052e
   GList *l;
c9052e
 
c9052e
-  meta_wayland_compositor_destroy_frame_callbacks (surface->compositor,
c9052e
-                                                   surface);
c9052e
-
c9052e
   if (wl_shell_surface->popup)
c9052e
     meta_wayland_popup_dismiss (wl_shell_surface->popup);
c9052e
 
c9052e
diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c
c9052e
index fa0207a03c..4a4995c425 100644
c9052e
--- a/src/wayland/meta-wayland-xdg-shell.c
c9052e
+++ b/src/wayland/meta-wayland-xdg-shell.c
c9052e
@@ -684,6 +684,8 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole  *surface_role,
c9052e
   MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_toplevel);
c9052e
   MetaWaylandXdgSurfacePrivate *xdg_surface_priv =
c9052e
     meta_wayland_xdg_surface_get_instance_private (xdg_surface);
c9052e
+  MetaWaylandActorSurface *actor_surface =
c9052e
+    META_WAYLAND_ACTOR_SURFACE (xdg_toplevel);
c9052e
   MetaWaylandSurfaceRoleClass *surface_role_class;
c9052e
   MetaWaylandSurface *surface =
c9052e
     meta_wayland_surface_role_get_surface (surface_role);
c9052e
@@ -695,15 +697,12 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole  *surface_role,
c9052e
   window = surface->window;
c9052e
   if (!window)
c9052e
     {
c9052e
-      meta_wayland_surface_cache_pending_frame_callbacks (surface, pending);
c9052e
+      meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending);
c9052e
       return;
c9052e
     }
c9052e
 
c9052e
   if (!surface->buffer_ref.buffer && xdg_surface_priv->first_buffer_attached)
c9052e
     {
c9052e
-      MetaWaylandActorSurface *actor_surface =
c9052e
-        META_WAYLAND_ACTOR_SURFACE (xdg_toplevel);
c9052e
-
c9052e
       meta_wayland_xdg_surface_reset (xdg_surface);
c9052e
       meta_wayland_actor_surface_queue_frame_callbacks (actor_surface,
c9052e
                                                         pending);
c9052e
@@ -1037,6 +1036,8 @@ meta_wayland_xdg_popup_commit (MetaWaylandSurfaceRole  *surface_role,
c9052e
   MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
c9052e
   MetaWaylandXdgSurfacePrivate *xdg_surface_priv =
c9052e
     meta_wayland_xdg_surface_get_instance_private (xdg_surface);
c9052e
+  MetaWaylandActorSurface *actor_surface =
c9052e
+    META_WAYLAND_ACTOR_SURFACE (xdg_popup);
c9052e
   MetaWaylandSurfaceRoleClass *surface_role_class;
c9052e
   MetaWaylandSurface *surface =
c9052e
     meta_wayland_surface_role_get_surface (surface_role);
c9052e
@@ -1048,7 +1049,7 @@ meta_wayland_xdg_popup_commit (MetaWaylandSurfaceRole  *surface_role,
c9052e
   if (!surface->buffer_ref.buffer && xdg_surface_priv->first_buffer_attached)
c9052e
     {
c9052e
       meta_wayland_xdg_surface_reset (xdg_surface);
c9052e
-      meta_wayland_surface_cache_pending_frame_callbacks (surface, pending);
c9052e
+      meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending);
c9052e
       return;
c9052e
     }
c9052e
 
c9052e
@@ -1313,14 +1314,10 @@ meta_wayland_xdg_surface_send_configure (MetaWaylandXdgSurface *xdg_surface)
c9052e
 static void
c9052e
 xdg_surface_destructor (struct wl_resource *resource)
c9052e
 {
c9052e
-  MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
c9052e
   MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (resource);
c9052e
   MetaWaylandXdgSurfacePrivate *priv =
c9052e
     meta_wayland_xdg_surface_get_instance_private (xdg_surface);
c9052e
 
c9052e
-  meta_wayland_compositor_destroy_frame_callbacks (surface->compositor,
c9052e
-                                                   surface);
c9052e
-
c9052e
   priv->shell_client->surfaces = g_list_remove (priv->shell_client->surfaces,
c9052e
                                                 xdg_surface);
c9052e
 
c9052e
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
c9052e
index 129da8e20d..4cb9ca650d 100644
c9052e
--- a/src/wayland/meta-wayland.c
c9052e
+++ b/src/wayland/meta-wayland.c
c9052e
@@ -194,15 +194,35 @@ meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
c9052e
 void
c9052e
 meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor)
c9052e
 {
c9052e
-  gint64 current_time = g_get_monotonic_time ();
c9052e
+  GList *l;
c9052e
+  int64_t now_us;
c9052e
 
c9052e
-  while (!wl_list_empty (&compositor->frame_callbacks))
c9052e
+  now_us = g_get_monotonic_time ();
c9052e
+
c9052e
+  l = compositor->frame_callback_surfaces;
c9052e
+  while (l)
c9052e
     {
c9052e
-      MetaWaylandFrameCallback *callback =
c9052e
-        wl_container_of (compositor->frame_callbacks.next, callback, link);
c9052e
+      GList *l_cur = l;
c9052e
+      MetaWaylandSurface *surface = l->data;
c9052e
+      MetaSurfaceActor *actor;
c9052e
+      MetaWaylandActorSurface *actor_surface;
c9052e
+
c9052e
+      l = l->next;
c9052e
+
c9052e
+      actor = meta_wayland_surface_get_actor (surface);
c9052e
+      if (!actor)
c9052e
+        continue;
c9052e
+
c9052e
+      if (!clutter_actor_has_mapped_clones (CLUTTER_ACTOR (actor)) &&
c9052e
+          meta_surface_actor_is_obscured (actor))
c9052e
+        continue;
c9052e
 
c9052e
-      wl_callback_send_done (callback->resource, current_time / 1000);
c9052e
-      wl_resource_destroy (callback->resource);
c9052e
+      actor_surface = META_WAYLAND_ACTOR_SURFACE (surface->role);
c9052e
+      meta_wayland_actor_surface_emit_frame_callbacks (actor_surface,
c9052e
+                                                       now_us / 1000);
c9052e
+
c9052e
+      compositor->frame_callback_surfaces =
c9052e
+        g_list_delete_link (compositor->frame_callback_surfaces, l_cur);
c9052e
     }
c9052e
 }
c9052e
 
c9052e
@@ -249,16 +269,22 @@ meta_wayland_compositor_update_key_state (MetaWaylandCompositor *compositor,
c9052e
 }
c9052e
 
c9052e
 void
c9052e
-meta_wayland_compositor_destroy_frame_callbacks (MetaWaylandCompositor *compositor,
c9052e
-                                                 MetaWaylandSurface    *surface)
c9052e
+meta_wayland_compositor_add_frame_callback_surface (MetaWaylandCompositor *compositor,
c9052e
+                                                    MetaWaylandSurface    *surface)
c9052e
 {
c9052e
-  MetaWaylandFrameCallback *callback, *next;
c9052e
+  if (g_list_find (compositor->frame_callback_surfaces, surface))
c9052e
+    return;
c9052e
 
c9052e
-  wl_list_for_each_safe (callback, next, &compositor->frame_callbacks, link)
c9052e
-    {
c9052e
-      if (callback->surface == surface)
c9052e
-        wl_resource_destroy (callback->resource);
c9052e
-    }
c9052e
+  compositor->frame_callback_surfaces =
c9052e
+    g_list_prepend (compositor->frame_callback_surfaces, surface);
c9052e
+}
c9052e
+
c9052e
+void
c9052e
+meta_wayland_compositor_remove_frame_callback_surface (MetaWaylandCompositor *compositor,
c9052e
+                                                       MetaWaylandSurface    *surface)
c9052e
+{
c9052e
+  compositor->frame_callback_surfaces =
c9052e
+    g_list_remove (compositor->frame_callback_surfaces, surface);
c9052e
 }
c9052e
 
c9052e
 static void
c9052e
@@ -309,8 +335,6 @@ meta_wayland_log_func (const char *fmt,
c9052e
 static void
c9052e
 meta_wayland_compositor_init (MetaWaylandCompositor *compositor)
c9052e
 {
c9052e
-  wl_list_init (&compositor->frame_callbacks);
c9052e
-
c9052e
   compositor->scheduled_surface_associations = g_hash_table_new (NULL, NULL);
c9052e
 
c9052e
   wl_log_set_handler_server (meta_wayland_log_func);
c9052e
diff --git a/src/wayland/meta-wayland.h b/src/wayland/meta-wayland.h
c9052e
index 2a0aa11400..c5e5924891 100644
c9052e
--- a/src/wayland/meta-wayland.h
c9052e
+++ b/src/wayland/meta-wayland.h
c9052e
@@ -64,9 +64,11 @@ void                    meta_wayland_compositor_set_input_focus (MetaWaylandComp
c9052e
 META_EXPORT_TEST
c9052e
 void                    meta_wayland_compositor_paint_finished  (MetaWaylandCompositor *compositor);
c9052e
 
c9052e
-META_EXPORT_TEST
c9052e
-void                    meta_wayland_compositor_destroy_frame_callbacks (MetaWaylandCompositor *compositor,
c9052e
-                                                                         MetaWaylandSurface    *surface);
c9052e
+void                    meta_wayland_compositor_add_frame_callback_surface (MetaWaylandCompositor *compositor,
c9052e
+                                                                            MetaWaylandSurface    *surface);
c9052e
+
c9052e
+void                    meta_wayland_compositor_remove_frame_callback_surface (MetaWaylandCompositor *compositor,
c9052e
+                                                                               MetaWaylandSurface    *surface);
c9052e
 
c9052e
 META_EXPORT_TEST
c9052e
 const char             *meta_wayland_get_wayland_display_name   (MetaWaylandCompositor *compositor);
c9052e
diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c
c9052e
index 275aeb78cb..6e4b9a8ffd 100644
c9052e
--- a/src/wayland/meta-xwayland.c
c9052e
+++ b/src/wayland/meta-xwayland.c
c9052e
@@ -788,49 +788,6 @@ meta_xwayland_stop (MetaXWaylandManager *manager)
c9052e
     }
c9052e
 }
c9052e
 
c9052e
-static void
c9052e
-xwayland_surface_assigned (MetaWaylandSurfaceRole *surface_role)
c9052e
-{
c9052e
-  MetaWaylandSurface *surface =
c9052e
-    meta_wayland_surface_role_get_surface (surface_role);
c9052e
-  MetaWaylandSurfaceRoleClass *surface_role_class =
c9052e
-    META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_surface_role_xwayland_parent_class);
c9052e
-
c9052e
-  /* See comment in xwayland_surface_commit for why we reply even though the
c9052e
-   * surface may not be drawn the next frame.
c9052e
-   */
c9052e
-  wl_list_insert_list (&surface->compositor->frame_callbacks,
c9052e
-                       &surface->pending_frame_callback_list);
c9052e
-  wl_list_init (&surface->pending_frame_callback_list);
c9052e
-
c9052e
-  surface_role_class->assigned (surface_role);
c9052e
-}
c9052e
-
c9052e
-static void
c9052e
-xwayland_surface_commit (MetaWaylandSurfaceRole  *surface_role,
c9052e
-                         MetaWaylandPendingState *pending)
c9052e
-{
c9052e
-  MetaWaylandSurface *surface =
c9052e
-    meta_wayland_surface_role_get_surface (surface_role);
c9052e
-  MetaWaylandSurfaceRoleClass *surface_role_class =
c9052e
-    META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_surface_role_xwayland_parent_class);
c9052e
-
c9052e
-  /* For Xwayland windows, throttling frames when the window isn't actually
c9052e
-   * drawn is less useful, because Xwayland still has to do the drawing sent
c9052e
-   * from the application - the throttling would only be of sending us damage
c9052e
-   * messages, so we simplify and send frame callbacks after the next paint of
c9052e
-   * the screen, whether the window was drawn or not.
c9052e
-   *
c9052e
-   * Currently it may take a few frames before we draw the window, for not
c9052e
-   * completely understood reasons, and in that case, not thottling frame
c9052e
-   * callbacks to drawing has the happy side effect that we avoid showing the
c9052e
-   * user the initial black frame from when the window is mapped empty.
c9052e
-   */
c9052e
-  meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
c9052e
-
c9052e
-  surface_role_class->commit (surface_role, pending);
c9052e
-}
c9052e
-
c9052e
 static MetaWaylandSurface *
c9052e
 xwayland_surface_get_toplevel (MetaWaylandSurfaceRole *surface_role)
c9052e
 {
c9052e
@@ -848,8 +805,6 @@ meta_wayland_surface_role_xwayland_class_init (MetaWaylandSurfaceRoleXWaylandCla
c9052e
   MetaWaylandSurfaceRoleClass *surface_role_class =
c9052e
     META_WAYLAND_SURFACE_ROLE_CLASS (klass);
c9052e
 
c9052e
-  surface_role_class->assigned = xwayland_surface_assigned;
c9052e
-  surface_role_class->commit = xwayland_surface_commit;
c9052e
   surface_role_class->get_toplevel = xwayland_surface_get_toplevel;
c9052e
 
c9052e
   xwayland_surface_signals[XWAYLAND_SURFACE_WINDOW_ASSOCIATED] =
c9052e
-- 
c9052e
2.31.1
c9052e
c9052e
c9052e
From 076ac20d34db128aea8ffe0dc3c2791918667c43 Mon Sep 17 00:00:00 2001
c9052e
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
c9052e
Date: Fri, 6 Aug 2021 19:46:06 +0200
c9052e
Subject: [PATCH 5/5] wayland: Respond to frame callbacks even if the paint was
c9052e
 empty
c9052e
c9052e
---
c9052e
 src/compositor/compositor.c | 10 +++++-----
c9052e
 1 file changed, 5 insertions(+), 5 deletions(-)
c9052e
c9052e
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
c9052e
index ce2c1b8a3b..8331737d1a 100644
c9052e
--- a/src/compositor/compositor.c
c9052e
+++ b/src/compositor/compositor.c
c9052e
@@ -467,11 +467,6 @@ after_stage_paint (ClutterStage *stage,
c9052e
 
c9052e
   for (l = compositor->windows; l; l = l->next)
c9052e
     meta_window_actor_post_paint (l->data);
c9052e
-
c9052e
-#ifdef HAVE_WAYLAND
c9052e
-  if (meta_is_wayland_compositor ())
c9052e
-    meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ());
c9052e
-#endif
c9052e
 }
c9052e
 
c9052e
 static void
c9052e
@@ -1404,6 +1399,11 @@ meta_post_paint_func (gpointer data)
c9052e
       break;
c9052e
     }
c9052e
 
c9052e
+#ifdef HAVE_WAYLAND
c9052e
+  if (meta_is_wayland_compositor ())
c9052e
+    meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ());
c9052e
+#endif
c9052e
+
c9052e
   return TRUE;
c9052e
 }
c9052e
 
c9052e
-- 
c9052e
2.31.1
c9052e