]> Pileus Git - ~andy/gtk/blob - gdk/gdkwindow.c
Reference count the fonts used in the text widget.
[~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_message ("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 = g_get_prgname ();
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 = NULL;
469   guint nchildren;
470
471   if(!XGetWindowAttributes (gdk_display, anid, &attrs)) {
472     g_warning("XGetWindowAttributes failed on window ID %d\n", anid);
473     return NULL;
474   }
475
476   private = g_new (GdkWindowPrivate, 1);
477   window = (GdkWindow*) private;
478
479   /* FIXME: This is pretty expensive. Maybe the caller should supply
480    *        the parent */
481   XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren);
482
483   if (children)
484     XFree (children);
485   private->parent = gdk_xid_table_lookup (parent);
486
487   parent_private = (GdkWindowPrivate *)private->parent;
488   
489   if (parent_private)
490     parent_private->children = g_list_prepend (parent_private->children, window);
491
492   private->xwindow = anid;
493   private->xdisplay = gdk_display;
494   private->x = attrs.x;
495   private->y = attrs.y;
496   private->width = attrs.width;
497   private->height = attrs.height;
498   private->resize_count = 0;
499   private->ref_count = 1;
500   private->window_type = GDK_WINDOW_FOREIGN;
501   private->destroyed = FALSE;
502   private->extension_events = 0;
503
504   private->colormap = NULL;
505
506   private->dnd_drag_data_type = None;
507   private->dnd_drag_data_typesavail =
508     private->dnd_drop_data_typesavail = NULL;
509   private->dnd_drop_enabled = private->dnd_drag_enabled =
510     private->dnd_drag_accepted = private->dnd_drag_datashow =
511     private->dnd_drop_data_numtypesavail =
512     private->dnd_drag_data_numtypesavail = 0;
513   private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
514
515   private->filters = NULL;
516   private->children = NULL;
517
518   window->user_data = NULL;
519
520   gdk_window_ref (window);
521   gdk_xid_table_insert (&private->xwindow, window);
522
523   return window;
524 }
525
526 /* Call this function when you want a window and all its children to
527    disappear.  When xdestroy is true, a request to destroy the XWindow
528    is sent out.  When it is false, it is assumed that the XWindow has
529    been or will be destroyed by destroying some ancestor of this
530    window.  */
531
532 static void
533 gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
534                              gboolean our_destroy)
535 {
536   GdkWindowPrivate *private;
537   GdkWindowPrivate *temp_private;
538   GdkWindow *temp_window;
539   GList *children;
540   GList *tmp;
541
542   g_return_if_fail (window != NULL);
543
544   private = (GdkWindowPrivate*) window;
545
546   switch (private->window_type)
547     {
548     case GDK_WINDOW_TOPLEVEL:
549     case GDK_WINDOW_CHILD:
550     case GDK_WINDOW_DIALOG:
551     case GDK_WINDOW_TEMP:
552     case GDK_WINDOW_FOREIGN:
553       if (!private->destroyed)
554         {
555           if (private->parent)
556             {
557               GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent;
558               if (parent_private->children)
559                 parent_private->children = g_list_remove (parent_private->children, window);
560             }
561
562           if (private->window_type != GDK_WINDOW_FOREIGN)
563             {
564               children = tmp = private->children;
565               private->children = NULL;
566
567               while (tmp)
568                 {
569                   temp_window = tmp->data;
570                   tmp = tmp->next;
571                   
572                   temp_private = (GdkWindowPrivate*) temp_window;
573                   if (temp_private)
574                     gdk_window_internal_destroy (temp_window, FALSE,
575                                                  our_destroy);
576                 }
577
578               g_list_free (children);
579             }
580
581           if (private->extension_events != 0)
582             gdk_input_window_destroy (window);
583
584           if(private->dnd_drag_data_numtypesavail > 0) 
585             {
586               g_free (private->dnd_drag_data_typesavail);
587               private->dnd_drag_data_typesavail = NULL;
588             }
589           if(private->dnd_drop_data_numtypesavail > 0) 
590             {
591               g_free (private->dnd_drop_data_typesavail);
592               private->dnd_drop_data_typesavail = NULL;
593             }
594
595           if (private->filters)
596             {
597               tmp = private->filters;
598
599               while (tmp)
600                 {
601                   g_free (tmp->data);
602                   tmp = tmp->next;
603                 }
604
605               g_list_free (private->filters);
606               private->filters = NULL;
607             }
608           
609           if (private->window_type == GDK_WINDOW_FOREIGN)
610             {
611               if (our_destroy && (private->parent != NULL))
612                 {
613                   /* It's somebody elses window, but in our heirarchy,
614                    * so reparent it to the root window, and then send
615                    * it a delete event, as if we were a WM
616                    */
617                   XClientMessageEvent xevent;
618                   
619                   gdk_window_hide (window);
620                   gdk_window_reparent (window, NULL, 0, 0);
621                   
622                   xevent.type = ClientMessage;
623                   xevent.window = private->xwindow;
624                   xevent.message_type = gdk_wm_protocols;
625                   xevent.format = 32;
626                   xevent.data.l[0] = gdk_wm_delete_window;
627                   xevent.data.l[1] = CurrentTime;
628                   
629                   XSendEvent (private->xdisplay, private->xwindow,
630                               False, 0, (XEvent *)&xevent);
631                 }
632             }
633           else if (xdestroy)
634             XDestroyWindow (private->xdisplay, private->xwindow);
635
636           if (private->colormap)
637             gdk_colormap_unref (private->colormap);
638
639           private->destroyed = TRUE;
640         }
641       break;
642
643     case GDK_WINDOW_ROOT:
644       g_error ("attempted to destroy root window");
645       break;
646
647     case GDK_WINDOW_PIXMAP:
648       g_error ("called gdk_window_destroy on a pixmap (use gdk_pixmap_unref)");
649       break;
650     }
651 }
652
653 /* Like internal_destroy, but also destroys the reference created by
654    gdk_window_new. */
655
656 void
657 gdk_window_destroy (GdkWindow *window)
658 {
659   gdk_window_internal_destroy (window, TRUE, TRUE);
660   gdk_window_unref (window);
661 }
662
663 /* This function is called when the XWindow is really gone.  */
664
665 void
666 gdk_window_destroy_notify (GdkWindow *window)
667 {
668   GdkWindowPrivate *private;
669
670   g_return_if_fail (window != NULL);
671
672   private = (GdkWindowPrivate*) window;
673
674   if (!private->destroyed)
675     {
676       if (private->window_type == GDK_WINDOW_FOREIGN)
677         gdk_window_internal_destroy (window, FALSE, FALSE);
678       else
679         g_warning ("GdkWindow %#lx unexpectedly destroyed", private->xwindow);
680     }
681   
682   gdk_xid_table_remove (private->xwindow);
683   gdk_window_unref (window);
684 }
685
686 GdkWindow*
687 gdk_window_ref (GdkWindow *window)
688 {
689   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
690   g_return_val_if_fail (window != NULL, NULL);
691
692   private->ref_count += 1;
693   return window;
694 }
695
696 void
697 gdk_window_unref (GdkWindow *window)
698 {
699   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
700   g_return_if_fail (window != NULL);
701
702   private->ref_count -= 1;
703   if (private->ref_count == 0)
704     {
705       if (!private->destroyed)
706         g_warning ("losing last reference to undestroyed window\n");
707       g_dataset_destroy (window);
708       g_free (window);
709     }
710
711 }
712
713 void
714 gdk_window_show (GdkWindow *window)
715 {
716   GdkWindowPrivate *private;
717
718   g_return_if_fail (window != NULL);
719
720   private = (GdkWindowPrivate*) window;
721   if (!private->destroyed)
722     {
723       XRaiseWindow (private->xdisplay, private->xwindow);
724       XMapWindow (private->xdisplay, private->xwindow);
725     }
726 }
727
728 void
729 gdk_window_hide (GdkWindow *window)
730 {
731   GdkWindowPrivate *private;
732
733   g_return_if_fail (window != NULL);
734
735   private = (GdkWindowPrivate*) window;
736   if (!private->destroyed)
737     XUnmapWindow (private->xdisplay, private->xwindow);
738 }
739
740 void
741 gdk_window_withdraw (GdkWindow *window)
742 {
743   GdkWindowPrivate *private;
744
745   g_return_if_fail (window != NULL);
746
747   private = (GdkWindowPrivate*) window;
748   if (!private->destroyed)
749     XWithdrawWindow (private->xdisplay, private->xwindow, 0);
750 }
751
752 void
753 gdk_window_move (GdkWindow *window,
754                  gint       x,
755                  gint       y)
756 {
757   GdkWindowPrivate *private;
758
759   g_return_if_fail (window != NULL);
760
761   private = (GdkWindowPrivate*) window;
762   if (!private->destroyed)
763     {
764       XMoveWindow (private->xdisplay, private->xwindow, x, y);
765       
766       if (private->window_type == GDK_WINDOW_CHILD)
767         {
768           private->x = x;
769           private->y = y;
770         }
771     }
772 }
773
774 void
775 gdk_window_resize (GdkWindow *window,
776                    gint       width,
777                    gint       height)
778 {
779   GdkWindowPrivate *private;
780
781   g_return_if_fail (window != NULL);
782
783   if (width < 1)
784     width = 1;
785   if (height < 1)
786     height = 1;
787
788   private = (GdkWindowPrivate*) window;
789
790   if (!private->destroyed &&
791       ((private->resize_count > 0) ||
792        (private->width != (guint16) width) ||
793        (private->height != (guint16) height)))
794     {
795       XResizeWindow (private->xdisplay, private->xwindow, width, height);
796       private->resize_count += 1;
797
798       if (private->window_type == GDK_WINDOW_CHILD)
799         {
800           private->width = width;
801           private->height = height;
802         }
803     }
804 }
805
806 void
807 gdk_window_move_resize (GdkWindow *window,
808                         gint       x,
809                         gint       y,
810                         gint       width,
811                         gint       height)
812 {
813   GdkWindowPrivate *private;
814
815   g_return_if_fail (window != NULL);
816
817   if (width < 1)
818     width = 1;
819   if (height < 1)
820     height = 1;
821
822   private = (GdkWindowPrivate*) window;
823   if (!private->destroyed)
824     {
825       XMoveResizeWindow (private->xdisplay, private->xwindow, x, y, width, height);
826       
827       if (private->window_type == GDK_WINDOW_CHILD)
828         {
829           private->x = x;
830           private->y = y;
831           private->width = width;
832           private->height = height;
833         }
834     }
835 }
836
837 void
838 gdk_window_reparent (GdkWindow *window,
839                      GdkWindow *new_parent,
840                      gint       x,
841                      gint       y)
842 {
843   GdkWindowPrivate *window_private;
844   GdkWindowPrivate *parent_private;
845   GdkWindowPrivate *old_parent_private;
846
847   g_return_if_fail (window != NULL);
848
849   if (!new_parent)
850     new_parent = (GdkWindow*) &gdk_root_parent;
851
852   window_private = (GdkWindowPrivate*) window;
853   old_parent_private = (GdkWindowPrivate*)window_private->parent;
854   parent_private = (GdkWindowPrivate*) new_parent;
855
856   if (!window_private->destroyed && !parent_private->destroyed)
857     XReparentWindow (window_private->xdisplay,
858                      window_private->xwindow,
859                      parent_private->xwindow,
860                      x, y);
861
862   window_private->parent = new_parent;
863
864   if (old_parent_private)
865     old_parent_private->children = g_list_remove (old_parent_private->children, window);
866   parent_private->children = g_list_prepend (parent_private->children, window);
867   
868 }
869
870 void
871 gdk_window_clear (GdkWindow *window)
872 {
873   GdkWindowPrivate *private;
874
875   g_return_if_fail (window != NULL);
876
877   private = (GdkWindowPrivate*) window;
878
879   if (!private->destroyed)
880     XClearWindow (private->xdisplay, private->xwindow);
881 }
882
883 void
884 gdk_window_clear_area (GdkWindow *window,
885                        gint       x,
886                        gint       y,
887                        gint       width,
888                        gint       height)
889 {
890   GdkWindowPrivate *private;
891   
892   g_return_if_fail (window != NULL);
893   
894   private = (GdkWindowPrivate*) window;
895   
896   if (!private->destroyed)
897     XClearArea (private->xdisplay, private->xwindow,
898                 x, y, width, height, False);
899 }
900
901 void
902 gdk_window_clear_area_e (GdkWindow *window,
903                          gint       x,
904                          gint       y,
905                          gint       width,
906                          gint       height)
907 {
908   GdkWindowPrivate *private;
909   
910   g_return_if_fail (window != NULL);
911   
912   private = (GdkWindowPrivate*) window;
913   
914   if (!private->destroyed)
915     XClearArea (private->xdisplay, private->xwindow,
916                 x, y, width, height, True);
917 }
918
919 void
920 gdk_window_copy_area (GdkWindow    *window,
921                       GdkGC        *gc,
922                       gint          x,
923                       gint          y,
924                       GdkWindow    *source_window,
925                       gint          source_x,
926                       gint          source_y,
927                       gint          width,
928                       gint          height)
929 {
930   GdkWindowPrivate *src_private;
931   GdkWindowPrivate *dest_private;
932   GdkGCPrivate *gc_private;
933   
934   g_return_if_fail (window != NULL);
935   g_return_if_fail (gc != NULL);
936   
937   if (source_window == NULL)
938     source_window = window;
939   
940   src_private = (GdkWindowPrivate*) source_window;
941   dest_private = (GdkWindowPrivate*) window;
942   gc_private = (GdkGCPrivate*) gc;
943   
944   if (!src_private->destroyed && !dest_private->destroyed)
945     {
946       XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow,
947                  gc_private->xgc,
948                  source_x, source_y,
949                  width, height,
950                  x, y);
951     }
952 }
953
954 void
955 gdk_window_raise (GdkWindow *window)
956 {
957   GdkWindowPrivate *private;
958   
959   g_return_if_fail (window != NULL);
960   
961   private = (GdkWindowPrivate*) window;
962   
963   if (!private->destroyed)
964     XRaiseWindow (private->xdisplay, private->xwindow);
965 }
966
967 void
968 gdk_window_lower (GdkWindow *window)
969 {
970   GdkWindowPrivate *private;
971   
972   g_return_if_fail (window != NULL);
973   
974   private = (GdkWindowPrivate*) window;
975   
976   if (!private->destroyed)
977     XLowerWindow (private->xdisplay, private->xwindow);
978 }
979
980 void
981 gdk_window_set_user_data (GdkWindow *window,
982                           gpointer   user_data)
983 {
984   g_return_if_fail (window != NULL);
985   
986   window->user_data = user_data;
987 }
988
989 void
990 gdk_window_set_hints (GdkWindow *window,
991                       gint       x,
992                       gint       y,
993                       gint       min_width,
994                       gint       min_height,
995                       gint       max_width,
996                       gint       max_height,
997                       gint       flags)
998 {
999   GdkWindowPrivate *private;
1000   XSizeHints size_hints;
1001   
1002   g_return_if_fail (window != NULL);
1003   
1004   private = (GdkWindowPrivate*) window;
1005   if (private->destroyed)
1006     return;
1007   
1008   size_hints.flags = 0;
1009   
1010   if (flags & GDK_HINT_POS)
1011     {
1012       size_hints.flags |= PPosition;
1013       size_hints.x = x;
1014       size_hints.y = y;
1015     }
1016   
1017   if (flags & GDK_HINT_MIN_SIZE)
1018     {
1019       size_hints.flags |= PMinSize;
1020       size_hints.min_width = min_width;
1021       size_hints.min_height = min_height;
1022     }
1023   
1024   if (flags & GDK_HINT_MAX_SIZE)
1025     {
1026       size_hints.flags |= PMaxSize;
1027       size_hints.max_width = max_width;
1028       size_hints.max_height = max_height;
1029     }
1030   
1031   if (flags)
1032     XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
1033 }
1034
1035 void
1036 gdk_window_set_title (GdkWindow   *window,
1037                       const gchar *title)
1038 {
1039   GdkWindowPrivate *private;
1040   
1041   g_return_if_fail (window != NULL);
1042   
1043   private = (GdkWindowPrivate*) window;
1044   if (!private->destroyed)
1045     XmbSetWMProperties (private->xdisplay, private->xwindow,
1046                         title, title, NULL, 0, NULL, NULL, NULL);
1047 }
1048
1049 void
1050 gdk_window_set_background (GdkWindow *window,
1051                            GdkColor  *color)
1052 {
1053   GdkWindowPrivate *private;
1054   
1055   g_return_if_fail (window != NULL);
1056   
1057   private = (GdkWindowPrivate*) window;
1058   if (!private->destroyed)
1059     XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel);
1060 }
1061
1062 void
1063 gdk_window_set_back_pixmap (GdkWindow *window,
1064                             GdkPixmap *pixmap,
1065                             gint       parent_relative)
1066 {
1067   GdkWindowPrivate *window_private;
1068   GdkPixmapPrivate *pixmap_private;
1069   Pixmap xpixmap;
1070   
1071   g_return_if_fail (window != NULL);
1072   
1073   window_private = (GdkWindowPrivate*) window;
1074   pixmap_private = (GdkPixmapPrivate*) pixmap;
1075   
1076   if (pixmap)
1077     xpixmap = pixmap_private->xwindow;
1078   else
1079     xpixmap = None;
1080   
1081   if (parent_relative)
1082     xpixmap = ParentRelative;
1083   
1084   if (!window_private->destroyed)
1085     XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap);
1086 }
1087
1088 void
1089 gdk_window_set_cursor (GdkWindow *window,
1090                        GdkCursor *cursor)
1091 {
1092   GdkWindowPrivate *window_private;
1093   GdkCursorPrivate *cursor_private;
1094   Cursor xcursor;
1095   
1096   g_return_if_fail (window != NULL);
1097   
1098   window_private = (GdkWindowPrivate*) window;
1099   cursor_private = (GdkCursorPrivate*) cursor;
1100   
1101   if (!cursor)
1102     xcursor = None;
1103   else
1104     xcursor = cursor_private->xcursor;
1105   
1106   if (!window_private->destroyed)
1107     XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor);
1108 }
1109
1110 void
1111 gdk_window_set_colormap (GdkWindow   *window,
1112                          GdkColormap *colormap)
1113 {
1114   GdkWindowPrivate *window_private;
1115   GdkColormapPrivate *colormap_private;
1116   
1117   g_return_if_fail (window != NULL);
1118   g_return_if_fail (colormap != NULL);
1119   
1120   window_private = (GdkWindowPrivate*) window;
1121   colormap_private = (GdkColormapPrivate*) colormap;
1122   
1123   if (!window_private->destroyed)
1124     {
1125       XSetWindowColormap (window_private->xdisplay,
1126                           window_private->xwindow,
1127                           colormap_private->xcolormap);
1128
1129       if (window_private->colormap)
1130         gdk_colormap_unref (window_private->colormap);
1131       window_private->colormap = colormap;
1132       gdk_colormap_ref (window_private->colormap);
1133       
1134       if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
1135         gdk_window_add_colormap_windows (window);
1136     }
1137 }
1138
1139 void
1140 gdk_window_get_user_data (GdkWindow *window,
1141                           gpointer  *data)
1142 {
1143   g_return_if_fail (window != NULL);
1144   
1145   *data = window->user_data;
1146 }
1147
1148 void
1149 gdk_window_get_geometry (GdkWindow *window,
1150                          gint      *x,
1151                          gint      *y,
1152                          gint      *width,
1153                          gint      *height,
1154                          gint      *depth)
1155 {
1156   GdkWindowPrivate *window_private;
1157   Window root;
1158   gint tx;
1159   gint ty;
1160   guint twidth;
1161   guint theight;
1162   guint tborder_width;
1163   guint tdepth;
1164   
1165   if (!window)
1166     window = (GdkWindow*) &gdk_root_parent;
1167   
1168   window_private = (GdkWindowPrivate*) window;
1169   
1170   if (!window_private->destroyed)
1171     {
1172       XGetGeometry (window_private->xdisplay, window_private->xwindow,
1173                     &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
1174       
1175       if (x)
1176         *x = tx;
1177       if (y)
1178         *y = ty;
1179       if (width)
1180         *width = twidth;
1181       if (height)
1182         *height = theight;
1183       if (depth)
1184         *depth = tdepth;
1185     }
1186 }
1187
1188 void
1189 gdk_window_get_position (GdkWindow *window,
1190                          gint      *x,
1191                          gint      *y)
1192 {
1193   GdkWindowPrivate *window_private;
1194   
1195   g_return_if_fail (window != NULL);
1196   
1197   window_private = (GdkWindowPrivate*) window;
1198   
1199   if (x)
1200     *x = window_private->x;
1201   if (y)
1202     *y = window_private->y;
1203 }
1204
1205 void
1206 gdk_window_get_size (GdkWindow *window,
1207                      gint       *width,
1208                      gint       *height)
1209 {
1210   GdkWindowPrivate *window_private;
1211   
1212   g_return_if_fail (window != NULL);
1213   
1214   window_private = (GdkWindowPrivate*) window;
1215   
1216   if (width)
1217     *width = window_private->width;
1218   if (height)
1219     *height = window_private->height;
1220 }
1221
1222 GdkVisual*
1223 gdk_window_get_visual (GdkWindow *window)
1224 {
1225   GdkWindowPrivate *window_private;
1226   XWindowAttributes window_attributes;
1227    
1228   g_return_val_if_fail (window != NULL, NULL);
1229
1230   window_private = (GdkWindowPrivate*) window;
1231   /* Huh? ->parent is never set for a pixmap. We should just return
1232    * null immeditately
1233    */
1234   while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
1235     window_private = (GdkWindowPrivate*) window_private->parent;
1236   
1237   if (window_private && !window_private->destroyed)
1238     {
1239        if (window_private->colormap == NULL)
1240          {
1241             XGetWindowAttributes (window_private->xdisplay,
1242                                   window_private->xwindow,
1243                                   &window_attributes);
1244             return gdk_visual_lookup (window_attributes.visual);
1245          }
1246        else
1247          return ((GdkColormapPrivate *)window_private->colormap)->visual;
1248     }
1249   
1250   return NULL;
1251 }
1252
1253 GdkColormap*
1254 gdk_window_get_colormap (GdkWindow *window)
1255 {
1256   GdkWindowPrivate *window_private;
1257   XWindowAttributes window_attributes;
1258   
1259   g_return_val_if_fail (window != NULL, NULL);
1260   window_private = (GdkWindowPrivate*) window;
1261
1262   g_return_val_if_fail (window_private->window_type != GDK_WINDOW_PIXMAP, NULL);
1263   if (!window_private->destroyed)
1264     {
1265       if (window_private->colormap == NULL)
1266         {
1267           XGetWindowAttributes (window_private->xdisplay,
1268                                 window_private->xwindow,
1269                                 &window_attributes);
1270           return gdk_colormap_lookup (window_attributes.colormap);
1271          }
1272        else
1273          return window_private->colormap;
1274     }
1275   
1276   return NULL;
1277 }
1278
1279 GdkWindowType
1280 gdk_window_get_type (GdkWindow *window)
1281 {
1282   GdkWindowPrivate *window_private;
1283
1284   g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
1285
1286   window_private = (GdkWindowPrivate*) window;
1287   return window_private->window_type;
1288 }
1289
1290 gint
1291 gdk_window_get_origin (GdkWindow *window,
1292                        gint      *x,
1293                        gint      *y)
1294 {
1295   GdkWindowPrivate *private;
1296   gint return_val;
1297   Window child;
1298   gint tx = 0;
1299   gint ty = 0;
1300
1301   g_return_val_if_fail (window != NULL, 0);
1302
1303   private = (GdkWindowPrivate*) window;
1304
1305   if (!private->destroyed)
1306     {
1307       return_val = XTranslateCoordinates (private->xdisplay,
1308                                           private->xwindow,
1309                                           gdk_root_window,
1310                                           0, 0, &tx, &ty,
1311                                           &child);
1312       
1313     }
1314   else
1315     return_val = 0;
1316   
1317   if (x)
1318     *x = tx;
1319   if (y)
1320     *y = ty;
1321   
1322   return return_val;
1323 }
1324
1325 GdkWindow*
1326 gdk_window_get_pointer (GdkWindow       *window,
1327                         gint            *x,
1328                         gint            *y,
1329                         GdkModifierType *mask)
1330 {
1331   GdkWindowPrivate *private;
1332   GdkWindow *return_val;
1333   Window root;
1334   Window child;
1335   int rootx, rooty;
1336   int winx = 0;
1337   int winy = 0;
1338   unsigned int xmask = 0;
1339
1340   if (!window)
1341     window = (GdkWindow*) &gdk_root_parent;
1342
1343   private = (GdkWindowPrivate*) window;
1344
1345   return_val = NULL;
1346   if (!private->destroyed &&
1347       XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
1348                      &rootx, &rooty, &winx, &winy, &xmask))
1349     {
1350       if (child)
1351         return_val = gdk_window_lookup (child);
1352     }
1353   
1354   if (x)
1355     *x = winx;
1356   if (y)
1357     *y = winy;
1358   if (mask)
1359     *mask = xmask;
1360   
1361   return return_val;
1362 }
1363
1364 GdkWindow*
1365 gdk_window_at_pointer (gint *win_x,
1366                        gint *win_y)
1367 {
1368   GdkWindowPrivate *private;
1369   GdkWindow *window;
1370   Window root;
1371   Window xwindow;
1372   Window xwindow_last = 0;
1373   int rootx = -1, rooty = -1;
1374   int winx, winy;
1375   unsigned int xmask;
1376
1377   private = &gdk_root_parent;
1378
1379   xwindow = private->xwindow;
1380
1381   XGrabServer (private->xdisplay);
1382   while (xwindow)
1383     {
1384       xwindow_last = xwindow;
1385       XQueryPointer (private->xdisplay,
1386                      xwindow,
1387                      &root, &xwindow,
1388                      &rootx, &rooty,
1389                      &winx, &winy,
1390                      &xmask);
1391     }
1392   XUngrabServer (private->xdisplay);
1393   
1394   window = gdk_window_lookup (xwindow_last);
1395
1396   if (win_x)
1397     *win_x = window ? winx : -1;
1398   if (win_y)
1399     *win_y = window ? winy : -1;
1400
1401   return window;
1402 }
1403
1404 GdkWindow*
1405 gdk_window_get_parent (GdkWindow *window)
1406 {
1407   g_return_val_if_fail (window != NULL, NULL);
1408
1409   return ((GdkWindowPrivate*) window)->parent;
1410 }
1411
1412 GdkWindow*
1413 gdk_window_get_toplevel (GdkWindow *window)
1414 {
1415   GdkWindowPrivate *private;
1416
1417   g_return_val_if_fail (window != NULL, NULL);
1418
1419   private = (GdkWindowPrivate*) window;
1420
1421   while (private->window_type == GDK_WINDOW_CHILD)
1422     {
1423       window = ((GdkWindowPrivate*) window)->parent;
1424       private = (GdkWindowPrivate*) window;
1425     }
1426
1427   return window;
1428 }
1429
1430 GList*
1431 gdk_window_get_children (GdkWindow *window)
1432 {
1433   GdkWindowPrivate *private;
1434   GdkWindow *child;
1435   GList *children;
1436   Window root;
1437   Window parent;
1438   Window *xchildren;
1439   unsigned int nchildren;
1440   unsigned int i;
1441
1442   g_return_val_if_fail (window != NULL, NULL);
1443
1444   private = (GdkWindowPrivate*) window;
1445   if (private->destroyed)
1446     return NULL;
1447
1448   XQueryTree (private->xdisplay, private->xwindow,
1449               &root, &parent, &xchildren, &nchildren);
1450
1451   children = NULL;
1452
1453   if (nchildren > 0)
1454     {
1455       for (i = 0; i < nchildren; i++)
1456         {
1457           child = gdk_window_lookup (xchildren[i]);
1458           if (child)
1459             children = g_list_prepend (children, child);
1460         }
1461
1462       if (xchildren)
1463         XFree (xchildren);
1464     }
1465
1466   return children;
1467 }
1468
1469 GdkEventMask  
1470 gdk_window_get_events      (GdkWindow       *window)
1471 {
1472   GdkWindowPrivate *private;
1473   XWindowAttributes attrs;
1474   GdkEventMask event_mask;
1475   int i;
1476
1477   g_return_val_if_fail (window != NULL, 0);
1478
1479   private = (GdkWindowPrivate*) window;
1480   if (private->destroyed)
1481     return 0;
1482
1483   XGetWindowAttributes (gdk_display, private->xwindow, 
1484                         &attrs);
1485
1486   event_mask = 0;
1487   for (i = 0; i < nevent_masks; i++)
1488     {
1489       if (attrs.your_event_mask & event_mask_table[i])
1490         event_mask |= 1 << (i + 1);
1491     }
1492
1493   return event_mask;
1494 }
1495
1496 void          
1497 gdk_window_set_events      (GdkWindow       *window,
1498                             GdkEventMask     event_mask)
1499 {
1500   GdkWindowPrivate *private;
1501   long xevent_mask;
1502   int i;
1503
1504   g_return_if_fail (window != NULL);
1505
1506   private = (GdkWindowPrivate*) window;
1507   if (private->destroyed)
1508     return;
1509
1510   xevent_mask = StructureNotifyMask;
1511   for (i = 0; i < nevent_masks; i++)
1512     {
1513       if (event_mask & (1 << (i + 1)))
1514         xevent_mask |= event_mask_table[i];
1515     }
1516   
1517   XSelectInput (gdk_display, private->xwindow, 
1518                 xevent_mask);
1519 }
1520
1521 void
1522 gdk_window_add_colormap_windows (GdkWindow *window)
1523 {
1524   GdkWindow *toplevel;
1525   GdkWindowPrivate *toplevel_private;
1526   GdkWindowPrivate *window_private;
1527   Window *old_windows;
1528   Window *new_windows;
1529   int i, count;
1530
1531   g_return_if_fail (window != NULL);
1532
1533   toplevel = gdk_window_get_toplevel (window);
1534   toplevel_private = (GdkWindowPrivate*) toplevel;
1535   window_private = (GdkWindowPrivate*) window;
1536   if (window_private->destroyed)
1537     return;
1538
1539   old_windows = NULL;
1540   if (!XGetWMColormapWindows (toplevel_private->xdisplay,
1541                               toplevel_private->xwindow,
1542                               &old_windows, &count))
1543     {
1544       count = 0;
1545     }
1546
1547   for (i = 0; i < count; i++)
1548     if (old_windows[i] == window_private->xwindow)
1549       {
1550         XFree (old_windows);
1551         return;
1552       }
1553
1554   new_windows = g_new (Window, count + 1);
1555
1556   for (i = 0; i < count; i++)
1557     new_windows[i] = old_windows[i];
1558   new_windows[count] = window_private->xwindow;
1559
1560   XSetWMColormapWindows (toplevel_private->xdisplay,
1561                          toplevel_private->xwindow,
1562                          new_windows, count + 1);
1563
1564   g_free (new_windows);
1565   if (old_windows)
1566     XFree (old_windows);
1567 }
1568
1569 /*
1570  * This needs the X11 shape extension.
1571  * If not available, shaped windows will look
1572  * ugly, but programs still work.    Stefan Wille
1573  */
1574 void
1575 gdk_window_shape_combine_mask (GdkWindow *window,
1576                                GdkBitmap *mask,
1577                                gint x, gint y)
1578 {
1579   enum { UNKNOWN, NO, YES };
1580
1581   static gint have_shape = UNKNOWN;
1582
1583   GdkWindowPrivate *window_private;
1584   Pixmap pixmap;
1585
1586   g_return_if_fail (window != NULL);
1587
1588 #ifdef HAVE_SHAPE_EXT
1589   if (have_shape == UNKNOWN)
1590     {
1591       int ignore;
1592       if (XQueryExtension(gdk_display, "SHAPE", &ignore, &ignore, &ignore))
1593         have_shape = YES;
1594       else
1595         have_shape = NO;
1596     }
1597   
1598   if (have_shape == YES)
1599     {
1600       window_private = (GdkWindowPrivate*) window;
1601       if (window_private->destroyed)
1602         return;
1603       
1604       if (mask)
1605         {
1606           GdkWindowPrivate *pixmap_private;
1607           
1608           pixmap_private = (GdkWindowPrivate*) mask;
1609           pixmap = (Pixmap) pixmap_private->xwindow;
1610         }
1611       else
1612         {
1613           x = 0;
1614           y = 0;
1615           pixmap = None;
1616         }
1617       
1618       XShapeCombineMask  (window_private->xdisplay,
1619                           window_private->xwindow,
1620                           ShapeBounding,
1621                           x, y,
1622                           pixmap,
1623                           ShapeSet);
1624     }
1625 #endif /* HAVE_SHAPE_EXT */
1626 }
1627
1628 void
1629 gdk_dnd_drag_addwindow (GdkWindow *window)
1630 {
1631   GdkWindowPrivate *window_private;
1632   
1633   g_return_if_fail (window != NULL);
1634   
1635   window_private = (GdkWindowPrivate *) window;
1636   if (window_private->destroyed)
1637     return;
1638   
1639   if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
1640     {
1641       gdk_dnd.drag_numwindows++;
1642       gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
1643                                              gdk_dnd.drag_numwindows
1644                                              * sizeof(GdkWindow *));
1645       gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
1646       window_private->dnd_drag_accepted = 0;
1647     } 
1648   else
1649     g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
1650 }
1651
1652 void
1653 gdk_window_dnd_drag_set (GdkWindow   *window,
1654                          guint8       drag_enable,
1655                          gchar      **typelist,
1656                          guint        numtypes)
1657 {
1658   GdkWindowPrivate *window_private;
1659   int i, wasset = 0;
1660   
1661   g_return_if_fail (window != NULL);
1662   window_private = (GdkWindowPrivate *) window;
1663   if (window_private->destroyed)
1664     return;
1665   
1666   window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
1667   
1668   if (drag_enable)
1669     {
1670       g_return_if_fail(typelist != NULL);
1671       
1672       if (window_private->dnd_drag_data_numtypesavail > 3)
1673         wasset = 1;
1674       window_private->dnd_drag_data_numtypesavail = numtypes;
1675       
1676       window_private->dnd_drag_data_typesavail =
1677         g_realloc (window_private->dnd_drag_data_typesavail,
1678                    (numtypes + 1) * sizeof (GdkAtom));
1679       
1680       for (i = 0; i < numtypes; i++)
1681         {
1682           /* Allow blanket use of ALL to get anything... */
1683           if (strcmp (typelist[i], "ALL"))
1684             window_private->dnd_drag_data_typesavail[i] =
1685               gdk_atom_intern (typelist[i], FALSE);
1686           else
1687             window_private->dnd_drag_data_typesavail[i] = None;
1688         }
1689       
1690       /* 
1691        * set our extended type list if we need to 
1692        */
1693       if (numtypes > 3)
1694         gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
1695                             XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
1696                             (guchar *)(window_private->dnd_drag_data_typesavail
1697                              + (sizeof(GdkAtom) * 3)),
1698                             (numtypes - 3) * sizeof(GdkAtom));
1699       else if (wasset)
1700         gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
1701     }
1702   else
1703     {
1704       g_free (window_private->dnd_drag_data_typesavail);
1705       window_private->dnd_drag_data_typesavail = NULL;
1706       window_private->dnd_drag_data_numtypesavail = 0;
1707     }
1708 }
1709
1710 void
1711 gdk_window_dnd_drop_set (GdkWindow   *window,
1712                          guint8       drop_enable,
1713                          gchar      **typelist,
1714                          guint        numtypes,
1715                          guint8       destructive_op)
1716 {
1717   GdkWindowPrivate *window_private;
1718   int i;
1719   
1720   g_return_if_fail (window != NULL);
1721   window_private = (GdkWindowPrivate *) window;
1722   if (window_private->destroyed)
1723     return;
1724   
1725   window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
1726   if (drop_enable)
1727     {
1728       g_return_if_fail(typelist != NULL);
1729       
1730       window_private->dnd_drop_data_numtypesavail = numtypes;
1731       
1732       window_private->dnd_drop_data_typesavail =
1733         g_realloc (window_private->dnd_drop_data_typesavail,
1734                    (numtypes + 1) * sizeof (GdkAtom));
1735       
1736       for (i = 0; i < numtypes; i++)
1737         window_private->dnd_drop_data_typesavail[i] =
1738           gdk_atom_intern (typelist[i], FALSE);
1739       
1740       window_private->dnd_drop_destructive_op = destructive_op;
1741     }
1742 }
1743
1744 /* 
1745  * This is used to reply to a GDK_DRAG_REQUEST event
1746  * (which may be generated by XdeRequest or a confirmed drop... 
1747  */
1748 void
1749 gdk_window_dnd_data_set (GdkWindow       *window,
1750                          GdkEvent        *event,
1751                          gpointer         data,
1752                          gulong           data_numbytes)
1753 {
1754   GdkWindowPrivate *window_private;
1755   XEvent sev;
1756   GdkEventDropDataAvailable tmp_ev;
1757   gchar *tmp;
1758   
1759   g_return_if_fail (window != NULL);
1760   g_return_if_fail (event != NULL);
1761   g_return_if_fail (data != NULL);
1762   g_return_if_fail (data_numbytes > 0);
1763   g_return_if_fail (event->type == GDK_DRAG_REQUEST);
1764
1765   window_private = (GdkWindowPrivate *) window;
1766   g_return_if_fail (window_private->dnd_drag_accepted != 0);    
1767   if (window_private->destroyed)
1768     return;
1769   
1770   /* We set the property on our window... */
1771   gdk_property_change (window, window_private->dnd_drag_data_type,
1772                        XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
1773                        data_numbytes);
1774   tmp = gdk_atom_name(window_private->dnd_drag_data_type);
1775 #ifdef DEBUG_DND
1776   g_message("DnD type %s on window %ld\n", tmp, window_private->xwindow);
1777 #endif
1778   g_free(tmp);
1779   
1780   /* 
1781    * Then we send the event to tell the receiving window that the
1782    * drop has happened 
1783    */
1784   tmp_ev.u.allflags = 0;
1785   tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
1786   tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
1787   
1788   sev.xclient.type = ClientMessage;
1789   sev.xclient.format = 32;
1790   sev.xclient.window = event->dragrequest.requestor;
1791   sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
1792   sev.xclient.data.l[0] = window_private->xwindow;
1793   sev.xclient.data.l[1] = tmp_ev.u.allflags;
1794   sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
1795
1796   if (event->dragrequest.isdrop)
1797     sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
1798       (event->dragrequest.drop_coords.y << 16);
1799   else
1800     sev.xclient.data.l[3] = 0;
1801
1802   sev.xclient.data.l[4] = event->dragrequest.timestamp;
1803
1804   if (!gdk_send_xevent (event->dragrequest.requestor, False,
1805                        StructureNotifyMask, &sev))
1806     GDK_NOTE (DND, g_message("Sending XdeDataAvailable to %#x failed\n",
1807                              event->dragrequest.requestor));
1808 }
1809
1810 void          
1811 gdk_window_add_filter     (GdkWindow     *window,
1812                            GdkFilterFunc  function,
1813                            gpointer       data)
1814 {
1815   GdkWindowPrivate *private;
1816   GList *tmp_list;
1817   GdkEventFilter *filter;
1818
1819   private = (GdkWindowPrivate*) window;
1820   if (private && private->destroyed)
1821     return;
1822
1823   if(private)
1824     tmp_list = private->filters;
1825   else
1826     tmp_list = gdk_default_filters;
1827
1828   while (tmp_list)
1829     {
1830       filter = (GdkEventFilter *)tmp_list->data;
1831       if ((filter->function == function) && (filter->data == data))
1832         return;
1833       tmp_list = tmp_list->next;
1834     }
1835
1836   filter = g_new (GdkEventFilter, 1);
1837   filter->function = function;
1838   filter->data = data;
1839
1840   if(private)
1841     private->filters = g_list_append (private->filters, filter);
1842   else
1843     gdk_default_filters = g_list_append (gdk_default_filters, filter);
1844 }
1845
1846 void
1847 gdk_window_remove_filter  (GdkWindow     *window,
1848                            GdkFilterFunc  function,
1849                            gpointer       data)
1850 {
1851   GdkWindowPrivate *private;
1852   GList *tmp_list;
1853   GdkEventFilter *filter;
1854
1855   private = (GdkWindowPrivate*) window;
1856
1857   if(private)
1858     tmp_list = private->filters;
1859   else
1860     tmp_list = gdk_default_filters;
1861
1862   while (tmp_list)
1863     {
1864       filter = (GdkEventFilter *)tmp_list->data;
1865       tmp_list = tmp_list->next;
1866
1867       if ((filter->function == function) && (filter->data == data))
1868         {
1869           if(private)
1870             private->filters = g_list_remove_link (private->filters, tmp_list);
1871           else
1872             gdk_default_filters = g_list_remove_link (gdk_default_filters, tmp_list);
1873           g_list_free_1 (tmp_list);
1874           g_free (filter);
1875           
1876           return;
1877         }
1878     }
1879 }
1880
1881 void
1882 gdk_window_set_override_redirect(GdkWindow *window,
1883                                  gboolean override_redirect)
1884 {
1885   GdkWindowPrivate *private;
1886   XSetWindowAttributes attr;
1887
1888   g_return_if_fail (window != NULL);
1889   private = (GdkWindowPrivate*) window;
1890   if (private->destroyed)
1891     return;
1892
1893   attr.override_redirect = (override_redirect == FALSE)?False:True;
1894   XChangeWindowAttributes(gdk_display,
1895                           ((GdkWindowPrivate *)window)->xwindow,
1896                           CWOverrideRedirect,
1897                           &attr);
1898 }
1899
1900 void          
1901 gdk_window_set_icon        (GdkWindow *window, 
1902                             GdkWindow *icon_window,
1903                             GdkPixmap *pixmap,
1904                             GdkBitmap *mask)
1905 {
1906   XWMHints wm_hints;
1907   GdkWindowPrivate *window_private;
1908   GdkWindowPrivate *private;
1909
1910   g_return_if_fail (window != NULL);
1911   window_private = (GdkWindowPrivate*) window;
1912   if (window_private->destroyed)
1913     return;
1914
1915   wm_hints.flags = 0;
1916   
1917   if (icon_window != NULL)
1918     {
1919       private = (GdkWindowPrivate *)icon_window;
1920       wm_hints.flags |= IconWindowHint;
1921       wm_hints.icon_window = private->xwindow;
1922     }
1923
1924   if (pixmap != NULL)
1925     {
1926       private = (GdkWindowPrivate *)pixmap;
1927       wm_hints.flags |= IconPixmapHint;
1928       wm_hints.icon_pixmap = private->xwindow;
1929     }
1930
1931   if (mask != NULL)
1932     {
1933       private = (GdkWindowPrivate *)mask;
1934       wm_hints.flags |= IconMaskHint;
1935       wm_hints.icon_mask = private->xwindow;
1936     }
1937
1938   XSetWMHints (window_private->xdisplay, window_private->xwindow, &wm_hints);
1939 }
1940
1941 void          
1942 gdk_window_set_icon_name   (GdkWindow *window, 
1943                             gchar *    name)
1944 {
1945   GdkWindowPrivate *window_private;
1946   XTextProperty property;
1947   gint res;
1948
1949   g_return_if_fail (window != NULL);
1950   window_private = (GdkWindowPrivate*) window;
1951   if (window_private->destroyed)
1952     return;
1953   res = XmbTextListToTextProperty (window_private->xdisplay,
1954                                    &name, 1, XStdICCTextStyle,
1955                                    &property);
1956   if (res < 0)
1957     {
1958       g_warning("Error converting icon name to text property: %d\n", res);
1959       return;
1960     }
1961
1962   XSetWMIconName (window_private->xdisplay, window_private->xwindow,
1963                   &property);
1964
1965   if (property.value)
1966     XFree (property.value);
1967 }
1968
1969 void          
1970 gdk_window_set_group   (GdkWindow *window, 
1971                         GdkWindow *leader)
1972 {
1973   XWMHints wm_hints;
1974   GdkWindowPrivate *window_private;
1975   GdkWindowPrivate *private;
1976
1977   g_return_if_fail (window != NULL);
1978   g_return_if_fail (leader != NULL);
1979   window_private = (GdkWindowPrivate*) window;
1980   if (window_private->destroyed)
1981     return;
1982
1983   private = (GdkWindowPrivate *)leader;
1984   wm_hints.flags = WindowGroupHint;
1985   wm_hints.window_group = private->xwindow;
1986
1987   XSetWMHints (window_private->xdisplay, window_private->xwindow, &wm_hints);
1988 }
1989
1990 static void
1991 gdk_window_set_mwm_hints (GdkWindow *window,
1992                           MotifWmHints *new_hints)
1993 {
1994   static Atom hints_atom = None;
1995   MotifWmHints *hints;
1996   Atom type;
1997   gint format;
1998   gulong nitems;
1999   gulong bytes_after;
2000
2001   GdkWindowPrivate *window_private;
2002
2003   g_return_if_fail (window != NULL);
2004   window_private = (GdkWindowPrivate*) window;
2005   if (window_private->destroyed)
2006     return;
2007
2008   if (!hints_atom)
2009     hints_atom = XInternAtom (window_private->xdisplay, 
2010                               _XA_MOTIF_WM_HINTS, FALSE);
2011   
2012   XGetWindowProperty (window_private->xdisplay, window_private->xwindow,
2013                       hints_atom, 0, sizeof(MotifWmHints)/4,
2014                       False, AnyPropertyType, &type, &format, &nitems,
2015                       &bytes_after, (guchar **)&hints);
2016
2017   if (type == None)
2018     hints = new_hints;
2019   else
2020     {
2021       if (new_hints->flags & MWM_HINTS_FUNCTIONS)
2022         {
2023           hints->flags |= MWM_HINTS_FUNCTIONS;
2024           hints->functions = new_hints->functions;
2025         }
2026       if (new_hints->flags & MWM_HINTS_DECORATIONS)
2027         {
2028           hints->flags |= MWM_HINTS_DECORATIONS;
2029           hints->decorations = new_hints->decorations;
2030         }
2031     }
2032
2033   XChangeProperty (window_private->xdisplay, window_private->xwindow,
2034                    hints_atom, hints_atom, 32, PropModeReplace,
2035                    (guchar *)hints, sizeof(MotifWmHints)/4);
2036
2037   if (hints != new_hints)
2038     XFree (hints);
2039 }
2040
2041 void
2042 gdk_window_set_decorations (GdkWindow      *window,
2043                             GdkWMDecoration decorations)
2044 {
2045   MotifWmHints hints;
2046
2047   hints.flags = MWM_HINTS_DECORATIONS;
2048   hints.decorations = decorations;
2049
2050   gdk_window_set_mwm_hints (window, &hints);
2051 }
2052
2053 void
2054 gdk_window_set_functions (GdkWindow    *window,
2055                           GdkWMFunction functions)
2056 {
2057   MotifWmHints hints;
2058
2059   hints.flags = MWM_HINTS_FUNCTIONS;
2060   hints.functions = functions;
2061
2062   gdk_window_set_mwm_hints (window, &hints);
2063 }
2064
2065 GList *
2066 gdk_window_get_toplevels (void)
2067 {
2068   GList *new_list = NULL;
2069   GList *tmp_list;
2070
2071   tmp_list = gdk_root_parent.children;
2072   while (tmp_list)
2073     {
2074       new_list = g_list_prepend (new_list, tmp_list->data);
2075       tmp_list = tmp_list->next;
2076     }
2077
2078   return new_list;
2079 }
2080
2081 void          
2082 gdk_drawable_set_data (GdkDrawable   *drawable,
2083                        const gchar   *key,
2084                        gpointer       data,
2085                        GDestroyNotify destroy_func)
2086 {
2087   g_dataset_set_data_full (drawable, key, data, destroy_func);
2088 }