]> Pileus Git - ~andy/gtk/blob - gdk/gdkwindow.c
new function to get the *real* geometry position of a window, taken
[~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 }
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_message ("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 = g_get_prgname ();
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 = NULL;
469   guint nchildren;
470
471   if(!XGetWindowAttributes (gdk_display, anid, &attrs)) {
472     g_warning("XGetWindowAttributes failed on window ID %d\n", anid);
473     return NULL;
474   }
475
476   private = g_new (GdkWindowPrivate, 1);
477   window = (GdkWindow*) private;
478
479   /* FIXME: This is pretty expensive. Maybe the caller should supply
480    *        the parent */
481   XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren);
482
483   if (children)
484     XFree (children);
485   private->parent = gdk_xid_table_lookup (parent);
486
487   parent_private = (GdkWindowPrivate *)private->parent;
488   
489   if (parent_private)
490     parent_private->children = g_list_prepend (parent_private->children, window);
491
492   private->xwindow = anid;
493   private->xdisplay = gdk_display;
494   private->x = attrs.x;
495   private->y = attrs.y;
496   private->width = attrs.width;
497   private->height = attrs.height;
498   private->resize_count = 0;
499   private->ref_count = 1;
500   private->window_type = GDK_WINDOW_FOREIGN;
501   private->destroyed = FALSE;
502   private->extension_events = 0;
503
504   private->colormap = NULL;
505
506   private->dnd_drag_data_type = None;
507   private->dnd_drag_data_typesavail =
508     private->dnd_drop_data_typesavail = NULL;
509   private->dnd_drop_enabled = private->dnd_drag_enabled =
510     private->dnd_drag_accepted = private->dnd_drag_datashow =
511     private->dnd_drop_data_numtypesavail =
512     private->dnd_drag_data_numtypesavail = 0;
513   private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
514
515   private->filters = NULL;
516   private->children = NULL;
517
518   window->user_data = NULL;
519
520   gdk_window_ref (window);
521   gdk_xid_table_insert (&private->xwindow, window);
522
523   return window;
524 }
525
526 /* Call this function when you want a window and all its children to
527    disappear.  When xdestroy is true, a request to destroy the XWindow
528    is sent out.  When it is false, it is assumed that the XWindow has
529    been or will be destroyed by destroying some ancestor of this
530    window.  */
531
532 static void
533 gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
534                              gboolean our_destroy)
535 {
536   GdkWindowPrivate *private;
537   GdkWindowPrivate *temp_private;
538   GdkWindow *temp_window;
539   GList *children;
540   GList *tmp;
541
542   g_return_if_fail (window != NULL);
543
544   private = (GdkWindowPrivate*) window;
545
546   switch (private->window_type)
547     {
548     case GDK_WINDOW_TOPLEVEL:
549     case GDK_WINDOW_CHILD:
550     case GDK_WINDOW_DIALOG:
551     case GDK_WINDOW_TEMP:
552     case GDK_WINDOW_FOREIGN:
553       if (!private->destroyed)
554         {
555           if (private->parent)
556             {
557               GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent;
558               if (parent_private->children)
559                 parent_private->children = g_list_remove (parent_private->children, window);
560             }
561
562           if (private->window_type != GDK_WINDOW_FOREIGN)
563             {
564               children = tmp = private->children;
565               private->children = NULL;
566
567               while (tmp)
568                 {
569                   temp_window = tmp->data;
570                   tmp = tmp->next;
571                   
572                   temp_private = (GdkWindowPrivate*) temp_window;
573                   if (temp_private)
574                     gdk_window_internal_destroy (temp_window, FALSE,
575                                                  our_destroy);
576                 }
577
578               g_list_free (children);
579             }
580
581           if (private->extension_events != 0)
582             gdk_input_window_destroy (window);
583
584           if(private->dnd_drag_data_numtypesavail > 0) 
585             {
586               g_free (private->dnd_drag_data_typesavail);
587               private->dnd_drag_data_typesavail = NULL;
588             }
589           if(private->dnd_drop_data_numtypesavail > 0) 
590             {
591               g_free (private->dnd_drop_data_typesavail);
592               private->dnd_drop_data_typesavail = NULL;
593             }
594
595           if (private->filters)
596             {
597               tmp = private->filters;
598
599               while (tmp)
600                 {
601                   g_free (tmp->data);
602                   tmp = tmp->next;
603                 }
604
605               g_list_free (private->filters);
606               private->filters = NULL;
607             }
608           
609           if (private->window_type == GDK_WINDOW_FOREIGN)
610             {
611               if (our_destroy && (private->parent != NULL))
612                 {
613                   /* It's somebody elses window, but in our heirarchy,
614                    * so reparent it to the root window, and then send
615                    * it a delete event, as if we were a WM
616                    */
617                   XClientMessageEvent xevent;
618                   
619                   gdk_window_hide (window);
620                   gdk_window_reparent (window, NULL, 0, 0);
621                   
622                   xevent.type = ClientMessage;
623                   xevent.window = private->xwindow;
624                   xevent.message_type = gdk_wm_protocols;
625                   xevent.format = 32;
626                   xevent.data.l[0] = gdk_wm_delete_window;
627                   xevent.data.l[1] = CurrentTime;
628                   
629                   XSendEvent (private->xdisplay, private->xwindow,
630                               False, 0, (XEvent *)&xevent);
631                 }
632             }
633           else if (xdestroy)
634             XDestroyWindow (private->xdisplay, private->xwindow);
635
636           if (private->colormap)
637             gdk_colormap_unref (private->colormap);
638
639           private->destroyed = TRUE;
640         }
641       break;
642
643     case GDK_WINDOW_ROOT:
644       g_error ("attempted to destroy root window");
645       break;
646
647     case GDK_WINDOW_PIXMAP:
648       g_error ("called gdk_window_destroy on a pixmap (use gdk_pixmap_unref)");
649       break;
650     }
651 }
652
653 /* Like internal_destroy, but also destroys the reference created by
654    gdk_window_new. */
655
656 void
657 gdk_window_destroy (GdkWindow *window)
658 {
659   gdk_window_internal_destroy (window, TRUE, TRUE);
660   gdk_window_unref (window);
661 }
662
663 /* This function is called when the XWindow is really gone.  */
664
665 void
666 gdk_window_destroy_notify (GdkWindow *window)
667 {
668   GdkWindowPrivate *private;
669
670   g_return_if_fail (window != NULL);
671
672   private = (GdkWindowPrivate*) window;
673
674   if (!private->destroyed)
675     {
676       if (private->window_type == GDK_WINDOW_FOREIGN)
677         gdk_window_internal_destroy (window, FALSE, FALSE);
678       else
679         g_warning ("GdkWindow %#lx unexpectedly destroyed", private->xwindow);
680     }
681   
682   gdk_xid_table_remove (private->xwindow);
683   gdk_window_unref (window);
684 }
685
686 GdkWindow*
687 gdk_window_ref (GdkWindow *window)
688 {
689   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
690   g_return_val_if_fail (window != NULL, NULL);
691
692   private->ref_count += 1;
693   return window;
694 }
695
696 void
697 gdk_window_unref (GdkWindow *window)
698 {
699   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
700   g_return_if_fail (window != NULL);
701
702   private->ref_count -= 1;
703   if (private->ref_count == 0)
704     {
705       if (!private->destroyed)
706         g_warning ("losing last reference to undestroyed window\n");
707       g_dataset_destroy (window);
708       g_free (window);
709     }
710
711 }
712
713 void
714 gdk_window_show (GdkWindow *window)
715 {
716   GdkWindowPrivate *private;
717
718   g_return_if_fail (window != NULL);
719
720   private = (GdkWindowPrivate*) window;
721   if (!private->destroyed)
722     {
723       XRaiseWindow (private->xdisplay, private->xwindow);
724       XMapWindow (private->xdisplay, private->xwindow);
725     }
726 }
727
728 void
729 gdk_window_hide (GdkWindow *window)
730 {
731   GdkWindowPrivate *private;
732
733   g_return_if_fail (window != NULL);
734
735   private = (GdkWindowPrivate*) window;
736   if (!private->destroyed)
737     XUnmapWindow (private->xdisplay, private->xwindow);
738 }
739
740 void
741 gdk_window_withdraw (GdkWindow *window)
742 {
743   GdkWindowPrivate *private;
744
745   g_return_if_fail (window != NULL);
746
747   private = (GdkWindowPrivate*) window;
748   if (!private->destroyed)
749     XWithdrawWindow (private->xdisplay, private->xwindow, 0);
750 }
751
752 void
753 gdk_window_move (GdkWindow *window,
754                  gint       x,
755                  gint       y)
756 {
757   GdkWindowPrivate *private;
758
759   g_return_if_fail (window != NULL);
760
761   private = (GdkWindowPrivate*) window;
762   if (!private->destroyed)
763     {
764       XMoveWindow (private->xdisplay, private->xwindow, x, y);
765       
766       if (private->window_type == GDK_WINDOW_CHILD)
767         {
768           private->x = x;
769           private->y = y;
770         }
771     }
772 }
773
774 void
775 gdk_window_resize (GdkWindow *window,
776                    gint       width,
777                    gint       height)
778 {
779   GdkWindowPrivate *private;
780
781   g_return_if_fail (window != NULL);
782
783   if (width < 1)
784     width = 1;
785   if (height < 1)
786     height = 1;
787
788   private = (GdkWindowPrivate*) window;
789
790   if (!private->destroyed &&
791       ((private->resize_count > 0) ||
792        (private->width != (guint16) width) ||
793        (private->height != (guint16) height)))
794     {
795       XResizeWindow (private->xdisplay, private->xwindow, width, height);
796       private->resize_count += 1;
797
798       if (private->window_type == GDK_WINDOW_CHILD)
799         {
800           private->width = width;
801           private->height = height;
802         }
803     }
804 }
805
806 void
807 gdk_window_move_resize (GdkWindow *window,
808                         gint       x,
809                         gint       y,
810                         gint       width,
811                         gint       height)
812 {
813   GdkWindowPrivate *private;
814
815   g_return_if_fail (window != NULL);
816
817   if (width < 1)
818     width = 1;
819   if (height < 1)
820     height = 1;
821
822   private = (GdkWindowPrivate*) window;
823   if (!private->destroyed)
824     {
825       XMoveResizeWindow (private->xdisplay, private->xwindow, x, y, width, height);
826       
827       if (private->window_type == GDK_WINDOW_CHILD)
828         {
829           private->x = x;
830           private->y = y;
831           private->width = width;
832           private->height = height;
833         }
834     }
835 }
836
837 void
838 gdk_window_reparent (GdkWindow *window,
839                      GdkWindow *new_parent,
840                      gint       x,
841                      gint       y)
842 {
843   GdkWindowPrivate *window_private;
844   GdkWindowPrivate *parent_private;
845   GdkWindowPrivate *old_parent_private;
846
847   g_return_if_fail (window != NULL);
848
849   if (!new_parent)
850     new_parent = (GdkWindow*) &gdk_root_parent;
851
852   window_private = (GdkWindowPrivate*) window;
853   old_parent_private = (GdkWindowPrivate*)window_private->parent;
854   parent_private = (GdkWindowPrivate*) new_parent;
855
856   if (!window_private->destroyed && !parent_private->destroyed)
857     XReparentWindow (window_private->xdisplay,
858                      window_private->xwindow,
859                      parent_private->xwindow,
860                      x, y);
861
862   window_private->parent = new_parent;
863
864   if (old_parent_private)
865     old_parent_private->children = g_list_remove (old_parent_private->children, window);
866   parent_private->children = g_list_prepend (parent_private->children, window);
867   
868 }
869
870 void
871 gdk_window_clear (GdkWindow *window)
872 {
873   GdkWindowPrivate *private;
874
875   g_return_if_fail (window != NULL);
876
877   private = (GdkWindowPrivate*) window;
878
879   if (!private->destroyed)
880     XClearWindow (private->xdisplay, private->xwindow);
881 }
882
883 void
884 gdk_window_clear_area (GdkWindow *window,
885                        gint       x,
886                        gint       y,
887                        gint       width,
888                        gint       height)
889 {
890   GdkWindowPrivate *private;
891   
892   g_return_if_fail (window != NULL);
893   
894   private = (GdkWindowPrivate*) window;
895   
896   if (!private->destroyed)
897     XClearArea (private->xdisplay, private->xwindow,
898                 x, y, width, height, False);
899 }
900
901 void
902 gdk_window_clear_area_e (GdkWindow *window,
903                          gint       x,
904                          gint       y,
905                          gint       width,
906                          gint       height)
907 {
908   GdkWindowPrivate *private;
909   
910   g_return_if_fail (window != NULL);
911   
912   private = (GdkWindowPrivate*) window;
913   
914   if (!private->destroyed)
915     XClearArea (private->xdisplay, private->xwindow,
916                 x, y, width, height, True);
917 }
918
919 void
920 gdk_window_copy_area (GdkWindow    *window,
921                       GdkGC        *gc,
922                       gint          x,
923                       gint          y,
924                       GdkWindow    *source_window,
925                       gint          source_x,
926                       gint          source_y,
927                       gint          width,
928                       gint          height)
929 {
930   GdkWindowPrivate *src_private;
931   GdkWindowPrivate *dest_private;
932   GdkGCPrivate *gc_private;
933   
934   g_return_if_fail (window != NULL);
935   g_return_if_fail (gc != NULL);
936   
937   if (source_window == NULL)
938     source_window = window;
939   
940   src_private = (GdkWindowPrivate*) source_window;
941   dest_private = (GdkWindowPrivate*) window;
942   gc_private = (GdkGCPrivate*) gc;
943   
944   if (!src_private->destroyed && !dest_private->destroyed)
945     {
946       XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow,
947                  gc_private->xgc,
948                  source_x, source_y,
949                  width, height,
950                  x, y);
951     }
952 }
953
954 void
955 gdk_window_raise (GdkWindow *window)
956 {
957   GdkWindowPrivate *private;
958   
959   g_return_if_fail (window != NULL);
960   
961   private = (GdkWindowPrivate*) window;
962   
963   if (!private->destroyed)
964     XRaiseWindow (private->xdisplay, private->xwindow);
965 }
966
967 void
968 gdk_window_lower (GdkWindow *window)
969 {
970   GdkWindowPrivate *private;
971   
972   g_return_if_fail (window != NULL);
973   
974   private = (GdkWindowPrivate*) window;
975   
976   if (!private->destroyed)
977     XLowerWindow (private->xdisplay, private->xwindow);
978 }
979
980 void
981 gdk_window_set_user_data (GdkWindow *window,
982                           gpointer   user_data)
983 {
984   g_return_if_fail (window != NULL);
985   
986   window->user_data = user_data;
987 }
988
989 void
990 gdk_window_set_hints (GdkWindow *window,
991                       gint       x,
992                       gint       y,
993                       gint       min_width,
994                       gint       min_height,
995                       gint       max_width,
996                       gint       max_height,
997                       gint       flags)
998 {
999   GdkWindowPrivate *private;
1000   XSizeHints size_hints;
1001   
1002   g_return_if_fail (window != NULL);
1003   
1004   private = (GdkWindowPrivate*) window;
1005   if (private->destroyed)
1006     return;
1007   
1008   size_hints.flags = 0;
1009   
1010   if (flags & GDK_HINT_POS)
1011     {
1012       size_hints.flags |= PPosition;
1013       size_hints.x = x;
1014       size_hints.y = y;
1015     }
1016   
1017   if (flags & GDK_HINT_MIN_SIZE)
1018     {
1019       size_hints.flags |= PMinSize;
1020       size_hints.min_width = min_width;
1021       size_hints.min_height = min_height;
1022     }
1023   
1024   if (flags & GDK_HINT_MAX_SIZE)
1025     {
1026       size_hints.flags |= PMaxSize;
1027       size_hints.max_width = max_width;
1028       size_hints.max_height = max_height;
1029     }
1030   
1031   if (flags)
1032     XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
1033 }
1034
1035 void
1036 gdk_window_set_title (GdkWindow   *window,
1037                       const gchar *title)
1038 {
1039   GdkWindowPrivate *private;
1040   
1041   g_return_if_fail (window != NULL);
1042   
1043   private = (GdkWindowPrivate*) window;
1044   if (!private->destroyed)
1045     XmbSetWMProperties (private->xdisplay, private->xwindow,
1046                         title, title, NULL, 0, NULL, NULL, NULL);
1047 }
1048
1049 void
1050 gdk_window_set_background (GdkWindow *window,
1051                            GdkColor  *color)
1052 {
1053   GdkWindowPrivate *private;
1054   
1055   g_return_if_fail (window != NULL);
1056   
1057   private = (GdkWindowPrivate*) window;
1058   if (!private->destroyed)
1059     XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel);
1060 }
1061
1062 void
1063 gdk_window_set_back_pixmap (GdkWindow *window,
1064                             GdkPixmap *pixmap,
1065                             gint       parent_relative)
1066 {
1067   GdkWindowPrivate *window_private;
1068   GdkPixmapPrivate *pixmap_private;
1069   Pixmap xpixmap;
1070   
1071   g_return_if_fail (window != NULL);
1072   
1073   window_private = (GdkWindowPrivate*) window;
1074   pixmap_private = (GdkPixmapPrivate*) pixmap;
1075   
1076   if (pixmap)
1077     xpixmap = pixmap_private->xwindow;
1078   else
1079     xpixmap = None;
1080   
1081   if (parent_relative)
1082     xpixmap = ParentRelative;
1083   
1084   if (!window_private->destroyed)
1085     XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap);
1086 }
1087
1088 void
1089 gdk_window_set_cursor (GdkWindow *window,
1090                        GdkCursor *cursor)
1091 {
1092   GdkWindowPrivate *window_private;
1093   GdkCursorPrivate *cursor_private;
1094   Cursor xcursor;
1095   
1096   g_return_if_fail (window != NULL);
1097   
1098   window_private = (GdkWindowPrivate*) window;
1099   cursor_private = (GdkCursorPrivate*) cursor;
1100   
1101   if (!cursor)
1102     xcursor = None;
1103   else
1104     xcursor = cursor_private->xcursor;
1105   
1106   if (!window_private->destroyed)
1107     XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor);
1108 }
1109
1110 void
1111 gdk_window_set_colormap (GdkWindow   *window,
1112                          GdkColormap *colormap)
1113 {
1114   GdkWindowPrivate *window_private;
1115   GdkColormapPrivate *colormap_private;
1116   
1117   g_return_if_fail (window != NULL);
1118   g_return_if_fail (colormap != NULL);
1119   
1120   window_private = (GdkWindowPrivate*) window;
1121   colormap_private = (GdkColormapPrivate*) colormap;
1122   
1123   if (!window_private->destroyed)
1124     {
1125       XSetWindowColormap (window_private->xdisplay,
1126                           window_private->xwindow,
1127                           colormap_private->xcolormap);
1128
1129       if (window_private->colormap)
1130         gdk_colormap_unref (window_private->colormap);
1131       window_private->colormap = colormap;
1132       gdk_colormap_ref (window_private->colormap);
1133       
1134       if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
1135         gdk_window_add_colormap_windows (window);
1136     }
1137 }
1138
1139 void
1140 gdk_window_get_user_data (GdkWindow *window,
1141                           gpointer  *data)
1142 {
1143   g_return_if_fail (window != NULL);
1144   
1145   *data = window->user_data;
1146 }
1147
1148 void
1149 gdk_window_get_geometry (GdkWindow *window,
1150                          gint      *x,
1151                          gint      *y,
1152                          gint      *width,
1153                          gint      *height,
1154                          gint      *depth)
1155 {
1156   GdkWindowPrivate *window_private;
1157   Window root;
1158   gint tx;
1159   gint ty;
1160   guint twidth;
1161   guint theight;
1162   guint tborder_width;
1163   guint tdepth;
1164   
1165   if (!window)
1166     window = (GdkWindow*) &gdk_root_parent;
1167   
1168   window_private = (GdkWindowPrivate*) window;
1169   
1170   if (!window_private->destroyed)
1171     {
1172       XGetGeometry (window_private->xdisplay, window_private->xwindow,
1173                     &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
1174       
1175       if (x)
1176         *x = tx;
1177       if (y)
1178         *y = ty;
1179       if (width)
1180         *width = twidth;
1181       if (height)
1182         *height = theight;
1183       if (depth)
1184         *depth = tdepth;
1185     }
1186 }
1187
1188 void
1189 gdk_window_get_position (GdkWindow *window,
1190                          gint      *x,
1191                          gint      *y)
1192 {
1193   GdkWindowPrivate *window_private;
1194   
1195   g_return_if_fail (window != NULL);
1196   
1197   window_private = (GdkWindowPrivate*) window;
1198   
1199   if (x)
1200     *x = window_private->x;
1201   if (y)
1202     *y = window_private->y;
1203 }
1204
1205 void
1206 gdk_window_get_size (GdkWindow *window,
1207                      gint       *width,
1208                      gint       *height)
1209 {
1210   GdkWindowPrivate *window_private;
1211   
1212   g_return_if_fail (window != NULL);
1213   
1214   window_private = (GdkWindowPrivate*) window;
1215   
1216   if (width)
1217     *width = window_private->width;
1218   if (height)
1219     *height = window_private->height;
1220 }
1221
1222 GdkVisual*
1223 gdk_window_get_visual (GdkWindow *window)
1224 {
1225   GdkWindowPrivate *window_private;
1226   XWindowAttributes window_attributes;
1227    
1228   g_return_val_if_fail (window != NULL, NULL);
1229
1230   window_private = (GdkWindowPrivate*) window;
1231   /* Huh? ->parent is never set for a pixmap. We should just return
1232    * null immeditately
1233    */
1234   while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
1235     window_private = (GdkWindowPrivate*) window_private->parent;
1236   
1237   if (window_private && !window_private->destroyed)
1238     {
1239        if (window_private->colormap == NULL)
1240          {
1241             XGetWindowAttributes (window_private->xdisplay,
1242                                   window_private->xwindow,
1243                                   &window_attributes);
1244             return gdk_visual_lookup (window_attributes.visual);
1245          }
1246        else
1247          return ((GdkColormapPrivate *)window_private->colormap)->visual;
1248     }
1249   
1250   return NULL;
1251 }
1252
1253 GdkColormap*
1254 gdk_window_get_colormap (GdkWindow *window)
1255 {
1256   GdkWindowPrivate *window_private;
1257   XWindowAttributes window_attributes;
1258   
1259   g_return_val_if_fail (window != NULL, NULL);
1260   window_private = (GdkWindowPrivate*) window;
1261
1262   g_return_val_if_fail (window_private->window_type != GDK_WINDOW_PIXMAP, NULL);
1263   if (!window_private->destroyed)
1264     {
1265       if (window_private->colormap == NULL)
1266         {
1267           XGetWindowAttributes (window_private->xdisplay,
1268                                 window_private->xwindow,
1269                                 &window_attributes);
1270           return gdk_colormap_lookup (window_attributes.colormap);
1271          }
1272        else
1273          return window_private->colormap;
1274     }
1275   
1276   return NULL;
1277 }
1278
1279 GdkWindowType
1280 gdk_window_get_type (GdkWindow *window)
1281 {
1282   GdkWindowPrivate *window_private;
1283
1284   g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
1285
1286   window_private = (GdkWindowPrivate*) window;
1287   return window_private->window_type;
1288 }
1289
1290 gint
1291 gdk_window_get_origin (GdkWindow *window,
1292                        gint      *x,
1293                        gint      *y)
1294 {
1295   GdkWindowPrivate *private;
1296   gint return_val;
1297   Window child;
1298   gint tx = 0;
1299   gint ty = 0;
1300
1301   g_return_val_if_fail (window != NULL, 0);
1302
1303   private = (GdkWindowPrivate*) window;
1304
1305   if (!private->destroyed)
1306     {
1307       return_val = XTranslateCoordinates (private->xdisplay,
1308                                           private->xwindow,
1309                                           gdk_root_window,
1310                                           0, 0, &tx, &ty,
1311                                           &child);
1312       
1313     }
1314   else
1315     return_val = 0;
1316   
1317   if (x)
1318     *x = tx;
1319   if (y)
1320     *y = ty;
1321   
1322   return return_val;
1323 }
1324
1325 void
1326 gdk_window_get_root_origin (GdkWindow *window,
1327                             gint      *x,
1328                             gint      *y)
1329 {
1330   GdkWindowPrivate *private;
1331   Window xwindow;
1332   Window xparent;
1333   Window root;
1334   Window *children;
1335   unsigned int nchildren;
1336
1337   g_return_if_fail (window != NULL);
1338
1339   private = (GdkWindowPrivate*) window;
1340   if (x)
1341     *x = 0;
1342   if (y)
1343     *y = 0;
1344   if (private->destroyed)
1345     return;
1346       
1347   while (private->parent && ((GdkWindowPrivate*) private->parent)->parent)
1348     private = (GdkWindowPrivate*) private->parent;
1349   if (private->destroyed)
1350     return;
1351
1352   xparent = private->xwindow;
1353   do
1354     {
1355       xwindow = xparent;
1356       if (!XQueryTree (private->xdisplay, xwindow,
1357                        &root, &xparent,
1358                        &children, &nchildren))
1359         return;
1360
1361       if (children)
1362         XFree (children);
1363     }
1364   while (xparent != root);
1365
1366   if (xparent == root)
1367     {
1368       unsigned int ww, wh, wb, wd;
1369       int wx, wy;
1370
1371       if (XGetGeometry (private->xdisplay, xwindow, &root, &wx, &wy, &ww, &wh, &wb, &wd))
1372         {
1373           if (x)
1374             *x = wx;
1375           if (y)
1376             *y = wy;
1377         }
1378     }
1379 }
1380
1381 GdkWindow*
1382 gdk_window_get_pointer (GdkWindow       *window,
1383                         gint            *x,
1384                         gint            *y,
1385                         GdkModifierType *mask)
1386 {
1387   GdkWindowPrivate *private;
1388   GdkWindow *return_val;
1389   Window root;
1390   Window child;
1391   int rootx, rooty;
1392   int winx = 0;
1393   int winy = 0;
1394   unsigned int xmask = 0;
1395
1396   if (!window)
1397     window = (GdkWindow*) &gdk_root_parent;
1398
1399   private = (GdkWindowPrivate*) window;
1400
1401   return_val = NULL;
1402   if (!private->destroyed &&
1403       XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
1404                      &rootx, &rooty, &winx, &winy, &xmask))
1405     {
1406       if (child)
1407         return_val = gdk_window_lookup (child);
1408     }
1409   
1410   if (x)
1411     *x = winx;
1412   if (y)
1413     *y = winy;
1414   if (mask)
1415     *mask = xmask;
1416   
1417   return return_val;
1418 }
1419
1420 GdkWindow*
1421 gdk_window_at_pointer (gint *win_x,
1422                        gint *win_y)
1423 {
1424   GdkWindowPrivate *private;
1425   GdkWindow *window;
1426   Window root;
1427   Window xwindow;
1428   Window xwindow_last = 0;
1429   int rootx = -1, rooty = -1;
1430   int winx, winy;
1431   unsigned int xmask;
1432
1433   private = &gdk_root_parent;
1434
1435   xwindow = private->xwindow;
1436
1437   XGrabServer (private->xdisplay);
1438   while (xwindow)
1439     {
1440       xwindow_last = xwindow;
1441       XQueryPointer (private->xdisplay,
1442                      xwindow,
1443                      &root, &xwindow,
1444                      &rootx, &rooty,
1445                      &winx, &winy,
1446                      &xmask);
1447     }
1448   XUngrabServer (private->xdisplay);
1449   
1450   window = gdk_window_lookup (xwindow_last);
1451
1452   if (win_x)
1453     *win_x = window ? winx : -1;
1454   if (win_y)
1455     *win_y = window ? winy : -1;
1456
1457   return window;
1458 }
1459
1460 GdkWindow*
1461 gdk_window_get_parent (GdkWindow *window)
1462 {
1463   g_return_val_if_fail (window != NULL, NULL);
1464
1465   return ((GdkWindowPrivate*) window)->parent;
1466 }
1467
1468 GdkWindow*
1469 gdk_window_get_toplevel (GdkWindow *window)
1470 {
1471   GdkWindowPrivate *private;
1472
1473   g_return_val_if_fail (window != NULL, NULL);
1474
1475   private = (GdkWindowPrivate*) window;
1476
1477   while (private->window_type == GDK_WINDOW_CHILD)
1478     {
1479       window = ((GdkWindowPrivate*) window)->parent;
1480       private = (GdkWindowPrivate*) window;
1481     }
1482
1483   return window;
1484 }
1485
1486 GList*
1487 gdk_window_get_children (GdkWindow *window)
1488 {
1489   GdkWindowPrivate *private;
1490   GdkWindow *child;
1491   GList *children;
1492   Window root;
1493   Window parent;
1494   Window *xchildren;
1495   unsigned int nchildren;
1496   unsigned int i;
1497
1498   g_return_val_if_fail (window != NULL, NULL);
1499
1500   private = (GdkWindowPrivate*) window;
1501   if (private->destroyed)
1502     return NULL;
1503
1504   XQueryTree (private->xdisplay, private->xwindow,
1505               &root, &parent, &xchildren, &nchildren);
1506
1507   children = NULL;
1508
1509   if (nchildren > 0)
1510     {
1511       for (i = 0; i < nchildren; i++)
1512         {
1513           child = gdk_window_lookup (xchildren[i]);
1514           if (child)
1515             children = g_list_prepend (children, child);
1516         }
1517
1518       if (xchildren)
1519         XFree (xchildren);
1520     }
1521
1522   return children;
1523 }
1524
1525 GdkEventMask  
1526 gdk_window_get_events      (GdkWindow       *window)
1527 {
1528   GdkWindowPrivate *private;
1529   XWindowAttributes attrs;
1530   GdkEventMask event_mask;
1531   int i;
1532
1533   g_return_val_if_fail (window != NULL, 0);
1534
1535   private = (GdkWindowPrivate*) window;
1536   if (private->destroyed)
1537     return 0;
1538
1539   XGetWindowAttributes (gdk_display, private->xwindow, 
1540                         &attrs);
1541
1542   event_mask = 0;
1543   for (i = 0; i < nevent_masks; i++)
1544     {
1545       if (attrs.your_event_mask & event_mask_table[i])
1546         event_mask |= 1 << (i + 1);
1547     }
1548
1549   return event_mask;
1550 }
1551
1552 void          
1553 gdk_window_set_events      (GdkWindow       *window,
1554                             GdkEventMask     event_mask)
1555 {
1556   GdkWindowPrivate *private;
1557   long xevent_mask;
1558   int i;
1559
1560   g_return_if_fail (window != NULL);
1561
1562   private = (GdkWindowPrivate*) window;
1563   if (private->destroyed)
1564     return;
1565
1566   xevent_mask = StructureNotifyMask;
1567   for (i = 0; i < nevent_masks; i++)
1568     {
1569       if (event_mask & (1 << (i + 1)))
1570         xevent_mask |= event_mask_table[i];
1571     }
1572   
1573   XSelectInput (gdk_display, private->xwindow, 
1574                 xevent_mask);
1575 }
1576
1577 void
1578 gdk_window_add_colormap_windows (GdkWindow *window)
1579 {
1580   GdkWindow *toplevel;
1581   GdkWindowPrivate *toplevel_private;
1582   GdkWindowPrivate *window_private;
1583   Window *old_windows;
1584   Window *new_windows;
1585   int i, count;
1586
1587   g_return_if_fail (window != NULL);
1588
1589   toplevel = gdk_window_get_toplevel (window);
1590   toplevel_private = (GdkWindowPrivate*) toplevel;
1591   window_private = (GdkWindowPrivate*) window;
1592   if (window_private->destroyed)
1593     return;
1594
1595   old_windows = NULL;
1596   if (!XGetWMColormapWindows (toplevel_private->xdisplay,
1597                               toplevel_private->xwindow,
1598                               &old_windows, &count))
1599     {
1600       count = 0;
1601     }
1602
1603   for (i = 0; i < count; i++)
1604     if (old_windows[i] == window_private->xwindow)
1605       {
1606         XFree (old_windows);
1607         return;
1608       }
1609
1610   new_windows = g_new (Window, count + 1);
1611
1612   for (i = 0; i < count; i++)
1613     new_windows[i] = old_windows[i];
1614   new_windows[count] = window_private->xwindow;
1615
1616   XSetWMColormapWindows (toplevel_private->xdisplay,
1617                          toplevel_private->xwindow,
1618                          new_windows, count + 1);
1619
1620   g_free (new_windows);
1621   if (old_windows)
1622     XFree (old_windows);
1623 }
1624
1625 /*
1626  * This needs the X11 shape extension.
1627  * If not available, shaped windows will look
1628  * ugly, but programs still work.    Stefan Wille
1629  */
1630 void
1631 gdk_window_shape_combine_mask (GdkWindow *window,
1632                                GdkBitmap *mask,
1633                                gint x, gint y)
1634 {
1635   enum { UNKNOWN, NO, YES };
1636
1637   static gint have_shape = UNKNOWN;
1638
1639   GdkWindowPrivate *window_private;
1640   Pixmap pixmap;
1641
1642   g_return_if_fail (window != NULL);
1643
1644 #ifdef HAVE_SHAPE_EXT
1645   if (have_shape == UNKNOWN)
1646     {
1647       int ignore;
1648       if (XQueryExtension(gdk_display, "SHAPE", &ignore, &ignore, &ignore))
1649         have_shape = YES;
1650       else
1651         have_shape = NO;
1652     }
1653   
1654   if (have_shape == YES)
1655     {
1656       window_private = (GdkWindowPrivate*) window;
1657       if (window_private->destroyed)
1658         return;
1659       
1660       if (mask)
1661         {
1662           GdkWindowPrivate *pixmap_private;
1663           
1664           pixmap_private = (GdkWindowPrivate*) mask;
1665           pixmap = (Pixmap) pixmap_private->xwindow;
1666         }
1667       else
1668         {
1669           x = 0;
1670           y = 0;
1671           pixmap = None;
1672         }
1673       
1674       XShapeCombineMask  (window_private->xdisplay,
1675                           window_private->xwindow,
1676                           ShapeBounding,
1677                           x, y,
1678                           pixmap,
1679                           ShapeSet);
1680     }
1681 #endif /* HAVE_SHAPE_EXT */
1682 }
1683
1684 void
1685 gdk_dnd_drag_addwindow (GdkWindow *window)
1686 {
1687   GdkWindowPrivate *window_private;
1688   
1689   g_return_if_fail (window != NULL);
1690   
1691   window_private = (GdkWindowPrivate *) window;
1692   if (window_private->destroyed)
1693     return;
1694   
1695   if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
1696     {
1697       gdk_dnd.drag_numwindows++;
1698       gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
1699                                              gdk_dnd.drag_numwindows
1700                                              * sizeof(GdkWindow *));
1701       gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
1702       window_private->dnd_drag_accepted = 0;
1703     } 
1704   else
1705     g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
1706 }
1707
1708 void
1709 gdk_window_dnd_drag_set (GdkWindow   *window,
1710                          guint8       drag_enable,
1711                          gchar      **typelist,
1712                          guint        numtypes)
1713 {
1714   GdkWindowPrivate *window_private;
1715   int i, wasset = 0;
1716   
1717   g_return_if_fail (window != NULL);
1718   window_private = (GdkWindowPrivate *) window;
1719   if (window_private->destroyed)
1720     return;
1721   
1722   window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
1723   
1724   if (drag_enable)
1725     {
1726       g_return_if_fail(typelist != NULL);
1727       
1728       if (window_private->dnd_drag_data_numtypesavail > 3)
1729         wasset = 1;
1730       window_private->dnd_drag_data_numtypesavail = numtypes;
1731       
1732       window_private->dnd_drag_data_typesavail =
1733         g_realloc (window_private->dnd_drag_data_typesavail,
1734                    (numtypes + 1) * sizeof (GdkAtom));
1735       
1736       for (i = 0; i < numtypes; i++)
1737         {
1738           /* Allow blanket use of ALL to get anything... */
1739           if (strcmp (typelist[i], "ALL"))
1740             window_private->dnd_drag_data_typesavail[i] =
1741               gdk_atom_intern (typelist[i], FALSE);
1742           else
1743             window_private->dnd_drag_data_typesavail[i] = None;
1744         }
1745       
1746       /* 
1747        * set our extended type list if we need to 
1748        */
1749       if (numtypes > 3)
1750         gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
1751                             XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
1752                             (guchar *)(window_private->dnd_drag_data_typesavail
1753                              + (sizeof(GdkAtom) * 3)),
1754                             (numtypes - 3) * sizeof(GdkAtom));
1755       else if (wasset)
1756         gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
1757     }
1758   else
1759     {
1760       g_free (window_private->dnd_drag_data_typesavail);
1761       window_private->dnd_drag_data_typesavail = NULL;
1762       window_private->dnd_drag_data_numtypesavail = 0;
1763     }
1764 }
1765
1766 void
1767 gdk_window_dnd_drop_set (GdkWindow   *window,
1768                          guint8       drop_enable,
1769                          gchar      **typelist,
1770                          guint        numtypes,
1771                          guint8       destructive_op)
1772 {
1773   GdkWindowPrivate *window_private;
1774   int i;
1775   
1776   g_return_if_fail (window != NULL);
1777   window_private = (GdkWindowPrivate *) window;
1778   if (window_private->destroyed)
1779     return;
1780   
1781   window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
1782   if (drop_enable)
1783     {
1784       g_return_if_fail(typelist != NULL);
1785       
1786       window_private->dnd_drop_data_numtypesavail = numtypes;
1787       
1788       window_private->dnd_drop_data_typesavail =
1789         g_realloc (window_private->dnd_drop_data_typesavail,
1790                    (numtypes + 1) * sizeof (GdkAtom));
1791       
1792       for (i = 0; i < numtypes; i++)
1793         window_private->dnd_drop_data_typesavail[i] =
1794           gdk_atom_intern (typelist[i], FALSE);
1795       
1796       window_private->dnd_drop_destructive_op = destructive_op;
1797     }
1798 }
1799
1800 /* 
1801  * This is used to reply to a GDK_DRAG_REQUEST event
1802  * (which may be generated by XdeRequest or a confirmed drop... 
1803  */
1804 void
1805 gdk_window_dnd_data_set (GdkWindow       *window,
1806                          GdkEvent        *event,
1807                          gpointer         data,
1808                          gulong           data_numbytes)
1809 {
1810   GdkWindowPrivate *window_private;
1811   XEvent sev;
1812   GdkEventDropDataAvailable tmp_ev;
1813   gchar *tmp;
1814   
1815   g_return_if_fail (window != NULL);
1816   g_return_if_fail (event != NULL);
1817   g_return_if_fail (data != NULL);
1818   g_return_if_fail (data_numbytes > 0);
1819   g_return_if_fail (event->type == GDK_DRAG_REQUEST);
1820
1821   window_private = (GdkWindowPrivate *) window;
1822   g_return_if_fail (window_private->dnd_drag_accepted != 0);    
1823   if (window_private->destroyed)
1824     return;
1825   
1826   /* We set the property on our window... */
1827   gdk_property_change (window, window_private->dnd_drag_data_type,
1828                        XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
1829                        data_numbytes);
1830   tmp = gdk_atom_name(window_private->dnd_drag_data_type);
1831 #ifdef DEBUG_DND
1832   g_message("DnD type %s on window %ld\n", tmp, window_private->xwindow);
1833 #endif
1834   g_free(tmp);
1835   
1836   /* 
1837    * Then we send the event to tell the receiving window that the
1838    * drop has happened 
1839    */
1840   tmp_ev.u.allflags = 0;
1841   tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
1842   tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
1843   
1844   sev.xclient.type = ClientMessage;
1845   sev.xclient.format = 32;
1846   sev.xclient.window = event->dragrequest.requestor;
1847   sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
1848   sev.xclient.data.l[0] = window_private->xwindow;
1849   sev.xclient.data.l[1] = tmp_ev.u.allflags;
1850   sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
1851
1852   if (event->dragrequest.isdrop)
1853     sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
1854       (event->dragrequest.drop_coords.y << 16);
1855   else
1856     sev.xclient.data.l[3] = 0;
1857
1858   sev.xclient.data.l[4] = event->dragrequest.timestamp;
1859
1860   if (!gdk_send_xevent (event->dragrequest.requestor, False,
1861                        StructureNotifyMask, &sev))
1862     GDK_NOTE (DND, g_message("Sending XdeDataAvailable to %#x failed\n",
1863                              event->dragrequest.requestor));
1864 }
1865
1866 void          
1867 gdk_window_add_filter     (GdkWindow     *window,
1868                            GdkFilterFunc  function,
1869                            gpointer       data)
1870 {
1871   GdkWindowPrivate *private;
1872   GList *tmp_list;
1873   GdkEventFilter *filter;
1874
1875   private = (GdkWindowPrivate*) window;
1876   if (private && private->destroyed)
1877     return;
1878
1879   if(private)
1880     tmp_list = private->filters;
1881   else
1882     tmp_list = gdk_default_filters;
1883
1884   while (tmp_list)
1885     {
1886       filter = (GdkEventFilter *)tmp_list->data;
1887       if ((filter->function == function) && (filter->data == data))
1888         return;
1889       tmp_list = tmp_list->next;
1890     }
1891
1892   filter = g_new (GdkEventFilter, 1);
1893   filter->function = function;
1894   filter->data = data;
1895
1896   if(private)
1897     private->filters = g_list_append (private->filters, filter);
1898   else
1899     gdk_default_filters = g_list_append (gdk_default_filters, filter);
1900 }
1901
1902 void
1903 gdk_window_remove_filter  (GdkWindow     *window,
1904                            GdkFilterFunc  function,
1905                            gpointer       data)
1906 {
1907   GdkWindowPrivate *private;
1908   GList *tmp_list;
1909   GdkEventFilter *filter;
1910
1911   private = (GdkWindowPrivate*) window;
1912
1913   if(private)
1914     tmp_list = private->filters;
1915   else
1916     tmp_list = gdk_default_filters;
1917
1918   while (tmp_list)
1919     {
1920       filter = (GdkEventFilter *)tmp_list->data;
1921       tmp_list = tmp_list->next;
1922
1923       if ((filter->function == function) && (filter->data == data))
1924         {
1925           if(private)
1926             private->filters = g_list_remove_link (private->filters, tmp_list);
1927           else
1928             gdk_default_filters = g_list_remove_link (gdk_default_filters, tmp_list);
1929           g_list_free_1 (tmp_list);
1930           g_free (filter);
1931           
1932           return;
1933         }
1934     }
1935 }
1936
1937 void
1938 gdk_window_set_override_redirect(GdkWindow *window,
1939                                  gboolean override_redirect)
1940 {
1941   GdkWindowPrivate *private;
1942   XSetWindowAttributes attr;
1943
1944   g_return_if_fail (window != NULL);
1945   private = (GdkWindowPrivate*) window;
1946   if (private->destroyed)
1947     return;
1948
1949   attr.override_redirect = (override_redirect == FALSE)?False:True;
1950   XChangeWindowAttributes(gdk_display,
1951                           ((GdkWindowPrivate *)window)->xwindow,
1952                           CWOverrideRedirect,
1953                           &attr);
1954 }
1955
1956 void          
1957 gdk_window_set_icon        (GdkWindow *window, 
1958                             GdkWindow *icon_window,
1959                             GdkPixmap *pixmap,
1960                             GdkBitmap *mask)
1961 {
1962   XWMHints wm_hints;
1963   GdkWindowPrivate *window_private;
1964   GdkWindowPrivate *private;
1965
1966   g_return_if_fail (window != NULL);
1967   window_private = (GdkWindowPrivate*) window;
1968   if (window_private->destroyed)
1969     return;
1970
1971   wm_hints.flags = 0;
1972   
1973   if (icon_window != NULL)
1974     {
1975       private = (GdkWindowPrivate *)icon_window;
1976       wm_hints.flags |= IconWindowHint;
1977       wm_hints.icon_window = private->xwindow;
1978     }
1979
1980   if (pixmap != NULL)
1981     {
1982       private = (GdkWindowPrivate *)pixmap;
1983       wm_hints.flags |= IconPixmapHint;
1984       wm_hints.icon_pixmap = private->xwindow;
1985     }
1986
1987   if (mask != NULL)
1988     {
1989       private = (GdkWindowPrivate *)mask;
1990       wm_hints.flags |= IconMaskHint;
1991       wm_hints.icon_mask = private->xwindow;
1992     }
1993
1994   XSetWMHints (window_private->xdisplay, window_private->xwindow, &wm_hints);
1995 }
1996
1997 void          
1998 gdk_window_set_icon_name   (GdkWindow *window, 
1999                             gchar *    name)
2000 {
2001   GdkWindowPrivate *window_private;
2002   XTextProperty property;
2003   gint res;
2004
2005   g_return_if_fail (window != NULL);
2006   window_private = (GdkWindowPrivate*) window;
2007   if (window_private->destroyed)
2008     return;
2009   res = XmbTextListToTextProperty (window_private->xdisplay,
2010                                    &name, 1, XStdICCTextStyle,
2011                                    &property);
2012   if (res < 0)
2013     {
2014       g_warning("Error converting icon name to text property: %d\n", res);
2015       return;
2016     }
2017
2018   XSetWMIconName (window_private->xdisplay, window_private->xwindow,
2019                   &property);
2020
2021   if (property.value)
2022     XFree (property.value);
2023 }
2024
2025 void          
2026 gdk_window_set_group   (GdkWindow *window, 
2027                         GdkWindow *leader)
2028 {
2029   XWMHints wm_hints;
2030   GdkWindowPrivate *window_private;
2031   GdkWindowPrivate *private;
2032
2033   g_return_if_fail (window != NULL);
2034   g_return_if_fail (leader != NULL);
2035   window_private = (GdkWindowPrivate*) window;
2036   if (window_private->destroyed)
2037     return;
2038
2039   private = (GdkWindowPrivate *)leader;
2040   wm_hints.flags = WindowGroupHint;
2041   wm_hints.window_group = private->xwindow;
2042
2043   XSetWMHints (window_private->xdisplay, window_private->xwindow, &wm_hints);
2044 }
2045
2046 static void
2047 gdk_window_set_mwm_hints (GdkWindow *window,
2048                           MotifWmHints *new_hints)
2049 {
2050   static Atom hints_atom = None;
2051   MotifWmHints *hints;
2052   Atom type;
2053   gint format;
2054   gulong nitems;
2055   gulong bytes_after;
2056
2057   GdkWindowPrivate *window_private;
2058
2059   g_return_if_fail (window != NULL);
2060   window_private = (GdkWindowPrivate*) window;
2061   if (window_private->destroyed)
2062     return;
2063
2064   if (!hints_atom)
2065     hints_atom = XInternAtom (window_private->xdisplay, 
2066                               _XA_MOTIF_WM_HINTS, FALSE);
2067   
2068   XGetWindowProperty (window_private->xdisplay, window_private->xwindow,
2069                       hints_atom, 0, sizeof(MotifWmHints)/4,
2070                       False, AnyPropertyType, &type, &format, &nitems,
2071                       &bytes_after, (guchar **)&hints);
2072
2073   if (type == None)
2074     hints = new_hints;
2075   else
2076     {
2077       if (new_hints->flags & MWM_HINTS_FUNCTIONS)
2078         {
2079           hints->flags |= MWM_HINTS_FUNCTIONS;
2080           hints->functions = new_hints->functions;
2081         }
2082       if (new_hints->flags & MWM_HINTS_DECORATIONS)
2083         {
2084           hints->flags |= MWM_HINTS_DECORATIONS;
2085           hints->decorations = new_hints->decorations;
2086         }
2087     }
2088
2089   XChangeProperty (window_private->xdisplay, window_private->xwindow,
2090                    hints_atom, hints_atom, 32, PropModeReplace,
2091                    (guchar *)hints, sizeof(MotifWmHints)/4);
2092
2093   if (hints != new_hints)
2094     XFree (hints);
2095 }
2096
2097 void
2098 gdk_window_set_decorations (GdkWindow      *window,
2099                             GdkWMDecoration decorations)
2100 {
2101   MotifWmHints hints;
2102
2103   hints.flags = MWM_HINTS_DECORATIONS;
2104   hints.decorations = decorations;
2105
2106   gdk_window_set_mwm_hints (window, &hints);
2107 }
2108
2109 void
2110 gdk_window_set_functions (GdkWindow    *window,
2111                           GdkWMFunction functions)
2112 {
2113   MotifWmHints hints;
2114
2115   hints.flags = MWM_HINTS_FUNCTIONS;
2116   hints.functions = functions;
2117
2118   gdk_window_set_mwm_hints (window, &hints);
2119 }
2120
2121 GList *
2122 gdk_window_get_toplevels (void)
2123 {
2124   GList *new_list = NULL;
2125   GList *tmp_list;
2126
2127   tmp_list = gdk_root_parent.children;
2128   while (tmp_list)
2129     {
2130       new_list = g_list_prepend (new_list, tmp_list->data);
2131       tmp_list = tmp_list->next;
2132     }
2133
2134   return new_list;
2135 }
2136
2137 void          
2138 gdk_drawable_set_data (GdkDrawable   *drawable,
2139                        const gchar   *key,
2140                        gpointer       data,
2141                        GDestroyNotify destroy_func)
2142 {
2143   g_dataset_set_data_full (drawable, key, data, destroy_func);
2144 }