Submitted By:            Xi Ruoyao <xry111@mengyan1223.wang>
Date:                    2022-03-22
Initial Package Version: 42.0
Upstream Status:         Partly merged
Origin:                  See below
Description:             Consolidated patch of various fixes for mutter that
                         couldn't go into 42.O. See
                         https://gitlab.gnome.org/GNOME/mutter/-/issues/2175

diff --color -Naur mutter-42.0/clutter/clutter/cally/cally-stage.c mutter-42.0-patched/clutter/clutter/cally/cally-stage.c
--- mutter-42.0/clutter/clutter/cally/cally-stage.c	2022-03-13 07:30:36.245525000 +0800
+++ mutter-42.0-patched/clutter/clutter/cally/cally-stage.c	2022-03-22 15:30:21.494145864 +0800
@@ -39,6 +39,8 @@
 #include "cally-stage.h"
 #include "cally-actor-private.h"
 
+#include "../clutter-stage-private.h"
+
 /* AtkObject.h */
 static void                  cally_stage_real_initialize (AtkObject *obj,
                                                           gpointer   data);
@@ -191,6 +193,9 @@
 
   stage = CLUTTER_STAGE (CALLY_GET_CLUTTER_ACTOR (obj));
 
+  if (clutter_stage_is_activated (stage))
+    cally_stage_activate_cb (stage, CALLY_STAGE (obj));
+
   g_signal_connect (stage, "activate", G_CALLBACK (cally_stage_activate_cb), obj);
   g_signal_connect (stage, "deactivate", G_CALLBACK (cally_stage_deactivate_cb), obj);
   g_signal_connect (stage, "notify::key-focus",
diff --color -Naur mutter-42.0/clutter/clutter/clutter-actor.c mutter-42.0-patched/clutter/clutter/clutter-actor.c
--- mutter-42.0/clutter/clutter/clutter-actor.c	2022-03-13 07:30:36.249525000 +0800
+++ mutter-42.0-patched/clutter/clutter/clutter-actor.c	2022-03-22 15:32:35.377543018 +0800
@@ -1264,6 +1264,10 @@
   if (CLUTTER_ACTOR_IS_MAPPED (self) == mapped)
     return;
 
+  g_return_if_fail (!CLUTTER_ACTOR_IN_MAP_UNMAP (self));
+
+  CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IN_MAP_UNMAP);
+
   if (mapped)
     {
       CLUTTER_ACTOR_GET_CLASS (self)->map (self);
@@ -1274,6 +1278,8 @@
       CLUTTER_ACTOR_GET_CLASS (self)->unmap (self);
       g_assert (!CLUTTER_ACTOR_IS_MAPPED (self));
     }
+
+  CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_IN_MAP_UNMAP);
 }
 
 /* this function updates the mapped and realized states according to
@@ -1695,6 +1701,13 @@
    */
   g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_MAPPED]);
 
+  if (priv->has_pointer)
+    {
+      ClutterActor *stage = _clutter_actor_get_stage_internal (self);
+
+      clutter_stage_pointer_actor_unreactive (CLUTTER_STAGE (stage), self);
+    }
+
   /* relinquish keyboard focus if we were unmapped while owning it */
   if (!CLUTTER_ACTOR_IS_TOPLEVEL (self))
     maybe_unset_key_focus (self);
@@ -12434,8 +12447,12 @@
 clutter_actor_set_reactive (ClutterActor *actor,
                             gboolean      reactive)
 {
+  ClutterActorPrivate *priv;
+
   g_return_if_fail (CLUTTER_IS_ACTOR (actor));
 
+  priv = actor->priv;
+
   if (reactive == CLUTTER_ACTOR_IS_REACTIVE (actor))
     return;
 
@@ -12445,6 +12462,13 @@
     CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REACTIVE);
 
   g_object_notify_by_pspec (G_OBJECT (actor), obj_props[PROP_REACTIVE]);
