]> Pileus Git - ~andy/gtk/blob - gdk/gdkwindow.c
129fea3b7c24e361937153ca657c19ee354d1bdf
[~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->extension_events != 0)
386             gdk_input_window_destroy (window);
387
388           if(private->dnd_drag_data_numtypesavail > 0) 
389             {
390               g_free (private->dnd_drag_data_typesavail);
391               private->dnd_drag_data_typesavail = NULL;
392             }
393           if(private->dnd_drop_data_numtypesavail > 0) 
394             {
395               g_free (private->dnd_drop_data_typesavail);
396               private->dnd_drop_data_typesavail = NULL;
397             }
398
399           if (xdestroy)
400             XDestroyWindow (private->xdisplay, private->xwindow);
401           private->destroyed = TRUE;
402         }
403       break;
404
405     case GDK_WINDOW_ROOT:
406       g_error ("attempted to destroy root window");
407       break;
408
409     case GDK_WINDOW_PIXMAP:
410       g_error ("called gdk_window_destroy on a pixmap (use gdk_pixmap_unref)");
411       break;
412     }
413 }
414
415 /* Like internal_destroy, but also destroys the reference created by
416    gdk_window_new. */
417
418 void
419 gdk_window_destroy (GdkWindow *window)
420 {
421   gdk_window_internal_destroy (window, TRUE);
422   gdk_window_unref (window);
423 }
424
425 /* This function is called when the XWindow is really gone.  */
426
427 void
428 gdk_window_destroy_notify (GdkWindow *window)
429 {
430   GdkWindowPrivate *private;
431
432   g_return_if_fail (window != NULL);
433
434   private = (GdkWindowPrivate*) 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 GdkVisual*
961 gdk_window_get_visual (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   while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
970     window_private = (GdkWindowPrivate*) window_private->parent;
971
972   if (window_private && !window_private->destroyed)
973     {
974       XGetWindowAttributes (window_private->xdisplay,
975                             window_private->xwindow,
976                             &window_attributes);
977
978       return gdk_visual_lookup (window_attributes.visual);
979     }
980
981   return NULL;
982 }
983
984 GdkColormap*
985 gdk_window_get_colormap (GdkWindow *window)
986 {
987   GdkWindowPrivate *window_private;
988   XWindowAttributes window_attributes;
989
990   g_return_val_if_fail (window != NULL, NULL);
991
992   window_private = (GdkWindowPrivate*) window;
993
994   if (!window_private->destroyed)
995     {
996       XGetWindowAttributes (window_private->xdisplay,
997                             window_private->xwindow,
998                             &window_attributes);
999       
1000       return gdk_colormap_lookup (window_attributes.colormap);
1001     }
1002
1003   return NULL;
1004 }
1005
1006 GdkWindowType
1007 gdk_window_get_type (GdkWindow *window)
1008 {
1009   GdkWindowPrivate *window_private;
1010
1011   g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
1012
1013   window_private = (GdkWindowPrivate*) window;
1014   return window_private->window_type;
1015 }
1016
1017 gint
1018 gdk_window_get_origin (GdkWindow *window,
1019                        gint      *x,
1020                        gint      *y)
1021 {
1022   GdkWindowPrivate *private;
1023   gint return_val;
1024   Window child;
1025   gint tx, ty;
1026
1027   g_return_val_if_fail (window != NULL, 0);
1028
1029   private = (GdkWindowPrivate*) window;
1030
1031   if (!private->destroyed)
1032     {
1033       return_val = XTranslateCoordinates (private->xdisplay,
1034                                           private->xwindow,
1035                                           gdk_root_window,
1036                                           0, 0, &tx, &ty,
1037                                           &child);
1038       
1039       if (x)
1040         *x = tx;
1041       if (y)
1042         *y = ty;
1043     }
1044   else
1045     return_val = 0;
1046   
1047   return return_val;
1048 }
1049
1050 GdkWindow*
1051 gdk_window_get_pointer (GdkWindow       *window,
1052                         gint            *x,
1053                         gint            *y,
1054                         GdkModifierType *mask)
1055 {
1056   GdkWindowPrivate *private;
1057   GdkWindow *return_val;
1058   Window root;
1059   Window child;
1060   int rootx, rooty;
1061   int winx, winy;
1062   unsigned int xmask;
1063
1064   if (!window)
1065     window = (GdkWindow*) &gdk_root_parent;
1066
1067   private = (GdkWindowPrivate*) window;
1068
1069   return_val = NULL;
1070   if (!private->destroyed &&
1071       XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
1072                      &rootx, &rooty, &winx, &winy, &xmask))
1073     {
1074       if (x) *x = winx;
1075       if (y) *y = winy;
1076       if (mask) *mask = xmask;
1077       
1078       if (child)
1079         return_val = gdk_window_lookup (child);
1080     }
1081   
1082   return return_val;
1083 }
1084
1085 GdkWindow*
1086 gdk_window_get_parent (GdkWindow *window)
1087 {
1088   g_return_val_if_fail (window != NULL, NULL);
1089
1090   return ((GdkWindowPrivate*) window)->parent;
1091 }
1092
1093 GdkWindow*
1094 gdk_window_get_toplevel (GdkWindow *window)
1095 {
1096   GdkWindowPrivate *private;
1097
1098   g_return_val_if_fail (window != NULL, NULL);
1099
1100   private = (GdkWindowPrivate*) window;
1101
1102   while (private->window_type == GDK_WINDOW_CHILD)
1103     {
1104       window = ((GdkWindowPrivate*) window)->parent;
1105       private = (GdkWindowPrivate*) window;
1106     }
1107
1108   return window;
1109 }
1110
1111 GList*
1112 gdk_window_get_children (GdkWindow *window)
1113 {
1114   GdkWindowPrivate *private;
1115   GdkWindow *child;
1116   GList *children;
1117   Window root;
1118   Window parent;
1119   Window *xchildren;
1120   unsigned int nchildren;
1121   unsigned int i;
1122
1123   g_return_val_if_fail (window != NULL, NULL);
1124
1125   private = (GdkWindowPrivate*) window;
1126   if (private->destroyed)
1127     return NULL;
1128
1129   XQueryTree (private->xdisplay, private->xwindow,
1130               &root, &parent, &xchildren, &nchildren);
1131
1132   children = NULL;
1133
1134   if (nchildren > 0)
1135     {
1136       for (i = 0; i < nchildren; i++)
1137         {
1138           child = gdk_window_lookup (xchildren[i]);
1139           if (child)
1140             children = g_list_prepend (children, child);
1141         }
1142
1143       XFree (xchildren);
1144     }
1145
1146   return children;
1147 }
1148
1149 GdkEventMask  
1150 gdk_window_get_events      (GdkWindow       *window)
1151 {
1152   GdkWindowPrivate *private;
1153   XWindowAttributes attrs;
1154   GdkEventMask event_mask;
1155   int i;
1156
1157   g_return_val_if_fail (window != NULL, 0);
1158
1159   private = (GdkWindowPrivate*) window;
1160   if (private->destroyed)
1161     return 0;
1162
1163   XGetWindowAttributes (gdk_display, private->xwindow, 
1164                         &attrs);
1165
1166   event_mask = 0;
1167   for (i = 0; i < nevent_masks; i++)
1168     {
1169       if (attrs.your_event_mask & event_mask_table[i])
1170         event_mask |= 1 << (i + 1);
1171     }
1172
1173   return event_mask;
1174 }
1175
1176 void          
1177 gdk_window_set_events      (GdkWindow       *window,
1178                             GdkEventMask     event_mask)
1179 {
1180   GdkWindowPrivate *private;
1181   long xevent_mask;
1182   int i;
1183
1184   g_return_if_fail (window != NULL);
1185
1186   private = (GdkWindowPrivate*) window;
1187   if (private->destroyed)
1188     return;
1189
1190   xevent_mask = StructureNotifyMask;
1191   for (i = 0; i < nevent_masks; i++)
1192     {
1193       if (event_mask & (1 << (i + 1)))
1194         xevent_mask |= event_mask_table[i];
1195     }
1196   
1197   XSelectInput (gdk_display, private->xwindow, 
1198                 xevent_mask);
1199 }
1200
1201 void
1202 gdk_window_add_colormap_windows (GdkWindow *window)
1203 {
1204   GdkWindow *toplevel;
1205   GdkWindowPrivate *toplevel_private;
1206   GdkWindowPrivate *window_private;
1207   Window *old_windows;
1208   Window *new_windows;
1209   int i, count;
1210
1211   g_return_if_fail (window != NULL);
1212
1213   toplevel = gdk_window_get_toplevel (window);
1214   toplevel_private = (GdkWindowPrivate*) toplevel;
1215   window_private = (GdkWindowPrivate*) window;
1216   if (window_private->destroyed)
1217     return;
1218
1219   if (!XGetWMColormapWindows (toplevel_private->xdisplay,
1220                               toplevel_private->xwindow,
1221                               &old_windows, &count))
1222     {
1223       old_windows = NULL;
1224       count = 0;
1225     }
1226
1227   for (i = 0; i < count; i++)
1228     if (old_windows[i] == window_private->xwindow)
1229       return;
1230
1231   new_windows = g_new (Window, count + 1);
1232
1233   for (i = 0; i < count; i++)
1234     new_windows[i] = old_windows[i];
1235   new_windows[count] = window_private->xwindow;
1236
1237   XSetWMColormapWindows (toplevel_private->xdisplay,
1238                          toplevel_private->xwindow,
1239                          new_windows, count + 1);
1240
1241   g_free (new_windows);
1242   if (old_windows)
1243     XFree (old_windows);
1244 }
1245
1246 /*
1247  * This needs the X11 shape extension.
1248  * If not available, simply remove the call to
1249  * XShapeCombineMask. Shaped windows will look
1250  * ugly, but programs still work.    Stefan Wille
1251  */
1252 void
1253 gdk_window_shape_combine_mask (GdkWindow *window,
1254                                GdkBitmap *mask,
1255                                gint x, gint y)
1256 {
1257   GdkWindowPrivate *window_private;
1258   GdkWindowPrivate *pixmap_private;
1259
1260   g_return_if_fail (window != NULL);
1261   g_return_if_fail (mask != NULL);
1262
1263   window_private = (GdkWindowPrivate*) window;
1264   pixmap_private = (GdkWindowPrivate*) mask;
1265   if (window_private->destroyed)
1266     return;
1267         
1268   XShapeCombineMask  (window_private->xdisplay,
1269                       window_private->xwindow,
1270                       ShapeBounding,
1271                       x, y, /* offset */
1272                       (Pixmap)pixmap_private->xwindow,
1273                       ShapeSet);
1274 }
1275
1276 void
1277 gdk_dnd_drag_addwindow (GdkWindow *window)
1278 {
1279   GdkWindowPrivate *window_private;
1280   
1281   g_return_if_fail (window != NULL);
1282   
1283   window_private = (GdkWindowPrivate *) window;
1284   if (window_private->destroyed)
1285     return;
1286   
1287   if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
1288     {
1289       gdk_dnd.drag_numwindows++;
1290       gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
1291                                              gdk_dnd.drag_numwindows
1292                                              * sizeof(GdkWindow *));
1293       gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
1294       window_private->dnd_drag_accepted = 0;
1295     } 
1296   else
1297     g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
1298 }
1299
1300 void
1301 gdk_window_dnd_drag_set (GdkWindow   *window,
1302                          guint8       drag_enable,
1303                          gchar      **typelist,
1304                          guint        numtypes)
1305 {
1306   GdkWindowPrivate *window_private;
1307   int i, wasset = 0;
1308   
1309   g_return_if_fail (window != NULL);
1310   window_private = (GdkWindowPrivate *) window;
1311   if (window_private->destroyed)
1312     return;
1313   
1314   window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
1315   
1316   if (drag_enable)
1317     {
1318       g_return_if_fail(typelist != NULL);
1319       
1320       if (window_private->dnd_drag_data_numtypesavail > 3)
1321         wasset = 1;
1322       window_private->dnd_drag_data_numtypesavail = numtypes;
1323       
1324       window_private->dnd_drag_data_typesavail =
1325         g_realloc (window_private->dnd_drag_data_typesavail,
1326                    (numtypes + 1) * sizeof (GdkAtom));
1327       
1328       for (i = 0; i < numtypes; i++)
1329         {
1330           /* Allow blanket use of ALL to get anything... */
1331           if (strcmp (typelist[i], "ALL"))
1332             window_private->dnd_drag_data_typesavail[i] =
1333               gdk_atom_intern (typelist[i], FALSE);
1334           else
1335             window_private->dnd_drag_data_typesavail[i] = None;
1336         }
1337       
1338       /* 
1339        * set our extended type list if we need to 
1340        */
1341       if (numtypes > 3)
1342         gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
1343                             XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
1344                             (guchar *)(window_private->dnd_drag_data_typesavail
1345                              + (sizeof(GdkAtom) * 3)),
1346                             (numtypes - 3) * sizeof(GdkAtom));
1347       else if (wasset)
1348         gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
1349     }
1350   else
1351     {
1352       g_free (window_private->dnd_drag_data_typesavail);
1353       window_private->dnd_drag_data_typesavail = NULL;
1354       window_private->dnd_drag_data_numtypesavail = 0;
1355     }
1356 }
1357
1358 void
1359 gdk_window_dnd_drop_set (GdkWindow   *window,
1360                          guint8       drop_enable,
1361                          gchar      **typelist,
1362                          guint        numtypes,
1363                          guint8       destructive_op)
1364 {
1365   GdkWindowPrivate *window_private;
1366   int i;
1367   
1368   g_return_if_fail (window != NULL);
1369   window_private = (GdkWindowPrivate *) window;
1370   if (window_private->destroyed)
1371     return;
1372   
1373   window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
1374   if (drop_enable)
1375     {
1376       g_return_if_fail(typelist != NULL);
1377       
1378       window_private->dnd_drop_data_numtypesavail = numtypes;
1379       
1380       window_private->dnd_drop_data_typesavail =
1381         g_realloc (window_private->dnd_drop_data_typesavail,
1382                    (numtypes + 1) * sizeof (GdkAtom));
1383       
1384       for (i = 0; i < numtypes; i++)
1385         window_private->dnd_drop_data_typesavail[i] =
1386           gdk_atom_intern (typelist[i], FALSE);
1387       
1388       window_private->dnd_drop_destructive_op = destructive_op;
1389     }
1390 }
1391
1392 /* 
1393  * This is used to reply to a GDK_DRAG_REQUEST event
1394  * (which may be generated by XdeRequest or a confirmed drop... 
1395  */
1396 void
1397 gdk_window_dnd_data_set (GdkWindow       *window,
1398                          GdkEvent        *event,
1399                          gpointer         data,
1400                          gulong           data_numbytes)
1401 {
1402   GdkWindowPrivate *window_private;
1403   XEvent sev;
1404   GdkEventDropDataAvailable tmp_ev;
1405   gchar *tmp;
1406   
1407   g_return_if_fail (window != NULL);
1408   g_return_if_fail (event != NULL);
1409   g_return_if_fail (data != NULL);
1410   g_return_if_fail (data_numbytes > 0);
1411   g_return_if_fail (event->type == GDK_DRAG_REQUEST);
1412
1413   window_private = (GdkWindowPrivate *) window;
1414   g_return_if_fail (window_private->dnd_drag_accepted != 0);    
1415   if (window_private->destroyed)
1416     return;
1417   
1418   /* We set the property on our window... */
1419   gdk_property_change (window, window_private->dnd_drag_data_type,
1420                        XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
1421                        data_numbytes);
1422   tmp = gdk_atom_name(window_private->dnd_drag_data_type);
1423 #ifdef DEBUG_DND
1424   g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow);
1425 #endif
1426   g_free(tmp);
1427   
1428   /* 
1429    * Then we send the event to tell the receiving window that the
1430    * drop has happened 
1431    */
1432   tmp_ev.u.allflags = 0;
1433   tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
1434   tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
1435   
1436   sev.xclient.type = ClientMessage;
1437   sev.xclient.format = 32;
1438   sev.xclient.window = event->dragrequest.requestor;
1439   sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
1440   sev.xclient.data.l[0] = window_private->xwindow;
1441   sev.xclient.data.l[1] = tmp_ev.u.allflags;
1442   sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
1443
1444   if (event->dragrequest.isdrop)
1445     sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
1446       (event->dragrequest.drop_coords.y << 16);
1447   else
1448     sev.xclient.data.l[3] = 0;
1449   
1450   sev.xclient.data.l[4] = 0;
1451   
1452   XSendEvent (gdk_display, event->dragrequest.requestor, False,
1453               NoEventMask, &sev);
1454 }
1455
1456 void          
1457 gdk_window_add_filter     (GdkWindow     *window,
1458                            GdkFilterFunc  function,
1459                            gpointer       data)
1460 {
1461   GdkWindowPrivate *private;
1462   GList *tmp_list;
1463   GdkEventFilter *filter;
1464
1465   g_return_if_fail (window != NULL);
1466
1467   private = (GdkWindowPrivate*) window;
1468   if (private->destroyed)
1469     return;
1470
1471   tmp_list = private->filters;
1472   while (tmp_list)
1473     {
1474       filter = (GdkEventFilter *)tmp_list->data;
1475       if ((filter->function == function) && (filter->data == data))
1476         return;
1477       tmp_list = tmp_list->next;
1478     }
1479
1480   filter = g_new (GdkEventFilter, 1);
1481   filter->function = function;
1482   filter->data = data;
1483   
1484   private->filters = g_list_append (private->filters, filter);
1485 }
1486
1487 void
1488 gdk_window_remove_filter  (GdkWindow     *window,
1489                            GdkFilterFunc  function,
1490                            gpointer       data)
1491 {
1492   GdkWindowPrivate *private;
1493   GList *tmp_list;
1494   GdkEventFilter *filter;
1495
1496   g_return_if_fail (window != NULL);
1497   private = (GdkWindowPrivate*) window;
1498
1499   tmp_list = private->filters;
1500   while (tmp_list)
1501     {
1502       filter = (GdkEventFilter *)tmp_list->data;
1503       tmp_list = tmp_list->next;
1504
1505       if ((filter->function == function) && (filter->data == data))
1506         {
1507           private->filters = g_list_remove_link (private->filters, tmp_list);
1508           g_list_free_1 (tmp_list);
1509           g_free (filter);
1510           
1511           return;
1512         }
1513     }
1514 }
1515
1516 void
1517 gdk_window_set_override_redirect(GdkWindow *window,
1518                                  gboolean override_redirect)
1519 {
1520   GdkWindowPrivate *private;
1521   XSetWindowAttributes attr;
1522
1523   g_return_if_fail (window != NULL);
1524   private = (GdkWindowPrivate*) window;
1525   if (private->destroyed)
1526     return;
1527
1528   attr.override_redirect = (override_redirect == FALSE)?False:True;
1529   XChangeWindowAttributes(gdk_display,
1530                           ((GdkWindowPrivate *)window)->xwindow,
1531                           CWOverrideRedirect,
1532                           &attr);
1533 }