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