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