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