1  /*
2  * gdkscreen-x11.c
3  *
4  * Copyright 2001 Sun Microsystems Inc.
5  *
6  * Erwann Chenede <erwann.chenede@sun.com>
7  *
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.
12  *
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.
17  *
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.
22  */
23 
24 #include "config.h"
25 
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include <glib.h>
30 #include "gdkscreen.h"
31 #include "gdkscreen-x11.h"
32 #include "gdkdisplay.h"
33 #include "gdkdisplay-x11.h"
34 #include "gdkx.h"
35 #include "gdkalias.h"
36 
37 #include <X11/Xatom.h>
38 
39 #ifdef HAVE_SOLARIS_XINERAMA
40 #include <X11/extensions/xinerama.h>
41 #endif
42 #ifdef HAVE_XFREE_XINERAMA
43 #include <X11/extensions/Xinerama.h>
44 #endif
45 
46 #ifdef HAVE_RANDR
47 #include <X11/extensions/Xrandr.h>
48 #endif
49 
50 #ifdef HAVE_XFIXES
51 #include <X11/extensions/Xfixes.h>
52 #endif
53 
54 static void         gdk_screen_x11_dispose     (GObject		  *object);
55 static void         gdk_screen_x11_finalize    (GObject		  *object);
56 static void	    init_randr_support	       (GdkScreen	  *screen);
57 static void	    deinit_multihead           (GdkScreen         *screen);
58 
59 enum
60 {
61   WINDOW_MANAGER_CHANGED,
62   LAST_SIGNAL
63 };
64 
65 static guint signals[LAST_SIGNAL] = { 0 };
66 
67 G_DEFINE_TYPE (GdkScreenX11, _gdk_screen_x11, GDK_TYPE_SCREEN)
68 
69 struct _GdkX11Monitor
70 {
71   GdkRectangle  geometry;
72   XID		output;
73   int		width_mm;
74   int		height_mm;
75   char *	output_name;
76   char *	manufacturer;
77 };
78 
79 static void
_gdk_screen_x11_class_init(GdkScreenX11Class * klass)80 _gdk_screen_x11_class_init (GdkScreenX11Class *klass)
81 {
82   GObjectClass *object_class = G_OBJECT_CLASS (klass);
83 
84   object_class->dispose = gdk_screen_x11_dispose;
85   object_class->finalize = gdk_screen_x11_finalize;
86 
87   signals[WINDOW_MANAGER_CHANGED] =
88     g_signal_new (g_intern_static_string ("window_manager_changed"),
89                   G_OBJECT_CLASS_TYPE (object_class),
90                   G_SIGNAL_RUN_LAST,
91                   G_STRUCT_OFFSET (GdkScreenX11Class, window_manager_changed),
92                   NULL, NULL,
93                   g_cclosure_marshal_VOID__VOID,
94                   G_TYPE_NONE,
95                   0);
96 }
97 
98 static void
_gdk_screen_x11_init(GdkScreenX11 * screen)99 _gdk_screen_x11_init (GdkScreenX11 *screen)
100 {
101 }
102 
103 /**
104  * gdk_screen_get_display:
105  * @screen: a #GdkScreen
106  *
107  * Gets the display to which the @screen belongs.
108  *
109  * Returns: the display to which @screen belongs
110  *
111  * Since: 2.2
112  **/
113 GdkDisplay *
gdk_screen_get_display(GdkScreen * screen)114 gdk_screen_get_display (GdkScreen *screen)
115 {
116   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
117 
118   return GDK_SCREEN_X11 (screen)->display;
119 }
120 /**
121  * gdk_screen_get_width:
122  * @screen: a #GdkScreen
123  *
124  * Gets the width of @screen in pixels
125  *
126  * Returns: the width of @screen in pixels.
127  *
128  * Since: 2.2
129  **/
130 gint
gdk_screen_get_width(GdkScreen * screen)131 gdk_screen_get_width (GdkScreen *screen)
132 {
133   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
134 
135   return WidthOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
136 }
137 
138 /**
139  * gdk_screen_get_height:
140  * @screen: a #GdkScreen
141  *
142  * Gets the height of @screen in pixels
143  *
144  * Returns: the height of @screen in pixels.
145  *
146  * Since: 2.2
147  **/
148 gint
gdk_screen_get_height(GdkScreen * screen)149 gdk_screen_get_height (GdkScreen *screen)
150 {
151   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
152 
153   return HeightOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
154 }
155 
156 /**
157  * gdk_screen_get_width_mm:
158  * @screen: a #GdkScreen
159  *
160  * Gets the width of @screen in millimeters.
161  * Note that on some X servers this value will not be correct.
162  *
163  * Returns: the width of @screen in millimeters.
164  *
165  * Since: 2.2
166  **/
167 gint
gdk_screen_get_width_mm(GdkScreen * screen)168 gdk_screen_get_width_mm (GdkScreen *screen)
169 {
170   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
171 
172   return WidthMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
173 }
174 
175 /**
176  * gdk_screen_get_height_mm:
177  * @screen: a #GdkScreen
178  *
179  * Returns the height of @screen in millimeters.
180  * Note that on some X servers this value will not be correct.
181  *
182  * Returns: the heigth of @screen in millimeters.
183  *
184  * Since: 2.2
185  **/
186 gint
gdk_screen_get_height_mm(GdkScreen * screen)187 gdk_screen_get_height_mm (GdkScreen *screen)
188 {
189   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
190 
191   return HeightMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
192 }
193 
194 /**
195  * gdk_screen_get_number:
196  * @screen: a #GdkScreen
197  *
198  * Gets the index of @screen among the screens in the display
199  * to which it belongs. (See gdk_screen_get_display())
200  *
201  * Returns: the index
202  *
203  * Since: 2.2
204  **/
205 gint
gdk_screen_get_number(GdkScreen * screen)206 gdk_screen_get_number (GdkScreen *screen)
207 {
208   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
209 
210   return GDK_SCREEN_X11 (screen)->screen_num;
211 }
212 
213 /**
214  * gdk_screen_get_root_window:
215  * @screen: a #GdkScreen
216  *
217  * Gets the root window of @screen.
218  *
219  * Returns: (transfer none): the root window
220  *
221  * Since: 2.2
222  **/
223 GdkWindow *
gdk_screen_get_root_window(GdkScreen * screen)224 gdk_screen_get_root_window (GdkScreen *screen)
225 {
226   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
227 
228   return GDK_SCREEN_X11 (screen)->root_window;
229 }
230 
231 /**
232  * gdk_screen_get_default_colormap:
233  * @screen: a #GdkScreen
234  *
235  * Gets the default colormap for @screen.
236  *
237  * Returns: (transfer none): the default #GdkColormap.
238  *
239  * Since: 2.2
240  **/
241 GdkColormap *
gdk_screen_get_default_colormap(GdkScreen * screen)242 gdk_screen_get_default_colormap (GdkScreen *screen)
243 {
244   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
245 
246   return GDK_SCREEN_X11 (screen)->default_colormap;
247 }
248 
249 /**
250  * gdk_screen_set_default_colormap:
251  * @screen: a #GdkScreen
252  * @colormap: a #GdkColormap
253  *
254  * Sets the default @colormap for @screen.
255  *
256  * Since: 2.2
257  **/
258 void
gdk_screen_set_default_colormap(GdkScreen * screen,GdkColormap * colormap)259 gdk_screen_set_default_colormap (GdkScreen   *screen,
260 				 GdkColormap *colormap)
261 {
262   GdkColormap *old_colormap;
263 
264   g_return_if_fail (GDK_IS_SCREEN (screen));
265   g_return_if_fail (GDK_IS_COLORMAP (colormap));
266 
267   old_colormap = GDK_SCREEN_X11 (screen)->default_colormap;
268 
269   GDK_SCREEN_X11 (screen)->default_colormap = g_object_ref (colormap);
270 
271   if (old_colormap)
272     g_object_unref (old_colormap);
273 }
274 
275 static void
gdk_screen_x11_dispose(GObject * object)276 gdk_screen_x11_dispose (GObject *object)
277 {
278   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
279 
280   _gdk_x11_events_uninit_screen (GDK_SCREEN (object));
281 
282   if (screen_x11->default_colormap)
283     {
284       g_object_unref (screen_x11->default_colormap);
285       screen_x11->default_colormap = NULL;
286     }
287 
288   if (screen_x11->system_colormap)
289     {
290       g_object_unref (screen_x11->system_colormap);
291       screen_x11->system_colormap = NULL;
292     }
293 
294   if (screen_x11->rgba_colormap)
295     {
296       g_object_unref (screen_x11->rgba_colormap);
297       screen_x11->rgba_colormap = NULL;
298     }
299 
300   if (screen_x11->root_window)
301     _gdk_window_destroy (screen_x11->root_window, TRUE);
302 
303   G_OBJECT_CLASS (_gdk_screen_x11_parent_class)->dispose (object);
304 
305   screen_x11->xdisplay = NULL;
306   screen_x11->xscreen = NULL;
307   screen_x11->screen_num = -1;
308   screen_x11->xroot_window = None;
309   screen_x11->wmspec_check_window = None;
310 }
311 
312 static void
gdk_screen_x11_finalize(GObject * object)313 gdk_screen_x11_finalize (GObject *object)
314 {
315   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
316   gint          i;
317 
318   if (screen_x11->root_window)
319     g_object_unref (screen_x11->root_window);
320 
321   if (screen_x11->renderer)
322     g_object_unref (screen_x11->renderer);
323 
324   /* Visual Part */
325   for (i = 0; i < screen_x11->nvisuals; i++)
326     g_object_unref (screen_x11->visuals[i]);
327   g_free (screen_x11->visuals);
328   g_hash_table_destroy (screen_x11->visual_hash);
329 
330   g_free (screen_x11->window_manager_name);
331 
332   g_hash_table_destroy (screen_x11->colormap_hash);
333 
334   deinit_multihead (GDK_SCREEN (object));
335 
336   G_OBJECT_CLASS (_gdk_screen_x11_parent_class)->finalize (object);
337 }
338 
339 /**
340  * gdk_screen_get_n_monitors:
341  * @screen: a #GdkScreen
342  *
343  * Returns the number of monitors which @screen consists of.
344  *
345  * Returns: number of monitors which @screen consists of
346  *
347  * Since: 2.2
348  */
349 gint
gdk_screen_get_n_monitors(GdkScreen * screen)350 gdk_screen_get_n_monitors (GdkScreen *screen)
351 {
352   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
353 
354   return GDK_SCREEN_X11 (screen)->n_monitors;
355 }
356 
357 /**
358  * gdk_screen_get_primary_monitor:
359  * @screen: a #GdkScreen.
360  *
361  * Gets the primary monitor for @screen.  The primary monitor
362  * is considered the monitor where the 'main desktop' lives.
363  * While normal application windows typically allow the window
364  * manager to place the windows, specialized desktop applications
365  * such as panels should place themselves on the primary monitor.
366  *
367  * If no primary monitor is configured by the user, the return value
368  * will be 0, defaulting to the first monitor.
369  *
370  * Returns: An integer index for the primary monitor, or 0 if none is configured.
371  *
372  * Since: 2.20
373  */
374 gint
gdk_screen_get_primary_monitor(GdkScreen * screen)375 gdk_screen_get_primary_monitor (GdkScreen *screen)
376 {
377   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
378 
379   return GDK_SCREEN_X11 (screen)->primary_monitor;
380 }
381 
382 /**
383  * gdk_screen_get_monitor_width_mm:
384  * @screen: a #GdkScreen
385  * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
386  *
387  * Gets the width in millimeters of the specified monitor, if available.
388  *
389  * Returns: the width of the monitor, or -1 if not available
390  *
391  * Since: 2.14
392  */
393 gint
gdk_screen_get_monitor_width_mm(GdkScreen * screen,gint monitor_num)394 gdk_screen_get_monitor_width_mm	(GdkScreen *screen,
395 				 gint       monitor_num)
396 {
397   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
398 
399   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
400   g_return_val_if_fail (monitor_num >= 0, -1);
401   g_return_val_if_fail (monitor_num < screen_x11->n_monitors, -1);
402 
403   return screen_x11->monitors[monitor_num].width_mm;
404 }
405 
406 /**
407  * gdk_screen_get_monitor_height_mm:
408  * @screen: a #GdkScreen
409  * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
410  *
411  * Gets the height in millimeters of the specified monitor.
412  *
413  * Returns: the height of the monitor, or -1 if not available
414  *
415  * Since: 2.14
416  */
417 gint
gdk_screen_get_monitor_height_mm(GdkScreen * screen,gint monitor_num)418 gdk_screen_get_monitor_height_mm (GdkScreen *screen,
419                                   gint       monitor_num)
420 {
421   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
422 
423   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
424   g_return_val_if_fail (monitor_num >= 0, -1);
425   g_return_val_if_fail (monitor_num < screen_x11->n_monitors, -1);
426 
427   return screen_x11->monitors[monitor_num].height_mm;
428 }
429 
430 /**
431  * gdk_screen_get_monitor_plug_name:
432  * @screen: a #GdkScreen
433  * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
434  *
435  * Returns the output name of the specified monitor.
436  * Usually something like VGA, DVI, or TV, not the actual
437  * product name of the display device.
438  *
439  * Returns: a newly-allocated string containing the name of the monitor,
440  *   or %NULL if the name cannot be determined
441  *
442  * Since: 2.14
443  */
444 gchar *
gdk_screen_get_monitor_plug_name(GdkScreen * screen,gint monitor_num)445 gdk_screen_get_monitor_plug_name (GdkScreen *screen,
446 				  gint       monitor_num)
447 {
448   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
449 
450   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
451   g_return_val_if_fail (monitor_num >= 0, NULL);
452   g_return_val_if_fail (monitor_num < screen_x11->n_monitors, NULL);
453 
454   return g_strdup (screen_x11->monitors[monitor_num].output_name);
455 }
456 
457 /**
458  * gdk_x11_screen_get_monitor_output:
459  * @screen: a #GdkScreen
460  * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
461  *
462  * Gets the XID of the specified output/monitor.
463  * If the X server does not support version 1.2 of the RANDR
464  * extension, 0 is returned.
465  *
466  * Returns: the XID of the monitor
467  *
468  * Since: 2.14
469  */
470 XID
gdk_x11_screen_get_monitor_output(GdkScreen * screen,gint monitor_num)471 gdk_x11_screen_get_monitor_output (GdkScreen *screen,
472                                    gint       monitor_num)
473 {
474   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
475 
476   g_return_val_if_fail (GDK_IS_SCREEN (screen), None);
477   g_return_val_if_fail (monitor_num >= 0, None);
478   g_return_val_if_fail (monitor_num < screen_x11->n_monitors, None);
479 
480   return screen_x11->monitors[monitor_num].output;
481 }
482 
483 /**
484  * gdk_screen_get_monitor_geometry:
485  * @screen: a #GdkScreen
486  * @monitor_num: the monitor number, between 0 and gdk_screen_get_n_monitors (screen)
487  * @dest: a #GdkRectangle to be filled with the monitor geometry
488  *
489  * Retrieves the #GdkRectangle representing the size and position of
490  * the individual monitor within the entire screen area.
491  *
492  * Note that the size of the entire screen area can be retrieved via
493  * gdk_screen_get_width() and gdk_screen_get_height().
494  *
495  * Since: 2.2
496  */
497 void
gdk_screen_get_monitor_geometry(GdkScreen * screen,gint monitor_num,GdkRectangle * dest)498 gdk_screen_get_monitor_geometry (GdkScreen    *screen,
499 				 gint          monitor_num,
500 				 GdkRectangle *dest)
501 {
502   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
503 
504   g_return_if_fail (GDK_IS_SCREEN (screen));
505   g_return_if_fail (monitor_num >= 0);
506   g_return_if_fail (monitor_num < screen_x11->n_monitors);
507 
508   if (dest)
509     *dest = screen_x11->monitors[monitor_num].geometry;
510 }
511 
512 /**
513  * gdk_screen_get_rgba_colormap:
514  * @screen: a #GdkScreen.
515  *
516  * Gets a colormap to use for creating windows or pixmaps with an
517  * alpha channel. The windowing system on which GTK+ is running
518  * may not support this capability, in which case %NULL will
519  * be returned. Even if a non-%NULL value is returned, its
520  * possible that the window's alpha channel won't be honored
521  * when displaying the window on the screen: in particular, for
522  * X an appropriate windowing manager and compositing manager
523  * must be running to provide appropriate display.
524  *
525  * This functionality is not implemented in the Windows backend.
526  *
527  * For setting an overall opacity for a top-level window, see
528  * gdk_window_set_opacity().
529 
530  * Return value: (transfer none): a colormap to use for windows with
531  *     an alpha channel or %NULL if the capability is not available.
532  *
533  * Since: 2.8
534  **/
535 GdkColormap *
gdk_screen_get_rgba_colormap(GdkScreen * screen)536 gdk_screen_get_rgba_colormap (GdkScreen *screen)
537 {
538   GdkScreenX11 *screen_x11;
539 
540   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
541 
542   screen_x11 = GDK_SCREEN_X11 (screen);
543 
544   if (!screen_x11->rgba_visual)
545     return NULL;
546 
547   if (!screen_x11->rgba_colormap)
548     screen_x11->rgba_colormap = gdk_colormap_new (screen_x11->rgba_visual,
549 						  FALSE);
550 
551   return screen_x11->rgba_colormap;
552 }
553 
554 /**
555  * gdk_screen_get_rgba_visual:
556  * @screen: a #GdkScreen
557  *
558  * Gets a visual to use for creating windows or pixmaps with an
559  * alpha channel. See the docs for gdk_screen_get_rgba_colormap()
560  * for caveats.
561  *
562  * Return value: (transfer none): a visual to use for windows with an
563  *     alpha channel or %NULL if the capability is not available.
564  *
565  * Since: 2.8
566  **/
567 GdkVisual *
gdk_screen_get_rgba_visual(GdkScreen * screen)568 gdk_screen_get_rgba_visual (GdkScreen *screen)
569 {
570   GdkScreenX11 *screen_x11;
571 
572   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
573 
574   screen_x11 = GDK_SCREEN_X11 (screen);
575 
576   return screen_x11->rgba_visual;
577 }
578 
579 /**
580  * gdk_x11_screen_get_xscreen:
581  * @screen: a #GdkScreen.
582  * @returns: (transfer none): an Xlib <type>Screen*</type>
583  *
584  * Returns the screen of a #GdkScreen.
585  *
586  * Since: 2.2
587  */
588 Screen *
gdk_x11_screen_get_xscreen(GdkScreen * screen)589 gdk_x11_screen_get_xscreen (GdkScreen *screen)
590 {
591   return GDK_SCREEN_X11 (screen)->xscreen;
592 }
593 
594 /**
595  * gdk_x11_screen_get_screen_number:
596  * @screen: a #GdkScreen.
597  * @returns: the position of @screen among the screens of
598  *   its display.
599  *
600  * Returns the index of a #GdkScreen.
601  *
602  * Since: 2.2
603  */
604 int
gdk_x11_screen_get_screen_number(GdkScreen * screen)605 gdk_x11_screen_get_screen_number (GdkScreen *screen)
606 {
607   return GDK_SCREEN_X11 (screen)->screen_num;
608 }
609 
610 static gboolean
check_is_composited(GdkDisplay * display,GdkScreenX11 * screen_x11)611 check_is_composited (GdkDisplay *display,
612 		     GdkScreenX11 *screen_x11)
613 {
614   Atom xselection = gdk_x11_atom_to_xatom_for_display (display, screen_x11->cm_selection_atom);
615   Window xwindow;
616 
617   xwindow = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display), xselection);
618 
619   return xwindow != None;
620 }
621 
622 static GdkAtom
make_cm_atom(int screen_number)623 make_cm_atom (int screen_number)
624 {
625   gchar *name = g_strdup_printf ("_NET_WM_CM_S%d", screen_number);
626   GdkAtom atom = gdk_atom_intern (name, FALSE);
627   g_free (name);
628   return atom;
629 }
630 
631 static void
init_monitor_geometry(GdkX11Monitor * monitor,int x,int y,int width,int height)632 init_monitor_geometry (GdkX11Monitor *monitor,
633 		       int x, int y, int width, int height)
634 {
635   monitor->geometry.x = x;
636   monitor->geometry.y = y;
637   monitor->geometry.width = width;
638   monitor->geometry.height = height;
639 
640   monitor->output = None;
641   monitor->width_mm = -1;
642   monitor->height_mm = -1;
643   monitor->output_name = NULL;
644   monitor->manufacturer = NULL;
645 }
646 
647 static gboolean
init_fake_xinerama(GdkScreen * screen)648 init_fake_xinerama (GdkScreen *screen)
649 {
650 #ifdef G_ENABLE_DEBUG
651   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
652   XSetWindowAttributes atts;
653   Window win;
654   gint w, h;
655 
656   if (!(_gdk_debug_flags & GDK_DEBUG_XINERAMA))
657     return FALSE;
658 
659   /* Fake Xinerama mode by splitting the screen into 4 monitors.
660    * Also draw a little cross to make the monitor boundaries visible.
661    */
662   w = WidthOfScreen (screen_x11->xscreen);
663   h = HeightOfScreen (screen_x11->xscreen);
664 
665   screen_x11->n_monitors = 4;
666   screen_x11->monitors = g_new0 (GdkX11Monitor, 4);
667   init_monitor_geometry (&screen_x11->monitors[0], 0, 0, w / 2, h / 2);
668   init_monitor_geometry (&screen_x11->monitors[1], w / 2, 0, w / 2, h / 2);
669   init_monitor_geometry (&screen_x11->monitors[2], 0, h / 2, w / 2, h / 2);
670   init_monitor_geometry (&screen_x11->monitors[3], w / 2, h / 2, w / 2, h / 2);
671 
672   atts.override_redirect = 1;
673   atts.background_pixel = WhitePixel(GDK_SCREEN_XDISPLAY (screen),
674 				     screen_x11->screen_num);
675   win = XCreateWindow(GDK_SCREEN_XDISPLAY (screen),
676 		      screen_x11->xroot_window, 0, h / 2, w, 1, 0,
677 		      DefaultDepth(GDK_SCREEN_XDISPLAY (screen),
678 				   screen_x11->screen_num),
679 		      InputOutput,
680 		      DefaultVisual(GDK_SCREEN_XDISPLAY (screen),
681 				    screen_x11->screen_num),
682 		      CWOverrideRedirect|CWBackPixel,
683 		      &atts);
684   XMapRaised(GDK_SCREEN_XDISPLAY (screen), win);
685   win = XCreateWindow(GDK_SCREEN_XDISPLAY (screen),
686 		      screen_x11->xroot_window, w/2 , 0, 1, h, 0,
687 		      DefaultDepth(GDK_SCREEN_XDISPLAY (screen),
688 				   screen_x11->screen_num),
689 		      InputOutput,
690 		      DefaultVisual(GDK_SCREEN_XDISPLAY (screen),
691 				    screen_x11->screen_num),
692 		      CWOverrideRedirect|CWBackPixel,
693 		      &atts);
694   XMapRaised(GDK_SCREEN_XDISPLAY (screen), win);
695   return TRUE;
696 #endif
697 
698   return FALSE;
699 }
700 
701 static void
free_monitors(GdkX11Monitor * monitors,gint n_monitors)702 free_monitors (GdkX11Monitor *monitors,
703                gint           n_monitors)
704 {
705   int i;
706 
707   for (i = 0; i < n_monitors; ++i)
708     {
709       g_free (monitors[i].output_name);
710       g_free (monitors[i].manufacturer);
711     }
712 
713   g_free (monitors);
714 }
715 
716 #ifdef HAVE_RANDR
717 static int
monitor_compare_function(GdkX11Monitor * monitor1,GdkX11Monitor * monitor2)718 monitor_compare_function (GdkX11Monitor *monitor1,
719                           GdkX11Monitor *monitor2)
720 {
721   /* Sort the leftmost/topmost monitors first.
722    * For "cloned" monitors, sort the bigger ones first
723    * (giving preference to taller monitors over wider
724    * monitors)
725    */
726 
727   if (monitor1->geometry.x != monitor2->geometry.x)
728     return monitor1->geometry.x - monitor2->geometry.x;
729 
730   if (monitor1->geometry.y != monitor2->geometry.y)
731     return monitor1->geometry.y - monitor2->geometry.y;
732 
733   if (monitor1->geometry.height != monitor2->geometry.height)
734     return - (monitor1->geometry.height - monitor2->geometry.height);
735 
736   if (monitor1->geometry.width != monitor2->geometry.width)
737     return - (monitor1->geometry.width - monitor2->geometry.width);
738 
739   return 0;
740 }
741 #endif
742 
743 #ifdef HAVE_RANDR15
744 static gboolean
init_randr15(GdkScreen * screen)745 init_randr15 (GdkScreen *screen)
746 {
747   GdkDisplay *display = gdk_screen_get_display (screen);
748   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
749   GdkScreenX11 *x11_screen = GDK_SCREEN_X11 (screen);
750   XRRMonitorInfo *rr_monitors;
751   int num_rr_monitors;
752   int i;
753   GArray *monitors;
754   XID primary_output = None;
755 
756   if (!display_x11->have_randr15)
757     return FALSE;
758 
759   rr_monitors = XRRGetMonitors (x11_screen->xdisplay,
760                                 x11_screen->xroot_window,
761                                 True,
762                                 &num_rr_monitors);
763   if (!rr_monitors)
764     return FALSE;
765 
766   monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor),
767                                 num_rr_monitors);
768   for (i = 0; i < num_rr_monitors; i++)
769     {
770       GdkX11Monitor monitor;
771       init_monitor_geometry (&monitor,
772                              rr_monitors[i].x,
773                              rr_monitors[i].y,
774                              rr_monitors[i].width,
775                              rr_monitors[i].height);
776 
777       monitor.width_mm = rr_monitors[i].mwidth;
778       monitor.height_mm = rr_monitors[i].mheight;
779       monitor.output = rr_monitors[i].outputs[0];
780       if (rr_monitors[i].primary)
781         primary_output = monitor.output;
782 
783       g_array_append_val (monitors, monitor);
784     }
785   XRRFreeMonitors (rr_monitors);
786 
787   g_array_sort (monitors,
788                 (GCompareFunc) monitor_compare_function);
789   x11_screen->n_monitors = monitors->len;
790   x11_screen->monitors = (GdkX11Monitor *) g_array_free (monitors, FALSE);
791 
792   x11_screen->primary_monitor = 0;
793 
794   for (i = 0; i < x11_screen->n_monitors; i++)
795     {
796       if (x11_screen->monitors[i].output == primary_output)
797         {
798           x11_screen->primary_monitor = i;
799           break;
800         }
801     }
802 
803   return x11_screen->n_monitors > 0;
804 }
805 #endif
806 
807 static gboolean
init_randr13(GdkScreen * screen)808 init_randr13 (GdkScreen *screen)
809 {
810 #ifdef HAVE_RANDR
811   GdkDisplay *display = gdk_screen_get_display (screen);
812   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
813   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
814   Display *dpy = GDK_SCREEN_XDISPLAY (screen);
815   XRRScreenResources *resources;
816   RROutput primary_output;
817   RROutput first_output = None;
818   int i;
819   GArray *monitors;
820   gboolean randr12_compat = FALSE;
821 
822   if (!display_x11->have_randr13)
823       return FALSE;
824 
825   resources = XRRGetScreenResourcesCurrent (screen_x11->xdisplay,
826 				            screen_x11->xroot_window);
827   if (!resources)
828     return FALSE;
829 
830   monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor),
831                                 resources->noutput);
832 
833   for (i = 0; i < resources->noutput; ++i)
834     {
835       XRROutputInfo *output =
836 	XRRGetOutputInfo (dpy, resources, resources->outputs[i]);
837 
838       /* Non RandR1.2 X driver have output name "default" */
839       randr12_compat |= !g_strcmp0 (output->name, "default");
840 
841       if (output->connection == RR_Disconnected)
842         {
843           XRRFreeOutputInfo (output);
844           continue;
845         }
846 
847       if (output->crtc)
848 	{
849 	  GdkX11Monitor monitor;
850 	  XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, output->crtc);
851 
852 	  monitor.geometry.x = crtc->x;
853 	  monitor.geometry.y = crtc->y;
854 	  monitor.geometry.width = crtc->width;
855 	  monitor.geometry.height = crtc->height;
856 
857 	  monitor.output = resources->outputs[i];
858 	  monitor.width_mm = output->mm_width;
859 	  monitor.height_mm = output->mm_height;
860 	  monitor.output_name = g_strdup (output->name);
861 	  /* FIXME: need EDID parser */
862 	  monitor.manufacturer = NULL;
863 
864 	  g_array_append_val (monitors, monitor);
865 
866           XRRFreeCrtcInfo (crtc);
867 	}
868 
869       XRRFreeOutputInfo (output);
870     }
871 
872   if (resources->noutput > 0)
873     first_output = resources->outputs[0];
874 
875   XRRFreeScreenResources (resources);
876 
877   /* non RandR 1.2 X driver doesn't return any usable multihead data */
878   if (randr12_compat)
879     {
880       guint n_monitors = monitors->len;
881 
882       free_monitors ((GdkX11Monitor *)g_array_free (monitors, FALSE),
883 		     n_monitors);
884 
885       return FALSE;
886     }
887 
888   g_array_sort (monitors,
889                 (GCompareFunc) monitor_compare_function);
890   screen_x11->n_monitors = monitors->len;
891   screen_x11->monitors = (GdkX11Monitor *)g_array_free (monitors, FALSE);
892 
893   screen_x11->primary_monitor = 0;
894 
895   primary_output = XRRGetOutputPrimary (screen_x11->xdisplay,
896                                         screen_x11->xroot_window);
897 
898   for (i = 0; i < screen_x11->n_monitors; ++i)
899     {
900       if (screen_x11->monitors[i].output == primary_output)
901 	{
902 	  screen_x11->primary_monitor = i;
903 	  break;
904 	}
905 
906       /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */
907       if (primary_output == None &&
908           g_ascii_strncasecmp (screen_x11->monitors[i].output_name, "LVDS", 4) == 0)
909 	{
910 	  screen_x11->primary_monitor = i;
911 	  break;
912 	}
913 
914       /* No primary specified and no LVDS found */
915       if (screen_x11->monitors[i].output == first_output)
916 	screen_x11->primary_monitor = i;
917     }
918 
919   return screen_x11->n_monitors > 0;
920 #endif
921 
922   return FALSE;
923 }
924 
925 static gboolean
init_solaris_xinerama(GdkScreen * screen)926 init_solaris_xinerama (GdkScreen *screen)
927 {
928 #ifdef HAVE_SOLARIS_XINERAMA
929   Display *dpy = GDK_SCREEN_XDISPLAY (screen);
930   int screen_no = gdk_screen_get_number (screen);
931   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
932   XRectangle monitors[MAXFRAMEBUFFERS];
933   unsigned char hints[16];
934   gint result;
935   int n_monitors;
936   int i;
937 
938   if (!XineramaGetState (dpy, screen_no))
939     return FALSE;
940 
941   result = XineramaGetInfo (dpy, screen_no, monitors, hints, &n_monitors);
942 
943   /* Yes I know it should be Success but the current implementation
944    * returns the num of monitor
945    */
946   if (result == 0)
947     {
948       return FALSE;
949     }
950 
951   screen_x11->monitors = g_new0 (GdkX11Monitor, n_monitors);
952   screen_x11->n_monitors = n_monitors;
953 
954   for (i = 0; i < n_monitors; i++)
955     {
956       init_monitor_geometry (&screen_x11->monitors[i],
957 			     monitors[i].x, monitors[i].y,
958 			     monitors[i].width, monitors[i].height);
959     }
960 
961   screen_x11->primary_monitor = 0;
962 
963   return TRUE;
964 #endif /* HAVE_SOLARIS_XINERAMA */
965 
966   return FALSE;
967 }
968 
969 static gboolean
init_xfree_xinerama(GdkScreen * screen)970 init_xfree_xinerama (GdkScreen *screen)
971 {
972 #ifdef HAVE_XFREE_XINERAMA
973   Display *dpy = GDK_SCREEN_XDISPLAY (screen);
974   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
975   XineramaScreenInfo *monitors;
976   int i, n_monitors;
977 
978   if (!XineramaIsActive (dpy))
979     return FALSE;
980 
981   monitors = XineramaQueryScreens (dpy, &n_monitors);
982 
983   if (n_monitors <= 0 || monitors == NULL)
984     {
985       /* If Xinerama doesn't think we have any monitors, try acting as
986        * though we had no Xinerama. If the "no monitors" condition
987        * is because XRandR 1.2 is currently switching between CRTCs,
988        * we'll be notified again when we have our monitor back,
989        * and can go back into Xinerama-ish mode at that point.
990        */
991       if (monitors)
992 	XFree (monitors);
993 
994       return FALSE;
995     }
996 
997   screen_x11->n_monitors = n_monitors;
998   screen_x11->monitors = g_new0 (GdkX11Monitor, n_monitors);
999 
1000   for (i = 0; i < n_monitors; ++i)
1001     {
1002       init_monitor_geometry (&screen_x11->monitors[i],
1003 			     monitors[i].x_org, monitors[i].y_org,
1004 			     monitors[i].width, monitors[i].height);
1005     }
1006 
1007   XFree (monitors);
1008 
1009   screen_x11->primary_monitor = 0;
1010 
1011   return TRUE;
1012 #endif /* HAVE_XFREE_XINERAMA */
1013 
1014   return FALSE;
1015 }
1016 
1017 static void
deinit_multihead(GdkScreen * screen)1018 deinit_multihead (GdkScreen *screen)
1019 {
1020   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1021 
1022   free_monitors (screen_x11->monitors, screen_x11->n_monitors);
1023 
1024   screen_x11->n_monitors = 0;
1025   screen_x11->monitors = NULL;
1026 }
1027 
1028 static gboolean
compare_monitor(GdkX11Monitor * m1,GdkX11Monitor * m2)1029 compare_monitor (GdkX11Monitor *m1,
1030                  GdkX11Monitor *m2)
1031 {
1032   if (m1->geometry.x != m2->geometry.x ||
1033       m1->geometry.y != m2->geometry.y ||
1034       m1->geometry.width != m2->geometry.width ||
1035       m1->geometry.height != m2->geometry.height)
1036     return FALSE;
1037 
1038   if (m1->width_mm != m2->width_mm ||
1039       m1->height_mm != m2->height_mm)
1040     return FALSE;
1041 
1042   if (g_strcmp0 (m1->output_name, m2->output_name) != 0)
1043     return FALSE;
1044 
1045   if (g_strcmp0 (m1->manufacturer, m2->manufacturer) != 0)
1046     return FALSE;
1047 
1048   return TRUE;
1049 }
1050 
1051 static gboolean
compare_monitors(GdkX11Monitor * monitors1,gint n_monitors1,GdkX11Monitor * monitors2,gint n_monitors2)1052 compare_monitors (GdkX11Monitor *monitors1, gint n_monitors1,
1053                   GdkX11Monitor *monitors2, gint n_monitors2)
1054 {
1055   gint i;
1056 
1057   if (n_monitors1 != n_monitors2)
1058     return FALSE;
1059 
1060   for (i = 0; i < n_monitors1; i++)
1061     {
1062       if (!compare_monitor (monitors1 + i, monitors2 + i))
1063         return FALSE;
1064     }
1065 
1066   return TRUE;
1067 }
1068 
1069 static void
init_multihead(GdkScreen * screen)1070 init_multihead (GdkScreen *screen)
1071 {
1072   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1073   int opcode, firstevent, firsterror;
1074 
1075   /* There are four different implementations of multihead support:
1076    *
1077    *  1. Fake Xinerama for debugging purposes
1078    *  2. RandR 1.2
1079    *  3. Solaris Xinerama
1080    *  4. XFree86/Xorg Xinerama
1081    *
1082    * We use them in that order.
1083    */
1084   if (init_fake_xinerama (screen))
1085     return;
1086 
1087 #ifdef HAVE_RANDR15
1088   if (init_randr15 (screen))
1089     return;
1090 #endif
1091 
1092   if (init_randr13 (screen))
1093     return;
1094 
1095   if (XQueryExtension (GDK_SCREEN_XDISPLAY (screen), "XINERAMA",
1096 		       &opcode, &firstevent, &firsterror))
1097     {
1098       if (init_solaris_xinerama (screen))
1099 	return;
1100 
1101       if (init_xfree_xinerama (screen))
1102 	return;
1103     }
1104 
1105   /* No multihead support of any kind for this screen */
1106   screen_x11->n_monitors = 1;
1107   screen_x11->monitors = g_new0 (GdkX11Monitor, 1);
1108   screen_x11->primary_monitor = 0;
1109 
1110   init_monitor_geometry (screen_x11->monitors, 0, 0,
1111 			 WidthOfScreen (screen_x11->xscreen),
1112 			 HeightOfScreen (screen_x11->xscreen));
1113 }
1114 
1115 GdkScreen *
_gdk_x11_screen_new(GdkDisplay * display,gint screen_number)1116 _gdk_x11_screen_new (GdkDisplay *display,
1117 		     gint	 screen_number)
1118 {
1119   GdkScreen *screen;
1120   GdkScreenX11 *screen_x11;
1121   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1122 
1123   screen = g_object_new (GDK_TYPE_SCREEN_X11, NULL);
1124 
1125   screen_x11 = GDK_SCREEN_X11 (screen);
1126   screen_x11->display = display;
1127   screen_x11->xdisplay = display_x11->xdisplay;
1128   screen_x11->xscreen = ScreenOfDisplay (display_x11->xdisplay, screen_number);
1129   screen_x11->screen_num = screen_number;
1130   screen_x11->xroot_window = RootWindow (display_x11->xdisplay,screen_number);
1131   screen_x11->wmspec_check_window = None;
1132   /* we want this to be always non-null */
1133   screen_x11->window_manager_name = g_strdup ("unknown");
1134 
1135   init_multihead (screen);
1136   init_randr_support (screen);
1137 
1138   _gdk_visual_init (screen);
1139   _gdk_windowing_window_init (screen);
1140 
1141   return screen;
1142 }
1143 
1144 /*
1145  * It is important that we first request the selection
1146  * notification, and then setup the initial state of
1147  * is_composited to avoid a race condition here.
1148  */
1149 void
_gdk_x11_screen_setup(GdkScreen * screen)1150 _gdk_x11_screen_setup (GdkScreen *screen)
1151 {
1152   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1153 
1154   screen_x11->cm_selection_atom = make_cm_atom (screen_x11->screen_num);
1155   gdk_display_request_selection_notification (screen_x11->display,
1156 					      screen_x11->cm_selection_atom);
1157   screen_x11->is_composited = check_is_composited (screen_x11->display, screen_x11);
1158 }
1159 
1160 /**
1161  * gdk_screen_is_composited:
1162  * @screen: a #GdkScreen
1163  *
1164  * Returns whether windows with an RGBA visual can reasonably
1165  * be expected to have their alpha channel drawn correctly on
1166  * the screen.
1167  *
1168  * On X11 this function returns whether a compositing manager is
1169  * compositing @screen.
1170  *
1171  * Return value: Whether windows with RGBA visuals can reasonably be
1172  * expected to have their alpha channels drawn correctly on the screen.
1173  *
1174  * Since: 2.10
1175  **/
1176 gboolean
gdk_screen_is_composited(GdkScreen * screen)1177 gdk_screen_is_composited (GdkScreen *screen)
1178 {
1179   GdkScreenX11 *screen_x11;
1180 
1181   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
1182 
1183   screen_x11 = GDK_SCREEN_X11 (screen);
1184 
1185   return screen_x11->is_composited;
1186 }
1187 
1188 static void
init_randr_support(GdkScreen * screen)1189 init_randr_support (GdkScreen * screen)
1190 {
1191   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1192 
1193   XSelectInput (GDK_SCREEN_XDISPLAY (screen),
1194 		screen_x11->xroot_window,
1195 		StructureNotifyMask);
1196 
1197 #ifdef HAVE_RANDR
1198   XRRSelectInput (GDK_SCREEN_XDISPLAY (screen),
1199 		  screen_x11->xroot_window,
1200 		  RRScreenChangeNotifyMask	|
1201 		  RRCrtcChangeNotifyMask	|
1202 		  RROutputPropertyNotifyMask);
1203 #endif
1204 }
1205 
1206 static void
process_monitors_change(GdkScreen * screen)1207 process_monitors_change (GdkScreen *screen)
1208 {
1209   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1210   gint		 n_monitors;
1211   gint		 primary_monitor;
1212   GdkX11Monitor	*monitors;
1213   gboolean changed;
1214 
1215   primary_monitor = screen_x11->primary_monitor;
1216   n_monitors = screen_x11->n_monitors;
1217   monitors = screen_x11->monitors;
1218 
1219   screen_x11->n_monitors = 0;
1220   screen_x11->monitors = NULL;
1221 
1222   init_multihead (screen);
1223 
1224   changed =
1225     !compare_monitors (monitors, n_monitors,
1226 		       screen_x11->monitors, screen_x11->n_monitors) ||
1227     screen_x11->primary_monitor != primary_monitor;
1228 
1229   free_monitors (monitors, n_monitors);
1230 
1231   if (changed)
1232     g_signal_emit_by_name (screen, "monitors-changed");
1233 }
1234 
1235 void
_gdk_x11_screen_size_changed(GdkScreen * screen,XEvent * event)1236 _gdk_x11_screen_size_changed (GdkScreen *screen,
1237 			      XEvent    *event)
1238 {
1239   gint width, height;
1240 #ifdef HAVE_RANDR
1241   GdkDisplayX11 *display_x11;
1242 #endif
1243 
1244   width = gdk_screen_get_width (screen);
1245   height = gdk_screen_get_height (screen);
1246 
1247 #ifdef HAVE_RANDR
1248   display_x11 = GDK_DISPLAY_X11 (gdk_screen_get_display (screen));
1249 
1250   if (display_x11->have_randr13 && event->type == ConfigureNotify)
1251     return;
1252 
1253   XRRUpdateConfiguration (event);
1254 #else
1255   if (event->type == ConfigureNotify)
1256     {
1257       XConfigureEvent *rcevent = (XConfigureEvent *) event;
1258       Screen	    *xscreen = gdk_x11_screen_get_xscreen (screen);
1259 
1260       xscreen->width   = rcevent->width;
1261       xscreen->height  = rcevent->height;
1262     }
1263   else
1264     return;
1265 #endif
1266 
1267   process_monitors_change (screen);
1268 
1269   if (width != gdk_screen_get_width (screen) ||
1270       height != gdk_screen_get_height (screen))
1271     g_signal_emit_by_name (screen, "size-changed");
1272 }
1273 
1274 void
_gdk_x11_screen_window_manager_changed(GdkScreen * screen)1275 _gdk_x11_screen_window_manager_changed (GdkScreen *screen)
1276 {
1277   g_signal_emit (screen, signals[WINDOW_MANAGER_CHANGED], 0);
1278 }
1279 
1280 void
_gdk_x11_screen_process_owner_change(GdkScreen * screen,XEvent * event)1281 _gdk_x11_screen_process_owner_change (GdkScreen *screen,
1282 				      XEvent *event)
1283 {
1284 #ifdef HAVE_XFIXES
1285   XFixesSelectionNotifyEvent *selection_event = (XFixesSelectionNotifyEvent *)event;
1286   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1287   Atom xcm_selection_atom = gdk_x11_atom_to_xatom_for_display (screen_x11->display,
1288 							       screen_x11->cm_selection_atom);
1289 
1290   if (selection_event->selection == xcm_selection_atom)
1291     {
1292       gboolean composited = selection_event->owner != None;
1293 
1294       if (composited != screen_x11->is_composited)
1295 	{
1296 	  screen_x11->is_composited = composited;
1297 
1298 	  g_signal_emit_by_name (screen, "composited-changed");
1299 	}
1300     }
1301 #endif
1302 }
1303 
1304 /**
1305  * _gdk_windowing_substitute_screen_number:
1306  * @display_name : The name of a display, in the form used by
1307  *                 gdk_display_open (). If %NULL a default value
1308  *                 will be used. On X11, this is derived from the DISPLAY
1309  *                 environment variable.
1310  * @screen_number : The number of a screen within the display
1311  *                  referred to by @display_name.
1312  *
1313  * Modifies a @display_name to make @screen_number the default
1314  * screen when the display is opened.
1315  *
1316  * Return value: a newly allocated string holding the resulting
1317  *   display name. Free with g_free().
1318  */
1319 gchar *
_gdk_windowing_substitute_screen_number(const gchar * display_name,gint screen_number)1320 _gdk_windowing_substitute_screen_number (const gchar *display_name,
1321 					 gint         screen_number)
1322 {
1323   GString *str;
1324   gchar   *p;
1325 
1326   if (!display_name)
1327     display_name = getenv ("DISPLAY");
1328 
1329   if (!display_name)
1330     return NULL;
1331 
1332   str = g_string_new (display_name);
1333 
1334   p = strrchr (str->str, '.');
1335   if (p && p >	strchr (str->str, ':'))
1336     g_string_truncate (str, p - str->str);
1337 
1338   g_string_append_printf (str, ".%d", screen_number);
1339 
1340   return g_string_free (str, FALSE);
1341 }
1342 
1343 /**
1344  * gdk_screen_make_display_name:
1345  * @screen: a #GdkScreen
1346  *
1347  * Determines the name to pass to gdk_display_open() to get
1348  * a #GdkDisplay with this screen as the default screen.
1349  *
1350  * Return value: a newly allocated string, free with g_free()
1351  *
1352  * Since: 2.2
1353  **/
1354 gchar *
gdk_screen_make_display_name(GdkScreen * screen)1355 gdk_screen_make_display_name (GdkScreen *screen)
1356 {
1357   const gchar *old_display;
1358 
1359   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1360 
1361   old_display = gdk_display_get_name (gdk_screen_get_display (screen));
1362 
1363   return _gdk_windowing_substitute_screen_number (old_display,
1364 						  gdk_screen_get_number (screen));
1365 }
1366 
1367 /**
1368  * gdk_screen_get_active_window
1369  * @screen: a #GdkScreen
1370  *
1371  * Returns the screen's currently active window.
1372  *
1373  * On X11, this is done by inspecting the _NET_ACTIVE_WINDOW property
1374  * on the root window, as described in the <ulink
1375  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
1376  * Manager Hints</ulink>. If there is no currently currently active
1377  * window, or the window manager does not support the
1378  * _NET_ACTIVE_WINDOW hint, this function returns %NULL.
1379  *
1380  * On other platforms, this function may return %NULL, depending on whether
1381  * it is implementable on that platform.
1382  *
1383  * The returned window should be unrefed using g_object_unref() when
1384  * no longer needed.
1385  *
1386  * Return value: the currently active window, or %NULL.
1387  *
1388  * Since: 2.10
1389  **/
1390 GdkWindow *
gdk_screen_get_active_window(GdkScreen * screen)1391 gdk_screen_get_active_window (GdkScreen *screen)
1392 {
1393   GdkScreenX11 *screen_x11;
1394   GdkWindow *ret = NULL;
1395   Atom type_return;
1396   gint format_return;
1397   gulong nitems_return;
1398   gulong bytes_after_return;
1399   guchar *data = NULL;
1400 
1401   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1402 
1403   if (!gdk_x11_screen_supports_net_wm_hint (screen,
1404                                             gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
1405     return NULL;
1406 
1407   screen_x11 = GDK_SCREEN_X11 (screen);
1408 
1409   if (XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1410 	                  gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
1411 			                                         "_NET_ACTIVE_WINDOW"),
1412 		          0, 1, False, XA_WINDOW, &type_return,
1413 		          &format_return, &nitems_return,
1414                           &bytes_after_return, &data)
1415       == Success)
1416     {
1417       if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
1418         {
1419           GdkNativeWindow window = *(GdkNativeWindow *) data;
1420 
1421           if (window != None)
1422             {
1423               ret = gdk_window_foreign_new_for_display (screen_x11->display,
1424                                                         *(GdkNativeWindow *) data);
1425             }
1426         }
1427     }
1428 
1429   if (data)
1430     XFree (data);
1431 
1432   return ret;
1433 }
1434 
1435 /**
1436  * gdk_screen_get_window_stack:
1437  * @screen: a #GdkScreen
1438  *
1439  * Returns a #GList of #GdkWindow<!-- -->s representing the current
1440  * window stack.
1441  *
1442  * On X11, this is done by inspecting the _NET_CLIENT_LIST_STACKING
1443  * property on the root window, as described in the <ulink
1444  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
1445  * Manager Hints</ulink>. If the window manager does not support the
1446  * _NET_CLIENT_LIST_STACKING hint, this function returns %NULL.
1447  *
1448  * On other platforms, this function may return %NULL, depending on whether
1449  * it is implementable on that platform.
1450  *
1451  * The returned list is newly allocated and owns references to the
1452  * windows it contains, so it should be freed using g_list_free() and
1453  * its windows unrefed using g_object_unref() when no longer needed.
1454  *
1455  * Return value: (transfer full) (element-type GdkWindow):
1456  *     a list of #GdkWindow<!-- -->s for the current window stack,
1457  *               or %NULL.
1458  *
1459  * Since: 2.10
1460  **/
1461 GList *
gdk_screen_get_window_stack(GdkScreen * screen)1462 gdk_screen_get_window_stack (GdkScreen *screen)
1463 {
1464   GdkScreenX11 *screen_x11;
1465   GList *ret = NULL;
1466   Atom type_return;
1467   gint format_return;
1468   gulong nitems_return;
1469   gulong bytes_after_return;
1470   guchar *data = NULL;
1471 
1472   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1473 
1474   if (!gdk_x11_screen_supports_net_wm_hint (screen,
1475                                             gdk_atom_intern_static_string ("_NET_CLIENT_LIST_STACKING")))
1476     return NULL;
1477 
1478   screen_x11 = GDK_SCREEN_X11 (screen);
1479 
1480   if (XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1481 	                  gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
1482 			                                         "_NET_CLIENT_LIST_STACKING"),
1483 		          0, G_MAXLONG, False, XA_WINDOW, &type_return,
1484 		          &format_return, &nitems_return,
1485                           &bytes_after_return, &data)
1486       == Success)
1487     {
1488       if ((type_return == XA_WINDOW) && (format_return == 32) &&
1489           (data) && (nitems_return > 0))
1490         {
1491           gulong *stack = (gulong *) data;
1492           GdkWindow *win;
1493           int i;
1494 
1495           for (i = 0; i < nitems_return; i++)
1496             {
1497               win = gdk_window_foreign_new_for_display (screen_x11->display,
1498                                                         (GdkNativeWindow)stack[i]);
1499 
1500               if (win != NULL)
1501                 ret = g_list_append (ret, win);
1502             }
1503         }
1504     }
1505 
1506   if (data)
1507     XFree (data);
1508 
1509   return ret;
1510 }
1511 
1512 #define __GDK_SCREEN_X11_C__
1513 #include "gdkaliasdef.c"
1514