+
+  if (!CLUTTER_ACTOR_IS_REACTIVE (actor) && priv->has_pointer)
+    {
+      ClutterActor *stage = _clutter_actor_get_stage_internal (actor);
+
+      clutter_stage_pointer_actor_unreactive (CLUTTER_STAGE (stage), actor);
+    }
 }
 
 /**
diff --color -Naur mutter-42.0/clutter/clutter/clutter-event.c mutter-42.0-patched/clutter/clutter/clutter-event.c
--- mutter-42.0/clutter/clutter/clutter-event.c	2022-03-13 07:30:36.265525300 +0800
+++ mutter-42.0-patched/clutter/clutter/clutter-event.c	2022-03-22 15:30:26.902562665 +0800
@@ -1772,7 +1772,8 @@
 }
 
 gboolean
-_clutter_event_process_filters (ClutterEvent *event)
+_clutter_event_process_filters (ClutterEvent *event,
+                                ClutterActor *event_actor)
 {
   ClutterMainContext *context = _clutter_context_get_default ();
   GList *l, *next;
@@ -1789,7 +1790,7 @@
       if (event_filter->stage && event_filter->stage != event->any.stage)
         continue;
 
-      if (event_filter->func (event, event_filter->user_data) == CLUTTER_EVENT_STOP)
+      if (event_filter->func (event, event_actor, event_filter->user_data) == CLUTTER_EVENT_STOP)
         return CLUTTER_EVENT_STOP;
     }
 
diff --color -Naur mutter-42.0/clutter/clutter/clutter-event.h mutter-42.0-patched/clutter/clutter/clutter-event.h
--- mutter-42.0/clutter/clutter/clutter-event.h	2022-03-13 07:30:36.265525300 +0800
+++ mutter-42.0-patched/clutter/clutter/clutter-event.h	2022-03-22 15:30:26.902562665 +0800
@@ -615,6 +615,7 @@
 /**
  * ClutterEventFilterFunc:
  * @event: the event that is going to be emitted
+ * @event_actor: the current device actor of the events device
  * @user_data: the data pointer passed to clutter_event_add_filter()
  *
  * A function pointer type used by event filters that are added with
@@ -628,6 +629,7 @@
  * Since: 1.18
  */
 typedef gboolean (* ClutterEventFilterFunc) (const ClutterEvent *event,
+                                             ClutterActor       *event_actor,
                                              gpointer            user_data);
 
 CLUTTER_EXPORT
diff --color -Naur mutter-42.0/clutter/clutter/clutter-event-private.h mutter-42.0-patched/clutter/clutter/clutter-event-private.h
--- mutter-42.0/clutter/clutter/clutter-event-private.h	2022-03-13 07:30:36.261525400 +0800
+++ mutter-42.0-patched/clutter/clutter/clutter-event-private.h	2022-03-22 15:30:26.902562665 +0800
@@ -14,7 +14,8 @@
 void            _clutter_process_event                  (ClutterEvent       *event);
 
 CLUTTER_EXPORT
-gboolean        _clutter_event_process_filters          (ClutterEvent       *event);
+gboolean        _clutter_event_process_filters          (ClutterEvent *event,
+                                                         ClutterActor *event_actor);
 
 /* clears the event queue inside the main context */
 void            _clutter_clear_events_queue             (void);
diff --color -Naur mutter-42.0/clutter/clutter/clutter-input-pointer-a11y.c mutter-42.0-patched/clutter/clutter/clutter-input-pointer-a11y.c
--- mutter-42.0/clutter/clutter/clutter-input-pointer-a11y.c	2022-03-13 07:30:36.269525500 +0800
+++ mutter-42.0-patched/clutter/clutter/clutter-input-pointer-a11y.c	2022-03-22 15:30:18.889956635 +0800
@@ -25,11 +25,13 @@
 
 #include "clutter-build-config.h"
 
+#include "clutter-backend-private.h"
 #include "clutter-enum-types.h"
 #include "clutter-input-device.h"
 #include "clutter-input-device-private.h"
 #include "clutter-input-pointer-a11y-private.h"
 #include "clutter-main.h"
+#include "clutter-private.h"
 #include "clutter-virtual-input-device.h"
 
 static gboolean
@@ -726,3 +728,39 @@
 
   return (is_secondary_click_enabled (device) || is_dwell_click_enabled (device));
 }
