]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkwindow-x11.c
do not avoid to queue for a resize if the container is not visible, we
[~andy/gtk] / gdk / x11 / gdkwindow-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <X11/Xlib.h>
21 #include <X11/Xutil.h>
22 #include <X11/Xatom.h>
23 #include <netinet/in.h>
24 #include "gdk.h"
25 #include "../config.h"
26 #include "gdkinput.h"
27 #include "gdkprivate.h"
28 #include "MwmUtil.h"
29 #include <stdlib.h>
30 #include <stdio.h>
31
32 #ifdef HAVE_SHAPE_EXT
33 #include <X11/extensions/shape.h>
34 #endif
35
36 int nevent_masks = 20;
37 int event_mask_table[20] =
38 {
39   ExposureMask,
40   PointerMotionMask,
41   PointerMotionHintMask,
42   ButtonMotionMask,
43   Button1MotionMask,
44   Button2MotionMask,
45   Button3MotionMask,
46   ButtonPressMask | OwnerGrabButtonMask,
47   ButtonReleaseMask | OwnerGrabButtonMask,
48   KeyPressMask,
49   KeyReleaseMask,
50   EnterWindowMask,
51   LeaveWindowMask,
52   FocusChangeMask,
53   StructureNotifyMask,
54   PropertyChangeMask,
55   VisibilityChangeMask,
56   0,                            /* PROXIMITY_IN */
57   0,                            /* PROXIMTY_OUT */
58   SubstructureNotifyMask
59 };
60
61
62 /* internal function created for and used by gdk_window_xid_at_coords */
63 Window
64 gdk_window_xid_at (Window   base,
65                    gint     bx,
66                    gint     by,
67                    gint     x,
68                    gint     y, 
69                    GList   *excludes,
70                    gboolean excl_child)
71 {
72    GdkWindow *window;
73    GdkWindowPrivate *private;
74    Display *disp;
75    Window *list = NULL;
76    Window child = 0, parent_win = 0, root_win = 0;
77    int i;
78    unsigned int ww, wh, wb, wd, num;
79    int wx, wy;
80    
81    window = (GdkWindow*) &gdk_root_parent;
82    private = (GdkWindowPrivate*) window;
83    disp = private->xdisplay;
84    if (!XGetGeometry (disp, base, &root_win, &wx, &wy, &ww, &wh, &wb, &wd))
85      return 0;
86    wx += bx;
87    wy += by;
88
89    if (!((x >= wx) &&
90          (y >= wy) &&
91          (x < (int) (wx + ww)) &&
92          (y < (int) (wy + wh))))
93      return 0;
94
95    if (!XQueryTree (disp, base, &root_win, &parent_win, &list, &num))
96      return base;
97
98    if (list)
99      {
100         for (i = num - 1; ; i--)
101           {
102              if ((!excl_child) || (!g_list_find (excludes, (gpointer *) list[i])))
103                {
104                  if ((child = gdk_window_xid_at (list[i], wx, wy, x, y, excludes, excl_child)) != 0)
105                    {
106                      XFree (list);
107                      return child;
108                    }
109                }
110              if (!i)
111                break;
112           }
113         XFree (list);
114      }
115    return base;
116 }
117
118 /* 
119  * The following fucntion by The Rasterman <raster@redhat.com>
120  * This function returns the X Window ID in which the x y location is in 
121  * (x and y being relative to the root window), excluding any windows listed
122  * in the GList excludes (this is a list of X Window ID's - gpointer being
123  * the Window ID).
124  * 
125  * This is primarily designed for internal gdk use - for DND for example
126  * when using a shaped icon window as the drag object - you exclude the
127  * X Window ID of the "icon" (perhaps more if excludes may be needed) and
128  * You can get back an X Window ID as to what X Window ID is infact under
129  * those X,Y co-ordinates.
130  */
131 Window
132 gdk_window_xid_at_coords (gint     x,
133                           gint     y,
134                           GList   *excludes,
135                           gboolean excl_child)
136 {
137    GdkWindow *window;
138    GdkWindowPrivate *private;
139    Display *disp;
140    Window *list = NULL;
141    Window root, child = 0, parent_win = 0, root_win = 0;
142    unsigned int num;
143    int i;
144    
145    window = (GdkWindow*) &gdk_root_parent;
146    private = (GdkWindowPrivate*) window;
147    disp = private->xdisplay;
148    root = private->xwindow;
149    num = g_list_length (excludes);
150
151    XGrabServer (disp);
152    if (!XQueryTree (disp, root, &root_win, &parent_win, &list, &num))
153      {
154        XUngrabServer(disp);
155        return root;
156      }
157    if (list)
158      {
159        i = num - 1;
160        do
161          {
162            XWindowAttributes xwa;
163
164            XGetWindowAttributes (disp, list [i], &xwa);
165
166            if (xwa.map_state != IsViewable)
167              continue;
168
169            if (excl_child && g_list_find (excludes, (gpointer *) list[i]))
170              continue;
171            
172            if ((child = gdk_window_xid_at (list[i], 0, 0, x, y, excludes, excl_child)) == 0)
173              continue;
174
175            if (excludes)
176              {
177                if (!g_list_find (excludes, (gpointer *) child))
178                  {
179                    XFree (list);
180                    XUngrabServer (disp);
181                    return child;
182                  }
183              }
184            else
185              {
186                XFree (list);
187                XUngrabServer (disp);
188                return child;
189              }
190          } while (--i > 0);
191         XFree (list);
192      }
193    XUngrabServer (disp);
194    return root;
195 }
196
197 void
198 gdk_window_init (void)
199 {
200   XWindowAttributes xattributes;
201   unsigned int width;
202   unsigned int height;
203   unsigned int border_width;
204   unsigned int depth;
205   int x, y;
206
207   XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window,
208                 &x, &y, &width, &height, &border_width, &depth);
209   XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes);
210
211   gdk_root_parent.xdisplay = gdk_display;
212   gdk_root_parent.xwindow = gdk_root_window;
213   gdk_root_parent.window_type = GDK_WINDOW_ROOT;
214   gdk_root_parent.window.user_data = NULL;
215   gdk_root_parent.width = width;
216   gdk_root_parent.height = height;
217   gdk_root_parent.children = NULL;
218   gdk_root_parent.colormap = NULL;
219 }
220
221 GdkWindow*
222 gdk_window_new (GdkWindow     *parent,
223                 GdkWindowAttr *attributes,
224                 gint           attributes_mask)
225 {
226   GdkWindow *window;
227   GdkWindowPrivate *private;
228   GdkWindowPrivate *parent_private;
229   GdkVisual *visual;
230   Display *parent_display;
231   Window xparent;
232   Visual *xvisual;
233   XSetWindowAttributes xattributes;
234   long xattributes_mask;
235   XSizeHints size_hints;
236   XWMHints wm_hints;
237   XClassHint *class_hint;
238   int x, y, depth;
239   unsigned int class;
240   char *title;
241   int i;
242
243   g_return_val_if_fail (attributes != NULL, NULL);
244
245   if (!parent)
246     parent = (GdkWindow*) &gdk_root_parent;
247
248   parent_private = (GdkWindowPrivate*) parent;
249   if (parent_private->destroyed)
250     return NULL;
251
252   xparent = parent_private->xwindow;
253   parent_display = parent_private->xdisplay;
254
255   private = g_new (GdkWindowPrivate, 1);
256   window = (GdkWindow*) private;
257
258   private->parent = parent;
259
260   if (parent_private)
261     parent_private->children = g_list_prepend (parent_private->children, window);
262
263   private->xdisplay = parent_display;
264   private->destroyed = FALSE;
265   private->resize_count = 0;
266   private->ref_count = 1;
267   xattributes_mask = 0;
268
269   if (attributes_mask & GDK_WA_X)
270     x = attributes->x;
271   else
272     x = 0;
273
274   if (attributes_mask & GDK_WA_Y)
275     y = attributes->y;
276   else
277     y = 0;
278
279   private->x = x;
280   private->y = y;
281   private->width = (attributes->width > 1) ? (attributes->width) : (1);
282   private->height = (attributes->height > 1) ? (attributes->height) : (1);
283   private->window_type = attributes->window_type;
284   private->extension_events = FALSE;
285   private->dnd_drag_data_type = None;
286   private->dnd_drag_data_typesavail =
287     private->dnd_drop_data_typesavail = NULL;
288   private->dnd_drop_enabled = private->dnd_drag_enabled =
289     private->dnd_drag_accepted = private->dnd_drag_datashow =
290     private->dnd_drop_data_numtypesavail =
291     private->dnd_drag_data_numtypesavail = 0;
292   private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
293
294   private->filters = NULL;
295   private->children = NULL;
296
297   window->user_data = NULL;
298
299   if (attributes_mask & GDK_WA_VISUAL)
300     visual = attributes->visual;
301   else
302     visual = gdk_visual_get_system ();
303   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
304
305   xattributes.event_mask = StructureNotifyMask;
306   for (i = 0; i < nevent_masks; i++)
307     {
308       if (attributes->event_mask & (1 << (i + 1)))
309         xattributes.event_mask |= event_mask_table[i];
310     }
311
312   if (xattributes.event_mask)
313     xattributes_mask |= CWEventMask;
314
315   if(attributes_mask & GDK_WA_NOREDIR) {
316         xattributes.override_redirect =
317                 (attributes->override_redirect == FALSE)?False:True;
318         xattributes_mask |= CWOverrideRedirect;
319   } else
320     xattributes.override_redirect = False;
321
322   if (attributes->wclass == GDK_INPUT_OUTPUT)
323     {
324       class = InputOutput;
325       depth = visual->depth;
326
327       if (attributes_mask & GDK_WA_COLORMAP)
328         private->colormap = attributes->colormap;
329       else
330         private->colormap = gdk_colormap_get_system ();
331
332       xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen);
333       xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
334       xattributes_mask |= CWBorderPixel | CWBackPixel;
335
336       switch (private->window_type)
337         {
338         case GDK_WINDOW_TOPLEVEL:
339           xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
340           xattributes_mask |= CWColormap;
341
342           xparent = gdk_root_window;
343           break;
344
345         case GDK_WINDOW_CHILD:
346           xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
347           xattributes_mask |= CWColormap;
348           break;
349
350         case GDK_WINDOW_DIALOG:
351           xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
352           xattributes_mask |= CWColormap;
353
354           xparent = gdk_root_window;
355           break;
356
357         case GDK_WINDOW_TEMP:
358           xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
359           xattributes_mask |= CWColormap;
360
361           xparent = gdk_root_window;
362
363           xattributes.save_under = True;
364           xattributes.override_redirect = True;
365           xattributes.cursor = None;
366           xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
367           break;
368         case GDK_WINDOW_ROOT:
369           g_error ("cannot make windows of type GDK_WINDOW_ROOT");
370           break;
371         case GDK_WINDOW_PIXMAP:
372           g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
373           break;
374         }
375     }
376   else
377     {
378       depth = 0;
379       class = InputOnly;
380       private->colormap = NULL;
381     }
382
383   private->xwindow = XCreateWindow (private->xdisplay, xparent,
384                                     x, y, private->width, private->height,
385                                     0, depth, class, xvisual,
386                                     xattributes_mask, &xattributes);
387   gdk_window_ref (window);
388   gdk_xid_table_insert (&private->xwindow, window);
389
390   if (private->colormap)
391     gdk_colormap_ref (private->colormap);
392
393   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
394                                   (attributes->cursor) :
395                                   NULL));
396
397   switch (private->window_type)
398     {
399     case GDK_WINDOW_DIALOG:
400       XSetTransientForHint (private->xdisplay, private->xwindow, xparent);
401     case GDK_WINDOW_TOPLEVEL:
402     case GDK_WINDOW_TEMP:
403       XSetWMProtocols (private->xdisplay, private->xwindow, gdk_wm_window_protocols, 2);
404       break;
405     case GDK_WINDOW_CHILD:
406       if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
407           (private->colormap != gdk_colormap_get_system ()) &&
408           (private->colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
409         {
410           GDK_NOTE (MISC, g_print ("adding colormap window\n"));
411           gdk_window_add_colormap_windows (window);
412         }
413
414       return window;
415     default:
416
417       return window;
418     }
419
420   size_hints.flags = PSize;
421   size_hints.width = private->width;
422   size_hints.height = private->height;
423
424   wm_hints.flags = InputHint | StateHint | WindowGroupHint;
425   wm_hints.window_group = gdk_leader_window;
426   wm_hints.input = True;
427   wm_hints.initial_state = NormalState;
428
429   /* FIXME: Is there any point in doing this? Do any WM's pay
430    * attention to PSize, and even if they do, is this the
431    * correct value???
432    */
433   XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
434
435   XSetWMHints (private->xdisplay, private->xwindow, &wm_hints);
436
437   if (attributes_mask & GDK_WA_TITLE)
438     title = attributes->title;
439   else
440     title = gdk_progname;
441
442   XmbSetWMProperties (private->xdisplay, private->xwindow,
443                       title, title,
444                       NULL, 0,
445                       NULL, NULL, NULL);
446
447   if (attributes_mask & GDK_WA_WMCLASS)
448     {
449       class_hint = XAllocClassHint ();
450       class_hint->res_name = attributes->wmclass_name;
451       class_hint->res_class = attributes->wmclass_class;
452       XSetClassHint (private->xdisplay, private->xwindow, class_hint);
453       XFree (class_hint);
454     }
455
456
457   return window;
458 }
459
460 GdkWindow *
461 gdk_window_foreign_new (guint32 anid)
462 {
463   GdkWindow *window;
464   GdkWindowPrivate *private;
465   GdkWindowPrivate *parent_private;
466   XWindowAttributes attrs;
467   Window root, parent;
468   Window *children;
469   guint nchildren;
470
471   private = g_new (GdkWindowPrivate, 1);
472   window = (GdkWindow*) private;
473
474   XGetWindowAttributes (gdk_display, anid, &attrs);
475
476   /* FIXME: This is pretty expensive. Maybe the caller should supply
477    *        the parent */
478   XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren);
479   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 = 0;
1289   gint ty = 0;
1290
1291   g_return_val_if_fail (window != NULL, 0);
1292
1293   private = (GdkWindowPrivate*) window;
1294
1295   if (!private->destroyed)
1296     {
1297       return_val = XTranslateCoordinates (private->xdisplay,
1298                                           private->xwindow,
1299                                           gdk_root_window,
1300                                           0, 0, &tx, &ty,
1301                                           &child);
1302       
1303     }
1304   else
1305     return_val = 0;
1306   
1307   if (x)
1308     *x = tx;
1309   if (y)
1310     *y = ty;
1311   
1312   return return_val;
1313 }
1314
1315 GdkWindow*
1316 gdk_window_get_pointer (GdkWindow       *window,
1317                         gint            *x,
1318                         gint            *y,
1319                         GdkModifierType *mask)
1320 {
1321   GdkWindowPrivate *private;
1322   GdkWindow *return_val;
1323   Window root;
1324   Window child;
1325   int rootx, rooty;
1326   int winx = 0;
1327   int winy = 0;
1328   unsigned int xmask = 0;
1329
1330   if (!window)
1331     window = (GdkWindow*) &gdk_root_parent;
1332
1333   private = (GdkWindowPrivate*) window;
1334
1335   return_val = NULL;
1336   if (!private->destroyed &&
1337       XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
1338                      &rootx, &rooty, &winx, &winy, &xmask))
1339     {
1340       if (child)
1341         return_val = gdk_window_lookup (child);
1342     }
1343   
1344   if (x)
1345     *x = winx;
1346   if (y)
1347     *y = winy;
1348   if (mask)
1349     *mask = xmask;
1350   
1351   return return_val;
1352 }
1353
1354 GdkWindow*
1355 gdk_window_at_pointer (gint *win_x,
1356                        gint *win_y)
1357 {
1358   GdkWindowPrivate *private;
1359   GdkWindow *window;
1360   Window root;
1361   Window xwindow;
1362   Window xwindow_last = 0;
1363   int rootx = -1, rooty = -1;
1364   int winx, winy;
1365   unsigned int xmask;
1366
1367   private = &gdk_root_parent;
1368
1369   xwindow = private->xwindow;
1370
1371   XGrabServer (private->xdisplay);
1372   while (xwindow)
1373     {
1374       xwindow_last = xwindow;
1375       XQueryPointer (private->xdisplay,
1376                      xwindow,
1377                      &root, &xwindow,
1378                      &rootx, &rooty,
1379                      &winx, &winy,
1380                      &xmask);
1381     }
1382   XUngrabServer (private->xdisplay);
1383   
1384   window = gdk_window_lookup (xwindow_last);
1385
1386   if (win_x)
1387     *win_x = window ? winx : -1;
1388   if (win_y)
1389     *win_y = window ? winy : -1;
1390
1391   return window;
1392 }
1393
1394 GdkWindow*
1395 gdk_window_get_parent (GdkWindow *window)
1396 {
1397   g_return_val_if_fail (window != NULL, NULL);
1398
1399   return ((GdkWindowPrivate*) window)->parent;
1400 }
1401
1402 GdkWindow*
1403 gdk_window_get_toplevel (GdkWindow *window)
1404 {
1405   GdkWindowPrivate *private;
1406
1407   g_return_val_if_fail (window != NULL, NULL);
1408
1409   private = (GdkWindowPrivate*) window;
1410
1411   while (private->window_type == GDK_WINDOW_CHILD)
1412     {
1413       window = ((GdkWindowPrivate*) window)->parent;
1414       private = (GdkWindowPrivate*) window;
1415     }
1416
1417   return window;
1418 }
1419
1420 GList*
1421 gdk_window_get_children (GdkWindow *window)
1422 {
1423   GdkWindowPrivate *private;
1424   GdkWindow *child;
1425   GList *children;
1426   Window root;
1427   Window parent;
1428   Window *xchildren;
1429   unsigned int nchildren;
1430   unsigned int i;
1431
1432   g_return_val_if_fail (window != NULL, NULL);
1433
1434   private = (GdkWindowPrivate*) window;
1435   if (private->destroyed)
1436     return NULL;
1437
1438   XQueryTree (private->xdisplay, private->xwindow,
1439               &root, &parent, &xchildren, &nchildren);
1440
1441   children = NULL;
1442
1443   if (nchildren > 0)
1444     {
1445       for (i = 0; i < nchildren; i++)
1446         {
1447           child = gdk_window_lookup (xchildren[i]);
1448           if (child)
1449             children = g_list_prepend (children, child);
1450         }
1451
1452       XFree (xchildren);
1453     }
1454
1455   return children;
1456 }
1457
1458 GdkEventMask  
1459 gdk_window_get_events      (GdkWindow       *window)
1460 {
1461   GdkWindowPrivate *private;
1462   XWindowAttributes attrs;
1463   GdkEventMask event_mask;
1464   int i;
1465
1466   g_return_val_if_fail (window != NULL, 0);
1467
1468   private = (GdkWindowPrivate*) window;
1469   if (private->destroyed)
1470     return 0;
1471
1472   XGetWindowAttributes (gdk_display, private->xwindow, 
1473                         &attrs);
1474
1475   event_mask = 0;
1476   for (i = 0; i < nevent_masks; i++)
1477     {
1478       if (attrs.your_event_mask & event_mask_table[i])
1479         event_mask |= 1 << (i + 1);
1480     }
1481
1482   return event_mask;
1483 }
1484
1485 void          
1486 gdk_window_set_events      (GdkWindow       *window,
1487                             GdkEventMask     event_mask)
1488 {
1489   GdkWindowPrivate *private;
1490   long xevent_mask;
1491   int i;
1492
1493   g_return_if_fail (window != NULL);
1494
1495   private = (GdkWindowPrivate*) window;
1496   if (private->destroyed)
1497     return;
1498
1499   xevent_mask = StructureNotifyMask;
1500   for (i = 0; i < nevent_masks; i++)
1501     {
1502       if (event_mask & (1 << (i + 1)))
1503         xevent_mask |= event_mask_table[i];
1504     }
1505   
1506   XSelectInput (gdk_display, private->xwindow, 
1507                 xevent_mask);
1508 }
1509
1510 void
1511 gdk_window_add_colormap_windows (GdkWindow *window)
1512 {
1513   GdkWindow *toplevel;
1514   GdkWindowPrivate *toplevel_private;
1515   GdkWindowPrivate *window_private;
1516   Window *old_windows;
1517   Window *new_windows;
1518   int i, count;
1519
1520   g_return_if_fail (window != NULL);
1521
1522   toplevel = gdk_window_get_toplevel (window);
1523   toplevel_private = (GdkWindowPrivate*) toplevel;
1524   window_private = (GdkWindowPrivate*) window;
1525   if (window_private->destroyed)
1526     return;
1527
1528   if (!XGetWMColormapWindows (toplevel_private->xdisplay,
1529                               toplevel_private->xwindow,
1530                               &old_windows, &count))
1531     {
1532       old_windows = NULL;
1533       count = 0;
1534     }
1535
1536   for (i = 0; i < count; i++)
1537     if (old_windows[i] == window_private->xwindow)
1538       return;
1539
1540   new_windows = g_new (Window, count + 1);
1541
1542   for (i = 0; i < count; i++)
1543     new_windows[i] = old_windows[i];
1544   new_windows[count] = window_private->xwindow;
1545
1546   XSetWMColormapWindows (toplevel_private->xdisplay,
1547                          toplevel_private->xwindow,
1548                          new_windows, count + 1);
1549
1550   g_free (new_windows);
1551   if (old_windows)
1552     XFree (old_windows);
1553 }
1554
1555 /*
1556  * This needs the X11 shape extension.
1557  * If not available, shaped windows will look
1558  * ugly, but programs still work.    Stefan Wille
1559  */
1560 void
1561 gdk_window_shape_combine_mask (GdkWindow *window,
1562                                GdkBitmap *mask,
1563                                gint x, gint y)
1564 {
1565   enum { UNKNOWN, NO, YES };
1566
1567   static gint have_shape = UNKNOWN;
1568
1569   GdkWindowPrivate *window_private;
1570   Pixmap pixmap;
1571
1572   g_return_if_fail (window != NULL);
1573
1574 #ifdef HAVE_SHAPE_EXT
1575   if (have_shape == UNKNOWN)
1576     {
1577       int ignore;
1578       if (XQueryExtension(gdk_display, "SHAPE", &ignore, &ignore, &ignore))
1579         have_shape = YES;
1580       else
1581         have_shape = NO;
1582     }
1583   
1584   if (have_shape == YES)
1585     {
1586       window_private = (GdkWindowPrivate*) window;
1587       if (window_private->destroyed)
1588         return;
1589       
1590       if (mask)
1591         {
1592           GdkWindowPrivate *pixmap_private;
1593           
1594           pixmap_private = (GdkWindowPrivate*) mask;
1595           pixmap = (Pixmap) pixmap_private->xwindow;
1596         }
1597       else
1598         {
1599           x = 0;
1600           y = 0;
1601           pixmap = None;
1602         }
1603       
1604       XShapeCombineMask  (window_private->xdisplay,
1605                           window_private->xwindow,
1606                           ShapeBounding,
1607                           x, y,
1608                           pixmap,
1609                           ShapeSet);
1610     }
1611 #endif /* HAVE_SHAPE_EXT */
1612 }
1613
1614 void
1615 gdk_dnd_drag_addwindow (GdkWindow *window)
1616 {
1617   GdkWindowPrivate *window_private;
1618   
1619   g_return_if_fail (window != NULL);
1620   
1621   window_private = (GdkWindowPrivate *) window;
1622   if (window_private->destroyed)
1623     return;
1624   
1625   if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
1626     {
1627       gdk_dnd.drag_numwindows++;
1628       gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
1629                                              gdk_dnd.drag_numwindows
1630                                              * sizeof(GdkWindow *));
1631       gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
1632       window_private->dnd_drag_accepted = 0;
1633     } 
1634   else
1635     g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
1636 }
1637
1638 void
1639 gdk_window_dnd_drag_set (GdkWindow   *window,
1640                          guint8       drag_enable,
1641                          gchar      **typelist,
1642                          guint        numtypes)
1643 {
1644   GdkWindowPrivate *window_private;
1645   int i, wasset = 0;
1646   
1647   g_return_if_fail (window != NULL);
1648   window_private = (GdkWindowPrivate *) window;
1649   if (window_private->destroyed)
1650     return;
1651   
1652   window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
1653   
1654   if (drag_enable)
1655     {
1656       g_return_if_fail(typelist != NULL);
1657       
1658       if (window_private->dnd_drag_data_numtypesavail > 3)
1659         wasset = 1;
1660       window_private->dnd_drag_data_numtypesavail = numtypes;
1661       
1662       window_private->dnd_drag_data_typesavail =
1663         g_realloc (window_private->dnd_drag_data_typesavail,
1664                    (numtypes + 1) * sizeof (GdkAtom));
1665       
1666       for (i = 0; i < numtypes; i++)
1667         {
1668           /* Allow blanket use of ALL to get anything... */
1669           if (strcmp (typelist[i], "ALL"))
1670             window_private->dnd_drag_data_typesavail[i] =
1671               gdk_atom_intern (typelist[i], FALSE);
1672           else
1673             window_private->dnd_drag_data_typesavail[i] = None;
1674         }
1675       
1676       /* 
1677        * set our extended type list if we need to 
1678        */
1679       if (numtypes > 3)
1680         gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
1681                             XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
1682                             (guchar *)(window_private->dnd_drag_data_typesavail
1683                              + (sizeof(GdkAtom) * 3)),
1684                             (numtypes - 3) * sizeof(GdkAtom));
1685       else if (wasset)
1686         gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
1687     }
1688   else
1689     {
1690       g_free (window_private->dnd_drag_data_typesavail);
1691       window_private->dnd_drag_data_typesavail = NULL;
1692       window_private->dnd_drag_data_numtypesavail = 0;
1693     }
1694 }
1695
1696 void
1697 gdk_window_dnd_drop_set (GdkWindow   *window,
1698                          guint8       drop_enable,
1699                          gchar      **typelist,
1700                          guint        numtypes,
1701                          guint8       destructive_op)
1702 {
1703   GdkWindowPrivate *window_private;
1704   int i;
1705   
1706   g_return_if_fail (window != NULL);
1707   window_private = (GdkWindowPrivate *) window;
1708   if (window_private->destroyed)
1709     return;
1710   
1711   window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
1712   if (drop_enable)
1713     {
1714       g_return_if_fail(typelist != NULL);
1715       
1716       window_private->dnd_drop_data_numtypesavail = numtypes;
1717       
1718       window_private->dnd_drop_data_typesavail =
1719         g_realloc (window_private->dnd_drop_data_typesavail,
1720                    (numtypes + 1) * sizeof (GdkAtom));
1721       
1722       for (i = 0; i < numtypes; i++)
1723         window_private->dnd_drop_data_typesavail[i] =
1724           gdk_atom_intern (typelist[i], FALSE);
1725       
1726       window_private->dnd_drop_destructive_op = destructive_op;
1727     }
1728 }
1729
1730 /* 
1731  * This is used to reply to a GDK_DRAG_REQUEST event
1732  * (which may be generated by XdeRequest or a confirmed drop... 
1733  */
1734 void
1735 gdk_window_dnd_data_set (GdkWindow       *window,
1736                          GdkEvent        *event,
1737                          gpointer         data,
1738                          gulong           data_numbytes)
1739 {
1740   GdkWindowPrivate *window_private;
1741   XEvent sev;
1742   GdkEventDropDataAvailable tmp_ev;
1743   gchar *tmp;
1744   
1745   g_return_if_fail (window != NULL);
1746   g_return_if_fail (event != NULL);
1747   g_return_if_fail (data != NULL);
1748   g_return_if_fail (data_numbytes > 0);
1749   g_return_if_fail (event->type == GDK_DRAG_REQUEST);
1750
1751   window_private = (GdkWindowPrivate *) window;
1752   g_return_if_fail (window_private->dnd_drag_accepted != 0);    
1753   if (window_private->destroyed)
1754     return;
1755   
1756   /* We set the property on our window... */
1757   gdk_property_change (window, window_private->dnd_drag_data_type,
1758                        XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
1759                        data_numbytes);
1760   tmp = gdk_atom_name(window_private->dnd_drag_data_type);
1761 #ifdef DEBUG_DND
1762   g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow);
1763 #endif
1764   g_free(tmp);
1765   
1766   /* 
1767    * Then we send the event to tell the receiving window that the
1768    * drop has happened 
1769    */
1770   tmp_ev.u.allflags = 0;
1771   tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
1772   tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
1773   
1774   sev.xclient.type = ClientMessage;
1775   sev.xclient.format = 32;
1776   sev.xclient.window = event->dragrequest.requestor;
1777   sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
1778   sev.xclient.data.l[0] = window_private->xwindow;
1779   sev.xclient.data.l[1] = tmp_ev.u.allflags;
1780   sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
1781
1782   if (event->dragrequest.isdrop)
1783     sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
1784       (event->dragrequest.drop_coords.y << 16);
1785   else
1786     sev.xclient.data.l[3] = 0;
1787
1788   sev.xclient.data.l[4] = event->dragrequest.timestamp;
1789
1790   if (!gdk_send_xevent (event->dragrequest.requestor, False,
1791                        StructureNotifyMask, &sev))
1792     GDK_NOTE (DND, g_print("Sending XdeDataAvailable to %#x failed\n",
1793                            event->dragrequest.requestor));
1794
1795 }
1796
1797 void          
1798 gdk_window_add_filter     (GdkWindow     *window,
1799                            GdkFilterFunc  function,
1800                            gpointer       data)
1801 {
1802   GdkWindowPrivate *private;
1803   GList *tmp_list;
1804   GdkEventFilter *filter;
1805
1806   private = (GdkWindowPrivate*) window;
1807   if (private && private->destroyed)
1808     return;
1809
1810   if(private)
1811     tmp_list = private->filters;
1812   else
1813     tmp_list = gdk_default_filters;
1814
1815   while (tmp_list)
1816     {
1817       filter = (GdkEventFilter *)tmp_list->data;
1818       if ((filter->function == function) && (filter->data == data))
1819         return;
1820       tmp_list = tmp_list->next;
1821     }
1822
1823   filter = g_new (GdkEventFilter, 1);
1824   filter->function = function;
1825   filter->data = data;
1826
1827   if(private)
1828     private->filters = g_list_append (private->filters, filter);
1829   else
1830     gdk_default_filters = g_list_append (gdk_default_filters, filter);
1831 }
1832
1833 void
1834 gdk_window_remove_filter  (GdkWindow     *window,
1835                            GdkFilterFunc  function,
1836                            gpointer       data)
1837 {
1838   GdkWindowPrivate *private;
1839   GList *tmp_list;
1840   GdkEventFilter *filter;
1841
1842   private = (GdkWindowPrivate*) window;
1843
1844   if(private)
1845     tmp_list = private->filters;
1846   else
1847     tmp_list = gdk_default_filters;
1848
1849   while (tmp_list)
1850     {
1851       filter = (GdkEventFilter *)tmp_list->data;
1852       tmp_list = tmp_list->next;
1853
1854       if ((filter->function == function) && (filter->data == data))
1855         {
1856           if(private)
1857             private->filters = g_list_remove_link (private->filters, tmp_list);
1858           else
1859             gdk_default_filters = g_list_remove_link (gdk_default_filters, tmp_list);
1860           g_list_free_1 (tmp_list);
1861           g_free (filter);
1862           
1863           return;
1864         }
1865     }
1866 }
1867
1868 void
1869 gdk_window_set_override_redirect(GdkWindow *window,
1870                                  gboolean override_redirect)
1871 {
1872   GdkWindowPrivate *private;
1873   XSetWindowAttributes attr;
1874
1875   g_return_if_fail (window != NULL);
1876   private = (GdkWindowPrivate*) window;
1877   if (private->destroyed)
1878     return;
1879
1880   attr.override_redirect = (override_redirect == FALSE)?False:True;
1881   XChangeWindowAttributes(gdk_display,
1882                           ((GdkWindowPrivate *)window)->xwindow,
1883                           CWOverrideRedirect,
1884                           &attr);
1885 }
1886
1887 void          
1888 gdk_window_set_icon        (GdkWindow *window, 
1889                             GdkWindow *icon_window,
1890                             GdkPixmap *pixmap,
1891                             GdkBitmap *mask)
1892 {
1893   XWMHints wm_hints;
1894   GdkWindowPrivate *window_private;
1895   GdkWindowPrivate *private;
1896
1897   g_return_if_fail (window != NULL);
1898   window_private = (GdkWindowPrivate*) window;
1899   if (window_private->destroyed)
1900     return;
1901
1902   wm_hints.flags = 0;
1903   
1904   if (icon_window != NULL)
1905     {
1906       private = (GdkWindowPrivate *)icon_window;
1907       wm_hints.flags |= IconWindowHint;
1908       wm_hints.icon_window = private->xwindow;
1909     }
1910
1911   if (pixmap != NULL)
1912     {
1913       private = (GdkWindowPrivate *)pixmap;
1914       wm_hints.flags |= IconPixmapHint;
1915       wm_hints.icon_pixmap = private->xwindow;
1916     }
1917
1918   if (mask != NULL)
1919     {
1920       private = (GdkWindowPrivate *)mask;
1921       wm_hints.flags |= IconMaskHint;
1922       wm_hints.icon_mask = private->xwindow;
1923     }
1924
1925   XSetWMHints (window_private->xdisplay, window_private->xwindow, &wm_hints);
1926 }
1927
1928 void          
1929 gdk_window_set_icon_name   (GdkWindow *window, 
1930                             gchar *    name)
1931 {
1932   GdkWindowPrivate *window_private;
1933   XTextProperty property;
1934   gint res;
1935
1936   g_return_if_fail (window != NULL);
1937   window_private = (GdkWindowPrivate*) window;
1938   if (window_private->destroyed)
1939     return;
1940   res = XmbTextListToTextProperty (window_private->xdisplay,
1941                                    &name, 1, XStdICCTextStyle,
1942                                    &property);
1943   if (res < 0)
1944     {
1945       g_warning("Error converting icon name to text property: %d\n", res);
1946       return;
1947     }
1948
1949   XSetWMIconName (window_private->xdisplay, window_private->xwindow,
1950                   &property);
1951
1952   XFree(property.value);
1953 }
1954
1955 void          
1956 gdk_window_set_group   (GdkWindow *window, 
1957                         GdkWindow *leader)
1958 {
1959   XWMHints wm_hints;
1960   GdkWindowPrivate *window_private;
1961   GdkWindowPrivate *private;
1962
1963   g_return_if_fail (window != NULL);
1964   g_return_if_fail (leader != NULL);
1965   window_private = (GdkWindowPrivate*) window;
1966   if (window_private->destroyed)
1967     return;
1968
1969   private = (GdkWindowPrivate *)leader;
1970   wm_hints.flags = WindowGroupHint;
1971   wm_hints.window_group = private->xwindow;
1972
1973   XSetWMHints (window_private->xdisplay, window_private->xwindow, &wm_hints);
1974 }
1975
1976 static void
1977 gdk_window_set_mwm_hints (GdkWindow *window,
1978                           MotifWmHints *new_hints)
1979 {
1980   static Atom hints_atom = None;
1981   MotifWmHints *hints;
1982   Atom type;
1983   gint format;
1984   gulong nitems;
1985   gulong bytes_after;
1986
1987   GdkWindowPrivate *window_private;
1988
1989   g_return_if_fail (window != NULL);
1990   window_private = (GdkWindowPrivate*) window;
1991   if (window_private->destroyed)
1992     return;
1993
1994   if (!hints_atom)
1995     hints_atom = XInternAtom (window_private->xdisplay, 
1996                               _XA_MOTIF_WM_HINTS, FALSE);
1997   
1998   XGetWindowProperty (window_private->xdisplay, window_private->xwindow,
1999                       hints_atom, 0, sizeof(MotifWmHints)/4,
2000                       False, AnyPropertyType, &type, &format, &nitems,
2001                       &bytes_after, (guchar **)&hints);
2002
2003   if (type == None)
2004     hints = new_hints;
2005   else
2006     {
2007       if (new_hints->flags & MWM_HINTS_FUNCTIONS)
2008         {
2009           hints->flags |= MWM_HINTS_FUNCTIONS;
2010           hints->functions = new_hints->functions;
2011         }
2012       if (new_hints->flags & MWM_HINTS_DECORATIONS)
2013         {
2014           hints->flags |= MWM_HINTS_DECORATIONS;
2015           hints->decorations = new_hints->decorations;
2016         }
2017     }
2018
2019   XChangeProperty (window_private->xdisplay, window_private->xwindow,
2020                    hints_atom, hints_atom, 32, PropModeReplace,
2021                    (guchar *)hints, sizeof(MotifWmHints)/4);
2022
2023   if (hints != new_hints)
2024     XFree (hints);
2025 }
2026
2027 void
2028 gdk_window_set_decorations (GdkWindow      *window,
2029                             GdkWMDecoration decorations)
2030 {
2031   MotifWmHints hints;
2032
2033   hints.flags = MWM_HINTS_DECORATIONS;
2034   hints.decorations = decorations;
2035
2036   gdk_window_set_mwm_hints (window, &hints);
2037 }
2038
2039 void
2040 gdk_window_set_functions (GdkWindow    *window,
2041                           GdkWMFunction functions)
2042 {
2043   MotifWmHints hints;
2044
2045   hints.flags = MWM_HINTS_FUNCTIONS;
2046   hints.functions = functions;
2047
2048   gdk_window_set_mwm_hints (window, &hints);
2049 }
2050
2051 GList *
2052 gdk_window_get_toplevels (void)
2053 {
2054   GList *new_list = NULL;
2055   GList *tmp_list;
2056
2057   tmp_list = gdk_root_parent.children;
2058   while (tmp_list)
2059     {
2060       new_list = g_list_prepend (new_list, tmp_list->data);
2061       tmp_list = tmp_list->next;
2062     }
2063
2064   return new_list;
2065 }
2066