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