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