[gtk/wip/chergert/quartz4u] macos: track and update stacking order of known GdkMacosWindow



commit 71466f48b7b763d05271de899d7691691913a7e8
Author: Christian Hergert <chergert redhat com>
Date:   Mon May 4 11:40:29 2020 -0700

    macos: track and update stacking order of known GdkMacosWindow
    
    We will need these ordered so that we can find the right destination window for events
    outside of an NSWindow when resolving from a GdkMacosDevice as well as other API
    to still be implemented.

 gdk/macos/GdkMacosWindow.c            | 39 ++++++++++++-----
 gdk/macos/GdkMacosWindow.h            |  2 +
 gdk/macos/gdkmacosdisplay-private.h   | 52 +++++++++++++---------
 gdk/macos/gdkmacosdisplay-translate.c |  5 +++
 gdk/macos/gdkmacosdisplay.c           | 81 ++++++++++++++++++++++++++++++++---
 gdk/macos/gdkmacossurface-private.h   |  1 +
 gdk/macos/gdkmacossurface.c           | 20 +++++++++
 7 files changed, 161 insertions(+), 39 deletions(-)
---
diff --git a/gdk/macos/GdkMacosWindow.c b/gdk/macos/GdkMacosWindow.c
index d71e07454f..bdddce78a8 100644
--- a/gdk/macos/GdkMacosWindow.c
+++ b/gdk/macos/GdkMacosWindow.c
@@ -27,12 +27,24 @@
 #import "GdkMacosCairoView.h"
 #import "GdkMacosWindow.h"
 
+#include "gdkmacosdisplay-private.h"
 #include "gdkmacossurface-private.h"
 
 #include "gdksurfaceprivate.h"
 
 @implementation GdkMacosWindow
 
