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