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