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.
30 #include "gdkscreen.h"
31 #include "gdkscreen-x11.h"
32 #include "gdkdisplay.h"
33 #include "gdkdisplay-x11.h"
37 #ifdef HAVE_SOLARIS_XINERAMA
38 #include <X11/extensions/xinerama.h>
40 #ifdef HAVE_XFREE_XINERAMA
41 #include <X11/extensions/Xinerama.h>
45 #include <X11/extensions/Xrandr.h>
48 static void gdk_screen_x11_class_init (GdkScreenX11Class *klass);
49 static void gdk_screen_x11_dispose (GObject *object);
50 static void gdk_screen_x11_finalize (GObject *object);
51 static void init_xinerama_support (GdkScreen *screen);
52 static void init_randr_support (GdkScreen *screen);
56 WINDOW_MANAGER_CHANGED,
60 static gpointer parent_class = NULL;
61 static guint signals[LAST_SIGNAL] = { 0 };
64 _gdk_screen_x11_get_type (void)
66 static GType object_type = 0;
70 static const GTypeInfo object_info =
72 sizeof (GdkScreenX11Class),
74 (GBaseFinalizeFunc) NULL,
75 (GClassInitFunc) gdk_screen_x11_class_init,
76 NULL, /* class_finalize */
77 NULL, /* class_data */
78 sizeof (GdkScreenX11),
80 (GInstanceInitFunc) NULL,
82 object_type = g_type_register_static (GDK_TYPE_SCREEN,
90 gdk_screen_x11_class_init (GdkScreenX11Class *klass)
92 GObjectClass *object_class = G_OBJECT_CLASS (klass);
94 object_class->dispose = gdk_screen_x11_dispose;
95 object_class->finalize = gdk_screen_x11_finalize;
97 parent_class = g_type_class_peek_parent (klass);
99 signals[WINDOW_MANAGER_CHANGED] =
100 g_signal_new ("window_manager_changed",
101 G_OBJECT_CLASS_TYPE (object_class),
103 G_STRUCT_OFFSET (GdkScreenX11Class, window_manager_changed),
105 g_cclosure_marshal_VOID__VOID,
111 * gdk_screen_get_display:
112 * @screen: a #GdkScreen
114 * Gets the display to which the @screen belongs.
116 * Returns: the display to which @screen belongs
121 gdk_screen_get_display (GdkScreen *screen)
123 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
125 return GDK_SCREEN_X11 (screen)->display;
128 * gdk_screen_get_width:
129 * @screen: a #GdkScreen
131 * Gets the width of @screen in pixels
133 * Returns: the width of @screen in pixels.
138 gdk_screen_get_width (GdkScreen *screen)
140 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
142 return WidthOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
146 * gdk_screen_get_height:
147 * @screen: a #GdkScreen
149 * Gets the height of @screen in pixels
151 * Returns: the height of @screen in pixels.
156 gdk_screen_get_height (GdkScreen *screen)
158 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
160 return HeightOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
164 * gdk_screen_get_width_mm:
165 * @screen: a #GdkScreen
167 * Gets the width of @screen in millimeters.
168 * Note that on some X servers this value will not be correct.
170 * Returns: the width of @screen in millimeters.
175 gdk_screen_get_width_mm (GdkScreen *screen)
177 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
179 return WidthMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
183 * gdk_screen_get_height_mm:
184 * @screen: a #GdkScreen
186 * Returns the height of @screen in millimeters.
187 * Note that on some X servers this value will not be correct.
189 * Returns: the heigth of @screen in millimeters.
194 gdk_screen_get_height_mm (GdkScreen *screen)
196 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
198 return HeightMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
202 * gdk_screen_get_number:
203 * @screen: a #GdkScreen
205 * Gets the index of @screen among the screens in the display
206 * to which it belongs. (See gdk_screen_get_display())
213 gdk_screen_get_number (GdkScreen *screen)
215 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
217 return GDK_SCREEN_X11 (screen)->screen_num;
221 * gdk_screen_get_root_window:
222 * @screen: a #GdkScreen
224 * Gets the root window of @screen.
226 * Returns: the root window
231 gdk_screen_get_root_window (GdkScreen *screen)
233 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
235 return GDK_SCREEN_X11 (screen)->root_window;
239 * gdk_screen_get_default_colormap:
240 * @screen: a #GdkScreen
242 * Gets the default colormap for @screen.
244 * Returns: the default #GdkColormap.
249 gdk_screen_get_default_colormap (GdkScreen *screen)
251 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
253 return GDK_SCREEN_X11 (screen)->default_colormap;
257 * gdk_screen_set_default_colormap:
258 * @screen: a #GdkScreen
259 * @colormap: a #GdkColormap
261 * Sets the default @colormap for @screen.
266 gdk_screen_set_default_colormap (GdkScreen *screen,
267 GdkColormap *colormap)
269 GdkColormap *old_colormap;
271 g_return_if_fail (GDK_IS_SCREEN (screen));
272 g_return_if_fail (GDK_IS_COLORMAP (colormap));
274 old_colormap = GDK_SCREEN_X11 (screen)->default_colormap;
276 GDK_SCREEN_X11 (screen)->default_colormap = g_object_ref (colormap);
279 g_object_unref (old_colormap);
283 gdk_screen_x11_dispose (GObject *object)
285 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
287 _gdk_x11_events_uninit_screen (GDK_SCREEN (object));
289 g_object_unref (screen_x11->default_colormap);
290 screen_x11->default_colormap = NULL;
292 screen_x11->root_window = NULL;
294 screen_x11->xdisplay = NULL;
295 screen_x11->xscreen = NULL;
296 screen_x11->screen_num = -1;
297 screen_x11->xroot_window = None;
298 screen_x11->wmspec_check_window = None;
300 G_OBJECT_CLASS (parent_class)->dispose (object);
304 gdk_screen_x11_finalize (GObject *object)
306 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
308 g_object_unref (screen_x11->root_window);
310 if (screen_x11->renderer)
311 g_object_unref (screen_x11->renderer);
313 /* Visual Part (Need to implement finalize for Visuals for a clean
315 /* for (i=0;i<screen_x11->nvisuals;i++)
316 g_object_unref (screen_x11->visuals[i]);*/
317 g_free (screen_x11->visuals);
318 g_hash_table_destroy (screen_x11->visual_hash);
320 g_free (screen_x11->window_manager_name);
322 g_hash_table_destroy (screen_x11->colormap_hash);
324 g_free (screen_x11->xsettings_client);
325 g_free (screen_x11->monitors);
327 G_OBJECT_CLASS (parent_class)->finalize (object);
331 * gdk_screen_get_n_monitors:
332 * @screen: a #GdkScreen.
334 * Returns the number of monitors which @screen consists of.
336 * Returns: number of monitors which @screen consists of.
341 gdk_screen_get_n_monitors (GdkScreen *screen)
343 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
345 return GDK_SCREEN_X11 (screen)->num_monitors;
349 * gdk_screen_get_monitor_geometry:
350 * @screen : a #GdkScreen.
351 * @monitor_num: the monitor number.
352 * @dest : a #GdkRectangle to be filled with the monitor geometry
354 * Retrieves the #GdkRectangle representing the size and position of
355 * the individual monitor within the entire screen area.
357 * Note that the size of the entire screen area can be retrieved via
358 * gdk_screen_get_width() and gdk_screen_get_height().
363 gdk_screen_get_monitor_geometry (GdkScreen *screen,
367 g_return_if_fail (GDK_IS_SCREEN (screen));
368 g_return_if_fail (monitor_num < GDK_SCREEN_X11 (screen)->num_monitors);
369 g_return_if_fail (monitor_num >= 0);
371 *dest = GDK_SCREEN_X11 (screen)->monitors[monitor_num];
375 * gdk_x11_screen_get_xscreen:
376 * @screen: a #GdkScreen.
377 * @returns: an Xlib <type>Screen*</type>
379 * Returns the screen of a #GdkScreen.
384 gdk_x11_screen_get_xscreen (GdkScreen *screen)
386 return GDK_SCREEN_X11 (screen)->xscreen;
391 * gdk_x11_screen_get_screen_number:
392 * @screen: a #GdkScreen.
393 * @returns: the position of @screen among the screens of
396 * Returns the index of a #GdkScreen.
401 gdk_x11_screen_get_screen_number (GdkScreen *screen)
403 return GDK_SCREEN_X11 (screen)->screen_num;
407 _gdk_x11_screen_new (GdkDisplay *display,
411 GdkScreenX11 *screen_x11;
412 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
414 screen = g_object_new (GDK_TYPE_SCREEN_X11, NULL);
416 screen_x11 = GDK_SCREEN_X11 (screen);
417 screen_x11->display = display;
418 screen_x11->xdisplay = display_x11->xdisplay;
419 screen_x11->xscreen = ScreenOfDisplay (display_x11->xdisplay, screen_number);
420 screen_x11->screen_num = screen_number;
421 screen_x11->xroot_window = RootWindow (display_x11->xdisplay,screen_number);
422 screen_x11->wmspec_check_window = None;
423 /* we want this to be always non-null */
424 screen_x11->window_manager_name = g_strdup ("unknown");
426 init_xinerama_support (screen);
427 init_randr_support (screen);
429 _gdk_visual_init (screen);
430 _gdk_windowing_window_init (screen);
437 check_solaris_xinerama (GdkScreen *screen)
439 #ifdef HAVE_SOLARIS_XINERAMA
441 if (XineramaGetState (GDK_SCREEN_XDISPLAY (screen),
442 gdk_screen_get_number (screen)))
444 XRectangle monitors[MAXFRAMEBUFFERS];
445 unsigned char hints[16];
447 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
449 result = XineramaGetInfo (GDK_SCREEN_XDISPLAY (screen),
450 gdk_screen_get_number (screen),
452 &screen_x11->num_monitors);
453 /* Yes I know it should be Success but the current implementation
454 returns the num of monitor*/
457 /* FIXME: We need to trap errors, since XINERAMA isn't always XINERAMA.
459 g_error ("error while retrieving Xinerama information");
464 screen_x11->monitors = g_new0 (GdkRectangle, screen_x11->num_monitors);
466 for (i = 0; i < screen_x11->num_monitors; i++)
468 screen_x11->monitors[i].x = monitors[i].x;
469 screen_x11->monitors[i].y = monitors[i].y;
470 screen_x11->monitors[i].width = monitors[i].width;
471 screen_x11->monitors[i].height = monitors[i].height;
477 #endif /* HAVE_SOLARIS_XINERAMA */
483 check_xfree_xinerama (GdkScreen *screen)
485 #ifdef HAVE_XFREE_XINERAMA
486 if (XineramaIsActive (GDK_SCREEN_XDISPLAY (screen)))
488 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
489 XineramaScreenInfo *monitors = XineramaQueryScreens (GDK_SCREEN_XDISPLAY (screen),
490 &screen_x11->num_monitors);
491 if (screen_x11->num_monitors <= 0)
493 /* FIXME: We need to trap errors, since XINERAMA isn't always XINERAMA.
494 * I don't think the num_monitors <= 0 check has any validity.
496 g_error ("error while retrieving Xinerama information");
501 screen_x11->monitors = g_new0 (GdkRectangle, screen_x11->num_monitors);
503 for (i = 0; i < screen_x11->num_monitors; i++)
505 screen_x11->monitors[i].x = monitors[i].x_org;
506 screen_x11->monitors[i].y = monitors[i].y_org;
507 screen_x11->monitors[i].width = monitors[i].width;
508 screen_x11->monitors[i].height = monitors[i].height;
516 #endif /* HAVE_XFREE_XINERAMA */
520 #endif /* HAVE_XINERAMA */
523 init_xinerama_support (GdkScreen * screen)
525 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
527 int opcode, firstevent, firsterror;
530 if (screen_x11->monitors)
531 g_free (screen_x11->monitors);
534 if (XQueryExtension (GDK_SCREEN_XDISPLAY (screen), "XINERAMA",
535 &opcode, &firstevent, &firsterror))
537 if (check_solaris_xinerama (screen) ||
538 check_xfree_xinerama (screen))
541 #endif /* HAVE_XINERAMA */
545 #ifdef G_ENABLE_DEBUG
546 if (_gdk_debug_flags & GDK_DEBUG_XINERAMA)
548 /* Fake Xinerama mode by splitting the screen into 4 monitors.
549 * Also draw a little cross to make the monitor boundaries visible.
551 XSetWindowAttributes atts;
555 w = WidthOfScreen (screen_x11->xscreen);
556 h = HeightOfScreen (screen_x11->xscreen);
557 screen_x11->num_monitors = 4;
558 screen_x11->monitors = g_new0 (GdkRectangle, 4);
559 screen_x11->monitors[0].x = 0;
560 screen_x11->monitors[0].y = 0;
561 screen_x11->monitors[0].width = w / 2;
562 screen_x11->monitors[0].height = h / 2;
563 screen_x11->monitors[1].x = w / 2;
564 screen_x11->monitors[1].y = 0;
565 screen_x11->monitors[1].width = w / 2;
566 screen_x11->monitors[1].height = h / 2;
567 screen_x11->monitors[2].x = 0;
568 screen_x11->monitors[2].y = h / 2;
569 screen_x11->monitors[2].width = w / 2;
570 screen_x11->monitors[2].height = h / 2;
571 screen_x11->monitors[3].x = w / 2;
572 screen_x11->monitors[3].y = h / 2;
573 screen_x11->monitors[3].width = w / 2;
574 screen_x11->monitors[3].height = h / 2;
575 atts.override_redirect = 1;
576 atts.background_pixel = WhitePixel(GDK_SCREEN_XDISPLAY (screen),
577 screen_x11->screen_num);
578 win = XCreateWindow(GDK_SCREEN_XDISPLAY (screen),
579 screen_x11->xroot_window, 0, h / 2, w, 1, 0,
580 DefaultDepth(GDK_SCREEN_XDISPLAY (screen),
581 screen_x11->screen_num),
583 DefaultVisual(GDK_SCREEN_XDISPLAY (screen),
584 screen_x11->screen_num),
585 CWOverrideRedirect|CWBackPixel,
587 XMapRaised(GDK_SCREEN_XDISPLAY (screen), win);
588 win = XCreateWindow(GDK_SCREEN_XDISPLAY (screen),
589 screen_x11->xroot_window, w/2 , 0, 1, h, 0,
590 DefaultDepth(GDK_SCREEN_XDISPLAY (screen),
591 screen_x11->screen_num),
593 DefaultVisual(GDK_SCREEN_XDISPLAY (screen),
594 screen_x11->screen_num),
595 CWOverrideRedirect|CWBackPixel,
597 XMapRaised(GDK_SCREEN_XDISPLAY (screen), win);
602 screen_x11->num_monitors = 1;
603 screen_x11->monitors = g_new0 (GdkRectangle, 1);
604 screen_x11->monitors[0].x = 0;
605 screen_x11->monitors[0].y = 0;
606 screen_x11->monitors[0].width = WidthOfScreen (screen_x11->xscreen);
607 screen_x11->monitors[0].height = HeightOfScreen (screen_x11->xscreen);
612 init_randr_support (GdkScreen * screen)
614 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
616 XSelectInput (GDK_SCREEN_XDISPLAY (screen),
617 screen_x11->xroot_window,
618 StructureNotifyMask);
622 _gdk_x11_screen_size_changed (GdkScreen *screen,
626 if (!XRRUpdateConfiguration (event))
629 if (event->type == ConfigureNotify)
631 XConfigureEvent *rcevent = (XConfigureEvent *) event;
632 Screen *xscreen = gdk_x11_screen_get_xscreen (screen);
634 xscreen->width = rcevent->width;
635 xscreen->height = rcevent->height;
641 init_xinerama_support (screen);
642 g_signal_emit_by_name (screen, "size_changed");
646 _gdk_x11_screen_window_manager_changed (GdkScreen *screen)
648 g_signal_emit (screen, signals[WINDOW_MANAGER_CHANGED], 0);
652 * _gdk_windowing_substitute_screen_number:
653 * @display_name : The name of a display, in the form used by
654 * gdk_display_open (). If %NULL a default value
655 * will be used. On X11, this is derived from the DISPLAY
656 * environment variable.
657 * @screen_number : The number of a screen within the display
658 * referred to by @display_name.
660 * Modifies a @display_name to make @screen_number the default
661 * screen when the display is opened.
663 * Return value: a newly allocated string holding the resulting
664 * display name. Free with g_free().
667 _gdk_windowing_substitute_screen_number (const gchar *display_name,
674 display_name = getenv ("DISPLAY");
679 str = g_string_new (display_name);
681 p = strrchr (str->str, '.');
682 if (p && p > strchr (str->str, ':'))
683 g_string_truncate (str, p - str->str);
685 g_string_append_printf (str, ".%d", screen_number);
687 return g_string_free (str, FALSE);
691 * gdk_screen_make_display_name:
692 * @screen: a #GdkScreen
694 * Determines the name to pass to gdk_display_open() to get
695 * a #GdkDisplay with this screen as the default screen.
697 * Return value: a newly allocated string, free with g_free()
702 gdk_screen_make_display_name (GdkScreen *screen)
704 const gchar *old_display;
706 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
708 old_display = gdk_display_get_name (gdk_screen_get_display (screen));
710 return _gdk_windowing_substitute_screen_number (old_display,
711 gdk_screen_get_number (screen));
714 #define __GDK_SCREEN_X11_C__
715 #include "gdkaliasdef.c"