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