[gtk/wip/fanc999/gtk-3-24-meson-msvc: 43/297] Move the CGDisplayReconfigurationCallback to gdkdisplay-quartz.c.



commit be6d58fc59e5e0ebbb49ad4233a6b05fc2cb339f
Author: John Ralls <jralls ceridwen us>
Date:   Wed Nov 21 21:32:41 2018 +0900

    Move the CGDisplayReconfigurationCallback to gdkdisplay-quartz.c.
    
    Handling more flags, handling them correctly, and emitting the requisite
    signals.
    
    Change screen layout to use CGGetActiveDisplayList instead of NSScreens,
    eliminating the latency between updating screens and recomputing the
    root window.

 gdk/quartz/gdkdisplay-quartz.c | 167 ++++++++++++++++++++++++++++++-----------
 gdk/quartz/gdkmonitor-quartz.h |   2 +-
 gdk/quartz/gdkscreen-quartz.c  | 150 ++++++------------------------------
 gdk/quartz/gdkscreen-quartz.h  |   2 +
 4 files changed, 148 insertions(+), 173 deletions(-)
---
diff --git a/gdk/quartz/gdkdisplay-quartz.c b/gdk/quartz/gdkdisplay-quartz.c
index 6e1bc33bdc..abd6a660c8 100644
--- a/gdk/quartz/gdkdisplay-quartz.c
+++ b/gdk/quartz/gdkdisplay-quartz.c
@@ -30,7 +30,13 @@
 #include "gdkscreen.h"
 #include "gdkmonitorprivate.h"
 #include "gdkdisplay-quartz.h"
+#include "gdkmonitor-quartz.h"
 
+static gint MONITORS_CHANGED = 0;
+
+static void display_reconfiguration_callback (CGDirectDisplayID            display,
+                                              CGDisplayChangeSummaryFlags  flags,
+                                              void                        *data);
 
 static GdkWindow *
 gdk_quartz_display_get_default_group (GdkDisplay *display)