+
+void
+_clutter_input_pointer_a11y_maybe_handle_event (ClutterEvent *event)
+{
+
+  ClutterInputDevice *device = clutter_event_get_device (event);
+  ClutterMainContext *clutter_context;
+  ClutterBackend *backend;
+
+  if (!_clutter_is_input_pointer_a11y_enabled (device))
+    return;
+
+  if ((event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC) != 0)
+    return;
+
+  clutter_context = _clutter_context_get_default ();
+  backend = clutter_context->backend;
+
+  if (!clutter_backend_is_display_server (backend))
+    return;
+
+  if (event->type == CLUTTER_MOTION)
+    {
+      float x, y;
+
+      clutter_event_get_coords (event, &x, &y);
+      _clutter_input_pointer_a11y_on_motion_event (device, x, y);
+    }
+  else if (event->type == CLUTTER_BUTTON_PRESS ||
+           event->type == CLUTTER_BUTTON_RELEASE)
+    {
+      _clutter_input_pointer_a11y_on_button_event (device,
+                                                   event->button.button,
+                                                   event->type == CLUTTER_BUTTON_PRESS);
+    }
+}
diff --color -Naur mutter-42.0/clutter/clutter/clutter-input-pointer-a11y-private.h mutter-42.0-patched/clutter/clutter/clutter-input-pointer-a11y-private.h
--- mutter-42.0/clutter/clutter/clutter-input-pointer-a11y-private.h	2022-03-13 07:30:36.269525500 +0800
+++ mutter-42.0-patched/clutter/clutter/clutter-input-pointer-a11y-private.h	2022-03-22 15:30:18.888956564 +0800
@@ -42,6 +42,9 @@
 CLUTTER_EXPORT
 gboolean _clutter_is_input_pointer_a11y_enabled  (ClutterInputDevice     *device);
 
