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