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