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