4 * Copyright 2001 Sun Microsystems Inc.
6 * Erwann Chenede <erwann.chenede@sun.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
26 #include "gdkscreen.h"
27 #include "gdkscreen-x11.h"
28 #include "gdkdisplay.h"
29 #include "gdkdisplay-x11.h"
33 #include <pango/pangoxft.h>
35 #include <pango/pangox.h>
37 #ifdef HAVE_SOLARIS_XINERAMA
38 #include <X11/extensions/xinerama.h>
40 #ifdef HAVE_XFREE_XINERAMA
41 #include <X11/extensions/Xinerama.h>
44 static void gdk_screen_x11_class_init (GdkScreenX11Class *klass);
45 static void gdk_screen_x11_dispose (GObject *object);
46 static void gdk_screen_x11_finalize (GObject *object);
47 static void init_xinerama_support (GdkScreen *screen);
48 static void init_randr_support (GdkScreen *screen);
52 WINDOW_MANAGER_CHANGED,
56 static gpointer parent_class = NULL;
57 static guint signals[LAST_SIGNAL] = { 0 };
60 _gdk_screen_x11_get_type ()
62 static GType object_type = 0;
66 static const GTypeInfo object_info =
68 sizeof (GdkScreenX11Class),
70 (GBaseFinalizeFunc) gdk_screen_x11_finalize,
71 (GClassInitFunc) gdk_screen_x11_class_init,
72 NULL, /* class_finalize */
73 NULL, /* class_data */
74 sizeof (GdkScreenX11),
76 (GInstanceInitFunc) NULL,
78 object_type = g_type_register_static (GDK_TYPE_SCREEN,
86 gdk_screen_x11_class_init (GdkScreenX11Class *klass)
88 GObjectClass *object_class = G_OBJECT_CLASS (klass);
90 object_class->dispose = gdk_screen_x11_dispose;
91 object_class->finalize = gdk_screen_x11_finalize;
93 parent_class = g_type_class_peek_parent (klass);
95 signals[WINDOW_MANAGER_CHANGED] =
96 g_signal_new ("window_manager_changed",
97 G_OBJECT_CLASS_TYPE (object_class),
99 G_STRUCT_OFFSET (GdkScreenX11Class, window_manager_changed),
101 g_cclosure_marshal_VOID__VOID,
107 * gdk_screen_get_display:
108 * @screen: a #GdkScreen
110 * Gets the display to which the @screen belongs.
112 * Returns: the display to which @screen belongs
115 gdk_screen_get_display (GdkScreen *screen)
117 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
119 return GDK_SCREEN_X11 (screen)->display;
122 * gdk_screen_get_width:
123 * @screen: a #GdkScreen
125 * Gets the width of @screen in pixels
127 * Returns: the width of @screen in pixels.
130 gdk_screen_get_width (GdkScreen *screen)
132 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
134 return WidthOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
138 * gdk_screen_get_height:
139 * @screen: a #GdkScreen
141 * Gets the height of @screen in pixels
143 * Returns: the height of @screen in pixels.
146 gdk_screen_get_height (GdkScreen *screen)
148 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
150 return HeightOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
154 * gdk_screen_get_width_mm:
155 * @screen: a #GdkScreen
157 * Gets the width of @screen in millimeters.
158 * Note that on some X servers this value will not be correct.
160 * Returns: the width of @screen in pixels.
163 gdk_screen_get_width_mm (GdkScreen *screen)
165 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
167 return WidthMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
171 * gdk_screen_get_height_mm:
172 * @screen: a #GdkScreen
174 * Returns the height of @screen in millimeters.
175 * Note that on some X servers this value will not be correct.
177 * Returns: the heigth of @screen in pixels.
180 gdk_screen_get_height_mm (GdkScreen *screen)
182 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
184 return HeightMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
188 * gdk_screen_get_number:
189 * @screen: a #GdkScreen
191 * Gets the index of @screen among the screens in the display
192 * to which it belongs. (See gdk_screen_get_display())
197 gdk_screen_get_number (GdkScreen *screen)
199 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
201 return GDK_SCREEN_X11 (screen)->screen_num;
205 * gdk_screen_get_root_window:
206 * @screen: a #GdkScreen
208 * Gets the root window of @screen.
210 * Returns: the root window
213 gdk_screen_get_root_window (GdkScreen *screen)
215 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
217 return GDK_SCREEN_X11 (screen)->root_window;
221 * gdk_screen_get_default_colormap:
222 * @screen: a #GdkScreen
224 * Gets the default colormap for @screen.
226 * Returns: the default #GdkColormap.
229 gdk_screen_get_default_colormap (GdkScreen *screen)
231 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
233 return GDK_SCREEN_X11 (screen)->default_colormap;
237 * gdk_screen_set_default_colormap:
238 * @screen: a #GdkScreen
239 * @colormap: a #GdkColormap
241 * Sets the default @colormap for @screen.
244 gdk_screen_set_default_colormap (GdkScreen *screen,
245 GdkColormap *colormap)
247 g_return_if_fail (GDK_IS_SCREEN (screen));
248 g_return_if_fail (GDK_IS_COLORMAP (colormap));
250 GDK_SCREEN_X11 (screen)->default_colormap = colormap;
254 gdk_screen_x11_dispose (GObject *object)
256 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
258 _gdk_x11_events_uninit_screen (GDK_SCREEN (object));
260 screen_x11->root_window = NULL;
262 screen_x11->xdisplay = NULL;
263 screen_x11->xscreen = NULL;
264 screen_x11->screen_num = -1;
265 screen_x11->xroot_window = None;
266 screen_x11->wmspec_check_window = None;
268 G_OBJECT_CLASS (parent_class)->dispose (object);
272 gdk_screen_x11_finalize (GObject *object)
274 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
276 g_object_unref (screen_x11->root_window);
278 /* Visual Part (Need to implement finalize for Visuals for a clean
280 /* for (i=0;i<screen_x11->nvisuals;i++)
281 g_object_unref (screen_x11->visuals[i]);*/
282 g_free (screen_x11->visuals);
283 g_hash_table_destroy (screen_x11->visual_hash);
285 g_free (screen_x11->window_manager_name);
287 g_hash_table_destroy (screen_x11->colormap_hash);
289 g_free (screen_x11->xsettings_client);
290 g_free (screen_x11->monitors);
292 G_OBJECT_CLASS (parent_class)->finalize (object);
296 * gdk_screen_get_n_monitors:
297 * @screen : a #GdkScreen.
299 * Returns the number of monitors being part of the virtual screen
301 * Returns: number of monitors part of the virtual screen or
302 * 0 if @screen is not in virtual screen mode.
305 gdk_screen_get_n_monitors (GdkScreen *screen)
307 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
309 return GDK_SCREEN_X11 (screen)->num_monitors;
313 * gdk_screen_get_monitor_geometry:
314 * @screen : a #GdkScreen.
315 * @monitor_num: the monitor number.
316 * @dest : a #GdkRectangle to be filled with the monitor geometry
318 * Retrieves the #GdkRectangle representing the size and start
319 * coordinates of the individual monitor within the the entire virtual
322 * Note that the virtual screen coordinates can be retrieved via
323 * gdk_screen_get_width() and gdk_screen_get_height().
327 gdk_screen_get_monitor_geometry (GdkScreen *screen,
331 g_return_if_fail (GDK_IS_SCREEN (screen));
332 g_return_if_fail (monitor_num < GDK_SCREEN_X11 (screen)->num_monitors);
333 g_return_if_fail (monitor_num >= 0);
335 *dest = GDK_SCREEN_X11 (screen)->monitors[monitor_num];
339 * gdk_x11_screen_get_xscreen:
340 * @screen: a #GdkScreen.
341 * @returns: an Xlib <type>Screen*</type>
343 * Returns the screen of a #GdkScreen.
346 gdk_x11_screen_get_xscreen (GdkScreen *screen)
348 return GDK_SCREEN_X11 (screen)->xscreen;
353 * gdk_x11_screen_get_screen_number:
354 * @screen: a #GdkScreen.
355 * @returns: the position of @screen among the screens of
358 * Returns the index of a #GdkScreen.
361 gdk_x11_screen_get_screen_number (GdkScreen *screen)
363 return GDK_SCREEN_X11 (screen)->screen_num;
367 _gdk_x11_screen_new (GdkDisplay *display,
371 GdkScreenX11 *screen_x11;
372 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
374 screen = g_object_new (GDK_TYPE_SCREEN_X11, NULL);
376 screen_x11 = GDK_SCREEN_X11 (screen);
377 screen_x11->display = display;
378 screen_x11->xdisplay = display_x11->xdisplay;
379 screen_x11->xscreen = ScreenOfDisplay (display_x11->xdisplay, screen_number);
380 screen_x11->screen_num = screen_number;
381 screen_x11->xroot_window = RootWindow (display_x11->xdisplay,screen_number);
382 screen_x11->wmspec_check_window = None;
383 /* we want this to be always non-null */
384 screen_x11->window_manager_name = g_strdup ("unknown");
386 init_xinerama_support (screen);
387 init_randr_support (screen);
389 _gdk_visual_init (screen);
390 _gdk_windowing_window_init (screen);
397 check_solaris_xinerama (GdkScreen *screen)
399 #ifdef HAVE_SOLARIS_XINERAMA
401 if (XineramaGetState (GDK_SCREEN_XDISPLAY (screen),
402 gdk_screen_get_number (screen)))
404 XRectangle monitors[MAXFRAMEBUFFERS];
405 unsigned char hints[16];
407 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
409 result = XineramaGetInfo (GDK_SCREEN_XDISPLAY (screen),
410 gdk_screen_get_number (screen),
412 &screen_x11->num_monitors);
413 /* Yes I know it should be Success but the current implementation
414 returns the num of monitor*/
417 /* FIXME: We need to trap errors, since XINERAMA isn't always XINERAMA.
419 g_error ("error while retrieving Xinerama information");
424 screen_x11->monitors = g_new0 (GdkRectangle, screen_x11->num_monitors);
426 for (i = 0; i < screen_x11->num_monitors; i++)
428 screen_x11->monitors[i].x = monitors[i].x;
429 screen_x11->monitors[i].y = monitors[i].y;
430 screen_x11->monitors[i].width = monitors[i].width;
431 screen_x11->monitors[i].height = monitors[i].height;
437 #endif /* HAVE_SOLARIS_XINERAMA */
443 check_xfree_xinerama (GdkScreen *screen)
445 #ifdef HAVE_XFREE_XINERAMA
446 if (XineramaIsActive (GDK_SCREEN_XDISPLAY (screen)))
448 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
449 XineramaScreenInfo *monitors = XineramaQueryScreens (GDK_SCREEN_XDISPLAY (screen),
450 &screen_x11->num_monitors);
451 if (screen_x11->num_monitors <= 0)
453 /* FIXME: We need to trap errors, since XINERAMA isn't always XINERAMA.
454 * I don't think the num_monitors <= 0 check has any validity.
456 g_error ("error while retrieving Xinerama information");
461 screen_x11->monitors = g_new0 (GdkRectangle, screen_x11->num_monitors);
463 for (i = 0; i < screen_x11->num_monitors; i++)
465 screen_x11->monitors[i].x = monitors[i].x_org;
466 screen_x11->monitors[i].y = monitors[i].y_org;
467 screen_x11->monitors[i].width = monitors[i].width;
468 screen_x11->monitors[i].height = monitors[i].height;
476 #endif /* HAVE_XFREE_XINERAMA */
480 #endif /* HAVE_XINERAMA */
483 init_xinerama_support (GdkScreen * screen)
485 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
487 int opcode, firstevent, firsterror;
490 if (screen_x11->monitors)
491 g_free (screen_x11->monitors);
494 if (XQueryExtension (GDK_SCREEN_XDISPLAY (screen), "XINERAMA",
495 &opcode, &firstevent, &firsterror))
497 if (check_solaris_xinerama (screen) ||
498 check_xfree_xinerama (screen))
501 #endif /* HAVE_XINERAMA */
505 screen_x11->num_monitors = 1;
506 screen_x11->monitors = g_new0 (GdkRectangle, 1);
507 screen_x11->monitors[0].x = 0;
508 screen_x11->monitors[0].y = 0;
509 screen_x11->monitors[0].width = WidthOfScreen (screen_x11->xscreen);
510 screen_x11->monitors[0].height = HeightOfScreen (screen_x11->xscreen);
514 init_randr_support (GdkScreen * screen)
516 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
518 XSelectInput (GDK_SCREEN_XDISPLAY (screen),
519 screen_x11->xroot_window,
520 StructureNotifyMask);
524 _gdk_x11_screen_size_changed (GdkScreen *screen,
528 if (!XRRUpdateConfiguration (event))
531 if (event->type == ConfigureNotify)
533 XConfigureEvent *rcevent = (XConfigureEvent *) event;
534 Screen *xscreen = gdk_x11_screen_get_xscreen (screen);
536 xscreen->width = rcevent->width;
537 xscreen->height = rcevent->height;
543 init_xinerama_support (screen);
544 g_signal_emit_by_name (G_OBJECT (screen), "size_changed");
548 _gdk_x11_screen_window_manager_changed (GdkScreen *screen)
550 g_signal_emit (G_OBJECT (screen),
551 signals[WINDOW_MANAGER_CHANGED], 0);
555 * gdk_screen_make_display_name:
556 * @screen: a #GdkScreen
558 * Determines the name to pass to gdk_display_open() to get
559 * a #GdkDisplay with this screen as the default screen.
561 * Return value: a newly allocated string, free with g_free()
564 gdk_screen_make_display_name (GdkScreen *screen)
567 const gchar *old_display;
570 old_display = gdk_display_get_name (gdk_screen_get_display (screen));
572 str = g_string_new (old_display);
574 p = strrchr (str->str, '.');
575 if (p && p > strchr (str->str, ':'))
576 g_string_truncate (str, p - str->str);
578 g_string_append_printf (str, ".%d", gdk_screen_get_number (screen));
580 return g_string_free (str, FALSE);