+CLUTTER_EXPORT
+void _clutter_input_pointer_a11y_maybe_handle_event (ClutterEvent *event);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_INPUT_POINTER_A11Y_H__ */
diff --color -Naur mutter-42.0/clutter/clutter/clutter-main.c mutter-42.0-patched/clutter/clutter/clutter-main.c
--- mutter-42.0/clutter/clutter/clutter-main.c	2022-03-13 07:30:36.273525700 +0800
+++ mutter-42.0-patched/clutter/clutter/clutter-main.c	2022-03-22 15:32:26.113902391 +0800
@@ -741,6 +741,9 @@
 void
 clutter_do_event (ClutterEvent *event)
 {
+  ClutterActor *event_actor = NULL;
+  ClutterContext *context = _clutter_context_get_default();
+
   /* we need the stage for the event */
   if (event->any.stage == NULL)
     {
@@ -765,8 +768,27 @@
       break;
     }
 
-  if (_clutter_event_process_filters (event))
-    return;
+  _clutter_input_pointer_a11y_maybe_handle_event (event);
+
+  context->current_event = g_slist_prepend (context->current_event, event);
+
+  if (event->any.type != CLUTTER_DEVICE_ADDED &&
+      event->any.type != CLUTTER_DEVICE_REMOVED &&
+      event->any.type != CLUTTER_NOTHING &&
+      event->any.type != CLUTTER_EVENT_LAST)
+    {
+      event_actor = clutter_stage_get_event_actor (event->any.stage, event);
+    }
+
+  if (_clutter_event_process_filters (event, event_actor))
+    {
+      context->current_event =
+        g_slist_delete_link (context->current_event, context->current_event);
+
+      return;
+    }
+
+  context->current_event = g_slist_delete_link (context->current_event, context->current_event);
 
   /* Instead of processing events when received, we queue them up to
    * handle per-frame before animations, layout, and drawing.
@@ -810,13 +832,8 @@
 {
   ClutterInputDevice *device = clutter_event_get_device (event);
   ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
-  ClutterMainContext *clutter_context;
-  ClutterBackend *backend;
   ClutterActor *target;
 
-  clutter_context = _clutter_context_get_default ();
-  backend = clutter_context->backend;
-
   switch (event->type)
     {
       case CLUTTER_NOTHING:
@@ -858,31 +875,8 @@
         break;
 
       case CLUTTER_MOTION:
-        if (clutter_backend_is_display_server (backend) &&
-            !(event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC))
-          {
-            if (_clutter_is_input_pointer_a11y_enabled (device))
-              {
-                gfloat x, y;
-
-                clutter_event_get_coords (event, &x, &y);
-                _clutter_input_pointer_a11y_on_motion_event (device, x, y);
-              }
-          }
-        G_GNUC_FALLTHROUGH;
       case CLUTTER_BUTTON_PRESS:
       case CLUTTER_BUTTON_RELEASE:
-        if (clutter_backend_is_display_server (backend))
-          {
-            if (_clutter_is_input_pointer_a11y_enabled (device) && (event->type != CLUTTER_MOTION))
-              {
-                _clutter_input_pointer_a11y_on_button_event (device,
-                                                             event->button.button,
-                                                             event->type == CLUTTER_BUTTON_PRESS);
-              }
-          }
-
-        G_GNUC_FALLTHROUGH;
       case CLUTTER_SCROLL:
       case CLUTTER_TOUCHPAD_PINCH:
       case CLUTTER_TOUCHPAD_SWIPE:
diff --color -Naur mutter-42.0/clutter/clutter/clutter-private.h mutter-42.0-patched/clutter/clutter/clutter-private.h
--- mutter-42.0/clutter/clutter/clutter-private.h	2022-03-13 07:30:36.277525700 +0800
+++ mutter-42.0-patched/clutter/clutter/clutter-private.h	2022-03-22 15:32:32.410022663 +0800
@@ -69,6 +69,7 @@
 #define CLUTTER_ACTOR_IN_PREF_WIDTH(a)          ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PREF_WIDTH) != FALSE)
 #define CLUTTER_ACTOR_IN_PREF_HEIGHT(a)         ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PREF_HEIGHT) != FALSE)
 #define CLUTTER_ACTOR_IN_PREF_SIZE(a)           ((CLUTTER_PRIVATE_FLAGS (a) & (CLUTTER_IN_PREF_HEIGHT|CLUTTER_IN_PREF_WIDTH)) != FALSE)
+#define CLUTTER_ACTOR_IN_MAP_UNMAP(a)           ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_MAP_UNMAP) != FALSE)
 
 #define CLUTTER_PARAM_READABLE  (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)
 #define CLUTTER_PARAM_WRITABLE  (G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)
@@ -105,6 +106,8 @@
 
   /* Used to avoid recursion */
   CLUTTER_IN_RELAYOUT    = 1 << 7,
+
+  CLUTTER_IN_MAP_UNMAP   = 1 << 8,
 } ClutterPrivateFlags;
 
 /*
diff --color -Naur mutter-42.0/clutter/clutter/clutter-stage.c mutter-42.0-patched/clutter/clutter/clutter-stage.c
--- mutter-42.0/clutter/clutter/clutter-stage.c	2022-03-13 07:30:36.285525800 +0800
+++ mutter-42.0-patched/clutter/clutter/clutter-stage.c	2022-03-22 15:32:35.378543193 +0800
@@ -128,6 +128,7 @@
   int update_freeze_count;
 
   gboolean pending_finish_queue_redraws;
+  gboolean is_activated;
 
   GHashTable *pointer_devices;
   GHashTable *touch_sequences;
@@ -579,12 +580,16 @@
 static void
 clutter_stage_real_activate (ClutterStage *stage)
 {
+  stage->priv->is_activated = TRUE;
+
   clutter_stage_emit_key_focus_event (stage, TRUE);
 }
 
 static void
 clutter_stage_real_deactivate (ClutterStage *stage)
 {
+  stage->priv->is_activated = FALSE;
+
   clutter_stage_emit_key_focus_event (stage, FALSE);
 }
 
@@ -3150,53 +3155,62 @@
   priv->actor_needs_immediate_relayout = TRUE;
 }
 
-static void
-on_device_actor_reactive_changed (ClutterActor       *actor,
-                                  GParamSpec         *pspec,
-                                  PointerDeviceEntry *entry)
+void
+clutter_stage_pointer_actor_unreactive (ClutterStage *self,
+                                        ClutterActor *actor)
 {
-  ClutterStage *self = entry->stage;
+  ClutterStagePrivate *priv = self->priv;
+  GHashTableIter iter;
+  gpointer value;
 
-  g_assert (!clutter_actor_get_reactive (actor));
+  if (CLUTTER_ACTOR_IN_DESTRUCTION (self))
+    return;
 
-  clutter_stage_pick_and_update_device (self,
-                                        entry->device,
-                                        entry->sequence,
-                                        CLUTTER_DEVICE_UPDATE_IGNORE_CACHE |
-                                        CLUTTER_DEVICE_UPDATE_EMIT_CROSSING,
-                                        entry->coords,
-                                        CLUTTER_CURRENT_TIME);
-}
+  g_assert (!clutter_actor_is_mapped (actor) || !clutter_actor_get_reactive (actor));
 
-static void
-on_device_actor_destroyed (ClutterActor       *actor,
-                           PointerDeviceEntry *entry)
-{
-  /* Simply unset the current_actor pointer here, there's no need to
-   * unset has_pointer or to disconnect any signals because the actor
-   * is gone anyway.
-   */
-  entry->current_actor = NULL;
-  g_clear_pointer (&entry->clear_area, cairo_region_destroy);
-  clutter_stage_repick_device (entry->stage, entry->device);
+  g_hash_table_iter_init (&iter, priv->pointer_devices);
+  while (g_hash_table_iter_next (&iter, NULL, &value))
+    {
+      PointerDeviceEntry *entry = value;
+
+      if (entry->current_actor != actor)
+        continue;
+
+      clutter_stage_pick_and_update_device (self,
+                                            entry->device,
+                                            NULL,
+                                            CLUTTER_DEVICE_UPDATE_IGNORE_CACHE |
+                                            CLUTTER_DEVICE_UPDATE_EMIT_CROSSING,
+                                            entry->coords,
+                                            CLUTTER_CURRENT_TIME);
+    }
+
+  g_hash_table_iter_init (&iter, priv->touch_sequences);
+  while (g_hash_table_iter_next (&iter, NULL, &value))
+    {
+      PointerDeviceEntry *entry = value;
+
+      if (entry->current_actor != actor)
+        continue;
+
+      clutter_stage_pick_and_update_device (self,
+                                            entry->device,
+                                            entry->sequence,
+                                            CLUTTER_DEVICE_UPDATE_IGNORE_CACHE |
+                                            CLUTTER_DEVICE_UPDATE_EMIT_CROSSING,
+                                            entry->coords,
+                                            CLUTTER_CURRENT_TIME);
+    }
+
+  if (actor != CLUTTER_ACTOR (self))
+    g_assert (!clutter_actor_has_pointer (actor));
 }
 
 static void
 free_pointer_device_entry (PointerDeviceEntry *entry)
 {
   if (entry->current_actor)
-    {
-      ClutterActor *actor = entry->current_actor;
-
-      g_signal_handlers_disconnect_by_func (actor,
-                                            G_CALLBACK (on_device_actor_reactive_changed),
-                                            entry);
-      g_signal_handlers_disconnect_by_func (actor,
-                                            G_CALLBACK (on_device_actor_destroyed),
-                                            entry);
-
-      _clutter_actor_set_has_pointer (actor, FALSE);
-   }
+    _clutter_actor_set_has_pointer (entry->current_actor, FALSE);
 
   g_clear_pointer (&entry->clear_area, cairo_region_destroy);
 
@@ -3240,30 +3254,12 @@
   if (entry->current_actor != actor)
     {
       if (entry->current_actor)
-        {
-          ClutterActor *old_actor = entry->current_actor;
-
-          g_signal_handlers_disconnect_by_func (old_actor,
-                                                G_CALLBACK (on_device_actor_reactive_changed),
-                                                entry);
-          g_signal_handlers_disconnect_by_func (old_actor,
-                                                G_CALLBACK (on_device_actor_destroyed),
-                                                entry);
-
-          _clutter_actor_set_has_pointer (old_actor, FALSE);
-        }
+        _clutter_actor_set_has_pointer (entry->current_actor, FALSE);
 
       entry->current_actor = actor;
 
       if (actor)
-        {
-          g_signal_connect (actor, "notify::reactive",
-                            G_CALLBACK (on_device_actor_reactive_changed), entry);
-          g_signal_connect (actor, "destroy",
-                            G_CALLBACK (on_device_actor_destroyed), entry);
-
-          _clutter_actor_set_has_pointer (actor, TRUE);
-        }
+        _clutter_actor_set_has_pointer (actor, TRUE);
     }
 
   g_clear_pointer (&entry->clear_area, cairo_region_destroy);
@@ -3478,7 +3474,7 @@
                                          CLUTTER_EVENT_NONE,
                                          old_actor, new_actor,
                                          point, time_ms);