@@ -198,18 +204,92 @@ gdk_quartz_display_notify_startup_complete (GdkDisplay  *display,
    the same for determining the number of monitors and indexing them.
  */
 
-static int
-gdk_quartz_display_get_n_monitors (GdkDisplay *display)
+int
+get_active_displays (CGDirectDisplayID **screens)
 {
-  int n;
+  unsigned int displays = 0;
 
-  GDK_QUARTZ_ALLOC_POOL;
+  CGGetActiveDisplayList (0, NULL, &displays);
+  if (screens)
+    {
+      *screens = g_new0 (CGDirectDisplayID, displays);
+      CGGetActiveDisplayList (displays, *screens, &displays);
+    }
 
-  n = [[NSScreen screens] count];
+  return displays;
+}
 
-  GDK_QUARTZ_RELEASE_POOL;
+static void
+configure_monitor (GdkMonitor *monitor)
+{
+  GdkQuartzMonitor *quartz_monitor = GDK_QUARTZ_MONITOR (monitor);
+  CGSize disp_size = CGDisplayScreenSize (quartz_monitor->id);
+  gint width = (int)trunc (disp_size.width);
+  gint height = (int)trunc (disp_size.height);
+  CGRect disp_bounds = CGDisplayBounds (quartz_monitor->id);
+  GdkRectangle disp_geometry = {(int)trunc (disp_bounds.origin.x),
+                                (int)trunc (disp_bounds.origin.y),
+                                (int)trunc (disp_bounds.size.width),
+                                (int)trunc (disp_bounds.size.height)};
+  CGDisplayModeRef mode = CGDisplayCopyDisplayMode (quartz_monitor->id);
+  gint refresh_rate = (int)trunc (CGDisplayModeGetRefreshRate (mode));
+
+  monitor->width_mm = width;
+  monitor->height_mm = height;
+  monitor->geometry = disp_geometry;
+  monitor->scale_factor = 1;
+  monitor->refresh_rate = refresh_rate;
+  monitor->subpixel_layout = GDK_SUBPIXEL_LAYOUT_UNKNOWN;
+  CGDisplayModeRelease (mode);
+}
 
-  return n;
+static void
+display_reconfiguration_callback (CGDirectDisplayID            cg_display,
+                                  CGDisplayChangeSummaryFlags  flags,
+                                  void                        *data)
+{
+  GdkQuartzDisplay *display = data;
+  GdkQuartzMonitor *monitor;
+
+  /* Ignore the begin configuration signal. */
+  if (flags & kCGDisplayBeginConfigurationFlag)
+      return;
+
+  if (flags & (kCGDisplayMovedFlag | kCGDisplayAddFlag | kCGDisplayEnabledFlag |
+               kCGDisplaySetMainFlag | kCGDisplayDesktopShapeChangedFlag |
+               kCGDisplayMirrorFlag | kCGDisplayUnMirrorFlag))
+    {
+      monitor = g_hash_table_lookup (display->monitors,
+                                     GINT_TO_POINTER (cg_display));
+      if (!monitor)
+        {
+          monitor = g_object_new (GDK_TYPE_QUARTZ_MONITOR,
+                                  "display", display, NULL);
+          monitor->id = cg_display;
+          g_hash_table_insert (display->monitors, GINT_TO_POINTER (monitor->id),
+                               monitor);
+          gdk_display_monitor_added (GDK_DISPLAY (display),
+                                     GDK_MONITOR (monitor));
+        }
+      configure_monitor (GDK_MONITOR (monitor));
+    }
+  else if (flags & (kCGDisplayRemoveFlag |  kCGDisplayDisabledFlag))
+    {
+      GdkMonitor *monitor = g_hash_table_lookup (display->monitors,
+                                                 GINT_TO_POINTER (cg_display));
+      gdk_display_monitor_removed (GDK_DISPLAY (display),
+                                   GDK_MONITOR (monitor));
+      g_hash_table_remove (display->monitors, GINT_TO_POINTER (cg_display));
+    }
+
+  g_signal_emit (display, MONITORS_CHANGED, 0);
+}
+
+
+static int
+gdk_quartz_display_get_n_monitors (GdkDisplay *display)
+{
+  return get_active_displays (NULL);
 }
 
 static GdkMonitor *
@@ -217,23 +297,13 @@ gdk_quartz_display_get_monitor (GdkDisplay *display,
                                 int         monitor_num)
 {
   GdkQuartzDisplay *quartz_display = GDK_QUARTZ_DISPLAY (display);
-  NSArray* screens;
-  NSScreen *screen = NULL;
-  CGDirectDisplayID id = 0;
-
-  GDK_QUARTZ_ALLOC_POOL;
+  CGDirectDisplayID *screens = NULL;
 
-  screens = [NSScreen screens];
-  if (monitor_num >= 0 && monitor_num < [screens count])
-    {
-      screen = [screens objectAtIndex:monitor_num];
-      id = [[[screen deviceDescription] valueForKey: @"NSScreenNumber"] unsignedIntValue];
-    }
+  int count = get_active_displays (&screens);
 
-  GDK_QUARTZ_RELEASE_POOL;
-
-  if (id)
-    return g_hash_table_lookup (quartz_display->monitors, GINT_TO_POINTER (id));
+  if (monitor_num >= 0 && monitor_num < count)
+    return g_hash_table_lookup (quartz_display->monitors,
+                                GINT_TO_POINTER (screens[monitor_num]));
 
   return NULL;
 }
@@ -255,6 +325,7 @@ gdk_quartz_display_init (GdkQuartzDisplay *display)
 {
   uint32_t max_displays = 0, disp;
   CGDirectDisplayID *displays;
+
   CGGetActiveDisplayList (0, NULL, &max_displays);
   display->monitors = g_hash_table_new_full (g_direct_hash, NULL,
                                              NULL, g_object_unref);
@@ -262,31 +333,16 @@ gdk_quartz_display_init (GdkQuartzDisplay *display)
   CGGetActiveDisplayList (max_displays, displays, &max_displays);
   for (disp = 0; disp < max_displays; ++disp)
     {
-      CGSize disp_size = CGDisplayScreenSize (displays[disp]);
-      gint width = (int)trunc (disp_size.width);
-      gint height = (int)trunc (disp_size.height);
-      CGRect disp_bounds = CGDisplayBounds (displays[disp]);
-      GdkRectangle disp_geometry = {(int)trunc (disp_bounds.origin.x),
-                                    (int)trunc (disp_bounds.origin.y),
-                                    (int)trunc (disp_bounds.size.width),
-                                    (int)trunc (disp_bounds.size.height)};
-      CGDisplayModeRef mode = CGDisplayCopyDisplayMode (displays[disp]);
-      gint refresh_rate = (int)trunc (CGDisplayModeGetRefreshRate (mode));
-      GdkQuartzMonitor *quartz_monitor = g_object_new (GDK_TYPE_QUARTZ_MONITOR,
+      GdkQuartzMonitor *monitor = g_object_new (GDK_TYPE_QUARTZ_MONITOR,
                                                        "display", display, NULL);
-      GdkMonitor *monitor = GDK_MONITOR (quartz_monitor);
-
-      monitor->width_mm = width;
-      monitor->height_mm = height;
-      monitor->geometry = disp_geometry;
-      monitor->scale_factor = 1;
-      monitor->refresh_rate = refresh_rate;
-      monitor->subpixel_layout = GDK_SUBPIXEL_LAYOUT_UNKNOWN;
-
-      g_hash_table_insert (display->monitors, GINT_TO_POINTER (displays[disp]),
+      monitor->id = displays[disp];
+      g_hash_table_insert (display->monitors, GINT_TO_POINTER (monitor->id),
                            monitor);
-      CGDisplayModeRelease (mode);
+      configure_monitor (GDK_MONITOR (monitor));
     }
+  CGDisplayRegisterReconfigurationCallback (display_reconfiguration_callback,
+                                            display);
+  g_signal_emit (display, MONITORS_CHANGED, 0);
 }
 
 static void
@@ -295,6 +351,8 @@ gdk_quartz_display_dispose (GObject *object)
   GdkQuartzDisplay *display_quartz = GDK_QUARTZ_DISPLAY (object);
 
   g_hash_table_destroy (display_quartz->monitors);
+  CGDisplayRemoveReconfigurationCallback (display_reconfiguration_callback,
+                                          display_quartz);
 
   G_OBJECT_CLASS (gdk_quartz_display_parent_class)->dispose (object);
 }
@@ -362,13 +420,32 @@ gdk_quartz_display_class_init (GdkQuartzDisplayClass *class)
   display_class->text_property_to_utf8_list = _gdk_quartz_display_text_property_to_utf8_list;
   display_class->utf8_to_string_target = _gdk_quartz_display_utf8_to_string_target;
 
-//  display_class->get_default_seat = NULL; /* FIXME */
+/* display_class->get_default_seat; The parent class default works fine. */
 
   display_class->get_n_monitors = gdk_quartz_display_get_n_monitors;
   display_class->get_monitor = gdk_quartz_display_get_monitor;
   display_class->get_primary_monitor = gdk_quartz_display_get_primary_monitor;
   display_class->get_monitor_at_window = NULL; /* FIXME */
 
+  /**
+   * GdkQuartzDisplay::monitors-changed:
+   * @display: The object on which the signal is emitted
+   *
+   * The ::monitors-changed signal is emitted whenever the arrangement
+   * of the monitors changes, either because of the addition or
+   * removal of a monitor or because of some other configuration
+   * change in System Preferences>Displays including a resolution
+   * change or a position change. Note that enabling or disabling
+   * mirroring will result in the addition or removal of the mirror
+   * monitor(s).
+   */
+  MONITORS_CHANGED =
+    g_signal_new (g_intern_static_string ("monitors-changed"),
+                  G_OBJECT_CLASS_TYPE (object_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0, NULL);
+
   ProcessSerialNumber psn = { 0, kCurrentProcess };
 
   /* Make the current process a foreground application, i.e. an app
diff --git a/gdk/quartz/gdkmonitor-quartz.h b/gdk/quartz/gdkmonitor-quartz.h
index 0f9a823211..75dc9c8b12 100644
--- a/gdk/quartz/gdkmonitor-quartz.h
+++ b/gdk/quartz/gdkmonitor-quartz.h
@@ -30,6 +30,7 @@ struct _GdkQuartzMonitor
 {
   GdkMonitor parent;
   gint monitor_num;
+  CGDirectDisplayID id;
 };
 
 struct _GdkQuartzMonitorClass {
@@ -37,4 +38,3 @@ struct _GdkQuartzMonitorClass {
 };
 
 #endif
-
diff --git a/gdk/quartz/gdkscreen-quartz.c b/gdk/quartz/gdkscreen-quartz.c
index 65f79a5cfb..cd9d6649cb 100644
--- a/gdk/quartz/gdkscreen-quartz.c
+++ b/gdk/quartz/gdkscreen-quartz.c
@@ -63,12 +63,10 @@
 static void  gdk_quartz_screen_dispose          (GObject         *object);
 static void  gdk_quartz_screen_finalize         (GObject         *object);
 static void  gdk_quartz_screen_calculate_layout (GdkQuartzScreen *screen);
+static void  gdk_quartz_screen_reconfigure      (GdkQuartzDisplay *dispplay,
+                                                 GdkQuartzScreen *screen);
 
-static void display_reconfiguration_callback (CGDirectDisplayID            display,
-                                              CGDisplayChangeSummaryFlags  flags,
-                                              void                        *userInfo);
 static const double dpi = 72.0;
-static gint get_mm_from_pixels (NSScreen *screen, int pixels);
 
 G_DEFINE_TYPE (GdkQuartzScreen, gdk_quartz_screen, GDK_TYPE_SCREEN);
 
@@ -86,13 +84,11 @@ gdk_quartz_screen_init (GdkQuartzScreen *quartz_screen)
    * pangocairo-coretext needs to default to that scaling factor.
    */
 
+  g_signal_connect (_gdk_display, "monitors-changed",
+                    G_CALLBACK (gdk_quartz_screen_reconfigure), quartz_screen);
+  /* The first monitors-changed should have fired already. */
   _gdk_screen_set_resolution (screen, dpi);
-
   gdk_quartz_screen_calculate_layout (quartz_screen);
-
-  CGDisplayRegisterReconfigurationCallback (display_reconfiguration_callback,
-                                            screen);
-
   quartz_screen->emit_monitors_changed = FALSE;
 }
 
@@ -107,9 +103,6 @@ gdk_quartz_screen_dispose (GObject *object)
       screen->screen_changed_id = 0;
     }
 
-  CGDisplayRemoveReconfigurationCallback (display_reconfiguration_callback,
-                                          screen);
-
   G_OBJECT_CLASS (gdk_quartz_screen_parent_class)->dispose (object);
 }
 
