]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkscreen-x11.c
Silence a few warnings in !HAVE_RANDR builds
[~andy/gtk] / gdk / x11 / gdkscreen-x11.c
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 #include "gdksettings.c"
55
56 static void         gdk_screen_x11_dispose     (GObject           *object);
57 static void         gdk_screen_x11_finalize    (GObject           *object);
58 static void         init_randr_support         (GdkScreen         *screen);
59 static void         deinit_multihead           (GdkScreen         *screen);
60
61 enum
62 {
63   WINDOW_MANAGER_CHANGED,
64   LAST_SIGNAL
65 };
66
67 static guint signals[LAST_SIGNAL] = { 0 };
68
69 G_DEFINE_TYPE (GdkScreenX11, _gdk_screen_x11, GDK_TYPE_SCREEN)
70
71 typedef struct _NetWmSupportedAtoms NetWmSupportedAtoms;
72
73 struct _NetWmSupportedAtoms
74 {
75   Atom *atoms;
76   gulong n_atoms;
77 };
78
79 struct _GdkX11Monitor
80 {
81   GdkRectangle  geometry;
82   XID           output;
83   int           width_mm;
84   int           height_mm;
85   char *        output_name;
86   char *        manufacturer;
87 };
88
89 static void
90 _gdk_screen_x11_class_init (GdkScreenX11Class *klass)
91 {
92   GObjectClass *object_class = G_OBJECT_CLASS (klass);
93   
94   object_class->dispose = gdk_screen_x11_dispose;
95   object_class->finalize = gdk_screen_x11_finalize;
96
97   signals[WINDOW_MANAGER_CHANGED] =
98     g_signal_new (g_intern_static_string ("window_manager_changed"),
99                   G_OBJECT_CLASS_TYPE (object_class),
100                   G_SIGNAL_RUN_LAST,
101                   G_STRUCT_OFFSET (GdkScreenX11Class, window_manager_changed),
102                   NULL, NULL,
103                   g_cclosure_marshal_VOID__VOID,
104                   G_TYPE_NONE,
105                   0);
106 }
107
108 static void
109 _gdk_screen_x11_init (GdkScreenX11 *screen)
110 {
111 }
112
113 /**
114  * gdk_screen_get_display:
115  * @screen: a #GdkScreen
116  *
117  * Gets the display to which the @screen belongs.
118  * 
119  * Returns: the display to which @screen belongs
120  *
121  * Since: 2.2
122  **/
123 GdkDisplay *
124 gdk_screen_get_display (GdkScreen *screen)
125 {
126   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
127
128   return GDK_SCREEN_X11 (screen)->display;
129 }
130 /**
131  * gdk_screen_get_width:
132  * @screen: a #GdkScreen
133  *
134  * Gets the width of @screen in pixels
135  * 
136  * Returns: the width of @screen in pixels.
137  *
138  * Since: 2.2
139  **/
140 gint
141 gdk_screen_get_width (GdkScreen *screen)
142 {
143   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
144
145   return WidthOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
146 }
147
148 /**
149  * gdk_screen_get_height:
150  * @screen: a #GdkScreen
151  *
152  * Gets the height of @screen in pixels
153  * 
154  * Returns: the height of @screen in pixels.
155  *
156  * Since: 2.2
157  **/
158 gint
159 gdk_screen_get_height (GdkScreen *screen)
160 {
161   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
162
163   return HeightOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
164 }
165
166 /**
167  * gdk_screen_get_width_mm:
168  * @screen: a #GdkScreen
169  *
170  * Gets the width of @screen in millimeters. 
171  * Note that on some X servers this value will not be correct.
172  * 
173  * Returns: the width of @screen in millimeters.
174  *
175  * Since: 2.2
176  **/
177 gint
178 gdk_screen_get_width_mm (GdkScreen *screen)
179 {
180   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);  
181
182   return WidthMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
183 }
184
185 /**
186  * gdk_screen_get_height_mm:
187  * @screen: a #GdkScreen
188  *
189  * Returns the height of @screen in millimeters. 
190  * Note that on some X servers this value will not be correct.
191  * 
192  * Returns: the heigth of @screen in millimeters.
193  *
194  * Since: 2.2
195  **/
196 gint
197 gdk_screen_get_height_mm (GdkScreen *screen)
198 {
199   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
200
201   return HeightMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
202 }
203
204 /**
205  * gdk_screen_get_number:
206  * @screen: a #GdkScreen
207  *
208  * Gets the index of @screen among the screens in the display
209  * to which it belongs. (See gdk_screen_get_display())
210  * 
211  * Returns: the index
212  *
213  * Since: 2.2
214  **/
215 gint
216 gdk_screen_get_number (GdkScreen *screen)
217 {
218   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
219   
220   return GDK_SCREEN_X11 (screen)->screen_num;
221 }
222
223 /**
224  * gdk_screen_get_root_window:
225  * @screen: a #GdkScreen
226  *
227  * Gets the root window of @screen.
228  *
229  * Returns: (transfer none): the root window
230  *
231  * Since: 2.2
232  **/
233 GdkWindow *
234 gdk_screen_get_root_window (GdkScreen *screen)
235 {
236   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
237
238   return GDK_SCREEN_X11 (screen)->root_window;
239 }
240
241 /**
242  * gdk_screen_get_default_colormap:
243  * @screen: a #GdkScreen
244  *
245  * Gets the default colormap for @screen.
246  * 
247  * Returns: (transfer none): the default #GdkColormap.
248  *
249  * Since: 2.2
250  **/
251 GdkColormap *
252 gdk_screen_get_default_colormap (GdkScreen *screen)
253 {
254   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
255
256   return GDK_SCREEN_X11 (screen)->default_colormap;
257 }
258
259 /**
260  * gdk_screen_set_default_colormap:
261  * @screen: a #GdkScreen
262  * @colormap: a #GdkColormap
263  *
264  * Sets the default @colormap for @screen.
265  *
266  * Since: 2.2
267  **/
268 void
269 gdk_screen_set_default_colormap (GdkScreen   *screen,
270                                  GdkColormap *colormap)
271 {
272   GdkColormap *old_colormap;
273   
274   g_return_if_fail (GDK_IS_SCREEN (screen));
275   g_return_if_fail (GDK_IS_COLORMAP (colormap));
276
277   old_colormap = GDK_SCREEN_X11 (screen)->default_colormap;
278
279   GDK_SCREEN_X11 (screen)->default_colormap = g_object_ref (colormap);
280   
281   if (old_colormap)
282     g_object_unref (old_colormap);
283 }
284
285 static void
286 _gdk_screen_x11_events_uninit (GdkScreen *screen)
287 {
288   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
289
290   if (screen_x11->xsettings_client)
291     {
292       xsettings_client_destroy (screen_x11->xsettings_client);
293       screen_x11->xsettings_client = NULL;
294     }
295 }
296
297 static void
298 gdk_screen_x11_dispose (GObject *object)
299 {
300   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
301
302   _gdk_screen_x11_events_uninit (GDK_SCREEN (object));
303
304   if (screen_x11->default_colormap)
305     {
306       g_object_unref (screen_x11->default_colormap);
307       screen_x11->default_colormap = NULL;
308     }
309
310   if (screen_x11->system_colormap)
311     {
312       g_object_unref (screen_x11->system_colormap);
313       screen_x11->system_colormap = NULL;
314     }
315
316   if (screen_x11->rgba_colormap)
317     {
318       g_object_unref (screen_x11->rgba_colormap);
319       screen_x11->rgba_colormap = NULL;
320     }
321
322   if (screen_x11->root_window)
323     _gdk_window_destroy (screen_x11->root_window, TRUE);
324
325   G_OBJECT_CLASS (_gdk_screen_x11_parent_class)->dispose (object);
326
327   screen_x11->xdisplay = NULL;
328   screen_x11->xscreen = NULL;
329   screen_x11->screen_num = -1;
330   screen_x11->xroot_window = None;
331   screen_x11->wmspec_check_window = None;
332 }
333
334 static void
335 gdk_screen_x11_finalize (GObject *object)
336 {
337   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
338   gint          i;
339
340   if (screen_x11->root_window)
341     g_object_unref (screen_x11->root_window);
342
343   if (screen_x11->renderer)
344     g_object_unref (screen_x11->renderer);
345
346   /* Visual Part */
347   for (i = 0; i < screen_x11->nvisuals; i++)
348     g_object_unref (screen_x11->visuals[i]);
349   g_free (screen_x11->visuals);
350   g_hash_table_destroy (screen_x11->visual_hash);
351
352   g_free (screen_x11->window_manager_name);
353
354   g_hash_table_destroy (screen_x11->colormap_hash);
355
356   deinit_multihead (GDK_SCREEN (object));
357   
358   G_OBJECT_CLASS (_gdk_screen_x11_parent_class)->finalize (object);
359 }
360
361 /**
362  * gdk_screen_get_n_monitors:
363  * @screen: a #GdkScreen
364  *
365  * Returns the number of monitors which @screen consists of.
366  *
367  * Returns: number of monitors which @screen consists of
368  *
369  * Since: 2.2
370  */
371 gint
372 gdk_screen_get_n_monitors (GdkScreen *screen)
373 {
374   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
375
376   return GDK_SCREEN_X11 (screen)->n_monitors;
377 }
378
379 /**
380  * gdk_screen_get_primary_monitor:
381  * @screen: a #GdkScreen.
382  *
383  * Gets the primary monitor for @screen.  The primary monitor
384  * is considered the monitor where the 'main desktop' lives.
385  * While normal application windows typically allow the window
386  * manager to place the windows, specialized desktop applications
387  * such as panels should place themselves on the primary monitor.
388  *
389  * If no primary monitor is configured by the user, the return value
390  * will be 0, defaulting to the first monitor.
391  *
392  * Returns: An integer index for the primary monitor, or 0 if none is configured.
393  *
394  * Since: 2.20
395  */
396 gint
397 gdk_screen_get_primary_monitor (GdkScreen *screen)
398 {
399   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
400
401   return GDK_SCREEN_X11 (screen)->primary_monitor;
402 }
403
404 /**
405  * gdk_screen_get_monitor_width_mm:
406  * @screen: a #GdkScreen
407  * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
408  *
409  * Gets the width in millimeters of the specified monitor, if available.
410  *
411  * Returns: the width of the monitor, or -1 if not available
412  *
413  * Since: 2.14
414  */
415 gint
416 gdk_screen_get_monitor_width_mm (GdkScreen *screen,
417                                  gint       monitor_num)
418 {
419   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
420
421   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
422   g_return_val_if_fail (monitor_num >= 0, -1);
423   g_return_val_if_fail (monitor_num < screen_x11->n_monitors, -1);
424
425   return screen_x11->monitors[monitor_num].width_mm;
426 }
427
428 /**
429  * gdk_screen_get_monitor_height_mm:
430  * @screen: a #GdkScreen
431  * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
432  *
433  * Gets the height in millimeters of the specified monitor.
434  *
435  * Returns: the height of the monitor, or -1 if not available
436  *
437  * Since: 2.14
438  */
439 gint
440 gdk_screen_get_monitor_height_mm (GdkScreen *screen,
441                                   gint       monitor_num)
442 {
443   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
444
445   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
446   g_return_val_if_fail (monitor_num >= 0, -1);
447   g_return_val_if_fail (monitor_num < screen_x11->n_monitors, -1);
448
449   return screen_x11->monitors[monitor_num].height_mm;
450 }
451
452 /**
453  * gdk_screen_get_monitor_plug_name:
454  * @screen: a #GdkScreen
455  * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
456  *
457  * Returns the output name of the specified monitor.
458  * Usually something like VGA, DVI, or TV, not the actual
459  * product name of the display device.
460  *
461  * Returns: a newly-allocated string containing the name of the monitor,
462  *   or %NULL if the name cannot be determined
463  *
464  * Since: 2.14
465  */
466 gchar *
467 gdk_screen_get_monitor_plug_name (GdkScreen *screen,
468                                   gint       monitor_num)
469 {
470   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
471
472   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
473   g_return_val_if_fail (monitor_num >= 0, NULL);
474   g_return_val_if_fail (monitor_num < screen_x11->n_monitors, NULL);
475
476   return g_strdup (screen_x11->monitors[monitor_num].output_name);
477 }
478
479 /**
480  * gdk_x11_screen_get_monitor_output:
481  * @screen: a #GdkScreen
482  * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
483  *
484  * Gets the XID of the specified output/monitor.
485  * If the X server does not support version 1.2 of the RANDR
486  * extension, 0 is returned.
487  *
488  * Returns: the XID of the monitor
489  *
490  * Since: 2.14
491  */
492 XID
493 gdk_x11_screen_get_monitor_output (GdkScreen *screen,
494                                    gint       monitor_num)
495 {
496   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
497
498   g_return_val_if_fail (GDK_IS_SCREEN (screen), None);
499   g_return_val_if_fail (monitor_num >= 0, None);
500   g_return_val_if_fail (monitor_num < screen_x11->n_monitors, None);
501
502   return screen_x11->monitors[monitor_num].output;
503 }
504
505 /**
506  * gdk_screen_get_monitor_geometry:
507  * @screen : a #GdkScreen
508  * @monitor_num: the monitor number, between 0 and gdk_screen_get_n_monitors (screen)
509  * @dest : a #GdkRectangle to be filled with the monitor geometry
510  *
511  * Retrieves the #GdkRectangle representing the size and position of
512  * the individual monitor within the entire screen area.
513  *
514  * Note that the size of the entire screen area can be retrieved via
515  * gdk_screen_get_width() and gdk_screen_get_height().
516  *
517  * Since: 2.2
518  */
519 void
520 gdk_screen_get_monitor_geometry (GdkScreen    *screen,
521                                  gint          monitor_num,
522                                  GdkRectangle *dest)
523 {
524   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
525
526   g_return_if_fail (GDK_IS_SCREEN (screen));
527   g_return_if_fail (monitor_num >= 0);
528   g_return_if_fail (monitor_num < screen_x11->n_monitors);
529
530   if (dest)
531     *dest = screen_x11->monitors[monitor_num].geometry;
532 }
533
534 /**
535  * gdk_screen_get_rgba_colormap:
536  * @screen: a #GdkScreen.
537  * 
538  * Gets a colormap to use for creating windows or pixmaps with an
539  * alpha channel. The windowing system on which GTK+ is running
540  * may not support this capability, in which case %NULL will
541  * be returned. Even if a non-%NULL value is returned, its
542  * possible that the window's alpha channel won't be honored
543  * when displaying the window on the screen: in particular, for
544  * X an appropriate windowing manager and compositing manager
545  * must be running to provide appropriate display.
546  *
547  * This functionality is not implemented in the Windows backend.
548  *
549  * For setting an overall opacity for a top-level window, see
550  * gdk_window_set_opacity().
551
552  * Return value: (transfer none): a colormap to use for windows with
553  *     an alpha channel or %NULL if the capability is not available.
554  *
555  * Since: 2.8
556  **/
557 GdkColormap *
558 gdk_screen_get_rgba_colormap (GdkScreen *screen)
559 {
560   GdkScreenX11 *screen_x11;
561
562   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
563
564   screen_x11 = GDK_SCREEN_X11 (screen);
565
566   if (!screen_x11->rgba_visual)
567     return NULL;
568
569   if (!screen_x11->rgba_colormap)
570     screen_x11->rgba_colormap = gdk_colormap_new (screen_x11->rgba_visual,
571                                                   FALSE);
572   
573   return screen_x11->rgba_colormap;
574 }
575
576 /**
577  * gdk_screen_get_rgba_visual:
578  * @screen: a #GdkScreen
579  * 
580  * Gets a visual to use for creating windows or pixmaps with an
581  * alpha channel. See the docs for gdk_screen_get_rgba_colormap()
582  * for caveats.
583  * 
584  * Return value: (transfer none): a visual to use for windows with an
585  *     alpha channel or %NULL if the capability is not available.
586  *
587  * Since: 2.8
588  **/
589 GdkVisual *
590 gdk_screen_get_rgba_visual (GdkScreen *screen)
591 {
592   GdkScreenX11 *screen_x11;
593
594   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
595
596   screen_x11 = GDK_SCREEN_X11 (screen);
597
598   return screen_x11->rgba_visual;
599 }
600
601 /**
602  * gdk_x11_screen_get_xscreen:
603  * @screen: a #GdkScreen.
604  * @returns: (transfer none): an Xlib <type>Screen*</type>
605  *
606  * Returns the screen of a #GdkScreen.
607  *
608  * Since: 2.2
609  */
610 Screen *
611 gdk_x11_screen_get_xscreen (GdkScreen *screen)
612 {
613   return GDK_SCREEN_X11 (screen)->xscreen;
614 }
615
616 /**
617  * gdk_x11_screen_get_screen_number:
618  * @screen: a #GdkScreen.
619  * @returns: the position of @screen among the screens of
620  *   its display.
621  *
622  * Returns the index of a #GdkScreen.
623  *
624  * Since: 2.2
625  */
626 int
627 gdk_x11_screen_get_screen_number (GdkScreen *screen)
628 {
629   return GDK_SCREEN_X11 (screen)->screen_num;
630 }
631
632 static gboolean
633 check_is_composited (GdkDisplay *display,
634                      GdkScreenX11 *screen_x11)
635 {
636   Atom xselection = gdk_x11_atom_to_xatom_for_display (display, screen_x11->cm_selection_atom);
637   Window xwindow;
638   
639   xwindow = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display), xselection);
640
641   return xwindow != None;
642 }
643
644 static GdkAtom
645 make_cm_atom (int screen_number)
646 {
647   gchar *name = g_strdup_printf ("_NET_WM_CM_S%d", screen_number);
648   GdkAtom atom = gdk_atom_intern (name, FALSE);
649   g_free (name);
650   return atom;
651 }
652
653 static void
654 init_monitor_geometry (GdkX11Monitor *monitor,
655                        int x, int y, int width, int height)
656 {
657   monitor->geometry.x = x;
658   monitor->geometry.y = y;
659   monitor->geometry.width = width;
660   monitor->geometry.height = height;
661
662   monitor->output = None;
663   monitor->width_mm = -1;
664   monitor->height_mm = -1;
665   monitor->output_name = NULL;
666   monitor->manufacturer = NULL;
667 }
668
669 static gboolean
670 init_fake_xinerama (GdkScreen *screen)
671 {
672 #ifdef G_ENABLE_DEBUG
673   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
674   XSetWindowAttributes atts;
675   Window win;
676   gint w, h;
677
678   if (!(_gdk_debug_flags & GDK_DEBUG_XINERAMA))
679     return FALSE;
680   
681   /* Fake Xinerama mode by splitting the screen into 4 monitors.
682    * Also draw a little cross to make the monitor boundaries visible.
683    */
684   w = WidthOfScreen (screen_x11->xscreen);
685   h = HeightOfScreen (screen_x11->xscreen);
686
687   screen_x11->n_monitors = 4;
688   screen_x11->monitors = g_new0 (GdkX11Monitor, 4);
689   init_monitor_geometry (&screen_x11->monitors[0], 0, 0, w / 2, h / 2);
690   init_monitor_geometry (&screen_x11->monitors[1], w / 2, 0, w / 2, h / 2);
691   init_monitor_geometry (&screen_x11->monitors[2], 0, h / 2, w / 2, h / 2);
692   init_monitor_geometry (&screen_x11->monitors[3], w / 2, h / 2, w / 2, h / 2);
693   
694   atts.override_redirect = 1;
695   atts.background_pixel = WhitePixel(GDK_SCREEN_XDISPLAY (screen), 
696                                      screen_x11->screen_num);
697   win = XCreateWindow(GDK_SCREEN_XDISPLAY (screen), 
698                       screen_x11->xroot_window, 0, h / 2, w, 1, 0, 
699                       DefaultDepth(GDK_SCREEN_XDISPLAY (screen), 
700                                    screen_x11->screen_num),
701                       InputOutput, 
702                       DefaultVisual(GDK_SCREEN_XDISPLAY (screen), 
703                                     screen_x11->screen_num),
704                       CWOverrideRedirect|CWBackPixel, 
705                       &atts);
706   XMapRaised(GDK_SCREEN_XDISPLAY (screen), win); 
707   win = XCreateWindow(GDK_SCREEN_XDISPLAY (screen), 
708                       screen_x11->xroot_window, w/2 , 0, 1, h, 0, 
709                       DefaultDepth(GDK_SCREEN_XDISPLAY (screen), 
710                                    screen_x11->screen_num),
711                       InputOutput, 
712                       DefaultVisual(GDK_SCREEN_XDISPLAY (screen), 
713                                     screen_x11->screen_num),
714                       CWOverrideRedirect|CWBackPixel, 
715                       &atts);
716   XMapRaised(GDK_SCREEN_XDISPLAY (screen), win);
717   return TRUE;
718 #endif
719   
720   return FALSE;
721 }
722
723 static void
724 free_monitors (GdkX11Monitor *monitors,
725                gint           n_monitors)
726 {
727   int i;
728
729   for (i = 0; i < n_monitors; ++i)
730     {
731       g_free (monitors[i].output_name);
732       g_free (monitors[i].manufacturer);
733     }
734
735   g_free (monitors);
736 }
737
738 #ifdef HAVE_RANDR
739 static int
740 monitor_compare_function (GdkX11Monitor *monitor1,
741                           GdkX11Monitor *monitor2)
742 {
743   /* Sort the leftmost/topmost monitors first.
744    * For "cloned" monitors, sort the bigger ones first
745    * (giving preference to taller monitors over wider
746    * monitors)
747    */
748
749   if (monitor1->geometry.x != monitor2->geometry.x)
750     return monitor1->geometry.x - monitor2->geometry.x;
751
752   if (monitor1->geometry.y != monitor2->geometry.y)
753     return monitor1->geometry.y - monitor2->geometry.y;
754
755   if (monitor1->geometry.height != monitor2->geometry.height)
756     return - (monitor1->geometry.height - monitor2->geometry.height);
757
758   if (monitor1->geometry.width != monitor2->geometry.width)
759     return - (monitor1->geometry.width - monitor2->geometry.width);
760
761   return 0;
762 }
763 #endif
764
765 static gboolean
766 init_randr13 (GdkScreen *screen)
767 {
768 #ifdef HAVE_RANDR
769   GdkDisplay *display = gdk_screen_get_display (screen);
770   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
771   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
772   Display *dpy = GDK_SCREEN_XDISPLAY (screen);
773   XRRScreenResources *resources;
774   RROutput primary_output;
775   RROutput first_output = None;
776   int i;
777   GArray *monitors;
778   gboolean randr12_compat = FALSE;
779
780   if (!display_x11->have_randr13)
781       return FALSE;
782
783   resources = XRRGetScreenResourcesCurrent (screen_x11->xdisplay,
784                                             screen_x11->xroot_window);
785   if (!resources)
786     return FALSE;
787
788   monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor),
789                                 resources->noutput);
790
791   for (i = 0; i < resources->noutput; ++i)
792     {
793       XRROutputInfo *output =
794         XRRGetOutputInfo (dpy, resources, resources->outputs[i]);
795
796       /* Non RandR1.2 X driver have output name "default" */
797       randr12_compat |= !g_strcmp0 (output->name, "default");
798
799       if (output->connection == RR_Disconnected)
800         {
801           XRRFreeOutputInfo (output);
802           continue;
803         }
804
805       if (output->crtc)
806         {
807           GdkX11Monitor monitor;
808           XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, output->crtc);
809
810           monitor.geometry.x = crtc->x;
811           monitor.geometry.y = crtc->y;
812           monitor.geometry.width = crtc->width;
813           monitor.geometry.height = crtc->height;
814
815           monitor.output = resources->outputs[i];
816           monitor.width_mm = output->mm_width;
817           monitor.height_mm = output->mm_height;
818           monitor.output_name = g_strdup (output->name);
819           /* FIXME: need EDID parser */
820           monitor.manufacturer = NULL;
821
822           g_array_append_val (monitors, monitor);
823
824           XRRFreeCrtcInfo (crtc);
825         }
826
827       XRRFreeOutputInfo (output);
828     }
829
830   if (resources->noutput > 0)
831     first_output = resources->outputs[0];
832
833   XRRFreeScreenResources (resources);
834
835   /* non RandR 1.2 X driver doesn't return any usable multihead data */
836   if (randr12_compat)
837     {
838       guint n_monitors = monitors->len;
839
840       free_monitors ((GdkX11Monitor *)g_array_free (monitors, FALSE),
841                      n_monitors);
842
843       return FALSE;
844     }
845
846   g_array_sort (monitors,
847                 (GCompareFunc) monitor_compare_function);
848   screen_x11->n_monitors = monitors->len;
849   screen_x11->monitors = (GdkX11Monitor *)g_array_free (monitors, FALSE);
850
851   screen_x11->primary_monitor = 0;
852
853   primary_output = XRRGetOutputPrimary (screen_x11->xdisplay,
854                                         screen_x11->xroot_window);
855
856   for (i = 0; i < screen_x11->n_monitors; ++i)
857     {
858       if (screen_x11->monitors[i].output == primary_output)
859         {
860           screen_x11->primary_monitor = i;
861           break;
862         }
863
864       /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */
865       if (primary_output == None &&
866           g_ascii_strncasecmp (screen_x11->monitors[i].output_name, "LVDS", 4) == 0)
867         {
868           screen_x11->primary_monitor = i;
869           break;
870         }
871
872       /* No primary specified and no LVDS found */
873       if (screen_x11->monitors[i].output == first_output)
874         screen_x11->primary_monitor = i;
875     }
876
877   return screen_x11->n_monitors > 0;
878 #endif
879
880   return FALSE;
881 }
882
883 static gboolean
884 init_solaris_xinerama (GdkScreen *screen)
885 {
886 #ifdef HAVE_SOLARIS_XINERAMA
887   Display *dpy = GDK_SCREEN_XDISPLAY (screen);
888   int screen_no = gdk_screen_get_number (screen);
889   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
890   XRectangle monitors[MAXFRAMEBUFFERS];
891   unsigned char hints[16];
892   gint result;
893   int n_monitors;
894   int i;
895   
896   if (!XineramaGetState (dpy, screen_no))
897     return FALSE;
898
899   result = XineramaGetInfo (dpy, screen_no, monitors, hints, &n_monitors);
900
901   /* Yes I know it should be Success but the current implementation 
902    * returns the num of monitor
903    */
904   if (result == 0)
905     {
906       return FALSE;
907     }
908
909   screen_x11->monitors = g_new0 (GdkX11Monitor, n_monitors);
910   screen_x11->n_monitors = n_monitors;
911
912   for (i = 0; i < n_monitors; i++)
913     {
914       init_monitor_geometry (&screen_x11->monitors[i],
915                              monitors[i].x, monitors[i].y,
916                              monitors[i].width, monitors[i].height);
917     }
918
919   screen_x11->primary_monitor = 0;
920
921   return TRUE;
922 #endif /* HAVE_SOLARIS_XINERAMA */
923
924   return FALSE;
925 }
926
927 static gboolean
928 init_xfree_xinerama (GdkScreen *screen)
929 {
930 #ifdef HAVE_XFREE_XINERAMA
931   Display *dpy = GDK_SCREEN_XDISPLAY (screen);
932   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
933   XineramaScreenInfo *monitors;
934   int i, n_monitors;
935   
936   if (!XineramaIsActive (dpy))
937     return FALSE;
938
939   monitors = XineramaQueryScreens (dpy, &n_monitors);
940   
941   if (n_monitors <= 0 || monitors == NULL)
942     {
943       /* If Xinerama doesn't think we have any monitors, try acting as
944        * though we had no Xinerama. If the "no monitors" condition
945        * is because XRandR 1.2 is currently switching between CRTCs,
946        * we'll be notified again when we have our monitor back,
947        * and can go back into Xinerama-ish mode at that point.
948        */
949       if (monitors)
950         XFree (monitors);
951       
952       return FALSE;
953     }
954
955   screen_x11->n_monitors = n_monitors;
956   screen_x11->monitors = g_new0 (GdkX11Monitor, n_monitors);
957   
958   for (i = 0; i < n_monitors; ++i)
959     {
960       init_monitor_geometry (&screen_x11->monitors[i],
961                              monitors[i].x_org, monitors[i].y_org,
962                              monitors[i].width, monitors[i].height);
963     }
964   
965   XFree (monitors);
966   
967   screen_x11->primary_monitor = 0;
968
969   return TRUE;
970 #endif /* HAVE_XFREE_XINERAMA */
971   
972   return FALSE;
973 }
974
975 static void
976 deinit_multihead (GdkScreen *screen)
977 {
978   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
979
980   free_monitors (screen_x11->monitors, screen_x11->n_monitors);
981
982   screen_x11->n_monitors = 0;
983   screen_x11->monitors = NULL;
984 }
985
986 static gboolean
987 compare_monitor (GdkX11Monitor *m1,
988                  GdkX11Monitor *m2)
989 {
990   if (m1->geometry.x != m2->geometry.x ||
991       m1->geometry.y != m2->geometry.y ||
992       m1->geometry.width != m2->geometry.width ||
993       m1->geometry.height != m2->geometry.height)
994     return FALSE;
995
996   if (m1->width_mm != m2->width_mm ||
997       m1->height_mm != m2->height_mm)
998     return FALSE;
999
1000   if (g_strcmp0 (m1->output_name, m2->output_name) != 0)
1001     return FALSE;
1002
1003   if (g_strcmp0 (m1->manufacturer, m2->manufacturer) != 0)
1004     return FALSE;
1005
1006   return TRUE;
1007 }
1008
1009 static gboolean
1010 compare_monitors (GdkX11Monitor *monitors1, gint n_monitors1,
1011                   GdkX11Monitor *monitors2, gint n_monitors2)
1012 {
1013   gint i;
1014
1015   if (n_monitors1 != n_monitors2)
1016     return FALSE;
1017
1018   for (i = 0; i < n_monitors1; i++)
1019     {
1020       if (!compare_monitor (monitors1 + i, monitors2 + i))
1021         return FALSE;
1022     }
1023
1024   return TRUE;
1025 }
1026
1027 static void
1028 init_multihead (GdkScreen *screen)
1029 {
1030   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1031   int opcode, firstevent, firsterror;
1032
1033   /* There are four different implementations of multihead support: 
1034    *
1035    *  1. Fake Xinerama for debugging purposes
1036    *  2. RandR 1.2
1037    *  3. Solaris Xinerama
1038    *  4. XFree86/Xorg Xinerama
1039    *
1040    * We use them in that order.
1041    */
1042   if (init_fake_xinerama (screen))
1043     return;
1044
1045   if (init_randr13 (screen))
1046     return;
1047
1048   if (XQueryExtension (GDK_SCREEN_XDISPLAY (screen), "XINERAMA",
1049                        &opcode, &firstevent, &firsterror))
1050     {
1051       if (init_solaris_xinerama (screen))
1052         return;
1053       
1054       if (init_xfree_xinerama (screen))
1055         return;
1056     }
1057
1058   /* No multihead support of any kind for this screen */
1059   screen_x11->n_monitors = 1;
1060   screen_x11->monitors = g_new0 (GdkX11Monitor, 1);
1061   screen_x11->primary_monitor = 0;
1062
1063   init_monitor_geometry (screen_x11->monitors, 0, 0,
1064                          WidthOfScreen (screen_x11->xscreen),
1065                          HeightOfScreen (screen_x11->xscreen));
1066 }
1067
1068 GdkScreen *
1069 _gdk_x11_screen_new (GdkDisplay *display,
1070                      gint        screen_number) 
1071 {
1072   GdkScreen *screen;
1073   GdkScreenX11 *screen_x11;
1074   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1075
1076   screen = g_object_new (GDK_TYPE_SCREEN_X11, NULL);
1077
1078   screen_x11 = GDK_SCREEN_X11 (screen);
1079   screen_x11->display = display;
1080   screen_x11->xdisplay = display_x11->xdisplay;
1081   screen_x11->xscreen = ScreenOfDisplay (display_x11->xdisplay, screen_number);
1082   screen_x11->screen_num = screen_number;
1083   screen_x11->xroot_window = RootWindow (display_x11->xdisplay,screen_number);
1084   screen_x11->wmspec_check_window = None;
1085   /* we want this to be always non-null */
1086   screen_x11->window_manager_name = g_strdup ("unknown");
1087   
1088   init_multihead (screen);
1089   init_randr_support (screen);
1090   
1091   _gdk_visual_init (screen);
1092   _gdk_windowing_window_init (screen);
1093   
1094   return screen;
1095 }
1096
1097 /*
1098  * It is important that we first request the selection
1099  * notification, and then setup the initial state of
1100  * is_composited to avoid a race condition here.
1101  */
1102 void
1103 _gdk_x11_screen_setup (GdkScreen *screen)
1104 {
1105   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1106
1107   screen_x11->cm_selection_atom = make_cm_atom (screen_x11->screen_num);
1108   gdk_display_request_selection_notification (screen_x11->display,
1109                                               screen_x11->cm_selection_atom);
1110   screen_x11->is_composited = check_is_composited (screen_x11->display, screen_x11);
1111 }
1112
1113 /**
1114  * gdk_screen_is_composited:
1115  * @screen: a #GdkScreen
1116  * 
1117  * Returns whether windows with an RGBA visual can reasonably
1118  * be expected to have their alpha channel drawn correctly on
1119  * the screen.
1120  *
1121  * On X11 this function returns whether a compositing manager is
1122  * compositing @screen.
1123  * 
1124  * Return value: Whether windows with RGBA visuals can reasonably be
1125  * expected to have their alpha channels drawn correctly on the screen.
1126  * 
1127  * Since: 2.10
1128  **/
1129 gboolean
1130 gdk_screen_is_composited (GdkScreen *screen)
1131 {
1132   GdkScreenX11 *screen_x11;
1133
1134   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
1135
1136   screen_x11 = GDK_SCREEN_X11 (screen);
1137
1138   return screen_x11->is_composited;
1139 }
1140
1141 static void
1142 init_randr_support (GdkScreen * screen)
1143 {
1144   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1145   
1146   XSelectInput (GDK_SCREEN_XDISPLAY (screen),
1147                 screen_x11->xroot_window,
1148                 StructureNotifyMask);
1149
1150 #ifdef HAVE_RANDR
1151   XRRSelectInput (GDK_SCREEN_XDISPLAY (screen),
1152                   screen_x11->xroot_window,
1153                   RRScreenChangeNotifyMask      |
1154                   RRCrtcChangeNotifyMask        |
1155                   RROutputPropertyNotifyMask);
1156 #endif
1157 }
1158
1159 static void
1160 process_monitors_change (GdkScreen *screen)
1161 {
1162   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1163   gint           n_monitors;
1164   GdkX11Monitor *monitors;
1165   gboolean changed;
1166
1167   n_monitors = screen_x11->n_monitors;
1168   monitors = screen_x11->monitors;
1169
1170   screen_x11->n_monitors = 0;
1171   screen_x11->monitors = NULL;
1172
1173   init_multihead (screen);
1174
1175   changed = !compare_monitors (monitors, n_monitors,
1176                                screen_x11->monitors, screen_x11->n_monitors);
1177
1178   free_monitors (monitors, n_monitors);
1179
1180   if (changed)
1181     g_signal_emit_by_name (screen, "monitors-changed");
1182 }
1183
1184 void
1185 _gdk_x11_screen_size_changed (GdkScreen *screen,
1186                               XEvent    *event)
1187 {
1188   gint width, height;
1189 #ifdef HAVE_RANDR
1190   GdkDisplayX11 *display_x11;
1191 #endif
1192
1193   width = gdk_screen_get_width (screen);
1194   height = gdk_screen_get_height (screen);
1195
1196 #ifdef HAVE_RANDR
1197   display_x11 = GDK_DISPLAY_X11 (gdk_screen_get_display (screen));
1198
1199   if (display_x11->have_randr13 && event->type == ConfigureNotify)
1200     {
1201       g_signal_emit_by_name (screen, "monitors-changed");
1202       return;
1203     }
1204
1205   XRRUpdateConfiguration (event);
1206 #else
1207   if (event->type == ConfigureNotify)
1208     {
1209       XConfigureEvent *rcevent = (XConfigureEvent *) event;
1210       Screen        *xscreen = gdk_x11_screen_get_xscreen (screen);
1211
1212       xscreen->width   = rcevent->width;
1213       xscreen->height  = rcevent->height;
1214     }
1215   else
1216     return;
1217 #endif
1218
1219   process_monitors_change (screen);
1220
1221   if (width != gdk_screen_get_width (screen) ||
1222       height != gdk_screen_get_height (screen))
1223     g_signal_emit_by_name (screen, "size-changed");
1224 }
1225
1226 void
1227 _gdk_x11_screen_window_manager_changed (GdkScreen *screen)
1228 {
1229   g_signal_emit (screen, signals[WINDOW_MANAGER_CHANGED], 0);
1230 }
1231
1232 void
1233 _gdk_x11_screen_process_owner_change (GdkScreen *screen,
1234                                       XEvent *event)
1235 {
1236 #ifdef HAVE_XFIXES
1237   XFixesSelectionNotifyEvent *selection_event = (XFixesSelectionNotifyEvent *)event;
1238   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1239   Atom xcm_selection_atom = gdk_x11_atom_to_xatom_for_display (screen_x11->display,
1240                                                                screen_x11->cm_selection_atom);
1241
1242   if (selection_event->selection == xcm_selection_atom)
1243     {
1244       gboolean composited = selection_event->owner != None;
1245
1246       if (composited != screen_x11->is_composited)
1247         {
1248           screen_x11->is_composited = composited;
1249
1250           g_signal_emit_by_name (screen, "composited-changed");
1251         }
1252     }
1253 #endif
1254 }
1255
1256 /**
1257  * _gdk_windowing_substitute_screen_number:
1258  * @display_name : The name of a display, in the form used by 
1259  *                 gdk_display_open (). If %NULL a default value
1260  *                 will be used. On X11, this is derived from the DISPLAY
1261  *                 environment variable.
1262  * @screen_number : The number of a screen within the display
1263  *                  referred to by @display_name.
1264  *
1265  * Modifies a @display_name to make @screen_number the default
1266  * screen when the display is opened.
1267  *
1268  * Return value: a newly allocated string holding the resulting
1269  *   display name. Free with g_free().
1270  */
1271 gchar * 
1272 _gdk_windowing_substitute_screen_number (const gchar *display_name,
1273                                          gint         screen_number)
1274 {
1275   GString *str;
1276   gchar   *p;
1277
1278   if (!display_name)
1279     display_name = getenv ("DISPLAY");
1280
1281   if (!display_name)
1282     return NULL;
1283
1284   str = g_string_new (display_name);
1285
1286   p = strrchr (str->str, '.');
1287   if (p && p >  strchr (str->str, ':'))
1288     g_string_truncate (str, p - str->str);
1289
1290   g_string_append_printf (str, ".%d", screen_number);
1291
1292   return g_string_free (str, FALSE);
1293 }
1294
1295 /**
1296  * gdk_screen_make_display_name:
1297  * @screen: a #GdkScreen
1298  * 
1299  * Determines the name to pass to gdk_display_open() to get
1300  * a #GdkDisplay with this screen as the default screen.
1301  * 
1302  * Return value: a newly allocated string, free with g_free()
1303  *
1304  * Since: 2.2
1305  **/
1306 gchar *
1307 gdk_screen_make_display_name (GdkScreen *screen)
1308 {
1309   const gchar *old_display;
1310
1311   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1312
1313   old_display = gdk_display_get_name (gdk_screen_get_display (screen));
1314
1315   return _gdk_windowing_substitute_screen_number (old_display, 
1316                                                   gdk_screen_get_number (screen));
1317 }
1318
1319 /**
1320  * gdk_screen_get_active_window
1321  * @screen: a #GdkScreen
1322  *
1323  * Returns the screen's currently active window.
1324  *
1325  * On X11, this is done by inspecting the _NET_ACTIVE_WINDOW property
1326  * on the root window, as described in the <ulink
1327  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
1328  * Manager Hints</ulink>. If there is no currently currently active
1329  * window, or the window manager does not support the
1330  * _NET_ACTIVE_WINDOW hint, this function returns %NULL.
1331  *
1332  * On other platforms, this function may return %NULL, depending on whether
1333  * it is implementable on that platform.
1334  *
1335  * The returned window should be unrefed using g_object_unref() when
1336  * no longer needed.
1337  *
1338  * Return value: the currently active window, or %NULL.
1339  *
1340  * Since: 2.10
1341  **/
1342 GdkWindow *
1343 gdk_screen_get_active_window (GdkScreen *screen)
1344 {
1345   GdkScreenX11 *screen_x11;
1346   GdkWindow *ret = NULL;
1347   Atom type_return;
1348   gint format_return;
1349   gulong nitems_return;
1350   gulong bytes_after_return;
1351   guchar *data = NULL;
1352
1353   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1354
1355   if (!gdk_x11_screen_supports_net_wm_hint (screen,
1356                                             gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
1357     return NULL;
1358
1359   screen_x11 = GDK_SCREEN_X11 (screen);
1360
1361   if (XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1362                           gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
1363                                                                  "_NET_ACTIVE_WINDOW"),
1364                           0, 1, False, XA_WINDOW, &type_return,
1365                           &format_return, &nitems_return,
1366                           &bytes_after_return, &data)
1367       == Success)
1368     {
1369       if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
1370         {
1371           GdkNativeWindow window = *(GdkNativeWindow *) data;
1372
1373           if (window != None)
1374             {
1375               ret = gdk_window_foreign_new_for_display (screen_x11->display,
1376                                                         *(GdkNativeWindow *) data);
1377             }
1378         }
1379     }
1380
1381   if (data)
1382     XFree (data);
1383
1384   return ret;
1385 }
1386
1387 /**
1388  * gdk_screen_get_window_stack
1389  * @screen: a #GdkScreen
1390  *
1391  * Returns a #GList of #GdkWindow<!-- -->s representing the current
1392  * window stack.
1393  *
1394  * On X11, this is done by inspecting the _NET_CLIENT_LIST_STACKING
1395  * property on the root window, as described in the <ulink
1396  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
1397  * Manager Hints</ulink>. If the window manager does not support the
1398  * _NET_CLIENT_LIST_STACKING hint, this function returns %NULL.
1399  *
1400  * On other platforms, this function may return %NULL, depending on whether
1401  * it is implementable on that platform.
1402  *
1403  * The returned list is newly allocated and owns references to the
1404  * windows it contains, so it should be freed using g_list_free() and
1405  * its windows unrefed using g_object_unref() when no longer needed.
1406  *
1407  * Return value: a list of #GdkWindow<!-- -->s for the current window stack,
1408  *               or %NULL.
1409  *
1410  * Since: 2.10
1411  **/
1412 GList *
1413 gdk_screen_get_window_stack (GdkScreen *screen)
1414 {
1415   GdkScreenX11 *screen_x11;
1416   GList *ret = NULL;
1417   Atom type_return;
1418   gint format_return;
1419   gulong nitems_return;
1420   gulong bytes_after_return;
1421   guchar *data = NULL;
1422
1423   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1424
1425   if (!gdk_x11_screen_supports_net_wm_hint (screen,
1426                                             gdk_atom_intern_static_string ("_NET_CLIENT_LIST_STACKING")))
1427     return NULL;
1428
1429   screen_x11 = GDK_SCREEN_X11 (screen);
1430
1431   if (XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1432                           gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
1433                                                                  "_NET_CLIENT_LIST_STACKING"),
1434                           0, G_MAXLONG, False, XA_WINDOW, &type_return,
1435                           &format_return, &nitems_return,
1436                           &bytes_after_return, &data)
1437       == Success)
1438     {
1439       if ((type_return == XA_WINDOW) && (format_return == 32) &&
1440           (data) && (nitems_return > 0))
1441         {
1442           gulong *stack = (gulong *) data;
1443           GdkWindow *win;
1444           int i;
1445
1446           for (i = 0; i < nitems_return; i++)
1447             {
1448               win = gdk_window_foreign_new_for_display (screen_x11->display,
1449                                                         (GdkNativeWindow)stack[i]);
1450
1451               if (win != NULL)
1452                 ret = g_list_append (ret, win);
1453             }
1454         }
1455     }
1456
1457   if (data)
1458     XFree (data);
1459
1460   return ret;
1461 }
1462
1463 /* Sends a ClientMessage to all toplevel client windows */
1464 static gboolean
1465 gdk_event_send_client_message_to_all_recurse (GdkDisplay *display,
1466                                               XEvent     *xev,
1467                                               guint32     xid,
1468                                               guint       level)
1469 {
1470   Atom type = None;
1471   int format;
1472   unsigned long nitems, after;
1473   unsigned char *data;
1474   Window *ret_children, ret_root, ret_parent;
1475   unsigned int ret_nchildren;
1476   gboolean send = FALSE;
1477   gboolean found = FALSE;
1478   gboolean result = FALSE;
1479   int i;
1480
1481   gdk_error_trap_push ();
1482
1483   if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xid,
1484                           gdk_x11_get_xatom_by_name_for_display (display, "WM_STATE"),
1485                           0, 0, False, AnyPropertyType,
1486                           &type, &format, &nitems, &after, &data) != Success)
1487     goto out;
1488
1489   if (type)
1490     {
1491       send = TRUE;
1492       XFree (data);
1493     }
1494   else
1495     {
1496       /* OK, we're all set, now let's find some windows to send this to */
1497       if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xid,
1498                       &ret_root, &ret_parent,
1499                       &ret_children, &ret_nchildren))
1500         goto out;
1501
1502       for(i = 0; i < ret_nchildren; i++)
1503         if (gdk_event_send_client_message_to_all_recurse (display, xev, ret_children[i], level + 1))
1504           found = TRUE;
1505
1506       XFree (ret_children);
1507     }
1508
1509   if (send || (!found && (level == 1)))
1510     {
1511       xev->xclient.window = xid;
1512       _gdk_send_xevent (display, xid, False, NoEventMask, xev);
1513     }
1514
1515   result = send || found;
1516
1517  out:
1518   gdk_error_trap_pop ();
1519
1520   return result;
1521 }
1522
1523 /**
1524  * gdk_screen_broadcast_client_message:
1525  * @screen: the #GdkScreen where the event will be broadcasted.
1526  * @event: the #GdkEvent.
1527  *
1528  * On X11, sends an X ClientMessage event to all toplevel windows on
1529  * @screen.
1530  *
1531  * Toplevel windows are determined by checking for the WM_STATE property,
1532  * as described in the Inter-Client Communication Conventions Manual (ICCCM).
1533  * If no windows are found with the WM_STATE property set, the message is
1534  * sent to all children of the root window.
1535  *
1536  * On Windows, broadcasts a message registered with the name
1537  * GDK_WIN32_CLIENT_MESSAGE to all top-level windows. The amount of
1538  * data is limited to one long, i.e. four bytes.
1539  *
1540  * Since: 2.2
1541  */
1542
1543 void
1544 gdk_screen_broadcast_client_message (GdkScreen *screen,
1545                                      GdkEvent  *event)
1546 {
1547   XEvent sev;
1548   GdkWindow *root_window;
1549
1550   g_return_if_fail (event != NULL);
1551
1552   root_window = gdk_screen_get_root_window (screen);
1553
1554   /* Set up our event to send, with the exception of its target window */
1555   sev.xclient.type = ClientMessage;
1556   sev.xclient.display = GDK_WINDOW_XDISPLAY (root_window);
1557   sev.xclient.format = event->client.data_format;
1558   memcpy(&sev.xclient.data, &event->client.data, sizeof (sev.xclient.data));
1559   sev.xclient.message_type =
1560     gdk_x11_atom_to_xatom_for_display (GDK_WINDOW_DISPLAY (root_window),
1561                                        event->client.message_type);
1562
1563   gdk_event_send_client_message_to_all_recurse (gdk_screen_get_display (screen),
1564                                                 &sev,
1565                                                 GDK_WINDOW_XID (root_window),
1566                                                 0);
1567 }
1568
1569 static gboolean
1570 check_transform (const gchar *xsettings_name,
1571                  GType        src_type,
1572                  GType        dest_type)
1573 {
1574   if (!g_value_type_transformable (src_type, dest_type))
1575     {
1576       g_warning ("Cannot transform xsetting %s of type %s to type %s\n",
1577                  xsettings_name,
1578                  g_type_name (src_type),
1579                  g_type_name (dest_type));
1580       return FALSE;
1581     }
1582   else
1583     return TRUE;
1584 }
1585
1586 /**
1587  * gdk_screen_get_setting:
1588  * @screen: the #GdkScreen where the setting is located
1589  * @name: the name of the setting
1590  * @value: location to store the value of the setting
1591  *
1592  * Retrieves a desktop-wide setting such as double-click time
1593  * for the #GdkScreen @screen.
1594  *
1595  * FIXME needs a list of valid settings here, or a link to
1596  * more information.
1597  *
1598  * Returns: %TRUE if the setting existed and a value was stored
1599  *   in @value, %FALSE otherwise.
1600  *
1601  * Since: 2.2
1602  **/
1603 gboolean
1604 gdk_screen_get_setting (GdkScreen   *screen,
1605                         const gchar *name,
1606                         GValue      *value)
1607 {
1608
1609   const char *xsettings_name = NULL;
1610   XSettingsResult result;
1611   XSettingsSetting *setting = NULL;
1612   GdkScreenX11 *screen_x11;
1613   gboolean success = FALSE;
1614   gint i;
1615   GValue tmp_val = { 0, };
1616
1617   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
1618
1619   screen_x11 = GDK_SCREEN_X11 (screen);
1620
1621   for (i = 0; i < GDK_SETTINGS_N_ELEMENTS(); i++)
1622     if (strcmp (GDK_SETTINGS_GDK_NAME (i), name) == 0)
1623       {
1624         xsettings_name = GDK_SETTINGS_X_NAME (i);
1625         break;
1626       }
1627
1628   if (!xsettings_name)
1629     goto out;
1630
1631   result = xsettings_client_get_setting (screen_x11->xsettings_client,
1632                                          xsettings_name, &setting);
1633   if (result != XSETTINGS_SUCCESS)
1634     goto out;
1635
1636   switch (setting->type)
1637     {
1638     case XSETTINGS_TYPE_INT:
1639       if (check_transform (xsettings_name, G_TYPE_INT, G_VALUE_TYPE (value)))
1640         {
1641           g_value_init (&tmp_val, G_TYPE_INT);
1642           g_value_set_int (&tmp_val, setting->data.v_int);
1643           g_value_transform (&tmp_val, value);
1644
1645           success = TRUE;
1646         }
1647       break;
1648     case XSETTINGS_TYPE_STRING:
1649       if (check_transform (xsettings_name, G_TYPE_STRING, G_VALUE_TYPE (value)))
1650         {
1651           g_value_init (&tmp_val, G_TYPE_STRING);
1652           g_value_set_string (&tmp_val, setting->data.v_string);
1653           g_value_transform (&tmp_val, value);
1654
1655           success = TRUE;
1656         }
1657       break;
1658     case XSETTINGS_TYPE_COLOR:
1659       if (!check_transform (xsettings_name, GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
1660         {
1661           GdkColor color;
1662
1663           g_value_init (&tmp_val, GDK_TYPE_COLOR);
1664
1665           color.pixel = 0;
1666           color.red = setting->data.v_color.red;
1667           color.green = setting->data.v_color.green;
1668           color.blue = setting->data.v_color.blue;
1669
1670           g_value_set_boxed (&tmp_val, &color);
1671
1672           g_value_transform (&tmp_val, value);
1673
1674           success = TRUE;
1675         }
1676       break;
1677     }
1678
1679   g_value_unset (&tmp_val);
1680
1681  out:
1682   if (setting)
1683     xsettings_setting_free (setting);
1684
1685   if (success)
1686     return TRUE;
1687   else
1688     return _gdk_x11_get_xft_setting (screen, name, value);
1689 }
1690
1691 static void
1692 cleanup_atoms(gpointer data)
1693 {
1694   NetWmSupportedAtoms *supported_atoms = data;
1695   if (supported_atoms->atoms)
1696       XFree (supported_atoms->atoms);
1697   g_free (supported_atoms);
1698 }
1699
1700 static void
1701 fetch_net_wm_check_window (GdkScreen *screen)
1702 {
1703   GdkScreenX11 *screen_x11;
1704   GdkDisplay *display;
1705   Atom type;
1706   gint format;
1707   gulong n_items;
1708   gulong bytes_after;
1709   guchar *data;
1710   Window *xwindow;
1711   GTimeVal tv;
1712   gint error;
1713
1714   screen_x11 = GDK_SCREEN_X11 (screen);
1715   display = screen_x11->display;
1716
1717   g_return_if_fail (GDK_DISPLAY_X11 (display)->trusted_client);
1718   
1719   g_get_current_time (&tv);
1720
1721   if (ABS  (tv.tv_sec - screen_x11->last_wmspec_check_time) < 15)
1722     return; /* we've checked recently */
1723
1724   screen_x11->last_wmspec_check_time = tv.tv_sec;
1725
1726   data = NULL;
1727   XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1728                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTING_WM_CHECK"),
1729                       0, G_MAXLONG, False, XA_WINDOW, &type, &format,
1730                       &n_items, &bytes_after, &data);
1731   
1732   if (type != XA_WINDOW)
1733     {
1734       if (data)
1735         XFree (data);
1736       return;
1737     }
1738
1739   xwindow = (Window *)data;
1740
1741   if (screen_x11->wmspec_check_window == *xwindow)
1742     {
1743       XFree (xwindow);
1744       return;
1745     }
1746
1747   gdk_error_trap_push ();
1748
1749   /* Find out if this WM goes away, so we can reset everything. */
1750   XSelectInput (screen_x11->xdisplay, *xwindow, StructureNotifyMask);
1751   gdk_display_sync (display);
1752
1753   error = gdk_error_trap_pop ();
1754   if (!error)
1755     {
1756       screen_x11->wmspec_check_window = *xwindow;
1757       screen_x11->need_refetch_net_supported = TRUE;
1758       screen_x11->need_refetch_wm_name = TRUE;
1759
1760       /* Careful, reentrancy */
1761       _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
1762     }
1763   else if (error == BadWindow)
1764     {
1765       /* Leftover property, try again immediately, new wm may be starting up */
1766       screen_x11->last_wmspec_check_time = 0;
1767     }
1768
1769   XFree (xwindow);
1770 }
1771
1772 /**
1773  * gdk_x11_screen_supports_net_wm_hint:
1774  * @screen: the relevant #GdkScreen.
1775  * @property: a property atom.
1776  *
1777  * This function is specific to the X11 backend of GDK, and indicates
1778  * whether the window manager supports a certain hint from the
1779  * Extended Window Manager Hints Specification. You can find this
1780  * specification on
1781  * <ulink url="http://www.freedesktop.org">http://www.freedesktop.org</ulink>.
1782  *
1783  * When using this function, keep in mind that the window manager
1784  * can change over time; so you shouldn't use this function in
1785  * a way that impacts persistent application state. A common bug
1786  * is that your application can start up before the window manager
1787  * does when the user logs in, and before the window manager starts
1788  * gdk_x11_screen_supports_net_wm_hint() will return %FALSE for every property.
1789  * You can monitor the window_manager_changed signal on #GdkScreen to detect
1790  * a window manager change.
1791  *
1792  * Return value: %TRUE if the window manager supports @property
1793  *
1794  * Since: 2.2
1795  **/
1796 gboolean
1797 gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen,
1798                                      GdkAtom    property)
1799 {
1800   gulong i;
1801   GdkScreenX11 *screen_x11;
1802   NetWmSupportedAtoms *supported_atoms;
1803   GdkDisplay *display;
1804
1805   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
1806
1807   screen_x11 = GDK_SCREEN_X11 (screen);
1808   display = screen_x11->display;
1809
1810   if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
1811     return FALSE;
1812
1813   supported_atoms = g_object_get_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms");
1814   if (!supported_atoms)
1815     {
1816       supported_atoms = g_new0 (NetWmSupportedAtoms, 1);
1817       g_object_set_data_full (G_OBJECT (screen), "gdk-net-wm-supported-atoms", supported_atoms, cleanup_atoms);
1818     }
1819
1820   fetch_net_wm_check_window (screen);
1821
1822   if (screen_x11->wmspec_check_window == None)
1823     return FALSE;
1824
1825   if (screen_x11->need_refetch_net_supported)
1826     {
1827       /* WM has changed since we last got the supported list,
1828        * refetch it.
1829        */
1830       Atom type;
1831       gint format;
1832       gulong bytes_after;
1833
1834       screen_x11->need_refetch_net_supported = FALSE;
1835
1836       if (supported_atoms->atoms)
1837         XFree (supported_atoms->atoms);
1838
1839       supported_atoms->atoms = NULL;
1840       supported_atoms->n_atoms = 0;
1841
1842       XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window,
1843                           gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTED"),
1844                           0, G_MAXLONG, False, XA_ATOM, &type, &format,
1845                           &supported_atoms->n_atoms, &bytes_after,
1846                           (guchar **)&supported_atoms->atoms);
1847
1848       if (type != XA_ATOM)
1849         return FALSE;
1850     }
1851
1852   if (supported_atoms->atoms == NULL)
1853     return FALSE;
1854
1855   i = 0;
1856   while (i < supported_atoms->n_atoms)
1857     {
1858       if (supported_atoms->atoms[i] == gdk_x11_atom_to_xatom_for_display (display, property))
1859         return TRUE;
1860
1861       ++i;
1862     }
1863
1864   return FALSE;
1865 }
1866
1867 /**
1868  * gdk_net_wm_supports:
1869  * @property: a property atom.
1870  *
1871  * This function is specific to the X11 backend of GDK, and indicates
1872  * whether the window manager for the default screen supports a certain
1873  * hint from the Extended Window Manager Hints Specification. See
1874  * gdk_x11_screen_supports_net_wm_hint() for complete details.
1875  *
1876  * Return value: %TRUE if the window manager supports @property
1877  **/
1878 gboolean
1879 gdk_net_wm_supports (GdkAtom property)
1880 {
1881   return gdk_x11_screen_supports_net_wm_hint (gdk_screen_get_default (), property);
1882 }
1883
1884 static void
1885 refcounted_grab_server (Display *xdisplay)
1886 {
1887   GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
1888
1889   gdk_x11_display_grab (display);
1890 }
1891
1892 static void
1893 refcounted_ungrab_server (Display *xdisplay)
1894 {
1895   GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
1896
1897   gdk_x11_display_ungrab (display);
1898 }
1899
1900 static GdkFilterReturn
1901 gdk_xsettings_client_event_filter (GdkXEvent *xevent,
1902                                    GdkEvent  *event,
1903                                    gpointer   data)
1904 {
1905   GdkScreenX11 *screen = data;
1906
1907   if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent))
1908     return GDK_FILTER_REMOVE;
1909   else
1910     return GDK_FILTER_CONTINUE;
1911 }
1912
1913 static Bool
1914 gdk_xsettings_watch_cb (Window   window,
1915                         Bool     is_start,
1916                         long     mask,
1917                         void    *cb_data)
1918 {
1919   GdkWindow *gdkwin;
1920   GdkScreen *screen = cb_data;
1921
1922   gdkwin = gdk_window_lookup_for_display (gdk_screen_get_display (screen), window);
1923
1924   if (is_start)
1925     {
1926       if (gdkwin)
1927         g_object_ref (gdkwin);
1928       else
1929         {
1930           gdkwin = gdk_window_foreign_new_for_display (gdk_screen_get_display (screen), window);
1931           
1932           /* gdk_window_foreign_new_for_display() can fail and return NULL if the
1933            * window has already been destroyed.
1934            */
1935           if (!gdkwin)
1936             return False;
1937         }
1938
1939       gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
1940     }
1941   else
1942     {
1943       if (!gdkwin)
1944         {
1945           /* gdkwin should not be NULL here, since if starting the watch succeeded
1946            * we have a reference on the window. It might mean that the caller didn't
1947            * remove the watch when it got a DestroyNotify event. Or maybe the
1948            * caller ignored the return value when starting the watch failed.
1949            */
1950           g_warning ("gdk_xsettings_watch_cb(): Couldn't find window to unwatch");
1951           return False;
1952         }
1953       
1954       gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
1955       g_object_unref (gdkwin);
1956     }
1957
1958   return True;
1959 }
1960
1961 static void
1962 gdk_xsettings_notify_cb (const char       *name,
1963                          XSettingsAction   action,
1964                          XSettingsSetting *setting,
1965                          void             *data)
1966 {
1967   GdkEvent new_event;
1968   GdkScreen *screen = data;
1969   GdkScreenX11 *screen_x11 = data;
1970   int i;
1971
1972   if (screen_x11->xsettings_in_init)
1973     return;
1974   
1975   new_event.type = GDK_SETTING;
1976   new_event.setting.window = gdk_screen_get_root_window (screen);
1977   new_event.setting.send_event = FALSE;
1978   new_event.setting.name = NULL;
1979
1980   for (i = 0; i < GDK_SETTINGS_N_ELEMENTS() ; i++)
1981     if (strcmp (GDK_SETTINGS_X_NAME (i), name) == 0)
1982       {
1983         new_event.setting.name = (char*) GDK_SETTINGS_GDK_NAME (i);
1984         break;
1985       }
1986   
1987   if (!new_event.setting.name)
1988     return;
1989   
1990   switch (action)
1991     {
1992     case XSETTINGS_ACTION_NEW:
1993       new_event.setting.action = GDK_SETTING_ACTION_NEW;
1994       break;
1995     case XSETTINGS_ACTION_CHANGED:
1996       new_event.setting.action = GDK_SETTING_ACTION_CHANGED;
1997       break;
1998     case XSETTINGS_ACTION_DELETED:
1999       new_event.setting.action = GDK_SETTING_ACTION_DELETED;
2000       break;
2001     }
2002
2003   gdk_event_put (&new_event);
2004 }
2005
2006 void
2007 _gdk_screen_x11_events_init (GdkScreen *screen)
2008 {
2009   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
2010
2011   /* Keep a flag to avoid extra notifies that we don't need
2012    */
2013   screen_x11->xsettings_in_init = TRUE;
2014   screen_x11->xsettings_client = xsettings_client_new_with_grab_funcs (screen_x11->xdisplay,
2015                                                                        screen_x11->screen_num,
2016                                                                        gdk_xsettings_notify_cb,
2017                                                                        gdk_xsettings_watch_cb,
2018                                                                        screen,
2019                                                                        refcounted_grab_server,
2020                                                                        refcounted_ungrab_server);
2021   screen_x11->xsettings_in_init = FALSE;
2022 }
2023
2024 /**
2025  * gdk_x11_screen_get_window_manager_name:
2026  * @screen: a #GdkScreen
2027  *
2028  * Returns the name of the window manager for @screen.
2029  *
2030  * Return value: the name of the window manager screen @screen, or
2031  * "unknown" if the window manager is unknown. The string is owned by GDK
2032  * and should not be freed.
2033  *
2034  * Since: 2.2
2035  **/
2036 const char*
2037 gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
2038 {
2039   GdkScreenX11 *screen_x11;
2040
2041   screen_x11 = GDK_SCREEN_X11 (screen);
2042
2043   if (!G_LIKELY (GDK_DISPLAY_X11 (screen_x11->display)->trusted_client))
2044     return screen_x11->window_manager_name;
2045
2046   fetch_net_wm_check_window (screen);
2047
2048   if (screen_x11->need_refetch_wm_name)
2049     {
2050       /* Get the name of the window manager */
2051       screen_x11->need_refetch_wm_name = FALSE;
2052
2053       g_free (screen_x11->window_manager_name);
2054       screen_x11->window_manager_name = g_strdup ("unknown");
2055
2056       if (screen_x11->wmspec_check_window != None)
2057         {
2058           Atom type;
2059           gint format;
2060           gulong n_items;
2061           gulong bytes_after;
2062           gchar *name;
2063
2064           name = NULL;
2065
2066           gdk_error_trap_push ();
2067
2068           XGetWindowProperty (GDK_DISPLAY_XDISPLAY (screen_x11->display),
2069                               screen_x11->wmspec_check_window,
2070                               gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
2071                                                                      "_NET_WM_NAME"),
2072                               0, G_MAXLONG, False,
2073                               gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
2074                                                                      "UTF8_STRING"),
2075                               &type, &format,
2076                               &n_items, &bytes_after,
2077                               (guchar **)&name);
2078
2079           gdk_display_sync (screen_x11->display);
2080
2081           gdk_error_trap_pop ();
2082
2083           if (name != NULL)
2084             {
2085               g_free (screen_x11->window_manager_name);
2086               screen_x11->window_manager_name = g_strdup (name);
2087               XFree (name);
2088             }
2089         }
2090     }
2091
2092   return GDK_SCREEN_X11 (screen)->window_manager_name;
2093 }
2094
2095 #define __GDK_SCREEN_X11_C__
2096 #include "gdkaliasdef.c"