3 * Copyright (C) 2005 Imendio AB
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
23 #include "gdkprivate-quartz.h"
25 /* FIXME: If we want to do it properly, this should be stored
26 * in a proper GdkScreen subclass.
28 static GdkColormap *default_colormap = NULL;
29 static int n_screens = 0;
30 static GdkRectangle *screen_rects = NULL;
32 static guint screen_changed_id = 0;
36 screen_rects_init (void)
42 GDK_QUARTZ_ALLOC_POOL;
44 array = [NSScreen screens];
46 n_screens = [array count];
47 screen_rects = g_new0 (GdkRectangle, n_screens);
49 /* FIXME: as stated above the get_width() and get_height() functions
50 * in this file, we only support horizontal screen layouts for now.
53 /* Find the monitor with the largest height. All monitors should be
54 * offset to this one in the GDK screen space instead of offset to
55 * the screen with the menu bar.
57 largest_rect = [[array objectAtIndex:0] frame];
58 for (i = 1; i < [array count]; i++)
60 NSRect rect = [[array objectAtIndex:i] frame];
62 if (rect.size.height > largest_rect.size.height)
63 largest_rect = [[array objectAtIndex:i] frame];
66 for (i = 0; i < n_screens; i++)
71 nsscreen = [array objectAtIndex:i];
72 rect = [nsscreen frame];
74 screen_rects[i].x = rect.origin.x;
75 screen_rects[i].width = rect.size.width;
76 screen_rects[i].height = rect.size.height;
78 if (largest_rect.size.height - rect.size.height == 0)
79 screen_rects[i].y = 0;
81 screen_rects[i].y = largest_rect.size.height - rect.size.height + largest_rect.origin.y;
84 GDK_QUARTZ_RELEASE_POOL;
88 screen_rects_free (void)
92 g_free (screen_rects);
98 process_display_reconfiguration (void)
100 screen_rects_free ();
101 screen_rects_init ();
103 /* FIXME: We should only emit this when the size of screen really
104 * has changed. We need to start bookkeeping width, height once
105 * we have a proper GdkScreen subclass.
107 g_signal_emit_by_name (_gdk_screen, "size-changed");
111 screen_changed_idle (gpointer data)
113 process_display_reconfiguration ();
115 screen_changed_id = 0;
121 screen_changed (CGDirectDisplayID display,
122 CGDisplayChangeSummaryFlags flags,
125 if (flags & kCGDisplayBeginConfigurationFlag)
127 /* Ignore the begin configuration signal. */
129 /* FIXME: We can most probably use this flag to properly
130 * emit monitors-changed.
136 /* At this point Cocoa does not know about the new screen data
137 * yet, so we delay our refresh into an idle handler.
140 if (!screen_changed_id)
141 screen_changed_id = gdk_threads_add_idle (screen_changed_idle, NULL);
146 _gdk_quartz_screen_init (void)
148 gdk_screen_set_default_colormap (_gdk_screen,
149 gdk_screen_get_system_colormap (_gdk_screen));
151 screen_rects_init ();
153 CGDisplayRegisterReconfigurationCallback (screen_changed,
158 gdk_screen_get_display (GdkScreen *screen)
160 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
167 gdk_screen_get_root_window (GdkScreen *screen)
169 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
175 gdk_screen_get_number (GdkScreen *screen)
177 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
183 _gdk_windowing_substitute_screen_number (const gchar *display_name,
186 if (screen_number != 0)
189 return g_strdup (display_name);
193 gdk_screen_get_default_colormap (GdkScreen *screen)
195 return default_colormap;
199 gdk_screen_set_default_colormap (GdkScreen *screen,
200 GdkColormap *colormap)
202 GdkColormap *old_colormap;
204 g_return_if_fail (GDK_IS_SCREEN (screen));
205 g_return_if_fail (GDK_IS_COLORMAP (colormap));
207 old_colormap = default_colormap;
209 default_colormap = g_object_ref (colormap);
212 g_object_unref (old_colormap);
215 /* FIXME: note on the get_width() and the get_height() methods. For
216 * now we only support screen layouts where the screens are laid out
217 * horizontally. Mac OS X also supports laying out the screens vertically
218 * and the screens having "non-standard" offsets from eachother. In the
219 * future we need a much more sophiscated algorithm to translate these
220 * layouts to GDK coordinate space and GDK screen layout.
223 gdk_screen_get_width (GdkScreen *screen)
229 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
231 GDK_QUARTZ_ALLOC_POOL;
232 array = [NSScreen screens];
235 for (i = 0; i < [array count]; i++)
237 NSRect rect = [[array objectAtIndex:i] frame];
238 width += rect.size.width;
241 GDK_QUARTZ_RELEASE_POOL;
247 gdk_screen_get_height (GdkScreen *screen)
253 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
255 GDK_QUARTZ_ALLOC_POOL;
256 array = [NSScreen screens];
259 for (i = 0; i < [array count]; i++)
261 NSRect rect = [[array objectAtIndex:i] frame];
262 height = MAX (height, rect.size.height);
265 GDK_QUARTZ_RELEASE_POOL;
271 get_mm_from_pixels (NSScreen *screen, int pixels)
273 /* userSpaceScaleFactor is in "pixels per point",
274 * 72 is the number of points per inch,
275 * and 25.4 is the number of millimeters per inch.
277 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_3
278 float dpi = [screen userSpaceScaleFactor] * 72.0;
280 float dpi = 96.0 / 72.0;
283 return (pixels / dpi) * 25.4;
287 gdk_screen_get_width_mm (GdkScreen *screen)
293 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
295 GDK_QUARTZ_ALLOC_POOL;
296 array = [NSScreen screens];
299 for (i = 0; i < [array count]; i++)
301 NSScreen *screen = [array objectAtIndex:i];
302 NSRect rect = [screen frame];
303 width += get_mm_from_pixels (screen, rect.size.width);
306 GDK_QUARTZ_RELEASE_POOL;
312 gdk_screen_get_height_mm (GdkScreen *screen)
318 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
320 GDK_QUARTZ_ALLOC_POOL;
321 array = [NSScreen screens];
324 for (i = 0; i < [array count]; i++)
326 NSScreen *screen = [array objectAtIndex:i];
327 NSRect rect = [screen frame];
328 gint h = get_mm_from_pixels (screen, rect.size.height);
329 height = MAX (height, h);
332 GDK_QUARTZ_RELEASE_POOL;
338 gdk_screen_get_n_monitors (GdkScreen *screen)
340 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
346 get_nsscreen_for_monitor (gint monitor_num)
351 GDK_QUARTZ_ALLOC_POOL;
353 array = [NSScreen screens];
354 screen = [array objectAtIndex:monitor_num];
356 GDK_QUARTZ_RELEASE_POOL;
362 gdk_screen_get_monitor_width_mm (GdkScreen *screen,
365 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
366 g_return_val_if_fail (monitor_num < gdk_screen_get_n_monitors (screen), 0);
367 g_return_val_if_fail (monitor_num >= 0, 0);
369 return get_mm_from_pixels (get_nsscreen_for_monitor (monitor_num),
370 screen_rects[monitor_num].width);
374 gdk_screen_get_monitor_height_mm (GdkScreen *screen,
377 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
378 g_return_val_if_fail (monitor_num < gdk_screen_get_n_monitors (screen), 0);
379 g_return_val_if_fail (monitor_num >= 0, 0);
381 return get_mm_from_pixels (get_nsscreen_for_monitor (monitor_num),
382 screen_rects[monitor_num].height);
386 gdk_screen_get_monitor_plug_name (GdkScreen *screen,
389 /* FIXME: Is there some useful name we could use here? */
394 gdk_screen_get_monitor_geometry (GdkScreen *screen,
398 g_return_if_fail (GDK_IS_SCREEN (screen));
399 g_return_if_fail (monitor_num < gdk_screen_get_n_monitors (screen));
400 g_return_if_fail (monitor_num >= 0);
402 *dest = screen_rects[monitor_num];
406 gdk_screen_make_display_name (GdkScreen *screen)
408 return g_strdup (gdk_display_get_name (_gdk_display));
412 gdk_screen_get_active_window (GdkScreen *screen)
414 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
420 gdk_screen_get_window_stack (GdkScreen *screen)
422 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
428 gdk_screen_is_composited (GdkScreen *screen)
430 g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);