@@ -127,64 +120,42 @@ gdk_quartz_screen_finalize (GObject *object)
 static void
 gdk_quartz_screen_calculate_layout (GdkQuartzScreen *screen)
 {
-  NSArray *array;
-  int i;
+  int i, monitors;
   int max_x, max_y;
   GdkDisplay *display = gdk_screen_get_display (GDK_SCREEN (screen));
 
-  GDK_QUARTZ_ALLOC_POOL;
-
-  array = [NSScreen screens];
-
   screen->width = 0;
   screen->height = 0;
   screen->min_x = 0;
   screen->min_y = 0;
   max_x = max_y = 0;
+  screen->mm_width = 0;
+  screen->mm_height = 0;
 
   /* We determine the minimum and maximum x and y coordinates
    * covered by the monitors.  From this we can deduce the width
    * and height of the root screen.
    */
-  for (i = 0; i < [array count]; i++)
+  monitors = gdk_display_get_n_monitors (display);
+  for (i = 0; i < monitors; ++i)
     {
-      GdkQuartzMonitor *monitor = gdk_display_get_monitor (display, i);
-      monitor->monitor_num = i;
+      GdkQuartzMonitor *monitor =
+           GDK_QUARTZ_MONITOR (gdk_display_get_monitor (display, i));
+      GdkRectangle rect;
 
-      NSRect rect = [[array objectAtIndex:i] frame];
+      gdk_monitor_get_geometry (GDK_MONITOR (monitor), &rect);
+      screen->min_x = MIN (screen->min_x, rect.x);
+      max_x = MAX (max_x, rect.x + rect.width);
 
-      screen->min_x = MIN (screen->min_x, rect.origin.x);
-      max_x = MAX (max_x, rect.origin.x + rect.size.width);
+      screen->min_y = MIN (screen->min_y, rect.y);
+      max_y = MAX (max_y, rect.y + rect.height);
 
-      screen->min_y = MIN (screen->min_y, rect.origin.y);
-      max_y = MAX (max_y, rect.origin.y + rect.size.height);
+      screen->mm_height += GDK_MONITOR (monitor)->height_mm;
+      screen->mm_width += GDK_MONITOR (monitor)->width_mm;
     }
 
   screen->width = max_x - screen->min_x;
   screen->height = max_y - screen->min_y;
-
-  for (i = 0; i < [array count] ; i++)
-    {
-      NSScreen *nsscreen;
-      NSRect rect;
-      GdkMonitor *monitor;
-
-      monitor = gdk_display_get_monitor (display, i);
-      nsscreen = [array objectAtIndex:i];
-      rect = [nsscreen frame];
-
-      monitor->geometry.x = rect.origin.x - screen->min_x;
-      monitor->geometry.y
-          = screen->height - (rect.origin.y + rect.size.height) + screen->min_y;
-      monitor->geometry.width = rect.size.width;
-      monitor->geometry.height = rect.size.height;
-      if (gdk_quartz_osx_version() >= GDK_OSX_LION)
-        monitor->scale_factor = [(id <ScaleFactor>) nsscreen backingScaleFactor];
-      else
-        monitor->scale_factor = 1;
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
 }
 
 void
@@ -223,7 +194,7 @@ _gdk_quartz_screen_update_window_sizes (GdkScreen *screen)
 }
 
 static void
