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