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