Implement the GdkMonitor/GdkDisplay API.

Moving the initialization of the GdkQuartzMonitors to GdkQuartzDisplay from
the now-obsolete GdkQuartzScreen. Use QuartzDisplayServices for
monitor enumeration and to populate the GdkMonitor properties. This is
better aligned with acting on the Quartz Services callbacks for monitor
changes and with Cairo which also uses CoreGraphics for drawing.
This commit is contained in:
John Ralls 2018-12-03 21:22:19 +09:00
parent cf279a14fa
commit 28b8bbda45
4 changed files with 72 additions and 27 deletions

View File

@ -20,6 +20,7 @@
#include <gdk/gdk.h>
#include <gdk/gdkdisplayprivate.h>
#include <gdk/gdkmonitorprivate.h>
#include "gdkprivate-quartz.h"
#include "gdkquartzscreen.h"
@ -189,23 +190,50 @@ gdk_quartz_display_notify_startup_complete (GdkDisplay *display,
/* FIXME: Implement? */
}
/* The display monitor list comprises all of the CGDisplays connected
to the system, some of which may not be drawable either because
they're asleep or are mirroring another monitor. The NSScreens
array contains only the monitors that are currently drawable and we
use the index of the screens array placing GdkNSViews, so we'll use
the same for determining the number of monitors and indexing them.
*/
static int
gdk_quartz_display_get_n_monitors (GdkDisplay *display)
{
GdkQuartzDisplay *quartz_display = GDK_QUARTZ_DISPLAY (display);
int n;
return quartz_display->monitors->len;
GDK_QUARTZ_ALLOC_POOL;
n = [[NSScreen screens] count];
GDK_QUARTZ_RELEASE_POOL;
return n;
}
static GdkMonitor *
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;
if (0 <= monitor_num || monitor_num < quartz_display->monitors->len)
return (GdkMonitor *)quartz_display->monitors->pdata[monitor_num];
GDK_QUARTZ_ALLOC_POOL;
screens = [NSScreen screens];
if (monitor_num >= 0 && monitor_num < [screens count])
{
screen = [screens objectAtIndex:monitor_num];
id = [[[screen deviceDescription] valueForKey: @"NSScreenNumber"] unsignedIntValue];
}
GDK_QUARTZ_RELEASE_POOL;
if (id)
return g_hash_table_lookup (quartz_display->monitors, GINT_TO_POINTER (id));
return NULL;
}
@ -214,8 +242,10 @@ static GdkMonitor *
gdk_quartz_display_get_primary_monitor (GdkDisplay *display)
{
GdkQuartzDisplay *quartz_display = GDK_QUARTZ_DISPLAY (display);
CGDirectDisplayID primary_id = CGMainDisplayID ();
return quartz_display->monitors->pdata[0];
return g_hash_table_lookup (quartz_display->monitors,
GINT_TO_POINTER (primary_id));
}
G_DEFINE_TYPE (GdkQuartzDisplay, gdk_quartz_display, GDK_TYPE_DISPLAY)
@ -223,11 +253,40 @@ G_DEFINE_TYPE (GdkQuartzDisplay, gdk_quartz_display, GDK_TYPE_DISPLAY)
static void
gdk_quartz_display_init (GdkQuartzDisplay *display)
{
GDK_QUARTZ_ALLOC_POOL;
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);
displays = g_new0 (CGDirectDisplayID, max_displays);
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,
"display", display, NULL);
GdkMonitor *monitor = GDK_MONITOR (quartz_monitor);
display->monitors = g_ptr_array_new_with_free_func (g_object_unref);
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;
GDK_QUARTZ_RELEASE_POOL;
g_hash_table_insert (display->monitors, GINT_TO_POINTER (displays[disp]),
monitor);
CGDisplayModeRelease (mode);
}
}
static void
@ -235,7 +294,7 @@ gdk_quartz_display_dispose (GObject *object)
{
GdkQuartzDisplay *display_quartz = GDK_QUARTZ_DISPLAY (object);
g_ptr_array_free (display_quartz->monitors, TRUE);
g_hash_table_destroy (display_quartz->monitors);
G_OBJECT_CLASS (gdk_quartz_display_parent_class)->dispose (object);
}

View File

@ -32,7 +32,7 @@ G_BEGIN_DECLS
struct _GdkQuartzDisplay
{
GdkDisplay parent_instance;
GPtrArray *monitors;
GHashTable *monitors;
};
struct _GdkQuartzDisplayClass

View File

@ -29,7 +29,6 @@
struct _GdkQuartzMonitor
{
GdkMonitor parent;
gint monitor_num;
};

View File

@ -131,10 +131,6 @@ gdk_quartz_screen_calculate_layout (GdkQuartzScreen *screen)
int i;
int max_x, max_y;
GdkDisplay *display = gdk_screen_get_display (GDK_SCREEN (screen));
GdkQuartzDisplay *display_quartz = GDK_QUARTZ_DISPLAY (display);
g_ptr_array_free (display_quartz->monitors, TRUE);
display_quartz->monitors = g_ptr_array_new_with_free_func (g_object_unref);
GDK_QUARTZ_ALLOC_POOL;
@ -152,10 +148,7 @@ gdk_quartz_screen_calculate_layout (GdkQuartzScreen *screen)
*/
for (i = 0; i < [array count]; i++)
{
GdkQuartzMonitor *monitor = g_object_new (GDK_TYPE_QUARTZ_MONITOR,
"display", display,
NULL);
g_ptr_array_add (display_quartz->monitors, monitor);
GdkQuartzMonitor *monitor = gdk_display_get_monitor (display, i);
monitor->monitor_num = i;
NSRect rect = [[array objectAtIndex:i] frame];
@ -176,7 +169,7 @@ gdk_quartz_screen_calculate_layout (GdkQuartzScreen *screen)
NSRect rect;
GdkMonitor *monitor;
monitor = GDK_MONITOR(display_quartz->monitors->pdata[i]);
monitor = gdk_display_get_monitor (display, i);
nsscreen = [array objectAtIndex:i];
rect = [nsscreen frame];
@ -189,12 +182,6 @@ gdk_quartz_screen_calculate_layout (GdkQuartzScreen *screen)
monitor->scale_factor = [(id <ScaleFactor>) nsscreen backingScaleFactor];
else
monitor->scale_factor = 1;
monitor->width_mm = get_mm_from_pixels(nsscreen, monitor->geometry.width);
monitor->height_mm = get_mm_from_pixels(nsscreen, monitor->geometry.height);
monitor->refresh_rate = 0; // unknown
monitor->manufacturer = NULL; // unknown
monitor->model = NULL; // unknown
monitor->subpixel_layout = GDK_SUBPIXEL_LAYOUT_UNKNOWN; // unknown
}
GDK_QUARTZ_RELEASE_POOL;