macos: select new key window after processing events
authorChristian Hergert <christian@hergert.me>
Fri, 11 Mar 2022 08:50:10 +0000 (00:50 -0800)
committerChristian Hergert <christian@hergert.me>
Fri, 11 Mar 2022 22:44:06 +0000 (14:44 -0800)
If we closed a key window in response to events, we need to denote another
window as the new key window. This is easiest to do from an idle so that
we don't clobber notification pairs of "did resign"/"did become" key
window.

We have a sorted set of surfaces by display server stacking, so we can
take the first one we come across that is already mapped and re-show it
to become key/main.

gdk/macos/gdkmacosdisplay-private.h
gdk/macos/gdkmacosdisplay.c

index 72b5f5cd57db22551b7f6ab422963c8698e97a11..1edff58d042e25c3c69b64f1d96c6830ab500059 100644 (file)
@@ -84,6 +84,9 @@ struct _GdkMacosDisplay
   int min_y;
   int max_x;
   int max_y;
+
+  /* A GSource to select a new main/key window */
+  guint select_key_in_idle;
 };
 
 struct _GdkMacosDisplayClass
index d1398335fd97a89fbad86cf741cc1eb3afb774dc..6c51ef901ee9d60ff5f66b22b4bcb8e220c19d49 100644 (file)
@@ -413,6 +413,34 @@ _gdk_macos_display_surface_became_key (GdkMacosDisplay *self,
   gdk_surface_request_motion (GDK_SURFACE (surface));
 }
 
+static gboolean
+select_key_in_idle_cb (gpointer data)
+{
+  GdkMacosDisplay *self = data;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  self->select_key_in_idle = 0;
+
+  if (self->keyboard_surface == NULL)
+    {
+      const GList *surfaces = _gdk_macos_display_get_surfaces (self);
+
+      for (const GList *iter = surfaces; iter; iter = iter->next)
+        {
+          GdkMacosSurface *surface = iter->data;
+
+          if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface)))
+            {
+              [surface->window showAndMakeKey:YES];
+              break;
+            }
+        }
+    }
+
+  return G_SOURCE_REMOVE;
+}
+
 void
 _gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
                                          GdkMacosSurface *surface)
@@ -457,6 +485,9 @@ _gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
     }
 
   _gdk_macos_display_clear_sorting (self);
+
+  if (self->select_key_in_idle == 0)
+    self->select_key_in_idle = g_idle_add (select_key_in_idle_cb, self);
 }
 
 /* Raises a transient window.
@@ -564,6 +595,7 @@ gdk_macos_display_finalize (GObject *object)
 
   _gdk_macos_display_feedback_destroy (self);
 
+  g_clear_handle_id (&self->select_key_in_idle, g_source_remove);
   g_clear_pointer (&self->active_drags, g_hash_table_unref);
   g_clear_pointer (&self->active_drops, g_hash_table_unref);
   g_clear_object (&GDK_DISPLAY (self)->clipboard);