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