]> Pileus Git - ~andy/gtk/blob - gdk/gdkwindow.c
Fix up getting colormap for FOREIGN windows to go along with Raster's fix
[~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   /* Huh? ->parent is never set for a pixmap. We should just return
1191    * null immeditately
1192    */
1193   while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
1194     window_private = (GdkWindowPrivate*) window_private->parent;
1195   
1196   if (window_private && !window_private->destroyed)
1197     {
1198        if (window_private->window_type == GDK_WINDOW_FOREIGN)
1199          {
1200             XGetWindowAttributes (window_private->xdisplay,
1201                                   window_private->xwindow,
1202                                   &window_attributes);
1203             return gdk_visual_lookup (window_attributes.visual);
1204          }
1205        else
1206          return ((GdkColormapPrivate *)window_private->colormap)->visual;
1207     }
1208   
1209   return NULL;
1210 }
1211
1212 GdkColormap*
1213 gdk_window_get_colormap (GdkWindow *window)
1214 {
1215   GdkWindowPrivate *window_private;
1216   XWindowAttributes window_attributes;
1217   
1218   g_return_val_if_fail (window != NULL, NULL);
1219   window_private = (GdkWindowPrivate*) window;
1220
1221   g_return_val_if_fail (window_private->window_type != GDK_WINDOW_PIXMAP, NULL);
1222   if (!window_private->destroyed)
1223     {
1224       if (window_private->window_type == GDK_WINDOW_FOREIGN)
1225         {
1226           XGetWindowAttributes (window_private->xdisplay,
1227                                 window_private->xwindow,
1228                                 &window_attributes);
1229           return gdk_colormap_lookup (window_attributes.colormap);
1230          }
1231        else
1232          return window_private->colormap;
1233     }
1234   
1235   return NULL;
1236 }
1237
1238 GdkWindowType
1239 gdk_window_get_type (GdkWindow *window)
1240 {
1241   GdkWindowPrivate *window_private;
1242
1243   g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
1244
1245   window_private = (GdkWindowPrivate*) window;
1246   return window_private->window_type;
1247 }
1248
1249 gint
1250 gdk_window_get_origin (GdkWindow *window,
1251                        gint      *x,
1252                        gint      *y)
1253 {
1254   GdkWindowPrivate *private;
1255   gint return_val;
1256   Window child;
1257   gint tx, ty;
1258
1259   g_return_val_if_fail (window != NULL, 0);
1260
1261   private = (GdkWindowPrivate*) window;
1262
1263   if (!private->destroyed)
1264     {
1265       return_val = XTranslateCoordinates (private->xdisplay,
1266                                           private->xwindow,
1267                                           gdk_root_window,
1268                                           0, 0, &tx, &ty,
1269                                           &child);
1270       
1271       if (x)
1272         *x = tx;
1273       if (y)
1274         *y = ty;
1275     }
1276   else
1277     return_val = 0;
1278   
1279   return return_val;
1280 }
1281
1282 GdkWindow*
1283 gdk_window_get_pointer (GdkWindow       *window,
1284                         gint            *x,
1285                         gint            *y,
1286                         GdkModifierType *mask)
1287 {
1288   GdkWindowPrivate *private;
1289   GdkWindow *return_val;
1290   Window root;
1291   Window child;
1292   int rootx, rooty;
1293   int winx, winy;
1294   unsigned int xmask;
1295
1296   if (!window)
1297     window = (GdkWindow*) &gdk_root_parent;
1298
1299   private = (GdkWindowPrivate*) window;
1300
1301   return_val = NULL;
1302   if (!private->destroyed &&
1303       XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
1304                      &rootx, &rooty, &winx, &winy, &xmask))
1305     {
1306       if (x) *x = winx;
1307       if (y) *y = winy;
1308       if (mask) *mask = xmask;
1309       
1310       if (child)
1311         return_val = gdk_window_lookup (child);
1312     }
1313   
1314   return return_val;
1315 }
1316
1317 GdkWindow*
1318 gdk_window_get_parent (GdkWindow *window)
1319 {
1320   g_return_val_if_fail (window != NULL, NULL);
1321
1322   return ((GdkWindowPrivate*) window)->parent;
1323 }
1324
1325 GdkWindow*
1326 gdk_window_get_toplevel (GdkWindow *window)
1327 {
1328   GdkWindowPrivate *private;
1329
1330   g_return_val_if_fail (window != NULL, NULL);
1331
1332   private = (GdkWindowPrivate*) window;
1333
1334   while (private->window_type == GDK_WINDOW_CHILD)
1335     {
1336       window = ((GdkWindowPrivate*) window)->parent;
1337       private = (GdkWindowPrivate*) window;
1338     }
1339
1340   return window;
1341 }
1342
1343 GList*
1344 gdk_window_get_children (GdkWindow *window)
1345 {
1346   GdkWindowPrivate *private;
1347   GdkWindow *child;
1348   GList *children;
1349   Window root;
1350   Window parent;
1351   Window *xchildren;
1352   unsigned int nchildren;
1353   unsigned int i;
1354
1355   g_return_val_if_fail (window != NULL, NULL);
1356
1357   private = (GdkWindowPrivate*) window;
1358   if (private->destroyed)
1359     return NULL;
1360
1361   XQueryTree (private->xdisplay, private->xwindow,
1362               &root, &parent, &xchildren, &nchildren);
1363
1364   children = NULL;
1365
1366   if (nchildren > 0)
1367     {
1368       for (i = 0; i < nchildren; i++)
1369         {
1370           child = gdk_window_lookup (xchildren[i]);
1371           if (child)
1372             children = g_list_prepend (children, child);
1373         }
1374
1375       XFree (xchildren);
1376     }
1377
1378   return children;
1379 }
1380
1381 GdkEventMask  
1382 gdk_window_get_events      (GdkWindow       *window)
1383 {
1384   GdkWindowPrivate *private;
1385   XWindowAttributes attrs;
1386   GdkEventMask event_mask;
1387   int i;
1388
1389   g_return_val_if_fail (window != NULL, 0);
1390
1391   private = (GdkWindowPrivate*) window;
1392   if (private->destroyed)
1393     return 0;
1394
1395   XGetWindowAttributes (gdk_display, private->xwindow, 
1396                         &attrs);
1397
1398   event_mask = 0;
1399   for (i = 0; i < nevent_masks; i++)
1400     {
1401       if (attrs.your_event_mask & event_mask_table[i])
1402         event_mask |= 1 << (i + 1);
1403     }
1404
1405   return event_mask;
1406 }
1407
1408 void          
1409 gdk_window_set_events      (GdkWindow       *window,
1410                             GdkEventMask     event_mask)
1411 {
1412   GdkWindowPrivate *private;
1413   long xevent_mask;
1414   int i;
1415
1416   g_return_if_fail (window != NULL);
1417
1418   private = (GdkWindowPrivate*) window;
1419   if (private->destroyed)
1420     return;
1421
1422   xevent_mask = StructureNotifyMask;
1423   for (i = 0; i < nevent_masks; i++)
1424     {
1425       if (event_mask & (1 << (i + 1)))
1426         xevent_mask |= event_mask_table[i];
1427     }
1428   
1429   XSelectInput (gdk_display, private->xwindow, 
1430                 xevent_mask);
1431 }
1432
1433 void
1434 gdk_window_add_colormap_windows (GdkWindow *window)
1435 {
1436   GdkWindow *toplevel;
1437   GdkWindowPrivate *toplevel_private;
1438   GdkWindowPrivate *window_private;
1439   Window *old_windows;
1440   Window *new_windows;
1441   int i, count;
1442
1443   g_return_if_fail (window != NULL);
1444
1445   toplevel = gdk_window_get_toplevel (window);
1446   toplevel_private = (GdkWindowPrivate*) toplevel;
1447   window_private = (GdkWindowPrivate*) window;
1448   if (window_private->destroyed)
1449     return;
1450
1451   if (!XGetWMColormapWindows (toplevel_private->xdisplay,
1452                               toplevel_private->xwindow,
1453                               &old_windows, &count))
1454     {
1455       old_windows = NULL;
1456       count = 0;
1457     }
1458
1459   for (i = 0; i < count; i++)
1460     if (old_windows[i] == window_private->xwindow)
1461       return;
1462
1463   new_windows = g_new (Window, count + 1);
1464
1465   for (i = 0; i < count; i++)
1466     new_windows[i] = old_windows[i];
1467   new_windows[count] = window_private->xwindow;
1468
1469   XSetWMColormapWindows (toplevel_private->xdisplay,
1470                          toplevel_private->xwindow,
1471                          new_windows, count + 1);
1472
1473   g_free (new_windows);
1474   if (old_windows)
1475     XFree (old_windows);
1476 }
1477
1478 /*
1479  * This needs the X11 shape extension.
1480  * If not available, simply remove the call to
1481  * XShapeCombineMask. Shaped windows will look
1482  * ugly, but programs still work.    Stefan Wille
1483  */
1484 void
1485 gdk_window_shape_combine_mask (GdkWindow *window,
1486                                GdkBitmap *mask,
1487                                gint x, gint y)
1488 {
1489   GdkWindowPrivate *window_private;
1490   Pixmap pixmap;
1491
1492   g_return_if_fail (window != NULL);
1493
1494   /* This is needed, according to raster */
1495   gdk_window_set_override_redirect(window, TRUE);
1496
1497   window_private = (GdkWindowPrivate*) window;
1498   if (window_private->destroyed)
1499     return;
1500
1501   if (mask)
1502     {
1503       GdkWindowPrivate *pixmap_private;
1504
1505       pixmap_private = (GdkWindowPrivate*) mask;
1506       pixmap = (Pixmap) pixmap_private->xwindow;
1507     }
1508   else
1509     {
1510       x = 0;
1511       y = 0;
1512       pixmap = None;
1513     }
1514
1515   XShapeCombineMask  (window_private->xdisplay,
1516                       window_private->xwindow,
1517                       ShapeBounding,
1518                       x, y,
1519                       pixmap,
1520                       ShapeSet);
1521 }
1522
1523 void
1524 gdk_dnd_drag_addwindow (GdkWindow *window)
1525 {
1526   GdkWindowPrivate *window_private;
1527   
1528   g_return_if_fail (window != NULL);
1529   
1530   window_private = (GdkWindowPrivate *) window;
1531   if (window_private->destroyed)
1532     return;
1533   
1534   if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
1535     {
1536       gdk_dnd.drag_numwindows++;
1537       gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
1538                                              gdk_dnd.drag_numwindows
1539                                              * sizeof(GdkWindow *));
1540       gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
1541       window_private->dnd_drag_accepted = 0;
1542     } 
1543   else
1544     g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
1545 }
1546
1547 void
1548 gdk_window_dnd_drag_set (GdkWindow   *window,
1549                          guint8       drag_enable,
1550                          gchar      **typelist,
1551                          guint        numtypes)
1552 {
1553   GdkWindowPrivate *window_private;
1554   int i, wasset = 0;
1555   
1556   g_return_if_fail (window != NULL);
1557   window_private = (GdkWindowPrivate *) window;
1558   if (window_private->destroyed)
1559     return;
1560   
1561   window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
1562   
1563   if (drag_enable)
1564     {
1565       g_return_if_fail(typelist != NULL);
1566       
1567       if (window_private->dnd_drag_data_numtypesavail > 3)
1568         wasset = 1;
1569       window_private->dnd_drag_data_numtypesavail = numtypes;
1570       
1571       window_private->dnd_drag_data_typesavail =
1572         g_realloc (window_private->dnd_drag_data_typesavail,
1573                    (numtypes + 1) * sizeof (GdkAtom));
1574       
1575       for (i = 0; i < numtypes; i++)
1576         {
1577           /* Allow blanket use of ALL to get anything... */
1578           if (strcmp (typelist[i], "ALL"))
1579             window_private->dnd_drag_data_typesavail[i] =
1580               gdk_atom_intern (typelist[i], FALSE);
1581           else
1582             window_private->dnd_drag_data_typesavail[i] = None;
1583         }
1584       
1585       /* 
1586        * set our extended type list if we need to 
1587        */
1588       if (numtypes > 3)
1589         gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
1590                             XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
1591                             (guchar *)(window_private->dnd_drag_data_typesavail
1592                              + (sizeof(GdkAtom) * 3)),
1593                             (numtypes - 3) * sizeof(GdkAtom));
1594       else if (wasset)
1595         gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
1596     }
1597   else
1598     {
1599       g_free (window_private->dnd_drag_data_typesavail);
1600       window_private->dnd_drag_data_typesavail = NULL;
1601       window_private->dnd_drag_data_numtypesavail = 0;
1602     }
1603 }
1604
1605 void
1606 gdk_window_dnd_drop_set (GdkWindow   *window,
1607                          guint8       drop_enable,
1608                          gchar      **typelist,
1609                          guint        numtypes,
1610                          guint8       destructive_op)
1611 {
1612   GdkWindowPrivate *window_private;
1613   int i;
1614   
1615   g_return_if_fail (window != NULL);
1616   window_private = (GdkWindowPrivate *) window;
1617   if (window_private->destroyed)
1618     return;
1619   
1620   window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
1621   if (drop_enable)
1622     {
1623       g_return_if_fail(typelist != NULL);
1624       
1625       window_private->dnd_drop_data_numtypesavail = numtypes;
1626       
1627       window_private->dnd_drop_data_typesavail =
1628         g_realloc (window_private->dnd_drop_data_typesavail,
1629                    (numtypes + 1) * sizeof (GdkAtom));
1630       
1631       for (i = 0; i < numtypes; i++)
1632         window_private->dnd_drop_data_typesavail[i] =
1633           gdk_atom_intern (typelist[i], FALSE);
1634       
1635       window_private->dnd_drop_destructive_op = destructive_op;
1636     }
1637 }
1638
1639 /* 
1640  * This is used to reply to a GDK_DRAG_REQUEST event
1641  * (which may be generated by XdeRequest or a confirmed drop... 
1642  */
1643 void
1644 gdk_window_dnd_data_set (GdkWindow       *window,
1645                          GdkEvent        *event,
1646                          gpointer         data,
1647                          gulong           data_numbytes)
1648 {
1649   GdkWindowPrivate *window_private;
1650   XEvent sev;
1651   GdkEventDropDataAvailable tmp_ev;
1652   gchar *tmp;
1653   
1654   g_return_if_fail (window != NULL);
1655   g_return_if_fail (event != NULL);
1656   g_return_if_fail (data != NULL);
1657   g_return_if_fail (data_numbytes > 0);
1658   g_return_if_fail (event->type == GDK_DRAG_REQUEST);
1659
1660   window_private = (GdkWindowPrivate *) window;
1661   g_return_if_fail (window_private->dnd_drag_accepted != 0);    
1662   if (window_private->destroyed)
1663     return;
1664   
1665   /* We set the property on our window... */
1666   gdk_property_change (window, window_private->dnd_drag_data_type,
1667                        XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
1668                        data_numbytes);
1669   tmp = gdk_atom_name(window_private->dnd_drag_data_type);
1670 #ifdef DEBUG_DND
1671   g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow);
1672 #endif
1673   g_free(tmp);
1674   
1675   /* 
1676    * Then we send the event to tell the receiving window that the
1677    * drop has happened 
1678    */
1679   tmp_ev.u.allflags = 0;
1680   tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
1681   tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
1682   
1683   sev.xclient.type = ClientMessage;
1684   sev.xclient.format = 32;
1685   sev.xclient.window = event->dragrequest.requestor;
1686   sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
1687   sev.xclient.data.l[0] = window_private->xwindow;
1688   sev.xclient.data.l[1] = tmp_ev.u.allflags;
1689   sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
1690
1691   if (event->dragrequest.isdrop)
1692     sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
1693       (event->dragrequest.drop_coords.y << 16);
1694   else
1695     sev.xclient.data.l[3] = 0;
1696
1697   sev.xclient.data.l[4] = event->dragrequest.timestamp;
1698
1699   if (!gdk_send_xevent (event->dragrequest.requestor, False,
1700                        StructureNotifyMask, &sev))
1701     GDK_NOTE (DND, g_print("Sending XdeDataAvailable to %#x failed\n",
1702                            event->dragrequest.requestor));
1703
1704 }
1705
1706 void          
1707 gdk_window_add_filter     (GdkWindow     *window,
1708                            GdkFilterFunc  function,
1709                            gpointer       data)
1710 {
1711   GdkWindowPrivate *private;
1712   GList *tmp_list;
1713   GdkEventFilter *filter;
1714
1715   private = (GdkWindowPrivate*) window;
1716   if (private && private->destroyed)
1717     return;
1718
1719   if(private)
1720     tmp_list = private->filters;
1721   else
1722     tmp_list = gdk_default_filters;
1723
1724   while (tmp_list)
1725     {
1726       filter = (GdkEventFilter *)tmp_list->data;
1727       if ((filter->function == function) && (filter->data == data))
1728         return;
1729       tmp_list = tmp_list->next;
1730     }
1731
1732   filter = g_new (GdkEventFilter, 1);
1733   filter->function = function;
1734   filter->data = data;
1735
1736   if(private)
1737     private->filters = g_list_append (private->filters, filter);
1738   else
1739     gdk_default_filters = g_list_append (gdk_default_filters, filter);
1740 }
1741
1742 void
1743 gdk_window_remove_filter  (GdkWindow     *window,
1744                            GdkFilterFunc  function,
1745                            gpointer       data)
1746 {
1747   GdkWindowPrivate *private;
1748   GList *tmp_list;
1749   GdkEventFilter *filter;
1750
1751   private = (GdkWindowPrivate*) window;
1752
1753   if(private)
1754     tmp_list = private->filters;
1755   else
1756     tmp_list = gdk_default_filters;
1757
1758   while (tmp_list)
1759     {
1760       filter = (GdkEventFilter *)tmp_list->data;
1761       tmp_list = tmp_list->next;
1762
1763       if ((filter->function == function) && (filter->data == data))
1764         {
1765           if(private)
1766             private->filters = g_list_remove_link (private->filters, tmp_list);
1767           else
1768             gdk_default_filters = g_list_remove_link (gdk_default_filters, tmp_list);
1769           g_list_free_1 (tmp_list);
1770           g_free (filter);
1771           
1772           return;
1773         }
1774     }
1775 }
1776
1777 void
1778 gdk_window_set_override_redirect(GdkWindow *window,
1779                                  gboolean override_redirect)
1780 {
1781   GdkWindowPrivate *private;
1782   XSetWindowAttributes attr;
1783
1784   g_return_if_fail (window != NULL);
1785   private = (GdkWindowPrivate*) window;
1786   if (private->destroyed)
1787     return;
1788
1789   attr.override_redirect = (override_redirect == FALSE)?False:True;
1790   XChangeWindowAttributes(gdk_display,
1791                           ((GdkWindowPrivate *)window)->xwindow,
1792                           CWOverrideRedirect,
1793                           &attr);
1794 }
1795
1796 void          
1797 gdk_window_set_icon        (GdkWindow *window, 
1798                             GdkWindow *icon_window,
1799                             GdkPixmap *pixmap,
1800                             GdkBitmap *mask)
1801 {
1802   XWMHints wm_hints;
1803   GdkWindowPrivate *window_private;
1804   GdkWindowPrivate *private;
1805
1806   g_return_if_fail (window != NULL);
1807   window_private = (GdkWindowPrivate*) window;
1808   if (window_private->destroyed)
1809     return;
1810
1811   wm_hints.flags = 0;
1812   
1813   if (icon_window != NULL)
1814     {
1815       private = (GdkWindowPrivate *)icon_window;
1816       wm_hints.flags |= IconWindowHint;
1817       wm_hints.icon_window = private->xwindow;
1818     }
1819
1820   if (pixmap != NULL)
1821     {
1822       private = (GdkWindowPrivate *)pixmap;
1823       wm_hints.flags |= IconPixmapHint;
1824       wm_hints.icon_pixmap = private->xwindow;
1825     }
1826
1827   if (mask != NULL)
1828     {
1829       private = (GdkWindowPrivate *)mask;
1830       wm_hints.flags |= IconMaskHint;
1831       wm_hints.icon_mask = private->xwindow;
1832     }
1833
1834   XSetWMHints (window_private->xdisplay, window_private->xwindow, &wm_hints);
1835 }
1836
1837 void          
1838 gdk_window_set_icon_name   (GdkWindow *window, 
1839                             gchar *    name)
1840 {
1841   GdkWindowPrivate *window_private;
1842   XTextProperty property;
1843   gint res;
1844
1845   g_return_if_fail (window != NULL);
1846   window_private = (GdkWindowPrivate*) window;
1847   if (window_private->destroyed)
1848     return;
1849   res = XmbTextListToTextProperty (window_private->xdisplay,
1850                                    &name, 1, XStdICCTextStyle,
1851                                    &property);
1852   if (res < 0)
1853     {
1854       g_warning("Error converting icon name to text property: %d\n", res);
1855       return;
1856     }
1857
1858   XSetWMIconName (window_private->xdisplay, window_private->xwindow,
1859                   &property);
1860
1861   XFree(property.value);
1862 }
1863
1864 void          
1865 gdk_window_set_group   (GdkWindow *window, 
1866                         GdkWindow *leader)
1867 {
1868   XWMHints wm_hints;
1869   GdkWindowPrivate *window_private;
1870   GdkWindowPrivate *private;
1871
1872   g_return_if_fail (window != NULL);
1873   g_return_if_fail (leader != NULL);
1874   window_private = (GdkWindowPrivate*) window;
1875   if (window_private->destroyed)
1876     return;
1877
1878   private = (GdkWindowPrivate *)leader;
1879   wm_hints.flags = WindowGroupHint;
1880   wm_hints.window_group = private->xwindow;
1881
1882   XSetWMHints (window_private->xdisplay, window_private->xwindow, &wm_hints);
1883 }
1884
1885 static void
1886 gdk_window_set_mwm_hints (GdkWindow *window,
1887                           MotifWmHints *new_hints)
1888 {
1889   static Atom hints_atom = None;
1890   MotifWmHints *hints;
1891   Atom type;
1892   gint format;
1893   gulong nitems;
1894   gulong bytes_after;
1895
1896   GdkWindowPrivate *window_private;
1897
1898   g_return_if_fail (window != NULL);
1899   window_private = (GdkWindowPrivate*) window;
1900   if (window_private->destroyed)
1901     return;
1902
1903   if (!hints_atom)
1904     hints_atom = XInternAtom (window_private->xdisplay, 
1905                               _XA_MOTIF_WM_HINTS, FALSE);
1906   
1907   XGetWindowProperty (window_private->xdisplay, window_private->xwindow,
1908                       hints_atom, 0, sizeof(MotifWmHints)/4,
1909                       False, AnyPropertyType, &type, &format, &nitems,
1910                       &bytes_after, (guchar **)&hints);
1911
1912   if (type == None)
1913     hints = new_hints;
1914   else
1915     {
1916       if (new_hints->flags & MWM_HINTS_FUNCTIONS)
1917         {
1918           hints->flags |= MWM_HINTS_FUNCTIONS;
1919           hints->functions = new_hints->functions;
1920         }
1921       if (new_hints->flags & MWM_HINTS_DECORATIONS)
1922         {
1923           hints->flags |= MWM_HINTS_DECORATIONS;
1924           hints->decorations = new_hints->decorations;
1925         }
1926     }
1927
1928   XChangeProperty (window_private->xdisplay, window_private->xwindow,
1929                    hints_atom, hints_atom, 32, PropModeReplace,
1930                    (guchar *)hints, sizeof(MotifWmHints)/4);
1931
1932   if (hints != new_hints)
1933     XFree (hints);
1934 }
1935
1936 void
1937 gdk_window_set_decorations (GdkWindow      *window,
1938                             GdkWMDecoration decorations)
1939 {
1940   MotifWmHints hints;
1941
1942   hints.flags = MWM_HINTS_DECORATIONS;
1943   hints.decorations = decorations;
1944
1945   gdk_window_set_mwm_hints (window, &hints);
1946 }
1947
1948 void
1949 gdk_window_set_functions (GdkWindow    *window,
1950                           GdkWMFunction functions)
1951 {
1952   MotifWmHints hints;
1953
1954   hints.flags = MWM_HINTS_FUNCTIONS;
1955   hints.functions = functions;
1956
1957   gdk_window_set_mwm_hints (window, &hints);
1958 }