-process_display_reconfiguration (GdkQuartzScreen *screen)
+gdk_quartz_screen_reconfigure (GdkQuartzDisplay *display, GdkQuartzScreen *screen)
 {
   int width, height;
 
@@ -245,56 +216,6 @@ process_display_reconfiguration (GdkQuartzScreen *screen)
     g_signal_emit_by_name (screen, "size-changed");
 }
 
-static gboolean
-screen_changed_idle (gpointer data)
-{
-  GdkQuartzScreen *screen = data;
-
-  process_display_reconfiguration (data);
-
-  screen->screen_changed_id = 0;
-
-  return FALSE;
-}
-
-static void
-display_reconfiguration_callback (CGDirectDisplayID            display,
-                                  CGDisplayChangeSummaryFlags  flags,
-                                  void                        *userInfo)
-{
-  GdkQuartzScreen *screen = userInfo;
-
-  if (flags & kCGDisplayBeginConfigurationFlag)
-    {
-      /* Ignore the begin configuration signal. */
-      return;
-    }
-  else
-    {
-      /* We save information about the changes, so we can emit
-       * ::monitors-changed when appropriate.  This signal must be
-       * emitted when the number, size of position of one of the
-       * monitors changes.
-       */
-      if (flags & kCGDisplayMovedFlag
-          || flags & kCGDisplayAddFlag
-          || flags & kCGDisplayRemoveFlag
-          || flags & kCGDisplayEnabledFlag
-          || flags & kCGDisplayDisabledFlag)
-        screen->emit_monitors_changed = TRUE;
-
-      /* At this point Cocoa does not know about the new screen data
-       * yet, so we delay our refresh into an idle handler.
-       */
-      if (!screen->screen_changed_id)
-        {
-          screen->screen_changed_id = gdk_threads_add_idle (screen_changed_idle,
-                                                            screen);
-          g_source_set_name_by_id (screen->screen_changed_id, "[gtk+] screen_changed_idle");
-        }
-    }
-}
-
 static GdkDisplay *
 gdk_quartz_screen_get_display (GdkScreen *screen)
 {
@@ -325,13 +246,6 @@ gdk_quartz_screen_get_height (GdkScreen *screen)
   return GDK_QUARTZ_SCREEN (screen)->height;
 }
 
