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