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