]> Pileus Git - ~andy/gtk/blob - gdk/gdkwindow.c
GDK_VISIBILITY_NOTIFY events were not working at all. It was my
[~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 <stdlib.h>
28 #include <stdio.h>
29
30 int nevent_masks = 17;
31 int event_mask_table[19] =
32 {
33   ExposureMask,
34   PointerMotionMask,
35   PointerMotionHintMask,
36   ButtonMotionMask,
37   Button1MotionMask,
38   Button2MotionMask,
39   Button3MotionMask,
40   ButtonPressMask | OwnerGrabButtonMask,
41   ButtonReleaseMask | OwnerGrabButtonMask,
42   KeyPressMask,
43   KeyReleaseMask,
44   EnterWindowMask,
45   LeaveWindowMask,
46   FocusChangeMask,
47   StructureNotifyMask,
48   PropertyChangeMask,
49   VisibilityChangeMask,
50   0,                            /* PROXIMITY_IN */
51   0                             /* PROXIMTY_OUT */
52 };
53
54
55 void
56 gdk_window_init ()
57 {
58   XWindowAttributes xattributes;
59   unsigned int width;
60   unsigned int height;
61   unsigned int border_width;
62   unsigned int depth;
63   int x, y;
64
65   XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window,
66                 &x, &y, &width, &height, &border_width, &depth);
67   XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes);
68
69   gdk_root_parent.xdisplay = gdk_display;
70   gdk_root_parent.xwindow = gdk_root_window;
71   gdk_root_parent.window_type = GDK_WINDOW_ROOT;
72   gdk_root_parent.window.user_data = NULL;
73 }
74
75 GdkWindow*
76 gdk_window_new (GdkWindow     *parent,
77                 GdkWindowAttr *attributes,
78                 gint           attributes_mask)
79 {
80   GdkWindow *window;
81   GdkWindowPrivate *private;
82   GdkWindowPrivate *parent_private;
83   GdkVisual *visual;
84   GdkColormap *colormap;
85   Display *parent_display;
86   Window xparent;
87   Visual *xvisual;
88   XSetWindowAttributes xattributes;
89   long xattributes_mask;
90   XSizeHints size_hints;
91   XWMHints wm_hints;
92   XClassHint *class_hint;
93   int x, y, depth;
94   unsigned int class;
95   char *title;
96   int i;
97
98   g_return_val_if_fail (attributes != NULL, NULL);
99
100   if (!parent)
101     parent = (GdkWindow*) &gdk_root_parent;
102
103   parent_private = (GdkWindowPrivate*) parent;
104   xparent = parent_private->xwindow;
105   parent_display = parent_private->xdisplay;
106
107   private = g_new (GdkWindowPrivate, 1);
108   window = (GdkWindow*) private;
109
110   private->parent = parent;
111   private->xdisplay = parent_display;
112   private->destroyed = FALSE;
113   private->resize_count = 0;
114   private->ref_count = 1;
115   xattributes_mask = 0;
116
117   if (attributes_mask & GDK_WA_X)
118     x = attributes->x;
119   else
120     x = 0;
121
122   if (attributes_mask & GDK_WA_Y)
123     y = attributes->y;
124   else
125     y = 0;
126
127   private->x = x;
128   private->y = y;
129   private->width = (attributes->width > 1) ? (attributes->width) : (1);
130   private->height = (attributes->height > 1) ? (attributes->height) : (1);
131   private->window_type = attributes->window_type;
132   private->extension_events = FALSE;
133   private->dnd_drag_data_type = None;
134   private->dnd_drag_data_typesavail =
135     private->dnd_drop_data_typesavail = NULL;
136   private->dnd_drop_enabled = private->dnd_drag_enabled =
137     private->dnd_drag_accepted = private->dnd_drag_datashow =
138     private->dnd_drop_data_numtypesavail =
139     private->dnd_drag_data_numtypesavail = 0;
140   private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
141
142   private->filters = NULL;
143
144   window->user_data = NULL;
145
146   if (attributes_mask & GDK_WA_VISUAL)
147     visual = attributes->visual;
148   else
149     visual = gdk_visual_get_system ();
150   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
151
152   xattributes.event_mask = StructureNotifyMask;
153   for (i = 0; i < nevent_masks; i++)
154     {
155       if (attributes->event_mask & (1 << (i + 1)))
156         xattributes.event_mask |= event_mask_table[i];
157     }
158
159   if (xattributes.event_mask)
160     xattributes_mask |= CWEventMask;
161
162   if(attributes_mask & GDK_WA_NOREDIR) {
163         xattributes.override_redirect =
164                 (attributes->override_redirect == FALSE)?False:True;
165         xattributes_mask |= CWOverrideRedirect;
166   } else
167     xattributes.override_redirect = False;
168
169   if (attributes->wclass == GDK_INPUT_OUTPUT)
170     {
171       class = InputOutput;
172       depth = visual->depth;
173
174       if (attributes_mask & GDK_WA_COLORMAP)
175         colormap = attributes->colormap;
176       else
177         colormap = gdk_colormap_get_system ();
178
179       xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen);
180       xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
181       xattributes_mask |= CWBorderPixel | CWBackPixel;
182
183       switch (private->window_type)
184         {
185         case GDK_WINDOW_TOPLEVEL:
186           xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
187           xattributes_mask |= CWColormap;
188
189           xparent = gdk_root_window;
190           break;
191
192         case GDK_WINDOW_CHILD:
193           xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
194           xattributes_mask |= CWColormap;
195           break;
196
197         case GDK_WINDOW_DIALOG:
198           xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
199           xattributes_mask |= CWColormap;
200
201           xparent = gdk_root_window;
202           break;
203
204         case GDK_WINDOW_TEMP:
205           xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
206           xattributes_mask |= CWColormap;
207
208           xparent = gdk_root_window;
209
210           xattributes.save_under = True;
211           xattributes.override_redirect = True;
212           xattributes.cursor = None;
213           xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
214           break;
215         case GDK_WINDOW_ROOT:
216           g_error ("cannot make windows of type GDK_WINDOW_ROOT");
217           break;
218         case GDK_WINDOW_PIXMAP:
219           g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
220           break;
221         }
222     }
223   else
224     {
225       depth = 1;
226       class = InputOnly;
227       colormap = NULL;
228     }
229
230   private->xwindow = XCreateWindow (private->xdisplay, xparent,
231                                     x, y, private->width, private->height,
232                                     0, depth, class, xvisual,
233                                     xattributes_mask, &xattributes);
234   gdk_window_ref (window);
235   gdk_xid_table_insert (&private->xwindow, window);
236
237   switch (private->window_type)
238     {
239     case GDK_WINDOW_DIALOG:
240       XSetTransientForHint (private->xdisplay, private->xwindow, xparent);
241     case GDK_WINDOW_TOPLEVEL:
242     case GDK_WINDOW_TEMP:
243       XSetWMProtocols (private->xdisplay, private->xwindow, gdk_wm_window_protocols, 2);
244       break;
245     case GDK_WINDOW_CHILD:
246       if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
247           (colormap != gdk_colormap_get_system ()) &&
248           (colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
249         {
250           g_print ("adding colormap window\n");
251           gdk_window_add_colormap_windows (window);
252         }
253       break;
254     default:
255       break;
256     }
257
258   size_hints.flags = PSize | PBaseSize;
259   size_hints.width = private->width;
260   size_hints.height = private->height;
261   size_hints.base_width = private->width;
262   size_hints.base_height = private->height;
263
264   wm_hints.flags = InputHint | StateHint | WindowGroupHint;
265   wm_hints.window_group = gdk_leader_window;
266   wm_hints.input = True;
267   wm_hints.initial_state = NormalState;
268
269   XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
270   XSetWMHints (private->xdisplay, private->xwindow, &wm_hints);
271
272   if (attributes_mask & GDK_WA_TITLE)
273     title = attributes->title;
274   else
275     title = gdk_progname;
276
277   XmbSetWMProperties (private->xdisplay, private->xwindow,
278                       title, title,
279                       NULL, 0,
280                       NULL, NULL, NULL);
281
282   if (attributes_mask & GDK_WA_WMCLASS)
283     {
284       class_hint = XAllocClassHint ();
285       class_hint->res_name = attributes->wmclass_name;
286       class_hint->res_class = attributes->wmclass_class;
287       XSetClassHint (private->xdisplay, private->xwindow, class_hint);
288       XFree (class_hint);
289     }
290
291   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
292                                   (attributes->cursor) :
293                                   NULL));
294
295   return window;
296 }
297
298 GdkWindow *
299 gdk_window_foreign_new (guint32 anid)
300 {
301   GdkWindow *window;
302   GdkWindowPrivate *private;
303   XWindowAttributes attrs;
304
305   private = g_new (GdkWindowPrivate, 1);
306   window = (GdkWindow*) private;
307
308   XGetWindowAttributes (gdk_display, anid, &attrs);
309
310   private->parent = NULL;
311   private->xwindow = anid;
312   private->xdisplay = gdk_display;
313   private->x = attrs.x;
314   private->y = attrs.y;
315   private->width = attrs.width;
316   private->height = attrs.height;
317   private->resize_count = 0;
318   private->ref_count = 1;
319   if (anid == attrs.root)
320     private->window_type = GDK_WINDOW_ROOT;
321   else
322     private->window_type = GDK_WINDOW_TOPLEVEL;
323   /* the above is probably wrong, but it may not be worth the extra
324      X call to get it right */
325     
326   private->destroyed = FALSE;
327   private->extension_events = 0;
328   private->filters = NULL;
329
330   window->user_data = NULL;
331
332   gdk_window_ref (window);
333   gdk_xid_table_insert (&private->xwindow, window);
334
335   return window;
336 }
337
338 /* Call this function when you want a window and all its children to
339    disappear.  When xdestroy is true, a request to destroy the XWindow
340    is sent out.  When it is false, it is assumed that the XWindow has
341    been or will be destroyed by destroying some ancestor of this
342    window.  */
343
344 static void
345 gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
346 {
347   GdkWindowPrivate *private;
348   GdkWindowPrivate *temp_private;
349   GdkWindow *temp_window;
350   GList *children;
351   GList *tmp;
352
353   g_return_if_fail (window != NULL);
354
355   private = (GdkWindowPrivate*) window;
356
357   switch (private->window_type)
358     {
359     case GDK_WINDOW_TOPLEVEL:
360     case GDK_WINDOW_CHILD:
361     case GDK_WINDOW_DIALOG:
362     case GDK_WINDOW_TEMP:
363       if (!private->destroyed)
364         {
365           children = gdk_window_get_children (window);
366           tmp = children;
367
368           while (tmp)
369             {
370               temp_window = tmp->data;
371               tmp = tmp->next;
372
373               temp_private = (GdkWindowPrivate*) temp_window;
374               if (temp_private)
375                 gdk_window_internal_destroy (temp_window, FALSE);
376             }
377
378           g_list_free (children);
379
380           if(private->dnd_drag_data_numtypesavail > 0) 
381             {
382               g_free (private->dnd_drag_data_typesavail);
383               private->dnd_drag_data_typesavail = NULL;
384             }
385           if(private->dnd_drop_data_numtypesavail > 0) 
386             {
387               g_free (private->dnd_drop_data_typesavail);
388               private->dnd_drop_data_typesavail = NULL;
389             }
390
391           if (xdestroy)
392             XDestroyWindow (private->xdisplay, private->xwindow);
393           private->destroyed = TRUE;
394         }
395       break;
396
397     case GDK_WINDOW_ROOT:
398       g_error ("attempted to destroy root window");
399       break;
400
401     case GDK_WINDOW_PIXMAP:
402       g_error ("called gdk_window_destroy on a pixmap (use gdk_pixmap_unref)");
403       break;
404     }
405 }
406
407 /* Like internal_destroy, but also destroys the reference created by
408    gdk_window_new. */
409
410 void
411 gdk_window_destroy (GdkWindow *window)
412 {
413   gdk_window_internal_destroy (window, TRUE);
414   gdk_window_unref (window);
415 }
416
417 /* This function is called when the XWindow is really gone.  */
418
419 void
420 gdk_window_destroy_notify (GdkWindow *window)
421 {
422   GdkWindowPrivate *private;
423
424   g_return_if_fail (window != NULL);
425
426   private = (GdkWindowPrivate*) window;
427
428   if (private->extension_events != 0)
429     gdk_input_window_destroy (window);
430
431   gdk_xid_table_remove (private->xwindow);
432   gdk_window_unref (window);
433 }
434
435 GdkWindow*
436 gdk_window_ref (GdkWindow *window)
437 {
438   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
439   g_return_val_if_fail (window != NULL, NULL);
440
441   private->ref_count += 1;
442   return window;
443 }
444
445 void
446 gdk_window_unref (GdkWindow *window)
447 {
448   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
449   g_return_if_fail (window != NULL);
450
451   private->ref_count -= 1;
452   if (private->ref_count == 0)
453     {
454       if (!private->destroyed)
455         g_warning ("losing last reference to undestroyed window\n");
456       g_free (window);
457     }
458 }
459
460 void
461 gdk_window_show (GdkWindow *window)
462 {
463   GdkWindowPrivate *private;
464
465   g_return_if_fail (window != NULL);
466
467   private = (GdkWindowPrivate*) window;
468   if (!private->destroyed)
469     {
470       XRaiseWindow (private->xdisplay, private->xwindow);
471       XMapWindow (private->xdisplay, private->xwindow);
472     }
473 }
474
475 void
476 gdk_window_hide (GdkWindow *window)
477 {
478   GdkWindowPrivate *private;
479
480   g_return_if_fail (window != NULL);
481
482   private = (GdkWindowPrivate*) window;
483   if (!private->destroyed)
484     XUnmapWindow (private->xdisplay, private->xwindow);
485 }
486
487 void
488 gdk_window_withdraw (GdkWindow *window)
489 {
490   GdkWindowPrivate *private;
491
492   g_return_if_fail (window != NULL);
493
494   private = (GdkWindowPrivate*) window;
495   if (!private->destroyed)
496     XWithdrawWindow (private->xdisplay, private->xwindow, 0);
497 }
498
499 void
500 gdk_window_move (GdkWindow *window,
501                  gint       x,
502                  gint       y)
503 {
504   GdkWindowPrivate *private;
505
506   g_return_if_fail (window != NULL);
507
508   private = (GdkWindowPrivate*) window;
509   XMoveWindow (private->xdisplay, private->xwindow, x, y);
510
511   if (private->window_type == GDK_WINDOW_CHILD)
512     {
513       private->x = x;
514       private->y = y;
515     }
516 }
517
518 void
519 gdk_window_resize (GdkWindow *window,
520                    gint       width,
521                    gint       height)
522 {
523   GdkWindowPrivate *private;
524
525   g_return_if_fail (window != NULL);
526
527   if (width < 1)
528     width = 1;
529   if (height < 1)
530     height = 1;
531
532   private = (GdkWindowPrivate*) window;
533
534   if (!private->destroyed &&
535       ((private->resize_count > 0) ||
536        (private->width != (guint16) width) ||
537        (private->height != (guint16) height)))
538     {
539       XResizeWindow (private->xdisplay, private->xwindow, width, height);
540       private->resize_count += 1;
541
542       if (private->window_type == GDK_WINDOW_CHILD)
543         {
544           private->width = width;
545           private->height = height;
546         }
547     }
548 }
549
550 void
551 gdk_window_move_resize (GdkWindow *window,
552                         gint       x,
553                         gint       y,
554                         gint       width,
555                         gint       height)
556 {
557   GdkWindowPrivate *private;
558
559   g_return_if_fail (window != NULL);
560
561   if (width < 1)
562     width = 1;
563   if (height < 1)
564     height = 1;
565
566   private = (GdkWindowPrivate*) window;
567   XMoveResizeWindow (private->xdisplay, private->xwindow, x, y, width, height);
568
569   if (!private->destroyed &&
570       (private->window_type == GDK_WINDOW_CHILD))
571     {
572       private->x = x;
573       private->y = y;
574       private->width = width;
575       private->height = height;
576     }
577 }
578
579 void
580 gdk_window_reparent (GdkWindow *window,
581                      GdkWindow *new_parent,
582                      gint       x,
583                      gint       y)
584 {
585   GdkWindowPrivate *window_private;
586   GdkWindowPrivate *parent_private;
587
588   g_return_if_fail (window != NULL);
589
590   if (!new_parent)
591     new_parent = (GdkWindow*) &gdk_root_parent;
592
593   window_private = (GdkWindowPrivate*) window;
594   parent_private = (GdkWindowPrivate*) new_parent;
595
596   XReparentWindow (window_private->xdisplay,
597                    window_private->xwindow,
598                    parent_private->xwindow,
599                    x, y);
600 }
601
602 void
603 gdk_window_clear (GdkWindow *window)
604 {
605   GdkWindowPrivate *private;
606
607   g_return_if_fail (window != NULL);
608
609   private = (GdkWindowPrivate*) window;
610
611   XClearWindow (private->xdisplay, private->xwindow);
612 }
613
614 void
615 gdk_window_clear_area (GdkWindow *window,
616                        gint       x,
617                        gint       y,
618                        gint       width,
619                        gint       height)
620 {
621   GdkWindowPrivate *private;
622
623   g_return_if_fail (window != NULL);
624
625   private = (GdkWindowPrivate*) window;
626
627   if (!private->destroyed)
628     XClearArea (private->xdisplay, private->xwindow,
629                 x, y, width, height, False);
630 }
631
632 void
633 gdk_window_clear_area_e (GdkWindow *window,
634                          gint       x,
635                          gint       y,
636                          gint       width,
637                          gint       height)
638 {
639   GdkWindowPrivate *private;
640
641   g_return_if_fail (window != NULL);
642
643   private = (GdkWindowPrivate*) window;
644
645   if (!private->destroyed)
646     XClearArea (private->xdisplay, private->xwindow,
647                 x, y, width, height, True);
648 }
649
650 void
651 gdk_window_copy_area (GdkWindow    *window,
652                       GdkGC        *gc,
653                       gint          x,
654                       gint          y,
655                       GdkWindow    *source_window,
656                       gint          source_x,
657                       gint          source_y,
658                       gint          width,
659                       gint          height)
660 {
661   GdkWindowPrivate *src_private;
662   GdkWindowPrivate *dest_private;
663   GdkGCPrivate *gc_private;
664
665   g_return_if_fail (window != NULL);
666   g_return_if_fail (gc != NULL);
667   
668   if (source_window == NULL)
669     source_window = window;
670
671   src_private = (GdkWindowPrivate*) source_window;
672   dest_private = (GdkWindowPrivate*) window;
673   gc_private = (GdkGCPrivate*) gc;
674   
675   if (!src_private->destroyed && !dest_private->destroyed)
676   {
677     XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow,
678                gc_private->xgc,
679                source_x, source_y,
680                width, height,
681                x, y);
682   }
683 }
684
685 void
686 gdk_window_raise (GdkWindow *window)
687 {
688   GdkWindowPrivate *private;
689
690   g_return_if_fail (window != NULL);
691
692   private = (GdkWindowPrivate*) window;
693
694   if (!private->destroyed)
695     XRaiseWindow (private->xdisplay, private->xwindow);
696 }
697
698 void
699 gdk_window_lower (GdkWindow *window)
700 {
701   GdkWindowPrivate *private;
702
703   g_return_if_fail (window != NULL);
704
705   private = (GdkWindowPrivate*) window;
706
707   if (!private->destroyed)
708     XLowerWindow (private->xdisplay, private->xwindow);
709 }
710
711 void
712 gdk_window_set_user_data (GdkWindow *window,
713                           gpointer   user_data)
714 {
715   g_return_if_fail (window != NULL);
716
717   window->user_data = user_data;
718 }
719
720 void
721 gdk_window_set_hints (GdkWindow *window,
722                       gint       x,
723                       gint       y,
724                       gint       min_width,
725                       gint       min_height,
726                       gint       max_width,
727                       gint       max_height,
728                       gint       flags)
729 {
730   GdkWindowPrivate *private;
731   XSizeHints size_hints;
732
733   g_return_if_fail (window != NULL);
734
735   private = (GdkWindowPrivate*) window;
736   size_hints.flags = 0;
737
738   if (flags & GDK_HINT_POS)
739     {
740       size_hints.flags |= PPosition;
741       size_hints.x = x;
742       size_hints.y = y;
743     }
744
745   if (flags & GDK_HINT_MIN_SIZE)
746     {
747       size_hints.flags |= PMinSize;
748       size_hints.min_width = min_width;
749       size_hints.min_height = min_height;
750     }
751
752   if (flags & GDK_HINT_MAX_SIZE)
753     {
754       size_hints.flags |= PMaxSize;
755       size_hints.max_width = max_width;
756       size_hints.max_height = max_height;
757     }
758
759   if (flags)
760     XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
761 }
762
763 void
764 gdk_window_set_title (GdkWindow   *window,
765                       const gchar *title)
766 {
767   GdkWindowPrivate *private;
768
769   g_return_if_fail (window != NULL);
770
771   private = (GdkWindowPrivate*) window;
772   XmbSetWMProperties (private->xdisplay, private->xwindow,
773                       title, title, NULL, 0, NULL, NULL, NULL);
774 }
775
776 void
777 gdk_window_set_background (GdkWindow *window,
778                            GdkColor  *color)
779 {
780   GdkWindowPrivate *private;
781
782   g_return_if_fail (window != NULL);
783
784   private = (GdkWindowPrivate*) window;
785   XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel);
786 }
787
788 void
789 gdk_window_set_back_pixmap (GdkWindow *window,
790                             GdkPixmap *pixmap,
791                             gint       parent_relative)
792 {
793   GdkWindowPrivate *window_private;
794   GdkPixmapPrivate *pixmap_private;
795   Pixmap xpixmap;
796
797   g_return_if_fail (window != NULL);
798
799   window_private = (GdkWindowPrivate*) window;
800   pixmap_private = (GdkPixmapPrivate*) pixmap;
801
802   if (pixmap)
803     xpixmap = pixmap_private->xwindow;
804   else
805     xpixmap = None;
806
807   if (parent_relative)
808     xpixmap = ParentRelative;
809
810   XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap);
811 }
812
813 void
814 gdk_window_set_cursor (GdkWindow *window,
815                        GdkCursor *cursor)
816 {
817   GdkWindowPrivate *window_private;
818   GdkCursorPrivate *cursor_private;
819   Cursor xcursor;
820
821   g_return_if_fail (window != NULL);
822
823   window_private = (GdkWindowPrivate*) window;
824   cursor_private = (GdkCursorPrivate*) cursor;
825
826   if (!cursor)
827     xcursor = None;
828   else
829     xcursor = cursor_private->xcursor;
830
831   XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor);
832 }
833
834 void
835 gdk_window_set_colormap (GdkWindow   *window,
836                          GdkColormap *colormap)
837 {
838   GdkWindowPrivate *window_private;
839   GdkColormapPrivate *colormap_private;
840
841   g_return_if_fail (window != NULL);
842   g_return_if_fail (colormap != NULL);
843
844   window_private = (GdkWindowPrivate*) window;
845   colormap_private = (GdkColormapPrivate*) colormap;
846
847   XSetWindowColormap (window_private->xdisplay,
848                       window_private->xwindow,
849                       colormap_private->xcolormap);
850
851   if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
852     gdk_window_add_colormap_windows (window);
853 }
854
855 void
856 gdk_window_get_user_data (GdkWindow *window,
857                           gpointer  *data)
858 {
859   g_return_if_fail (window != NULL);
860
861   *data = window->user_data;
862 }
863
864 void
865 gdk_window_get_geometry (GdkWindow *window,
866                          gint      *x,
867                          gint      *y,
868                          gint      *width,
869                          gint      *height,
870                          gint      *depth)
871 {
872   GdkWindowPrivate *window_private;
873   Window root;
874   gint tx;
875   gint ty;
876   guint twidth;
877   guint theight;
878   guint tborder_width;
879   guint tdepth;
880
881   if (!window)
882     window = (GdkWindow*) &gdk_root_parent;
883
884   window_private = (GdkWindowPrivate*) window;
885
886   XGetGeometry (window_private->xdisplay, window_private->xwindow,
887                 &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
888
889   if (x)
890     *x = tx;
891   if (y)
892     *y = ty;
893   if (width)
894     *width = twidth;
895   if (height)
896     *height = theight;
897   if (depth)
898     *depth = tdepth;
899 }
900
901 void
902 gdk_window_get_position (GdkWindow *window,
903                          gint      *x,
904                          gint      *y)
905 {
906   GdkWindowPrivate *window_private;
907
908   g_return_if_fail (window != NULL);
909
910   window_private = (GdkWindowPrivate*) window;
911
912   if (x)
913     *x = window_private->x;
914   if (y)
915     *y = window_private->y;
916 }
917
918 void
919 gdk_window_get_size (GdkWindow *window,
920                      gint       *width,
921                      gint       *height)
922 {
923   GdkWindowPrivate *window_private;
924
925   g_return_if_fail (window != NULL);
926
927   window_private = (GdkWindowPrivate*) window;
928
929   if (width)
930     *width = window_private->width;
931   if (height)
932     *height = window_private->height;
933 }
934
935
936 GdkVisual*
937 gdk_window_get_visual (GdkWindow *window)
938 {
939   GdkWindowPrivate *window_private;
940   XWindowAttributes window_attributes;
941
942   g_return_val_if_fail (window != NULL, NULL);
943
944   window_private = (GdkWindowPrivate*) window;
945   while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
946     window_private = (GdkWindowPrivate*) window_private->parent;
947
948   if (window_private)
949     {
950       XGetWindowAttributes (window_private->xdisplay,
951                             window_private->xwindow,
952                             &window_attributes);
953
954       return gdk_visual_lookup (window_attributes.visual);
955     }
956
957   return NULL;
958 }
959
960 GdkColormap*
961 gdk_window_get_colormap (GdkWindow *window)
962 {
963   GdkWindowPrivate *window_private;
964   XWindowAttributes window_attributes;
965
966   g_return_val_if_fail (window != NULL, NULL);
967
968   window_private = (GdkWindowPrivate*) window;
969
970   XGetWindowAttributes (window_private->xdisplay,
971                         window_private->xwindow,
972                         &window_attributes);
973
974   return gdk_colormap_lookup (window_attributes.colormap);
975 }
976
977 GdkWindowType
978 gdk_window_get_type (GdkWindow *window)
979 {
980   GdkWindowPrivate *window_private;
981
982   g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
983
984   window_private = (GdkWindowPrivate*) window;
985   return window_private->window_type;
986 }
987
988 gint
989 gdk_window_get_origin (GdkWindow *window,
990                        gint      *x,
991                        gint      *y)
992 {
993   GdkWindowPrivate *private;
994   gint return_val;
995   Window child;
996   gint tx, ty;
997
998   g_return_val_if_fail (window != NULL, 0);
999
1000   private = (GdkWindowPrivate*) window;
1001
1002   return_val = XTranslateCoordinates (private->xdisplay,
1003                                       private->xwindow,
1004                                       gdk_root_window,
1005                                       0, 0, &tx, &ty,
1006                                       &child);
1007
1008   if (x)
1009     *x = tx;
1010   if (y)
1011     *y = ty;
1012
1013   return return_val;
1014 }
1015
1016 GdkWindow*
1017 gdk_window_get_pointer (GdkWindow       *window,
1018                         gint            *x,
1019                         gint            *y,
1020                         GdkModifierType *mask)
1021 {
1022   GdkWindowPrivate *private;
1023   GdkWindow *return_val;
1024   Window root;
1025   Window child;
1026   int rootx, rooty;
1027   int winx, winy;
1028   unsigned int xmask;
1029
1030   if (!window)
1031     window = (GdkWindow*) &gdk_root_parent;
1032
1033   private = (GdkWindowPrivate*) window;
1034
1035   return_val = NULL;
1036   if (XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
1037                      &rootx, &rooty, &winx, &winy, &xmask))
1038     {
1039       if (x) *x = winx;
1040       if (y) *y = winy;
1041       if (mask) *mask = xmask;
1042
1043       if (child)
1044         return_val = gdk_window_lookup (child);
1045     }
1046
1047   return return_val;
1048 }
1049
1050 GdkWindow*
1051 gdk_window_get_parent (GdkWindow *window)
1052 {
1053   g_return_val_if_fail (window != NULL, NULL);
1054
1055   return ((GdkWindowPrivate*) window)->parent;
1056 }
1057
1058 GdkWindow*
1059 gdk_window_get_toplevel (GdkWindow *window)
1060 {
1061   GdkWindowPrivate *private;
1062
1063   g_return_val_if_fail (window != NULL, NULL);
1064
1065   private = (GdkWindowPrivate*) window;
1066
1067   while (private->window_type == GDK_WINDOW_CHILD)
1068     {
1069       window = ((GdkWindowPrivate*) window)->parent;
1070       private = (GdkWindowPrivate*) window;
1071     }
1072
1073   return window;
1074 }
1075
1076 GList*
1077 gdk_window_get_children (GdkWindow *window)
1078 {
1079   GdkWindowPrivate *private;
1080   GdkWindow *child;
1081   GList *children;
1082   Window root;
1083   Window parent;
1084   Window *xchildren;
1085   unsigned int nchildren;
1086   unsigned int i;
1087
1088   g_return_val_if_fail (window != NULL, NULL);
1089
1090   private = (GdkWindowPrivate*) window;
1091
1092   XQueryTree (private->xdisplay, private->xwindow,
1093               &root, &parent, &xchildren, &nchildren);
1094
1095   children = NULL;
1096
1097   if (nchildren > 0)
1098     {
1099       for (i = 0; i < nchildren; i++)
1100         {
1101           child = gdk_window_lookup (xchildren[i]);
1102           if (child)
1103             children = g_list_prepend (children, child);
1104         }
1105
1106       XFree (xchildren);
1107     }
1108
1109   return children;
1110 }
1111
1112 GdkEventMask  
1113 gdk_window_get_events      (GdkWindow       *window)
1114 {
1115   XWindowAttributes attrs;
1116   GdkEventMask event_mask;
1117   int i;
1118
1119   XGetWindowAttributes (gdk_display, ((GdkWindowPrivate *)window)->xwindow, 
1120                         &attrs);
1121
1122   event_mask = 0;
1123   for (i = 0; i < nevent_masks; i++)
1124     {
1125       if (attrs.your_event_mask & event_mask_table[i])
1126         event_mask |= 1 << (i + 1);
1127     }
1128
1129   return event_mask;
1130 }
1131
1132 void          
1133 gdk_window_set_events      (GdkWindow       *window,
1134                             GdkEventMask     event_mask)
1135 {
1136   long xevent_mask;
1137   int i;
1138
1139   xevent_mask = StructureNotifyMask;
1140   for (i = 0; i < nevent_masks; i++)
1141     {
1142       if (event_mask & (1 << (i + 1)))
1143         xevent_mask |= event_mask_table[i];
1144     }
1145   
1146   XSelectInput (gdk_display, ((GdkWindowPrivate *)window)->xwindow, 
1147                 xevent_mask);
1148 }
1149
1150 void
1151 gdk_window_add_colormap_windows (GdkWindow *window)
1152 {
1153   GdkWindow *toplevel;
1154   GdkWindowPrivate *toplevel_private;
1155   GdkWindowPrivate *window_private;
1156   Window *old_windows;
1157   Window *new_windows;
1158   int i, count;
1159
1160   g_return_if_fail (window != NULL);
1161
1162   toplevel = gdk_window_get_toplevel (window);
1163   toplevel_private = (GdkWindowPrivate*) toplevel;
1164   window_private = (GdkWindowPrivate*) window;
1165
1166   if (!XGetWMColormapWindows (toplevel_private->xdisplay,
1167                               toplevel_private->xwindow,
1168                               &old_windows, &count))
1169     {
1170       old_windows = NULL;
1171       count = 0;
1172     }
1173
1174   for (i = 0; i < count; i++)
1175     if (old_windows[i] == window_private->xwindow)
1176       return;
1177
1178   new_windows = g_new (Window, count + 1);
1179
1180   for (i = 0; i < count; i++)
1181     new_windows[i] = old_windows[i];
1182   new_windows[count] = window_private->xwindow;
1183
1184   XSetWMColormapWindows (toplevel_private->xdisplay,
1185                          toplevel_private->xwindow,
1186                          new_windows, count + 1);
1187
1188   g_free (new_windows);
1189   if (old_windows)
1190     XFree (old_windows);
1191 }
1192
1193 /*
1194  * This needs the X11 shape extension.
1195  * If not available, simply remove the call to
1196  * XShapeCombineMask. Shaped windows will look
1197  * ugly, but programs still work.    Stefan Wille
1198  */
1199 void
1200 gdk_window_shape_combine_mask (GdkWindow *window,
1201                                GdkBitmap *mask,
1202                                gint x, gint y)
1203 {
1204   GdkWindowPrivate *window_private;
1205   GdkWindowPrivate *pixmap_private;
1206
1207   g_return_if_fail (window != NULL);
1208   g_return_if_fail (mask != NULL);
1209
1210   window_private = (GdkWindowPrivate*) window;
1211   pixmap_private = (GdkWindowPrivate*) mask;
1212         
1213   XShapeCombineMask  (window_private->xdisplay,
1214                       window_private->xwindow,
1215                       ShapeBounding,
1216                       x, y, /* offset */
1217                       (Pixmap)pixmap_private->xwindow,
1218                       ShapeSet);
1219 }
1220
1221 void
1222 gdk_dnd_drag_addwindow (GdkWindow *window)
1223 {
1224   GdkWindowPrivate *window_private;
1225   
1226   g_return_if_fail (window != NULL);
1227   
1228   window_private = (GdkWindowPrivate *) window;
1229   
1230   if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
1231     {
1232       gdk_dnd.drag_numwindows++;
1233       gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
1234                                              gdk_dnd.drag_numwindows
1235                                              * sizeof(GdkWindow *));
1236       gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
1237       window_private->dnd_drag_accepted = 0;
1238     } 
1239   else
1240     g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
1241 }
1242
1243 void
1244 gdk_window_dnd_drag_set (GdkWindow   *window,
1245                          guint8       drag_enable,
1246                          gchar      **typelist,
1247                          guint        numtypes)
1248 {
1249   GdkWindowPrivate *window_private;
1250   int i, wasset = 0;
1251   
1252   g_return_if_fail (window != NULL);
1253   window_private = (GdkWindowPrivate *) window;
1254   
1255   window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
1256   
1257   if (drag_enable)
1258     {
1259       g_return_if_fail(typelist != NULL);
1260       
1261       if (window_private->dnd_drag_data_numtypesavail > 3)
1262         wasset = 1;
1263       window_private->dnd_drag_data_numtypesavail = numtypes;
1264       
1265       window_private->dnd_drag_data_typesavail =
1266         g_realloc (window_private->dnd_drag_data_typesavail,
1267                    (numtypes + 1) * sizeof (GdkAtom));
1268       
1269       for (i = 0; i < numtypes; i++)
1270         {
1271           /* Allow blanket use of ALL to get anything... */
1272           if (strcmp (typelist[i], "ALL"))
1273             window_private->dnd_drag_data_typesavail[i] =
1274               gdk_atom_intern (typelist[i], FALSE);
1275           else
1276             window_private->dnd_drag_data_typesavail[i] = None;
1277         }
1278       
1279       /* 
1280        * set our extended type list if we need to 
1281        */
1282       if (numtypes > 3)
1283         gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
1284                             XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
1285                             (guchar *)(window_private->dnd_drag_data_typesavail
1286                              + (sizeof(GdkAtom) * 3)),
1287                             (numtypes - 3) * sizeof(GdkAtom));
1288       else if (wasset)
1289         gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
1290     }
1291   else
1292     {
1293       free (window_private->dnd_drag_data_typesavail);
1294       window_private->dnd_drag_data_typesavail = NULL;
1295       window_private->dnd_drag_data_numtypesavail = 0;
1296     }
1297 }
1298
1299 void
1300 gdk_window_dnd_drop_set (GdkWindow   *window,
1301                          guint8       drop_enable,
1302                          gchar      **typelist,
1303                          guint        numtypes,
1304                          guint8       destructive_op)
1305 {
1306   GdkWindowPrivate *window_private;
1307   int i;
1308   
1309   g_return_if_fail (window != NULL);
1310   
1311   window_private = (GdkWindowPrivate *) window;
1312   
1313   window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
1314   if (drop_enable)
1315     {
1316       g_return_if_fail(typelist != NULL);
1317       
1318       window_private->dnd_drop_data_numtypesavail = numtypes;
1319       
1320       window_private->dnd_drop_data_typesavail =
1321         g_realloc (window_private->dnd_drop_data_typesavail,
1322                    (numtypes + 1) * sizeof (GdkAtom));
1323       
1324       for (i = 0; i < numtypes; i++)
1325         window_private->dnd_drop_data_typesavail[i] =
1326           gdk_atom_intern (typelist[i], FALSE);
1327       
1328       window_private->dnd_drop_destructive_op = destructive_op;
1329     }
1330 }
1331
1332 /* 
1333  * This is used to reply to a GDK_DRAG_REQUEST event
1334  * (which may be generated by XdeRequest or a confirmed drop... 
1335  */
1336 void
1337 gdk_window_dnd_data_set (GdkWindow       *window,
1338                          GdkEvent        *event,
1339                          gpointer         data,
1340                          gulong           data_numbytes)
1341 {
1342   GdkWindowPrivate *window_private;
1343   XEvent sev;
1344   GdkEventDropDataAvailable tmp_ev;
1345   gchar *tmp;
1346   
1347   g_return_if_fail (window != NULL);
1348   g_return_if_fail (event != NULL);
1349   g_return_if_fail (data != NULL);
1350   g_return_if_fail (data_numbytes > 0);
1351   g_return_if_fail (event->type == GDK_DRAG_REQUEST);
1352
1353   g_free (event->dragrequest.data_type);
1354   event->dragrequest.data_type = NULL;
1355   
1356   window_private = (GdkWindowPrivate *) window;
1357   g_return_if_fail (window_private->dnd_drag_accepted != 0);    
1358   
1359   /* We set the property on our window... */
1360   gdk_property_change (window, window_private->dnd_drag_data_type,
1361                        XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
1362                        data_numbytes);
1363   tmp = gdk_atom_name(window_private->dnd_drag_data_type);
1364 #ifdef DEBUG_DND
1365   g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow);
1366 #endif
1367   g_free(tmp);
1368   
1369   /* 
1370    * Then we send the event to tell the receiving window that the
1371    * drop has happened 
1372    */
1373   tmp_ev.u.allflags = 0;
1374   tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
1375   tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
1376   
1377   sev.xclient.type = ClientMessage;
1378   sev.xclient.format = 32;
1379   sev.xclient.window = event->dragrequest.requestor;
1380   sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
1381   sev.xclient.data.l[0] = window_private->xwindow;
1382   sev.xclient.data.l[1] = tmp_ev.u.allflags;
1383   sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
1384
1385   if (event->dragrequest.isdrop)
1386     sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
1387       (event->dragrequest.drop_coords.y << 16);
1388   else
1389     sev.xclient.data.l[3] = 0;
1390   
1391   sev.xclient.data.l[4] = 0;
1392   
1393   XSendEvent (gdk_display, event->dragrequest.requestor, False,
1394               NoEventMask, &sev);
1395 }
1396
1397 void          
1398 gdk_window_add_filter     (GdkWindow     *window,
1399                            GdkFilterFunc  function,
1400                            gpointer       data)
1401 {
1402   GdkWindowPrivate *private;
1403   GList *tmp_list;
1404   GdkEventFilter *filter;
1405
1406   private = (GdkWindowPrivate *)window;
1407
1408   tmp_list = private->filters;
1409   while (tmp_list)
1410     {
1411       filter = (GdkEventFilter *)tmp_list->data;
1412       if ((filter->function == function) && (filter->data == data))
1413         return;
1414       tmp_list = tmp_list->next;
1415     }
1416
1417   filter = g_new (GdkEventFilter, 1);
1418   filter->function = function;
1419   filter->data = data;
1420   
1421   private->filters = g_list_append (private->filters, filter);
1422 }
1423
1424 void
1425 gdk_window_remove_filter  (GdkWindow     *window,
1426                            GdkFilterFunc  function,
1427                            gpointer       data)
1428 {
1429   GdkWindowPrivate *private;
1430   GList *tmp_list;
1431   GdkEventFilter *filter;
1432
1433   private = (GdkWindowPrivate *)window;
1434
1435   tmp_list = private->filters;
1436   while (tmp_list)
1437     {
1438       filter = (GdkEventFilter *)tmp_list->data;
1439       tmp_list = tmp_list->next;
1440
1441       if ((filter->function == function) && (filter->data == data))
1442         {
1443           private->filters = g_list_remove_link (private->filters, tmp_list);
1444           g_list_free_1 (tmp_list);
1445           
1446           return;
1447         }
1448     }
1449 }
1450
1451 void
1452 gdk_window_set_override_redirect(GdkWindow *window,
1453                                  gboolean override_redirect)
1454 {
1455   XSetWindowAttributes attr;
1456   attr.override_redirect = (override_redirect == FALSE)?False:True;
1457   XChangeWindowAttributes(gdk_display,
1458                           ((GdkWindowPrivate *)window)->xwindow,
1459                           CWOverrideRedirect,
1460                           &attr);
1461 }