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