]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkwindow-x11.c
Make this compile without framebuffer enabled
[~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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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-1999.  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 <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 #include <X11/Xatom.h>
30 #include <netinet/in.h>
31 #include "gdk.h"
32 #include "config.h"
33
34 #include "gdkwindow.h"
35 #include "gdkinputprivate.h"
36 #include "gdkprivate-x11.h"
37 #include "gdkregion.h"
38 #include "gdkinternals.h"
39 #include "MwmUtil.h"
40 #include "gdkwindow-x11.h"
41
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45
46
47 #ifdef HAVE_SHAPE_EXT
48 #include <X11/extensions/shape.h>
49 #endif
50
51 const int gdk_event_mask_table[21] =
52 {
53   ExposureMask,
54   PointerMotionMask,
55   PointerMotionHintMask,
56   ButtonMotionMask,
57   Button1MotionMask,
58   Button2MotionMask,
59   Button3MotionMask,
60   ButtonPressMask,
61   ButtonReleaseMask,
62   KeyPressMask,
63   KeyReleaseMask,
64   EnterWindowMask,
65   LeaveWindowMask,
66   FocusChangeMask,
67   StructureNotifyMask,
68   PropertyChangeMask,
69   VisibilityChangeMask,
70   0,                            /* PROXIMITY_IN */
71   0,                            /* PROXIMTY_OUT */
72   SubstructureNotifyMask,
73   ButtonPressMask      /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
74 };
75 const int gdk_nevent_masks = sizeof (gdk_event_mask_table) / sizeof (int);
76
77 /* Forward declarations */
78 static gboolean gdk_window_gravity_works (void);
79 static void     gdk_window_set_static_win_gravity (GdkWindow *window, 
80                                                    gboolean   on);
81 static gboolean gdk_window_have_shape_ext (void);
82
83 static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
84 static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
85                                                   GdkColormap *cmap);
86 static void         gdk_window_impl_x11_get_size     (GdkDrawable *drawable,
87                                                   gint *width,
88                                                   gint *height);
89 static void gdk_window_impl_x11_init       (GdkWindowImplX11      *window);
90 static void gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass);
91 static void gdk_window_impl_x11_finalize   (GObject            *object);
92
93 static gpointer parent_class = NULL;
94
95 GType
96 gdk_window_impl_x11_get_type (void)
97 {
98   static GType object_type = 0;
99
100   if (!object_type)
101     {
102       static const GTypeInfo object_info =
103       {
104         sizeof (GdkWindowImplX11Class),
105         (GBaseInitFunc) NULL,
106         (GBaseFinalizeFunc) NULL,
107         (GClassInitFunc) gdk_window_impl_x11_class_init,
108         NULL,           /* class_finalize */
109         NULL,           /* class_data */
110         sizeof (GdkWindowImplX11),
111         0,              /* n_preallocs */
112         (GInstanceInitFunc) gdk_window_impl_x11_init,
113       };
114       
115       object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_X11,
116                                             "GdkWindowImplX11",
117                                             &object_info);
118     }
119   
120   return object_type;
121 }
122
123 GType
124 _gdk_window_impl_get_type (void)
125 {
126   return gdk_window_impl_x11_get_type ();
127 }
128
129 static void
130 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
131 {
132   impl->width = 1;
133   impl->height = 1;
134 }
135
136 static void
137 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
138 {
139   GObjectClass *object_class = G_OBJECT_CLASS (klass);
140   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
141   
142   parent_class = g_type_class_peek_parent (klass);
143
144   object_class->finalize = gdk_window_impl_x11_finalize;
145
146   drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
147   drawable_class->get_colormap = gdk_window_impl_x11_get_colormap;
148   drawable_class->get_size = gdk_window_impl_x11_get_size;
149 }
150
151 static void
152 gdk_window_impl_x11_finalize (GObject *object)
153 {
154   GdkWindowObject *wrapper;
155   GdkDrawableImplX11 *draw_impl;
156   GdkWindowImplX11 *window_impl;
157   
158   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
159
160   draw_impl = GDK_DRAWABLE_IMPL_X11 (object);
161   window_impl = GDK_WINDOW_IMPL_X11 (object);
162   
163   wrapper = (GdkWindowObject*) draw_impl->wrapper;
164
165   if (!GDK_WINDOW_DESTROYED (wrapper))
166     {
167       gdk_xid_table_remove (draw_impl->xid);
168     }
169
170   G_OBJECT_CLASS (parent_class)->finalize (object);
171 }
172
173 static GdkColormap*
174 gdk_window_impl_x11_get_colormap (GdkDrawable *drawable)
175 {
176   GdkDrawableImplX11 *drawable_impl;
177   GdkWindowImplX11 *window_impl;
178   
179   g_return_val_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable), NULL);
180
181   drawable_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
182   window_impl = GDK_WINDOW_IMPL_X11 (drawable);
183
184   if (!((GdkWindowObject *) drawable_impl->wrapper)->input_only && 
185       drawable_impl->colormap == NULL)
186     {
187       XWindowAttributes window_attributes;
188       
189       XGetWindowAttributes (drawable_impl->xdisplay,
190                             drawable_impl->xid,
191                             &window_attributes);
192       drawable_impl->colormap =
193         gdk_colormap_lookup (window_attributes.colormap);
194     }
195   
196   return drawable_impl->colormap;
197 }
198
199 static void
200 gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
201                                   GdkColormap *cmap)
202 {
203   GdkWindowImplX11 *impl;
204   GdkDrawableImplX11 *draw_impl;
205   
206   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
207   g_return_if_fail (gdk_colormap_get_visual (cmap) != gdk_drawable_get_visual (drawable));
208
209   impl = GDK_WINDOW_IMPL_X11 (drawable);
210   draw_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
211
212   GDK_DRAWABLE_GET_CLASS (draw_impl)->set_colormap (drawable, cmap);
213   
214   XSetWindowColormap (draw_impl->xdisplay,
215                       draw_impl->xid,
216                       GDK_COLORMAP_XCOLORMAP (cmap));
217
218   if (((GdkWindowObject*)draw_impl->wrapper)->window_type !=
219       GDK_WINDOW_TOPLEVEL)
220     gdk_window_add_colormap_windows (GDK_WINDOW (draw_impl->wrapper));
221 }
222
223
224 static void
225 gdk_window_impl_x11_get_size (GdkDrawable *drawable,
226                               gint        *width,
227                               gint        *height)
228 {
229   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
230
231   if (width)
232     *width = GDK_WINDOW_IMPL_X11 (drawable)->width;
233   if (height)
234     *height = GDK_WINDOW_IMPL_X11 (drawable)->height;
235 }
236
237 void
238 _gdk_windowing_window_init (void)
239 {
240   GdkWindowObject *private;
241   GdkWindowImplX11 *impl;
242   GdkDrawableImplX11 *draw_impl;
243   XWindowAttributes xattributes;
244   unsigned int width;
245   unsigned int height;
246   unsigned int border_width;
247   unsigned int depth;
248   int x, y;
249
250   g_assert (gdk_parent_root == NULL);
251   
252   XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window,
253                 &x, &y, &width, &height, &border_width, &depth);
254   XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes);
255
256   gdk_parent_root = GDK_WINDOW (g_type_create_instance (GDK_TYPE_WINDOW));
257   private = (GdkWindowObject *)gdk_parent_root;
258   impl = GDK_WINDOW_IMPL_X11 (private->impl);
259   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
260   
261   draw_impl->xdisplay = gdk_display;
262   draw_impl->xid = gdk_root_window;
263   draw_impl->wrapper = GDK_DRAWABLE (private);
264   
265   private->window_type = GDK_WINDOW_ROOT;
266   private->depth = depth;
267   impl->width = width;
268   impl->height = height;
269   
270   gdk_xid_table_insert (&gdk_root_window, gdk_parent_root);
271 }
272
273 static GdkAtom wm_client_leader_atom = GDK_NONE;
274
275 GdkWindow*
276 gdk_window_new (GdkWindow     *parent,
277                 GdkWindowAttr *attributes,
278                 gint           attributes_mask)
279 {
280   GdkWindow *window;
281   GdkWindowObject *private;
282   GdkWindowObject *parent_private;
283   GdkWindowImplX11 *impl;
284   GdkDrawableImplX11 *draw_impl;
285   
286   GdkVisual *visual;
287   Window xparent;
288   Visual *xvisual;
289
290   XSetWindowAttributes xattributes;
291   long xattributes_mask;
292   XSizeHints size_hints;
293   XWMHints wm_hints;
294   XClassHint *class_hint;
295   int x, y, depth;
296   
297   unsigned int class;
298   char *title;
299   int i;
300   
301   g_return_val_if_fail (attributes != NULL, NULL);
302   
303   if (!parent)
304     parent = gdk_parent_root;
305
306   g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
307   
308   parent_private = (GdkWindowObject*) parent;
309   if (GDK_WINDOW_DESTROYED (parent))
310     return NULL;
311   
312   xparent = GDK_WINDOW_XID (parent);
313   
314   window = GDK_WINDOW (g_type_create_instance (GDK_TYPE_WINDOW));
315   private = (GdkWindowObject *)window;
316   impl = GDK_WINDOW_IMPL_X11 (private->impl);
317   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
318   draw_impl->wrapper = GDK_DRAWABLE (window);
319   
320   draw_impl->xdisplay = GDK_WINDOW_XDISPLAY (parent); 
321   
322   private->parent = (GdkWindowObject *)parent;
323
324   xattributes_mask = 0;
325   
326   if (attributes_mask & GDK_WA_X)
327     x = attributes->x;
328   else
329     x = 0;
330   
331   if (attributes_mask & GDK_WA_Y)
332     y = attributes->y;
333   else
334     y = 0;
335   
336   private->x = x;
337   private->y = y;
338   impl->width = (attributes->width > 1) ? (attributes->width) : (1);
339   impl->height = (attributes->height > 1) ? (attributes->height) : (1);
340   private->window_type = attributes->window_type;
341
342   _gdk_window_init_position (GDK_WINDOW (private));
343   if (impl->position_info.big)
344     private->guffaw_gravity = TRUE;
345   
346   if (attributes_mask & GDK_WA_VISUAL)
347     visual = attributes->visual;
348   else
349     visual = gdk_visual_get_system ();
350   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
351   
352   xattributes.event_mask = StructureNotifyMask;
353   for (i = 0; i < gdk_nevent_masks; i++)
354     {
355       if (attributes->event_mask & (1 << (i + 1)))
356         xattributes.event_mask |= gdk_event_mask_table[i];
357     }
358   
359   if (xattributes.event_mask)
360     xattributes_mask |= CWEventMask;
361   
362   if (attributes_mask & GDK_WA_NOREDIR)
363     {
364       xattributes.override_redirect =
365         (attributes->override_redirect == FALSE)?False:True;
366       xattributes_mask |= CWOverrideRedirect;
367     } 
368   else
369     xattributes.override_redirect = False;
370
371   if (parent_private && parent_private->guffaw_gravity)
372     {
373       xattributes.win_gravity = StaticGravity;
374       xattributes_mask |= CWWinGravity;
375     }
376   
377   if (attributes->wclass == GDK_INPUT_OUTPUT)
378     {
379       class = InputOutput;
380       depth = visual->depth;
381
382       private->input_only = FALSE;
383       private->depth = depth;
384       
385       if (attributes_mask & GDK_WA_COLORMAP)
386         {
387           draw_impl->colormap = attributes->colormap;
388           gdk_colormap_ref (attributes->colormap);
389         }
390       else
391         {
392           if ((((GdkVisualPrivate*)gdk_visual_get_system ())->xvisual) == xvisual)
393             {
394               draw_impl->colormap =
395                 gdk_colormap_get_system ();
396               gdk_colormap_ref (draw_impl->colormap);
397             }
398           else
399             {
400               draw_impl->colormap =
401                 gdk_colormap_new (visual, FALSE);
402             }
403         }
404       
405       private->bg_color.pixel = BlackPixel (gdk_display, gdk_screen);
406       xattributes.background_pixel = private->bg_color.pixel;
407
408       private->bg_pixmap = NULL;
409       
410       xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
411       xattributes_mask |= CWBorderPixel | CWBackPixel;
412
413       if (private->guffaw_gravity)
414         xattributes.bit_gravity = StaticGravity;
415       else
416         xattributes.bit_gravity = NorthWestGravity;
417       
418       xattributes_mask |= CWBitGravity;
419   
420       switch (private->window_type)
421         {
422         case GDK_WINDOW_TOPLEVEL:
423           xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
424           xattributes_mask |= CWColormap;
425           
426           xparent = gdk_root_window;
427           break;
428           
429         case GDK_WINDOW_CHILD:
430           xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
431           xattributes_mask |= CWColormap;
432           break;
433           
434         case GDK_WINDOW_DIALOG:
435           xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
436           xattributes_mask |= CWColormap;
437           
438           xparent = gdk_root_window;
439           break;
440           
441         case GDK_WINDOW_TEMP:
442           xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
443           xattributes_mask |= CWColormap;
444           
445           xparent = gdk_root_window;
446           
447           xattributes.save_under = True;
448           xattributes.override_redirect = True;
449           xattributes.cursor = None;
450           xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
451           break;
452         case GDK_WINDOW_ROOT:
453           g_error ("cannot make windows of type GDK_WINDOW_ROOT");
454           break;
455         }
456     }
457   else
458     {
459       depth = 0;
460       private->depth = 0;
461       class = InputOnly;
462       private->input_only = TRUE;
463       draw_impl->colormap = NULL;
464     }
465
466   draw_impl->xid = XCreateWindow (GDK_WINDOW_XDISPLAY (parent),
467                                   xparent,
468                                   x, y,
469                                   impl->width, impl->height,
470                                   0, depth, class, xvisual,
471                                   xattributes_mask, &xattributes);
472
473   gdk_drawable_ref (window);
474   gdk_xid_table_insert (&GDK_WINDOW_XID (window), window);
475   
476   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
477                                   (attributes->cursor) :
478                                   NULL));
479   
480   if (parent_private)
481     parent_private->children = g_list_prepend (parent_private->children, window);
482   
483   switch (GDK_WINDOW_TYPE (private))
484     {
485     case GDK_WINDOW_DIALOG:
486       XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
487                             GDK_WINDOW_XID (window),
488                             xparent);
489     case GDK_WINDOW_TOPLEVEL:
490     case GDK_WINDOW_TEMP:
491       XSetWMProtocols (GDK_WINDOW_XDISPLAY (window),
492                        GDK_WINDOW_XID (window),
493                        gdk_wm_window_protocols, 2);
494       break;
495     case GDK_WINDOW_CHILD:
496       if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
497           (draw_impl->colormap != gdk_colormap_get_system ()) &&
498           (draw_impl->colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
499         {
500           GDK_NOTE (MISC, g_message ("adding colormap window\n"));
501           gdk_window_add_colormap_windows (window);
502         }
503       
504       return window;
505     default:
506       
507       return window;
508     }
509   
510   size_hints.flags = PSize;
511   size_hints.width = impl->width;
512   size_hints.height = impl->height;
513   
514   wm_hints.flags = InputHint | StateHint | WindowGroupHint;
515   wm_hints.window_group = gdk_leader_window;
516   wm_hints.input = True;
517   wm_hints.initial_state = NormalState;
518   
519   /* FIXME: Is there any point in doing this? Do any WM's pay
520    * attention to PSize, and even if they do, is this the
521    * correct value???
522    */
523   XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
524                      GDK_WINDOW_XID (window),
525                      &size_hints);
526   
527   XSetWMHints (GDK_WINDOW_XDISPLAY (window),
528                GDK_WINDOW_XID (window),
529                &wm_hints);
530   
531   if (!wm_client_leader_atom)
532     wm_client_leader_atom = gdk_atom_intern ("WM_CLIENT_LEADER", FALSE);
533   
534   XChangeProperty (GDK_WINDOW_XDISPLAY (window),
535                    GDK_WINDOW_XID (window),
536                    wm_client_leader_atom,
537                    XA_WINDOW, 32, PropModeReplace,
538                    (guchar*) &gdk_leader_window, 1);
539   
540   if (attributes_mask & GDK_WA_TITLE)
541     title = attributes->title;
542   else
543     title = g_get_prgname ();
544   
545   XmbSetWMProperties (GDK_WINDOW_XDISPLAY (window),
546                       GDK_WINDOW_XID (window),
547                       title, title,
548                       NULL, 0,
549                       NULL, NULL, NULL);
550   
551   if (attributes_mask & GDK_WA_WMCLASS)
552     {
553       class_hint = XAllocClassHint ();
554       class_hint->res_name = attributes->wmclass_name;
555       class_hint->res_class = attributes->wmclass_class;
556       XSetClassHint (GDK_WINDOW_XDISPLAY (window),
557                      GDK_WINDOW_XID (window),
558                      class_hint);
559       XFree (class_hint);
560     }
561   
562   return window;
563 }
564
565 GdkWindow *
566 gdk_window_foreign_new (GdkNativeWindow anid)
567 {
568   GdkWindow *window;
569   GdkWindowObject *private;
570   GdkWindowObject *parent_private;
571   GdkWindowImplX11 *impl;
572   GdkDrawableImplX11 *draw_impl;
573   XWindowAttributes attrs;
574   Window root, parent;
575   Window *children = NULL;
576   guint nchildren;
577   gboolean result;
578
579   gdk_error_trap_push ();
580   result = XGetWindowAttributes (gdk_display, anid, &attrs);
581   if (gdk_error_trap_pop () || !result)
582     return NULL;
583
584   /* FIXME: This is pretty expensive. Maybe the caller should supply
585    *        the parent */
586   gdk_error_trap_push ();
587   result = XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren);
588   if (gdk_error_trap_pop () || !result)
589     return NULL;
590
591   if (children)
592     XFree (children);
593   
594   window = GDK_WINDOW (g_type_create_instance (GDK_TYPE_WINDOW));
595   private = (GdkWindowObject *)window;
596   impl = GDK_WINDOW_IMPL_X11 (private->impl);
597   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
598   draw_impl->wrapper = GDK_DRAWABLE (window);
599   
600   private->parent = gdk_xid_table_lookup (parent);
601   
602   parent_private = (GdkWindowObject *)private->parent;
603   
604   if (parent_private)
605     parent_private->children = g_list_prepend (parent_private->children, window);
606
607   draw_impl->xid = anid;
608   draw_impl->xdisplay = gdk_display;
609
610   private->x = attrs.x;
611   private->y = attrs.y;
612   impl->width = attrs.width;
613   impl->height = attrs.height;
614   private->window_type = GDK_WINDOW_FOREIGN;
615   private->destroyed = FALSE;
616   private->mapped = (attrs.map_state != IsUnmapped);
617   private->depth = attrs.depth;
618   
619   gdk_drawable_ref (window);
620   gdk_xid_table_insert (&GDK_WINDOW_XID (window), window);
621   
622   return window;
623 }
624
625 void
626 _gdk_windowing_window_destroy (GdkWindow *window,
627                                gboolean   recursing,
628                                gboolean   foreign_destroy)
629 {
630   GdkWindowObject *private = (GdkWindowObject *)window;
631
632   g_return_if_fail (GDK_IS_WINDOW (window));
633   
634   if (private->extension_events != 0)
635     gdk_input_window_destroy (window);
636
637   if (private->window_type == GDK_WINDOW_FOREIGN)
638     {
639       if (!foreign_destroy && (private->parent != NULL))
640         {
641           /* It's somebody else's window, but in our heirarchy,
642            * so reparent it to the root window, and then send
643            * it a delete event, as if we were a WM
644            */
645           XClientMessageEvent xevent;
646           
647           gdk_error_trap_push ();
648           gdk_window_hide (window);
649           gdk_window_reparent (window, NULL, 0, 0);
650           
651           xevent.type = ClientMessage;
652           xevent.window = GDK_WINDOW_XID (window);
653           xevent.message_type = gdk_wm_protocols;
654           xevent.format = 32;
655           xevent.data.l[0] = gdk_wm_delete_window;
656           xevent.data.l[1] = CurrentTime;
657           
658           XSendEvent (GDK_WINDOW_XDISPLAY (window),
659                       GDK_WINDOW_XID (window),
660                       False, 0, (XEvent *)&xevent);
661           gdk_flush ();
662           gdk_error_trap_pop ();
663         }
664     }
665   else if (!recursing && !foreign_destroy)
666     XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
667 }
668
669 /* This function is called when the XWindow is really gone.
670  */
671 void
672 gdk_window_destroy_notify (GdkWindow *window)
673 {
674   g_return_if_fail (window != NULL);
675   
676   if (!GDK_WINDOW_DESTROYED (window))
677     {
678       if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
679         g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
680
681       _gdk_window_destroy (window, TRUE);
682     }
683   
684   gdk_xid_table_remove (GDK_WINDOW_XID (window));
685   gdk_drawable_unref (window);
686 }
687
688 void
689 gdk_window_show (GdkWindow *window)
690 {
691   GdkWindowObject *private;
692   
693   g_return_if_fail (GDK_IS_WINDOW (window));
694   
695   private = (GdkWindowObject*) window;
696   if (!private->destroyed)
697     {
698       private->mapped = TRUE;
699       XRaiseWindow (GDK_WINDOW_XDISPLAY (window),
700                     GDK_WINDOW_XID (window));
701       
702       if (GDK_WINDOW_IMPL_X11 (private->impl)->position_info.mapped)
703         XMapWindow (GDK_WINDOW_XDISPLAY (window),
704                     GDK_WINDOW_XID (window));
705     }
706 }
707
708 void
709 gdk_window_hide (GdkWindow *window)
710 {
711   GdkWindowObject *private;
712   
713   g_return_if_fail (window != NULL);
714
715   private = (GdkWindowObject*) window;
716   if (!private->destroyed)
717     {
718       private->mapped = FALSE;
719
720       _gdk_window_clear_update_area (window);
721       
722       XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
723                     GDK_WINDOW_XID (window));
724     }
725 }
726
727 void
728 gdk_window_withdraw (GdkWindow *window)
729 {
730   GdkWindowObject *private;
731   
732   g_return_if_fail (window != NULL);
733   
734   private = (GdkWindowObject*) window;
735   if (!private->destroyed)
736     XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
737                      GDK_WINDOW_XID (window), 0);
738 }
739
740 void
741 gdk_window_move (GdkWindow *window,
742                  gint       x,
743                  gint       y)
744 {
745   GdkWindowObject *private = (GdkWindowObject *)window;
746   GdkWindowImplX11 *impl;
747
748   g_return_if_fail (window != NULL);
749   g_return_if_fail (GDK_IS_WINDOW (window));
750
751   impl = GDK_WINDOW_IMPL_X11 (private->impl);
752   
753   gdk_window_move_resize (window, x, y,
754                           impl->width, impl->height);
755 }
756
757 void
758 gdk_window_resize (GdkWindow *window,
759                    gint       width,
760                    gint       height)
761 {
762   GdkWindowObject *private;
763   
764   g_return_if_fail (window != NULL);
765   g_return_if_fail (GDK_IS_WINDOW (window));
766   
767   if (width < 1)
768     width = 1;
769   if (height < 1)
770     height = 1;
771
772   private = (GdkWindowObject*) window;
773   
774   if (!GDK_WINDOW_DESTROYED (window))
775     {
776       if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
777         _gdk_window_move_resize_child (window, private->x, private->y,
778                                        width, height);
779       else
780         {
781           XResizeWindow (GDK_WINDOW_XDISPLAY (window),
782                          GDK_WINDOW_XID (window),
783                          width, height);
784           private->resize_count += 1;
785         }
786     }
787 }
788
789 void
790 gdk_window_move_resize (GdkWindow *window,
791                         gint       x,
792                         gint       y,
793                         gint       width,
794                         gint       height)
795 {
796   GdkWindowObject *private;
797   
798   g_return_if_fail (window != NULL);
799   g_return_if_fail (GDK_IS_WINDOW (window));
800
801   if (width < 1)
802     width = 1;
803   if (height < 1)
804     height = 1;
805   
806   private = (GdkWindowObject*) window;
807
808   if (!GDK_WINDOW_DESTROYED (window))
809     {
810       if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
811         _gdk_window_move_resize_child (window, x, y, width, height);
812       else
813         {
814           XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
815                              GDK_WINDOW_XID (window),
816                              x, y, width, height);
817         }
818     }
819 }
820
821 void
822 gdk_window_reparent (GdkWindow *window,
823                      GdkWindow *new_parent,
824                      gint       x,
825                      gint       y)
826 {
827   GdkWindowObject *window_private;
828   GdkWindowObject *parent_private;
829   GdkWindowObject *old_parent_private;
830   
831   g_return_if_fail (window != NULL);
832   g_return_if_fail (GDK_IS_WINDOW (window));
833   g_return_if_fail (new_parent != NULL);
834   g_return_if_fail (GDK_IS_WINDOW (new_parent));
835   
836   if (!new_parent)
837     new_parent = gdk_parent_root;
838   
839   window_private = (GdkWindowObject*) window;
840   old_parent_private = (GdkWindowObject*)window_private->parent;
841   parent_private = (GdkWindowObject*) new_parent;
842   
843   if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (new_parent))
844     XReparentWindow (GDK_WINDOW_XDISPLAY (window),
845                      GDK_WINDOW_XID (window),
846                      GDK_WINDOW_XID (new_parent),
847                      x, y);
848   
849   window_private->parent = (GdkWindowObject *)new_parent;
850   
851   if (old_parent_private)
852     old_parent_private->children = g_list_remove (old_parent_private->children, window);
853   
854   if ((old_parent_private &&
855        (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
856       (!old_parent_private && parent_private->guffaw_gravity))
857     gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
858   
859   parent_private->children = g_list_prepend (parent_private->children, window);
860 }
861
862 void
863 _gdk_windowing_window_clear_area (GdkWindow *window,
864                                   gint       x,
865                                   gint       y,
866                                   gint       width,
867                                   gint       height)
868 {
869   g_return_if_fail (window != NULL);
870   g_return_if_fail (GDK_IS_WINDOW (window));
871   
872   if (!GDK_WINDOW_DESTROYED (window))
873     XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
874                 x, y, width, height, False);
875 }
876
877 void
878 _gdk_windowing_window_clear_area_e (GdkWindow *window,
879                                     gint       x,
880                                     gint       y,
881                                     gint       width,
882                                     gint       height)
883 {
884   g_return_if_fail (window != NULL);
885   g_return_if_fail (GDK_IS_WINDOW (window));
886   
887   if (!GDK_WINDOW_DESTROYED (window))
888     XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
889                 x, y, width, height, True);
890 }
891
892 void
893 gdk_window_raise (GdkWindow *window)
894 {
895   g_return_if_fail (window != NULL);
896   g_return_if_fail (GDK_IS_WINDOW (window));
897   
898   if (!GDK_WINDOW_DESTROYED (window))
899     XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
900 }
901
902 void
903 gdk_window_lower (GdkWindow *window)
904 {
905   g_return_if_fail (window != NULL);
906   g_return_if_fail (GDK_IS_WINDOW (window));
907   
908   if (!GDK_WINDOW_DESTROYED (window))
909     XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
910 }
911
912 void
913 gdk_window_set_hints (GdkWindow *window,
914                       gint       x,
915                       gint       y,
916                       gint       min_width,
917                       gint       min_height,
918                       gint       max_width,
919                       gint       max_height,
920                       gint       flags)
921 {
922   XSizeHints size_hints;
923   
924   g_return_if_fail (window != NULL);
925   g_return_if_fail (GDK_IS_WINDOW (window));
926   
927   if (GDK_WINDOW_DESTROYED (window))
928     return;
929   
930   size_hints.flags = 0;
931   
932   if (flags & GDK_HINT_POS)
933     {
934       size_hints.flags |= PPosition;
935       size_hints.x = x;
936       size_hints.y = y;
937     }
938   
939   if (flags & GDK_HINT_MIN_SIZE)
940     {
941       size_hints.flags |= PMinSize;
942       size_hints.min_width = min_width;
943       size_hints.min_height = min_height;
944     }
945   
946   if (flags & GDK_HINT_MAX_SIZE)
947     {
948       size_hints.flags |= PMaxSize;
949       size_hints.max_width = max_width;
950       size_hints.max_height = max_height;
951     }
952   
953   /* FIXME: Would it be better to delete this property of
954    *        flags == 0? It would save space on the server
955    */
956   XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
957                      GDK_WINDOW_XID (window),
958                      &size_hints);
959 }
960
961 void 
962 gdk_window_set_geometry_hints (GdkWindow      *window,
963                                GdkGeometry    *geometry,
964                                GdkWindowHints  geom_mask)
965 {
966   XSizeHints size_hints;
967   
968   g_return_if_fail (window != NULL);
969   g_return_if_fail (GDK_IS_WINDOW (window));
970   
971   if (GDK_WINDOW_DESTROYED (window))
972     return;
973   
974   size_hints.flags = 0;
975   
976   if (geom_mask & GDK_HINT_POS)
977     {
978       size_hints.flags |= PPosition;
979       /* We need to initialize the following obsolete fields because KWM 
980        * apparently uses these fields if they are non-zero.
981        * #@#!#!$!.
982        */
983       size_hints.x = 0;
984       size_hints.y = 0;
985     }
986   
987   if (geom_mask & GDK_HINT_MIN_SIZE)
988     {
989       size_hints.flags |= PMinSize;
990       size_hints.min_width = geometry->min_width;
991       size_hints.min_height = geometry->min_height;
992     }
993   
994   if (geom_mask & GDK_HINT_MAX_SIZE)
995     {
996       size_hints.flags |= PMaxSize;
997       size_hints.max_width = MAX (geometry->max_width, 1);
998       size_hints.max_height = MAX (geometry->max_height, 1);
999     }
1000   
1001   if (geom_mask & GDK_HINT_BASE_SIZE)
1002     {
1003       size_hints.flags |= PBaseSize;
1004       size_hints.base_width = geometry->base_width;
1005       size_hints.base_height = geometry->base_height;
1006     }
1007   
1008   if (geom_mask & GDK_HINT_RESIZE_INC)
1009     {
1010       size_hints.flags |= PResizeInc;
1011       size_hints.width_inc = geometry->width_inc;
1012       size_hints.height_inc = geometry->height_inc;
1013     }
1014   
1015   if (geom_mask & GDK_HINT_ASPECT)
1016     {
1017       size_hints.flags |= PAspect;
1018       if (geometry->min_aspect <= 1)
1019         {
1020           size_hints.min_aspect.x = 65536 * geometry->min_aspect;
1021           size_hints.min_aspect.y = 65536;
1022         }
1023       else
1024         {
1025           size_hints.min_aspect.x = 65536;
1026           size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
1027         }
1028       if (geometry->max_aspect <= 1)
1029         {
1030           size_hints.max_aspect.x = 65536 * geometry->max_aspect;
1031           size_hints.max_aspect.y = 65536;
1032         }
1033       else
1034         {
1035           size_hints.max_aspect.x = 65536;
1036           size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
1037         }
1038     }
1039
1040   /* FIXME: Would it be better to delete this property of
1041    *        geom_mask == 0? It would save space on the server
1042    */
1043   XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
1044                      GDK_WINDOW_XID (window),
1045                      &size_hints);
1046 }
1047
1048 void
1049 gdk_window_set_title (GdkWindow   *window,
1050                       const gchar *title)
1051 {
1052   g_return_if_fail (window != NULL);
1053   g_return_if_fail (GDK_IS_WINDOW (window));
1054   
1055   if (!GDK_WINDOW_DESTROYED (window))
1056     XmbSetWMProperties (GDK_WINDOW_XDISPLAY (window),
1057                         GDK_WINDOW_XID (window),
1058                         title, title, NULL, 0, NULL, NULL, NULL);
1059 }
1060
1061 void          
1062 gdk_window_set_role (GdkWindow   *window,
1063                      const gchar *role)
1064 {
1065   g_return_if_fail (window != NULL);
1066   g_return_if_fail (GDK_IS_WINDOW (window));
1067
1068   if (!GDK_WINDOW_DESTROYED (window))
1069     {
1070       if (role)
1071         XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
1072                          gdk_atom_intern ("WM_WINDOW_ROLE", FALSE), XA_STRING,
1073                          8, PropModeReplace, role, strlen (role));
1074       else
1075         XDeleteProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
1076                          gdk_atom_intern ("WM_WINDOW_ROLE", FALSE));
1077     }
1078 }
1079
1080 void          
1081 gdk_window_set_transient_for (GdkWindow *window, 
1082                               GdkWindow *parent)
1083 {
1084   GdkWindowObject *private;
1085   GdkWindowObject *parent_private;
1086   
1087   g_return_if_fail (window != NULL);
1088   g_return_if_fail (GDK_IS_WINDOW (window));
1089   
1090   private = (GdkWindowObject*) window;
1091   parent_private = (GdkWindowObject*) parent;
1092   
1093   if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent))
1094     XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), 
1095                           GDK_WINDOW_XID (window),
1096                           GDK_WINDOW_XID (parent));
1097 }
1098
1099 void
1100 gdk_window_set_background (GdkWindow *window,
1101                            GdkColor  *color)
1102 {
1103   GdkWindowObject *private = (GdkWindowObject *)window;
1104   
1105   g_return_if_fail (window != NULL);
1106   g_return_if_fail (GDK_IS_WINDOW (window));
1107   
1108   if (!GDK_WINDOW_DESTROYED (window))
1109     XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
1110                           GDK_WINDOW_XID (window), color->pixel);
1111
1112   private->bg_color = *color;
1113
1114   if (private->bg_pixmap &&
1115       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1116       private->bg_pixmap != GDK_NO_BG)
1117     {
1118       gdk_pixmap_unref (private->bg_pixmap);
1119       private->bg_pixmap = NULL;
1120     }
1121 }
1122
1123 void
1124 gdk_window_set_back_pixmap (GdkWindow *window,
1125                             GdkPixmap *pixmap,
1126                             gboolean   parent_relative)
1127 {
1128   GdkWindowObject *private = (GdkWindowObject *)window;
1129   Pixmap xpixmap;
1130   
1131   g_return_if_fail (window != NULL);
1132   g_return_if_fail (GDK_IS_WINDOW (window));
1133   g_return_if_fail (pixmap == NULL || !parent_relative);
1134
1135   if (private->bg_pixmap &&
1136       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1137       private->bg_pixmap != GDK_NO_BG)
1138     gdk_pixmap_unref (private->bg_pixmap);
1139
1140   if (parent_relative)
1141     {
1142       xpixmap = ParentRelative;
1143       private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
1144     }
1145   else
1146     {
1147       if (pixmap)
1148         {
1149           gdk_pixmap_ref (pixmap);
1150           private->bg_pixmap = pixmap;
1151           xpixmap = GDK_PIXMAP_XID (pixmap);
1152         }
1153       else
1154         {
1155           xpixmap = None;
1156           private->bg_pixmap = GDK_NO_BG;
1157         }
1158     }
1159   
1160   if (!GDK_WINDOW_DESTROYED (window))
1161     XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
1162                                 GDK_WINDOW_XID (window), xpixmap);
1163 }
1164
1165 void
1166 gdk_window_set_cursor (GdkWindow *window,
1167                        GdkCursor *cursor)
1168 {
1169   GdkCursorPrivate *cursor_private;
1170   Cursor xcursor;
1171   
1172   g_return_if_fail (window != NULL);
1173   g_return_if_fail (GDK_IS_WINDOW (window));
1174   
1175   cursor_private = (GdkCursorPrivate*) cursor;
1176   
1177   if (!cursor)
1178     xcursor = None;
1179   else
1180     xcursor = cursor_private->xcursor;
1181   
1182   if (!GDK_WINDOW_DESTROYED (window))
1183     XDefineCursor (GDK_WINDOW_XDISPLAY (window),
1184                    GDK_WINDOW_XID (window),
1185                    xcursor);
1186 }
1187
1188 void
1189 gdk_window_get_geometry (GdkWindow *window,
1190                          gint      *x,
1191                          gint      *y,
1192                          gint      *width,
1193                          gint      *height,
1194                          gint      *depth)
1195 {
1196   Window root;
1197   gint tx;
1198   gint ty;
1199   guint twidth;
1200   guint theight;
1201   guint tborder_width;
1202   guint tdepth;
1203   
1204   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1205   
1206   if (!window)
1207     window = gdk_parent_root;
1208   
1209   if (!GDK_WINDOW_DESTROYED (window))
1210     {
1211       XGetGeometry (GDK_WINDOW_XDISPLAY (window),
1212                     GDK_WINDOW_XID (window),
1213                     &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
1214       
1215       if (x)
1216         *x = tx;
1217       if (y)
1218         *y = ty;
1219       if (width)
1220         *width = twidth;
1221       if (height)
1222         *height = theight;
1223       if (depth)
1224         *depth = tdepth;
1225     }
1226 }
1227
1228 gint
1229 gdk_window_get_origin (GdkWindow *window,
1230                        gint      *x,
1231                        gint      *y)
1232 {
1233   gint return_val;
1234   Window child;
1235   gint tx = 0;
1236   gint ty = 0;
1237   
1238   g_return_val_if_fail (window != NULL, 0);
1239   
1240   if (!GDK_WINDOW_DESTROYED (window))
1241     {
1242       return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
1243                                           GDK_WINDOW_XID (window),
1244                                           gdk_root_window,
1245                                           0, 0, &tx, &ty,
1246                                           &child);
1247       
1248     }
1249   else
1250     return_val = 0;
1251   
1252   if (x)
1253     *x = tx;
1254   if (y)
1255     *y = ty;
1256   
1257   return return_val;
1258 }
1259
1260 gboolean
1261 gdk_window_get_deskrelative_origin (GdkWindow *window,
1262                                     gint      *x,
1263                                     gint      *y)
1264 {
1265   gboolean return_val = FALSE;
1266   gint num_children, format_return;
1267   Window win, *child, parent, root;
1268   gint tx = 0;
1269   gint ty = 0;
1270   Atom type_return;
1271   static Atom atom = 0;
1272   gulong number_return, bytes_after_return;
1273   guchar *data_return;
1274   
1275   g_return_val_if_fail (window != NULL, 0);
1276   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1277   
1278   if (!GDK_WINDOW_DESTROYED (window))
1279     {
1280       if (!atom)
1281         atom = gdk_atom_intern ("ENLIGHTENMENT_DESKTOP", FALSE);
1282       win = GDK_WINDOW_XID (window);
1283       
1284       while (XQueryTree (GDK_WINDOW_XDISPLAY (window), win, &root, &parent,
1285                          &child, (unsigned int *)&num_children))
1286         {
1287           if ((child) && (num_children > 0))
1288             XFree (child);
1289           
1290           if (!parent)
1291             break;
1292           else
1293             win = parent;
1294           
1295           if (win == root)
1296             break;
1297           
1298           data_return = NULL;
1299           XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), win, atom, 0, 0,
1300                               False, XA_CARDINAL, &type_return, &format_return,
1301                               &number_return, &bytes_after_return, &data_return);
1302           if (type_return == XA_CARDINAL)
1303             {
1304               XFree (data_return);
1305               break;
1306             }
1307         }
1308       
1309       return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
1310                                           GDK_WINDOW_XID (window),
1311                                           win,
1312                                           0, 0, &tx, &ty,
1313                                           &root);
1314       if (x)
1315         *x = tx;
1316       if (y)
1317         *y = ty;
1318     }
1319   
1320   
1321   return return_val;
1322 }
1323
1324 void
1325 gdk_window_get_root_origin (GdkWindow *window,
1326                             gint      *x,
1327                             gint      *y)
1328 {
1329   GdkWindowObject *private;
1330   Window xwindow;
1331   Window xparent;
1332   Window root;
1333   Window *children;
1334   unsigned int nchildren;
1335   
1336   g_return_if_fail (window != NULL);
1337   g_return_if_fail (GDK_IS_WINDOW (window));
1338   
1339   private = (GdkWindowObject*) window;
1340   if (x)
1341     *x = 0;
1342   if (y)
1343     *y = 0;
1344
1345   if (GDK_WINDOW_DESTROYED (window))
1346     return;
1347   
1348   while (private->parent && ((GdkWindowObject*) private->parent)->parent)
1349     private = (GdkWindowObject*) private->parent;
1350   if (GDK_WINDOW_DESTROYED (window))
1351     return;
1352   
1353   xparent = GDK_WINDOW_XID (window);
1354   do
1355     {
1356       xwindow = xparent;
1357       if (!XQueryTree (GDK_WINDOW_XDISPLAY (window), xwindow,
1358                        &root, &xparent,
1359                        &children, &nchildren))
1360         return;
1361       
1362       if (children)
1363         XFree (children);
1364     }
1365   while (xparent != root);
1366   
1367   if (xparent == root)
1368     {
1369       unsigned int ww, wh, wb, wd;
1370       int wx, wy;
1371       
1372       if (XGetGeometry (GDK_WINDOW_XDISPLAY (window), xwindow, &root, &wx, &wy, &ww, &wh, &wb, &wd))
1373         {
1374           if (x)
1375             *x = wx;
1376           if (y)
1377             *y = wy;
1378         }
1379     }
1380 }
1381
1382 GdkWindow*
1383 gdk_window_get_pointer (GdkWindow       *window,
1384                         gint            *x,
1385                         gint            *y,
1386                         GdkModifierType *mask)
1387 {
1388   GdkWindow *return_val;
1389   Window root;
1390   Window child;
1391   int rootx, rooty;
1392   int winx = 0;
1393   int winy = 0;
1394   unsigned int xmask = 0;
1395   gint xoffset, yoffset;
1396
1397   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
1398   
1399   if (!window)
1400     window = gdk_parent_root;
1401   
1402   _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
1403
1404   return_val = NULL;
1405   if (!GDK_WINDOW_DESTROYED (window) &&
1406       XQueryPointer (GDK_WINDOW_XDISPLAY (window),
1407                      GDK_WINDOW_XID (window),
1408                      &root, &child, &rootx, &rooty, &winx, &winy, &xmask))
1409     {
1410       if (child)
1411         return_val = gdk_window_lookup (child);
1412     }
1413   
1414   if (x)
1415     *x = winx + xoffset;
1416   if (y)
1417     *y = winy + yoffset;
1418   if (mask)
1419     *mask = xmask;
1420   
1421   return return_val;
1422 }
1423
1424 GdkWindow*
1425 gdk_window_at_pointer (gint *win_x,
1426                        gint *win_y)
1427 {
1428   GdkWindow *window;
1429   Window root;
1430   Window xwindow;
1431   Window xwindow_last = 0;
1432   Display *xdisplay;
1433   int rootx = -1, rooty = -1;
1434   int winx, winy;
1435   unsigned int xmask;
1436   
1437   xwindow = GDK_ROOT_WINDOW ();
1438   xdisplay = GDK_DISPLAY ();
1439   
1440   XGrabServer (xdisplay);
1441   while (xwindow)
1442     {
1443       xwindow_last = xwindow;
1444       XQueryPointer (xdisplay, xwindow,
1445                      &root, &xwindow,
1446                      &rootx, &rooty,
1447                      &winx, &winy,
1448                      &xmask);
1449     }
1450   XUngrabServer (xdisplay);
1451   
1452   window = gdk_window_lookup (xwindow_last);
1453   
1454   if (win_x)
1455     *win_x = window ? winx : -1;
1456   if (win_y)
1457     *win_y = window ? winy : -1;
1458   
1459   return window;
1460 }
1461
1462 GdkEventMask  
1463 gdk_window_get_events (GdkWindow *window)
1464 {
1465   XWindowAttributes attrs;
1466   GdkEventMask event_mask;
1467   int i;
1468   
1469   g_return_val_if_fail (window != NULL, 0);
1470   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1471
1472   if (GDK_WINDOW_DESTROYED (window))
1473     return 0;
1474   else
1475     {
1476       XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
1477                             GDK_WINDOW_XID (window), 
1478                             &attrs);
1479       
1480       event_mask = 0;
1481       for (i = 0; i < gdk_nevent_masks; i++)
1482         {
1483           if (attrs.your_event_mask & gdk_event_mask_table[i])
1484             event_mask |= 1 << (i + 1);
1485         }
1486   
1487       return event_mask;
1488     }
1489 }
1490
1491 void          
1492 gdk_window_set_events (GdkWindow       *window,
1493                        GdkEventMask     event_mask)
1494 {
1495   long xevent_mask;
1496   int i;
1497   
1498   g_return_if_fail (window != NULL);
1499   g_return_if_fail (GDK_IS_WINDOW (window));
1500   
1501   if (!GDK_WINDOW_DESTROYED (window))
1502     {
1503       xevent_mask = StructureNotifyMask;
1504       for (i = 0; i < gdk_nevent_masks; i++)
1505         {
1506           if (event_mask & (1 << (i + 1)))
1507             xevent_mask |= gdk_event_mask_table[i];
1508         }
1509       
1510       XSelectInput (GDK_WINDOW_XDISPLAY (window),
1511                     GDK_WINDOW_XID (window),
1512                     xevent_mask);
1513     }
1514 }
1515
1516 void
1517 gdk_window_add_colormap_windows (GdkWindow *window)
1518 {
1519   GdkWindow *toplevel;
1520   Window *old_windows;
1521   Window *new_windows;
1522   int i, count;
1523   
1524   g_return_if_fail (window != NULL);
1525   g_return_if_fail (GDK_IS_WINDOW (window));
1526   
1527   toplevel = gdk_window_get_toplevel (window);
1528   if (GDK_WINDOW_DESTROYED (toplevel))
1529     return;
1530   
1531   old_windows = NULL;
1532   if (!XGetWMColormapWindows (GDK_WINDOW_XDISPLAY (toplevel),
1533                               GDK_WINDOW_XID (toplevel),
1534                               &old_windows, &count))
1535     {
1536       count = 0;
1537     }
1538   
1539   for (i = 0; i < count; i++)
1540     if (old_windows[i] == GDK_WINDOW_XID (window))
1541       {
1542         XFree (old_windows);
1543         return;
1544       }
1545   
1546   new_windows = g_new (Window, count + 1);
1547   
1548   for (i = 0; i < count; i++)
1549     new_windows[i] = old_windows[i];
1550   new_windows[count] = GDK_WINDOW_XID (window);
1551   
1552   XSetWMColormapWindows (GDK_WINDOW_XDISPLAY (toplevel),
1553                          GDK_WINDOW_XID (toplevel),
1554                          new_windows, count + 1);
1555   
1556   g_free (new_windows);
1557   if (old_windows)
1558     XFree (old_windows);
1559 }
1560
1561 static gboolean
1562 gdk_window_have_shape_ext (void)
1563 {
1564   enum { UNKNOWN, NO, YES };
1565   static gint have_shape = UNKNOWN;
1566   
1567   if (have_shape == UNKNOWN)
1568     {
1569       int ignore;
1570       if (XQueryExtension (gdk_display, "SHAPE", &ignore, &ignore, &ignore))
1571         have_shape = YES;
1572       else
1573         have_shape = NO;
1574     }
1575   
1576   return (have_shape == YES);
1577 }
1578
1579 /*
1580  * This needs the X11 shape extension.
1581  * If not available, shaped windows will look
1582  * ugly, but programs still work.    Stefan Wille
1583  */
1584 void
1585 gdk_window_shape_combine_mask (GdkWindow *window,
1586                                GdkBitmap *mask,
1587                                gint x, gint y)
1588 {
1589   Pixmap pixmap;
1590   
1591   g_return_if_fail (window != NULL);
1592   g_return_if_fail (GDK_IS_WINDOW (window));
1593   
1594 #ifdef HAVE_SHAPE_EXT
1595   if (GDK_WINDOW_DESTROYED (window))
1596     return;
1597   
1598   if (gdk_window_have_shape_ext ())
1599     {
1600       if (mask)
1601         {
1602           pixmap = GDK_PIXMAP_XID (mask);
1603         }
1604       else
1605         {
1606           x = 0;
1607           y = 0;
1608           pixmap = None;
1609         }
1610       
1611       XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
1612                          GDK_WINDOW_XID (window),
1613                          ShapeBounding,
1614                          x, y,
1615                          pixmap,
1616                          ShapeSet);
1617     }
1618 #endif /* HAVE_SHAPE_EXT */
1619 }
1620
1621 void
1622 gdk_window_set_override_redirect (GdkWindow *window,
1623                                   gboolean override_redirect)
1624 {
1625   XSetWindowAttributes attr;
1626   
1627   g_return_if_fail (window != NULL);
1628   g_return_if_fail (GDK_IS_WINDOW (window));
1629
1630   if (GDK_WINDOW_DESTROYED (window))
1631     {
1632       attr.override_redirect = (override_redirect == FALSE)?False:True;
1633       XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
1634                                GDK_WINDOW_XID (window),
1635                                CWOverrideRedirect,
1636                                &attr);
1637     }
1638 }
1639
1640 void          
1641 gdk_window_set_icon (GdkWindow *window, 
1642                      GdkWindow *icon_window,
1643                      GdkPixmap *pixmap,
1644                      GdkBitmap *mask)
1645 {
1646   XWMHints *wm_hints;
1647   
1648   g_return_if_fail (window != NULL);
1649   g_return_if_fail (GDK_IS_WINDOW (window));
1650
1651   if (GDK_WINDOW_DESTROYED (window))
1652     return;
1653
1654   wm_hints = XGetWMHints (GDK_WINDOW_XDISPLAY (window),
1655                           GDK_WINDOW_XID (window));
1656   if (!wm_hints)
1657     wm_hints = XAllocWMHints ();
1658
1659   if (icon_window != NULL)
1660     {
1661       wm_hints->flags |= IconWindowHint;
1662       wm_hints->icon_window = GDK_WINDOW_XID (icon_window);
1663     }
1664   
1665   if (pixmap != NULL)
1666     {
1667       wm_hints->flags |= IconPixmapHint;
1668       wm_hints->icon_pixmap = GDK_PIXMAP_XID (pixmap);
1669     }
1670   
1671   if (mask != NULL)
1672     {
1673       wm_hints->flags |= IconMaskHint;
1674       wm_hints->icon_mask = GDK_PIXMAP_XID (mask);
1675     }
1676
1677   XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1678                GDK_WINDOW_XID (window), wm_hints);
1679   XFree (wm_hints);
1680 }
1681
1682 void          
1683 gdk_window_set_icon_name (GdkWindow   *window, 
1684                           const gchar *name)
1685 {
1686   XTextProperty property;
1687   gint res;
1688   
1689   g_return_if_fail (window != NULL);
1690   g_return_if_fail (GDK_IS_WINDOW (window));
1691
1692   if (GDK_WINDOW_DESTROYED (window))
1693     return;
1694   
1695   res = XmbTextListToTextProperty (GDK_WINDOW_XDISPLAY (window),
1696                                    &name, 1, XStdICCTextStyle,
1697                                    &property);
1698   if (res < 0)
1699     {
1700       g_warning ("Error converting icon name to text property: %d\n", res);
1701       return;
1702     }
1703   
1704   XSetWMIconName (GDK_WINDOW_XDISPLAY (window),
1705                   GDK_WINDOW_XID (window),
1706                   &property);
1707   
1708   if (property.value)
1709     XFree (property.value);
1710 }
1711
1712 void          
1713 gdk_window_set_group (GdkWindow *window, 
1714                       GdkWindow *leader)
1715 {
1716   XWMHints *wm_hints;
1717   
1718   g_return_if_fail (window != NULL);
1719   g_return_if_fail (GDK_IS_WINDOW (window));
1720   g_return_if_fail (leader != NULL);
1721   g_return_if_fail (GDK_IS_WINDOW (leader));
1722
1723   if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader))
1724     return;
1725   
1726   wm_hints = XGetWMHints (GDK_WINDOW_XDISPLAY (window),
1727                           GDK_WINDOW_XID (window));
1728   if (!wm_hints)
1729     wm_hints = XAllocWMHints ();
1730
1731   wm_hints->flags |= WindowGroupHint;
1732   wm_hints->window_group = GDK_WINDOW_XID (leader);
1733
1734   XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1735                GDK_WINDOW_XID (window), wm_hints);
1736   XFree (wm_hints);
1737 }
1738
1739 static void
1740 gdk_window_set_mwm_hints (GdkWindow *window,
1741                           MotifWmHints *new_hints)
1742 {
1743   static Atom hints_atom = None;
1744   MotifWmHints *hints;
1745   Atom type;
1746   gint format;
1747   gulong nitems;
1748   gulong bytes_after;
1749   
1750   if (GDK_WINDOW_DESTROYED (window))
1751     return;
1752   
1753   if (!hints_atom)
1754     hints_atom = XInternAtom (GDK_WINDOW_XDISPLAY (window), 
1755                               _XA_MOTIF_WM_HINTS, FALSE);
1756   
1757   XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
1758                       hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
1759                       False, AnyPropertyType, &type, &format, &nitems,
1760                       &bytes_after, (guchar **)&hints);
1761   
1762   if (type == None)
1763     hints = new_hints;
1764   else
1765     {
1766       if (new_hints->flags & MWM_HINTS_FUNCTIONS)
1767         {
1768           hints->flags |= MWM_HINTS_FUNCTIONS;
1769           hints->functions = new_hints->functions;
1770         }
1771       if (new_hints->flags & MWM_HINTS_DECORATIONS)
1772         {
1773           hints->flags |= MWM_HINTS_DECORATIONS;
1774           hints->decorations = new_hints->decorations;
1775         }
1776     }
1777   
1778   XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
1779                    hints_atom, hints_atom, 32, PropModeReplace,
1780                    (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
1781   
1782   if (hints != new_hints)
1783     XFree (hints);
1784 }
1785
1786 void
1787 gdk_window_set_decorations (GdkWindow      *window,
1788                             GdkWMDecoration decorations)
1789 {
1790   MotifWmHints hints;
1791   
1792   g_return_if_fail (window != NULL);
1793   g_return_if_fail (GDK_IS_WINDOW (window));
1794   
1795   hints.flags = MWM_HINTS_DECORATIONS;
1796   hints.decorations = decorations;
1797   
1798   gdk_window_set_mwm_hints (window, &hints);
1799 }
1800
1801 void
1802 gdk_window_set_functions (GdkWindow    *window,
1803                           GdkWMFunction functions)
1804 {
1805   MotifWmHints hints;
1806   
1807   g_return_if_fail (window != NULL);
1808   g_return_if_fail (GDK_IS_WINDOW (window));
1809   
1810   hints.flags = MWM_HINTS_FUNCTIONS;
1811   hints.functions = functions;
1812   
1813   gdk_window_set_mwm_hints (window, &hints);
1814 }
1815
1816 /* 
1817  * propagate the shapes from all child windows of a GDK window to the parent 
1818  * window. Shamelessly ripped from Enlightenment's code
1819  * 
1820  * - Raster
1821  */
1822 struct _gdk_span
1823 {
1824   gint                start;
1825   gint                end;
1826   struct _gdk_span    *next;
1827 };
1828
1829 static void
1830 gdk_add_to_span (struct _gdk_span **s,
1831                  gint               x,
1832                  gint               xx)
1833 {
1834   struct _gdk_span *ptr1, *ptr2, *noo, *ss;
1835   gchar             spanning;
1836   
1837   ptr2 = NULL;
1838   ptr1 = *s;
1839   spanning = 0;
1840   ss = NULL;
1841   /* scan the spans for this line */
1842   while (ptr1)
1843     {
1844       /* -- -> new span */
1845       /* == -> existing span */
1846       /* ## -> spans intersect */
1847       /* if we are in the middle of spanning the span into the line */
1848       if (spanning)
1849         {
1850           /* case: ---- ==== */
1851           if (xx < ptr1->start - 1)
1852             {
1853               /* ends before next span - extend to here */
1854               ss->end = xx;
1855               return;
1856             }
1857           /* case: ----##=== */
1858           else if (xx <= ptr1->end)
1859             {
1860               /* crosses into next span - delete next span and append */
1861               ss->end = ptr1->end;
1862               ss->next = ptr1->next;
1863               g_free (ptr1);
1864               return;
1865             }
1866           /* case: ---###--- */
1867           else
1868             {
1869               /* overlaps next span - delete and keep checking */
1870               ss->next = ptr1->next;
1871               g_free (ptr1);
1872               ptr1 = ss;
1873             }
1874         }
1875       /* otherwise havent started spanning it in yet */
1876       else
1877         {
1878           /* case: ---- ==== */
1879           if (xx < ptr1->start - 1)
1880             {
1881               /* insert span here in list */
1882               noo = g_malloc (sizeof (struct _gdk_span));
1883               
1884               if (noo)
1885                 {
1886                   noo->start = x;
1887                   noo->end = xx;
1888                   noo->next = ptr1;
1889                   if (ptr2)
1890                     ptr2->next = noo;
1891                   else
1892                     *s = noo;
1893                 }
1894               return;
1895             }
1896           /* case: ----##=== */
1897           else if ((x < ptr1->start) && (xx <= ptr1->end))
1898             {
1899               /* expand this span to the left point of the new one */
1900               ptr1->start = x;
1901               return;
1902             }
1903           /* case: ===###=== */
1904           else if ((x >= ptr1->start) && (xx <= ptr1->end))
1905             {
1906               /* throw the span away */
1907               return;
1908             }
1909           /* case: ---###--- */
1910           else if ((x < ptr1->start) && (xx > ptr1->end))
1911             {
1912               ss = ptr1;
1913               spanning = 1;
1914               ptr1->start = x;
1915               ptr1->end = xx;
1916             }
1917           /* case: ===##---- */
1918           else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end))
1919             {
1920               ss = ptr1;
1921               spanning = 1;
1922               ptr1->end = xx;
1923             }
1924           /* case: ==== ---- */
1925           /* case handled by next loop iteration - first case */
1926         }
1927       ptr2 = ptr1;
1928       ptr1 = ptr1->next;
1929     }
1930   /* it started in the middle but spans beyond your current list */
1931   if (spanning)
1932     {
1933       ptr2->end = xx;
1934       return;
1935     }
1936   /* it does not start inside a span or in the middle, so add it to the end */
1937   noo = g_malloc (sizeof (struct _gdk_span));
1938   
1939   if (noo)
1940     {
1941       noo->start = x;
1942       noo->end = xx;
1943       if (ptr2)
1944         {
1945           noo->next = ptr2->next;
1946           ptr2->next = noo;
1947         }
1948       else
1949         {
1950           noo->next = NULL;
1951           *s = noo;
1952         }
1953     }
1954   return;
1955 }
1956
1957 static void
1958 gdk_add_rectangles (Display           *disp,
1959                     Window             win,
1960                     struct _gdk_span **spans,
1961                     gint               basew,
1962                     gint               baseh,
1963                     gint               x,
1964                     gint               y)
1965 {
1966   gint a, k;
1967   gint x1, y1, x2, y2;
1968   gint rn, ord;
1969   XRectangle *rl;
1970   
1971   rl = XShapeGetRectangles (disp, win, ShapeBounding, &rn, &ord);
1972   if (rl)
1973     {
1974       /* go through all clip rects in this window's shape */
1975       for (k = 0; k < rn; k++)
1976         {
1977           /* for each clip rect, add it to each line's spans */
1978           x1 = x + rl[k].x;
1979           x2 = x + rl[k].x + (rl[k].width - 1);
1980           y1 = y + rl[k].y;
1981           y2 = y + rl[k].y + (rl[k].height - 1);
1982           if (x1 < 0)
1983             x1 = 0;
1984           if (y1 < 0)
1985             y1 = 0;
1986           if (x2 >= basew)
1987             x2 = basew - 1;
1988           if (y2 >= baseh)
1989             y2 = baseh - 1;
1990           for (a = y1; a <= y2; a++)
1991             {
1992               if ((x2 - x1) >= 0)
1993                 gdk_add_to_span (&spans[a], x1, x2);
1994             }
1995         }
1996       XFree (rl);
1997     }
1998 }
1999
2000 static void
2001 gdk_propagate_shapes (Display *disp,
2002                       Window   win,
2003                       gboolean merge)
2004 {
2005   Window              rt, par, *list = NULL;
2006   gint                i, j, num = 0, num_rects = 0;
2007   gint                x, y, contig;
2008   guint               w, h, d;
2009   gint                baseh, basew;
2010   XRectangle         *rects = NULL;
2011   struct _gdk_span  **spans = NULL, *ptr1, *ptr2, *ptr3;
2012   XWindowAttributes   xatt;
2013   
2014   XGetGeometry (disp, win, &rt, &x, &y, &w, &h, &d, &d);
2015   if (h <= 0)
2016     return;
2017   basew = w;
2018   baseh = h;
2019   spans = g_malloc (sizeof (struct _gdk_span *) * h);
2020   
2021   for (i = 0; i < h; i++)
2022     spans[i] = NULL;
2023   XQueryTree (disp, win, &rt, &par, &list, (unsigned int *)&num);
2024   if (list)
2025     {
2026       /* go through all child windows and create/insert spans */
2027       for (i = 0; i < num; i++)
2028         {
2029           if (XGetWindowAttributes (disp, list[i], &xatt) && (xatt.map_state != IsUnmapped))
2030             if (XGetGeometry (disp, list[i], &rt, &x, &y, &w, &h, &d, &d))
2031               gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y);
2032         }
2033       if (merge)
2034         gdk_add_rectangles (disp, win, spans, basew, baseh, x, y);
2035       
2036       /* go through the spans list and build a list of rects */
2037       rects = g_malloc (sizeof (XRectangle) * 256);
2038       num_rects = 0;
2039       for (i = 0; i < baseh; i++)
2040         {
2041           ptr1 = spans[i];
2042           /* go through the line for all spans */
2043           while (ptr1)
2044             {
2045               rects[num_rects].x = ptr1->start;
2046               rects[num_rects].y = i;
2047               rects[num_rects].width = ptr1->end - ptr1->start + 1;
2048               rects[num_rects].height = 1;
2049               j = i + 1;
2050               /* if there are more lines */
2051               contig = 1;
2052               /* while contigous rects (same start/end coords) exist */
2053               while ((contig) && (j < baseh))
2054                 {
2055                   /* search next line for spans matching this one */
2056                   contig = 0;
2057                   ptr2 = spans[j];
2058                   ptr3 = NULL;
2059                   while (ptr2)
2060                     {
2061                       /* if we have an exact span match set contig */
2062                       if ((ptr2->start == ptr1->start) &&
2063                           (ptr2->end == ptr1->end))
2064                         {
2065                           contig = 1;
2066                           /* remove the span - not needed */
2067                           if (ptr3)
2068                             {
2069                               ptr3->next = ptr2->next;
2070                               g_free (ptr2);
2071                               ptr2 = NULL;
2072                             }
2073                           else
2074                             {
2075                               spans[j] = ptr2->next;
2076                               g_free (ptr2);
2077                               ptr2 = NULL;
2078                             }
2079                           break;
2080                         }
2081                       /* gone past the span point no point looking */
2082                       else if (ptr2->start < ptr1->start)
2083                         break;
2084                       if (ptr2)
2085                         {
2086                           ptr3 = ptr2;
2087                           ptr2 = ptr2->next;
2088                         }
2089                     }
2090                   /* if a contiguous span was found increase the rect h */
2091                   if (contig)
2092                     {
2093                       rects[num_rects].height++;
2094                       j++;
2095                     }
2096                 }
2097               /* up the rect count */
2098               num_rects++;
2099               /* every 256 new rects increase the rect array */
2100               if ((num_rects % 256) == 0)
2101                 rects = g_realloc (rects, sizeof (XRectangle) * (num_rects + 256));
2102               ptr1 = ptr1->next;
2103             }
2104         }
2105       /* set the rects as the shape mask */
2106       if (rects)
2107         {
2108           XShapeCombineRectangles (disp, win, ShapeBounding, 0, 0, rects, num_rects,
2109                                    ShapeSet, YXSorted);
2110           g_free (rects);
2111         }
2112       XFree (list);
2113     }
2114   /* free up all the spans we made */
2115   for (i = 0; i < baseh; i++)
2116     {
2117       ptr1 = spans[i];
2118       while (ptr1)
2119         {
2120           ptr2 = ptr1;
2121           ptr1 = ptr1->next;
2122           g_free (ptr2);
2123         }
2124     }
2125   g_free (spans);
2126 }
2127
2128 void
2129 gdk_window_set_child_shapes (GdkWindow *window)
2130 {
2131   g_return_if_fail (window != NULL);
2132   g_return_if_fail (GDK_IS_WINDOW (window));
2133   
2134 #ifdef HAVE_SHAPE_EXT
2135   if (!GDK_WINDOW_DESTROYED (window) &&
2136       gdk_window_have_shape_ext ())
2137     gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
2138                           GDK_WINDOW_XID (window), FALSE);
2139 #endif   
2140 }
2141
2142 void
2143 gdk_window_merge_child_shapes (GdkWindow *window)
2144 {
2145   g_return_if_fail (window != NULL);
2146   g_return_if_fail (GDK_IS_WINDOW (window));
2147   
2148 #ifdef HAVE_SHAPE_EXT
2149   if (!GDK_WINDOW_DESTROYED (window) &&
2150       gdk_window_have_shape_ext ())
2151     gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
2152                           GDK_WINDOW_XID (window), TRUE);
2153 #endif   
2154 }
2155
2156 /* Support for windows that can be guffaw-scrolled
2157  * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
2158  */
2159
2160 static gboolean
2161 gdk_window_gravity_works (void)
2162 {
2163   enum { UNKNOWN, NO, YES };
2164   static gint gravity_works = UNKNOWN;
2165   
2166   if (gravity_works == UNKNOWN)
2167     {
2168       GdkWindowAttr attr;
2169       GdkWindow *parent;
2170       GdkWindow *child;
2171       gint y;
2172       
2173       /* This particular server apparently has a bug so that the test
2174        * works but the actual code crashes it
2175        */
2176       if ((!strcmp (XServerVendor (gdk_display), "Sun Microsystems, Inc.")) &&
2177           (VendorRelease (gdk_display) == 3400))
2178         {
2179           gravity_works = NO;
2180           return FALSE;
2181         }
2182       
2183       attr.window_type = GDK_WINDOW_TEMP;
2184       attr.wclass = GDK_INPUT_OUTPUT;
2185       attr.x = 0;
2186       attr.y = 0;
2187       attr.width = 100;
2188       attr.height = 100;
2189       attr.event_mask = 0;
2190       
2191       parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
2192       
2193       attr.window_type = GDK_WINDOW_CHILD;
2194       child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
2195       
2196       gdk_window_set_static_win_gravity (child, TRUE);
2197       
2198       gdk_window_resize (parent, 100, 110);
2199       gdk_window_move (parent, 0, -10);
2200       gdk_window_move_resize (parent, 0, 0, 100, 100);
2201       
2202       gdk_window_resize (parent, 100, 110);
2203       gdk_window_move (parent, 0, -10);
2204       gdk_window_move_resize (parent, 0, 0, 100, 100);
2205       
2206       gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
2207       
2208       gdk_window_destroy (parent);
2209       gdk_window_destroy (child);
2210       
2211       gravity_works = ((y == -20) ? YES : NO);
2212     }
2213   
2214   return (gravity_works == YES);
2215 }
2216
2217 static void
2218 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
2219 {
2220   XSetWindowAttributes xattributes;
2221   guint xattributes_mask = 0;
2222   
2223   g_return_if_fail (window != NULL);
2224   
2225   xattributes.bit_gravity = StaticGravity;
2226   xattributes_mask |= CWBitGravity;
2227   xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
2228   XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
2229                            GDK_WINDOW_XID (window),
2230                            CWBitGravity,  &xattributes);
2231 }
2232
2233 static void
2234 gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
2235 {
2236   XSetWindowAttributes xattributes;
2237   
2238   g_return_if_fail (window != NULL);
2239   
2240   xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
2241   
2242   XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
2243                            GDK_WINDOW_XID (window),
2244                            CWWinGravity,  &xattributes);
2245 }
2246
2247 /*************************************************************
2248  * gdk_window_set_static_gravities:
2249  *     Set the bit gravity of the given window to static,
2250  *     and flag it so all children get static subwindow
2251  *     gravity.
2252  *   arguments:
2253  *     window: window for which to set static gravity
2254  *     use_static: Whether to turn static gravity on or off.
2255  *   results:
2256  *     Does the XServer support static gravity?
2257  *************************************************************/
2258
2259 gboolean 
2260 gdk_window_set_static_gravities (GdkWindow *window,
2261                                  gboolean   use_static)
2262 {
2263   GdkWindowObject *private = (GdkWindowObject *)window;
2264   GList *tmp_list;
2265   
2266   g_return_val_if_fail (window != NULL, FALSE);
2267   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2268
2269   if (!use_static == !private->guffaw_gravity)
2270     return TRUE;
2271   
2272   if (use_static && !gdk_window_gravity_works ())
2273     return FALSE;
2274   
2275   private->guffaw_gravity = use_static;
2276   
2277   if (!GDK_WINDOW_DESTROYED (window))
2278     {
2279       gdk_window_set_static_bit_gravity (window, use_static);
2280       
2281       tmp_list = private->children;
2282       while (tmp_list)
2283         {
2284           gdk_window_set_static_win_gravity (window, use_static);
2285           
2286           tmp_list = tmp_list->next;
2287         }
2288     }
2289   
2290   return TRUE;
2291 }
2292
2293 /* internal function created for and used by gdk_window_xid_at_coords */
2294 Window
2295 gdk_window_xid_at (Window   base,
2296                    gint     bx,
2297                    gint     by,
2298                    gint     x,
2299                    gint     y, 
2300                    GList   *excludes,
2301                    gboolean excl_child)
2302 {
2303   Display *xdisplay;
2304   Window *list = NULL;
2305   Window child = 0, parent_win = 0, root_win = 0;
2306   int i;
2307   unsigned int ww, wh, wb, wd, num;
2308   int wx, wy;
2309   
2310   xdisplay = GDK_DISPLAY ();
2311   if (!XGetGeometry (xdisplay, base, &root_win, &wx, &wy, &ww, &wh, &wb, &wd))
2312     return 0;
2313   wx += bx;
2314   wy += by;
2315   
2316   if (!((x >= wx) &&
2317         (y >= wy) &&
2318         (x < (int) (wx + ww)) &&
2319         (y < (int) (wy + wh))))
2320     return 0;
2321   
2322   if (!XQueryTree (xdisplay, base, &root_win, &parent_win, &list, &num))
2323     return base;
2324   
2325   if (list)
2326     {
2327       for (i = num - 1; ; i--)
2328         {
2329           if ((!excl_child) || (!g_list_find (excludes, (gpointer *) list[i])))
2330             {
2331               if ((child = gdk_window_xid_at (list[i], wx, wy, x, y, excludes, excl_child)) != 0)
2332                 {
2333                   XFree (list);
2334                   return child;
2335                 }
2336             }
2337           if (!i)
2338             break;
2339         }
2340       XFree (list);
2341     }
2342   return base;
2343 }
2344
2345 /* 
2346  * The following fucntion by The Rasterman <raster@redhat.com>
2347  * This function returns the X Window ID in which the x y location is in 
2348  * (x and y being relative to the root window), excluding any windows listed
2349  * in the GList excludes (this is a list of X Window ID's - gpointer being
2350  * the Window ID).
2351  * 
2352  * This is primarily designed for internal gdk use - for DND for example
2353  * when using a shaped icon window as the drag object - you exclude the
2354  * X Window ID of the "icon" (perhaps more if excludes may be needed) and
2355  * You can get back an X Window ID as to what X Window ID is infact under
2356  * those X,Y co-ordinates.
2357  */
2358 Window
2359 gdk_window_xid_at_coords (gint     x,
2360                           gint     y,
2361                           GList   *excludes,
2362                           gboolean excl_child)
2363 {
2364   GdkWindow *window;
2365   Display *xdisplay;
2366   Window *list = NULL;
2367   Window root, child = 0, parent_win = 0, root_win = 0;
2368   unsigned int num;
2369   int i;
2370
2371   window = gdk_parent_root;
2372   xdisplay = GDK_WINDOW_XDISPLAY (window);
2373   root = GDK_WINDOW_XID (window);
2374   num = g_list_length (excludes);
2375   
2376   XGrabServer (xdisplay);
2377   if (!XQueryTree (xdisplay, root, &root_win, &parent_win, &list, &num))
2378     {
2379       XUngrabServer (xdisplay);
2380       return root;
2381     }
2382   if (list)
2383     {
2384       i = num - 1;
2385       do
2386         {
2387           XWindowAttributes xwa;
2388           
2389           XGetWindowAttributes (xdisplay, list [i], &xwa);
2390           
2391           if (xwa.map_state != IsViewable)
2392             continue;
2393           
2394           if (excl_child && g_list_find (excludes, (gpointer *) list[i]))
2395             continue;
2396           
2397           if ((child = gdk_window_xid_at (list[i], 0, 0, x, y, excludes, excl_child)) == 0)
2398             continue;
2399           
2400           if (excludes)
2401             {
2402               if (!g_list_find (excludes, (gpointer *) child))
2403                 {
2404                   XFree (list);
2405                   XUngrabServer (xdisplay);
2406                   return child;
2407                 }
2408             }
2409           else
2410             {
2411               XFree (list);
2412               XUngrabServer (xdisplay);
2413               return child;
2414             }
2415         } while (--i > 0);
2416       XFree (list);
2417     }
2418   XUngrabServer (xdisplay);
2419   return root;
2420 }
2421