-          if (!_clutter_event_process_filters (event))
+          if (!_clutter_event_process_filters (event, old_actor))
             _clutter_actor_handle_event (old_actor, root, event);
 
           clutter_event_free (event);
@@ -3492,7 +3488,7 @@
                                          CLUTTER_EVENT_NONE,
                                          new_actor, old_actor,
                                          point, time_ms);
-          if (!_clutter_event_process_filters (event))
+          if (!_clutter_event_process_filters (event, new_actor))
             _clutter_actor_handle_event (new_actor, root, event);
 
           clutter_event_free (event);
@@ -3676,7 +3672,7 @@
                                      grab_actor : old_grab_actor,
                                      entry->coords,
                                      CLUTTER_CURRENT_TIME);
-      if (!_clutter_event_process_filters (event))
+      if (!_clutter_event_process_filters (event, entry->current_actor))
         _clutter_actor_handle_event (deepmost, topmost, event);
       clutter_event_free (event);
     }
@@ -3987,3 +3983,11 @@
 
   return NULL;
 }
+
+gboolean
+clutter_stage_is_activated (ClutterStage *stage)
+{
+  g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
+
+  return stage->priv->is_activated;
+}
diff --color -Naur mutter-42.0/clutter/clutter/clutter-stage-private.h mutter-42.0-patched/clutter/clutter/clutter-stage-private.h
--- mutter-42.0/clutter/clutter/clutter-stage-private.h	2022-03-13 07:30:36.285525800 +0800
+++ mutter-42.0-patched/clutter/clutter/clutter-stage-private.h	2022-03-22 15:32:35.377543018 +0800
@@ -154,6 +154,11 @@
 void clutter_stage_unlink_grab (ClutterStage *self,
                                 ClutterGrab  *grab);
 
