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