]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkwindow-x11.c
changed reversed_[12] to reserved_[12] in gtk_*_get_type functions.
[~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
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   old_parent_private->children = g_list_remove (old_parent_private->children, window);
857   parent_private->children = g_list_prepend (parent_private->children, window);
858   
859 }
860
861 void
862 gdk_window_clear (GdkWindow *window)
863 {
864   GdkWindowPrivate *private;
865
866   g_return_if_fail (window != NULL);
867
868   private = (GdkWindowPrivate*) window;
869
870   if (!private->destroyed)
871     XClearWindow (private->xdisplay, private->xwindow);
872 }
873
874 void
875 gdk_window_clear_area (GdkWindow *window,
876                        gint       x,
877                        gint       y,
878                        gint       width,
879                        gint       height)
880 {
881   GdkWindowPrivate *private;
882   
883   g_return_if_fail (window != NULL);
884   
885   private = (GdkWindowPrivate*) window;
886   
887   if (!private->destroyed)
888     XClearArea (private->xdisplay, private->xwindow,
889                 x, y, width, height, False);
890 }
891
892 void
893 gdk_window_clear_area_e (GdkWindow *window,
894                          gint       x,
895                          gint       y,
896                          gint       width,
897                          gint       height)
898 {
899   GdkWindowPrivate *private;
900   
901   g_return_if_fail (window != NULL);
902   
903   private = (GdkWindowPrivate*) window;
904   
905   if (!private->destroyed)
906     XClearArea (private->xdisplay, private->xwindow,
907                 x, y, width, height, True);
908 }
909
910 void
911 gdk_window_copy_area (GdkWindow    *window,
912                       GdkGC        *gc,
913                       gint          x,
914                       gint          y,
915                       GdkWindow    *source_window,
916                       gint          source_x,
917                       gint          source_y,
918                       gint          width,
919                       gint          height)
920 {
921   GdkWindowPrivate *src_private;
922   GdkWindowPrivate *dest_private;
923   GdkGCPrivate *gc_private;
924   
925   g_return_if_fail (window != NULL);
926   g_return_if_fail (gc != NULL);
927   
928   if (source_window == NULL)
929     source_window = window;
930   
931   src_private = (GdkWindowPrivate*) source_window;
932   dest_private = (GdkWindowPrivate*) window;
933   gc_private = (GdkGCPrivate*) gc;
934   
935   if (!src_private->destroyed && !dest_private->destroyed)
936     {
937       XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow,
938                  gc_private->xgc,
939                  source_x, source_y,
940                  width, height,
941                  x, y);
942     }
943 }
944
945 void
946 gdk_window_raise (GdkWindow *window)
947 {
948   GdkWindowPrivate *private;
949   
950   g_return_if_fail (window != NULL);
951   
952   private = (GdkWindowPrivate*) window;
953   
954   if (!private->destroyed)
955     XRaiseWindow (private->xdisplay, private->xwindow);
956 }
957
958 void
959 gdk_window_lower (GdkWindow *window)
960 {
961   GdkWindowPrivate *private;
962   
963   g_return_if_fail (window != NULL);
964   
965   private = (GdkWindowPrivate*) window;
966   
967   if (!private->destroyed)
968     XLowerWindow (private->xdisplay, private->xwindow);
969 }
970
971 void
972 gdk_window_set_user_data (GdkWindow *window,
973                           gpointer   user_data)
974 {
975   g_return_if_fail (window != NULL);
976   
977   window->user_data = user_data;
978 }
979
980 void
981 gdk_window_set_hints (GdkWindow *window,
982                       gint       x,
983                       gint       y,
984                       gint       min_width,
985                       gint       min_height,
986                       gint       max_width,
987                       gint       max_height,
988                       gint       flags)
989 {
990   GdkWindowPrivate *private;
991   XSizeHints size_hints;
992   
993   g_return_if_fail (window != NULL);
994   
995   private = (GdkWindowPrivate*) window;
996   if (private->destroyed)
997     return;
998   
999   size_hints.flags = 0;
1000   
1001   if (flags & GDK_HINT_POS)
1002     {
1003       size_hints.flags |= PPosition;
1004       size_hints.x = x;
1005       size_hints.y = y;
1006     }
1007   
1008   if (flags & GDK_HINT_MIN_SIZE)
1009     {
1010       size_hints.flags |= PMinSize;
1011       size_hints.min_width = min_width;
1012       size_hints.min_height = min_height;
1013     }
1014   
1015   if (flags & GDK_HINT_MAX_SIZE)
1016     {
1017       size_hints.flags |= PMaxSize;
1018       size_hints.max_width = max_width;
1019       size_hints.max_height = max_height;
1020     }
1021   
1022   if (flags)
1023     XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
1024 }
1025
1026 void
1027 gdk_window_set_title (GdkWindow   *window,
1028                       const gchar *title)
1029 {
1030   GdkWindowPrivate *private;
1031   
1032   g_return_if_fail (window != NULL);
1033   
1034   private = (GdkWindowPrivate*) window;
1035   if (!private->destroyed)
1036     XmbSetWMProperties (private->xdisplay, private->xwindow,
1037                         title, title, NULL, 0, NULL, NULL, NULL);
1038 }
1039
1040 void
1041 gdk_window_set_background (GdkWindow *window,
1042                            GdkColor  *color)
1043 {
1044   GdkWindowPrivate *private;
1045   
1046   g_return_if_fail (window != NULL);
1047   
1048   private = (GdkWindowPrivate*) window;
1049   if (!private->destroyed)
1050     XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel);
1051 }
1052
1053 void
1054 gdk_window_set_back_pixmap (GdkWindow *window,
1055                             GdkPixmap *pixmap,
1056                             gint       parent_relative)
1057 {
1058   GdkWindowPrivate *window_private;
1059   GdkPixmapPrivate *pixmap_private;
1060   Pixmap xpixmap;
1061   
1062   g_return_if_fail (window != NULL);
1063   
1064   window_private = (GdkWindowPrivate*) window;
1065   pixmap_private = (GdkPixmapPrivate*) pixmap;
1066   
1067   if (pixmap)
1068     xpixmap = pixmap_private->xwindow;
1069   else
1070     xpixmap = None;
1071   
1072   if (parent_relative)
1073     xpixmap = ParentRelative;
1074   
1075   if (!window_private->destroyed)
1076     XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap);
1077 }
1078
1079 void
1080 gdk_window_set_cursor (GdkWindow *window,
1081                        GdkCursor *cursor)
1082 {
1083   GdkWindowPrivate *window_private;
1084   GdkCursorPrivate *cursor_private;
1085   Cursor xcursor;
1086   
1087   g_return_if_fail (window != NULL);
1088   
1089   window_private = (GdkWindowPrivate*) window;
1090   cursor_private = (GdkCursorPrivate*) cursor;
1091   
1092   if (!cursor)
1093     xcursor = None;
1094   else
1095     xcursor = cursor_private->xcursor;
1096   
1097   if (!window_private->destroyed)
1098     XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor);
1099 }
1100
1101 void
1102 gdk_window_set_colormap (GdkWindow   *window,
1103                          GdkColormap *colormap)
1104 {
1105   GdkWindowPrivate *window_private;
1106   GdkColormapPrivate *colormap_private;
1107   
1108   g_return_if_fail (window != NULL);
1109   g_return_if_fail (colormap != NULL);
1110   
1111   window_private = (GdkWindowPrivate*) window;
1112   colormap_private = (GdkColormapPrivate*) colormap;
1113   
1114   if (!window_private->destroyed)
1115     {
1116       XSetWindowColormap (window_private->xdisplay,
1117                           window_private->xwindow,
1118                           colormap_private->xcolormap);
1119
1120       if (window_private->colormap)
1121         gdk_colormap_unref (window_private->colormap);
1122       window_private->colormap = colormap;
1123       gdk_colormap_ref (window_private->colormap);
1124       
1125       if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
1126         gdk_window_add_colormap_windows (window);
1127     }
1128 }
1129
1130 void
1131 gdk_window_get_user_data (GdkWindow *window,
1132                           gpointer  *data)
1133 {
1134   g_return_if_fail (window != NULL);
1135   
1136   *data = window->user_data;
1137 }
1138
1139 void
1140 gdk_window_get_geometry (GdkWindow *window,
1141                          gint      *x,
1142                          gint      *y,
1143                          gint      *width,
1144                          gint      *height,
1145                          gint      *depth)
1146 {
1147   GdkWindowPrivate *window_private;
1148   Window root;
1149   gint tx;
1150   gint ty;
1151   guint twidth;
1152   guint theight;
1153   guint tborder_width;
1154   guint tdepth;
1155   
1156   if (!window)
1157     window = (GdkWindow*) &gdk_root_parent;
1158   
1159   window_private = (GdkWindowPrivate*) window;
1160   
1161   if (!window_private->destroyed)
1162     {
1163       XGetGeometry (window_private->xdisplay, window_private->xwindow,
1164                     &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
1165       
1166       if (x)
1167         *x = tx;
1168       if (y)
1169         *y = ty;
1170       if (width)
1171         *width = twidth;
1172       if (height)
1173         *height = theight;
1174       if (depth)
1175         *depth = tdepth;
1176     }
1177 }
1178
1179 void
1180 gdk_window_get_position (GdkWindow *window,
1181                          gint      *x,
1182                          gint      *y)
1183 {
1184   GdkWindowPrivate *window_private;
1185   
1186   g_return_if_fail (window != NULL);
1187   
1188   window_private = (GdkWindowPrivate*) window;
1189   
1190   if (x)
1191     *x = window_private->x;
1192   if (y)
1193     *y = window_private->y;
1194 }
1195
1196 void
1197 gdk_window_get_size (GdkWindow *window,
1198                      gint       *width,
1199                      gint       *height)
1200 {
1201   GdkWindowPrivate *window_private;
1202   
1203   g_return_if_fail (window != NULL);
1204   
1205   window_private = (GdkWindowPrivate*) window;
1206   
1207   if (width)
1208     *width = window_private->width;
1209   if (height)
1210     *height = window_private->height;
1211 }
1212
1213 GdkVisual*
1214 gdk_window_get_visual (GdkWindow *window)
1215 {
1216   GdkWindowPrivate *window_private;
1217   XWindowAttributes window_attributes;
1218    
1219   g_return_val_if_fail (window != NULL, NULL);
1220
1221   window_private = (GdkWindowPrivate*) window;
1222   /* Huh? ->parent is never set for a pixmap. We should just return
1223    * null immeditately
1224    */
1225   while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
1226     window_private = (GdkWindowPrivate*) window_private->parent;
1227   
1228   if (window_private && !window_private->destroyed)
1229     {
1230        if (window_private->colormap == NULL)
1231          {
1232             XGetWindowAttributes (window_private->xdisplay,
1233                                   window_private->xwindow,
1234                                   &window_attributes);
1235             return gdk_visual_lookup (window_attributes.visual);
1236          }
1237        else
1238          return ((GdkColormapPrivate *)window_private->colormap)->visual;
1239     }
1240   
1241   return NULL;
1242 }
1243
1244 GdkColormap*
1245 gdk_window_get_colormap (GdkWindow *window)
1246 {
1247   GdkWindowPrivate *window_private;
1248   XWindowAttributes window_attributes;
1249   
1250   g_return_val_if_fail (window != NULL, NULL);
1251   window_private = (GdkWindowPrivate*) window;
1252
1253   g_return_val_if_fail (window_private->window_type != GDK_WINDOW_PIXMAP, NULL);
1254   if (!window_private->destroyed)
1255     {
1256       if (window_private->colormap == NULL)
1257         {
1258           XGetWindowAttributes (window_private->xdisplay,
1259                                 window_private->xwindow,
1260                                 &window_attributes);
1261           return gdk_colormap_lookup (window_attributes.colormap);
1262          }
1263        else
1264          return window_private->colormap;
1265     }
1266   
1267   return NULL;
1268 }
1269
1270 GdkWindowType
1271 gdk_window_get_type (GdkWindow *window)
1272 {
1273   GdkWindowPrivate *window_private;
1274
1275   g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
1276
1277   window_private = (GdkWindowPrivate*) window;
1278   return window_private->window_type;
1279 }
1280
1281 gint
1282 gdk_window_get_origin (GdkWindow *window,
1283                        gint      *x,
1284                        gint      *y)
1285 {
1286   GdkWindowPrivate *private;
1287   gint return_val;
1288   Window child;
1289   gint tx = 0;
1290   gint ty = 0;
1291
1292   g_return_val_if_fail (window != NULL, 0);
1293
1294   private = (GdkWindowPrivate*) window;
1295
1296   if (!private->destroyed)
1297     {
1298       return_val = XTranslateCoordinates (private->xdisplay,
1299                                           private->xwindow,
1300                                           gdk_root_window,
1301                                           0, 0, &tx, &ty,
1302                                           &child);
1303       
1304     }
1305   else
1306     return_val = 0;
1307   
1308   if (x)
1309     *x = tx;
1310   if (y)
1311     *y = ty;
1312   
1313   return return_val;
1314 }
1315
1316 GdkWindow*
1317 gdk_window_get_pointer (GdkWindow       *window,
1318                         gint            *x,
1319                         gint            *y,
1320                         GdkModifierType *mask)
1321 {
1322   GdkWindowPrivate *private;
1323   GdkWindow *return_val;
1324   Window root;
1325   Window child;
1326   int rootx, rooty;
1327   int winx = 0;
1328   int winy = 0;
1329   unsigned int xmask = 0;
1330
1331   if (!window)
1332     window = (GdkWindow*) &gdk_root_parent;
1333
1334   private = (GdkWindowPrivate*) window;
1335
1336   return_val = NULL;
1337   if (!private->destroyed &&
1338       XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
1339                      &rootx, &rooty, &winx, &winy, &xmask))
1340     {
1341       if (child)
1342         return_val = gdk_window_lookup (child);
1343     }
1344   
1345   if (x)
1346     *x = winx;
1347   if (y)
1348     *y = winy;
1349   if (mask)
1350     *mask = xmask;
1351   
1352   return return_val;
1353 }
1354
1355 GdkWindow*
1356 gdk_window_at_pointer (gint *win_x,
1357                        gint *win_y)
1358 {
1359   GdkWindowPrivate *private;
1360   GdkWindow *window;
1361   Window root;
1362   Window xwindow;
1363   Window xwindow_last = 0;
1364   int rootx = -1, rooty = -1;
1365   int winx, winy;
1366   unsigned int xmask;
1367
1368   private = &gdk_root_parent;
1369
1370   xwindow = private->xwindow;
1371
1372   XGrabServer (private->xdisplay);
1373   while (xwindow)
1374     {
1375       xwindow_last = xwindow;
1376       XQueryPointer (private->xdisplay,
1377                      xwindow,
1378                      &root, &xwindow,
1379                      &rootx, &rooty,
1380                      &winx, &winy,
1381                      &xmask);
1382     }
1383   XUngrabServer (private->xdisplay);
1384   
1385   window = gdk_window_lookup (xwindow_last);
1386
1387   if (win_x)
1388     *win_x = window ? winx : -1;
1389   if (win_y)
1390     *win_y = window ? winy : -1;
1391
1392   return window;
1393 }
1394
1395 GdkWindow*
1396 gdk_window_get_parent (GdkWindow *window)
1397 {
1398   g_return_val_if_fail (window != NULL, NULL);
1399
1400   return ((GdkWindowPrivate*) window)->parent;
1401 }
1402
1403 GdkWindow*
1404 gdk_window_get_toplevel (GdkWindow *window)
1405 {
1406   GdkWindowPrivate *private;
1407
1408   g_return_val_if_fail (window != NULL, NULL);
1409
1410   private = (GdkWindowPrivate*) window;
1411
1412   while (private->window_type == GDK_WINDOW_CHILD)
1413     {
1414       window = ((GdkWindowPrivate*) window)->parent;
1415       private = (GdkWindowPrivate*) window;
1416     }
1417
1418   return window;
1419 }
1420
1421 GList*
1422 gdk_window_get_children (GdkWindow *window)
1423 {
1424   GdkWindowPrivate *private;
1425   GdkWindow *child;
1426   GList *children;
1427   Window root;
1428   Window parent;
1429   Window *xchildren;
1430   unsigned int nchildren;
1431   unsigned int i;
1432
1433   g_return_val_if_fail (window != NULL, NULL);
1434
1435   private = (GdkWindowPrivate*) window;
1436   if (private->destroyed)
1437     return NULL;
1438
1439   XQueryTree (private->xdisplay, private->xwindow,
1440               &root, &parent, &xchildren, &nchildren);
1441
1442   children = NULL;
1443
1444   if (nchildren > 0)
1445     {
1446       for (i = 0; i < nchildren; i++)
1447         {
1448           child = gdk_window_lookup (xchildren[i]);
1449           if (child)
1450             children = g_list_prepend (children, child);
1451         }
1452
1453       if (xchildren)
1454         XFree (xchildren);
1455     }
1456
1457   return children;
1458 }
1459
1460 GdkEventMask  
1461 gdk_window_get_events      (GdkWindow       *window)
1462 {
1463   GdkWindowPrivate *private;
1464   XWindowAttributes attrs;
1465   GdkEventMask event_mask;
1466   int i;
1467
1468   g_return_val_if_fail (window != NULL, 0);
1469
1470   private = (GdkWindowPrivate*) window;
1471   if (private->destroyed)
1472     return 0;
1473
1474   XGetWindowAttributes (gdk_display, private->xwindow, 
1475                         &attrs);
1476
1477   event_mask = 0;
1478   for (i = 0; i < nevent_masks; i++)
1479     {
1480       if (attrs.your_event_mask & event_mask_table[i])
1481         event_mask |= 1 << (i + 1);
1482     }
1483
1484   return event_mask;
1485 }
1486
1487 void          
1488 gdk_window_set_events      (GdkWindow       *window,
1489                             GdkEventMask     event_mask)
1490 {
1491   GdkWindowPrivate *private;
1492   long xevent_mask;
1493   int i;
1494
1495   g_return_if_fail (window != NULL);
1496
1497   private = (GdkWindowPrivate*) window;
1498   if (private->destroyed)
1499     return;
1500
1501   xevent_mask = StructureNotifyMask;
1502   for (i = 0; i < nevent_masks; i++)
1503     {
1504       if (event_mask & (1 << (i + 1)))
1505         xevent_mask |= event_mask_table[i];
1506     }
1507   
1508   XSelectInput (gdk_display, private->xwindow, 
1509                 xevent_mask);
1510 }
1511
1512 void
1513 gdk_window_add_colormap_windows (GdkWindow *window)
1514 {
1515   GdkWindow *toplevel;
1516   GdkWindowPrivate *toplevel_private;
1517   GdkWindowPrivate *window_private;
1518   Window *old_windows;
1519   Window *new_windows;
1520   int i, count;
1521
1522   g_return_if_fail (window != NULL);
1523
1524   toplevel = gdk_window_get_toplevel (window);
1525   toplevel_private = (GdkWindowPrivate*) toplevel;
1526   window_private = (GdkWindowPrivate*) window;
1527   if (window_private->destroyed)
1528     return;
1529
1530   old_windows = NULL;
1531   if (!XGetWMColormapWindows (toplevel_private->xdisplay,
1532                               toplevel_private->xwindow,
1533                               &old_windows, &count))
1534     {
1535       count = 0;
1536     }
1537
1538   for (i = 0; i < count; i++)
1539     if (old_windows[i] == window_private->xwindow)
1540       {
1541         XFree (old_windows);
1542         return;
1543       }
1544
1545   new_windows = g_new (Window, count + 1);
1546
1547   for (i = 0; i < count; i++)
1548     new_windows[i] = old_windows[i];
1549   new_windows[count] = window_private->xwindow;
1550
1551   XSetWMColormapWindows (toplevel_private->xdisplay,
1552                          toplevel_private->xwindow,
1553                          new_windows, count + 1);
1554
1555   g_free (new_windows);
1556   if (old_windows)
1557     XFree (old_windows);
1558 }
1559
1560 /*
1561  * This needs the X11 shape extension.
1562  * If not available, shaped windows will look
1563  * ugly, but programs still work.    Stefan Wille
1564  */
1565 void
1566 gdk_window_shape_combine_mask (GdkWindow *window,
1567                                GdkBitmap *mask,
1568                                gint x, gint y)
1569 {
1570   enum { UNKNOWN, NO, YES };
1571
1572   static gint have_shape = UNKNOWN;
1573
1574   GdkWindowPrivate *window_private;
1575   Pixmap pixmap;
1576
1577   g_return_if_fail (window != NULL);
1578
1579 #ifdef HAVE_SHAPE_EXT
1580   if (have_shape == UNKNOWN)
1581     {
1582       int ignore;
1583       if (XQueryExtension(gdk_display, "SHAPE", &ignore, &ignore, &ignore))
1584         have_shape = YES;
1585       else
1586         have_shape = NO;
1587     }
1588   
1589   if (have_shape == YES)
1590     {
1591       window_private = (GdkWindowPrivate*) window;
1592       if (window_private->destroyed)
1593         return;
1594       
1595       if (mask)
1596         {
1597           GdkWindowPrivate *pixmap_private;
1598           
1599           pixmap_private = (GdkWindowPrivate*) mask;
1600           pixmap = (Pixmap) pixmap_private->xwindow;
1601         }
1602       else
1603         {
1604           x = 0;
1605           y = 0;
1606           pixmap = None;
1607         }
1608       
1609       XShapeCombineMask  (window_private->xdisplay,
1610                           window_private->xwindow,
1611                           ShapeBounding,
1612                           x, y,
1613                           pixmap,
1614                           ShapeSet);
1615     }
1616 #endif /* HAVE_SHAPE_EXT */
1617 }
1618
1619 void
1620 gdk_dnd_drag_addwindow (GdkWindow *window)
1621 {
1622   GdkWindowPrivate *window_private;
1623   
1624   g_return_if_fail (window != NULL);
1625   
1626   window_private = (GdkWindowPrivate *) window;
1627   if (window_private->destroyed)
1628     return;
1629   
1630   if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
1631     {
1632       gdk_dnd.drag_numwindows++;
1633       gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
1634                                              gdk_dnd.drag_numwindows
1635                                              * sizeof(GdkWindow *));
1636       gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
1637       window_private->dnd_drag_accepted = 0;
1638     } 
1639   else
1640     g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
1641 }
1642
1643 void
1644 gdk_window_dnd_drag_set (GdkWindow   *window,
1645                          guint8       drag_enable,
1646                          gchar      **typelist,
1647                          guint        numtypes)
1648 {
1649   GdkWindowPrivate *window_private;
1650   int i, wasset = 0;
1651   
1652   g_return_if_fail (window != NULL);
1653   window_private = (GdkWindowPrivate *) window;
1654   if (window_private->destroyed)
1655     return;
1656   
1657   window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
1658   
1659   if (drag_enable)
1660     {
1661       g_return_if_fail(typelist != NULL);
1662       
1663       if (window_private->dnd_drag_data_numtypesavail > 3)
1664         wasset = 1;
1665       window_private->dnd_drag_data_numtypesavail = numtypes;
1666       
1667       window_private->dnd_drag_data_typesavail =
1668         g_realloc (window_private->dnd_drag_data_typesavail,
1669                    (numtypes + 1) * sizeof (GdkAtom));
1670       
1671       for (i = 0; i < numtypes; i++)
1672         {
1673           /* Allow blanket use of ALL to get anything... */
1674           if (strcmp (typelist[i], "ALL"))
1675             window_private->dnd_drag_data_typesavail[i] =
1676               gdk_atom_intern (typelist[i], FALSE);
1677           else
1678             window_private->dnd_drag_data_typesavail[i] = None;
1679         }
1680       
1681       /* 
1682        * set our extended type list if we need to 
1683        */
1684       if (numtypes > 3)
1685         gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
1686                             XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
1687                             (guchar *)(window_private->dnd_drag_data_typesavail
1688                              + (sizeof(GdkAtom) * 3)),
1689                             (numtypes - 3) * sizeof(GdkAtom));
1690       else if (wasset)
1691         gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
1692     }
1693   else
1694     {
1695       g_free (window_private->dnd_drag_data_typesavail);
1696       window_private->dnd_drag_data_typesavail = NULL;
1697       window_private->dnd_drag_data_numtypesavail = 0;
1698     }
1699 }
1700
1701 void
1702 gdk_window_dnd_drop_set (GdkWindow   *window,
1703                          guint8       drop_enable,
1704                          gchar      **typelist,
1705                          guint        numtypes,
1706                          guint8       destructive_op)
1707 {
1708   GdkWindowPrivate *window_private;
1709   int i;
1710   
1711   g_return_if_fail (window != NULL);
1712   window_private = (GdkWindowPrivate *) window;
1713   if (window_private->destroyed)
1714     return;
1715   
1716   window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
1717   if (drop_enable)
1718     {
1719       g_return_if_fail(typelist != NULL);
1720       
1721       window_private->dnd_drop_data_numtypesavail = numtypes;
1722       
1723       window_private->dnd_drop_data_typesavail =
1724         g_realloc (window_private->dnd_drop_data_typesavail,
1725                    (numtypes + 1) * sizeof (GdkAtom));
1726       
1727       for (i = 0; i < numtypes; i++)
1728         window_private->dnd_drop_data_typesavail[i] =
1729           gdk_atom_intern (typelist[i], FALSE);
1730       
1731       window_private->dnd_drop_destructive_op = destructive_op;
1732     }
1733 }
1734
1735 /* 
1736  * This is used to reply to a GDK_DRAG_REQUEST event
1737  * (which may be generated by XdeRequest or a confirmed drop... 
1738  */
1739 void
1740 gdk_window_dnd_data_set (GdkWindow       *window,
1741                          GdkEvent        *event,
1742                          gpointer         data,
1743                          gulong           data_numbytes)
1744 {
1745   GdkWindowPrivate *window_private;
1746   XEvent sev;
1747   GdkEventDropDataAvailable tmp_ev;
1748   gchar *tmp;
1749   
1750   g_return_if_fail (window != NULL);
1751   g_return_if_fail (event != NULL);
1752   g_return_if_fail (data != NULL);
1753   g_return_if_fail (data_numbytes > 0);
1754   g_return_if_fail (event->type == GDK_DRAG_REQUEST);
1755
1756   window_private = (GdkWindowPrivate *) window;
1757   g_return_if_fail (window_private->dnd_drag_accepted != 0);    
1758   if (window_private->destroyed)
1759     return;
1760   
1761   /* We set the property on our window... */
1762   gdk_property_change (window, window_private->dnd_drag_data_type,
1763                        XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
1764                        data_numbytes);
1765   tmp = gdk_atom_name(window_private->dnd_drag_data_type);
1766 #ifdef DEBUG_DND
1767   g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow);
1768 #endif
1769   g_free(tmp);
1770   
1771   /* 
1772    * Then we send the event to tell the receiving window that the
1773    * drop has happened 
1774    */
1775   tmp_ev.u.allflags = 0;
1776   tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
1777   tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
1778   
1779   sev.xclient.type = ClientMessage;
1780   sev.xclient.format = 32;
1781   sev.xclient.window = event->dragrequest.requestor;
1782   sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
1783   sev.xclient.data.l[0] = window_private->xwindow;
1784   sev.xclient.data.l[1] = tmp_ev.u.allflags;
1785   sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
1786
1787   if (event->dragrequest.isdrop)
1788     sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
1789       (event->dragrequest.drop_coords.y << 16);
1790   else
1791     sev.xclient.data.l[3] = 0;
1792
1793   sev.xclient.data.l[4] = event->dragrequest.timestamp;
1794
1795   if (!gdk_send_xevent (event->dragrequest.requestor, False,
1796                        StructureNotifyMask, &sev))
1797     GDK_NOTE (DND, g_print("Sending XdeDataAvailable to %#x failed\n",
1798                            event->dragrequest.requestor));
1799
1800 }
1801
1802 void          
1803 gdk_window_add_filter     (GdkWindow     *window,
1804                            GdkFilterFunc  function,
1805                            gpointer       data)
1806 {
1807   GdkWindowPrivate *private;
1808   GList *tmp_list;
1809   GdkEventFilter *filter;
1810
1811   private = (GdkWindowPrivate*) window;
1812   if (private && private->destroyed)
1813     return;
1814
1815   if(private)
1816     tmp_list = private->filters;
1817   else
1818     tmp_list = gdk_default_filters;
1819
1820   while (tmp_list)
1821     {
1822       filter = (GdkEventFilter *)tmp_list->data;
1823       if ((filter->function == function) && (filter->data == data))
1824         return;
1825       tmp_list = tmp_list->next;
1826     }
1827
1828   filter = g_new (GdkEventFilter, 1);
1829   filter->function = function;
1830   filter->data = data;
1831
1832   if(private)
1833     private->filters = g_list_append (private->filters, filter);
1834   else
1835     gdk_default_filters = g_list_append (gdk_default_filters, filter);
1836 }
1837
1838 void
1839 gdk_window_remove_filter  (GdkWindow     *window,
1840                            GdkFilterFunc  function,
1841                            gpointer       data)
1842 {
1843   GdkWindowPrivate *private;
1844   GList *tmp_list;
1845   GdkEventFilter *filter;
1846
1847   private = (GdkWindowPrivate*) window;
1848
1849   if(private)
1850     tmp_list = private->filters;
1851   else
1852     tmp_list = gdk_default_filters;
1853
1854   while (tmp_list)
1855     {
1856       filter = (GdkEventFilter *)tmp_list->data;
1857       tmp_list = tmp_list->next;
1858
1859       if ((filter->function == function) && (filter->data == data))
1860         {
1861           if(private)
1862             private->filters = g_list_remove_link (private->filters, tmp_list);
1863           else
1864             gdk_default_filters = g_list_remove_link (gdk_default_filters, tmp_list);
1865           g_list_free_1 (tmp_list);
1866           g_free (filter);
1867           
1868           return;
1869         }
1870     }
1871 }
1872
1873 void
1874 gdk_window_set_override_redirect(GdkWindow *window,
1875                                  gboolean override_redirect)
1876 {
1877   GdkWindowPrivate *private;
1878   XSetWindowAttributes attr;
1879
1880   g_return_if_fail (window != NULL);
1881   private = (GdkWindowPrivate*) window;
1882   if (private->destroyed)
1883     return;
1884
1885   attr.override_redirect = (override_redirect == FALSE)?False:True;
1886   XChangeWindowAttributes(gdk_display,
1887                           ((GdkWindowPrivate *)window)->xwindow,
1888                           CWOverrideRedirect,
1889                           &attr);
1890 }
1891
1892 void          
1893 gdk_window_set_icon        (GdkWindow *window, 
1894                             GdkWindow *icon_window,
1895                             GdkPixmap *pixmap,
1896                             GdkBitmap *mask)
1897 {
1898   XWMHints wm_hints;
1899   GdkWindowPrivate *window_private;
1900   GdkWindowPrivate *private;
1901
1902   g_return_if_fail (window != NULL);
1903   window_private = (GdkWindowPrivate*) window;
1904   if (window_private->destroyed)
1905     return;
1906
1907   wm_hints.flags = 0;
1908   
1909   if (icon_window != NULL)
1910     {
1911       private = (GdkWindowPrivate *)icon_window;
1912       wm_hints.flags |= IconWindowHint;
1913       wm_hints.icon_window = private->xwindow;
1914     }
1915
1916   if (pixmap != NULL)
1917     {
1918       private = (GdkWindowPrivate *)pixmap;
1919       wm_hints.flags |= IconPixmapHint;
1920       wm_hints.icon_pixmap = private->xwindow;
1921     }
1922
1923   if (mask != NULL)
1924     {
1925       private = (GdkWindowPrivate *)mask;
1926       wm_hints.flags |= IconMaskHint;
1927       wm_hints.icon_mask = private->xwindow;
1928     }
1929
1930   XSetWMHints (window_private->xdisplay, window_private->xwindow, &wm_hints);
1931 }
1932
1933 void          
1934 gdk_window_set_icon_name   (GdkWindow *window, 
1935                             gchar *    name)
1936 {
1937   GdkWindowPrivate *window_private;
1938   XTextProperty property;
1939   gint res;
1940
1941   g_return_if_fail (window != NULL);
1942   window_private = (GdkWindowPrivate*) window;
1943   if (window_private->destroyed)
1944     return;
1945   res = XmbTextListToTextProperty (window_private->xdisplay,
1946                                    &name, 1, XStdICCTextStyle,
1947                                    &property);
1948   if (res < 0)
1949     {
1950       g_warning("Error converting icon name to text property: %d\n", res);
1951       return;
1952     }
1953
1954   XSetWMIconName (window_private->xdisplay, window_private->xwindow,
1955                   &property);
1956
1957   if (property.value)
1958     XFree (property.value);
1959 }
1960
1961 void          
1962 gdk_window_set_group   (GdkWindow *window, 
1963                         GdkWindow *leader)
1964 {
1965   XWMHints wm_hints;
1966   GdkWindowPrivate *window_private;
1967   GdkWindowPrivate *private;
1968
1969   g_return_if_fail (window != NULL);
1970   g_return_if_fail (leader != NULL);
1971   window_private = (GdkWindowPrivate*) window;
1972   if (window_private->destroyed)
1973     return;
1974
1975   private = (GdkWindowPrivate *)leader;
1976   wm_hints.flags = WindowGroupHint;
1977   wm_hints.window_group = private->xwindow;
1978
1979   XSetWMHints (window_private->xdisplay, window_private->xwindow, &wm_hints);
1980 }
1981
1982 static void
1983 gdk_window_set_mwm_hints (GdkWindow *window,
1984                           MotifWmHints *new_hints)
1985 {
1986   static Atom hints_atom = None;
1987   MotifWmHints *hints;
1988   Atom type;
1989   gint format;
1990   gulong nitems;
1991   gulong bytes_after;
1992
1993   GdkWindowPrivate *window_private;
1994
1995   g_return_if_fail (window != NULL);
1996   window_private = (GdkWindowPrivate*) window;
1997   if (window_private->destroyed)
1998     return;
1999
2000   if (!hints_atom)
2001     hints_atom = XInternAtom (window_private->xdisplay, 
2002                               _XA_MOTIF_WM_HINTS, FALSE);
2003   
2004   XGetWindowProperty (window_private->xdisplay, window_private->xwindow,
2005                       hints_atom, 0, sizeof(MotifWmHints)/4,
2006                       False, AnyPropertyType, &type, &format, &nitems,
2007                       &bytes_after, (guchar **)&hints);
2008
2009   if (type == None)
2010     hints = new_hints;
2011   else
2012     {
2013       if (new_hints->flags & MWM_HINTS_FUNCTIONS)
2014         {
2015           hints->flags |= MWM_HINTS_FUNCTIONS;
2016           hints->functions = new_hints->functions;
2017         }
2018       if (new_hints->flags & MWM_HINTS_DECORATIONS)
2019         {
2020           hints->flags |= MWM_HINTS_DECORATIONS;
2021           hints->decorations = new_hints->decorations;
2022         }
2023     }
2024
2025   XChangeProperty (window_private->xdisplay, window_private->xwindow,
2026                    hints_atom, hints_atom, 32, PropModeReplace,
2027                    (guchar *)hints, sizeof(MotifWmHints)/4);
2028
2029   if (hints != new_hints)
2030     XFree (hints);
2031 }
2032
2033 void
2034 gdk_window_set_decorations (GdkWindow      *window,
2035                             GdkWMDecoration decorations)
2036 {
2037   MotifWmHints hints;
2038
2039   hints.flags = MWM_HINTS_DECORATIONS;
2040   hints.decorations = decorations;
2041
2042   gdk_window_set_mwm_hints (window, &hints);
2043 }
2044
2045 void
2046 gdk_window_set_functions (GdkWindow    *window,
2047                           GdkWMFunction functions)
2048 {
2049   MotifWmHints hints;
2050
2051   hints.flags = MWM_HINTS_FUNCTIONS;
2052   hints.functions = functions;
2053
2054   gdk_window_set_mwm_hints (window, &hints);
2055 }
2056
2057 GList *
2058 gdk_window_get_toplevels (void)
2059 {
2060   GList *new_list = NULL;
2061   GList *tmp_list;
2062
2063   tmp_list = gdk_root_parent.children;
2064   while (tmp_list)
2065     {
2066       new_list = g_list_prepend (new_list, tmp_list->data);
2067       tmp_list = tmp_list->next;
2068     }
2069
2070   return new_list;
2071 }
2072