+gboolean clutter_stage_is_activated (ClutterStage *stage);
+
+void clutter_stage_pointer_actor_unreactive (ClutterStage *self,
+                                             ClutterActor *actor);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_STAGE_PRIVATE_H__ */
diff --color -Naur mutter-42.0/src/backends/native/meta-stage-native.c mutter-42.0-patched/src/backends/native/meta-stage-native.c
--- mutter-42.0/src/backends/native/meta-stage-native.c	2022-03-13 07:30:36.469529900 +0800
+++ mutter-42.0-patched/src/backends/native/meta-stage-native.c	2022-03-22 15:30:21.496146012 +0800
@@ -27,6 +27,7 @@
 #include "backends/native/meta-stage-native.h"
 
 #include "backends/meta-backend-private.h"
+#include "backends/meta-stage-private.h"
 #include "backends/native/meta-crtc-virtual.h"
 #include "backends/native/meta-cursor-renderer-native.h"
 #include "backends/native/meta-renderer-native.h"
@@ -171,8 +172,22 @@
 }
 
 static void
+meta_stage_native_constructed (GObject *object)
+{
+  MetaStageNative *self = META_STAGE_NATIVE (object);
+
+  G_OBJECT_CLASS (meta_stage_native_parent_class)->constructed (object);
+
+  meta_stage_set_active ((MetaStage *) self->parent.wrapper, TRUE);
+}
+
+static void
 meta_stage_native_class_init (MetaStageNativeClass *klass)
 {
+  GObjectClass *object_class = (GObjectClass *) klass;
+
+  object_class->constructed = meta_stage_native_constructed;
+
   quark_view_frame_closure =
     g_quark_from_static_string ("-meta-native-stage-view-frame-closure");
 }
