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 GdkColormap *old_colormap;
249 g_return_if_fail (GDK_IS_SCREEN (screen));
250 g_return_if_fail (GDK_IS_COLORMAP (colormap));
252 old_colormap = GDK_SCREEN_X11 (screen)->default_colormap;
254 GDK_SCREEN_X11 (screen)->default_colormap = g_object_ref (colormap);
257 g_object_unref (old_colormap);
261 gdk_screen_x11_dispose (GObject *object)
263 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
265 _gdk_x11_events_uninit_screen (GDK_SCREEN (object));
267 g_object_unref (screen_x11->default_colormap);
268 screen_x11->default_colormap = NULL;
270 screen_x11->root_window = NULL;
272 screen_x11->xdisplay = NULL;
273 screen_x11->xscreen = NULL;
274 screen_x11->screen_num = -1;
275 screen_x11->xroot_window = None;
276 screen_x11->wmspec_check_window = None;
278 G_OBJECT_CLASS (parent_class)->dispose (object);
282 gdk_screen_x11_finalize (GObject *object)
284 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
286 g_object_unref (screen_x11->root_window);
288 /* Visual Part (Need to implement finalize for Visuals for a clean
290 /* for (i=0;i<screen_x11->nvisuals;i++)
291 g_object_unref (screen_x11->visuals[i]);*/
292 g_free (screen_x11->visuals);
293 g_hash_table_destroy (screen_x11->visual_hash);
295 g_free (screen_x11->window_manager_name);
297 g_hash_table_destroy (screen_x11->colormap_hash);
299 g_free (screen_x11->xsettings_client);
300 g_free (screen_x11->monitors);
302 G_OBJECT_CLASS (parent_class)->finalize (object);
306 * gdk_screen_get_n_monitors:
307 * @screen : a #GdkScreen.
309 * Returns the number of monitors being part of the virtual screen
311 * Returns: number of monitors part of the virtual screen or
312 * 0 if @screen is not in virtual screen mode.
315 gdk_screen_get_n_monitors (GdkScreen *screen)
317 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
319 return GDK_SCREEN_X11 (screen)->num_monitors;
323 * gdk_screen_get_monitor_geometry:
324 * @screen : a #GdkScreen.
325 * @monitor_num: the monitor number.
326 * @dest : a #GdkRectangle to be filled with the monitor geometry
328 * Retrieves the #GdkRectangle representing the size and start
329 * coordinates of the individual monitor within the the entire virtual
332 * Note that the virtual screen coordinates can be retrieved via
333 * gdk_screen_get_width() and gdk_screen_get_height().
337 gdk_screen_get_monitor_geometry (GdkScreen *screen,
341 g_return_if_fail (GDK_IS_SCREEN (screen));
342 g_return_if_fail (monitor_num < GDK_SCREEN_X11 (screen)->num_monitors);
343 g_return_if_fail (monitor_num >= 0);
345 *dest = GDK_SCREEN_X11 (screen)->monitors[monitor_num];
349 * gdk_x11_screen_get_xscreen:
350 * @screen: a #GdkScreen.
351 * @returns: an Xlib <type>Screen*</type>
353 * Returns the screen of a #GdkScreen.
356 gdk_x11_screen_get_xscreen (GdkScreen *screen)
358 return GDK_SCREEN_X11 (screen)->xscreen;
363 * gdk_x11_screen_get_screen_number:
364 * @screen: a #GdkScreen.
365 * @returns: the position of @screen among the screens of
368 * Returns the index of a #GdkScreen.
371 gdk_x11_screen_get_screen_number (GdkScreen *screen)
373 return GDK_SCREEN_X11 (screen)->screen_num;
377 _gdk_x11_screen_new (GdkDisplay *display,
381 GdkScreenX11 *screen_x11;
382 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
384 screen = g_object_new (GDK_TYPE_SCREEN_X11, NULL);
386 screen_x11 = GDK_SCREEN_X11 (screen);
387 screen_x11->display = display;
388 screen_x11->xdisplay = display_x11->xdisplay;
389 screen_x11->xscreen = ScreenOfDisplay (display_x11->xdisplay, screen_number);
390 screen_x11->screen_num = screen_number;
391 screen_x11->xroot_window = RootWindow (display_x11->xdisplay,screen_number);
392 screen_x11->wmspec_check_window = None;
393 /* we want this to be always non-null */
394 screen_x11->window_manager_name = g_strdup ("unknown");
396 init_xinerama_support (screen);
397 init_randr_support (screen);
399 _gdk_visual_init (screen);
400 _gdk_windowing_window_init (screen);
407 check_solaris_xinerama (GdkScreen *screen)
409 #ifdef HAVE_SOLARIS_XINERAMA
411 if (XineramaGetState (GDK_SCREEN_XDISPLAY (screen),
412 gdk_screen_get_number (screen)))
414 XRectangle monitors[MAXFRAMEBUFFERS];
415 unsigned char hints[16];
417 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
419 result = XineramaGetInfo (GDK_SCREEN_XDISPLAY (screen),
420 gdk_screen_get_number (screen),
422 &screen_x11->num_monitors);
423 /* Yes I know it should be Success but the current implementation
424 returns the num of monitor*/
427 /* FIXME: We need to trap errors, since XINERAMA isn't always XINERAMA.
429 g_error ("error while retrieving Xinerama information");
434 screen_x11->monitors = g_new0 (GdkRectangle, screen_x11->num_monitors);
436 for (i = 0; i < screen_x11->num_monitors; i++)
438 screen_x11->monitors[i].x = monitors[i].x;
439 screen_x11->monitors[i].y = monitors[i].y;
440 screen_x11->monitors[i].width = monitors[i].width;
441 screen_x11->monitors[i].height = monitors[i].height;
447 #endif /* HAVE_SOLARIS_XINERAMA */
453 check_xfree_xinerama (GdkScreen *screen)
455 #ifdef HAVE_XFREE_XINERAMA
456 if (XineramaIsActive (GDK_SCREEN_XDISPLAY (screen)))
458 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
459 XineramaScreenInfo *monitors = XineramaQueryScreens (GDK_SCREEN_XDISPLAY (screen),
460 &screen_x11->num_monitors);
461 if (screen_x11->num_monitors <= 0)
463 /* FIXME: We need to trap errors, since XINERAMA isn't always XINERAMA.
464 * I don't think the num_monitors <= 0 check has any validity.
466 g_error ("error while retrieving Xinerama information");
471 screen_x11->monitors = g_new0 (GdkRectangle, screen_x11->num_monitors);
473 for (i = 0; i < screen_x11->num_monitors; i++)
475 screen_x11->monitors[i].x = monitors[i].x_org;
476 screen_x11->monitors[i].y = monitors[i].y_org;
477 screen_x11->monitors[i].width = monitors[i].width;
478 screen_x11->monitors[i].height = monitors[i].height;
486 #endif /* HAVE_XFREE_XINERAMA */
490 #endif /* HAVE_XINERAMA */
493 init_xinerama_support (GdkScreen * screen)
495 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
497 int opcode, firstevent, firsterror;
500 if (screen_x11->monitors)
501 g_free (screen_x11->monitors);
504 if (XQueryExtension (GDK_SCREEN_XDISPLAY (screen), "XINERAMA",
505 &opcode, &firstevent, &firsterror))
507 if (check_solaris_xinerama (screen) ||
508 check_xfree_xinerama (screen))
511 #endif /* HAVE_XINERAMA */
515 screen_x11->num_monitors = 1;
516 screen_x11->monitors = g_new0 (GdkRectangle, 1);
517 screen_x11->monitors[0].x = 0;
518 screen_x11->monitors[0].y = 0;
519 screen_x11->monitors[0].width = WidthOfScreen (screen_x11->xscreen);
520 screen_x11->monitors[0].height = HeightOfScreen (screen_x11->xscreen);
524 init_randr_support (GdkScreen * screen)
526 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
528 XSelectInput (GDK_SCREEN_XDISPLAY (screen),
529 screen_x11->xroot_window,
530 StructureNotifyMask);
534 _gdk_x11_screen_size_changed (GdkScreen *screen,
538 if (!XRRUpdateConfiguration (event))
541 if (event->type == ConfigureNotify)
543 XConfigureEvent *rcevent = (XConfigureEvent *) event;
544 Screen *xscreen = gdk_x11_screen_get_xscreen (screen);
546 xscreen->width = rcevent->width;
547 xscreen->height = rcevent->height;
553 init_xinerama_support (screen);
554 g_signal_emit_by_name (G_OBJECT (screen), "size_changed");
558 _gdk_x11_screen_window_manager_changed (GdkScreen *screen)
560 g_signal_emit (G_OBJECT (screen),
561 signals[WINDOW_MANAGER_CHANGED], 0);
565 * _gdk_windowing_substitute_screen_number:
566 * @display_name : The name of a display, in the form used by
567 * gdk_display_open (). If %NULL a default value
568 * will be used. On X11, this is derived from the DISPLAY
569 * environment variable.
570 * @screen_number : The number of a screen within the display
571 * referred to by @display_name.
573 * Modifies a @display_name to make @screen_number the default
574 * screen when the display is opened.
576 * Return value: a newly allocated string holding the resulting
577 * display name. Free with g_free().
580 _gdk_windowing_substitute_screen_number (const gchar *display_name,
587 display_name = getenv ("DISPLAY");
592 str = g_string_new (display_name);
594 p = strrchr (str->str, '.');
595 if (p && p > strchr (str->str, ':'))
596 g_string_truncate (str, p - str->str);
598 g_string_append_printf (str, ".%d", screen_number);
600 return g_string_free (str, FALSE);
604 * gdk_screen_make_display_name:
605 * @screen: a #GdkScreen
607 * Determines the name to pass to gdk_display_open() to get
608 * a #GdkDisplay with this screen as the default screen.
610 * Return value: a newly allocated string, free with g_free()
613 gdk_screen_make_display_name (GdkScreen *screen)
615 const gchar *old_display;
617 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
619 old_display = gdk_display_get_name (gdk_screen_get_display (screen));
621 return _gdk_windowing_substitute_screen_number (old_display,
622 gdk_screen_get_number (screen));