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