-static gint
-get_mm_from_pixels (NSScreen *screen, int pixels)
-{
-  const float mm_per_inch = 25.4;
-  return (pixels / dpi) * mm_per_inch;
-}
-
 static gchar *
 gdk_quartz_screen_make_display_name (GdkScreen *screen)
 {
@@ -356,34 +270,16 @@ gdk_quartz_screen_is_composited (GdkScreen *screen)
   return TRUE;
 }
 
-static NSScreen *
-get_nsscreen_for_monitor (gint monitor_num)
-{
-  NSArray *array;
-  NSScreen *screen;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  array = [NSScreen screens];
-  screen = [array objectAtIndex:monitor_num];
-
-  GDK_QUARTZ_RELEASE_POOL;
-
-  return screen;
-}
-
 static gint
 gdk_quartz_screen_get_width_mm (GdkScreen *screen)
 {
-  return get_mm_from_pixels (get_nsscreen_for_monitor (0),
-                             GDK_QUARTZ_SCREEN (screen)->width);
+  return GDK_QUARTZ_SCREEN (screen)->mm_width;
 }
 
 static gint
 gdk_quartz_screen_get_height_mm (GdkScreen *screen)
 {
-  return get_mm_from_pixels (get_nsscreen_for_monitor (0),
-                             GDK_QUARTZ_SCREEN (screen)->height);
+  return GDK_QUARTZ_SCREEN (screen)->mm_height;
 }
 
 static void
diff --git a/gdk/quartz/gdkscreen-quartz.h b/gdk/quartz/gdkscreen-quartz.h
index 5a1cfa3398..99c2c4fe88 100644
--- a/gdk/quartz/gdkscreen-quartz.h
+++ b/gdk/quartz/gdkscreen-quartz.h
@@ -35,6 +35,8 @@ struct _GdkQuartzScreen
 
   gint width;
   gint height;
+  gint mm_width;
+  gint mm_height;
 
   guint screen_changed_id;
 


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