+-(void)invalidateStacking
+{
+  if (gdkSurface != NULL)
+    {
+      GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdkSurface));
+
+      if (GDK_IS_MACOS_DISPLAY (display))
+        _gdk_macos_display_stacking_changed (GDK_MACOS_DISPLAY (display));
+    }
+}
+
 -(void)windowWillClose:(NSNotification*)notification
 {
   /* Clears the delegate when window is going to be closed; since EL
@@ -71,6 +83,8 @@
 
   gdk_synthesize_surface_state (window, 0, GDK_SURFACE_STATE_MINIMIZED);
 #endif
+
+  [self invalidateStacking];
 }
 
 -(void)windowDidDeminiaturize:(NSNotification *)aNotification
@@ -82,6 +96,8 @@
 
   gdk_synthesize_surface_state (window, GDK_SURFACE_STATE_MINIMIZED, 0);
 #endif
+
+  [self invalidateStacking];
 }
 
 -(void)windowDidBecomeKey:(NSNotification *)aNotification
@@ -106,9 +122,6 @@
 
 -(void)windowDidBecomeMain:(NSNotification *)aNotification
 {
-#if 0
-  GdkSurface *window = [[self contentView] gdkSurface];
-
   if (![self isVisible])
     {
       /* Note: This is a hack needed because for unknown reasons, hidden
@@ -119,18 +132,12 @@
       return;
     }
 
-  _gdk_quartz_surface_did_become_main (window);
-#endif
+  [self invalidateStacking];
 }
 
 -(void)windowDidResignMain:(NSNotification *)aNotification
 {
-#if 0
-  GdkSurface *window;
-
-  window = [[self contentView] gdkSurface];
-  _gdk_quartz_surface_did_resign_main (window);
-#endif
+  [self invalidateStacking];
 }
 
 /* Used in combination with NSLeftMouseUp in sendEvent to keep track
@@ -633,11 +640,21 @@
   lastUnfullscreenFrame = [self frame];
 }
 
+-(void)windowDidEnterFullScreen:(NSNotification *)aNotification
+{
+  [self invalidateStacking];
+}
+
 -(void)windowWillExitFullScreen:(NSNotification *)aNotification
 {
   [self setFrame:lastUnfullscreenFrame display:YES];
 }
 
+-(void)windowDidExitFullScreen:(NSNotification *)aNotification
+{
+  [self invalidateStacking];
+}
+
 -(void)setGdkSurface:(GdkMacosSurface *)surface
 {
   self->gdkSurface = surface;
diff --git a/gdk/macos/GdkMacosWindow.h b/gdk/macos/GdkMacosWindow.h
index 3f1c6f337d..c6e101584f 100644
--- a/gdk/macos/GdkMacosWindow.h
+++ b/gdk/macos/GdkMacosWindow.h
@@ -26,6 +26,8 @@
 
 #include "gdkmacossurface.h"
 
+#define GDK_IS_MACOS_WINDOW(obj) ([obj isKindOfClass:[GdkMacosWindow class]])
+
 @interface GdkMacosWindow : NSWindow {
   GdkMacosSurface *gdkSurface;
 
diff --git a/gdk/macos/gdkmacosdisplay-private.h b/gdk/macos/gdkmacosdisplay-private.h
index 5f32411a82..d7b737fd5d 100644
--- a/gdk/macos/gdkmacosdisplay-private.h
+++ b/gdk/macos/gdkmacosdisplay-private.h
@@ -23,30 +23,40 @@
 #include <AppKit/AppKit.h>
 
 #include "gdkmacosdisplay.h"
+#include "gdkmacossurface.h"
 
 G_BEGIN_DECLS
 
-GdkDisplay      *_gdk_macos_display_open                         (const gchar     *display_name);
-int              _gdk_macos_display_get_fd                       (GdkMacosDisplay *self);
-void             _gdk_macos_display_queue_events                 (GdkMacosDisplay *self);
-void             _gdk_macos_display_to_display_coords            (GdkMacosDisplay *self,
-                                                                  int              x,
-                                                                  int              y,
-                                                                  int             *out_x,
-                                                                  int             *out_y);
-void             _gdk_macos_display_from_display_coords          (GdkMacosDisplay *self,
-                                                                  int              x,
-                                                                  int              y,
-                                                                  int             *out_x,
-                                                                  int             *out_y);
-NSScreen        *_gdk_macos_display_get_screen_at_display_coords (GdkMacosDisplay *self,
-                                                                  int              x,
-                                                                  int              y);
-GdkEvent        *_gdk_macos_display_translate                    (GdkMacosDisplay *self,
-                                                                  NSEvent         *event);
-void             _gdk_macos_display_break_all_grabs              (GdkMacosDisplay *self,
-                                                                  guint32          time);
-GdkModifierType  _gdk_macos_display_get_current_mouse_modifiers  (GdkMacosDisplay *self);
+GdkDisplay      *_gdk_macos_display_open                           (const gchar     *display_name);
+int              _gdk_macos_display_get_fd                         (GdkMacosDisplay *self);
+void             _gdk_macos_display_queue_events                   (GdkMacosDisplay *self);
+void             _gdk_macos_display_to_display_coords              (GdkMacosDisplay *self,
+                                                                    int              x,
+                                                                    int              y,
+                                                                    int             *out_x,
+                                                                    int             *out_y);
+void             _gdk_macos_display_from_display_coords            (GdkMacosDisplay *self,
+                                                                    int              x,
+                                                                    int              y,
+                                                                    int             *out_x,
+                                                                    int             *out_y);
+NSScreen        *_gdk_macos_display_get_screen_at_display_coords   (GdkMacosDisplay *self,
+                                                                    int              x,
+                                                                    int              y);
+GdkEvent        *_gdk_macos_display_translate                      (GdkMacosDisplay *self,
+                                                                    NSEvent         *event);
+void             _gdk_macos_display_break_all_grabs                (GdkMacosDisplay *self,
+                                                                    guint32          time);
+GdkModifierType  _gdk_macos_display_get_current_keyboard_modifiers (GdkMacosDisplay *self);
+GdkModifierType  _gdk_macos_display_get_current_mouse_modifiers    (GdkMacosDisplay *self);
+GdkMacosSurface *_gdk_macos_display_get_surface_at_display_coords  (GdkMacosDisplay *self,
+                                                                    double           x,
+                                                                    double           y,
+                                                                    int             *surface_x,
+                                                                    int             *surface_y);
+void             _gdk_macos_display_stacking_changed               (GdkMacosDisplay *self);
+void             _gdk_macos_display_surface_removed                (GdkMacosDisplay *self,
+                                                                    GdkMacosSurface *surface);
 
 G_END_DECLS
 
diff --git a/gdk/macos/gdkmacosdisplay-translate.c b/gdk/macos/gdkmacosdisplay-translate.c
index 4be05493df..cc44e16344 100644
--- a/gdk/macos/gdkmacosdisplay-translate.c
+++ b/gdk/macos/gdkmacosdisplay-translate.c
@@ -186,6 +186,11 @@ _gdk_macos_display_get_current_mouse_modifiers (GdkMacosDisplay *self)
   return get_mouse_button_modifiers_from_ns_buttons ([NSEvent pressedMouseButtons]);
 }
 
+GdkModifierType
+_gdk_macos_display_get_current_keyboard_modifiers (GdkMacosDisplay *self)
+{
+  return get_keyboard_modifiers_from_ns_flags ([NSEvent modifierFlags]);
+}
 
 static GdkEvent *
 fill_button_event (GdkMacosDisplay *display,
diff --git a/gdk/macos/gdkmacosdisplay.c b/gdk/macos/gdkmacosdisplay.c
index a6282cb679..04894726a1 100644
--- a/gdk/macos/gdkmacosdisplay.c
+++ b/gdk/macos/gdkmacosdisplay.c
@@ -21,6 +21,8 @@
 
 #include <AppKit/AppKit.h>
 
+#import "GdkMacosWindow.h"
+
 #include "gdkeventsprivate.h"
 
 #include "gdkmacoscairocontext-private.h"
@@ -72,9 +74,11 @@ struct _GdkMacosDisplay
   GdkDisplay           parent_instance;
 
   char                *name;
-  GPtrArray           *monitors;
   GdkMacosKeymap      *keymap;
 
+  GPtrArray           *monitors;
+  GQueue               surfaces;
+
   int                  width;
   int                  height;
   int                  min_x;
@@ -310,6 +314,62 @@ gdk_macos_display_queue_events (GdkDisplay *display)
   _gdk_macos_event_source_release_event (nsevent);
 }
 
+void
+_gdk_macos_display_surface_removed (GdkMacosDisplay *self,
+                                    GdkMacosSurface *surface)
+{
+  GList *stacking;
+
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
+
+  stacking = _gdk_macos_surface_get_stacking (surface);
+
+  g_queue_unlink (&self->surfaces, stacking);
+
+  stacking->prev = NULL;
+  stacking->next = NULL;
+}
+
+void
+_gdk_macos_display_stacking_changed (GdkMacosDisplay *self)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  NSArray *ordered;
+  GQueue sorted = G_QUEUE_INIT;
+
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+
+  /* "orderedWindows" gives us the stacking order starting from front-to-back.
+   * We maintain this so that we can resolve X,Y coordinates in the topmost
+   * surfaces while processing GDK operations from devices, etc.
+   */
+
+  ordered = [NSApp orderedWindows];
+
+  for (id nswindow in ordered)
+    {
+      GdkMacosSurface *surface;
+      GList *link;
+
+      if (!GDK_IS_MACOS_WINDOW (nswindow))
+        continue;
+
+      surface = [(GdkMacosWindow *)nswindow getGdkSurface];
+      link = _gdk_macos_surface_get_stacking (surface);
+
+      link->prev = NULL;
+      link->next = NULL;
+
+      g_queue_push_tail_link (&sorted, link);
+    }
+
+  self->surfaces = sorted;
+
+  GDK_END_MACOS_ALLOC_POOL;
+}
+
 static GdkSurface *
 gdk_macos_display_create_surface (GdkDisplay     *display,
                                   GdkSurfaceType  surface_type,
@@ -319,16 +379,21 @@ gdk_macos_display_create_surface (GdkDisplay     *display,
                                   int             width,
                                   int             height)
 {
+  GdkMacosDisplay *self = (GdkMacosDisplay *)display;
   GdkMacosSurface *surface;
 
-  g_assert (GDK_IS_MACOS_DISPLAY (display));
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
   g_assert (!parent || GDK_IS_MACOS_SURFACE (parent));
 
-  surface = _gdk_macos_surface_new (GDK_MACOS_DISPLAY (display),
-                                    surface_type,
-                                    parent,
-                                    x, y,
-                                    width, height);
+  surface = _gdk_macos_surface_new (self, surface_type, parent, x, y, width, height);
+
+  if (surface != NULL)
+    {
+      GList *stacking = _gdk_macos_surface_get_stacking (surface);
+
+      g_queue_push_head_link (&self->surfaces, stacking);
+      _gdk_macos_display_stacking_changed (self);
+    }
 
   return GDK_SURFACE (surface);
 }
@@ -519,5 +584,7 @@ _gdk_macos_display_break_all_grabs (GdkMacosDisplay *self,
 void
 _gdk_macos_display_queue_events (GdkMacosDisplay *self)
 {
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+
   gdk_macos_display_queue_events (GDK_DISPLAY (self));
 }
diff --git a/gdk/macos/gdkmacossurface-private.h b/gdk/macos/gdkmacossurface-private.h
index 5829888151..2eea9b07cd 100644
--- a/gdk/macos/gdkmacossurface-private.h
+++ b/gdk/macos/gdkmacossurface-private.h
@@ -54,6 +54,7 @@ GdkMacosSurface   *_gdk_macos_surface_new                     (GdkMacosDisplay
                                                                int                 height);
 NSWindow          *_gdk_macos_surface_get_native              (GdkMacosSurface    *self);
 CGDirectDisplayID  _gdk_macos_surface_get_screen_id           (GdkMacosSurface    *self);
+GList             *_gdk_macos_surface_get_stacking            (GdkMacosSurface    *self);
 const char        *_gdk_macos_surface_get_title               (GdkMacosSurface    *self);
 void               _gdk_macos_surface_set_title               (GdkMacosSurface    *self,
                                                                const gchar        *title);
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
index f6d307174b..6d932f673a 100644
--- a/gdk/macos/gdkmacossurface.c
+++ b/gdk/macos/gdkmacossurface.c
@@ -40,6 +40,8 @@
 
 typedef struct
 {
+  GList stacking;
+
   GdkMacosWindow *window;
 
   char *title;
@@ -64,6 +66,16 @@ enum {
 
 static GParamSpec *properties [LAST_PROP];
 
+GList *
+_gdk_macos_surface_get_stacking (GdkMacosSurface *self)
+{
+  GdkMacosSurfacePrivate *priv = gdk_macos_surface_get_instance_private (self);
+
+  g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), NULL);
+
+  return &priv->stacking;
+}
+
 static gboolean
 window_is_fullscreen (GdkMacosSurface *self)
 {
@@ -318,6 +330,11 @@ gdk_macos_surface_destroy (GdkSurface *surface,
   if (window != NULL)
     [window close];
 
+  _gdk_macos_display_surface_removed (GDK_MACOS_DISPLAY (surface->display), self);
+
+  g_assert (priv->stacking.prev == NULL);
+  g_assert (priv->stacking.next == NULL);
+
   GDK_END_MACOS_ALLOC_POOL;
 }
 
@@ -419,6 +436,9 @@ gdk_macos_surface_class_init (GdkMacosSurfaceClass *klass)
 static void
 gdk_macos_surface_init (GdkMacosSurface *self)
 {
+  GdkMacosSurfacePrivate *priv = gdk_macos_surface_get_instance_private (self);
+
+  priv->stacking.data = self;
 }
 
 GdkMacosSurface *


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]