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