source: trunk/third/gtk/gdk/gdkwindow.c @ 19019

Revision 19019, 63.8 KB checked in by ghudson, 22 years ago (diff)
From jfc: When using the default X server policy, FocusChange events are not sent by the server. gtk contains code to use EnterWindow and LeaveWindows events as well, but we need to request those events to make that work.
Line 
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
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20/*
21 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22 * file for a list of people on the GTK+ Team.  See the ChangeLog
23 * files for a list of changes.  These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27#include <X11/Xlib.h>
28#include <X11/Xutil.h>
29#include <X11/Xatom.h>
30#include <netinet/in.h>
31#include "gdk.h"
32#include "config.h"
33#include "gdkinput.h"
34#include "gdkprivate.h"
35#include "MwmUtil.h"
36
37#include <stdlib.h>
38#include <stdio.h>
39#include <string.h>
40
41
42#ifdef HAVE_SHAPE_EXT
43#include <X11/extensions/shape.h>
44#endif
45
46const int gdk_event_mask_table[20] =
47{
48  ExposureMask,
49  PointerMotionMask,
50  PointerMotionHintMask,
51  ButtonMotionMask,
52  Button1MotionMask,
53  Button2MotionMask,
54  Button3MotionMask,
55  ButtonPressMask | OwnerGrabButtonMask,
56  ButtonReleaseMask | OwnerGrabButtonMask,
57  KeyPressMask,
58  KeyReleaseMask,
59  EnterWindowMask,
60  LeaveWindowMask,
61  FocusChangeMask | EnterWindowMask | LeaveWindowMask,
62  StructureNotifyMask,
63  PropertyChangeMask,
64  VisibilityChangeMask,
65  0,                            /* PROXIMITY_IN */
66  0,                            /* PROXIMTY_OUT */
67  SubstructureNotifyMask
68};
69const int gdk_nevent_masks = sizeof (gdk_event_mask_table) / sizeof (int);
70
71/* Forward declarations */
72static gboolean gdk_window_gravity_works (void);
73static void     gdk_window_set_static_win_gravity (GdkWindow *window,
74                                                   gboolean   on);
75static gboolean gdk_window_have_shape_ext (void);
76
77/* internal function created for and used by gdk_window_xid_at_coords */
78Window
79gdk_window_xid_at (Window   base,
80                   gint     bx,
81                   gint     by,
82                   gint     x,
83                   gint     y,
84                   GList   *excludes,
85                   gboolean excl_child)
86{
87  GdkWindow *window;
88  GdkWindowPrivate *private;
89  Display *disp;
90  Window *list = NULL;
91  Window child = 0, parent_win = 0, root_win = 0;
92  int i;
93  unsigned int ww, wh, wb, wd, num;
94  int wx, wy;
95 
96  window = (GdkWindow*) &gdk_root_parent;
97  private = (GdkWindowPrivate*) window;
98  disp = private->xdisplay;
99  if (!XGetGeometry (disp, base, &root_win, &wx, &wy, &ww, &wh, &wb, &wd))
100    return 0;
101  wx += bx;
102  wy += by;
103 
104  if (!((x >= wx) &&
105        (y >= wy) &&
106        (x < (int) (wx + ww)) &&
107        (y < (int) (wy + wh))))
108    return 0;
109 
110  if (!XQueryTree (disp, base, &root_win, &parent_win, &list, &num))
111    return base;
112 
113  if (list)
114    {
115      for (i = num - 1; ; i--)
116        {
117          if ((!excl_child) || (!g_list_find (excludes, (gpointer *) list[i])))
118            {
119              if ((child = gdk_window_xid_at (list[i], wx, wy, x, y, excludes, excl_child)) != 0)
120                {
121                  XFree (list);
122                  return child;
123                }
124            }
125          if (!i)
126            break;
127        }
128      XFree (list);
129    }
130  return base;
131}
132
133/*
134 * The following fucntion by The Rasterman <raster@redhat.com>
135 * This function returns the X Window ID in which the x y location is in
136 * (x and y being relative to the root window), excluding any windows listed
137 * in the GList excludes (this is a list of X Window ID's - gpointer being
138 * the Window ID).
139 *
140 * This is primarily designed for internal gdk use - for DND for example
141 * when using a shaped icon window as the drag object - you exclude the
142 * X Window ID of the "icon" (perhaps more if excludes may be needed) and
143 * You can get back an X Window ID as to what X Window ID is infact under
144 * those X,Y co-ordinates.
145 */
146Window
147gdk_window_xid_at_coords (gint     x,
148                          gint     y,
149                          GList   *excludes,
150                          gboolean excl_child)
151{
152  GdkWindow *window;
153  GdkWindowPrivate *private;
154  Display *disp;
155  Window *list = NULL;
156  Window root, child = 0, parent_win = 0, root_win = 0;
157  unsigned int num;
158  int i;
159 
160  window = (GdkWindow*) &gdk_root_parent;
161  private = (GdkWindowPrivate*) window;
162  disp = private->xdisplay;
163  root = private->xwindow;
164  num = g_list_length (excludes);
165 
166  XGrabServer (disp);
167  if (!XQueryTree (disp, root, &root_win, &parent_win, &list, &num))
168    {
169      XUngrabServer (disp);
170      return root;
171    }
172  if (list)
173    {
174      i = num - 1;
175      do
176        {
177          XWindowAttributes xwa;
178         
179          XGetWindowAttributes (disp, list [i], &xwa);
180         
181          if (xwa.map_state != IsViewable)
182            continue;
183         
184          if (excl_child && g_list_find (excludes, (gpointer *) list[i]))
185            continue;
186         
187          if ((child = gdk_window_xid_at (list[i], 0, 0, x, y, excludes, excl_child)) == 0)
188            continue;
189         
190          if (excludes)
191            {
192              if (!g_list_find (excludes, (gpointer *) child))
193                {
194                  XFree (list);
195                  XUngrabServer (disp);
196                  return child;
197                }
198            }
199          else
200            {
201              XFree (list);
202              XUngrabServer (disp);
203              return child;
204            }
205        } while (--i > 0);
206      XFree (list);
207    }
208  XUngrabServer (disp);
209  return root;
210}
211
212void
213gdk_window_init (void)
214{
215  XWindowAttributes xattributes;
216  unsigned int width;
217  unsigned int height;
218  unsigned int border_width;
219  unsigned int depth;
220  int x, y;
221 
222  XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window,
223                &x, &y, &width, &height, &border_width, &depth);
224  XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes);
225 
226  gdk_root_parent.xwindow = gdk_root_window;
227  gdk_root_parent.xdisplay = gdk_display;
228  gdk_root_parent.window_type = GDK_WINDOW_ROOT;
229  gdk_root_parent.window.user_data = NULL;
230  gdk_root_parent.width = width;
231  gdk_root_parent.height = height;
232  gdk_root_parent.children = NULL;
233  gdk_root_parent.colormap = NULL;
234  gdk_root_parent.ref_count = 1;
235 
236  gdk_xid_table_insert (&gdk_root_window, &gdk_root_parent);
237}
238
239static GdkAtom wm_client_leader_atom = GDK_NONE;
240
241GdkWindow*
242gdk_window_new (GdkWindow     *parent,
243                GdkWindowAttr *attributes,
244                gint           attributes_mask)
245{
246  GdkWindow *window;
247  GdkWindowPrivate *private;
248  GdkWindowPrivate *parent_private;
249  GdkVisual *visual;
250  Display *parent_display;
251  Window xparent;
252  Visual *xvisual;
253  XSetWindowAttributes xattributes;
254  long xattributes_mask;
255  XSizeHints size_hints;
256  XWMHints wm_hints;
257  XClassHint *class_hint;
258  int x, y, depth;
259  unsigned int class;
260  char *title;
261  int i;
262 
263  g_return_val_if_fail (attributes != NULL, NULL);
264 
265  if (!parent)
266    parent = (GdkWindow*) &gdk_root_parent;
267 
268  parent_private = (GdkWindowPrivate*) parent;
269  if (parent_private->destroyed)
270    return NULL;
271 
272  xparent = parent_private->xwindow;
273  parent_display = parent_private->xdisplay;
274 
275  private = g_new (GdkWindowPrivate, 1);
276  window = (GdkWindow*) private;
277 
278  private->parent = parent;
279 
280  private->xdisplay = parent_display;
281  private->destroyed = FALSE;
282  private->mapped = FALSE;
283  private->guffaw_gravity = FALSE;
284  private->resize_count = 0;
285  private->ref_count = 1;
286  xattributes_mask = 0;
287 
288  if (attributes_mask & GDK_WA_X)
289    x = attributes->x;
290  else
291    x = 0;
292 
293  if (attributes_mask & GDK_WA_Y)
294    y = attributes->y;
295  else
296    y = 0;
297 
298  private->x = x;
299  private->y = y;
300  private->width = (attributes->width > 1) ? (attributes->width) : (1);
301  private->height = (attributes->height > 1) ? (attributes->height) : (1);
302  private->window_type = attributes->window_type;
303  private->extension_events = FALSE;
304 
305  private->filters = NULL;
306  private->children = NULL;
307 
308  window->user_data = NULL;
309 
310  if (attributes_mask & GDK_WA_VISUAL)
311    visual = attributes->visual;
312  else
313    visual = gdk_visual_get_system ();
314  xvisual = ((GdkVisualPrivate*) visual)->xvisual;
315 
316  xattributes.event_mask = StructureNotifyMask;
317  for (i = 0; i < gdk_nevent_masks; i++)
318    {
319      if (attributes->event_mask & (1 << (i + 1)))
320        xattributes.event_mask |= gdk_event_mask_table[i];
321    }
322 
323  if (xattributes.event_mask)
324    xattributes_mask |= CWEventMask;
325 
326  if (attributes_mask & GDK_WA_NOREDIR)
327    {
328      xattributes.override_redirect =
329        (attributes->override_redirect == FALSE)?False:True;
330      xattributes_mask |= CWOverrideRedirect;
331    }
332  else
333    xattributes.override_redirect = False;
334 
335  if (parent_private && parent_private->guffaw_gravity)
336    {
337      xattributes.win_gravity = StaticGravity;
338      xattributes_mask |= CWWinGravity;
339    }
340 
341  if (attributes->wclass == GDK_INPUT_OUTPUT)
342    {
343      class = InputOutput;
344      depth = visual->depth;
345     
346      if (attributes_mask & GDK_WA_COLORMAP)
347        private->colormap = attributes->colormap;
348      else
349        {
350          if ((((GdkVisualPrivate*)gdk_visual_get_system ())->xvisual) == xvisual)
351            private->colormap = gdk_colormap_get_system ();
352          else
353            private->colormap = gdk_colormap_new (visual, False);
354        }
355     
356      xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen);
357      xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
358      xattributes_mask |= CWBorderPixel | CWBackPixel;
359     
360      switch (private->window_type)
361        {
362        case GDK_WINDOW_TOPLEVEL:
363          xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
364          xattributes_mask |= CWColormap;
365         
366          xparent = gdk_root_window;
367          break;
368         
369        case GDK_WINDOW_CHILD:
370          xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
371          xattributes_mask |= CWColormap;
372          break;
373         
374        case GDK_WINDOW_DIALOG:
375          xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
376          xattributes_mask |= CWColormap;
377         
378          xparent = gdk_root_window;
379          break;
380         
381        case GDK_WINDOW_TEMP:
382          xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
383          xattributes_mask |= CWColormap;
384         
385          xparent = gdk_root_window;
386         
387          xattributes.save_under = True;
388          xattributes.override_redirect = True;
389          xattributes.cursor = None;
390          xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
391          break;
392        case GDK_WINDOW_ROOT:
393          g_error ("cannot make windows of type GDK_WINDOW_ROOT");
394          break;
395        case GDK_WINDOW_PIXMAP:
396          g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
397          break;
398        }
399    }
400  else
401    {
402      depth = 0;
403      class = InputOnly;
404      private->colormap = gdk_colormap_get_system ();
405    }
406 
407  private->xwindow = XCreateWindow (private->xdisplay, xparent,
408                                    x, y, private->width, private->height,
409                                    0, depth, class, xvisual,
410                                    xattributes_mask, &xattributes);
411  gdk_window_ref (window);
412  gdk_xid_table_insert (&private->xwindow, window);
413 
414  if (private->colormap)
415    gdk_colormap_ref (private->colormap);
416 
417  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
418                                  (attributes->cursor) :
419                                  NULL));
420 
421  if (parent_private)
422    parent_private->children = g_list_prepend (parent_private->children, window);
423 
424  switch (private->window_type)
425    {
426    case GDK_WINDOW_DIALOG:
427      XSetTransientForHint (private->xdisplay, private->xwindow, xparent);
428    case GDK_WINDOW_TOPLEVEL:
429    case GDK_WINDOW_TEMP:
430      XSetWMProtocols (private->xdisplay, private->xwindow, gdk_wm_window_protocols, 2);
431      break;
432    case GDK_WINDOW_CHILD:
433      if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
434          (private->colormap != gdk_colormap_get_system ()) &&
435          (private->colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
436        {
437          GDK_NOTE (MISC, g_message ("adding colormap window\n"));
438          gdk_window_add_colormap_windows (window);
439        }
440     
441      return window;
442    default:
443     
444      return window;
445    }
446 
447  size_hints.flags = PSize;
448  size_hints.width = private->width;
449  size_hints.height = private->height;
450 
451  wm_hints.flags = InputHint | StateHint | WindowGroupHint;
452  wm_hints.window_group = gdk_leader_window;
453  wm_hints.input = True;
454  wm_hints.initial_state = NormalState;
455 
456  /* FIXME: Is there any point in doing this? Do any WM's pay
457   * attention to PSize, and even if they do, is this the
458   * correct value???
459   */
460  XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
461 
462  XSetWMHints (private->xdisplay, private->xwindow, &wm_hints);
463 
464  if (!wm_client_leader_atom)
465    wm_client_leader_atom = gdk_atom_intern ("WM_CLIENT_LEADER", FALSE);
466 
467  XChangeProperty (private->xdisplay, private->xwindow,
468                   wm_client_leader_atom,
469                   XA_WINDOW, 32, PropModeReplace,
470                   (guchar*) &gdk_leader_window, 1);
471 
472  if (attributes_mask & GDK_WA_TITLE)
473    title = attributes->title;
474  else
475    title = g_get_prgname ();
476 
477  XmbSetWMProperties (private->xdisplay, private->xwindow,
478                      title, title,
479                      NULL, 0,
480                      NULL, NULL, NULL);
481 
482  if (attributes_mask & GDK_WA_WMCLASS)
483    {
484      class_hint = XAllocClassHint ();
485      class_hint->res_name = attributes->wmclass_name;
486      class_hint->res_class = attributes->wmclass_class;
487      XSetClassHint (private->xdisplay, private->xwindow, class_hint);
488      XFree (class_hint);
489    }
490 
491 
492  return window;
493}
494
495GdkWindow *
496gdk_window_foreign_new (guint32 anid)
497{
498  GdkWindow *window;
499  GdkWindowPrivate *private;
500  GdkWindowPrivate *parent_private;
501  XWindowAttributes attrs;
502  Window root, parent;
503  Window *children = NULL;
504  guint nchildren;
505  gboolean result;
506
507  gdk_error_trap_push ();
508  result = XGetWindowAttributes (gdk_display, anid, &attrs);
509  if (gdk_error_trap_pop () || !result)
510    return NULL;
511
512  /* FIXME: This is pretty expensive. Maybe the caller should supply
513   *        the parent */
514  gdk_error_trap_push ();
515  result = XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren);
516  if (gdk_error_trap_pop () || !result)
517    return NULL;
518 
519  private = g_new (GdkWindowPrivate, 1);
520  window = (GdkWindow*) private;
521 
522  if (children)
523    XFree (children);
524  private->parent = gdk_xid_table_lookup (parent);
525 
526  parent_private = (GdkWindowPrivate *)private->parent;
527 
528  if (parent_private)
529    parent_private->children = g_list_prepend (parent_private->children, window);
530 
531  private->xwindow = anid;
532  private->xdisplay = gdk_display;
533  private->x = attrs.x;
534  private->y = attrs.y;
535  private->width = attrs.width;
536  private->height = attrs.height;
537  private->resize_count = 0;
538  private->ref_count = 1;
539  private->window_type = GDK_WINDOW_FOREIGN;
540  private->destroyed = FALSE;
541  private->mapped = (attrs.map_state != IsUnmapped);
542  private->guffaw_gravity = FALSE;
543  private->extension_events = 0;
544 
545  private->colormap = NULL;
546 
547  private->filters = NULL;
548  private->children = NULL;
549 
550  window->user_data = NULL;
551 
552  gdk_window_ref (window);
553  gdk_xid_table_insert (&private->xwindow, window);
554 
555  return window;
556}
557
558/* Call this function when you want a window and all its children to
559 * disappear.  When xdestroy is true, a request to destroy the XWindow
560 * is sent out.  When it is false, it is assumed that the XWindow has
561 * been or will be destroyed by destroying some ancestor of this
562 * window.
563 */
564static void
565gdk_window_internal_destroy (GdkWindow *window,
566                             gboolean   xdestroy,
567                             gboolean   our_destroy)
568{
569  GdkWindowPrivate *private;
570  GdkWindowPrivate *temp_private;
571  GdkWindow *temp_window;
572  GList *children;
573  GList *tmp;
574 
575  g_return_if_fail (window != NULL);
576 
577  private = (GdkWindowPrivate*) window;
578 
579  switch (private->window_type)
580    {
581    case GDK_WINDOW_TOPLEVEL:
582    case GDK_WINDOW_CHILD:
583    case GDK_WINDOW_DIALOG:
584    case GDK_WINDOW_TEMP:
585    case GDK_WINDOW_FOREIGN:
586      if (!private->destroyed)
587        {
588          if (private->parent)
589            {
590              GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent;
591              if (parent_private->children)
592                parent_private->children = g_list_remove (parent_private->children, window);
593            }
594         
595          if (private->window_type != GDK_WINDOW_FOREIGN)
596            {
597              children = tmp = private->children;
598              private->children = NULL;
599             
600              while (tmp)
601                {
602                  temp_window = tmp->data;
603                  tmp = tmp->next;
604                 
605                  temp_private = (GdkWindowPrivate*) temp_window;
606                  if (temp_private)
607                    gdk_window_internal_destroy (temp_window, FALSE,
608                                                 our_destroy);
609                }
610             
611              g_list_free (children);
612            }
613         
614          if (private->extension_events != 0)
615            gdk_input_window_destroy (window);
616         
617          if (private->filters)
618            {
619              tmp = private->filters;
620             
621              while (tmp)
622                {
623                  g_free (tmp->data);
624                  tmp = tmp->next;
625                }
626             
627              g_list_free (private->filters);
628              private->filters = NULL;
629            }
630         
631          if (private->window_type == GDK_WINDOW_FOREIGN)
632            {
633              if (our_destroy && (private->parent != NULL))
634                {
635                  /* It's somebody elses window, but in our heirarchy,
636                   * so reparent it to the root window, and then send
637                   * it a delete event, as if we were a WM
638                   */
639                  XClientMessageEvent xevent;
640
641                  gdk_error_trap_push ();
642                  gdk_window_hide (window);
643                  gdk_window_reparent (window, NULL, 0, 0);
644                 
645                  xevent.type = ClientMessage;
646                  xevent.window = private->xwindow;
647                  xevent.message_type = gdk_wm_protocols;
648                  xevent.format = 32;
649                  xevent.data.l[0] = gdk_wm_delete_window;
650                  xevent.data.l[1] = CurrentTime;
651
652                  XSendEvent (private->xdisplay, private->xwindow,
653                              False, 0, (XEvent *)&xevent);
654                  gdk_flush ();
655                  gdk_error_trap_pop ();
656                }
657            }
658          else if (xdestroy)
659            XDestroyWindow (private->xdisplay, private->xwindow);
660         
661          if (private->colormap)
662            gdk_colormap_unref (private->colormap);
663         
664          private->mapped = FALSE;
665          private->destroyed = TRUE;
666        }
667      break;
668     
669    case GDK_WINDOW_ROOT:
670      g_error ("attempted to destroy root window");
671      break;
672     
673    case GDK_WINDOW_PIXMAP:
674      g_error ("called gdk_window_destroy on a pixmap (use gdk_pixmap_unref)");
675      break;
676    }
677}
678
679/* Like internal_destroy, but also destroys the reference created by
680   gdk_window_new. */
681
682void
683gdk_window_destroy (GdkWindow *window)
684{
685  gdk_window_internal_destroy (window, TRUE, TRUE);
686  gdk_window_unref (window);
687}
688
689/* This function is called when the XWindow is really gone.  */
690
691void
692gdk_window_destroy_notify (GdkWindow *window)
693{
694  GdkWindowPrivate *private;
695 
696  g_return_if_fail (window != NULL);
697 
698  private = (GdkWindowPrivate*) window;
699 
700  if (!private->destroyed)
701    {
702      if (private->window_type != GDK_WINDOW_FOREIGN)
703        g_warning ("GdkWindow %#lx unexpectedly destroyed", private->xwindow);
704
705      gdk_window_internal_destroy (window, FALSE, FALSE);
706    }
707 
708  gdk_xid_table_remove (private->xwindow);
709  gdk_window_unref (window);
710}
711
712GdkWindow*
713gdk_window_ref (GdkWindow *window)
714{
715  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
716  g_return_val_if_fail (window != NULL, NULL);
717 
718  private->ref_count += 1;
719  return window;
720}
721
722void
723gdk_window_unref (GdkWindow *window)
724{
725  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
726  g_return_if_fail (window != NULL);
727  g_return_if_fail (private->ref_count > 0);
728 
729  private->ref_count -= 1;
730  if (private->ref_count == 0)
731    {
732      if (!private->destroyed)
733        {
734          if (private->window_type == GDK_WINDOW_FOREIGN)
735            gdk_xid_table_remove (private->xwindow);
736          else
737            g_warning ("losing last reference to undestroyed window\n");
738        }
739      g_dataset_destroy (window);
740      g_free (window);
741    }
742}
743
744void
745gdk_window_show (GdkWindow *window)
746{
747  GdkWindowPrivate *private;
748 
749  g_return_if_fail (window != NULL);
750 
751  private = (GdkWindowPrivate*) window;
752  if (!private->destroyed)
753    {
754      private->mapped = TRUE;
755      XRaiseWindow (private->xdisplay, private->xwindow);
756      XMapWindow (private->xdisplay, private->xwindow);
757    }
758}
759
760void
761gdk_window_hide (GdkWindow *window)
762{
763  GdkWindowPrivate *private;
764 
765  g_return_if_fail (window != NULL);
766 
767  private = (GdkWindowPrivate*) window;
768  if (!private->destroyed)
769    {
770      private->mapped = FALSE;
771      XUnmapWindow (private->xdisplay, private->xwindow);
772    }
773}
774
775void
776gdk_window_withdraw (GdkWindow *window)
777{
778  GdkWindowPrivate *private;
779 
780  g_return_if_fail (window != NULL);
781 
782  private = (GdkWindowPrivate*) window;
783  if (!private->destroyed)
784    XWithdrawWindow (private->xdisplay, private->xwindow, 0);
785}
786
787void
788gdk_window_move (GdkWindow *window,
789                 gint       x,
790                 gint       y)
791{
792  GdkWindowPrivate *private;
793 
794  g_return_if_fail (window != NULL);
795 
796  private = (GdkWindowPrivate*) window;
797  if (!private->destroyed)
798    {
799      XMoveWindow (private->xdisplay, private->xwindow, x, y);
800     
801      if (private->window_type == GDK_WINDOW_CHILD)
802        {
803          private->x = x;
804          private->y = y;
805        }
806    }
807}
808
809void
810gdk_window_resize (GdkWindow *window,
811                   gint       width,
812                   gint       height)
813{
814  GdkWindowPrivate *private;
815 
816  g_return_if_fail (window != NULL);
817 
818  if (width < 1)
819    width = 1;
820  if (height < 1)
821    height = 1;
822 
823  private = (GdkWindowPrivate*) window;
824 
825  if (!private->destroyed &&
826      ((private->resize_count > 0) ||
827       (private->width != (guint16) width) ||
828       (private->height != (guint16) height)))
829    {
830      XResizeWindow (private->xdisplay, private->xwindow, width, height);
831      private->resize_count += 1;
832     
833      if (private->window_type == GDK_WINDOW_CHILD)
834        {
835          private->width = width;
836          private->height = height;
837        }
838    }
839}
840
841void
842gdk_window_move_resize (GdkWindow *window,
843                        gint       x,
844                        gint       y,
845                        gint       width,
846                        gint       height)
847{
848  GdkWindowPrivate *private;
849 
850  g_return_if_fail (window != NULL);
851 
852  if (width < 1)
853    width = 1;
854  if (height < 1)
855    height = 1;
856 
857  private = (GdkWindowPrivate*) window;
858  if (!private->destroyed)
859    {
860      XMoveResizeWindow (private->xdisplay, private->xwindow, x, y, width, height);
861     
862      if (private->guffaw_gravity)
863        {
864          GList *tmp_list = private->children;
865          while (tmp_list)
866            {
867              GdkWindowPrivate *child_private = tmp_list->data;
868             
869              child_private->x -= x - private->x;
870              child_private->y -= y - private->y;
871             
872              tmp_list = tmp_list->next;
873            }
874        }
875     
876      if (private->window_type == GDK_WINDOW_CHILD)
877        {
878          private->x = x;
879          private->y = y;
880          private->width = width;
881          private->height = height;
882        }
883    }
884}
885
886void
887gdk_window_reparent (GdkWindow *window,
888                     GdkWindow *new_parent,
889                     gint       x,
890                     gint       y)
891{
892  GdkWindowPrivate *window_private;
893  GdkWindowPrivate *parent_private;
894  GdkWindowPrivate *old_parent_private;
895 
896  g_return_if_fail (window != NULL);
897 
898  if (!new_parent)
899    new_parent = (GdkWindow*) &gdk_root_parent;
900 
901  window_private = (GdkWindowPrivate*) window;
902  old_parent_private = (GdkWindowPrivate*)window_private->parent;
903  parent_private = (GdkWindowPrivate*) new_parent;
904 
905  if (!window_private->destroyed && !parent_private->destroyed)
906    XReparentWindow (window_private->xdisplay,
907                     window_private->xwindow,
908                     parent_private->xwindow,
909                     x, y);
910 
911  window_private->parent = new_parent;
912 
913  if (old_parent_private)
914    old_parent_private->children = g_list_remove (old_parent_private->children, window);
915 
916  if ((old_parent_private &&
917       (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
918      (!old_parent_private && parent_private->guffaw_gravity))
919    gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
920 
921  parent_private->children = g_list_prepend (parent_private->children, window);
922}
923
924void
925gdk_window_clear (GdkWindow *window)
926{
927  GdkWindowPrivate *private;
928 
929  g_return_if_fail (window != NULL);
930 
931  private = (GdkWindowPrivate*) window;
932 
933  if (!private->destroyed)
934    XClearWindow (private->xdisplay, private->xwindow);
935}
936
937void
938gdk_window_clear_area (GdkWindow *window,
939                       gint       x,
940                       gint       y,
941                       gint       width,
942                       gint       height)
943{
944  GdkWindowPrivate *private;
945 
946  g_return_if_fail (window != NULL);
947 
948  private = (GdkWindowPrivate*) window;
949 
950  if (!private->destroyed)
951    XClearArea (private->xdisplay, private->xwindow,
952                x, y, width, height, False);
953}
954
955void
956gdk_window_clear_area_e (GdkWindow *window,
957                         gint       x,
958                         gint       y,
959                         gint       width,
960                         gint       height)
961{
962  GdkWindowPrivate *private;
963 
964  g_return_if_fail (window != NULL);
965 
966  private = (GdkWindowPrivate*) window;
967 
968  if (!private->destroyed)
969    XClearArea (private->xdisplay, private->xwindow,
970                x, y, width, height, True);
971}
972
973void
974gdk_window_copy_area (GdkWindow    *window,
975                      GdkGC        *gc,
976                      gint          x,
977                      gint          y,
978                      GdkWindow    *source_window,
979                      gint          source_x,
980                      gint          source_y,
981                      gint          width,
982                      gint          height)
983{
984  GdkWindowPrivate *src_private;
985  GdkWindowPrivate *dest_private;
986  GdkGCPrivate *gc_private;
987 
988  g_return_if_fail (window != NULL);
989  g_return_if_fail (gc != NULL);
990 
991  if (source_window == NULL)
992    source_window = window;
993 
994  src_private = (GdkWindowPrivate*) source_window;
995  dest_private = (GdkWindowPrivate*) window;
996  gc_private = (GdkGCPrivate*) gc;
997 
998  if (!src_private->destroyed && !dest_private->destroyed)
999    {
1000      XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow,
1001                 gc_private->xgc,
1002                 source_x, source_y,
1003                 width, height,
1004                 x, y);
1005    }
1006}
1007
1008void
1009gdk_window_raise (GdkWindow *window)
1010{
1011  GdkWindowPrivate *private;
1012 
1013  g_return_if_fail (window != NULL);
1014 
1015  private = (GdkWindowPrivate*) window;
1016 
1017  if (!private->destroyed)
1018    XRaiseWindow (private->xdisplay, private->xwindow);
1019}
1020
1021void
1022gdk_window_lower (GdkWindow *window)
1023{
1024  GdkWindowPrivate *private;
1025 
1026  g_return_if_fail (window != NULL);
1027 
1028  private = (GdkWindowPrivate*) window;
1029 
1030  if (!private->destroyed)
1031    XLowerWindow (private->xdisplay, private->xwindow);
1032}
1033
1034void
1035gdk_window_set_user_data (GdkWindow *window,
1036                          gpointer   user_data)
1037{
1038  g_return_if_fail (window != NULL);
1039 
1040  window->user_data = user_data;
1041}
1042
1043void
1044gdk_window_set_hints (GdkWindow *window,
1045                      gint       x,
1046                      gint       y,
1047                      gint       min_width,
1048                      gint       min_height,
1049                      gint       max_width,
1050                      gint       max_height,
1051                      gint       flags)
1052{
1053  GdkWindowPrivate *private;
1054  XSizeHints size_hints;
1055 
1056  g_return_if_fail (window != NULL);
1057 
1058  private = (GdkWindowPrivate*) window;
1059  if (private->destroyed)
1060    return;
1061 
1062  size_hints.flags = 0;
1063 
1064  if (flags & GDK_HINT_POS)
1065    {
1066      size_hints.flags |= PPosition;
1067      size_hints.x = x;
1068      size_hints.y = y;
1069    }
1070 
1071  if (flags & GDK_HINT_MIN_SIZE)
1072    {
1073      size_hints.flags |= PMinSize;
1074      size_hints.min_width = min_width;
1075      size_hints.min_height = min_height;
1076    }
1077 
1078  if (flags & GDK_HINT_MAX_SIZE)
1079    {
1080      size_hints.flags |= PMaxSize;
1081      size_hints.max_width = max_width;
1082      size_hints.max_height = max_height;
1083    }
1084 
1085  /* FIXME: Would it be better to delete this property of
1086   *        flags == 0? It would save space on the server
1087   */
1088  XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
1089}
1090
1091void
1092gdk_window_set_geometry_hints (GdkWindow      *window,
1093                               GdkGeometry    *geometry,
1094                               GdkWindowHints  geom_mask)
1095{
1096  GdkWindowPrivate *private;
1097  XSizeHints size_hints;
1098 
1099  g_return_if_fail (window != NULL);
1100 
1101  private = (GdkWindowPrivate*) window;
1102  if (private->destroyed)
1103    return;
1104 
1105  size_hints.flags = 0;
1106 
1107  if (geom_mask & GDK_HINT_POS)
1108    {
1109      size_hints.flags |= PPosition;
1110      /* We need to initialize the following obsolete fields because KWM
1111       * apparently uses these fields if they are non-zero.
1112       * #@#!#!$!.
1113       */
1114      size_hints.x = 0;
1115      size_hints.y = 0;
1116    }
1117 
1118  if (geom_mask & GDK_HINT_MIN_SIZE)
1119    {
1120      size_hints.flags |= PMinSize;
1121      size_hints.min_width = geometry->min_width;
1122      size_hints.min_height = geometry->min_height;
1123    }
1124 
1125  if (geom_mask & GDK_HINT_MAX_SIZE)
1126    {
1127      size_hints.flags |= PMaxSize;
1128      size_hints.max_width = MAX (geometry->max_width, 1);
1129      size_hints.max_height = MAX (geometry->max_height, 1);
1130    }
1131 
1132  if (geom_mask & GDK_HINT_BASE_SIZE)
1133    {
1134      size_hints.flags |= PBaseSize;
1135      size_hints.base_width = geometry->base_width;
1136      size_hints.base_height = geometry->base_height;
1137    }
1138 
1139  if (geom_mask & GDK_HINT_RESIZE_INC)
1140    {
1141      size_hints.flags |= PResizeInc;
1142      size_hints.width_inc = geometry->width_inc;
1143      size_hints.height_inc = geometry->height_inc;
1144    }
1145 
1146  if (geom_mask & GDK_HINT_ASPECT)
1147    {
1148      size_hints.flags |= PAspect;
1149      if (geometry->min_aspect <= 1)
1150        {
1151          size_hints.min_aspect.x = 65536 * geometry->min_aspect;
1152          size_hints.min_aspect.y = 65536;
1153        }
1154      else
1155        {
1156          size_hints.min_aspect.x = 65536;
1157          size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
1158        }
1159      if (geometry->max_aspect <= 1)
1160        {
1161          size_hints.max_aspect.x = 65536 * geometry->max_aspect;
1162          size_hints.max_aspect.y = 65536;
1163        }
1164      else
1165        {
1166          size_hints.max_aspect.x = 65536;
1167          size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
1168        }
1169    }
1170
1171  /* FIXME: Would it be better to delete this property of
1172   *        geom_mask == 0? It would save space on the server
1173   */
1174  XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
1175}
1176
1177void
1178gdk_window_set_title (GdkWindow   *window,
1179                      const gchar *title)
1180{
1181  GdkWindowPrivate *private;
1182 
1183  g_return_if_fail (window != NULL);
1184 
1185  private = (GdkWindowPrivate*) window;
1186  if (!private->destroyed)
1187    XmbSetWMProperties (private->xdisplay, private->xwindow,
1188                        title, title, NULL, 0, NULL, NULL, NULL);
1189}
1190
1191void         
1192gdk_window_set_role (GdkWindow   *window,
1193                     const gchar *role)
1194{
1195  GdkWindowPrivate *private;
1196 
1197  g_return_if_fail (window != NULL);
1198 
1199  private = (GdkWindowPrivate*) window;
1200 
1201  if (role)
1202    XChangeProperty (private->xdisplay, private->xwindow,
1203                     gdk_atom_intern ("WM_WINDOW_ROLE", FALSE), XA_STRING,
1204                     8, PropModeReplace, role, strlen (role));
1205  else
1206    XDeleteProperty (private->xdisplay, private->xwindow,
1207                     gdk_atom_intern ("WM_WINDOW_ROLE", FALSE));
1208}
1209
1210void         
1211gdk_window_set_transient_for (GdkWindow *window,
1212                              GdkWindow *parent)
1213{
1214  GdkWindowPrivate *private;
1215  GdkWindowPrivate *parent_private;
1216 
1217  g_return_if_fail (window != NULL);
1218 
1219  private = (GdkWindowPrivate*) window;
1220  parent_private = (GdkWindowPrivate*) parent;
1221 
1222  if (!private->destroyed && !parent_private->destroyed)
1223    XSetTransientForHint (private->xdisplay,
1224                          private->xwindow, parent_private->xwindow);
1225}
1226
1227void
1228gdk_window_set_background (GdkWindow *window,
1229                           GdkColor  *color)
1230{
1231  GdkWindowPrivate *private;
1232 
1233  g_return_if_fail (window != NULL);
1234 
1235  private = (GdkWindowPrivate*) window;
1236  if (!private->destroyed)
1237    XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel);
1238}
1239
1240void
1241gdk_window_set_back_pixmap (GdkWindow *window,
1242                            GdkPixmap *pixmap,
1243                            gboolean   parent_relative)
1244{
1245  GdkWindowPrivate *window_private;
1246  GdkPixmapPrivate *pixmap_private;
1247  Pixmap xpixmap;
1248 
1249  g_return_if_fail (window != NULL);
1250 
1251  window_private = (GdkWindowPrivate*) window;
1252  pixmap_private = (GdkPixmapPrivate*) pixmap;
1253 
1254  if (pixmap)
1255    xpixmap = pixmap_private->xwindow;
1256  else
1257    xpixmap = None;
1258 
1259  if (parent_relative)
1260    xpixmap = ParentRelative;
1261 
1262  if (!window_private->destroyed)
1263    XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap);
1264}
1265
1266void
1267gdk_window_set_cursor (GdkWindow *window,
1268                       GdkCursor *cursor)
1269{
1270  GdkWindowPrivate *window_private;
1271  GdkCursorPrivate *cursor_private;
1272  Cursor xcursor;
1273 
1274  g_return_if_fail (window != NULL);
1275 
1276  window_private = (GdkWindowPrivate*) window;
1277  cursor_private = (GdkCursorPrivate*) cursor;
1278 
1279  if (!cursor)
1280    xcursor = None;
1281  else
1282    xcursor = cursor_private->xcursor;
1283 
1284  if (!window_private->destroyed)
1285    XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor);
1286}
1287
1288void
1289gdk_window_set_colormap (GdkWindow   *window,
1290                         GdkColormap *colormap)
1291{
1292  GdkWindowPrivate *window_private;
1293  GdkColormapPrivate *colormap_private;
1294 
1295  g_return_if_fail (window != NULL);
1296  g_return_if_fail (colormap != NULL);
1297 
1298  window_private = (GdkWindowPrivate*) window;
1299  colormap_private = (GdkColormapPrivate*) colormap;
1300 
1301  if (!window_private->destroyed)
1302    {
1303      XSetWindowColormap (window_private->xdisplay,
1304                          window_private->xwindow,
1305                          colormap_private->xcolormap);
1306     
1307      if (window_private->colormap)
1308        gdk_colormap_unref (window_private->colormap);
1309      window_private->colormap = colormap;
1310      gdk_colormap_ref (window_private->colormap);
1311     
1312      if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
1313        gdk_window_add_colormap_windows (window);
1314    }
1315}
1316
1317void
1318gdk_window_get_user_data (GdkWindow *window,
1319                          gpointer  *data)
1320{
1321  g_return_if_fail (window != NULL);
1322 
1323  *data = window->user_data;
1324}
1325
1326void
1327gdk_window_get_geometry (GdkWindow *window,
1328                         gint      *x,
1329                         gint      *y,
1330                         gint      *width,
1331                         gint      *height,
1332                         gint      *depth)
1333{
1334  GdkWindowPrivate *window_private;
1335  Window root;
1336  gint tx;
1337  gint ty;
1338  guint twidth;
1339  guint theight;
1340  guint tborder_width;
1341  guint tdepth;
1342 
1343  if (!window)
1344    window = (GdkWindow*) &gdk_root_parent;
1345 
1346  window_private = (GdkWindowPrivate*) window;
1347 
1348  if (!window_private->destroyed)
1349    {
1350      XGetGeometry (window_private->xdisplay, window_private->xwindow,
1351                    &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
1352     
1353      if (x)
1354        *x = tx;
1355      if (y)
1356        *y = ty;
1357      if (width)
1358        *width = twidth;
1359      if (height)
1360        *height = theight;
1361      if (depth)
1362        *depth = tdepth;
1363    }
1364}
1365
1366void
1367gdk_window_get_position (GdkWindow *window,
1368                         gint      *x,
1369                         gint      *y)
1370{
1371  GdkWindowPrivate *window_private;
1372 
1373  g_return_if_fail (window != NULL);
1374 
1375  window_private = (GdkWindowPrivate*) window;
1376 
1377  if (x)
1378    *x = window_private->x;
1379  if (y)
1380    *y = window_private->y;
1381}
1382
1383void
1384gdk_window_get_size (GdkWindow *window,
1385                     gint       *width,
1386                     gint       *height)
1387{
1388  GdkWindowPrivate *window_private;
1389 
1390  g_return_if_fail (window != NULL);
1391 
1392  window_private = (GdkWindowPrivate*) window;
1393 
1394  if (width)
1395    *width = window_private->width;
1396  if (height)
1397    *height = window_private->height;
1398}
1399
1400GdkVisual*
1401gdk_window_get_visual (GdkWindow *window)
1402{
1403  GdkWindowPrivate *window_private;
1404  XWindowAttributes window_attributes;
1405 
1406  g_return_val_if_fail (window != NULL, NULL);
1407 
1408  window_private = (GdkWindowPrivate*) window;
1409  /* Huh? ->parent is never set for a pixmap. We should just return
1410   * null immeditately
1411   */
1412  while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
1413    window_private = (GdkWindowPrivate*) window_private->parent;
1414 
1415  if (window_private && !window_private->destroyed)
1416    {
1417      if (window_private->colormap == NULL)
1418        {
1419          XGetWindowAttributes (window_private->xdisplay,
1420                                window_private->xwindow,
1421                                &window_attributes);
1422          return gdk_visual_lookup (window_attributes.visual);
1423        }
1424      else
1425        return ((GdkColormapPrivate *)window_private->colormap)->visual;
1426    }
1427 
1428  return NULL;
1429}
1430
1431GdkColormap*
1432gdk_window_get_colormap (GdkWindow *window)
1433{
1434  GdkWindowPrivate *window_private;
1435  XWindowAttributes window_attributes;
1436 
1437  g_return_val_if_fail (window != NULL, NULL);
1438  window_private = (GdkWindowPrivate*) window;
1439 
1440  g_return_val_if_fail (window_private->window_type != GDK_WINDOW_PIXMAP, NULL);
1441  if (!window_private->destroyed)
1442    {
1443      if (window_private->colormap == NULL)
1444        {
1445          XGetWindowAttributes (window_private->xdisplay,
1446                                window_private->xwindow,
1447                                &window_attributes);
1448          return gdk_colormap_lookup (window_attributes.colormap);
1449        }
1450      else
1451        return window_private->colormap;
1452    }
1453 
1454  return NULL;
1455}
1456
1457GdkWindowType
1458gdk_window_get_type (GdkWindow *window)
1459{
1460  GdkWindowPrivate *window_private;
1461 
1462  g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
1463 
1464  window_private = (GdkWindowPrivate*) window;
1465  return window_private->window_type;
1466}
1467
1468gint
1469gdk_window_get_origin (GdkWindow *window,
1470                       gint      *x,
1471                       gint      *y)
1472{
1473  GdkWindowPrivate *private;
1474  gint return_val;
1475  Window child;
1476  gint tx = 0;
1477  gint ty = 0;
1478 
1479  g_return_val_if_fail (window != NULL, 0);
1480 
1481  private = (GdkWindowPrivate*) window;
1482 
1483  if (!private->destroyed)
1484    {
1485      return_val = XTranslateCoordinates (private->xdisplay,
1486                                          private->xwindow,
1487                                          gdk_root_window,
1488                                          0, 0, &tx, &ty,
1489                                          &child);
1490     
1491    }
1492  else
1493    return_val = 0;
1494 
1495  if (x)
1496    *x = tx;
1497  if (y)
1498    *y = ty;
1499 
1500  return return_val;
1501}
1502
1503gboolean
1504gdk_window_get_deskrelative_origin (GdkWindow *window,
1505                                    gint      *x,
1506                                    gint      *y)
1507{
1508  GdkWindowPrivate *private;
1509  gboolean return_val = FALSE;
1510  gint num_children, format_return;
1511  Window win, *child, parent, root;
1512  gint tx = 0;
1513  gint ty = 0;
1514  Atom type_return;
1515  static Atom atom = 0;
1516  gulong number_return, bytes_after_return;
1517  guchar *data_return;
1518 
1519  g_return_val_if_fail (window != NULL, 0);
1520 
1521  private = (GdkWindowPrivate*) window;
1522 
1523  if (!private->destroyed)
1524    {
1525      if (!atom)
1526        atom = XInternAtom (private->xdisplay, "ENLIGHTENMENT_DESKTOP", False);
1527      win = private->xwindow;
1528     
1529      while (XQueryTree (private->xdisplay, win, &root, &parent,
1530                         &child, (unsigned int *)&num_children))
1531        {
1532          if ((child) && (num_children > 0))
1533            XFree (child);
1534         
1535          if (!parent)
1536            break;
1537          else
1538            win = parent;
1539         
1540          if (win == root)
1541            break;
1542         
1543          data_return = NULL;
1544          XGetWindowProperty (private->xdisplay, win, atom, 0, 0,
1545                              False, XA_CARDINAL, &type_return, &format_return,
1546                              &number_return, &bytes_after_return, &data_return);
1547          if (type_return == XA_CARDINAL)
1548            {
1549              XFree (data_return);
1550              break;
1551            }
1552        }
1553     
1554      return_val = XTranslateCoordinates (private->xdisplay,
1555                                          private->xwindow,
1556                                          win,
1557                                          0, 0, &tx, &ty,
1558                                          &root);
1559      if (x)
1560        *x = tx;
1561      if (y)
1562        *y = ty;
1563    }
1564 
1565 
1566  return return_val;
1567}
1568
1569void
1570gdk_window_get_root_origin (GdkWindow *window,
1571                            gint      *x,
1572                            gint      *y)
1573{
1574  GdkWindowPrivate *private;
1575  Window xwindow;
1576  Window xparent;
1577  Window root;
1578  Window *children;
1579  unsigned int nchildren;
1580 
1581  g_return_if_fail (window != NULL);
1582 
1583  private = (GdkWindowPrivate*) window;
1584  if (x)
1585    *x = 0;
1586  if (y)
1587    *y = 0;
1588  if (private->destroyed)
1589    return;
1590 
1591  while (private->parent && ((GdkWindowPrivate*) private->parent)->parent)
1592    private = (GdkWindowPrivate*) private->parent;
1593  if (private->destroyed)
1594    return;
1595 
1596  xparent = private->xwindow;
1597  do
1598    {
1599      xwindow = xparent;
1600      if (!XQueryTree (private->xdisplay, xwindow,
1601                       &root, &xparent,
1602                       &children, &nchildren))
1603        return;
1604     
1605      if (children)
1606        XFree (children);
1607    }
1608  while (xparent != root);
1609 
1610  if (xparent == root)
1611    {
1612      unsigned int ww, wh, wb, wd;
1613      int wx, wy;
1614     
1615      if (XGetGeometry (private->xdisplay, xwindow, &root, &wx, &wy, &ww, &wh, &wb, &wd))
1616        {
1617          if (x)
1618            *x = wx;
1619          if (y)
1620            *y = wy;
1621        }
1622    }
1623}
1624
1625GdkWindow*
1626gdk_window_get_pointer (GdkWindow       *window,
1627                        gint            *x,
1628                        gint            *y,
1629                        GdkModifierType *mask)
1630{
1631  GdkWindowPrivate *private;
1632  GdkWindow *return_val;
1633  Window root;
1634  Window child;
1635  int rootx, rooty;
1636  int winx = 0;
1637  int winy = 0;
1638  unsigned int xmask = 0;
1639 
1640  if (!window)
1641    window = (GdkWindow*) &gdk_root_parent;
1642 
1643  private = (GdkWindowPrivate*) window;
1644 
1645  return_val = NULL;
1646  if (!private->destroyed &&
1647      XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
1648                     &rootx, &rooty, &winx, &winy, &xmask))
1649    {
1650      if (child)
1651        return_val = gdk_window_lookup (child);
1652    }
1653 
1654  if (x)
1655    *x = winx;
1656  if (y)
1657    *y = winy;
1658  if (mask)
1659    *mask = xmask;
1660 
1661  return return_val;
1662}
1663
1664GdkWindow*
1665gdk_window_at_pointer (gint *win_x,
1666                       gint *win_y)
1667{
1668  GdkWindowPrivate *private;
1669  GdkWindow *window;
1670  Window root;
1671  Window xwindow;
1672  Window xwindow_last = 0;
1673  int rootx = -1, rooty = -1;
1674  int winx, winy;
1675  unsigned int xmask;
1676 
1677  private = &gdk_root_parent;
1678 
1679  xwindow = private->xwindow;
1680 
1681  XGrabServer (private->xdisplay);
1682  while (xwindow)
1683    {
1684      xwindow_last = xwindow;
1685      XQueryPointer (private->xdisplay,
1686                     xwindow,
1687                     &root, &xwindow,
1688                     &rootx, &rooty,
1689                     &winx, &winy,
1690                     &xmask);
1691    }
1692  XUngrabServer (private->xdisplay);
1693 
1694  window = gdk_window_lookup (xwindow_last);
1695 
1696  if (win_x)
1697    *win_x = window ? winx : -1;
1698  if (win_y)
1699    *win_y = window ? winy : -1;
1700 
1701  return window;
1702}
1703
1704GdkWindow*
1705gdk_window_get_parent (GdkWindow *window)
1706{
1707  g_return_val_if_fail (window != NULL, NULL);
1708 
1709  return ((GdkWindowPrivate*) window)->parent;
1710}
1711
1712GdkWindow*
1713gdk_window_get_toplevel (GdkWindow *window)
1714{
1715  GdkWindowPrivate *private;
1716 
1717  g_return_val_if_fail (window != NULL, NULL);
1718 
1719  private = (GdkWindowPrivate*) window;
1720 
1721  while (private->window_type == GDK_WINDOW_CHILD)
1722    {
1723      window = ((GdkWindowPrivate*) window)->parent;
1724      private = (GdkWindowPrivate*) window;
1725    }
1726 
1727  return window;
1728}
1729
1730GList*
1731gdk_window_get_children (GdkWindow *window)
1732{
1733  GdkWindowPrivate *private;
1734  GdkWindow *child;
1735  GList *children;
1736  Window root;
1737  Window parent;
1738  Window *xchildren;
1739  unsigned int nchildren;
1740  unsigned int i;
1741 
1742  g_return_val_if_fail (window != NULL, NULL);
1743 
1744  private = (GdkWindowPrivate*) window;
1745  if (private->destroyed)
1746    return NULL;
1747 
1748  XQueryTree (private->xdisplay, private->xwindow,
1749              &root, &parent, &xchildren, &nchildren);
1750 
1751  children = NULL;
1752 
1753  if (nchildren > 0)
1754    {
1755      for (i = 0; i < nchildren; i++)
1756        {
1757          child = gdk_window_lookup (xchildren[i]);
1758          if (child)
1759            children = g_list_prepend (children, child);
1760        }
1761     
1762      if (xchildren)
1763        XFree (xchildren);
1764    }
1765 
1766  return children;
1767}
1768
1769GdkEventMask 
1770gdk_window_get_events (GdkWindow *window)
1771{
1772  GdkWindowPrivate *private;
1773  XWindowAttributes attrs;
1774  GdkEventMask event_mask;
1775  int i;
1776 
1777  g_return_val_if_fail (window != NULL, 0);
1778 
1779  private = (GdkWindowPrivate*) window;
1780  if (private->destroyed)
1781    return 0;
1782 
1783  XGetWindowAttributes (gdk_display, private->xwindow,
1784                        &attrs);
1785 
1786  event_mask = 0;
1787  for (i = 0; i < gdk_nevent_masks; i++)
1788    {
1789      if (attrs.your_event_mask & gdk_event_mask_table[i])
1790        event_mask |= 1 << (i + 1);
1791    }
1792 
1793  return event_mask;
1794}
1795
1796void         
1797gdk_window_set_events (GdkWindow       *window,
1798                       GdkEventMask     event_mask)
1799{
1800  GdkWindowPrivate *private;
1801  long xevent_mask;
1802  int i;
1803 
1804  g_return_if_fail (window != NULL);
1805 
1806  private = (GdkWindowPrivate*) window;
1807  if (private->destroyed)
1808    return;
1809 
1810  xevent_mask = StructureNotifyMask;
1811  for (i = 0; i < gdk_nevent_masks; i++)
1812    {
1813      if (event_mask & (1 << (i + 1)))
1814        xevent_mask |= gdk_event_mask_table[i];
1815    }
1816 
1817  XSelectInput (gdk_display, private->xwindow,
1818                xevent_mask);
1819}
1820
1821void
1822gdk_window_add_colormap_windows (GdkWindow *window)
1823{
1824  GdkWindow *toplevel;
1825  GdkWindowPrivate *toplevel_private;
1826  GdkWindowPrivate *window_private;
1827  Window *old_windows;
1828  Window *new_windows;
1829  int i, count;
1830 
1831  g_return_if_fail (window != NULL);
1832 
1833  toplevel = gdk_window_get_toplevel (window);
1834  toplevel_private = (GdkWindowPrivate*) toplevel;
1835  window_private = (GdkWindowPrivate*) window;
1836  if (window_private->destroyed)
1837    return;
1838 
1839  old_windows = NULL;
1840  if (!XGetWMColormapWindows (toplevel_private->xdisplay,
1841                              toplevel_private->xwindow,
1842                              &old_windows, &count))
1843    {
1844      count = 0;
1845    }
1846 
1847  for (i = 0; i < count; i++)
1848    if (old_windows[i] == window_private->xwindow)
1849      {
1850        XFree (old_windows);
1851        return;
1852      }
1853 
1854  new_windows = g_new (Window, count + 1);
1855 
1856  for (i = 0; i < count; i++)
1857    new_windows[i] = old_windows[i];
1858  new_windows[count] = window_private->xwindow;
1859 
1860  XSetWMColormapWindows (toplevel_private->xdisplay,
1861                         toplevel_private->xwindow,
1862                         new_windows, count + 1);
1863 
1864  g_free (new_windows);
1865  if (old_windows)
1866    XFree (old_windows);
1867}
1868
1869static gboolean
1870gdk_window_have_shape_ext (void)
1871{
1872  enum { UNKNOWN, NO, YES };
1873  static gint have_shape = UNKNOWN;
1874 
1875  if (have_shape == UNKNOWN)
1876    {
1877      int ignore;
1878      if (XQueryExtension (gdk_display, "SHAPE", &ignore, &ignore, &ignore))
1879        have_shape = YES;
1880      else
1881        have_shape = NO;
1882    }
1883 
1884  return (have_shape == YES);
1885}
1886
1887/*
1888 * This needs the X11 shape extension.
1889 * If not available, shaped windows will look
1890 * ugly, but programs still work.    Stefan Wille
1891 */
1892void
1893gdk_window_shape_combine_mask (GdkWindow *window,
1894                               GdkBitmap *mask,
1895                               gint x, gint y)
1896{
1897  GdkWindowPrivate *window_private;
1898  Pixmap pixmap;
1899 
1900  g_return_if_fail (window != NULL);
1901 
1902#ifdef HAVE_SHAPE_EXT
1903  window_private = (GdkWindowPrivate*) window;
1904  if (window_private->destroyed)
1905    return;
1906 
1907  if (gdk_window_have_shape_ext ())
1908    {
1909      if (mask)
1910        {
1911          GdkWindowPrivate *pixmap_private;
1912         
1913          pixmap_private = (GdkWindowPrivate*) mask;
1914          pixmap = (Pixmap) pixmap_private->xwindow;
1915        }
1916      else
1917        {
1918          x = 0;
1919          y = 0;
1920          pixmap = None;
1921        }
1922     
1923      XShapeCombineMask (window_private->xdisplay,
1924                         window_private->xwindow,
1925                         ShapeBounding,
1926                         x, y,
1927                         pixmap,
1928                         ShapeSet);
1929    }
1930#endif /* HAVE_SHAPE_EXT */
1931}
1932
1933void         
1934gdk_window_add_filter (GdkWindow     *window,
1935                       GdkFilterFunc  function,
1936                       gpointer       data)
1937{
1938  GdkWindowPrivate *private;
1939  GList *tmp_list;
1940  GdkEventFilter *filter;
1941 
1942  private = (GdkWindowPrivate*) window;
1943  if (private && private->destroyed)
1944    return;
1945 
1946  if (private)
1947    tmp_list = private->filters;
1948  else
1949    tmp_list = gdk_default_filters;
1950 
1951  while (tmp_list)
1952    {
1953      filter = (GdkEventFilter *)tmp_list->data;
1954      if ((filter->function == function) && (filter->data == data))
1955        return;
1956      tmp_list = tmp_list->next;
1957    }
1958 
1959  filter = g_new (GdkEventFilter, 1);
1960  filter->function = function;
1961  filter->data = data;
1962 
1963  if (private)
1964    private->filters = g_list_append (private->filters, filter);
1965  else
1966    gdk_default_filters = g_list_append (gdk_default_filters, filter);
1967}
1968
1969void
1970gdk_window_remove_filter (GdkWindow     *window,
1971                          GdkFilterFunc  function,
1972                          gpointer       data)
1973{
1974  GdkWindowPrivate *private;
1975  GList *tmp_list, *node;
1976  GdkEventFilter *filter;
1977 
1978  private = (GdkWindowPrivate*) window;
1979 
1980  if (private)
1981    tmp_list = private->filters;
1982  else
1983    tmp_list = gdk_default_filters;
1984 
1985  while (tmp_list)
1986    {
1987      filter = (GdkEventFilter *)tmp_list->data;
1988      node = tmp_list;
1989      tmp_list = tmp_list->next;
1990     
1991      if ((filter->function == function) && (filter->data == data))
1992        {
1993          if (private)
1994            private->filters = g_list_remove_link (private->filters, node);
1995          else
1996            gdk_default_filters = g_list_remove_link (gdk_default_filters, node);
1997          g_list_free_1 (node);
1998          g_free (filter);
1999         
2000          return;
2001        }
2002    }
2003}
2004
2005void
2006gdk_window_set_override_redirect (GdkWindow *window,
2007                                  gboolean override_redirect)
2008{
2009  GdkWindowPrivate *private;
2010  XSetWindowAttributes attr;
2011 
2012  g_return_if_fail (window != NULL);
2013  private = (GdkWindowPrivate*) window;
2014  if (private->destroyed)
2015    return;
2016 
2017  attr.override_redirect = (override_redirect == FALSE)?False:True;
2018  XChangeWindowAttributes (gdk_display,
2019                           ((GdkWindowPrivate *)window)->xwindow,
2020                           CWOverrideRedirect,
2021                           &attr);
2022}
2023
2024void         
2025gdk_window_set_icon (GdkWindow *window,
2026                     GdkWindow *icon_window,
2027                     GdkPixmap *pixmap,
2028                     GdkBitmap *mask)
2029{
2030  XWMHints *wm_hints;
2031  GdkWindowPrivate *window_private;
2032  GdkWindowPrivate *private;
2033 
2034  g_return_if_fail (window != NULL);
2035  window_private = (GdkWindowPrivate*) window;
2036  if (window_private->destroyed)
2037    return;
2038
2039  wm_hints = XGetWMHints (window_private->xdisplay, window_private->xwindow);
2040  if (!wm_hints)
2041    wm_hints = XAllocWMHints ();
2042
2043  if (icon_window != NULL)
2044    {
2045      private = (GdkWindowPrivate *)icon_window;
2046      wm_hints->flags |= IconWindowHint;
2047      wm_hints->icon_window = private->xwindow;
2048    }
2049 
2050  if (pixmap != NULL)
2051    {
2052      private = (GdkWindowPrivate *)pixmap;
2053      wm_hints->flags |= IconPixmapHint;
2054      wm_hints->icon_pixmap = private->xwindow;
2055    }
2056 
2057  if (mask != NULL)
2058    {
2059      private = (GdkWindowPrivate *)mask;
2060      wm_hints->flags |= IconMaskHint;
2061      wm_hints->icon_mask = private->xwindow;
2062    }
2063
2064  XSetWMHints (window_private->xdisplay, window_private->xwindow, wm_hints);
2065  XFree (wm_hints);
2066}
2067
2068void         
2069gdk_window_set_icon_name (GdkWindow   *window,
2070                          const gchar *name)
2071{
2072  GdkWindowPrivate *window_private;
2073  XTextProperty property;
2074  gint res;
2075 
2076  g_return_if_fail (window != NULL);
2077  window_private = (GdkWindowPrivate*) window;
2078  if (window_private->destroyed)
2079    return;
2080  res = XmbTextListToTextProperty (window_private->xdisplay,
2081                                   &name, 1, XStdICCTextStyle,
2082                                   &property);
2083  if (res < 0)
2084    {
2085      g_warning ("Error converting icon name to text property: %d\n", res);
2086      return;
2087    }
2088 
2089  XSetWMIconName (window_private->xdisplay, window_private->xwindow,
2090                  &property);
2091 
2092  if (property.value)
2093    XFree (property.value);
2094}
2095
2096void         
2097gdk_window_set_group (GdkWindow *window,
2098                      GdkWindow *leader)
2099{
2100  XWMHints *wm_hints;
2101  GdkWindowPrivate *window_private;
2102  GdkWindowPrivate *private;
2103 
2104  g_return_if_fail (window != NULL);
2105  g_return_if_fail (leader != NULL);
2106  window_private = (GdkWindowPrivate*) window;
2107  if (window_private->destroyed)
2108    return;
2109 
2110  private = (GdkWindowPrivate *)leader;
2111
2112  wm_hints = XGetWMHints (window_private->xdisplay, window_private->xwindow);
2113  if (!wm_hints)
2114    wm_hints = XAllocWMHints ();
2115
2116  wm_hints->flags |= WindowGroupHint;
2117  wm_hints->window_group = private->xwindow;
2118
2119  XSetWMHints (window_private->xdisplay, window_private->xwindow, wm_hints);
2120  XFree (wm_hints);
2121}
2122
2123static void
2124gdk_window_set_mwm_hints (GdkWindow *window,
2125                          MotifWmHints *new_hints)
2126{
2127  static Atom hints_atom = None;
2128  MotifWmHints *hints;
2129  Atom type;
2130  gint format;
2131  gulong nitems;
2132  gulong bytes_after;
2133 
2134  GdkWindowPrivate *window_private;
2135 
2136  g_return_if_fail (window != NULL);
2137  window_private = (GdkWindowPrivate*) window;
2138  if (window_private->destroyed)
2139    return;
2140 
2141  if (!hints_atom)
2142    hints_atom = XInternAtom (window_private->xdisplay,
2143                              _XA_MOTIF_WM_HINTS, FALSE);
2144 
2145  XGetWindowProperty (window_private->xdisplay, window_private->xwindow,
2146                      hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
2147                      False, AnyPropertyType, &type, &format, &nitems,
2148                      &bytes_after, (guchar **)&hints);
2149 
2150  if (type == None)
2151    hints = new_hints;
2152  else
2153    {
2154      if (new_hints->flags & MWM_HINTS_FUNCTIONS)
2155        {
2156          hints->flags |= MWM_HINTS_FUNCTIONS;
2157          hints->functions = new_hints->functions;
2158        }
2159      if (new_hints->flags & MWM_HINTS_DECORATIONS)
2160        {
2161          hints->flags |= MWM_HINTS_DECORATIONS;
2162          hints->decorations = new_hints->decorations;
2163        }
2164    }
2165 
2166  XChangeProperty (window_private->xdisplay, window_private->xwindow,
2167                   hints_atom, hints_atom, 32, PropModeReplace,
2168                   (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
2169 
2170  if (hints != new_hints)
2171    XFree (hints);
2172}
2173
2174void
2175gdk_window_set_decorations (GdkWindow      *window,
2176                            GdkWMDecoration decorations)
2177{
2178  MotifWmHints hints;
2179 
2180  hints.flags = MWM_HINTS_DECORATIONS;
2181  hints.decorations = decorations;
2182 
2183  gdk_window_set_mwm_hints (window, &hints);
2184}
2185
2186void
2187gdk_window_set_functions (GdkWindow    *window,
2188                          GdkWMFunction functions)
2189{
2190  MotifWmHints hints;
2191 
2192  hints.flags = MWM_HINTS_FUNCTIONS;
2193  hints.functions = functions;
2194 
2195  gdk_window_set_mwm_hints (window, &hints);
2196}
2197
2198GList *
2199gdk_window_get_toplevels (void)
2200{
2201  GList *new_list = NULL;
2202  GList *tmp_list;
2203 
2204  tmp_list = gdk_root_parent.children;
2205  while (tmp_list)
2206    {
2207      new_list = g_list_prepend (new_list, tmp_list->data);
2208      tmp_list = tmp_list->next;
2209    }
2210 
2211  return new_list;
2212}
2213
2214#ifdef HAVE_SHAPE_EXT
2215
2216/*
2217 * propagate the shapes from all child windows of a GDK window to the parent
2218 * window. Shamelessly ripped from Enlightenment's code
2219 *
2220 * - Raster
2221 */
2222
2223struct _gdk_span
2224{
2225  gint                start;
2226  gint                end;
2227  struct _gdk_span    *next;
2228};
2229
2230static void
2231gdk_add_to_span (struct _gdk_span **s,
2232                 gint               x,
2233                 gint               xx)
2234{
2235  struct _gdk_span *ptr1, *ptr2, *noo, *ss;
2236  gchar             spanning;
2237 
2238  ptr2 = NULL;
2239  ptr1 = *s;
2240  spanning = 0;
2241  ss = NULL;
2242  /* scan the spans for this line */
2243  while (ptr1)
2244    {
2245      /* -- -> new span */
2246      /* == -> existing span */
2247      /* ## -> spans intersect */
2248      /* if we are in the middle of spanning the span into the line */
2249      if (spanning)
2250        {
2251          /* case: ---- ==== */
2252          if (xx < ptr1->start - 1)
2253            {
2254              /* ends before next span - extend to here */
2255              ss->end = xx;
2256              return;
2257            }
2258          /* case: ----##=== */
2259          else if (xx <= ptr1->end)
2260            {
2261              /* crosses into next span - delete next span and append */
2262              ss->end = ptr1->end;
2263              ss->next = ptr1->next;
2264              g_free (ptr1);
2265              return;
2266            }
2267          /* case: ---###--- */
2268          else
2269            {
2270              /* overlaps next span - delete and keep checking */
2271              ss->next = ptr1->next;
2272              g_free (ptr1);
2273              ptr1 = ss;
2274            }
2275        }
2276      /* otherwise havent started spanning it in yet */
2277      else
2278        {
2279          /* case: ---- ==== */
2280          if (xx < ptr1->start - 1)
2281            {
2282              /* insert span here in list */
2283              noo = g_malloc (sizeof (struct _gdk_span));
2284             
2285              if (noo)
2286                {
2287                  noo->start = x;
2288                  noo->end = xx;
2289                  noo->next = ptr1;
2290                  if (ptr2)
2291                    ptr2->next = noo;
2292                  else
2293                    *s = noo;
2294                }
2295              return;
2296            }
2297          /* case: ----##=== */
2298          else if ((x < ptr1->start) && (xx <= ptr1->end))
2299            {
2300              /* expand this span to the left point of the new one */
2301              ptr1->start = x;
2302              return;
2303            }
2304          /* case: ===###=== */
2305          else if ((x >= ptr1->start) && (xx <= ptr1->end))
2306            {
2307              /* throw the span away */
2308              return;
2309            }
2310          /* case: ---###--- */
2311          else if ((x < ptr1->start) && (xx > ptr1->end))
2312            {
2313              ss = ptr1;
2314              spanning = 1;
2315              ptr1->start = x;
2316              ptr1->end = xx;
2317            }
2318          /* case: ===##---- */
2319          else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end))
2320            {
2321              ss = ptr1;
2322              spanning = 1;
2323              ptr1->end = xx;
2324            }
2325          /* case: ==== ---- */
2326          /* case handled by next loop iteration - first case */
2327        }
2328      ptr2 = ptr1;
2329      ptr1 = ptr1->next;
2330    }
2331  /* it started in the middle but spans beyond your current list */
2332  if (spanning)
2333    {
2334      ptr2->end = xx;
2335      return;
2336    }
2337  /* it does not start inside a span or in the middle, so add it to the end */
2338  noo = g_malloc (sizeof (struct _gdk_span));
2339 
2340  if (noo)
2341    {
2342      noo->start = x;
2343      noo->end = xx;
2344      if (ptr2)
2345        {
2346          noo->next = ptr2->next;
2347          ptr2->next = noo;
2348        }
2349      else
2350        {
2351          noo->next = NULL;
2352          *s = noo;
2353        }
2354    }
2355  return;
2356}
2357
2358static void
2359gdk_add_rectangles (Display           *disp,
2360                    Window             win,
2361                    struct _gdk_span **spans,
2362                    gint               basew,
2363                    gint               baseh,
2364                    gint               x,
2365                    gint               y)
2366{
2367  gint a, k;
2368  gint x1, y1, x2, y2;
2369  gint rn, ord;
2370  XRectangle *rl;
2371 
2372  rl = XShapeGetRectangles (disp, win, ShapeBounding, &rn, &ord);
2373  if (rl)
2374    {
2375      /* go through all clip rects in this window's shape */
2376      for (k = 0; k < rn; k++)
2377        {
2378          /* for each clip rect, add it to each line's spans */
2379          x1 = x + rl[k].x;
2380          x2 = x + rl[k].x + (rl[k].width - 1);
2381          y1 = y + rl[k].y;
2382          y2 = y + rl[k].y + (rl[k].height - 1);
2383          if (x1 < 0)
2384            x1 = 0;
2385          if (y1 < 0)
2386            y1 = 0;
2387          if (x2 >= basew)
2388            x2 = basew - 1;
2389          if (y2 >= baseh)
2390            y2 = baseh - 1;
2391          for (a = y1; a <= y2; a++)
2392            {
2393              if ((x2 - x1) >= 0)
2394                gdk_add_to_span (&spans[a], x1, x2);
2395            }
2396        }
2397      XFree (rl);
2398    }
2399}
2400
2401static void
2402gdk_propagate_shapes (Display *disp,
2403                      Window   win,
2404                      gboolean merge)
2405{
2406  Window              rt, par, *list = NULL;
2407  gint                i, j, num = 0, num_rects = 0;
2408  gint                x, y, contig;
2409  guint               w, h, d;
2410  gint                baseh, basew;
2411  XRectangle         *rects = NULL;
2412  struct _gdk_span  **spans = NULL, *ptr1, *ptr2, *ptr3;
2413  XWindowAttributes   xatt;
2414 
2415  XGetGeometry (disp, win, &rt, &x, &y, &w, &h, &d, &d);
2416  if (h <= 0)
2417    return;
2418  basew = w;
2419  baseh = h;
2420  spans = g_malloc (sizeof (struct _gdk_span *) * h);
2421 
2422  for (i = 0; i < h; i++)
2423    spans[i] = NULL;
2424  XQueryTree (disp, win, &rt, &par, &list, (unsigned int *)&num);
2425  if (list)
2426    {
2427      /* go through all child windows and create/insert spans */
2428      for (i = 0; i < num; i++)
2429        {
2430          if (XGetWindowAttributes (disp, list[i], &xatt) && (xatt.map_state != IsUnmapped))
2431            if (XGetGeometry (disp, list[i], &rt, &x, &y, &w, &h, &d, &d))
2432              gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y);
2433        }
2434      if (merge)
2435        gdk_add_rectangles (disp, win, spans, basew, baseh, x, y);
2436     
2437      /* go through the spans list and build a list of rects */
2438      rects = g_malloc (sizeof (XRectangle) * 256);
2439      num_rects = 0;
2440      for (i = 0; i < baseh; i++)
2441        {
2442          ptr1 = spans[i];
2443          /* go through the line for all spans */
2444          while (ptr1)
2445            {
2446              rects[num_rects].x = ptr1->start;
2447              rects[num_rects].y = i;
2448              rects[num_rects].width = ptr1->end - ptr1->start + 1;
2449              rects[num_rects].height = 1;
2450              j = i + 1;
2451              /* if there are more lines */
2452              contig = 1;
2453              /* while contigous rects (same start/end coords) exist */
2454              while ((contig) && (j < baseh))
2455                {
2456                  /* search next line for spans matching this one */
2457                  contig = 0;
2458                  ptr2 = spans[j];
2459                  ptr3 = NULL;
2460                  while (ptr2)
2461                    {
2462                      /* if we have an exact span match set contig */
2463                      if ((ptr2->start == ptr1->start) &&
2464                          (ptr2->end == ptr1->end))
2465                        {
2466                          contig = 1;
2467                          /* remove the span - not needed */
2468                          if (ptr3)
2469                            {
2470                              ptr3->next = ptr2->next;
2471                              g_free (ptr2);
2472                              ptr2 = NULL;
2473                            }
2474                          else
2475                            {
2476                              spans[j] = ptr2->next;
2477                              g_free (ptr2);
2478                              ptr2 = NULL;
2479                            }
2480                          break;
2481                        }
2482                      /* gone past the span point no point looking */
2483                      else if (ptr2->start < ptr1->start)
2484                        break;
2485                      if (ptr2)
2486                        {
2487                          ptr3 = ptr2;
2488                          ptr2 = ptr2->next;
2489                        }
2490                    }
2491                  /* if a contiguous span was found increase the rect h */
2492                  if (contig)
2493                    {
2494                      rects[num_rects].height++;
2495                      j++;
2496                    }
2497                }
2498              /* up the rect count */
2499              num_rects++;
2500              /* every 256 new rects increase the rect array */
2501              if ((num_rects % 256) == 0)
2502                rects = g_realloc (rects, sizeof (XRectangle) * (num_rects + 256));
2503              ptr1 = ptr1->next;
2504            }
2505        }
2506      /* set the rects as the shape mask */
2507      if (rects)
2508        {
2509          XShapeCombineRectangles (disp, win, ShapeBounding, 0, 0, rects, num_rects,
2510                                   ShapeSet, YXSorted);
2511          g_free (rects);
2512        }
2513      XFree (list);
2514    }
2515  /* free up all the spans we made */
2516  for (i = 0; i < baseh; i++)
2517    {
2518      ptr1 = spans[i];
2519      while (ptr1)
2520        {
2521          ptr2 = ptr1;
2522          ptr1 = ptr1->next;
2523          g_free (ptr2);
2524        }
2525    }
2526  g_free (spans);
2527}
2528
2529#endif /* HAVE_SHAPE_EXT */
2530
2531void
2532gdk_window_set_child_shapes (GdkWindow *window)
2533{
2534  GdkWindowPrivate *private;
2535 
2536  g_return_if_fail (window != NULL);
2537 
2538#ifdef HAVE_SHAPE_EXT
2539  private = (GdkWindowPrivate*) window;
2540  if (private->destroyed)
2541    return;
2542 
2543  if (gdk_window_have_shape_ext ())
2544    gdk_propagate_shapes (private->xdisplay, private->xwindow, FALSE);
2545#endif   
2546}
2547
2548void
2549gdk_window_merge_child_shapes (GdkWindow *window)
2550{
2551  GdkWindowPrivate *private;
2552 
2553  g_return_if_fail (window != NULL);
2554 
2555#ifdef HAVE_SHAPE_EXT
2556  private = (GdkWindowPrivate*) window;
2557  if (private->destroyed)
2558    return;
2559 
2560  if (gdk_window_have_shape_ext ())
2561    gdk_propagate_shapes (private->xdisplay, private->xwindow, TRUE);
2562#endif   
2563}
2564
2565/*************************************************************
2566 * gdk_window_is_visible:
2567 *     Check if the given window is mapped.
2568 *   arguments:
2569 *     window:
2570 *   results:
2571 *     is the window mapped
2572 *************************************************************/
2573
2574gboolean
2575gdk_window_is_visible (GdkWindow *window)
2576{
2577  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2578 
2579  g_return_val_if_fail (window != NULL, FALSE);
2580 
2581  return private->mapped;
2582}
2583
2584/*************************************************************
2585 * gdk_window_is_viewable:
2586 *     Check if the window and all ancestors of the window
2587 *     are mapped. (This is not necessarily "viewable" in
2588 *     the X sense, since we only check as far as we have
2589 *     GDK window parents, not to the root window)
2590 *   arguments:
2591 *     window:
2592 *   results:
2593 *     is the window viewable
2594 *************************************************************/
2595
2596gboolean
2597gdk_window_is_viewable (GdkWindow *window)
2598{
2599  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2600 
2601  g_return_val_if_fail (window != NULL, FALSE);
2602 
2603  while (private &&
2604         (private != &gdk_root_parent) &&
2605         (private->window_type != GDK_WINDOW_FOREIGN))
2606    {
2607      if (!private->mapped)
2608        return FALSE;
2609     
2610      private = (GdkWindowPrivate *)private->parent;
2611    }
2612 
2613  return TRUE;
2614}
2615
2616void         
2617gdk_drawable_set_data (GdkDrawable   *drawable,
2618                       const gchar   *key,
2619                       gpointer       data,
2620                       GDestroyNotify destroy_func)
2621{
2622  g_dataset_set_data_full (drawable, key, data, destroy_func);
2623}
2624
2625
2626/* Support for windows that can be guffaw-scrolled
2627 * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
2628 */
2629
2630static gboolean
2631gdk_window_gravity_works (void)
2632{
2633  enum { UNKNOWN, NO, YES };
2634  static gint gravity_works = UNKNOWN;
2635 
2636  if (gravity_works == UNKNOWN)
2637    {
2638      GdkWindowAttr attr;
2639      GdkWindow *parent;
2640      GdkWindow *child;
2641      gint y;
2642     
2643      /* This particular server apparently has a bug so that the test
2644       * works but the actual code crashes it
2645       */
2646      if ((!strcmp (XServerVendor (gdk_display), "Sun Microsystems, Inc.")) &&
2647          (VendorRelease (gdk_display) == 3400))
2648        {
2649          gravity_works = NO;
2650          return FALSE;
2651        }
2652     
2653      attr.window_type = GDK_WINDOW_TEMP;
2654      attr.wclass = GDK_INPUT_OUTPUT;
2655      attr.x = 0;
2656      attr.y = 0;
2657      attr.width = 100;
2658      attr.height = 100;
2659      attr.event_mask = 0;
2660     
2661      parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
2662     
2663      attr.window_type = GDK_WINDOW_CHILD;
2664      child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
2665     
2666      gdk_window_set_static_win_gravity (child, TRUE);
2667     
2668      gdk_window_resize (parent, 100, 110);
2669      gdk_window_move (parent, 0, -10);
2670      gdk_window_move_resize (parent, 0, 0, 100, 100);
2671     
2672      gdk_window_resize (parent, 100, 110);
2673      gdk_window_move (parent, 0, -10);
2674      gdk_window_move_resize (parent, 0, 0, 100, 100);
2675     
2676      gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
2677     
2678      gdk_window_destroy (parent);
2679      gdk_window_destroy (child);
2680     
2681      gravity_works = ((y == -20) ? YES : NO);
2682    }
2683 
2684  return (gravity_works == YES);
2685}
2686
2687static void
2688gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
2689{
2690  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2691  XSetWindowAttributes xattributes;
2692 
2693  g_return_if_fail (window != NULL);
2694 
2695  xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
2696  XChangeWindowAttributes (private->xdisplay,
2697                           private->xwindow,
2698                           CWBitGravity,  &xattributes);
2699}
2700
2701static void
2702gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
2703{
2704  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2705  XSetWindowAttributes xattributes;
2706 
2707  g_return_if_fail (window != NULL);
2708 
2709  xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
2710 
2711  XChangeWindowAttributes (private->xdisplay,
2712                           private->xwindow,
2713                           CWWinGravity,  &xattributes);
2714}
2715
2716/*************************************************************
2717 * gdk_window_set_static_gravities:
2718 *     Set the bit gravity of the given window to static,
2719 *     and flag it so all children get static subwindow
2720 *     gravity.
2721 *   arguments:
2722 *     window: window for which to set static gravity
2723 *     use_static: Whether to turn static gravity on or off.
2724 *   results:
2725 *     Does the XServer support static gravity?
2726 *************************************************************/
2727
2728gboolean
2729gdk_window_set_static_gravities (GdkWindow *window,
2730                                 gboolean   use_static)
2731{
2732  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2733  GList *tmp_list;
2734 
2735  g_return_val_if_fail (window != NULL, FALSE);
2736 
2737  if (!use_static == !private->guffaw_gravity)
2738    return TRUE;
2739 
2740  if (use_static && !gdk_window_gravity_works ())
2741    return FALSE;
2742 
2743  private->guffaw_gravity = use_static;
2744 
2745  gdk_window_set_static_bit_gravity (window, use_static);
2746 
2747  tmp_list = private->children;
2748  while (tmp_list)
2749    {
2750      gdk_window_set_static_win_gravity (window, use_static);
2751     
2752      tmp_list = tmp_list->next;
2753    }
2754 
2755  return TRUE;
2756}
Note: See TracBrowser for help on using the repository browser.