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