diff --color -Naur mutter-42.0/src/core/display.c mutter-42.0-patched/src/core/display.c
--- mutter-42.0/src/core/display.c	2022-03-13 07:30:36.489530300 +0800
+++ mutter-42.0-patched/src/core/display.c	2022-03-22 15:30:21.497146086 +0800
@@ -1436,7 +1436,6 @@
   else
     meta_topic (META_DEBUG_FOCUS, "Focus change has no effect, because there is no matching wayland surface");
 
-  meta_stage_set_active (stage, focus_window == NULL);
   meta_wayland_compositor_set_input_focus (compositor, focus_window);
 
   clutter_stage_repick_device (CLUTTER_STAGE (stage),
diff --color -Naur mutter-42.0/src/core/events.c mutter-42.0-patched/src/core/events.c
--- mutter-42.0/src/core/events.c	2022-03-13 07:30:36.489530300 +0800
+++ mutter-42.0-patched/src/core/events.c	2022-03-22 15:30:26.905562903 +0800
@@ -81,23 +81,20 @@
 
 static MetaWindow *
 get_window_for_event (MetaDisplay        *display,
-                      const ClutterEvent *event)
+                      const ClutterEvent *event,
+                      ClutterActor       *event_actor)
 {
   switch (display->event_route)
     {
     case META_EVENT_ROUTE_NORMAL:
       {
-        ClutterActor *target;
         MetaWindowActor *window_actor;
 
         /* Always use the key focused window for key events. */
         if (IS_KEY_EVENT (event))
             return stage_has_key_focus () ? display->focus_window : NULL;
 
-        target = clutter_stage_get_device_actor (clutter_event_get_stage (event),
-                                                 clutter_event_get_device (event),
-                                                 clutter_event_get_event_sequence (event));
-        window_actor = meta_window_actor_from_actor (target);
+        window_actor = meta_window_actor_from_actor (event_actor);
         if (window_actor)
           return meta_window_actor_get_meta_window (window_actor);
         else
@@ -213,7 +210,8 @@
 
 static gboolean
 meta_display_handle_event (MetaDisplay        *display,
-                           const ClutterEvent *event)
+                           const ClutterEvent *event,
+                           ClutterActor       *event_actor)
 {
   MetaBackend *backend = meta_get_backend ();
   MetaWindow *window = NULL;
@@ -338,7 +336,7 @@
     }
 #endif
 
-  window = get_window_for_event (display, event);
+  window = get_window_for_event (display, event, event_actor);
 
   display->current_time = event->any.time;
 
@@ -540,11 +538,12 @@
 
 static gboolean
 event_callback (const ClutterEvent *event,
+                ClutterActor       *event_actor,
                 gpointer            data)
 {
   MetaDisplay *display = data;
 
-  return meta_display_handle_event (display, event);
+  return meta_display_handle_event (display, event, event_actor);
 }
 
 void
diff --color -Naur mutter-42.0/src/wayland/meta-wayland-surface.c mutter-42.0-patched/src/wayland/meta-wayland-surface.c
--- mutter-42.0/src/wayland/meta-wayland-surface.c	2022-03-13 07:30:36.549531500 +0800
+++ mutter-42.0-patched/src/wayland/meta-wayland-surface.c	2022-03-22 15:32:37.302878150 +0800
@@ -791,12 +791,16 @@
   if ((get_buffer_width (surface) % surface->scale != 0) ||
       (get_buffer_height (surface) % surface->scale != 0))
     {
-      wl_resource_post_error (surface->resource, WL_SURFACE_ERROR_INVALID_SIZE,
-                              "Buffer size (%dx%d) must be an integer multiple "
-                              "of the buffer_scale (%d)",
-                              get_buffer_width (surface),
-                              get_buffer_height (surface), surface->scale);
-      goto cleanup;
+      struct wl_resource *resource = surface->resource;
+      pid_t pid;
+
+      wl_client_get_credentials (wl_resource_get_client (resource), &pid, NULL,
+                                 NULL);
+
+      g_warning ("Bug in client with pid %ld: Buffer size (%dx%d) is not an"
+                 "integer multiple of the buffer_scale (%d).", (long) pid,
+                 get_buffer_width (surface), get_buffer_height (surface),
+                 surface->scale);
     }
 
   if (state->has_new_buffer_transform)
