]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkwindow-x11.c
Do an empty begin_paint_region()/end_paint() for windows without
[~andy/gtk] / gdk / x11 / gdkwindow-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <config.h>
28
29 #include <X11/Xlib.h>
30 #include <X11/Xutil.h>
31 #include <X11/Xatom.h>
32 #include <netinet/in.h>
33 #include <unistd.h>
34 #include "gdk.h"
35
36 #include "gdkwindow.h"
37 #include "gdkasync.h"
38 #include "gdkinputprivate.h"
39 #include "gdkdisplay-x11.h"
40 #include "gdkprivate-x11.h"
41 #include "gdkregion.h"
42 #include "gdkinternals.h"
43 #include "MwmUtil.h"
44 #include "gdkwindow-x11.h"
45
46 #include <stdlib.h>
47 #include <stdio.h>
48 #include <string.h>
49
50
51 #ifdef HAVE_SHAPE_EXT
52 #include <X11/extensions/shape.h>
53 #endif
54
55 const int _gdk_event_mask_table[21] =
56 {
57   ExposureMask,
58   PointerMotionMask,
59   PointerMotionHintMask,
60   ButtonMotionMask,
61   Button1MotionMask,
62   Button2MotionMask,
63   Button3MotionMask,
64   ButtonPressMask,
65   ButtonReleaseMask,
66   KeyPressMask,
67   KeyReleaseMask,
68   EnterWindowMask,
69   LeaveWindowMask,
70   FocusChangeMask,
71   StructureNotifyMask,
72   PropertyChangeMask,
73   VisibilityChangeMask,
74   0,                            /* PROXIMITY_IN */
75   0,                            /* PROXIMTY_OUT */
76   SubstructureNotifyMask,
77   ButtonPressMask      /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
78 };
79 const int _gdk_nenvent_masks = sizeof (_gdk_event_mask_table) / sizeof (int);
80
81 /* Forward declarations */
82 static void     gdk_window_set_static_win_gravity (GdkWindow  *window,
83                                                    gboolean    on);
84 static gboolean gdk_window_have_shape_ext         (GdkDisplay *display);
85 static gboolean gdk_window_icon_name_set          (GdkWindow  *window);
86 static void     gdk_window_add_colormap_windows   (GdkWindow  *window);
87 static void     set_wm_name                       (GdkDisplay  *display,
88                                                    Window       xwindow,
89                                                    const gchar *name);
90
91 static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
92 static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
93                                                       GdkColormap *cmap);
94 static void         gdk_window_impl_x11_get_size    (GdkDrawable *drawable,
95                                                      gint *width,
96                                                      gint *height);
97 static GdkRegion*  gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable);
98 static void gdk_window_impl_x11_init       (GdkWindowImplX11      *window);
99 static void gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass);
100 static void gdk_window_impl_x11_finalize   (GObject            *object);
101
102 static gpointer parent_class = NULL;
103
104 #define WINDOW_IS_TOPLEVEL(window)                 \
105   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
106    GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
107
108 GType
109 gdk_window_impl_x11_get_type (void)
110 {
111   static GType object_type = 0;
112
113   if (!object_type)
114     {
115       static const GTypeInfo object_info =
116       {
117         sizeof (GdkWindowImplX11Class),
118         (GBaseInitFunc) NULL,
119         (GBaseFinalizeFunc) NULL,
120         (GClassInitFunc) gdk_window_impl_x11_class_init,
121         NULL,           /* class_finalize */
122         NULL,           /* class_data */
123         sizeof (GdkWindowImplX11),
124         0,              /* n_preallocs */
125         (GInstanceInitFunc) gdk_window_impl_x11_init,
126       };
127       
128       object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_X11,
129                                             "GdkWindowImplX11",
130                                             &object_info, 0);
131     }
132   
133   return object_type;
134 }
135
136 GType
137 _gdk_window_impl_get_type (void)
138 {
139   return gdk_window_impl_x11_get_type ();
140 }
141
142 static void
143 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
144 {  
145   impl->width = 1;
146   impl->height = 1;
147   impl->toplevel_window_type = -1;
148 }
149
150 GdkToplevelX11 *
151 _gdk_x11_window_get_toplevel (GdkWindow *window)
152 {
153   GdkWindowObject *private;
154   GdkWindowImplX11 *impl;
155   
156   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
157
158   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
159     return NULL;
160
161   private = (GdkWindowObject *)window;
162   impl = GDK_WINDOW_IMPL_X11 (private->impl);
163
164   if (!impl->toplevel)
165     impl->toplevel = g_new0 (GdkToplevelX11, 1);
166
167   return impl->toplevel;
168 }
169
170 static void
171 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
172 {
173   GObjectClass *object_class = G_OBJECT_CLASS (klass);
174   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
175   
176   parent_class = g_type_class_peek_parent (klass);
177
178   object_class->finalize = gdk_window_impl_x11_finalize;
179
180   drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
181   drawable_class->get_colormap = gdk_window_impl_x11_get_colormap;
182   drawable_class->get_size = gdk_window_impl_x11_get_size;
183
184   /* Visible and clip regions are the same */
185   drawable_class->get_clip_region = gdk_window_impl_x11_get_visible_region;
186   drawable_class->get_visible_region = gdk_window_impl_x11_get_visible_region;
187 }
188
189 static void
190 gdk_window_impl_x11_finalize (GObject *object)
191 {
192   GdkWindowObject *wrapper;
193   GdkDrawableImplX11 *draw_impl;
194   GdkWindowImplX11 *window_impl;
195   
196   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
197
198   draw_impl = GDK_DRAWABLE_IMPL_X11 (object);
199   window_impl = GDK_WINDOW_IMPL_X11 (object);
200   
201   wrapper = (GdkWindowObject*) draw_impl->wrapper;
202
203   _gdk_xgrab_check_destroy (GDK_WINDOW (wrapper));
204
205   if (!GDK_WINDOW_DESTROYED (wrapper))
206     {
207       GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
208       
209       _gdk_xid_table_remove (display, draw_impl->xid);
210       if (window_impl->toplevel && window_impl->toplevel->focus_window)
211         _gdk_xid_table_remove (display, window_impl->toplevel->focus_window);
212     }
213
214   if (window_impl->toplevel)
215     g_free (window_impl->toplevel);
216
217   G_OBJECT_CLASS (parent_class)->finalize (object);
218 }
219
220 static void
221 tmp_unset_bg (GdkWindow *window)
222 {
223   GdkWindowImplX11 *impl;
224   GdkWindowObject *obj;
225
226   obj = (GdkWindowObject *) window;
227   impl = GDK_WINDOW_IMPL_X11 (obj->impl);
228
229   impl->position_info.no_bg = TRUE;
230
231   if (obj->bg_pixmap != GDK_NO_BG)
232     XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
233                                 GDK_DRAWABLE_XID (window), None);
234 }
235
236 static void
237 tmp_reset_bg (GdkWindow *window)
238 {
239   GdkWindowImplX11 *impl;
240   GdkWindowObject *obj;
241
242   obj = (GdkWindowObject *) window;
243   impl = GDK_WINDOW_IMPL_X11 (obj->impl);
244
245   impl->position_info.no_bg = FALSE;
246
247   if (obj->bg_pixmap == GDK_NO_BG)
248     return;
249   
250   if (obj->bg_pixmap)
251     {
252       Pixmap xpixmap;
253
254       if (obj->bg_pixmap == GDK_PARENT_RELATIVE_BG)
255         xpixmap = ParentRelative;
256       else 
257         xpixmap = GDK_DRAWABLE_XID (obj->bg_pixmap);
258
259       XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
260                                   GDK_DRAWABLE_XID (window), xpixmap);
261     }
262   else
263     {
264       XSetWindowBackground (GDK_DRAWABLE_XDISPLAY (window),
265                             GDK_DRAWABLE_XID (window),
266                             obj->bg_color.pixel);
267     }
268 }
269
270 void
271 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
272                               gboolean   recurse)
273 {
274   GdkWindowObject *private;
275
276   g_return_if_fail (GDK_IS_WINDOW (window));
277   
278   private = (GdkWindowObject *)window;
279
280   if (private->input_only || private->destroyed ||
281       (private->window_type != GDK_WINDOW_ROOT &&
282        !GDK_WINDOW_IS_MAPPED (window)))
283     {
284       return;
285     }
286
287   if (private->window_type != GDK_WINDOW_ROOT &&
288       private->window_type != GDK_WINDOW_FOREIGN)
289     {
290       tmp_unset_bg (window);
291     }
292
293   if (recurse)
294     {
295       GList *l;
296
297       for (l = private->children; l != NULL; l = l->next)
298         _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
299     }
300 }
301
302 void
303 _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
304                               gboolean   recurse)
305 {
306   GdkWindowObject *private;
307
308   g_return_if_fail (GDK_IS_WINDOW (window));
309
310   private = (GdkWindowObject *)window;
311
312   if (private->input_only || private->destroyed ||
313       (private->window_type != GDK_WINDOW_ROOT &&
314        !GDK_WINDOW_IS_MAPPED (window)))
315     {
316       return;
317     }
318
319   if (private->window_type != GDK_WINDOW_ROOT &&
320       private->window_type != GDK_WINDOW_FOREIGN)
321     {
322       tmp_reset_bg (window);
323     }
324
325   if (recurse)
326     {
327       GList *l;
328
329       for (l = private->children; l != NULL; l = l->next)
330         _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
331     }
332 }
333
334 static GdkColormap*
335 gdk_window_impl_x11_get_colormap (GdkDrawable *drawable)
336 {
337   GdkDrawableImplX11 *drawable_impl;
338   GdkWindowImplX11 *window_impl;
339   
340   g_return_val_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable), NULL);
341
342   drawable_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
343   window_impl = GDK_WINDOW_IMPL_X11 (drawable);
344
345   if (!((GdkWindowObject *) drawable_impl->wrapper)->input_only && 
346       drawable_impl->colormap == NULL)
347     {
348       XWindowAttributes window_attributes;
349       GdkVisual *visual;
350
351       XGetWindowAttributes (GDK_SCREEN_XDISPLAY (drawable_impl->screen),
352                             drawable_impl->xid,
353                             &window_attributes);
354
355       visual = gdk_x11_screen_lookup_visual (drawable_impl->screen,
356                                              window_attributes.visual->visualid);
357       drawable_impl->colormap = gdk_x11_colormap_foreign_new (visual,
358                                                               window_attributes.colormap);
359     }
360   
361   return drawable_impl->colormap;
362 }
363
364 static void
365 gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
366                                   GdkColormap *cmap)
367 {
368   GdkWindowImplX11 *impl;
369   GdkDrawableImplX11 *draw_impl;
370   
371   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
372
373   impl = GDK_WINDOW_IMPL_X11 (drawable);
374   draw_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
375
376   if (cmap && GDK_WINDOW_DESTROYED (draw_impl->wrapper))
377     return;
378
379   /* chain up */
380   GDK_DRAWABLE_CLASS (parent_class)->set_colormap (drawable, cmap);
381
382   if (cmap)
383     {
384       XSetWindowColormap (GDK_SCREEN_XDISPLAY (draw_impl->screen),
385                           draw_impl->xid,
386                           GDK_COLORMAP_XCOLORMAP (cmap));
387
388       if (((GdkWindowObject*)draw_impl->wrapper)->window_type !=
389           GDK_WINDOW_TOPLEVEL)
390         gdk_window_add_colormap_windows (GDK_WINDOW (draw_impl->wrapper));
391     }
392 }
393
394
395 static void
396 gdk_window_impl_x11_get_size (GdkDrawable *drawable,
397                               gint        *width,
398                               gint        *height)
399 {
400   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
401
402   if (width)
403     *width = GDK_WINDOW_IMPL_X11 (drawable)->width;
404   if (height)
405     *height = GDK_WINDOW_IMPL_X11 (drawable)->height;
406 }
407
408 static GdkRegion*
409 gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable)
410 {
411   GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (drawable);
412   GdkRectangle result_rect;
413
414   result_rect.x = 0;
415   result_rect.y = 0;
416   result_rect.width = impl->width;
417   result_rect.height = impl->height;
418
419   gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
420
421   return gdk_region_rectangle (&result_rect);
422 }
423
424 void
425 _gdk_windowing_window_init (GdkScreen * screen)
426 {
427   GdkWindowObject *private;
428   GdkWindowImplX11 *impl;
429   GdkDrawableImplX11 *draw_impl;
430   GdkScreenX11 *screen_x11;
431
432   screen_x11 = GDK_SCREEN_X11 (screen);
433
434   g_assert (screen_x11->root_window == NULL);
435
436   gdk_screen_set_default_colormap (screen,
437                                    gdk_screen_get_system_colormap (screen));
438
439   screen_x11->root_window = g_object_new (GDK_TYPE_WINDOW, NULL);
440   private = (GdkWindowObject *)screen_x11->root_window;
441   impl = GDK_WINDOW_IMPL_X11 (private->impl);
442   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
443   
444   draw_impl->screen = screen;
445   draw_impl->xid = screen_x11->xroot_window;
446   draw_impl->wrapper = GDK_DRAWABLE (private);
447   draw_impl->colormap = gdk_screen_get_system_colormap (screen);
448   g_object_ref (draw_impl->colormap);
449   
450   private->window_type = GDK_WINDOW_ROOT;
451   private->depth = DefaultDepthOfScreen (screen_x11->xscreen);
452   
453   impl->width = WidthOfScreen (screen_x11->xscreen);
454   impl->height = HeightOfScreen (screen_x11->xscreen);
455   
456   _gdk_window_init_position (GDK_WINDOW (private));
457
458   _gdk_xid_table_insert (screen_x11->display,
459                          &screen_x11->xroot_window,
460                          screen_x11->root_window);
461 }
462
463 static void
464 set_wm_protocols (GdkWindow *window)
465 {
466   GdkDisplay *display = gdk_drawable_get_display (window);
467   Atom protocols[4];
468   int n = 0;
469   
470   protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
471   protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
472   protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
473
474 #ifdef HAVE_XSYNC
475   if (GDK_DISPLAY_X11 (display)->use_sync)
476     protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
477 #endif
478   
479   XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
480 }
481
482 static const gchar *
483 get_default_title (void)
484 {
485   const char *title;
486
487   title = g_get_application_name ();
488   if (!title)
489     title = g_get_prgname ();
490
491   return title;
492 }
493
494 static void
495 check_leader_window_title (GdkDisplay *display)
496 {
497   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
498
499   if (display_x11->leader_window && !display_x11->leader_window_title_set)
500     {
501       set_wm_name (display,
502                    display_x11->leader_window,
503                    get_default_title ());
504       
505       display_x11->leader_window_title_set = TRUE;
506     }
507 }
508
509 static Window
510 create_focus_window (Display *xdisplay,
511                      XID      parent)
512 {
513   Window focus_window = XCreateSimpleWindow (xdisplay, parent,
514                                              -1, -1, 1, 1, 0,
515                                              0, 0);
516   
517   /* FIXME: probably better to actually track the requested event mask for the toplevel
518    */
519   XSelectInput (xdisplay, focus_window,
520                 KeyPressMask | KeyReleaseMask | FocusChangeMask);
521   
522   XMapWindow (xdisplay, focus_window);
523
524   return focus_window;
525 }
526
527 static void
528 setup_toplevel_window (GdkWindow *window, 
529                        GdkWindow *parent)
530 {
531   GdkWindowObject *obj = (GdkWindowObject *)window;
532   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
533   GdkWindowImplX11 *impl = (GdkWindowImplX11 *)obj->impl;
534   Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
535   XID xid = GDK_WINDOW_XID (window);
536   XID xparent = GDK_WINDOW_XID (parent);
537   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (parent));
538   XSizeHints size_hints;
539   long pid;
540     
541   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_DIALOG)
542     XSetTransientForHint (xdisplay, xid, xparent);
543   
544   set_wm_protocols (window);
545   
546   if (!obj->input_only)
547     {
548       /* The focus window is off the visible area, and serves to receive key
549        * press events so they don't get sent to child windows.
550        */
551       toplevel->focus_window = create_focus_window (xdisplay, xid);
552       _gdk_xid_table_insert (screen_x11->display, &toplevel->focus_window, window);
553     }
554   
555   check_leader_window_title (screen_x11->display);
556   
557   /* FIXME: Is there any point in doing this? Do any WM's pay
558    * attention to PSize, and even if they do, is this the
559    * correct value???
560    */
561   size_hints.flags = PSize;
562   size_hints.width = impl->width;
563   size_hints.height = impl->height;
564   
565   XSetWMNormalHints (xdisplay, xid, &size_hints);
566   
567   /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
568   XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
569   
570   pid = getpid ();
571   XChangeProperty (xdisplay, xid,
572                    gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "_NET_WM_PID"),
573                    XA_CARDINAL, 32,
574                    PropModeReplace,
575                    (guchar *)&pid, 1);
576   
577   XChangeProperty (xdisplay, xid, 
578                    gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "WM_CLIENT_LEADER"),
579                    XA_WINDOW, 32, PropModeReplace,
580                    (guchar *) &GDK_DISPLAY_X11 (screen_x11->display)->leader_window, 1);
581
582   if (!obj->focus_on_map)
583     gdk_x11_window_set_user_time (window, 0);
584   else if (GDK_DISPLAY_X11 (screen_x11->display)->user_time != 0)
585     gdk_x11_window_set_user_time (window, GDK_DISPLAY_X11 (screen_x11->display)->user_time);
586 }
587
588 /**
589  * gdk_window_new:
590  * @parent: a #GdkWindow, or %NULL to create the window as a child of
591  *   the default root window for the default display.
592  * @attributes: attributes of the new window
593  * @attributes_mask: mask indicating which fields in @attributes are valid
594  * 
595  * Creates a new #GdkWindow using the attributes from
596  * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
597  * more details.  Note: to use this on displays other than the default
598  * display, @parent must be specified.
599  * 
600  * Return value: the new #GdkWindow
601  **/
602 GdkWindow*
603 gdk_window_new (GdkWindow     *parent,
604                 GdkWindowAttr *attributes,
605                 gint           attributes_mask)
606 {
607   GdkWindow *window;
608   GdkWindowObject *private;
609   GdkWindowImplX11 *impl;
610   GdkDrawableImplX11 *draw_impl;
611   GdkScreenX11 *screen_x11;
612   GdkScreen *screen;
613   
614   GdkVisual *visual;
615   Window xparent;
616   Visual *xvisual;
617   Display *xdisplay;
618   Window xid;
619
620   XSetWindowAttributes xattributes;
621   long xattributes_mask;
622   XClassHint *class_hint;
623   int x, y, depth;
624   
625   unsigned int class;
626   const char *title;
627   int i;
628   
629   g_return_val_if_fail (attributes != NULL, NULL);
630   
631   if (!parent)
632     {
633       GDK_NOTE (MULTIHEAD,
634                 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
635       
636       screen = gdk_screen_get_default ();
637       parent = gdk_screen_get_root_window (screen);
638     }
639   else
640     screen = gdk_drawable_get_screen (parent);
641
642   screen_x11 = GDK_SCREEN_X11 (screen);
643
644   g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
645   
646   if (GDK_WINDOW_DESTROYED (parent))
647     return NULL;
648   
649   xparent = GDK_WINDOW_XID (parent);
650   
651   window = g_object_new (GDK_TYPE_WINDOW, NULL);
652   private = (GdkWindowObject *)window;
653   impl = GDK_WINDOW_IMPL_X11 (private->impl);
654   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
655   draw_impl->wrapper = GDK_DRAWABLE (window);
656   
657   draw_impl->screen = screen;
658   xdisplay = screen_x11->xdisplay;
659
660   /* Windows with a foreign parent are treated as if they are children
661    * of the root window, except for actual creation.
662    */
663   if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
664     parent = gdk_screen_get_root_window (screen);
665   
666   private->parent = (GdkWindowObject *)parent;
667
668   private->accept_focus = TRUE;
669   private->focus_on_map = TRUE;
670
671   xattributes_mask = 0;
672   
673   if (attributes_mask & GDK_WA_X)
674     x = attributes->x;
675   else
676     x = 0;
677   
678   if (attributes_mask & GDK_WA_Y)
679     y = attributes->y;
680   else
681     y = 0;
682   
683   private->x = x;
684   private->y = y;
685   impl->width = (attributes->width > 1) ? (attributes->width) : (1);
686   impl->height = (attributes->height > 1) ? (attributes->height) : (1);
687
688   if (attributes->wclass == GDK_INPUT_ONLY)
689     {
690       /* Backwards compatiblity - we've always ignored
691        * attributes->window_type for input-only windows
692        * before
693        */
694       if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
695         private->window_type = GDK_WINDOW_TEMP;
696       else
697         private->window_type = GDK_WINDOW_CHILD;
698     }
699   else
700     private->window_type = attributes->window_type;
701
702   _gdk_window_init_position (GDK_WINDOW (private));
703   if (impl->position_info.big)
704     private->guffaw_gravity = TRUE;
705   
706   if (attributes_mask & GDK_WA_VISUAL)
707     visual = attributes->visual;
708   else
709     visual = gdk_screen_get_system_visual (screen);
710   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
711   
712   xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
713   for (i = 0; i < _gdk_nenvent_masks; i++)
714     {
715       if (attributes->event_mask & (1 << (i + 1)))
716         xattributes.event_mask |= _gdk_event_mask_table[i];
717     }
718   private->event_mask = attributes->event_mask;
719   
720   if (xattributes.event_mask)
721     xattributes_mask |= CWEventMask;
722   
723   if (attributes_mask & GDK_WA_NOREDIR)
724     {
725       xattributes.override_redirect =
726         (attributes->override_redirect == FALSE)?False:True;
727       xattributes_mask |= CWOverrideRedirect;
728     } 
729   else
730     xattributes.override_redirect = False;
731
732   impl->override_redirect = xattributes.override_redirect;
733   
734   if (private->parent && private->parent->guffaw_gravity)
735     {
736       xattributes.win_gravity = StaticGravity;
737       xattributes_mask |= CWWinGravity;
738     }
739   
740   /* Sanity checks */
741   switch (private->window_type)
742     {
743     case GDK_WINDOW_TOPLEVEL:
744     case GDK_WINDOW_DIALOG:
745     case GDK_WINDOW_TEMP:
746       if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
747         {
748           g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
749                      "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
750           xparent = GDK_SCREEN_XROOTWIN (screen);
751         }
752     case GDK_WINDOW_CHILD:
753       break;
754     default:
755       g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
756       return NULL;
757     }
758           
759   if (attributes->wclass == GDK_INPUT_OUTPUT)
760     {
761       class = InputOutput;
762       depth = visual->depth;
763
764       private->input_only = FALSE;
765       private->depth = depth;
766       
767       if (attributes_mask & GDK_WA_COLORMAP)
768         {
769           draw_impl->colormap = attributes->colormap;
770           g_object_ref (attributes->colormap);
771         }
772       else
773         {
774           if ((((GdkVisualPrivate *)gdk_screen_get_system_visual (screen))->xvisual) ==  xvisual)
775             {
776               draw_impl->colormap = gdk_screen_get_system_colormap (screen);
777               g_object_ref (draw_impl->colormap);
778             }
779           else
780             {
781               draw_impl->colormap = gdk_colormap_new (visual, FALSE);
782             }
783         }
784       
785       private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num);
786       xattributes.background_pixel = private->bg_color.pixel;
787
788       private->bg_pixmap = NULL;
789       
790       xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
791       xattributes_mask |= CWBorderPixel | CWBackPixel;
792
793       if (private->guffaw_gravity)
794         xattributes.bit_gravity = StaticGravity;
795       else
796         xattributes.bit_gravity = NorthWestGravity;
797       
798       xattributes_mask |= CWBitGravity;
799
800       xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
801       xattributes_mask |= CWColormap;
802
803       if (private->window_type == GDK_WINDOW_TEMP)
804         {
805           xattributes.save_under = True;
806           xattributes.override_redirect = True;
807           xattributes.cursor = None;
808           xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
809
810           impl->override_redirect = TRUE;
811         }
812     }
813   else
814     {
815       depth = 0;
816       private->depth = 0;
817       class = InputOnly;
818       private->input_only = TRUE;
819       draw_impl->colormap = gdk_screen_get_system_colormap (screen);
820       g_object_ref (draw_impl->colormap);
821     }
822
823   xid = draw_impl->xid = XCreateWindow (xdisplay, xparent,
824                                         impl->position_info.x, impl->position_info.y,
825                                         impl->position_info.width, impl->position_info.height,
826                                         0, depth, class, xvisual,
827                                         xattributes_mask, &xattributes);
828
829   g_object_ref (window);
830   _gdk_xid_table_insert (screen_x11->display, &draw_impl->xid, window);
831   
832   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
833                                   (attributes->cursor) :
834                                   NULL));
835   
836   if (private->parent)
837     private->parent->children = g_list_prepend (private->parent->children, window);
838   
839   switch (GDK_WINDOW_TYPE (private))
840     {
841     case GDK_WINDOW_DIALOG:
842     case GDK_WINDOW_TOPLEVEL:
843     case GDK_WINDOW_TEMP:
844       if (attributes_mask & GDK_WA_TITLE)
845         title = attributes->title;
846       else
847         title = get_default_title ();
848       
849       gdk_window_set_title (window, title);
850       
851       if (attributes_mask & GDK_WA_WMCLASS)
852         {
853           class_hint = XAllocClassHint ();
854           class_hint->res_name = attributes->wmclass_name;
855           class_hint->res_class = attributes->wmclass_class;
856           XSetClassHint (xdisplay, xid, class_hint);
857           XFree (class_hint);
858         }
859   
860       setup_toplevel_window (window, parent);
861       break;
862
863     case GDK_WINDOW_CHILD:
864       if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
865           (draw_impl->colormap != gdk_screen_get_system_colormap (screen)) &&
866           (draw_impl->colormap != gdk_drawable_get_colormap (gdk_window_get_toplevel (window))))
867         {
868           GDK_NOTE (MISC, g_message ("adding colormap window\n"));
869           gdk_window_add_colormap_windows (window);
870         }
871       break;
872       
873     default:
874       break;
875     }
876
877   return window;
878 }
879
880 static GdkEventMask
881 x_event_mask_to_gdk_event_mask (long mask)
882 {
883   GdkEventMask event_mask = 0;
884   int i;
885
886   for (i = 0; i < _gdk_nenvent_masks; i++)
887     {
888       if (mask & _gdk_event_mask_table[i])
889         event_mask |= 1 << (i + 1);
890     }
891
892   return event_mask;
893 }
894
895 /**
896  * gdk_window_foreign_new_for_display:
897  * @display: the #GdkDisplay where the window handle comes from.
898  * @anid: a native window handle.
899  * 
900  * Wraps a native window in a #GdkWindow.
901  * This may fail if the window has been destroyed.
902  *
903  * For example in the X backend, a native window handle is an Xlib
904  * <type>XID</type>.
905  * 
906  * Return value: the newly-created #GdkWindow wrapper for the 
907  *    native window or %NULL if the window has been destroyed.
908  *
909  * Since: 2.2
910  **/
911 GdkWindow *
912 gdk_window_foreign_new_for_display (GdkDisplay     *display,
913                                     GdkNativeWindow anid)
914 {
915   GdkWindow *window;
916   GdkWindowObject *private;
917   GdkWindowImplX11 *impl;
918   GdkDrawableImplX11 *draw_impl;
919   GdkDisplayX11 *display_x11;
920   XWindowAttributes attrs;
921   Window root, parent;
922   Window *children = NULL;
923   guint nchildren;
924   gboolean result;
925
926   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
927
928   display_x11 = GDK_DISPLAY_X11 (display);
929   
930   gdk_error_trap_push ();
931   result = XGetWindowAttributes (display_x11->xdisplay, anid, &attrs);
932   if (gdk_error_trap_pop () || !result)
933     return NULL;
934
935   /* FIXME: This is pretty expensive. Maybe the caller should supply
936    *        the parent */
937   gdk_error_trap_push ();
938   result = XQueryTree (display_x11->xdisplay, anid, &root, &parent, &children, &nchildren);
939   if (gdk_error_trap_pop () || !result)
940     return NULL;
941
942   if (children)
943     XFree (children);
944   
945   window = g_object_new (GDK_TYPE_WINDOW, NULL);
946   private = (GdkWindowObject *)window;
947   impl = GDK_WINDOW_IMPL_X11 (private->impl);
948   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
949   draw_impl->wrapper = GDK_DRAWABLE (window);
950   draw_impl->screen = _gdk_x11_display_screen_for_xrootwin (display, root);
951   
952   private->parent = gdk_xid_table_lookup_for_display (display, parent);
953   
954   if (!private->parent || GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_FOREIGN)
955     private->parent = (GdkWindowObject *) gdk_screen_get_root_window (draw_impl->screen);
956   
957   private->parent->children = g_list_prepend (private->parent->children, window);
958
959   draw_impl->xid = anid;
960
961   private->x = attrs.x;
962   private->y = attrs.y;
963   impl->width = attrs.width;
964   impl->height = attrs.height;
965   private->window_type = GDK_WINDOW_FOREIGN;
966   private->destroyed = FALSE;
967
968   private->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
969
970   if (attrs.map_state == IsUnmapped)
971     private->state = GDK_WINDOW_STATE_WITHDRAWN;
972   else
973     private->state = 0;
974
975   private->depth = attrs.depth;
976   
977   _gdk_window_init_position (GDK_WINDOW (private));
978
979   g_object_ref (window);
980   _gdk_xid_table_insert (display, &GDK_WINDOW_XID (window), window);
981   return window;
982 }
983
984 /**
985  * gdk_window_lookup_for_display:
986  * @display: the #GdkDisplay corresponding to the window handle
987  * @anid: a native window handle.
988  *
989  * Looks up the #GdkWindow that wraps the given native window handle.
990  *
991  * For example in the X backend, a native window handle is an Xlib
992  * <type>XID</type>.
993  *
994  * Return value: the #GdkWindow wrapper for the native window, 
995  *    or %NULL if there is none.
996  *
997  * Since: 2.2
998  **/
999 GdkWindow *
1000 gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
1001 {
1002   return (GdkWindow*) gdk_xid_table_lookup_for_display (display, anid);
1003 }
1004
1005 /**
1006  * gdk_window_lookup:
1007  * @anid: a native window handle.
1008  *
1009  * Looks up the #GdkWindow that wraps the given native window handle. 
1010  *
1011  * For example in the X backend, a native window handle is an Xlib
1012  * <type>XID</type>.
1013  *
1014  * Return value: the #GdkWindow wrapper for the native window, 
1015  *    or %NULL if there is none.
1016  **/
1017 GdkWindow *
1018 gdk_window_lookup (GdkNativeWindow anid)
1019 {
1020   return (GdkWindow*) gdk_xid_table_lookup (anid);
1021 }
1022
1023 static void
1024 gdk_toplevel_x11_free_contents (GdkDisplay *display,
1025                                 GdkToplevelX11 *toplevel)
1026 {
1027   if (toplevel->icon_window)
1028     {
1029       g_object_unref (toplevel->icon_window);
1030       toplevel->icon_window = NULL;
1031     }
1032   if (toplevel->icon_pixmap)
1033     {
1034       g_object_unref (toplevel->icon_pixmap);
1035       toplevel->icon_pixmap = NULL;
1036     }
1037   if (toplevel->icon_mask)
1038     {
1039       g_object_unref (toplevel->icon_mask);
1040       toplevel->icon_mask = NULL;
1041     }
1042   if (toplevel->group_leader)
1043     {
1044       g_object_unref (toplevel->group_leader);
1045       toplevel->group_leader = NULL;
1046     }
1047 #ifdef HAVE_XSYNC
1048   if (toplevel->update_counter != None)
1049     {
1050       XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display), 
1051                            toplevel->update_counter);
1052       toplevel->update_counter = None;
1053
1054       XSyncIntToValue (&toplevel->current_counter_value, 0);
1055       XSyncIntToValue (&toplevel->pending_counter_value, 0);
1056     }
1057 #endif
1058 }
1059
1060 void
1061 _gdk_windowing_window_destroy (GdkWindow *window,
1062                                gboolean   recursing,
1063                                gboolean   foreign_destroy)
1064 {
1065   GdkWindowObject *private = (GdkWindowObject *)window;
1066   GdkToplevelX11 *toplevel;
1067   GdkDrawableImplX11 *draw_impl;
1068   
1069   g_return_if_fail (GDK_IS_WINDOW (window));
1070
1071   _gdk_selection_window_destroyed (window);
1072   
1073   if (private->extension_events != 0)
1074     _gdk_input_window_destroy (window);
1075
1076   toplevel = _gdk_x11_window_get_toplevel (window);
1077   if (toplevel)
1078     gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
1079
1080   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
1081     
1082   if (draw_impl->xft_draw)
1083     XftDrawDestroy (draw_impl->xft_draw);
1084
1085   if (!recursing && !foreign_destroy)
1086     {
1087       XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1088     }
1089 }
1090
1091 void
1092 _gdk_windowing_window_destroy_foreign (GdkWindow *window)
1093 {
1094   /* It's somebody else's window, but in our heirarchy,
1095    * so reparent it to the root window, and then send
1096    * it a delete event, as if we were a WM
1097    */
1098   XClientMessageEvent xevent;
1099   
1100   gdk_error_trap_push ();
1101   gdk_window_hide (window);
1102   gdk_window_reparent (window, NULL, 0, 0);
1103   
1104   xevent.type = ClientMessage;
1105   xevent.window = GDK_WINDOW_XID (window);
1106   xevent.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
1107                                                                "WM_PROTOCOLS");
1108   xevent.format = 32;
1109   xevent.data.l[0] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
1110                                                             "WM_DELETE_WINDOW");
1111   xevent.data.l[1] = CurrentTime;
1112   xevent.data.l[2] = 0;
1113   xevent.data.l[3] = 0;
1114   xevent.data.l[4] = 0;
1115   
1116   XSendEvent (GDK_WINDOW_XDISPLAY (window),
1117               GDK_WINDOW_XID (window),
1118               False, 0, (XEvent *)&xevent);
1119   gdk_display_sync (GDK_WINDOW_DISPLAY (window));
1120   gdk_error_trap_pop ();
1121 }
1122
1123 static GdkWindow *
1124 get_root (GdkWindow *window)
1125 {
1126   GdkScreen *screen = gdk_drawable_get_screen (window);
1127
1128   return gdk_screen_get_root_window (screen);
1129 }
1130
1131 /* This function is called when the XWindow is really gone.
1132  */
1133 void
1134 gdk_window_destroy_notify (GdkWindow *window)
1135 {
1136   GdkWindowImplX11 *window_impl;
1137
1138   g_return_if_fail (window != NULL);
1139   
1140   window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
1141
1142   if (!GDK_WINDOW_DESTROYED (window))
1143     {
1144       if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1145         g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
1146
1147       _gdk_window_destroy (window, TRUE);
1148     }
1149   
1150   _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
1151   if (window_impl->toplevel && window_impl->toplevel->focus_window)
1152     _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
1153
1154   _gdk_xgrab_check_destroy (window);
1155   
1156   g_object_unref (window);
1157 }
1158
1159 static void
1160 update_wm_hints (GdkWindow *window,
1161                  gboolean   force)
1162 {
1163   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
1164   GdkWindowObject *private = (GdkWindowObject *)window;
1165   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1166   XWMHints wm_hints;
1167
1168   if (!force &&
1169       private->state & GDK_WINDOW_STATE_WITHDRAWN)
1170     return;
1171
1172   wm_hints.flags = StateHint | InputHint;
1173   wm_hints.input = private->accept_focus ? True : False;
1174   wm_hints.initial_state = NormalState;
1175   
1176   if (private->state & GDK_WINDOW_STATE_ICONIFIED)
1177     {
1178       wm_hints.flags |= StateHint;
1179       wm_hints.initial_state = IconicState;
1180     }
1181
1182   if (toplevel->icon_window && !GDK_WINDOW_DESTROYED (toplevel->icon_window))
1183     {
1184       wm_hints.flags |= IconWindowHint;
1185       wm_hints.icon_window = GDK_WINDOW_XID (toplevel->icon_window);
1186     }
1187
1188   if (toplevel->icon_pixmap)
1189     {
1190       wm_hints.flags |= IconPixmapHint;
1191       wm_hints.icon_pixmap = GDK_PIXMAP_XID (toplevel->icon_pixmap);
1192     }
1193
1194   if (toplevel->icon_mask)
1195     {
1196       wm_hints.flags |= IconMaskHint;
1197       wm_hints.icon_mask = GDK_PIXMAP_XID (toplevel->icon_mask);
1198     }
1199   
1200   wm_hints.flags |= WindowGroupHint;
1201   if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
1202     {
1203       wm_hints.flags |= WindowGroupHint;
1204       wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
1205     }
1206   else
1207     wm_hints.window_group = GDK_DISPLAY_X11 (display)->leader_window;
1208   
1209   XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1210                GDK_WINDOW_XID (window),
1211                &wm_hints);
1212 }
1213
1214 static void
1215 set_initial_hints (GdkWindow *window)
1216 {
1217   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1218   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1219   Window xwindow = GDK_WINDOW_XID (window);  
1220   GdkWindowObject *private;
1221   GdkToplevelX11 *toplevel;
1222   Atom atoms[7];
1223   gint i;
1224
1225   private = (GdkWindowObject*) window;
1226   toplevel = _gdk_x11_window_get_toplevel (window);
1227
1228   if (!toplevel)
1229     return;
1230
1231   update_wm_hints (window, TRUE);
1232   
1233   /* We set the spec hints regardless of whether the spec is supported,
1234    * since it can't hurt and it's kind of expensive to check whether
1235    * it's supported.
1236    */
1237   
1238   i = 0;
1239
1240   if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
1241     {
1242       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1243                                                         "_NET_WM_STATE_MAXIMIZED_VERT");
1244       ++i;
1245       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1246                                                         "_NET_WM_STATE_MAXIMIZED_HORZ");
1247       ++i;
1248     }
1249
1250   if (private->state & GDK_WINDOW_STATE_ABOVE)
1251     {
1252       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1253                                                         "_NET_WM_STATE_ABOVE");
1254       ++i;
1255     }
1256   
1257   if (private->state & GDK_WINDOW_STATE_BELOW)
1258     {
1259       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1260                                                         "_NET_WM_STATE_BELOW");
1261       ++i;
1262     }
1263   
1264   if (private->state & GDK_WINDOW_STATE_STICKY)
1265     {
1266       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1267                                                         "_NET_WM_STATE_STICKY");
1268       ++i;
1269     }
1270
1271   if (private->state & GDK_WINDOW_STATE_FULLSCREEN)
1272     {
1273       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1274                                                         "_NET_WM_STATE_FULLSCREEN");
1275       ++i;
1276     }
1277
1278   if (private->modal_hint)
1279     {
1280       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1281                                                         "_NET_WM_STATE_MODAL");
1282       ++i;
1283     }
1284
1285   if (toplevel->skip_taskbar_hint)
1286     {
1287       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1288                                                         "_NET_WM_STATE_SKIP_TASKBAR");
1289       ++i;
1290     }
1291
1292   if (toplevel->skip_pager_hint)
1293     {
1294       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1295                                                         "_NET_WM_STATE_SKIP_PAGER");
1296       ++i;
1297     }
1298
1299   if (i > 0)
1300     {
1301       XChangeProperty (xdisplay,
1302                        xwindow,
1303                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
1304                        XA_ATOM, 32, PropModeReplace,
1305                        (guchar*) atoms, i);
1306     }
1307   else 
1308     {
1309       XDeleteProperty (xdisplay,
1310                        xwindow,
1311                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
1312     }
1313
1314   if (private->state & GDK_WINDOW_STATE_STICKY)
1315     {
1316       atoms[0] = 0xFFFFFFFF;
1317       XChangeProperty (xdisplay,
1318                        xwindow,
1319                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
1320                        XA_CARDINAL, 32, PropModeReplace,
1321                        (guchar*) atoms, 1);
1322     }
1323   else
1324     {
1325       XDeleteProperty (xdisplay,
1326                        xwindow,
1327                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
1328     }
1329
1330   toplevel->map_serial = NextRequest (xdisplay);
1331 }
1332
1333 static void
1334 show_window_internal (GdkWindow *window,
1335                       gboolean   raise)
1336 {
1337   GdkWindowObject *private;
1338   
1339   g_return_if_fail (GDK_IS_WINDOW (window));
1340   
1341   private = (GdkWindowObject*) window;
1342   if (!private->destroyed)
1343     {
1344       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
1345       Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
1346       Window xwindow = GDK_WINDOW_XID (window);
1347       
1348       if (raise)
1349         XRaiseWindow (xdisplay, xwindow);
1350
1351       if (!GDK_WINDOW_IS_MAPPED (window))
1352         {
1353           set_initial_hints (window);
1354           
1355           gdk_synthesize_window_state (window,
1356                                        GDK_WINDOW_STATE_WITHDRAWN,
1357                                        0);
1358         }
1359       
1360       g_assert (GDK_WINDOW_IS_MAPPED (window));
1361
1362       if (impl->position_info.mapped)
1363         {
1364           gboolean unset_bg = !private->input_only &&
1365             (private->window_type == GDK_WINDOW_CHILD ||
1366              impl->override_redirect) &&
1367             gdk_window_is_viewable (window);
1368
1369           if (unset_bg)
1370             _gdk_x11_window_tmp_unset_bg (window, TRUE);
1371           
1372           XMapWindow (xdisplay, xwindow);
1373
1374           if (unset_bg)
1375             {
1376               _gdk_x11_window_tmp_reset_bg (window, TRUE);
1377               gdk_window_invalidate_rect (window, NULL, TRUE);
1378             }
1379         }
1380     }
1381 }
1382
1383 /**
1384  * gdk_window_show_unraised:
1385  * @window: a #GdkWindow
1386  *
1387  * Shows a #GdkWindow onscreen, but does not modify its stacking
1388  * order. In contrast, gdk_window_show() will raise the window
1389  * to the top of the window stack.
1390  *
1391  * On the X11 platform, in Xlib terms, this function calls
1392  * XMapWindow() (it also updates some internal GDK state, which means
1393  * that you can't really use XMapWindow() directly on a GDK window).
1394  * 
1395  **/
1396 void
1397 gdk_window_show_unraised (GdkWindow *window)
1398 {
1399   g_return_if_fail (GDK_IS_WINDOW (window));
1400   
1401   show_window_internal (window, FALSE);
1402 }
1403
1404 /**
1405  * gdk_window_show:
1406  * @window: a #GdkWindow
1407  *
1408  * Like gdk_window_show_unraised(), but also raises the window to the
1409  * top of the window stack (moves the window to the front of the
1410  * Z-order).
1411  *
1412  * This function maps a window so it's visible onscreen. Its opposite
1413  * is gdk_window_hide().
1414  *
1415  * When implementing a #GtkWidget, you should call this function on the widget's
1416  * #GdkWindow as part of the "map" method.
1417  * 
1418  **/
1419 void
1420 gdk_window_show (GdkWindow *window)
1421 {
1422   g_return_if_fail (GDK_IS_WINDOW (window));
1423
1424   show_window_internal (window, TRUE);
1425 }
1426
1427 static void
1428 pre_unmap (GdkWindow *window)
1429 {
1430   GdkWindow *start_window = NULL;
1431   GdkWindowObject *private = (GdkWindowObject *)window;
1432
1433   if (private->input_only)
1434     return;
1435
1436   if (private->window_type == GDK_WINDOW_CHILD)
1437     start_window = (GdkWindow *)private->parent;
1438   else if (private->window_type == GDK_WINDOW_TEMP)
1439     start_window = get_root (window);
1440
1441   if (start_window)
1442     _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
1443 }
1444
1445 static void
1446 post_unmap (GdkWindow *window)
1447 {
1448   GdkWindow *start_window = NULL;
1449   GdkWindowObject *private = (GdkWindowObject *)window;
1450   
1451   if (private->input_only)
1452     return;
1453
1454   if (private->window_type == GDK_WINDOW_CHILD)
1455     start_window = (GdkWindow *)private->parent;
1456   else if (private->window_type == GDK_WINDOW_TEMP)
1457     start_window = get_root (window);
1458
1459   if (start_window)
1460     {
1461       _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
1462
1463       if (private->window_type == GDK_WINDOW_CHILD && private->parent)
1464         {
1465           GdkRectangle invalid_rect;
1466       
1467           gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
1468           gdk_drawable_get_size (GDK_DRAWABLE (window),
1469                                  &invalid_rect.width, &invalid_rect.height);
1470           gdk_window_invalidate_rect ((GdkWindow *)private->parent,
1471                                       &invalid_rect, TRUE);
1472         }
1473     }
1474 }
1475
1476 /**
1477  * gdk_window_hide:
1478  * @window: a #GdkWindow
1479  *
1480  * For toplevel windows, withdraws them, so they will no longer be
1481  * known to the window manager; for all windows, unmaps them, so
1482  * they won't be displayed. Normally done automatically as
1483  * part of gtk_widget_hide().
1484  * 
1485  **/
1486 void
1487 gdk_window_hide (GdkWindow *window)
1488 {
1489   GdkWindowObject *private;
1490   
1491   g_return_if_fail (window != NULL);
1492
1493   private = (GdkWindowObject*) window;
1494
1495   /* We'll get the unmap notify eventually, and handle it then,
1496    * but checking here makes things more consistent if we are
1497    * just doing stuff ourself.
1498    */
1499   _gdk_xgrab_check_unmap (window,
1500                           NextRequest (GDK_WINDOW_XDISPLAY (window)));
1501
1502   /* You can't simply unmap toplevel windows. */
1503   switch (private->window_type)
1504     {
1505     case GDK_WINDOW_TOPLEVEL:
1506     case GDK_WINDOW_DIALOG:
1507     case GDK_WINDOW_TEMP: /* ? */
1508       gdk_window_withdraw (window);
1509       return;
1510       break;
1511       
1512     case GDK_WINDOW_FOREIGN:
1513     case GDK_WINDOW_ROOT:
1514     case GDK_WINDOW_CHILD:
1515       break;
1516     }
1517   
1518   if (!private->destroyed)
1519     {
1520       if (GDK_WINDOW_IS_MAPPED (window))
1521         gdk_synthesize_window_state (window,
1522                                      0,
1523                                      GDK_WINDOW_STATE_WITHDRAWN);
1524
1525       g_assert (!GDK_WINDOW_IS_MAPPED (window));
1526       
1527       _gdk_window_clear_update_area (window);
1528
1529       pre_unmap (window);
1530       
1531       XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
1532                     GDK_WINDOW_XID (window));
1533
1534       post_unmap (window);
1535     }
1536 }
1537
1538 /**
1539  * gdk_window_withdraw:
1540  * @window: a toplevel #GdkWindow
1541  * 
1542  * Withdraws a window (unmaps it and asks the window manager to forget about it).
1543  * This function is not really useful as gdk_window_hide() automatically
1544  * withdraws toplevel windows before hiding them.
1545  * 
1546  **/
1547 void
1548 gdk_window_withdraw (GdkWindow *window)
1549 {
1550   GdkWindowObject *private;
1551   
1552   g_return_if_fail (window != NULL);
1553   
1554   private = (GdkWindowObject*) window;
1555   if (!private->destroyed)
1556     {
1557       if (GDK_WINDOW_IS_MAPPED (window))
1558         gdk_synthesize_window_state (window,
1559                                      0,
1560                                      GDK_WINDOW_STATE_WITHDRAWN);
1561
1562       g_assert (!GDK_WINDOW_IS_MAPPED (window));
1563
1564       pre_unmap (window);
1565       
1566       XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
1567                        GDK_WINDOW_XID (window), 0);
1568
1569       post_unmap (window);
1570     }
1571 }
1572
1573 /**
1574  * gdk_window_move:
1575  * @window: a #GdkWindow
1576  * @x: X coordinate relative to window's parent
1577  * @y: Y coordinate relative to window's parent
1578  *
1579  * Repositions a window relative to its parent window.
1580  * For toplevel windows, window managers may ignore or modify the move;
1581  * you should probably use gtk_window_move() on a #GtkWindow widget
1582  * anyway, instead of using GDK functions. For child windows,
1583  * the move will reliably succeed.
1584  *
1585  * If you're also planning to resize the window, use gdk_window_move_resize()
1586  * to both move and resize simultaneously, for a nicer visual effect.
1587  **/
1588 void
1589 gdk_window_move (GdkWindow *window,
1590                  gint       x,
1591                  gint       y)
1592 {
1593   GdkWindowObject *private = (GdkWindowObject *)window;
1594   GdkWindowImplX11 *impl;
1595
1596   g_return_if_fail (window != NULL);
1597   g_return_if_fail (GDK_IS_WINDOW (window));
1598
1599   impl = GDK_WINDOW_IMPL_X11 (private->impl);
1600           
1601   if (!GDK_WINDOW_DESTROYED (window))
1602     {
1603       if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
1604         {
1605           _gdk_window_move_resize_child (window, x, y,
1606                                          impl->width, impl->height);
1607         }
1608       else
1609         {
1610           XMoveWindow (GDK_WINDOW_XDISPLAY (window),
1611                        GDK_WINDOW_XID (window),
1612                        x, y);
1613
1614           if (impl->override_redirect)
1615             {
1616               private->x = x;
1617               private->y = y;
1618             }
1619         }
1620     }
1621 }
1622
1623 /**
1624  * gdk_window_resize:
1625  * @window: a #GdkWindow
1626  * @width: new width of the window
1627  * @height: new height of the window
1628  *
1629  * Resizes @window; for toplevel windows, asks the window manager to resize
1630  * the window. The window manager may not allow the resize. When using GTK+,
1631  * use gtk_window_resize() instead of this low-level GDK function.
1632  *
1633  * Windows may not be resized below 1x1.
1634  * 
1635  * If you're also planning to move the window, use gdk_window_move_resize()
1636  * to both move and resize simultaneously, for a nicer visual effect.
1637  **/
1638 void
1639 gdk_window_resize (GdkWindow *window,
1640                    gint       width,
1641                    gint       height)
1642 {
1643   GdkWindowObject *private;
1644   
1645   g_return_if_fail (window != NULL);
1646   g_return_if_fail (GDK_IS_WINDOW (window));
1647   
1648   if (width < 1)
1649     width = 1;
1650   if (height < 1)
1651     height = 1;
1652
1653   private = (GdkWindowObject*) window;
1654   
1655   if (!GDK_WINDOW_DESTROYED (window))
1656     {
1657       if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
1658         {
1659           _gdk_window_move_resize_child (window, private->x, private->y,
1660                                          width, height);
1661         }
1662       else
1663         {
1664           GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
1665
1666           XResizeWindow (GDK_WINDOW_XDISPLAY (window),
1667                          GDK_WINDOW_XID (window),
1668                          width, height);
1669
1670           if (impl->override_redirect)
1671             {
1672               impl->width = width;
1673               impl->height = height;
1674             }
1675           else
1676             {
1677               if (width != impl->width || height != impl->height)
1678                 private->resize_count += 1;
1679             }
1680         }
1681     }
1682 }
1683
1684 /**
1685  * gdk_window_move_resize:
1686  * @window: a #GdkWindow
1687  * @x: new X position relative to window's parent
1688  * @y: new Y position relative to window's parent
1689  * @width: new width
1690  * @height: new height
1691  *
1692  * Equivalent to calling gdk_window_move() and gdk_window_resize(),
1693  * except that both operations are performed at once, avoiding strange
1694  * visual effects. (i.e. the user may be able to see the window first
1695  * move, then resize, if you don't use gdk_window_move_resize().)
1696  **/
1697 void
1698 gdk_window_move_resize (GdkWindow *window,
1699                         gint       x,
1700                         gint       y,
1701                         gint       width,
1702                         gint       height)
1703 {
1704   GdkWindowObject *private;
1705   
1706   g_return_if_fail (window != NULL);
1707   g_return_if_fail (GDK_IS_WINDOW (window));
1708
1709   if (width < 1)
1710     width = 1;
1711   if (height < 1)
1712     height = 1;
1713   
1714   private = (GdkWindowObject*) window;
1715
1716   if (!GDK_WINDOW_DESTROYED (window))
1717     {
1718       if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
1719         {
1720           _gdk_window_move_resize_child (window, x, y, width, height);
1721         }
1722       else
1723         {
1724           GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
1725
1726           XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
1727                              GDK_WINDOW_XID (window),
1728                              x, y, width, height);
1729           if (impl->override_redirect)
1730             {
1731               private->x = x;
1732               private->y = y;
1733               impl->width = width;
1734               impl->height = height;
1735             }
1736           else
1737             {
1738               if (width != impl->width || height != impl->height)
1739                 private->resize_count += 1;
1740             }
1741         }
1742     }
1743 }
1744
1745 /**
1746  * gdk_window_reparent:
1747  * @window: a #GdkWindow
1748  * @new_parent: new parent to move @window into
1749  * @x: X location inside the new parent
1750  * @y: Y location inside the new parent
1751  *
1752  * Reparents @window into the given @new_parent. The window being
1753  * reparented will be unmapped as a side effect.
1754  * 
1755  **/
1756 void
1757 gdk_window_reparent (GdkWindow *window,
1758                      GdkWindow *new_parent,
1759                      gint       x,
1760                      gint       y)
1761 {
1762   GdkDisplay *display;
1763   GdkWindowObject *window_private;
1764   GdkWindowObject *parent_private;
1765   GdkWindowObject *old_parent_private;
1766   GdkWindowImplX11 *impl;
1767   gboolean was_toplevel;
1768   
1769   g_return_if_fail (window != NULL);
1770   g_return_if_fail (GDK_IS_WINDOW (window));
1771   g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1772   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1773
1774   if (GDK_WINDOW_DESTROYED (window) ||
1775       (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1776     {
1777       return;
1778     }
1779   
1780   if (!new_parent)
1781     new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1782
1783   display = GDK_WINDOW_DISPLAY (window);
1784   
1785   window_private = (GdkWindowObject*) window;
1786   old_parent_private = (GdkWindowObject*)window_private->parent;
1787   parent_private = (GdkWindowObject*) new_parent;
1788   impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
1789   
1790   XReparentWindow (GDK_WINDOW_XDISPLAY (window),
1791                    GDK_WINDOW_XID (window),
1792                    GDK_WINDOW_XID (new_parent),
1793                    x, y);
1794
1795   window_private->x = x;
1796   window_private->y = y;
1797   
1798   /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1799    * the root window
1800    */
1801   if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1802     new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1803   
1804   window_private->parent = (GdkWindowObject *)new_parent;
1805
1806   /* Switch the window type as appropriate */
1807
1808   switch (GDK_WINDOW_TYPE (new_parent))
1809     {
1810     case GDK_WINDOW_ROOT:
1811     case GDK_WINDOW_FOREIGN:
1812       was_toplevel = WINDOW_IS_TOPLEVEL (window);
1813       
1814       if (impl->toplevel_window_type != -1)
1815         GDK_WINDOW_TYPE (window) = impl->toplevel_window_type;
1816       else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1817         GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1818
1819       if (WINDOW_IS_TOPLEVEL (window) && !was_toplevel)
1820         setup_toplevel_window (window, new_parent);
1821       break;
1822     case GDK_WINDOW_TOPLEVEL:
1823     case GDK_WINDOW_CHILD:
1824     case GDK_WINDOW_DIALOG:
1825     case GDK_WINDOW_TEMP:
1826       if (WINDOW_IS_TOPLEVEL (window))
1827         {
1828           /* Save the original window type so we can restore it if the
1829            * window is reparented back to be a toplevel
1830            */
1831           impl->toplevel_window_type = GDK_WINDOW_TYPE (window);
1832           GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1833           if (impl->toplevel)
1834             {
1835               if (impl->toplevel->focus_window)
1836                 {
1837                   XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
1838                   _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
1839                 }
1840                 
1841               gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
1842                                               impl->toplevel);
1843               g_free (impl->toplevel);
1844               impl->toplevel = NULL;
1845             }
1846         }
1847     }
1848
1849   if (old_parent_private)
1850     old_parent_private->children = g_list_remove (old_parent_private->children, window);
1851   
1852   if ((old_parent_private &&
1853        (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
1854       (!old_parent_private && parent_private->guffaw_gravity))
1855     gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
1856   
1857   parent_private->children = g_list_prepend (parent_private->children, window);
1858   _gdk_window_init_position (GDK_WINDOW (window_private));
1859 }
1860
1861 void
1862 _gdk_windowing_window_clear_area (GdkWindow *window,
1863                                   gint       x,
1864                                   gint       y,
1865                                   gint       width,
1866                                   gint       height)
1867 {
1868   g_return_if_fail (window != NULL);
1869   g_return_if_fail (GDK_IS_WINDOW (window));
1870   
1871   if (!GDK_WINDOW_DESTROYED (window))
1872     XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
1873                 x, y, width, height, False);
1874 }
1875
1876 void
1877 _gdk_windowing_window_clear_area_e (GdkWindow *window,
1878                                     gint       x,
1879                                     gint       y,
1880                                     gint       width,
1881                                     gint       height)
1882 {
1883   g_return_if_fail (window != NULL);
1884   g_return_if_fail (GDK_IS_WINDOW (window));
1885   
1886   if (!GDK_WINDOW_DESTROYED (window))
1887     XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
1888                 x, y, width, height, True);
1889 }
1890
1891
1892 /**
1893  * gdk_window_raise:
1894  * @window: a #GdkWindow
1895  * 
1896  * Raises @window to the top of the Z-order (stacking order), so that
1897  * other windows with the same parent window appear below @window.
1898  * This is true whether or not the windows are visible.
1899  *
1900  * If @window is a toplevel, the window manager may choose to deny the
1901  * request to move the window in the Z-order, gdk_window_raise() only
1902  * requests the restack, does not guarantee it.
1903  * 
1904  **/
1905 void
1906 gdk_window_raise (GdkWindow *window)
1907 {
1908   g_return_if_fail (window != NULL);
1909   g_return_if_fail (GDK_IS_WINDOW (window));
1910   
1911   if (!GDK_WINDOW_DESTROYED (window))
1912     XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1913 }
1914
1915 /**
1916  * gdk_window_lower:
1917  * @window: a #GdkWindow
1918  * 
1919  * Lowers @window to the bottom of the Z-order (stacking order), so that
1920  * other windows with the same parent window appear above @window.
1921  * This is true whether or not the other windows are visible.
1922  *
1923  * If @window is a toplevel, the window manager may choose to deny the
1924  * request to move the window in the Z-order, gdk_window_lower() only
1925  * requests the restack, does not guarantee it.
1926  *
1927  * Note that gdk_window_show() raises the window again, so don't call this
1928  * function before gdk_window_show(). (Try gdk_window_show_unraised().)
1929  * 
1930  **/
1931 void
1932 gdk_window_lower (GdkWindow *window)
1933 {
1934   g_return_if_fail (window != NULL);
1935   g_return_if_fail (GDK_IS_WINDOW (window));
1936   
1937   if (!GDK_WINDOW_DESTROYED (window))
1938     XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1939 }
1940
1941 /**
1942  * gdk_window_focus:
1943  * @window: a #GdkWindow
1944  * @timestamp: timestamp of the event triggering the window focus
1945  *
1946  * Sets keyboard focus to @window. If @window is not onscreen this
1947  * will not work. In most cases, gtk_window_present() should be used on
1948  * a #GtkWindow, rather than calling this function.
1949  * 
1950  **/
1951 void
1952 gdk_window_focus (GdkWindow *window,
1953                   guint32    timestamp)
1954 {
1955   GdkDisplay *display;
1956   
1957   g_return_if_fail (GDK_IS_WINDOW (window));
1958
1959   if (GDK_WINDOW_DESTROYED (window))
1960     return;
1961
1962   display = GDK_WINDOW_DISPLAY (window);
1963
1964   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1965                                            gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE)))
1966     {
1967       XEvent xev;
1968
1969       xev.xclient.type = ClientMessage;
1970       xev.xclient.serial = 0;
1971       xev.xclient.send_event = True;
1972       xev.xclient.window = GDK_WINDOW_XWINDOW (window);
1973       xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
1974                                                                         "_NET_ACTIVE_WINDOW");
1975       xev.xclient.format = 32;
1976       xev.xclient.data.l[0] = 0;
1977       xev.xclient.data.l[1] = 0;
1978       xev.xclient.data.l[2] = 0;
1979       xev.xclient.data.l[3] = 0;
1980       xev.xclient.data.l[4] = 0;
1981       
1982       XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
1983                   SubstructureRedirectMask | SubstructureNotifyMask,
1984                   &xev);
1985     }
1986   else
1987     {
1988       XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
1989
1990       /* There is no way of knowing reliably whether we are viewable;
1991        * _gdk_x11_set_input_focus_safe() traps errors asynchronously.
1992        */
1993       _gdk_x11_set_input_focus_safe (display, GDK_WINDOW_XID (window),
1994                                      RevertToParent,
1995                                      timestamp);
1996     }
1997 }
1998
1999 /**
2000  * gdk_window_set_hints:
2001  * @window: a #GdkWindow
2002  * @x: ignored field, does not matter
2003  * @y: ignored field, does not matter
2004  * @min_width: minimum width hint
2005  * @min_height: minimum height hint
2006  * @max_width: max width hint
2007  * @max_height: max height hint
2008  * @flags: logical OR of GDK_HINT_POS, GDK_HINT_MIN_SIZE, and/or GDK_HINT_MAX_SIZE
2009  *
2010  * This function is broken and useless and you should ignore it.
2011  * If using GTK+, use functions such as gtk_window_resize(), gtk_window_set_size_request(),
2012  * gtk_window_move(), gtk_window_parse_geometry(), and gtk_window_set_geometry_hints(),
2013  * depending on what you're trying to do.
2014  *
2015  * If using GDK directly, use gdk_window_set_geometry_hints().
2016  * 
2017  **/
2018 void
2019 gdk_window_set_hints (GdkWindow *window,
2020                       gint       x,
2021                       gint       y,
2022                       gint       min_width,
2023                       gint       min_height,
2024                       gint       max_width,
2025                       gint       max_height,
2026                       gint       flags)
2027 {
2028   XSizeHints size_hints;
2029   
2030   g_return_if_fail (window != NULL);
2031   g_return_if_fail (GDK_IS_WINDOW (window));
2032   
2033   if (GDK_WINDOW_DESTROYED (window))
2034     return;
2035   
2036   size_hints.flags = 0;
2037   
2038   if (flags & GDK_HINT_POS)
2039     {
2040       size_hints.flags |= PPosition;
2041       size_hints.x = x;
2042       size_hints.y = y;
2043     }
2044   
2045   if (flags & GDK_HINT_MIN_SIZE)
2046     {
2047       size_hints.flags |= PMinSize;
2048       size_hints.min_width = min_width;
2049       size_hints.min_height = min_height;
2050     }
2051   
2052   if (flags & GDK_HINT_MAX_SIZE)
2053     {
2054       size_hints.flags |= PMaxSize;
2055       size_hints.max_width = max_width;
2056       size_hints.max_height = max_height;
2057     }
2058   
2059   /* FIXME: Would it be better to delete this property if
2060    *        flags == 0? It would save space on the server
2061    */
2062   XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2063                      GDK_WINDOW_XID (window),
2064                      &size_hints);
2065 }
2066
2067 /**
2068  * gdk_window_set_type_hint:
2069  * @window: A toplevel #GdkWindow
2070  * @hint: A hint of the function this window will have
2071  *
2072  * The application can use this call to provide a hint to the window
2073  * manager about the functionality of a window. The window manager
2074  * can use this information when determining the decoration and behaviour
2075  * of the window.
2076  *
2077  * The hint must be set before the window is mapped.
2078  **/
2079 void
2080 gdk_window_set_type_hint (GdkWindow        *window,
2081                           GdkWindowTypeHint hint)
2082 {
2083   GdkDisplay *display;
2084   Atom atom;
2085   
2086   g_return_if_fail (window != NULL);
2087   g_return_if_fail (GDK_IS_WINDOW (window));
2088   
2089   if (GDK_WINDOW_DESTROYED (window))
2090     return;
2091
2092   display = gdk_drawable_get_display (window);
2093
2094   switch (hint)
2095     {
2096     case GDK_WINDOW_TYPE_HINT_DIALOG:
2097       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
2098       break;
2099     case GDK_WINDOW_TYPE_HINT_MENU:
2100       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
2101       break;
2102     case GDK_WINDOW_TYPE_HINT_TOOLBAR:
2103       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
2104       break;
2105     case GDK_WINDOW_TYPE_HINT_UTILITY:
2106       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
2107       break;
2108     case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2109       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
2110       break;
2111     case GDK_WINDOW_TYPE_HINT_DOCK:
2112       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
2113       break;
2114     case GDK_WINDOW_TYPE_HINT_DESKTOP:
2115       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
2116       break;
2117     default:
2118       g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
2119       /* Fall thru */
2120     case GDK_WINDOW_TYPE_HINT_NORMAL:
2121       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
2122       break;
2123     }
2124
2125   XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2126                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2127                    XA_ATOM, 32, PropModeReplace,
2128                    (guchar *)&atom, 1);
2129 }
2130
2131
2132 static void
2133 gdk_wmspec_change_state (gboolean   add,
2134                          GdkWindow *window,
2135                          GdkAtom    state1,
2136                          GdkAtom    state2)
2137 {
2138   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
2139   XEvent xev;
2140   
2141 #define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
2142 #define _NET_WM_STATE_ADD           1    /* add/set property */
2143 #define _NET_WM_STATE_TOGGLE        2    /* toggle property  */  
2144   
2145   xev.xclient.type = ClientMessage;
2146   xev.xclient.serial = 0;
2147   xev.xclient.send_event = True;
2148   xev.xclient.window = GDK_WINDOW_XID (window);
2149   xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
2150   xev.xclient.format = 32;
2151   xev.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
2152   xev.xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
2153   xev.xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
2154   xev.xclient.data.l[3] = 0;
2155   xev.xclient.data.l[4] = 0;
2156   
2157   XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
2158               SubstructureRedirectMask | SubstructureNotifyMask,
2159               &xev);
2160 }
2161
2162 /**
2163  * gdk_window_set_modal_hint:
2164  * @window: A toplevel #GdkWindow
2165  * @modal: TRUE if the window is modal, FALSE otherwise.
2166  *
2167  * The application can use this hint to tell the window manager
2168  * that a certain window has modal behaviour. The window manager
2169  * can use this information to handle modal windows in a special
2170  * way.
2171  *
2172  * You should only use this on windows for which you have
2173  * previously called #gdk_window_set_transient_for()
2174  **/
2175 void
2176 gdk_window_set_modal_hint (GdkWindow *window,
2177                            gboolean   modal)
2178 {
2179   GdkWindowObject *private;
2180
2181   g_return_if_fail (window != NULL);
2182   g_return_if_fail (GDK_IS_WINDOW (window));
2183   
2184   if (GDK_WINDOW_DESTROYED (window))
2185     return;
2186
2187   private = (GdkWindowObject*) window;
2188
2189   private->modal_hint = modal;
2190
2191   if (GDK_WINDOW_IS_MAPPED (window))
2192     gdk_wmspec_change_state (modal, window,
2193                              gdk_atom_intern ("_NET_WM_STATE_MODAL", FALSE), 
2194                              0);
2195 }
2196
2197 /**
2198  * gdk_window_set_skip_taskbar_hint:
2199  * @window: a toplevel #GdkWindow
2200  * @skips_taskbar: %TRUE to skip the taskbar
2201  * 
2202  * Toggles whether a window should appear in a task list or window
2203  * list. If a window's semantic type as specified with
2204  * gdk_window_set_type_hint() already fully describes the window, this
2205  * function should NOT be called in addition, instead you should allow
2206  * the window to be treated according to standard policy for its
2207  * semantic type.
2208  *
2209  * Since: 2.2
2210  **/
2211 void
2212 gdk_window_set_skip_taskbar_hint (GdkWindow *window,
2213                                   gboolean   skips_taskbar)
2214 {
2215   GdkToplevelX11 *toplevel;
2216   
2217   g_return_if_fail (window != NULL);
2218   g_return_if_fail (GDK_IS_WINDOW (window));
2219   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2220   
2221   if (GDK_WINDOW_DESTROYED (window))
2222     return;
2223
2224   toplevel = _gdk_x11_window_get_toplevel (window);
2225   toplevel->skip_taskbar_hint = skips_taskbar;
2226
2227   if (GDK_WINDOW_IS_MAPPED (window))
2228     gdk_wmspec_change_state (skips_taskbar, window,
2229                              gdk_atom_intern ("_NET_WM_STATE_SKIP_TASKBAR", FALSE), 
2230                              0);
2231 }
2232
2233 /**
2234  * gdk_window_set_skip_pager_hint:
2235  * @window: a toplevel #GdkWindow
2236  * @skips_pager: %TRUE to skip the pager
2237  * 
2238  * Toggles whether a window should appear in a pager (workspace
2239  * switcher, or other desktop utility program that displays a small
2240  * thumbnail representation of the windows on the desktop). If a
2241  * window's semantic type as specified with gdk_window_set_type_hint()
2242  * already fully describes the window, this function should NOT be
2243  * called in addition, instead you should allow the window to be
2244  * treated according to standard policy for its semantic type.
2245  *
2246  * Since: 2.2
2247  **/
2248 void
2249 gdk_window_set_skip_pager_hint (GdkWindow *window,
2250                                 gboolean   skips_pager)
2251 {
2252   GdkToplevelX11 *toplevel;
2253     
2254   g_return_if_fail (window != NULL);
2255   g_return_if_fail (GDK_IS_WINDOW (window));
2256   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2257   
2258   if (GDK_WINDOW_DESTROYED (window))
2259     return;
2260
2261   toplevel = _gdk_x11_window_get_toplevel (window);
2262   toplevel->skip_pager_hint = skips_pager;
2263   
2264   if (GDK_WINDOW_IS_MAPPED (window))
2265     gdk_wmspec_change_state (skips_pager, window,
2266                              gdk_atom_intern ("_NET_WM_STATE_SKIP_PAGER", FALSE), 
2267                              0);
2268 }
2269
2270 /**
2271  * gdk_window_set_geometry_hints:
2272  * @window: a toplevel #GdkWindow
2273  * @geometry: geometry hints
2274  * @geom_mask: bitmask indicating fields of @geometry to pay attention to
2275  *
2276  * Sets the geometry hints for @window. Hints flagged in @geom_mask
2277  * are set, hints not flagged in @geom_mask are unset.
2278  * To unset all hints, use a @geom_mask of 0 and a @geometry of %NULL.
2279  *
2280  * This function provides hints to the windowing system about
2281  * acceptable sizes for a toplevel window. The purpose of 
2282  * this is to constrain user resizing, but the windowing system
2283  * will typically  (but is not required to) also constrain the
2284  * current size of the window to the provided values and
2285  * constrain programatic resizing via gdk_window_resize() or
2286  * gdk_window_move_resize().
2287  * 
2288  * Note that on X11, this effect has no effect on windows
2289  * of type GDK_WINDOW_TEMP or windows where override_redirect
2290  * has been turned on via gdk_window_set_override_redirect()
2291  * since these windows are not resizable by the user.
2292  * 
2293  * Since you can't count on the windowing system doing the
2294  * constraints for programmatic resizes, you should generally
2295  * call gdk_window_constrain_size() yourself to determine
2296  * appropriate sizes.
2297  *
2298  **/
2299 void 
2300 gdk_window_set_geometry_hints (GdkWindow      *window,
2301                                GdkGeometry    *geometry,
2302                                GdkWindowHints  geom_mask)
2303 {
2304   XSizeHints size_hints;
2305   
2306   g_return_if_fail (window != NULL);
2307   g_return_if_fail (GDK_IS_WINDOW (window));
2308   
2309   if (GDK_WINDOW_DESTROYED (window))
2310     return;
2311   
2312   size_hints.flags = 0;
2313   
2314   if (geom_mask & GDK_HINT_POS)
2315     {
2316       size_hints.flags |= PPosition;
2317       /* We need to initialize the following obsolete fields because KWM 
2318        * apparently uses these fields if they are non-zero.
2319        * #@#!#!$!.
2320        */
2321       size_hints.x = 0;
2322       size_hints.y = 0;
2323     }
2324
2325   if (geom_mask & GDK_HINT_USER_POS)
2326     {
2327       size_hints.flags |= USPosition;
2328     }
2329
2330   if (geom_mask & GDK_HINT_USER_SIZE)
2331     {
2332       size_hints.flags |= USSize;
2333     }
2334   
2335   if (geom_mask & GDK_HINT_MIN_SIZE)
2336     {
2337       size_hints.flags |= PMinSize;
2338       size_hints.min_width = geometry->min_width;
2339       size_hints.min_height = geometry->min_height;
2340     }
2341   
2342   if (geom_mask & GDK_HINT_MAX_SIZE)
2343     {
2344       size_hints.flags |= PMaxSize;
2345       size_hints.max_width = MAX (geometry->max_width, 1);
2346       size_hints.max_height = MAX (geometry->max_height, 1);
2347     }
2348   
2349   if (geom_mask & GDK_HINT_BASE_SIZE)
2350     {
2351       size_hints.flags |= PBaseSize;
2352       size_hints.base_width = geometry->base_width;
2353       size_hints.base_height = geometry->base_height;
2354     }
2355   
2356   if (geom_mask & GDK_HINT_RESIZE_INC)
2357     {
2358       size_hints.flags |= PResizeInc;
2359       size_hints.width_inc = geometry->width_inc;
2360       size_hints.height_inc = geometry->height_inc;
2361     }
2362   
2363   if (geom_mask & GDK_HINT_ASPECT)
2364     {
2365       size_hints.flags |= PAspect;
2366       if (geometry->min_aspect <= 1)
2367         {
2368           size_hints.min_aspect.x = 65536 * geometry->min_aspect;
2369           size_hints.min_aspect.y = 65536;
2370         }
2371       else
2372         {
2373           size_hints.min_aspect.x = 65536;
2374           size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
2375         }
2376       if (geometry->max_aspect <= 1)
2377         {
2378           size_hints.max_aspect.x = 65536 * geometry->max_aspect;
2379           size_hints.max_aspect.y = 65536;
2380         }
2381       else
2382         {
2383           size_hints.max_aspect.x = 65536;
2384           size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
2385         }
2386     }
2387
2388   if (geom_mask & GDK_HINT_WIN_GRAVITY)
2389     {
2390       size_hints.flags |= PWinGravity;
2391       size_hints.win_gravity = geometry->win_gravity;
2392     }
2393   
2394   /* FIXME: Would it be better to delete this property if
2395    *        geom_mask == 0? It would save space on the server
2396    */
2397   XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2398                      GDK_WINDOW_XID (window),
2399                      &size_hints);
2400 }
2401
2402 static void
2403 gdk_window_get_geometry_hints (GdkWindow      *window,
2404                                GdkGeometry    *geometry,
2405                                GdkWindowHints *geom_mask)
2406 {
2407   XSizeHints size_hints;  
2408   glong junk_size_mask = 0;
2409
2410   g_return_if_fail (GDK_IS_WINDOW (window));
2411   g_return_if_fail (geometry != NULL);
2412   g_return_if_fail (geom_mask != NULL);
2413
2414   *geom_mask = 0;
2415   
2416   if (GDK_WINDOW_DESTROYED (window))
2417     return;
2418   
2419   if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2420                           GDK_WINDOW_XID (window),
2421                           &size_hints,
2422                           &junk_size_mask))
2423     return;                   
2424
2425   if (size_hints.flags & PMinSize)
2426     {
2427       *geom_mask |= GDK_HINT_MIN_SIZE;
2428       geometry->min_width = size_hints.min_width;
2429       geometry->min_height = size_hints.min_height;
2430     }
2431
2432   if (size_hints.flags & PMaxSize)
2433     {
2434       *geom_mask |= GDK_HINT_MAX_SIZE;
2435       geometry->max_width = MAX (size_hints.max_width, 1);
2436       geometry->max_height = MAX (size_hints.max_height, 1);
2437     }
2438
2439   if (size_hints.flags & PResizeInc)
2440     {
2441       *geom_mask |= GDK_HINT_RESIZE_INC;
2442       geometry->width_inc = size_hints.width_inc;
2443       geometry->height_inc = size_hints.height_inc;
2444     }
2445
2446   if (size_hints.flags & PAspect)
2447     {
2448       *geom_mask |= GDK_HINT_ASPECT;
2449
2450       geometry->min_aspect = (gdouble) size_hints.min_aspect.x / (gdouble) size_hints.min_aspect.y;
2451       geometry->max_aspect = (gdouble) size_hints.max_aspect.x / (gdouble) size_hints.max_aspect.y;
2452     }
2453
2454   if (size_hints.flags & PWinGravity)
2455     {
2456       *geom_mask |= GDK_HINT_WIN_GRAVITY;
2457       geometry->win_gravity = size_hints.win_gravity;
2458     }
2459 }
2460
2461 static gboolean
2462 utf8_is_latin1 (const gchar *str)
2463 {
2464   const char *p = str;
2465
2466   while (*p)
2467     {
2468       gunichar ch = g_utf8_get_char (p);
2469
2470       if (ch > 0xff)
2471         return FALSE;
2472       
2473       p = g_utf8_next_char (p);
2474     }
2475
2476   return TRUE;
2477 }
2478
2479 /* Set the property to @utf8_str as STRING if the @utf8_str is fully
2480  * convertable to STRING, otherwise, set it as compound text
2481  */
2482 static void
2483 set_text_property (GdkDisplay  *display,
2484                    Window       xwindow,
2485                    Atom         property,
2486                    const gchar *utf8_str)
2487 {
2488   guchar *prop_text = NULL;
2489   Atom prop_type;
2490   gint prop_length;
2491   gint prop_format;
2492   gboolean is_compound_text;
2493   
2494   if (utf8_is_latin1 (utf8_str))
2495     {
2496       prop_type = XA_STRING;
2497       prop_text = gdk_utf8_to_string_target (utf8_str);
2498       prop_length = prop_text ? strlen (prop_text) : 0;
2499       prop_format = 8;
2500       is_compound_text = FALSE;
2501     }
2502   else
2503     {
2504       GdkAtom gdk_type;
2505       
2506       gdk_utf8_to_compound_text_for_display (display,
2507                                              utf8_str, &gdk_type, &prop_format,
2508                                              &prop_text, &prop_length);
2509       prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
2510       is_compound_text = TRUE;
2511     }
2512
2513   if (prop_text)
2514     {
2515       XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
2516                        xwindow,
2517                        property,
2518                        prop_type, prop_format,
2519                        PropModeReplace, prop_text,
2520                        prop_length);
2521
2522       if (is_compound_text)
2523         gdk_free_compound_text (prop_text);
2524       else
2525         g_free (prop_text);
2526     }
2527 }
2528
2529 /* Set WM_NAME and _NET_WM_NAME
2530  */
2531 static void
2532 set_wm_name (GdkDisplay  *display,
2533              Window       xwindow,
2534              const gchar *name)
2535 {
2536   XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2537                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
2538                    gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2539                    PropModeReplace, name, strlen (name));
2540   
2541   set_text_property (display, xwindow,
2542                      gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
2543                      name);
2544 }
2545
2546 /**
2547  * gdk_window_set_title:
2548  * @window: a toplevel #GdkWindow
2549  * @title: title of @window
2550  *
2551  * Sets the title of a toplevel window, to be displayed in the titlebar.
2552  * If you haven't explicitly set the icon name for the window
2553  * (using gdk_window_set_icon_name()), the icon name will be set to
2554  * @title as well. @title must be in UTF-8 encoding (as with all
2555  * user-readable strings in GDK/GTK+). @title may not be %NULL.
2556  **/
2557 void
2558 gdk_window_set_title (GdkWindow   *window,
2559                       const gchar *title)
2560 {
2561   GdkDisplay *display;
2562   Display *xdisplay;
2563   Window xwindow;
2564   
2565   g_return_if_fail (window != NULL);
2566   g_return_if_fail (GDK_IS_WINDOW (window));
2567   g_return_if_fail (title != NULL);
2568
2569   if (GDK_WINDOW_DESTROYED (window))
2570     return;
2571   
2572   display = gdk_drawable_get_display (window);
2573   xdisplay = GDK_DISPLAY_XDISPLAY (display);
2574   xwindow = GDK_WINDOW_XID (window);
2575
2576   set_wm_name (display, xwindow, title);
2577   
2578   if (!gdk_window_icon_name_set (window))
2579     {
2580       XChangeProperty (xdisplay, xwindow,
2581                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
2582                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2583                        PropModeReplace, title, strlen (title));
2584       
2585       set_text_property (display, xwindow,
2586                          gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
2587                          title);
2588     }
2589 }
2590
2591 /**
2592  * gdk_window_set_role:
2593  * @window: a toplevel #GdkWindow
2594  * @role: a string indicating its role
2595  *
2596  * When using GTK+, typically you should use gtk_window_set_role() instead
2597  * of this low-level function.
2598  * 
2599  * The window manager and session manager use a window's role to
2600  * distinguish it from other kinds of window in the same application.
2601  * When an application is restarted after being saved in a previous
2602  * session, all windows with the same title and role are treated as
2603  * interchangeable.  So if you have two windows with the same title
2604  * that should be distinguished for session management purposes, you
2605  * should set the role on those windows. It doesn't matter what string
2606  * you use for the role, as long as you have a different role for each
2607  * non-interchangeable kind of window.
2608  * 
2609  **/
2610 void          
2611 gdk_window_set_role (GdkWindow   *window,
2612                      const gchar *role)
2613 {
2614   GdkDisplay *display;
2615   
2616   g_return_if_fail (window != NULL);
2617   g_return_if_fail (GDK_IS_WINDOW (window));
2618
2619   display = gdk_drawable_get_display (window);
2620
2621   if (!GDK_WINDOW_DESTROYED (window))
2622     {
2623       if (role)
2624         XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2625                          gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
2626                          XA_STRING, 8, PropModeReplace, role, strlen (role));
2627       else
2628         XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2629                          gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
2630     }
2631 }
2632
2633 /**
2634  * gdk_window_set_transient_for:
2635  * @window: a toplevel #GdkWindow
2636  * @parent: another toplevel #GdkWindow
2637  *
2638  * Indicates to the window manager that @window is a transient dialog
2639  * associated with the application window @parent. This allows the
2640  * window manager to do things like center @window on @parent and
2641  * keep @window above @parent.
2642  *
2643  * See gtk_window_set_transient_for() if you're using #GtkWindow or
2644  * #GtkDialog.
2645  * 
2646  **/
2647 void          
2648 gdk_window_set_transient_for (GdkWindow *window, 
2649                               GdkWindow *parent)
2650 {
2651   GdkWindowObject *private;
2652   GdkWindowObject *parent_private;
2653   
2654   g_return_if_fail (window != NULL);
2655   g_return_if_fail (GDK_IS_WINDOW (window));
2656   
2657   private = (GdkWindowObject*) window;
2658   parent_private = (GdkWindowObject*) parent;
2659   
2660   if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent))
2661     XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), 
2662                           GDK_WINDOW_XID (window),
2663                           GDK_WINDOW_XID (parent));
2664 }
2665
2666 /**
2667  * gdk_window_set_background:
2668  * @window: a #GdkWindow
2669  * @color: an allocated #GdkColor
2670  *
2671  * Sets the background color of @window. (However, when using GTK+,
2672  * set the background of a widget with gtk_widget_modify_bg() - if
2673  * you're an application - or gtk_style_set_background() - if you're
2674  * implementing a custom widget.)
2675  *
2676  * The @color must be allocated; gdk_rgb_find_color() is the best way
2677  * to allocate a color.
2678  *
2679  * See also gdk_window_set_back_pixmap().
2680  * 
2681  **/
2682 void
2683 gdk_window_set_background (GdkWindow      *window,
2684                            const GdkColor *color)
2685 {
2686   GdkWindowObject *private = (GdkWindowObject *)window;
2687   
2688   g_return_if_fail (window != NULL);
2689   g_return_if_fail (GDK_IS_WINDOW (window));
2690   
2691   if (!GDK_WINDOW_DESTROYED (window))
2692     XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
2693                           GDK_WINDOW_XID (window), color->pixel);
2694
2695   private->bg_color = *color;
2696
2697   if (private->bg_pixmap &&
2698       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
2699       private->bg_pixmap != GDK_NO_BG)
2700     g_object_unref (private->bg_pixmap);
2701   
2702   private->bg_pixmap = NULL;
2703 }
2704
2705 /**
2706  * gdk_window_set_back_pixmap:
2707  * @window: a #GdkWindow
2708  * @pixmap: a #GdkPixmap, or %NULL
2709  * @parent_relative: whether the tiling origin is at the origin of @window's parent
2710  *
2711  * Sets the background pixmap of @window. May also be used to set a background of
2712  * "None" on @window, by setting a background pixmap of %NULL.
2713  * A background pixmap will be tiled, positioning the first tile at the origin of
2714  * @window, or if @parent_relative is %TRUE, the tiling will be done based on the
2715  * origin of the parent window (useful to align tiles in a parent with tiles
2716  * in a child).
2717  *
2718  * A background pixmap of %NULL means that the window will have no
2719  * background.  A window with no background will never have its
2720  * background filled by the windowing system, instead the window will
2721  * contain whatever pixels were already in the corresponding area of
2722  * the display.
2723  *
2724  * The windowing system will normally fill a window with its background
2725  * when the window is obscured then exposed, and when you call
2726  * gdk_window_clear().
2727  * 
2728  **/
2729 void
2730 gdk_window_set_back_pixmap (GdkWindow *window,
2731                             GdkPixmap *pixmap,
2732                             gboolean   parent_relative)
2733 {
2734   GdkWindowObject *private = (GdkWindowObject *)window;
2735   Pixmap xpixmap;
2736   
2737   g_return_if_fail (window != NULL);
2738   g_return_if_fail (GDK_IS_WINDOW (window));
2739   g_return_if_fail (pixmap == NULL || !parent_relative);
2740   g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
2741   
2742   if (private->bg_pixmap &&
2743       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
2744       private->bg_pixmap != GDK_NO_BG)
2745     g_object_unref (private->bg_pixmap);
2746
2747   if (parent_relative)
2748     {
2749       xpixmap = ParentRelative;
2750       private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
2751     }
2752   else
2753     {
2754       if (pixmap)
2755         {
2756           g_object_ref (pixmap);
2757           private->bg_pixmap = pixmap;
2758           xpixmap = GDK_PIXMAP_XID (pixmap);
2759         }
2760       else
2761         {
2762           xpixmap = None;
2763           private->bg_pixmap = GDK_NO_BG;
2764         }
2765     }
2766   
2767   if (!GDK_WINDOW_DESTROYED (window))
2768     XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2769                                 GDK_WINDOW_XID (window), xpixmap);
2770 }
2771
2772 /**
2773  * gdk_window_set_cursor:
2774  * @window: a #GdkWindow
2775  * @cursor: a cursor
2776  *
2777  * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new() or
2778  * gdk_cursor_new_from_pixmap() to create the cursor.
2779  * To make the cursor invisible, use gdk_cursor_new_from_pixmap() to create
2780  * a cursor with no pixels in it. Passing %NULL for the @cursor argument
2781  * to gdk_window_set_cursor() means that @window will use the cursor of
2782  * its parent window. Most windows should use this default.
2783  * 
2784  **/
2785 void
2786 gdk_window_set_cursor (GdkWindow *window,
2787                        GdkCursor *cursor)
2788 {
2789   GdkCursorPrivate *cursor_private;
2790   Cursor xcursor;
2791   
2792   g_return_if_fail (window != NULL);
2793   g_return_if_fail (GDK_IS_WINDOW (window));
2794   
2795   cursor_private = (GdkCursorPrivate*) cursor;
2796   
2797   if (!cursor)
2798     xcursor = None;
2799   else
2800     xcursor = cursor_private->xcursor;
2801   
2802   if (!GDK_WINDOW_DESTROYED (window))
2803     XDefineCursor (GDK_WINDOW_XDISPLAY (window),
2804                    GDK_WINDOW_XID (window),
2805                    xcursor);
2806 }
2807
2808 /**
2809  * gdk_window_get_geometry:
2810  * @window: a #GdkWindow
2811  * @x: return location for X coordinate of window (relative to its parent)
2812  * @y: return location for Y coordinate of window (relative to its parent)
2813  * @width: return location for width of window
2814  * @height: return location for height of window
2815  * @depth: return location for bit depth of window
2816  *
2817  * Any of the return location arguments to this function may be %NULL,
2818  * if you aren't interested in getting the value of that field.
2819  *
2820  * The X and Y coordinates returned are relative to the parent window
2821  * of @window, which for toplevels usually means relative to the
2822  * window decorations (titlebar, etc.) rather than relative to the
2823  * root window (screen-size background window).
2824  *
2825  * On the X11 platform, the geometry is obtained from the X server,
2826  * so reflects the latest position of @window; this may be out-of-sync
2827  * with the position of @window delivered in the most-recently-processed
2828  * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
2829  * position from the most recent configure event.
2830  * 
2831  **/
2832 void
2833 gdk_window_get_geometry (GdkWindow *window,
2834                          gint      *x,
2835                          gint      *y,
2836                          gint      *width,
2837                          gint      *height,
2838                          gint      *depth)
2839 {
2840   Window root;
2841   gint tx;
2842   gint ty;
2843   guint twidth;
2844   guint theight;
2845   guint tborder_width;
2846   guint tdepth;
2847   
2848   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2849   
2850   if (!window)
2851     {
2852       GDK_NOTE (MULTIHEAD,
2853                 g_message ("gdk_window_get_geometry(): Window needs to be non-NULL to be multi head safe"));
2854       window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
2855     }
2856
2857   if (!GDK_WINDOW_DESTROYED (window))
2858     {
2859       XGetGeometry (GDK_WINDOW_XDISPLAY (window),
2860                     GDK_WINDOW_XID (window),
2861                     &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
2862       
2863       if (x)
2864         *x = tx;
2865       if (y)
2866         *y = ty;
2867       if (width)
2868         *width = twidth;
2869       if (height)
2870         *height = theight;
2871       if (depth)
2872         *depth = tdepth;
2873     }
2874 }
2875
2876 /**
2877  * gdk_window_get_origin:
2878  * @window: a #GdkWindow
2879  * @x: return location for X coordinate
2880  * @y: return location for Y coordinate
2881  * 
2882  * Obtains the position of a window in root window coordinates.
2883  * (Compare with gdk_window_get_position() and
2884  * gdk_window_get_geometry() which return the position of a window
2885  * relative to its parent window.)
2886  * 
2887  * Return value: not meaningful, ignore
2888  **/
2889 gint
2890 gdk_window_get_origin (GdkWindow *window,
2891                        gint      *x,
2892                        gint      *y)
2893 {
2894   gint return_val;
2895   Window child;
2896   gint tx = 0;
2897   gint ty = 0;
2898   
2899   g_return_val_if_fail (window != NULL, 0);
2900   
2901   if (!GDK_WINDOW_DESTROYED (window))
2902     {
2903       return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2904                                           GDK_WINDOW_XID (window),
2905                                           GDK_WINDOW_XROOTWIN (window),
2906                                           0, 0, &tx, &ty,
2907                                           &child);
2908     }
2909   else
2910     return_val = 0;
2911   
2912   if (x)
2913     *x = tx;
2914   if (y)
2915     *y = ty;
2916   
2917   return return_val;
2918 }
2919
2920 /**
2921  * gdk_window_get_deskrelative_origin:
2922  * @window: a toplevel #GdkWindow
2923  * @x: return location for X coordinate
2924  * @y: return location for Y coordinate
2925  * 
2926  * This gets the origin of a #GdkWindow relative to
2927  * an Enlightenment-window-manager desktop. As long as you don't
2928  * assume that the user's desktop/workspace covers the entire
2929  * root window (i.e. you don't assume that the desktop begins
2930  * at root window coordinate 0,0) this function is not necessary.
2931  * It's deprecated for that reason.
2932  * 
2933  * Return value: not meaningful
2934  **/
2935 gboolean
2936 gdk_window_get_deskrelative_origin (GdkWindow *window,
2937                                     gint      *x,
2938                                     gint      *y)
2939 {
2940   gboolean return_val = FALSE;
2941   gint num_children, format_return;
2942   Window win, *child, parent, root;
2943   gint tx = 0;
2944   gint ty = 0;
2945   Atom type_return;
2946   Atom atom;
2947   gulong number_return, bytes_after_return;
2948   guchar *data_return;
2949   
2950   g_return_val_if_fail (window != NULL, FALSE);
2951   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2952   
2953   if (!GDK_WINDOW_DESTROYED (window))
2954     {
2955       atom = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
2956                                                     "ENLIGHTENMENT_DESKTOP");
2957       win = GDK_WINDOW_XID (window);
2958       
2959       while (XQueryTree (GDK_WINDOW_XDISPLAY (window), win, &root, &parent,
2960                          &child, (unsigned int *)&num_children))
2961         {
2962           if ((child) && (num_children > 0))
2963             XFree (child);
2964           
2965           if (!parent)
2966             break;
2967           else
2968             win = parent;
2969           
2970           if (win == root)
2971             break;
2972           
2973           data_return = NULL;
2974           XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), win, atom, 0, 0,
2975                               False, XA_CARDINAL, &type_return, &format_return,
2976                               &number_return, &bytes_after_return, &data_return);
2977
2978           if (type_return == XA_CARDINAL)
2979             {
2980               XFree (data_return);
2981               break;
2982             }
2983         }
2984       
2985       return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2986                                           GDK_WINDOW_XID (window),
2987                                           win,
2988                                           0, 0, &tx, &ty,
2989                                           &root);
2990       if (x)
2991         *x = tx;
2992       if (y)
2993         *y = ty;
2994     }
2995   
2996   
2997   return return_val;
2998 }
2999
3000 /**
3001  * gdk_window_get_root_origin:
3002  * @window: a toplevel #GdkWindow
3003  * @x: return location for X position of window frame
3004  * @y: return location for Y position of window frame
3005  *
3006  * Obtains the top-left corner of the window manager frame in root
3007  * window coordinates.
3008  * 
3009  **/
3010 void
3011 gdk_window_get_root_origin (GdkWindow *window,
3012                             gint      *x,
3013                             gint      *y)
3014 {
3015   GdkRectangle rect;
3016
3017   g_return_if_fail (GDK_IS_WINDOW (window));
3018
3019   gdk_window_get_frame_extents (window, &rect);
3020
3021   if (x)
3022     *x = rect.x;
3023
3024   if (y)
3025     *y = rect.y;
3026 }
3027
3028 /**
3029  * gdk_window_get_frame_extents:
3030  * @window: a toplevel #GdkWindow
3031  * @rect: rectangle to fill with bounding box of the window frame
3032  *
3033  * Obtains the bounding box of the window, including window manager
3034  * titlebar/borders if any. The frame position is given in root window
3035  * coordinates. To get the position of the window itself (rather than
3036  * the frame) in root window coordinates, use gdk_window_get_origin().
3037  * 
3038  **/
3039 void
3040 gdk_window_get_frame_extents (GdkWindow    *window,
3041                               GdkRectangle *rect)
3042 {
3043   GdkWindowObject *private;
3044   Window xwindow;
3045   Window xparent;
3046   Window root;
3047   Window *children;
3048   unsigned int nchildren;
3049   
3050   g_return_if_fail (GDK_IS_WINDOW (window));
3051   g_return_if_fail (rect != NULL);
3052   
3053   private = (GdkWindowObject*) window;
3054   
3055   rect->x = 0;
3056   rect->y = 0;
3057   rect->width = 1;
3058   rect->height = 1;
3059   
3060   if (GDK_WINDOW_DESTROYED (window))
3061     return;
3062   
3063   while (private->parent && ((GdkWindowObject*) private->parent)->parent)
3064     private = (GdkWindowObject*) private->parent;
3065
3066   /* Refine our fallback answer a bit using local information */
3067   rect->x = private->x;
3068   rect->y = private->y;
3069   gdk_drawable_get_size ((GdkDrawable *)private, &rect->width, &rect->height);
3070
3071   if (GDK_WINDOW_DESTROYED (private))
3072     return;
3073
3074   gdk_error_trap_push();
3075   
3076   xparent = GDK_WINDOW_XID (window);
3077   do
3078     {
3079       xwindow = xparent;
3080       if (!XQueryTree (GDK_WINDOW_XDISPLAY (window), xwindow,
3081                        &root, &xparent,
3082                        &children, &nchildren))
3083         goto fail;
3084       
3085       if (children)
3086         XFree (children);
3087     }
3088   while (xparent != root);
3089   
3090   if (xparent == root)
3091     {
3092       unsigned int ww, wh, wb, wd;
3093       int wx, wy;
3094       
3095       if (XGetGeometry (GDK_WINDOW_XDISPLAY (window), xwindow, &root, &wx, &wy, &ww, &wh, &wb, &wd))
3096         {
3097           rect->x = wx;
3098           rect->y = wy;
3099           rect->width = ww;
3100           rect->height = wh;
3101         }
3102     }
3103
3104  fail:
3105   gdk_error_trap_pop ();
3106 }
3107
3108 void
3109 _gdk_windowing_get_pointer (GdkDisplay       *display,
3110                             GdkScreen       **screen,
3111                             gint             *x,
3112                             gint             *y,
3113                             GdkModifierType  *mask)
3114 {
3115   GdkScreen *default_screen;
3116   Window root = None;
3117   Window child;
3118   int rootx, rooty;
3119   int winx;
3120   int winy;
3121   unsigned int xmask;
3122
3123   if (display->closed)
3124     return;
3125
3126   default_screen = gdk_display_get_default_screen (display);
3127   
3128   XQueryPointer (GDK_SCREEN_XDISPLAY (default_screen),
3129                  GDK_SCREEN_XROOTWIN (default_screen),
3130                  &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
3131   
3132   if (root != None)
3133     {
3134       GdkWindow *gdk_root = gdk_window_lookup_for_display (display, root);
3135       *screen = gdk_drawable_get_screen (gdk_root);
3136     }
3137   
3138   *x = rootx;
3139   *y = rooty;
3140   *mask = xmask;
3141 }
3142
3143 GdkWindow*
3144 _gdk_windowing_window_get_pointer (GdkDisplay      *display,
3145                                    GdkWindow       *window,
3146                                    gint            *x,
3147                                    gint            *y,
3148                                    GdkModifierType *mask)
3149 {
3150   GdkWindow *return_val;
3151   Window root;
3152   Window child;
3153   int rootx, rooty;
3154   int winx = 0;
3155   int winy = 0;
3156   unsigned int xmask = 0;
3157   gint xoffset, yoffset;
3158
3159   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
3160   
3161   _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
3162
3163   return_val = NULL;
3164   if (!GDK_WINDOW_DESTROYED (window) &&
3165       XQueryPointer (GDK_WINDOW_XDISPLAY (window),
3166                      GDK_WINDOW_XID (window),
3167                      &root, &child, &rootx, &rooty, &winx, &winy, &xmask))
3168     {
3169       if (child)
3170         return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child);
3171     }
3172   
3173   *x = winx + xoffset;
3174   *y = winy + yoffset;
3175   *mask = xmask;
3176   
3177   return return_val;
3178 }
3179
3180 GdkWindow*
3181 _gdk_windowing_window_at_pointer (GdkDisplay *display,
3182                                   gint       *win_x,
3183                                   gint       *win_y)
3184 {
3185   GdkWindow *window;
3186   GdkScreen *screen;
3187   Window root;
3188   Window xwindow;
3189   Window child;
3190   Window xwindow_last = 0;
3191   Display *xdisplay;
3192   int rootx = -1, rooty = -1;
3193   int winx, winy;
3194   unsigned int xmask;
3195
3196   screen = gdk_display_get_default_screen (display);
3197   
3198   xwindow = GDK_SCREEN_XROOTWIN (screen);
3199   xdisplay = GDK_SCREEN_XDISPLAY (screen);
3200
3201   /* This function really only works if the mouse pointer is held still
3202    * during its operation. If it moves from one leaf window to another
3203    * than we'll end up with inaccurate values for win_x, win_y
3204    * and the result.
3205    */
3206   gdk_x11_display_grab (display);
3207   XQueryPointer (xdisplay, xwindow,
3208                  &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
3209
3210   if (root == xwindow)
3211     xwindow = child;
3212   else
3213     xwindow = root;
3214   
3215   while (xwindow)
3216     {
3217       xwindow_last = xwindow;
3218       XQueryPointer (xdisplay, xwindow,
3219                      &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
3220     }
3221   gdk_x11_display_ungrab (display);
3222
3223   window = gdk_window_lookup_for_display (GDK_SCREEN_DISPLAY(screen),
3224                                           xwindow_last);
3225   *win_x = window ? winx : -1;
3226   *win_y = window ? winy : -1;
3227
3228   return window;
3229 }
3230
3231 /**
3232  * gdk_window_get_events:
3233  * @window: a #GdkWindow
3234  * 
3235  * Gets the event mask for @window. See gdk_window_set_events().
3236  * 
3237  * Return value: event mask for @window
3238  **/
3239 GdkEventMask  
3240 gdk_window_get_events (GdkWindow *window)
3241 {
3242   XWindowAttributes attrs;
3243   GdkEventMask event_mask;
3244   
3245   g_return_val_if_fail (window != NULL, 0);
3246   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
3247
3248   if (GDK_WINDOW_DESTROYED (window))
3249     return 0;
3250   else
3251     {
3252       XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3253                             GDK_WINDOW_XID (window), 
3254                             &attrs);
3255       
3256       event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
3257       GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
3258   
3259       return event_mask;
3260     }
3261 }
3262
3263 /**
3264  * gdk_window_set_events:
3265  * @window: a #GdkWindow
3266  * @event_mask: event mask for @window
3267  *
3268  * The event mask for a window determines which events will be reported
3269  * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
3270  * means the window should report button press events. The event mask
3271  * is the bitwise OR of values from the #GdkEventMask enumeration.
3272  * 
3273  **/
3274 void          
3275 gdk_window_set_events (GdkWindow       *window,
3276                        GdkEventMask     event_mask)
3277 {
3278   long xevent_mask;
3279   int i;
3280   
3281   g_return_if_fail (window != NULL);
3282   g_return_if_fail (GDK_IS_WINDOW (window));
3283   
3284   if (!GDK_WINDOW_DESTROYED (window))
3285     {
3286       GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
3287       xevent_mask = StructureNotifyMask | PropertyChangeMask;
3288       for (i = 0; i < _gdk_nenvent_masks; i++)
3289         {
3290           if (event_mask & (1 << (i + 1)))
3291             xevent_mask |= _gdk_event_mask_table[i];
3292         }
3293       
3294       XSelectInput (GDK_WINDOW_XDISPLAY (window),
3295                     GDK_WINDOW_XID (window),
3296                     xevent_mask);
3297     }
3298 }
3299
3300 static void
3301 gdk_window_add_colormap_windows (GdkWindow *window)
3302 {
3303   GdkWindow *toplevel;
3304   Window *old_windows;
3305   Window *new_windows;
3306   int i, count;
3307   
3308   g_return_if_fail (window != NULL);
3309   g_return_if_fail (GDK_IS_WINDOW (window));
3310
3311   if (GDK_WINDOW_DESTROYED (window))
3312     return;
3313   toplevel = gdk_window_get_toplevel (window);
3314   
3315   old_windows = NULL;
3316   if (!XGetWMColormapWindows (GDK_WINDOW_XDISPLAY (toplevel),
3317                               GDK_WINDOW_XID (toplevel),
3318                               &old_windows, &count))
3319     {
3320       count = 0;
3321     }
3322   
3323   for (i = 0; i < count; i++)
3324     if (old_windows[i] == GDK_WINDOW_XID (window))
3325       {
3326         XFree (old_windows);
3327         return;
3328       }
3329   
3330   new_windows = g_new (Window, count + 1);
3331   
3332   for (i = 0; i < count; i++)
3333     new_windows[i] = old_windows[i];
3334   new_windows[count] = GDK_WINDOW_XID (window);
3335   
3336   XSetWMColormapWindows (GDK_WINDOW_XDISPLAY (toplevel),
3337                          GDK_WINDOW_XID (toplevel),
3338                          new_windows, count + 1);
3339   
3340   g_free (new_windows);
3341   if (old_windows)
3342     XFree (old_windows);
3343 }
3344
3345 static gboolean
3346 gdk_window_have_shape_ext (GdkDisplay *display)
3347 {
3348 #ifdef HAVE_SHAPE_EXT
3349   int ignore;
3350
3351   return XShapeQueryExtension (GDK_DISPLAY_XDISPLAY (display),
3352                                &ignore, &ignore);
3353 #else
3354   return 0;
3355 #endif  
3356 }
3357
3358 #define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
3359
3360 /*
3361  * This needs the X11 shape extension.
3362  * If not available, shaped windows will look
3363  * ugly, but programs still work.    Stefan Wille
3364  */
3365 /**
3366  * gdk_window_shape_combine_mask:
3367  * @window: a #GdkWindow
3368  * @mask: shape mask
3369  * @x: X position of shape mask with respect to @window
3370  * @y: Y position of shape mask with respect to @window
3371  *
3372  * Applies a shape mask to @window. Pixels in @window corresponding to
3373  * set bits in the @mask will be visible; pixels in @window
3374  * corresponding to unset bits in the @mask will be transparent. This
3375  * gives a non-rectangular window.
3376  *
3377  * If @mask is %NULL, the shape mask will be unset, and the @x/@y
3378  * parameters are not used.
3379  *
3380  * On the X11 platform, this uses an X server extension which is
3381  * widely available on most common platforms, but not available on
3382  * very old X servers, and occasionally the implementation will be
3383  * buggy. On servers without the shape extension, this function
3384  * will do nothing.
3385  *
3386  * This function works on both toplevel and child windows.
3387  * 
3388  **/
3389 void
3390 gdk_window_shape_combine_mask (GdkWindow *window,
3391                                GdkBitmap *mask,
3392                                gint x, gint y)
3393 {
3394   Pixmap pixmap;
3395   gint xoffset, yoffset;
3396   
3397   g_return_if_fail (window != NULL);
3398   g_return_if_fail (GDK_IS_WINDOW (window));
3399   
3400 #ifdef HAVE_SHAPE_EXT
3401   if (GDK_WINDOW_DESTROYED (window))
3402     return;
3403
3404   _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
3405
3406   if (xoffset != 0 || yoffset != 0)
3407     {
3408       WARN_SHAPE_TOO_BIG ();
3409       return;
3410     }
3411   
3412   if (gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
3413     {
3414       if (mask)
3415         {
3416           pixmap = GDK_PIXMAP_XID (mask);
3417         }
3418       else
3419         {
3420           x = 0;
3421           y = 0;
3422           pixmap = None;
3423         }
3424       
3425       XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
3426                          GDK_WINDOW_XID (window),
3427                          ShapeBounding,
3428                          x, y,
3429                          pixmap,
3430                          ShapeSet);
3431     }
3432 #endif /* HAVE_SHAPE_EXT */
3433 }
3434
3435 /**
3436  * gdk_window_shape_combine_region:
3437  * @window: a #GdkWindow
3438  * @shape_region: region of window to be non-transparent
3439  * @offset_x: X position of @shape_region in @window coordinates
3440  * @offset_y: Y position of @shape_region in @window coordinates
3441  *
3442  * Makes pixels in @window outside @shape_region be transparent,
3443  * so that the window may be nonrectangular. See also
3444  * gdk_window_shape_combine_mask() to use a bitmap as the mask.
3445  *
3446  * If @shape_region is %NULL, the shape will be unset, so the whole
3447  * window will be opaque again. @offset_x and @offset_y are ignored
3448  * if @shape_region is %NULL.
3449  * 
3450  * On the X11 platform, this uses an X server extension which is
3451  * widely available on most common platforms, but not available on
3452  * very old X servers, and occasionally the implementation will be
3453  * buggy. On servers without the shape extension, this function
3454  * will do nothing.
3455  *
3456  * This function works on both toplevel and child windows.
3457  * 
3458  **/
3459 void
3460 gdk_window_shape_combine_region (GdkWindow *window,
3461                                  GdkRegion *shape_region,
3462                                  gint       offset_x,
3463                                  gint       offset_y)
3464 {
3465   gint xoffset, yoffset;
3466   
3467   g_return_if_fail (GDK_IS_WINDOW (window));
3468   
3469 #ifdef HAVE_SHAPE_EXT
3470   if (GDK_WINDOW_DESTROYED (window))
3471     return;
3472
3473   _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
3474
3475   if (xoffset != 0 || yoffset != 0)
3476     {
3477       WARN_SHAPE_TOO_BIG ();
3478       return;
3479     }
3480   
3481   if (shape_region == NULL)
3482     {
3483       /* Use NULL mask to unset the shape */
3484       gdk_window_shape_combine_mask (window, NULL, 0, 0);
3485       return;
3486     }
3487   
3488   if (gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
3489     {
3490       gint n_rects = 0;
3491       XRectangle *xrects = NULL;
3492
3493       _gdk_region_get_xrectangles (shape_region,
3494                                    0, 0,
3495                                    &xrects, &n_rects);
3496       
3497       XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
3498                                GDK_WINDOW_XID (window),
3499                                ShapeBounding,
3500                                offset_x, offset_y,
3501                                xrects, n_rects,
3502                                ShapeSet,
3503                                YXBanded);
3504
3505       g_free (xrects);
3506     }
3507 #endif /* HAVE_SHAPE_EXT */
3508 }
3509
3510
3511 /**
3512  * gdk_window_set_override_redirect:
3513  * @window: a toplevel #GdkWindow
3514  * @override_redirect: %TRUE if window should be override redirect
3515  *
3516  * An override redirect window is not under the control of the window manager.
3517  * This means it won't have a titlebar, won't be minimizable, etc. - it will
3518  * be entirely under the control of the application. The window manager
3519  * can't see the override redirect window at all.
3520  *
3521  * Override redirect should only be used for short-lived temporary
3522  * windows, such as popup menus. #GtkMenu uses an override redirect
3523  * window in its implementation, for example.
3524  * 
3525  **/
3526 void
3527 gdk_window_set_override_redirect (GdkWindow *window,
3528                                   gboolean override_redirect)
3529 {
3530   XSetWindowAttributes attr;
3531   
3532   g_return_if_fail (window != NULL);
3533   g_return_if_fail (GDK_IS_WINDOW (window));
3534
3535   if (!GDK_WINDOW_DESTROYED (window))
3536     {
3537       GdkWindowObject *private = (GdkWindowObject *)window;
3538       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
3539
3540       attr.override_redirect = (override_redirect? True : False);
3541       XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3542                                GDK_WINDOW_XID (window),
3543                                CWOverrideRedirect,
3544                                &attr);
3545
3546       impl->override_redirect = attr.override_redirect;
3547     }
3548 }
3549
3550 /**
3551  * gdk_window_set_accept_focus:
3552  * @window: a toplevel #GdkWindow
3553  * @accept_focus: %TRUE if the window should receive input focus
3554  *
3555  * Setting @accept_focus to %FALSE hints the desktop environment that the
3556  * window doesn't want to receive input focus. 
3557  *
3558  * On X, it is the responsibility of the window manager to interpret this 
3559  * hint. ICCCM-compliant window manager usually respect it.
3560  *
3561  * Since: 2.4 
3562  **/
3563 void
3564 gdk_window_set_accept_focus (GdkWindow *window,
3565                              gboolean accept_focus)
3566 {
3567   GdkWindowObject *private;
3568   g_return_if_fail (window != NULL);
3569   g_return_if_fail (GDK_IS_WINDOW (window));
3570
3571   private = (GdkWindowObject *)window;  
3572   
3573   accept_focus = accept_focus != FALSE;
3574
3575   if (private->accept_focus != accept_focus)
3576     {
3577       private->accept_focus = accept_focus;
3578
3579       if (!GDK_WINDOW_DESTROYED (window))
3580         update_wm_hints (window, FALSE);
3581     }
3582 }
3583
3584 /**
3585  * gdk_window_set_focus_on_map:
3586  * @window: a toplevel #GdkWindow
3587  * @focus_on_map: %TRUE if the window should receive input focus when mapped
3588  *
3589  * Setting @focus_on_map to %FALSE hints the desktop environment that the
3590  * window doesn't want to receive input focus when it is mapped.  
3591  * focus_on_map should be turned off for windows that aren't triggered
3592  * interactively (such as popups from network activity).
3593  *
3594  * On X, it is the responsibility of the window manager to interpret
3595  * this hint. Window managers following the freedesktop.org window
3596  * manager extension specification should respect it.
3597  *
3598  * Since: 2.6 
3599  **/
3600 void
3601 gdk_window_set_focus_on_map (GdkWindow *window,
3602                              gboolean focus_on_map)
3603 {
3604   GdkWindowObject *private;
3605   g_return_if_fail (window != NULL);
3606   g_return_if_fail (GDK_IS_WINDOW (window));
3607
3608   private = (GdkWindowObject *)window;  
3609   
3610   focus_on_map = focus_on_map != FALSE;
3611
3612   if (private->focus_on_map != focus_on_map)
3613     {
3614       private->focus_on_map = focus_on_map;
3615
3616       if ((!GDK_WINDOW_DESTROYED (window)) && (!private->focus_on_map))
3617         gdk_x11_window_set_user_time (window, 0);
3618     }
3619 }
3620
3621 /**
3622  * gdk_x11_window_set_user_time:
3623  * @window: A toplevel #GdkWindow
3624  * @timestamp: An XServer timestamp to which the property should be set
3625  *
3626  * The application can use this call to update the _NET_WM_USER_TIME
3627  * property on a toplevel window.  This property stores an Xserver
3628  * time which represents the time of the last user input event
3629  * received for this window.  This property may be used by the window
3630  * manager to alter the focus, stacking, and/or placement behavior of
3631  * windows when they are mapped depending on whether the new window
3632  * was created by a user action or is a "pop-up" window activated by a
3633  * timer or some other event.
3634  *
3635  * Note that this property is automatically updated by GDK, so this
3636  * function should only be used by applications which handle input
3637  * events bypassing GDK.
3638  *
3639  * Since: 2.6
3640  **/
3641 void
3642 gdk_x11_window_set_user_time (GdkWindow *window,
3643                               guint32    timestamp)
3644 {
3645   GdkDisplay *display;
3646   GdkDisplayX11 *display_x11;
3647   glong timestamp_long = (glong)timestamp;
3648
3649   g_return_if_fail (window != NULL);
3650   g_return_if_fail (GDK_IS_WINDOW (window));
3651
3652   if (GDK_WINDOW_DESTROYED (window))
3653     return;
3654
3655   display = gdk_drawable_get_display (window);
3656   display_x11 = GDK_DISPLAY_X11 (display);
3657
3658   XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
3659                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
3660                    XA_CARDINAL, 32, PropModeReplace,
3661                    (guchar *)&timestamp_long, 1);
3662
3663   if (timestamp_long != GDK_CURRENT_TIME)
3664     display_x11->user_time = timestamp_long;
3665 }
3666
3667 /**
3668  * gdk_window_set_icon_list:
3669  * @window: The #GdkWindow toplevel window to set the icon of.
3670  * @pixbufs: A list of pixbufs, of different sizes.
3671  *
3672  * Sets a list of icons for the window. One of these will be used
3673  * to represent the window when it has been iconified. The icon is
3674  * usually shown in an icon box or some sort of task bar. Which icon
3675  * size is shown depends on the window manager. The window manager
3676  * can scale the icon  but setting several size icons can give better
3677  * image quality since the window manager may only need to scale the
3678  * icon by a small amount or not at all.
3679  *
3680  **/
3681 void
3682 gdk_window_set_icon_list (GdkWindow *window,
3683                           GList     *pixbufs)
3684 {
3685   gulong *data;
3686   guchar *pixels;
3687   gulong *p;
3688   gint size;
3689   GList *l;
3690   GdkPixbuf *pixbuf;
3691   gint width, height, stride;
3692   gint x, y;
3693   gint n_channels;
3694   GdkDisplay *display;
3695   
3696   g_return_if_fail (GDK_IS_WINDOW (window));
3697
3698   if (GDK_WINDOW_DESTROYED (window))
3699     return;
3700
3701   display = gdk_drawable_get_display (window);
3702   
3703   l = pixbufs;
3704   size = 0;
3705   
3706   while (l)
3707     {
3708       pixbuf = l->data;
3709       g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3710
3711       width = gdk_pixbuf_get_width (pixbuf);
3712       height = gdk_pixbuf_get_height (pixbuf);
3713       
3714       size += 2 + width * height;
3715
3716       l = g_list_next (l);
3717     }
3718
3719   data = g_malloc (size * sizeof (gulong));
3720
3721   l = pixbufs;
3722   p = data;
3723   while (l)
3724     {
3725       pixbuf = l->data;
3726       
3727       width = gdk_pixbuf_get_width (pixbuf);
3728       height = gdk_pixbuf_get_height (pixbuf);
3729       stride = gdk_pixbuf_get_rowstride (pixbuf);
3730       n_channels = gdk_pixbuf_get_n_channels (pixbuf);
3731       
3732       *p++ = width;
3733       *p++ = height;
3734
3735       pixels = gdk_pixbuf_get_pixels (pixbuf);
3736
3737       for (y = 0; y < height; y++)
3738         {
3739           for (x = 0; x < width; x++)
3740             {
3741               guchar r, g, b, a;
3742               
3743               r = pixels[y*stride + x*n_channels + 0];
3744               g = pixels[y*stride + x*n_channels + 1];
3745               b = pixels[y*stride + x*n_channels + 2];
3746               if (n_channels >= 4)
3747                 a = pixels[y*stride + x*n_channels + 3];
3748               else
3749                 a = 255;
3750               
3751               *p++ = a << 24 | r << 16 | g << 8 | b ;
3752             }
3753         }
3754
3755       l = g_list_next (l);
3756     }
3757
3758   if (size > 0)
3759     {
3760       XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3761                        GDK_WINDOW_XID (window),
3762                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
3763                        XA_CARDINAL, 32,
3764                        PropModeReplace,
3765                        (guchar*) data, size);
3766     }
3767   else
3768     {
3769       XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3770                        GDK_WINDOW_XID (window),
3771                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
3772     }
3773   
3774   g_free (data);
3775 }
3776
3777 /**
3778  * gdk_window_set_icon:
3779  * @window: a toplevel #GdkWindow
3780  * @icon_window: a #GdkWindow to use for the icon, or %NULL to unset
3781  * @pixmap: a #GdkPixmap to use as the icon, or %NULL to unset
3782  * @mask: a 1-bit pixmap (#GdkBitmap) to use as mask for @pixmap, or %NULL to have none
3783  *
3784  * Sets the icon of @window as a pixmap or window. If using GTK+, investigate
3785  * gtk_window_set_default_icon_list() first, and then gtk_window_set_icon_list()
3786  * and gtk_window_set_icon(). If those don't meet your needs, look at
3787  * gdk_window_set_icon_list(). Only if all those are too high-level do you
3788  * want to fall back to gdk_window_set_icon().
3789  * 
3790  **/
3791 void          
3792 gdk_window_set_icon (GdkWindow *window, 
3793                      GdkWindow *icon_window,
3794                      GdkPixmap *pixmap,
3795                      GdkBitmap *mask)
3796 {
3797   GdkToplevelX11 *toplevel;
3798
3799   g_return_if_fail (window != NULL);
3800   g_return_if_fail (GDK_IS_WINDOW (window));
3801   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
3802   
3803   if (GDK_WINDOW_DESTROYED (window))
3804     return;
3805
3806   toplevel = _gdk_x11_window_get_toplevel (window);
3807
3808   if (toplevel->icon_window != icon_window)
3809     {
3810       if (toplevel->icon_window)
3811         g_object_unref (toplevel->icon_window);
3812       toplevel->icon_window = g_object_ref (icon_window);
3813     }
3814   
3815   if (toplevel->icon_pixmap != pixmap)
3816     {
3817       if (pixmap)
3818         g_object_ref (pixmap);
3819       if (toplevel->icon_pixmap)
3820         g_object_unref (toplevel->icon_pixmap);
3821       toplevel->icon_pixmap = pixmap;
3822     }
3823   
3824   if (toplevel->icon_mask != mask)
3825     {
3826       if (mask)
3827         g_object_ref (mask);
3828       if (toplevel->icon_mask)
3829         g_object_unref (toplevel->icon_mask);
3830       toplevel->icon_mask = mask;
3831     }
3832   
3833   update_wm_hints (window, FALSE);
3834 }
3835
3836 static gboolean
3837 gdk_window_icon_name_set (GdkWindow *window)
3838 {
3839   return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
3840                                                g_quark_from_static_string ("gdk-icon-name-set")));
3841 }
3842
3843 /**
3844  * gdk_window_set_icon_name:
3845  * @window: a toplevel #GdkWindow
3846  * @name: name of window while iconified (minimized)
3847  *
3848  * Windows may have a name used while minimized, distinct from the
3849  * name they display in their titlebar. Most of the time this is a bad
3850  * idea from a user interface standpoint. But you can set such a name
3851  * with this function, if you like.
3852  *
3853  **/
3854 void          
3855 gdk_window_set_icon_name (GdkWindow   *window, 
3856                           const gchar *name)
3857 {
3858   GdkDisplay *display;
3859   
3860   g_return_if_fail (window != NULL);
3861   g_return_if_fail (GDK_IS_WINDOW (window));
3862
3863   if (GDK_WINDOW_DESTROYED (window))
3864     return;
3865
3866   display = gdk_drawable_get_display (window);
3867
3868   g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
3869                       GUINT_TO_POINTER (TRUE));
3870
3871   XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3872                    GDK_WINDOW_XID (window),
3873                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
3874                    gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3875                    PropModeReplace, name, strlen (name));
3876   
3877   set_text_property (display, GDK_WINDOW_XID (window),
3878                      gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
3879                      name);
3880 }
3881
3882 /**
3883  * gdk_window_iconify:
3884  * @window: a toplevel #GdkWindow
3885  * 
3886  * Asks to iconify (minimize) @window. The window manager may choose
3887  * to ignore the request, but normally will honor it. Using
3888  * gtk_window_iconify() is preferred, if you have a #GtkWindow widget.
3889  *
3890  * This function only makes sense when @window is a toplevel window.
3891  *
3892  **/
3893 void
3894 gdk_window_iconify (GdkWindow *window)
3895 {
3896   GdkWindowObject *private;
3897   
3898   g_return_if_fail (window != NULL);
3899   g_return_if_fail (GDK_IS_WINDOW (window));
3900
3901   if (GDK_WINDOW_DESTROYED (window))
3902     return;
3903
3904   private = (GdkWindowObject*) window;
3905
3906   if (GDK_WINDOW_IS_MAPPED (window))
3907     {  
3908       XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
3909                       GDK_WINDOW_XWINDOW (window),
3910                       gdk_screen_get_number (GDK_WINDOW_SCREEN (window)));
3911     }
3912   else
3913     {
3914       /* Flip our client side flag, the real work happens on map. */
3915       gdk_synthesize_window_state (window,
3916                                    0,
3917                                    GDK_WINDOW_STATE_ICONIFIED);
3918     }
3919 }
3920
3921 /**
3922  * gdk_window_deiconify:
3923  * @window: a toplevel #GdkWindow
3924  *
3925  * Attempt to deiconify (unminimize) @window. On X11 the window manager may
3926  * choose to ignore the request to deiconify. When using GTK+,
3927  * use gtk_window_deiconify() instead of the #GdkWindow variant. Or better yet,
3928  * you probably want to use gtk_window_present(), which raises the window, focuses it,
3929  * unminimizes it, and puts it on the current desktop.
3930  *
3931  **/
3932 void
3933 gdk_window_deiconify (GdkWindow *window)
3934 {
3935   GdkWindowObject *private;
3936   
3937   g_return_if_fail (window != NULL);
3938   g_return_if_fail (GDK_IS_WINDOW (window));
3939
3940   if (GDK_WINDOW_DESTROYED (window))
3941     return;
3942
3943   private = (GdkWindowObject*) window;
3944
3945   if (GDK_WINDOW_IS_MAPPED (window))
3946     {  
3947       gdk_window_show (window);
3948     }
3949   else
3950     {
3951       /* Flip our client side flag, the real work happens on map. */
3952       gdk_synthesize_window_state (window,
3953                                    GDK_WINDOW_STATE_ICONIFIED,
3954                                    0);
3955     }
3956 }
3957
3958 /**
3959  * gdk_window_stick:
3960  * @window: a toplevel #GdkWindow
3961  *
3962  * "Pins" a window such that it's on all workspaces and does not scroll
3963  * with viewports, for window managers that have scrollable viewports.
3964  * (When using #GtkWindow, gtk_window_stick() may be more useful.)
3965  *
3966  * On the X11 platform, this function depends on window manager
3967  * support, so may have no effect with many window managers. However,
3968  * GDK will do the best it can to convince the window manager to stick
3969  * the window. For window managers that don't support this operation,
3970  * there's nothing you can do to force it to happen.
3971  * 
3972  **/
3973 void
3974 gdk_window_stick (GdkWindow *window)
3975 {
3976   g_return_if_fail (GDK_IS_WINDOW (window));
3977
3978   if (GDK_WINDOW_DESTROYED (window))
3979     return;
3980
3981   if (GDK_WINDOW_IS_MAPPED (window))
3982     {
3983       /* "stick" means stick to all desktops _and_ do not scroll with the
3984        * viewport. i.e. glue to the monitor glass in all cases.
3985        */
3986       
3987       XEvent xev;
3988
3989       /* Request stick during viewport scroll */
3990       gdk_wmspec_change_state (TRUE, window,
3991                                gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE),
3992                                0);
3993
3994       /* Request desktop 0xFFFFFFFF */
3995       xev.xclient.type = ClientMessage;
3996       xev.xclient.serial = 0;
3997       xev.xclient.send_event = True;
3998       xev.xclient.window = GDK_WINDOW_XWINDOW (window);
3999       xev.xclient.display = GDK_WINDOW_XDISPLAY (window);
4000       xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), 
4001                                                                         "_NET_WM_DESKTOP");
4002       xev.xclient.format = 32;
4003
4004       xev.xclient.data.l[0] = 0xFFFFFFFF;
4005       xev.xclient.data.l[1] = 0;
4006       xev.xclient.data.l[2] = 0;
4007       xev.xclient.data.l[3] = 0;
4008       xev.xclient.data.l[4] = 0;
4009
4010       XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
4011                   SubstructureRedirectMask | SubstructureNotifyMask,
4012                   &xev);
4013     }
4014   else
4015     {
4016       /* Flip our client side flag, the real work happens on map. */
4017       gdk_synthesize_window_state (window,
4018                                    0,
4019                                    GDK_WINDOW_STATE_STICKY);
4020     }
4021 }
4022
4023 /**
4024  * gdk_window_unstick:
4025  * @window: a toplevel #GdkWindow
4026  *
4027  * Reverse operation for gdk_window_stick(); see gdk_window_stick(),
4028  * and gtk_window_unstick().
4029  * 
4030  **/
4031 void
4032 gdk_window_unstick (GdkWindow *window)
4033 {
4034   g_return_if_fail (GDK_IS_WINDOW (window));
4035
4036   if (GDK_WINDOW_DESTROYED (window))
4037     return;
4038
4039   if (GDK_WINDOW_IS_MAPPED (window))
4040     {
4041       XEvent xev;
4042       Atom type;
4043       gint format;
4044       gulong nitems;
4045       gulong bytes_after;
4046       gulong *current_desktop;
4047       GdkDisplay *display = gdk_drawable_get_display (window);
4048       
4049       /* Request unstick from viewport */
4050       gdk_wmspec_change_state (FALSE, window,
4051                                gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE),
4052                                0);
4053
4054       /* Get current desktop, then set it; this is a race, but not
4055        * one that matters much in practice.
4056        */
4057       XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window),
4058                           gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
4059                           0, G_MAXLONG,
4060                           False, XA_CARDINAL, &type, &format, &nitems,
4061                           &bytes_after, (guchar **)&current_desktop);
4062
4063       if (type == XA_CARDINAL)
4064         {
4065           xev.xclient.type = ClientMessage;
4066           xev.xclient.serial = 0;
4067           xev.xclient.send_event = True;
4068           xev.xclient.window = GDK_WINDOW_XWINDOW (window);
4069           xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
4070           xev.xclient.format = 32;
4071
4072           xev.xclient.data.l[0] = *current_desktop;
4073           xev.xclient.data.l[1] = 0;
4074           xev.xclient.data.l[2] = 0;
4075           xev.xclient.data.l[3] = 0;
4076           xev.xclient.data.l[4] = 0;
4077       
4078           XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
4079                       SubstructureRedirectMask | SubstructureNotifyMask,
4080                       &xev);
4081
4082           XFree (current_desktop);
4083         }
4084     }
4085   else
4086     {
4087       /* Flip our client side flag, the real work happens on map. */
4088       gdk_synthesize_window_state (window,
4089                                    GDK_WINDOW_STATE_STICKY,
4090                                    0);
4091
4092     }
4093 }
4094
4095 /**
4096  * gdk_window_maximize:
4097  * @window: a toplevel #GdkWindow
4098  *
4099  * Maximizes the window. If the window was already maximized, then
4100  * this function does nothing.
4101  * 
4102  * On X11, asks the window manager to maximize @window, if the window
4103  * manager supports this operation. Not all window managers support
4104  * this, and some deliberately ignore it or don't have a concept of
4105  * "maximized"; so you can't rely on the maximization actually
4106  * happening. But it will happen with most standard window managers,
4107  * and GDK makes a best effort to get it to happen.
4108  *
4109  * On Windows, reliably maximizes the window.
4110  * 
4111  **/
4112 void
4113 gdk_window_maximize (GdkWindow *window)
4114 {
4115   g_return_if_fail (GDK_IS_WINDOW (window));
4116
4117   if (GDK_WINDOW_DESTROYED (window))
4118     return;
4119
4120   if (GDK_WINDOW_IS_MAPPED (window))
4121     gdk_wmspec_change_state (TRUE, window,
4122                              gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE),
4123                              gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE));
4124   else
4125     gdk_synthesize_window_state (window,
4126                                  0,
4127                                  GDK_WINDOW_STATE_MAXIMIZED);
4128 }
4129
4130 /**
4131  * gdk_window_unmaximize:
4132  * @window: a toplevel #GdkWindow
4133  *
4134  * Unmaximizes the window. If the window wasn't maximized, then this
4135  * function does nothing.
4136  * 
4137  * On X11, asks the window manager to unmaximize @window, if the
4138  * window manager supports this operation. Not all window managers
4139  * support this, and some deliberately ignore it or don't have a
4140  * concept of "maximized"; so you can't rely on the unmaximization
4141  * actually happening. But it will happen with most standard window
4142  * managers, and GDK makes a best effort to get it to happen.
4143  *
4144  * On Windows, reliably unmaximizes the window.
4145  * 
4146  **/
4147 void
4148 gdk_window_unmaximize (GdkWindow *window)
4149 {
4150   g_return_if_fail (GDK_IS_WINDOW (window));
4151
4152   if (GDK_WINDOW_DESTROYED (window))
4153     return;
4154
4155   if (GDK_WINDOW_IS_MAPPED (window))
4156     gdk_wmspec_change_state (FALSE, window,
4157                              gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE),
4158                              gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE));
4159   else
4160     gdk_synthesize_window_state (window,
4161                                  GDK_WINDOW_STATE_MAXIMIZED,
4162                                  0);
4163 }
4164
4165 /**
4166  * gdk_window_fullscreen:
4167  * @window: a toplevel #GdkWindow
4168  *
4169  * Moves the window into fullscreen mode. This means the
4170  * window covers the entire screen and is above any panels
4171  * or task bars.
4172  *
4173  * If the window was already fullscreen, then this function does nothing.
4174  * 
4175  * On X11, asks the window manager to put @window in a fullscreen
4176  * state, if the window manager supports this operation. Not all
4177  * window managers support this, and some deliberately ignore it or
4178  * don't have a concept of "fullscreen"; so you can't rely on the
4179  * fullscreenification actually happening. But it will happen with
4180  * most standard window managers, and GDK makes a best effort to get
4181  * it to happen.
4182  *
4183  * Since: 2.2
4184  **/
4185 void
4186 gdk_window_fullscreen (GdkWindow *window)
4187 {
4188   g_return_if_fail (GDK_IS_WINDOW (window));
4189
4190   if (GDK_WINDOW_DESTROYED (window))
4191     return;
4192
4193   if (GDK_WINDOW_IS_MAPPED (window))
4194     gdk_wmspec_change_state (TRUE, window,
4195                              gdk_atom_intern ("_NET_WM_STATE_FULLSCREEN", FALSE),
4196                              GDK_NONE);
4197
4198   else
4199     gdk_synthesize_window_state (window,
4200                                  0,
4201                                  GDK_WINDOW_STATE_FULLSCREEN);
4202 }
4203
4204 /**
4205  * gdk_window_unfullscreen:
4206  * @window: a toplevel #GdkWindow
4207  *
4208  * Moves the window out of fullscreen mode. If the window was not
4209  * fullscreen, does nothing.
4210  * 
4211  * On X11, asks the window manager to move @window out of the fullscreen
4212  * state, if the window manager supports this operation. Not all
4213  * window managers support this, and some deliberately ignore it or
4214  * don't have a concept of "fullscreen"; so you can't rely on the
4215  * unfullscreenification actually happening. But it will happen with
4216  * most standard window managers, and GDK makes a best effort to get
4217  * it to happen. 
4218  *
4219  * Since: 2.2
4220  **/
4221 void
4222 gdk_window_unfullscreen (GdkWindow *window)
4223 {
4224   g_return_if_fail (GDK_IS_WINDOW (window));
4225
4226   if (GDK_WINDOW_DESTROYED (window))
4227     return;
4228
4229   if (GDK_WINDOW_IS_MAPPED (window))
4230     gdk_wmspec_change_state (FALSE, window,
4231                              gdk_atom_intern ("_NET_WM_STATE_FULLSCREEN", FALSE),
4232                              GDK_NONE);
4233
4234   else
4235     gdk_synthesize_window_state (window,
4236                                  GDK_WINDOW_STATE_FULLSCREEN,
4237                                  0);
4238 }
4239
4240 /**
4241  * gdk_window_set_keep_above:
4242  * @window: a toplevel #GdkWindow
4243  * @setting: whether to keep @window above other windows
4244  *
4245  * Set if @window must be kept above other windows. If the
4246  * window was already above, then this function does nothing.
4247  * 
4248  * On X11, asks the window manager to keep @window above, if the window
4249  * manager supports this operation. Not all window managers support
4250  * this, and some deliberately ignore it or don't have a concept of
4251  * "keep above"; so you can't rely on the window being kept above.
4252  * But it will happen with most standard window managers,
4253  * and GDK makes a best effort to get it to happen.
4254  *
4255  * Since: 2.4
4256  **/
4257 void
4258 gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
4259 {
4260   g_return_if_fail (GDK_IS_WINDOW (window));
4261
4262   if (GDK_WINDOW_DESTROYED (window))
4263     return;
4264
4265   if (GDK_WINDOW_IS_MAPPED (window))
4266     gdk_wmspec_change_state (setting, window,
4267                              gdk_atom_intern ("_NET_WM_STATE_ABOVE", setting),
4268                              setting ? gdk_atom_intern ("_NET_WM_STATE_BELOW", FALSE)
4269                                 : GDK_NONE);
4270   else
4271     gdk_synthesize_window_state (window,
4272                                  setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
4273                                  setting ? GDK_WINDOW_STATE_ABOVE : 0);
4274 }
4275
4276 /**
4277  * gdk_window_set_keep_below:
4278  * @window: a toplevel #GdkWindow
4279  * @setting: whether to keep @window below other windows
4280  *
4281  * Set if @window must be kept below other windows. If the
4282  * window was already below, then this function does nothing.
4283  * 
4284  * On X11, asks the window manager to keep @window below, if the window
4285  * manager supports this operation. Not all window managers support
4286  * this, and some deliberately ignore it or don't have a concept of
4287  * "keep below"; so you can't rely on the window being kept below.
4288  * But it will happen with most standard window managers,
4289  * and GDK makes a best effort to get it to happen.
4290  *
4291  * Since: 2.4
4292  **/
4293 void
4294 gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
4295 {
4296   g_return_if_fail (GDK_IS_WINDOW (window));
4297
4298   if (GDK_WINDOW_DESTROYED (window))
4299     return;
4300
4301   if (GDK_WINDOW_IS_MAPPED (window))
4302     gdk_wmspec_change_state (setting, window,
4303                              gdk_atom_intern ("_NET_WM_STATE_BELOW", setting),
4304                              setting ? gdk_atom_intern ("_NET_WM_STATE_ABOVE", FALSE)
4305                                  : GDK_NONE);
4306   else
4307     gdk_synthesize_window_state (window,
4308                                  setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
4309                                  setting ? GDK_WINDOW_STATE_BELOW : 0);
4310 }
4311
4312 /**
4313  * gdk_window_get_group:
4314  * @window: a toplevel #GdkWindow
4315  * 
4316  * Returns the group leader window for @window. See gdk_window_set_group().
4317  * 
4318  * Return value: the group leader window for @window
4319  *
4320  * Since: 2.4
4321  **/
4322 GdkWindow *
4323 gdk_window_get_group (GdkWindow *window)
4324 {
4325   GdkToplevelX11 *toplevel;
4326   
4327   g_return_val_if_fail (window != NULL, NULL);
4328   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
4329   g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
4330
4331   if (GDK_WINDOW_DESTROYED (window))
4332     return NULL;
4333   
4334   toplevel = _gdk_x11_window_get_toplevel (window);
4335
4336   return toplevel->group_leader;
4337 }
4338
4339 /**
4340  * gdk_window_set_group:
4341  * @window: a toplevel #GdkWindow
4342  * @leader: group leader window, or %NULL to restore the default group leader window
4343  *
4344  * Sets the group leader window for @window. By default,
4345  * GDK sets the group leader for all toplevel windows
4346  * to a global window implicitly created by GDK. With this function
4347  * you can override this default.
4348  *
4349  * The group leader window allows the window manager to distinguish
4350  * all windows that belong to a single application. It may for example
4351  * allow users to minimize/unminimize all windows belonging to an
4352  * application at once. You should only set a non-default group window
4353  * if your application pretends to be multiple applications.
4354  **/
4355 void          
4356 gdk_window_set_group (GdkWindow *window, 
4357                       GdkWindow *leader)
4358 {
4359   GdkToplevelX11 *toplevel;
4360   
4361   g_return_if_fail (window != NULL);
4362   g_return_if_fail (GDK_IS_WINDOW (window));
4363   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
4364   g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
4365
4366   if (GDK_WINDOW_DESTROYED (window) || (leader != NULL && GDK_WINDOW_DESTROYED (leader)))
4367     return;
4368
4369   toplevel = _gdk_x11_window_get_toplevel (window);
4370
4371   if (leader == NULL) 
4372     leader = gdk_display_get_default_group (gdk_drawable_get_display (window));
4373   
4374   if (toplevel->group_leader != leader)
4375     {
4376       if (toplevel->group_leader)
4377         g_object_unref (toplevel->group_leader);
4378       toplevel->group_leader = g_object_ref (leader);
4379     }
4380
4381   update_wm_hints (window, FALSE);
4382 }
4383
4384 static MotifWmHints *
4385 gdk_window_get_mwm_hints (GdkWindow *window)
4386 {
4387   GdkDisplay *display;
4388   Atom hints_atom = None;
4389   MotifWmHints *hints;
4390   Atom type;
4391   gint format;
4392   gulong nitems;
4393   gulong bytes_after;
4394   
4395   if (GDK_WINDOW_DESTROYED (window))
4396     return NULL;
4397
4398   display = gdk_drawable_get_display (window);
4399   
4400   hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4401
4402   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
4403                       hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4404                       False, AnyPropertyType, &type, &format, &nitems,
4405                       &bytes_after, (guchar **)&hints);
4406
4407   if (type == None)
4408     return NULL;
4409   
4410   return hints;
4411 }
4412
4413 static void
4414 gdk_window_set_mwm_hints (GdkWindow *window,
4415                           MotifWmHints *new_hints)
4416 {
4417   GdkDisplay *display;
4418   Atom hints_atom = None;
4419   MotifWmHints *hints;
4420   Atom type;
4421   gint format;
4422   gulong nitems;
4423   gulong bytes_after;
4424   
4425   if (GDK_WINDOW_DESTROYED (window))
4426     return;
4427   
4428   display = gdk_drawable_get_display (window);
4429   
4430   hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4431
4432   XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4433                       hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4434                       False, AnyPropertyType, &type, &format, &nitems,
4435                       &bytes_after, (guchar **)&hints);
4436   
4437   if (type == None)
4438     hints = new_hints;
4439   else
4440     {
4441       if (new_hints->flags & MWM_HINTS_FUNCTIONS)
4442         {
4443           hints->flags |= MWM_HINTS_FUNCTIONS;
4444           hints->functions = new_hints->functions;
4445         }
4446       if (new_hints->flags & MWM_HINTS_DECORATIONS)
4447         {
4448           hints->flags |= MWM_HINTS_DECORATIONS;
4449           hints->decorations = new_hints->decorations;
4450         }
4451     }
4452   
4453   XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4454                    hints_atom, hints_atom, 32, PropModeReplace,
4455                    (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
4456   
4457   if (hints != new_hints)
4458     XFree (hints);
4459 }
4460
4461 /**
4462  * gdk_window_set_decorations:
4463  * @window: a toplevel #GdkWindow
4464  * @decorations: decoration hint mask
4465  *
4466  * "Decorations" are the features the window manager adds to a toplevel #GdkWindow.
4467  * This function sets the traditional Motif window manager hints that tell the
4468  * window manager which decorations you would like your window to have.
4469  * Usually you should use gtk_window_set_decorated() on a #GtkWindow instead of
4470  * using the GDK function directly.
4471  *
4472  * The @decorations argument is the logical OR of the fields in
4473  * the #GdkWMDecoration enumeration. If #GDK_DECOR_ALL is included in the
4474  * mask, the other bits indicate which decorations should be turned off.
4475  * If #GDK_DECOR_ALL is not included, then the other bits indicate
4476  * which decorations should be turned on.
4477  *
4478  * Most window managers honor a decorations hint of 0 to disable all decorations,
4479  * but very few honor all possible combinations of bits.
4480  * 
4481  **/
4482 void
4483 gdk_window_set_decorations (GdkWindow      *window,
4484                             GdkWMDecoration decorations)
4485 {
4486   MotifWmHints hints;
4487   
4488   g_return_if_fail (window != NULL);
4489   g_return_if_fail (GDK_IS_WINDOW (window));
4490   
4491   hints.flags = MWM_HINTS_DECORATIONS;
4492   hints.decorations = decorations;
4493   
4494   gdk_window_set_mwm_hints (window, &hints);
4495 }
4496
4497 /**
4498  * gdk_window_get_decorations:
4499  * @window: The toplevel #GdkWindow to get the decorations from
4500  * @decorations: The window decorations will be written here
4501  *
4502  * Returns the decorations set on the GdkWindow with #gdk_window_set_decorations
4503  * Returns: TRUE if the window has decorations set, FALSE otherwise.
4504  **/
4505 gboolean
4506 gdk_window_get_decorations(GdkWindow       *window,
4507                            GdkWMDecoration *decorations)
4508 {
4509   MotifWmHints *hints;
4510   gboolean result = FALSE;
4511
4512   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
4513
4514   hints = gdk_window_get_mwm_hints (window);
4515   
4516   if (hints)
4517     {
4518       if (hints->flags & MWM_HINTS_DECORATIONS)
4519         {
4520           if (decorations)
4521             *decorations = hints->decorations;
4522           result = TRUE;
4523         }
4524       
4525       XFree (hints);
4526     }
4527
4528   return result;
4529 }
4530
4531 /**
4532  * gdk_window_set_functions:
4533  * @window: a toplevel #GdkWindow
4534  * @functions: bitmask of operations to allow on @window
4535  *
4536  * This function isn't really good for much. It sets the traditional
4537  * Motif window manager hint for which operations the window manager
4538  * should allow on a toplevel window. However, few window managers do
4539  * anything reliable or interesting with this hint. Many ignore it
4540  * entirely.
4541  *
4542  * The @functions argument is the logical OR of values from the
4543  * #GdkWMFunction enumeration. If the bitmask includes #GDK_FUNC_ALL,
4544  * then the other bits indicate which functions to disable; if
4545  * it doesn't include #GDK_FUNC_ALL, it indicates which functions to
4546  * enable.
4547  * 
4548  **/
4549 void
4550 gdk_window_set_functions (GdkWindow    *window,
4551                           GdkWMFunction functions)
4552 {
4553   MotifWmHints hints;
4554   
4555   g_return_if_fail (window != NULL);
4556   g_return_if_fail (GDK_IS_WINDOW (window));
4557   
4558   hints.flags = MWM_HINTS_FUNCTIONS;
4559   hints.functions = functions;
4560   
4561   gdk_window_set_mwm_hints (window, &hints);
4562 }
4563
4564 #ifdef HAVE_SHAPE_EXT
4565
4566 /* 
4567  * propagate the shapes from all child windows of a GDK window to the parent 
4568  * window. Shamelessly ripped from Enlightenment's code
4569  * 
4570  * - Raster
4571  */
4572 struct _gdk_span
4573 {
4574   gint                start;
4575   gint                end;
4576   struct _gdk_span    *next;
4577 };
4578
4579 static void
4580 gdk_add_to_span (struct _gdk_span **s,
4581                  gint               x,
4582                  gint               xx)
4583 {
4584   struct _gdk_span *ptr1, *ptr2, *noo, *ss;
4585   gchar             spanning;
4586   
4587   ptr2 = NULL;
4588   ptr1 = *s;
4589   spanning = 0;
4590   ss = NULL;
4591   /* scan the spans for this line */
4592   while (ptr1)
4593     {
4594       /* -- -> new span */
4595       /* == -> existing span */
4596       /* ## -> spans intersect */
4597       /* if we are in the middle of spanning the span into the line */
4598       if (spanning)
4599         {
4600           /* case: ---- ==== */
4601           if (xx < ptr1->start - 1)
4602             {
4603               /* ends before next span - extend to here */
4604               ss->end = xx;
4605               return;
4606             }
4607           /* case: ----##=== */
4608           else if (xx <= ptr1->end)
4609             {
4610               /* crosses into next span - delete next span and append */
4611               ss->end = ptr1->end;
4612               ss->next = ptr1->next;
4613               g_free (ptr1);
4614               return;
4615             }
4616           /* case: ---###--- */
4617           else
4618             {
4619               /* overlaps next span - delete and keep checking */
4620               ss->next = ptr1->next;
4621               g_free (ptr1);
4622               ptr1 = ss;
4623             }
4624         }
4625       /* otherwise havent started spanning it in yet */
4626       else
4627         {
4628           /* case: ---- ==== */
4629           if (xx < ptr1->start - 1)
4630             {
4631               /* insert span here in list */
4632               noo = g_malloc (sizeof (struct _gdk_span));
4633               
4634               if (noo)
4635                 {
4636                   noo->start = x;
4637                   noo->end = xx;
4638                   noo->next = ptr1;
4639                   if (ptr2)
4640                     ptr2->next = noo;
4641                   else
4642                     *s = noo;
4643                 }
4644               return;
4645             }
4646           /* case: ----##=== */
4647           else if ((x < ptr1->start) && (xx <= ptr1->end))
4648             {
4649               /* expand this span to the left point of the new one */
4650               ptr1->start = x;
4651               return;
4652             }
4653           /* case: ===###=== */
4654           else if ((x >= ptr1->start) && (xx <= ptr1->end))
4655             {
4656               /* throw the span away */
4657               return;
4658             }
4659           /* case: ---###--- */
4660           else if ((x < ptr1->start) && (xx > ptr1->end))
4661             {
4662               ss = ptr1;
4663               spanning = 1;
4664               ptr1->start = x;
4665               ptr1->end = xx;
4666             }
4667           /* case: ===##---- */
4668           else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end))
4669             {
4670               ss = ptr1;
4671               spanning = 1;
4672               ptr1->end = xx;
4673             }
4674           /* case: ==== ---- */
4675           /* case handled by next loop iteration - first case */
4676         }
4677       ptr2 = ptr1;
4678       ptr1 = ptr1->next;
4679     }
4680   /* it started in the middle but spans beyond your current list */
4681   if (spanning)
4682     {
4683       ptr2->end = xx;
4684       return;
4685     }
4686   /* it does not start inside a span or in the middle, so add it to the end */
4687   noo = g_malloc (sizeof (struct _gdk_span));
4688   
4689   if (noo)
4690     {
4691       noo->start = x;
4692       noo->end = xx;
4693       if (ptr2)
4694         {
4695           noo->next = ptr2->next;
4696           ptr2->next = noo;
4697         }
4698       else
4699         {
4700           noo->next = NULL;
4701           *s = noo;
4702         }
4703     }
4704   return;
4705 }
4706
4707 static void
4708 gdk_add_rectangles (Display           *disp,
4709                     Window             win,
4710                     struct _gdk_span **spans,
4711                     gint               basew,
4712                     gint               baseh,
4713                     gint               x,
4714                     gint               y)
4715 {
4716   gint a, k;
4717   gint x1, y1, x2, y2;
4718   gint rn, ord;
4719   XRectangle *rl;
4720   
4721   rl = XShapeGetRectangles (disp, win, ShapeBounding, &rn, &ord);
4722   if (rl)
4723     {
4724       /* go through all clip rects in this window's shape */
4725       for (k = 0; k < rn; k++)
4726         {
4727           /* for each clip rect, add it to each line's spans */
4728           x1 = x + rl[k].x;
4729           x2 = x + rl[k].x + (rl[k].width - 1);
4730           y1 = y + rl[k].y;
4731           y2 = y + rl[k].y + (rl[k].height - 1);
4732           if (x1 < 0)
4733             x1 = 0;
4734           if (y1 < 0)
4735             y1 = 0;
4736           if (x2 >= basew)
4737             x2 = basew - 1;
4738           if (y2 >= baseh)
4739             y2 = baseh - 1;
4740           for (a = y1; a <= y2; a++)
4741             {
4742               if ((x2 - x1) >= 0)
4743                 gdk_add_to_span (&spans[a], x1, x2);
4744             }
4745         }
4746       XFree (rl);
4747     }
4748 }
4749
4750 static void
4751 gdk_propagate_shapes (Display *disp,
4752                       Window   win,
4753                       gboolean merge)
4754 {
4755   Window              rt, par, *list = NULL;
4756   gint                i, j, num = 0, num_rects = 0;
4757   gint                x, y, contig;
4758   guint               w, h, d;
4759   gint                baseh, basew;
4760   XRectangle         *rects = NULL;
4761   struct _gdk_span  **spans = NULL, *ptr1, *ptr2, *ptr3;
4762   XWindowAttributes   xatt;
4763   
4764   XGetGeometry (disp, win, &rt, &x, &y, &w, &h, &d, &d);
4765   if (h <= 0)
4766     return;
4767   basew = w;
4768   baseh = h;
4769   spans = g_malloc (sizeof (struct _gdk_span *) * h);
4770   
4771   for (i = 0; i < h; i++)
4772     spans[i] = NULL;
4773   XQueryTree (disp, win, &rt, &par, &list, (unsigned int *)&num);
4774   if (list)
4775     {
4776       /* go through all child windows and create/insert spans */
4777       for (i = 0; i < num; i++)
4778         {
4779           if (XGetWindowAttributes (disp, list[i], &xatt) && (xatt.map_state != IsUnmapped))
4780             if (XGetGeometry (disp, list[i], &rt, &x, &y, &w, &h, &d, &d))
4781               gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y);
4782         }
4783       if (merge)
4784         gdk_add_rectangles (disp, win, spans, basew, baseh, x, y);
4785       
4786       /* go through the spans list and build a list of rects */
4787       rects = g_malloc (sizeof (XRectangle) * 256);
4788       num_rects = 0;
4789       for (i = 0; i < baseh; i++)
4790         {
4791           ptr1 = spans[i];
4792           /* go through the line for all spans */
4793           while (ptr1)
4794             {
4795               rects[num_rects].x = ptr1->start;
4796               rects[num_rects].y = i;
4797               rects[num_rects].width = ptr1->end - ptr1->start + 1;
4798               rects[num_rects].height = 1;
4799               j = i + 1;
4800               /* if there are more lines */
4801               contig = 1;
4802               /* while contigous rects (same start/end coords) exist */
4803               while ((contig) && (j < baseh))
4804                 {
4805                   /* search next line for spans matching this one */
4806                   contig = 0;
4807                   ptr2 = spans[j];
4808                   ptr3 = NULL;
4809                   while (ptr2)
4810                     {
4811                       /* if we have an exact span match set contig */
4812                       if ((ptr2->start == ptr1->start) &&
4813                           (ptr2->end == ptr1->end))
4814                         {
4815                           contig = 1;
4816                           /* remove the span - not needed */
4817                           if (ptr3)
4818                             {
4819                               ptr3->next = ptr2->next;
4820                               g_free (ptr2);
4821                               ptr2 = NULL;
4822                             }
4823                           else
4824                             {
4825                               spans[j] = ptr2->next;
4826                               g_free (ptr2);
4827                               ptr2 = NULL;
4828                             }
4829                           break;
4830                         }
4831                       /* gone past the span point no point looking */
4832                       else if (ptr2->start < ptr1->start)
4833                         break;
4834                       if (ptr2)
4835                         {
4836                           ptr3 = ptr2;
4837                           ptr2 = ptr2->next;
4838                         }
4839                     }
4840                   /* if a contiguous span was found increase the rect h */
4841                   if (contig)
4842                     {
4843                       rects[num_rects].height++;
4844                       j++;
4845                     }
4846                 }
4847               /* up the rect count */
4848               num_rects++;
4849               /* every 256 new rects increase the rect array */
4850               if ((num_rects % 256) == 0)
4851                 rects = g_realloc (rects, sizeof (XRectangle) * (num_rects + 256));
4852               ptr1 = ptr1->next;
4853             }
4854         }
4855       /* set the rects as the shape mask */
4856       if (rects)
4857         {
4858           XShapeCombineRectangles (disp, win, ShapeBounding, 0, 0, rects, num_rects,
4859                                    ShapeSet, YXSorted);
4860           g_free (rects);
4861         }
4862       XFree (list);
4863     }
4864   /* free up all the spans we made */
4865   for (i = 0; i < baseh; i++)
4866     {
4867       ptr1 = spans[i];
4868       while (ptr1)
4869         {
4870           ptr2 = ptr1;
4871           ptr1 = ptr1->next;
4872           g_free (ptr2);
4873         }
4874     }
4875   g_free (spans);
4876 }
4877
4878 #endif /* HAVE_SHAPE_EXT */
4879
4880 /**
4881  * gdk_window_set_child_shapes:
4882  * @window: a #GdkWindow
4883  * 
4884  * Sets the shape mask of @window to the union of shape masks
4885  * for all children of @window, ignoring the shape mask of @window
4886  * itself. Contrast with gdk_window_merge_child_shapes() which includes
4887  * the shape mask of @window in the masks to be merged.
4888  **/
4889 void
4890 gdk_window_set_child_shapes (GdkWindow *window)
4891 {
4892   g_return_if_fail (window != NULL);
4893   g_return_if_fail (GDK_IS_WINDOW (window));
4894   
4895 #ifdef HAVE_SHAPE_EXT
4896   if (!GDK_WINDOW_DESTROYED (window) &&
4897       gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
4898     gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
4899                           GDK_WINDOW_XID (window), FALSE);
4900 #endif   
4901 }
4902
4903 /**
4904  * gdk_window_merge_child_shapes:
4905  * @window: a #GdkWindow
4906  * 
4907  * Merges the shape masks for any child windows into the
4908  * shape mask for @window. i.e. the union of all masks
4909  * for @window and its children will become the new mask
4910  * for @window. See gdk_window_shape_combine_mask().
4911  *
4912  * This function is distinct from gdk_window_set_child_shapes()
4913  * because it includes @window's shape mask in the set of shapes to
4914  * be merged.
4915  * 
4916  **/
4917 void
4918 gdk_window_merge_child_shapes (GdkWindow *window)
4919 {
4920   g_return_if_fail (window != NULL);
4921   g_return_if_fail (GDK_IS_WINDOW (window));
4922   
4923 #ifdef HAVE_SHAPE_EXT
4924   if (!GDK_WINDOW_DESTROYED (window) &&
4925       gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
4926     gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
4927                           GDK_WINDOW_XID (window), TRUE);
4928 #endif   
4929 }
4930
4931 static void
4932 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
4933 {
4934   XSetWindowAttributes xattributes;
4935   GdkWindowObject *private;
4936   guint xattributes_mask = 0;
4937   
4938   g_return_if_fail (window != NULL);
4939
4940   private = GDK_WINDOW_OBJECT (window);
4941   if (private->input_only)
4942     return;
4943   
4944   xattributes.bit_gravity = StaticGravity;
4945   xattributes_mask |= CWBitGravity;
4946   xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
4947   XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4948                            GDK_WINDOW_XID (window),
4949                            CWBitGravity,  &xattributes);
4950 }
4951
4952 static void
4953 gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
4954 {
4955   XSetWindowAttributes xattributes;
4956   
4957   g_return_if_fail (window != NULL);
4958   
4959   xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
4960   
4961   XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4962                            GDK_WINDOW_XID (window),
4963                            CWWinGravity,  &xattributes);
4964 }
4965
4966 /**
4967  * gdk_window_set_static_gravities:
4968  * @window: a #GdkWindow
4969  * @use_static: %TRUE to turn on static gravity
4970  *
4971  * Set the bit gravity of the given window to static, and flag it so
4972  * all children get static subwindow gravity. This is used if you are
4973  * implementing scary features that involve deep knowledge of the
4974  * windowing system. Don't worry about it unless you have to.
4975  * 
4976  * Return value: %TRUE if the server supports static gravity
4977  **/
4978 gboolean 
4979 gdk_window_set_static_gravities (GdkWindow *window,
4980                                  gboolean   use_static)
4981 {
4982   GdkWindowObject *private = (GdkWindowObject *)window;
4983   GList *tmp_list;
4984   
4985   g_return_val_if_fail (window != NULL, FALSE);
4986   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
4987
4988   if (!use_static == !private->guffaw_gravity)
4989     return TRUE;
4990
4991   private->guffaw_gravity = use_static;
4992   
4993   if (!GDK_WINDOW_DESTROYED (window))
4994     {
4995       gdk_window_set_static_bit_gravity (window, use_static);
4996       
4997       tmp_list = private->children;
4998       while (tmp_list)
4999         {
5000           gdk_window_set_static_win_gravity (tmp_list->data, use_static);
5001           
5002           tmp_list = tmp_list->next;
5003         }
5004     }
5005   
5006   return TRUE;
5007 }
5008
5009 static void
5010 wmspec_moveresize (GdkWindow *window,
5011                    gint       direction,
5012                    gint       root_x,
5013                    gint       root_y,
5014                    guint32    timestamp)     
5015 {
5016   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
5017   
5018   XEvent xev;
5019
5020   /* Release passive grab */
5021   gdk_display_pointer_ungrab (display, timestamp);
5022
5023   xev.xclient.type = ClientMessage;
5024   xev.xclient.serial = 0;
5025   xev.xclient.send_event = True;
5026   xev.xclient.window = GDK_WINDOW_XID (window);
5027   xev.xclient.message_type =
5028     gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
5029   xev.xclient.format = 32;
5030   xev.xclient.data.l[0] = root_x;
5031   xev.xclient.data.l[1] = root_y;
5032   xev.xclient.data.l[2] = direction;
5033   xev.xclient.data.l[3] = 0;
5034   xev.xclient.data.l[4] = 0;
5035   
5036   XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
5037               SubstructureRedirectMask | SubstructureNotifyMask,
5038               &xev);
5039 }
5040
5041 typedef struct _MoveResizeData MoveResizeData;
5042
5043 struct _MoveResizeData
5044 {
5045   GdkDisplay *display;
5046   
5047   GdkWindow *moveresize_window;
5048   GdkWindow *moveresize_emulation_window;
5049   gboolean is_resize;
5050   GdkWindowEdge resize_edge;
5051   gint moveresize_button;
5052   gint moveresize_x;
5053   gint moveresize_y;
5054   gint moveresize_orig_x;
5055   gint moveresize_orig_y;
5056   gint moveresize_orig_width;
5057   gint moveresize_orig_height;
5058   GdkWindowHints moveresize_geom_mask;
5059   GdkGeometry moveresize_geometry;
5060   Time moveresize_process_time;
5061   XEvent *moveresize_pending_event;
5062 };
5063
5064 /* From the WM spec */
5065 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT      0
5066 #define _NET_WM_MOVERESIZE_SIZE_TOP          1
5067 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT     2
5068 #define _NET_WM_MOVERESIZE_SIZE_RIGHT        3
5069 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT  4
5070 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM       5
5071 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT   6
5072 #define _NET_WM_MOVERESIZE_SIZE_LEFT         7
5073 #define _NET_WM_MOVERESIZE_MOVE              8
5074
5075 static void
5076 wmspec_resize_drag (GdkWindow     *window,
5077                     GdkWindowEdge  edge,
5078                     gint           button,
5079                     gint           root_x,
5080                     gint           root_y,
5081                     guint32        timestamp)
5082 {
5083   gint direction;
5084   
5085   /* Let the compiler turn a switch into a table, instead
5086    * of doing the table manually, this way is easier to verify.
5087    */
5088   switch (edge)
5089     {
5090     case GDK_WINDOW_EDGE_NORTH_WEST:
5091       direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
5092       break;
5093
5094     case GDK_WINDOW_EDGE_NORTH:
5095       direction = _NET_WM_MOVERESIZE_SIZE_TOP;
5096       break;
5097
5098     case GDK_WINDOW_EDGE_NORTH_EAST:
5099       direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
5100       break;
5101
5102     case GDK_WINDOW_EDGE_WEST:
5103       direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
5104       break;
5105
5106     case GDK_WINDOW_EDGE_EAST:
5107       direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
5108       break;
5109
5110     case GDK_WINDOW_EDGE_SOUTH_WEST:
5111       direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
5112       break;
5113
5114     case GDK_WINDOW_EDGE_SOUTH:
5115       direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
5116       break;
5117
5118     case GDK_WINDOW_EDGE_SOUTH_EAST:
5119       direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
5120       break;
5121
5122     default:
5123       g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
5124                  edge);
5125       return;
5126       break;
5127     }
5128   
5129   wmspec_moveresize (window, direction, root_x, root_y, timestamp);
5130 }
5131
5132 static MoveResizeData *
5133 get_move_resize_data (GdkDisplay *display,
5134                       gboolean    create)
5135 {
5136   MoveResizeData *mv_resize;
5137   static GQuark move_resize_quark = 0;
5138
5139   if (!move_resize_quark)
5140     move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
5141   
5142   mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
5143
5144   if (!mv_resize && create)
5145     {
5146       mv_resize = g_new0 (MoveResizeData, 1);
5147       mv_resize->display = display;
5148       
5149       g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
5150     }
5151
5152   return mv_resize;
5153 }
5154
5155 static void
5156 update_pos (MoveResizeData *mv_resize,
5157             gint            new_root_x,
5158             gint            new_root_y)
5159 {
5160   gint dx, dy;
5161
5162   dx = new_root_x - mv_resize->moveresize_x;
5163   dy = new_root_y - mv_resize->moveresize_y;
5164
5165   if (mv_resize->is_resize)
5166     {
5167       gint x, y, w, h;
5168
5169       x = mv_resize->moveresize_orig_x;
5170       y = mv_resize->moveresize_orig_y;
5171
5172       w = mv_resize->moveresize_orig_width;
5173       h = mv_resize->moveresize_orig_height;
5174
5175       switch (mv_resize->resize_edge)
5176         {
5177         case GDK_WINDOW_EDGE_NORTH_WEST:
5178           x += dx;
5179           y += dy;
5180           w -= dx;
5181           h -= dy;
5182           break;
5183         case GDK_WINDOW_EDGE_NORTH:
5184           y += dy;
5185           h -= dy;
5186           break;
5187         case GDK_WINDOW_EDGE_NORTH_EAST:
5188           y += dy;
5189           h -= dy;
5190           w += dx;
5191           break;
5192         case GDK_WINDOW_EDGE_SOUTH_WEST:
5193           h += dy;
5194           x += dx;
5195           w -= dx;
5196           break;
5197         case GDK_WINDOW_EDGE_SOUTH_EAST:
5198           w += dx;
5199           h += dy;
5200           break;
5201         case GDK_WINDOW_EDGE_SOUTH:
5202           h += dy;
5203           break;
5204         case GDK_WINDOW_EDGE_EAST:
5205           w += dx;
5206           break;
5207         case GDK_WINDOW_EDGE_WEST:
5208           x += dx;
5209           w -= dx;
5210           break;
5211         }
5212
5213       x = MAX (x, 0);
5214       y = MAX (y, 0);
5215       w = MAX (w, 1);
5216       h = MAX (h, 1);
5217
5218       if (mv_resize->moveresize_geom_mask)
5219         {
5220           gdk_window_constrain_size (&mv_resize->moveresize_geometry,
5221                                      mv_resize->moveresize_geom_mask,
5222                                      w, h, &w, &h);
5223         }
5224
5225       gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
5226     }
5227   else
5228     {
5229       gint x, y;
5230
5231       x = mv_resize->moveresize_orig_x + dx;
5232       y = mv_resize->moveresize_orig_y + dy;
5233
5234       gdk_window_move (mv_resize->moveresize_window, x, y);
5235     }
5236 }
5237
5238 static void
5239 finish_drag (MoveResizeData *mv_resize)
5240 {
5241   gdk_window_destroy (mv_resize->moveresize_emulation_window);
5242   mv_resize->moveresize_emulation_window = NULL;
5243   mv_resize->moveresize_window = NULL;
5244
5245   if (mv_resize->moveresize_pending_event)
5246     {
5247       g_free (mv_resize->moveresize_pending_event);
5248       mv_resize->moveresize_pending_event = NULL;
5249     }
5250 }
5251
5252 static int
5253 lookahead_motion_predicate (Display *xdisplay,
5254                             XEvent  *event,
5255                             XPointer arg)
5256 {
5257   gboolean *seen_release = (gboolean *)arg;
5258   GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
5259   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
5260
5261   if (*seen_release)
5262     return False;
5263
5264   switch (event->xany.type)
5265     {
5266     case ButtonRelease:
5267       *seen_release = TRUE;
5268       break;
5269     case MotionNotify:
5270       mv_resize->moveresize_process_time = event->xmotion.time;
5271       break;
5272     default:
5273       break;
5274     }
5275
5276   return False;
5277 }
5278
5279 static gboolean
5280 moveresize_lookahead (MoveResizeData *mv_resize,
5281                       XEvent         *event)
5282 {
5283   XEvent tmp_event;
5284   gboolean seen_release = FALSE;
5285
5286   if (mv_resize->moveresize_process_time)
5287     {
5288       if (event->xmotion.time == mv_resize->moveresize_process_time)
5289         {
5290           mv_resize->moveresize_process_time = 0;
5291           return TRUE;
5292         }
5293       else
5294         return FALSE;
5295     }
5296
5297   XCheckIfEvent (event->xany.display, &tmp_event,
5298                  lookahead_motion_predicate, (XPointer) & seen_release);
5299
5300   return mv_resize->moveresize_process_time == 0;
5301 }
5302         
5303 gboolean
5304 _gdk_moveresize_handle_event (XEvent *event)
5305 {
5306   guint button_mask = 0;
5307   GdkWindowObject *window_private;
5308   GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
5309   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
5310
5311   if (!mv_resize || !mv_resize->moveresize_window)
5312     return FALSE;
5313
5314   window_private = (GdkWindowObject *) mv_resize->moveresize_window;
5315
5316   button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
5317
5318   switch (event->xany.type)
5319     {
5320     case MotionNotify:
5321       if (window_private->resize_count > 0)
5322         {
5323           if (mv_resize->moveresize_pending_event)
5324             *mv_resize->moveresize_pending_event = *event;
5325           else
5326             mv_resize->moveresize_pending_event =
5327               g_memdup (event, sizeof (XEvent));
5328
5329           break;
5330         }
5331       if (!moveresize_lookahead (mv_resize, event))
5332         break;
5333
5334       update_pos (mv_resize,
5335                   event->xmotion.x_root,
5336                   event->xmotion.y_root);
5337
5338       /* This should never be triggered in normal cases, but in the
5339        * case where the drag started without an implicit grab being
5340        * in effect, we could miss the release if it occurs before
5341        * we grab the pointer; this ensures that we will never
5342        * get a permanently stuck grab.
5343        */
5344       if ((event->xmotion.state & button_mask) == 0)
5345         finish_drag (mv_resize);
5346       break;
5347
5348     case ButtonRelease:
5349       update_pos (mv_resize,
5350                   event->xbutton.x_root,
5351                   event->xbutton.y_root);
5352
5353       if (event->xbutton.button == mv_resize->moveresize_button)
5354         finish_drag (mv_resize);
5355       break;
5356     }
5357   return TRUE;
5358 }
5359
5360 gboolean 
5361 _gdk_moveresize_configure_done (GdkDisplay *display,
5362                                 GdkWindow  *window)
5363 {
5364   XEvent *tmp_event;
5365   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
5366   
5367   if (!mv_resize || window != mv_resize->moveresize_window)
5368     return FALSE;
5369
5370   if (mv_resize->moveresize_pending_event)
5371     {
5372       tmp_event = mv_resize->moveresize_pending_event;
5373       mv_resize->moveresize_pending_event = NULL;
5374       _gdk_moveresize_handle_event (tmp_event);
5375       g_free (tmp_event);
5376     }
5377   
5378   return TRUE;
5379 }
5380
5381 static void
5382 create_moveresize_window (MoveResizeData *mv_resize,
5383                           guint32         timestamp)
5384 {
5385   GdkWindowAttr attributes;
5386   gint attributes_mask;
5387   GdkGrabStatus status;
5388
5389   g_assert (mv_resize->moveresize_emulation_window == NULL);
5390
5391   attributes.x = -100;
5392   attributes.y = -100;
5393   attributes.width = 10;
5394   attributes.height = 10;
5395   attributes.window_type = GDK_WINDOW_TEMP;
5396   attributes.wclass = GDK_INPUT_ONLY;
5397   attributes.override_redirect = TRUE;
5398   attributes.event_mask = 0;
5399
5400   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
5401
5402   mv_resize->moveresize_emulation_window = 
5403     gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
5404                     &attributes,
5405                     attributes_mask);
5406
5407   gdk_window_show (mv_resize->moveresize_emulation_window);
5408
5409   status = gdk_pointer_grab (mv_resize->moveresize_emulation_window,
5410                              FALSE,
5411                              GDK_BUTTON_RELEASE_MASK |
5412                              GDK_POINTER_MOTION_MASK,
5413                              NULL,
5414                              NULL,
5415                              timestamp);
5416
5417   if (status != GDK_GRAB_SUCCESS)
5418     {
5419       /* If this fails, some other client has grabbed the window
5420        * already.
5421        */
5422       gdk_window_destroy (mv_resize->moveresize_emulation_window);
5423       mv_resize->moveresize_emulation_window = NULL;
5424     }
5425
5426   mv_resize->moveresize_process_time = 0;
5427 }
5428
5429 /* 
5430    Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
5431    so that calling XMoveWindow with these coordinates will not move the 
5432    window.
5433    Note that this depends on the WM to implement ICCCM-compliant reference
5434    point handling.
5435 */
5436 static void 
5437 calculate_unmoving_origin (MoveResizeData *mv_resize)
5438 {
5439   GdkRectangle rect;
5440   gint width, height;
5441
5442   if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
5443       mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
5444     {
5445       gdk_window_get_origin (mv_resize->moveresize_window,
5446                              &mv_resize->moveresize_orig_x,
5447                              &mv_resize->moveresize_orig_y);
5448     }
5449   else
5450     {
5451       gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
5452       gdk_window_get_geometry (mv_resize->moveresize_window, 
5453                                NULL, NULL, &width, &height, NULL);
5454       
5455       switch (mv_resize->moveresize_geometry.win_gravity) 
5456         {
5457         case GDK_GRAVITY_NORTH_WEST:
5458           mv_resize->moveresize_orig_x = rect.x;
5459           mv_resize->moveresize_orig_y = rect.y;
5460           break;
5461         case GDK_GRAVITY_NORTH:
5462           mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
5463           mv_resize->moveresize_orig_y = rect.y;
5464           break;          
5465         case GDK_GRAVITY_NORTH_EAST:
5466           mv_resize->moveresize_orig_x = rect.x + rect.width - width;
5467           mv_resize->moveresize_orig_y = rect.y;
5468           break;
5469         case GDK_GRAVITY_WEST:
5470           mv_resize->moveresize_orig_x = rect.x;
5471           mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
5472           break;
5473         case GDK_GRAVITY_CENTER:
5474           mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
5475           mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
5476           break;
5477         case GDK_GRAVITY_EAST:
5478           mv_resize->moveresize_orig_x = rect.x + rect.width - width;
5479           mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
5480           break;
5481         case GDK_GRAVITY_SOUTH_WEST:
5482           mv_resize->moveresize_orig_x = rect.x;
5483           mv_resize->moveresize_orig_y = rect.y + rect.height - height;
5484           break;
5485         case GDK_GRAVITY_SOUTH:
5486           mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
5487           mv_resize->moveresize_orig_y = rect.y + rect.height - height;
5488           break;
5489         case GDK_GRAVITY_SOUTH_EAST:
5490           mv_resize->moveresize_orig_x = rect.x + rect.width - width;
5491           mv_resize->moveresize_orig_y = rect.y + rect.height - height;
5492           break;
5493         default:
5494           mv_resize->moveresize_orig_x = rect.x;
5495           mv_resize->moveresize_orig_y = rect.y;
5496           break; 
5497         }
5498     }  
5499 }
5500
5501 static void
5502 emulate_resize_drag (GdkWindow     *window,
5503                      GdkWindowEdge  edge,
5504                      gint           button,
5505                      gint           root_x,
5506                      gint           root_y,
5507                      guint32        timestamp)
5508 {
5509   MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
5510
5511   mv_resize->is_resize = TRUE;
5512   mv_resize->moveresize_button = button;
5513   mv_resize->resize_edge = edge;
5514   mv_resize->moveresize_x = root_x;
5515   mv_resize->moveresize_y = root_y;
5516   mv_resize->moveresize_window = g_object_ref (window);
5517
5518   gdk_drawable_get_size (window,
5519                          &mv_resize->moveresize_orig_width,
5520                          &mv_resize->moveresize_orig_height);
5521
5522   mv_resize->moveresize_geom_mask = 0;
5523   gdk_window_get_geometry_hints (window,
5524                                  &mv_resize->moveresize_geometry,
5525                                  &mv_resize->moveresize_geom_mask);
5526
5527   calculate_unmoving_origin (mv_resize);
5528
5529   create_moveresize_window (mv_resize, timestamp);
5530 }
5531
5532 static void
5533 emulate_move_drag (GdkWindow     *window,
5534                    gint           button,
5535                    gint           root_x,
5536                    gint           root_y,
5537                    guint32        timestamp)
5538 {
5539   MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
5540   
5541   mv_resize->is_resize = FALSE;
5542   mv_resize->moveresize_button = button;
5543   mv_resize->moveresize_x = root_x;
5544   mv_resize->moveresize_y = root_y;
5545
5546   mv_resize->moveresize_window = g_object_ref (window);
5547
5548   calculate_unmoving_origin (mv_resize);
5549
5550   create_moveresize_window (mv_resize, timestamp);
5551 }
5552
5553 /**
5554  * gdk_window_begin_resize_drag:
5555  * @window: a toplevel #GdkWindow
5556  * @edge: the edge or corner from which the drag is started
5557  * @button: the button being used to drag
5558  * @root_x: root window X coordinate of mouse click that began the drag
5559  * @root_y: root window Y coordinate of mouse click that began the drag
5560  * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
5561  *
5562  * Begins a window resize operation (for a toplevel window).
5563  * You might use this function to implement a "window resize grip," for
5564  * example; in fact #GtkStatusbar uses it. The function works best
5565  * with window managers that support the Extended Window Manager Hints spec
5566  * (see http://www.freedesktop.org), but has a fallback implementation
5567  * for other window managers.
5568  * 
5569  **/
5570 void
5571 gdk_window_begin_resize_drag (GdkWindow     *window,
5572                               GdkWindowEdge  edge,
5573                               gint           button,
5574                               gint           root_x,
5575                               gint           root_y,
5576                               guint32        timestamp)
5577 {
5578   g_return_if_fail (GDK_IS_WINDOW (window));
5579
5580   if (GDK_WINDOW_DESTROYED (window))
5581     return;
5582
5583   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5584                                            gdk_atom_intern ("_NET_WM_MOVERESIZE", FALSE)))
5585     wmspec_resize_drag (window, edge, button, root_x, root_y, timestamp);
5586   else
5587     emulate_resize_drag (window, edge, button, root_x, root_y, timestamp);
5588 }
5589
5590 /**
5591  * gdk_window_begin_move_drag:
5592  * @window: a toplevel #GdkWindow
5593  * @button: the button being used to drag
5594  * @root_x: root window X coordinate of mouse click that began the drag
5595  * @root_y: root window Y coordinate of mouse click that began the drag
5596  * @timestamp: timestamp of mouse click that began the drag
5597  *
5598  * Begins a window move operation (for a toplevel window).  You might
5599  * use this function to implement a "window move grip," for
5600  * example. The function works best with window managers that support
5601  * the Extended Window Manager Hints spec (see
5602  * http://www.freedesktop.org), but has a fallback implementation for
5603  * other window managers.
5604  * 
5605  **/
5606 void
5607 gdk_window_begin_move_drag (GdkWindow *window,
5608                             gint       button,
5609                             gint       root_x,
5610                             gint       root_y,
5611                             guint32    timestamp)
5612 {
5613   g_return_if_fail (GDK_IS_WINDOW (window));
5614
5615   if (GDK_WINDOW_DESTROYED (window))
5616     return;
5617
5618   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5619                                            gdk_atom_intern ("_NET_WM_MOVERESIZE", FALSE)))
5620     wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE, root_x, root_y,
5621                        timestamp);
5622   else
5623     emulate_move_drag (window, button, root_x, root_y, timestamp);
5624 }
5625
5626 /**
5627  * gdk_window_enable_synchronized_configure:
5628  * @window: a toplevel #GdkWindow
5629  * 
5630  * Indicates that the application will cooperate with the window
5631  * system in synchronizing the window repaint with the window
5632  * manager during resizing operations. After an application calls
5633  * this function, it must call gdk_window_configure_finished() every
5634  * time it has finished all processing associated with a set of
5635  * Configure events. Toplevel GTK+ windows automatically use this
5636  * protocol.
5637  * 
5638  * On X, calling this function makes @window participate in the
5639  * _NET_WM_SYNC_REQUEST window manager protocol.
5640  * 
5641  * Since: 2.6
5642  **/
5643 void
5644 gdk_window_enable_synchronized_configure (GdkWindow *window)
5645 {
5646   g_return_if_fail (GDK_IS_WINDOW (window));
5647   
5648 #ifdef HAVE_XSYNC
5649   if (!GDK_WINDOW_DESTROYED (window))
5650     {
5651       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
5652       GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
5653
5654       if (toplevel && toplevel->update_counter == None &&
5655           GDK_DISPLAY_X11 (display)->use_sync)
5656         {
5657           Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
5658           XSyncValue value;
5659           Atom atom;
5660           
5661           if (toplevel->update_counter != None)
5662             return;
5663           
5664           XSyncIntToValue (&value, 0);
5665           
5666           toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
5667           
5668           atom = gdk_x11_get_xatom_by_name_for_display (display,
5669                                                         "_NET_WM_SYNC_REQUEST_COUNTER");
5670           
5671           XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
5672                            atom, XA_CARDINAL,
5673                            32, PropModeReplace,
5674                            (guchar *)&toplevel->update_counter, 1);
5675           
5676           XSyncIntToValue (&toplevel->current_counter_value, 0);
5677         }
5678     }
5679 #endif /* HAVE_XSYNC */
5680 }
5681
5682 /**
5683  * gdk_window_configure_finished:
5684  * @window: a toplevel #GdkWindow
5685  * 
5686  * Signal to the window system that the application has finished
5687  * handling Configure events it has received. Window Managers can
5688  * use this to better synchronize the frame repaint with the
5689  * application. GTK+ applications will automatically call this
5690  * function when appropriate.
5691  *
5692  * This function can only be called if gdk_window_use_configure()
5693  * was called previously.
5694  *
5695  * Since: 2.6
5696  **/
5697 void
5698 gdk_window_configure_finished (GdkWindow *window)
5699 {
5700   g_return_if_fail (GDK_IS_WINDOW (window));
5701
5702 #ifdef HAVE_XSYNC
5703   if (!GDK_WINDOW_DESTROYED (window))
5704     {
5705       GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
5706       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
5707
5708       g_return_if_fail (toplevel->update_counter != None);
5709       
5710       if (toplevel && GDK_DISPLAY_X11 (display)->use_sync &&
5711           !XSyncValueIsZero (toplevel->current_counter_value))
5712         {
5713           XSyncSetCounter (GDK_WINDOW_XDISPLAY (window), 
5714                            toplevel->update_counter,
5715                            toplevel->current_counter_value);
5716           
5717           XSyncIntToValue (&toplevel->current_counter_value, 0);
5718         }
5719     }
5720 #endif
5721 }