]> Pileus Git - ~andy/gtk/blob - gdk/gdkwindow.c
applied patch to fix draw_indicator behaviour from Lars Hamann and Stefan
[~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   Pixmap pixmap;
1259
1260   g_return_if_fail (window != NULL);
1261
1262   window_private = (GdkWindowPrivate*) window;
1263   if (window_private->destroyed)
1264     return;
1265
1266   if (mask)
1267     {
1268       GdkWindowPrivate *pixmap_private;
1269
1270       pixmap_private = (GdkWindowPrivate*) mask;
1271       pixmap = (Pixmap) pixmap_private->xwindow;
1272     }
1273   else
1274     {
1275       x = 0;
1276       y = 0;
1277       pixmap = None;
1278     }
1279
1280   XShapeCombineMask  (window_private->xdisplay,
1281                       window_private->xwindow,
1282                       ShapeBounding,
1283                       x, y,
1284                       pixmap,
1285                       ShapeSet);
1286 }
1287
1288 void
1289 gdk_dnd_drag_addwindow (GdkWindow *window)
1290 {
1291   GdkWindowPrivate *window_private;
1292   
1293   g_return_if_fail (window != NULL);
1294   
1295   window_private = (GdkWindowPrivate *) window;
1296   if (window_private->destroyed)
1297     return;
1298   
1299   if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
1300     {
1301       gdk_dnd.drag_numwindows++;
1302       gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
1303                                              gdk_dnd.drag_numwindows
1304                                              * sizeof(GdkWindow *));
1305       gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
1306       window_private->dnd_drag_accepted = 0;
1307     } 
1308   else
1309     g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
1310 }
1311
1312 void
1313 gdk_window_dnd_drag_set (GdkWindow   *window,
1314                          guint8       drag_enable,
1315                          gchar      **typelist,
1316                          guint        numtypes)
1317 {
1318   GdkWindowPrivate *window_private;
1319   int i, wasset = 0;
1320   
1321   g_return_if_fail (window != NULL);
1322   window_private = (GdkWindowPrivate *) window;
1323   if (window_private->destroyed)
1324     return;
1325   
1326   window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
1327   
1328   if (drag_enable)
1329     {
1330       g_return_if_fail(typelist != NULL);
1331       
1332       if (window_private->dnd_drag_data_numtypesavail > 3)
1333         wasset = 1;
1334       window_private->dnd_drag_data_numtypesavail = numtypes;
1335       
1336       window_private->dnd_drag_data_typesavail =
1337         g_realloc (window_private->dnd_drag_data_typesavail,
1338                    (numtypes + 1) * sizeof (GdkAtom));
1339       
1340       for (i = 0; i < numtypes; i++)
1341         {
1342           /* Allow blanket use of ALL to get anything... */
1343           if (strcmp (typelist[i], "ALL"))
1344             window_private->dnd_drag_data_typesavail[i] =
1345               gdk_atom_intern (typelist[i], FALSE);
1346           else
1347             window_private->dnd_drag_data_typesavail[i] = None;
1348         }
1349       
1350       /* 
1351        * set our extended type list if we need to 
1352        */
1353       if (numtypes > 3)
1354         gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
1355                             XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
1356                             (guchar *)(window_private->dnd_drag_data_typesavail
1357                              + (sizeof(GdkAtom) * 3)),
1358                             (numtypes - 3) * sizeof(GdkAtom));
1359       else if (wasset)
1360         gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
1361     }
1362   else
1363     {
1364       g_free (window_private->dnd_drag_data_typesavail);
1365       window_private->dnd_drag_data_typesavail = NULL;
1366       window_private->dnd_drag_data_numtypesavail = 0;
1367     }
1368 }
1369
1370 void
1371 gdk_window_dnd_drop_set (GdkWindow   *window,
1372                          guint8       drop_enable,
1373                          gchar      **typelist,
1374                          guint        numtypes,
1375                          guint8       destructive_op)
1376 {
1377   GdkWindowPrivate *window_private;
1378   int i;
1379   
1380   g_return_if_fail (window != NULL);
1381   window_private = (GdkWindowPrivate *) window;
1382   if (window_private->destroyed)
1383     return;
1384   
1385   window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
1386   if (drop_enable)
1387     {
1388       g_return_if_fail(typelist != NULL);
1389       
1390       window_private->dnd_drop_data_numtypesavail = numtypes;
1391       
1392       window_private->dnd_drop_data_typesavail =
1393         g_realloc (window_private->dnd_drop_data_typesavail,
1394                    (numtypes + 1) * sizeof (GdkAtom));
1395       
1396       for (i = 0; i < numtypes; i++)
1397         window_private->dnd_drop_data_typesavail[i] =
1398           gdk_atom_intern (typelist[i], FALSE);
1399       
1400       window_private->dnd_drop_destructive_op = destructive_op;
1401     }
1402 }
1403
1404 /* 
1405  * This is used to reply to a GDK_DRAG_REQUEST event
1406  * (which may be generated by XdeRequest or a confirmed drop... 
1407  */
1408 void
1409 gdk_window_dnd_data_set (GdkWindow       *window,
1410                          GdkEvent        *event,
1411                          gpointer         data,
1412                          gulong           data_numbytes)
1413 {
1414   GdkWindowPrivate *window_private;
1415   XEvent sev;
1416   GdkEventDropDataAvailable tmp_ev;
1417   gchar *tmp;
1418   
1419   g_return_if_fail (window != NULL);
1420   g_return_if_fail (event != NULL);
1421   g_return_if_fail (data != NULL);
1422   g_return_if_fail (data_numbytes > 0);
1423   g_return_if_fail (event->type == GDK_DRAG_REQUEST);
1424
1425   window_private = (GdkWindowPrivate *) window;
1426   g_return_if_fail (window_private->dnd_drag_accepted != 0);    
1427   if (window_private->destroyed)
1428     return;
1429   
1430   /* We set the property on our window... */
1431   gdk_property_change (window, window_private->dnd_drag_data_type,
1432                        XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
1433                        data_numbytes);
1434   tmp = gdk_atom_name(window_private->dnd_drag_data_type);
1435 #ifdef DEBUG_DND
1436   g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow);
1437 #endif
1438   g_free(tmp);
1439   
1440   /* 
1441    * Then we send the event to tell the receiving window that the
1442    * drop has happened 
1443    */
1444   tmp_ev.u.allflags = 0;
1445   tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
1446   tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
1447   
1448   sev.xclient.type = ClientMessage;
1449   sev.xclient.format = 32;
1450   sev.xclient.window = event->dragrequest.requestor;
1451   sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
1452   sev.xclient.data.l[0] = window_private->xwindow;
1453   sev.xclient.data.l[1] = tmp_ev.u.allflags;
1454   sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
1455
1456   if (event->dragrequest.isdrop)
1457     sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
1458       (event->dragrequest.drop_coords.y << 16);
1459   else
1460     sev.xclient.data.l[3] = 0;
1461   
1462   sev.xclient.data.l[4] = 0;
1463   
1464   XSendEvent (gdk_display, event->dragrequest.requestor, False,
1465               NoEventMask, &sev);
1466 }
1467
1468 void          
1469 gdk_window_add_filter     (GdkWindow     *window,
1470                            GdkFilterFunc  function,
1471                            gpointer       data)
1472 {
1473   GdkWindowPrivate *private;
1474   GList *tmp_list;
1475   GdkEventFilter *filter;
1476
1477   g_return_if_fail (window != NULL);
1478
1479   private = (GdkWindowPrivate*) window;
1480   if (private->destroyed)
1481     return;
1482
1483   tmp_list = private->filters;
1484   while (tmp_list)
1485     {
1486       filter = (GdkEventFilter *)tmp_list->data;
1487       if ((filter->function == function) && (filter->data == data))
1488         return;
1489       tmp_list = tmp_list->next;
1490     }
1491
1492   filter = g_new (GdkEventFilter, 1);
1493   filter->function = function;
1494   filter->data = data;
1495   
1496   private->filters = g_list_append (private->filters, filter);
1497 }
1498
1499 void
1500 gdk_window_remove_filter  (GdkWindow     *window,
1501                            GdkFilterFunc  function,
1502                            gpointer       data)
1503 {
1504   GdkWindowPrivate *private;
1505   GList *tmp_list;
1506   GdkEventFilter *filter;
1507
1508   g_return_if_fail (window != NULL);
1509   private = (GdkWindowPrivate*) window;
1510
1511   tmp_list = private->filters;
1512   while (tmp_list)
1513     {
1514       filter = (GdkEventFilter *)tmp_list->data;
1515       tmp_list = tmp_list->next;
1516
1517       if ((filter->function == function) && (filter->data == data))
1518         {
1519           private->filters = g_list_remove_link (private->filters, tmp_list);
1520           g_list_free_1 (tmp_list);
1521           g_free (filter);
1522           
1523           return;
1524         }
1525     }
1526 }
1527
1528 void
1529 gdk_window_set_override_redirect(GdkWindow *window,
1530                                  gboolean override_redirect)
1531 {
1532   GdkWindowPrivate *private;
1533   XSetWindowAttributes attr;
1534
1535   g_return_if_fail (window != NULL);
1536   private = (GdkWindowPrivate*) window;
1537   if (private->destroyed)
1538     return;
1539
1540   attr.override_redirect = (override_redirect == FALSE)?False:True;
1541   XChangeWindowAttributes(gdk_display,
1542                           ((GdkWindowPrivate *)window)->xwindow,
1543                           CWOverrideRedirect,
1544                           &attr);
1545 }