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