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. */ +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 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 ) 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;