[gtk/wip/chergert/quartz4u] macos: load monitor information



commit 54d0da41438c893176c2182061fb668bca732e83
Author: Christian Hergert <chergert redhat com>
Date:   Tue May 5 12:54:17 2020 -0700

    macos: load monitor information

 gdk/macos/gdkmacosdisplay.c         |  39 ++++++---
 gdk/macos/gdkmacosmonitor-private.h |   1 +
 gdk/macos/gdkmacosmonitor.c         | 167 ++++++++++++++++++++++++++++++++++++
 3 files changed, 194 insertions(+), 13 deletions(-)
---
diff --git a/gdk/macos/gdkmacosdisplay.c b/gdk/macos/gdkmacosdisplay.c
index bfc00190e7..5b504404f9 100644
--- a/gdk/macos/gdkmacosdisplay.c
+++ b/gdk/macos/gdkmacosdisplay.c
@@ -188,41 +188,54 @@ gdk_macos_display_remove_monitor (GdkMacosDisplay *self,
 }
 
 static void
-gdk_macos_display_load_monitors (GdkMacosDisplay *self)
+gdk_macos_display_update_bounds (GdkMacosDisplay *self)
 {
   GDK_BEGIN_MACOS_ALLOC_POOL;
 
-  NSArray *screens;
   int max_x = 0;
   int max_y = 0;
 
   g_assert (GDK_IS_MACOS_DISPLAY (self));
 
-  screens = [NSScreen screens];
+  self->min_x = 0;
+  self->min_y = 0;
 
-  for (id obj in screens)
+  for (id obj in [NSScreen screens])
     {
-      CGDirectDisplayID screen_id;
-      GdkMacosMonitor *monitor;
-      NSRect geom;
+      NSRect geom = [(NSScreen *)obj frame];
 
-      geom = [obj frame];
       self->min_x = MIN (self->min_x, geom.origin.x);
       self->min_y = MIN (self->min_y, geom.origin.y);
       max_x = MAX (max_x, geom.origin.x + geom.size.width);
       max_y = MAX (max_y, geom.origin.y + geom.size.height);
+    }
+
+  self->width = max_x - self->min_x;
+  self->height = max_y - self->min_y;
+
+  GDK_END_MACOS_ALLOC_POOL;
+}
+
+static void
+gdk_macos_display_load_monitors (GdkMacosDisplay *self)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  gdk_macos_display_update_bounds (self);
+
+  for (id obj in [NSScreen screens])
+    {
+      CGDirectDisplayID screen_id;
+      GdkMacosMonitor *monitor;
 
       screen_id = [[[obj deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
       monitor = _gdk_macos_monitor_new (self, screen_id);
-
       gdk_macos_display_add_monitor (self, monitor);
-
       g_object_unref (monitor);
     }
 
-  self->width = max_x - self->min_x;
-  self->height = max_y - self->min_y;
-
   GDK_END_MACOS_ALLOC_POOL;
 }
 
diff --git a/gdk/macos/gdkmacosmonitor-private.h b/gdk/macos/gdkmacosmonitor-private.h
index 8e65e73c3d..3c6f058bd0 100644
--- a/gdk/macos/gdkmacosmonitor-private.h
+++ b/gdk/macos/gdkmacosmonitor-private.h
@@ -32,6 +32,7 @@ G_BEGIN_DECLS
 GdkMacosMonitor   *_gdk_macos_monitor_new           (GdkMacosDisplay   *display,
                                                      CGDirectDisplayID  screen_id);
 CGDirectDisplayID  _gdk_macos_monitor_get_screen_id (GdkMacosMonitor   *self);
+gboolean           _gdk_macos_monitor_reconfigure   (GdkMacosMonitor   *self);
 
 G_END_DECLS
 
diff --git a/gdk/macos/gdkmacosmonitor.c b/gdk/macos/gdkmacosmonitor.c
index 755f16d831..80cd56d484 100644
--- a/gdk/macos/gdkmacosmonitor.c
+++ b/gdk/macos/gdkmacosmonitor.c
@@ -20,6 +20,7 @@
 #include "config.h"
 
 #include <gdk/gdk.h>
+#include <math.h>
 
 #include "gdkmacosdisplay-private.h"
 #include "gdkmacosmonitor-private.h"
@@ -29,6 +30,7 @@ struct _GdkMacosMonitor
 {
   GdkMonitor        parent_instance;
   CGDirectDisplayID screen_id;
+  guint             has_opengl : 1;
 };
 
 struct _GdkMacosMonitorClass
@@ -94,6 +96,168 @@ gdk_macos_monitor_init (GdkMacosMonitor *self)
 {
 }
 
+static GdkSubpixelLayout
+GetSubpixelLayout (CGDirectDisplayID screen_id)
+{
+#if 0
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  GdkSubpixelLayout subpixel_layout = GDK_SUBPIXEL_LAYOUT_UNKNOWN;
+  io_service_t iosvc;
+  NSDictionary *dict;
+  guint layout;
+  gboolean rotation;
+
+  rotation = CGDisplayRotation (screen_id);
+  iosvc = CGDisplayIOServicePort (screen_id);
+  dict = (NSDictionary *)IODisplayCreateInfoDictionary (iosvc, kIODisplayOnlyPreferredName);
+  layout = [[dict objectForKey:@kDisplaySubPixelLayout] unsignedIntValue];
+
+  switch (layout)
+    {
+    case kDisplaySubPixelLayoutRGB:
+      if (rotation == 0.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_HORIZONTAL_RGB;
+      else if (rotation == 90.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_VERTICAL_RGB;
+      else if (rotation == 180.0 || rotation == -180.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_HORIZONTAL_BGR;
+      else if (rotation == -90.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_VERTICAL_BGR;
+      break;
+
+    case kDisplaySubPixelLayoutBGR:
+      if (rotation == 0.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_HORIZONTAL_BGR;
+      else if (rotation == 90.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_VERTICAL_BGR;
+      else if (rotation == 180.0 || rotation == -180.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_HORIZONTAL_RGB;
+      else if (rotation == -90.0 || rotation == 270.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_VERTICAL_RGB;
+      break;
+
+    default:
+      break;
+    }
+
+  GDK_END_MACOS_ALLOC_POOL;
+
+  return subpixel_layout;
+#endif
+
+  return GDK_SUBPIXEL_LAYOUT_UNKNOWN;
+}
+
+static char *
+GetLocalizedName (CGDirectDisplayID screen_id)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  char *name = NULL;
+
+  for (id obj in [NSScreen screens])
+    {
+      CGDirectDisplayID this_id = [[[obj deviceDescription] objectForKey:@"NSScreenNumber"] 
unsignedIntValue];
+
+      if (screen_id == this_id)
+        {
+          NSString *str = [(NSScreen *)obj localizedName];
+          name = g_strdup ([str UTF8String]);
+          break;
+        }
+    }
+
+  GDK_END_MACOS_ALLOC_POOL;
+
+  return g_steal_pointer (&name);
+}
+
+static gchar *
+GetConnectorName (CGDirectDisplayID screen_id)
+{
+  guint unit = CGDisplayUnitNumber (screen_id);
+  return g_strdup_printf ("unit-%u", unit);
+}
+
+gboolean
+_gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
+{
+  GdkSubpixelLayout subpixel_layout;
+  CGDisplayModeRef mode;
+  GdkMacosDisplay *display;
+  GdkRectangle geom;
+  gboolean has_opengl;
+  CGSize size;
+  CGRect bounds;
+  CGRect main_bounds;
+  size_t width;
+  size_t pixel_width;
+  gchar *connector;
+  gchar *name;
+  int refresh_rate;
+  int scale_factor = 1;
+  int width_mm;
+  int height_mm;
+
+  g_return_val_if_fail (GDK_IS_MACOS_MONITOR (self), FALSE);
+
+  if (!(mode = CGDisplayCopyDisplayMode (self->screen_id)))
+    return FALSE;
+
+  size = CGDisplayScreenSize (self->screen_id);
+  bounds = CGDisplayBounds (self->screen_id);
+  main_bounds = CGDisplayBounds (CGMainDisplayID ());
+  width = CGDisplayModeGetWidth (mode);
+  pixel_width = CGDisplayModeGetPixelWidth (mode);
+  refresh_rate = CGDisplayModeGetRefreshRate (mode);
+  has_opengl = CGDisplayUsesOpenGLAcceleration (self->screen_id);
+  subpixel_layout = GetSubpixelLayout (self->screen_id);
+  name = GetLocalizedName (self->screen_id);
+  connector = GetConnectorName (self->screen_id);
+
+  if (width != 0 && pixel_width != 0)
+    scale_factor = MAX (1, pixel_width / width);
+
+  width_mm = size.width;
+  height_mm = size.height;
+
+  CGDisplayModeRelease (mode);
+
+  /* This requires that the display bounds have been
+   * updated before the monitor is reconfigured.
+   */
+  display = GDK_MACOS_DISPLAY (GDK_MONITOR (self)->display);
+  _gdk_macos_display_from_display_coords (display,
+                                          bounds.origin.x,
+                                          bounds.origin.y,
+                                          &geom.x, &geom.y);
+  geom.width = bounds.size.width;
+  geom.height = bounds.size.height;
+
+  gdk_monitor_set_connector (GDK_MONITOR (self), connector);
+  gdk_monitor_set_model (GDK_MONITOR (self), name);
+  gdk_monitor_set_position (GDK_MONITOR (self), geom.x, geom.y);
+  gdk_monitor_set_size (GDK_MONITOR (self), geom.width, geom.height);
+  gdk_monitor_set_physical_size (GDK_MONITOR (self), width_mm, height_mm);
+  gdk_monitor_set_scale_factor (GDK_MONITOR (self), scale_factor);
+  gdk_monitor_set_refresh_rate (GDK_MONITOR (self), refresh_rate);
+  gdk_monitor_set_subpixel_layout (GDK_MONITOR (self), GDK_SUBPIXEL_LAYOUT_UNKNOWN);
+
+  /* We might be able to use this at some point to change which GSK renderer
+   * we use for surfaces on this monitor.  For example, it might be better
+   * to use cairo if we cannot use OpenGL (or it would be software) anyway.
+   * Presumably that is more common in cases where macOS is running under
+   * an emulator such as QEMU.
+   */
+  self->has_opengl = !!has_opengl;
+
+  g_free (name);
+  g_free (connector);
+
+  return TRUE;
+}
+
 GdkMacosMonitor *
 _gdk_macos_monitor_new (GdkMacosDisplay   *display,
                         CGDirectDisplayID  screen_id)
@@ -105,8 +269,11 @@ _gdk_macos_monitor_new (GdkMacosDisplay   *display,
   self = g_object_new (GDK_TYPE_MACOS_MONITOR,
                        "display", display,
                        NULL);
+
   self->screen_id = screen_id;
 
+  _gdk_macos_monitor_reconfigure (self);
+
   return g_steal_pointer (&self);
 }
 


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