]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkwindow-x11.c
Merge branch 'gdk-backend-wayland'
[~andy/gtk] / gdk / x11 / gdkwindow-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3  * Josh MacDonald, Ryan Lortie
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "config.h"
29
30 #include "gdkwindow-x11.h"
31
32 #include "gdkwindow.h"
33 #include "gdkwindowimpl.h"
34 #include "gdkvisualprivate.h"
35 #include "gdkinternals.h"
36 #include "gdkdeviceprivate.h"
37 #include "gdkasync.h"
38 #include "gdkeventsource.h"
39 #include "gdkdisplay-x11.h"
40 #include "gdkprivate-x11.h"
41
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <netinet/in.h>
46 #include <unistd.h>
47
48 #include <cairo-xlib.h>
49
50 #include "MwmUtil.h"
51
52 #include <X11/Xlib.h>
53 #include <X11/Xutil.h>
54 #include <X11/Xatom.h>
55
56 #include <X11/extensions/shape.h>
57
58 #ifdef HAVE_XKB
59 #include <X11/XKBlib.h>
60 #endif
61
62 #ifdef HAVE_XCOMPOSITE
63 #include <X11/extensions/Xcomposite.h>
64 #endif
65
66 #ifdef HAVE_XFIXES
67 #include <X11/extensions/Xfixes.h>
68 #endif
69
70 #ifdef HAVE_XDAMAGE
71 #include <X11/extensions/Xdamage.h>
72 #endif
73
74 const int _gdk_x11_event_mask_table[21] =
75 {
76   ExposureMask,
77   PointerMotionMask,
78   PointerMotionHintMask,
79   ButtonMotionMask,
80   Button1MotionMask,
81   Button2MotionMask,
82   Button3MotionMask,
83   ButtonPressMask,
84   ButtonReleaseMask,
85   KeyPressMask,
86   KeyReleaseMask,
87   EnterWindowMask,
88   LeaveWindowMask,
89   FocusChangeMask,
90   StructureNotifyMask,
91   PropertyChangeMask,
92   VisibilityChangeMask,
93   0,                    /* PROXIMITY_IN */
94   0,                    /* PROXIMTY_OUT */
95   SubstructureNotifyMask,
96   ButtonPressMask      /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
97 };
98
99 const gint _gdk_x11_event_mask_table_size = G_N_ELEMENTS (_gdk_x11_event_mask_table);
100
101 /* Forward declarations */
102 static void     gdk_window_set_static_win_gravity (GdkWindow  *window,
103                                                    gboolean    on);
104 static gboolean gdk_window_icon_name_set          (GdkWindow  *window);
105 static void     set_wm_name                       (GdkDisplay  *display,
106                                                    Window       xwindow,
107                                                    const gchar *name);
108 static void     move_to_current_desktop           (GdkWindow *window);
109 static void     gdk_window_x11_set_background     (GdkWindow      *window,
110                                                    cairo_pattern_t *pattern);
111
112 static void        gdk_window_impl_x11_finalize   (GObject            *object);
113
114 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
115   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
116    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
117
118 #define WINDOW_IS_TOPLEVEL(window)                   \
119   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
120    GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
121    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
122
123 /* Return whether time1 is considered later than time2 as far as xserver
124  * time is concerned.  Accounts for wraparound.
125  */
126 #define XSERVER_TIME_IS_LATER(time1, time2)                        \
127   ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
128     (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
129   )
130
131 struct _GdkX11Window {
132   GdkWindow parent;
133 };
134
135 struct _GdkX11WindowClass {
136   GdkWindowClass parent_class;
137 };
138
139 G_DEFINE_TYPE (GdkX11Window, gdk_x11_window, GDK_TYPE_WINDOW)
140
141 static void
142 gdk_x11_window_class_init (GdkX11WindowClass *x11_window_class)
143 {
144 }
145
146 static void
147 gdk_x11_window_init (GdkX11Window *x11_window)
148 {
149 }
150
151
152 G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GDK_TYPE_WINDOW_IMPL)
153
154 static void
155 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
156 {  
157   impl->toplevel_window_type = -1;
158   impl->device_cursor = g_hash_table_new_full (NULL, NULL,
159                                                NULL, g_object_unref);
160 }
161
162 GdkToplevelX11 *
163 _gdk_x11_window_get_toplevel (GdkWindow *window)
164 {
165   GdkWindowImplX11 *impl;
166   
167   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
168
169   if (!WINDOW_IS_TOPLEVEL (window))
170     return NULL;
171
172   impl = GDK_WINDOW_IMPL_X11 (window->impl);
173
174   if (!impl->toplevel)
175     impl->toplevel = g_new0 (GdkToplevelX11, 1);
176
177   return impl->toplevel;
178 }
179
180 static const cairo_user_data_key_t gdk_x11_cairo_key;
181
182 /**
183  * _gdk_x11_window_update_size:
184  * @impl: a #GdkWindowImplX11.
185  * 
186  * Updates the state of the window (in particular the drawable's
187  * cairo surface) when its size has changed.
188  **/
189 void
190 _gdk_x11_window_update_size (GdkWindowImplX11 *impl)
191 {
192   if (impl->cairo_surface)
193     {
194       cairo_xlib_surface_set_size (impl->cairo_surface,
195                                    gdk_window_get_width (impl->wrapper),
196                                    gdk_window_get_height (impl->wrapper));
197     }
198 }
199
200 /*****************************************************
201  * X11 specific implementations of generic functions *
202  *****************************************************/
203
204 static void
205 gdk_x11_cairo_surface_destroy (void *data)
206 {
207   GdkWindowImplX11 *impl = data;
208
209   impl->cairo_surface = NULL;
210 }
211
212 static cairo_surface_t *
213 gdk_x11_create_cairo_surface (GdkWindowImplX11 *impl,
214                               int width,
215                               int height)
216 {
217   GdkVisual *visual;
218     
219   visual = gdk_window_get_visual (impl->wrapper);
220   return cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (impl->wrapper),
221                                     GDK_WINDOW_IMPL_X11 (impl)->xid,
222                                     GDK_VISUAL_XVISUAL (visual),
223                                     width, height);
224 }
225
226 static cairo_surface_t *
227 gdk_x11_ref_cairo_surface (GdkWindow *window)
228 {
229   GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
230
231   if (GDK_WINDOW_DESTROYED (window))
232     return NULL;
233
234   if (!impl->cairo_surface)
235     {
236       impl->cairo_surface = gdk_x11_create_cairo_surface (impl,
237                                                           gdk_window_get_width (window),
238                                                           gdk_window_get_height (window));
239       
240       if (impl->cairo_surface)
241         cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
242                                      impl, gdk_x11_cairo_surface_destroy);
243     }
244   else
245     cairo_surface_reference (impl->cairo_surface);
246
247   return impl->cairo_surface;
248 }
249
250 static void
251 gdk_window_impl_x11_finalize (GObject *object)
252 {
253   GdkWindow *wrapper;
254   GdkWindowImplX11 *impl;
255
256   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
257
258   impl = GDK_WINDOW_IMPL_X11 (object);
259
260   wrapper = impl->wrapper;
261
262   _gdk_x11_window_grab_check_destroy (wrapper);
263
264   if (!GDK_WINDOW_DESTROYED (wrapper))
265     {
266       GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
267
268       _gdk_x11_display_remove_window (display, impl->xid);
269       if (impl->toplevel && impl->toplevel->focus_window)
270         _gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
271     }
272
273   g_free (impl->toplevel);
274
275   if (impl->cursor)
276     gdk_cursor_unref (impl->cursor);
277
278   g_hash_table_destroy (impl->device_cursor);
279
280   G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
281 }
282
283 typedef struct {
284   GdkDisplay *display;
285   Pixmap pixmap;
286 } FreePixmapData;
287
288 static void
289 free_pixmap (gpointer datap)
290 {
291   FreePixmapData *data = datap;
292
293   if (!gdk_display_is_closed (data->display))
294     {
295       XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display),
296                    data->pixmap);
297     }
298
299   g_object_unref (data->display);
300   g_slice_free (FreePixmapData, data);
301 }
302
303 static void
304 attach_free_pixmap_handler (cairo_surface_t *surface,
305                             GdkDisplay      *display,
306                             Pixmap           pixmap)
307 {
308   static const cairo_user_data_key_t key;
309   FreePixmapData *data;
310   
311   data = g_slice_new (FreePixmapData);
312   data->display = g_object_ref (display);
313   data->pixmap = pixmap;
314
315   cairo_surface_set_user_data (surface, &key, data, free_pixmap);
316 }
317
318 /* Cairo does not guarantee we get an xlib surface if we call
319  * cairo_surface_create_similar(). In some cases however, we must use a
320  * pixmap or bitmap in the X11 API.
321  * These functions ensure an Xlib surface.
322  */
323 cairo_surface_t *
324 _gdk_x11_window_create_bitmap_surface (GdkWindow *window,
325                                        int        width,
326                                        int        height)
327 {
328   cairo_surface_t *surface;
329   Pixmap pixmap;
330
331   pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
332                           GDK_WINDOW_XID (window),
333                           width, height, 1);
334   surface = cairo_xlib_surface_create_for_bitmap (GDK_WINDOW_XDISPLAY (window),
335                                                   pixmap,
336                                                   GDK_X11_SCREEN (GDK_WINDOW_SCREEN (window))->xscreen,
337                                                   width, height);
338   attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
339
340   return surface;
341 }
342
343 /* Create a surface backed with a pixmap without alpha on the same screen as window */
344 static cairo_surface_t *
345 gdk_x11_window_create_pixmap_surface (GdkWindow *window,
346                                       int        width,
347                                       int        height)
348 {
349   GdkScreen *screen = gdk_window_get_screen (window);
350   GdkVisual *visual = gdk_screen_get_system_visual (screen);
351   cairo_surface_t *surface;
352   Pixmap pixmap;
353
354   pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
355                           GDK_WINDOW_XID (window),
356                           width, height,
357                           gdk_visual_get_depth (visual));
358   surface = cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (window),
359                                        pixmap,
360                                        GDK_VISUAL_XVISUAL (visual),
361                                        width, height);
362   attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
363
364   return surface;
365 }
366
367 static void
368 tmp_unset_bg (GdkWindow *window)
369 {
370   GdkWindowImplX11 *impl;
371
372   impl = GDK_WINDOW_IMPL_X11 (window->impl);
373
374   impl->no_bg = TRUE;
375
376   XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
377                               GDK_WINDOW_XID (window), None);
378 }
379
380 static void
381 tmp_reset_bg (GdkWindow *window)
382 {
383   GdkWindowImplX11 *impl;
384
385   impl = GDK_WINDOW_IMPL_X11 (window->impl);
386
387   impl->no_bg = FALSE;
388
389   gdk_window_x11_set_background (window, window->background);
390 }
391
392 /* Unsetting and resetting window backgrounds.
393  *
394  * In many cases it is possible to avoid flicker by unsetting the
395  * background of windows. For example if the background of the
396  * parent window is unset when a window is unmapped, a brief flicker
397  * of background painting is avoided.
398  */
399 void
400 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
401                               gboolean   recurse)
402 {
403   g_return_if_fail (GDK_IS_WINDOW (window));
404   
405   if (window->input_only || window->destroyed ||
406       (window->window_type != GDK_WINDOW_ROOT &&
407        !GDK_WINDOW_IS_MAPPED (window)))
408     return;
409   
410   if (_gdk_window_has_impl (window) &&
411       GDK_WINDOW_IS_X11 (window) &&
412       window->window_type != GDK_WINDOW_ROOT &&
413       window->window_type != GDK_WINDOW_FOREIGN)
414     tmp_unset_bg (window);
415
416   if (recurse)
417     {
418       GList *l;
419
420       for (l = window->children; l != NULL; l = l->next)
421         _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
422     }
423 }
424
425 void
426 _gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window)
427 {
428   if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
429     return;
430   
431   window = _gdk_window_get_impl_window (window->parent);
432   _gdk_x11_window_tmp_unset_bg (window, FALSE);
433 }
434
435 void
436 _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
437                               gboolean   recurse)
438 {
439   g_return_if_fail (GDK_IS_WINDOW (window));
440
441   if (window->input_only || window->destroyed ||
442       (window->window_type != GDK_WINDOW_ROOT &&
443        !GDK_WINDOW_IS_MAPPED (window)))
444     return;
445
446   
447   if (_gdk_window_has_impl (window) &&
448       GDK_WINDOW_IS_X11 (window) &&
449       window->window_type != GDK_WINDOW_ROOT &&
450       window->window_type != GDK_WINDOW_FOREIGN)
451     tmp_reset_bg (window);
452
453   if (recurse)
454     {
455       GList *l;
456
457       for (l = window->children; l != NULL; l = l->next)
458         _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
459     }
460 }
461
462 void
463 _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
464 {
465   if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
466     return;
467   
468   window = _gdk_window_get_impl_window (window->parent);
469
470   _gdk_x11_window_tmp_reset_bg (window, FALSE);
471 }
472
473 void
474 _gdk_x11_screen_init_root_window (GdkScreen *screen)
475 {
476   GdkWindow *window;
477   GdkWindowImplX11 *impl;
478   GdkX11Screen *x11_screen;
479
480   x11_screen = GDK_X11_SCREEN (screen);
481
482   g_assert (x11_screen->root_window == NULL);
483
484   window = x11_screen->root_window = _gdk_display_create_window (gdk_screen_get_display (screen));
485
486   window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
487   window->impl_window = window;
488   window->visual = gdk_screen_get_system_visual (screen);
489
490   impl = GDK_WINDOW_IMPL_X11 (window->impl);
491   
492   impl->xid = x11_screen->xroot_window;
493   impl->wrapper = window;
494   
495   window->window_type = GDK_WINDOW_ROOT;
496   window->depth = DefaultDepthOfScreen (x11_screen->xscreen);
497
498   window->x = 0;
499   window->y = 0;
500   window->abs_x = 0;
501   window->abs_y = 0;
502   window->width = WidthOfScreen (x11_screen->xscreen);
503   window->height = HeightOfScreen (x11_screen->xscreen);
504   window->viewable = TRUE;
505
506   /* see init_randr_support() in gdkscreen-x11.c */
507   window->event_mask = GDK_STRUCTURE_MASK;
508
509   _gdk_window_update_size (x11_screen->root_window);
510
511   _gdk_x11_display_add_window (x11_screen->display,
512                                &x11_screen->xroot_window,
513                                x11_screen->root_window);
514 }
515
516 static void
517 set_wm_protocols (GdkWindow *window)
518 {
519   GdkDisplay *display = gdk_window_get_display (window);
520   Atom protocols[4];
521   int n = 0;
522   
523   protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
524   protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
525   protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
526
527 #ifdef HAVE_XSYNC
528   if (GDK_X11_DISPLAY (display)->use_sync)
529     protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
530 #endif
531   
532   XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
533 }
534
535 static const gchar *
536 get_default_title (void)
537 {
538   const char *title;
539
540   title = g_get_application_name ();
541   if (!title)
542     title = g_get_prgname ();
543   if (!title)
544     title = "";
545
546   return title;
547 }
548
549 static void
550 check_leader_window_title (GdkDisplay *display)
551 {
552   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
553
554   if (display_x11->leader_window && !display_x11->leader_window_title_set)
555     {
556       set_wm_name (display,
557                    display_x11->leader_window,
558                    get_default_title ());
559       
560       display_x11->leader_window_title_set = TRUE;
561     }
562 }
563
564 static Window
565 create_focus_window (GdkDisplay *display,
566                      XID         parent)
567 {
568   GdkX11Display *display_x11;
569   GdkEventMask event_mask;
570   Display *xdisplay;
571   Window focus_window;
572
573   xdisplay = GDK_DISPLAY_XDISPLAY (display);
574   display_x11 = GDK_X11_DISPLAY (display);
575
576   focus_window = XCreateSimpleWindow (xdisplay, parent,
577                                       -1, -1, 1, 1, 0,
578                                       0, 0);
579
580   /* FIXME: probably better to actually track the requested event mask for the toplevel
581    */
582   event_mask = (GDK_KEY_PRESS_MASK |
583                 GDK_KEY_RELEASE_MASK |
584                 GDK_FOCUS_CHANGE_MASK);
585
586   gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
587                                       focus_window,
588                                       event_mask, 0);
589
590   XMapWindow (xdisplay, focus_window);
591
592   return focus_window;
593 }
594
595 static void
596 ensure_sync_counter (GdkWindow *window)
597 {
598 #ifdef HAVE_XSYNC
599   if (!GDK_WINDOW_DESTROYED (window))
600     {
601       GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
602       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
603       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
604
605       if (toplevel && impl->use_synchronized_configure &&
606           toplevel->update_counter == None &&
607           GDK_X11_DISPLAY (display)->use_sync)
608         {
609           Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
610           XSyncValue value;
611           Atom atom;
612
613           XSyncIntToValue (&value, 0);
614           
615           toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
616           
617           atom = gdk_x11_get_xatom_by_name_for_display (display,
618                                                         "_NET_WM_SYNC_REQUEST_COUNTER");
619           
620           XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
621                            atom, XA_CARDINAL,
622                            32, PropModeReplace,
623                            (guchar *)&toplevel->update_counter, 1);
624           
625           XSyncIntToValue (&toplevel->current_counter_value, 0);
626         }
627     }
628 #endif
629 }
630
631 static void
632 setup_toplevel_window (GdkWindow *window, 
633                        GdkWindow *parent)
634 {
635   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
636   GdkDisplay *display = gdk_window_get_display (window);
637   Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
638   XID xid = GDK_WINDOW_XID (window);
639   GdkX11Screen *x11_screen = GDK_X11_SCREEN (GDK_WINDOW_SCREEN (parent));
640   XSizeHints size_hints;
641   long pid;
642   Window leader_window;
643
644   set_wm_protocols (window);
645
646   if (!window->input_only)
647     {
648       /* The focus window is off the visible area, and serves to receive key
649        * press events so they don't get sent to child windows.
650        */
651       toplevel->focus_window = create_focus_window (display, xid);
652       _gdk_x11_display_add_window (x11_screen->display,
653                                    &toplevel->focus_window,
654                                    window);
655     }
656
657   check_leader_window_title (x11_screen->display);
658
659   /* FIXME: Is there any point in doing this? Do any WM's pay
660    * attention to PSize, and even if they do, is this the
661    * correct value???
662    */
663   size_hints.flags = PSize;
664   size_hints.width = window->width;
665   size_hints.height = window->height;
666   
667   XSetWMNormalHints (xdisplay, xid, &size_hints);
668   
669   /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
670   XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
671   
672   pid = getpid ();
673   XChangeProperty (xdisplay, xid,
674                    gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
675                    XA_CARDINAL, 32,
676                    PropModeReplace,
677                    (guchar *)&pid, 1);
678
679   leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window;
680   if (!leader_window)
681     leader_window = xid;
682   XChangeProperty (xdisplay, xid, 
683                    gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"),
684                    XA_WINDOW, 32, PropModeReplace,
685                    (guchar *) &leader_window, 1);
686
687   if (toplevel->focus_window != None)
688     XChangeProperty (xdisplay, xid, 
689                      gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"),
690                      XA_WINDOW, 32, PropModeReplace,
691                      (guchar *) &toplevel->focus_window, 1);
692
693   if (!window->focus_on_map)
694     gdk_x11_window_set_user_time (window, 0);
695   else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
696     gdk_x11_window_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
697
698   ensure_sync_counter (window);
699 }
700
701 void
702 _gdk_x11_display_create_window_impl (GdkDisplay    *display,
703                                      GdkWindow     *window,
704                                      GdkWindow     *real_parent,
705                                      GdkScreen     *screen,
706                                      GdkEventMask   event_mask,
707                                      GdkWindowAttr *attributes,
708                                      gint           attributes_mask)
709 {
710   GdkWindowImplX11 *impl;
711   GdkX11Screen *x11_screen;
712   GdkX11Display *display_x11;
713
714   Window xparent;
715   Visual *xvisual;
716   Display *xdisplay;
717
718   XSetWindowAttributes xattributes;
719   long xattributes_mask;
720   XClassHint *class_hint;
721
722   unsigned int class;
723   const char *title;
724
725   display_x11 = GDK_X11_DISPLAY (display);
726   xparent = GDK_WINDOW_XID (real_parent);
727   x11_screen = GDK_X11_SCREEN (screen);
728
729   impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
730   window->impl = GDK_WINDOW_IMPL (impl);
731   impl->wrapper = GDK_WINDOW (window);
732
733   xdisplay = x11_screen->xdisplay;
734
735   xattributes_mask = 0;
736
737   xvisual = gdk_x11_visual_get_xvisual (window->visual);
738
739   if (attributes_mask & GDK_WA_NOREDIR)
740     {
741       xattributes.override_redirect =
742         (attributes->override_redirect == FALSE)?False:True;
743       xattributes_mask |= CWOverrideRedirect;
744     }
745   else
746     xattributes.override_redirect = False;
747
748   impl->override_redirect = xattributes.override_redirect;
749
750   if (window->parent && window->parent->guffaw_gravity)
751     {
752       xattributes.win_gravity = StaticGravity;
753       xattributes_mask |= CWWinGravity;
754     }
755
756   /* Sanity checks */
757   switch (window->window_type)
758     {
759     case GDK_WINDOW_TOPLEVEL:
760     case GDK_WINDOW_TEMP:
761       if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
762         {
763           /* The common code warns for this case */
764           xparent = GDK_SCREEN_XROOTWIN (screen);
765         }
766     }
767
768   if (!window->input_only)
769     {
770       class = InputOutput;
771
772       xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
773
774       xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
775       xattributes_mask |= CWBorderPixel | CWBackPixel;
776
777       if (window->guffaw_gravity)
778         xattributes.bit_gravity = StaticGravity;
779       else
780         xattributes.bit_gravity = NorthWestGravity;
781
782       xattributes_mask |= CWBitGravity;
783
784       xattributes.colormap = _gdk_visual_get_x11_colormap (window->visual);
785       xattributes_mask |= CWColormap;
786
787       if (window->window_type == GDK_WINDOW_TEMP)
788         {
789           xattributes.save_under = True;
790           xattributes.override_redirect = True;
791           xattributes.cursor = None;
792           xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
793
794           impl->override_redirect = TRUE;
795         }
796     }
797   else
798     {
799       class = InputOnly;
800     }
801
802   if (window->width > 65535 ||
803       window->height > 65535)
804     {
805       g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
806
807       if (window->width > 65535)
808         window->width = 65535;
809       if (window->height > 65535)
810         window->height = 65535;
811     }
812
813   impl->xid = XCreateWindow (xdisplay, xparent,
814                              window->x + window->parent->abs_x,
815                              window->y + window->parent->abs_y,
816                              window->width, window->height,
817                              0, window->depth, class, xvisual,
818                              xattributes_mask, &xattributes);
819
820   g_object_ref (window);
821   _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
822
823   switch (GDK_WINDOW_TYPE (window))
824     {
825     case GDK_WINDOW_TOPLEVEL:
826     case GDK_WINDOW_TEMP:
827       if (attributes_mask & GDK_WA_TITLE)
828         title = attributes->title;
829       else
830         title = get_default_title ();
831
832       gdk_window_set_title (window, title);
833
834       if (attributes_mask & GDK_WA_WMCLASS)
835         {
836           class_hint = XAllocClassHint ();
837           class_hint->res_name = attributes->wmclass_name;
838           class_hint->res_class = attributes->wmclass_class;
839           XSetClassHint (xdisplay, impl->xid, class_hint);
840           XFree (class_hint);
841         }
842
843       setup_toplevel_window (window, window->parent);
844       break;
845
846     case GDK_WINDOW_CHILD:
847     default:
848       break;
849     }
850
851   if (attributes_mask & GDK_WA_TYPE_HINT)
852     gdk_window_set_type_hint (window, attributes->type_hint);
853
854   gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
855                                       GDK_WINDOW_XID (window), event_mask,
856                                       StructureNotifyMask | PropertyChangeMask);
857 }
858
859 static GdkEventMask
860 x_event_mask_to_gdk_event_mask (long mask)
861 {
862   GdkEventMask event_mask = 0;
863   int i;
864
865   for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
866     {
867       if (mask & _gdk_x11_event_mask_table[i])
868         event_mask |= 1 << (i + 1);
869     }
870
871   return event_mask;
872 }
873
874 /**
875  * gdk_x11_window_foreign_new_for_display:
876  * @display: the #GdkDisplay where the window handle comes from.
877  * @window: an XLib <type>Window</type>
878  *
879  * Wraps a native window in a #GdkWindow. The function will try to
880  * look up the window using gdk_x11_window_lookup_for_display() first.
881  * If it does not find it there, it will create a new window.
882  *
883  * This may fail if the window has been destroyed. If the window
884  * was already known to GDK, a new reference to the existing
885  * #GdkWindow is returned.
886  *
887  * Return value: (transfer full): a #GdkWindow wrapper for the native
888  *   window, or %NULL if the window has been destroyed. The wrapper
889  *   will be newly created, if one doesn't exist already.
890  *
891  * Since: 2.24
892  */
893 GdkWindow *
894 gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
895                                         Window      window)
896 {
897   GdkScreen *screen;
898   GdkWindow *win;
899   GdkWindowImplX11 *impl;
900   GdkX11Display *display_x11;
901   XWindowAttributes attrs;
902   Window root, parent;
903   Window *children = NULL;
904   guint nchildren;
905   gboolean result;
906
907   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
908
909   display_x11 = GDK_X11_DISPLAY (display);
910
911   if ((win = gdk_x11_window_lookup_for_display (display, window)) != NULL)
912     return g_object_ref (win);
913
914   gdk_x11_display_error_trap_push (display);
915   result = XGetWindowAttributes (display_x11->xdisplay, window, &attrs);
916   if (gdk_x11_display_error_trap_pop (display) || !result)
917     return NULL;
918
919   /* FIXME: This is pretty expensive.
920    * Maybe the caller should supply the parent
921    */
922   gdk_x11_display_error_trap_push (display);
923   result = XQueryTree (display_x11->xdisplay, window, &root, &parent, &children, &nchildren);
924   if (gdk_x11_display_error_trap_pop (display) || !result)
925     return NULL;
926
927   if (children)
928     XFree (children);
929
930   screen = _gdk_x11_display_screen_for_xrootwin (display, root);
931
932   win = _gdk_display_create_window (display);
933   win->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
934   win->impl_window = win;
935   win->visual = gdk_x11_screen_lookup_visual (screen,
936                                               XVisualIDFromVisual (attrs.visual));
937
938   impl = GDK_WINDOW_IMPL_X11 (win->impl);
939   impl->wrapper = win;
940
941   win->parent = gdk_x11_window_lookup_for_display (display, parent);
942
943   if (!win->parent || GDK_WINDOW_TYPE (win->parent) == GDK_WINDOW_FOREIGN)
944     win->parent = gdk_screen_get_root_window (screen);
945
946   win->parent->children = g_list_prepend (win->parent->children, win);
947
948   impl->xid = window;
949
950   win->x = attrs.x;
951   win->y = attrs.y;
952   win->width = attrs.width;
953   win->height = attrs.height;
954   win->window_type = GDK_WINDOW_FOREIGN;
955   win->destroyed = FALSE;
956
957   win->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
958
959   if (attrs.map_state == IsUnmapped)
960     win->state = GDK_WINDOW_STATE_WITHDRAWN;
961   else
962     win->state = 0;
963   win->viewable = TRUE;
964
965   win->depth = attrs.depth;
966
967   g_object_ref (win);
968   _gdk_x11_display_add_window (display, &GDK_WINDOW_XID (win), win);
969
970   /* Update the clip region, etc */
971   _gdk_window_update_size (win);
972
973   return win;
974 }
975
976 static void
977 gdk_toplevel_x11_free_contents (GdkDisplay *display,
978                                 GdkToplevelX11 *toplevel)
979 {
980   if (toplevel->icon_pixmap)
981     {
982       cairo_surface_destroy (toplevel->icon_pixmap);
983       toplevel->icon_pixmap = NULL;
984     }
985   if (toplevel->icon_mask)
986     {
987       cairo_surface_destroy (toplevel->icon_mask);
988       toplevel->icon_mask = NULL;
989     }
990   if (toplevel->group_leader)
991     {
992       g_object_unref (toplevel->group_leader);
993       toplevel->group_leader = NULL;
994     }
995 #ifdef HAVE_XSYNC
996   if (toplevel->update_counter != None)
997     {
998       XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display), 
999                            toplevel->update_counter);
1000       toplevel->update_counter = None;
1001
1002       XSyncIntToValue (&toplevel->current_counter_value, 0);
1003     }
1004 #endif
1005 }
1006
1007 static void
1008 gdk_x11_window_destroy (GdkWindow *window,
1009                         gboolean   recursing,
1010                         gboolean   foreign_destroy)
1011 {
1012   GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1013   GdkToplevelX11 *toplevel;
1014
1015   g_return_if_fail (GDK_IS_WINDOW (window));
1016
1017   _gdk_x11_selection_window_destroyed (window);
1018
1019   toplevel = _gdk_x11_window_get_toplevel (window);
1020   if (toplevel)
1021     gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
1022
1023   if (impl->cairo_surface)
1024     {
1025       cairo_surface_finish (impl->cairo_surface);
1026       cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
1027                                    NULL, NULL);
1028     }
1029
1030   if (!recursing && !foreign_destroy)
1031     XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1032 }
1033
1034 static cairo_surface_t *
1035 gdk_window_x11_resize_cairo_surface (GdkWindow       *window,
1036                                      cairo_surface_t *surface,
1037                                      gint             width,
1038                                      gint             height)
1039 {
1040   cairo_xlib_surface_set_size (surface, width, height);
1041
1042   return surface;
1043 }
1044
1045 static void
1046 gdk_x11_window_destroy_foreign (GdkWindow *window)
1047 {
1048   /* It's somebody else's window, but in our hierarchy,
1049    * so reparent it to the root window, and then send
1050    * it a delete event, as if we were a WM
1051    */
1052   XClientMessageEvent xclient;
1053   GdkDisplay *display;
1054
1055   display = GDK_WINDOW_DISPLAY (window);
1056   gdk_x11_display_error_trap_push (display);
1057   gdk_window_hide (window);
1058   gdk_window_reparent (window, NULL, 0, 0);
1059
1060   memset (&xclient, 0, sizeof (xclient));
1061   xclient.type = ClientMessage;
1062   xclient.window = GDK_WINDOW_XID (window);
1063   xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS");
1064   xclient.format = 32;
1065   xclient.data.l[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
1066   xclient.data.l[1] = CurrentTime;
1067   xclient.data.l[2] = 0;
1068   xclient.data.l[3] = 0;
1069   xclient.data.l[4] = 0;
1070   
1071   XSendEvent (GDK_WINDOW_XDISPLAY (window),
1072               GDK_WINDOW_XID (window),
1073               False, 0, (XEvent *)&xclient);
1074   gdk_x11_display_error_trap_pop_ignored (display);
1075 }
1076
1077 static GdkWindow *
1078 get_root (GdkWindow *window)
1079 {
1080   GdkScreen *screen = gdk_window_get_screen (window);
1081
1082   return gdk_screen_get_root_window (screen);
1083 }
1084
1085 /* This function is called when the XWindow is really gone.
1086  */
1087 static void
1088 gdk_x11_window_destroy_notify (GdkWindow *window)
1089 {
1090   GdkWindowImplX11 *window_impl;
1091
1092   window_impl = GDK_WINDOW_IMPL_X11 ((window)->impl);
1093
1094   if (!GDK_WINDOW_DESTROYED (window))
1095     {
1096       if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1097         g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
1098
1099       _gdk_window_destroy (window, TRUE);
1100     }
1101
1102   _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
1103   if (window_impl->toplevel && window_impl->toplevel->focus_window)
1104     _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
1105
1106   _gdk_x11_window_grab_check_destroy (window);
1107
1108   g_object_unref (window);
1109 }
1110
1111 static GdkDragProtocol
1112 gdk_x11_window_get_drag_protocol (GdkWindow *window,
1113                                   GdkWindow **target)
1114 {
1115   GdkDragProtocol protocol;
1116   GdkDisplay *display;
1117   guint version;
1118   Window xid;
1119
1120   display = gdk_window_get_display (window);
1121   xid = _gdk_x11_display_get_drag_protocol (display,
1122                                             GDK_WINDOW_XID (window->impl_window),
1123                                             &protocol,
1124                                             &version);
1125
1126   if (target)
1127     {
1128       if (xid != None)
1129         *target = gdk_x11_window_foreign_new_for_display (display, xid);
1130       else
1131         *target = NULL;
1132     }
1133
1134   return protocol;
1135 }
1136
1137 static void
1138 update_wm_hints (GdkWindow *window,
1139                  gboolean   force)
1140 {
1141   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
1142   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1143   XWMHints wm_hints;
1144
1145   if (!force &&
1146       !toplevel->is_leader &&
1147       window->state & GDK_WINDOW_STATE_WITHDRAWN)
1148     return;
1149
1150   wm_hints.flags = StateHint | InputHint;
1151   wm_hints.input = window->accept_focus ? True : False;
1152   wm_hints.initial_state = NormalState;
1153   
1154   if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1155     {
1156       wm_hints.flags |= StateHint;
1157       wm_hints.initial_state = IconicState;
1158     }
1159
1160   if (toplevel->icon_pixmap)
1161     {
1162       wm_hints.flags |= IconPixmapHint;
1163       wm_hints.icon_pixmap = cairo_xlib_surface_get_drawable (toplevel->icon_pixmap);
1164     }
1165
1166   if (toplevel->icon_mask)
1167     {
1168       wm_hints.flags |= IconMaskHint;
1169       wm_hints.icon_mask = cairo_xlib_surface_get_drawable (toplevel->icon_mask);
1170     }
1171   
1172   wm_hints.flags |= WindowGroupHint;
1173   if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
1174     {
1175       wm_hints.flags |= WindowGroupHint;
1176       wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
1177     }
1178   else
1179     wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
1180
1181   if (toplevel->urgency_hint)
1182     wm_hints.flags |= XUrgencyHint;
1183   
1184   XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1185                GDK_WINDOW_XID (window),
1186                &wm_hints);
1187 }
1188
1189 static void
1190 set_initial_hints (GdkWindow *window)
1191 {
1192   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1193   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1194   Window xwindow = GDK_WINDOW_XID (window);  
1195   GdkToplevelX11 *toplevel;
1196   Atom atoms[9];
1197   gint i;
1198
1199   toplevel = _gdk_x11_window_get_toplevel (window);
1200
1201   if (!toplevel)
1202     return;
1203
1204   update_wm_hints (window, TRUE);
1205   
1206   /* We set the spec hints regardless of whether the spec is supported,
1207    * since it can't hurt and it's kind of expensive to check whether
1208    * it's supported.
1209    */
1210   
1211   i = 0;
1212
1213   if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1214     {
1215       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1216                                                         "_NET_WM_STATE_MAXIMIZED_VERT");
1217       ++i;
1218       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1219                                                         "_NET_WM_STATE_MAXIMIZED_HORZ");
1220       ++i;
1221       toplevel->have_maxhorz = toplevel->have_maxvert = TRUE;
1222     }
1223
1224   if (window->state & GDK_WINDOW_STATE_ABOVE)
1225     {
1226       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1227                                                         "_NET_WM_STATE_ABOVE");
1228       ++i;
1229     }
1230   
1231   if (window->state & GDK_WINDOW_STATE_BELOW)
1232     {
1233       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1234                                                         "_NET_WM_STATE_BELOW");
1235       ++i;
1236     }
1237   
1238   if (window->state & GDK_WINDOW_STATE_STICKY)
1239     {
1240       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1241                                                         "_NET_WM_STATE_STICKY");
1242       ++i;
1243       toplevel->have_sticky = TRUE;
1244     }
1245
1246   if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1247     {
1248       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1249                                                         "_NET_WM_STATE_FULLSCREEN");
1250       ++i;
1251       toplevel->have_fullscreen = TRUE;
1252     }
1253
1254   if (window->modal_hint)
1255     {
1256       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1257                                                         "_NET_WM_STATE_MODAL");
1258       ++i;
1259     }
1260
1261   if (toplevel->skip_taskbar_hint)
1262     {
1263       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1264                                                         "_NET_WM_STATE_SKIP_TASKBAR");
1265       ++i;
1266     }
1267
1268   if (toplevel->skip_pager_hint)
1269     {
1270       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1271                                                         "_NET_WM_STATE_SKIP_PAGER");
1272       ++i;
1273     }
1274
1275   if (i > 0)
1276     {
1277       XChangeProperty (xdisplay,
1278                        xwindow,
1279                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
1280                        XA_ATOM, 32, PropModeReplace,
1281                        (guchar*) atoms, i);
1282     }
1283   else 
1284     {
1285       XDeleteProperty (xdisplay,
1286                        xwindow,
1287                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
1288     }
1289
1290   if (window->state & GDK_WINDOW_STATE_STICKY)
1291     {
1292       atoms[0] = 0xFFFFFFFF;
1293       XChangeProperty (xdisplay,
1294                        xwindow,
1295                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
1296                        XA_CARDINAL, 32, PropModeReplace,
1297                        (guchar*) atoms, 1);
1298       toplevel->on_all_desktops = TRUE;
1299     }
1300   else
1301     {
1302       XDeleteProperty (xdisplay,
1303                        xwindow,
1304                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
1305     }
1306
1307   toplevel->map_serial = NextRequest (xdisplay);
1308 }
1309
1310 static void
1311 gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
1312 {
1313   GdkDisplay *display;
1314   GdkX11Display *display_x11;
1315   GdkToplevelX11 *toplevel;
1316   GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1317   Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
1318   Window xwindow = GDK_WINDOW_XID (window);
1319   gboolean unset_bg;
1320
1321   if (!already_mapped)
1322     set_initial_hints (window);
1323       
1324   if (WINDOW_IS_TOPLEVEL (window))
1325     {
1326       display = gdk_window_get_display (window);
1327       display_x11 = GDK_X11_DISPLAY (display);
1328       toplevel = _gdk_x11_window_get_toplevel (window);
1329       
1330       if (toplevel->user_time != 0 &&
1331               display_x11->user_time != 0 &&
1332           XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
1333         gdk_x11_window_set_user_time (window, display_x11->user_time);
1334     }
1335   
1336   unset_bg = !window->input_only &&
1337     (window->window_type == GDK_WINDOW_CHILD ||
1338      impl->override_redirect) &&
1339     gdk_window_is_viewable (window);
1340   
1341   if (unset_bg)
1342     _gdk_x11_window_tmp_unset_bg (window, TRUE);
1343   
1344   XMapWindow (xdisplay, xwindow);
1345   
1346   if (unset_bg)
1347     _gdk_x11_window_tmp_reset_bg (window, TRUE);
1348 }
1349
1350 static void
1351 pre_unmap (GdkWindow *window)
1352 {
1353   GdkWindow *start_window = NULL;
1354
1355   if (window->input_only)
1356     return;
1357
1358   if (window->window_type == GDK_WINDOW_CHILD)
1359     start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1360   else if (window->window_type == GDK_WINDOW_TEMP)
1361     start_window = get_root (window);
1362
1363   if (start_window)
1364     _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
1365 }
1366
1367 static void
1368 post_unmap (GdkWindow *window)
1369 {
1370   GdkWindow *start_window = NULL;
1371   
1372   if (window->input_only)
1373     return;
1374
1375   if (window->window_type == GDK_WINDOW_CHILD)
1376     start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1377   else if (window->window_type == GDK_WINDOW_TEMP)
1378     start_window = get_root (window);
1379
1380   if (start_window)
1381     {
1382       _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
1383
1384       if (window->window_type == GDK_WINDOW_CHILD && window->parent)
1385         {
1386           GdkRectangle invalid_rect;
1387       
1388           gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
1389           invalid_rect.width = gdk_window_get_width (window);
1390           invalid_rect.height = gdk_window_get_height (window);
1391           gdk_window_invalidate_rect ((GdkWindow *)window->parent,
1392                                       &invalid_rect, TRUE);
1393         }
1394     }
1395 }
1396
1397 static void
1398 gdk_window_x11_hide (GdkWindow *window)
1399 {
1400   /* We'll get the unmap notify eventually, and handle it then,
1401    * but checking here makes things more consistent if we are
1402    * just doing stuff ourself.
1403    */
1404   _gdk_x11_window_grab_check_unmap (window,
1405                                     NextRequest (GDK_WINDOW_XDISPLAY (window)));
1406
1407   /* You can't simply unmap toplevel windows. */
1408   switch (window->window_type)
1409     {
1410     case GDK_WINDOW_TOPLEVEL:
1411     case GDK_WINDOW_TEMP: /* ? */
1412       gdk_window_withdraw (window);
1413       return;
1414       
1415     case GDK_WINDOW_FOREIGN:
1416     case GDK_WINDOW_ROOT:
1417     case GDK_WINDOW_CHILD:
1418       break;
1419     }
1420   
1421   _gdk_window_clear_update_area (window);
1422   
1423   pre_unmap (window);
1424   XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
1425                 GDK_WINDOW_XID (window));
1426   post_unmap (window);
1427 }
1428
1429 static void
1430 gdk_window_x11_withdraw (GdkWindow *window)
1431 {
1432   if (!window->destroyed)
1433     {
1434       if (GDK_WINDOW_IS_MAPPED (window))
1435         gdk_synthesize_window_state (window,
1436                                      0,
1437                                      GDK_WINDOW_STATE_WITHDRAWN);
1438
1439       g_assert (!GDK_WINDOW_IS_MAPPED (window));
1440
1441       pre_unmap (window);
1442       
1443       XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
1444                        GDK_WINDOW_XID (window), 0);
1445
1446       post_unmap (window);
1447     }
1448 }
1449
1450 static inline void
1451 window_x11_move (GdkWindow *window,
1452                  gint       x,
1453                  gint       y)
1454 {
1455   GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1456
1457   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1458     {
1459       _gdk_x11_window_move_resize_child (window,
1460                                          x, y,
1461                                          window->width, window->height);
1462     }
1463   else
1464     {
1465       XMoveWindow (GDK_WINDOW_XDISPLAY (window),
1466                    GDK_WINDOW_XID (window),
1467                    x, y);
1468
1469       if (impl->override_redirect)
1470         {
1471           window->x = x;
1472           window->y = y;
1473         }
1474     }
1475 }
1476
1477 static inline void
1478 window_x11_resize (GdkWindow *window,
1479                    gint       width,
1480                    gint       height)
1481 {
1482   if (width < 1)
1483     width = 1;
1484
1485   if (height < 1)
1486     height = 1;
1487
1488   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1489     {
1490       _gdk_x11_window_move_resize_child (window,
1491                                          window->x, window->y,
1492                                          width, height);
1493     }
1494   else
1495     {
1496       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1497
1498       XResizeWindow (GDK_WINDOW_XDISPLAY (window),
1499                      GDK_WINDOW_XID (window),
1500                      width, height);
1501
1502       if (impl->override_redirect)
1503         {
1504           window->width = width;
1505           window->height = height;
1506           _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1507         }
1508       else
1509         {
1510           if (width != window->width || height != window->height)
1511             window->resize_count += 1;
1512         }
1513     }
1514
1515   _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1516 }
1517
1518 static inline void
1519 window_x11_move_resize (GdkWindow *window,
1520                         gint       x,
1521                         gint       y,
1522                         gint       width,
1523                         gint       height)
1524 {
1525   if (width < 1)
1526     width = 1;
1527
1528   if (height < 1)
1529     height = 1;
1530
1531   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1532     {
1533       _gdk_x11_window_move_resize_child (window, x, y, width, height);
1534       _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1535     }
1536   else
1537     {
1538       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1539
1540       XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
1541                          GDK_WINDOW_XID (window),
1542                          x, y, width, height);
1543
1544       if (impl->override_redirect)
1545         {
1546           window->x = x;
1547           window->y = y;
1548
1549           window->width = width;
1550           window->height = height;
1551
1552           _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1553         }
1554       else
1555         {
1556           if (width != window->width || height != window->height)
1557             window->resize_count += 1;
1558         }
1559     }
1560 }
1561
1562 static void
1563 gdk_window_x11_move_resize (GdkWindow *window,
1564                             gboolean   with_move,
1565                             gint       x,
1566                             gint       y,
1567                             gint       width,
1568                             gint       height)
1569 {
1570   if (with_move && (width < 0 && height < 0))
1571     window_x11_move (window, x, y);
1572   else
1573     {
1574       if (with_move)
1575         window_x11_move_resize (window, x, y, width, height);
1576       else
1577         window_x11_resize (window, width, height);
1578     }
1579 }
1580
1581 static gboolean
1582 gdk_window_x11_reparent (GdkWindow *window,
1583                          GdkWindow *new_parent,
1584                          gint       x,
1585                          gint       y)
1586 {
1587   GdkWindowImplX11 *impl;
1588
1589   impl = GDK_WINDOW_IMPL_X11 (window->impl);
1590
1591   _gdk_x11_window_tmp_unset_bg (window, TRUE);
1592   _gdk_x11_window_tmp_unset_parent_bg (window);
1593   XReparentWindow (GDK_WINDOW_XDISPLAY (window),
1594                    GDK_WINDOW_XID (window),
1595                    GDK_WINDOW_XID (new_parent),
1596                    new_parent->abs_x + x, new_parent->abs_y + y);
1597   _gdk_x11_window_tmp_reset_parent_bg (window);
1598   _gdk_x11_window_tmp_reset_bg (window, TRUE);
1599
1600   if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1601     new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1602
1603   window->parent = new_parent;
1604
1605   /* Switch the window type as appropriate */
1606
1607   switch (GDK_WINDOW_TYPE (new_parent))
1608     {
1609     case GDK_WINDOW_ROOT:
1610     case GDK_WINDOW_FOREIGN:
1611       /* Reparenting to toplevel */
1612       
1613       if (!WINDOW_IS_TOPLEVEL (window) &&
1614           GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1615         {
1616           /* This is also done in common code at a later stage, but we
1617              need it in setup_toplevel, so do it here too */
1618           if (window->toplevel_window_type != -1)
1619             GDK_WINDOW_TYPE (window) = window->toplevel_window_type;
1620           else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1621             GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1622           
1623           /* Wasn't a toplevel, set up */
1624           setup_toplevel_window (window, new_parent);
1625         }
1626
1627       break;
1628       
1629     case GDK_WINDOW_TOPLEVEL:
1630     case GDK_WINDOW_CHILD:
1631     case GDK_WINDOW_TEMP:
1632       if (WINDOW_IS_TOPLEVEL (window) &&
1633           impl->toplevel)
1634         {
1635           if (impl->toplevel->focus_window)
1636             {
1637               XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
1638               _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
1639             }
1640           
1641           gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
1642                                           impl->toplevel);
1643           g_free (impl->toplevel);
1644           impl->toplevel = NULL;
1645         }
1646     }
1647
1648   return FALSE;
1649 }
1650
1651 static void
1652 gdk_window_x11_raise (GdkWindow *window)
1653 {
1654   XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1655 }
1656
1657 static void
1658 gdk_window_x11_restack_under (GdkWindow *window,
1659                               GList *native_siblings /* in requested order, first is bottom-most */)
1660 {
1661   Window *windows;
1662   int n_windows, i;
1663   GList *l;
1664
1665   n_windows = g_list_length (native_siblings) + 1;
1666   windows = g_new (Window, n_windows);
1667
1668   windows[0] = GDK_WINDOW_XID (window);
1669   /* Reverse order, as input order is bottom-most first */
1670   i = n_windows - 1;
1671   for (l = native_siblings; l != NULL; l = l->next)
1672     windows[i--] = GDK_WINDOW_XID (l->data);
1673  
1674   XRestackWindows (GDK_WINDOW_XDISPLAY (window), windows, n_windows);
1675   
1676   g_free (windows);
1677 }
1678
1679 static void
1680 gdk_window_x11_restack_toplevel (GdkWindow *window,
1681                                  GdkWindow *sibling,
1682                                  gboolean   above)
1683 {
1684   XWindowChanges changes;
1685
1686   changes.sibling = GDK_WINDOW_XID (sibling);
1687   changes.stack_mode = above ? Above : Below;
1688   XReconfigureWMWindow (GDK_WINDOW_XDISPLAY (window),
1689                         GDK_WINDOW_XID (window),
1690                         gdk_screen_get_number (GDK_WINDOW_SCREEN (window)),
1691                         CWStackMode | CWSibling, &changes);
1692 }
1693
1694 static void
1695 gdk_window_x11_lower (GdkWindow *window)
1696 {
1697   XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1698 }
1699
1700 /**
1701  * gdk_x11_window_move_to_current_desktop:
1702  * @window: a #GdkWindow
1703  * 
1704  * Moves the window to the correct workspace when running under a 
1705  * window manager that supports multiple workspaces, as described
1706  * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended 
1707  * Window Manager Hints</ulink>.  Will not do anything if the
1708  * window is already on all workspaces.
1709  * 
1710  * Since: 2.8
1711  */
1712 void
1713 gdk_x11_window_move_to_current_desktop (GdkWindow *window)
1714 {
1715   GdkToplevelX11 *toplevel;
1716
1717   g_return_if_fail (GDK_IS_WINDOW (window));
1718   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1719
1720   toplevel = _gdk_x11_window_get_toplevel (window);
1721
1722   if (toplevel->on_all_desktops)
1723     return;
1724   
1725   move_to_current_desktop (window);
1726 }
1727
1728 static void
1729 move_to_current_desktop (GdkWindow *window)
1730 {
1731   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1732                                            gdk_atom_intern_static_string ("_NET_WM_DESKTOP")))
1733     {
1734       Atom type;
1735       gint format;
1736       gulong nitems;
1737       gulong bytes_after;
1738       guchar *data;
1739       gulong *current_desktop;
1740       GdkDisplay *display;
1741       
1742       display = gdk_window_get_display (window);
1743
1744       /* Get current desktop, then set it; this is a race, but not
1745        * one that matters much in practice.
1746        */
1747       XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), 
1748                           GDK_WINDOW_XROOTWIN (window),
1749                           gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
1750                           0, G_MAXLONG,
1751                           False, XA_CARDINAL, &type, &format, &nitems,
1752                           &bytes_after, &data);
1753
1754       if (type == XA_CARDINAL)
1755         {
1756           XClientMessageEvent xclient;
1757           current_desktop = (gulong *)data;
1758           
1759           memset (&xclient, 0, sizeof (xclient));
1760           xclient.type = ClientMessage;
1761           xclient.serial = 0;
1762           xclient.send_event = True;
1763           xclient.window = GDK_WINDOW_XID (window);
1764           xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
1765           xclient.format = 32;
1766
1767           xclient.data.l[0] = *current_desktop;
1768           xclient.data.l[1] = 0;
1769           xclient.data.l[2] = 0;
1770           xclient.data.l[3] = 0;
1771           xclient.data.l[4] = 0;
1772       
1773           XSendEvent (GDK_DISPLAY_XDISPLAY (display), 
1774                       GDK_WINDOW_XROOTWIN (window), 
1775                       False,
1776                       SubstructureRedirectMask | SubstructureNotifyMask,
1777                       (XEvent *)&xclient);
1778
1779           XFree (current_desktop);
1780         }
1781     }
1782 }
1783
1784 static void
1785 gdk_x11_window_focus (GdkWindow *window,
1786                       guint32    timestamp)
1787 {
1788   GdkDisplay *display;
1789
1790   g_return_if_fail (GDK_IS_WINDOW (window));
1791
1792   if (GDK_WINDOW_DESTROYED (window) ||
1793       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1794     return;
1795
1796   display = GDK_WINDOW_DISPLAY (window);
1797
1798   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1799                                            gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
1800     {
1801       XClientMessageEvent xclient;
1802
1803       memset (&xclient, 0, sizeof (xclient));
1804       xclient.type = ClientMessage;
1805       xclient.window = GDK_WINDOW_XID (window);
1806       xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
1807                                                                         "_NET_ACTIVE_WINDOW");
1808       xclient.format = 32;
1809       xclient.data.l[0] = 1; /* requestor type; we're an app */
1810       xclient.data.l[1] = timestamp;
1811       xclient.data.l[2] = None; /* currently active window */
1812       xclient.data.l[3] = 0;
1813       xclient.data.l[4] = 0;
1814       
1815       XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
1816                   SubstructureRedirectMask | SubstructureNotifyMask,
1817                   (XEvent *)&xclient);
1818     }
1819   else
1820     {
1821       XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
1822
1823       /* There is no way of knowing reliably whether we are viewable;
1824        * so trap errors asynchronously around the XSetInputFocus call
1825        */
1826       gdk_x11_display_error_trap_push (display);
1827       XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
1828                       GDK_WINDOW_XID (window),
1829                       RevertToParent,
1830                       timestamp);
1831       gdk_x11_display_error_trap_pop_ignored (display);
1832     }
1833 }
1834
1835 static void
1836 gdk_x11_window_set_type_hint (GdkWindow        *window,
1837                               GdkWindowTypeHint hint)
1838 {
1839   GdkDisplay *display;
1840   Atom atom;
1841   
1842   if (GDK_WINDOW_DESTROYED (window) ||
1843       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1844     return;
1845
1846   display = gdk_window_get_display (window);
1847
1848   switch (hint)
1849     {
1850     case GDK_WINDOW_TYPE_HINT_DIALOG:
1851       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
1852       break;
1853     case GDK_WINDOW_TYPE_HINT_MENU:
1854       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
1855       break;
1856     case GDK_WINDOW_TYPE_HINT_TOOLBAR:
1857       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
1858       break;
1859     case GDK_WINDOW_TYPE_HINT_UTILITY:
1860       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
1861       break;
1862     case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
1863       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
1864       break;
1865     case GDK_WINDOW_TYPE_HINT_DOCK:
1866       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
1867       break;
1868     case GDK_WINDOW_TYPE_HINT_DESKTOP:
1869       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
1870       break;
1871     case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
1872       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
1873       break;
1874     case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
1875       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
1876       break;
1877     case GDK_WINDOW_TYPE_HINT_TOOLTIP:
1878       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
1879       break;
1880     case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
1881       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
1882       break;
1883     case GDK_WINDOW_TYPE_HINT_COMBO:
1884       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
1885       break;
1886     case GDK_WINDOW_TYPE_HINT_DND:
1887       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
1888       break;
1889     default:
1890       g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
1891       /* Fall thru */
1892     case GDK_WINDOW_TYPE_HINT_NORMAL:
1893       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
1894       break;
1895     }
1896
1897   XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
1898                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
1899                    XA_ATOM, 32, PropModeReplace,
1900                    (guchar *)&atom, 1);
1901 }
1902
1903 static GdkWindowTypeHint
1904 gdk_x11_window_get_type_hint (GdkWindow *window)
1905 {
1906   GdkDisplay *display;
1907   GdkWindowTypeHint type;
1908   Atom type_return;
1909   gint format_return;
1910   gulong nitems_return;
1911   gulong bytes_after_return;
1912   guchar *data = NULL;
1913
1914   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1915
1916   if (GDK_WINDOW_DESTROYED (window) ||
1917       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1918     return GDK_WINDOW_TYPE_HINT_NORMAL;
1919
1920   type = GDK_WINDOW_TYPE_HINT_NORMAL;
1921
1922   display = gdk_window_get_display (window);
1923
1924   if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
1925                           gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
1926                           0, G_MAXLONG, False, XA_ATOM, &type_return,
1927                           &format_return, &nitems_return, &bytes_after_return,
1928                           &data) == Success)
1929     {
1930       if ((type_return == XA_ATOM) && (format_return == 32) &&
1931           (data) && (nitems_return == 1))
1932         {
1933           Atom atom = *(Atom*)data;
1934
1935           if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
1936             type = GDK_WINDOW_TYPE_HINT_DIALOG;
1937           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
1938             type = GDK_WINDOW_TYPE_HINT_MENU;
1939           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
1940             type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
1941           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
1942             type = GDK_WINDOW_TYPE_HINT_UTILITY;
1943           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
1944             type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
1945           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
1946             type = GDK_WINDOW_TYPE_HINT_DOCK;
1947           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
1948             type = GDK_WINDOW_TYPE_HINT_DESKTOP;
1949           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
1950             type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
1951           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
1952             type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
1953           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
1954             type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
1955           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
1956             type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
1957           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
1958             type = GDK_WINDOW_TYPE_HINT_COMBO;
1959           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
1960             type = GDK_WINDOW_TYPE_HINT_DND;
1961         }
1962
1963       if (type_return != None && data != NULL)
1964         XFree (data);
1965     }
1966
1967   return type;
1968 }
1969
1970 static void
1971 gdk_wmspec_change_state (gboolean   add,
1972                          GdkWindow *window,
1973                          GdkAtom    state1,
1974                          GdkAtom    state2)
1975 {
1976   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1977   XClientMessageEvent xclient;
1978   
1979 #define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
1980 #define _NET_WM_STATE_ADD           1    /* add/set property */
1981 #define _NET_WM_STATE_TOGGLE        2    /* toggle property  */  
1982   
1983   memset (&xclient, 0, sizeof (xclient));
1984   xclient.type = ClientMessage;
1985   xclient.window = GDK_WINDOW_XID (window);
1986   xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
1987   xclient.format = 32;
1988   xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
1989   xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
1990   xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
1991   xclient.data.l[3] = 0;
1992   xclient.data.l[4] = 0;
1993   
1994   XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
1995               SubstructureRedirectMask | SubstructureNotifyMask,
1996               (XEvent *)&xclient);
1997 }
1998
1999 static void
2000 gdk_x11_window_set_modal_hint (GdkWindow *window,
2001                                gboolean   modal)
2002 {
2003   if (GDK_WINDOW_DESTROYED (window) ||
2004       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2005     return;
2006
2007   window->modal_hint = modal;
2008
2009   if (GDK_WINDOW_IS_MAPPED (window))
2010     gdk_wmspec_change_state (modal, window,
2011                              gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"), 
2012                              GDK_NONE);
2013 }
2014
2015 static void
2016 gdk_x11_window_set_skip_taskbar_hint (GdkWindow *window,
2017                                       gboolean   skips_taskbar)
2018 {
2019   GdkToplevelX11 *toplevel;
2020   
2021   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2022   
2023   if (GDK_WINDOW_DESTROYED (window) ||
2024       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2025     return;
2026
2027   toplevel = _gdk_x11_window_get_toplevel (window);
2028   toplevel->skip_taskbar_hint = skips_taskbar;
2029
2030   if (GDK_WINDOW_IS_MAPPED (window))
2031     gdk_wmspec_change_state (skips_taskbar, window,
2032                              gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
2033                              GDK_NONE);
2034 }
2035
2036 static void
2037 gdk_x11_window_set_skip_pager_hint (GdkWindow *window,
2038                                     gboolean   skips_pager)
2039 {
2040   GdkToplevelX11 *toplevel;
2041     
2042   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2043   
2044   if (GDK_WINDOW_DESTROYED (window) ||
2045       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2046     return;
2047
2048   toplevel = _gdk_x11_window_get_toplevel (window);
2049   toplevel->skip_pager_hint = skips_pager;
2050   
2051   if (GDK_WINDOW_IS_MAPPED (window))
2052     gdk_wmspec_change_state (skips_pager, window,
2053                              gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"), 
2054                              GDK_NONE);
2055 }
2056
2057 static void
2058 gdk_x11_window_set_urgency_hint (GdkWindow *window,
2059                              gboolean   urgent)
2060 {
2061   GdkToplevelX11 *toplevel;
2062     
2063   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2064   
2065   if (GDK_WINDOW_DESTROYED (window) ||
2066       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2067     return;
2068
2069   toplevel = _gdk_x11_window_get_toplevel (window);
2070   toplevel->urgency_hint = urgent;
2071   
2072   update_wm_hints (window, FALSE);
2073 }
2074
2075 static void
2076 gdk_x11_window_set_geometry_hints (GdkWindow         *window,
2077                                    const GdkGeometry *geometry,
2078                                    GdkWindowHints     geom_mask)
2079 {
2080   XSizeHints size_hints;
2081   
2082   if (GDK_WINDOW_DESTROYED (window) ||
2083       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2084     return;
2085   
2086   size_hints.flags = 0;
2087   
2088   if (geom_mask & GDK_HINT_POS)
2089     {
2090       size_hints.flags |= PPosition;
2091       /* We need to initialize the following obsolete fields because KWM 
2092        * apparently uses these fields if they are non-zero.
2093        * #@#!#!$!.
2094        */
2095       size_hints.x = 0;
2096       size_hints.y = 0;
2097     }
2098
2099   if (geom_mask & GDK_HINT_USER_POS)
2100     {
2101       size_hints.flags |= USPosition;
2102     }
2103
2104   if (geom_mask & GDK_HINT_USER_SIZE)
2105     {
2106       size_hints.flags |= USSize;
2107     }
2108   
2109   if (geom_mask & GDK_HINT_MIN_SIZE)
2110     {
2111       size_hints.flags |= PMinSize;
2112       size_hints.min_width = geometry->min_width;
2113       size_hints.min_height = geometry->min_height;
2114     }
2115   
2116   if (geom_mask & GDK_HINT_MAX_SIZE)
2117     {
2118       size_hints.flags |= PMaxSize;
2119       size_hints.max_width = MAX (geometry->max_width, 1);
2120       size_hints.max_height = MAX (geometry->max_height, 1);
2121     }
2122   
2123   if (geom_mask & GDK_HINT_BASE_SIZE)
2124     {
2125       size_hints.flags |= PBaseSize;
2126       size_hints.base_width = geometry->base_width;
2127       size_hints.base_height = geometry->base_height;
2128     }
2129   
2130   if (geom_mask & GDK_HINT_RESIZE_INC)
2131     {
2132       size_hints.flags |= PResizeInc;
2133       size_hints.width_inc = geometry->width_inc;
2134       size_hints.height_inc = geometry->height_inc;
2135     }
2136   
2137   if (geom_mask & GDK_HINT_ASPECT)
2138     {
2139       size_hints.flags |= PAspect;
2140       if (geometry->min_aspect <= 1)
2141         {
2142           size_hints.min_aspect.x = 65536 * geometry->min_aspect;
2143           size_hints.min_aspect.y = 65536;
2144         }
2145       else
2146         {
2147           size_hints.min_aspect.x = 65536;
2148           size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
2149         }
2150       if (geometry->max_aspect <= 1)
2151         {
2152           size_hints.max_aspect.x = 65536 * geometry->max_aspect;
2153           size_hints.max_aspect.y = 65536;
2154         }
2155       else
2156         {
2157           size_hints.max_aspect.x = 65536;
2158           size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
2159         }
2160     }
2161
2162   if (geom_mask & GDK_HINT_WIN_GRAVITY)
2163     {
2164       size_hints.flags |= PWinGravity;
2165       size_hints.win_gravity = geometry->win_gravity;
2166     }
2167   
2168   /* FIXME: Would it be better to delete this property if
2169    *        geom_mask == 0? It would save space on the server
2170    */
2171   XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2172                      GDK_WINDOW_XID (window),
2173                      &size_hints);
2174 }
2175
2176 static void
2177 gdk_window_get_geometry_hints (GdkWindow      *window,
2178                                GdkGeometry    *geometry,
2179                                GdkWindowHints *geom_mask)
2180 {
2181   XSizeHints *size_hints;  
2182   glong junk_supplied_mask = 0;
2183
2184   g_return_if_fail (GDK_IS_WINDOW (window));
2185   g_return_if_fail (geometry != NULL);
2186   g_return_if_fail (geom_mask != NULL);
2187
2188   *geom_mask = 0;
2189   
2190   if (GDK_WINDOW_DESTROYED (window) ||
2191       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2192     return;
2193
2194   size_hints = XAllocSizeHints ();
2195   if (!size_hints)
2196     return;
2197   
2198   if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2199                           GDK_WINDOW_XID (window),
2200                           size_hints,
2201                           &junk_supplied_mask))
2202     size_hints->flags = 0;
2203
2204   if (size_hints->flags & PMinSize)
2205     {
2206       *geom_mask |= GDK_HINT_MIN_SIZE;
2207       geometry->min_width = size_hints->min_width;
2208       geometry->min_height = size_hints->min_height;
2209     }
2210
2211   if (size_hints->flags & PMaxSize)
2212     {
2213       *geom_mask |= GDK_HINT_MAX_SIZE;
2214       geometry->max_width = MAX (size_hints->max_width, 1);
2215       geometry->max_height = MAX (size_hints->max_height, 1);
2216     }
2217
2218   if (size_hints->flags & PResizeInc)
2219     {
2220       *geom_mask |= GDK_HINT_RESIZE_INC;
2221       geometry->width_inc = size_hints->width_inc;
2222       geometry->height_inc = size_hints->height_inc;
2223     }
2224
2225   if (size_hints->flags & PAspect)
2226     {
2227       *geom_mask |= GDK_HINT_ASPECT;
2228
2229       geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
2230       geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
2231     }
2232
2233   if (size_hints->flags & PWinGravity)
2234     {
2235       *geom_mask |= GDK_HINT_WIN_GRAVITY;
2236       geometry->win_gravity = size_hints->win_gravity;
2237     }
2238
2239   XFree (size_hints);
2240 }
2241
2242 static gboolean
2243 utf8_is_latin1 (const gchar *str)
2244 {
2245   const char *p = str;
2246
2247   while (*p)
2248     {
2249       gunichar ch = g_utf8_get_char (p);
2250
2251       if (ch > 0xff)
2252         return FALSE;
2253       
2254       p = g_utf8_next_char (p);
2255     }
2256
2257   return TRUE;
2258 }
2259
2260 /* Set the property to @utf8_str as STRING if the @utf8_str is fully
2261  * convertable to STRING, otherwise, set it as compound text
2262  */
2263 static void
2264 set_text_property (GdkDisplay  *display,
2265                    Window       xwindow,
2266                    Atom         property,
2267                    const gchar *utf8_str)
2268 {
2269   gchar *prop_text = NULL;
2270   Atom prop_type;
2271   gint prop_length;
2272   gint prop_format;
2273   gboolean is_compound_text;
2274   
2275   if (utf8_is_latin1 (utf8_str))
2276     {
2277       prop_type = XA_STRING;
2278       prop_text = _gdk_x11_display_utf8_to_string_target (display, utf8_str);
2279       prop_length = prop_text ? strlen (prop_text) : 0;
2280       prop_format = 8;
2281       is_compound_text = FALSE;
2282     }
2283   else
2284     {
2285       GdkAtom gdk_type;
2286
2287       gdk_x11_display_utf8_to_compound_text (display,
2288                                              utf8_str, &gdk_type, &prop_format,
2289                                              (guchar **)&prop_text, &prop_length);
2290       prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
2291       is_compound_text = TRUE;
2292     }
2293
2294   if (prop_text)
2295     {
2296       XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
2297                        xwindow,
2298                        property,
2299                        prop_type, prop_format,
2300                        PropModeReplace, (guchar *)prop_text,
2301                        prop_length);
2302
2303       if (is_compound_text)
2304         gdk_x11_free_compound_text ((guchar *)prop_text);
2305       else
2306         g_free (prop_text);
2307     }
2308 }
2309
2310 /* Set WM_NAME and _NET_WM_NAME
2311  */
2312 static void
2313 set_wm_name (GdkDisplay  *display,
2314              Window       xwindow,
2315              const gchar *name)
2316 {
2317   XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2318                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
2319                    gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2320                    PropModeReplace, (guchar *)name, strlen (name));
2321   
2322   set_text_property (display, xwindow,
2323                      gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
2324                      name);
2325 }
2326
2327 static void
2328 gdk_x11_window_set_title (GdkWindow   *window,
2329                           const gchar *title)
2330 {
2331   GdkDisplay *display;
2332   Display *xdisplay;
2333   Window xwindow;
2334   
2335   g_return_if_fail (title != NULL);
2336
2337   if (GDK_WINDOW_DESTROYED (window) ||
2338       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2339     return;
2340   
2341   display = gdk_window_get_display (window);
2342   xdisplay = GDK_DISPLAY_XDISPLAY (display);
2343   xwindow = GDK_WINDOW_XID (window);
2344
2345   set_wm_name (display, xwindow, title);
2346   
2347   if (!gdk_window_icon_name_set (window))
2348     {
2349       XChangeProperty (xdisplay, xwindow,
2350                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
2351                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2352                        PropModeReplace, (guchar *)title, strlen (title));
2353       
2354       set_text_property (display, xwindow,
2355                          gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
2356                          title);
2357     }
2358 }
2359
2360 static void
2361 gdk_x11_window_set_role (GdkWindow   *window,
2362                          const gchar *role)
2363 {
2364   GdkDisplay *display;
2365
2366   display = gdk_window_get_display (window);
2367
2368   if (GDK_WINDOW_DESTROYED (window) ||
2369       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2370     return;
2371
2372   if (role)
2373     XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2374                      gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
2375                      XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
2376   else
2377     XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2378                      gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
2379 }
2380
2381 static void
2382 gdk_x11_window_set_startup_id (GdkWindow   *window,
2383                                const gchar *startup_id)
2384 {
2385   GdkDisplay *display;
2386
2387   g_return_if_fail (GDK_IS_WINDOW (window));
2388
2389   display = gdk_window_get_display (window);
2390
2391   if (GDK_WINDOW_DESTROYED (window) ||
2392       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2393     return;
2394
2395   if (startup_id)
2396     XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2397                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"), 
2398                      gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2399                      PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
2400   else
2401     XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2402                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
2403 }
2404
2405 static void
2406 gdk_x11_window_set_transient_for (GdkWindow *window,
2407                                   GdkWindow *parent)
2408 {
2409   if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
2410       WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2411     XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), 
2412                           GDK_WINDOW_XID (window),
2413                           GDK_WINDOW_XID (parent));
2414 }
2415
2416 static gboolean
2417 gdk_window_x11_set_back_color (GdkWindow *window,
2418                                double     red,
2419                                double     green,
2420                                double     blue,
2421                                double     alpha)
2422 {
2423   GdkVisual *visual = gdk_window_get_visual (window);
2424
2425   /* I suppose we could handle these, but that'd require fiddling with 
2426    * xrender formats... */
2427   if (alpha != 1.0)
2428     return FALSE;
2429
2430   switch (visual->type)
2431     {
2432     case GDK_VISUAL_DIRECT_COLOR:
2433     case GDK_VISUAL_TRUE_COLOR:
2434         {
2435           /* If bits not used for color are used for something other than padding,
2436            * it's likely alpha, so we set them to 1s.
2437            */
2438           guint padding, pixel;
2439
2440           /* Shifting by >= width-of-type isn't defined in C */
2441           if (visual->depth >= 32)
2442             padding = 0;
2443           else
2444             padding = ((~(guint32)0)) << visual->depth;
2445           
2446           pixel = ~ (visual->red_mask | visual->green_mask | visual->blue_mask | padding);
2447           
2448           pixel += (((int) (red   * ((1 << visual->red_prec  ) - 1))) << visual->red_shift  ) +
2449                    (((int) (green * ((1 << visual->green_prec) - 1))) << visual->green_shift) +
2450                    (((int) (blue  * ((1 << visual->blue_prec ) - 1))) << visual->blue_shift );
2451
2452           XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
2453                                 GDK_WINDOW_XID (window), pixel);
2454         }
2455       return TRUE;
2456
2457     /* These require fiddling with the colormap, and as they're essentially unused
2458      * we're just gonna skip them for now.
2459      */
2460     case GDK_VISUAL_PSEUDO_COLOR:
2461     case GDK_VISUAL_GRAYSCALE:
2462     case GDK_VISUAL_STATIC_GRAY:
2463     case GDK_VISUAL_STATIC_COLOR:
2464     default:
2465       break;
2466     }
2467
2468   return FALSE;
2469 }
2470
2471 static gboolean
2472 matrix_is_identity (cairo_matrix_t *matrix)
2473 {
2474   return matrix->xx == 1.0 && matrix->yy == 1.0 &&
2475     matrix->yx == 0.0 && matrix->xy == 0.0 &&
2476     matrix->x0 == 0.0 && matrix->y0 == 0.0;
2477 }
2478
2479 static void
2480 gdk_window_x11_set_background (GdkWindow      *window,
2481                                cairo_pattern_t *pattern)
2482 {
2483   double r, g, b, a;
2484   cairo_surface_t *surface;
2485   cairo_matrix_t matrix;
2486
2487   if (GDK_WINDOW_DESTROYED (window))
2488     return;
2489
2490   if (pattern == NULL)
2491     {
2492       GdkWindow *parent;
2493
2494       /* X throws BadMatch if the parent has a different visual when
2495        * using ParentRelative */
2496       parent = gdk_window_get_parent (window);
2497       if (parent && gdk_window_get_visual (parent) == gdk_window_get_visual (window))
2498         XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2499                                     GDK_WINDOW_XID (window), ParentRelative);
2500       else
2501         XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2502                                     GDK_WINDOW_XID (window), None);
2503       return;
2504     }
2505
2506   switch (cairo_pattern_get_type (pattern))
2507     {
2508     case CAIRO_PATTERN_TYPE_SOLID:
2509       cairo_pattern_get_rgba (pattern, &r, &g, &b, &a);
2510       if (gdk_window_x11_set_back_color (window, r, g, b, a))
2511         return;
2512       break;
2513     case CAIRO_PATTERN_TYPE_SURFACE:
2514       cairo_pattern_get_matrix (pattern, &matrix);
2515       if (cairo_pattern_get_surface (pattern, &surface) == CAIRO_STATUS_SUCCESS &&
2516           matrix_is_identity (&matrix) &&
2517           cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB &&
2518           cairo_xlib_surface_get_visual (surface) == GDK_VISUAL_XVISUAL (gdk_window_get_visual ((window))) &&
2519           cairo_xlib_surface_get_display (surface) == GDK_WINDOW_XDISPLAY (window))
2520         {
2521           double x, y;
2522
2523           cairo_surface_get_device_offset (surface, &x, &y);
2524           /* XXX: This still bombs for non-pixmaps, but there's no way to
2525            * detect we're not a pixmap in Cairo... */
2526           if (x == 0.0 && y == 0.0)
2527             {
2528               XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2529                                           GDK_WINDOW_XID (window),
2530                                           cairo_xlib_surface_get_drawable (surface));
2531               return;
2532             }
2533         }
2534       /* fall through */
2535     case CAIRO_PATTERN_TYPE_LINEAR:
2536     case CAIRO_PATTERN_TYPE_RADIAL:
2537     default:
2538       /* fallback: just use black */
2539       break;
2540     }
2541
2542   XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2543                               GDK_WINDOW_XID (window), None);
2544 }
2545
2546 static void
2547 gdk_window_x11_set_device_cursor (GdkWindow *window,
2548                                   GdkDevice *device,
2549                                   GdkCursor *cursor)
2550 {
2551   GdkWindowImplX11 *impl;
2552
2553   g_return_if_fail (GDK_IS_WINDOW (window));
2554   g_return_if_fail (GDK_IS_DEVICE (device));
2555
2556   impl = GDK_WINDOW_IMPL_X11 (window->impl);
2557
2558   if (!cursor)
2559     g_hash_table_remove (impl->device_cursor, device);
2560   else
2561     {
2562       _gdk_x11_cursor_update_theme (cursor);
2563       g_hash_table_replace (impl->device_cursor,
2564                             device, g_object_ref (cursor));
2565     }
2566
2567   if (!GDK_WINDOW_DESTROYED (window))
2568     GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
2569 }
2570
2571 GdkCursor *
2572 _gdk_x11_window_get_cursor (GdkWindow *window)
2573 {
2574   GdkWindowImplX11 *impl;
2575   
2576   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2577     
2578   impl = GDK_WINDOW_IMPL_X11 (window->impl);
2579
2580   return impl->cursor;
2581 }
2582
2583 static void
2584 gdk_window_x11_get_geometry (GdkWindow *window,
2585                              gint      *x,
2586                              gint      *y,
2587                              gint      *width,
2588                              gint      *height)
2589 {
2590   Window root;
2591   gint tx;
2592   gint ty;
2593   guint twidth;
2594   guint theight;
2595   guint tborder_width;
2596   guint tdepth;
2597   
2598   if (!GDK_WINDOW_DESTROYED (window))
2599     {
2600       XGetGeometry (GDK_WINDOW_XDISPLAY (window),
2601                     GDK_WINDOW_XID (window),
2602                     &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
2603       
2604       if (x)
2605         *x = tx;
2606       if (y)
2607         *y = ty;
2608       if (width)
2609         *width = twidth;
2610       if (height)
2611         *height = theight;
2612     }
2613 }
2614
2615 static gint
2616 gdk_window_x11_get_root_coords (GdkWindow *window,
2617                                 gint       x,
2618                                 gint       y,
2619                                 gint      *root_x,
2620                                 gint      *root_y)
2621 {
2622   gint return_val;
2623   Window child;
2624   gint tx;
2625   gint ty;
2626   
2627   return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2628                                       GDK_WINDOW_XID (window),
2629                                       GDK_WINDOW_XROOTWIN (window),
2630                                       x, y, &tx, &ty,
2631                                       &child);
2632   
2633   if (root_x)
2634     *root_x = tx;
2635   if (root_y)
2636     *root_y = ty;
2637   
2638   return return_val;
2639 }
2640
2641 static void
2642 gdk_x11_window_get_root_origin (GdkWindow *window,
2643                             gint      *x,
2644                             gint      *y)
2645 {
2646   GdkRectangle rect;
2647
2648   gdk_window_get_frame_extents (window, &rect);
2649
2650   if (x)
2651     *x = rect.x;
2652
2653   if (y)
2654     *y = rect.y;
2655 }
2656
2657 static void
2658 gdk_x11_window_get_frame_extents (GdkWindow    *window,
2659                                   GdkRectangle *rect)
2660 {
2661   GdkDisplay *display;
2662   GdkWindowImplX11 *impl;
2663   Window xwindow;
2664   Window xparent;
2665   Window root;
2666   Window child;
2667   Window *children;
2668   guchar *data;
2669   Window *vroots;
2670   Atom type_return;
2671   guint nchildren;
2672   guint nvroots;
2673   gulong nitems_return;
2674   gulong bytes_after_return;
2675   gint format_return;
2676   gint i;
2677   guint ww, wh, wb, wd;
2678   gint wx, wy;
2679   gboolean got_frame_extents = FALSE;
2680
2681   g_return_if_fail (rect != NULL);
2682
2683   rect->x = 0;
2684   rect->y = 0;
2685   rect->width = 1;
2686   rect->height = 1;
2687
2688   while (window->parent && (window->parent)->parent)
2689     window = window->parent;
2690
2691   /* Refine our fallback answer a bit using local information */
2692   rect->x = window->x;
2693   rect->y = window->y;
2694   rect->width = window->width;
2695   rect->height = window->height;
2696
2697   impl = GDK_WINDOW_IMPL_X11 (window->impl);
2698   if (GDK_WINDOW_DESTROYED (window) || impl->override_redirect)
2699     return;
2700
2701   nvroots = 0;
2702   vroots = NULL;
2703
2704   display = gdk_window_get_display (window);
2705
2706   gdk_x11_display_error_trap_push (display);
2707
2708   xwindow = GDK_WINDOW_XID (window);
2709
2710   /* first try: use _NET_FRAME_EXTENTS */
2711   if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2712                           gdk_x11_get_xatom_by_name_for_display (display,
2713                                                                   "_NET_FRAME_EXTENTS"),
2714                           0, G_MAXLONG, False, XA_CARDINAL, &type_return,
2715                           &format_return, &nitems_return, &bytes_after_return,
2716                           &data)
2717       == Success)
2718     {
2719       if ((type_return == XA_CARDINAL) && (format_return == 32) &&
2720           (nitems_return == 4) && (data))
2721         {
2722           gulong *ldata = (gulong *) data;
2723           got_frame_extents = TRUE;
2724
2725           /* try to get the real client window geometry */
2726           if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
2727                             &root, &wx, &wy, &ww, &wh, &wb, &wd) &&
2728               XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (display),
2729                                      xwindow, root, 0, 0, &wx, &wy, &child))
2730             {
2731               rect->x = wx;
2732               rect->y = wy;
2733               rect->width = ww;
2734               rect->height = wh;
2735             }
2736
2737           /* _NET_FRAME_EXTENTS format is left, right, top, bottom */
2738           rect->x -= ldata[0];
2739           rect->y -= ldata[2];
2740           rect->width += ldata[0] + ldata[1];
2741           rect->height += ldata[2] + ldata[3];
2742         }
2743
2744       if (data)
2745         XFree (data);
2746     }
2747
2748   if (got_frame_extents)
2749     goto out;
2750
2751   /* no frame extents property available, which means we either have a WM that
2752      is not EWMH compliant or is broken - try fallback and walk up the window
2753      tree to get our window's parent which hopefully is the window frame */
2754
2755   /* use NETWM_VIRTUAL_ROOTS if available */
2756   root = GDK_WINDOW_XROOTWIN (window);
2757
2758   if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
2759                           gdk_x11_get_xatom_by_name_for_display (display, 
2760                                                                  "_NET_VIRTUAL_ROOTS"),
2761                           0, G_MAXLONG, False, XA_WINDOW, &type_return,
2762                           &format_return, &nitems_return, &bytes_after_return,
2763                           &data)
2764       == Success)
2765     {
2766       if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
2767         {
2768           nvroots = nitems_return;
2769           vroots = (Window *)data;
2770         }
2771     }
2772
2773   xparent = GDK_WINDOW_XID (window);
2774
2775   do
2776     {
2777       xwindow = xparent;
2778
2779       if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
2780                        &root, &xparent,
2781                        &children, &nchildren))
2782         goto out;
2783       
2784       if (children)
2785         XFree (children);
2786
2787       /* check virtual roots */
2788       for (i = 0; i < nvroots; i++)
2789         {
2790           if (xparent == vroots[i])
2791             {
2792               root = xparent;
2793               break;
2794            }
2795         }
2796     }
2797   while (xparent != root);
2798
2799   if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
2800                     &root, &wx, &wy, &ww, &wh, &wb, &wd))
2801     {
2802       rect->x = wx;
2803       rect->y = wy;
2804       rect->width = ww;
2805       rect->height = wh;
2806     }
2807
2808  out:
2809   if (vroots)
2810     XFree (vroots);
2811
2812   gdk_x11_display_error_trap_pop_ignored (display);
2813 }
2814
2815 static gboolean
2816 gdk_window_x11_get_device_state (GdkWindow       *window,
2817                                  GdkDevice       *device,
2818                                  gint            *x,
2819                                  gint            *y,
2820                                  GdkModifierType *mask)
2821 {
2822   GdkWindow *child;
2823
2824   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
2825
2826   if (GDK_WINDOW_DESTROYED (window))
2827     return FALSE;
2828
2829   GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
2830                                               NULL, &child,
2831                                               NULL, NULL,
2832                                               x, y, mask);
2833   return child != NULL;
2834 }
2835
2836 static GdkEventMask
2837 gdk_window_x11_get_events (GdkWindow *window)
2838 {
2839   XWindowAttributes attrs;
2840   GdkEventMask event_mask;
2841   GdkEventMask filtered;
2842
2843   if (GDK_WINDOW_DESTROYED (window))
2844     return 0;
2845   else
2846     {
2847       XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
2848                             GDK_WINDOW_XID (window),
2849                             &attrs);
2850       event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
2851       /* if property change was filtered out before, keep it filtered out */
2852       filtered = GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK;
2853       window->event_mask = event_mask & ((window->event_mask & filtered) | ~filtered);
2854
2855       return event_mask;
2856     }
2857 }
2858 static void
2859 gdk_window_x11_set_events (GdkWindow    *window,
2860                            GdkEventMask  event_mask)
2861 {
2862   long xevent_mask = 0;
2863   
2864   if (!GDK_WINDOW_DESTROYED (window))
2865     {
2866       GdkX11Display *display_x11;
2867
2868       if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
2869         xevent_mask = StructureNotifyMask | PropertyChangeMask;
2870
2871       display_x11 = GDK_X11_DISPLAY (gdk_window_get_display (window));
2872       gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
2873                                           GDK_WINDOW_XID (window), event_mask,
2874                                           xevent_mask);
2875     }
2876 }
2877
2878 static inline void
2879 do_shape_combine_region (GdkWindow       *window,
2880                          const cairo_region_t *shape_region,
2881                          gint             offset_x,
2882                          gint             offset_y,
2883                          gint             shape)
2884 {
2885   if (GDK_WINDOW_DESTROYED (window))
2886     return;
2887
2888   if (shape_region == NULL)
2889     {
2890       /* Use NULL mask to unset the shape */
2891       if (shape == ShapeBounding
2892           ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
2893           : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
2894         {
2895           if (shape == ShapeBounding)
2896             {
2897               _gdk_x11_window_tmp_unset_parent_bg (window);
2898               _gdk_x11_window_tmp_unset_bg (window, TRUE);
2899             }
2900           XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
2901                              GDK_WINDOW_XID (window),
2902                              shape,
2903                              0, 0,
2904                              None,
2905                              ShapeSet);
2906           if (shape == ShapeBounding)
2907             {
2908               _gdk_x11_window_tmp_reset_parent_bg (window);
2909               _gdk_x11_window_tmp_reset_bg (window, TRUE);
2910             }
2911         }
2912       return;
2913     }
2914   
2915   if (shape == ShapeBounding
2916       ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
2917       : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
2918     {
2919       gint n_rects = 0;
2920       XRectangle *xrects = NULL;
2921
2922       _gdk_x11_region_get_xrectangles (shape_region,
2923                                        0, 0,
2924                                        &xrects, &n_rects);
2925       
2926       if (shape == ShapeBounding)
2927         {
2928           _gdk_x11_window_tmp_unset_parent_bg (window);
2929           _gdk_x11_window_tmp_unset_bg (window, TRUE);
2930         }
2931       XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
2932                                GDK_WINDOW_XID (window),
2933                                shape,
2934                                offset_x, offset_y,
2935                                xrects, n_rects,
2936                                ShapeSet,
2937                                YXBanded);
2938
2939       if (shape == ShapeBounding)
2940         {
2941           _gdk_x11_window_tmp_reset_parent_bg (window);
2942           _gdk_x11_window_tmp_reset_bg (window, TRUE);
2943         }
2944       
2945       g_free (xrects);
2946     }
2947 }
2948
2949 static void
2950 gdk_window_x11_shape_combine_region (GdkWindow       *window,
2951                                      const cairo_region_t *shape_region,
2952                                      gint             offset_x,
2953                                      gint             offset_y)
2954 {
2955   do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
2956 }
2957
2958 static void 
2959 gdk_window_x11_input_shape_combine_region (GdkWindow       *window,
2960                                            const cairo_region_t *shape_region,
2961                                            gint             offset_x,
2962                                            gint             offset_y)
2963 {
2964 #ifdef ShapeInput
2965   do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
2966 #endif
2967 }
2968
2969
2970 static void
2971 gdk_x11_window_set_override_redirect (GdkWindow *window,
2972                                   gboolean override_redirect)
2973 {
2974   XSetWindowAttributes attr;
2975   
2976   if (!GDK_WINDOW_DESTROYED (window) &&
2977       WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2978     {
2979       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
2980
2981       attr.override_redirect = (override_redirect? True : False);
2982       XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
2983                                GDK_WINDOW_XID (window),
2984                                CWOverrideRedirect,
2985                                &attr);
2986
2987       impl->override_redirect = attr.override_redirect;
2988     }
2989 }
2990
2991 static void
2992 gdk_x11_window_set_accept_focus (GdkWindow *window,
2993                                  gboolean accept_focus)
2994 {
2995   accept_focus = accept_focus != FALSE;
2996
2997   if (window->accept_focus != accept_focus)
2998     {
2999       window->accept_focus = accept_focus;
3000
3001       if (!GDK_WINDOW_DESTROYED (window) &&
3002           WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3003         update_wm_hints (window, FALSE);
3004     }
3005 }
3006
3007 static void
3008 gdk_x11_window_set_focus_on_map (GdkWindow *window,
3009                                  gboolean focus_on_map)
3010 {
3011   focus_on_map = focus_on_map != FALSE;
3012
3013   if (window->focus_on_map != focus_on_map)
3014     {
3015       window->focus_on_map = focus_on_map;
3016       
3017       if ((!GDK_WINDOW_DESTROYED (window)) &&
3018           (!window->focus_on_map) &&
3019           WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3020         gdk_x11_window_set_user_time (window, 0);
3021     }
3022 }
3023
3024 /**
3025  * gdk_x11_window_set_user_time:
3026  * @window: A toplevel #GdkWindow
3027  * @timestamp: An XServer timestamp to which the property should be set
3028  *
3029  * The application can use this call to update the _NET_WM_USER_TIME
3030  * property on a toplevel window.  This property stores an Xserver
3031  * time which represents the time of the last user input event
3032  * received for this window.  This property may be used by the window
3033  * manager to alter the focus, stacking, and/or placement behavior of
3034  * windows when they are mapped depending on whether the new window
3035  * was created by a user action or is a "pop-up" window activated by a
3036  * timer or some other event.
3037  *
3038  * Note that this property is automatically updated by GDK, so this
3039  * function should only be used by applications which handle input
3040  * events bypassing GDK.
3041  *
3042  * Since: 2.6
3043  **/
3044 void
3045 gdk_x11_window_set_user_time (GdkWindow *window,
3046                               guint32    timestamp)
3047 {
3048   GdkDisplay *display;
3049   GdkX11Display *display_x11;
3050   GdkToplevelX11 *toplevel;
3051   glong timestamp_long = (glong)timestamp;
3052   Window xid;
3053
3054   if (GDK_WINDOW_DESTROYED (window) ||
3055       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3056     return;
3057
3058   display = gdk_window_get_display (window);
3059   display_x11 = GDK_X11_DISPLAY (display);
3060   toplevel = _gdk_x11_window_get_toplevel (window);
3061
3062   if (!toplevel)
3063     {
3064       g_warning ("gdk_window_set_user_time called on non-toplevel\n");
3065       return;
3066     }
3067
3068   if (toplevel->focus_window != None &&
3069       gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3070                                            gdk_atom_intern_static_string ("_NET_WM_USER_TIME_WINDOW")))
3071     xid = toplevel->focus_window;
3072   else
3073     xid = GDK_WINDOW_XID (window);
3074
3075   XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xid,
3076                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
3077                    XA_CARDINAL, 32, PropModeReplace,
3078                    (guchar *)&timestamp_long, 1);
3079
3080   if (timestamp_long != GDK_CURRENT_TIME &&
3081       (display_x11->user_time == GDK_CURRENT_TIME ||
3082        XSERVER_TIME_IS_LATER (timestamp_long, display_x11->user_time)))
3083     display_x11->user_time = timestamp_long;
3084
3085   if (toplevel)
3086     toplevel->user_time = timestamp_long;
3087 }
3088
3089 /**
3090  * gdk_x11_window_set_theme_variant:
3091  * @window: a #GdkWindow
3092  * @variant: the theme variant to export
3093  *
3094  * GTK+ applications can request a dark theme variant. In order to
3095  * make other applications - namely window managers using GTK+ for
3096  * themeing - aware of this choice, GTK+ uses this function to
3097  * export the requested theme variant as _GTK_THEME_VARIANT property
3098  * on toplevel windows.
3099  *
3100  * Note that this property is automatically updated by GTK+, so this
3101  * function should only be used by applications which do not use GTK+
3102  * to create toplevel windows.
3103  *
3104  * Since: 3.2
3105  */
3106 void
3107 gdk_x11_window_set_theme_variant (GdkWindow *window,
3108                                   char      *variant)
3109 {
3110   GdkDisplay *display;
3111
3112   if (!WINDOW_IS_TOPLEVEL (window))
3113     return;
3114
3115   display = gdk_window_get_display (window);
3116
3117   if (variant != NULL)
3118     {
3119       XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3120                        GDK_WINDOW_XID (window),
3121                        gdk_x11_get_xatom_by_name_for_display (display, "_GTK_THEME_VARIANT"),
3122                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3123                        PropModeReplace, (guchar *)variant, strlen (variant));
3124     }
3125   else
3126     {
3127       XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3128                        GDK_WINDOW_XID (window),
3129                        gdk_x11_get_xatom_by_name_for_display (display, "_GTK_THEME_VARIANT"));
3130     }
3131 }
3132
3133 #define GDK_SELECTION_MAX_SIZE(display)                                 \
3134   MIN(262144,                                                           \
3135       XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0     \
3136        ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100         \
3137        : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
3138
3139 static void
3140 gdk_window_update_icon (GdkWindow *window,
3141                         GList     *icon_list)
3142 {
3143   GdkToplevelX11 *toplevel;
3144   GdkPixbuf *best_icon;
3145   GList *tmp_list;
3146   int best_size;
3147   
3148   toplevel = _gdk_x11_window_get_toplevel (window);
3149
3150   if (toplevel->icon_pixmap != NULL)
3151     {
3152       cairo_surface_destroy (toplevel->icon_pixmap);
3153       toplevel->icon_pixmap = NULL;
3154     }
3155   
3156   if (toplevel->icon_mask != NULL)
3157     {
3158       cairo_surface_destroy (toplevel->icon_mask);
3159       toplevel->icon_mask = NULL;
3160     }
3161   
3162 #define IDEAL_SIZE 48
3163   
3164   best_size = G_MAXINT;
3165   best_icon = NULL;
3166   for (tmp_list = icon_list; tmp_list; tmp_list = tmp_list->next)
3167     {
3168       GdkPixbuf *pixbuf = tmp_list->data;
3169       int this;
3170   
3171       /* average width and height - if someone passes in a rectangular
3172        * icon they deserve what they get.
3173        */
3174       this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3175       this /= 2;
3176   
3177       if (best_icon == NULL)
3178         {
3179           best_icon = pixbuf;
3180           best_size = this;
3181         }
3182       else
3183         {
3184           /* icon is better if it's 32 pixels or larger, and closer to
3185            * the ideal size than the current best.
3186            */
3187           if (this >= 32 &&
3188               (ABS (best_size - IDEAL_SIZE) <
3189                ABS (this - IDEAL_SIZE)))
3190             {
3191               best_icon = pixbuf;
3192               best_size = this;
3193             }
3194         }
3195     }
3196
3197   if (best_icon)
3198     {
3199       int width = gdk_pixbuf_get_width (best_icon);
3200       int height = gdk_pixbuf_get_height (best_icon);
3201       cairo_t *cr;
3202
3203       toplevel->icon_pixmap = gdk_x11_window_create_pixmap_surface (window,
3204                                                                     width,
3205                                                                     height);
3206
3207       cr = cairo_create (toplevel->icon_pixmap);
3208       cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3209       gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3210       if (gdk_pixbuf_get_has_alpha (best_icon))
3211         {
3212           /* Saturate the image, so it has bilevel alpha */
3213           cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
3214           cairo_paint (cr);
3215           cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE);
3216           cairo_paint (cr);
3217           cairo_pop_group_to_source (cr);
3218         }
3219       cairo_paint (cr);
3220       cairo_destroy (cr);
3221
3222       if (gdk_pixbuf_get_has_alpha (best_icon))
3223         {
3224           toplevel->icon_mask = _gdk_x11_window_create_bitmap_surface (window,
3225                                                                        width,
3226                                                                        height);
3227
3228           cr = cairo_create (toplevel->icon_mask);
3229           gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3230           cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3231           cairo_paint (cr);
3232           cairo_destroy (cr);
3233         }
3234     }
3235
3236   update_wm_hints (window, FALSE);
3237 }
3238
3239 static void
3240 gdk_x11_window_set_icon_list (GdkWindow *window,
3241                               GList     *pixbufs)
3242 {
3243   gulong *data;
3244   guchar *pixels;
3245   gulong *p;
3246   gint size;
3247   GList *l;
3248   GdkPixbuf *pixbuf;
3249   gint width, height, stride;
3250   gint x, y;
3251   gint n_channels;
3252   GdkDisplay *display;
3253   gint n;
3254   
3255   if (GDK_WINDOW_DESTROYED (window) ||
3256       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3257     return;
3258
3259   display = gdk_window_get_display (window);
3260   
3261   l = pixbufs;
3262   size = 0;
3263   n = 0;
3264   while (l)
3265     {
3266       pixbuf = l->data;
3267       g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3268
3269       width = gdk_pixbuf_get_width (pixbuf);
3270       height = gdk_pixbuf_get_height (pixbuf);
3271       
3272       /* silently ignore overlarge icons */
3273       if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
3274         {
3275           g_warning ("gdk_window_set_icon_list: icons too large");
3276           break;
3277         }
3278      
3279       n++;
3280       size += 2 + width * height;
3281       
3282       l = g_list_next (l);
3283     }
3284
3285   data = g_malloc (size * sizeof (gulong));
3286
3287   l = pixbufs;
3288   p = data;
3289   while (l && n > 0)
3290     {
3291       pixbuf = l->data;
3292       
3293       width = gdk_pixbuf_get_width (pixbuf);
3294       height = gdk_pixbuf_get_height (pixbuf);
3295       stride = gdk_pixbuf_get_rowstride (pixbuf);
3296       n_channels = gdk_pixbuf_get_n_channels (pixbuf);
3297       
3298       *p++ = width;
3299       *p++ = height;
3300
3301       pixels = gdk_pixbuf_get_pixels (pixbuf);
3302
3303       for (y = 0; y < height; y++)
3304         {
3305           for (x = 0; x < width; x++)
3306             {
3307               guchar r, g, b, a;
3308               
3309               r = pixels[y*stride + x*n_channels + 0];
3310               g = pixels[y*stride + x*n_channels + 1];
3311               b = pixels[y*stride + x*n_channels + 2];
3312               if (n_channels >= 4)
3313                 a = pixels[y*stride + x*n_channels + 3];
3314               else
3315                 a = 255;
3316               
3317               *p++ = a << 24 | r << 16 | g << 8 | b ;
3318             }
3319         }
3320
3321       l = g_list_next (l);
3322       n--;
3323     }
3324
3325   if (size > 0)
3326     {
3327       XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3328                        GDK_WINDOW_XID (window),
3329                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
3330                        XA_CARDINAL, 32,
3331                        PropModeReplace,
3332                        (guchar*) data, size);
3333     }
3334   else
3335     {
3336       XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3337                        GDK_WINDOW_XID (window),
3338                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
3339     }
3340   
3341   g_free (data);
3342
3343   gdk_window_update_icon (window, pixbufs);
3344 }
3345
3346 static gboolean
3347 gdk_window_icon_name_set (GdkWindow *window)
3348 {
3349   return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
3350                                                g_quark_from_static_string ("gdk-icon-name-set")));
3351 }
3352
3353 static void
3354 gdk_x11_window_set_icon_name (GdkWindow   *window,
3355                               const gchar *name)
3356 {
3357   GdkDisplay *display;
3358
3359   if (GDK_WINDOW_DESTROYED (window) ||
3360       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3361     return;
3362
3363   display = gdk_window_get_display (window);
3364
3365   g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
3366                       GUINT_TO_POINTER (name != NULL));
3367
3368   if (name != NULL)
3369     {
3370       XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3371                        GDK_WINDOW_XID (window),
3372                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
3373                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3374                        PropModeReplace, (guchar *)name, strlen (name));
3375
3376       set_text_property (display, GDK_WINDOW_XID (window),
3377                          gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
3378                          name);
3379     }
3380   else
3381     {
3382       XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3383                        GDK_WINDOW_XID (window),
3384                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"));
3385       XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3386                        GDK_WINDOW_XID (window),
3387                        gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"));
3388     }
3389 }
3390
3391 static void
3392 gdk_x11_window_iconify (GdkWindow *window)
3393 {
3394   if (GDK_WINDOW_DESTROYED (window) ||
3395       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3396     return;
3397
3398   if (GDK_WINDOW_IS_MAPPED (window))
3399     {  
3400       XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
3401                       GDK_WINDOW_XID (window),
3402                       gdk_screen_get_number (GDK_WINDOW_SCREEN (window)));
3403     }
3404   else
3405     {
3406       /* Flip our client side flag, the real work happens on map. */
3407       gdk_synthesize_window_state (window,
3408                                    0,
3409                                    GDK_WINDOW_STATE_ICONIFIED);
3410     }
3411 }
3412
3413 static void
3414 gdk_x11_window_deiconify (GdkWindow *window)
3415 {
3416   if (GDK_WINDOW_DESTROYED (window) ||
3417       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3418     return;
3419
3420   if (GDK_WINDOW_IS_MAPPED (window))
3421     {  
3422       gdk_window_show (window);
3423     }
3424   else
3425     {
3426       /* Flip our client side flag, the real work happens on map. */
3427       gdk_synthesize_window_state (window,
3428                                    GDK_WINDOW_STATE_ICONIFIED,
3429                                    0);
3430     }
3431 }
3432
3433 static void
3434 gdk_x11_window_stick (GdkWindow *window)
3435 {
3436   if (GDK_WINDOW_DESTROYED (window) ||
3437       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3438     return;
3439
3440   if (GDK_WINDOW_IS_MAPPED (window))
3441     {
3442       /* "stick" means stick to all desktops _and_ do not scroll with the
3443        * viewport. i.e. glue to the monitor glass in all cases.
3444        */
3445       
3446       XClientMessageEvent xclient;
3447
3448       /* Request stick during viewport scroll */
3449       gdk_wmspec_change_state (TRUE, window,
3450                                gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3451                                GDK_NONE);
3452
3453       /* Request desktop 0xFFFFFFFF */
3454       memset (&xclient, 0, sizeof (xclient));
3455       xclient.type = ClientMessage;
3456       xclient.window = GDK_WINDOW_XID (window);
3457       xclient.display = GDK_WINDOW_XDISPLAY (window);
3458       xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), 
3459                                                                         "_NET_WM_DESKTOP");
3460       xclient.format = 32;
3461
3462       xclient.data.l[0] = 0xFFFFFFFF;
3463       xclient.data.l[1] = 0;
3464       xclient.data.l[2] = 0;
3465       xclient.data.l[3] = 0;
3466       xclient.data.l[4] = 0;
3467
3468       XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3469                   SubstructureRedirectMask | SubstructureNotifyMask,
3470                   (XEvent *)&xclient);
3471     }
3472   else
3473     {
3474       /* Flip our client side flag, the real work happens on map. */
3475       gdk_synthesize_window_state (window,
3476                                    0,
3477                                    GDK_WINDOW_STATE_STICKY);
3478     }
3479 }
3480
3481 static void
3482 gdk_x11_window_unstick (GdkWindow *window)
3483 {
3484   if (GDK_WINDOW_DESTROYED (window) ||
3485       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3486     return;
3487
3488   if (GDK_WINDOW_IS_MAPPED (window))
3489     {
3490       /* Request unstick from viewport */
3491       gdk_wmspec_change_state (FALSE, window,
3492                                gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3493                                GDK_NONE);
3494
3495       move_to_current_desktop (window);
3496     }
3497   else
3498     {
3499       /* Flip our client side flag, the real work happens on map. */
3500       gdk_synthesize_window_state (window,
3501                                    GDK_WINDOW_STATE_STICKY,
3502                                    0);
3503
3504     }
3505 }
3506
3507 static void
3508 gdk_x11_window_maximize (GdkWindow *window)
3509 {
3510   if (GDK_WINDOW_DESTROYED (window) ||
3511       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3512     return;
3513
3514   if (GDK_WINDOW_IS_MAPPED (window))
3515     gdk_wmspec_change_state (TRUE, window,
3516                              gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3517                              gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3518   else
3519     gdk_synthesize_window_state (window,
3520                                  0,
3521                                  GDK_WINDOW_STATE_MAXIMIZED);
3522 }
3523
3524 static void
3525 gdk_x11_window_unmaximize (GdkWindow *window)
3526 {
3527   if (GDK_WINDOW_DESTROYED (window) ||
3528       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3529     return;
3530
3531   if (GDK_WINDOW_IS_MAPPED (window))
3532     gdk_wmspec_change_state (FALSE, window,
3533                              gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3534                              gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3535   else
3536     gdk_synthesize_window_state (window,
3537                                  GDK_WINDOW_STATE_MAXIMIZED,
3538                                  0);
3539 }
3540
3541 static void
3542 gdk_x11_window_fullscreen (GdkWindow *window)
3543 {
3544   if (GDK_WINDOW_DESTROYED (window) ||
3545       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3546     return;
3547
3548   if (GDK_WINDOW_IS_MAPPED (window))
3549     gdk_wmspec_change_state (TRUE, window,
3550                              gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
3551                              GDK_NONE);
3552
3553   else
3554     gdk_synthesize_window_state (window,
3555                                  0,
3556                                  GDK_WINDOW_STATE_FULLSCREEN);
3557 }
3558
3559 static void
3560 gdk_x11_window_unfullscreen (GdkWindow *window)
3561 {
3562   if (GDK_WINDOW_DESTROYED (window) ||
3563       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3564     return;
3565
3566   if (GDK_WINDOW_IS_MAPPED (window))
3567     gdk_wmspec_change_state (FALSE, window,
3568                              gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
3569                              GDK_NONE);
3570
3571   else
3572     gdk_synthesize_window_state (window,
3573                                  GDK_WINDOW_STATE_FULLSCREEN,
3574                                  0);
3575 }
3576
3577 static void
3578 gdk_x11_window_set_keep_above (GdkWindow *window,
3579                                gboolean   setting)
3580 {
3581   g_return_if_fail (GDK_IS_WINDOW (window));
3582
3583   if (GDK_WINDOW_DESTROYED (window) ||
3584       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3585     return;
3586
3587   if (GDK_WINDOW_IS_MAPPED (window))
3588     {
3589       if (setting)
3590         gdk_wmspec_change_state (FALSE, window,
3591                                  gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
3592                                  GDK_NONE);
3593       gdk_wmspec_change_state (setting, window,
3594                                gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
3595                                GDK_NONE);
3596     }
3597   else
3598     gdk_synthesize_window_state (window,
3599                                  setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
3600                                  setting ? GDK_WINDOW_STATE_ABOVE : 0);
3601 }
3602
3603 static void
3604 gdk_x11_window_set_keep_below (GdkWindow *window, gboolean setting)
3605 {
3606   g_return_if_fail (GDK_IS_WINDOW (window));
3607
3608   if (GDK_WINDOW_DESTROYED (window) ||
3609       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3610     return;
3611
3612   if (GDK_WINDOW_IS_MAPPED (window))
3613     {
3614       if (setting)
3615         gdk_wmspec_change_state (FALSE, window,
3616                                  gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
3617                                  GDK_NONE);
3618       gdk_wmspec_change_state (setting, window,
3619                                gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
3620                                GDK_NONE);
3621     }
3622   else
3623     gdk_synthesize_window_state (window,
3624                                  setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
3625                                  setting ? GDK_WINDOW_STATE_BELOW : 0);
3626 }
3627
3628 static GdkWindow *
3629 gdk_x11_window_get_group (GdkWindow *window)
3630 {
3631   GdkToplevelX11 *toplevel;
3632   
3633   if (GDK_WINDOW_DESTROYED (window) ||
3634       !WINDOW_IS_TOPLEVEL (window))
3635     return NULL;
3636   
3637   toplevel = _gdk_x11_window_get_toplevel (window);
3638
3639   return toplevel->group_leader;
3640 }
3641
3642 static void
3643 gdk_x11_window_set_group (GdkWindow *window,
3644                           GdkWindow *leader)
3645 {
3646   GdkToplevelX11 *toplevel;
3647   
3648   g_return_if_fail (GDK_IS_WINDOW (window));
3649   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
3650   g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
3651
3652   if (GDK_WINDOW_DESTROYED (window) ||
3653       (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
3654       !WINDOW_IS_TOPLEVEL (window))
3655     return;
3656
3657   toplevel = _gdk_x11_window_get_toplevel (window);
3658
3659   if (leader == NULL)
3660     leader = gdk_display_get_default_group (gdk_window_get_display (window));
3661   
3662   if (toplevel->group_leader != leader)
3663     {
3664       if (toplevel->group_leader)
3665         g_object_unref (toplevel->group_leader);
3666       toplevel->group_leader = g_object_ref (leader);
3667       (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;      
3668     }
3669
3670   update_wm_hints (window, FALSE);
3671 }
3672
3673 static MotifWmHints *
3674 gdk_window_get_mwm_hints (GdkWindow *window)
3675 {
3676   GdkDisplay *display;
3677   Atom hints_atom = None;
3678   guchar *data;
3679   Atom type;
3680   gint format;
3681   gulong nitems;
3682   gulong bytes_after;
3683   
3684   if (GDK_WINDOW_DESTROYED (window))
3685     return NULL;
3686
3687   display = gdk_window_get_display (window);
3688   
3689   hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
3690
3691   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
3692                       hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
3693                       False, AnyPropertyType, &type, &format, &nitems,
3694                       &bytes_after, &data);
3695
3696   if (type == None)
3697     return NULL;
3698   
3699   return (MotifWmHints *)data;
3700 }
3701
3702 static void
3703 gdk_window_set_mwm_hints (GdkWindow *window,
3704                           MotifWmHints *new_hints)
3705 {
3706   GdkDisplay *display;
3707   Atom hints_atom = None;
3708   guchar *data;
3709   MotifWmHints *hints;
3710   Atom type;
3711   gint format;
3712   gulong nitems;
3713   gulong bytes_after;
3714   
3715   if (GDK_WINDOW_DESTROYED (window))
3716     return;
3717   
3718   display = gdk_window_get_display (window);
3719   
3720   hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
3721
3722   XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
3723                       hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
3724                       False, AnyPropertyType, &type, &format, &nitems,
3725                       &bytes_after, &data);
3726   
3727   if (type == None)
3728     hints = new_hints;
3729   else
3730     {
3731       hints = (MotifWmHints *)data;
3732         
3733       if (new_hints->flags & MWM_HINTS_FUNCTIONS)
3734         {
3735           hints->flags |= MWM_HINTS_FUNCTIONS;
3736           hints->functions = new_hints->functions;
3737         }
3738       if (new_hints->flags & MWM_HINTS_DECORATIONS)
3739         {
3740           hints->flags |= MWM_HINTS_DECORATIONS;
3741           hints->decorations = new_hints->decorations;
3742         }
3743     }
3744   
3745   XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
3746                    hints_atom, hints_atom, 32, PropModeReplace,
3747                    (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
3748   
3749   if (hints != new_hints)
3750     XFree (hints);
3751 }
3752
3753 static void
3754 gdk_x11_window_set_decorations (GdkWindow      *window,
3755                                 GdkWMDecoration decorations)
3756 {
3757   MotifWmHints hints;
3758
3759   if (GDK_WINDOW_DESTROYED (window) ||
3760       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3761     return;
3762   
3763   /* initialize to zero to avoid writing uninitialized data to socket */
3764   memset(&hints, 0, sizeof(hints));
3765   hints.flags = MWM_HINTS_DECORATIONS;
3766   hints.decorations = decorations;
3767   
3768   gdk_window_set_mwm_hints (window, &hints);
3769 }
3770
3771 static gboolean
3772 gdk_x11_window_get_decorations(GdkWindow       *window,
3773                                GdkWMDecoration *decorations)
3774 {
3775   MotifWmHints *hints;
3776   gboolean result = FALSE;
3777
3778   if (GDK_WINDOW_DESTROYED (window) ||
3779       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3780     return FALSE;
3781   
3782   hints = gdk_window_get_mwm_hints (window);
3783   
3784   if (hints)
3785     {
3786       if (hints->flags & MWM_HINTS_DECORATIONS)
3787         {
3788           if (decorations)
3789             *decorations = hints->decorations;
3790           result = TRUE;
3791         }
3792       
3793       XFree (hints);
3794     }
3795
3796   return result;
3797 }
3798
3799 static void
3800 gdk_x11_window_set_functions (GdkWindow    *window,
3801                           GdkWMFunction functions)
3802 {
3803   MotifWmHints hints;
3804   
3805   g_return_if_fail (GDK_IS_WINDOW (window));
3806
3807   if (GDK_WINDOW_DESTROYED (window) ||
3808       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3809     return;
3810   
3811   /* initialize to zero to avoid writing uninitialized data to socket */
3812   memset(&hints, 0, sizeof(hints));
3813   hints.flags = MWM_HINTS_FUNCTIONS;
3814   hints.functions = functions;
3815   
3816   gdk_window_set_mwm_hints (window, &hints);
3817 }
3818
3819 cairo_region_t *
3820 _gdk_x11_xwindow_get_shape (Display *xdisplay,
3821                             Window   window,
3822                             gint     shape_type)
3823 {
3824   cairo_region_t *shape;
3825   GdkRectangle *rl;
3826   XRectangle *xrl;
3827   gint rn, ord, i;
3828
3829   shape = NULL;
3830   rn = 0;
3831
3832   xrl = XShapeGetRectangles (xdisplay,
3833                              window,
3834                              shape_type, &rn, &ord);
3835
3836   if (xrl == NULL || rn == 0)
3837     return cairo_region_create (); /* Empty */
3838
3839   if (ord != YXBanded)
3840     {
3841       /* This really shouldn't happen with any xserver, as they
3842          generally convert regions to YXBanded internally */
3843       g_warning ("non YXBanded shape masks not supported");
3844       XFree (xrl);
3845       return NULL;
3846     }
3847
3848   rl = g_new (GdkRectangle, rn);
3849   for (i = 0; i < rn; i++)
3850     {
3851       rl[i].x = xrl[i].x;
3852       rl[i].y = xrl[i].y;
3853       rl[i].width = xrl[i].width;
3854       rl[i].height = xrl[i].height;
3855     }
3856   XFree (xrl);
3857   
3858   shape = cairo_region_create_rectangles (rl, rn);
3859   g_free (rl);
3860   
3861   return shape;
3862 }
3863
3864
3865 static cairo_region_t *
3866 gdk_x11_window_get_shape (GdkWindow *window)
3867 {
3868   if (!GDK_WINDOW_DESTROYED (window) &&
3869       gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
3870     return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
3871                                        GDK_WINDOW_XID (window),
3872                                        ShapeBounding);
3873
3874   return NULL;
3875 }
3876
3877 static cairo_region_t *
3878 gdk_x11_window_get_input_shape (GdkWindow *window)
3879 {
3880 #if defined(ShapeInput)
3881   if (!GDK_WINDOW_DESTROYED (window) &&
3882       gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
3883     return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
3884                                        GDK_WINDOW_XID (window),
3885                                        ShapeInput);
3886 #endif
3887
3888   return NULL;
3889 }
3890
3891 static void
3892 gdk_window_set_static_bit_gravity (GdkWindow *window,
3893                                    gboolean   on)
3894 {
3895   XSetWindowAttributes xattributes;
3896   guint xattributes_mask = 0;
3897   
3898   g_return_if_fail (GDK_IS_WINDOW (window));
3899
3900   if (window->input_only)
3901     return;
3902   
3903   xattributes.bit_gravity = StaticGravity;
3904   xattributes_mask |= CWBitGravity;
3905   xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
3906   XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3907                            GDK_WINDOW_XID (window),
3908                            CWBitGravity,  &xattributes);
3909 }
3910
3911 static void
3912 gdk_window_set_static_win_gravity (GdkWindow *window,
3913                                    gboolean   on)
3914 {
3915   XSetWindowAttributes xattributes;
3916   
3917   g_return_if_fail (GDK_IS_WINDOW (window));
3918   
3919   xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
3920   
3921   XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3922                            GDK_WINDOW_XID (window),
3923                            CWWinGravity,  &xattributes);
3924 }
3925
3926 static gboolean
3927 gdk_window_x11_set_static_gravities (GdkWindow *window,
3928                                      gboolean   use_static)
3929 {
3930   GList *tmp_list;
3931   
3932   if (!use_static == !window->guffaw_gravity)
3933     return TRUE;
3934
3935   window->guffaw_gravity = use_static;
3936   
3937   if (!GDK_WINDOW_DESTROYED (window))
3938     {
3939       gdk_window_set_static_bit_gravity (window, use_static);
3940       
3941       tmp_list = window->children;
3942       while (tmp_list)
3943         {
3944           gdk_window_set_static_win_gravity (tmp_list->data, use_static);
3945           
3946           tmp_list = tmp_list->next;
3947         }
3948     }
3949   
3950   return TRUE;
3951 }
3952
3953 static void
3954 wmspec_moveresize (GdkWindow *window,
3955                    gint       direction,
3956                    gint       root_x,
3957                    gint       root_y,
3958                    guint32    timestamp)     
3959 {
3960   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
3961   
3962   XClientMessageEvent xclient;
3963
3964   /* Release passive grab */
3965   gdk_display_pointer_ungrab (display, timestamp);
3966
3967   memset (&xclient, 0, sizeof (xclient));
3968   xclient.type = ClientMessage;
3969   xclient.window = GDK_WINDOW_XID (window);
3970   xclient.message_type =
3971     gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
3972   xclient.format = 32;
3973   xclient.data.l[0] = root_x;
3974   xclient.data.l[1] = root_y;
3975   xclient.data.l[2] = direction;
3976   xclient.data.l[3] = 0;
3977   xclient.data.l[4] = 0;
3978   
3979   XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
3980               SubstructureRedirectMask | SubstructureNotifyMask,
3981               (XEvent *)&xclient);
3982 }
3983
3984 typedef struct _MoveResizeData MoveResizeData;
3985
3986 struct _MoveResizeData
3987 {
3988   GdkDisplay *display;
3989   
3990   GdkWindow *moveresize_window;
3991   GdkWindow *moveresize_emulation_window;
3992   gboolean is_resize;
3993   GdkWindowEdge resize_edge;
3994   gint moveresize_button;
3995   gint moveresize_x;
3996   gint moveresize_y;
3997   gint moveresize_orig_x;
3998   gint moveresize_orig_y;
3999   gint moveresize_orig_width;
4000   gint moveresize_orig_height;
4001   GdkWindowHints moveresize_geom_mask;
4002   GdkGeometry moveresize_geometry;
4003   Time moveresize_process_time;
4004   XEvent *moveresize_pending_event;
4005 };
4006
4007 /* From the WM spec */
4008 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT      0
4009 #define _NET_WM_MOVERESIZE_SIZE_TOP          1
4010 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT     2
4011 #define _NET_WM_MOVERESIZE_SIZE_RIGHT        3
4012 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT  4
4013 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM       5
4014 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT   6
4015 #define _NET_WM_MOVERESIZE_SIZE_LEFT         7
4016 #define _NET_WM_MOVERESIZE_MOVE              8
4017
4018 static void
4019 wmspec_resize_drag (GdkWindow     *window,
4020                     GdkWindowEdge  edge,
4021                     gint           button,
4022                     gint           root_x,
4023                     gint           root_y,
4024                     guint32        timestamp)
4025 {
4026   gint direction;
4027   
4028   /* Let the compiler turn a switch into a table, instead
4029    * of doing the table manually, this way is easier to verify.
4030    */
4031   switch (edge)
4032     {
4033     case GDK_WINDOW_EDGE_NORTH_WEST:
4034       direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
4035       break;
4036
4037     case GDK_WINDOW_EDGE_NORTH:
4038       direction = _NET_WM_MOVERESIZE_SIZE_TOP;
4039       break;
4040
4041     case GDK_WINDOW_EDGE_NORTH_EAST:
4042       direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
4043       break;
4044
4045     case GDK_WINDOW_EDGE_WEST:
4046       direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
4047       break;
4048
4049     case GDK_WINDOW_EDGE_EAST:
4050       direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
4051       break;
4052
4053     case GDK_WINDOW_EDGE_SOUTH_WEST:
4054       direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
4055       break;
4056
4057     case GDK_WINDOW_EDGE_SOUTH:
4058       direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
4059       break;
4060
4061     case GDK_WINDOW_EDGE_SOUTH_EAST:
4062       direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
4063       break;
4064
4065     default:
4066       g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
4067                  edge);
4068       return;
4069     }
4070   
4071   wmspec_moveresize (window, direction, root_x, root_y, timestamp);
4072 }
4073
4074 static MoveResizeData *
4075 get_move_resize_data (GdkDisplay *display,
4076                       gboolean    create)
4077 {
4078   MoveResizeData *mv_resize;
4079   static GQuark move_resize_quark = 0;
4080
4081   if (!move_resize_quark)
4082     move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
4083   
4084   mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
4085
4086   if (!mv_resize && create)
4087     {
4088       mv_resize = g_new0 (MoveResizeData, 1);
4089       mv_resize->display = display;
4090       
4091       g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
4092     }
4093
4094   return mv_resize;
4095 }
4096
4097 static void
4098 update_pos (MoveResizeData *mv_resize,
4099             gint            new_root_x,
4100             gint            new_root_y)
4101 {
4102   gint dx, dy;
4103
4104   dx = new_root_x - mv_resize->moveresize_x;
4105   dy = new_root_y - mv_resize->moveresize_y;
4106
4107   if (mv_resize->is_resize)
4108     {
4109       gint x, y, w, h;
4110
4111       x = mv_resize->moveresize_orig_x;
4112       y = mv_resize->moveresize_orig_y;
4113
4114       w = mv_resize->moveresize_orig_width;
4115       h = mv_resize->moveresize_orig_height;
4116
4117       switch (mv_resize->resize_edge)
4118         {
4119         case GDK_WINDOW_EDGE_NORTH_WEST:
4120           x += dx;
4121           y += dy;
4122           w -= dx;
4123           h -= dy;
4124           break;
4125         case GDK_WINDOW_EDGE_NORTH:
4126           y += dy;
4127           h -= dy;
4128           break;
4129         case GDK_WINDOW_EDGE_NORTH_EAST:
4130           y += dy;
4131           h -= dy;
4132           w += dx;
4133           break;
4134         case GDK_WINDOW_EDGE_SOUTH_WEST:
4135           h += dy;
4136           x += dx;
4137           w -= dx;
4138           break;
4139         case GDK_WINDOW_EDGE_SOUTH_EAST:
4140           w += dx;
4141           h += dy;
4142           break;
4143         case GDK_WINDOW_EDGE_SOUTH:
4144           h += dy;
4145           break;
4146         case GDK_WINDOW_EDGE_EAST:
4147           w += dx;
4148           break;
4149         case GDK_WINDOW_EDGE_WEST:
4150           x += dx;
4151           w -= dx;
4152           break;
4153         }
4154
4155       x = MAX (x, 0);
4156       y = MAX (y, 0);
4157       w = MAX (w, 1);
4158       h = MAX (h, 1);
4159
4160       if (mv_resize->moveresize_geom_mask)
4161         {
4162           gdk_window_constrain_size (&mv_resize->moveresize_geometry,
4163                                      mv_resize->moveresize_geom_mask,
4164                                      w, h, &w, &h);
4165         }
4166
4167       gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
4168     }
4169   else
4170     {
4171       gint x, y;
4172
4173       x = mv_resize->moveresize_orig_x + dx;
4174       y = mv_resize->moveresize_orig_y + dy;
4175
4176       gdk_window_move (mv_resize->moveresize_window, x, y);
4177     }
4178 }
4179
4180 static void
4181 finish_drag (MoveResizeData *mv_resize)
4182 {
4183   gdk_window_destroy (mv_resize->moveresize_emulation_window);
4184   mv_resize->moveresize_emulation_window = NULL;
4185   g_object_unref (mv_resize->moveresize_window);
4186   mv_resize->moveresize_window = NULL;
4187
4188   if (mv_resize->moveresize_pending_event)
4189     {
4190       g_free (mv_resize->moveresize_pending_event);
4191       mv_resize->moveresize_pending_event = NULL;
4192     }
4193 }
4194
4195 static int
4196 lookahead_motion_predicate (Display *xdisplay,
4197                             XEvent  *event,
4198                             XPointer arg)
4199 {
4200   gboolean *seen_release = (gboolean *)arg;
4201   GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
4202   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4203
4204   if (*seen_release)
4205     return False;
4206
4207   switch (event->xany.type)
4208     {
4209     case ButtonRelease:
4210       *seen_release = TRUE;
4211       break;
4212     case MotionNotify:
4213       mv_resize->moveresize_process_time = event->xmotion.time;
4214       break;
4215     default:
4216       break;
4217     }
4218
4219   return False;
4220 }
4221
4222 static gboolean
4223 moveresize_lookahead (MoveResizeData *mv_resize,
4224                       XEvent         *event)
4225 {
4226   XEvent tmp_event;
4227   gboolean seen_release = FALSE;
4228
4229   if (mv_resize->moveresize_process_time)
4230     {
4231       if (event->xmotion.time == mv_resize->moveresize_process_time)
4232         {
4233           mv_resize->moveresize_process_time = 0;
4234           return TRUE;
4235         }
4236       else
4237         return FALSE;
4238     }
4239
4240   XCheckIfEvent (event->xany.display, &tmp_event,
4241                  lookahead_motion_predicate, (XPointer) & seen_release);
4242
4243   return mv_resize->moveresize_process_time == 0;
4244 }
4245
4246 gboolean
4247 _gdk_x11_moveresize_handle_event (XEvent *event)
4248 {
4249   guint button_mask = 0;
4250   GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
4251   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4252
4253   if (!mv_resize || !mv_resize->moveresize_window)
4254     return FALSE;
4255
4256   button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
4257
4258   switch (event->xany.type)
4259     {
4260     case MotionNotify:
4261       if (mv_resize->moveresize_window->resize_count > 0)
4262         {
4263           if (mv_resize->moveresize_pending_event)
4264             *mv_resize->moveresize_pending_event = *event;
4265           else
4266             mv_resize->moveresize_pending_event =
4267               g_memdup (event, sizeof (XEvent));
4268
4269           break;
4270         }
4271       if (!moveresize_lookahead (mv_resize, event))
4272         break;
4273
4274       update_pos (mv_resize,
4275                   event->xmotion.x_root,
4276                   event->xmotion.y_root);
4277
4278       /* This should never be triggered in normal cases, but in the
4279        * case where the drag started without an implicit grab being
4280        * in effect, we could miss the release if it occurs before
4281        * we grab the pointer; this ensures that we will never
4282        * get a permanently stuck grab.
4283        */
4284       if ((event->xmotion.state & button_mask) == 0)
4285         finish_drag (mv_resize);
4286       break;
4287
4288     case ButtonRelease:
4289       update_pos (mv_resize,
4290                   event->xbutton.x_root,
4291                   event->xbutton.y_root);
4292
4293       if (event->xbutton.button == mv_resize->moveresize_button)
4294         finish_drag (mv_resize);
4295       break;
4296     }
4297   return TRUE;
4298 }
4299
4300 gboolean
4301 _gdk_x11_moveresize_configure_done (GdkDisplay *display,
4302                                     GdkWindow  *window)
4303 {
4304   XEvent *tmp_event;
4305   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4306
4307   if (!mv_resize || window != mv_resize->moveresize_window)
4308     return FALSE;
4309
4310   if (mv_resize->moveresize_pending_event)
4311     {
4312       tmp_event = mv_resize->moveresize_pending_event;
4313       mv_resize->moveresize_pending_event = NULL;
4314       _gdk_x11_moveresize_handle_event (tmp_event);
4315       g_free (tmp_event);
4316     }
4317
4318   return TRUE;
4319 }
4320
4321 static void
4322 create_moveresize_window (MoveResizeData *mv_resize,
4323                           guint32         timestamp)
4324 {
4325   GdkWindowAttr attributes;
4326   gint attributes_mask;
4327   GdkGrabStatus status;
4328
4329   g_assert (mv_resize->moveresize_emulation_window == NULL);
4330
4331   attributes.x = -100;
4332   attributes.y = -100;
4333   attributes.width = 10;
4334   attributes.height = 10;
4335   attributes.window_type = GDK_WINDOW_TEMP;
4336   attributes.wclass = GDK_INPUT_ONLY;
4337   attributes.override_redirect = TRUE;
4338   attributes.event_mask = 0;
4339
4340   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
4341
4342   mv_resize->moveresize_emulation_window = 
4343     gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
4344                     &attributes,
4345                     attributes_mask);
4346
4347   gdk_window_show (mv_resize->moveresize_emulation_window);
4348
4349   status = gdk_pointer_grab (mv_resize->moveresize_emulation_window,
4350                              FALSE,
4351                              GDK_BUTTON_RELEASE_MASK |
4352                              GDK_POINTER_MOTION_MASK,
4353                              NULL,
4354                              NULL,
4355                              timestamp);
4356
4357   if (status != GDK_GRAB_SUCCESS)
4358     {
4359       /* If this fails, some other client has grabbed the window
4360        * already.
4361        */
4362       finish_drag (mv_resize);
4363     }
4364
4365   mv_resize->moveresize_process_time = 0;
4366 }
4367
4368 /* 
4369    Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
4370    so that calling XMoveWindow with these coordinates will not move the 
4371    window.
4372    Note that this depends on the WM to implement ICCCM-compliant reference
4373    point handling.
4374 */
4375 static void 
4376 calculate_unmoving_origin (MoveResizeData *mv_resize)
4377 {
4378   GdkRectangle rect;
4379   gint width, height;
4380
4381   if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
4382       mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
4383     {
4384       gdk_window_get_origin (mv_resize->moveresize_window,
4385                              &mv_resize->moveresize_orig_x,
4386                              &mv_resize->moveresize_orig_y);
4387     }
4388   else
4389     {
4390       gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
4391       gdk_window_get_geometry (mv_resize->moveresize_window, 
4392                                NULL, NULL, &width, &height);
4393       
4394       switch (mv_resize->moveresize_geometry.win_gravity) 
4395         {
4396         case GDK_GRAVITY_NORTH_WEST:
4397           mv_resize->moveresize_orig_x = rect.x;
4398           mv_resize->moveresize_orig_y = rect.y;
4399           break;
4400         case GDK_GRAVITY_NORTH:
4401           mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4402           mv_resize->moveresize_orig_y = rect.y;
4403           break;          
4404         case GDK_GRAVITY_NORTH_EAST:
4405           mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4406           mv_resize->moveresize_orig_y = rect.y;
4407           break;
4408         case GDK_GRAVITY_WEST:
4409           mv_resize->moveresize_orig_x = rect.x;
4410           mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4411           break;
4412         case GDK_GRAVITY_CENTER:
4413           mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4414           mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4415           break;
4416         case GDK_GRAVITY_EAST:
4417           mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4418           mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4419           break;
4420         case GDK_GRAVITY_SOUTH_WEST:
4421           mv_resize->moveresize_orig_x = rect.x;
4422           mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4423           break;
4424         case GDK_GRAVITY_SOUTH:
4425           mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4426           mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4427           break;
4428         case GDK_GRAVITY_SOUTH_EAST:
4429           mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4430           mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4431           break;
4432         default:
4433           mv_resize->moveresize_orig_x = rect.x;
4434           mv_resize->moveresize_orig_y = rect.y;
4435           break; 
4436         }
4437     }  
4438 }
4439
4440 static void
4441 emulate_resize_drag (GdkWindow     *window,
4442                      GdkWindowEdge  edge,
4443                      gint           button,
4444                      gint           root_x,
4445                      gint           root_y,
4446                      guint32        timestamp)
4447 {
4448   MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
4449
4450   mv_resize->is_resize = TRUE;
4451   mv_resize->moveresize_button = button;
4452   mv_resize->resize_edge = edge;
4453   mv_resize->moveresize_x = root_x;
4454   mv_resize->moveresize_y = root_y;
4455   mv_resize->moveresize_window = g_object_ref (window);
4456
4457   mv_resize->moveresize_orig_width = gdk_window_get_width (window);
4458   mv_resize->moveresize_orig_height = gdk_window_get_height (window);
4459
4460   mv_resize->moveresize_geom_mask = 0;
4461   gdk_window_get_geometry_hints (window,
4462                                  &mv_resize->moveresize_geometry,
4463                                  &mv_resize->moveresize_geom_mask);
4464
4465   calculate_unmoving_origin (mv_resize);
4466
4467   create_moveresize_window (mv_resize, timestamp);
4468 }
4469
4470 static void
4471 emulate_move_drag (GdkWindow     *window,
4472                    gint           button,
4473                    gint           root_x,
4474                    gint           root_y,
4475                    guint32        timestamp)
4476 {
4477   MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
4478   
4479   mv_resize->is_resize = FALSE;
4480   mv_resize->moveresize_button = button;
4481   mv_resize->moveresize_x = root_x;
4482   mv_resize->moveresize_y = root_y;
4483
4484   mv_resize->moveresize_window = g_object_ref (window);
4485
4486   calculate_unmoving_origin (mv_resize);
4487
4488   create_moveresize_window (mv_resize, timestamp);
4489 }
4490
4491 static void
4492 gdk_x11_window_begin_resize_drag (GdkWindow     *window,
4493                                   GdkWindowEdge  edge,
4494                                   gint           button,
4495                                   gint           root_x,
4496                                   gint           root_y,
4497                                   guint32        timestamp)
4498 {
4499   if (GDK_WINDOW_DESTROYED (window) ||
4500       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4501     return;
4502
4503   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
4504                                            gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
4505     wmspec_resize_drag (window, edge, button, root_x, root_y, timestamp);
4506   else
4507     emulate_resize_drag (window, edge, button, root_x, root_y, timestamp);
4508 }
4509
4510 static void
4511 gdk_x11_window_begin_move_drag (GdkWindow *window,
4512                                 gint       button,
4513                                 gint       root_x,
4514                                 gint       root_y,
4515                                 guint32    timestamp)
4516 {
4517   if (GDK_WINDOW_DESTROYED (window) ||
4518       !WINDOW_IS_TOPLEVEL (window))
4519     return;
4520
4521   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
4522                                            gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
4523     wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE, root_x, root_y,
4524                        timestamp);
4525   else
4526     emulate_move_drag (window, button, root_x, root_y, timestamp);
4527 }
4528
4529 static void
4530 gdk_x11_window_enable_synchronized_configure (GdkWindow *window)
4531 {
4532   GdkWindowImplX11 *impl;
4533
4534   if (!GDK_IS_WINDOW_IMPL_X11 (window->impl))
4535     return;
4536   
4537   impl = GDK_WINDOW_IMPL_X11 (window->impl);
4538           
4539   if (!impl->use_synchronized_configure)
4540     {
4541       /* This basically means you want to do fancy X specific stuff, so
4542          ensure we have a native window */
4543       gdk_window_ensure_native (window);
4544
4545       impl->use_synchronized_configure = TRUE;
4546       ensure_sync_counter (window);
4547     }
4548 }
4549
4550 static void
4551 gdk_x11_window_configure_finished (GdkWindow *window)
4552 {
4553   GdkWindowImplX11 *impl;
4554
4555   if (!WINDOW_IS_TOPLEVEL (window))
4556     return;
4557   
4558   impl = GDK_WINDOW_IMPL_X11 (window->impl);
4559   if (!impl->use_synchronized_configure)
4560     return;
4561   
4562 #ifdef HAVE_XSYNC
4563   if (!GDK_WINDOW_DESTROYED (window))
4564     {
4565       GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
4566       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
4567
4568       if (toplevel && toplevel->update_counter != None &&
4569           GDK_X11_DISPLAY (display)->use_sync &&
4570           !XSyncValueIsZero (toplevel->current_counter_value))
4571         {
4572           XSyncSetCounter (GDK_WINDOW_XDISPLAY (window), 
4573                            toplevel->update_counter,
4574                            toplevel->current_counter_value);
4575           
4576           XSyncIntToValue (&toplevel->current_counter_value, 0);
4577         }
4578     }
4579 #endif
4580 }
4581
4582 static gboolean
4583 gdk_x11_window_beep (GdkWindow *window)
4584 {
4585   GdkDisplay *display;
4586
4587   display = GDK_WINDOW_DISPLAY (window);
4588
4589 #ifdef HAVE_XKB
4590   if (GDK_X11_DISPLAY (display)->use_xkb)
4591     {
4592       XkbBell (GDK_DISPLAY_XDISPLAY (display),
4593                GDK_WINDOW_XID (window),
4594                0,
4595                None);
4596       return TRUE;
4597     }
4598 #endif
4599
4600   return FALSE;
4601 }
4602
4603 static void
4604 gdk_x11_window_set_opacity (GdkWindow *window,
4605                             gdouble    opacity)
4606 {
4607   GdkDisplay *display;
4608   guint32 cardinal;
4609   
4610   g_return_if_fail (GDK_IS_WINDOW (window));
4611
4612   if (GDK_WINDOW_DESTROYED (window) ||
4613       !WINDOW_IS_TOPLEVEL (window))
4614     return;
4615
4616   display = gdk_window_get_display (window);
4617
4618   if (opacity < 0)
4619     opacity = 0;
4620   else if (opacity > 1)
4621     opacity = 1;
4622
4623   cardinal = opacity * 0xffffffff;
4624
4625   if (cardinal == 0xffffffff)
4626     XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
4627                      GDK_WINDOW_XID (window),
4628                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"));
4629   else
4630     XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
4631                      GDK_WINDOW_XID (window),
4632                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"),
4633                      XA_CARDINAL, 32,
4634                      PropModeReplace,
4635                      (guchar *) &cardinal, 1);
4636 }
4637
4638 static void
4639 gdk_x11_window_set_composited (GdkWindow *window,
4640                                gboolean   composited)
4641 {
4642 #if defined(HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
4643   GdkWindowImplX11 *impl;
4644   GdkDisplay *display;
4645   Display *dpy;
4646   Window xid;
4647
4648   impl = GDK_WINDOW_IMPL_X11 (window->impl);
4649
4650   display = gdk_window_get_display (window);
4651   dpy = GDK_DISPLAY_XDISPLAY (display);
4652   xid = GDK_WINDOW_XID (window);
4653
4654   if (composited)
4655     {
4656       XCompositeRedirectWindow (dpy, xid, CompositeRedirectManual);
4657       impl->damage = XDamageCreate (dpy, xid, XDamageReportBoundingBox);
4658     }
4659   else
4660     {
4661       XCompositeUnredirectWindow (dpy, xid, CompositeRedirectManual);
4662       XDamageDestroy (dpy, impl->damage);
4663       impl->damage = None;
4664     }
4665 #endif
4666 }
4667
4668 static void
4669 gdk_x11_window_process_updates_recurse (GdkWindow      *window,
4670                                         cairo_region_t *region)
4671 {
4672   _gdk_window_process_updates_recurse (window, region);
4673 }
4674
4675 void
4676 _gdk_x11_display_before_process_all_updates (GdkDisplay *display)
4677 {
4678 }
4679
4680 void
4681 _gdk_x11_display_after_process_all_updates (GdkDisplay *display)
4682 {
4683 }
4684
4685 static Bool
4686 timestamp_predicate (Display *display,
4687                      XEvent  *xevent,
4688                      XPointer arg)
4689 {
4690   Window xwindow = GPOINTER_TO_UINT (arg);
4691   GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
4692
4693   if (xevent->type == PropertyNotify &&
4694       xevent->xproperty.window == xwindow &&
4695       xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
4696                                                                        "GDK_TIMESTAMP_PROP"))
4697     return True;
4698
4699   return False;
4700 }
4701
4702 /**
4703  * gdk_x11_get_server_time:
4704  * @window: a #GdkWindow, used for communication with the server.
4705  *          The window must have GDK_PROPERTY_CHANGE_MASK in its
4706  *          events mask or a hang will result.
4707  *
4708  * Routine to get the current X server time stamp.
4709  *
4710  * Return value: the time stamp.
4711  **/
4712 guint32
4713 gdk_x11_get_server_time (GdkWindow *window)
4714 {
4715   Display *xdisplay;
4716   Window   xwindow;
4717   guchar c = 'a';
4718   XEvent xevent;
4719   Atom timestamp_prop_atom;
4720
4721   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
4722   g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
4723
4724   xdisplay = GDK_WINDOW_XDISPLAY (window);
4725   xwindow = GDK_WINDOW_XID (window);
4726   timestamp_prop_atom =
4727     gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
4728                                            "GDK_TIMESTAMP_PROP");
4729
4730   XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
4731                    timestamp_prop_atom,
4732                    8, PropModeReplace, &c, 1);
4733
4734   XIfEvent (xdisplay, &xevent,
4735             timestamp_predicate, GUINT_TO_POINTER(xwindow));
4736
4737   return xevent.xproperty.time;
4738 }
4739
4740 /**
4741  * gdk_x11_window_get_xid: (skip)
4742  * @window: a native #GdkWindow.
4743  * 
4744  * Returns the X resource (window) belonging to a #GdkWindow.
4745  * 
4746  * Return value: the ID of @drawable's X resource.
4747  **/
4748 XID
4749 gdk_x11_window_get_xid (GdkWindow *window)
4750 {
4751   /* Try to ensure the window has a native window */
4752   if (!_gdk_window_has_impl (window))
4753     {
4754       gdk_window_ensure_native (window);
4755
4756       /* We sync here to ensure the window is created in the Xserver when
4757        * this function returns. This is required because the returned XID
4758        * for this window must be valid immediately, even with another
4759        * connection to the Xserver */
4760       gdk_display_sync (gdk_window_get_display (window));
4761     }
4762   
4763   if (!GDK_WINDOW_IS_X11 (window))
4764     {
4765       g_warning (G_STRLOC " drawable is not a native X11 window");
4766       return None;
4767     }
4768   
4769   return GDK_WINDOW_IMPL_X11 (window->impl)->xid;
4770 }
4771
4772 extern GdkDragContext * _gdk_x11_window_drag_begin (GdkWindow *window,
4773                                                     GdkDevice *device,
4774                                                     GList     *targets);
4775
4776 static void
4777 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
4778 {
4779   GObjectClass *object_class = G_OBJECT_CLASS (klass);
4780   GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
4781   
4782   object_class->finalize = gdk_window_impl_x11_finalize;
4783   
4784   impl_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
4785   impl_class->show = gdk_window_x11_show;
4786   impl_class->hide = gdk_window_x11_hide;
4787   impl_class->withdraw = gdk_window_x11_withdraw;
4788   impl_class->set_events = gdk_window_x11_set_events;
4789   impl_class->get_events = gdk_window_x11_get_events;
4790   impl_class->raise = gdk_window_x11_raise;
4791   impl_class->lower = gdk_window_x11_lower;
4792   impl_class->restack_under = gdk_window_x11_restack_under;
4793   impl_class->restack_toplevel = gdk_window_x11_restack_toplevel;
4794   impl_class->move_resize = gdk_window_x11_move_resize;
4795   impl_class->set_background = gdk_window_x11_set_background;
4796   impl_class->reparent = gdk_window_x11_reparent;
4797   impl_class->set_device_cursor = gdk_window_x11_set_device_cursor;
4798   impl_class->get_geometry = gdk_window_x11_get_geometry;
4799   impl_class->get_root_coords = gdk_window_x11_get_root_coords;
4800   impl_class->get_device_state = gdk_window_x11_get_device_state;
4801   impl_class->shape_combine_region = gdk_window_x11_shape_combine_region;
4802   impl_class->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
4803   impl_class->set_static_gravities = gdk_window_x11_set_static_gravities;
4804   impl_class->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
4805   impl_class->translate = _gdk_x11_window_translate;
4806   impl_class->destroy = gdk_x11_window_destroy;
4807   impl_class->destroy_foreign = gdk_x11_window_destroy_foreign;
4808   impl_class->resize_cairo_surface = gdk_window_x11_resize_cairo_surface;
4809   impl_class->get_shape = gdk_x11_window_get_shape;
4810   impl_class->get_input_shape = gdk_x11_window_get_input_shape;
4811   impl_class->beep = gdk_x11_window_beep;
4812
4813   impl_class->focus = gdk_x11_window_focus;
4814   impl_class->set_type_hint = gdk_x11_window_set_type_hint;
4815   impl_class->get_type_hint = gdk_x11_window_get_type_hint;
4816   impl_class->set_modal_hint = gdk_x11_window_set_modal_hint;
4817   impl_class->set_skip_taskbar_hint = gdk_x11_window_set_skip_taskbar_hint;
4818   impl_class->set_skip_pager_hint = gdk_x11_window_set_skip_pager_hint;
4819   impl_class->set_urgency_hint = gdk_x11_window_set_urgency_hint;
4820   impl_class->set_geometry_hints = gdk_x11_window_set_geometry_hints;
4821   impl_class->set_title = gdk_x11_window_set_title;
4822   impl_class->set_role = gdk_x11_window_set_role;
4823   impl_class->set_startup_id = gdk_x11_window_set_startup_id;
4824   impl_class->set_transient_for = gdk_x11_window_set_transient_for;
4825   impl_class->get_root_origin = gdk_x11_window_get_root_origin;
4826   impl_class->get_frame_extents = gdk_x11_window_get_frame_extents;
4827   impl_class->set_override_redirect = gdk_x11_window_set_override_redirect;
4828   impl_class->set_accept_focus = gdk_x11_window_set_accept_focus;
4829   impl_class->set_focus_on_map = gdk_x11_window_set_focus_on_map;
4830   impl_class->set_icon_list = gdk_x11_window_set_icon_list;
4831   impl_class->set_icon_name = gdk_x11_window_set_icon_name;
4832   impl_class->iconify = gdk_x11_window_iconify;
4833   impl_class->deiconify = gdk_x11_window_deiconify;
4834   impl_class->stick = gdk_x11_window_stick;
4835   impl_class->unstick = gdk_x11_window_unstick;
4836   impl_class->maximize = gdk_x11_window_maximize;
4837   impl_class->unmaximize = gdk_x11_window_unmaximize;
4838   impl_class->fullscreen = gdk_x11_window_fullscreen;
4839   impl_class->unfullscreen = gdk_x11_window_unfullscreen;
4840   impl_class->set_keep_above = gdk_x11_window_set_keep_above;
4841   impl_class->set_keep_below = gdk_x11_window_set_keep_below;
4842   impl_class->get_group = gdk_x11_window_get_group;
4843   impl_class->set_group = gdk_x11_window_set_group;
4844   impl_class->set_decorations = gdk_x11_window_set_decorations;
4845   impl_class->get_decorations = gdk_x11_window_get_decorations;
4846   impl_class->set_functions = gdk_x11_window_set_functions;
4847   impl_class->set_functions = gdk_x11_window_set_functions;
4848   impl_class->begin_resize_drag = gdk_x11_window_begin_resize_drag;
4849   impl_class->begin_move_drag = gdk_x11_window_begin_move_drag;
4850   impl_class->enable_synchronized_configure = gdk_x11_window_enable_synchronized_configure;
4851   impl_class->configure_finished = gdk_x11_window_configure_finished;
4852   impl_class->set_opacity = gdk_x11_window_set_opacity;
4853   impl_class->set_composited = gdk_x11_window_set_composited;
4854   impl_class->destroy_notify = gdk_x11_window_destroy_notify;
4855   impl_class->get_drag_protocol = gdk_x11_window_get_drag_protocol;
4856   impl_class->register_dnd = _gdk_x11_window_register_dnd;
4857   impl_class->drag_begin = _gdk_x11_window_drag_begin;
4858   impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;
4859   impl_class->sync_rendering = _gdk_x11_window_sync_rendering;
4860   impl_class->simulate_key = _gdk_x11_window_simulate_key;
4861   impl_class->simulate_button = _gdk_x11_window_simulate_button;
4862   impl_class->get_property = _gdk_x11_window_get_property;
4863   impl_class->change_property = _gdk_x11_window_change_property;
4864   impl_class->delete_property = _gdk_x11_window_delete_property;
4865 }