]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkwindow-x11.c
Cleanups
[~andy/gtk] / gdk / x11 / gdkwindow-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3  * Josh MacDonald, Ryan Lortie
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "config.h"
29
30 #include <X11/Xlib.h>
31 #include <X11/Xutil.h>
32 #include <X11/Xatom.h>
33
34 #ifdef HAVE_XKB
35 #include <X11/XKBlib.h>
36 #endif
37
38 #include <netinet/in.h>
39 #include <unistd.h>
40
41 #include "gdk.h"
42
43 #include "gdkwindow.h"
44 #include "gdkwindowimpl.h"
45 #include "gdkasync.h"
46 #include "gdkinputprivate.h"
47 #include "gdkdisplay-x11.h"
48 #include "gdkprivate-x11.h"
49 #include "gdkregion.h"
50 #include "gdkinternals.h"
51 #include "MwmUtil.h"
52 #include "gdkwindow-x11.h"
53 #include "gdkalias.h"
54
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <string.h>
58
59
60 #include <X11/extensions/shape.h>
61
62 #ifdef HAVE_XCOMPOSITE
63 #include <X11/extensions/Xcomposite.h>
64 #endif
65
66 #ifdef HAVE_XFIXES
67 #include <X11/extensions/Xfixes.h>
68 #endif
69
70 #ifdef HAVE_XDAMAGE
71 #include <X11/extensions/Xdamage.h>
72 #endif
73
74 const int _gdk_event_mask_table[21] =
75 {
76   ExposureMask,
77   PointerMotionMask,
78   PointerMotionHintMask,
79   ButtonMotionMask,
80   Button1MotionMask,
81   Button2MotionMask,
82   Button3MotionMask,
83   ButtonPressMask,
84   ButtonReleaseMask,
85   KeyPressMask,
86   KeyReleaseMask,
87   EnterWindowMask,
88   LeaveWindowMask,
89   FocusChangeMask,
90   StructureNotifyMask,
91   PropertyChangeMask,
92   VisibilityChangeMask,
93   0,                            /* PROXIMITY_IN */
94   0,                            /* PROXIMTY_OUT */
95   SubstructureNotifyMask,
96   ButtonPressMask      /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
97 };
98 const int _gdk_nenvent_masks = sizeof (_gdk_event_mask_table) / sizeof (int);
99
100 /* Forward declarations */
101 static void     gdk_window_set_static_win_gravity (GdkWindow  *window,
102                                                    gboolean    on);
103 static gboolean gdk_window_icon_name_set          (GdkWindow  *window);
104 static void     gdk_window_add_colormap_windows   (GdkWindow  *window);
105 static void     set_wm_name                       (GdkDisplay  *display,
106                                                    Window       xwindow,
107                                                    const gchar *name);
108 static void     move_to_current_desktop           (GdkWindow *window);
109
110 static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
111 static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
112                                                       GdkColormap *cmap);
113 static void        gdk_window_impl_x11_finalize   (GObject            *object);
114 static void        gdk_window_impl_iface_init     (GdkWindowImplIface *iface);
115
116 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
117   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
118    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
119
120 #define WINDOW_IS_TOPLEVEL(window)                   \
121   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
122    GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
123    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
124
125 /* Return whether time1 is considered later than time2 as far as xserver
126  * time is concerned.  Accounts for wraparound.
127  */
128 #define XSERVER_TIME_IS_LATER(time1, time2)                        \
129   ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
130     (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
131   )
132
133 G_DEFINE_TYPE_WITH_CODE (GdkWindowImplX11,
134                          gdk_window_impl_x11,
135                          GDK_TYPE_DRAWABLE_IMPL_X11,
136                          G_IMPLEMENT_INTERFACE (GDK_TYPE_WINDOW_IMPL,
137                                                 gdk_window_impl_iface_init));
138
139 GType
140 _gdk_window_impl_get_type (void)
141 {
142   return gdk_window_impl_x11_get_type ();
143 }
144
145 static void
146 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
147 {  
148   impl->toplevel_window_type = -1;
149 }
150
151 GdkToplevelX11 *
152 _gdk_x11_window_get_toplevel (GdkWindow *window)
153 {
154   GdkWindowObject *private;
155   GdkWindowImplX11 *impl;
156   
157   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
158
159   if (!WINDOW_IS_TOPLEVEL (window))
160     return NULL;
161
162   private = (GdkWindowObject *)window;
163   impl = GDK_WINDOW_IMPL_X11 (private->impl);
164
165   if (!impl->toplevel)
166     impl->toplevel = g_new0 (GdkToplevelX11, 1);
167
168   return impl->toplevel;
169 }
170
171 static void
172 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
173 {
174   GObjectClass *object_class = G_OBJECT_CLASS (klass);
175   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
176   
177   object_class->finalize = gdk_window_impl_x11_finalize;
178
179   drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
180   drawable_class->get_colormap = gdk_window_impl_x11_get_colormap;
181 }
182
183 static void
184 gdk_window_impl_x11_finalize (GObject *object)
185 {
186   GdkWindowObject *wrapper;
187   GdkDrawableImplX11 *draw_impl;
188   GdkWindowImplX11 *window_impl;
189   
190   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
191
192   draw_impl = GDK_DRAWABLE_IMPL_X11 (object);
193   window_impl = GDK_WINDOW_IMPL_X11 (object);
194   
195   wrapper = (GdkWindowObject*) draw_impl->wrapper;
196
197   _gdk_xgrab_check_destroy (GDK_WINDOW (wrapper));
198
199   if (!GDK_WINDOW_DESTROYED (wrapper))
200     {
201       GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
202       
203       _gdk_xid_table_remove (display, draw_impl->xid);
204       if (window_impl->toplevel && window_impl->toplevel->focus_window)
205         _gdk_xid_table_remove (display, window_impl->toplevel->focus_window);
206     }
207
208   g_free (window_impl->toplevel);
209
210   if (window_impl->cursor)
211     gdk_cursor_unref (window_impl->cursor);
212
213   G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
214 }
215
216 static void
217 tmp_unset_bg (GdkWindow *window)
218 {
219   GdkWindowImplX11 *impl;
220   GdkWindowObject *obj;
221
222   obj = (GdkWindowObject *) window;
223   impl = GDK_WINDOW_IMPL_X11 (obj->impl);
224
225   impl->no_bg = TRUE;
226
227   if (obj->bg_pixmap != GDK_NO_BG)
228     XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
229                                 GDK_DRAWABLE_XID (window), None);
230 }
231
232 static void
233 tmp_reset_bg (GdkWindow *window)
234 {
235   GdkWindowImplX11 *impl;
236   GdkWindowObject *obj;
237
238   obj = (GdkWindowObject *) window;
239   impl = GDK_WINDOW_IMPL_X11 (obj->impl);
240
241   impl->no_bg = FALSE;
242
243   if (obj->bg_pixmap == GDK_NO_BG)
244     return;
245   
246   if (obj->bg_pixmap)
247     {
248       Pixmap xpixmap;
249
250       if (obj->bg_pixmap == GDK_PARENT_RELATIVE_BG)
251         xpixmap = ParentRelative;
252       else 
253         xpixmap = GDK_DRAWABLE_XID (obj->bg_pixmap);
254
255       XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
256                                   GDK_DRAWABLE_XID (window), xpixmap);
257     }
258   else
259     {
260       XSetWindowBackground (GDK_DRAWABLE_XDISPLAY (window),
261                             GDK_DRAWABLE_XID (window),
262                             obj->bg_color.pixel);
263     }
264 }
265
266 /* Unsetting and resetting window backgrounds.
267  *
268  * In many cases it is possible to avoid flicker by unsetting the
269  * background of windows. For example if the background of the
270  * parent window is unset when a window is unmapped, a brief flicker
271  * of background painting is avoided.
272  */
273 void
274 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
275                               gboolean   recurse)
276 {
277   GdkWindowObject *private;
278
279   g_return_if_fail (GDK_IS_WINDOW (window));
280   
281   private = (GdkWindowObject *)window;
282
283   if (private->input_only || private->destroyed ||
284       (private->window_type != GDK_WINDOW_ROOT &&
285        !GDK_WINDOW_IS_MAPPED (window)))
286     return;
287   
288   if (_gdk_window_has_impl (window) &&
289       GDK_WINDOW_IS_X11 (window) &&
290       private->window_type != GDK_WINDOW_ROOT &&
291       private->window_type != GDK_WINDOW_FOREIGN)
292     tmp_unset_bg (window);
293
294   if (recurse)
295     {
296       GList *l;
297
298       for (l = private->children; l != NULL; l = l->next)
299         _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
300     }
301 }
302
303 void
304 _gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window)
305 {
306   GdkWindowObject *private;
307   private = (GdkWindowObject*) window;
308
309   if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
310     return;
311   
312   window = _gdk_window_get_impl_window ((GdkWindow *)private->parent);
313   _gdk_x11_window_tmp_unset_bg (window, FALSE);
314 }
315
316 void
317 _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
318                               gboolean   recurse)
319 {
320   GdkWindowObject *private;
321
322   g_return_if_fail (GDK_IS_WINDOW (window));
323
324   private = (GdkWindowObject *)window;
325
326   if (private->input_only || private->destroyed ||
327       (private->window_type != GDK_WINDOW_ROOT &&
328        !GDK_WINDOW_IS_MAPPED (window)))
329     return;
330
331   
332   if (_gdk_window_has_impl (window) &&
333       GDK_WINDOW_IS_X11 (window) &&
334       private->window_type != GDK_WINDOW_ROOT &&
335       private->window_type != GDK_WINDOW_FOREIGN)
336     tmp_reset_bg (window);
337
338   if (recurse)
339     {
340       GList *l;
341
342       for (l = private->children; l != NULL; l = l->next)
343         _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
344     }
345 }
346
347 void
348 _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
349 {
350   GdkWindowObject *private;
351   private = (GdkWindowObject*) window;
352
353   if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
354     return;
355   
356   window = _gdk_window_get_impl_window ((GdkWindow *)private->parent);
357
358   _gdk_x11_window_tmp_reset_bg (window, FALSE);
359 }
360
361 static GdkColormap*
362 gdk_window_impl_x11_get_colormap (GdkDrawable *drawable)
363 {
364   GdkDrawableImplX11 *drawable_impl;
365   
366   g_return_val_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable), NULL);
367
368   drawable_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
369
370   if (!((GdkWindowObject *) drawable_impl->wrapper)->input_only && 
371       drawable_impl->colormap == NULL)
372     {
373       XWindowAttributes window_attributes;
374       GdkVisual *visual;
375
376       XGetWindowAttributes (GDK_SCREEN_XDISPLAY (drawable_impl->screen),
377                             drawable_impl->xid,
378                             &window_attributes);
379
380       visual = gdk_x11_screen_lookup_visual (drawable_impl->screen,
381                                              window_attributes.visual->visualid);
382       drawable_impl->colormap = gdk_x11_colormap_foreign_new (visual,
383                                                               window_attributes.colormap);
384     }
385   
386   return drawable_impl->colormap;
387 }
388
389 static void
390 gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
391                                   GdkColormap *cmap)
392 {
393   GdkDrawableImplX11 *draw_impl;
394   
395   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
396
397   draw_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
398
399   if (cmap && GDK_WINDOW_DESTROYED (draw_impl->wrapper))
400     return;
401
402   /* chain up */
403   GDK_DRAWABLE_CLASS (gdk_window_impl_x11_parent_class)->set_colormap (drawable, cmap);
404
405   if (cmap)
406     {
407       XSetWindowColormap (GDK_SCREEN_XDISPLAY (draw_impl->screen),
408                           draw_impl->xid,
409                           GDK_COLORMAP_XCOLORMAP (cmap));
410
411       if (((GdkWindowObject*)draw_impl->wrapper)->window_type !=
412           GDK_WINDOW_TOPLEVEL)
413         gdk_window_add_colormap_windows (GDK_WINDOW (draw_impl->wrapper));
414     }
415 }
416
417
418 void
419 _gdk_windowing_window_init (GdkScreen * screen)
420 {
421   GdkWindowObject *private;
422   GdkDrawableImplX11 *draw_impl;
423   GdkScreenX11 *screen_x11;
424
425   screen_x11 = GDK_SCREEN_X11 (screen);
426
427   g_assert (screen_x11->root_window == NULL);
428
429   gdk_screen_set_default_colormap (screen,
430                                    gdk_screen_get_system_colormap (screen));
431
432   screen_x11->root_window = g_object_new (GDK_TYPE_WINDOW, NULL);
433
434   private = (GdkWindowObject *) screen_x11->root_window;
435   private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
436   private->impl_window = private;
437
438   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
439   
440   draw_impl->screen = screen;
441   draw_impl->xid = screen_x11->xroot_window;
442   draw_impl->wrapper = GDK_DRAWABLE (private);
443   draw_impl->colormap = gdk_screen_get_system_colormap (screen);
444   g_object_ref (draw_impl->colormap);
445   
446   private->window_type = GDK_WINDOW_ROOT;
447   private->depth = DefaultDepthOfScreen (screen_x11->xscreen);
448
449   private->x = 0;
450   private->y = 0;
451   private->abs_x = 0;
452   private->abs_y = 0;
453   private->width = WidthOfScreen (screen_x11->xscreen);
454   private->height = HeightOfScreen (screen_x11->xscreen);
455   private->viewable = TRUE;
456
457   /* see init_randr_support() in gdkscreen-x11.c */
458   private->event_mask = GDK_STRUCTURE_MASK;
459
460   _gdk_window_update_size (screen_x11->root_window);
461   
462   _gdk_xid_table_insert (screen_x11->display,
463                          &screen_x11->xroot_window,
464                          screen_x11->root_window);
465 }
466
467 static void
468 set_wm_protocols (GdkWindow *window)
469 {
470   GdkDisplay *display = gdk_drawable_get_display (window);
471   Atom protocols[4];
472   int n = 0;
473   
474   protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
475   protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
476   protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
477
478 #ifdef HAVE_XSYNC
479   if (GDK_DISPLAY_X11 (display)->use_sync)
480     protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
481 #endif
482   
483   XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
484 }
485
486 static const gchar *
487 get_default_title (void)
488 {
489   const char *title;
490
491   title = g_get_application_name ();
492   if (!title)
493     title = g_get_prgname ();
494   if (!title)
495     title = "";
496
497   return title;
498 }
499
500 static void
501 check_leader_window_title (GdkDisplay *display)
502 {
503   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
504
505   if (display_x11->leader_window && !display_x11->leader_window_title_set)
506     {
507       set_wm_name (display,
508                    display_x11->leader_window,
509                    get_default_title ());
510       
511       display_x11->leader_window_title_set = TRUE;
512     }
513 }
514
515 static Window
516 create_focus_window (Display *xdisplay,
517                      XID      parent)
518 {
519   Window focus_window = XCreateSimpleWindow (xdisplay, parent,
520                                              -1, -1, 1, 1, 0,
521                                              0, 0);
522   
523   /* FIXME: probably better to actually track the requested event mask for the toplevel
524    */
525   XSelectInput (xdisplay, focus_window,
526                 KeyPressMask | KeyReleaseMask | FocusChangeMask);
527   
528   XMapWindow (xdisplay, focus_window);
529
530   return focus_window;
531 }
532
533 static void
534 ensure_sync_counter (GdkWindow *window)
535 {
536 #ifdef HAVE_XSYNC
537   if (!GDK_WINDOW_DESTROYED (window))
538     {
539       GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
540       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
541       GdkWindowObject *private = (GdkWindowObject *)window;
542       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
543
544       if (toplevel && impl->use_synchronized_configure &&
545           toplevel->update_counter == None &&
546           GDK_DISPLAY_X11 (display)->use_sync)
547         {
548           Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
549           XSyncValue value;
550           Atom atom;
551
552           XSyncIntToValue (&value, 0);
553           
554           toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
555           
556           atom = gdk_x11_get_xatom_by_name_for_display (display,
557                                                         "_NET_WM_SYNC_REQUEST_COUNTER");
558           
559           XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
560                            atom, XA_CARDINAL,
561                            32, PropModeReplace,
562                            (guchar *)&toplevel->update_counter, 1);
563           
564           XSyncIntToValue (&toplevel->current_counter_value, 0);
565         }
566     }
567 #endif
568 }
569
570 static void
571 setup_toplevel_window (GdkWindow *window, 
572                        GdkWindow *parent)
573 {
574   GdkWindowObject *obj = (GdkWindowObject *)window;
575   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
576   Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
577   XID xid = GDK_WINDOW_XID (window);
578   XID xparent = GDK_WINDOW_XID (parent);
579   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (parent));
580   XSizeHints size_hints;
581   long pid;
582   Window leader_window;
583     
584   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_DIALOG)
585     XSetTransientForHint (xdisplay, xid, xparent);
586   
587   set_wm_protocols (window);
588   
589   if (!obj->input_only)
590     {
591       /* The focus window is off the visible area, and serves to receive key
592        * press events so they don't get sent to child windows.
593        */
594       toplevel->focus_window = create_focus_window (xdisplay, xid);
595       _gdk_xid_table_insert (screen_x11->display, &toplevel->focus_window, window);
596     }
597   
598   check_leader_window_title (screen_x11->display);
599   
600   /* FIXME: Is there any point in doing this? Do any WM's pay
601    * attention to PSize, and even if they do, is this the
602    * correct value???
603    */
604   size_hints.flags = PSize;
605   size_hints.width = obj->width;
606   size_hints.height = obj->height;
607   
608   XSetWMNormalHints (xdisplay, xid, &size_hints);
609   
610   /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
611   XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
612   
613   pid = getpid ();
614   XChangeProperty (xdisplay, xid,
615                    gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "_NET_WM_PID"),
616                    XA_CARDINAL, 32,
617                    PropModeReplace,
618                    (guchar *)&pid, 1);
619
620   leader_window = GDK_DISPLAY_X11 (screen_x11->display)->leader_window;
621   if (!leader_window)
622     leader_window = xid;
623   XChangeProperty (xdisplay, xid, 
624                    gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "WM_CLIENT_LEADER"),
625                    XA_WINDOW, 32, PropModeReplace,
626                    (guchar *) &leader_window, 1);
627
628   if (toplevel->focus_window != None)
629     XChangeProperty (xdisplay, xid, 
630                      gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "_NET_WM_USER_TIME_WINDOW"),
631                      XA_WINDOW, 32, PropModeReplace,
632                      (guchar *) &toplevel->focus_window, 1);
633
634   if (!obj->focus_on_map)
635     gdk_x11_window_set_user_time (window, 0);
636   else if (GDK_DISPLAY_X11 (screen_x11->display)->user_time != 0)
637     gdk_x11_window_set_user_time (window, GDK_DISPLAY_X11 (screen_x11->display)->user_time);
638
639   ensure_sync_counter (window);
640 }
641
642 void
643 _gdk_window_impl_new (GdkWindow     *window,
644                       GdkWindow     *real_parent,
645                       GdkScreen     *screen,
646                       GdkVisual     *visual,
647                       GdkEventMask   event_mask,
648                       GdkWindowAttr *attributes,
649                       gint           attributes_mask)
650 {
651   GdkWindowObject *private;
652   GdkWindowImplX11 *impl;
653   GdkDrawableImplX11 *draw_impl;
654   GdkScreenX11 *screen_x11;
655   
656   Window xparent;
657   Visual *xvisual;
658   Display *xdisplay;
659   Window xid;
660
661   XSetWindowAttributes xattributes;
662   long xattributes_mask;
663   XClassHint *class_hint;
664   
665   unsigned int class;
666   const char *title;
667   int i;
668   
669   private = (GdkWindowObject *) window;
670   
671   screen_x11 = GDK_SCREEN_X11 (screen);
672   xparent = GDK_WINDOW_XID (real_parent);
673   
674   impl = g_object_new (_gdk_window_impl_get_type (), NULL);
675   private->impl = (GdkDrawable *)impl;
676   draw_impl = GDK_DRAWABLE_IMPL_X11 (impl);
677   draw_impl->wrapper = GDK_DRAWABLE (window);
678   
679   draw_impl->screen = screen;
680   xdisplay = screen_x11->xdisplay;
681
682   xattributes_mask = 0;
683
684   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
685   
686   xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
687   for (i = 0; i < _gdk_nenvent_masks; i++)
688     {
689       if (event_mask & (1 << (i + 1)))
690         xattributes.event_mask |= _gdk_event_mask_table[i];
691     }
692   if (xattributes.event_mask)
693     xattributes_mask |= CWEventMask;
694   
695   if (attributes_mask & GDK_WA_NOREDIR)
696     {
697       xattributes.override_redirect =
698         (attributes->override_redirect == FALSE)?False:True;
699       xattributes_mask |= CWOverrideRedirect;
700     } 
701   else
702     xattributes.override_redirect = False;
703
704   impl->override_redirect = xattributes.override_redirect;
705   
706   if (private->parent && private->parent->guffaw_gravity)
707     {
708       xattributes.win_gravity = StaticGravity;
709       xattributes_mask |= CWWinGravity;
710     }
711   
712   /* Sanity checks */
713   switch (private->window_type)
714     {
715     case GDK_WINDOW_TOPLEVEL:
716     case GDK_WINDOW_DIALOG:
717     case GDK_WINDOW_TEMP:
718       if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
719         {
720           /* The common code warns for this case */
721           xparent = GDK_SCREEN_XROOTWIN (screen);
722         }
723     }
724           
725   if (!private->input_only)
726     {
727       class = InputOutput;
728
729       if (attributes_mask & GDK_WA_COLORMAP)
730         {
731           draw_impl->colormap = attributes->colormap;
732           g_object_ref (attributes->colormap);
733         }
734       else
735         {
736           if ((((GdkVisualPrivate *)gdk_screen_get_system_visual (screen))->xvisual) ==  xvisual)
737             {
738               draw_impl->colormap = gdk_screen_get_system_colormap (screen);
739               g_object_ref (draw_impl->colormap);
740             }
741           else
742             {
743               draw_impl->colormap = gdk_colormap_new (visual, FALSE);
744             }
745         }
746       
747       xattributes.background_pixel = private->bg_color.pixel;
748
749       xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
750       xattributes_mask |= CWBorderPixel | CWBackPixel;
751
752       if (private->guffaw_gravity)
753         xattributes.bit_gravity = StaticGravity;
754       else
755         xattributes.bit_gravity = NorthWestGravity;
756       
757       xattributes_mask |= CWBitGravity;
758
759       xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
760       xattributes_mask |= CWColormap;
761
762       if (private->window_type == GDK_WINDOW_TEMP)
763         {
764           xattributes.save_under = True;
765           xattributes.override_redirect = True;
766           xattributes.cursor = None;
767           xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
768
769           impl->override_redirect = TRUE;
770         }
771     }
772   else
773     {
774       class = InputOnly;
775       draw_impl->colormap = gdk_screen_get_system_colormap (screen);
776       g_object_ref (draw_impl->colormap);
777     }
778
779   if (private->width > 65535 ||
780       private->height > 65535)
781     {
782       g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
783       
784       if (private->width > 65535)
785         private->width = 65535;
786       if (private->height > 65535)
787         private->height = 65535;
788     }
789   
790   xid = draw_impl->xid = XCreateWindow (xdisplay, xparent,
791                                         private->x + private->parent->abs_x,
792                                         private->y + private->parent->abs_y,
793                                         private->width, private->height,
794                                         0, private->depth, class, xvisual,
795                                         xattributes_mask, &xattributes);
796
797   g_object_ref (window);
798   _gdk_xid_table_insert (screen_x11->display, &draw_impl->xid, window);
799
800   switch (GDK_WINDOW_TYPE (private))
801     {
802     case GDK_WINDOW_DIALOG:
803     case GDK_WINDOW_TOPLEVEL:
804     case GDK_WINDOW_TEMP:
805       if (attributes_mask & GDK_WA_TITLE)
806         title = attributes->title;
807       else
808         title = get_default_title ();
809       
810       gdk_window_set_title (window, title);
811       
812       if (attributes_mask & GDK_WA_WMCLASS)
813         {
814           class_hint = XAllocClassHint ();
815           class_hint->res_name = attributes->wmclass_name;
816           class_hint->res_class = attributes->wmclass_class;
817           XSetClassHint (xdisplay, xid, class_hint);
818           XFree (class_hint);
819         }
820   
821       setup_toplevel_window (window, (GdkWindow *)private->parent);
822       break;
823
824     case GDK_WINDOW_CHILD:
825       if (!private->input_only &&
826           (draw_impl->colormap != gdk_screen_get_system_colormap (screen)) &&
827           (draw_impl->colormap != gdk_drawable_get_colormap (gdk_window_get_toplevel (window))))
828         {
829           GDK_NOTE (MISC, g_message ("adding colormap window\n"));
830           gdk_window_add_colormap_windows (window);
831         }
832       break;
833       
834     default:
835       break;
836     }
837
838   if (attributes_mask & GDK_WA_TYPE_HINT)
839     gdk_window_set_type_hint (window, attributes->type_hint);
840 }
841
842 static GdkEventMask
843 x_event_mask_to_gdk_event_mask (long mask)
844 {
845   GdkEventMask event_mask = 0;
846   int i;
847
848   for (i = 0; i < _gdk_nenvent_masks; i++)
849     {
850       if (mask & _gdk_event_mask_table[i])
851         event_mask |= 1 << (i + 1);
852     }
853
854   return event_mask;
855 }
856
857 /**
858  * gdk_window_foreign_new_for_display:
859  * @display: the #GdkDisplay where the window handle comes from.
860  * @anid: a native window handle.
861  * 
862  * Wraps a native window in a #GdkWindow.
863  * This may fail if the window has been destroyed. If the window
864  * was already known to GDK, a new reference to the existing 
865  * #GdkWindow is returned.
866  *
867  * For example in the X backend, a native window handle is an Xlib
868  * <type>XID</type>.
869  * 
870  * Return value: a #GdkWindow wrapper for the native window or 
871  *   %NULL if the window has been destroyed. The wrapper will be
872  *   newly created, if one doesn't exist already.
873  *
874  * Since: 2.2
875  **/
876 GdkWindow *
877 gdk_window_foreign_new_for_display (GdkDisplay     *display,
878                                     GdkNativeWindow anid)
879 {
880   GdkWindow *window;
881   GdkWindowObject *private;
882   GdkWindowImplX11 *impl;
883   GdkDrawableImplX11 *draw_impl;
884   GdkDisplayX11 *display_x11;
885   XWindowAttributes attrs;
886   Window root, parent;
887   Window *children = NULL;
888   guint nchildren;
889   gboolean result;
890
891   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
892
893   display_x11 = GDK_DISPLAY_X11 (display);
894
895   if ((window = gdk_xid_table_lookup_for_display (display, anid)) != NULL)
896     return g_object_ref (window);
897
898   gdk_error_trap_push ();
899   result = XGetWindowAttributes (display_x11->xdisplay, anid, &attrs);
900   if (gdk_error_trap_pop () || !result)
901     return NULL;
902
903   /* FIXME: This is pretty expensive. Maybe the caller should supply
904    *        the parent */
905   gdk_error_trap_push ();
906   result = XQueryTree (display_x11->xdisplay, anid, &root, &parent, &children, &nchildren);
907   if (gdk_error_trap_pop () || !result)
908     return NULL;
909
910   if (children)
911     XFree (children);
912   
913   window = g_object_new (GDK_TYPE_WINDOW, NULL);
914
915   private = (GdkWindowObject *) window;
916   private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
917   private->impl_window = private;
918
919   impl = GDK_WINDOW_IMPL_X11 (private->impl);
920   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
921   draw_impl->wrapper = GDK_DRAWABLE (window);
922   draw_impl->screen = _gdk_x11_display_screen_for_xrootwin (display, root);
923   
924   private->parent = gdk_xid_table_lookup_for_display (display, parent);
925   
926   if (!private->parent || GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_FOREIGN)
927     private->parent = (GdkWindowObject *) gdk_screen_get_root_window (draw_impl->screen);
928   
929   private->parent->children = g_list_prepend (private->parent->children, window);
930
931   draw_impl->xid = anid;
932
933   private->x = attrs.x;
934   private->y = attrs.y;
935   private->width = attrs.width;
936   private->height = attrs.height;
937   private->window_type = GDK_WINDOW_FOREIGN;
938   private->destroyed = FALSE;
939
940   private->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
941
942   if (attrs.map_state == IsUnmapped)
943     private->state = GDK_WINDOW_STATE_WITHDRAWN;
944   else
945     private->state = 0;
946   private->viewable = TRUE;
947
948   private->depth = attrs.depth;
949   
950   g_object_ref (window);
951   _gdk_xid_table_insert (display, &GDK_WINDOW_XID (window), window);
952
953   /* Update the clip region, etc */
954   _gdk_window_update_size (window);
955
956   return window;
957 }
958
959 /**
960  * gdk_window_lookup_for_display:
961  * @display: the #GdkDisplay corresponding to the window handle
962  * @anid: a native window handle.
963  *
964  * Looks up the #GdkWindow that wraps the given native window handle.
965  *
966  * For example in the X backend, a native window handle is an Xlib
967  * <type>XID</type>.
968  *
969  * Return value: the #GdkWindow wrapper for the native window, 
970  *    or %NULL if there is none.
971  *
972  * Since: 2.2
973  **/
974 GdkWindow *
975 gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
976 {
977   return (GdkWindow*) gdk_xid_table_lookup_for_display (display, anid);
978 }
979
980 /**
981  * gdk_window_lookup:
982  * @anid: a native window handle.
983  *
984  * Looks up the #GdkWindow that wraps the given native window handle. 
985  *
986  * For example in the X backend, a native window handle is an Xlib
987  * <type>XID</type>.
988  *
989  * Return value: the #GdkWindow wrapper for the native window, 
990  *    or %NULL if there is none.
991  **/
992 GdkWindow *
993 gdk_window_lookup (GdkNativeWindow anid)
994 {
995   return (GdkWindow*) gdk_xid_table_lookup (anid);
996 }
997
998 static void
999 gdk_toplevel_x11_free_contents (GdkDisplay *display,
1000                                 GdkToplevelX11 *toplevel)
1001 {
1002   if (toplevel->icon_window)
1003     {
1004       g_object_unref (toplevel->icon_window);
1005       toplevel->icon_window = NULL;
1006     }
1007   if (toplevel->icon_pixmap)
1008     {
1009       g_object_unref (toplevel->icon_pixmap);
1010       toplevel->icon_pixmap = NULL;
1011     }
1012   if (toplevel->icon_mask)
1013     {
1014       g_object_unref (toplevel->icon_mask);
1015       toplevel->icon_mask = NULL;
1016     }
1017   if (toplevel->group_leader)
1018     {
1019       g_object_unref (toplevel->group_leader);
1020       toplevel->group_leader = NULL;
1021     }
1022 #ifdef HAVE_XSYNC
1023   if (toplevel->update_counter != None)
1024     {
1025       XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display), 
1026                            toplevel->update_counter);
1027       toplevel->update_counter = None;
1028
1029       XSyncIntToValue (&toplevel->current_counter_value, 0);
1030     }
1031 #endif
1032 }
1033
1034 static void
1035 _gdk_x11_window_destroy (GdkWindow *window,
1036                          gboolean   recursing,
1037                          gboolean   foreign_destroy)
1038 {
1039   GdkWindowObject *private = (GdkWindowObject *)window;
1040   GdkToplevelX11 *toplevel;
1041   
1042   g_return_if_fail (GDK_IS_WINDOW (window));
1043
1044   _gdk_selection_window_destroyed (window);
1045   
1046   toplevel = _gdk_x11_window_get_toplevel (window);
1047   if (toplevel)
1048     gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
1049
1050   _gdk_x11_drawable_finish (private->impl);
1051
1052   if (!recursing && !foreign_destroy)
1053     {
1054       XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1055     }
1056 }
1057
1058 void
1059 _gdk_windowing_window_destroy_foreign (GdkWindow *window)
1060 {
1061   /* It's somebody else's window, but in our hierarchy,
1062    * so reparent it to the root window, and then send
1063    * it a delete event, as if we were a WM
1064    */
1065   XClientMessageEvent xclient;
1066   
1067   gdk_error_trap_push ();
1068   gdk_window_hide (window);
1069   gdk_window_reparent (window, NULL, 0, 0);
1070   
1071   memset (&xclient, 0, sizeof (xclient));
1072   xclient.type = ClientMessage;
1073   xclient.window = GDK_WINDOW_XID (window);
1074   xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
1075                                                                "WM_PROTOCOLS");
1076   xclient.format = 32;
1077   xclient.data.l[0] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
1078                                                             "WM_DELETE_WINDOW");
1079   xclient.data.l[1] = CurrentTime;
1080   xclient.data.l[2] = 0;
1081   xclient.data.l[3] = 0;
1082   xclient.data.l[4] = 0;
1083   
1084   XSendEvent (GDK_WINDOW_XDISPLAY (window),
1085               GDK_WINDOW_XID (window),
1086               False, 0, (XEvent *)&xclient);
1087   gdk_display_sync (GDK_WINDOW_DISPLAY (window));
1088   gdk_error_trap_pop ();
1089 }
1090
1091 static GdkWindow *
1092 get_root (GdkWindow *window)
1093 {
1094   GdkScreen *screen = gdk_drawable_get_screen (window);
1095
1096   return gdk_screen_get_root_window (screen);
1097 }
1098
1099 /* This function is called when the XWindow is really gone.
1100  */
1101 void
1102 gdk_window_destroy_notify (GdkWindow *window)
1103 {
1104   GdkWindowImplX11 *window_impl;
1105
1106   window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
1107
1108   if (!GDK_WINDOW_DESTROYED (window))
1109     {
1110       if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1111         g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
1112
1113       _gdk_window_destroy (window, TRUE);
1114     }
1115   
1116   _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
1117   if (window_impl->toplevel && window_impl->toplevel->focus_window)
1118     _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
1119
1120   _gdk_xgrab_check_destroy (window);
1121   
1122   g_object_unref (window);
1123 }
1124
1125 static void
1126 update_wm_hints (GdkWindow *window,
1127                  gboolean   force)
1128 {
1129   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
1130   GdkWindowObject *private = (GdkWindowObject *)window;
1131   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1132   XWMHints wm_hints;
1133
1134   if (!force &&
1135       !toplevel->is_leader &&
1136       private->state & GDK_WINDOW_STATE_WITHDRAWN)
1137     return;
1138
1139   wm_hints.flags = StateHint | InputHint;
1140   wm_hints.input = private->accept_focus ? True : False;
1141   wm_hints.initial_state = NormalState;
1142   
1143   if (private->state & GDK_WINDOW_STATE_ICONIFIED)
1144     {
1145       wm_hints.flags |= StateHint;
1146       wm_hints.initial_state = IconicState;
1147     }
1148
1149   if (toplevel->icon_window && !GDK_WINDOW_DESTROYED (toplevel->icon_window))
1150     {
1151       wm_hints.flags |= IconWindowHint;
1152       wm_hints.icon_window = GDK_WINDOW_XID (toplevel->icon_window);
1153     }
1154
1155   if (toplevel->icon_pixmap)
1156     {
1157       wm_hints.flags |= IconPixmapHint;
1158       wm_hints.icon_pixmap = GDK_PIXMAP_XID (toplevel->icon_pixmap);
1159     }
1160
1161   if (toplevel->icon_mask)
1162     {
1163       wm_hints.flags |= IconMaskHint;
1164       wm_hints.icon_mask = GDK_PIXMAP_XID (toplevel->icon_mask);
1165     }
1166   
1167   wm_hints.flags |= WindowGroupHint;
1168   if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
1169     {
1170       wm_hints.flags |= WindowGroupHint;
1171       wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
1172     }
1173   else
1174     wm_hints.window_group = GDK_DISPLAY_X11 (display)->leader_window;
1175
1176   if (toplevel->urgency_hint)
1177     wm_hints.flags |= XUrgencyHint;
1178   
1179   XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1180                GDK_WINDOW_XID (window),
1181                &wm_hints);
1182 }
1183
1184 static void
1185 set_initial_hints (GdkWindow *window)
1186 {
1187   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1188   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1189   Window xwindow = GDK_WINDOW_XID (window);  
1190   GdkWindowObject *private;
1191   GdkToplevelX11 *toplevel;
1192   Atom atoms[9];
1193   gint i;
1194
1195   private = (GdkWindowObject*) window;
1196   toplevel = _gdk_x11_window_get_toplevel (window);
1197
1198   if (!toplevel)
1199     return;
1200
1201   update_wm_hints (window, TRUE);
1202   
1203   /* We set the spec hints regardless of whether the spec is supported,
1204    * since it can't hurt and it's kind of expensive to check whether
1205    * it's supported.
1206    */
1207   
1208   i = 0;
1209
1210   if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
1211     {
1212       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1213                                                         "_NET_WM_STATE_MAXIMIZED_VERT");
1214       ++i;
1215       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1216                                                         "_NET_WM_STATE_MAXIMIZED_HORZ");
1217       ++i;
1218       toplevel->have_maxhorz = toplevel->have_maxvert = TRUE;
1219     }
1220
1221   if (private->state & GDK_WINDOW_STATE_ABOVE)
1222     {
1223       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1224                                                         "_NET_WM_STATE_ABOVE");
1225       ++i;
1226     }
1227   
1228   if (private->state & GDK_WINDOW_STATE_BELOW)
1229     {
1230       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1231                                                         "_NET_WM_STATE_BELOW");
1232       ++i;
1233     }
1234   
1235   if (private->state & GDK_WINDOW_STATE_STICKY)
1236     {
1237       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1238                                                         "_NET_WM_STATE_STICKY");
1239       ++i;
1240       toplevel->have_sticky = TRUE;
1241     }
1242
1243   if (private->state & GDK_WINDOW_STATE_FULLSCREEN)
1244     {
1245       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1246                                                         "_NET_WM_STATE_FULLSCREEN");
1247       ++i;
1248       toplevel->have_fullscreen = TRUE;
1249     }
1250
1251   if (private->modal_hint)
1252     {
1253       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1254                                                         "_NET_WM_STATE_MODAL");
1255       ++i;
1256     }
1257
1258   if (toplevel->skip_taskbar_hint)
1259     {
1260       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1261                                                         "_NET_WM_STATE_SKIP_TASKBAR");
1262       ++i;
1263     }
1264
1265   if (toplevel->skip_pager_hint)
1266     {
1267       atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1268                                                         "_NET_WM_STATE_SKIP_PAGER");
1269       ++i;
1270     }
1271
1272   if (i > 0)
1273     {
1274       XChangeProperty (xdisplay,
1275                        xwindow,
1276                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
1277                        XA_ATOM, 32, PropModeReplace,
1278                        (guchar*) atoms, i);
1279     }
1280   else 
1281     {
1282       XDeleteProperty (xdisplay,
1283                        xwindow,
1284                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
1285     }
1286
1287   if (private->state & GDK_WINDOW_STATE_STICKY)
1288     {
1289       atoms[0] = 0xFFFFFFFF;
1290       XChangeProperty (xdisplay,
1291                        xwindow,
1292                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
1293                        XA_CARDINAL, 32, PropModeReplace,
1294                        (guchar*) atoms, 1);
1295       toplevel->on_all_desktops = TRUE;
1296     }
1297   else
1298     {
1299       XDeleteProperty (xdisplay,
1300                        xwindow,
1301                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
1302     }
1303
1304   toplevel->map_serial = NextRequest (xdisplay);
1305 }
1306
1307 static void
1308 gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
1309 {
1310   GdkWindowObject *private = (GdkWindowObject*) window;
1311   GdkDisplay *display;
1312   GdkDisplayX11 *display_x11;
1313   GdkToplevelX11 *toplevel;
1314   GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
1315   Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
1316   Window xwindow = GDK_WINDOW_XID (window);
1317   gboolean unset_bg;
1318
1319   if (!already_mapped)
1320     set_initial_hints (window);
1321       
1322   if (WINDOW_IS_TOPLEVEL (window))
1323     {
1324       display = gdk_drawable_get_display (window);
1325       display_x11 = GDK_DISPLAY_X11 (display);
1326       toplevel = _gdk_x11_window_get_toplevel (window);
1327       
1328       if (toplevel->user_time != 0 &&
1329               display_x11->user_time != 0 &&
1330           XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
1331         gdk_x11_window_set_user_time (window, display_x11->user_time);
1332     }
1333   
1334   unset_bg = !private->input_only &&
1335     (private->window_type == GDK_WINDOW_CHILD ||
1336      impl->override_redirect) &&
1337     gdk_window_is_viewable (window);
1338   
1339   if (unset_bg)
1340     _gdk_x11_window_tmp_unset_bg (window, TRUE);
1341   
1342   XMapWindow (xdisplay, xwindow);
1343   
1344   if (unset_bg)
1345     _gdk_x11_window_tmp_reset_bg (window, TRUE);
1346 }
1347
1348 static void
1349 pre_unmap (GdkWindow *window)
1350 {
1351   GdkWindow *start_window = NULL;
1352   GdkWindowObject *private = (GdkWindowObject *)window;
1353
1354   if (private->input_only)
1355     return;
1356
1357   if (private->window_type == GDK_WINDOW_CHILD)
1358     start_window = _gdk_window_get_impl_window ((GdkWindow *)private->parent);
1359   else if (private->window_type == GDK_WINDOW_TEMP)
1360     start_window = get_root (window);
1361
1362   if (start_window)
1363     _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
1364 }
1365
1366 static void
1367 post_unmap (GdkWindow *window)
1368 {
1369   GdkWindow *start_window = NULL;
1370   GdkWindowObject *private = (GdkWindowObject *)window;
1371   
1372   if (private->input_only)
1373     return;
1374
1375   if (private->window_type == GDK_WINDOW_CHILD)
1376     start_window = _gdk_window_get_impl_window ((GdkWindow *)private->parent);
1377   else if (private->window_type == GDK_WINDOW_TEMP)
1378     start_window = get_root (window);
1379
1380   if (start_window)
1381     {
1382       _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
1383
1384       if (private->window_type == GDK_WINDOW_CHILD && private->parent)
1385         {
1386           GdkRectangle invalid_rect;
1387       
1388           gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
1389           gdk_drawable_get_size (GDK_DRAWABLE (window),
1390                                  &invalid_rect.width, &invalid_rect.height);
1391           gdk_window_invalidate_rect ((GdkWindow *)private->parent,
1392                                       &invalid_rect, TRUE);
1393         }
1394     }
1395 }
1396
1397 static void
1398 gdk_window_x11_hide (GdkWindow *window)
1399 {
1400   GdkWindowObject *private;
1401   
1402   private = (GdkWindowObject*) window;
1403
1404   /* We'll get the unmap notify eventually, and handle it then,
1405    * but checking here makes things more consistent if we are
1406    * just doing stuff ourself.
1407    */
1408   _gdk_xgrab_check_unmap (window,
1409                           NextRequest (GDK_WINDOW_XDISPLAY (window)));
1410
1411   /* You can't simply unmap toplevel windows. */
1412   switch (private->window_type)
1413     {
1414     case GDK_WINDOW_TOPLEVEL:
1415     case GDK_WINDOW_DIALOG:
1416     case GDK_WINDOW_TEMP: /* ? */
1417       gdk_window_withdraw (window);
1418       return;
1419       
1420     case GDK_WINDOW_FOREIGN:
1421     case GDK_WINDOW_ROOT:
1422     case GDK_WINDOW_CHILD:
1423       break;
1424     }
1425   
1426   _gdk_window_clear_update_area (window);
1427   
1428   pre_unmap (window);
1429   XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
1430                 GDK_WINDOW_XID (window));
1431   post_unmap (window);
1432 }
1433
1434 static void
1435 gdk_window_x11_withdraw (GdkWindow *window)
1436 {
1437   GdkWindowObject *private;
1438   
1439   private = (GdkWindowObject*) window;
1440   if (!private->destroyed)
1441     {
1442       if (GDK_WINDOW_IS_MAPPED (window))
1443         gdk_synthesize_window_state (window,
1444                                      0,
1445                                      GDK_WINDOW_STATE_WITHDRAWN);
1446
1447       g_assert (!GDK_WINDOW_IS_MAPPED (window));
1448
1449       pre_unmap (window);
1450       
1451       XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
1452                        GDK_WINDOW_XID (window), 0);
1453
1454       post_unmap (window);
1455     }
1456 }
1457
1458 static inline void
1459 window_x11_move (GdkWindow *window,
1460                  gint       x,
1461                  gint       y)
1462 {
1463   GdkWindowObject *private = (GdkWindowObject *) window;
1464   GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
1465
1466   if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
1467     {
1468       _gdk_window_move_resize_child (window,
1469                                      x, y,
1470                                      private->width, private->height);
1471     }
1472   else
1473     {
1474       XMoveWindow (GDK_WINDOW_XDISPLAY (window),
1475                    GDK_WINDOW_XID (window),
1476                    x, y);
1477
1478       if (impl->override_redirect)
1479         {
1480           private->x = x;
1481           private->y = y;
1482         }
1483     }
1484 }
1485
1486 static inline void
1487 window_x11_resize (GdkWindow *window,
1488                    gint       width,
1489                    gint       height)
1490 {
1491   GdkWindowObject *private = (GdkWindowObject *) window;
1492
1493   if (width < 1)
1494     width = 1;
1495
1496   if (height < 1)
1497     height = 1;
1498
1499   if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
1500     {
1501       _gdk_window_move_resize_child (window,
1502                                      private->x, private->y,
1503                                      width, height);
1504     }
1505   else
1506     {
1507       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
1508
1509       XResizeWindow (GDK_WINDOW_XDISPLAY (window),
1510                      GDK_WINDOW_XID (window),
1511                      width, height);
1512
1513       if (impl->override_redirect)
1514         {
1515           private->width = width;
1516           private->height = height;
1517           _gdk_x11_drawable_update_size (private->impl);
1518         }
1519       else
1520         {
1521           if (width != private->width || height != private->height)
1522             private->resize_count += 1;
1523         }
1524     }
1525
1526   _gdk_x11_drawable_update_size (private->impl);
1527 }
1528
1529 static inline void
1530 window_x11_move_resize (GdkWindow *window,
1531                         gint       x,
1532                         gint       y,
1533                         gint       width,
1534                         gint       height)
1535 {
1536   GdkWindowObject *private = (GdkWindowObject *) window;;
1537   
1538   if (width < 1)
1539     width = 1;
1540
1541   if (height < 1)
1542     height = 1;
1543
1544   if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
1545     {
1546       _gdk_window_move_resize_child (window, x, y, width, height);
1547       _gdk_x11_drawable_update_size (private->impl);
1548     }
1549   else
1550     {
1551       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
1552
1553       XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
1554                          GDK_WINDOW_XID (window),
1555                          x, y, width, height);
1556
1557       if (impl->override_redirect)
1558         {
1559           private->x = x;
1560           private->y = y;
1561
1562           private->width = width;
1563           private->height = height;
1564
1565           _gdk_x11_drawable_update_size (private->impl);
1566         }
1567       else
1568         {
1569           if (width != private->width || height != private->height)
1570             private->resize_count += 1;
1571         }
1572     }
1573 }
1574
1575 static void
1576 gdk_window_x11_move_resize (GdkWindow *window,
1577                             gboolean   with_move,
1578                             gint       x,
1579                             gint       y,
1580                             gint       width,
1581                             gint       height)
1582 {
1583   if (with_move && (width < 0 && height < 0))
1584     window_x11_move (window, x, y);
1585   else
1586     {
1587       if (with_move)
1588         window_x11_move_resize (window, x, y, width, height);
1589       else
1590         window_x11_resize (window, width, height);
1591     }
1592 }
1593
1594 static gboolean
1595 gdk_window_x11_reparent (GdkWindow *window,
1596                          GdkWindow *new_parent,
1597                          gint       x,
1598                          gint       y)
1599 {
1600   GdkWindowObject *window_private;
1601   GdkWindowObject *parent_private;
1602   GdkWindowImplX11 *impl;
1603
1604   window_private = (GdkWindowObject*) window;
1605   parent_private = (GdkWindowObject*) new_parent;
1606   impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
1607
1608   _gdk_x11_window_tmp_unset_bg (window, TRUE);
1609   _gdk_x11_window_tmp_unset_parent_bg (window);
1610   XReparentWindow (GDK_WINDOW_XDISPLAY (window),
1611                    GDK_WINDOW_XID (window),
1612                    GDK_WINDOW_XID (new_parent),
1613                    parent_private->abs_x + x, parent_private->abs_y + y);
1614   _gdk_x11_window_tmp_reset_parent_bg (window);
1615   _gdk_x11_window_tmp_reset_bg (window, TRUE);
1616
1617   if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1618     new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1619
1620   window_private->parent = parent_private;
1621
1622   /* Switch the window type as appropriate */
1623
1624   switch (GDK_WINDOW_TYPE (new_parent))
1625     {
1626     case GDK_WINDOW_ROOT:
1627     case GDK_WINDOW_FOREIGN:
1628       /* Reparenting to toplevel */
1629       
1630       if (!WINDOW_IS_TOPLEVEL (window) &&
1631           GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1632         {
1633           /* This is also done in common code at a later stage, but we
1634              need it in setup_toplevel, so do it here too */
1635           if (window_private->toplevel_window_type != -1)
1636             GDK_WINDOW_TYPE (window) = window_private->toplevel_window_type;
1637           else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1638             GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1639           
1640           /* Wasn't a toplevel, set up */
1641           setup_toplevel_window (window, new_parent);
1642         }
1643
1644       break;
1645       
1646     case GDK_WINDOW_TOPLEVEL:
1647     case GDK_WINDOW_CHILD:
1648     case GDK_WINDOW_DIALOG:
1649     case GDK_WINDOW_TEMP:
1650       if (WINDOW_IS_TOPLEVEL (window) &&
1651           impl->toplevel)
1652         {
1653           if (impl->toplevel->focus_window)
1654             {
1655               XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
1656               _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
1657             }
1658           
1659           gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
1660                                           impl->toplevel);
1661           g_free (impl->toplevel);
1662           impl->toplevel = NULL;
1663         }
1664     }
1665
1666   return FALSE;
1667 }
1668
1669 static void
1670 gdk_window_x11_clear_region (GdkWindow *window,
1671                              GdkRegion *region,
1672                              gboolean   send_expose)
1673 {
1674   GdkRectangle *rectangles;
1675   int n_rectangles, i;
1676
1677   gdk_region_get_rectangles  (region,
1678                               &rectangles,
1679                               &n_rectangles);
1680
1681   for (i = 0; i < n_rectangles; i++)
1682     XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
1683                 rectangles[i].x, rectangles[i].y,
1684                 rectangles[i].width, rectangles[i].height,
1685                 send_expose);
1686
1687   g_free (rectangles);
1688 }
1689
1690 static void
1691 gdk_window_x11_raise (GdkWindow *window)
1692 {
1693   XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1694 }
1695
1696 static void
1697 gdk_window_x11_restack_under (GdkWindow *window,
1698                               GList *native_siblings /* in requested order, first is bottom-most */)
1699 {
1700   Window *windows;
1701   int n_windows, i;
1702   GList *l;
1703
1704   n_windows = g_list_length (native_siblings) + 1;
1705   windows = g_new (Window, n_windows);
1706
1707   windows[0] = GDK_WINDOW_XID (window);
1708   /* Reverse order, as input order is bottom-most first */
1709   i = n_windows - 1;
1710   for (l = native_siblings; l != NULL; l = l->next)
1711     windows[i--] = GDK_WINDOW_XID (l->data);
1712  
1713   XRestackWindows (GDK_WINDOW_XDISPLAY (window), windows, n_windows);
1714   
1715   g_free (windows);
1716 }
1717
1718 static void
1719 gdk_window_x11_restack_toplevel (GdkWindow *window,
1720                                  GdkWindow *sibling,
1721                                  gboolean   above)
1722 {
1723   XWindowChanges changes;
1724
1725   changes.sibling = GDK_WINDOW_XID (sibling);
1726   changes.stack_mode = above ? Above : Below;
1727   XReconfigureWMWindow (GDK_WINDOW_XDISPLAY (window),
1728                         GDK_WINDOW_XID (window),
1729                         GDK_WINDOW_SCREEN (window),
1730                         CWStackMode | CWSibling, &changes);
1731 }
1732
1733 static void
1734 gdk_window_x11_lower (GdkWindow *window)
1735 {
1736   XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1737 }
1738
1739 /**
1740  * gdk_x11_window_move_to_current_desktop:
1741  * @window: a #GdkWindow
1742  * 
1743  * Moves the window to the correct workspace when running under a 
1744  * window manager that supports multiple workspaces, as described
1745  * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended 
1746  * Window Manager Hints</ulink>.  Will not do anything if the
1747  * window is already on all workspaces.
1748  * 
1749  * Since: 2.8
1750  */
1751 void
1752 gdk_x11_window_move_to_current_desktop (GdkWindow *window)
1753 {
1754   GdkToplevelX11 *toplevel;
1755
1756   g_return_if_fail (GDK_IS_WINDOW (window));
1757   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1758
1759   toplevel = _gdk_x11_window_get_toplevel (window);
1760
1761   if (toplevel->on_all_desktops)
1762     return;
1763   
1764   move_to_current_desktop (window);
1765 }
1766
1767 static void
1768 move_to_current_desktop (GdkWindow *window)
1769 {
1770   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1771                                            gdk_atom_intern_static_string ("_NET_WM_DESKTOP")))
1772     {
1773       Atom type;
1774       gint format;
1775       gulong nitems;
1776       gulong bytes_after;
1777       guchar *data;
1778       gulong *current_desktop;
1779       GdkDisplay *display;
1780       
1781       display = gdk_drawable_get_display (window);
1782
1783       /* Get current desktop, then set it; this is a race, but not
1784        * one that matters much in practice.
1785        */
1786       XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), 
1787                           GDK_WINDOW_XROOTWIN (window),
1788                           gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
1789                           0, G_MAXLONG,
1790                           False, XA_CARDINAL, &type, &format, &nitems,
1791                           &bytes_after, &data);
1792
1793       if (type == XA_CARDINAL)
1794         {
1795           XClientMessageEvent xclient;
1796           current_desktop = (gulong *)data;
1797           
1798           memset (&xclient, 0, sizeof (xclient));
1799           xclient.type = ClientMessage;
1800           xclient.serial = 0;
1801           xclient.send_event = True;
1802           xclient.window = GDK_WINDOW_XWINDOW (window);
1803           xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
1804           xclient.format = 32;
1805
1806           xclient.data.l[0] = *current_desktop;
1807           xclient.data.l[1] = 0;
1808           xclient.data.l[2] = 0;
1809           xclient.data.l[3] = 0;
1810           xclient.data.l[4] = 0;
1811       
1812           XSendEvent (GDK_DISPLAY_XDISPLAY (display), 
1813                       GDK_WINDOW_XROOTWIN (window), 
1814                       False,
1815                       SubstructureRedirectMask | SubstructureNotifyMask,
1816                       (XEvent *)&xclient);
1817
1818           XFree (current_desktop);
1819         }
1820     }
1821 }
1822
1823 /**
1824  * gdk_window_focus:
1825  * @window: a #GdkWindow
1826  * @timestamp: timestamp of the event triggering the window focus
1827  *
1828  * Sets keyboard focus to @window. In most cases, gtk_window_present() 
1829  * should be used on a #GtkWindow, rather than calling this function.
1830  * 
1831  **/
1832 void
1833 gdk_window_focus (GdkWindow *window,
1834                   guint32    timestamp)
1835 {
1836   GdkDisplay *display;
1837
1838   g_return_if_fail (GDK_IS_WINDOW (window));
1839
1840   if (GDK_WINDOW_DESTROYED (window) ||
1841       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1842     return;
1843
1844   display = GDK_WINDOW_DISPLAY (window);
1845
1846   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1847                                            gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
1848     {
1849       XClientMessageEvent xclient;
1850
1851       memset (&xclient, 0, sizeof (xclient));
1852       xclient.type = ClientMessage;
1853       xclient.window = GDK_WINDOW_XWINDOW (window);
1854       xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
1855                                                                         "_NET_ACTIVE_WINDOW");
1856       xclient.format = 32;
1857       xclient.data.l[0] = 1; /* requestor type; we're an app */
1858       xclient.data.l[1] = timestamp;
1859       xclient.data.l[2] = None; /* currently active window */
1860       xclient.data.l[3] = 0;
1861       xclient.data.l[4] = 0;
1862       
1863       XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
1864                   SubstructureRedirectMask | SubstructureNotifyMask,
1865                   (XEvent *)&xclient);
1866     }
1867   else
1868     {
1869       XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
1870
1871       /* There is no way of knowing reliably whether we are viewable;
1872        * _gdk_x11_set_input_focus_safe() traps errors asynchronously.
1873        */
1874       _gdk_x11_set_input_focus_safe (display, GDK_WINDOW_XID (window),
1875                                      RevertToParent,
1876                                      timestamp);
1877     }
1878 }
1879
1880 /**
1881  * gdk_window_set_hints:
1882  * @window: a #GdkWindow
1883  * @x: ignored field, does not matter
1884  * @y: ignored field, does not matter
1885  * @min_width: minimum width hint
1886  * @min_height: minimum height hint
1887  * @max_width: max width hint
1888  * @max_height: max height hint
1889  * @flags: logical OR of GDK_HINT_POS, GDK_HINT_MIN_SIZE, and/or GDK_HINT_MAX_SIZE
1890  *
1891  * This function is broken and useless and you should ignore it.
1892  * If using GTK+, use functions such as gtk_window_resize(), gtk_window_set_size_request(),
1893  * gtk_window_move(), gtk_window_parse_geometry(), and gtk_window_set_geometry_hints(),
1894  * depending on what you're trying to do.
1895  *
1896  * If using GDK directly, use gdk_window_set_geometry_hints().
1897  * 
1898  **/
1899 void
1900 gdk_window_set_hints (GdkWindow *window,
1901                       gint       x,
1902                       gint       y,
1903                       gint       min_width,
1904                       gint       min_height,
1905                       gint       max_width,
1906                       gint       max_height,
1907                       gint       flags)
1908 {
1909   XSizeHints size_hints;
1910   
1911   if (GDK_WINDOW_DESTROYED (window) ||
1912       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1913     return;
1914   
1915   size_hints.flags = 0;
1916   
1917   if (flags & GDK_HINT_POS)
1918     {
1919       size_hints.flags |= PPosition;
1920       size_hints.x = x;
1921       size_hints.y = y;
1922     }
1923   
1924   if (flags & GDK_HINT_MIN_SIZE)
1925     {
1926       size_hints.flags |= PMinSize;
1927       size_hints.min_width = min_width;
1928       size_hints.min_height = min_height;
1929     }
1930   
1931   if (flags & GDK_HINT_MAX_SIZE)
1932     {
1933       size_hints.flags |= PMaxSize;
1934       size_hints.max_width = max_width;
1935       size_hints.max_height = max_height;
1936     }
1937   
1938   /* FIXME: Would it be better to delete this property if
1939    *        flags == 0? It would save space on the server
1940    */
1941   XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
1942                      GDK_WINDOW_XID (window),
1943                      &size_hints);
1944 }
1945
1946 /**
1947  * gdk_window_set_type_hint:
1948  * @window: A toplevel #GdkWindow
1949  * @hint: A hint of the function this window will have
1950  *
1951  * The application can use this call to provide a hint to the window
1952  * manager about the functionality of a window. The window manager
1953  * can use this information when determining the decoration and behaviour
1954  * of the window.
1955  *
1956  * The hint must be set before the window is mapped.
1957  **/
1958 void
1959 gdk_window_set_type_hint (GdkWindow        *window,
1960                           GdkWindowTypeHint hint)
1961 {
1962   GdkDisplay *display;
1963   Atom atom;
1964   
1965   if (GDK_WINDOW_DESTROYED (window) ||
1966       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1967     return;
1968
1969   display = gdk_drawable_get_display (window);
1970
1971   switch (hint)
1972     {
1973     case GDK_WINDOW_TYPE_HINT_DIALOG:
1974       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
1975       break;
1976     case GDK_WINDOW_TYPE_HINT_MENU:
1977       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
1978       break;
1979     case GDK_WINDOW_TYPE_HINT_TOOLBAR:
1980       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
1981       break;
1982     case GDK_WINDOW_TYPE_HINT_UTILITY:
1983       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
1984       break;
1985     case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
1986       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
1987       break;
1988     case GDK_WINDOW_TYPE_HINT_DOCK:
1989       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
1990       break;
1991     case GDK_WINDOW_TYPE_HINT_DESKTOP:
1992       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
1993       break;
1994     case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
1995       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
1996       break;
1997     case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
1998       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
1999       break;
2000     case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2001       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
2002       break;
2003     case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2004       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
2005       break;
2006     case GDK_WINDOW_TYPE_HINT_COMBO:
2007       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
2008       break;
2009     case GDK_WINDOW_TYPE_HINT_DND:
2010       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
2011       break;
2012     default:
2013       g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
2014       /* Fall thru */
2015     case GDK_WINDOW_TYPE_HINT_NORMAL:
2016       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
2017       break;
2018     }
2019
2020   XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2021                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2022                    XA_ATOM, 32, PropModeReplace,
2023                    (guchar *)&atom, 1);
2024 }
2025
2026 /**
2027  * gdk_window_get_type_hint:
2028  * @window: A toplevel #GdkWindow
2029  *
2030  * This function returns the type hint set for a window.
2031  *
2032  * Return value: The type hint set for @window
2033  *
2034  * Since: 2.10
2035  **/
2036 GdkWindowTypeHint
2037 gdk_window_get_type_hint (GdkWindow *window)
2038 {
2039   GdkDisplay *display;
2040   GdkWindowTypeHint type;
2041   Atom type_return;
2042   gint format_return;
2043   gulong nitems_return;
2044   gulong bytes_after_return;
2045   guchar *data = NULL;
2046
2047   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2048
2049   if (GDK_WINDOW_DESTROYED (window) ||
2050       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2051     return GDK_WINDOW_TYPE_HINT_NORMAL;
2052
2053   type = GDK_WINDOW_TYPE_HINT_NORMAL;
2054
2055   display = gdk_drawable_get_display (window);
2056
2057   if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2058                           gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2059                           0, G_MAXLONG, False, XA_ATOM, &type_return,
2060                           &format_return, &nitems_return, &bytes_after_return,
2061                           &data) == Success)
2062     {
2063       if ((type_return == XA_ATOM) && (format_return == 32) &&
2064           (data) && (nitems_return == 1))
2065         {
2066           Atom atom = *(Atom*)data;
2067
2068           if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
2069             type = GDK_WINDOW_TYPE_HINT_DIALOG;
2070           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
2071             type = GDK_WINDOW_TYPE_HINT_MENU;
2072           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
2073             type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
2074           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
2075             type = GDK_WINDOW_TYPE_HINT_UTILITY;
2076           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
2077             type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
2078           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
2079             type = GDK_WINDOW_TYPE_HINT_DOCK;
2080           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
2081             type = GDK_WINDOW_TYPE_HINT_DESKTOP;
2082           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
2083             type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
2084           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
2085             type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
2086           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
2087             type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
2088           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
2089             type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
2090           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
2091             type = GDK_WINDOW_TYPE_HINT_COMBO;
2092           else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
2093             type = GDK_WINDOW_TYPE_HINT_DND;
2094         }
2095
2096       if (type_return != None && data != NULL)
2097         XFree (data);
2098     }
2099
2100   return type;
2101 }
2102
2103 static void
2104 gdk_wmspec_change_state (gboolean   add,
2105                          GdkWindow *window,
2106                          GdkAtom    state1,
2107                          GdkAtom    state2)
2108 {
2109   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
2110   XClientMessageEvent xclient;
2111   
2112 #define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
2113 #define _NET_WM_STATE_ADD           1    /* add/set property */
2114 #define _NET_WM_STATE_TOGGLE        2    /* toggle property  */  
2115   
2116   memset (&xclient, 0, sizeof (xclient));
2117   xclient.type = ClientMessage;
2118   xclient.window = GDK_WINDOW_XID (window);
2119   xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
2120   xclient.format = 32;
2121   xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
2122   xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
2123   xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
2124   xclient.data.l[3] = 0;
2125   xclient.data.l[4] = 0;
2126   
2127   XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
2128               SubstructureRedirectMask | SubstructureNotifyMask,
2129               (XEvent *)&xclient);
2130 }
2131
2132 /**
2133  * gdk_window_set_modal_hint:
2134  * @window: A toplevel #GdkWindow
2135  * @modal: %TRUE if the window is modal, %FALSE otherwise.
2136  *
2137  * The application can use this hint to tell the window manager
2138  * that a certain window has modal behaviour. The window manager
2139  * can use this information to handle modal windows in a special
2140  * way.
2141  *
2142  * You should only use this on windows for which you have
2143  * previously called gdk_window_set_transient_for()
2144  **/
2145 void
2146 gdk_window_set_modal_hint (GdkWindow *window,
2147                            gboolean   modal)
2148 {
2149   GdkWindowObject *private;
2150
2151   if (GDK_WINDOW_DESTROYED (window) ||
2152       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2153     return;
2154
2155   private = (GdkWindowObject*) window;
2156
2157   private->modal_hint = modal;
2158
2159   if (GDK_WINDOW_IS_MAPPED (window))
2160     gdk_wmspec_change_state (modal, window,
2161                              gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"), 
2162                              GDK_NONE);
2163 }
2164
2165 /**
2166  * gdk_window_set_skip_taskbar_hint:
2167  * @window: a toplevel #GdkWindow
2168  * @skips_taskbar: %TRUE to skip the taskbar
2169  * 
2170  * Toggles whether a window should appear in a task list or window
2171  * list. If a window's semantic type as specified with
2172  * gdk_window_set_type_hint() already fully describes the window, this
2173  * function should <emphasis>not</emphasis> be called in addition, 
2174  * instead you should allow the window to be treated according to 
2175  * standard policy for its semantic type.
2176  *
2177  * Since: 2.2
2178  **/
2179 void
2180 gdk_window_set_skip_taskbar_hint (GdkWindow *window,
2181                                   gboolean   skips_taskbar)
2182 {
2183   GdkToplevelX11 *toplevel;
2184   
2185   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2186   
2187   if (GDK_WINDOW_DESTROYED (window) ||
2188       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2189     return;
2190
2191   toplevel = _gdk_x11_window_get_toplevel (window);
2192   toplevel->skip_taskbar_hint = skips_taskbar;
2193
2194   if (GDK_WINDOW_IS_MAPPED (window))
2195     gdk_wmspec_change_state (skips_taskbar, window,
2196                              gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
2197                              GDK_NONE);
2198 }
2199
2200 /**
2201  * gdk_window_set_skip_pager_hint:
2202  * @window: a toplevel #GdkWindow
2203  * @skips_pager: %TRUE to skip the pager
2204  * 
2205  * Toggles whether a window should appear in a pager (workspace
2206  * switcher, or other desktop utility program that displays a small
2207  * thumbnail representation of the windows on the desktop). If a
2208  * window's semantic type as specified with gdk_window_set_type_hint()
2209  * already fully describes the window, this function should 
2210  * <emphasis>not</emphasis> be called in addition, instead you should 
2211  * allow the window to be treated according to standard policy for 
2212  * its semantic type.
2213  *
2214  * Since: 2.2
2215  **/
2216 void
2217 gdk_window_set_skip_pager_hint (GdkWindow *window,
2218                                 gboolean   skips_pager)
2219 {
2220   GdkToplevelX11 *toplevel;
2221     
2222   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2223   
2224   if (GDK_WINDOW_DESTROYED (window) ||
2225       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2226     return;
2227
2228   toplevel = _gdk_x11_window_get_toplevel (window);
2229   toplevel->skip_pager_hint = skips_pager;
2230   
2231   if (GDK_WINDOW_IS_MAPPED (window))
2232     gdk_wmspec_change_state (skips_pager, window,
2233                              gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"), 
2234                              GDK_NONE);
2235 }
2236
2237 /**
2238  * gdk_window_set_urgency_hint:
2239  * @window: a toplevel #GdkWindow
2240  * @urgent: %TRUE if the window is urgent
2241  * 
2242  * Toggles whether a window needs the user's
2243  * urgent attention.
2244  *
2245  * Since: 2.8
2246  **/
2247 void
2248 gdk_window_set_urgency_hint (GdkWindow *window,
2249                              gboolean   urgent)
2250 {
2251   GdkToplevelX11 *toplevel;
2252     
2253   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2254   
2255   if (GDK_WINDOW_DESTROYED (window) ||
2256       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2257     return;
2258
2259   toplevel = _gdk_x11_window_get_toplevel (window);
2260   toplevel->urgency_hint = urgent;
2261   
2262   update_wm_hints (window, FALSE);
2263 }
2264
2265 /**
2266  * gdk_window_set_geometry_hints:
2267  * @window: a toplevel #GdkWindow
2268  * @geometry: geometry hints
2269  * @geom_mask: bitmask indicating fields of @geometry to pay attention to
2270  *
2271  * Sets the geometry hints for @window. Hints flagged in @geom_mask
2272  * are set, hints not flagged in @geom_mask are unset.
2273  * To unset all hints, use a @geom_mask of 0 and a @geometry of %NULL.
2274  *
2275  * This function provides hints to the windowing system about
2276  * acceptable sizes for a toplevel window. The purpose of 
2277  * this is to constrain user resizing, but the windowing system
2278  * will typically  (but is not required to) also constrain the
2279  * current size of the window to the provided values and
2280  * constrain programatic resizing via gdk_window_resize() or
2281  * gdk_window_move_resize().
2282  * 
2283  * Note that on X11, this effect has no effect on windows
2284  * of type %GDK_WINDOW_TEMP or windows where override redirect
2285  * has been turned on via gdk_window_set_override_redirect()
2286  * since these windows are not resizable by the user.
2287  * 
2288  * Since you can't count on the windowing system doing the
2289  * constraints for programmatic resizes, you should generally
2290  * call gdk_window_constrain_size() yourself to determine
2291  * appropriate sizes.
2292  *
2293  **/
2294 void 
2295 gdk_window_set_geometry_hints (GdkWindow         *window,
2296                                const GdkGeometry *geometry,
2297                                GdkWindowHints     geom_mask)
2298 {
2299   XSizeHints size_hints;
2300   
2301   if (GDK_WINDOW_DESTROYED (window) ||
2302       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2303     return;
2304   
2305   size_hints.flags = 0;
2306   
2307   if (geom_mask & GDK_HINT_POS)
2308     {
2309       size_hints.flags |= PPosition;
2310       /* We need to initialize the following obsolete fields because KWM 
2311        * apparently uses these fields if they are non-zero.
2312        * #@#!#!$!.
2313        */
2314       size_hints.x = 0;
2315       size_hints.y = 0;
2316     }
2317
2318   if (geom_mask & GDK_HINT_USER_POS)
2319     {
2320       size_hints.flags |= USPosition;
2321     }
2322
2323   if (geom_mask & GDK_HINT_USER_SIZE)
2324     {
2325       size_hints.flags |= USSize;
2326     }
2327   
2328   if (geom_mask & GDK_HINT_MIN_SIZE)
2329     {
2330       size_hints.flags |= PMinSize;
2331       size_hints.min_width = geometry->min_width;
2332       size_hints.min_height = geometry->min_height;
2333     }
2334   
2335   if (geom_mask & GDK_HINT_MAX_SIZE)
2336     {
2337       size_hints.flags |= PMaxSize;
2338       size_hints.max_width = MAX (geometry->max_width, 1);
2339       size_hints.max_height = MAX (geometry->max_height, 1);
2340     }
2341   
2342   if (geom_mask & GDK_HINT_BASE_SIZE)
2343     {
2344       size_hints.flags |= PBaseSize;
2345       size_hints.base_width = geometry->base_width;
2346       size_hints.base_height = geometry->base_height;
2347     }
2348   
2349   if (geom_mask & GDK_HINT_RESIZE_INC)
2350     {
2351       size_hints.flags |= PResizeInc;
2352       size_hints.width_inc = geometry->width_inc;
2353       size_hints.height_inc = geometry->height_inc;
2354     }
2355   
2356   if (geom_mask & GDK_HINT_ASPECT)
2357     {
2358       size_hints.flags |= PAspect;
2359       if (geometry->min_aspect <= 1)
2360         {
2361           size_hints.min_aspect.x = 65536 * geometry->min_aspect;
2362           size_hints.min_aspect.y = 65536;
2363         }
2364       else
2365         {
2366           size_hints.min_aspect.x = 65536;
2367           size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
2368         }
2369       if (geometry->max_aspect <= 1)
2370         {
2371           size_hints.max_aspect.x = 65536 * geometry->max_aspect;
2372           size_hints.max_aspect.y = 65536;
2373         }
2374       else
2375         {
2376           size_hints.max_aspect.x = 65536;
2377           size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
2378         }
2379     }
2380
2381   if (geom_mask & GDK_HINT_WIN_GRAVITY)
2382     {
2383       size_hints.flags |= PWinGravity;
2384       size_hints.win_gravity = geometry->win_gravity;
2385     }
2386   
2387   /* FIXME: Would it be better to delete this property if
2388    *        geom_mask == 0? It would save space on the server
2389    */
2390   XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2391                      GDK_WINDOW_XID (window),
2392                      &size_hints);
2393 }
2394
2395 static void
2396 gdk_window_get_geometry_hints (GdkWindow      *window,
2397                                GdkGeometry    *geometry,
2398                                GdkWindowHints *geom_mask)
2399 {
2400   XSizeHints *size_hints;  
2401   glong junk_supplied_mask = 0;
2402
2403   g_return_if_fail (GDK_IS_WINDOW (window));
2404   g_return_if_fail (geometry != NULL);
2405   g_return_if_fail (geom_mask != NULL);
2406
2407   *geom_mask = 0;
2408   
2409   if (GDK_WINDOW_DESTROYED (window) ||
2410       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2411     return;
2412
2413   size_hints = XAllocSizeHints ();
2414   if (!size_hints)
2415     return;
2416   
2417   if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2418                           GDK_WINDOW_XID (window),
2419                           size_hints,
2420                           &junk_supplied_mask))
2421     size_hints->flags = 0;
2422
2423   if (size_hints->flags & PMinSize)
2424     {
2425       *geom_mask |= GDK_HINT_MIN_SIZE;
2426       geometry->min_width = size_hints->min_width;
2427       geometry->min_height = size_hints->min_height;
2428     }
2429
2430   if (size_hints->flags & PMaxSize)
2431     {
2432       *geom_mask |= GDK_HINT_MAX_SIZE;
2433       geometry->max_width = MAX (size_hints->max_width, 1);
2434       geometry->max_height = MAX (size_hints->max_height, 1);
2435     }
2436
2437   if (size_hints->flags & PResizeInc)
2438     {
2439       *geom_mask |= GDK_HINT_RESIZE_INC;
2440       geometry->width_inc = size_hints->width_inc;
2441       geometry->height_inc = size_hints->height_inc;
2442     }
2443
2444   if (size_hints->flags & PAspect)
2445     {
2446       *geom_mask |= GDK_HINT_ASPECT;
2447
2448       geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
2449       geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
2450     }
2451
2452   if (size_hints->flags & PWinGravity)
2453     {
2454       *geom_mask |= GDK_HINT_WIN_GRAVITY;
2455       geometry->win_gravity = size_hints->win_gravity;
2456     }
2457
2458   XFree (size_hints);
2459 }
2460
2461 static gboolean
2462 utf8_is_latin1 (const gchar *str)
2463 {
2464   const char *p = str;
2465
2466   while (*p)
2467     {
2468       gunichar ch = g_utf8_get_char (p);
2469
2470       if (ch > 0xff)
2471         return FALSE;
2472       
2473       p = g_utf8_next_char (p);
2474     }
2475
2476   return TRUE;
2477 }
2478
2479 /* Set the property to @utf8_str as STRING if the @utf8_str is fully
2480  * convertable to STRING, otherwise, set it as compound text
2481  */
2482 static void
2483 set_text_property (GdkDisplay  *display,
2484                    Window       xwindow,
2485                    Atom         property,
2486                    const gchar *utf8_str)
2487 {
2488   gchar *prop_text = NULL;
2489   Atom prop_type;
2490   gint prop_length;
2491   gint prop_format;
2492   gboolean is_compound_text;
2493   
2494   if (utf8_is_latin1 (utf8_str))
2495     {
2496       prop_type = XA_STRING;
2497       prop_text = gdk_utf8_to_string_target (utf8_str);
2498       prop_length = prop_text ? strlen (prop_text) : 0;
2499       prop_format = 8;
2500       is_compound_text = FALSE;
2501     }
2502   else
2503     {
2504       GdkAtom gdk_type;
2505       
2506       gdk_utf8_to_compound_text_for_display (display,
2507                                              utf8_str, &gdk_type, &prop_format,
2508                                              (guchar **)&prop_text, &prop_length);
2509       prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
2510       is_compound_text = TRUE;
2511     }
2512
2513   if (prop_text)
2514     {
2515       XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
2516                        xwindow,
2517                        property,
2518                        prop_type, prop_format,
2519                        PropModeReplace, (guchar *)prop_text,
2520                        prop_length);
2521
2522       if (is_compound_text)
2523         gdk_free_compound_text ((guchar *)prop_text);
2524       else
2525         g_free (prop_text);
2526     }
2527 }
2528
2529 /* Set WM_NAME and _NET_WM_NAME
2530  */
2531 static void
2532 set_wm_name (GdkDisplay  *display,
2533              Window       xwindow,
2534              const gchar *name)
2535 {
2536   XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2537                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
2538                    gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2539                    PropModeReplace, (guchar *)name, strlen (name));
2540   
2541   set_text_property (display, xwindow,
2542                      gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
2543                      name);
2544 }
2545
2546 /**
2547  * gdk_window_set_title:
2548  * @window: a toplevel #GdkWindow
2549  * @title: title of @window
2550  *
2551  * Sets the title of a toplevel window, to be displayed in the titlebar.
2552  * If you haven't explicitly set the icon name for the window
2553  * (using gdk_window_set_icon_name()), the icon name will be set to
2554  * @title as well. @title must be in UTF-8 encoding (as with all
2555  * user-readable strings in GDK/GTK+). @title may not be %NULL.
2556  **/
2557 void
2558 gdk_window_set_title (GdkWindow   *window,
2559                       const gchar *title)
2560 {
2561   GdkDisplay *display;
2562   Display *xdisplay;
2563   Window xwindow;
2564   
2565   g_return_if_fail (title != NULL);
2566
2567   if (GDK_WINDOW_DESTROYED (window) ||
2568       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2569     return;
2570   
2571   display = gdk_drawable_get_display (window);
2572   xdisplay = GDK_DISPLAY_XDISPLAY (display);
2573   xwindow = GDK_WINDOW_XID (window);
2574
2575   set_wm_name (display, xwindow, title);
2576   
2577   if (!gdk_window_icon_name_set (window))
2578     {
2579       XChangeProperty (xdisplay, xwindow,
2580                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
2581                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2582                        PropModeReplace, (guchar *)title, strlen (title));
2583       
2584       set_text_property (display, xwindow,
2585                          gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
2586                          title);
2587     }
2588 }
2589
2590 /**
2591  * gdk_window_set_role:
2592  * @window: a toplevel #GdkWindow
2593  * @role: a string indicating its role
2594  *
2595  * When using GTK+, typically you should use gtk_window_set_role() instead
2596  * of this low-level function.
2597  * 
2598  * The window manager and session manager use a window's role to
2599  * distinguish it from other kinds of window in the same application.
2600  * When an application is restarted after being saved in a previous
2601  * session, all windows with the same title and role are treated as
2602  * interchangeable.  So if you have two windows with the same title
2603  * that should be distinguished for session management purposes, you
2604  * should set the role on those windows. It doesn't matter what string
2605  * you use for the role, as long as you have a different role for each
2606  * non-interchangeable kind of window.
2607  * 
2608  **/
2609 void          
2610 gdk_window_set_role (GdkWindow   *window,
2611                      const gchar *role)
2612 {
2613   GdkDisplay *display;
2614
2615   display = gdk_drawable_get_display (window);
2616
2617   if (GDK_WINDOW_DESTROYED (window) ||
2618       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2619     return;
2620
2621   if (role)
2622     XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2623                      gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
2624                      XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
2625   else
2626     XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2627                      gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
2628 }
2629
2630 /**
2631  * gdk_window_set_startup_id:
2632  * @window: a toplevel #GdkWindow
2633  * @startup_id: a string with startup-notification identifier
2634  *
2635  * When using GTK+, typically you should use gtk_window_set_startup_id()
2636  * instead of this low-level function.
2637  *
2638  * Since: 2.12
2639  *
2640  **/
2641 void
2642 gdk_window_set_startup_id (GdkWindow   *window,
2643                            const gchar *startup_id)
2644 {
2645   GdkDisplay *display;
2646
2647   g_return_if_fail (GDK_IS_WINDOW (window));
2648
2649   display = gdk_drawable_get_display (window);
2650
2651   if (GDK_WINDOW_DESTROYED (window) ||
2652       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2653     return;
2654
2655   if (startup_id)
2656     XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2657                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"), 
2658                      gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2659                      PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
2660   else
2661     XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2662                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
2663 }
2664
2665 /**
2666  * gdk_window_set_transient_for:
2667  * @window: a toplevel #GdkWindow
2668  * @parent: another toplevel #GdkWindow
2669  *
2670  * Indicates to the window manager that @window is a transient dialog
2671  * associated with the application window @parent. This allows the
2672  * window manager to do things like center @window on @parent and
2673  * keep @window above @parent.
2674  *
2675  * See gtk_window_set_transient_for() if you're using #GtkWindow or
2676  * #GtkDialog.
2677  **/
2678 void
2679 gdk_window_set_transient_for (GdkWindow *window,
2680                               GdkWindow *parent)
2681 {
2682   if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
2683       WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2684     XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), 
2685                           GDK_WINDOW_XID (window),
2686                           GDK_WINDOW_XID (parent));
2687 }
2688
2689 static void
2690 gdk_window_x11_set_background (GdkWindow      *window,
2691                                const GdkColor *color)
2692 {
2693   XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
2694                         GDK_WINDOW_XID (window), color->pixel);
2695 }
2696
2697 static void
2698 gdk_window_x11_set_back_pixmap (GdkWindow *window,
2699                                 GdkPixmap *pixmap)
2700 {
2701   Pixmap xpixmap;
2702   
2703   if (pixmap == GDK_PARENT_RELATIVE_BG)
2704     xpixmap = ParentRelative;
2705   else if (pixmap == GDK_NO_BG)
2706     xpixmap = None;
2707   else
2708     xpixmap = GDK_PIXMAP_XID (pixmap);
2709   
2710   if (!GDK_WINDOW_DESTROYED (window))
2711     XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2712                                 GDK_WINDOW_XID (window), xpixmap);
2713 }
2714
2715 static void
2716 gdk_window_x11_set_cursor (GdkWindow *window,
2717                            GdkCursor *cursor)
2718 {
2719   GdkWindowObject *private;
2720   GdkWindowImplX11 *impl;
2721   GdkCursorPrivate *cursor_private;
2722   Cursor xcursor;
2723   
2724   private = (GdkWindowObject *)window;
2725   impl = GDK_WINDOW_IMPL_X11 (private->impl);
2726   cursor_private = (GdkCursorPrivate*) cursor;
2727
2728   if (impl->cursor)
2729     {
2730       gdk_cursor_unref (impl->cursor);
2731       impl->cursor = NULL;
2732     }
2733
2734   if (!cursor)
2735     xcursor = None;
2736   else
2737     {
2738       _gdk_x11_cursor_update_theme (cursor);
2739       xcursor = cursor_private->xcursor;
2740     }
2741   
2742   if (!GDK_WINDOW_DESTROYED (window))
2743     {
2744       XDefineCursor (GDK_WINDOW_XDISPLAY (window),
2745                      GDK_WINDOW_XID (window),
2746                      xcursor);
2747       
2748       if (cursor)
2749         impl->cursor = gdk_cursor_ref (cursor);
2750     }
2751 }
2752
2753 GdkCursor *
2754 _gdk_x11_window_get_cursor (GdkWindow *window)
2755 {
2756   GdkWindowObject *private;
2757   GdkWindowImplX11 *impl;
2758   
2759   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2760     
2761   private = (GdkWindowObject *)window;
2762   impl = GDK_WINDOW_IMPL_X11 (private->impl);
2763
2764   return impl->cursor;
2765 }
2766
2767 static void
2768 gdk_window_x11_get_geometry (GdkWindow *window,
2769                              gint      *x,
2770                              gint      *y,
2771                              gint      *width,
2772                              gint      *height,
2773                              gint      *depth)
2774 {
2775   Window root;
2776   gint tx;
2777   gint ty;
2778   guint twidth;
2779   guint theight;
2780   guint tborder_width;
2781   guint tdepth;
2782   
2783   if (!GDK_WINDOW_DESTROYED (window))
2784     {
2785       XGetGeometry (GDK_WINDOW_XDISPLAY (window),
2786                     GDK_WINDOW_XID (window),
2787                     &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
2788       
2789       if (x)
2790         *x = tx;
2791       if (y)
2792         *y = ty;
2793       if (width)
2794         *width = twidth;
2795       if (height)
2796         *height = theight;
2797       if (depth)
2798         *depth = tdepth;
2799     }
2800 }
2801
2802 static gint
2803 gdk_window_x11_get_root_coords (GdkWindow *window,
2804                                 gint       x,
2805                                 gint       y,
2806                                 gint      *root_x,
2807                                 gint      *root_y)
2808 {
2809   gint return_val;
2810   Window child;
2811   gint tx;
2812   gint ty;
2813   
2814   return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2815                                       GDK_WINDOW_XID (window),
2816                                       GDK_WINDOW_XROOTWIN (window),
2817                                       x, y, &tx, &ty,
2818                                       &child);
2819   
2820   if (root_x)
2821     *root_x = tx;
2822   if (root_y)
2823     *root_y = ty;
2824   
2825   return return_val;
2826 }
2827
2828 static gboolean
2829 gdk_window_x11_get_deskrelative_origin (GdkWindow *window,
2830                                         gint      *x,
2831                                         gint      *y)
2832 {
2833   gboolean return_val = FALSE;
2834   gint num_children, format_return;
2835   Window win, *child, parent, root;
2836   Atom type_return;
2837   Atom atom;
2838   gulong number_return, bytes_after_return;
2839   guchar *data_return;
2840   
2841   atom = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
2842                                                 "ENLIGHTENMENT_DESKTOP");
2843   win = GDK_WINDOW_XID (window);
2844   
2845   while (XQueryTree (GDK_WINDOW_XDISPLAY (window), win, &root, &parent,
2846                      &child, (unsigned int *)&num_children))
2847     {
2848       if ((child) && (num_children > 0))
2849         XFree (child);
2850       
2851       if (!parent)
2852         break;
2853       else
2854         win = parent;
2855       
2856       if (win == root)
2857         break;
2858       
2859       data_return = NULL;
2860       XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), win, atom, 0, 0,
2861                           False, XA_CARDINAL, &type_return, &format_return,
2862                           &number_return, &bytes_after_return, &data_return);
2863       
2864       if (type_return == XA_CARDINAL)
2865         {
2866           XFree (data_return);
2867           break;
2868         }
2869     }
2870   
2871   return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2872                                       GDK_WINDOW_XID (window),
2873                                       win,
2874                                       0, 0, x, y,
2875                                       &root);
2876   
2877   return return_val;
2878 }
2879
2880 /**
2881  * gdk_window_get_root_origin:
2882  * @window: a toplevel #GdkWindow
2883  * @x: return location for X position of window frame
2884  * @y: return location for Y position of window frame
2885  *
2886  * Obtains the top-left corner of the window manager frame in root
2887  * window coordinates.
2888  * 
2889  **/
2890 void
2891 gdk_window_get_root_origin (GdkWindow *window,
2892                             gint      *x,
2893                             gint      *y)
2894 {
2895   GdkRectangle rect;
2896
2897   gdk_window_get_frame_extents (window, &rect);
2898
2899   if (x)
2900     *x = rect.x;
2901
2902   if (y)
2903     *y = rect.y;
2904 }
2905
2906 /**
2907  * gdk_window_get_frame_extents:
2908  * @window: a toplevel #GdkWindow
2909  * @rect: rectangle to fill with bounding box of the window frame
2910  *
2911  * Obtains the bounding box of the window, including window manager
2912  * titlebar/borders if any. The frame position is given in root window
2913  * coordinates. To get the position of the window itself (rather than
2914  * the frame) in root window coordinates, use gdk_window_get_origin().
2915  * 
2916  **/
2917 void
2918 gdk_window_get_frame_extents (GdkWindow    *window,
2919                               GdkRectangle *rect)
2920 {
2921   GdkDisplay *display;
2922   GdkWindowObject *private;
2923   Window xwindow;
2924   Window xparent;
2925   Window root;
2926   Window child;
2927   Window *children;
2928   guchar *data;
2929   Window *vroots;
2930   Atom type_return;
2931   guint nchildren;
2932   guint nvroots;
2933   gulong nitems_return;
2934   gulong bytes_after_return;
2935   gint format_return;
2936   gint i;
2937   guint ww, wh, wb, wd;
2938   gint wx, wy;
2939   gboolean got_frame_extents = FALSE;
2940   
2941   g_return_if_fail (rect != NULL);
2942   
2943   private = (GdkWindowObject*) window;
2944   
2945   rect->x = 0;
2946   rect->y = 0;
2947   rect->width = 1;
2948   rect->height = 1;
2949   
2950   while (private->parent && ((GdkWindowObject*) private->parent)->parent)
2951     private = (GdkWindowObject*) private->parent;
2952
2953   /* Refine our fallback answer a bit using local information */
2954   rect->x = private->x;
2955   rect->y = private->y;
2956   gdk_drawable_get_size ((GdkDrawable *)private, &rect->width, &rect->height);
2957
2958   if (GDK_WINDOW_DESTROYED (private))
2959     return;
2960
2961   nvroots = 0;
2962   vroots = NULL;
2963
2964   gdk_error_trap_push();
2965   
2966   display = gdk_drawable_get_display (window);
2967   xwindow = GDK_WINDOW_XID (window);
2968
2969   /* first try: use _NET_FRAME_EXTENTS */
2970   if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2971                           gdk_x11_get_xatom_by_name_for_display (display,
2972                                                                  "_NET_FRAME_EXTENTS"),
2973                           0, G_MAXLONG, False, XA_CARDINAL, &type_return,
2974                           &format_return, &nitems_return, &bytes_after_return,
2975                           &data)
2976       == Success)
2977     {
2978       if ((type_return == XA_CARDINAL) && (format_return == 32) &&
2979           (nitems_return == 4) && (data))
2980         {
2981           gulong *ldata = (gulong *) data;
2982           got_frame_extents = TRUE;
2983
2984           /* try to get the real client window geometry */
2985           if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
2986                             &root, &wx, &wy, &ww, &wh, &wb, &wd) &&
2987               XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (display),
2988                                      xwindow, root, 0, 0, &wx, &wy, &child))
2989             {
2990               rect->x = wx;
2991               rect->y = wy;
2992               rect->width = ww;
2993               rect->height = wh;
2994             }
2995
2996           /* _NET_FRAME_EXTENTS format is left, right, top, bottom */
2997           rect->x -= ldata[0];
2998           rect->y -= ldata[2];
2999           rect->width += ldata[0] + ldata[1];
3000           rect->height += ldata[2] + ldata[3];
3001         }
3002
3003       if (data)
3004         XFree (data);
3005     }
3006
3007   if (got_frame_extents)
3008     goto out;
3009
3010   /* no frame extents property available, which means we either have a WM that
3011      is not EWMH compliant or is broken - try fallback and walk up the window
3012      tree to get our window's parent which hopefully is the window frame */
3013
3014   /* use NETWM_VIRTUAL_ROOTS if available */
3015   root = GDK_WINDOW_XROOTWIN (window);
3016
3017   if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
3018                           gdk_x11_get_xatom_by_name_for_display (display, 
3019                                                                  "_NET_VIRTUAL_ROOTS"),
3020                           0, G_MAXLONG, False, XA_WINDOW, &type_return,
3021                           &format_return, &nitems_return, &bytes_after_return,
3022                           &data)
3023       == Success)
3024     {
3025       if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
3026         {
3027           nvroots = nitems_return;
3028           vroots = (Window *)data;
3029         }
3030     }
3031
3032   xparent = GDK_WINDOW_XID (window);
3033
3034   do
3035     {
3036       xwindow = xparent;
3037
3038       if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
3039                        &root, &xparent,
3040                        &children, &nchildren))
3041         goto out;
3042       
3043       if (children)
3044         XFree (children);
3045
3046       /* check virtual roots */
3047       for (i = 0; i < nvroots; i++)
3048         {
3049           if (xparent == vroots[i])
3050             {
3051               root = xparent;
3052               break;
3053            }
3054         }
3055     }
3056   while (xparent != root);
3057   
3058   if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow, 
3059                     &root, &wx, &wy, &ww, &wh, &wb, &wd))
3060     {
3061       rect->x = wx;
3062       rect->y = wy;
3063       rect->width = ww;
3064       rect->height = wh;
3065     }
3066
3067  out:
3068   if (vroots)
3069     XFree (vroots);
3070
3071   gdk_error_trap_pop ();
3072 }
3073
3074 void
3075 _gdk_windowing_get_pointer (GdkDisplay       *display,
3076                             GdkScreen       **screen,
3077                             gint             *x,
3078                             gint             *y,
3079                             GdkModifierType  *mask)
3080 {
3081   GdkScreen *default_screen;
3082   Display *xdisplay;
3083   Window xwindow;
3084   Window root = None;
3085   Window child;
3086   int rootx, rooty;
3087   int winx;
3088   int winy;
3089   unsigned int xmask;
3090
3091   if (display->closed)
3092     return;
3093
3094   default_screen = gdk_display_get_default_screen (display);
3095
3096   xdisplay = GDK_SCREEN_XDISPLAY (default_screen);
3097   xwindow = GDK_SCREEN_XROOTWIN (default_screen);
3098   
3099   if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) 
3100     {
3101       XQueryPointer (xdisplay, xwindow,
3102                      &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
3103     } 
3104   else 
3105     {
3106       XSetWindowAttributes attributes;
3107       Window w;
3108       
3109       w = XCreateWindow (xdisplay, xwindow, 0, 0, 1, 1, 0, 
3110                          CopyFromParent, InputOnly, CopyFromParent, 
3111                          0, &attributes);
3112       XQueryPointer (xdisplay, w, 
3113                      &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
3114       XDestroyWindow (xdisplay, w);
3115     }
3116   
3117   if (root != None)
3118     {
3119       GdkWindow *gdk_root = gdk_window_lookup_for_display (display, root);
3120       *screen = gdk_drawable_get_screen (gdk_root);
3121     }
3122   
3123   *x = rootx;
3124   *y = rooty;
3125   *mask = xmask;
3126 }
3127
3128 static gboolean
3129 gdk_window_x11_get_pointer (GdkWindow       *window,
3130                             gint            *x,
3131                             gint            *y,
3132                             GdkModifierType *mask)
3133 {
3134   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
3135   gboolean return_val;
3136   Window root;
3137   Window child;
3138   int rootx, rooty;
3139   int winx = 0;
3140   int winy = 0;
3141   unsigned int xmask = 0;
3142
3143   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
3144
3145   
3146   return_val = TRUE;
3147   if (!GDK_WINDOW_DESTROYED (window))
3148     {
3149       if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
3150         {
3151           if (XQueryPointer (GDK_WINDOW_XDISPLAY (window),
3152                              GDK_WINDOW_XID (window),
3153                              &root, &child, &rootx, &rooty, &winx, &winy, &xmask))
3154             {
3155               if (child)
3156                 return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child) != NULL;
3157             }
3158         }
3159       else
3160         {
3161           GdkScreen *screen;
3162           int originx, originy;
3163           _gdk_windowing_get_pointer (gdk_drawable_get_display (window), &screen,
3164                                       &rootx, &rooty, &xmask);
3165           gdk_window_get_origin (window, &originx, &originy);
3166           winx = rootx - originx;
3167           winy = rooty - originy;
3168         }
3169     }
3170
3171   *x = winx;
3172   *y = winy;
3173   *mask = xmask;
3174
3175   return return_val;
3176 }
3177
3178 /**
3179  * gdk_display_warp_pointer:
3180  * @display: a #GdkDisplay
3181  * @screen: the screen of @display to warp the pointer to
3182  * @x: the x coordinate of the destination
3183  * @y: the y coordinate of the destination
3184  * 
3185  * Warps the pointer of @display to the point @x,@y on 
3186  * the screen @screen, unless the pointer is confined
3187  * to a window by a grab, in which case it will be moved
3188  * as far as allowed by the grab. Warping the pointer 
3189  * creates events as if the user had moved the mouse 
3190  * instantaneously to the destination.
3191  * 
3192  * Note that the pointer should normally be under the
3193  * control of the user. This function was added to cover
3194  * some rare use cases like keyboard navigation support
3195  * for the color picker in the #GtkColorSelectionDialog.
3196  *
3197  * Since: 2.8
3198  */ 
3199 void
3200 gdk_display_warp_pointer (GdkDisplay *display,
3201                           GdkScreen  *screen,
3202                           gint        x,
3203                           gint        y)
3204 {
3205   Display *xdisplay;
3206   Window dest;
3207
3208   xdisplay = GDK_DISPLAY_XDISPLAY (display);
3209   dest = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
3210
3211   XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0, x, y);  
3212 }
3213
3214 GdkWindow*
3215 _gdk_windowing_window_at_pointer (GdkDisplay *display,
3216                                   gint       *win_x,
3217                                   gint       *win_y,
3218                                   GdkModifierType *mask)
3219 {
3220   GdkWindow *window;
3221   GdkScreen *screen;
3222   Window root;
3223   Window xwindow;
3224   Window child;
3225   Window xwindow_last = 0;
3226   Display *xdisplay;
3227   int rootx = -1, rooty = -1;
3228   int winx, winy;
3229   unsigned int xmask;
3230
3231   screen = gdk_display_get_default_screen (display);
3232   
3233   xwindow = GDK_SCREEN_XROOTWIN (screen);
3234   xdisplay = GDK_SCREEN_XDISPLAY (screen);
3235
3236   /* This function really only works if the mouse pointer is held still
3237    * during its operation. If it moves from one leaf window to another
3238    * than we'll end up with inaccurate values for win_x, win_y
3239    * and the result.
3240    */
3241   gdk_x11_display_grab (display);
3242   if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) 
3243     {
3244       XQueryPointer (xdisplay, xwindow,
3245                      &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
3246       if (root == xwindow)
3247         xwindow = child;
3248       else
3249         xwindow = root;
3250       
3251       while (xwindow)
3252         {
3253           xwindow_last = xwindow;
3254           XQueryPointer (xdisplay, xwindow,
3255                          &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
3256         }
3257     } 
3258   else 
3259     {
3260       gint i, screens, width, height;
3261       GList *toplevels, *list;
3262       Window pointer_window;
3263       
3264       pointer_window = None;
3265       screens = gdk_display_get_n_screens (display);
3266       for (i = 0; i < screens; ++i) {
3267         screen = gdk_display_get_screen (display, i);
3268         toplevels = gdk_screen_get_toplevel_windows (screen);
3269         for (list = toplevels; list != NULL; list = g_list_next (list)) {
3270           window = GDK_WINDOW (list->data);
3271           xwindow = GDK_WINDOW_XWINDOW (window);
3272           gdk_error_trap_push ();
3273           XQueryPointer (xdisplay, xwindow,
3274                          &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
3275           gdk_flush ();
3276           if (gdk_error_trap_pop ())
3277             continue;
3278           if (child != None) 
3279             {
3280               pointer_window = child;
3281               break;
3282             }
3283           gdk_window_get_geometry (window, NULL, NULL, &width, &height, NULL);
3284           if (winx >= 0 && winy >= 0 && winx < width && winy < height) 
3285             {
3286               /* A childless toplevel, or below another window? */
3287               XSetWindowAttributes attributes;
3288               Window w;
3289               
3290               w = XCreateWindow (xdisplay, xwindow, winx, winy, 1, 1, 0, 
3291                                  CopyFromParent, InputOnly, CopyFromParent, 
3292                                  0, &attributes);
3293               XMapWindow (xdisplay, w);
3294               XQueryPointer (xdisplay, xwindow, 
3295                              &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
3296               XDestroyWindow (xdisplay, w);
3297               if (child == w) 
3298                 {
3299                   pointer_window = xwindow;
3300                   break;
3301                 }
3302             }
3303         }
3304         g_list_free (toplevels);
3305         if (pointer_window != None)
3306           break;
3307       }
3308       xwindow = pointer_window;
3309
3310       while (xwindow)
3311         {
3312           xwindow_last = xwindow;
3313           gdk_error_trap_push ();
3314           XQueryPointer (xdisplay, xwindow,
3315                          &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
3316           gdk_flush ();
3317           if (gdk_error_trap_pop ())
3318             break;
3319         }
3320     }
3321   
3322   gdk_x11_display_ungrab (display);
3323
3324   window = gdk_window_lookup_for_display (display, xwindow_last);
3325   *win_x = window ? winx : -1;
3326   *win_y = window ? winy : -1;
3327   if (mask)
3328     *mask = xmask;
3329   
3330   return window;
3331 }
3332
3333 static GdkEventMask
3334 gdk_window_x11_get_events (GdkWindow *window)
3335 {
3336   XWindowAttributes attrs;
3337   GdkEventMask event_mask;
3338   GdkEventMask filtered;
3339
3340   if (GDK_WINDOW_DESTROYED (window))
3341     return 0;
3342   else
3343     {
3344       XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3345                             GDK_WINDOW_XID (window),
3346                             &attrs);
3347       event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
3348       /* if property change was filtered out before, keep it filtered out */
3349       filtered = GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK;
3350       GDK_WINDOW_OBJECT (window)->event_mask = event_mask & ((GDK_WINDOW_OBJECT (window)->event_mask & filtered) | ~filtered);
3351
3352       return event_mask;
3353     }
3354 }
3355 static void
3356 gdk_window_x11_set_events (GdkWindow    *window,
3357                            GdkEventMask  event_mask)
3358 {
3359   long xevent_mask = 0;
3360   int i;
3361   
3362   if (!GDK_WINDOW_DESTROYED (window))
3363     {
3364       if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
3365         xevent_mask = StructureNotifyMask | PropertyChangeMask;
3366       for (i = 0; i < _gdk_nenvent_masks; i++)
3367         {
3368           if (event_mask & (1 << (i + 1)))
3369             xevent_mask |= _gdk_event_mask_table[i];
3370         }
3371       
3372       XSelectInput (GDK_WINDOW_XDISPLAY (window),
3373                     GDK_WINDOW_XID (window),
3374                     xevent_mask);
3375     }
3376 }
3377
3378 static void
3379 gdk_window_add_colormap_windows (GdkWindow *window)
3380 {
3381   GdkWindow *toplevel;
3382   Window *old_windows;
3383   Window *new_windows;
3384   int i, count;
3385   
3386   g_return_if_fail (GDK_IS_WINDOW (window));
3387
3388   if (GDK_WINDOW_DESTROYED (window))
3389     return;
3390
3391   toplevel = gdk_window_get_toplevel (window);
3392   
3393   old_windows = NULL;
3394   if (!XGetWMColormapWindows (GDK_WINDOW_XDISPLAY (toplevel),
3395                               GDK_WINDOW_XID (toplevel),
3396                               &old_windows, &count))
3397     {
3398       count = 0;
3399     }
3400   
3401   for (i = 0; i < count; i++)
3402     if (old_windows[i] == GDK_WINDOW_XID (window))
3403       {
3404         XFree (old_windows);
3405         return;
3406       }
3407   
3408   new_windows = g_new (Window, count + 1);
3409   
3410   for (i = 0; i < count; i++)
3411     new_windows[i] = old_windows[i];
3412   new_windows[count] = GDK_WINDOW_XID (window);
3413   
3414   XSetWMColormapWindows (GDK_WINDOW_XDISPLAY (toplevel),
3415                          GDK_WINDOW_XID (toplevel),
3416                          new_windows, count + 1);
3417   
3418   g_free (new_windows);
3419   if (old_windows)
3420     XFree (old_windows);
3421 }
3422
3423 static inline void
3424 do_shape_combine_region (GdkWindow       *window,
3425                          const GdkRegion *shape_region,
3426                          gint             offset_x,
3427                          gint             offset_y,
3428                          gint             shape)
3429 {
3430   GdkWindowObject *private = (GdkWindowObject *)window;
3431   
3432   if (GDK_WINDOW_DESTROYED (window))
3433     return;
3434
3435   if (shape_region == NULL)
3436     {
3437       /* Use NULL mask to unset the shape */
3438       if (shape == ShapeBounding
3439           ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3440           : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3441         {
3442           if (shape == ShapeBounding)
3443             {
3444               _gdk_x11_window_tmp_unset_parent_bg (window);
3445               _gdk_x11_window_tmp_unset_bg (window, TRUE);
3446             }
3447           XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
3448                              GDK_WINDOW_XID (window),
3449                              shape,
3450                              0, 0,
3451                              None,
3452                              ShapeSet);
3453           if (shape == ShapeBounding)
3454             {
3455               _gdk_x11_window_tmp_reset_parent_bg (window);
3456               _gdk_x11_window_tmp_reset_bg (window, TRUE);
3457             }
3458         }
3459       return;
3460     }
3461   
3462   if (shape == ShapeBounding
3463       ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3464       : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3465     {
3466       gint n_rects = 0;
3467       XRectangle *xrects = NULL;
3468
3469       _gdk_region_get_xrectangles (shape_region,
3470                                    0, 0,
3471                                    &xrects, &n_rects);
3472       
3473       if (shape == ShapeBounding)
3474         {
3475           _gdk_x11_window_tmp_unset_parent_bg (window);
3476           _gdk_x11_window_tmp_unset_bg (window, TRUE);
3477         }
3478       XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
3479                                GDK_WINDOW_XID (window),
3480                                shape,
3481                                offset_x, offset_y,
3482                                xrects, n_rects,
3483                                ShapeSet,
3484                                YXBanded);
3485
3486       if (shape == ShapeBounding)
3487         {
3488           _gdk_x11_window_tmp_reset_parent_bg (window);
3489           _gdk_x11_window_tmp_reset_bg (window, TRUE);
3490         }
3491       
3492       g_free (xrects);
3493     }
3494 }
3495
3496 static void
3497 gdk_window_x11_shape_combine_region (GdkWindow       *window,
3498                                      const GdkRegion *shape_region,
3499                                      gint             offset_x,
3500                                      gint             offset_y)
3501 {
3502   do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
3503 }
3504
3505 static void 
3506 gdk_window_x11_input_shape_combine_region (GdkWindow       *window,
3507                                            const GdkRegion *shape_region,
3508                                            gint             offset_x,
3509                                            gint             offset_y)
3510 {
3511 #ifdef ShapeInput
3512   do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
3513 #endif
3514 }
3515
3516
3517 /**
3518  * gdk_window_set_override_redirect:
3519  * @window: a toplevel #GdkWindow
3520  * @override_redirect: %TRUE if window should be override redirect
3521  *
3522  * An override redirect window is not under the control of the window manager.
3523  * This means it won't have a titlebar, won't be minimizable, etc. - it will
3524  * be entirely under the control of the application. The window manager
3525  * can't see the override redirect window at all.
3526  *
3527  * Override redirect should only be used for short-lived temporary
3528  * windows, such as popup menus. #GtkMenu uses an override redirect
3529  * window in its implementation, for example.
3530  * 
3531  **/
3532 void
3533 gdk_window_set_override_redirect (GdkWindow *window,
3534                                   gboolean override_redirect)
3535 {
3536   XSetWindowAttributes attr;
3537   
3538   if (!GDK_WINDOW_DESTROYED (window) &&
3539       WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3540     {
3541       GdkWindowObject *private = (GdkWindowObject *)window;
3542       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
3543
3544       attr.override_redirect = (override_redirect? True : False);
3545       XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3546                                GDK_WINDOW_XID (window),
3547                                CWOverrideRedirect,
3548                                &attr);
3549
3550       impl->override_redirect = attr.override_redirect;
3551     }
3552 }
3553
3554 /**
3555  * gdk_window_set_accept_focus:
3556  * @window: a toplevel #GdkWindow
3557  * @accept_focus: %TRUE if the window should receive input focus
3558  *
3559  * Setting @accept_focus to %FALSE hints the desktop environment that the
3560  * window doesn't want to receive input focus. 
3561  *
3562  * On X, it is the responsibility of the window manager to interpret this 
3563  * hint. ICCCM-compliant window manager usually respect it.
3564  *
3565  * Since: 2.4 
3566  **/
3567 void
3568 gdk_window_set_accept_focus (GdkWindow *window,
3569                              gboolean accept_focus)
3570 {
3571   GdkWindowObject *private;
3572
3573   private = (GdkWindowObject *)window;  
3574   
3575   accept_focus = accept_focus != FALSE;
3576
3577   if (private->accept_focus != accept_focus)
3578     {
3579       private->accept_focus = accept_focus;
3580
3581       if (!GDK_WINDOW_DESTROYED (window) &&
3582           WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3583         update_wm_hints (window, FALSE);
3584     }
3585 }
3586
3587 /**
3588  * gdk_window_set_focus_on_map:
3589  * @window: a toplevel #GdkWindow
3590  * @focus_on_map: %TRUE if the window should receive input focus when mapped
3591  *
3592  * Setting @focus_on_map to %FALSE hints the desktop environment that the
3593  * window doesn't want to receive input focus when it is mapped.  
3594  * focus_on_map should be turned off for windows that aren't triggered
3595  * interactively (such as popups from network activity).
3596  *
3597  * On X, it is the responsibility of the window manager to interpret
3598  * this hint. Window managers following the freedesktop.org window
3599  * manager extension specification should respect it.
3600  *
3601  * Since: 2.6 
3602  **/
3603 void
3604 gdk_window_set_focus_on_map (GdkWindow *window,
3605                              gboolean focus_on_map)
3606 {
3607   GdkWindowObject *private;
3608
3609   private = (GdkWindowObject *)window;  
3610   
3611   focus_on_map = focus_on_map != FALSE;
3612
3613   if (private->focus_on_map != focus_on_map)
3614     {
3615       private->focus_on_map = focus_on_map;
3616       
3617       if ((!GDK_WINDOW_DESTROYED (window)) &&
3618           (!private->focus_on_map) &&
3619           WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3620         gdk_x11_window_set_user_time (window, 0);
3621     }
3622 }
3623
3624 /**
3625  * gdk_x11_window_set_user_time:
3626  * @window: A toplevel #GdkWindow
3627  * @timestamp: An XServer timestamp to which the property should be set
3628  *
3629  * The application can use this call to update the _NET_WM_USER_TIME
3630  * property on a toplevel window.  This property stores an Xserver
3631  * time which represents the time of the last user input event
3632  * received for this window.  This property may be used by the window
3633  * manager to alter the focus, stacking, and/or placement behavior of
3634  * windows when they are mapped depending on whether the new window
3635  * was created by a user action or is a "pop-up" window activated by a
3636  * timer or some other event.
3637  *
3638  * Note that this property is automatically updated by GDK, so this
3639  * function should only be used by applications which handle input
3640  * events bypassing GDK.
3641  *
3642  * Since: 2.6
3643  **/
3644 void
3645 gdk_x11_window_set_user_time (GdkWindow *window,
3646                               guint32    timestamp)
3647 {
3648   GdkDisplay *display;
3649   GdkDisplayX11 *display_x11;
3650   GdkToplevelX11 *toplevel;
3651   glong timestamp_long = (glong)timestamp;
3652   Window xid;
3653
3654   if (GDK_WINDOW_DESTROYED (window) ||
3655       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3656     return;
3657
3658   display = gdk_drawable_get_display (window);
3659   display_x11 = GDK_DISPLAY_X11 (display);
3660   toplevel = _gdk_x11_window_get_toplevel (window);
3661
3662   if (!toplevel)
3663     {
3664       g_warning ("gdk_window_set_user_time called on non-toplevel\n");
3665       return;
3666     }
3667
3668   if (toplevel->focus_window != None &&
3669       gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3670                                            gdk_atom_intern_static_string ("_NET_WM_USER_TIME_WINDOW")))
3671     xid = toplevel->focus_window;
3672   else
3673     xid = GDK_WINDOW_XID (window);
3674
3675   XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xid,
3676                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
3677                    XA_CARDINAL, 32, PropModeReplace,
3678                    (guchar *)&timestamp_long, 1);
3679
3680   if (timestamp_long != GDK_CURRENT_TIME &&
3681       (display_x11->user_time == GDK_CURRENT_TIME ||
3682        XSERVER_TIME_IS_LATER (timestamp_long, display_x11->user_time)))
3683     display_x11->user_time = timestamp_long;
3684
3685   if (toplevel)
3686     toplevel->user_time = timestamp_long;
3687 }
3688
3689 #define GDK_SELECTION_MAX_SIZE(display)                                 \
3690   MIN(262144,                                                           \
3691       XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0     \
3692        ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100         \
3693        : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
3694
3695 /**
3696  * gdk_window_set_icon_list:
3697  * @window: The #GdkWindow toplevel window to set the icon of.
3698  * @pixbufs: A list of pixbufs, of different sizes.
3699  *
3700  * Sets a list of icons for the window. One of these will be used
3701  * to represent the window when it has been iconified. The icon is
3702  * usually shown in an icon box or some sort of task bar. Which icon
3703  * size is shown depends on the window manager. The window manager
3704  * can scale the icon  but setting several size icons can give better
3705  * image quality since the window manager may only need to scale the
3706  * icon by a small amount or not at all.
3707  *
3708  **/
3709 void
3710 gdk_window_set_icon_list (GdkWindow *window,
3711                           GList     *pixbufs)
3712 {
3713   gulong *data;
3714   guchar *pixels;
3715   gulong *p;
3716   gint size;
3717   GList *l;
3718   GdkPixbuf *pixbuf;
3719   gint width, height, stride;
3720   gint x, y;
3721   gint n_channels;
3722   GdkDisplay *display;
3723   gint n;
3724   
3725   if (GDK_WINDOW_DESTROYED (window) ||
3726       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3727     return;
3728
3729   display = gdk_drawable_get_display (window);
3730   
3731   l = pixbufs;
3732   size = 0;
3733   n = 0;
3734   while (l)
3735     {
3736       pixbuf = l->data;
3737       g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3738
3739       width = gdk_pixbuf_get_width (pixbuf);
3740       height = gdk_pixbuf_get_height (pixbuf);
3741       
3742       /* silently ignore overlarge icons */
3743       if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
3744         {
3745           g_warning ("gdk_window_set_icon_list: icons too large");
3746           break;
3747         }
3748      
3749       n++;
3750       size += 2 + width * height;
3751       
3752       l = g_list_next (l);
3753     }
3754
3755   data = g_malloc (size * sizeof (gulong));
3756
3757   l = pixbufs;
3758   p = data;
3759   while (l && n > 0)
3760     {
3761       pixbuf = l->data;
3762       
3763       width = gdk_pixbuf_get_width (pixbuf);
3764       height = gdk_pixbuf_get_height (pixbuf);
3765       stride = gdk_pixbuf_get_rowstride (pixbuf);
3766       n_channels = gdk_pixbuf_get_n_channels (pixbuf);
3767       
3768       *p++ = width;
3769       *p++ = height;
3770
3771       pixels = gdk_pixbuf_get_pixels (pixbuf);
3772
3773       for (y = 0; y < height; y++)
3774         {
3775           for (x = 0; x < width; x++)
3776             {
3777               guchar r, g, b, a;
3778               
3779               r = pixels[y*stride + x*n_channels + 0];
3780               g = pixels[y*stride + x*n_channels + 1];
3781               b = pixels[y*stride + x*n_channels + 2];
3782               if (n_channels >= 4)
3783                 a = pixels[y*stride + x*n_channels + 3];
3784               else
3785                 a = 255;
3786               
3787               *p++ = a << 24 | r << 16 | g << 8 | b ;
3788             }
3789         }
3790
3791       l = g_list_next (l);
3792       n--;
3793     }
3794
3795   if (size > 0)
3796     {
3797       XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3798                        GDK_WINDOW_XID (window),
3799                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
3800                        XA_CARDINAL, 32,
3801                        PropModeReplace,
3802                        (guchar*) data, size);
3803     }
3804   else
3805     {
3806       XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3807                        GDK_WINDOW_XID (window),
3808                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
3809     }
3810   
3811   g_free (data);
3812 }
3813
3814 /**
3815  * gdk_window_set_icon:
3816  * @window: a toplevel #GdkWindow
3817  * @icon_window: a #GdkWindow to use for the icon, or %NULL to unset
3818  * @pixmap: a #GdkPixmap to use as the icon, or %NULL to unset
3819  * @mask: a 1-bit pixmap (#GdkBitmap) to use as mask for @pixmap, or %NULL to have none
3820  *
3821  * Sets the icon of @window as a pixmap or window. If using GTK+, investigate
3822  * gtk_window_set_default_icon_list() first, and then gtk_window_set_icon_list()
3823  * and gtk_window_set_icon(). If those don't meet your needs, look at
3824  * gdk_window_set_icon_list(). Only if all those are too high-level do you
3825  * want to fall back to gdk_window_set_icon().
3826  * 
3827  **/
3828 void          
3829 gdk_window_set_icon (GdkWindow *window, 
3830                      GdkWindow *icon_window,
3831                      GdkPixmap *pixmap,
3832                      GdkBitmap *mask)
3833 {
3834   GdkToplevelX11 *toplevel;
3835
3836   if (GDK_WINDOW_DESTROYED (window) ||
3837       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3838     return;
3839
3840   toplevel = _gdk_x11_window_get_toplevel (window);
3841
3842   if (toplevel->icon_window != icon_window)
3843     {
3844       if (toplevel->icon_window)
3845         g_object_unref (toplevel->icon_window);
3846       toplevel->icon_window = g_object_ref (icon_window);
3847     }
3848   
3849   if (toplevel->icon_pixmap != pixmap)
3850     {
3851       if (pixmap)
3852         g_object_ref (pixmap);
3853       if (toplevel->icon_pixmap)
3854         g_object_unref (toplevel->icon_pixmap);
3855       toplevel->icon_pixmap = pixmap;
3856     }
3857   
3858   if (toplevel->icon_mask != mask)
3859     {
3860       if (mask)
3861         g_object_ref (mask);
3862       if (toplevel->icon_mask)
3863         g_object_unref (toplevel->icon_mask);
3864       toplevel->icon_mask = mask;
3865     }
3866   
3867   update_wm_hints (window, FALSE);
3868 }
3869
3870 static gboolean
3871 gdk_window_icon_name_set (GdkWindow *window)
3872 {
3873   return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
3874                                                g_quark_from_static_string ("gdk-icon-name-set")));
3875 }
3876
3877 /**
3878  * gdk_window_set_icon_name:
3879  * @window: a toplevel #GdkWindow
3880  * @name: name of window while iconified (minimized)
3881  *
3882  * Windows may have a name used while minimized, distinct from the
3883  * name they display in their titlebar. Most of the time this is a bad
3884  * idea from a user interface standpoint. But you can set such a name
3885  * with this function, if you like.
3886  *
3887  * After calling this with a non-%NULL @name, calls to gdk_window_set_title()
3888  * will not update the icon title.
3889  *
3890  * Using %NULL for @name unsets the icon title; further calls to
3891  * gdk_window_set_title() will again update the icon title as well.
3892  **/
3893 void
3894 gdk_window_set_icon_name (GdkWindow   *window, 
3895                           const gchar *name)
3896 {
3897   GdkDisplay *display;
3898
3899   if (GDK_WINDOW_DESTROYED (window) ||
3900       WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3901     return;
3902
3903   display = gdk_drawable_get_display (window);
3904
3905   g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
3906                       GUINT_TO_POINTER (name != NULL));
3907
3908   if (name != NULL)
3909     {
3910       XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3911                        GDK_WINDOW_XID (window),
3912                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
3913                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3914                        PropModeReplace, (guchar *)name, strlen (name));
3915
3916       set_text_property (display, GDK_WINDOW_XID (window),
3917                          gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
3918                          name);
3919     }
3920   else
3921     {
3922       XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3923                        GDK_WINDOW_XID (window),
3924                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"));
3925       XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3926                        GDK_WINDOW_XID (window),
3927                        gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"));
3928     }
3929 }
3930
3931 /**
3932  * gdk_window_iconify:
3933  * @window: a toplevel #GdkWindow
3934  * 
3935  * Asks to iconify (minimize) @window. The window manager may choose
3936  * to ignore the request, but normally will honor it. Using
3937  * gtk_window_iconify() is preferred, if you have a #GtkWindow widget.
3938  *
3939  * This function only makes sense when @window is a toplevel window.
3940  *
3941  **/
3942 void
3943 gdk_window_iconify (GdkWindow *window)
3944 {
3945   if (GDK_WINDOW_DESTROYED (window) ||
3946       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3947     return;
3948
3949   if (GDK_WINDOW_IS_MAPPED (window))
3950     {  
3951       XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
3952                       GDK_WINDOW_XWINDOW (window),
3953                       gdk_screen_get_number (GDK_WINDOW_SCREEN (window)));
3954     }
3955   else
3956     {
3957       /* Flip our client side flag, the real work happens on map. */
3958       gdk_synthesize_window_state (window,
3959                                    0,
3960                                    GDK_WINDOW_STATE_ICONIFIED);
3961     }
3962 }
3963
3964 /**
3965  * gdk_window_deiconify:
3966  * @window: a toplevel #GdkWindow
3967  *
3968  * Attempt to deiconify (unminimize) @window. On X11 the window manager may
3969  * choose to ignore the request to deiconify. When using GTK+,
3970  * use gtk_window_deiconify() instead of the #GdkWindow variant. Or better yet,
3971  * you probably want to use gtk_window_present(), which raises the window, focuses it,
3972  * unminimizes it, and puts it on the current desktop.
3973  *
3974  **/
3975 void
3976 gdk_window_deiconify (GdkWindow *window)
3977 {
3978   if (GDK_WINDOW_DESTROYED (window) ||
3979       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3980     return;
3981
3982   if (GDK_WINDOW_IS_MAPPED (window))
3983     {  
3984       gdk_window_show (window);
3985     }
3986   else
3987     {
3988       /* Flip our client side flag, the real work happens on map. */
3989       gdk_synthesize_window_state (window,
3990                                    GDK_WINDOW_STATE_ICONIFIED,
3991                                    0);
3992     }
3993 }
3994
3995 /**
3996  * gdk_window_stick:
3997  * @window: a toplevel #GdkWindow
3998  *
3999  * "Pins" a window such that it's on all workspaces and does not scroll
4000  * with viewports, for window managers that have scrollable viewports.
4001  * (When using #GtkWindow, gtk_window_stick() may be more useful.)
4002  *
4003  * On the X11 platform, this function depends on window manager
4004  * support, so may have no effect with many window managers. However,
4005  * GDK will do the best it can to convince the window manager to stick
4006  * the window. For window managers that don't support this operation,
4007  * there's nothing you can do to force it to happen.
4008  * 
4009  **/
4010 void
4011 gdk_window_stick (GdkWindow *window)
4012 {
4013   if (GDK_WINDOW_DESTROYED (window) ||
4014       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4015     return;
4016
4017   if (GDK_WINDOW_IS_MAPPED (window))
4018     {
4019       /* "stick" means stick to all desktops _and_ do not scroll with the
4020        * viewport. i.e. glue to the monitor glass in all cases.
4021        */
4022       
4023       XClientMessageEvent xclient;
4024
4025       /* Request stick during viewport scroll */
4026       gdk_wmspec_change_state (TRUE, window,
4027                                gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
4028                                GDK_NONE);
4029
4030       /* Request desktop 0xFFFFFFFF */
4031       memset (&xclient, 0, sizeof (xclient));
4032       xclient.type = ClientMessage;
4033       xclient.window = GDK_WINDOW_XWINDOW (window);
4034       xclient.display = GDK_WINDOW_XDISPLAY (window);
4035       xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), 
4036                                                                         "_NET_WM_DESKTOP");
4037       xclient.format = 32;
4038
4039       xclient.data.l[0] = 0xFFFFFFFF;
4040       xclient.data.l[1] = 0;
4041       xclient.data.l[2] = 0;
4042       xclient.data.l[3] = 0;
4043       xclient.data.l[4] = 0;
4044
4045       XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
4046                   SubstructureRedirectMask | SubstructureNotifyMask,
4047                   (XEvent *)&xclient);
4048     }
4049   else
4050     {
4051       /* Flip our client side flag, the real work happens on map. */
4052       gdk_synthesize_window_state (window,
4053                                    0,
4054                                    GDK_WINDOW_STATE_STICKY);
4055     }
4056 }
4057
4058 /**
4059  * gdk_window_unstick:
4060  * @window: a toplevel #GdkWindow
4061  *
4062  * Reverse operation for gdk_window_stick(); see gdk_window_stick(),
4063  * and gtk_window_unstick().
4064  * 
4065  **/
4066 void
4067 gdk_window_unstick (GdkWindow *window)
4068 {
4069   if (GDK_WINDOW_DESTROYED (window) ||
4070       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4071     return;
4072
4073   if (GDK_WINDOW_IS_MAPPED (window))
4074     {
4075       /* Request unstick from viewport */
4076       gdk_wmspec_change_state (FALSE, window,
4077                                gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
4078                                GDK_NONE);
4079
4080       move_to_current_desktop (window);
4081     }
4082   else
4083     {
4084       /* Flip our client side flag, the real work happens on map. */
4085       gdk_synthesize_window_state (window,
4086                                    GDK_WINDOW_STATE_STICKY,
4087                                    0);
4088
4089     }
4090 }
4091
4092 /**
4093  * gdk_window_maximize:
4094  * @window: a toplevel #GdkWindow
4095  *
4096  * Maximizes the window. If the window was already maximized, then
4097  * this function does nothing.
4098  * 
4099  * On X11, asks the window manager to maximize @window, if the window
4100  * manager supports this operation. Not all window managers support
4101  * this, and some deliberately ignore it or don't have a concept of
4102  * "maximized"; so you can't rely on the maximization actually
4103  * happening. But it will happen with most standard window managers,
4104  * and GDK makes a best effort to get it to happen.
4105  *
4106  * On Windows, reliably maximizes the window.
4107  * 
4108  **/
4109 void
4110 gdk_window_maximize (GdkWindow *window)
4111 {
4112   if (GDK_WINDOW_DESTROYED (window) ||
4113       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4114     return;
4115
4116   if (GDK_WINDOW_IS_MAPPED (window))
4117     gdk_wmspec_change_state (TRUE, window,
4118                              gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
4119                              gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
4120   else
4121     gdk_synthesize_window_state (window,
4122                                  0,
4123                                  GDK_WINDOW_STATE_MAXIMIZED);
4124 }
4125
4126 /**
4127  * gdk_window_unmaximize:
4128  * @window: a toplevel #GdkWindow
4129  *
4130  * Unmaximizes the window. If the window wasn't maximized, then this
4131  * function does nothing.
4132  * 
4133  * On X11, asks the window manager to unmaximize @window, if the
4134  * window manager supports this operation. Not all window managers
4135  * support this, and some deliberately ignore it or don't have a
4136  * concept of "maximized"; so you can't rely on the unmaximization
4137  * actually happening. But it will happen with most standard window
4138  * managers, and GDK makes a best effort to get it to happen.
4139  *
4140  * On Windows, reliably unmaximizes the window.
4141  * 
4142  **/
4143 void
4144 gdk_window_unmaximize (GdkWindow *window)
4145 {
4146   if (GDK_WINDOW_DESTROYED (window) ||
4147       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4148     return;
4149
4150   if (GDK_WINDOW_IS_MAPPED (window))
4151     gdk_wmspec_change_state (FALSE, window,
4152                              gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
4153                              gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
4154   else
4155     gdk_synthesize_window_state (window,
4156                                  GDK_WINDOW_STATE_MAXIMIZED,
4157                                  0);
4158 }
4159
4160 /**
4161  * gdk_window_fullscreen:
4162  * @window: a toplevel #GdkWindow
4163  *
4164  * Moves the window into fullscreen mode. This means the
4165  * window covers the entire screen and is above any panels
4166  * or task bars.
4167  *
4168  * If the window was already fullscreen, then this function does nothing.
4169  * 
4170  * On X11, asks the window manager to put @window in a fullscreen
4171  * state, if the window manager supports this operation. Not all
4172  * window managers support this, and some deliberately ignore it or
4173  * don't have a concept of "fullscreen"; so you can't rely on the
4174  * fullscreenification actually happening. But it will happen with
4175  * most standard window managers, and GDK makes a best effort to get
4176  * it to happen.
4177  *
4178  * Since: 2.2
4179  **/
4180 void
4181 gdk_window_fullscreen (GdkWindow *window)
4182 {
4183   if (GDK_WINDOW_DESTROYED (window) ||
4184       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4185     return;
4186
4187   if (GDK_WINDOW_IS_MAPPED (window))
4188     gdk_wmspec_change_state (TRUE, window,
4189                              gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
4190                              GDK_NONE);
4191
4192   else
4193     gdk_synthesize_window_state (window,
4194                                  0,
4195                                  GDK_WINDOW_STATE_FULLSCREEN);
4196 }
4197
4198 /**
4199  * gdk_window_unfullscreen:
4200  * @window: a toplevel #GdkWindow
4201  *
4202  * Moves the window out of fullscreen mode. If the window was not
4203  * fullscreen, does nothing.
4204  * 
4205  * On X11, asks the window manager to move @window out of the fullscreen
4206  * state, if the window manager supports this operation. Not all
4207  * window managers support this, and some deliberately ignore it or
4208  * don't have a concept of "fullscreen"; so you can't rely on the
4209  * unfullscreenification actually happening. But it will happen with
4210  * most standard window managers, and GDK makes a best effort to get
4211  * it to happen. 
4212  *
4213  * Since: 2.2
4214  **/
4215 void
4216 gdk_window_unfullscreen (GdkWindow *window)
4217 {
4218   if (GDK_WINDOW_DESTROYED (window) ||
4219       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4220     return;
4221
4222   if (GDK_WINDOW_IS_MAPPED (window))
4223     gdk_wmspec_change_state (FALSE, window,
4224                              gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
4225                              GDK_NONE);
4226
4227   else
4228     gdk_synthesize_window_state (window,
4229                                  GDK_WINDOW_STATE_FULLSCREEN,
4230                                  0);
4231 }
4232
4233 /**
4234  * gdk_window_set_keep_above:
4235  * @window: a toplevel #GdkWindow
4236  * @setting: whether to keep @window above other windows
4237  *
4238  * Set if @window must be kept above other windows. If the
4239  * window was already above, then this function does nothing.
4240  * 
4241  * On X11, asks the window manager to keep @window above, if the window
4242  * manager supports this operation. Not all window managers support
4243  * this, and some deliberately ignore it or don't have a concept of
4244  * "keep above"; so you can't rely on the window being kept above.
4245  * But it will happen with most standard window managers,
4246  * and GDK makes a best effort to get it to happen.
4247  *
4248  * Since: 2.4
4249  **/
4250 void
4251 gdk_window_set_keep_above (GdkWindow *window,
4252                            gboolean   setting)
4253 {
4254   g_return_if_fail (GDK_IS_WINDOW (window));
4255
4256   if (GDK_WINDOW_DESTROYED (window) ||
4257       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4258     return;
4259
4260   if (GDK_WINDOW_IS_MAPPED (window))
4261     {
4262       if (setting)
4263         gdk_wmspec_change_state (FALSE, window,
4264                                  gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
4265                                  GDK_NONE);
4266       gdk_wmspec_change_state (setting, window,
4267                                gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4268                                GDK_NONE);
4269     }
4270   else
4271     gdk_synthesize_window_state (window,
4272                                  setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
4273                                  setting ? GDK_WINDOW_STATE_ABOVE : 0);
4274 }
4275
4276 /**
4277  * gdk_window_set_keep_below:
4278  * @window: a toplevel #GdkWindow
4279  * @setting: whether to keep @window below other windows
4280  *
4281  * Set if @window must be kept below other windows. If the
4282  * window was already below, then this function does nothing.
4283  * 
4284  * On X11, asks the window manager to keep @window below, if the window
4285  * manager supports this operation. Not all window managers support
4286  * this, and some deliberately ignore it or don't have a concept of
4287  * "keep below"; so you can't rely on the window being kept below.
4288  * But it will happen with most standard window managers,
4289  * and GDK makes a best effort to get it to happen.
4290  *
4291  * Since: 2.4
4292  **/
4293 void
4294 gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
4295 {
4296   g_return_if_fail (GDK_IS_WINDOW (window));
4297
4298   if (GDK_WINDOW_DESTROYED (window) ||
4299       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4300     return;
4301
4302   if (GDK_WINDOW_IS_MAPPED (window))
4303     {
4304       if (setting)
4305         gdk_wmspec_change_state (FALSE, window,
4306                                  gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4307                                  GDK_NONE);
4308       gdk_wmspec_change_state (setting, window,
4309                                gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
4310                                GDK_NONE);
4311     }
4312   else
4313     gdk_synthesize_window_state (window,
4314                                  setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
4315                                  setting ? GDK_WINDOW_STATE_BELOW : 0);
4316 }
4317
4318 /**
4319  * gdk_window_get_group:
4320  * @window: a toplevel #GdkWindow
4321  * 
4322  * Returns the group leader window for @window. See gdk_window_set_group().
4323  * 
4324  * Return value: the group leader window for @window
4325  *
4326  * Since: 2.4
4327  **/
4328 GdkWindow *
4329 gdk_window_get_group (GdkWindow *window)
4330 {
4331   GdkToplevelX11 *toplevel;
4332   
4333   if (GDK_WINDOW_DESTROYED (window) ||
4334       !WINDOW_IS_TOPLEVEL (window))
4335     return NULL;
4336   
4337   toplevel = _gdk_x11_window_get_toplevel (window);
4338
4339   return toplevel->group_leader;
4340 }
4341
4342 /**
4343  * gdk_window_set_group:
4344  * @window: a toplevel #GdkWindow
4345  * @leader: group leader window, or %NULL to restore the default group leader window
4346  *
4347  * Sets the group leader window for @window. By default,
4348  * GDK sets the group leader for all toplevel windows
4349  * to a global window implicitly created by GDK. With this function
4350  * you can override this default.
4351  *
4352  * The group leader window allows the window manager to distinguish
4353  * all windows that belong to a single application. It may for example
4354  * allow users to minimize/unminimize all windows belonging to an
4355  * application at once. You should only set a non-default group window
4356  * if your application pretends to be multiple applications.
4357  **/
4358 void          
4359 gdk_window_set_group (GdkWindow *window,
4360                       GdkWindow *leader)
4361 {
4362   GdkToplevelX11 *toplevel;
4363   
4364   g_return_if_fail (GDK_IS_WINDOW (window));
4365   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
4366   g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
4367
4368   if (GDK_WINDOW_DESTROYED (window) ||
4369       (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
4370       !WINDOW_IS_TOPLEVEL (window))
4371     return;
4372
4373   toplevel = _gdk_x11_window_get_toplevel (window);
4374
4375   if (leader == NULL)
4376     leader = gdk_display_get_default_group (gdk_drawable_get_display (window));
4377   
4378   if (toplevel->group_leader != leader)
4379     {
4380       if (toplevel->group_leader)
4381         g_object_unref (toplevel->group_leader);
4382       toplevel->group_leader = g_object_ref (leader);
4383       (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;      
4384     }
4385
4386   update_wm_hints (window, FALSE);
4387 }
4388
4389 static MotifWmHints *
4390 gdk_window_get_mwm_hints (GdkWindow *window)
4391 {
4392   GdkDisplay *display;
4393   Atom hints_atom = None;
4394   guchar *data;
4395   Atom type;
4396   gint format;
4397   gulong nitems;
4398   gulong bytes_after;
4399   
4400   if (GDK_WINDOW_DESTROYED (window))
4401     return NULL;
4402
4403   display = gdk_drawable_get_display (window);
4404   
4405   hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4406
4407   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
4408                       hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4409                       False, AnyPropertyType, &type, &format, &nitems,
4410                       &bytes_after, &data);
4411
4412   if (type == None)
4413     return NULL;
4414   
4415   return (MotifWmHints *)data;
4416 }
4417
4418 static void
4419 gdk_window_set_mwm_hints (GdkWindow *window,
4420                           MotifWmHints *new_hints)
4421 {
4422   GdkDisplay *display;
4423   Atom hints_atom = None;
4424   guchar *data;
4425   MotifWmHints *hints;
4426   Atom type;
4427   gint format;
4428   gulong nitems;
4429   gulong bytes_after;
4430   
4431   if (GDK_WINDOW_DESTROYED (window))
4432     return;
4433   
4434   display = gdk_drawable_get_display (window);
4435   
4436   hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4437
4438   XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4439                       hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4440                       False, AnyPropertyType, &type, &format, &nitems,
4441                       &bytes_after, &data);
4442   
4443   if (type == None)
4444     hints = new_hints;
4445   else
4446     {
4447       hints = (MotifWmHints *)data;
4448         
4449       if (new_hints->flags & MWM_HINTS_FUNCTIONS)
4450         {
4451           hints->flags |= MWM_HINTS_FUNCTIONS;
4452           hints->functions = new_hints->functions;
4453         }
4454       if (new_hints->flags & MWM_HINTS_DECORATIONS)
4455         {
4456           hints->flags |= MWM_HINTS_DECORATIONS;
4457           hints->decorations = new_hints->decorations;
4458         }
4459     }
4460   
4461   XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4462                    hints_atom, hints_atom, 32, PropModeReplace,
4463                    (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
4464   
4465   if (hints != new_hints)
4466     XFree (hints);
4467 }
4468
4469 /**
4470  * gdk_window_set_decorations:
4471  * @window: a toplevel #GdkWindow
4472  * @decorations: decoration hint mask
4473  *
4474  * "Decorations" are the features the window manager adds to a toplevel #GdkWindow.
4475  * This function sets the traditional Motif window manager hints that tell the
4476  * window manager which decorations you would like your window to have.
4477  * Usually you should use gtk_window_set_decorated() on a #GtkWindow instead of
4478  * using the GDK function directly.
4479  *
4480  * The @decorations argument is the logical OR of the fields in
4481  * the #GdkWMDecoration enumeration. If #GDK_DECOR_ALL is included in the
4482  * mask, the other bits indicate which decorations should be turned off.
4483  * If #GDK_DECOR_ALL is not included, then the other bits indicate
4484  * which decorations should be turned on.
4485  *
4486  * Most window managers honor a decorations hint of 0 to disable all decorations,
4487  * but very few honor all possible combinations of bits.
4488  * 
4489  **/
4490 void
4491 gdk_window_set_decorations (GdkWindow      *window,
4492                             GdkWMDecoration decorations)
4493 {
4494   MotifWmHints hints;
4495
4496   if (GDK_WINDOW_DESTROYED (window) ||
4497       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4498     return;
4499   
4500   /* initialize to zero to avoid writing uninitialized data to socket */
4501   memset(&hints, 0, sizeof(hints));
4502   hints.flags = MWM_HINTS_DECORATIONS;
4503   hints.decorations = decorations;
4504   
4505   gdk_window_set_mwm_hints (window, &hints);
4506 }
4507
4508 /**
4509  * gdk_window_get_decorations:
4510  * @window: The toplevel #GdkWindow to get the decorations from
4511  * @decorations: The window decorations will be written here
4512  *
4513  * Returns the decorations set on the GdkWindow with #gdk_window_set_decorations
4514  * Returns: TRUE if the window has decorations set, FALSE otherwise.
4515  **/
4516 gboolean
4517 gdk_window_get_decorations(GdkWindow       *window,
4518                            GdkWMDecoration *decorations)
4519 {
4520   MotifWmHints *hints;
4521   gboolean result = FALSE;
4522
4523   if (GDK_WINDOW_DESTROYED (window) ||
4524       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4525     return FALSE;
4526   
4527   hints = gdk_window_get_mwm_hints (window);
4528   
4529   if (hints)
4530     {
4531       if (hints->flags & MWM_HINTS_DECORATIONS)
4532         {
4533           if (decorations)
4534             *decorations = hints->decorations;
4535           result = TRUE;
4536         }
4537       
4538       XFree (hints);
4539     }
4540
4541   return result;
4542 }
4543
4544 /**
4545  * gdk_window_set_functions:
4546  * @window: a toplevel #GdkWindow
4547  * @functions: bitmask of operations to allow on @window
4548  *
4549  * Sets hints about the window management functions to make available
4550  * via buttons on the window frame.
4551  * 
4552  * On the X backend, this function sets the traditional Motif window 
4553  * manager hint for this purpose. However, few window managers do
4554  * anything reliable or interesting with this hint. Many ignore it
4555  * entirely.
4556  *
4557  * The @functions argument is the logical OR of values from the
4558  * #GdkWMFunction enumeration. If the bitmask includes #GDK_FUNC_ALL,
4559  * then the other bits indicate which functions to disable; if
4560  * it doesn't include #GDK_FUNC_ALL, it indicates which functions to
4561  * enable.
4562  * 
4563  **/
4564 void
4565 gdk_window_set_functions (GdkWindow    *window,
4566                           GdkWMFunction functions)
4567 {
4568   MotifWmHints hints;
4569   
4570   g_return_if_fail (GDK_IS_WINDOW (window));
4571
4572   if (GDK_WINDOW_DESTROYED (window) ||
4573       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4574     return;
4575   
4576   /* initialize to zero to avoid writing uninitialized data to socket */
4577   memset(&hints, 0, sizeof(hints));
4578   hints.flags = MWM_HINTS_FUNCTIONS;
4579   hints.functions = functions;
4580   
4581   gdk_window_set_mwm_hints (window, &hints);
4582 }
4583
4584 static GdkRegion *
4585 xwindow_get_shape (Display *xdisplay,
4586                    Window window,
4587                    gint shape_type)
4588 {
4589   GdkRegion *shape;
4590   GdkRectangle *rl;
4591   XRectangle *xrl;
4592   gint rn, ord, i;
4593
4594   shape = NULL;
4595   
4596   xrl = XShapeGetRectangles (xdisplay,
4597                              window,
4598                              shape_type, &rn, &ord);
4599   
4600   if (rn == 0)
4601     return gdk_region_new (); /* Empty */
4602   
4603   if (ord != YXBanded)
4604     {
4605       /* This really shouldn't happen with any xserver, as they
4606          generally convert regions to YXBanded internally */
4607       g_warning ("non YXBanded shape masks not supported");
4608       XFree (xrl);
4609       return NULL;
4610     }
4611
4612   rl = g_new (GdkRectangle, rn);
4613   for (i = 0; i < rn; i++)
4614     {
4615       rl[i].x = xrl[i].x;
4616       rl[i].y = xrl[i].y;
4617       rl[i].width = xrl[i].width;
4618       rl[i].height = xrl[i].height;
4619     }
4620   XFree (xrl);
4621   
4622   shape = _gdk_region_new_from_yxbanded_rects (rl, rn);
4623   g_free (rl);
4624   
4625   return shape;
4626 }
4627
4628
4629 GdkRegion *
4630 _gdk_windowing_get_shape_for_mask (GdkBitmap *mask)
4631 {
4632   GdkDisplay *display;
4633   Window window;
4634   GdkRegion *region;
4635
4636   display = gdk_drawable_get_display (GDK_DRAWABLE (mask));
4637
4638   window = XCreateSimpleWindow (GDK_DISPLAY_XDISPLAY (display),
4639                                 GDK_SCREEN_XROOTWIN (gdk_display_get_default_screen (display)),
4640                                 -1, -1, 1, 1, 0,
4641                                 0, 0);
4642   XShapeCombineMask (GDK_DISPLAY_XDISPLAY (display),
4643                      window,
4644                      ShapeBounding,
4645                      0, 0,
4646                      GDK_PIXMAP_XID (mask),
4647                      ShapeSet);
4648   
4649   region = xwindow_get_shape (GDK_DISPLAY_XDISPLAY (display),
4650                               window, ShapeBounding);
4651
4652   XDestroyWindow (GDK_DISPLAY_XDISPLAY (display),
4653                   window);
4654
4655   return region;
4656 }
4657
4658 GdkRegion *
4659 _gdk_windowing_window_get_shape (GdkWindow *window)
4660 {
4661   if (!GDK_WINDOW_DESTROYED (window) &&
4662       gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
4663     return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4664                               GDK_WINDOW_XID (window), ShapeBounding);
4665
4666   return NULL;
4667 }
4668
4669 GdkRegion *
4670 _gdk_windowing_window_get_input_shape (GdkWindow *window)
4671 {
4672 #if defined(ShapeInput)
4673   if (!GDK_WINDOW_DESTROYED (window) &&
4674       gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
4675     return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4676                               GDK_WINDOW_XID (window),
4677                               ShapeInput);
4678 #endif
4679
4680   return NULL;
4681 }
4682
4683 static void
4684 gdk_window_set_static_bit_gravity (GdkWindow *window,
4685                                    gboolean   on)
4686 {
4687   XSetWindowAttributes xattributes;
4688   GdkWindowObject *private;
4689   guint xattributes_mask = 0;
4690   
4691   g_return_if_fail (GDK_IS_WINDOW (window));
4692
4693   private = GDK_WINDOW_OBJECT (window);
4694   if (private->input_only)
4695     return;
4696   
4697   xattributes.bit_gravity = StaticGravity;
4698   xattributes_mask |= CWBitGravity;
4699   xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
4700   XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4701                            GDK_WINDOW_XID (window),
4702                            CWBitGravity,  &xattributes);
4703 }
4704
4705 static void
4706 gdk_window_set_static_win_gravity (GdkWindow *window,
4707                                    gboolean   on)
4708 {
4709   XSetWindowAttributes xattributes;
4710   
4711   g_return_if_fail (GDK_IS_WINDOW (window));
4712   
4713   xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
4714   
4715   XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4716                            GDK_WINDOW_XID (window),
4717                            CWWinGravity,  &xattributes);
4718 }
4719
4720 static gboolean
4721 gdk_window_x11_set_static_gravities (GdkWindow *window,
4722                                      gboolean   use_static)
4723 {
4724   GdkWindowObject *private = (GdkWindowObject *)window;
4725   GList *tmp_list;
4726   
4727   if (!use_static == !private->guffaw_gravity)
4728     return TRUE;
4729
4730   private->guffaw_gravity = use_static;
4731   
4732   if (!GDK_WINDOW_DESTROYED (window))
4733     {
4734       gdk_window_set_static_bit_gravity (window, use_static);
4735       
4736       tmp_list = private->children;
4737       while (tmp_list)
4738         {
4739           gdk_window_set_static_win_gravity (tmp_list->data, use_static);
4740           
4741           tmp_list = tmp_list->next;
4742         }
4743     }
4744   
4745   return TRUE;
4746 }
4747
4748 static void
4749 wmspec_moveresize (GdkWindow *window,
4750                    gint       direction,
4751                    gint       root_x,
4752                    gint       root_y,
4753                    guint32    timestamp)     
4754 {
4755   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
4756   
4757   XClientMessageEvent xclient;
4758
4759   /* Release passive grab */
4760   gdk_display_pointer_ungrab (display, timestamp);
4761
4762   memset (&xclient, 0, sizeof (xclient));
4763   xclient.type = ClientMessage;
4764   xclient.window = GDK_WINDOW_XID (window);
4765   xclient.message_type =
4766     gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
4767   xclient.format = 32;
4768   xclient.data.l[0] = root_x;
4769   xclient.data.l[1] = root_y;
4770   xclient.data.l[2] = direction;
4771   xclient.data.l[3] = 0;
4772   xclient.data.l[4] = 0;
4773   
4774   XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
4775               SubstructureRedirectMask | SubstructureNotifyMask,
4776               (XEvent *)&xclient);
4777 }
4778
4779 typedef struct _MoveResizeData MoveResizeData;
4780
4781 struct _MoveResizeData
4782 {
4783   GdkDisplay *display;
4784   
4785   GdkWindow *moveresize_window;
4786   GdkWindow *moveresize_emulation_window;
4787   gboolean is_resize;
4788   GdkWindowEdge resize_edge;
4789   gint moveresize_button;
4790   gint moveresize_x;
4791   gint moveresize_y;
4792   gint moveresize_orig_x;
4793   gint moveresize_orig_y;
4794   gint moveresize_orig_width;
4795   gint moveresize_orig_height;
4796   GdkWindowHints moveresize_geom_mask;
4797   GdkGeometry moveresize_geometry;
4798   Time moveresize_process_time;
4799   XEvent *moveresize_pending_event;
4800 };
4801
4802 /* From the WM spec */
4803 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT      0
4804 #define _NET_WM_MOVERESIZE_SIZE_TOP          1
4805 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT     2
4806 #define _NET_WM_MOVERESIZE_SIZE_RIGHT        3
4807 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT  4
4808 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM       5
4809 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT   6
4810 #define _NET_WM_MOVERESIZE_SIZE_LEFT         7
4811 #define _NET_WM_MOVERESIZE_MOVE              8
4812
4813 static void
4814 wmspec_resize_drag (GdkWindow     *window,
4815                     GdkWindowEdge  edge,
4816                     gint           button,
4817                     gint           root_x,
4818                     gint           root_y,
4819                     guint32        timestamp)
4820 {
4821   gint direction;
4822   
4823   /* Let the compiler turn a switch into a table, instead
4824    * of doing the table manually, this way is easier to verify.
4825    */
4826   switch (edge)
4827     {
4828     case GDK_WINDOW_EDGE_NORTH_WEST:
4829       direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
4830       break;
4831
4832     case GDK_WINDOW_EDGE_NORTH:
4833       direction = _NET_WM_MOVERESIZE_SIZE_TOP;
4834       break;
4835
4836     case GDK_WINDOW_EDGE_NORTH_EAST:
4837       direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
4838       break;
4839
4840     case GDK_WINDOW_EDGE_WEST:
4841       direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
4842       break;
4843
4844     case GDK_WINDOW_EDGE_EAST:
4845       direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
4846       break;
4847
4848     case GDK_WINDOW_EDGE_SOUTH_WEST:
4849       direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
4850       break;
4851
4852     case GDK_WINDOW_EDGE_SOUTH:
4853       direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
4854       break;
4855
4856     case GDK_WINDOW_EDGE_SOUTH_EAST:
4857       direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
4858       break;
4859
4860     default:
4861       g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
4862                  edge);
4863       return;
4864     }
4865   
4866   wmspec_moveresize (window, direction, root_x, root_y, timestamp);
4867 }
4868
4869 static MoveResizeData *
4870 get_move_resize_data (GdkDisplay *display,
4871                       gboolean    create)
4872 {
4873   MoveResizeData *mv_resize;
4874   static GQuark move_resize_quark = 0;
4875
4876   if (!move_resize_quark)
4877     move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
4878   
4879   mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
4880
4881   if (!mv_resize && create)
4882     {
4883       mv_resize = g_new0 (MoveResizeData, 1);
4884       mv_resize->display = display;
4885       
4886       g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
4887     }
4888
4889   return mv_resize;
4890 }
4891
4892 static void
4893 update_pos (MoveResizeData *mv_resize,
4894             gint            new_root_x,
4895             gint            new_root_y)
4896 {
4897   gint dx, dy;
4898
4899   dx = new_root_x - mv_resize->moveresize_x;
4900   dy = new_root_y - mv_resize->moveresize_y;
4901
4902   if (mv_resize->is_resize)
4903     {
4904       gint x, y, w, h;
4905
4906       x = mv_resize->moveresize_orig_x;
4907       y = mv_resize->moveresize_orig_y;
4908
4909       w = mv_resize->moveresize_orig_width;
4910       h = mv_resize->moveresize_orig_height;
4911
4912       switch (mv_resize->resize_edge)
4913         {
4914         case GDK_WINDOW_EDGE_NORTH_WEST:
4915           x += dx;
4916           y += dy;
4917           w -= dx;
4918           h -= dy;
4919           break;
4920         case GDK_WINDOW_EDGE_NORTH:
4921           y += dy;
4922           h -= dy;
4923           break;
4924         case GDK_WINDOW_EDGE_NORTH_EAST:
4925           y += dy;
4926           h -= dy;
4927           w += dx;
4928           break;
4929         case GDK_WINDOW_EDGE_SOUTH_WEST:
4930           h += dy;
4931           x += dx;
4932           w -= dx;
4933           break;
4934         case GDK_WINDOW_EDGE_SOUTH_EAST:
4935           w += dx;
4936           h += dy;
4937           break;
4938         case GDK_WINDOW_EDGE_SOUTH:
4939           h += dy;
4940           break;
4941         case GDK_WINDOW_EDGE_EAST:
4942           w += dx;
4943           break;
4944         case GDK_WINDOW_EDGE_WEST:
4945           x += dx;
4946           w -= dx;
4947           break;
4948         }
4949
4950       x = MAX (x, 0);
4951       y = MAX (y, 0);
4952       w = MAX (w, 1);
4953       h = MAX (h, 1);
4954
4955       if (mv_resize->moveresize_geom_mask)
4956         {
4957           gdk_window_constrain_size (&mv_resize->moveresize_geometry,
4958                                      mv_resize->moveresize_geom_mask,
4959                                      w, h, &w, &h);
4960         }
4961
4962       gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
4963     }
4964   else
4965     {
4966       gint x, y;
4967
4968       x = mv_resize->moveresize_orig_x + dx;
4969       y = mv_resize->moveresize_orig_y + dy;
4970
4971       gdk_window_move (mv_resize->moveresize_window, x, y);
4972     }
4973 }
4974
4975 static void
4976 finish_drag (MoveResizeData *mv_resize)
4977 {
4978   gdk_window_destroy (mv_resize->moveresize_emulation_window);
4979   mv_resize->moveresize_emulation_window = NULL;
4980   g_object_unref (mv_resize->moveresize_window);
4981   mv_resize->moveresize_window = NULL;
4982
4983   if (mv_resize->moveresize_pending_event)
4984     {
4985       g_free (mv_resize->moveresize_pending_event);
4986       mv_resize->moveresize_pending_event = NULL;
4987     }
4988 }
4989
4990 static int
4991 lookahead_motion_predicate (Display *xdisplay,
4992                             XEvent  *event,
4993                             XPointer arg)
4994 {
4995   gboolean *seen_release = (gboolean *)arg;
4996   GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
4997   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4998
4999   if (*seen_release)
5000     return False;
5001
5002   switch (event->xany.type)
5003     {
5004     case ButtonRelease:
5005       *seen_release = TRUE;
5006       break;
5007     case MotionNotify:
5008       mv_resize->moveresize_process_time = event->xmotion.time;
5009       break;
5010     default:
5011       break;
5012     }
5013
5014   return False;
5015 }
5016
5017 static gboolean
5018 moveresize_lookahead (MoveResizeData *mv_resize,
5019                       XEvent         *event)
5020 {
5021   XEvent tmp_event;
5022   gboolean seen_release = FALSE;
5023
5024   if (mv_resize->moveresize_process_time)
5025     {
5026       if (event->xmotion.time == mv_resize->moveresize_process_time)
5027         {
5028           mv_resize->moveresize_process_time = 0;
5029           return TRUE;
5030         }
5031       else
5032         return FALSE;
5033     }
5034
5035   XCheckIfEvent (event->xany.display, &tmp_event,
5036                  lookahead_motion_predicate, (XPointer) & seen_release);
5037
5038   return mv_resize->moveresize_process_time == 0;
5039 }
5040         
5041 gboolean
5042 _gdk_moveresize_handle_event (XEvent *event)
5043 {
5044   guint button_mask = 0;
5045   GdkWindowObject *window_private;
5046   GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
5047   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
5048
5049   if (!mv_resize || !mv_resize->moveresize_window)
5050     return FALSE;
5051
5052   window_private = (GdkWindowObject *) mv_resize->moveresize_window;
5053
5054   button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
5055
5056   switch (event->xany.type)
5057     {
5058     case MotionNotify:
5059       if (window_private->resize_count > 0)
5060         {
5061           if (mv_resize->moveresize_pending_event)
5062             *mv_resize->moveresize_pending_event = *event;
5063           else
5064             mv_resize->moveresize_pending_event =
5065               g_memdup (event, sizeof (XEvent));
5066
5067           break;
5068         }
5069       if (!moveresize_lookahead (mv_resize, event))
5070         break;
5071
5072       update_pos (mv_resize,
5073                   event->xmotion.x_root,
5074                   event->xmotion.y_root);
5075
5076       /* This should never be triggered in normal cases, but in the
5077        * case where the drag started without an implicit grab being
5078        * in effect, we could miss the release if it occurs before
5079        * we grab the pointer; this ensures that we will never
5080        * get a permanently stuck grab.
5081        */
5082       if ((event->xmotion.state & button_mask) == 0)
5083         finish_drag (mv_resize);
5084       break;
5085
5086     case ButtonRelease:
5087       update_pos (mv_resize,
5088                   event->xbutton.x_root,
5089                   event->xbutton.y_root);
5090
5091       if (event->xbutton.button == mv_resize->moveresize_button)
5092         finish_drag (mv_resize);
5093       break;
5094     }
5095   return TRUE;
5096 }
5097
5098 gboolean 
5099 _gdk_moveresize_configure_done (GdkDisplay *display,
5100                                 GdkWindow  *window)
5101 {
5102   XEvent *tmp_event;
5103   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
5104   
5105   if (!mv_resize || window != mv_resize->moveresize_window)
5106     return FALSE;
5107
5108   if (mv_resize->moveresize_pending_event)
5109     {
5110       tmp_event = mv_resize->moveresize_pending_event;
5111       mv_resize->moveresize_pending_event = NULL;
5112       _gdk_moveresize_handle_event (tmp_event);
5113       g_free (tmp_event);
5114     }
5115   
5116   return TRUE;
5117 }
5118
5119 static void
5120 create_moveresize_window (MoveResizeData *mv_resize,
5121                           guint32         timestamp)
5122 {
5123   GdkWindowAttr attributes;
5124   gint attributes_mask;
5125   GdkGrabStatus status;
5126
5127   g_assert (mv_resize->moveresize_emulation_window == NULL);
5128
5129   attributes.x = -100;
5130   attributes.y = -100;
5131   attributes.width = 10;
5132   attributes.height = 10;
5133   attributes.window_type = GDK_WINDOW_TEMP;
5134   attributes.wclass = GDK_INPUT_ONLY;
5135   attributes.override_redirect = TRUE;
5136   attributes.event_mask = 0;
5137
5138   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
5139
5140   mv_resize->moveresize_emulation_window = 
5141     gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
5142                     &attributes,
5143                     attributes_mask);
5144
5145   gdk_window_show (mv_resize->moveresize_emulation_window);
5146
5147   status = gdk_pointer_grab (mv_resize->moveresize_emulation_window,
5148                              FALSE,
5149                              GDK_BUTTON_RELEASE_MASK |
5150                              GDK_POINTER_MOTION_MASK,
5151                              NULL,
5152                              NULL,
5153                              timestamp);
5154
5155   if (status != GDK_GRAB_SUCCESS)
5156     {
5157       /* If this fails, some other client has grabbed the window
5158        * already.
5159        */
5160       finish_drag (mv_resize);
5161     }
5162
5163   mv_resize->moveresize_process_time = 0;
5164 }
5165
5166 /* 
5167    Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
5168    so that calling XMoveWindow with these coordinates will not move the 
5169    window.
5170    Note that this depends on the WM to implement ICCCM-compliant reference
5171    point handling.
5172 */
5173 static void 
5174 calculate_unmoving_origin (MoveResizeData *mv_resize)
5175 {
5176   GdkRectangle rect;
5177   gint width, height;
5178
5179   if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
5180       mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
5181     {
5182       gdk_window_get_origin (mv_resize->moveresize_window,
5183                              &mv_resize->moveresize_orig_x,
5184                              &mv_resize->moveresize_orig_y);
5185     }
5186   else
5187     {
5188       gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
5189       gdk_window_get_geometry (mv_resize->moveresize_window, 
5190                                NULL, NULL, &width, &height, NULL);
5191       
5192       switch (mv_resize->moveresize_geometry.win_gravity) 
5193         {
5194         case GDK_GRAVITY_NORTH_WEST:
5195           mv_resize->moveresize_orig_x = rect.x;
5196           mv_resize->moveresize_orig_y = rect.y;
5197           break;
5198         case GDK_GRAVITY_NORTH:
5199           mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
5200           mv_resize->moveresize_orig_y = rect.y;
5201           break;          
5202         case GDK_GRAVITY_NORTH_EAST:
5203           mv_resize->moveresize_orig_x = rect.x + rect.width - width;
5204           mv_resize->moveresize_orig_y = rect.y;
5205           break;
5206         case GDK_GRAVITY_WEST:
5207           mv_resize->moveresize_orig_x = rect.x;
5208           mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
5209           break;
5210         case GDK_GRAVITY_CENTER:
5211           mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
5212           mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
5213           break;
5214         case GDK_GRAVITY_EAST:
5215           mv_resize->moveresize_orig_x = rect.x + rect.width - width;
5216           mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
5217           break;
5218         case GDK_GRAVITY_SOUTH_WEST:
5219           mv_resize->moveresize_orig_x = rect.x;
5220           mv_resize->moveresize_orig_y = rect.y + rect.height - height;
5221           break;
5222         case GDK_GRAVITY_SOUTH:
5223           mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
5224           mv_resize->moveresize_orig_y = rect.y + rect.height - height;
5225           break;
5226         case GDK_GRAVITY_SOUTH_EAST:
5227           mv_resize->moveresize_orig_x = rect.x + rect.width - width;
5228           mv_resize->moveresize_orig_y = rect.y + rect.height - height;
5229           break;
5230         default:
5231           mv_resize->moveresize_orig_x = rect.x;
5232           mv_resize->moveresize_orig_y = rect.y;
5233           break; 
5234         }
5235     }  
5236 }
5237
5238 static void
5239 emulate_resize_drag (GdkWindow     *window,
5240                      GdkWindowEdge  edge,
5241                      gint           button,
5242                      gint           root_x,
5243                      gint           root_y,
5244                      guint32        timestamp)
5245 {
5246   MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
5247
5248   mv_resize->is_resize = TRUE;
5249   mv_resize->moveresize_button = button;
5250   mv_resize->resize_edge = edge;
5251   mv_resize->moveresize_x = root_x;
5252   mv_resize->moveresize_y = root_y;
5253   mv_resize->moveresize_window = g_object_ref (window);
5254
5255   gdk_drawable_get_size (window,
5256                          &mv_resize->moveresize_orig_width,
5257                          &mv_resize->moveresize_orig_height);
5258
5259   mv_resize->moveresize_geom_mask = 0;
5260   gdk_window_get_geometry_hints (window,
5261                                  &mv_resize->moveresize_geometry,
5262                                  &mv_resize->moveresize_geom_mask);
5263
5264   calculate_unmoving_origin (mv_resize);
5265
5266   create_moveresize_window (mv_resize, timestamp);
5267 }
5268
5269 static void
5270 emulate_move_drag (GdkWindow     *window,
5271                    gint           button,
5272                    gint           root_x,
5273                    gint           root_y,
5274                    guint32        timestamp)
5275 {
5276   MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
5277   
5278   mv_resize->is_resize = FALSE;
5279   mv_resize->moveresize_button = button;
5280   mv_resize->moveresize_x = root_x;
5281   mv_resize->moveresize_y = root_y;
5282
5283   mv_resize->moveresize_window = g_object_ref (window);
5284
5285   calculate_unmoving_origin (mv_resize);
5286
5287   create_moveresize_window (mv_resize, timestamp);
5288 }
5289
5290 /**
5291  * gdk_window_begin_resize_drag:
5292  * @window: a toplevel #GdkWindow
5293  * @edge: the edge or corner from which the drag is started
5294  * @button: the button being used to drag
5295  * @root_x: root window X coordinate of mouse click that began the drag
5296  * @root_y: root window Y coordinate of mouse click that began the drag
5297  * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
5298  *
5299  * Begins a window resize operation (for a toplevel window).
5300  * You might use this function to implement a "window resize grip," for
5301  * example; in fact #GtkStatusbar uses it. The function works best
5302  * with window managers that support the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended Window Manager Hints</ulink>, but has a 
5303  * fallback implementation for other window managers.
5304  * 
5305  **/
5306 void
5307 gdk_window_begin_resize_drag (GdkWindow     *window,
5308                               GdkWindowEdge  edge,
5309                               gint           button,
5310                               gint           root_x,
5311                               gint           root_y,
5312                               guint32        timestamp)
5313 {
5314   if (GDK_WINDOW_DESTROYED (window) ||
5315       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
5316     return;
5317
5318   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5319                                            gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5320     wmspec_resize_drag (window, edge, button, root_x, root_y, timestamp);
5321   else
5322     emulate_resize_drag (window, edge, button, root_x, root_y, timestamp);
5323 }
5324
5325 /**
5326  * gdk_window_begin_move_drag:
5327  * @window: a toplevel #GdkWindow
5328  * @button: the button being used to drag
5329  * @root_x: root window X coordinate of mouse click that began the drag
5330  * @root_y: root window Y coordinate of mouse click that began the drag
5331  * @timestamp: timestamp of mouse click that began the drag
5332  *
5333  * Begins a window move operation (for a toplevel window).  You might
5334  * use this function to implement a "window move grip," for
5335  * example. The function works best with window managers that support
5336  * the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended 
5337  * Window Manager Hints</ulink>, but has a fallback implementation for
5338  * other window managers.
5339  * 
5340  **/
5341 void
5342 gdk_window_begin_move_drag (GdkWindow *window,
5343                             gint       button,
5344                             gint       root_x,
5345                             gint       root_y,
5346                             guint32    timestamp)
5347 {
5348   if (GDK_WINDOW_DESTROYED (window) ||
5349       !WINDOW_IS_TOPLEVEL (window))
5350     return;
5351
5352   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5353                                            gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5354     wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE, root_x, root_y,
5355                        timestamp);
5356   else
5357     emulate_move_drag (window, button, root_x, root_y, timestamp);
5358 }
5359
5360 /**
5361  * gdk_window_enable_synchronized_configure:
5362  * @window: a toplevel #GdkWindow
5363  * 
5364  * Indicates that the application will cooperate with the window
5365  * system in synchronizing the window repaint with the window
5366  * manager during resizing operations. After an application calls
5367  * this function, it must call gdk_window_configure_finished() every
5368  * time it has finished all processing associated with a set of
5369  * Configure events. Toplevel GTK+ windows automatically use this
5370  * protocol.
5371  * 
5372  * On X, calling this function makes @window participate in the
5373  * _NET_WM_SYNC_REQUEST window manager protocol.
5374  * 
5375  * Since: 2.6
5376  **/
5377 void
5378 gdk_window_enable_synchronized_configure (GdkWindow *window)
5379 {
5380   GdkWindowObject *private = (GdkWindowObject *)window;
5381   GdkWindowImplX11 *impl;
5382
5383   if (!GDK_IS_WINDOW_IMPL_X11 (private->impl))
5384     return;
5385   
5386   impl = GDK_WINDOW_IMPL_X11 (private->impl);
5387           
5388   if (!impl->use_synchronized_configure)
5389     {
5390       /* This basically means you want to do fancy X specific stuff, so
5391          ensure we have a native window */
5392       gdk_window_ensure_native (window);
5393
5394       impl->use_synchronized_configure = TRUE;
5395       ensure_sync_counter (window);
5396     }
5397 }
5398
5399 /**
5400  * gdk_window_configure_finished:
5401  * @window: a toplevel #GdkWindow
5402  * 
5403  * Signal to the window system that the application has finished
5404  * handling Configure events it has received. Window Managers can
5405  * use this to better synchronize the frame repaint with the
5406  * application. GTK+ applications will automatically call this
5407  * function when appropriate.
5408  *
5409  * This function can only be called if gdk_window_enable_synchronized_configure()
5410  * was called previously.
5411  *
5412  * Since: 2.6
5413  **/
5414 void
5415 gdk_window_configure_finished (GdkWindow *window)
5416 {
5417   GdkWindowImplX11 *impl;
5418
5419   if (!WINDOW_IS_TOPLEVEL (window))
5420     return;
5421   
5422   impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
5423   if (!impl->use_synchronized_configure)
5424     return;
5425   
5426 #ifdef HAVE_XSYNC
5427   if (!GDK_WINDOW_DESTROYED (window))
5428     {
5429       GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
5430       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
5431
5432       if (toplevel && toplevel->update_counter != None &&
5433           GDK_DISPLAY_X11 (display)->use_sync &&
5434           !XSyncValueIsZero (toplevel->current_counter_value))
5435         {
5436           XSyncSetCounter (GDK_WINDOW_XDISPLAY (window), 
5437                            toplevel->update_counter,
5438                            toplevel->current_counter_value);
5439           
5440           XSyncIntToValue (&toplevel->current_counter_value, 0);
5441         }
5442     }
5443 #endif
5444 }
5445
5446 void
5447 _gdk_windowing_window_beep (GdkWindow *window)
5448 {
5449   GdkDisplay *display;
5450
5451   g_return_if_fail (GDK_IS_WINDOW (window));
5452
5453   display = GDK_WINDOW_DISPLAY (window);
5454
5455 #ifdef HAVE_XKB
5456   if (GDK_DISPLAY_X11 (display)->use_xkb)
5457     XkbBell (GDK_DISPLAY_XDISPLAY (display),
5458              GDK_WINDOW_XID (window),
5459              0,
5460              None);
5461   else
5462 #endif
5463     gdk_display_beep (display);
5464 }
5465
5466 /**
5467  * gdk_window_set_opacity:
5468  * @window: a top-level #GdkWindow
5469  * @opacity: opacity
5470  *
5471  * Request the windowing system to make @window partially transparent,
5472  * with opacity 0 being fully transparent and 1 fully opaque. (Values
5473  * of the opacity parameter are clamped to the [0,1] range.) 
5474  *
5475  * On X11, this works only on X screens with a compositing manager 
5476  * running.
5477  *
5478  * For setting up per-pixel alpha, see gdk_screen_get_rgba_colormap().
5479  * For making non-toplevel windows translucent, see 
5480  * gdk_window_set_composited().
5481  *
5482  * Since: 2.12
5483  */
5484 void
5485 gdk_window_set_opacity (GdkWindow *window,
5486                         gdouble    opacity)
5487 {
5488   GdkDisplay *display;
5489   guint32 cardinal;
5490   
5491   g_return_if_fail (GDK_IS_WINDOW (window));
5492
5493   if (GDK_WINDOW_DESTROYED (window) ||
5494       !WINDOW_IS_TOPLEVEL (window))
5495     return;
5496
5497   display = gdk_drawable_get_display (window);
5498
5499   if (opacity < 0)
5500     opacity = 0;
5501   else if (opacity > 1)
5502     opacity = 1;
5503
5504   cardinal = opacity * 0xffffffff;
5505
5506   if (cardinal == 0xffffffff)
5507     XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
5508                      GDK_WINDOW_XID (window),
5509                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"));
5510   else
5511     XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
5512                      GDK_WINDOW_XID (window),
5513                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"),
5514                      XA_CARDINAL, 32,
5515                      PropModeReplace,
5516                      (guchar *) &cardinal, 1);
5517 }
5518
5519 void
5520 _gdk_windowing_window_set_composited (GdkWindow *window,
5521                                       gboolean   composited)
5522 {
5523 #if defined(HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
5524   GdkWindowObject *private = (GdkWindowObject *) window;
5525   GdkWindowImplX11 *impl;
5526   GdkDisplay *display;
5527   Display *dpy;
5528   Window xid;
5529
5530   impl = GDK_WINDOW_IMPL_X11 (private->impl);
5531
5532   display = gdk_screen_get_display (GDK_DRAWABLE_IMPL_X11 (impl)->screen);
5533   dpy = GDK_DISPLAY_XDISPLAY (display);
5534   xid = GDK_WINDOW_XWINDOW (private);
5535
5536   if (composited)
5537     {
5538       XCompositeRedirectWindow (dpy, xid, CompositeRedirectManual);
5539       impl->damage = XDamageCreate (dpy, xid, XDamageReportBoundingBox);
5540     }
5541   else
5542     {
5543       XCompositeUnredirectWindow (dpy, xid, CompositeRedirectManual);
5544       XDamageDestroy (dpy, impl->damage);
5545       impl->damage = None;
5546     }
5547 #endif
5548 }
5549
5550 void
5551 _gdk_windowing_window_process_updates_recurse (GdkWindow *window,
5552                                                GdkRegion *region)
5553 {
5554   _gdk_window_process_updates_recurse (window, region);
5555 }
5556
5557 void
5558 _gdk_windowing_before_process_all_updates (void)
5559 {
5560 }
5561
5562 void
5563 _gdk_windowing_after_process_all_updates (void)
5564 {
5565 }
5566
5567 static void
5568 gdk_window_impl_iface_init (GdkWindowImplIface *iface)
5569 {
5570   iface->show = gdk_window_x11_show;
5571   iface->hide = gdk_window_x11_hide;
5572   iface->withdraw = gdk_window_x11_withdraw;
5573   iface->set_events = gdk_window_x11_set_events;
5574   iface->get_events = gdk_window_x11_get_events;
5575   iface->raise = gdk_window_x11_raise;
5576   iface->lower = gdk_window_x11_lower;
5577   iface->restack_under = gdk_window_x11_restack_under;
5578   iface->restack_toplevel = gdk_window_x11_restack_toplevel;
5579   iface->move_resize = gdk_window_x11_move_resize;
5580   iface->set_background = gdk_window_x11_set_background;
5581   iface->set_back_pixmap = gdk_window_x11_set_back_pixmap;
5582   iface->reparent = gdk_window_x11_reparent;
5583   iface->clear_region = gdk_window_x11_clear_region;
5584   iface->set_cursor = gdk_window_x11_set_cursor;
5585   iface->get_geometry = gdk_window_x11_get_geometry;
5586   iface->get_root_coords = gdk_window_x11_get_root_coords;
5587   iface->get_pointer = gdk_window_x11_get_pointer;
5588   iface->get_deskrelative_origin = gdk_window_x11_get_deskrelative_origin;
5589   iface->shape_combine_region = gdk_window_x11_shape_combine_region;
5590   iface->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
5591   iface->set_static_gravities = gdk_window_x11_set_static_gravities;
5592   iface->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
5593   iface->queue_translation = _gdk_x11_window_queue_translation;
5594   iface->destroy = _gdk_x11_window_destroy;
5595   iface->input_window_destroy = _gdk_input_window_destroy;
5596   iface->input_window_crossing = _gdk_input_crossing_event;
5597 }
5598
5599 #define __GDK_WINDOW_X11_C__
5600 #include "gdkaliasdef.c"