forked from AuroraMiddleware/gtk
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.
This commit is contained in:
parent
9773b1951c
commit
941f3c3887
@ -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.
|
||||
*/
|
||||
|
||||
int
|
||||
get_active_displays (CGDirectDisplayID **screens)
|
||||
{
|
||||
unsigned int displays = 0;
|
||||
|
||||
CGGetActiveDisplayList (0, NULL, &displays);
|
||||
if (screens)
|
||||
{
|
||||
*screens = g_new0 (CGDirectDisplayID, displays);
|
||||
CGGetActiveDisplayList (displays, *screens, &displays);
|
||||
}
|
||||
|
||||
return displays;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int n;
|
||||
|
||||
GDK_QUARTZ_ALLOC_POOL;
|
||||
|
||||
n = [[NSScreen screens] count];
|
||||
|
||||
GDK_QUARTZ_RELEASE_POOL;
|
||||
|
||||
return n;
|
||||
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;
|
||||
CGDirectDisplayID *screens = NULL;
|
||||
|
||||
GDK_QUARTZ_ALLOC_POOL;
|
||||
int count = get_active_displays (&screens);
|
||||
|
||||
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));
|
||||
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
|
||||
|
@ -30,6 +30,7 @@ struct _GdkQuartzMonitor
|
||||
{
|
||||
GdkMonitor parent;
|
||||
gint monitor_num;
|
||||
CGDirectDisplayID id;
|
||||
};
|
||||
|
||||
struct _GdkQuartzMonitorClass {
|
||||
@ -37,4 +38,3 @@ struct _GdkQuartzMonitorClass {
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -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
|
||||
|
@ -35,6 +35,8 @@ struct _GdkQuartzScreen
|
||||
|
||||
gint width;
|
||||
gint height;
|
||||
gint mm_width;
|
||||
gint mm_height;
|
||||
|
||||
guint screen_changed_id;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user