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