]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkscreen-x11.c
Clean up gdkx.h a bit
[~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 "gdkscreen-x11.h"
27 #include "gdkdisplay-x11.h"
28 #include "gdkprivate-x11.h"
29
30 #include <glib.h>
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include <X11/Xatom.h>
36
37 #ifdef HAVE_SOLARIS_XINERAMA
38 #include <X11/extensions/xinerama.h>
39 #endif
40 #ifdef HAVE_XFREE_XINERAMA
41 #include <X11/extensions/Xinerama.h>
42 #endif
43
44 #ifdef HAVE_RANDR
45 #include <X11/extensions/Xrandr.h>
46 #endif
47
48 #ifdef HAVE_XFIXES
49 #include <X11/extensions/Xfixes.h>
50 #endif
51
52 #include "gdksettings.c"
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 typedef struct _NetWmSupportedAtoms NetWmSupportedAtoms;
70
71 struct _NetWmSupportedAtoms
72 {
73   Atom *atoms;
74   gulong n_atoms;
75 };
76
77 struct _GdkX11Monitor
78 {
79   GdkRectangle  geometry;
80   XID           output;
81   int           width_mm;
82   int           height_mm;
83   char *        output_name;
84   char *        manufacturer;
85 };
86
87
88 static void
89 _gdk_screen_x11_init (GdkScreenX11 *screen)
90 {
91 }
92
93 static GdkDisplay *
94 gdk_screen_x11_get_display (GdkScreen *screen)
95 {
96   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
97
98   return GDK_SCREEN_X11 (screen)->display;
99 }
100
101 static gint
102 gdk_screen_x11_get_width (GdkScreen *screen)
103 {
104   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
105
106   return WidthOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
107 }
108
109 static gint
110 gdk_screen_x11_get_height (GdkScreen *screen)
111 {
112   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
113
114   return HeightOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
115 }
116
117 static gint
118 gdk_screen_x11_get_width_mm (GdkScreen *screen)
119 {
120   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);  
121
122   return WidthMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
123 }
124
125 static gint
126 gdk_screen_x11_get_height_mm (GdkScreen *screen)
127 {
128   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
129
130   return HeightMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
131 }
132
133 static gint
134 gdk_screen_x11_get_number (GdkScreen *screen)
135 {
136   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
137   
138   return GDK_SCREEN_X11 (screen)->screen_num;
139 }
140
141 static GdkWindow *
142 gdk_screen_x11_get_root_window (GdkScreen *screen)
143 {
144   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
145
146   return GDK_SCREEN_X11 (screen)->root_window;
147 }
148
149 static void
150 _gdk_screen_x11_events_uninit (GdkScreen *screen)
151 {
152   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
153
154   if (screen_x11->xsettings_client)
155     {
156       xsettings_client_destroy (screen_x11->xsettings_client);
157       screen_x11->xsettings_client = NULL;
158     }
159 }
160
161 static void
162 gdk_screen_x11_dispose (GObject *object)
163 {
164   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
165   int i;
166
167   for (i = 0; i < 32; ++i)
168     {
169       if (screen_x11->subwindow_gcs[i])
170         {
171           XFreeGC (screen_x11->xdisplay, screen_x11->subwindow_gcs[i]);
172           screen_x11->subwindow_gcs[i] = 0;
173         }
174     }
175
176   _gdk_screen_x11_events_uninit (GDK_SCREEN (object));
177
178   if (screen_x11->root_window)
179     _gdk_window_destroy (screen_x11->root_window, TRUE);
180
181   G_OBJECT_CLASS (_gdk_screen_x11_parent_class)->dispose (object);
182
183   screen_x11->xdisplay = NULL;
184   screen_x11->xscreen = NULL;
185   screen_x11->screen_num = -1;
186   screen_x11->xroot_window = None;
187   screen_x11->wmspec_check_window = None;
188 }
189
190 static void
191 gdk_screen_x11_finalize (GObject *object)
192 {
193   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
194   gint          i;
195
196   if (screen_x11->root_window)
197     g_object_unref (screen_x11->root_window);
198
199   /* Visual Part */
200   for (i = 0; i < screen_x11->nvisuals; i++)
201     g_object_unref (screen_x11->visuals[i]);
202   g_free (screen_x11->visuals);
203   g_hash_table_destroy (screen_x11->visual_hash);
204
205   g_free (screen_x11->window_manager_name);
206
207   deinit_multihead (GDK_SCREEN (object));
208   
209   G_OBJECT_CLASS (_gdk_screen_x11_parent_class)->finalize (object);
210 }
211
212 static gint
213 gdk_screen_x11_get_n_monitors (GdkScreen *screen)
214 {
215   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
216
217   return GDK_SCREEN_X11 (screen)->n_monitors;
218 }
219
220 static gint
221 gdk_screen_x11_get_primary_monitor (GdkScreen *screen)
222 {
223   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
224
225   return GDK_SCREEN_X11 (screen)->primary_monitor;
226 }
227
228 static gint
229 gdk_screen_x11_get_monitor_width_mm     (GdkScreen *screen,
230                                          gint       monitor_num)
231 {
232   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
233
234   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
235   g_return_val_if_fail (monitor_num >= 0, -1);
236   g_return_val_if_fail (monitor_num < screen_x11->n_monitors, -1);
237
238   return screen_x11->monitors[monitor_num].width_mm;
239 }
240
241 static gint
242 gdk_screen_x11_get_monitor_height_mm (GdkScreen *screen,
243                                       gint       monitor_num)
244 {
245   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
246
247   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
248   g_return_val_if_fail (monitor_num >= 0, -1);
249   g_return_val_if_fail (monitor_num < screen_x11->n_monitors, -1);
250
251   return screen_x11->monitors[monitor_num].height_mm;
252 }
253
254 static gchar *
255 gdk_screen_x11_get_monitor_plug_name (GdkScreen *screen,
256                                       gint       monitor_num)
257 {
258   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
259
260   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
261   g_return_val_if_fail (monitor_num >= 0, NULL);
262   g_return_val_if_fail (monitor_num < screen_x11->n_monitors, NULL);
263
264   return g_strdup (screen_x11->monitors[monitor_num].output_name);
265 }
266
267 /**
268  * gdk_x11_screen_get_monitor_output:
269  * @screen: a #GdkScreen
270  * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
271  *
272  * Gets the XID of the specified output/monitor.
273  * If the X server does not support version 1.2 of the RANDR
274  * extension, 0 is returned.
275  *
276  * Returns: the XID of the monitor
277  *
278  * Since: 2.14
279  */
280 XID
281 gdk_x11_screen_get_monitor_output (GdkScreen *screen,
282                                    gint       monitor_num)
283 {
284   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
285
286   g_return_val_if_fail (GDK_IS_SCREEN (screen), None);
287   g_return_val_if_fail (monitor_num >= 0, None);
288   g_return_val_if_fail (monitor_num < screen_x11->n_monitors, None);
289
290   return screen_x11->monitors[monitor_num].output;
291 }
292
293 static void
294 gdk_screen_x11_get_monitor_geometry (GdkScreen    *screen,
295                                      gint          monitor_num,
296                                      GdkRectangle *dest)
297 {
298   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
299
300   g_return_if_fail (GDK_IS_SCREEN (screen));
301   g_return_if_fail (monitor_num >= 0);
302   g_return_if_fail (monitor_num < screen_x11->n_monitors);
303
304   if (dest)
305     *dest = screen_x11->monitors[monitor_num].geometry;
306 }
307
308 static GdkVisual *
309 gdk_screen_x11_get_rgba_visual (GdkScreen *screen)
310 {
311   GdkScreenX11 *screen_x11;
312
313   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
314
315   screen_x11 = GDK_SCREEN_X11 (screen);
316
317   return screen_x11->rgba_visual;
318 }
319
320 /**
321  * gdk_x11_screen_get_xscreen:
322  * @screen: a #GdkScreen.
323  * @returns: (transfer none): an Xlib <type>Screen*</type>
324  *
325  * Returns the screen of a #GdkScreen.
326  *
327  * Since: 2.2
328  */
329 Screen *
330 gdk_x11_screen_get_xscreen (GdkScreen *screen)
331 {
332   return GDK_SCREEN_X11 (screen)->xscreen;
333 }
334
335 /**
336  * gdk_x11_screen_get_screen_number:
337  * @screen: a #GdkScreen.
338  * @returns: the position of @screen among the screens of
339  *   its display.
340  *
341  * Returns the index of a #GdkScreen.
342  *
343  * Since: 2.2
344  */
345 int
346 gdk_x11_screen_get_screen_number (GdkScreen *screen)
347 {
348   return GDK_SCREEN_X11 (screen)->screen_num;
349 }
350
351 static gboolean
352 check_is_composited (GdkDisplay *display,
353                      GdkScreenX11 *screen_x11)
354 {
355   Atom xselection = gdk_x11_atom_to_xatom_for_display (display, screen_x11->cm_selection_atom);
356   Window xwindow;
357   
358   xwindow = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display), xselection);
359
360   return xwindow != None;
361 }
362
363 static GdkAtom
364 make_cm_atom (int screen_number)
365 {
366   gchar *name = g_strdup_printf ("_NET_WM_CM_S%d", screen_number);
367   GdkAtom atom = gdk_atom_intern (name, FALSE);
368   g_free (name);
369   return atom;
370 }
371
372 static void
373 init_monitor_geometry (GdkX11Monitor *monitor,
374                        int x, int y, int width, int height)
375 {
376   monitor->geometry.x = x;
377   monitor->geometry.y = y;
378   monitor->geometry.width = width;
379   monitor->geometry.height = height;
380
381   monitor->output = None;
382   monitor->width_mm = -1;
383   monitor->height_mm = -1;
384   monitor->output_name = NULL;
385   monitor->manufacturer = NULL;
386 }
387
388 static gboolean
389 init_fake_xinerama (GdkScreen *screen)
390 {
391 #ifdef G_ENABLE_DEBUG
392   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
393   XSetWindowAttributes atts;
394   Window win;
395   gint w, h;
396
397   if (!(_gdk_debug_flags & GDK_DEBUG_XINERAMA))
398     return FALSE;
399   
400   /* Fake Xinerama mode by splitting the screen into 4 monitors.
401    * Also draw a little cross to make the monitor boundaries visible.
402    */
403   w = WidthOfScreen (screen_x11->xscreen);
404   h = HeightOfScreen (screen_x11->xscreen);
405
406   screen_x11->n_monitors = 4;
407   screen_x11->monitors = g_new0 (GdkX11Monitor, 4);
408   init_monitor_geometry (&screen_x11->monitors[0], 0, 0, w / 2, h / 2);
409   init_monitor_geometry (&screen_x11->monitors[1], w / 2, 0, w / 2, h / 2);
410   init_monitor_geometry (&screen_x11->monitors[2], 0, h / 2, w / 2, h / 2);
411   init_monitor_geometry (&screen_x11->monitors[3], w / 2, h / 2, w / 2, h / 2);
412   
413   atts.override_redirect = 1;
414   atts.background_pixel = WhitePixel(GDK_SCREEN_XDISPLAY (screen), 
415                                      screen_x11->screen_num);
416   win = XCreateWindow(GDK_SCREEN_XDISPLAY (screen), 
417                       screen_x11->xroot_window, 0, h / 2, w, 1, 0, 
418                       DefaultDepth(GDK_SCREEN_XDISPLAY (screen), 
419                                    screen_x11->screen_num),
420                       InputOutput, 
421                       DefaultVisual(GDK_SCREEN_XDISPLAY (screen), 
422                                     screen_x11->screen_num),
423                       CWOverrideRedirect|CWBackPixel, 
424                       &atts);
425   XMapRaised(GDK_SCREEN_XDISPLAY (screen), win); 
426   win = XCreateWindow(GDK_SCREEN_XDISPLAY (screen), 
427                       screen_x11->xroot_window, w/2 , 0, 1, h, 0, 
428                       DefaultDepth(GDK_SCREEN_XDISPLAY (screen), 
429                                    screen_x11->screen_num),
430                       InputOutput, 
431                       DefaultVisual(GDK_SCREEN_XDISPLAY (screen), 
432                                     screen_x11->screen_num),
433                       CWOverrideRedirect|CWBackPixel, 
434                       &atts);
435   XMapRaised(GDK_SCREEN_XDISPLAY (screen), win);
436   return TRUE;
437 #endif
438   
439   return FALSE;
440 }
441
442 static void
443 free_monitors (GdkX11Monitor *monitors,
444                gint           n_monitors)
445 {
446   int i;
447
448   for (i = 0; i < n_monitors; ++i)
449     {
450       g_free (monitors[i].output_name);
451       g_free (monitors[i].manufacturer);
452     }
453
454   g_free (monitors);
455 }
456
457 #ifdef HAVE_RANDR
458 static int
459 monitor_compare_function (GdkX11Monitor *monitor1,
460                           GdkX11Monitor *monitor2)
461 {
462   /* Sort the leftmost/topmost monitors first.
463    * For "cloned" monitors, sort the bigger ones first
464    * (giving preference to taller monitors over wider
465    * monitors)
466    */
467
468   if (monitor1->geometry.x != monitor2->geometry.x)
469     return monitor1->geometry.x - monitor2->geometry.x;
470
471   if (monitor1->geometry.y != monitor2->geometry.y)
472     return monitor1->geometry.y - monitor2->geometry.y;
473
474   if (monitor1->geometry.height != monitor2->geometry.height)
475     return - (monitor1->geometry.height - monitor2->geometry.height);
476
477   if (monitor1->geometry.width != monitor2->geometry.width)
478     return - (monitor1->geometry.width - monitor2->geometry.width);
479
480   return 0;
481 }
482 #endif
483
484 static gboolean
485 init_randr13 (GdkScreen *screen)
486 {
487 #ifdef HAVE_RANDR
488   GdkDisplay *display = gdk_screen_get_display (screen);
489   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
490   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
491   Display *dpy = GDK_SCREEN_XDISPLAY (screen);
492   XRRScreenResources *resources;
493   RROutput primary_output;
494   RROutput first_output = None;
495   int i;
496   GArray *monitors;
497   gboolean randr12_compat = FALSE;
498
499   if (!display_x11->have_randr13)
500       return FALSE;
501
502   resources = XRRGetScreenResourcesCurrent (screen_x11->xdisplay,
503                                             screen_x11->xroot_window);
504   if (!resources)
505     return FALSE;
506
507   monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor),
508                                 resources->noutput);
509
510   for (i = 0; i < resources->noutput; ++i)
511     {
512       XRROutputInfo *output =
513         XRRGetOutputInfo (dpy, resources, resources->outputs[i]);
514
515       /* Non RandR1.2 X driver have output name "default" */
516       randr12_compat |= !g_strcmp0 (output->name, "default");
517
518       if (output->connection == RR_Disconnected)
519         {
520           XRRFreeOutputInfo (output);
521           continue;
522         }
523
524       if (output->crtc)
525         {
526           GdkX11Monitor monitor;
527           XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, output->crtc);
528
529           monitor.geometry.x = crtc->x;
530           monitor.geometry.y = crtc->y;
531           monitor.geometry.width = crtc->width;
532           monitor.geometry.height = crtc->height;
533
534           monitor.output = resources->outputs[i];
535           monitor.width_mm = output->mm_width;
536           monitor.height_mm = output->mm_height;
537           monitor.output_name = g_strdup (output->name);
538           /* FIXME: need EDID parser */
539           monitor.manufacturer = NULL;
540
541           g_array_append_val (monitors, monitor);
542
543           XRRFreeCrtcInfo (crtc);
544         }
545
546       XRRFreeOutputInfo (output);
547     }
548
549   if (resources->noutput > 0)
550     first_output = resources->outputs[0];
551
552   XRRFreeScreenResources (resources);
553
554   /* non RandR 1.2 X driver doesn't return any usable multihead data */
555   if (randr12_compat)
556     {
557       guint n_monitors = monitors->len;
558
559       free_monitors ((GdkX11Monitor *)g_array_free (monitors, FALSE),
560                      n_monitors);
561
562       return FALSE;
563     }
564
565   g_array_sort (monitors,
566                 (GCompareFunc) monitor_compare_function);
567   screen_x11->n_monitors = monitors->len;
568   screen_x11->monitors = (GdkX11Monitor *)g_array_free (monitors, FALSE);
569
570   screen_x11->primary_monitor = 0;
571
572   primary_output = XRRGetOutputPrimary (screen_x11->xdisplay,
573                                         screen_x11->xroot_window);
574
575   for (i = 0; i < screen_x11->n_monitors; ++i)
576     {
577       if (screen_x11->monitors[i].output == primary_output)
578         {
579           screen_x11->primary_monitor = i;
580           break;
581         }
582
583       /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */
584       if (primary_output == None &&
585           g_ascii_strncasecmp (screen_x11->monitors[i].output_name, "LVDS", 4) == 0)
586         {
587           screen_x11->primary_monitor = i;
588           break;
589         }
590
591       /* No primary specified and no LVDS found */
592       if (screen_x11->monitors[i].output == first_output)
593         screen_x11->primary_monitor = i;
594     }
595
596   return screen_x11->n_monitors > 0;
597 #endif
598
599   return FALSE;
600 }
601
602 static gboolean
603 init_solaris_xinerama (GdkScreen *screen)
604 {
605 #ifdef HAVE_SOLARIS_XINERAMA
606   Display *dpy = GDK_SCREEN_XDISPLAY (screen);
607   int screen_no = gdk_screen_get_number (screen);
608   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
609   XRectangle monitors[MAXFRAMEBUFFERS];
610   unsigned char hints[16];
611   gint result;
612   int n_monitors;
613   int i;
614   
615   if (!XineramaGetState (dpy, screen_no))
616     return FALSE;
617
618   result = XineramaGetInfo (dpy, screen_no, monitors, hints, &n_monitors);
619
620   /* Yes I know it should be Success but the current implementation 
621    * returns the num of monitor
622    */
623   if (result == 0)
624     {
625       return FALSE;
626     }
627
628   screen_x11->monitors = g_new0 (GdkX11Monitor, n_monitors);
629   screen_x11->n_monitors = n_monitors;
630
631   for (i = 0; i < n_monitors; i++)
632     {
633       init_monitor_geometry (&screen_x11->monitors[i],
634                              monitors[i].x, monitors[i].y,
635                              monitors[i].width, monitors[i].height);
636     }
637
638   screen_x11->primary_monitor = 0;
639
640   return TRUE;
641 #endif /* HAVE_SOLARIS_XINERAMA */
642
643   return FALSE;
644 }
645
646 static gboolean
647 init_xfree_xinerama (GdkScreen *screen)
648 {
649 #ifdef HAVE_XFREE_XINERAMA
650   Display *dpy = GDK_SCREEN_XDISPLAY (screen);
651   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
652   XineramaScreenInfo *monitors;
653   int i, n_monitors;
654   
655   if (!XineramaIsActive (dpy))
656     return FALSE;
657
658   monitors = XineramaQueryScreens (dpy, &n_monitors);
659   
660   if (n_monitors <= 0 || monitors == NULL)
661     {
662       /* If Xinerama doesn't think we have any monitors, try acting as
663        * though we had no Xinerama. If the "no monitors" condition
664        * is because XRandR 1.2 is currently switching between CRTCs,
665        * we'll be notified again when we have our monitor back,
666        * and can go back into Xinerama-ish mode at that point.
667        */
668       if (monitors)
669         XFree (monitors);
670       
671       return FALSE;
672     }
673
674   screen_x11->n_monitors = n_monitors;
675   screen_x11->monitors = g_new0 (GdkX11Monitor, n_monitors);
676   
677   for (i = 0; i < n_monitors; ++i)
678     {
679       init_monitor_geometry (&screen_x11->monitors[i],
680                              monitors[i].x_org, monitors[i].y_org,
681                              monitors[i].width, monitors[i].height);
682     }
683   
684   XFree (monitors);
685   
686   screen_x11->primary_monitor = 0;
687
688   return TRUE;
689 #endif /* HAVE_XFREE_XINERAMA */
690   
691   return FALSE;
692 }
693
694 static void
695 deinit_multihead (GdkScreen *screen)
696 {
697   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
698
699   free_monitors (screen_x11->monitors, screen_x11->n_monitors);
700
701   screen_x11->n_monitors = 0;
702   screen_x11->monitors = NULL;
703 }
704
705 static gboolean
706 compare_monitor (GdkX11Monitor *m1,
707                  GdkX11Monitor *m2)
708 {
709   if (m1->geometry.x != m2->geometry.x ||
710       m1->geometry.y != m2->geometry.y ||
711       m1->geometry.width != m2->geometry.width ||
712       m1->geometry.height != m2->geometry.height)
713     return FALSE;
714
715   if (m1->width_mm != m2->width_mm ||
716       m1->height_mm != m2->height_mm)
717     return FALSE;
718
719   if (g_strcmp0 (m1->output_name, m2->output_name) != 0)
720     return FALSE;
721
722   if (g_strcmp0 (m1->manufacturer, m2->manufacturer) != 0)
723     return FALSE;
724
725   return TRUE;
726 }
727
728 static gboolean
729 compare_monitors (GdkX11Monitor *monitors1, gint n_monitors1,
730                   GdkX11Monitor *monitors2, gint n_monitors2)
731 {
732   gint i;
733
734   if (n_monitors1 != n_monitors2)
735     return FALSE;
736
737   for (i = 0; i < n_monitors1; i++)
738     {
739       if (!compare_monitor (monitors1 + i, monitors2 + i))
740         return FALSE;
741     }
742
743   return TRUE;
744 }
745
746 static void
747 init_multihead (GdkScreen *screen)
748 {
749   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
750   int opcode, firstevent, firsterror;
751
752   /* There are four different implementations of multihead support: 
753    *
754    *  1. Fake Xinerama for debugging purposes
755    *  2. RandR 1.2
756    *  3. Solaris Xinerama
757    *  4. XFree86/Xorg Xinerama
758    *
759    * We use them in that order.
760    */
761   if (init_fake_xinerama (screen))
762     return;
763
764   if (init_randr13 (screen))
765     return;
766
767   if (XQueryExtension (GDK_SCREEN_XDISPLAY (screen), "XINERAMA",
768                        &opcode, &firstevent, &firsterror))
769     {
770       if (init_solaris_xinerama (screen))
771         return;
772       
773       if (init_xfree_xinerama (screen))
774         return;
775     }
776
777   /* No multihead support of any kind for this screen */
778   screen_x11->n_monitors = 1;
779   screen_x11->monitors = g_new0 (GdkX11Monitor, 1);
780   screen_x11->primary_monitor = 0;
781
782   init_monitor_geometry (screen_x11->monitors, 0, 0,
783                          WidthOfScreen (screen_x11->xscreen),
784                          HeightOfScreen (screen_x11->xscreen));
785 }
786
787 GdkScreen *
788 _gdk_x11_screen_new (GdkDisplay *display,
789                      gint        screen_number) 
790 {
791   GdkScreen *screen;
792   GdkScreenX11 *screen_x11;
793   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
794
795   screen = g_object_new (GDK_TYPE_SCREEN_X11, NULL);
796
797   screen_x11 = GDK_SCREEN_X11 (screen);
798   screen_x11->display = display;
799   screen_x11->xdisplay = display_x11->xdisplay;
800   screen_x11->xscreen = ScreenOfDisplay (display_x11->xdisplay, screen_number);
801   screen_x11->screen_num = screen_number;
802   screen_x11->xroot_window = RootWindow (display_x11->xdisplay,screen_number);
803   screen_x11->wmspec_check_window = None;
804   /* we want this to be always non-null */
805   screen_x11->window_manager_name = g_strdup ("unknown");
806   
807   init_multihead (screen);
808   init_randr_support (screen);
809   
810   _gdk_x11_screen_init_visuals (screen);
811   _gdk_x11_screen_init_root_window (screen);
812   
813   return screen;
814 }
815
816 /*
817  * It is important that we first request the selection
818  * notification, and then setup the initial state of
819  * is_composited to avoid a race condition here.
820  */
821 void
822 _gdk_x11_screen_setup (GdkScreen *screen)
823 {
824   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
825
826   screen_x11->cm_selection_atom = make_cm_atom (screen_x11->screen_num);
827   gdk_display_request_selection_notification (screen_x11->display,
828                                               screen_x11->cm_selection_atom);
829   screen_x11->is_composited = check_is_composited (screen_x11->display, screen_x11);
830 }
831
832 static gboolean
833 gdk_screen_x11_is_composited (GdkScreen *screen)
834 {
835   GdkScreenX11 *screen_x11;
836
837   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
838
839   screen_x11 = GDK_SCREEN_X11 (screen);
840
841   return screen_x11->is_composited;
842 }
843
844 static void
845 init_randr_support (GdkScreen * screen)
846 {
847   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
848   
849   XSelectInput (GDK_SCREEN_XDISPLAY (screen),
850                 screen_x11->xroot_window,
851                 StructureNotifyMask);
852
853 #ifdef HAVE_RANDR
854   XRRSelectInput (GDK_SCREEN_XDISPLAY (screen),
855                   screen_x11->xroot_window,
856                   RRScreenChangeNotifyMask      |
857                   RRCrtcChangeNotifyMask        |
858                   RROutputPropertyNotifyMask);
859 #endif
860 }
861
862 static void
863 process_monitors_change (GdkScreen *screen)
864 {
865   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
866   gint           n_monitors;
867   GdkX11Monitor *monitors;
868   gboolean changed;
869
870   n_monitors = screen_x11->n_monitors;
871   monitors = screen_x11->monitors;
872
873   screen_x11->n_monitors = 0;
874   screen_x11->monitors = NULL;
875
876   init_multihead (screen);
877
878   changed = !compare_monitors (monitors, n_monitors,
879                                screen_x11->monitors, screen_x11->n_monitors);
880
881   free_monitors (monitors, n_monitors);
882
883   if (changed)
884     g_signal_emit_by_name (screen, "monitors-changed");
885 }
886
887 void
888 _gdk_x11_screen_size_changed (GdkScreen *screen,
889                               XEvent    *event)
890 {
891   gint width, height;
892 #ifdef HAVE_RANDR
893   GdkDisplayX11 *display_x11;
894 #endif
895
896   width = gdk_screen_get_width (screen);
897   height = gdk_screen_get_height (screen);
898
899 #ifdef HAVE_RANDR
900   display_x11 = GDK_DISPLAY_X11 (gdk_screen_get_display (screen));
901
902   if (display_x11->have_randr13 && event->type == ConfigureNotify)
903     {
904       g_signal_emit_by_name (screen, "monitors-changed");
905       return;
906     }
907
908   XRRUpdateConfiguration (event);
909 #else
910   if (event->type == ConfigureNotify)
911     {
912       XConfigureEvent *rcevent = (XConfigureEvent *) event;
913       Screen        *xscreen = gdk_x11_screen_get_xscreen (screen);
914
915       xscreen->width   = rcevent->width;
916       xscreen->height  = rcevent->height;
917     }
918   else
919     return;
920 #endif
921
922   process_monitors_change (screen);
923
924   if (width != gdk_screen_get_width (screen) ||
925       height != gdk_screen_get_height (screen))
926     g_signal_emit_by_name (screen, "size-changed");
927 }
928
929 void
930 _gdk_x11_screen_window_manager_changed (GdkScreen *screen)
931 {
932   g_signal_emit (screen, signals[WINDOW_MANAGER_CHANGED], 0);
933 }
934
935 void
936 _gdk_x11_screen_process_owner_change (GdkScreen *screen,
937                                       XEvent *event)
938 {
939 #ifdef HAVE_XFIXES
940   XFixesSelectionNotifyEvent *selection_event = (XFixesSelectionNotifyEvent *)event;
941   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
942   Atom xcm_selection_atom = gdk_x11_atom_to_xatom_for_display (screen_x11->display,
943                                                                screen_x11->cm_selection_atom);
944
945   if (selection_event->selection == xcm_selection_atom)
946     {
947       gboolean composited = selection_event->owner != None;
948
949       if (composited != screen_x11->is_composited)
950         {
951           screen_x11->is_composited = composited;
952
953           g_signal_emit_by_name (screen, "composited-changed");
954         }
955     }
956 #endif
957 }
958
959 static gchar *
960 substitute_screen_number (const gchar *display_name,
961                           gint         screen_number)
962 {
963   GString *str;
964   gchar   *p;
965
966   str = g_string_new (display_name);
967
968   p = strrchr (str->str, '.');
969   if (p && p >  strchr (str->str, ':'))
970     g_string_truncate (str, p - str->str);
971
972   g_string_append_printf (str, ".%d", screen_number);
973
974   return g_string_free (str, FALSE);
975 }
976
977 static gchar *
978 gdk_screen_x11_make_display_name (GdkScreen *screen)
979 {
980   const gchar *old_display;
981
982   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
983
984   old_display = gdk_display_get_name (gdk_screen_get_display (screen));
985
986   return substitute_screen_number (old_display,
987                                    gdk_screen_get_number (screen));
988 }
989
990 static GdkWindow *
991 gdk_screen_x11_get_active_window (GdkScreen *screen)
992 {
993   GdkScreenX11 *screen_x11;
994   GdkWindow *ret = NULL;
995   Atom type_return;
996   gint format_return;
997   gulong nitems_return;
998   gulong bytes_after_return;
999   guchar *data = NULL;
1000
1001   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1002
1003   if (!gdk_x11_screen_supports_net_wm_hint (screen,
1004                                             gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
1005     return NULL;
1006
1007   screen_x11 = GDK_SCREEN_X11 (screen);
1008
1009   if (XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1010                           gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
1011                                                                  "_NET_ACTIVE_WINDOW"),
1012                           0, 1, False, XA_WINDOW, &type_return,
1013                           &format_return, &nitems_return,
1014                           &bytes_after_return, &data)
1015       == Success)
1016     {
1017       if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
1018         {
1019           GdkNativeWindow window = *(GdkNativeWindow *) data;
1020
1021           if (window != None)
1022             {
1023               ret = gdk_x11_window_foreign_new_for_display (screen_x11->display,
1024                                                         *(Window *) data);
1025             }
1026         }
1027     }
1028
1029   if (data)
1030     XFree (data);
1031
1032   return ret;
1033 }
1034
1035 static GList *
1036 gdk_screen_x11_get_window_stack (GdkScreen *screen)
1037 {
1038   GdkScreenX11 *screen_x11;
1039   GList *ret = NULL;
1040   Atom type_return;
1041   gint format_return;
1042   gulong nitems_return;
1043   gulong bytes_after_return;
1044   guchar *data = NULL;
1045
1046   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1047
1048   if (!gdk_x11_screen_supports_net_wm_hint (screen,
1049                                             gdk_atom_intern_static_string ("_NET_CLIENT_LIST_STACKING")))
1050     return NULL;
1051
1052   screen_x11 = GDK_SCREEN_X11 (screen);
1053
1054   if (XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1055                           gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
1056                                                                  "_NET_CLIENT_LIST_STACKING"),
1057                           0, G_MAXLONG, False, XA_WINDOW, &type_return,
1058                           &format_return, &nitems_return,
1059                           &bytes_after_return, &data)
1060       == Success)
1061     {
1062       if ((type_return == XA_WINDOW) && (format_return == 32) &&
1063           (data) && (nitems_return > 0))
1064         {
1065           gulong *stack = (gulong *) data;
1066           GdkWindow *win;
1067           int i;
1068
1069           for (i = 0; i < nitems_return; i++)
1070             {
1071               win = gdk_x11_window_foreign_new_for_display (screen_x11->display,
1072                                                             (Window)stack[i]);
1073
1074               if (win != NULL)
1075                 ret = g_list_append (ret, win);
1076             }
1077         }
1078     }
1079
1080   if (data)
1081     XFree (data);
1082
1083   return ret;
1084 }
1085
1086 /* Sends a ClientMessage to all toplevel client windows */
1087 static gboolean
1088 gdk_event_send_client_message_to_all_recurse (GdkDisplay *display,
1089                                               XEvent     *xev,
1090                                               guint32     xid,
1091                                               guint       level)
1092 {
1093   Atom type = None;
1094   int format;
1095   unsigned long nitems, after;
1096   unsigned char *data;
1097   Window *ret_children, ret_root, ret_parent;
1098   unsigned int ret_nchildren;
1099   gboolean send = FALSE;
1100   gboolean found = FALSE;
1101   gboolean result = FALSE;
1102   int i;
1103
1104   gdk_x11_display_error_trap_push (display);
1105
1106   if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xid,
1107                           gdk_x11_get_xatom_by_name_for_display (display, "WM_STATE"),
1108                           0, 0, False, AnyPropertyType,
1109                           &type, &format, &nitems, &after, &data) != Success)
1110     goto out;
1111
1112   if (type)
1113     {
1114       send = TRUE;
1115       XFree (data);
1116     }
1117   else
1118     {
1119       /* OK, we're all set, now let's find some windows to send this to */
1120       if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xid,
1121                       &ret_root, &ret_parent,
1122                       &ret_children, &ret_nchildren))
1123         goto out;
1124
1125       for(i = 0; i < ret_nchildren; i++)
1126         if (gdk_event_send_client_message_to_all_recurse (display, xev, ret_children[i], level + 1))
1127           found = TRUE;
1128
1129       XFree (ret_children);
1130     }
1131
1132   if (send || (!found && (level == 1)))
1133     {
1134       xev->xclient.window = xid;
1135       _gdk_x11_display_send_xevent (display, xid, False, NoEventMask, xev);
1136     }
1137
1138   result = send || found;
1139
1140  out:
1141   gdk_x11_display_error_trap_pop_ignored (display);
1142
1143   return result;
1144 }
1145
1146 static void
1147 gdk_screen_x11_broadcast_client_message (GdkScreen *screen,
1148                                          GdkEvent  *event)
1149 {
1150   XEvent sev;
1151   GdkWindow *root_window;
1152
1153   g_return_if_fail (event != NULL);
1154
1155   root_window = gdk_screen_get_root_window (screen);
1156
1157   /* Set up our event to send, with the exception of its target window */
1158   sev.xclient.type = ClientMessage;
1159   sev.xclient.display = GDK_WINDOW_XDISPLAY (root_window);
1160   sev.xclient.format = event->client.data_format;
1161   memcpy(&sev.xclient.data, &event->client.data, sizeof (sev.xclient.data));
1162   sev.xclient.message_type =
1163     gdk_x11_atom_to_xatom_for_display (GDK_WINDOW_DISPLAY (root_window),
1164                                        event->client.message_type);
1165
1166   gdk_event_send_client_message_to_all_recurse (gdk_screen_get_display (screen),
1167                                                 &sev,
1168                                                 GDK_WINDOW_XID (root_window),
1169                                                 0);
1170 }
1171
1172 static gboolean
1173 check_transform (const gchar *xsettings_name,
1174                  GType        src_type,
1175                  GType        dest_type)
1176 {
1177   if (!g_value_type_transformable (src_type, dest_type))
1178     {
1179       g_warning ("Cannot transform xsetting %s of type %s to type %s\n",
1180                  xsettings_name,
1181                  g_type_name (src_type),
1182                  g_type_name (dest_type));
1183       return FALSE;
1184     }
1185   else
1186     return TRUE;
1187 }
1188
1189 static gboolean
1190 gdk_screen_x11_get_setting (GdkScreen   *screen,
1191                             const gchar *name,
1192                             GValue      *value)
1193 {
1194
1195   const char *xsettings_name = NULL;
1196   XSettingsResult result;
1197   XSettingsSetting *setting = NULL;
1198   GdkScreenX11 *screen_x11;
1199   gboolean success = FALSE;
1200   gint i;
1201   GValue tmp_val = { 0, };
1202
1203   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
1204
1205   screen_x11 = GDK_SCREEN_X11 (screen);
1206
1207   for (i = 0; i < GDK_SETTINGS_N_ELEMENTS(); i++)
1208     if (strcmp (GDK_SETTINGS_GDK_NAME (i), name) == 0)
1209       {
1210         xsettings_name = GDK_SETTINGS_X_NAME (i);
1211         break;
1212       }
1213
1214   if (!xsettings_name)
1215     goto out;
1216
1217   result = xsettings_client_get_setting (screen_x11->xsettings_client,
1218                                          xsettings_name, &setting);
1219   if (result != XSETTINGS_SUCCESS)
1220     goto out;
1221
1222   switch (setting->type)
1223     {
1224     case XSETTINGS_TYPE_INT:
1225       if (check_transform (xsettings_name, G_TYPE_INT, G_VALUE_TYPE (value)))
1226         {
1227           g_value_init (&tmp_val, G_TYPE_INT);
1228           g_value_set_int (&tmp_val, setting->data.v_int);
1229           g_value_transform (&tmp_val, value);
1230
1231           success = TRUE;
1232         }
1233       break;
1234     case XSETTINGS_TYPE_STRING:
1235       if (check_transform (xsettings_name, G_TYPE_STRING, G_VALUE_TYPE (value)))
1236         {
1237           g_value_init (&tmp_val, G_TYPE_STRING);
1238           g_value_set_string (&tmp_val, setting->data.v_string);
1239           g_value_transform (&tmp_val, value);
1240
1241           success = TRUE;
1242         }
1243       break;
1244     case XSETTINGS_TYPE_COLOR:
1245       if (!check_transform (xsettings_name, GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
1246         {
1247           GdkColor color;
1248
1249           g_value_init (&tmp_val, GDK_TYPE_COLOR);
1250
1251           color.pixel = 0;
1252           color.red = setting->data.v_color.red;
1253           color.green = setting->data.v_color.green;
1254           color.blue = setting->data.v_color.blue;
1255
1256           g_value_set_boxed (&tmp_val, &color);
1257
1258           g_value_transform (&tmp_val, value);
1259
1260           success = TRUE;
1261         }
1262       break;
1263     }
1264
1265   g_value_unset (&tmp_val);
1266
1267  out:
1268   if (setting)
1269     xsettings_setting_free (setting);
1270
1271   if (success)
1272     return TRUE;
1273   else
1274     return _gdk_x11_get_xft_setting (screen, name, value);
1275 }
1276
1277 static void
1278 cleanup_atoms(gpointer data)
1279 {
1280   NetWmSupportedAtoms *supported_atoms = data;
1281   if (supported_atoms->atoms)
1282       XFree (supported_atoms->atoms);
1283   g_free (supported_atoms);
1284 }
1285
1286 static void
1287 fetch_net_wm_check_window (GdkScreen *screen)
1288 {
1289   GdkScreenX11 *screen_x11;
1290   GdkDisplay *display;
1291   Atom type;
1292   gint format;
1293   gulong n_items;
1294   gulong bytes_after;
1295   guchar *data;
1296   Window *xwindow;
1297   GTimeVal tv;
1298   gint error;
1299
1300   screen_x11 = GDK_SCREEN_X11 (screen);
1301   display = screen_x11->display;
1302
1303   g_return_if_fail (GDK_DISPLAY_X11 (display)->trusted_client);
1304   
1305   g_get_current_time (&tv);
1306
1307   if (ABS  (tv.tv_sec - screen_x11->last_wmspec_check_time) < 15)
1308     return; /* we've checked recently */
1309
1310   screen_x11->last_wmspec_check_time = tv.tv_sec;
1311
1312   data = NULL;
1313   XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1314                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTING_WM_CHECK"),
1315                       0, G_MAXLONG, False, XA_WINDOW, &type, &format,
1316                       &n_items, &bytes_after, &data);
1317   
1318   if (type != XA_WINDOW)
1319     {
1320       if (data)
1321         XFree (data);
1322       return;
1323     }
1324
1325   xwindow = (Window *)data;
1326
1327   if (screen_x11->wmspec_check_window == *xwindow)
1328     {
1329       XFree (xwindow);
1330       return;
1331     }
1332
1333   gdk_x11_display_error_trap_push (display);
1334
1335   /* Find out if this WM goes away, so we can reset everything. */
1336   XSelectInput (screen_x11->xdisplay, *xwindow, StructureNotifyMask);
1337
1338   error = gdk_x11_display_error_trap_pop (display);
1339   if (!error)
1340     {
1341       screen_x11->wmspec_check_window = *xwindow;
1342       screen_x11->need_refetch_net_supported = TRUE;
1343       screen_x11->need_refetch_wm_name = TRUE;
1344
1345       /* Careful, reentrancy */
1346       _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
1347     }
1348   else if (error == BadWindow)
1349     {
1350       /* Leftover property, try again immediately, new wm may be starting up */
1351       screen_x11->last_wmspec_check_time = 0;
1352     }
1353
1354   XFree (xwindow);
1355 }
1356
1357 /**
1358  * gdk_x11_screen_supports_net_wm_hint:
1359  * @screen: the relevant #GdkScreen.
1360  * @property: a property atom.
1361  *
1362  * This function is specific to the X11 backend of GDK, and indicates
1363  * whether the window manager supports a certain hint from the
1364  * Extended Window Manager Hints Specification. You can find this
1365  * specification on
1366  * <ulink url="http://www.freedesktop.org">http://www.freedesktop.org</ulink>.
1367  *
1368  * When using this function, keep in mind that the window manager
1369  * can change over time; so you shouldn't use this function in
1370  * a way that impacts persistent application state. A common bug
1371  * is that your application can start up before the window manager
1372  * does when the user logs in, and before the window manager starts
1373  * gdk_x11_screen_supports_net_wm_hint() will return %FALSE for every property.
1374  * You can monitor the window_manager_changed signal on #GdkScreen to detect
1375  * a window manager change.
1376  *
1377  * Return value: %TRUE if the window manager supports @property
1378  *
1379  * Since: 2.2
1380  **/
1381 gboolean
1382 gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen,
1383                                      GdkAtom    property)
1384 {
1385   gulong i;
1386   GdkScreenX11 *screen_x11;
1387   NetWmSupportedAtoms *supported_atoms;
1388   GdkDisplay *display;
1389
1390   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
1391
1392   screen_x11 = GDK_SCREEN_X11 (screen);
1393   display = screen_x11->display;
1394
1395   if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
1396     return FALSE;
1397
1398   supported_atoms = g_object_get_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms");
1399   if (!supported_atoms)
1400     {
1401       supported_atoms = g_new0 (NetWmSupportedAtoms, 1);
1402       g_object_set_data_full (G_OBJECT (screen), "gdk-net-wm-supported-atoms", supported_atoms, cleanup_atoms);
1403     }
1404
1405   fetch_net_wm_check_window (screen);
1406
1407   if (screen_x11->wmspec_check_window == None)
1408     return FALSE;
1409
1410   if (screen_x11->need_refetch_net_supported)
1411     {
1412       /* WM has changed since we last got the supported list,
1413        * refetch it.
1414        */
1415       Atom type;
1416       gint format;
1417       gulong bytes_after;
1418
1419       screen_x11->need_refetch_net_supported = FALSE;
1420
1421       if (supported_atoms->atoms)
1422         XFree (supported_atoms->atoms);
1423
1424       supported_atoms->atoms = NULL;
1425       supported_atoms->n_atoms = 0;
1426
1427       XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window,
1428                           gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTED"),
1429                           0, G_MAXLONG, False, XA_ATOM, &type, &format,
1430                           &supported_atoms->n_atoms, &bytes_after,
1431                           (guchar **)&supported_atoms->atoms);
1432
1433       if (type != XA_ATOM)
1434         return FALSE;
1435     }
1436
1437   if (supported_atoms->atoms == NULL)
1438     return FALSE;
1439
1440   i = 0;
1441   while (i < supported_atoms->n_atoms)
1442     {
1443       if (supported_atoms->atoms[i] == gdk_x11_atom_to_xatom_for_display (display, property))
1444         return TRUE;
1445
1446       ++i;
1447     }
1448
1449   return FALSE;
1450 }
1451
1452 /**
1453  * gdk_net_wm_supports:
1454  * @property: a property atom.
1455  *
1456  * This function is specific to the X11 backend of GDK, and indicates
1457  * whether the window manager for the default screen supports a certain
1458  * hint from the Extended Window Manager Hints Specification. See
1459  * gdk_x11_screen_supports_net_wm_hint() for complete details.
1460  *
1461  * Return value: %TRUE if the window manager supports @property
1462  **/
1463 gboolean
1464 gdk_net_wm_supports (GdkAtom property)
1465 {
1466   return gdk_x11_screen_supports_net_wm_hint (gdk_screen_get_default (), property);
1467 }
1468
1469 static void
1470 refcounted_grab_server (Display *xdisplay)
1471 {
1472   GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
1473
1474   gdk_x11_display_grab (display);
1475 }
1476
1477 static void
1478 refcounted_ungrab_server (Display *xdisplay)
1479 {
1480   GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
1481
1482   gdk_x11_display_ungrab (display);
1483 }
1484
1485 static GdkFilterReturn
1486 gdk_xsettings_client_event_filter (GdkXEvent *xevent,
1487                                    GdkEvent  *event,
1488                                    gpointer   data)
1489 {
1490   GdkScreenX11 *screen = data;
1491
1492   if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent))
1493     return GDK_FILTER_REMOVE;
1494   else
1495     return GDK_FILTER_CONTINUE;
1496 }
1497
1498 static Bool
1499 gdk_xsettings_watch_cb (Window   window,
1500                         Bool     is_start,
1501                         long     mask,
1502                         void    *cb_data)
1503 {
1504   GdkWindow *gdkwin;
1505   GdkScreen *screen = cb_data;
1506
1507   gdkwin = gdk_x11_window_lookup_for_display (gdk_screen_get_display (screen), window);
1508
1509   if (is_start)
1510     {
1511       if (gdkwin)
1512         g_object_ref (gdkwin);
1513       else
1514         {
1515           gdkwin = gdk_x11_window_foreign_new_for_display (gdk_screen_get_display (screen), window);
1516           
1517           /* gdk_window_foreign_new_for_display() can fail and return NULL if the
1518            * window has already been destroyed.
1519            */
1520           if (!gdkwin)
1521             return False;
1522         }
1523
1524       gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
1525     }
1526   else
1527     {
1528       if (!gdkwin)
1529         {
1530           /* gdkwin should not be NULL here, since if starting the watch succeeded
1531            * we have a reference on the window. It might mean that the caller didn't
1532            * remove the watch when it got a DestroyNotify event. Or maybe the
1533            * caller ignored the return value when starting the watch failed.
1534            */
1535           g_warning ("gdk_xsettings_watch_cb(): Couldn't find window to unwatch");
1536           return False;
1537         }
1538       
1539       gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
1540       g_object_unref (gdkwin);
1541     }
1542
1543   return True;
1544 }
1545
1546 static void
1547 gdk_xsettings_notify_cb (const char       *name,
1548                          XSettingsAction   action,
1549                          XSettingsSetting *setting,
1550                          void             *data)
1551 {
1552   GdkEvent new_event;
1553   GdkScreen *screen = data;
1554   GdkScreenX11 *screen_x11 = data;
1555   int i;
1556
1557   if (screen_x11->xsettings_in_init)
1558     return;
1559   
1560   new_event.type = GDK_SETTING;
1561   new_event.setting.window = gdk_screen_get_root_window (screen);
1562   new_event.setting.send_event = FALSE;
1563   new_event.setting.name = NULL;
1564
1565   for (i = 0; i < GDK_SETTINGS_N_ELEMENTS() ; i++)
1566     if (strcmp (GDK_SETTINGS_X_NAME (i), name) == 0)
1567       {
1568         new_event.setting.name = (char*) GDK_SETTINGS_GDK_NAME (i);
1569         break;
1570       }
1571   
1572   if (!new_event.setting.name)
1573     return;
1574   
1575   switch (action)
1576     {
1577     case XSETTINGS_ACTION_NEW:
1578       new_event.setting.action = GDK_SETTING_ACTION_NEW;
1579       break;
1580     case XSETTINGS_ACTION_CHANGED:
1581       new_event.setting.action = GDK_SETTING_ACTION_CHANGED;
1582       break;
1583     case XSETTINGS_ACTION_DELETED:
1584       new_event.setting.action = GDK_SETTING_ACTION_DELETED;
1585       break;
1586     }
1587
1588   gdk_event_put (&new_event);
1589 }
1590
1591 void
1592 _gdk_x11_screen_init_events (GdkScreen *screen)
1593 {
1594   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1595
1596   /* Keep a flag to avoid extra notifies that we don't need
1597    */
1598   screen_x11->xsettings_in_init = TRUE;
1599   screen_x11->xsettings_client = xsettings_client_new_with_grab_funcs (screen_x11->xdisplay,
1600                                                                        screen_x11->screen_num,
1601                                                                        gdk_xsettings_notify_cb,
1602                                                                        gdk_xsettings_watch_cb,
1603                                                                        screen,
1604                                                                        refcounted_grab_server,
1605                                                                        refcounted_ungrab_server);
1606   screen_x11->xsettings_in_init = FALSE;
1607 }
1608
1609 /**
1610  * gdk_x11_screen_get_window_manager_name:
1611  * @screen: a #GdkScreen
1612  *
1613  * Returns the name of the window manager for @screen.
1614  *
1615  * Return value: the name of the window manager screen @screen, or
1616  * "unknown" if the window manager is unknown. The string is owned by GDK
1617  * and should not be freed.
1618  *
1619  * Since: 2.2
1620  **/
1621 const char*
1622 gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
1623 {
1624   GdkScreenX11 *screen_x11;
1625   GdkDisplay *display;
1626
1627   screen_x11 = GDK_SCREEN_X11 (screen);
1628   display = screen_x11->display;
1629
1630   if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
1631     return screen_x11->window_manager_name;
1632
1633   fetch_net_wm_check_window (screen);
1634
1635   if (screen_x11->need_refetch_wm_name)
1636     {
1637       /* Get the name of the window manager */
1638       screen_x11->need_refetch_wm_name = FALSE;
1639
1640       g_free (screen_x11->window_manager_name);
1641       screen_x11->window_manager_name = g_strdup ("unknown");
1642
1643       if (screen_x11->wmspec_check_window != None)
1644         {
1645           Atom type;
1646           gint format;
1647           gulong n_items;
1648           gulong bytes_after;
1649           gchar *name;
1650
1651           name = NULL;
1652
1653           gdk_x11_display_error_trap_push (display);
1654
1655           XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
1656                               screen_x11->wmspec_check_window,
1657                               gdk_x11_get_xatom_by_name_for_display (display,
1658                                                                      "_NET_WM_NAME"),
1659                               0, G_MAXLONG, False,
1660                               gdk_x11_get_xatom_by_name_for_display (display,
1661                                                                      "UTF8_STRING"),
1662                               &type, &format,
1663                               &n_items, &bytes_after,
1664                               (guchar **)&name);
1665
1666           gdk_x11_display_error_trap_pop_ignored (display);
1667
1668           if (name != NULL)
1669             {
1670               g_free (screen_x11->window_manager_name);
1671               screen_x11->window_manager_name = g_strdup (name);
1672               XFree (name);
1673             }
1674         }
1675     }
1676
1677   return GDK_SCREEN_X11 (screen)->window_manager_name;
1678 }
1679
1680 static void
1681 _gdk_screen_x11_class_init (GdkScreenX11Class *klass)
1682 {
1683   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1684   GdkScreenClass *screen_class = GDK_SCREEN_CLASS (klass);
1685
1686   object_class->dispose = gdk_screen_x11_dispose;
1687   object_class->finalize = gdk_screen_x11_finalize;
1688
1689   screen_class->get_display = gdk_screen_x11_get_display;
1690   screen_class->get_width = gdk_screen_x11_get_width;
1691   screen_class->get_height = gdk_screen_x11_get_height;
1692   screen_class->get_width_mm = gdk_screen_x11_get_width_mm;
1693   screen_class->get_height_mm = gdk_screen_x11_get_height_mm;
1694   screen_class->get_number = gdk_screen_x11_get_number;
1695   screen_class->get_root_window = gdk_screen_x11_get_root_window;
1696   screen_class->get_n_monitors = gdk_screen_x11_get_n_monitors;
1697   screen_class->get_primary_monitor = gdk_screen_x11_get_primary_monitor;
1698   screen_class->get_monitor_width_mm = gdk_screen_x11_get_monitor_width_mm;
1699   screen_class->get_monitor_height_mm = gdk_screen_x11_get_monitor_height_mm;
1700   screen_class->get_monitor_plug_name = gdk_screen_x11_get_monitor_plug_name;
1701   screen_class->get_monitor_geometry = gdk_screen_x11_get_monitor_geometry;
1702   screen_class->get_system_visual = _gdk_screen_x11_get_system_visual;
1703   screen_class->get_rgba_visual = gdk_screen_x11_get_rgba_visual;
1704   screen_class->is_composited = gdk_screen_x11_is_composited;
1705   screen_class->make_display_name = gdk_screen_x11_make_display_name;
1706   screen_class->get_active_window = gdk_screen_x11_get_active_window;
1707   screen_class->get_window_stack = gdk_screen_x11_get_window_stack;
1708   screen_class->broadcast_client_message = gdk_screen_x11_broadcast_client_message;
1709   screen_class->get_setting = gdk_screen_x11_get_setting;
1710   screen_class->visual_get_best_depth = _gdk_screen_x11_visual_get_best_depth;
1711   screen_class->visual_get_best_type = _gdk_screen_x11_visual_get_best_type;
1712   screen_class->visual_get_best = _gdk_screen_x11_visual_get_best;
1713   screen_class->visual_get_best_with_depth = _gdk_screen_x11_visual_get_best_with_depth;
1714   screen_class->visual_get_best_with_type = _gdk_screen_x11_visual_get_best_with_type;
1715   screen_class->visual_get_best_with_both = _gdk_screen_x11_visual_get_best_with_both;
1716   screen_class->query_depths = _gdk_screen_x11_query_depths;
1717   screen_class->query_visual_types = _gdk_screen_x11_query_visual_types;
1718   screen_class->list_visuals = _gdk_screen_x11_list_visuals;
1719
1720   signals[WINDOW_MANAGER_CHANGED] =
1721     g_signal_new (g_intern_static_string ("window_manager_changed"),
1722                   G_OBJECT_CLASS_TYPE (object_class),
1723                   G_SIGNAL_RUN_LAST,
1724                   G_STRUCT_OFFSET (GdkScreenX11Class, window_manager_changed),
1725                   NULL, NULL,
1726                   g_cclosure_marshal_VOID__VOID,
1727                   G_TYPE_NONE,
1728                   0);
1729 }