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