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