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