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