]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
566bedde2d80c6dbab21158a0ceefd548c758290
[~andy/gtk] / gtk / gtkwindow.c
1 /* GTK - The GIMP Toolkit
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 "gtkwindow.h"
30
31 #include <string.h>
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <limits.h>
35
36 #include "gtkprivate.h"
37 #include "gtkwindowprivate.h"
38 #include "gtkaccelgroupprivate.h"
39 #include "gtkbindings.h"
40 #include "gtkkeyhash.h"
41 #include "gtkmain.h"
42 #include "gtkmnemonichash.h"
43 #include "gtkmenubar.h"
44 #include "gtkiconfactory.h"
45 #include "gtkicontheme.h"
46 #include "gtkmarshalers.h"
47 #include "gtkplug.h"
48 #include "gtkbuildable.h"
49 #include "gtkwidgetprivate.h"
50 #include "gtkcontainerprivate.h"
51 #include "gtkintl.h"
52 #include "gtktypebuiltins.h"
53 #include "a11y/gtkwindowaccessible.h"
54
55 #include "deprecated/gtkstyle.h"
56
57 #ifdef GDK_WINDOWING_X11
58 #include "x11/gdkx.h"
59 #endif
60
61 /**
62  * SECTION:gtkwindow
63  * @title: GtkWindow
64  * @short_description: Toplevel which can contain other widgets
65  *
66  * A GtkWindow is a toplevel window which can contain other widgets.
67  * Windows normally have decorations that are under the control
68  * of the windowing system and allow the user to manipulate the window
69  * (resize it, move it, close it,...).
70  *
71  * GTK+ also allows windows to have a resize grip (a small area in the lower
72  * right or left corner) which can be clicked to reszie the window. To
73  * control whether a window has a resize grip, use
74  * gtk_window_set_has_resize_grip().
75  *
76  * <refsect2 id="GtkWindow-BUILDER-UI">
77  * <title>GtkWindow as GtkBuildable</title>
78  * <para>
79  * The GtkWindow implementation of the GtkBuildable interface supports a
80  * custom <tag class="starttag">accel-groups</tag> element, which supports
81  * any number of <tag class="starttag">group</tag> elements representing the
82  * #GtkAccelGroup objects you want to add to your window (synonymous with
83  * gtk_window_add_accel_group().
84  * </para>
85  * <example>
86  * <title>A UI definition fragment with accel groups</title>
87  * <programlisting><![CDATA[
88  * <object class="GtkWindow">
89  *   <accel-groups>
90  *     <group name="accelgroup1"/>
91  *   </accel-groups>
92  * </object>
93  * <!-- -->
94  * ...
95  * <!-- -->
96  * <object class="GtkAccelGroup" id="accelgroup1"/>
97  * ]]></programlisting>
98  * </example>
99  * </refsect2>
100  */
101
102 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
103
104 struct _GtkWindowPrivate
105 {
106   GtkMnemonicHash       *mnemonic_hash;
107
108   GtkWidget             *attach_widget;
109   GtkWidget             *default_widget;
110   GtkWidget             *focus_widget;
111   GtkWindow             *transient_parent;
112   GtkWindowGeometryInfo *geometry_info;
113   GtkWindowGroup        *group;
114   GdkScreen             *screen;
115   GtkApplication        *application;
116
117   GdkModifierType        mnemonic_modifier;
118   GdkWindowTypeHint      gdk_type_hint;
119
120   gdouble  opacity;
121
122   GdkWindow *grip_window;
123
124   gchar   *startup_id;
125   gchar   *title;
126   gchar   *wmclass_class;
127   gchar   *wmclass_name;
128   gchar   *wm_role;
129
130   guint    keys_changed_handler;
131
132   guint32  initial_timestamp;
133
134   guint16  configure_request_count;
135
136   /* The following flags are initially TRUE (before a window is mapped).
137    * They cause us to compute a configure request that involves
138    * default-only parameters. Once mapped, we set them to FALSE.
139    * Then we set them to TRUE again on unmap (for position)
140    * and on unrealize (for size).
141    */
142   guint    need_default_position     : 1;
143   guint    need_default_size         : 1;
144
145   guint    above_initially           : 1;
146   guint    accept_focus              : 1;
147   guint    below_initially           : 1;
148   guint    builder_visible           : 1;
149   guint    configure_notify_received : 1;
150   guint    decorated                 : 1;
151   guint    deletable                 : 1;
152   guint    destroy_with_parent       : 1;
153   guint    focus_on_map              : 1;
154   guint    fullscreen_initially      : 1;
155   guint    has_focus                 : 1;
156   guint    has_user_ref_count        : 1;
157   guint    has_toplevel_focus        : 1;
158   guint    hide_titlebar_when_maximized : 1;
159   guint    iconify_initially         : 1; /* gtk_window_iconify() called before realization */
160   guint    is_active                 : 1;
161   guint    maximize_initially        : 1;
162   guint    mnemonics_visible         : 1;
163   guint    mnemonics_visible_set     : 1;
164   guint    focus_visible             : 1;
165   guint    modal                     : 1;
166   guint    opacity_set               : 1;
167   guint    position                  : 3;
168   guint    reset_type_hint           : 1;
169   guint    resizable                 : 1;
170   guint    skips_pager               : 1;
171   guint    skips_taskbar             : 1;
172   guint    stick_initially           : 1;
173   guint    transient_parent_group    : 1;
174   guint    type                      : 4; /* GtkWindowType */
175   guint    type_hint                 : 3; /* GdkWindowTypeHint if the hint is
176                                            * one of the original eight. If not,
177                                            * then it contains
178                                            * GDK_WINDOW_TYPE_HINT_NORMAL
179                                            */
180   guint    urgent                    : 1;
181   guint    has_resize_grip           : 1;
182   guint    resize_grip_visible       : 1;  /* don't use, just for "resize-
183                                             * grip-visible" notification
184                                             */
185   guint    gravity                   : 5; /* GdkGravity */
186
187 };
188
189 enum {
190   SET_FOCUS,
191   FRAME_EVENT,
192   ACTIVATE_FOCUS,
193   ACTIVATE_DEFAULT,
194   KEYS_CHANGED,
195   LAST_SIGNAL
196 };
197
198 enum {
199   PROP_0,
200
201   /* Construct */
202   PROP_TYPE,
203
204   /* Normal Props */
205   PROP_TITLE,
206   PROP_ROLE,
207   PROP_RESIZABLE,
208   PROP_MODAL,
209   PROP_WIN_POS,
210   PROP_DEFAULT_WIDTH,
211   PROP_DEFAULT_HEIGHT,
212   PROP_DESTROY_WITH_PARENT,
213   PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
214   PROP_ICON,
215   PROP_ICON_NAME,
216   PROP_SCREEN,
217   PROP_TYPE_HINT,
218   PROP_SKIP_TASKBAR_HINT,
219   PROP_SKIP_PAGER_HINT,
220   PROP_URGENCY_HINT,
221   PROP_ACCEPT_FOCUS,
222   PROP_FOCUS_ON_MAP,
223   PROP_DECORATED,
224   PROP_DELETABLE,
225   PROP_GRAVITY,
226   PROP_TRANSIENT_FOR,
227   PROP_ATTACHED_TO,
228   PROP_OPACITY,
229   PROP_HAS_RESIZE_GRIP,
230   PROP_RESIZE_GRIP_VISIBLE,
231   PROP_APPLICATION,
232   /* Readonly properties */
233   PROP_IS_ACTIVE,
234   PROP_HAS_TOPLEVEL_FOCUS,
235
236   /* Writeonly properties */
237   PROP_STARTUP_ID,
238
239   PROP_MNEMONICS_VISIBLE,
240   PROP_FOCUS_VISIBLE,
241
242   LAST_ARG
243 };
244
245 typedef struct
246 {
247   GList     *icon_list;
248   gchar     *icon_name;
249   guint      realized : 1;
250   guint      using_default_icon : 1;
251   guint      using_parent_icon : 1;
252   guint      using_themed_icon : 1;
253 } GtkWindowIconInfo;
254
255 typedef struct {
256   GdkGeometry    geometry; /* Last set of geometry hints we set */
257   GdkWindowHints flags;
258   GdkRectangle   configure_request;
259 } GtkWindowLastGeometryInfo;
260
261 struct _GtkWindowGeometryInfo
262 {
263   /* Properties that the app has set on the window
264    */
265   GdkGeometry    geometry;      /* Geometry hints */
266   GdkWindowHints mask;
267   GtkWidget     *widget;        /* subwidget to which hints apply */
268   /* from last gtk_window_resize () - if > 0, indicates that
269    * we should resize to this size.
270    */
271   gint           resize_width;  
272   gint           resize_height;
273
274   /* From last gtk_window_move () prior to mapping -
275    * only used if initial_pos_set
276    */
277   gint           initial_x;
278   gint           initial_y;
279   
280   /* Default size - used only the FIRST time we map a window,
281    * only if > 0.
282    */
283   gint           default_width; 
284   gint           default_height;
285   /* whether to use initial_x, initial_y */
286   guint          initial_pos_set : 1;
287   /* CENTER_ALWAYS or other position constraint changed since
288    * we sent the last configure request.
289    */
290   guint          position_constraints_changed : 1;
291
292   /* if true, default_width, height should be multiplied by the
293    * increments and affect the geometry widget only
294    */
295   guint          default_is_geometry : 1;
296
297   /* if true, resize_width, height should be multiplied by the
298    * increments and affect the geometry widget only
299    */
300   guint          resize_is_geometry : 1;
301   
302   GtkWindowLastGeometryInfo last;
303 };
304
305
306 struct _GtkDeviceGrabInfo
307 {
308   GtkWidget *widget;
309   GdkDevice *device;
310   guint block_others : 1;
311 };
312
313 struct _GtkWindowGroupPrivate
314 {
315   GSList *grabs;
316   GSList *device_grabs;
317 };
318
319 static void gtk_window_dispose            (GObject           *object);
320 static void gtk_window_finalize           (GObject           *object);
321 static void gtk_window_destroy            (GtkWidget         *widget);
322 static void gtk_window_show               (GtkWidget         *widget);
323 static void gtk_window_hide               (GtkWidget         *widget);
324 static void gtk_window_map                (GtkWidget         *widget);
325 static void gtk_window_unmap              (GtkWidget         *widget);
326 static void gtk_window_realize            (GtkWidget         *widget);
327 static void gtk_window_unrealize          (GtkWidget         *widget);
328 static void gtk_window_size_allocate      (GtkWidget         *widget,
329                                            GtkAllocation     *allocation);
330 static gboolean gtk_window_map_event      (GtkWidget         *widget,
331                                            GdkEventAny       *event);
332 static gint gtk_window_configure_event    (GtkWidget         *widget,
333                                            GdkEventConfigure *event);
334 static gint gtk_window_key_press_event    (GtkWidget         *widget,
335                                            GdkEventKey       *event);
336 static gint gtk_window_key_release_event  (GtkWidget         *widget,
337                                            GdkEventKey       *event);
338 static gint gtk_window_button_press_event (GtkWidget         *widget,
339                                            GdkEventButton    *event);
340 static gint gtk_window_enter_notify_event (GtkWidget         *widget,
341                                            GdkEventCrossing  *event);
342 static gint gtk_window_leave_notify_event (GtkWidget         *widget,
343                                            GdkEventCrossing  *event);
344 static gint gtk_window_focus_in_event     (GtkWidget         *widget,
345                                            GdkEventFocus     *event);
346 static gint gtk_window_focus_out_event    (GtkWidget         *widget,
347                                            GdkEventFocus     *event);
348 static void gtk_window_style_updated      (GtkWidget         *widget);
349 static gboolean gtk_window_state_event    (GtkWidget          *widget,
350                                            GdkEventWindowState *event);
351 static void gtk_window_check_resize       (GtkContainer      *container);
352 static gint gtk_window_focus              (GtkWidget        *widget,
353                                            GtkDirectionType  direction);
354 static void gtk_window_move_focus         (GtkWidget         *widget,
355                                            GtkDirectionType   dir);
356 static void gtk_window_real_set_focus     (GtkWindow         *window,
357                                            GtkWidget         *focus);
358 static void gtk_window_direction_changed  (GtkWidget         *widget,
359                                            GtkTextDirection   prev_dir);
360 static void gtk_window_state_changed      (GtkWidget         *widget,
361                                            GtkStateType       previous_state);
362
363 static void gtk_window_real_activate_default (GtkWindow         *window);
364 static void gtk_window_real_activate_focus   (GtkWindow         *window);
365 static void gtk_window_keys_changed          (GtkWindow         *window);
366 static gint gtk_window_draw                  (GtkWidget         *widget,
367                                               cairo_t           *cr);
368 static void gtk_window_unset_transient_for         (GtkWindow  *window);
369 static void gtk_window_transient_parent_realized   (GtkWidget  *parent,
370                                                     GtkWidget  *window);
371 static void gtk_window_transient_parent_unrealized (GtkWidget  *parent,
372                                                     GtkWidget  *window);
373
374 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
375
376 static GtkWindowGeometryInfo* gtk_window_get_geometry_info         (GtkWindow    *window,
377                                                                     gboolean      create);
378
379 static void     gtk_window_move_resize               (GtkWindow    *window);
380 static gboolean gtk_window_compare_hints             (GdkGeometry  *geometry_a,
381                                                       guint         flags_a,
382                                                       GdkGeometry  *geometry_b,
383                                                       guint         flags_b);
384 static void     gtk_window_constrain_size            (GtkWindow    *window,
385                                                       GdkGeometry  *geometry,
386                                                       guint         flags,
387                                                       gint          width,
388                                                       gint          height,
389                                                       gint         *new_width,
390                                                       gint         *new_height);
391 static void     gtk_window_constrain_position        (GtkWindow    *window,
392                                                       gint          new_width,
393                                                       gint          new_height,
394                                                       gint         *x,
395                                                       gint         *y);
396 static void     gtk_window_compute_hints             (GtkWindow    *window,
397                                                       GdkGeometry  *new_geometry,
398                                                       guint        *new_flags);
399 static void     gtk_window_compute_configure_request (GtkWindow    *window,
400                                                       GdkRectangle *request,
401                                                       GdkGeometry  *geometry,
402                                                       guint        *flags);
403
404 static void     gtk_window_set_default_size_internal (GtkWindow    *window,
405                                                       gboolean      change_width,
406                                                       gint          width,
407                                                       gboolean      change_height,
408                                                       gint          height,
409                                                       gboolean      is_geometry);
410
411 static void     update_themed_icon                    (GtkIconTheme *theme,
412                                                        GtkWindow    *window);
413 static GList   *icon_list_from_theme                  (GtkWidget    *widget,
414                                                        const gchar  *name);
415 static void     gtk_window_realize_icon               (GtkWindow    *window);
416 static void     gtk_window_unrealize_icon             (GtkWindow    *window);
417 static void     resize_grip_create_window             (GtkWindow    *window);
418 static void     resize_grip_destroy_window            (GtkWindow    *window);
419 static void     update_grip_visibility                (GtkWindow    *window);
420
421 static void        gtk_window_notify_keys_changed (GtkWindow   *window);
422 static GtkKeyHash *gtk_window_get_key_hash        (GtkWindow   *window);
423 static void        gtk_window_free_key_hash       (GtkWindow   *window);
424 static void        gtk_window_on_composited_changed (GdkScreen *screen,
425                                                      GtkWindow *window);
426 static void        gtk_window_on_theme_variant_changed (GtkSettings *settings,
427                                                         GParamSpec  *pspec,
428                                                         GtkWindow   *window);
429 static void        gtk_window_set_theme_variant         (GtkWindow  *window);
430
431 static GSList      *toplevel_list = NULL;
432 static guint        window_signals[LAST_SIGNAL] = { 0 };
433 static GList       *default_icon_list = NULL;
434 static gchar       *default_icon_name = NULL;
435 static guint        default_icon_serial = 0;
436 static gboolean     disable_startup_notification = FALSE;
437 static gboolean     sent_startup_notification = FALSE;
438
439 static GQuark       quark_gtk_embedded = 0;
440 static GQuark       quark_gtk_window_key_hash = 0;
441 static GQuark       quark_gtk_window_icon_info = 0;
442 static GQuark       quark_gtk_buildable_accels = 0;
443
444 static GtkBuildableIface *parent_buildable_iface;
445
446 static void gtk_window_set_property (GObject         *object,
447                                      guint            prop_id,
448                                      const GValue    *value,
449                                      GParamSpec      *pspec);
450 static void gtk_window_get_property (GObject         *object,
451                                      guint            prop_id,
452                                      GValue          *value,
453                                      GParamSpec      *pspec);
454
455 /* GtkBuildable */
456 static void gtk_window_buildable_interface_init  (GtkBuildableIface *iface);
457 static void gtk_window_buildable_set_buildable_property (GtkBuildable        *buildable,
458                                                          GtkBuilder          *builder,
459                                                          const gchar         *name,
460                                                          const GValue        *value);
461 static void gtk_window_buildable_parser_finished (GtkBuildable     *buildable,
462                                                   GtkBuilder       *builder);
463 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable  *buildable,
464                                                        GtkBuilder    *builder,
465                                                        GObject       *child,
466                                                        const gchar   *tagname,
467                                                        GMarkupParser *parser,
468                                                        gpointer      *data);
469 static void gtk_window_buildable_custom_finished (GtkBuildable  *buildable,
470                                                       GtkBuilder    *builder,
471                                                       GObject       *child,
472                                                       const gchar   *tagname,
473                                                       gpointer       user_data);
474
475
476 static void gtk_window_get_preferred_width    (GtkWidget           *widget,
477                                                gint                *minimum_size,
478                                                gint                *natural_size);
479 static void gtk_window_get_preferred_height   (GtkWidget           *widget,
480                                                gint                *minimum_size,
481                                                gint                *natural_size);
482
483 static void ensure_state_flag_backdrop (GtkWidget *widget);
484
485 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
486                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
487                                                 gtk_window_buildable_interface_init))
488
489 static void
490 add_tab_bindings (GtkBindingSet    *binding_set,
491                   GdkModifierType   modifiers,
492                   GtkDirectionType  direction)
493 {
494   gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
495                                 "move-focus", 1,
496                                 GTK_TYPE_DIRECTION_TYPE, direction);
497   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
498                                 "move-focus", 1,
499                                 GTK_TYPE_DIRECTION_TYPE, direction);
500 }
501
502 static void
503 add_arrow_bindings (GtkBindingSet    *binding_set,
504                     guint             keysym,
505                     GtkDirectionType  direction)
506 {
507   guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
508   
509   gtk_binding_entry_add_signal (binding_set, keysym, 0,
510                                 "move-focus", 1,
511                                 GTK_TYPE_DIRECTION_TYPE, direction);
512   gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
513                                 "move-focus", 1,
514                                 GTK_TYPE_DIRECTION_TYPE, direction);
515   gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
516                                 "move-focus", 1,
517                                 GTK_TYPE_DIRECTION_TYPE, direction);
518   gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
519                                 "move-focus", 1,
520                                 GTK_TYPE_DIRECTION_TYPE, direction);
521 }
522
523 static guint32
524 extract_time_from_startup_id (const gchar* startup_id)
525 {
526   gchar *timestr = g_strrstr (startup_id, "_TIME");
527   guint32 retval = GDK_CURRENT_TIME;
528
529   if (timestr)
530     {
531       gchar *end;
532       guint32 timestamp; 
533     
534       /* Skip past the "_TIME" part */
535       timestr += 5;
536
537       end = NULL;
538       errno = 0;
539       timestamp = g_ascii_strtoull (timestr, &end, 0);
540       if (errno == 0 && end != timestr)
541         retval = timestamp;
542     }
543
544   return retval;
545 }
546
547 static gboolean
548 startup_id_is_fake (const gchar* startup_id)
549 {
550   return strncmp (startup_id, "_TIME", 5) == 0;
551 }
552
553 static void
554 gtk_window_class_init (GtkWindowClass *klass)
555 {
556   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
557   GtkWidgetClass *widget_class;
558   GtkContainerClass *container_class;
559   GtkBindingSet *binding_set;
560
561   widget_class = (GtkWidgetClass*) klass;
562   container_class = (GtkContainerClass*) klass;
563   
564   quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
565   quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
566   quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
567   quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
568
569   gobject_class->dispose = gtk_window_dispose;
570   gobject_class->finalize = gtk_window_finalize;
571
572   gobject_class->set_property = gtk_window_set_property;
573   gobject_class->get_property = gtk_window_get_property;
574
575   widget_class->destroy = gtk_window_destroy;
576   widget_class->show = gtk_window_show;
577   widget_class->hide = gtk_window_hide;
578   widget_class->map = gtk_window_map;
579   widget_class->map_event = gtk_window_map_event;
580   widget_class->unmap = gtk_window_unmap;
581   widget_class->realize = gtk_window_realize;
582   widget_class->unrealize = gtk_window_unrealize;
583   widget_class->size_allocate = gtk_window_size_allocate;
584   widget_class->configure_event = gtk_window_configure_event;
585   widget_class->key_press_event = gtk_window_key_press_event;
586   widget_class->key_release_event = gtk_window_key_release_event;
587   widget_class->enter_notify_event = gtk_window_enter_notify_event;
588   widget_class->leave_notify_event = gtk_window_leave_notify_event;
589   widget_class->focus_in_event = gtk_window_focus_in_event;
590   widget_class->button_press_event = gtk_window_button_press_event;
591   widget_class->focus_out_event = gtk_window_focus_out_event;
592   widget_class->focus = gtk_window_focus;
593   widget_class->move_focus = gtk_window_move_focus;
594   widget_class->draw = gtk_window_draw;
595   widget_class->get_preferred_width = gtk_window_get_preferred_width;
596   widget_class->get_preferred_height = gtk_window_get_preferred_height;
597   widget_class->window_state_event = gtk_window_state_event;
598   widget_class->direction_changed = gtk_window_direction_changed;
599   widget_class->state_changed = gtk_window_state_changed;
600   widget_class->style_updated = gtk_window_style_updated;
601
602   container_class->check_resize = gtk_window_check_resize;
603
604   klass->set_focus = gtk_window_real_set_focus;
605
606   klass->activate_default = gtk_window_real_activate_default;
607   klass->activate_focus = gtk_window_real_activate_focus;
608   klass->keys_changed = gtk_window_keys_changed;
609
610   g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
611
612   /* Construct */
613   g_object_class_install_property (gobject_class,
614                                    PROP_TYPE,
615                                    g_param_spec_enum ("type",
616                                                       P_("Window Type"),
617                                                       P_("The type of the window"),
618                                                       GTK_TYPE_WINDOW_TYPE,
619                                                       GTK_WINDOW_TOPLEVEL,
620                                                       GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
621   /* Regular Props */
622   g_object_class_install_property (gobject_class,
623                                    PROP_TITLE,
624                                    g_param_spec_string ("title",
625                                                         P_("Window Title"),
626                                                         P_("The title of the window"),
627                                                         NULL,
628                                                         GTK_PARAM_READWRITE));
629
630   g_object_class_install_property (gobject_class,
631                                    PROP_ROLE,
632                                    g_param_spec_string ("role",
633                                                         P_("Window Role"),
634                                                         P_("Unique identifier for the window to be used when restoring a session"),
635                                                         NULL,
636                                                         GTK_PARAM_READWRITE));
637
638   /**
639    * GtkWindow:startup-id:
640    *
641    * The :startup-id is a write-only property for setting window's
642    * startup notification identifier. See gtk_window_set_startup_id()
643    * for more details.
644    *
645    * Since: 2.12
646    */
647   g_object_class_install_property (gobject_class,
648                                    PROP_STARTUP_ID,
649                                    g_param_spec_string ("startup-id",
650                                                         P_("Startup ID"),
651                                                         P_("Unique startup identifier for the window used by startup-notification"),
652                                                         NULL,
653                                                         GTK_PARAM_WRITABLE));
654
655   g_object_class_install_property (gobject_class,
656                                    PROP_RESIZABLE,
657                                    g_param_spec_boolean ("resizable",
658                                                          P_("Resizable"),
659                                                          P_("If TRUE, users can resize the window"),
660                                                          TRUE,
661                                                          GTK_PARAM_READWRITE));
662   
663   g_object_class_install_property (gobject_class,
664                                    PROP_MODAL,
665                                    g_param_spec_boolean ("modal",
666                                                          P_("Modal"),
667                                                          P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
668                                                          FALSE,
669                                                          GTK_PARAM_READWRITE));
670
671   g_object_class_install_property (gobject_class,
672                                    PROP_WIN_POS,
673                                    g_param_spec_enum ("window-position",
674                                                       P_("Window Position"),
675                                                       P_("The initial position of the window"),
676                                                       GTK_TYPE_WINDOW_POSITION,
677                                                       GTK_WIN_POS_NONE,
678                                                       GTK_PARAM_READWRITE));
679  
680   g_object_class_install_property (gobject_class,
681                                    PROP_DEFAULT_WIDTH,
682                                    g_param_spec_int ("default-width",
683                                                      P_("Default Width"),
684                                                      P_("The default width of the window, used when initially showing the window"),
685                                                      -1,
686                                                      G_MAXINT,
687                                                      -1,
688                                                      GTK_PARAM_READWRITE));
689   
690   g_object_class_install_property (gobject_class,
691                                    PROP_DEFAULT_HEIGHT,
692                                    g_param_spec_int ("default-height",
693                                                      P_("Default Height"),
694                                                      P_("The default height of the window, used when initially showing the window"),
695                                                      -1,
696                                                      G_MAXINT,
697                                                      -1,
698                                                      GTK_PARAM_READWRITE));
699   
700   g_object_class_install_property (gobject_class,
701                                    PROP_DESTROY_WITH_PARENT,
702                                    g_param_spec_boolean ("destroy-with-parent",
703                                                          P_("Destroy with Parent"),
704                                                          P_("If this window should be destroyed when the parent is destroyed"),
705                                                          FALSE,
706                                                          GTK_PARAM_READWRITE));
707
708   /**
709    * GtkWindow:hide-titlebar-when-maximized:
710    *
711    * Whether the titlebar should be hidden during maximization.
712    *
713    * Since: 3.4
714    */
715   g_object_class_install_property (gobject_class,
716                                    PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
717                                    g_param_spec_boolean ("hide-titlebar-when-maximized",
718                                                          P_("Hide the titlebar during maximization"),
719                                                          P_("If this window's titlebar should be hidden when the window is maximized"),
720                                                          FALSE,
721                                                          GTK_PARAM_READWRITE));
722
723   g_object_class_install_property (gobject_class,
724                                    PROP_ICON,
725                                    g_param_spec_object ("icon",
726                                                         P_("Icon"),
727                                                         P_("Icon for this window"),
728                                                         GDK_TYPE_PIXBUF,
729                                                         GTK_PARAM_READWRITE));
730
731   /**
732    * GtkWindow:mnemonics-visible:
733    *
734    * Whether mnemonics are currently visible in this window.
735    *
736    * This property is maintained by GTK+ based on the
737    * #GtkSettings:gtk-auto-mnemonics setting and user input,
738    * and should not be set by applications.
739    *
740    * Since: 2.20
741    */
742   g_object_class_install_property (gobject_class,
743                                    PROP_MNEMONICS_VISIBLE,
744                                    g_param_spec_boolean ("mnemonics-visible",
745                                                          P_("Mnemonics Visible"),
746                                                          P_("Whether mnemonics are currently visible in this window"),
747                                                          TRUE,
748                                                          GTK_PARAM_READWRITE));
749
750   /**
751    * GtkWindow:focus-visible:
752    *
753    * Whether 'focus rectangles' are currently visible in this window.
754    *
755    * This property is maintained by GTK+ based on the
756    * #GtkSettings:gtk-visible-focus setting and user input
757    * and should not be set by applications.
758    *
759    * Since: 2.20
760    */
761   g_object_class_install_property (gobject_class,
762                                    PROP_FOCUS_VISIBLE,
763                                    g_param_spec_boolean ("focus-visible",
764                                                          P_("Focus Visible"),
765                                                          P_("Whether focus rectangles are currently visible in this window"),
766                                                          TRUE,
767                                                          GTK_PARAM_READWRITE));
768   
769   /**
770    * GtkWindow:icon-name:
771    *
772    * The :icon-name property specifies the name of the themed icon to
773    * use as the window icon. See #GtkIconTheme for more details.
774    *
775    * Since: 2.6
776    */
777   g_object_class_install_property (gobject_class,
778                                    PROP_ICON_NAME,
779                                    g_param_spec_string ("icon-name",
780                                                         P_("Icon Name"),
781                                                         P_("Name of the themed icon for this window"),
782                                                         NULL,
783                                                         GTK_PARAM_READWRITE));
784   
785   g_object_class_install_property (gobject_class,
786                                    PROP_SCREEN,
787                                    g_param_spec_object ("screen",
788                                                         P_("Screen"),
789                                                         P_("The screen where this window will be displayed"),
790                                                         GDK_TYPE_SCREEN,
791                                                         GTK_PARAM_READWRITE));
792
793   g_object_class_install_property (gobject_class,
794                                    PROP_IS_ACTIVE,
795                                    g_param_spec_boolean ("is-active",
796                                                          P_("Is Active"),
797                                                          P_("Whether the toplevel is the current active window"),
798                                                          FALSE,
799                                                          GTK_PARAM_READABLE));
800   
801   g_object_class_install_property (gobject_class,
802                                    PROP_HAS_TOPLEVEL_FOCUS,
803                                    g_param_spec_boolean ("has-toplevel-focus",
804                                                          P_("Focus in Toplevel"),
805                                                          P_("Whether the input focus is within this GtkWindow"),
806                                                          FALSE,
807                                                          GTK_PARAM_READABLE));
808
809   g_object_class_install_property (gobject_class,
810                                    PROP_TYPE_HINT,
811                                    g_param_spec_enum ("type-hint",
812                                                       P_("Type hint"),
813                                                       P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
814                                                       GDK_TYPE_WINDOW_TYPE_HINT,
815                                                       GDK_WINDOW_TYPE_HINT_NORMAL,
816                                                       GTK_PARAM_READWRITE));
817
818   g_object_class_install_property (gobject_class,
819                                    PROP_SKIP_TASKBAR_HINT,
820                                    g_param_spec_boolean ("skip-taskbar-hint",
821                                                          P_("Skip taskbar"),
822                                                          P_("TRUE if the window should not be in the task bar."),
823                                                          FALSE,
824                                                          GTK_PARAM_READWRITE));
825
826   g_object_class_install_property (gobject_class,
827                                    PROP_SKIP_PAGER_HINT,
828                                    g_param_spec_boolean ("skip-pager-hint",
829                                                          P_("Skip pager"),
830                                                          P_("TRUE if the window should not be in the pager."),
831                                                          FALSE,
832                                                          GTK_PARAM_READWRITE));  
833
834   g_object_class_install_property (gobject_class,
835                                    PROP_URGENCY_HINT,
836                                    g_param_spec_boolean ("urgency-hint",
837                                                          P_("Urgent"),
838                                                          P_("TRUE if the window should be brought to the user's attention."),
839                                                          FALSE,
840                                                          GTK_PARAM_READWRITE));  
841
842   /**
843    * GtkWindow:accept-focus:
844    *
845    * Whether the window should receive the input focus.
846    *
847    * Since: 2.4
848    */
849   g_object_class_install_property (gobject_class,
850                                    PROP_ACCEPT_FOCUS,
851                                    g_param_spec_boolean ("accept-focus",
852                                                          P_("Accept focus"),
853                                                          P_("TRUE if the window should receive the input focus."),
854                                                          TRUE,
855                                                          GTK_PARAM_READWRITE));  
856
857   /**
858    * GtkWindow:focus-on-map:
859    *
860    * Whether the window should receive the input focus when mapped.
861    *
862    * Since: 2.6
863    */
864   g_object_class_install_property (gobject_class,
865                                    PROP_FOCUS_ON_MAP,
866                                    g_param_spec_boolean ("focus-on-map",
867                                                          P_("Focus on map"),
868                                                          P_("TRUE if the window should receive the input focus when mapped."),
869                                                          TRUE,
870                                                          GTK_PARAM_READWRITE));  
871
872   /**
873    * GtkWindow:decorated:
874    *
875    * Whether the window should be decorated by the window manager.
876    *
877    * Since: 2.4
878    */
879   g_object_class_install_property (gobject_class,
880                                    PROP_DECORATED,
881                                    g_param_spec_boolean ("decorated",
882                                                          P_("Decorated"),
883                                                          P_("Whether the window should be decorated by the window manager"),
884                                                          TRUE,
885                                                          GTK_PARAM_READWRITE));
886
887   /**
888    * GtkWindow:deletable:
889    *
890    * Whether the window frame should have a close button.
891    *
892    * Since: 2.10
893    */
894   g_object_class_install_property (gobject_class,
895                                    PROP_DELETABLE,
896                                    g_param_spec_boolean ("deletable",
897                                                          P_("Deletable"),
898                                                          P_("Whether the window frame should have a close button"),
899                                                          TRUE,
900                                                          GTK_PARAM_READWRITE));
901
902   /**
903    * GtkWindow:has-resize-grip
904    *
905    * Whether the window has a corner resize grip.
906    *
907    * Note that the resize grip is only shown if the window is
908    * actually resizable and not maximized. Use
909    * #GtkWindow:resize-grip-visible to find out if the resize
910    * grip is currently shown.
911    *
912    * Since: 3.0
913    */
914   g_object_class_install_property (gobject_class,
915                                    PROP_HAS_RESIZE_GRIP,
916                                    g_param_spec_boolean ("has-resize-grip",
917                                                          P_("Resize grip"),
918                                                          P_("Specifies whether the window should have a resize grip"),
919                                                          TRUE,
920                                                          GTK_PARAM_READWRITE));
921
922   /**
923    * GtkWindow:resize-grip-visible:
924    *
925    * Whether a corner resize grip is currently shown.
926    *
927    * Since: 3.0
928    */
929   g_object_class_install_property (gobject_class,
930                                    PROP_RESIZE_GRIP_VISIBLE,
931                                    g_param_spec_boolean ("resize-grip-visible",
932                                                          P_("Resize grip is visible"),
933                                                          P_("Specifies whether the window's resize grip is visible."),
934                                                          FALSE,
935                                                          GTK_PARAM_READABLE));
936
937
938   /**
939    * GtkWindow:gravity:
940    *
941    * The window gravity of the window. See gtk_window_move() and #GdkGravity for
942    * more details about window gravity.
943    *
944    * Since: 2.4
945    */
946   g_object_class_install_property (gobject_class,
947                                    PROP_GRAVITY,
948                                    g_param_spec_enum ("gravity",
949                                                       P_("Gravity"),
950                                                       P_("The window gravity of the window"),
951                                                       GDK_TYPE_GRAVITY,
952                                                       GDK_GRAVITY_NORTH_WEST,
953                                                       GTK_PARAM_READWRITE));
954
955
956   /**
957    * GtkWindow:transient-for:
958    *
959    * The transient parent of the window. See gtk_window_set_transient_for() for
960    * more details about transient windows.
961    *
962    * Since: 2.10
963    */
964   g_object_class_install_property (gobject_class,
965                                    PROP_TRANSIENT_FOR,
966                                    g_param_spec_object ("transient-for",
967                                                         P_("Transient for Window"),
968                                                         P_("The transient parent of the dialog"),
969                                                         GTK_TYPE_WINDOW,
970                                                         GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
971
972   /**
973    * GtkWindow:attached-to:
974    *
975    * The widget to which this window is attached.
976    * See gtk_window_set_attached_to().
977    *
978    * Examples of places where specifying this relation is useful are
979    * for instance a #GtkMenu created by a #GtkComboBox, a completion
980    * popup window created by #GtkEntry or a typeahead search entry
981    * created by #GtkTreeView.
982    *
983    * Since: 3.4
984    */
985   g_object_class_install_property (gobject_class,
986                                    PROP_ATTACHED_TO,
987                                    g_param_spec_object ("attached-to",
988                                                         P_("Attached to Widget"),
989                                                         P_("The widget where the window is attached"),
990                                                         GTK_TYPE_WIDGET,
991                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
992
993   /**
994    * GtkWindow:opacity:
995    *
996    * The requested opacity of the window. See gtk_window_set_opacity() for
997    * more details about window opacity.
998    *
999    * Since: 2.12
1000    */
1001   g_object_class_install_property (gobject_class,
1002                                    PROP_OPACITY,
1003                                    g_param_spec_double ("opacity",
1004                                                         P_("Opacity for Window"),
1005                                                         P_("The opacity of the window, from 0 to 1"),
1006                                                         0.0,
1007                                                         1.0,
1008                                                         1.0,
1009                                                         GTK_PARAM_READWRITE));
1010
1011   /* Style properties.
1012    */
1013   gtk_widget_class_install_style_property (widget_class,
1014                                            g_param_spec_int ("resize-grip-width",
1015                                                              P_("Width of resize grip"),
1016                                                              P_("Width of resize grip"),
1017                                                              0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1018
1019   gtk_widget_class_install_style_property (widget_class,
1020                                            g_param_spec_int ("resize-grip-height",
1021                                                              P_("Height of resize grip"),
1022                                                              P_("Height of resize grip"),
1023                                                              0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1024
1025
1026   /**
1027    * GtkWindow:application:
1028    *
1029    * The #GtkApplication associated with the window.
1030    *
1031    * The application will be kept alive for at least as long as it
1032    * has any windows associated with it (see g_application_hold()
1033    * for a way to keep it alive without windows).
1034    *
1035    * Normally, the connection between the application and the window
1036    * will remain until the window is destroyed, but you can explicitly
1037    * remove it by setting the ::application property to %NULL.
1038    *
1039    * Since: 3.0
1040    */
1041   g_object_class_install_property (gobject_class,
1042                                    PROP_APPLICATION,
1043                                    g_param_spec_object ("application",
1044                                                         P_("GtkApplication"),
1045                                                         P_("The GtkApplication for the window"),
1046                                                         GTK_TYPE_APPLICATION,
1047                                                         GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1048
1049   window_signals[SET_FOCUS] =
1050     g_signal_new (I_("set-focus"),
1051                   G_TYPE_FROM_CLASS (gobject_class),
1052                   G_SIGNAL_RUN_LAST,
1053                   G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1054                   NULL, NULL,
1055                   _gtk_marshal_VOID__OBJECT,
1056                   G_TYPE_NONE, 1,
1057                   GTK_TYPE_WIDGET);
1058
1059   /**
1060    * GtkWindow::activate-focus:
1061    * @window: the window which received the signal
1062    *
1063    * The ::activate-focus signal is a
1064    * <link linkend="keybinding-signals">keybinding signal</link>
1065    * which gets emitted when the user activates the currently
1066    * focused widget of @window.
1067    */
1068   window_signals[ACTIVATE_FOCUS] =
1069     g_signal_new (I_("activate-focus"),
1070                   G_TYPE_FROM_CLASS (gobject_class),
1071                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1072                   G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1073                   NULL, NULL,
1074                   _gtk_marshal_VOID__VOID,
1075                   G_TYPE_NONE,
1076                   0);
1077
1078   /**
1079    * GtkWindow::activate-default:
1080    * @window: the window which received the signal
1081    *
1082    * The ::activate-default signal is a
1083    * <link linkend="keybinding-signals">keybinding signal</link>
1084    * which gets emitted when the user activates the default widget
1085    * of @window.
1086    */
1087   window_signals[ACTIVATE_DEFAULT] =
1088     g_signal_new (I_("activate-default"),
1089                   G_TYPE_FROM_CLASS (gobject_class),
1090                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1091                   G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1092                   NULL, NULL,
1093                   _gtk_marshal_VOID__VOID,
1094                   G_TYPE_NONE,
1095                   0);
1096
1097   /**
1098    * GtkWindow::keys-changed:
1099    * @window: the window which received the signal
1100    *
1101    * The ::keys-changed signal gets emitted when the set of accelerators
1102    * or mnemonics that are associated with @window changes.
1103    */
1104   window_signals[KEYS_CHANGED] =
1105     g_signal_new (I_("keys-changed"),
1106                   G_TYPE_FROM_CLASS (gobject_class),
1107                   G_SIGNAL_RUN_FIRST,
1108                   G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1109                   NULL, NULL,
1110                   _gtk_marshal_VOID__VOID,
1111                   G_TYPE_NONE,
1112                   0);
1113
1114   /*
1115    * Key bindings
1116    */
1117
1118   binding_set = gtk_binding_set_by_class (klass);
1119
1120   gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1121                                 "activate-focus", 0);
1122   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1123                                 "activate-focus", 0);
1124   
1125   gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1126                                 "activate-default", 0);
1127   gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1128                                 "activate-default", 0);
1129   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1130                                 "activate-default", 0);
1131
1132   add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1133   add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1134   add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1135   add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1136
1137   add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1138   add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1139   add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1140   add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1141
1142   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1143 }
1144
1145 static void
1146 gtk_window_init (GtkWindow *window)
1147 {
1148   GtkWindowPrivate *priv;
1149
1150   window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1151                                               GTK_TYPE_WINDOW,
1152                                               GtkWindowPrivate);
1153   priv = window->priv;
1154   
1155   gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1156   _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1157
1158   _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1159
1160   gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1161
1162   priv->title = NULL;
1163   priv->wmclass_name = g_strdup (g_get_prgname ());
1164   priv->wmclass_class = g_strdup (gdk_get_program_class ());
1165   priv->wm_role = NULL;
1166   priv->geometry_info = NULL;
1167   priv->type = GTK_WINDOW_TOPLEVEL;
1168   priv->focus_widget = NULL;
1169   priv->default_widget = NULL;
1170   priv->configure_request_count = 0;
1171   priv->resizable = TRUE;
1172   priv->configure_notify_received = FALSE;
1173   priv->position = GTK_WIN_POS_NONE;
1174   priv->need_default_size = TRUE;
1175   priv->need_default_position = TRUE;
1176   priv->modal = FALSE;
1177   priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1178   priv->gravity = GDK_GRAVITY_NORTH_WEST;
1179   priv->decorated = TRUE;
1180   priv->mnemonic_modifier = GDK_MOD1_MASK;
1181   priv->screen = gdk_screen_get_default ();
1182
1183   priv->accept_focus = TRUE;
1184   priv->focus_on_map = TRUE;
1185   priv->deletable = TRUE;
1186   priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1187   priv->opacity = 1.0;
1188   priv->startup_id = NULL;
1189   priv->initial_timestamp = GDK_CURRENT_TIME;
1190   priv->has_resize_grip = TRUE;
1191   priv->mnemonics_visible = TRUE;
1192   priv->focus_visible = TRUE;
1193
1194   g_object_ref_sink (window);
1195   priv->has_user_ref_count = TRUE;
1196   toplevel_list = g_slist_prepend (toplevel_list, window);
1197
1198   if (priv->screen)
1199     g_signal_connect (priv->screen, "composited-changed",
1200                       G_CALLBACK (gtk_window_on_composited_changed), window);
1201
1202 #ifdef GDK_WINDOWING_X11
1203   g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1204                     "notify::gtk-application-prefer-dark-theme",
1205                     G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1206 #endif
1207 }
1208
1209 static void
1210 gtk_window_set_property (GObject      *object,
1211                          guint         prop_id,
1212                          const GValue *value,
1213                          GParamSpec   *pspec)
1214 {
1215   GtkWindow  *window = GTK_WINDOW (object);
1216   GtkWindowPrivate *priv = window->priv;
1217
1218   switch (prop_id)
1219     {
1220     case PROP_TYPE:
1221       priv->type = g_value_get_enum (value);
1222       break;
1223     case PROP_TITLE:
1224       gtk_window_set_title (window, g_value_get_string (value));
1225       break;
1226     case PROP_ROLE:
1227       gtk_window_set_role (window, g_value_get_string (value));
1228       break;
1229     case PROP_STARTUP_ID:
1230       gtk_window_set_startup_id (window, g_value_get_string (value));
1231       break;
1232     case PROP_RESIZABLE:
1233       gtk_window_set_resizable (window, g_value_get_boolean (value));
1234       break;
1235     case PROP_MODAL:
1236       gtk_window_set_modal (window, g_value_get_boolean (value));
1237       break;
1238     case PROP_WIN_POS:
1239       gtk_window_set_position (window, g_value_get_enum (value));
1240       break;
1241     case PROP_DEFAULT_WIDTH:
1242       gtk_window_set_default_size_internal (window,
1243                                             TRUE, g_value_get_int (value),
1244                                             FALSE, -1, FALSE);
1245       break;
1246     case PROP_DEFAULT_HEIGHT:
1247       gtk_window_set_default_size_internal (window,
1248                                             FALSE, -1,
1249                                             TRUE, g_value_get_int (value), FALSE);
1250       break;
1251     case PROP_DESTROY_WITH_PARENT:
1252       gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1253       break;
1254     case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1255       gtk_window_set_hide_titlebar_when_maximized (window, g_value_get_boolean (value));
1256       break;
1257     case PROP_ICON:
1258       gtk_window_set_icon (window,
1259                            g_value_get_object (value));
1260       break;
1261     case PROP_ICON_NAME:
1262       gtk_window_set_icon_name (window, g_value_get_string (value));
1263       break;
1264     case PROP_SCREEN:
1265       gtk_window_set_screen (window, g_value_get_object (value));
1266       break;
1267     case PROP_TYPE_HINT:
1268       gtk_window_set_type_hint (window,
1269                                 g_value_get_enum (value));
1270       break;
1271     case PROP_SKIP_TASKBAR_HINT:
1272       gtk_window_set_skip_taskbar_hint (window,
1273                                         g_value_get_boolean (value));
1274       break;
1275     case PROP_SKIP_PAGER_HINT:
1276       gtk_window_set_skip_pager_hint (window,
1277                                       g_value_get_boolean (value));
1278       break;
1279     case PROP_URGENCY_HINT:
1280       gtk_window_set_urgency_hint (window,
1281                                    g_value_get_boolean (value));
1282       break;
1283     case PROP_ACCEPT_FOCUS:
1284       gtk_window_set_accept_focus (window,
1285                                    g_value_get_boolean (value));
1286       break;
1287     case PROP_FOCUS_ON_MAP:
1288       gtk_window_set_focus_on_map (window,
1289                                    g_value_get_boolean (value));
1290       break;
1291     case PROP_DECORATED:
1292       gtk_window_set_decorated (window, g_value_get_boolean (value));
1293       break;
1294     case PROP_DELETABLE:
1295       gtk_window_set_deletable (window, g_value_get_boolean (value));
1296       break;
1297     case PROP_GRAVITY:
1298       gtk_window_set_gravity (window, g_value_get_enum (value));
1299       break;
1300     case PROP_TRANSIENT_FOR:
1301       gtk_window_set_transient_for (window, g_value_get_object (value));
1302       break;
1303     case PROP_ATTACHED_TO:
1304       gtk_window_set_attached_to (window, g_value_get_object (value));
1305       break;
1306     case PROP_OPACITY:
1307       gtk_window_set_opacity (window, g_value_get_double (value));
1308       break;
1309     case PROP_HAS_RESIZE_GRIP:
1310       gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1311       break;
1312     case PROP_APPLICATION:
1313       gtk_window_set_application (window, g_value_get_object (value));
1314       break;
1315     case PROP_MNEMONICS_VISIBLE:
1316       gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1317       break;
1318     case PROP_FOCUS_VISIBLE:
1319       gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1320       break;
1321     default:
1322       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1323       break;
1324     }
1325 }
1326
1327 static void
1328 gtk_window_get_property (GObject      *object,
1329                          guint         prop_id,
1330                          GValue       *value,
1331                          GParamSpec   *pspec)
1332 {
1333   GtkWindow  *window = GTK_WINDOW (object);
1334   GtkWindowPrivate *priv = window->priv;
1335
1336   switch (prop_id)
1337     {
1338       GtkWindowGeometryInfo *info;
1339     case PROP_TYPE:
1340       g_value_set_enum (value, priv->type);
1341       break;
1342     case PROP_ROLE:
1343       g_value_set_string (value, priv->wm_role);
1344       break;
1345     case PROP_TITLE:
1346       g_value_set_string (value, priv->title);
1347       break;
1348     case PROP_RESIZABLE:
1349       g_value_set_boolean (value, priv->resizable);
1350       break;
1351     case PROP_MODAL:
1352       g_value_set_boolean (value, priv->modal);
1353       break;
1354     case PROP_WIN_POS:
1355       g_value_set_enum (value, priv->position);
1356       break;
1357     case PROP_DEFAULT_WIDTH:
1358       info = gtk_window_get_geometry_info (window, FALSE);
1359       if (!info)
1360         g_value_set_int (value, -1);
1361       else
1362         g_value_set_int (value, info->default_width);
1363       break;
1364     case PROP_DEFAULT_HEIGHT:
1365       info = gtk_window_get_geometry_info (window, FALSE);
1366       if (!info)
1367         g_value_set_int (value, -1);
1368       else
1369         g_value_set_int (value, info->default_height);
1370       break;
1371     case PROP_DESTROY_WITH_PARENT:
1372       g_value_set_boolean (value, priv->destroy_with_parent);
1373       break;
1374     case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1375       g_value_set_boolean (value, priv->hide_titlebar_when_maximized);
1376       break;
1377     case PROP_ICON:
1378       g_value_set_object (value, gtk_window_get_icon (window));
1379       break;
1380     case PROP_ICON_NAME:
1381       g_value_set_string (value, gtk_window_get_icon_name (window));
1382       break;
1383     case PROP_SCREEN:
1384       g_value_set_object (value, priv->screen);
1385       break;
1386     case PROP_IS_ACTIVE:
1387       g_value_set_boolean (value, priv->is_active);
1388       break;
1389     case PROP_HAS_TOPLEVEL_FOCUS:
1390       g_value_set_boolean (value, priv->has_toplevel_focus);
1391       break;
1392     case PROP_TYPE_HINT:
1393       g_value_set_enum (value, priv->type_hint);
1394       break;
1395     case PROP_SKIP_TASKBAR_HINT:
1396       g_value_set_boolean (value,
1397                            gtk_window_get_skip_taskbar_hint (window));
1398       break;
1399     case PROP_SKIP_PAGER_HINT:
1400       g_value_set_boolean (value,
1401                            gtk_window_get_skip_pager_hint (window));
1402       break;
1403     case PROP_URGENCY_HINT:
1404       g_value_set_boolean (value,
1405                            gtk_window_get_urgency_hint (window));
1406       break;
1407     case PROP_ACCEPT_FOCUS:
1408       g_value_set_boolean (value,
1409                            gtk_window_get_accept_focus (window));
1410       break;
1411     case PROP_FOCUS_ON_MAP:
1412       g_value_set_boolean (value,
1413                            gtk_window_get_focus_on_map (window));
1414       break;
1415     case PROP_DECORATED:
1416       g_value_set_boolean (value, gtk_window_get_decorated (window));
1417       break;
1418     case PROP_DELETABLE:
1419       g_value_set_boolean (value, gtk_window_get_deletable (window));
1420       break;
1421     case PROP_GRAVITY:
1422       g_value_set_enum (value, gtk_window_get_gravity (window));
1423       break;
1424     case PROP_TRANSIENT_FOR:
1425       g_value_set_object (value, gtk_window_get_transient_for (window));
1426       break;
1427     case PROP_ATTACHED_TO:
1428       g_value_set_object (value, gtk_window_get_attached_to (window));
1429       break;
1430     case PROP_OPACITY:
1431       g_value_set_double (value, gtk_window_get_opacity (window));
1432       break;
1433     case PROP_HAS_RESIZE_GRIP:
1434       g_value_set_boolean (value, priv->has_resize_grip);
1435       break;
1436     case PROP_RESIZE_GRIP_VISIBLE:
1437       g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1438       break;
1439     case PROP_APPLICATION:
1440       g_value_set_object (value, gtk_window_get_application (window));
1441       break;
1442     case PROP_MNEMONICS_VISIBLE:
1443       g_value_set_boolean (value, priv->mnemonics_visible);
1444       break;
1445     case PROP_FOCUS_VISIBLE:
1446       g_value_set_boolean (value, priv->focus_visible);
1447       break;
1448     default:
1449       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1450       break;
1451     }
1452 }
1453
1454 static void
1455 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1456 {
1457   parent_buildable_iface = g_type_interface_peek_parent (iface);
1458   iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1459   iface->parser_finished = gtk_window_buildable_parser_finished;
1460   iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1461   iface->custom_finished = gtk_window_buildable_custom_finished;
1462 }
1463
1464 static void
1465 gtk_window_buildable_set_buildable_property (GtkBuildable        *buildable,
1466                                              GtkBuilder          *builder,
1467                                              const gchar         *name,
1468                                              const GValue        *value)
1469 {
1470   GtkWindow *window = GTK_WINDOW (buildable);
1471   GtkWindowPrivate *priv = window->priv;
1472
1473   if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1474     priv->builder_visible = TRUE;
1475   else
1476     parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1477 }
1478
1479 static void
1480 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1481                                       GtkBuilder   *builder)
1482 {
1483   GtkWindow *window = GTK_WINDOW (buildable);
1484   GtkWindowPrivate *priv = window->priv;
1485   GObject *object;
1486   GSList *accels, *l;
1487
1488   if (priv->builder_visible)
1489     gtk_widget_show (GTK_WIDGET (buildable));
1490
1491   accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1492   for (l = accels; l; l = l->next)
1493     {
1494       object = gtk_builder_get_object (builder, l->data);
1495       if (!object)
1496         {
1497           g_warning ("Unknown accel group %s specified in window %s",
1498                      (const gchar*)l->data, gtk_buildable_get_name (buildable));
1499           continue;
1500         }
1501       gtk_window_add_accel_group (GTK_WINDOW (buildable),
1502                                   GTK_ACCEL_GROUP (object));
1503       g_free (l->data);
1504     }
1505
1506   g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1507
1508   parent_buildable_iface->parser_finished (buildable, builder);
1509 }
1510
1511 typedef struct {
1512   GObject *object;
1513   GSList *items;
1514 } GSListSubParserData;
1515
1516 static void
1517 window_start_element (GMarkupParseContext *context,
1518                           const gchar         *element_name,
1519                           const gchar        **names,
1520                           const gchar        **values,
1521                           gpointer            user_data,
1522                           GError            **error)
1523 {
1524   guint i;
1525   GSListSubParserData *data = (GSListSubParserData*)user_data;
1526
1527   if (strcmp (element_name, "group") == 0)
1528     {
1529       for (i = 0; names[i]; i++)
1530         {
1531           if (strcmp (names[i], "name") == 0)
1532             data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1533         }
1534     }
1535   else if (strcmp (element_name, "accel-groups") == 0)
1536     return;
1537   else
1538     g_warning ("Unsupported tag type for GtkWindow: %s\n",
1539                element_name);
1540
1541 }
1542
1543 static const GMarkupParser window_parser =
1544   {
1545     window_start_element
1546   };
1547
1548 static gboolean
1549 gtk_window_buildable_custom_tag_start (GtkBuildable  *buildable,
1550                                        GtkBuilder    *builder,
1551                                        GObject       *child,
1552                                        const gchar   *tagname,
1553                                        GMarkupParser *parser,
1554                                        gpointer      *data)
1555 {
1556   GSListSubParserData *parser_data;
1557
1558   if (parent_buildable_iface->custom_tag_start (buildable, builder, child, 
1559                                                 tagname, parser, data))
1560     return TRUE;
1561
1562   if (strcmp (tagname, "accel-groups") == 0)
1563     {
1564       parser_data = g_slice_new0 (GSListSubParserData);
1565       parser_data->items = NULL;
1566       parser_data->object = G_OBJECT (buildable);
1567
1568       *parser = window_parser;
1569       *data = parser_data;
1570       return TRUE;
1571     }
1572
1573   return FALSE;
1574 }
1575
1576 static void
1577 gtk_window_buildable_custom_finished (GtkBuildable  *buildable,
1578                                           GtkBuilder    *builder,
1579                                           GObject       *child,
1580                                           const gchar   *tagname,
1581                                           gpointer       user_data)
1582 {
1583   GSListSubParserData *data;
1584
1585   parent_buildable_iface->custom_finished (buildable, builder, child, 
1586                                            tagname, user_data);
1587
1588   if (strcmp (tagname, "accel-groups") != 0)
1589     return;
1590   
1591   data = (GSListSubParserData*)user_data;
1592
1593   g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels, 
1594                            data->items, (GDestroyNotify) g_slist_free);
1595
1596   g_slice_free (GSListSubParserData, data);
1597 }
1598
1599 /**
1600  * gtk_window_new:
1601  * @type: type of window
1602  * 
1603  * Creates a new #GtkWindow, which is a toplevel window that can
1604  * contain other widgets. Nearly always, the type of the window should
1605  * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1606  * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1607  * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1608  * dialogs, though in some other toolkits dialogs are called "popups".
1609  * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1610  * On X11, popup windows are not controlled by the <link
1611  * linkend="gtk-X11-arch">window manager</link>.
1612  *
1613  * If you simply want an undecorated window (no window borders), use
1614  * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1615  * 
1616  * Return value: a new #GtkWindow.
1617  **/
1618 GtkWidget*
1619 gtk_window_new (GtkWindowType type)
1620 {
1621   GtkWindowPrivate *priv;
1622   GtkWindow *window;
1623
1624   g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1625
1626   window = g_object_new (GTK_TYPE_WINDOW, NULL);
1627   priv = window->priv;
1628
1629   priv->type = type;
1630
1631   return GTK_WIDGET (window);
1632 }
1633
1634 /**
1635  * gtk_window_set_title:
1636  * @window: a #GtkWindow
1637  * @title: title of the window
1638  * 
1639  * Sets the title of the #GtkWindow. The title of a window will be
1640  * displayed in its title bar; on the X Window System, the title bar
1641  * is rendered by the <link linkend="gtk-X11-arch">window
1642  * manager</link>, so exactly how the title appears to users may vary
1643  * according to a user's exact configuration. The title should help a
1644  * user distinguish this window from other windows they may have
1645  * open. A good title might include the application name and current
1646  * document filename, for example.
1647  * 
1648  **/
1649 void
1650 gtk_window_set_title (GtkWindow   *window,
1651                       const gchar *title)
1652 {
1653   GtkWindowPrivate *priv;
1654   GtkWidget *widget;
1655   char *new_title;
1656   
1657   g_return_if_fail (GTK_IS_WINDOW (window));
1658
1659   priv = window->priv;
1660   widget = GTK_WIDGET (window);
1661
1662   new_title = g_strdup (title);
1663   g_free (priv->title);
1664   priv->title = new_title;
1665
1666   if (gtk_widget_get_realized (widget))
1667     {
1668       gdk_window_set_title (gtk_widget_get_window (widget),
1669                             priv->title);
1670     }
1671
1672   g_object_notify (G_OBJECT (window), "title");
1673 }
1674
1675 /**
1676  * gtk_window_get_title:
1677  * @window: a #GtkWindow
1678  *
1679  * Retrieves the title of the window. See gtk_window_set_title().
1680  *
1681  * Return value: the title of the window, or %NULL if none has
1682  *    been set explicitely. The returned string is owned by the widget
1683  *    and must not be modified or freed.
1684  **/
1685 const gchar *
1686 gtk_window_get_title (GtkWindow *window)
1687 {
1688   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1689
1690   return window->priv->title;
1691 }
1692
1693 /**
1694  * gtk_window_set_wmclass:
1695  * @window: a #GtkWindow
1696  * @wmclass_name: window name hint
1697  * @wmclass_class: window class hint
1698  *
1699  * Don't use this function. It sets the X Window System "class" and
1700  * "name" hints for a window.  According to the ICCCM, you should
1701  * always set these to the same value for all windows in an
1702  * application, and GTK+ sets them to that value by default, so calling
1703  * this function is sort of pointless. However, you may want to call
1704  * gtk_window_set_role() on each window in your application, for the
1705  * benefit of the session manager. Setting the role allows the window
1706  * manager to restore window positions when loading a saved session.
1707  * 
1708  **/
1709 void
1710 gtk_window_set_wmclass (GtkWindow *window,
1711                         const gchar *wmclass_name,
1712                         const gchar *wmclass_class)
1713 {
1714   GtkWindowPrivate *priv;
1715
1716   g_return_if_fail (GTK_IS_WINDOW (window));
1717
1718   priv = window->priv;
1719
1720   g_free (priv->wmclass_name);
1721   priv->wmclass_name = g_strdup (wmclass_name);
1722
1723   g_free (priv->wmclass_class);
1724   priv->wmclass_class = g_strdup (wmclass_class);
1725
1726   if (gtk_widget_get_realized (GTK_WIDGET (window)))
1727     g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1728 }
1729
1730 /**
1731  * gtk_window_set_role:
1732  * @window: a #GtkWindow
1733  * @role: unique identifier for the window to be used when restoring a session
1734  *
1735  * This function is only useful on X11, not with other GTK+ targets.
1736  * 
1737  * In combination with the window title, the window role allows a
1738  * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1739  * same" window when an application is restarted. So for example you
1740  * might set the "toolbox" role on your app's toolbox window, so that
1741  * when the user restarts their session, the window manager can put
1742  * the toolbox back in the same place.
1743  *
1744  * If a window already has a unique title, you don't need to set the
1745  * role, since the WM can use the title to identify the window when
1746  * restoring the session.
1747  * 
1748  **/
1749 void
1750 gtk_window_set_role (GtkWindow   *window,
1751                      const gchar *role)
1752 {
1753   GtkWindowPrivate *priv;
1754   char *new_role;
1755   
1756   g_return_if_fail (GTK_IS_WINDOW (window));
1757
1758   priv = window->priv;
1759
1760   new_role = g_strdup (role);
1761   g_free (priv->wm_role);
1762   priv->wm_role = new_role;
1763
1764   if (gtk_widget_get_realized (GTK_WIDGET (window)))
1765     gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1766                          priv->wm_role);
1767
1768   g_object_notify (G_OBJECT (window), "role");
1769 }
1770
1771 /**
1772  * gtk_window_set_startup_id:
1773  * @window: a #GtkWindow
1774  * @startup_id: a string with startup-notification identifier
1775  *
1776  * Startup notification identifiers are used by desktop environment to 
1777  * track application startup, to provide user feedback and other 
1778  * features. This function changes the corresponding property on the
1779  * underlying GdkWindow. Normally, startup identifier is managed 
1780  * automatically and you should only use this function in special cases
1781  * like transferring focus from other processes. You should use this
1782  * function before calling gtk_window_present() or any equivalent
1783  * function generating a window map event.
1784  *
1785  * This function is only useful on X11, not with other GTK+ targets.
1786  * 
1787  * Since: 2.12
1788  **/
1789 void
1790 gtk_window_set_startup_id (GtkWindow   *window,
1791                            const gchar *startup_id)
1792 {
1793   GtkWindowPrivate *priv;
1794   GtkWidget *widget;
1795
1796   g_return_if_fail (GTK_IS_WINDOW (window));
1797
1798   priv = window->priv;
1799   widget = GTK_WIDGET (window);
1800
1801   g_free (priv->startup_id);
1802   priv->startup_id = g_strdup (startup_id);
1803
1804   if (gtk_widget_get_realized (widget))
1805     {
1806       GdkWindow *gdk_window;
1807       guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1808
1809       gdk_window = gtk_widget_get_window (widget);
1810
1811 #ifdef GDK_WINDOWING_X11
1812       if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1813         gdk_x11_window_set_user_time (gdk_window, timestamp);
1814 #endif
1815
1816       /* Here we differentiate real and "fake" startup notification IDs,
1817        * constructed on purpose just to pass interaction timestamp
1818        */
1819       if (startup_id_is_fake (priv->startup_id))
1820         gtk_window_present_with_time (window, timestamp);
1821       else 
1822         {
1823           gdk_window_set_startup_id (gdk_window,
1824                                      priv->startup_id);
1825           
1826           /* If window is mapped, terminate the startup-notification too */
1827           if (gtk_widget_get_mapped (widget) &&
1828               !disable_startup_notification)
1829             gdk_notify_startup_complete_with_id (priv->startup_id);
1830         }
1831     }
1832
1833   g_object_notify (G_OBJECT (window), "startup-id");
1834 }
1835
1836 /**
1837  * gtk_window_get_role:
1838  * @window: a #GtkWindow
1839  *
1840  * Returns the role of the window. See gtk_window_set_role() for
1841  * further explanation.
1842  *
1843  * Return value: the role of the window if set, or %NULL. The
1844  *   returned is owned by the widget and must not be modified
1845  *   or freed.
1846  **/
1847 const gchar *
1848 gtk_window_get_role (GtkWindow *window)
1849 {
1850   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1851
1852   return window->priv->wm_role;
1853 }
1854
1855 /**
1856  * gtk_window_set_focus:
1857  * @window: a #GtkWindow
1858  * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1859  *   any focus widget for the toplevel window.
1860  *
1861  * If @focus is not the current focus widget, and is focusable, sets
1862  * it as the focus widget for the window. If @focus is %NULL, unsets
1863  * the focus widget for this window. To set the focus to a particular
1864  * widget in the toplevel, it is usually more convenient to use
1865  * gtk_widget_grab_focus() instead of this function.
1866  **/
1867 void
1868 gtk_window_set_focus (GtkWindow *window,
1869                       GtkWidget *focus)
1870 {
1871   GtkWindowPrivate *priv;
1872   GtkWidget *parent;
1873
1874   g_return_if_fail (GTK_IS_WINDOW (window));
1875
1876   priv = window->priv;
1877
1878   if (focus)
1879     {
1880       g_return_if_fail (GTK_IS_WIDGET (focus));
1881       g_return_if_fail (gtk_widget_get_can_focus (focus));
1882     }
1883
1884   if (focus)
1885     gtk_widget_grab_focus (focus);
1886   else
1887     {
1888       /* Clear the existing focus chain, so that when we focus into
1889        * the window again, we start at the beginnning.
1890        */
1891       GtkWidget *widget = priv->focus_widget;
1892       if (widget)
1893         {
1894           while ((parent = gtk_widget_get_parent (widget)))
1895             {
1896               widget = parent;
1897               gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1898             }
1899         }
1900       
1901       _gtk_window_internal_set_focus (window, NULL);
1902     }
1903 }
1904
1905 void
1906 _gtk_window_internal_set_focus (GtkWindow *window,
1907                                 GtkWidget *focus)
1908 {
1909   GtkWindowPrivate *priv;
1910
1911   g_return_if_fail (GTK_IS_WINDOW (window));
1912
1913   priv = window->priv;
1914
1915   if ((priv->focus_widget != focus) ||
1916       (focus && !gtk_widget_has_focus (focus)))
1917     g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1918 }
1919
1920 /**
1921  * gtk_window_set_default:
1922  * @window: a #GtkWindow
1923  * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1924  *                  default widget for the toplevel.
1925  *
1926  * The default widget is the widget that's activated when the user
1927  * presses Enter in a dialog (for example). This function sets or
1928  * unsets the default widget for a #GtkWindow about. When setting
1929  * (rather than unsetting) the default widget it's generally easier to
1930  * call gtk_widget_grab_focus() on the widget. Before making a widget
1931  * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1932  * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1933  **/
1934 void
1935 gtk_window_set_default (GtkWindow *window,
1936                         GtkWidget *default_widget)
1937 {
1938   GtkWindowPrivate *priv;
1939
1940   g_return_if_fail (GTK_IS_WINDOW (window));
1941
1942   priv = window->priv;
1943
1944   if (default_widget)
1945     g_return_if_fail (gtk_widget_get_can_default (default_widget));
1946
1947   if (priv->default_widget != default_widget)
1948     {
1949       GtkWidget *old_default_widget = NULL;
1950       
1951       if (default_widget)
1952         g_object_ref (default_widget);
1953
1954       if (priv->default_widget)
1955         {
1956           old_default_widget = priv->default_widget;
1957
1958           if (priv->focus_widget != priv->default_widget ||
1959               !gtk_widget_get_receives_default (priv->default_widget))
1960             _gtk_widget_set_has_default (priv->default_widget, FALSE);
1961
1962           gtk_widget_queue_draw (priv->default_widget);
1963         }
1964
1965       priv->default_widget = default_widget;
1966
1967       if (priv->default_widget)
1968         {
1969           if (priv->focus_widget == NULL ||
1970               !gtk_widget_get_receives_default (priv->focus_widget))
1971             _gtk_widget_set_has_default (priv->default_widget, TRUE);
1972
1973           gtk_widget_queue_draw (priv->default_widget);
1974         }
1975
1976       if (old_default_widget)
1977         g_object_notify (G_OBJECT (old_default_widget), "has-default");
1978       
1979       if (default_widget)
1980         {
1981           g_object_notify (G_OBJECT (default_widget), "has-default");
1982           g_object_unref (default_widget);
1983         }
1984     }
1985 }
1986
1987 /**
1988  * gtk_window_get_default_widget:
1989  * @window: a #GtkWindow
1990  *
1991  * Returns the default widget for @window. See gtk_window_set_default()
1992  * for more details.
1993  *
1994  * Returns: (transfer none): the default widget, or %NULL if there is none.
1995  *
1996  * Since: 2.14
1997  **/
1998 GtkWidget *
1999 gtk_window_get_default_widget (GtkWindow *window)
2000 {
2001   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2002
2003   return window->priv->default_widget;
2004 }
2005
2006 static gboolean
2007 handle_keys_changed (gpointer data)
2008 {
2009   GtkWindow *window = GTK_WINDOW (data);
2010   GtkWindowPrivate *priv = window->priv;
2011
2012   if (priv->keys_changed_handler)
2013     {
2014       g_source_remove (priv->keys_changed_handler);
2015       priv->keys_changed_handler = 0;
2016     }
2017
2018   g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
2019   
2020   return FALSE;
2021 }
2022
2023 static void
2024 gtk_window_notify_keys_changed (GtkWindow *window)
2025 {
2026   GtkWindowPrivate *priv = window->priv;
2027
2028   if (!priv->keys_changed_handler)
2029     priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
2030 }
2031
2032 /**
2033  * gtk_window_add_accel_group:
2034  * @window: window to attach accelerator group to
2035  * @accel_group: a #GtkAccelGroup
2036  *
2037  * Associate @accel_group with @window, such that calling
2038  * gtk_accel_groups_activate() on @window will activate accelerators
2039  * in @accel_group.
2040  **/
2041 void
2042 gtk_window_add_accel_group (GtkWindow     *window,
2043                             GtkAccelGroup *accel_group)
2044 {
2045   g_return_if_fail (GTK_IS_WINDOW (window));
2046   g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2047
2048   _gtk_accel_group_attach (accel_group, G_OBJECT (window));
2049   g_signal_connect_object (accel_group, "accel-changed",
2050                            G_CALLBACK (gtk_window_notify_keys_changed),
2051                            window, G_CONNECT_SWAPPED);
2052   gtk_window_notify_keys_changed (window);
2053 }
2054
2055 /**
2056  * gtk_window_remove_accel_group:
2057  * @window: a #GtkWindow
2058  * @accel_group: a #GtkAccelGroup
2059  *
2060  * Reverses the effects of gtk_window_add_accel_group().
2061  **/
2062 void
2063 gtk_window_remove_accel_group (GtkWindow     *window,
2064                                GtkAccelGroup *accel_group)
2065 {
2066   g_return_if_fail (GTK_IS_WINDOW (window));
2067   g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2068
2069   g_signal_handlers_disconnect_by_func (accel_group,
2070                                         gtk_window_notify_keys_changed,
2071                                         window);
2072   _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2073   gtk_window_notify_keys_changed (window);
2074 }
2075
2076 static GtkMnemonicHash *
2077 gtk_window_get_mnemonic_hash (GtkWindow *window,
2078                               gboolean   create)
2079 {
2080   GtkWindowPrivate *private = window->priv;
2081
2082   if (!private->mnemonic_hash && create)
2083     private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2084
2085   return private->mnemonic_hash;
2086 }
2087
2088 /**
2089  * gtk_window_add_mnemonic:
2090  * @window: a #GtkWindow
2091  * @keyval: the mnemonic
2092  * @target: the widget that gets activated by the mnemonic
2093  *
2094  * Adds a mnemonic to this window.
2095  */
2096 void
2097 gtk_window_add_mnemonic (GtkWindow *window,
2098                          guint      keyval,
2099                          GtkWidget *target)
2100 {
2101   g_return_if_fail (GTK_IS_WINDOW (window));
2102   g_return_if_fail (GTK_IS_WIDGET (target));
2103
2104   _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2105                           keyval, target);
2106   gtk_window_notify_keys_changed (window);
2107 }
2108
2109 /**
2110  * gtk_window_remove_mnemonic:
2111  * @window: a #GtkWindow
2112  * @keyval: the mnemonic
2113  * @target: the widget that gets activated by the mnemonic
2114  *
2115  * Removes a mnemonic from this window.
2116  */
2117 void
2118 gtk_window_remove_mnemonic (GtkWindow *window,
2119                             guint      keyval,
2120                             GtkWidget *target)
2121 {
2122   g_return_if_fail (GTK_IS_WINDOW (window));
2123   g_return_if_fail (GTK_IS_WIDGET (target));
2124   
2125   _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2126                              keyval, target);
2127   gtk_window_notify_keys_changed (window);
2128 }
2129
2130 /**
2131  * gtk_window_mnemonic_activate:
2132  * @window: a #GtkWindow
2133  * @keyval: the mnemonic
2134  * @modifier: the modifiers
2135  *
2136  * Activates the targets associated with the mnemonic.
2137  *
2138  * Returns: %TRUE if the activation is done.
2139  */
2140 gboolean
2141 gtk_window_mnemonic_activate (GtkWindow      *window,
2142                               guint           keyval,
2143                               GdkModifierType modifier)
2144 {
2145   GtkWindowPrivate *priv;
2146
2147   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2148
2149   priv = window->priv;
2150
2151   if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2152       {
2153         GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2154         if (mnemonic_hash)
2155           return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2156       }
2157
2158   return FALSE;
2159 }
2160
2161 /**
2162  * gtk_window_set_mnemonic_modifier:
2163  * @window: a #GtkWindow
2164  * @modifier: the modifier mask used to activate
2165  *               mnemonics on this window.
2166  *
2167  * Sets the mnemonic modifier for this window. 
2168  **/
2169 void
2170 gtk_window_set_mnemonic_modifier (GtkWindow      *window,
2171                                   GdkModifierType modifier)
2172 {
2173   GtkWindowPrivate *priv;
2174
2175   g_return_if_fail (GTK_IS_WINDOW (window));
2176   g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2177
2178   priv = window->priv;
2179
2180   priv->mnemonic_modifier = modifier;
2181   gtk_window_notify_keys_changed (window);
2182 }
2183
2184 /**
2185  * gtk_window_get_mnemonic_modifier:
2186  * @window: a #GtkWindow
2187  *
2188  * Returns the mnemonic modifier for this window. See
2189  * gtk_window_set_mnemonic_modifier().
2190  *
2191  * Return value: the modifier mask used to activate
2192  *               mnemonics on this window.
2193  **/
2194 GdkModifierType
2195 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2196 {
2197   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2198
2199   return window->priv->mnemonic_modifier;
2200 }
2201
2202 /**
2203  * gtk_window_set_position:
2204  * @window: a #GtkWindow.
2205  * @position: a position constraint.
2206  *
2207  * Sets a position constraint for this window. If the old or new
2208  * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2209  * the window to be repositioned to satisfy the new constraint. 
2210  **/
2211 void
2212 gtk_window_set_position (GtkWindow         *window,
2213                          GtkWindowPosition  position)
2214 {
2215   GtkWindowPrivate *priv;
2216
2217   g_return_if_fail (GTK_IS_WINDOW (window));
2218
2219   priv = window->priv;
2220
2221   if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2222       priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2223     {
2224       GtkWindowGeometryInfo *info;
2225
2226       info = gtk_window_get_geometry_info (window, TRUE);
2227
2228       /* this flag causes us to re-request the CENTER_ALWAYS
2229        * constraint in gtk_window_move_resize(), see
2230        * comment in that function.
2231        */
2232       info->position_constraints_changed = TRUE;
2233
2234       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2235     }
2236
2237   priv->position = position;
2238   
2239   g_object_notify (G_OBJECT (window), "window-position");
2240 }
2241
2242 /**
2243  * gtk_window_activate_focus:
2244  * @window: a #GtkWindow
2245  * 
2246  * Activates the current focused widget within the window.
2247  * 
2248  * Return value: %TRUE if a widget got activated.
2249  **/
2250 gboolean 
2251 gtk_window_activate_focus (GtkWindow *window)
2252 {
2253   GtkWindowPrivate *priv;
2254
2255   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2256
2257   priv = window->priv;
2258
2259   if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2260     return gtk_widget_activate (priv->focus_widget);
2261
2262   return FALSE;
2263 }
2264
2265 /**
2266  * gtk_window_get_focus:
2267  * @window: a #GtkWindow
2268  * 
2269  * Retrieves the current focused widget within the window.
2270  * Note that this is the widget that would have the focus
2271  * if the toplevel window focused; if the toplevel window
2272  * is not focused then  <literal>gtk_widget_has_focus (widget)</literal> will
2273  * not be %TRUE for the widget.
2274  *
2275  * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2276  **/
2277 GtkWidget *
2278 gtk_window_get_focus (GtkWindow *window)
2279 {
2280   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2281
2282   return window->priv->focus_widget;
2283 }
2284
2285 /**
2286  * gtk_window_activate_default:
2287  * @window: a #GtkWindow
2288  * 
2289  * Activates the default widget for the window, unless the current 
2290  * focused widget has been configured to receive the default action 
2291  * (see gtk_widget_set_receives_default()), in which case the
2292  * focused widget is activated. 
2293  * 
2294  * Return value: %TRUE if a widget got activated.
2295  **/
2296 gboolean
2297 gtk_window_activate_default (GtkWindow *window)
2298 {
2299   GtkWindowPrivate *priv;
2300
2301   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2302
2303   priv = window->priv;
2304
2305   if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2306       (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2307     return gtk_widget_activate (priv->default_widget);
2308   else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2309     return gtk_widget_activate (priv->focus_widget);
2310
2311   return FALSE;
2312 }
2313
2314 /**
2315  * gtk_window_set_modal:
2316  * @window: a #GtkWindow
2317  * @modal: whether the window is modal
2318  * 
2319  * Sets a window modal or non-modal. Modal windows prevent interaction
2320  * with other windows in the same application. To keep modal dialogs
2321  * on top of main application windows, use
2322  * gtk_window_set_transient_for() to make the dialog transient for the
2323  * parent; most <link linkend="gtk-X11-arch">window managers</link>
2324  * will then disallow lowering the dialog below the parent.
2325  * 
2326  * 
2327  **/
2328 void
2329 gtk_window_set_modal (GtkWindow *window,
2330                       gboolean   modal)
2331 {
2332   GtkWindowPrivate *priv;
2333   GtkWidget *widget;
2334
2335   g_return_if_fail (GTK_IS_WINDOW (window));
2336
2337   priv = window->priv;
2338
2339   modal = modal != FALSE;
2340   if (priv->modal == modal)
2341     return;
2342
2343   priv->modal = modal;
2344   widget = GTK_WIDGET (window);
2345   
2346   /* adjust desired modality state */
2347   if (gtk_widget_get_realized (widget))
2348     {
2349       if (priv->modal)
2350         gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2351       else
2352         gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2353     }
2354
2355   if (gtk_widget_get_visible (widget))
2356     {
2357       if (priv->modal)
2358         gtk_grab_add (widget);
2359       else
2360         gtk_grab_remove (widget);
2361     }
2362
2363   g_object_notify (G_OBJECT (window), "modal");
2364 }
2365
2366 /**
2367  * gtk_window_get_modal:
2368  * @window: a #GtkWindow
2369  * 
2370  * Returns whether the window is modal. See gtk_window_set_modal().
2371  *
2372  * Return value: %TRUE if the window is set to be modal and
2373  *               establishes a grab when shown
2374  **/
2375 gboolean
2376 gtk_window_get_modal (GtkWindow *window)
2377 {
2378   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2379
2380   return window->priv->modal;
2381 }
2382
2383 /**
2384  * gtk_window_list_toplevels:
2385  * 
2386  * Returns a list of all existing toplevel windows. The widgets
2387  * in the list are not individually referenced. If you want
2388  * to iterate through the list and perform actions involving
2389  * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2390  * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2391  * then unref all the widgets afterwards.
2392  *
2393  * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2394  **/
2395 GList*
2396 gtk_window_list_toplevels (void)
2397 {
2398   GList *list = NULL;
2399   GSList *slist;
2400
2401   for (slist = toplevel_list; slist; slist = slist->next)
2402     list = g_list_prepend (list, slist->data);
2403
2404   return list;
2405 }
2406
2407 static void
2408 remove_attach_widget (GtkWindow *window)
2409 {
2410   GtkWindowPrivate *priv = window->priv;
2411
2412   if (priv->attach_widget)
2413     {
2414       _gtk_widget_remove_attached_window (priv->attach_widget, window);
2415
2416       g_object_unref (priv->attach_widget);
2417       priv->attach_widget = NULL;
2418     }
2419 }
2420
2421 static void
2422 gtk_window_dispose (GObject *object)
2423 {
2424   GtkWindow *window = GTK_WINDOW (object);
2425
2426   gtk_window_set_focus (window, NULL);
2427   gtk_window_set_default (window, NULL);
2428
2429   remove_attach_widget (GTK_WINDOW (object));
2430
2431   G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2432 }
2433
2434 static void
2435 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2436 {
2437   gtk_widget_destroy (GTK_WIDGET (child));
2438 }
2439
2440 static void
2441 connect_parent_destroyed (GtkWindow *window)
2442 {
2443   GtkWindowPrivate *priv = window->priv;
2444
2445   if (priv->transient_parent)
2446     {
2447       g_signal_connect (priv->transient_parent,
2448                         "destroy",
2449                         G_CALLBACK (parent_destroyed_callback),
2450                         window);
2451     }  
2452 }
2453
2454 static void
2455 disconnect_parent_destroyed (GtkWindow *window)
2456 {
2457   GtkWindowPrivate *priv = window->priv;
2458
2459   if (priv->transient_parent)
2460     {
2461       g_signal_handlers_disconnect_by_func (priv->transient_parent,
2462                                             parent_destroyed_callback,
2463                                             window);
2464     }
2465 }
2466
2467 static void
2468 gtk_window_transient_parent_realized (GtkWidget *parent,
2469                                       GtkWidget *window)
2470 {
2471   if (gtk_widget_get_realized (window))
2472     gdk_window_set_transient_for (gtk_widget_get_window (window),
2473                                   gtk_widget_get_window (parent));
2474 }
2475
2476 static void
2477 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2478                                         GtkWidget *window)
2479 {
2480   if (gtk_widget_get_realized (window))
2481     gdk_property_delete (gtk_widget_get_window (window),
2482                          gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2483 }
2484
2485 static void
2486 gtk_window_transient_parent_screen_changed (GtkWindow   *parent,
2487                                             GParamSpec  *pspec,
2488                                             GtkWindow   *window)
2489 {
2490   gtk_window_set_screen (window, parent->priv->screen);
2491 }
2492
2493 static void       
2494 gtk_window_unset_transient_for  (GtkWindow *window)
2495 {
2496   GtkWindowPrivate *priv = window->priv;
2497
2498   if (priv->transient_parent)
2499     {
2500       g_signal_handlers_disconnect_by_func (priv->transient_parent,
2501                                             gtk_window_transient_parent_realized,
2502                                             window);
2503       g_signal_handlers_disconnect_by_func (priv->transient_parent,
2504                                             gtk_window_transient_parent_unrealized,
2505                                             window);
2506       g_signal_handlers_disconnect_by_func (priv->transient_parent,
2507                                             gtk_window_transient_parent_screen_changed,
2508                                             window);
2509       g_signal_handlers_disconnect_by_func (priv->transient_parent,
2510                                             gtk_widget_destroyed,
2511                                             &priv->transient_parent);
2512
2513       if (priv->destroy_with_parent)
2514         disconnect_parent_destroyed (window);
2515
2516       priv->transient_parent = NULL;
2517
2518       if (priv->transient_parent_group)
2519         {
2520           priv->transient_parent_group = FALSE;
2521           gtk_window_group_remove_window (priv->group,
2522                                           window);
2523         }
2524     }
2525 }
2526
2527 /**
2528  * gtk_window_set_transient_for:
2529  * @window: a #GtkWindow
2530  * @parent: (allow-none): parent window, or %NULL
2531  *
2532  * Dialog windows should be set transient for the main application
2533  * window they were spawned from. This allows <link
2534  * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2535  * dialog on top of the main window, or center the dialog over the
2536  * main window. gtk_dialog_new_with_buttons() and other convenience
2537  * functions in GTK+ will sometimes call
2538  * gtk_window_set_transient_for() on your behalf.
2539  *
2540  * Passing %NULL for @parent unsets the current transient window.
2541  *
2542  * On Windows, this function puts the child window on top of the parent,
2543  * much as the window manager would have done on X.
2544  */
2545 void
2546 gtk_window_set_transient_for  (GtkWindow *window,
2547                                GtkWindow *parent)
2548 {
2549   GtkWindowPrivate *priv;
2550
2551   g_return_if_fail (GTK_IS_WINDOW (window));
2552   g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2553   g_return_if_fail (window != parent);
2554
2555   priv = window->priv;
2556
2557   if (priv->transient_parent)
2558     {
2559       if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2560           gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2561           (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2562         gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2563                                                 GTK_WIDGET (window));
2564
2565       gtk_window_unset_transient_for (window);
2566     }
2567
2568   priv->transient_parent = parent;
2569
2570   if (parent)
2571     {
2572       g_signal_connect (parent, "destroy",
2573                         G_CALLBACK (gtk_widget_destroyed),
2574                         &priv->transient_parent);
2575       g_signal_connect (parent, "realize",
2576                         G_CALLBACK (gtk_window_transient_parent_realized),
2577                         window);
2578       g_signal_connect (parent, "unrealize",
2579                         G_CALLBACK (gtk_window_transient_parent_unrealized),
2580                         window);
2581       g_signal_connect (parent, "notify::screen",
2582                         G_CALLBACK (gtk_window_transient_parent_screen_changed),
2583                         window);
2584
2585       gtk_window_set_screen (window, parent->priv->screen);
2586
2587       if (priv->destroy_with_parent)
2588         connect_parent_destroyed (window);
2589       
2590       if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2591           gtk_widget_get_realized (GTK_WIDGET (parent)))
2592         gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2593                                               GTK_WIDGET (window));
2594
2595       if (parent->priv->group)
2596         {
2597           gtk_window_group_add_window (parent->priv->group, window);
2598           priv->transient_parent_group = TRUE;
2599         }
2600     }
2601 }
2602
2603 /**
2604  * gtk_window_get_transient_for:
2605  * @window: a #GtkWindow
2606  *
2607  * Fetches the transient parent for this window. See
2608  * gtk_window_set_transient_for().
2609  *
2610  * Return value: (transfer none): the transient parent for this window, or %NULL
2611  *    if no transient parent has been set.
2612  **/
2613 GtkWindow *
2614 gtk_window_get_transient_for (GtkWindow *window)
2615 {
2616   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2617
2618   return window->priv->transient_parent;
2619 }
2620
2621 /**
2622  * gtk_window_set_attached_to:
2623  * @window: a #GtkWindow
2624  * @attach_widget: (allow-none): a #GtkWidget, or %NULL
2625  *
2626  * Marks @window as attached to @attach_widget. This creates a logical binding
2627  * between the window and the widget it belongs to, which is used by GTK+ to
2628  * propagate information such as styling or accessibility to @window as if it
2629  * was a children of @attach_widget.
2630  *
2631  * Examples of places where specifying this relation is useful are for instance
2632  * a #GtkMenu created by a #GtkComboBox, a completion popup window
2633  * created by #GtkEntry or a typeahead search entry created by #GtkTreeView.
2634  *
2635  * Note that this function should not be confused with
2636  * gtk_window_set_transient_for(), which specifies a window manager relation
2637  * between two toplevels instead.
2638  *
2639  * Passing %NULL for @attach_widget detaches the window.
2640  *
2641  * Since: 3.4
2642  **/
2643 void
2644 gtk_window_set_attached_to (GtkWindow *window,
2645                             GtkWidget *attach_widget)
2646 {
2647   GtkWindowPrivate *priv;
2648
2649   g_return_if_fail (GTK_IS_WINDOW (window));
2650   g_return_if_fail (GTK_WIDGET (window) != attach_widget);
2651
2652   priv = window->priv;
2653
2654   if (priv->attach_widget == attach_widget)
2655     return;
2656
2657   remove_attach_widget (window);
2658
2659   priv->attach_widget = attach_widget;
2660
2661   if (priv->attach_widget)
2662     {
2663       _gtk_widget_add_attached_window (priv->attach_widget, window);
2664
2665       g_object_ref (priv->attach_widget);
2666     }
2667
2668   /* Update the style, as the widget path might change. */
2669   gtk_widget_reset_style (GTK_WIDGET (window)); 
2670 }
2671
2672 /**
2673  * gtk_window_get_attached_to:
2674  * @window: a #GtkWindow
2675  *
2676  * Fetches the attach widget for this window. See
2677  * gtk_window_set_attached_to().
2678  *
2679  * Return value: (transfer none): the widget where the window is attached,
2680  *   or %NULL if the window is not attached to any widget.
2681  *
2682  * Since: 3.4
2683  **/
2684 GtkWidget *
2685 gtk_window_get_attached_to (GtkWindow *window)
2686 {
2687   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2688
2689   return window->priv->attach_widget;
2690 }
2691
2692 /**
2693  * gtk_window_set_opacity:
2694  * @window: a #GtkWindow
2695  * @opacity: desired opacity, between 0 and 1
2696  *
2697  * Request the windowing system to make @window partially transparent,
2698  * with opacity 0 being fully transparent and 1 fully opaque. (Values
2699  * of the opacity parameter are clamped to the [0,1] range.) On X11
2700  * this has any effect only on X screens with a compositing manager
2701  * running. See gtk_widget_is_composited(). On Windows it should work
2702  * always.
2703  * 
2704  * Note that setting a window's opacity after the window has been
2705  * shown causes it to flicker once on Windows.
2706  *
2707  * Since: 2.12
2708  **/
2709 void       
2710 gtk_window_set_opacity  (GtkWindow *window, 
2711                          gdouble    opacity)
2712 {
2713   GtkWindowPrivate *priv;
2714
2715   g_return_if_fail (GTK_IS_WINDOW (window));
2716
2717   priv = window->priv;
2718
2719   if (opacity < 0.0)
2720     opacity = 0.0;
2721   else if (opacity > 1.0)
2722     opacity = 1.0;
2723
2724   priv->opacity_set = TRUE;
2725   priv->opacity = opacity;
2726
2727   if (gtk_widget_get_realized (GTK_WIDGET (window)))
2728     gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2729                             priv->opacity);
2730 }
2731
2732 /**
2733  * gtk_window_get_opacity:
2734  * @window: a #GtkWindow
2735  *
2736  * Fetches the requested opacity for this window. See
2737  * gtk_window_set_opacity().
2738  *
2739  * Return value: the requested opacity for this window.
2740  *
2741  * Since: 2.12
2742  **/
2743 gdouble
2744 gtk_window_get_opacity (GtkWindow *window)
2745 {
2746   g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2747
2748   return window->priv->opacity;
2749 }
2750
2751 /**
2752  * gtk_window_get_application:
2753  * @window: a #GtkWindow
2754  *
2755  * Gets the #GtkApplication associated with the window (if any).
2756  *
2757  * Return value: (transfer none): a #GtkApplication, or %NULL
2758  *
2759  * Since: 3.0
2760  **/
2761 GtkApplication *
2762 gtk_window_get_application (GtkWindow *window)
2763 {
2764   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2765
2766   return window->priv->application;
2767 }
2768
2769 static void
2770 gtk_window_release_application (GtkWindow *window)
2771 {
2772   if (window->priv->application)
2773     {
2774       GtkApplication *application;
2775
2776       /* steal reference into temp variable */
2777       application = window->priv->application;
2778       window->priv->application = NULL;
2779
2780       gtk_application_remove_window (application, window);
2781       g_object_unref (application);
2782     }
2783 }
2784
2785 /**
2786  * gtk_window_set_application:
2787  * @window: a #GtkWindow
2788  * @application: (allow-none): a #GtkApplication, or %NULL
2789  *
2790  * Sets or unsets the #GtkApplication associated with the window.
2791  *
2792  * The application will be kept alive for at least as long as the window
2793  * is open.
2794  *
2795  * Since: 3.0
2796  **/
2797 void
2798 gtk_window_set_application (GtkWindow      *window,
2799                             GtkApplication *application)
2800 {
2801   GtkWindowPrivate *priv;
2802
2803   g_return_if_fail (GTK_IS_WINDOW (window));
2804
2805   priv = window->priv;
2806   if (priv->application != application)
2807     {
2808       gtk_window_release_application (window);
2809
2810       priv->application = application;
2811
2812       if (priv->application != NULL)
2813         {
2814           g_object_ref (priv->application);
2815
2816           gtk_application_add_window (priv->application, window);
2817         }
2818
2819       g_object_notify (G_OBJECT (window), "application");
2820     }
2821 }
2822
2823 /**
2824  * gtk_window_set_type_hint:
2825  * @window: a #GtkWindow
2826  * @hint: the window type
2827  *
2828  * By setting the type hint for the window, you allow the window
2829  * manager to decorate and handle the window in a way which is
2830  * suitable to the function of the window in your application.
2831  *
2832  * This function should be called before the window becomes visible.
2833  *
2834  * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2835  * will sometimes call gtk_window_set_type_hint() on your behalf.
2836  * 
2837  **/
2838 void
2839 gtk_window_set_type_hint (GtkWindow           *window, 
2840                           GdkWindowTypeHint    hint)
2841 {
2842   GtkWindowPrivate *priv;
2843
2844   g_return_if_fail (GTK_IS_WINDOW (window));
2845   g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2846
2847   priv = window->priv;
2848
2849   if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2850     priv->type_hint = hint;
2851   else
2852     priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2853
2854   priv->reset_type_hint = TRUE;
2855   priv->gdk_type_hint = hint;
2856 }
2857
2858 /**
2859  * gtk_window_get_type_hint:
2860  * @window: a #GtkWindow
2861  *
2862  * Gets the type hint for this window. See gtk_window_set_type_hint().
2863  *
2864  * Return value: the type hint for @window.
2865  **/
2866 GdkWindowTypeHint
2867 gtk_window_get_type_hint (GtkWindow *window)
2868 {
2869   g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2870
2871   return window->priv->gdk_type_hint;
2872 }
2873
2874 /**
2875  * gtk_window_set_skip_taskbar_hint:
2876  * @window: a #GtkWindow 
2877  * @setting: %TRUE to keep this window from appearing in the task bar
2878  * 
2879  * Windows may set a hint asking the desktop environment not to display
2880  * the window in the task bar. This function sets this hint.
2881  * 
2882  * Since: 2.2
2883  **/
2884 void
2885 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2886                                   gboolean   setting)
2887 {
2888   GtkWindowPrivate *priv;
2889
2890   g_return_if_fail (GTK_IS_WINDOW (window));
2891
2892   priv = window->priv;
2893
2894   setting = setting != FALSE;
2895
2896   if (priv->skips_taskbar != setting)
2897     {
2898       priv->skips_taskbar = setting;
2899       if (gtk_widget_get_realized (GTK_WIDGET (window)))
2900         gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2901                                           priv->skips_taskbar);
2902       g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2903     }
2904 }
2905
2906 /**
2907  * gtk_window_get_skip_taskbar_hint:
2908  * @window: a #GtkWindow
2909  * 
2910  * Gets the value set by gtk_window_set_skip_taskbar_hint()
2911  * 
2912  * Return value: %TRUE if window shouldn't be in taskbar
2913  * 
2914  * Since: 2.2
2915  **/
2916 gboolean
2917 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2918 {
2919   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2920
2921   return window->priv->skips_taskbar;
2922 }
2923
2924 /**
2925  * gtk_window_set_skip_pager_hint:
2926  * @window: a #GtkWindow 
2927  * @setting: %TRUE to keep this window from appearing in the pager
2928  * 
2929  * Windows may set a hint asking the desktop environment not to display
2930  * the window in the pager. This function sets this hint.
2931  * (A "pager" is any desktop navigation tool such as a workspace
2932  * switcher that displays a thumbnail representation of the windows
2933  * on the screen.)
2934  * 
2935  * Since: 2.2
2936  **/
2937 void
2938 gtk_window_set_skip_pager_hint (GtkWindow *window,
2939                                 gboolean   setting)
2940 {
2941   GtkWindowPrivate *priv;
2942
2943   g_return_if_fail (GTK_IS_WINDOW (window));
2944
2945   priv = window->priv;
2946
2947   setting = setting != FALSE;
2948
2949   if (priv->skips_pager != setting)
2950     {
2951       priv->skips_pager = setting;
2952       if (gtk_widget_get_realized (GTK_WIDGET (window)))
2953         gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2954                                         priv->skips_pager);
2955       g_object_notify (G_OBJECT (window), "skip-pager-hint");
2956     }
2957 }
2958
2959 /**
2960  * gtk_window_get_skip_pager_hint:
2961  * @window: a #GtkWindow
2962  * 
2963  * Gets the value set by gtk_window_set_skip_pager_hint().
2964  * 
2965  * Return value: %TRUE if window shouldn't be in pager
2966  * 
2967  * Since: 2.2
2968  **/
2969 gboolean
2970 gtk_window_get_skip_pager_hint (GtkWindow *window)
2971 {
2972   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2973
2974   return window->priv->skips_pager;
2975 }
2976
2977 /**
2978  * gtk_window_set_urgency_hint:
2979  * @window: a #GtkWindow 
2980  * @setting: %TRUE to mark this window as urgent
2981  * 
2982  * Windows may set a hint asking the desktop environment to draw
2983  * the users attention to the window. This function sets this hint.
2984  * 
2985  * Since: 2.8
2986  **/
2987 void
2988 gtk_window_set_urgency_hint (GtkWindow *window,
2989                              gboolean   setting)
2990 {
2991   GtkWindowPrivate *priv;
2992
2993   g_return_if_fail (GTK_IS_WINDOW (window));
2994
2995   priv = window->priv;
2996
2997   setting = setting != FALSE;
2998
2999   if (priv->urgent != setting)
3000     {
3001       priv->urgent = setting;
3002       if (gtk_widget_get_realized (GTK_WIDGET (window)))
3003         gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
3004                                      priv->urgent);
3005       g_object_notify (G_OBJECT (window), "urgency-hint");
3006     }
3007 }
3008
3009 /**
3010  * gtk_window_get_urgency_hint:
3011  * @window: a #GtkWindow
3012  * 
3013  * Gets the value set by gtk_window_set_urgency_hint()
3014  * 
3015  * Return value: %TRUE if window is urgent
3016  * 
3017  * Since: 2.8
3018  **/
3019 gboolean
3020 gtk_window_get_urgency_hint (GtkWindow *window)
3021 {
3022   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3023
3024   return window->priv->urgent;
3025 }
3026
3027 /**
3028  * gtk_window_set_accept_focus:
3029  * @window: a #GtkWindow 
3030  * @setting: %TRUE to let this window receive input focus
3031  * 
3032  * Windows may set a hint asking the desktop environment not to receive
3033  * the input focus. This function sets this hint.
3034  * 
3035  * Since: 2.4
3036  **/
3037 void
3038 gtk_window_set_accept_focus (GtkWindow *window,
3039                              gboolean   setting)
3040 {
3041   GtkWindowPrivate *priv;
3042
3043   g_return_if_fail (GTK_IS_WINDOW (window));
3044
3045   priv = window->priv;
3046
3047   setting = setting != FALSE;
3048
3049   if (priv->accept_focus != setting)
3050     {
3051       priv->accept_focus = setting;
3052       if (gtk_widget_get_realized (GTK_WIDGET (window)))
3053         gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
3054                                      priv->accept_focus);
3055       g_object_notify (G_OBJECT (window), "accept-focus");
3056     }
3057 }
3058
3059 /**
3060  * gtk_window_get_accept_focus:
3061  * @window: a #GtkWindow
3062  * 
3063  * Gets the value set by gtk_window_set_accept_focus().
3064  * 
3065  * Return value: %TRUE if window should receive the input focus
3066  * 
3067  * Since: 2.4
3068  **/
3069 gboolean
3070 gtk_window_get_accept_focus (GtkWindow *window)
3071 {
3072   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3073
3074   return window->priv->accept_focus;
3075 }
3076
3077 /**
3078  * gtk_window_set_focus_on_map:
3079  * @window: a #GtkWindow 
3080  * @setting: %TRUE to let this window receive input focus on map
3081  * 
3082  * Windows may set a hint asking the desktop environment not to receive
3083  * the input focus when the window is mapped.  This function sets this
3084  * hint.
3085  * 
3086  * Since: 2.6
3087  **/
3088 void
3089 gtk_window_set_focus_on_map (GtkWindow *window,
3090                              gboolean   setting)
3091 {
3092   GtkWindowPrivate *priv;
3093
3094   g_return_if_fail (GTK_IS_WINDOW (window));
3095
3096   priv = window->priv;
3097
3098   setting = setting != FALSE;
3099
3100   if (priv->focus_on_map != setting)
3101     {
3102       priv->focus_on_map = setting;
3103       if (gtk_widget_get_realized (GTK_WIDGET (window)))
3104         gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
3105                                      priv->focus_on_map);
3106       g_object_notify (G_OBJECT (window), "focus-on-map");
3107     }
3108 }
3109
3110 /**
3111  * gtk_window_get_focus_on_map:
3112  * @window: a #GtkWindow
3113  * 
3114  * Gets the value set by gtk_window_set_focus_on_map().
3115  * 
3116  * Return value: %TRUE if window should receive the input focus when
3117  * mapped.
3118  * 
3119  * Since: 2.6
3120  **/
3121 gboolean
3122 gtk_window_get_focus_on_map (GtkWindow *window)
3123 {
3124   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3125
3126   return window->priv->focus_on_map;
3127 }
3128
3129 /**
3130  * gtk_window_set_destroy_with_parent:
3131  * @window: a #GtkWindow
3132  * @setting: whether to destroy @window with its transient parent
3133  * 
3134  * If @setting is %TRUE, then destroying the transient parent of @window
3135  * will also destroy @window itself. This is useful for dialogs that
3136  * shouldn't persist beyond the lifetime of the main window they're
3137  * associated with, for example.
3138  **/
3139 void
3140 gtk_window_set_destroy_with_parent  (GtkWindow *window,
3141                                      gboolean   setting)
3142 {
3143   GtkWindowPrivate *priv;
3144
3145   g_return_if_fail (GTK_IS_WINDOW (window));
3146
3147   priv = window->priv;
3148
3149   if (priv->destroy_with_parent == (setting != FALSE))
3150     return;
3151
3152   if (priv->destroy_with_parent)
3153     {
3154       disconnect_parent_destroyed (window);
3155     }
3156   else
3157     {
3158       connect_parent_destroyed (window);
3159     }
3160
3161   priv->destroy_with_parent = setting;
3162
3163   g_object_notify (G_OBJECT (window), "destroy-with-parent");
3164 }
3165
3166 /**
3167  * gtk_window_get_destroy_with_parent:
3168  * @window: a #GtkWindow
3169  * 
3170  * Returns whether the window will be destroyed with its transient parent. See
3171  * gtk_window_set_destroy_with_parent ().
3172  *
3173  * Return value: %TRUE if the window will be destroyed with its transient parent.
3174  **/
3175 gboolean
3176 gtk_window_get_destroy_with_parent (GtkWindow *window)
3177 {
3178   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3179
3180   return window->priv->destroy_with_parent;
3181 }
3182
3183 /**
3184  * gtk_window_set_hide_titlebar_when_maximized:
3185  * @window: a #GtkWindow
3186  * @setting: whether to hide the titlebar when @window is maximized
3187  *
3188  * If @setting is %TRUE, then @window will request that it's titlebar
3189  * should be hidden when maximized.
3190  * This is useful for windows that don't convey any information other
3191  * than the application name in the titlebar, to put the available
3192  * screen space to better use. If the underlying window system does not
3193  * support the request, the setting will not have any effect.
3194  *
3195  * Since: 3.4
3196  **/
3197 void
3198 gtk_window_set_hide_titlebar_when_maximized (GtkWindow *window,
3199                                              gboolean   setting)
3200 {
3201   g_return_if_fail (GTK_IS_WINDOW (window));
3202
3203 #ifdef GDK_WINDOWING_X11
3204   {
3205     GdkWindow *gdk_window;
3206
3207     gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3208
3209     if (GDK_IS_X11_WINDOW (gdk_window))
3210       gdk_x11_window_set_hide_titlebar_when_maximized (gdk_window, setting);
3211   }
3212 #endif
3213
3214   window->priv->hide_titlebar_when_maximized = setting;
3215   g_object_notify (G_OBJECT (window), "hide-titlebar-when-maximized");
3216 }
3217
3218 /**
3219  * gtk_window_get_hide_titlebar_when_maximized:
3220  * @window: a #GtkWindow
3221  *
3222  * Returns whether the window has requested to have its titlebar hidden
3223  * when maximized. See gtk_window_set_hide_titlebar_when_maximized ().
3224  *
3225  * Return value: %TRUE if the window has requested to have its titlebar
3226  *               hidden when maximized
3227  *
3228  * Since: 3.4
3229  **/
3230 gboolean
3231 gtk_window_get_hide_titlebar_when_maximized (GtkWindow *window)
3232 {
3233   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3234
3235   return window->priv->hide_titlebar_when_maximized;
3236 }
3237
3238 static GtkWindowGeometryInfo*
3239 gtk_window_get_geometry_info (GtkWindow *window,
3240                               gboolean   create)
3241 {
3242   GtkWindowPrivate *priv = window->priv;
3243   GtkWindowGeometryInfo *info;
3244
3245   info = priv->geometry_info;
3246   if (!info && create)
3247     {
3248       info = g_new0 (GtkWindowGeometryInfo, 1);
3249
3250       info->default_width = -1;
3251       info->default_height = -1;
3252       info->resize_width = -1;
3253       info->resize_height = -1;
3254       info->initial_x = 0;
3255       info->initial_y = 0;
3256       info->initial_pos_set = FALSE;
3257       info->default_is_geometry = FALSE;
3258       info->position_constraints_changed = FALSE;
3259       info->last.configure_request.x = 0;
3260       info->last.configure_request.y = 0;
3261       info->last.configure_request.width = -1;
3262       info->last.configure_request.height = -1;
3263       info->widget = NULL;
3264       info->mask = 0;
3265       priv->geometry_info = info;
3266     }
3267
3268   return info;
3269 }
3270
3271 /**
3272  * gtk_window_set_geometry_hints:
3273  * @window: a #GtkWindow
3274  * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3275  * @geometry: (allow-none): struct containing geometry information or %NULL
3276  * @geom_mask: mask indicating which struct fields should be paid attention to
3277  *
3278  * This function sets up hints about how a window can be resized by
3279  * the user.  You can set a minimum and maximum size; allowed resize
3280  * increments (e.g. for xterm, you can only resize by the size of a
3281  * character); aspect ratios; and more. See the #GdkGeometry struct.
3282  * 
3283  **/
3284 void       
3285 gtk_window_set_geometry_hints (GtkWindow       *window,
3286                                GtkWidget       *geometry_widget,
3287                                GdkGeometry     *geometry,
3288                                GdkWindowHints   geom_mask)
3289 {
3290   GtkWindowGeometryInfo *info;
3291
3292   g_return_if_fail (GTK_IS_WINDOW (window));
3293   g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3294
3295   info = gtk_window_get_geometry_info (window, TRUE);
3296   
3297   if (info->widget)
3298     g_signal_handlers_disconnect_by_func (info->widget,
3299                                           gtk_widget_destroyed,
3300                                           &info->widget);
3301   
3302   info->widget = geometry_widget;
3303   if (info->widget)
3304     g_signal_connect (geometry_widget, "destroy",
3305                       G_CALLBACK (gtk_widget_destroyed),
3306                       &info->widget);
3307
3308   if (geometry)
3309     info->geometry = *geometry;
3310
3311   /* We store gravity in priv->gravity not in the hints. */
3312   info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3313
3314   if (geom_mask & GDK_HINT_WIN_GRAVITY)
3315     {
3316       gtk_window_set_gravity (window, geometry->win_gravity);
3317     }
3318
3319   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3320 }
3321
3322 /**
3323  * gtk_window_set_decorated:
3324  * @window: a #GtkWindow
3325  * @setting: %TRUE to decorate the window
3326  *
3327  * By default, windows are decorated with a title bar, resize
3328  * controls, etc.  Some <link linkend="gtk-X11-arch">window
3329  * managers</link> allow GTK+ to disable these decorations, creating a
3330  * borderless window. If you set the decorated property to %FALSE
3331  * using this function, GTK+ will do its best to convince the window
3332  * manager not to decorate the window. Depending on the system, this
3333  * function may not have any effect when called on a window that is
3334  * already visible, so you should call it before calling gtk_widget_show().
3335  *
3336  * On Windows, this function always works, since there's no window manager
3337  * policy involved.
3338  * 
3339  **/
3340 void
3341 gtk_window_set_decorated (GtkWindow *window,
3342                           gboolean   setting)
3343 {
3344   GtkWindowPrivate *priv;
3345   GdkWindow *gdk_window;
3346
3347   g_return_if_fail (GTK_IS_WINDOW (window));
3348
3349   priv = window->priv;
3350
3351   setting = setting != FALSE;
3352
3353   if (setting == priv->decorated)
3354     return;
3355
3356   priv->decorated = setting;
3357
3358   gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3359   if (gdk_window)
3360     {
3361       if (priv->decorated)
3362         gdk_window_set_decorations (gdk_window,
3363                                     GDK_DECOR_ALL);
3364       else
3365         gdk_window_set_decorations (gdk_window,
3366                                     0);
3367     }
3368
3369   g_object_notify (G_OBJECT (window), "decorated");
3370 }
3371
3372 /**
3373  * gtk_window_get_decorated:
3374  * @window: a #GtkWindow
3375  *
3376  * Returns whether the window has been set to have decorations
3377  * such as a title bar via gtk_window_set_decorated().
3378  *
3379  * Return value: %TRUE if the window has been set to have decorations
3380  **/
3381 gboolean
3382 gtk_window_get_decorated (GtkWindow *window)
3383 {
3384   g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3385
3386   return window->priv->decorated;
3387 }
3388
3389 /**
3390  * gtk_window_set_deletable:
3391  * @window: a #GtkWindow
3392  * @setting: %TRUE to decorate the window as deletable
3393  *
3394  * By default, windows have a close button in the window frame. Some 
3395  * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to 
3396  * disable this button. If you set the deletable property to %FALSE
3397  * using this function, GTK+ will do its best to convince the window
3398  * manager not to show a close button. Depending on the system, this
3399  * function may not have any effect when called on a window that is
3400  * already visible, so you should call it before calling gtk_window_show().
3401  *
3402  * On Windows, this function always works, since there's no window manager
3403  * policy involved.
3404  *
3405  * Since: 2.10
3406  */
3407 void
3408 gtk_window_set_deletable (GtkWindow *window,
3409                           gboolean   setting)
3410 {
3411   GtkWindowPrivate *priv;
3412   GdkWindow *gdk_window;
3413
3414   g_return_if_fail (GTK_IS_WINDOW (window));
3415
3416   priv = window->priv;
3417
3418   setting = setting != FALSE;
3419
3420   if (setting == priv->deletable)
3421     return;
3422
3423   priv->deletable = setting;
3424
3425   gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3426   if (gdk_window)
3427     {
3428       if (priv->deletable)
3429         gdk_window_set_functions (gdk_window,
3430                                   GDK_FUNC_ALL);
3431       else
3432         gdk_window_set_functions (gdk_window,
3433                                   GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3434     }
3435
3436   g_object_notify (G_OBJECT (window), "deletable");  
3437 }
3438
3439 /**
3440  * gtk_window_get_deletable:
3441  * @window: a #GtkWindow
3442  *
3443  * Returns whether the window has been set to have a close button
3444  * via gtk_window_set_deletable().
3445  *
3446  * Return value: %TRUE if the window has been set to have a close button
3447  *
3448  * Since: 2.10
3449  **/
3450 gboolean
3451 gtk_window_get_deletable (GtkWindow *window)
3452 {
3453   g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3454
3455   return window->priv->deletable;
3456 }
3457
3458 static GtkWindowIconInfo*
3459 get_icon_info (GtkWindow *window)
3460 {
3461   return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3462 }
3463      
3464 static void
3465 free_icon_info (GtkWindowIconInfo *info)
3466 {
3467   g_free (info->icon_name);
3468   g_slice_free (GtkWindowIconInfo, info);
3469 }
3470
3471
3472 static GtkWindowIconInfo*
3473 ensure_icon_info (GtkWindow *window)
3474 {
3475   GtkWindowIconInfo *info;
3476
3477   info = get_icon_info (window);
3478   
3479   if (info == NULL)
3480     {
3481       info = g_slice_new0 (GtkWindowIconInfo);
3482       g_object_set_qdata_full (G_OBJECT (window),
3483                               quark_gtk_window_icon_info,
3484                               info,
3485                               (GDestroyNotify)free_icon_info);
3486     }
3487
3488   return info;
3489 }
3490
3491 static GList *
3492 icon_list_from_theme (GtkWidget    *widget,
3493                       const gchar  *name)
3494 {
3495   GList *list;
3496
3497   GtkIconTheme *icon_theme;
3498   GdkPixbuf *icon;
3499   gint *sizes;
3500   gint i;
3501
3502   icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3503
3504   sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3505
3506   list = NULL;
3507   for (i = 0; sizes[i]; i++)
3508     {      
3509       /* FIXME
3510        * We need an EWMH extension to handle scalable icons 
3511        * by passing their name to the WM. For now just use a 
3512        * fixed size of 48.
3513        */ 
3514       if (sizes[i] == -1)
3515         icon = gtk_icon_theme_load_icon (icon_theme, name,
3516                                          48, 0, NULL);
3517       else
3518         icon = gtk_icon_theme_load_icon (icon_theme, name,
3519                                          sizes[i], 0, NULL);
3520       if (icon)
3521         list = g_list_append (list, icon);
3522     }
3523
3524   g_free (sizes);
3525
3526   return list;
3527 }
3528
3529
3530 static void
3531 gtk_window_realize_icon (GtkWindow *window)
3532 {
3533   GtkWindowPrivate *priv = window->priv;
3534   GtkWidget *widget;
3535   GtkWindowIconInfo *info;
3536   GdkWindow *gdk_window;
3537   GList *icon_list;
3538
3539   widget = GTK_WIDGET (window);
3540   gdk_window = gtk_widget_get_window (widget);
3541
3542   g_return_if_fail (gdk_window != NULL);
3543
3544   /* no point setting an icon on override-redirect */
3545   if (priv->type == GTK_WINDOW_POPUP)
3546     return;
3547
3548   icon_list = NULL;
3549   
3550   info = ensure_icon_info (window);
3551
3552   if (info->realized)
3553     return;
3554
3555   info->using_default_icon = FALSE;
3556   info->using_parent_icon = FALSE;
3557   info->using_themed_icon = FALSE;
3558   
3559   icon_list = info->icon_list;
3560
3561   /* Look up themed icon */
3562   if (icon_list == NULL && info->icon_name) 
3563     {
3564       icon_list = icon_list_from_theme (widget, info->icon_name);
3565       if (icon_list)
3566         info->using_themed_icon = TRUE;
3567     }
3568
3569   /* Inherit from transient parent */
3570   if (icon_list == NULL && priv->transient_parent)
3571     {
3572       icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3573       if (icon_list)
3574         info->using_parent_icon = TRUE;
3575     }      
3576
3577   /* Inherit from default */
3578   if (icon_list == NULL)
3579     {
3580       icon_list = default_icon_list;
3581       if (icon_list)
3582         info->using_default_icon = TRUE;
3583     }
3584
3585   /* Look up themed icon */
3586   if (icon_list == NULL && default_icon_name) 
3587     {
3588       icon_list = icon_list_from_theme (widget, default_icon_name);
3589       info->using_default_icon = TRUE;
3590       info->using_themed_icon = TRUE;  
3591     }
3592
3593   info->realized = TRUE;
3594
3595   gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3596   
3597   if (info->using_themed_icon) 
3598     {
3599       GtkIconTheme *icon_theme;
3600
3601       g_list_free_full (icon_list, g_object_unref);
3602  
3603       icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3604       g_signal_connect (icon_theme, "changed",
3605                         G_CALLBACK (update_themed_icon), window);
3606     }
3607 }
3608
3609 static void
3610 gtk_window_unrealize_icon (GtkWindow *window)
3611 {
3612   GtkWindowIconInfo *info;
3613
3614   info = get_icon_info (window);
3615
3616   if (info == NULL)
3617     return;
3618   
3619   if (info->using_themed_icon)
3620     {
3621       GtkIconTheme *icon_theme;
3622
3623       icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3624
3625       g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3626     }
3627     
3628   /* We don't clear the properties on the window, just figure the
3629    * window is going away.
3630    */
3631
3632   info->realized = FALSE;
3633
3634 }
3635
3636 /**
3637  * gtk_window_set_icon_list:
3638  * @window: a #GtkWindow
3639  * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3640  *
3641  * Sets up the icon representing a #GtkWindow. The icon is used when
3642  * the window is minimized (also known as iconified).  Some window
3643  * managers or desktop environments may also place it in the window
3644  * frame, or display it in other contexts.
3645  *
3646  * gtk_window_set_icon_list() allows you to pass in the same icon in
3647  * several hand-drawn sizes. The list should contain the natural sizes
3648  * your icon is available in; that is, don't scale the image before
3649  * passing it to GTK+. Scaling is postponed until the last minute,
3650  * when the desired final size is known, to allow best quality.
3651  *
3652  * By passing several sizes, you may improve the final image quality
3653  * of the icon, by reducing or eliminating automatic image scaling.
3654  *
3655  * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3656  * larger images (64x64, 128x128) if you have them.
3657  *
3658  * See also gtk_window_set_default_icon_list() to set the icon
3659  * for all windows in your application in one go.
3660  *
3661  * Note that transient windows (those who have been set transient for another
3662  * window using gtk_window_set_transient_for()) will inherit their
3663  * icon from their transient parent. So there's no need to explicitly
3664  * set the icon on transient windows.
3665  **/
3666 void
3667 gtk_window_set_icon_list (GtkWindow  *window,
3668                           GList      *list)
3669 {
3670   GtkWindowIconInfo *info;
3671
3672   g_return_if_fail (GTK_IS_WINDOW (window));
3673
3674   info = ensure_icon_info (window);
3675
3676   if (info->icon_list == list) /* check for NULL mostly */
3677     return;
3678
3679   g_list_foreach (list,
3680                   (GFunc) g_object_ref, NULL);
3681
3682   g_list_free_full (info->icon_list, g_object_unref);
3683
3684   info->icon_list = g_list_copy (list);
3685
3686   g_object_notify (G_OBJECT (window), "icon");
3687   
3688   gtk_window_unrealize_icon (window);
3689   
3690   if (gtk_widget_get_realized (GTK_WIDGET (window)))
3691     gtk_window_realize_icon (window);
3692
3693   /* We could try to update our transient children, but I don't think
3694    * it's really worth it. If we did it, the best way would probably
3695    * be to have children connect to notify::icon-list
3696    */
3697 }
3698
3699 /**
3700  * gtk_window_get_icon_list:
3701  * @window: a #GtkWindow
3702  * 
3703  * Retrieves the list of icons set by gtk_window_set_icon_list().
3704  * The list is copied, but the reference count on each
3705  * member won't be incremented.
3706  *
3707  * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3708  **/
3709 GList*
3710 gtk_window_get_icon_list (GtkWindow  *window)
3711 {
3712   GtkWindowIconInfo *info;
3713   
3714   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3715
3716   info = get_icon_info (window);
3717
3718   if (info)
3719     return g_list_copy (info->icon_list);
3720   else
3721     return NULL;  
3722 }
3723
3724 /**
3725  * gtk_window_set_icon:
3726  * @window: a #GtkWindow
3727  * @icon: (allow-none): icon image, or %NULL
3728  *
3729  * Sets up the icon representing a #GtkWindow. This icon is used when
3730  * the window is minimized (also known as iconified).  Some window
3731  * managers or desktop environments may also place it in the window
3732  * frame, or display it in other contexts.
3733  *
3734  * The icon should be provided in whatever size it was naturally
3735  * drawn; that is, don't scale the image before passing it to
3736  * GTK+. Scaling is postponed until the last minute, when the desired
3737  * final size is known, to allow best quality.
3738  *
3739  * If you have your icon hand-drawn in multiple sizes, use
3740  * gtk_window_set_icon_list(). Then the best size will be used.
3741  *
3742  * This function is equivalent to calling gtk_window_set_icon_list()
3743  * with a 1-element list.
3744  *
3745  * See also gtk_window_set_default_icon_list() to set the icon
3746  * for all windows in your application in one go.
3747  **/
3748 void
3749 gtk_window_set_icon (GtkWindow  *window,
3750                      GdkPixbuf  *icon)
3751 {
3752   GList *list;
3753   
3754   g_return_if_fail (GTK_IS_WINDOW (window));
3755   g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3756
3757   list = NULL;
3758
3759   if (icon)
3760     list = g_list_append (list, icon);
3761   
3762   gtk_window_set_icon_list (window, list);
3763   g_list_free (list);  
3764 }
3765
3766
3767 static void 
3768 update_themed_icon (GtkIconTheme *icon_theme,
3769                     GtkWindow    *window)
3770 {
3771   g_object_notify (G_OBJECT (window), "icon");
3772   
3773   gtk_window_unrealize_icon (window);
3774   
3775   if (gtk_widget_get_realized (GTK_WIDGET (window)))
3776     gtk_window_realize_icon (window);  
3777 }
3778
3779 /**
3780  * gtk_window_set_icon_name:
3781  * @window: a #GtkWindow
3782  * @name: (allow-none): the name of the themed icon
3783  *
3784  * Sets the icon for the window from a named themed icon. See
3785  * the docs for #GtkIconTheme for more details.
3786  *
3787  * Note that this has nothing to do with the WM_ICON_NAME 
3788  * property which is mentioned in the ICCCM.
3789  *
3790  * Since: 2.6
3791  */
3792 void 
3793 gtk_window_set_icon_name (GtkWindow   *window,
3794                           const gchar *name)
3795 {
3796   GtkWindowIconInfo *info;
3797   gchar *tmp;
3798   
3799   g_return_if_fail (GTK_IS_WINDOW (window));
3800
3801   info = ensure_icon_info (window);
3802
3803   if (g_strcmp0 (info->icon_name, name) == 0)
3804     return;
3805
3806   tmp = info->icon_name;
3807   info->icon_name = g_strdup (name);
3808   g_free (tmp);
3809
3810   g_list_free_full (info->icon_list, g_object_unref);
3811   info->icon_list = NULL;
3812   
3813   update_themed_icon (NULL, window);
3814
3815   g_object_notify (G_OBJECT (window), "icon-name");
3816 }
3817
3818 /**
3819  * gtk_window_get_icon_name:
3820  * @window: a #GtkWindow
3821  *
3822  * Returns the name of the themed icon for the window,
3823  * see gtk_window_set_icon_name().
3824  *
3825  * Returns: the icon name or %NULL if the window has 
3826  * no themed icon
3827  *
3828  * Since: 2.6
3829  */
3830 const gchar *
3831 gtk_window_get_icon_name (GtkWindow *window)
3832 {
3833   GtkWindowIconInfo *info;
3834
3835   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3836
3837   info = ensure_icon_info (window);
3838
3839   return info->icon_name;
3840 }
3841
3842 /**
3843  * gtk_window_get_icon:
3844  * @window: a #GtkWindow
3845  * 
3846  * Gets the value set by gtk_window_set_icon() (or if you've
3847  * called gtk_window_set_icon_list(), gets the first icon in
3848  * the icon list).
3849  *
3850  * Return value: (transfer none): icon for window
3851  **/
3852 GdkPixbuf*
3853 gtk_window_get_icon (GtkWindow  *window)
3854 {
3855   GtkWindowIconInfo *info;
3856
3857   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3858
3859   info = get_icon_info (window);
3860   if (info && info->icon_list)
3861     return GDK_PIXBUF (info->icon_list->data);
3862   else
3863     return NULL;
3864 }
3865
3866 /* Load pixbuf, printing warning on failure if error == NULL
3867  */
3868 static GdkPixbuf *
3869 load_pixbuf_verbosely (const char *filename,
3870                        GError    **err)
3871 {
3872   GError *local_err = NULL;
3873   GdkPixbuf *pixbuf;
3874
3875   pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3876
3877   if (!pixbuf)
3878     {
3879       if (err)
3880         *err = local_err;
3881       else
3882         {
3883           g_warning ("Error loading icon from file '%s':\n\t%s",
3884                      filename, local_err->message);
3885           g_error_free (local_err);
3886         }
3887     }
3888
3889   return pixbuf;
3890 }
3891
3892 /**
3893  * gtk_window_set_icon_from_file:
3894  * @window: a #GtkWindow
3895  * @filename: (type filename): location of icon file
3896  * @err: (allow-none): location to store error, or %NULL.
3897  *
3898  * Sets the icon for @window.  
3899  * Warns on failure if @err is %NULL.
3900  *
3901  * This function is equivalent to calling gtk_window_set_icon()
3902  * with a pixbuf created by loading the image from @filename.
3903  *
3904  * Returns: %TRUE if setting the icon succeeded.
3905  *
3906  * Since: 2.2
3907  **/
3908 gboolean
3909 gtk_window_set_icon_from_file (GtkWindow   *window,
3910                                const gchar *filename,
3911                                GError     **err)
3912 {
3913   GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3914
3915   if (pixbuf)
3916     {
3917       gtk_window_set_icon (window, pixbuf);
3918       g_object_unref (pixbuf);
3919       
3920       return TRUE;
3921     }
3922   else
3923     return FALSE;
3924 }
3925
3926 /**
3927  * gtk_window_set_default_icon_list:
3928  * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3929  *
3930  * Sets an icon list to be used as fallback for windows that haven't
3931  * had gtk_window_set_icon_list() called on them to set up a
3932  * window-specific icon list. This function allows you to set up the
3933  * icon for all windows in your app at once.
3934  *
3935  * See gtk_window_set_icon_list() for more details.
3936  * 
3937  **/
3938 void
3939 gtk_window_set_default_icon_list (GList *list)
3940 {
3941   GList *toplevels;
3942   GList *tmp_list;
3943   if (list == default_icon_list)
3944     return;
3945
3946   /* Update serial so we don't used cached pixmaps/masks
3947    */
3948   default_icon_serial++;
3949   
3950   g_list_foreach (list,
3951                   (GFunc) g_object_ref, NULL);
3952
3953   g_list_free_full (default_icon_list, g_object_unref);
3954
3955   default_icon_list = g_list_copy (list);
3956   
3957   /* Update all toplevels */
3958   toplevels = gtk_window_list_toplevels ();
3959   tmp_list = toplevels;
3960   while (tmp_list != NULL)
3961     {
3962       GtkWindowIconInfo *info;
3963       GtkWindow *w = tmp_list->data;
3964       
3965       info = get_icon_info (w);
3966       if (info && info->using_default_icon)
3967         {
3968           gtk_window_unrealize_icon (w);
3969           if (gtk_widget_get_realized (GTK_WIDGET (w)))
3970             gtk_window_realize_icon (w);
3971         }
3972
3973       tmp_list = tmp_list->next;
3974     }
3975   g_list_free (toplevels);
3976 }
3977
3978 /**
3979  * gtk_window_set_default_icon:
3980  * @icon: the icon
3981  *
3982  * Sets an icon to be used as fallback for windows that haven't
3983  * had gtk_window_set_icon() called on them from a pixbuf.
3984  *
3985  * Since: 2.4
3986  **/
3987 void
3988 gtk_window_set_default_icon (GdkPixbuf *icon)
3989 {
3990   GList *list;
3991   
3992   g_return_if_fail (GDK_IS_PIXBUF (icon));
3993
3994   list = g_list_prepend (NULL, icon);
3995   gtk_window_set_default_icon_list (list);
3996   g_list_free (list);
3997 }
3998
3999 /**
4000  * gtk_window_set_default_icon_name:
4001  * @name: the name of the themed icon
4002  *
4003  * Sets an icon to be used as fallback for windows that haven't
4004  * had gtk_window_set_icon_list() called on them from a named
4005  * themed icon, see gtk_window_set_icon_name().
4006  *
4007  * Since: 2.6
4008  **/
4009 void
4010 gtk_window_set_default_icon_name (const gchar *name)
4011 {
4012   GList *tmp_list;
4013   GList *toplevels;
4014
4015   /* Update serial so we don't used cached pixmaps/masks
4016    */
4017   default_icon_serial++;
4018
4019   g_free (default_icon_name);
4020   default_icon_name = g_strdup (name);
4021
4022   g_list_free_full (default_icon_list, g_object_unref);
4023   default_icon_list = NULL;
4024   
4025   /* Update all toplevels */
4026   toplevels = gtk_window_list_toplevels ();
4027   tmp_list = toplevels;
4028   while (tmp_list != NULL)
4029     {
4030       GtkWindowIconInfo *info;
4031       GtkWindow *w = tmp_list->data;
4032       
4033       info = get_icon_info (w);
4034       if (info && info->using_default_icon && info->using_themed_icon)
4035         {
4036           gtk_window_unrealize_icon (w);
4037           if (gtk_widget_get_realized (GTK_WIDGET (w)))
4038             gtk_window_realize_icon (w);
4039         }
4040
4041       tmp_list = tmp_list->next;
4042     }
4043   g_list_free (toplevels);
4044 }
4045
4046 /**
4047  * gtk_window_get_default_icon_name:
4048  *
4049  * Returns the fallback icon name for windows that has been set
4050  * with gtk_window_set_default_icon_name(). The returned
4051  * string is owned by GTK+ and should not be modified. It
4052  * is only valid until the next call to
4053  * gtk_window_set_default_icon_name().
4054  *
4055  * Returns: the fallback icon name for windows
4056  *
4057  * Since: 2.16
4058  */
4059 const gchar *
4060 gtk_window_get_default_icon_name (void)
4061 {
4062   return default_icon_name;
4063 }
4064
4065 /**
4066  * gtk_window_set_default_icon_from_file:
4067  * @filename: (type filename): location of icon file
4068  * @err: (allow-none): location to store error, or %NULL.
4069  *
4070  * Sets an icon to be used as fallback for windows that haven't
4071  * had gtk_window_set_icon_list() called on them from a file
4072  * on disk. Warns on failure if @err is %NULL.
4073  *
4074  * Returns: %TRUE if setting the icon succeeded.
4075  *
4076  * Since: 2.2
4077  **/
4078 gboolean
4079 gtk_window_set_default_icon_from_file (const gchar *filename,
4080                                        GError     **err)
4081 {
4082   GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
4083
4084   if (pixbuf)
4085     {
4086       gtk_window_set_default_icon (pixbuf);
4087       g_object_unref (pixbuf);
4088       
4089       return TRUE;
4090     }
4091   else
4092     return FALSE;
4093 }
4094
4095 /**
4096  * gtk_window_get_default_icon_list:
4097  * 
4098  * Gets the value set by gtk_window_set_default_icon_list().
4099  * The list is a copy and should be freed with g_list_free(),
4100  * but the pixbufs in the list have not had their reference count
4101  * incremented.
4102  * 
4103  * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list 
4104  **/
4105 GList*
4106 gtk_window_get_default_icon_list (void)
4107 {
4108   return g_list_copy (default_icon_list);
4109 }
4110
4111 static void
4112 gtk_window_set_default_size_internal (GtkWindow    *window,
4113                                       gboolean      change_width,
4114                                       gint          width,
4115                                       gboolean      change_height,
4116                                       gint          height,
4117                                       gboolean      is_geometry)
4118 {
4119   GtkWindowGeometryInfo *info;
4120
4121   g_return_if_fail (change_width == FALSE || width >= -1);
4122   g_return_if_fail (change_height == FALSE || height >= -1);
4123
4124   info = gtk_window_get_geometry_info (window, TRUE);
4125
4126   g_object_freeze_notify (G_OBJECT (window));
4127
4128   info->default_is_geometry = is_geometry != FALSE;
4129
4130   if (change_width)
4131     {
4132       if (width == 0)
4133         width = 1;
4134
4135       if (width < 0)
4136         width = -1;
4137
4138       info->default_width = width;
4139
4140       g_object_notify (G_OBJECT (window), "default-width");
4141     }
4142
4143   if (change_height)
4144     {
4145       if (height == 0)
4146         height = 1;
4147
4148       if (height < 0)
4149         height = -1;
4150
4151       info->default_height = height;
4152       
4153       g_object_notify (G_OBJECT (window), "default-height");
4154     }
4155   
4156   g_object_thaw_notify (G_OBJECT (window));
4157   
4158   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4159 }
4160
4161 /**
4162  * gtk_window_set_default_size:
4163  * @window: a #GtkWindow
4164  * @width: width in pixels, or -1 to unset the default width
4165  * @height: height in pixels, or -1 to unset the default height
4166  *
4167  * Sets the default size of a window. If the window's "natural" size
4168  * (its size request) is larger than the default, the default will be
4169  * ignored. More generally, if the default size does not obey the
4170  * geometry hints for the window (gtk_window_set_geometry_hints() can
4171  * be used to set these explicitly), the default size will be clamped
4172  * to the nearest permitted size.
4173  * 
4174  * Unlike gtk_widget_set_size_request(), which sets a size request for
4175  * a widget and thus would keep users from shrinking the window, this
4176  * function only sets the initial size, just as if the user had
4177  * resized the window themselves. Users can still shrink the window
4178  * again as they normally would. Setting a default size of -1 means to
4179  * use the "natural" default size (the size request of the window).
4180  *
4181  * For more control over a window's initial size and how resizing works,
4182  * investigate gtk_window_set_geometry_hints().
4183  *
4184  * For some uses, gtk_window_resize() is a more appropriate function.
4185  * gtk_window_resize() changes the current size of the window, rather
4186  * than the size to be used on initial display. gtk_window_resize() always
4187  * affects the window itself, not the geometry widget.
4188  *
4189  * The default size of a window only affects the first time a window is
4190  * shown; if a window is hidden and re-shown, it will remember the size
4191  * it had prior to hiding, rather than using the default size.
4192  *
4193  * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4194  * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4195  **/
4196 void       
4197 gtk_window_set_default_size (GtkWindow   *window,
4198                              gint         width,
4199                              gint         height)
4200 {
4201   g_return_if_fail (GTK_IS_WINDOW (window));
4202   g_return_if_fail (width >= -1);
4203   g_return_if_fail (height >= -1);
4204
4205   gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4206 }
4207
4208 /**
4209  * gtk_window_set_default_geometry:
4210  * @window: a #GtkWindow
4211  * @width: width in resize increments, or -1 to unset the default width
4212  * @height: height in resize increments, or -1 to unset the default height
4213  *
4214  * Like gtk_window_set_default_size(), but @width and @height are interpreted
4215  * in terms of the base size and increment set with
4216  * gtk_window_set_geometry_hints.
4217  *
4218  * Since: 3.0
4219  */
4220 void
4221 gtk_window_set_default_geometry (GtkWindow *window,
4222                                  gint       width,
4223                                  gint       height)
4224 {
4225   g_return_if_fail (GTK_IS_WINDOW (window));
4226   g_return_if_fail (width >= -1);
4227   g_return_if_fail (height >= -1);
4228
4229   gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4230 }
4231
4232 /**
4233  * gtk_window_get_default_size:
4234  * @window: a #GtkWindow
4235  * @width: (out) (allow-none): location to store the default width, or %NULL
4236  * @height: (out) (allow-none): location to store the default height, or %NULL
4237  *
4238  * Gets the default size of the window. A value of -1 for the width or
4239  * height indicates that a default size has not been explicitly set
4240  * for that dimension, so the "natural" size of the window will be
4241  * used.
4242  * 
4243  **/
4244 void
4245 gtk_window_get_default_size (GtkWindow *window,
4246                              gint      *width,
4247                              gint      *height)
4248 {
4249   GtkWindowGeometryInfo *info;
4250
4251   g_return_if_fail (GTK_IS_WINDOW (window));
4252
4253   info = gtk_window_get_geometry_info (window, FALSE);
4254
4255   if (width)
4256     *width = info ? info->default_width : -1;
4257
4258   if (height)
4259     *height = info ? info->default_height : -1;
4260 }
4261
4262 /**
4263  * gtk_window_resize:
4264  * @window: a #GtkWindow
4265  * @width: width in pixels to resize the window to
4266  * @height: height in pixels to resize the window to
4267  *
4268  * Resizes the window as if the user had done so, obeying geometry
4269  * constraints. The default geometry constraint is that windows may
4270  * not be smaller than their size request; to override this
4271  * constraint, call gtk_widget_set_size_request() to set the window's
4272  * request to a smaller value.
4273  *
4274  * If gtk_window_resize() is called before showing a window for the
4275  * first time, it overrides any default size set with
4276  * gtk_window_set_default_size().
4277  *
4278  * Windows may not be resized smaller than 1 by 1 pixels.
4279  * 
4280  **/
4281 void
4282 gtk_window_resize (GtkWindow *window,
4283                    gint       width,
4284                    gint       height)
4285 {
4286   GtkWindowGeometryInfo *info;
4287   
4288   g_return_if_fail (GTK_IS_WINDOW (window));
4289   g_return_if_fail (width > 0);
4290   g_return_if_fail (height > 0);
4291
4292   info = gtk_window_get_geometry_info (window, TRUE);
4293
4294   info->resize_width = width;
4295   info->resize_height = height;
4296   info->resize_is_geometry = FALSE;
4297
4298   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4299 }
4300
4301 /**
4302  * gtk_window_resize_to_geometry:
4303  * @window: a #GtkWindow
4304  * @width: width in resize increments to resize the window to
4305  * @height: height in resize increments to resize the window to
4306  *
4307  * Like gtk_window_resize(), but @width and @height are interpreted
4308  * in terms of the base size and increment set with
4309  * gtk_window_set_geometry_hints.
4310  *
4311  * Since: 3.0
4312  */
4313 void
4314 gtk_window_resize_to_geometry (GtkWindow *window,
4315                                gint       width,
4316                                gint       height)
4317 {
4318   GtkWindowGeometryInfo *info;
4319
4320   g_return_if_fail (GTK_IS_WINDOW (window));
4321   g_return_if_fail (width > 0);
4322   g_return_if_fail (height > 0);
4323
4324   info = gtk_window_get_geometry_info (window, TRUE);
4325
4326   info->resize_width = width;
4327   info->resize_height = height;
4328   info->resize_is_geometry = TRUE;
4329
4330   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4331 }
4332
4333 /**
4334  * gtk_window_get_size:
4335  * @window: a #GtkWindow
4336  * @width: (out) (allow-none): return location for width, or %NULL
4337  * @height: (out) (allow-none): return location for height, or %NULL
4338  *
4339  * Obtains the current size of @window. If @window is not onscreen,
4340  * it returns the size GTK+ will suggest to the <link
4341  * linkend="gtk-X11-arch">window manager</link> for the initial window
4342  * size (but this is not reliably the same as the size the window
4343  * manager will actually select). The size obtained by
4344  * gtk_window_get_size() is the last size received in a
4345  * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4346  * rather than querying the X server for the size. As a result, if you
4347  * call gtk_window_resize() then immediately call
4348  * gtk_window_get_size(), the size won't have taken effect yet. After
4349  * the window manager processes the resize request, GTK+ receives
4350  * notification that the size has changed via a configure event, and
4351  * the size of the window gets updated.
4352  *
4353  * Note 1: Nearly any use of this function creates a race condition,
4354  * because the size of the window may change between the time that you
4355  * get the size and the time that you perform some action assuming
4356  * that size is the current size. To avoid race conditions, connect to
4357  * "configure-event" on the window and adjust your size-dependent
4358  * state to match the size delivered in the #GdkEventConfigure.
4359  *
4360  * Note 2: The returned size does <emphasis>not</emphasis> include the
4361  * size of the window manager decorations (aka the window frame or
4362  * border). Those are not drawn by GTK+ and GTK+ has no reliable
4363  * method of determining their size.
4364  *
4365  * Note 3: If you are getting a window size in order to position
4366  * the window onscreen, there may be a better way. The preferred
4367  * way is to simply set the window's semantic type with
4368  * gtk_window_set_type_hint(), which allows the window manager to
4369  * e.g. center dialogs. Also, if you set the transient parent of
4370  * dialogs with gtk_window_set_transient_for() window managers
4371  * will often center the dialog over its parent window. It's
4372  * much preferred to let the window manager handle these
4373  * things rather than doing it yourself, because all apps will
4374  * behave consistently and according to user prefs if the window
4375  * manager handles it. Also, the window manager can take the size
4376  * of the window decorations/border into account, while your
4377  * application cannot.
4378  *
4379  * In any case, if you insist on application-specified window
4380  * positioning, there's <emphasis>still</emphasis> a better way than
4381  * doing it yourself - gtk_window_set_position() will frequently
4382  * handle the details for you.
4383  * 
4384  **/
4385 void
4386 gtk_window_get_size (GtkWindow *window,
4387                      gint      *width,
4388                      gint      *height)
4389 {
4390   gint w, h;
4391   
4392   g_return_if_fail (GTK_IS_WINDOW (window));
4393
4394   if (width == NULL && height == NULL)
4395     return;
4396
4397   if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4398     {
4399       w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4400       h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4401     }
4402   else
4403     {
4404       GdkRectangle configure_request;
4405
4406       gtk_window_compute_configure_request (window,
4407                                             &configure_request,
4408                                             NULL, NULL);
4409
4410       w = configure_request.width;
4411       h = configure_request.height;
4412     }
4413   
4414   if (width)
4415     *width = w;
4416   if (height)
4417     *height = h;
4418 }
4419
4420 /**
4421  * gtk_window_move:
4422  * @window: a #GtkWindow
4423  * @x: X coordinate to move window to
4424  * @y: Y coordinate to move window to
4425  *
4426  * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4427  * @window to the given position.  Window managers are free to ignore
4428  * this; most window managers ignore requests for initial window
4429  * positions (instead using a user-defined placement algorithm) and
4430  * honor requests after the window has already been shown.
4431  *
4432  * Note: the position is the position of the gravity-determined
4433  * reference point for the window. The gravity determines two things:
4434  * first, the location of the reference point in root window
4435  * coordinates; and second, which point on the window is positioned at
4436  * the reference point.
4437  *
4438  * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4439  * point is simply the @x, @y supplied to gtk_window_move(). The
4440  * top-left corner of the window decorations (aka window frame or
4441  * border) will be placed at @x, @y.  Therefore, to position a window
4442  * at the top left of the screen, you want to use the default gravity
4443  * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4444  *
4445  * To position a window at the bottom right corner of the screen, you
4446  * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4447  * point is at @x + the window width and @y + the window height, and
4448  * the bottom-right corner of the window border will be placed at that
4449  * reference point. So, to place a window in the bottom right corner
4450  * you would first set gravity to south east, then write:
4451  * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4452  * gdk_screen_height () - window_height)</literal> (note that this
4453  * example does not take multi-head scenarios into account).
4454  *
4455  * The Extended Window Manager Hints specification at <ulink
4456  * url="http://www.freedesktop.org/Standards/wm-spec">
4457  * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4458  * nice table of gravities in the "implementation notes" section.
4459  *
4460  * The gtk_window_get_position() documentation may also be relevant.
4461  */
4462 void
4463 gtk_window_move (GtkWindow *window,
4464                  gint       x,
4465                  gint       y)
4466 {
4467   GtkWindowGeometryInfo *info;
4468   GtkWidget *widget;
4469
4470   g_return_if_fail (GTK_IS_WINDOW (window));
4471
4472   widget = GTK_WIDGET (window);
4473
4474   info = gtk_window_get_geometry_info (window, TRUE);  
4475
4476   if (gtk_widget_get_mapped (widget))
4477     {
4478       GtkAllocation allocation;
4479
4480       gtk_widget_get_allocation (widget, &allocation);
4481
4482       /* we have now sent a request with this position
4483        * with currently-active constraints, so toggle flag.
4484        */
4485       info->position_constraints_changed = FALSE;
4486
4487       /* we only constrain if mapped - if not mapped,
4488        * then gtk_window_compute_configure_request()
4489        * will apply the constraints later, and we
4490        * don't want to lose information about
4491        * what position the user set before then.
4492        * i.e. if you do a move() then turn off POS_CENTER
4493        * then show the window, your move() will work.
4494        */
4495       gtk_window_constrain_position (window,
4496                                      allocation.width, allocation.height,
4497                                      &x, &y);
4498
4499       /* Note that this request doesn't go through our standard request
4500        * framework, e.g. doesn't increment configure_request_count,
4501        * doesn't set info->last, etc.; that's because
4502        * we don't save the info needed to arrive at this same request
4503        * again.
4504        *
4505        * To gtk_window_move_resize(), this will end up looking exactly
4506        * the same as the position being changed by the window
4507        * manager.
4508        */
4509       gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4510     }
4511   else
4512     {
4513       /* Save this position to apply on mapping */
4514       info->initial_x = x;
4515       info->initial_y = y;
4516       info->initial_pos_set = TRUE;
4517     }
4518 }
4519
4520 /**
4521  * gtk_window_get_position:
4522  * @window: a #GtkWindow
4523  * @root_x: (out) (allow-none): return location for X coordinate of
4524  *     gravity-determined reference point, or %NULL
4525  * @root_y: (out) (allow-none): return location for Y coordinate of
4526  *     gravity-determined reference point, or %NULL
4527  *
4528  * This function returns the position you need to pass to
4529  * gtk_window_move() to keep @window in its current position.
4530  * This means that the meaning of the returned value varies with
4531  * window gravity. See gtk_window_move() for more details.
4532  *
4533  * If you haven't changed the window gravity, its gravity will be
4534  * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4535  * gets the position of the top-left corner of the window manager
4536  * frame for the window. gtk_window_move() sets the position of this
4537  * same top-left corner.
4538  *
4539  * gtk_window_get_position() is not 100% reliable because the X Window System
4540  * does not specify a way to obtain the geometry of the
4541  * decorations placed on a window by the window manager.
4542  * Thus GTK+ is using a "best guess" that works with most
4543  * window managers.
4544  *
4545  * Moreover, nearly all window managers are historically broken with
4546  * respect to their handling of window gravity. So moving a window to
4547  * its current position as returned by gtk_window_get_position() tends
4548  * to result in moving the window slightly. Window managers are
4549  * slowly getting better over time.
4550  *
4551  * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4552  * frame is not relevant, and thus gtk_window_get_position() will
4553  * always produce accurate results. However you can't use static
4554  * gravity to do things like place a window in a corner of the screen,
4555  * because static gravity ignores the window manager decorations.
4556  *
4557  * If you are saving and restoring your application's window
4558  * positions, you should know that it's impossible for applications to
4559  * do this without getting it somewhat wrong because applications do
4560  * not have sufficient knowledge of window manager state. The Correct
4561  * Mechanism is to support the session management protocol (see the
4562  * "GnomeClient" object in the GNOME libraries for example) and allow
4563  * the window manager to save your window sizes and positions.
4564  * 
4565  **/
4566
4567 void
4568 gtk_window_get_position (GtkWindow *window,
4569                          gint      *root_x,
4570                          gint      *root_y)
4571 {
4572   GtkWindowPrivate *priv;
4573   GtkWidget *widget;
4574   GdkWindow *gdk_window;
4575
4576   g_return_if_fail (GTK_IS_WINDOW (window));
4577
4578   priv = window->priv;
4579   widget = GTK_WIDGET (window);
4580   gdk_window = gtk_widget_get_window (widget);
4581
4582   if (priv->gravity == GDK_GRAVITY_STATIC)
4583     {
4584       if (gtk_widget_get_mapped (widget))
4585         {
4586           /* This does a server round-trip, which is sort of wrong;
4587            * but a server round-trip is inevitable for
4588            * gdk_window_get_frame_extents() in the usual
4589            * NorthWestGravity case below, so not sure what else to
4590            * do. We should likely be consistent about whether we get
4591            * the client-side info or the server-side info.
4592            */
4593           gdk_window_get_origin (gdk_window, root_x, root_y);
4594         }
4595       else
4596         {
4597           GdkRectangle configure_request;
4598           
4599           gtk_window_compute_configure_request (window,
4600                                                 &configure_request,
4601                                                 NULL, NULL);
4602           
4603           *root_x = configure_request.x;
4604           *root_y = configure_request.y;
4605         }
4606     }
4607   else
4608     {
4609       GdkRectangle frame_extents;
4610       
4611       gint x, y;
4612       gint w, h;
4613       
4614       if (gtk_widget_get_mapped (widget))
4615         {
4616           gdk_window_get_frame_extents (gdk_window, &frame_extents);
4617           x = frame_extents.x;
4618           y = frame_extents.y;
4619           gtk_window_get_size (window, &w, &h);
4620         }
4621       else
4622         {
4623           /* We just say the frame has 0 size on all sides.
4624            * Not sure what else to do.
4625            */
4626           gtk_window_compute_configure_request (window,
4627                                                 &frame_extents,
4628                                                 NULL, NULL);
4629           x = frame_extents.x;
4630           y = frame_extents.y;
4631           w = frame_extents.width;
4632           h = frame_extents.height;
4633         }
4634       
4635       switch (priv->gravity)
4636         {
4637         case GDK_GRAVITY_NORTH:
4638         case GDK_GRAVITY_CENTER:
4639         case GDK_GRAVITY_SOUTH:
4640           /* Find center of frame. */
4641           x += frame_extents.width / 2;
4642           /* Center client window on that point. */
4643           x -= w / 2;
4644           break;
4645
4646         case GDK_GRAVITY_SOUTH_EAST:
4647         case GDK_GRAVITY_EAST:
4648         case GDK_GRAVITY_NORTH_EAST:
4649           /* Find right edge of frame */
4650           x += frame_extents.width;
4651           /* Align left edge of client at that point. */
4652           x -= w;
4653           break;
4654         default:
4655           break;
4656         }
4657
4658       switch (priv->gravity)
4659         {
4660         case GDK_GRAVITY_WEST:
4661         case GDK_GRAVITY_CENTER:
4662         case GDK_GRAVITY_EAST:
4663           /* Find center of frame. */
4664           y += frame_extents.height / 2;
4665           /* Center client window there. */
4666           y -= h / 2;
4667           break;
4668         case GDK_GRAVITY_SOUTH_WEST:
4669         case GDK_GRAVITY_SOUTH:
4670         case GDK_GRAVITY_SOUTH_EAST:
4671           /* Find south edge of frame */
4672           y += frame_extents.height;
4673           /* Place bottom edge of client there */
4674           y -= h;
4675           break;
4676         default:
4677           break;
4678         }
4679       
4680       if (root_x)
4681         *root_x = x;
4682       if (root_y)
4683         *root_y = y;
4684     }
4685 }
4686
4687 /**
4688  * gtk_window_reshow_with_initial_size:
4689  * @window: a #GtkWindow
4690  * 
4691  * Hides @window, then reshows it, resetting the
4692  * default size and position of the window. Used
4693  * by GUI builders only.
4694  **/
4695 void
4696 gtk_window_reshow_with_initial_size (GtkWindow *window)
4697 {
4698   GtkWidget *widget;
4699   
4700   g_return_if_fail (GTK_IS_WINDOW (window));
4701
4702   widget = GTK_WIDGET (window);
4703   
4704   gtk_widget_hide (widget);
4705   gtk_widget_unrealize (widget);
4706   gtk_widget_show (widget);
4707 }
4708
4709 static void
4710 gtk_window_destroy (GtkWidget *widget)
4711 {
4712   GtkWindow *window = GTK_WINDOW (widget);
4713   GtkWindowPrivate *priv = window->priv;
4714
4715   gtk_window_release_application (window);
4716
4717   toplevel_list = g_slist_remove (toplevel_list, window);
4718
4719   if (priv->transient_parent)
4720     gtk_window_set_transient_for (window, NULL);
4721
4722   remove_attach_widget (GTK_WINDOW (widget));
4723
4724   /* frees the icons */
4725   gtk_window_set_icon_list (window, NULL);
4726
4727   if (priv->has_user_ref_count)
4728     {
4729       priv->has_user_ref_count = FALSE;
4730       g_object_unref (window);
4731     }
4732
4733   if (priv->group)
4734     gtk_window_group_remove_window (priv->group, window);
4735
4736    gtk_window_free_key_hash (window);
4737
4738   GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4739 }
4740
4741 static void
4742 gtk_window_finalize (GObject *object)
4743 {
4744   GtkWindow *window = GTK_WINDOW (object);
4745   GtkWindowPrivate *priv = window->priv;
4746   GtkMnemonicHash *mnemonic_hash;
4747
4748   g_free (priv->title);
4749   g_free (priv->wmclass_name);
4750   g_free (priv->wmclass_class);
4751   g_free (priv->wm_role);
4752   gtk_window_release_application (window);
4753
4754   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4755   if (mnemonic_hash)
4756     _gtk_mnemonic_hash_free (mnemonic_hash);
4757
4758   if (priv->geometry_info)
4759     {
4760       if (priv->geometry_info->widget)
4761         g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4762                                               gtk_widget_destroyed,
4763                                               &priv->geometry_info->widget);
4764       g_free (priv->geometry_info);
4765     }
4766
4767   if (priv->keys_changed_handler)
4768     {
4769       g_source_remove (priv->keys_changed_handler);
4770       priv->keys_changed_handler = 0;
4771     }
4772
4773   if (priv->screen)
4774     g_signal_handlers_disconnect_by_func (priv->screen,
4775                                           gtk_window_on_composited_changed, window);
4776
4777   g_free (priv->startup_id);
4778
4779 #ifdef GDK_WINDOWING_X11
4780   g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4781                                         gtk_window_on_theme_variant_changed,
4782                                         window);
4783 #endif
4784
4785   G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4786 }
4787
4788 static void
4789 gtk_window_show (GtkWidget *widget)
4790 {
4791   GtkWindow *window = GTK_WINDOW (widget);
4792   GtkWindowPrivate *priv = window->priv;
4793   GtkContainer *container = GTK_CONTAINER (window);
4794   gboolean need_resize;
4795   gboolean is_plug;
4796
4797   if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4798     {
4799       GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4800       return;
4801     }
4802
4803   _gtk_widget_set_visible_flag (widget, TRUE);
4804
4805   need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4806   _gtk_container_set_need_resize (container, FALSE);
4807
4808   if (need_resize)
4809     {
4810       GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4811       GtkAllocation allocation = { 0, 0 };
4812       GdkRectangle configure_request;
4813       GdkGeometry new_geometry;
4814       guint new_flags;
4815       gboolean was_realized;
4816
4817       /* We are going to go ahead and perform this configure request
4818        * and then emulate a configure notify by going ahead and
4819        * doing a size allocate. Sort of a synchronous
4820        * mini-copy of gtk_window_move_resize() here.
4821        */
4822       gtk_window_compute_configure_request (window,
4823                                             &configure_request,
4824                                             &new_geometry,
4825                                             &new_flags);
4826       
4827       /* We update this because we are going to go ahead
4828        * and gdk_window_resize() below, rather than
4829        * queuing it.
4830        */
4831       info->last.configure_request.width = configure_request.width;
4832       info->last.configure_request.height = configure_request.height;
4833       
4834       /* and allocate the window - this is normally done
4835        * in move_resize in response to configure notify
4836        */
4837       allocation.width  = configure_request.width;
4838       allocation.height = configure_request.height;
4839       gtk_widget_size_allocate (widget, &allocation);
4840
4841       /* Then we guarantee we have a realize */
4842       was_realized = FALSE;
4843       if (!gtk_widget_get_realized (widget))
4844         {
4845           gtk_widget_realize (widget);
4846           was_realized = TRUE;
4847         }
4848
4849       /* We only send configure request if we didn't just finish
4850        * creating the window; if we just created the window
4851        * then we created it with widget->allocation anyhow.
4852        */
4853       if (!was_realized)
4854         gdk_window_move_resize (gtk_widget_get_window (widget),
4855                                 configure_request.x,
4856                                 configure_request.y,
4857                                 configure_request.width,
4858                                 configure_request.height);
4859     }
4860   
4861   gtk_container_check_resize (container);
4862
4863   gtk_widget_map (widget);
4864
4865   /* Try to make sure that we have some focused widget
4866    */
4867 #ifdef GDK_WINDOWING_X11
4868   is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4869     GTK_IS_PLUG (window);
4870 #else
4871   is_plug = FALSE;
4872 #endif
4873   if (!priv->focus_widget && !is_plug)
4874     gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4875   
4876   if (priv->modal)
4877     gtk_grab_add (widget);
4878 }
4879
4880 static void
4881 gtk_window_hide (GtkWidget *widget)
4882 {
4883   GtkWindow *window = GTK_WINDOW (widget);
4884   GtkWindowPrivate *priv = window->priv;
4885
4886   if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4887     {
4888       GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4889       return;
4890     }
4891
4892   _gtk_widget_set_visible_flag (widget, FALSE);
4893   gtk_widget_unmap (widget);
4894
4895   if (priv->modal)
4896     gtk_grab_remove (widget);
4897 }
4898
4899 static void
4900 gtk_window_map (GtkWidget *widget)
4901 {
4902   GtkWidget *child;
4903   GtkWindow *window = GTK_WINDOW (widget);
4904   GtkWindowPrivate *priv = window->priv;
4905   GdkWindow *gdk_window;
4906   gboolean auto_mnemonics;
4907   GtkPolicyType visible_focus;
4908
4909   if (!gtk_widget_is_toplevel (widget))
4910     {
4911       GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4912       return;
4913     }
4914
4915   gtk_widget_set_mapped (widget, TRUE);
4916
4917   child = gtk_bin_get_child (&(window->bin));
4918   if (child &&
4919       gtk_widget_get_visible (child) &&
4920       !gtk_widget_get_mapped (child))
4921     gtk_widget_map (child);
4922
4923   gdk_window = gtk_widget_get_window (widget);
4924
4925   if (priv->maximize_initially)
4926     gdk_window_maximize (gdk_window);
4927   else
4928     gdk_window_unmaximize (gdk_window);
4929
4930   if (priv->stick_initially)
4931     gdk_window_stick (gdk_window);
4932   else
4933     gdk_window_unstick (gdk_window);
4934
4935   if (priv->iconify_initially)
4936     gdk_window_iconify (gdk_window);
4937   else
4938     gdk_window_deiconify (gdk_window);
4939
4940   if (priv->fullscreen_initially)
4941     gdk_window_fullscreen (gdk_window);
4942   else
4943     gdk_window_unfullscreen (gdk_window);
4944
4945   gdk_window_set_keep_above (gdk_window, priv->above_initially);
4946
4947   gdk_window_set_keep_below (gdk_window, priv->below_initially);
4948
4949   if (priv->type == GTK_WINDOW_TOPLEVEL)
4950     {
4951       gtk_window_set_theme_variant (window);
4952       gtk_window_set_hide_titlebar_when_maximized (window,
4953                                                    priv->hide_titlebar_when_maximized);
4954     }
4955
4956   /* No longer use the default settings */
4957   priv->need_default_size = FALSE;
4958   priv->need_default_position = FALSE;
4959
4960   if (priv->reset_type_hint)
4961     {
4962       /* We should only reset the type hint when the application
4963        * used gtk_window_set_type_hint() to change the hint.
4964        * Some applications use X directly to change the properties;
4965        * in that case, we shouldn't overwrite what they did.
4966        */
4967       gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4968       priv->reset_type_hint = FALSE;
4969     }
4970
4971   gdk_window_show (gdk_window);
4972
4973   if (priv->grip_window)
4974     gdk_window_show (priv->grip_window);
4975
4976   if (!disable_startup_notification)
4977     {
4978       /* Do we have a custom startup-notification id? */
4979       if (priv->startup_id != NULL)
4980         {
4981           /* Make sure we have a "real" id */
4982           if (!startup_id_is_fake (priv->startup_id))
4983             gdk_notify_startup_complete_with_id (priv->startup_id);
4984
4985           g_free (priv->startup_id);
4986           priv->startup_id = NULL;
4987         }
4988       else if (!sent_startup_notification)
4989         {
4990           sent_startup_notification = TRUE;
4991           gdk_notify_startup_complete ();
4992         }
4993     }
4994
4995   /* if auto-mnemonics is enabled and mnemonics visible is not already set
4996    * (as in the case of popup menus), then hide mnemonics initially
4997    */
4998   g_object_get (gtk_widget_get_settings (widget),
4999                 "gtk-auto-mnemonics", &auto_mnemonics,
5000                 "gtk-visible-focus", &visible_focus,
5001                 NULL);
5002
5003   if (auto_mnemonics && !priv->mnemonics_visible_set)
5004     gtk_window_set_mnemonics_visible (window, FALSE);
5005
5006   /* inherit from transient parent, so that a dialog that is
5007    * opened via keynav shows focus initially
5008    */
5009   if (priv->transient_parent)
5010     gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
5011   else
5012     gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
5013
5014   ensure_state_flag_backdrop (widget);
5015 }
5016
5017 static gboolean
5018 gtk_window_map_event (GtkWidget   *widget,
5019                       GdkEventAny *event)
5020 {
5021   if (!gtk_widget_get_mapped (widget))
5022     {
5023       /* we should be be unmapped, but are getting a MapEvent, this may happen
5024        * to toplevel XWindows if mapping was intercepted by a window manager
5025        * and an unmap request occoured while the MapRequestEvent was still
5026        * being handled. we work around this situaiton here by re-requesting
5027        * the window being unmapped. more details can be found in:
5028        *   http://bugzilla.gnome.org/show_bug.cgi?id=316180
5029        */
5030       gdk_window_hide (gtk_widget_get_window (widget));
5031     }
5032   return FALSE;
5033 }
5034
5035 static void
5036 gtk_window_unmap (GtkWidget *widget)
5037 {
5038   GtkWindow *window = GTK_WINDOW (widget);
5039   GtkWindowPrivate *priv = window->priv;
5040   GtkWidget *child;
5041   GtkWindowGeometryInfo *info;
5042   GdkWindow *gdk_window;
5043   GdkWindowState state;
5044
5045   if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5046     {
5047       GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
5048       return;
5049     }
5050
5051   gdk_window = gtk_widget_get_window (widget);
5052
5053   gtk_widget_set_mapped (widget, FALSE);
5054   gdk_window_withdraw (gdk_window);
5055
5056   priv->configure_request_count = 0;
5057   priv->configure_notify_received = FALSE;
5058
5059   /* on unmap, we reset the default positioning of the window,
5060    * so it's placed again, but we don't reset the default
5061    * size of the window, so it's remembered.
5062    */
5063   priv->need_default_position = TRUE;
5064
5065   info = gtk_window_get_geometry_info (window, FALSE);
5066   if (info)
5067     {
5068       info->initial_pos_set = FALSE;
5069       info->position_constraints_changed = FALSE;
5070     }
5071
5072   state = gdk_window_get_state (gdk_window);
5073   priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
5074   priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
5075   priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
5076   priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
5077   priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
5078
5079   child = gtk_bin_get_child (&(window->bin));
5080   if (child)
5081     gtk_widget_unmap (child);
5082 }
5083
5084 /* (Note: Replace "size" with "width" or "height". Also, the request
5085  * mode is honoured.)
5086  * For selecting the default window size, the following conditions
5087  * should hold (in order of importance):
5088  * - the size is not below the minimum size
5089  *   Windows cannot be resized below their minimum size, so we must
5090  *   ensure we don't do that either.
5091  * - the size is not above the natural size
5092  *   It seems weird to allocate more than this in an initial guess.
5093  * - the size does not exceed that of a maximized window
5094  *   We want to see the whole window after all.
5095  *   (Note that this may not be possible to achieve due to imperfect
5096  *    information from the windowing system.)
5097  */
5098
5099 /* We use these for now to not make windows too big by accident. Note
5100  * that we still clamp these numbers by screen size. Also note that
5101  * minimum size still overrides this. So keep your windows small! :)
5102  */
5103 #define MAX_DEFAULT_WINDOW_WIDTH 640
5104 #define MAX_DEFAULT_WINDOW_HEIGHT 480
5105
5106 static void
5107 gtk_window_guess_default_size (GtkWindow *window,
5108                                gint      *width,
5109                                gint      *height)
5110 {
5111   GtkWidget *widget = GTK_WIDGET (window);
5112   GdkScreen *screen;
5113   int minimum, natural;
5114
5115   screen = gtk_widget_get_screen (widget);
5116
5117   *width = gdk_screen_get_width (screen);
5118   *height = gdk_screen_get_height (screen);
5119
5120   if (*width >= *height)
5121     {
5122       /* landscape */
5123       *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
5124       *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
5125     }
5126   else
5127     {
5128       /* portrait */
5129       *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
5130       *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
5131     }
5132
5133   if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
5134     {
5135       gtk_widget_get_preferred_height (widget, &minimum, &natural);
5136       *height = MAX (minimum, MIN (*height, natural));
5137
5138       gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
5139       *width = MAX (minimum, MIN (*width, natural));
5140     }
5141   else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
5142     {
5143       gtk_widget_get_preferred_width (widget, &minimum, &natural);
5144       *width = MAX (minimum, MIN (*width, natural));
5145
5146       gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
5147       *height = MAX (minimum, MIN (*height, natural));
5148     }
5149 }
5150
5151 static void
5152 gtk_window_realize (GtkWidget *widget)
5153 {
5154   GtkAllocation allocation;
5155   GtkWindow *window;
5156   GdkWindow *parent_window;
5157   GdkWindow *gdk_window;
5158   GdkWindowAttr attributes;
5159   gint attributes_mask;
5160   GtkWindowPrivate *priv;
5161   GtkStyleContext *context;
5162
5163   window = GTK_WINDOW (widget);
5164   priv = window->priv;
5165
5166   gtk_widget_get_allocation (widget, &allocation);
5167
5168   if (gtk_widget_get_parent_window (widget))
5169     {
5170       gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
5171
5172       gtk_widget_set_realized (widget, TRUE);
5173
5174       attributes.x = allocation.x;
5175       attributes.y = allocation.y;
5176       attributes.width = allocation.width;
5177       attributes.height = allocation.height;
5178       attributes.window_type = GDK_WINDOW_CHILD;
5179
5180       attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
5181
5182       attributes.visual = gtk_widget_get_visual (widget);
5183       attributes.wclass = GDK_INPUT_OUTPUT;
5184
5185       attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
5186
5187       gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
5188                                    &attributes, attributes_mask);
5189       gtk_widget_set_window (widget, gdk_window);
5190       gdk_window_set_user_data (gdk_window, widget);
5191
5192       gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
5193
5194       gdk_window_enable_synchronized_configure (gdk_window);
5195       return;
5196     }
5197
5198   gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5199
5200   /* ensure widget tree is properly size allocated */
5201   if (allocation.x == -1 &&
5202       allocation.y == -1 &&
5203       allocation.width == 1 &&
5204       allocation.height == 1)
5205     {
5206
5207       allocation.x = 0;
5208       allocation.y = 0;
5209
5210       gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5211       if (allocation.width == 0 || allocation.height == 0)
5212         {
5213           /* non-empty window */
5214           allocation.width = 200;
5215           allocation.height = 200;
5216         }
5217       gtk_widget_size_allocate (widget, &allocation);
5218       
5219       _gtk_container_queue_resize (GTK_CONTAINER (widget));
5220
5221       g_return_if_fail (!gtk_widget_get_realized (widget));
5222     }
5223   
5224   gtk_widget_set_realized (widget, TRUE);
5225   
5226   switch (priv->type)
5227     {
5228     case GTK_WINDOW_TOPLEVEL:
5229       attributes.window_type = GDK_WINDOW_TOPLEVEL;
5230       break;
5231     case GTK_WINDOW_POPUP:
5232       attributes.window_type = GDK_WINDOW_TEMP;
5233       break;
5234     default:
5235       g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5236       break;
5237     }
5238
5239   attributes.title = priv->title;
5240   attributes.wmclass_name = priv->wmclass_name;
5241   attributes.wmclass_class = priv->wmclass_class;
5242   attributes.wclass = GDK_INPUT_OUTPUT;
5243   attributes.visual = gtk_widget_get_visual (widget);
5244
5245   attributes_mask = 0;
5246   parent_window = gtk_widget_get_root_window (widget);
5247
5248   gtk_widget_get_allocation (widget, &allocation);
5249   attributes.width = allocation.width;
5250   attributes.height = allocation.height;
5251   attributes.event_mask = gtk_widget_get_events (widget);
5252   attributes.event_mask |= (GDK_EXPOSURE_MASK |
5253                             GDK_KEY_PRESS_MASK |
5254                             GDK_KEY_RELEASE_MASK |
5255                             GDK_ENTER_NOTIFY_MASK |
5256                             GDK_LEAVE_NOTIFY_MASK |
5257                             GDK_FOCUS_CHANGE_MASK |
5258                             GDK_STRUCTURE_MASK);
5259   attributes.type_hint = priv->type_hint;
5260
5261   attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5262   attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5263   attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5264
5265   gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5266   gtk_widget_set_window (widget, gdk_window);
5267
5268   if (priv->opacity_set)
5269     gdk_window_set_opacity (gdk_window, priv->opacity);
5270
5271   gdk_window_enable_synchronized_configure (gdk_window);
5272
5273   gdk_window_set_user_data (gdk_window, window);
5274
5275   context = gtk_widget_get_style_context (widget);
5276   gtk_style_context_set_background (context, gdk_window);
5277
5278
5279   if (priv->transient_parent &&
5280       gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5281     gdk_window_set_transient_for (gdk_window,
5282                                   gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5283
5284   if (priv->wm_role)
5285     gdk_window_set_role (gdk_window, priv->wm_role);
5286   
5287   if (!priv->decorated)
5288     gdk_window_set_decorations (gdk_window, 0);
5289   
5290   if (!priv->deletable)
5291     gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5292   
5293   if (gtk_window_get_skip_pager_hint (window))
5294     gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5295   
5296   if (gtk_window_get_skip_taskbar_hint (window))
5297     gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5298   
5299   if (gtk_window_get_accept_focus (window))
5300     gdk_window_set_accept_focus (gdk_window, TRUE);
5301   else
5302     gdk_window_set_accept_focus (gdk_window, FALSE);
5303   
5304   if (gtk_window_get_focus_on_map (window))
5305     gdk_window_set_focus_on_map (gdk_window, TRUE);
5306   else
5307     gdk_window_set_focus_on_map (gdk_window, FALSE);
5308   
5309   if (priv->modal)
5310     gdk_window_set_modal_hint (gdk_window, TRUE);
5311   else
5312     gdk_window_set_modal_hint (gdk_window, FALSE);
5313
5314   if (priv->startup_id)
5315     {
5316 #ifdef GDK_WINDOWING_X11
5317       if (GDK_IS_X11_WINDOW (gdk_window))
5318         {
5319           guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5320           if (timestamp != GDK_CURRENT_TIME)
5321             gdk_x11_window_set_user_time (gdk_window, timestamp);
5322         }
5323 #endif
5324       if (!startup_id_is_fake (priv->startup_id))
5325         gdk_window_set_startup_id (gdk_window, priv->startup_id);
5326     }
5327
5328 #ifdef GDK_WINDOWING_X11
5329   if (priv->initial_timestamp != GDK_CURRENT_TIME)
5330     {
5331       if (GDK_IS_X11_WINDOW (gdk_window))
5332         gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5333     }
5334 #endif
5335
5336   /* Icons */
5337   gtk_window_realize_icon (window);
5338   
5339   if (priv->has_resize_grip)
5340     resize_grip_create_window (window);
5341 }
5342
5343 static void
5344 gtk_window_unrealize (GtkWidget *widget)
5345 {
5346   GtkWindow *window = GTK_WINDOW (widget);
5347   GtkWindowPrivate *priv = window->priv;
5348   GtkWindowGeometryInfo *info;
5349
5350   /* On unrealize, we reset the size of the window such
5351    * that we will re-apply the default sizing stuff
5352    * next time we show the window.
5353    *
5354    * Default positioning is reset on unmap, instead of unrealize.
5355    */
5356   priv->need_default_size = TRUE;
5357   info = gtk_window_get_geometry_info (window, FALSE);
5358   if (info)
5359     {
5360       info->resize_width = -1;
5361       info->resize_height = -1;
5362       info->last.configure_request.x = 0;
5363       info->last.configure_request.y = 0;
5364       info->last.configure_request.width = -1;
5365       info->last.configure_request.height = -1;
5366       /* be sure we reset geom hints on re-realize */
5367       info->last.flags = 0;
5368     }
5369
5370   /* Icons */
5371   gtk_window_unrealize_icon (window);
5372
5373   if (priv->grip_window != NULL)
5374     resize_grip_destroy_window (window);
5375
5376   GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5377 }
5378
5379 static GtkJunctionSides
5380 get_grip_junction (GtkWidget *widget)
5381 {
5382   if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5383     return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5384   else
5385     return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5386 }
5387
5388 static gboolean
5389 get_drag_edge (GtkWidget     *widget,
5390                GdkWindowEdge *edge)
5391 {
5392   GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5393   gboolean hresizable;
5394   gboolean vresizable;
5395   GtkTextDirection dir;
5396   GtkWindowGeometryInfo *info;
5397
5398   hresizable = TRUE;
5399   vresizable = TRUE;
5400
5401   info = priv->geometry_info;
5402   if (info)
5403     {
5404       GdkWindowHints flags = info->last.flags;
5405       GdkGeometry *geometry = &info->last.geometry;
5406
5407       if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5408         {
5409           hresizable = geometry->min_width < geometry->max_width;
5410           vresizable = geometry->min_height < geometry->max_height;
5411         }
5412     }
5413
5414   dir = gtk_widget_get_direction (widget);
5415
5416   if (hresizable && vresizable)
5417     *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5418   else if (hresizable)
5419     *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5420   else if (vresizable)
5421     *edge = GDK_WINDOW_EDGE_SOUTH;
5422   else
5423     return FALSE;
5424
5425   return TRUE;
5426 }
5427
5428 static void
5429 set_grip_cursor (GtkWindow *window)
5430 {
5431   GtkWidget *widget = GTK_WIDGET (window);
5432   GtkWindowPrivate *priv = window->priv;
5433
5434   if (priv->grip_window == NULL)
5435     return;
5436
5437   if (gtk_widget_is_sensitive (widget))
5438     {
5439       GdkWindowEdge edge;
5440       GdkDisplay *display;
5441       GdkCursorType cursor_type;
5442       GdkCursor *cursor;
5443
5444       cursor_type = GDK_LEFT_PTR;
5445
5446       if (get_drag_edge (widget, &edge))
5447         {
5448           switch (edge)
5449             {
5450             case GDK_WINDOW_EDGE_EAST:
5451               cursor_type = GDK_RIGHT_SIDE;
5452               break;
5453             case GDK_WINDOW_EDGE_SOUTH_EAST:
5454               cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5455               break;
5456             case GDK_WINDOW_EDGE_SOUTH:
5457               cursor_type = GDK_BOTTOM_SIDE;
5458               break;
5459             case GDK_WINDOW_EDGE_SOUTH_WEST:
5460               cursor_type = GDK_BOTTOM_LEFT_CORNER;
5461               break;
5462             case GDK_WINDOW_EDGE_WEST:
5463               cursor_type = GDK_LEFT_SIDE;
5464               break;
5465             default: ;
5466             }
5467         }
5468
5469       display = gtk_widget_get_display (widget);
5470       cursor = gdk_cursor_new_for_display (display, cursor_type);
5471       gdk_window_set_cursor (priv->grip_window, cursor);
5472       g_object_unref (cursor);
5473     }
5474   else
5475     gdk_window_set_cursor (priv->grip_window, NULL);
5476 }
5477
5478 static void
5479 set_grip_shape (GtkWindow *window)
5480 {
5481   GtkWindowPrivate *priv = window->priv;
5482   cairo_region_t *region;
5483   cairo_surface_t *surface;
5484   cairo_t *cr;
5485   double width, height;
5486
5487   if (priv->grip_window == NULL)
5488     return;
5489
5490   width = gdk_window_get_width (priv->grip_window);
5491   height = gdk_window_get_height (priv->grip_window);
5492   surface = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
5493
5494   cr = cairo_create (surface);
5495   cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5496   cairo_paint (cr);
5497   cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5498   if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5499     {
5500       cairo_move_to (cr, width, 0.0);
5501       cairo_line_to (cr, width, height);
5502       cairo_line_to (cr, 0.0, height);
5503     }
5504   else
5505     {
5506       cairo_move_to (cr, 0.0, 0.0);
5507       cairo_line_to (cr, width, height);
5508       cairo_line_to (cr, 0.0, height);
5509     }
5510   cairo_close_path (cr);
5511   cairo_fill (cr);
5512   cairo_destroy (cr);
5513   region = gdk_cairo_region_create_from_surface (surface);
5514   cairo_surface_destroy (surface);
5515
5516   gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5517   cairo_region_destroy (region);
5518 }
5519
5520 static void
5521 set_grip_position (GtkWindow *window)
5522 {
5523   GtkWindowPrivate *priv = window->priv;
5524   GdkRectangle rect;
5525
5526   if (priv->grip_window == NULL)
5527     return;
5528
5529   gtk_window_get_resize_grip_area (window, &rect);
5530   gdk_window_raise (priv->grip_window);
5531   gdk_window_move_resize (priv->grip_window,
5532                           rect.x, rect.y,
5533                           rect.width, rect.height);
5534 }
5535
5536 /* _gtk_window_set_allocation:
5537  * @window: a #GtkWindow
5538  * @allocation: the new allocation
5539  *
5540  * This function is like gtk_widget_set_allocation()
5541  * but does the necessary extra work to update
5542  * the resize grip positioning, etc.
5543  *
5544  * Call this instead of gtk_widget_set_allocation()
5545  * when overriding ::size_allocate in a GtkWindow
5546  * subclass without chaining up.
5547  */
5548 void
5549 _gtk_window_set_allocation (GtkWindow     *window,
5550                             GtkAllocation *allocation)
5551 {
5552   GtkWidget *widget = (GtkWidget *)window;
5553
5554   gtk_widget_set_allocation (widget, allocation);
5555
5556   if (gtk_widget_get_realized (widget))
5557     {
5558       /* If it's not a toplevel we're embedded, we need to resize
5559        * the window's window and skip the grip.
5560        */
5561       if (!gtk_widget_is_toplevel (widget))
5562         {
5563           gdk_window_move_resize (gtk_widget_get_window (widget),
5564                                   allocation->x, allocation->y,
5565                                   allocation->width, allocation->height);
5566         }
5567       else
5568         {
5569           update_grip_visibility (window);
5570           set_grip_position (window);
5571         }
5572     }
5573 }
5574
5575 static void
5576 gtk_window_size_allocate (GtkWidget     *widget,
5577                           GtkAllocation *allocation)
5578 {
5579   GtkWindow *window = GTK_WINDOW (widget);
5580   GtkAllocation child_allocation;
5581   GtkWidget *child;
5582   guint border_width;
5583
5584   _gtk_window_set_allocation (window, allocation);
5585
5586   child = gtk_bin_get_child (&(window->bin));
5587   if (child && gtk_widget_get_visible (child))
5588     {
5589       border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5590       child_allocation.x = border_width;
5591       child_allocation.y = border_width;
5592       child_allocation.width = MAX (1, allocation->width - border_width * 2);
5593       child_allocation.height = MAX (1, allocation->height - border_width * 2);
5594
5595       gtk_widget_size_allocate (child, &child_allocation);
5596     }
5597 }
5598
5599 static gint
5600 gtk_window_configure_event (GtkWidget         *widget,
5601                             GdkEventConfigure *event)
5602 {
5603   GtkAllocation allocation;
5604   GtkWindow *window = GTK_WINDOW (widget);
5605   GtkWindowPrivate *priv = window->priv;
5606   gboolean expected_reply = priv->configure_request_count > 0;
5607
5608   if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5609     {
5610       if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5611         return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5612
5613       gdk_window_configure_finished (gtk_widget_get_window (widget));
5614       return FALSE;
5615     }
5616
5617   /* priv->configure_request_count incremented for each
5618    * configure request, and decremented to a min of 0 for
5619    * each configure notify.
5620    *
5621    * All it means is that we know we will get at least
5622    * priv->configure_request_count more configure notifies.
5623    * We could get more configure notifies than that; some
5624    * of the configure notifies we get may be unrelated to
5625    * the configure requests. But we will get at least
5626    * priv->configure_request_count notifies.
5627    */
5628
5629   if (priv->configure_request_count > 0)
5630     {
5631       priv->configure_request_count -= 1;
5632       gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5633     }
5634   
5635   /* As an optimization, we avoid a resize when possible.
5636    *
5637    * The only times we can avoid a resize are:
5638    *   - we know only the position changed, not the size
5639    *   - we know we have made more requests and so will get more
5640    *     notifies and can wait to resize when we get them
5641    */
5642   gtk_widget_get_allocation (widget, &allocation);
5643   if (!expected_reply &&
5644       (allocation.width == event->width &&
5645        allocation.height == event->height))
5646     {
5647       gdk_window_configure_finished (gtk_widget_get_window (widget));
5648       return TRUE;
5649     }
5650
5651   /*
5652    * If we do need to resize, we do that by:
5653    *   - filling in widget->allocation with the new size
5654    *   - setting configure_notify_received to TRUE
5655    *     for use in gtk_window_move_resize()
5656    *   - queueing a resize, leading to invocation of
5657    *     gtk_window_move_resize() in an idle handler
5658    *
5659    */
5660   
5661   priv->configure_notify_received = TRUE;
5662
5663   allocation.width = event->width;
5664   allocation.height = event->height;
5665   gtk_widget_set_allocation (widget, &allocation);
5666
5667   gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5668
5669   _gtk_container_queue_resize (GTK_CONTAINER (widget));
5670   
5671   return TRUE;
5672 }
5673
5674 static gboolean
5675 gtk_window_state_event (GtkWidget           *widget,
5676                         GdkEventWindowState *event)
5677 {
5678   update_grip_visibility (GTK_WINDOW (widget));
5679
5680   if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
5681     ensure_state_flag_backdrop (widget);
5682
5683   return FALSE;
5684 }
5685
5686 static void
5687 gtk_window_direction_changed (GtkWidget        *widget,
5688                               GtkTextDirection  prev_dir)
5689 {
5690   GtkWindow *window = GTK_WINDOW (widget);
5691
5692   set_grip_cursor (window);
5693   set_grip_position (window);
5694   set_grip_shape (window);
5695 }
5696
5697 static void
5698 gtk_window_state_changed (GtkWidget    *widget,
5699                           GtkStateType  previous_state)
5700 {
5701   GtkWindow *window = GTK_WINDOW (widget);
5702
5703   update_grip_visibility (window);
5704 }
5705
5706 static void
5707 gtk_window_style_updated (GtkWidget *widget)
5708 {
5709   GtkWindow *window = GTK_WINDOW (widget);
5710   GtkWindowPrivate *priv = window->priv;
5711   GdkRectangle rect;
5712
5713   GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5714
5715   if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5716     {
5717       gdk_window_move_resize (priv->grip_window,
5718                               rect.x, rect.y,
5719                               rect.width, rect.height);
5720
5721       set_grip_shape (window);
5722       gtk_widget_queue_resize (widget);
5723     }
5724 }
5725
5726 static void
5727 resize_grip_create_window (GtkWindow *window)
5728 {
5729   GtkWidget *widget;
5730   GtkWindowPrivate *priv;
5731   GdkWindowAttr attributes;
5732   gint attributes_mask;
5733   GdkRectangle rect;
5734   GdkRGBA transparent = {0, 0, 0, 0};
5735
5736   priv = window->priv;
5737   widget = GTK_WIDGET (window);
5738
5739   g_return_if_fail (gtk_widget_get_realized (widget));
5740   g_return_if_fail (priv->grip_window == NULL);
5741
5742   gtk_window_get_resize_grip_area (window, &rect);
5743
5744   attributes.x = rect.x;
5745   attributes.y = rect.y;
5746   attributes.width = rect.width;
5747   attributes.height = rect.height;
5748   attributes.window_type = GDK_WINDOW_CHILD;
5749   attributes.wclass = GDK_INPUT_OUTPUT;
5750   attributes.event_mask = gtk_widget_get_events (widget) |
5751                           GDK_EXPOSURE_MASK |
5752                           GDK_BUTTON_PRESS_MASK;
5753
5754   attributes_mask = GDK_WA_X | GDK_WA_Y;
5755
5756   priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5757                                       &attributes,
5758                                       attributes_mask);
5759   gdk_window_set_background_rgba (priv->grip_window, &transparent);
5760
5761   gdk_window_set_user_data (priv->grip_window, widget);
5762
5763   gdk_window_raise (priv->grip_window);
5764
5765   set_grip_shape (window);
5766   update_grip_visibility (window);
5767 }
5768
5769 static void
5770 resize_grip_destroy_window (GtkWindow *window)
5771 {
5772   GtkWindowPrivate *priv = window->priv;
5773
5774   gdk_window_set_user_data (priv->grip_window, NULL);
5775   gdk_window_destroy (priv->grip_window);
5776   priv->grip_window = NULL;
5777   update_grip_visibility (window);
5778 }
5779
5780 /**
5781  * gtk_window_set_has_resize_grip:
5782  * @window: a #GtkWindow
5783  * @value: %TRUE to allow a resize grip
5784  *
5785  * Sets whether @window has a corner resize grip.
5786  *
5787  * Note that the resize grip is only shown if the window
5788  * is actually resizable and not maximized. Use
5789  * gtk_window_resize_grip_is_visible() to find out if the
5790  * resize grip is currently shown.
5791  *
5792  * Since: 3.0
5793  */
5794 void
5795 gtk_window_set_has_resize_grip (GtkWindow *window,
5796                                 gboolean   value)
5797 {
5798   GtkWidget *widget = GTK_WIDGET (window);
5799   GtkWindowPrivate *priv = window->priv;
5800
5801   value = value != FALSE;
5802
5803   if (value != priv->has_resize_grip)
5804     {
5805       priv->has_resize_grip = value;
5806       gtk_widget_queue_draw (widget);
5807
5808       if (gtk_widget_get_realized (widget) && 
5809           gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5810         {
5811           if (priv->has_resize_grip && priv->grip_window == NULL)
5812             resize_grip_create_window (window);
5813           else if (!priv->has_resize_grip && priv->grip_window != NULL)
5814             resize_grip_destroy_window (window);
5815         }
5816
5817       g_object_notify (G_OBJECT (window), "has-resize-grip");
5818     }
5819 }
5820
5821 static void
5822 update_grip_visibility (GtkWindow *window)
5823 {
5824   GtkWindowPrivate *priv = window->priv;
5825   gboolean val;
5826
5827   val = gtk_window_resize_grip_is_visible (window);
5828
5829   if (priv->grip_window != NULL)
5830     {
5831       if (val)
5832         {
5833           gdk_window_show (priv->grip_window);
5834           set_grip_cursor (window);
5835         }
5836       else
5837         {
5838           gdk_window_hide (priv->grip_window);
5839         }
5840     }
5841
5842   if (priv->resize_grip_visible != val)
5843     {
5844       priv->resize_grip_visible = val;
5845
5846       g_object_notify (G_OBJECT (window), "resize-grip-visible");
5847     }
5848 }
5849
5850 /**
5851  * gtk_window_resize_grip_is_visible:
5852  * @window: a #GtkWindow
5853  *
5854  * Determines whether a resize grip is visible for the specified window.
5855  *
5856  * Returns: %TRUE if a resize grip exists and is visible
5857  *
5858  * Since: 3.0
5859  */
5860 gboolean
5861 gtk_window_resize_grip_is_visible (GtkWindow *window)
5862 {
5863   GtkWidget *widget;
5864   GtkWindowPrivate *priv;
5865   GdkWindowEdge edge;
5866
5867   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5868
5869   priv = window->priv;
5870   widget = GTK_WIDGET (window);
5871
5872   if (priv->type == GTK_WINDOW_POPUP)
5873     return FALSE;
5874
5875   if (!priv->resizable)
5876     return FALSE;
5877
5878   if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5879     return FALSE;
5880
5881   if (gtk_widget_get_realized (widget))
5882     {
5883       GdkWindowState state;
5884
5885       state = gdk_window_get_state (gtk_widget_get_window (widget));
5886
5887       if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5888         return FALSE;
5889     }
5890
5891   if (!get_drag_edge (widget, &edge))
5892     return FALSE;
5893
5894   return window->priv->has_resize_grip;
5895 }
5896
5897 /**
5898  * gtk_window_get_has_resize_grip:
5899  * @window: a #GtkWindow
5900  *
5901  * Determines whether the window may have a resize grip.
5902  *
5903  * Returns: %TRUE if the window has a resize grip
5904  *
5905  * Since: 3.0
5906  */
5907 gboolean
5908 gtk_window_get_has_resize_grip (GtkWindow *window)
5909 {
5910   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5911
5912   return window->priv->has_resize_grip;
5913 }
5914
5915 /**
5916  * gtk_window_get_resize_grip_area:
5917  * @window: a #GtkWindow
5918  * @rect: (out): a pointer to a #GdkRectangle which we should store
5919  *     the resize grip area
5920  *
5921  * If a window has a resize grip, this will retrieve the grip
5922  * position, width and height into the specified #GdkRectangle.
5923  *
5924  * Returns: %TRUE if the resize grip's area was retrieved
5925  *
5926  * Since: 3.0
5927  */
5928 gboolean
5929 gtk_window_get_resize_grip_area (GtkWindow    *window,
5930                                  GdkRectangle *rect)
5931 {
5932   GtkWidget *widget = GTK_WIDGET (window);
5933   GtkAllocation allocation;
5934   gint grip_width;
5935   gint grip_height;
5936
5937   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5938
5939   if (!window->priv->has_resize_grip)
5940     return FALSE;
5941
5942   gtk_widget_get_allocation (widget, &allocation);
5943
5944   gtk_widget_style_get (widget,
5945                         "resize-grip-width", &grip_width,
5946                         "resize-grip-height", &grip_height,
5947                         NULL);
5948
5949   if (grip_width > allocation.width)
5950     grip_width = allocation.width;
5951
5952   if (grip_height > allocation.height)
5953     grip_height = allocation.height;
5954
5955   rect->width = grip_width;
5956   rect->height = grip_height;
5957   rect->y = allocation.y + allocation.height - grip_height;
5958
5959   if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5960     rect->x = allocation.x + allocation.width - grip_width;
5961   else
5962     rect->x = allocation.x;
5963
5964   return TRUE;
5965 }
5966
5967 /* the accel_key and accel_mods fields of the key have to be setup
5968  * upon calling this function. it'll then return whether that key
5969  * is at all used as accelerator, and if so will OR in the
5970  * accel_flags member of the key.
5971  */
5972 gboolean
5973 _gtk_window_query_nonaccels (GtkWindow      *window,
5974                              guint           accel_key,
5975                              GdkModifierType accel_mods)
5976 {
5977   GtkWindowPrivate *priv;
5978
5979   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5980
5981   priv = window->priv;
5982
5983   /* movement keys are considered locked accels */
5984   if (!accel_mods)
5985     {
5986       static const guint bindings[] = {
5987         GDK_KEY_space, GDK_KEY_KP_Space, GDK_KEY_Return, GDK_KEY_ISO_Enter, GDK_KEY_KP_Enter, GDK_KEY_Up, GDK_KEY_KP_Up, GDK_KEY_Down, GDK_KEY_KP_Down,
5988         GDK_KEY_Left, GDK_KEY_KP_Left, GDK_KEY_Right, GDK_KEY_KP_Right, GDK_KEY_Tab, GDK_KEY_KP_Tab, GDK_KEY_ISO_Left_Tab,
5989       };
5990       guint i;
5991       
5992       for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5993         if (bindings[i] == accel_key)
5994           return TRUE;
5995     }
5996
5997   /* mnemonics are considered locked accels */
5998   if (accel_mods == priv->mnemonic_modifier)
5999     {
6000       GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
6001       if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
6002         return TRUE;
6003     }
6004
6005   return FALSE;
6006 }
6007
6008 /**
6009  * gtk_window_propagate_key_event:
6010  * @window:  a #GtkWindow
6011  * @event:   a #GdkEventKey
6012  *
6013  * Propagate a key press or release event to the focus widget and
6014  * up the focus container chain until a widget handles @event.
6015  * This is normally called by the default ::key_press_event and
6016  * ::key_release_event handlers for toplevel windows,
6017  * however in some cases it may be useful to call this directly when
6018  * overriding the standard key handling for a toplevel window.
6019  *
6020  * Return value: %TRUE if a widget in the focus chain handled the event.
6021  *
6022  * Since: 2.4
6023  */
6024 gboolean
6025 gtk_window_propagate_key_event (GtkWindow        *window,
6026                                 GdkEventKey      *event)
6027 {
6028   GtkWindowPrivate *priv;
6029   gboolean handled = FALSE;
6030   GtkWidget *widget, *focus;
6031
6032   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6033
6034   priv = window->priv;
6035   widget = GTK_WIDGET (window);
6036
6037   focus = priv->focus_widget;
6038   if (focus)
6039     g_object_ref (focus);
6040   
6041   while (!handled &&
6042          focus && focus != widget &&
6043          gtk_widget_get_toplevel (focus) == widget)
6044     {
6045       GtkWidget *parent;
6046       
6047       if (gtk_widget_is_sensitive (focus))
6048         handled = gtk_widget_event (focus, (GdkEvent*) event);
6049
6050       parent = gtk_widget_get_parent (focus);
6051       if (parent)
6052         g_object_ref (parent);
6053       
6054       g_object_unref (focus);
6055       
6056       focus = parent;
6057     }
6058   
6059   if (focus)
6060     g_object_unref (focus);
6061
6062   return handled;
6063 }
6064
6065 static gint
6066 gtk_window_key_press_event (GtkWidget   *widget,
6067                             GdkEventKey *event)
6068 {
6069   GtkWindow *window = GTK_WINDOW (widget);
6070   gboolean handled = FALSE;
6071
6072   /* handle mnemonics and accelerators */
6073   if (!handled)
6074     handled = gtk_window_activate_key (window, event);
6075
6076   /* handle focus widget key events */
6077   if (!handled)
6078     handled = gtk_window_propagate_key_event (window, event);
6079
6080   /* Chain up, invokes binding set */
6081   if (!handled)
6082     handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
6083
6084   return handled;
6085 }
6086
6087 static gint
6088 gtk_window_key_release_event (GtkWidget   *widget,
6089                               GdkEventKey *event)
6090 {
6091   GtkWindow *window = GTK_WINDOW (widget);
6092   gboolean handled = FALSE;
6093
6094   /* handle focus widget key events */
6095   if (!handled)
6096     handled = gtk_window_propagate_key_event (window, event);
6097
6098   /* Chain up, invokes binding set */
6099   if (!handled)
6100     handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
6101
6102   return handled;
6103 }
6104
6105 static gint
6106 gtk_window_button_press_event (GtkWidget *widget,
6107                                GdkEventButton *event)
6108 {
6109   GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
6110   GdkWindowEdge edge;
6111
6112   if (event->window == priv->grip_window)
6113     {
6114       if (get_drag_edge (widget, &edge))
6115         gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
6116                                                  edge,
6117                                                  gdk_event_get_device ((GdkEvent *) event),
6118                                                  event->button,
6119                                                  event->x_root,
6120                                                  event->y_root,
6121                                                  event->time);
6122
6123       return TRUE;
6124     }
6125
6126   return FALSE;
6127 }
6128
6129 static void
6130 gtk_window_real_activate_default (GtkWindow *window)
6131 {
6132   gtk_window_activate_default (window);
6133 }
6134
6135 static void
6136 gtk_window_real_activate_focus (GtkWindow *window)
6137 {
6138   gtk_window_activate_focus (window);
6139 }
6140
6141 static gint
6142 gtk_window_enter_notify_event (GtkWidget        *widget,
6143                                GdkEventCrossing *event)
6144 {
6145   return FALSE;
6146 }
6147
6148 static gint
6149 gtk_window_leave_notify_event (GtkWidget        *widget,
6150                                GdkEventCrossing *event)
6151 {
6152   return FALSE;
6153 }
6154
6155 static void
6156 do_focus_change (GtkWidget *widget,
6157                  gboolean   in)
6158 {
6159   GdkWindow *window;
6160   GdkDeviceManager *device_manager;
6161   GList *devices, *d;
6162
6163   g_object_ref (widget);
6164
6165   device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
6166   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6167   devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
6168   devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
6169
6170   for (d = devices; d; d = d->next)
6171     {
6172       GdkDevice *dev = d->data;
6173       GdkEvent *fevent;
6174
6175       if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
6176         continue;
6177
6178       /* Skip non-master keyboards that haven't
6179        * selected for events from this window
6180        */
6181       window = gtk_widget_get_window (widget);
6182       if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
6183           window && !gdk_window_get_device_events (window, dev))
6184         continue;
6185
6186       fevent = gdk_event_new (GDK_FOCUS_CHANGE);
6187
6188       fevent->focus_change.type = GDK_FOCUS_CHANGE;
6189       fevent->focus_change.window = window;
6190       if (window)
6191         g_object_ref (window);
6192       fevent->focus_change.in = in;
6193       gdk_event_set_device (fevent, dev);
6194
6195       gtk_widget_send_focus_change (widget, fevent);
6196
6197       gdk_event_free (fevent);
6198     }
6199
6200   g_list_free (devices);
6201   g_object_unref (widget);
6202 }
6203
6204 static void
6205 maybe_set_mnemonics_visible (GtkWindow *window)
6206 {
6207   GList *devices, *d;
6208   GdkDeviceManager *device_manager;
6209
6210   device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
6211   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6212
6213   for (d = devices; d; d = d->next)
6214     {
6215       GdkDevice *dev = d->data;
6216
6217       if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6218         {
6219           GdkModifierType mask;
6220
6221           gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6222                                 NULL, &mask);
6223           if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6224             {
6225               gtk_window_set_mnemonics_visible (window, TRUE);
6226               break;
6227             }
6228         }
6229     }
6230
6231   g_list_free (devices);
6232 }
6233
6234 static gint
6235 gtk_window_focus_in_event (GtkWidget     *widget,
6236                            GdkEventFocus *event)
6237 {
6238   GtkWindow *window = GTK_WINDOW (widget);
6239   gboolean auto_mnemonics;
6240
6241   /* It appears spurious focus in events can occur when
6242    *  the window is hidden. So we'll just check to see if
6243    *  the window is visible before actually handling the
6244    *  event
6245    */
6246   if (gtk_widget_get_visible (widget))
6247     {
6248       _gtk_window_set_has_toplevel_focus (window, TRUE);
6249       _gtk_window_set_is_active (window, TRUE);
6250
6251       g_object_get (gtk_widget_get_settings (widget),
6252                     "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6253       if (auto_mnemonics)
6254         maybe_set_mnemonics_visible (window);
6255     }
6256
6257   return FALSE;
6258 }
6259
6260 static gint
6261 gtk_window_focus_out_event (GtkWidget     *widget,
6262                             GdkEventFocus *event)
6263 {
6264   GtkWindow *window = GTK_WINDOW (widget);
6265   gboolean auto_mnemonics;
6266
6267   _gtk_window_set_has_toplevel_focus (window, FALSE);
6268   _gtk_window_set_is_active (window, FALSE);
6269
6270   /* set the mnemonic-visible property to false */
6271   g_object_get (gtk_widget_get_settings (widget),
6272                 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6273   if (auto_mnemonics)
6274     gtk_window_set_mnemonics_visible (window, FALSE);
6275
6276   return FALSE;
6277 }
6278
6279 static void
6280 gtk_window_check_resize (GtkContainer *container)
6281 {
6282   /* If the window is not toplevel anymore than it's embedded somewhere,
6283    * so handle it like a normal window */
6284   if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6285     GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6286   else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6287     gtk_window_move_resize (GTK_WINDOW (container));
6288 }
6289
6290 static gboolean
6291 gtk_window_focus (GtkWidget        *widget,
6292                   GtkDirectionType  direction)
6293 {
6294   GtkWindowPrivate *priv;
6295   GtkBin *bin;
6296   GtkWindow *window;
6297   GtkContainer *container;
6298   GtkWidget *child;
6299   GtkWidget *old_focus_child;
6300   GtkWidget *parent;
6301
6302   if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6303     return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6304
6305   container = GTK_CONTAINER (widget);
6306   window = GTK_WINDOW (widget);
6307   priv = window->priv;
6308   bin = GTK_BIN (widget);
6309
6310   old_focus_child = gtk_container_get_focus_child (container);
6311   
6312   /* We need a special implementation here to deal properly with wrapping
6313    * around in the tab chain without the danger of going into an
6314    * infinite loop.
6315    */
6316   if (old_focus_child)
6317     {
6318       if (gtk_widget_child_focus (old_focus_child, direction))
6319         return TRUE;
6320     }
6321
6322   if (priv->focus_widget)
6323     {
6324       if (direction == GTK_DIR_LEFT ||
6325           direction == GTK_DIR_RIGHT ||
6326           direction == GTK_DIR_UP ||
6327           direction == GTK_DIR_DOWN)
6328         {
6329           return FALSE;
6330         }
6331       
6332       /* Wrapped off the end, clear the focus setting for the toplpevel */
6333       parent = gtk_widget_get_parent (priv->focus_widget);
6334       while (parent)
6335         {
6336           gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6337           parent = gtk_widget_get_parent (parent);
6338         }
6339       
6340       gtk_window_set_focus (GTK_WINDOW (container), NULL);
6341     }
6342
6343   /* Now try to focus the first widget in the window */
6344   child = gtk_bin_get_child (bin);
6345   if (child)
6346     {
6347       if (gtk_widget_child_focus (child, direction))
6348         return TRUE;
6349     }
6350
6351   return FALSE;
6352 }
6353
6354 static void
6355 gtk_window_move_focus (GtkWidget       *widget,
6356                        GtkDirectionType dir)
6357 {
6358   if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6359     {
6360       GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6361       return;
6362     }
6363
6364   gtk_widget_child_focus (widget, dir);
6365
6366   if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6367     gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6368 }
6369
6370 static void
6371 gtk_window_real_set_focus (GtkWindow *window,
6372                            GtkWidget *focus)
6373 {
6374   GtkWindowPrivate *priv = window->priv;
6375   GtkWidget *old_focus = priv->focus_widget;
6376   gboolean had_default = FALSE;
6377   gboolean focus_had_default = FALSE;
6378   gboolean old_focus_had_default = FALSE;
6379
6380   if (old_focus)
6381     {
6382       g_object_ref (old_focus);
6383       g_object_freeze_notify (G_OBJECT (old_focus));
6384       old_focus_had_default = gtk_widget_has_default (old_focus);
6385     }
6386   if (focus)
6387     {
6388       g_object_ref (focus);
6389       g_object_freeze_notify (G_OBJECT (focus));
6390       focus_had_default = gtk_widget_has_default (focus);
6391     }
6392
6393   if (priv->default_widget)
6394     had_default = gtk_widget_has_default (priv->default_widget);
6395
6396   if (priv->focus_widget)
6397     {
6398       if (gtk_widget_get_receives_default (priv->focus_widget) &&
6399           (priv->focus_widget != priv->default_widget))
6400         {
6401           _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6402           gtk_widget_queue_draw (priv->focus_widget);
6403
6404           if (priv->default_widget)
6405             _gtk_widget_set_has_default (priv->default_widget, TRUE);
6406         }
6407
6408       priv->focus_widget = NULL;
6409
6410       if (priv->has_focus)
6411         do_focus_change (old_focus, FALSE);
6412
6413       g_object_notify (G_OBJECT (old_focus), "is-focus");
6414     }
6415
6416   /* The above notifications may have set a new focus widget,
6417    * if so, we don't want to override it.
6418    */
6419   if (focus && !priv->focus_widget)
6420     {
6421       priv->focus_widget = focus;
6422
6423       if (gtk_widget_get_receives_default (priv->focus_widget) &&
6424           (priv->focus_widget != priv->default_widget))
6425         {
6426           if (gtk_widget_get_can_default (priv->focus_widget))
6427             _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6428
6429           if (priv->default_widget)
6430             _gtk_widget_set_has_default (priv->default_widget, FALSE);
6431         }
6432
6433       if (priv->has_focus)
6434         do_focus_change (priv->focus_widget, TRUE);
6435
6436       g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6437     }
6438
6439   /* If the default widget changed, a redraw will have been queued
6440    * on the old and new default widgets by gtk_window_set_default(), so
6441    * we only have to worry about the case where it didn't change.
6442    * We'll sometimes queue a draw twice on the new widget but that
6443    * is harmless.
6444    */
6445   if (priv->default_widget &&
6446       (had_default != gtk_widget_has_default (priv->default_widget)))
6447     gtk_widget_queue_draw (priv->default_widget);
6448   
6449   if (old_focus)
6450     {
6451       if (old_focus_had_default != gtk_widget_has_default (old_focus))
6452         gtk_widget_queue_draw (old_focus);
6453         
6454       g_object_thaw_notify (G_OBJECT (old_focus));
6455       g_object_unref (old_focus);
6456     }
6457   if (focus)
6458     {
6459       if (focus_had_default != gtk_widget_has_default (focus))
6460         gtk_widget_queue_draw (focus);
6461
6462       g_object_thaw_notify (G_OBJECT (focus));
6463       g_object_unref (focus);
6464     }
6465 }
6466
6467
6468 static void 
6469 gtk_window_get_preferred_width (GtkWidget *widget,
6470                                 gint      *minimum_size,
6471                                 gint      *natural_size)
6472 {
6473   GtkWindow *window;
6474   GtkWidget *child;
6475   guint border_width;
6476
6477   window = GTK_WINDOW (widget);
6478   child  = gtk_bin_get_child (GTK_BIN (window));
6479
6480   border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6481   *minimum_size = border_width * 2;
6482   *natural_size = border_width * 2;
6483
6484   if (child && gtk_widget_get_visible (child))
6485     {
6486       gint child_min, child_nat;
6487       gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6488
6489       *minimum_size += child_min;
6490       *natural_size += child_nat;
6491     }
6492 }
6493
6494 static void 
6495 gtk_window_get_preferred_height (GtkWidget *widget,
6496                                  gint      *minimum_size,
6497                                  gint      *natural_size)
6498 {
6499   GtkWindow *window;
6500   GtkWidget *child;
6501   guint border_width;
6502
6503   window = GTK_WINDOW (widget);
6504   child  = gtk_bin_get_child (GTK_BIN (window));
6505
6506   border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6507   *minimum_size = border_width * 2;
6508   *natural_size = border_width * 2;
6509
6510   if (child && gtk_widget_get_visible (child))
6511     {
6512       gint child_min, child_nat;
6513       gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6514
6515       *minimum_size += child_min;
6516       *natural_size += child_nat;
6517     }
6518 }
6519
6520
6521 /**
6522  * _gtk_window_unset_focus_and_default:
6523  * @window: a #GtkWindow
6524  * @widget: a widget inside of @window
6525  * 
6526  * Checks whether the focus and default widgets of @window are
6527  * @widget or a descendent of @widget, and if so, unset them.
6528  **/
6529 void
6530 _gtk_window_unset_focus_and_default (GtkWindow *window,
6531                                      GtkWidget *widget)
6532
6533 {
6534   GtkWindowPrivate *priv = window->priv;
6535   GtkWidget *child;
6536   GtkWidget *parent;
6537
6538   g_object_ref (window);
6539   g_object_ref (widget);
6540
6541   parent = gtk_widget_get_parent (widget);
6542   if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6543     {
6544       child = priv->focus_widget;
6545       
6546       while (child && child != widget)
6547         child = gtk_widget_get_parent (child);
6548
6549       if (child == widget)
6550         gtk_window_set_focus (GTK_WINDOW (window), NULL);
6551     }
6552       
6553   child = priv->default_widget;
6554       
6555   while (child && child != widget)
6556     child = gtk_widget_get_parent (child);
6557
6558   if (child == widget)
6559     gtk_window_set_default (window, NULL);
6560   
6561   g_object_unref (widget);
6562   g_object_unref (window);
6563 }
6564
6565 /*********************************
6566  * Functions related to resizing *
6567  *********************************/
6568
6569 static void
6570 geometry_size_to_pixels (GdkGeometry *geometry,
6571                          guint        flags,
6572                          gint        *width,
6573                          gint        *height)
6574 {
6575   gint base_width = 0;
6576   gint base_height = 0;
6577   gint min_width = 0;
6578   gint min_height = 0;
6579   gint width_inc = 1;
6580   gint height_inc = 1;
6581
6582   if (flags & GDK_HINT_BASE_SIZE)
6583     {
6584       base_width = geometry->base_width;
6585       base_height = geometry->base_height;
6586     }
6587   if (flags & GDK_HINT_MIN_SIZE)
6588     {
6589       min_width = geometry->min_width;
6590       min_height = geometry->min_height;
6591     }
6592   if (flags & GDK_HINT_RESIZE_INC)
6593     {
6594       width_inc = geometry->width_inc;
6595       height_inc = geometry->height_inc;
6596     }
6597
6598   if (width)
6599     *width = MAX (*width * width_inc + base_width, min_width);
6600   if (height)
6601     *height = MAX (*height * height_inc + base_height, min_height);
6602 }
6603
6604 /* This function doesn't constrain to geometry hints */
6605 static void 
6606 gtk_window_compute_configure_request_size (GtkWindow   *window,
6607                                            GdkGeometry *geometry,
6608                                            guint        flags,
6609                                            gint        *width,
6610                                            gint        *height)
6611 {
6612   GtkWindowPrivate *priv = window->priv;
6613   GtkWindowGeometryInfo *info;
6614
6615   /* Preconditions:
6616    *  - we've done a size request
6617    */
6618   
6619   info = gtk_window_get_geometry_info (window, FALSE);
6620
6621   if (priv->need_default_size)
6622     {
6623       gtk_window_guess_default_size (window, width, height);
6624
6625       /* If window is empty so requests 0, default to random nonzero size */
6626        if (*width == 0 && *height == 0)
6627          {
6628            *width = 200;
6629            *height = 200;
6630          }
6631
6632        /* Override with default size */
6633
6634        if (info)
6635          {
6636            if (info->default_width > 0)
6637              *width = info->default_width;
6638            if (info->default_height > 0)
6639              *height = info->default_height;
6640
6641            if (info->default_is_geometry)
6642              geometry_size_to_pixels (geometry, flags,
6643                                       info->default_width > 0 ? width : NULL,
6644                                       info->default_height > 0 ? height : NULL);
6645          }
6646     }
6647   else
6648     {
6649       GtkAllocation allocation;
6650
6651       gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6652
6653       /* Default to keeping current size */
6654       *width = allocation.width;
6655       *height = allocation.height;
6656     }
6657
6658   /* Override any size with gtk_window_resize() values */
6659   if (info)
6660     {
6661       if (info->resize_width > 0)
6662         *width = info->resize_width;
6663       if (info->resize_height > 0)
6664         *height = info->resize_height;
6665
6666       if (info->resize_is_geometry)
6667         geometry_size_to_pixels (geometry, flags,
6668                                  info->resize_width > 0 ? width : NULL,
6669                                  info->resize_height > 0 ? height : NULL);
6670     }
6671
6672   /* Don't ever request zero width or height, its not supported by
6673      gdk. The size allocation code will round it to 1 anyway but if
6674      we do it then the value returned from this function will is
6675      not comparable to the size allocation read from the GtkWindow. */
6676   *width = MAX (*width, 1);
6677   *height = MAX (*height, 1);
6678 }
6679
6680 static GtkWindowPosition
6681 get_effective_position (GtkWindow *window)
6682 {
6683   GtkWindowPrivate *priv = window->priv;
6684   GtkWindowPosition pos = priv->position;
6685
6686   if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6687       (priv->transient_parent == NULL ||
6688        !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6689     pos = GTK_WIN_POS_NONE;
6690
6691   return pos;
6692 }
6693
6694 static int
6695 get_center_monitor_of_window (GtkWindow *window)
6696 {
6697   /* We could try to sort out the relative positions of the monitors and
6698    * stuff, or we could just be losers and assume you have a row
6699    * or column of monitors.
6700    */
6701   return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6702 }
6703
6704 static int
6705 get_monitor_containing_pointer (GtkWindow *window)
6706 {
6707   gint px, py;
6708   gint monitor_num;
6709   GdkScreen *window_screen;
6710   GdkScreen *pointer_screen;
6711   GdkDisplay *display;
6712   GdkDeviceManager *device_manager;
6713   GdkDevice *pointer;
6714
6715   window_screen = gtk_window_check_screen (window);
6716   display = gdk_screen_get_display (window_screen);
6717   device_manager = gdk_display_get_device_manager (display);
6718   pointer = gdk_device_manager_get_client_pointer (device_manager);
6719
6720   gdk_device_get_position (pointer,
6721                            &pointer_screen,
6722                            &px, &py);
6723
6724   if (pointer_screen == window_screen)
6725     monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6726   else
6727     monitor_num = -1;
6728
6729   return monitor_num;
6730 }
6731
6732 static void
6733 center_window_on_monitor (GtkWindow *window,
6734                           gint       w,
6735                           gint       h,
6736                           gint      *x,
6737                           gint      *y)
6738 {
6739   GdkRectangle monitor;
6740   int monitor_num;
6741
6742   monitor_num = get_monitor_containing_pointer (window);
6743
6744   if (monitor_num == -1)
6745     monitor_num = get_center_monitor_of_window (window);
6746
6747   gdk_screen_get_monitor_workarea (gtk_window_check_screen (window),
6748                                     monitor_num, &monitor);
6749
6750   *x = (monitor.width - w) / 2 + monitor.x;
6751   *y = (monitor.height - h) / 2 + monitor.y;
6752
6753   /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6754    * and WM decorations.
6755    */
6756   if (*x < monitor.x)
6757     *x = monitor.x;
6758   if (*y < monitor.y)
6759     *y = monitor.y;
6760 }
6761
6762 static void
6763 clamp (gint *base,
6764        gint  extent,
6765        gint  clamp_base,
6766        gint  clamp_extent)
6767 {
6768   if (extent > clamp_extent)
6769     /* Center */
6770     *base = clamp_base + clamp_extent/2 - extent/2;
6771   else if (*base < clamp_base)
6772     *base = clamp_base;
6773   else if (*base + extent > clamp_base + clamp_extent)
6774     *base = clamp_base + clamp_extent - extent;
6775 }
6776
6777 static void
6778 clamp_window_to_rectangle (gint               *x,
6779                            gint               *y,
6780                            gint                w,
6781                            gint                h,
6782                            const GdkRectangle *rect)
6783 {
6784 #ifdef DEBUGGING_OUTPUT
6785   g_print ("%s: %+d%+d %dx%d: %+d%+d: %dx%d", G_STRFUNC, rect->x, rect->y, rect->width, rect->height, *x, *y, w, h);
6786 #endif
6787
6788   /* If it is too large, center it. If it fits on the monitor but is
6789    * partially outside, move it to the closest edge. Do this
6790    * separately in x and y directions.
6791    */
6792   clamp (x, w, rect->x, rect->width);
6793   clamp (y, h, rect->y, rect->height);
6794 #ifdef DEBUGGING_OUTPUT
6795   g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6796 #endif
6797 }
6798
6799
6800 static void
6801 gtk_window_compute_configure_request (GtkWindow    *window,
6802                                       GdkRectangle *request,
6803                                       GdkGeometry  *geometry,
6804                                       guint        *flags)
6805 {
6806   GtkWindowPrivate *priv = window->priv;
6807   GdkGeometry new_geometry;
6808   guint new_flags;
6809   int w, h;
6810   GtkWindowPosition pos;
6811   GtkWidget *parent_widget;
6812   GtkWindowGeometryInfo *info;
6813   GdkScreen *screen;
6814   int x, y;
6815
6816   screen = gtk_window_check_screen (window);
6817
6818   gtk_window_compute_hints (window, &new_geometry, &new_flags);
6819   gtk_window_compute_configure_request_size (window,
6820                                              &new_geometry, new_flags,
6821                                              &w, &h);
6822
6823   gtk_window_constrain_size (window,
6824                              &new_geometry, new_flags,
6825                              w, h,
6826                              &w, &h);
6827
6828   parent_widget = (GtkWidget*) priv->transient_parent;
6829
6830   pos = get_effective_position (window);
6831   info = gtk_window_get_geometry_info (window, FALSE);
6832
6833   /* by default, don't change position requested */
6834   if (info)
6835     {
6836       x = info->last.configure_request.x;
6837       y = info->last.configure_request.y;
6838     }
6839   else
6840     {
6841       x = 0;
6842       y = 0;
6843     }
6844
6845
6846   if (priv->need_default_position)
6847     {
6848
6849       /* FIXME this all interrelates with window gravity.
6850        * For most of them I think we want to set GRAVITY_CENTER.
6851        *
6852        * Not sure how to go about that.
6853        */
6854       switch (pos)
6855         {
6856           /* here we are only handling CENTER_ALWAYS
6857            * as it relates to default positioning,
6858            * where it's equivalent to simply CENTER
6859            */
6860         case GTK_WIN_POS_CENTER_ALWAYS:
6861         case GTK_WIN_POS_CENTER:
6862           center_window_on_monitor (window, w, h, &x, &y);
6863           break;
6864
6865         case GTK_WIN_POS_CENTER_ON_PARENT:
6866           {
6867             GtkAllocation allocation;
6868             GdkWindow *gdk_window;
6869             gint monitor_num;
6870             GdkRectangle monitor;
6871             gint ox, oy;
6872
6873             g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6874
6875             gdk_window = gtk_widget_get_window (parent_widget);
6876
6877             if (gdk_window != NULL)
6878               monitor_num = gdk_screen_get_monitor_at_window (screen,
6879                                                               gdk_window);
6880             else
6881               monitor_num = -1;
6882
6883             gdk_window_get_origin (gdk_window,
6884                                    &ox, &oy);
6885
6886             gtk_widget_get_allocation (parent_widget, &allocation);
6887             x = ox + (allocation.width - w) / 2;
6888             y = oy + (allocation.height - h) / 2;
6889
6890             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6891              * WM decorations. If parent wasn't on a monitor, just
6892              * give up.
6893              */
6894             if (monitor_num >= 0)
6895               {
6896                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6897                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6898               }
6899           }
6900           break;
6901
6902         case GTK_WIN_POS_MOUSE:
6903           {
6904             gint screen_width = gdk_screen_get_width (screen);
6905             gint screen_height = gdk_screen_get_height (screen);
6906             gint monitor_num;
6907             GdkRectangle monitor;
6908             GdkDisplay *display;
6909             GdkDeviceManager *device_manager;
6910             GdkDevice *pointer;
6911             GdkScreen *pointer_screen;
6912             gint px, py;
6913
6914             display = gdk_screen_get_display (screen);
6915             device_manager = gdk_display_get_device_manager (display);
6916             pointer = gdk_device_manager_get_client_pointer (device_manager);
6917
6918             gdk_device_get_position (pointer,
6919                                      &pointer_screen,
6920                                      &px, &py);
6921
6922             if (pointer_screen == screen)
6923               monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6924             else
6925               monitor_num = -1;
6926
6927             x = px - w / 2;
6928             y = py - h / 2;
6929             x = CLAMP (x, 0, screen_width - w);
6930             y = CLAMP (y, 0, screen_height - h);
6931
6932             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6933              * WM decorations. Don't try to figure out what's going
6934              * on if the mouse wasn't inside a monitor.
6935              */
6936             if (monitor_num >= 0)
6937               {
6938                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6939                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6940               }
6941           }
6942           break;
6943
6944         default:
6945           break;
6946         }
6947     } /* if (priv->need_default_position) */
6948
6949   if (priv->need_default_position && info &&
6950       info->initial_pos_set)
6951     {
6952       x = info->initial_x;
6953       y = info->initial_y;
6954       gtk_window_constrain_position (window, w, h, &x, &y);
6955     }
6956
6957   request->x = x;
6958   request->y = y;
6959   request->width = w;
6960   request->height = h;
6961
6962   if (geometry)
6963     *geometry = new_geometry;
6964   if (flags)
6965     *flags = new_flags;
6966 }
6967
6968 static void
6969 gtk_window_constrain_position (GtkWindow    *window,
6970                                gint          new_width,
6971                                gint          new_height,
6972                                gint         *x,
6973                                gint         *y)
6974 {
6975   GtkWindowPrivate *priv = window->priv;
6976
6977   /* See long comments in gtk_window_move_resize()
6978    * on when it's safe to call this function.
6979    */
6980   if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6981     {
6982       gint center_x, center_y;
6983
6984       center_window_on_monitor (window, new_width, new_height, &center_x, &center_y);
6985       
6986       *x = center_x;
6987       *y = center_y;
6988     }
6989 }
6990
6991 static void
6992 gtk_window_move_resize (GtkWindow *window)
6993 {
6994   /* Overview:
6995    *
6996    * First we determine whether any information has changed that would
6997    * cause us to revise our last configure request.  If we would send
6998    * a different configure request from last time, then
6999    * configure_request_size_changed = TRUE or
7000    * configure_request_pos_changed = TRUE. configure_request_size_changed
7001    * may be true due to new hints, a gtk_window_resize(), or whatever.
7002    * configure_request_pos_changed may be true due to gtk_window_set_position()
7003    * or gtk_window_move().
7004    *
7005    * If the configure request has changed, we send off a new one.  To
7006    * ensure GTK+ invariants are maintained (resize queue does what it
7007    * should), we go ahead and size_allocate the requested size in this
7008    * function.
7009    *
7010    * If the configure request has not changed, we don't ever resend
7011    * it, because it could mean fighting the user or window manager.
7012    *
7013    * 
7014    *   To prepare the configure request, we come up with a base size/pos:
7015    *      - the one from gtk_window_move()/gtk_window_resize()
7016    *      - else default_width, default_height if we haven't ever
7017    *        been mapped
7018    *      - else the size request if we haven't ever been mapped,
7019    *        as a substitute default size
7020    *      - else the current size of the window, as received from
7021    *        configure notifies (i.e. the current allocation)
7022    *
7023    *   If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
7024    *   the position request to be centered.
7025    */
7026   GtkWindowPrivate *priv = window->priv;
7027   GtkAllocation allocation;
7028   GtkWidget *widget;
7029   GtkContainer *container;
7030   GtkWindowGeometryInfo *info;
7031   GdkGeometry new_geometry;
7032   GdkWindow *gdk_window;
7033   guint new_flags;
7034   GdkRectangle new_request;
7035   gboolean configure_request_size_changed;
7036   gboolean configure_request_pos_changed;
7037   gboolean hints_changed; /* do we need to send these again */
7038   GtkWindowLastGeometryInfo saved_last_info;
7039   
7040   widget = GTK_WIDGET (window);
7041
7042   gdk_window = gtk_widget_get_window (widget);
7043   container = GTK_CONTAINER (widget);
7044   info = gtk_window_get_geometry_info (window, TRUE);
7045   
7046   configure_request_size_changed = FALSE;
7047   configure_request_pos_changed = FALSE;
7048   
7049   gtk_window_compute_configure_request (window, &new_request,
7050                                         &new_geometry, &new_flags);  
7051   
7052   /* This check implies the invariant that we never set info->last
7053    * without setting the hints and sending off a configure request.
7054    *
7055    * If we change info->last without sending the request, we may
7056    * miss a request.
7057    */
7058   if (info->last.configure_request.x != new_request.x ||
7059       info->last.configure_request.y != new_request.y)
7060     configure_request_pos_changed = TRUE;
7061
7062   if ((info->last.configure_request.width != new_request.width ||
7063        info->last.configure_request.height != new_request.height))
7064     configure_request_size_changed = TRUE;
7065   
7066   hints_changed = FALSE;
7067   
7068   if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
7069                                  &new_geometry, new_flags))
7070     {
7071       hints_changed = TRUE;
7072     }
7073   
7074   /* Position Constraints
7075    * ====================
7076    * 
7077    * POS_CENTER_ALWAYS is conceptually a constraint rather than
7078    * a default. The other POS_ values are used only when the
7079    * window is shown, not after that.
7080    * 
7081    * However, we can't implement a position constraint as
7082    * "anytime the window size changes, center the window"
7083    * because this may well end up fighting the WM or user.  In
7084    * fact it gets in an infinite loop with at least one WM.
7085    *
7086    * Basically, applications are in no way in a position to
7087    * constrain the position of a window, with one exception:
7088    * override redirect windows. (Really the intended purpose
7089    * of CENTER_ALWAYS anyhow, I would think.)
7090    *
7091    * So the way we implement this "constraint" is to say that when WE
7092    * cause a move or resize, i.e. we make a configure request changing
7093    * window size, we recompute the CENTER_ALWAYS position to reflect
7094    * the new window size, and include it in our request.  Also, if we
7095    * just turned on CENTER_ALWAYS we snap to center with a new
7096    * request.  Otherwise, if we are just NOTIFIED of a move or resize
7097    * done by someone else e.g. the window manager, we do NOT send a
7098    * new configure request.
7099    *
7100    * For override redirect windows, this works fine; all window
7101    * sizes are from our configure requests. For managed windows,
7102    * it is at least semi-sane, though who knows what the
7103    * app author is thinking.
7104    */
7105
7106   /* This condition should be kept in sync with the condition later on
7107    * that determines whether we send a configure request.  i.e. we
7108    * should do this position constraining anytime we were going to
7109    * send a configure request anyhow, plus when constraints have
7110    * changed.
7111    */
7112   if (configure_request_pos_changed ||
7113       configure_request_size_changed ||
7114       hints_changed ||
7115       info->position_constraints_changed)
7116     {
7117       /* We request the constrained position if:
7118        *  - we were changing position, and need to clamp
7119        *    the change to the constraint
7120        *  - we're changing the size anyway
7121        *  - set_position() was called to toggle CENTER_ALWAYS on
7122        */
7123
7124       gtk_window_constrain_position (window,
7125                                      new_request.width,
7126                                      new_request.height,
7127                                      &new_request.x,
7128                                      &new_request.y);
7129       
7130       /* Update whether we need to request a move */
7131       if (info->last.configure_request.x != new_request.x ||
7132           info->last.configure_request.y != new_request.y)
7133         configure_request_pos_changed = TRUE;
7134       else
7135         configure_request_pos_changed = FALSE;
7136     }
7137
7138 #if 0
7139   if (priv->type == GTK_WINDOW_TOPLEVEL)
7140     {
7141       int notify_x, notify_y;
7142
7143       /* this is the position from the last configure notify */
7144       gdk_window_get_position (widget->window, &notify_x, &notify_y);
7145     
7146       g_message ("--- %s ---\n"
7147                  "last  : %d,%d\t%d x %d\n"
7148                  "this  : %d,%d\t%d x %d\n"
7149                  "alloc : %d,%d\t%d x %d\n"
7150                  "req   :      \t%d x %d\n"
7151                  "resize:      \t%d x %d\n" 
7152                  "size_changed: %d pos_changed: %d hints_changed: %d\n"
7153                  "configure_notify_received: %d\n"
7154                  "configure_request_count: %d\n"
7155                  "position_constraints_changed: %d\n",
7156                  priv->title ? priv->title : "(no title)",
7157                  info->last.configure_request.x,
7158                  info->last.configure_request.y,
7159                  info->last.configure_request.width,
7160                  info->last.configure_request.height,
7161                  new_request.x,
7162                  new_request.y,
7163                  new_request.width,
7164                  new_request.height,
7165                  notify_x, notify_y,
7166                  widget->allocation.width,
7167                  widget->allocation.height,
7168                  widget->requisition.width,
7169                  widget->requisition.height,
7170                  info->resize_width,
7171                  info->resize_height,
7172                  configure_request_pos_changed,
7173                  configure_request_size_changed,
7174                  hints_changed,
7175                  priv->configure_notify_received,
7176                  priv->configure_request_count,
7177                  info->position_constraints_changed);
7178     }
7179 #endif
7180   
7181   saved_last_info = info->last;
7182   info->last.geometry = new_geometry;
7183   info->last.flags = new_flags;
7184   info->last.configure_request = new_request;
7185   
7186   /* need to set PPosition so the WM will look at our position,
7187    * but we don't want to count PPosition coming and going as a hints
7188    * change for future iterations. So we saved info->last prior to
7189    * this.
7190    */
7191   
7192   /* Also, if the initial position was explicitly set, then we always
7193    * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
7194    * work.
7195    */
7196
7197   /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
7198    * this is an initial map
7199    */
7200   
7201   if ((configure_request_pos_changed ||
7202        info->initial_pos_set ||
7203        (priv->need_default_position &&
7204         get_effective_position (window) != GTK_WIN_POS_NONE)) &&
7205       (new_flags & GDK_HINT_POS) == 0)
7206     {
7207       new_flags |= GDK_HINT_POS;
7208       hints_changed = TRUE;
7209     }
7210   
7211   /* Set hints if necessary
7212    */
7213   if (hints_changed)
7214     gdk_window_set_geometry_hints (gdk_window,
7215                                    &new_geometry,
7216                                    new_flags);
7217
7218   gtk_widget_get_allocation (widget, &allocation);
7219
7220   /* handle resizing/moving and widget tree allocation
7221    */
7222   if (priv->configure_notify_received)
7223     { 
7224       /* If we have received a configure event since
7225        * the last time in this function, we need to
7226        * accept our new size and size_allocate child widgets.
7227        * (see gtk_window_configure_event() for more details).
7228        *
7229        * 1 or more configure notifies may have been received.
7230        * Also, configure_notify_received will only be TRUE
7231        * if all expected configure notifies have been received
7232        * (one per configure request), as an optimization.
7233        *
7234        */
7235       priv->configure_notify_received = FALSE;
7236
7237       /* gtk_window_configure_event() filled in widget->allocation */
7238       gtk_widget_size_allocate (widget, &allocation);
7239
7240       set_grip_position (window);
7241       update_grip_visibility (window);
7242
7243       gdk_window_process_updates (gdk_window, TRUE);
7244
7245       gdk_window_configure_finished (gdk_window);
7246
7247       /* If the configure request changed, it means that
7248        * we either:
7249        *   1) coincidentally changed hints or widget properties
7250        *      impacting the configure request before getting
7251        *      a configure notify, or
7252        *   2) some broken widget is changing its size request
7253        *      during size allocation, resulting in
7254        *      a false appearance of changed configure request.
7255        *
7256        * For 1), we could just go ahead and ask for the
7257        * new size right now, but doing that for 2)
7258        * might well be fighting the user (and can even
7259        * trigger a loop). Since we really don't want to
7260        * do that, we requeue a resize in hopes that
7261        * by the time it gets handled, the child has seen
7262        * the light and is willing to go along with the
7263        * new size. (this happens for the zvt widget, since
7264        * the size_allocate() above will have stored the
7265        * requisition corresponding to the new size in the
7266        * zvt widget)
7267        *
7268        * This doesn't buy us anything for 1), but it shouldn't
7269        * hurt us too badly, since it is what would have
7270        * happened if we had gotten the configure event before
7271        * the new size had been set.
7272        */
7273
7274       if (configure_request_size_changed ||
7275           configure_request_pos_changed)
7276         {
7277           /* Don't change the recorded last info after all, because we
7278            * haven't actually updated to the new info yet - we decided
7279            * to postpone our configure request until later.
7280            */
7281           info->last = saved_last_info;
7282           
7283           gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7284         }
7285
7286       return;                   /* Bail out, we didn't really process the move/resize */
7287     }
7288   else if ((configure_request_size_changed || hints_changed) &&
7289            (allocation.width != new_request.width || allocation.height != new_request.height))
7290
7291     {
7292       /* We are in one of the following situations:
7293        * A. configure_request_size_changed
7294        *    our requisition has changed and we need a different window size,
7295        *    so we request it from the window manager.
7296        * B. !configure_request_size_changed && hints_changed
7297        *    the window manager rejects our size, but we have just changed the
7298        *    window manager hints, so there's a chance our request will
7299        *    be honoured this time, so we try again.
7300        *
7301        * However, if the new requisition is the same as the current allocation,
7302        * we don't request it again, since we won't get a ConfigureNotify back from
7303        * the window manager unless it decides to change our requisition. If
7304        * we don't get the ConfigureNotify back, the resize queue will never be run.
7305        */
7306
7307       /* Now send the configure request */
7308       if (configure_request_pos_changed)
7309         {
7310           gdk_window_move_resize (gdk_window,
7311                                   new_request.x, new_request.y,
7312                                   new_request.width, new_request.height);
7313         }
7314       else  /* only size changed */
7315         {
7316           gdk_window_resize (gdk_window,
7317                              new_request.width, new_request.height);
7318         }
7319
7320       if (priv->type == GTK_WINDOW_POPUP)
7321         {
7322           GtkAllocation allocation;
7323
7324           /* Directly size allocate for override redirect (popup) windows. */
7325           allocation.x = 0;
7326           allocation.y = 0;
7327           allocation.width = new_request.width;
7328           allocation.height = new_request.height;
7329
7330           gtk_widget_size_allocate (widget, &allocation);
7331
7332           gdk_window_process_updates (gdk_window, TRUE);
7333
7334           if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7335             gtk_widget_queue_draw (widget);
7336         }
7337       else
7338         {
7339           /* Increment the number of have-not-yet-received-notify requests */
7340           priv->configure_request_count += 1;
7341           gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7342
7343           /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7344            * configure event in response to our resizing request.
7345            * the configure event will cause a new resize with
7346            * ->configure_notify_received=TRUE.
7347            * until then, we want to
7348            * - discard expose events
7349            * - coalesce resizes for our children
7350            * - defer any window resizes until the configure event arrived
7351            * to achieve this, we queue a resize for the window, but remove its
7352            * resizing handler, so resizing will not be handled from the next
7353            * idle handler but when the configure event arrives.
7354            *
7355            * FIXME: we should also dequeue the pending redraws here, since
7356            * we handle those ourselves upon ->configure_notify_received==TRUE.
7357            */
7358           if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7359             {
7360               gtk_widget_queue_resize_no_redraw (widget);
7361               _gtk_container_dequeue_resize_handler (container);
7362             }
7363         }
7364     }
7365   else
7366     {
7367       /* Handle any position changes.
7368        */
7369       if (configure_request_pos_changed)
7370         {
7371           gdk_window_move (gdk_window,
7372                            new_request.x, new_request.y);
7373         }
7374
7375       /* And run the resize queue.
7376        */
7377       gtk_container_resize_children (container);
7378     }
7379   
7380   /* We have now processed a move/resize since the last position
7381    * constraint change, setting of the initial position, or resize.
7382    * (Not resetting these flags here can lead to infinite loops for
7383    * GTK_RESIZE_IMMEDIATE containers)
7384    */
7385   info->position_constraints_changed = FALSE;
7386   info->initial_pos_set = FALSE;
7387   info->resize_width = -1;
7388   info->resize_height = -1;
7389 }
7390
7391 /* Compare two sets of Geometry hints for equality.
7392  */
7393 static gboolean
7394 gtk_window_compare_hints (GdkGeometry *geometry_a,
7395                           guint        flags_a,
7396                           GdkGeometry *geometry_b,
7397                           guint        flags_b)
7398 {
7399   if (flags_a != flags_b)
7400     return FALSE;
7401   
7402   if ((flags_a & GDK_HINT_MIN_SIZE) &&
7403       (geometry_a->min_width != geometry_b->min_width ||
7404        geometry_a->min_height != geometry_b->min_height))
7405     return FALSE;
7406
7407   if ((flags_a & GDK_HINT_MAX_SIZE) &&
7408       (geometry_a->max_width != geometry_b->max_width ||
7409        geometry_a->max_height != geometry_b->max_height))
7410     return FALSE;
7411
7412   if ((flags_a & GDK_HINT_BASE_SIZE) &&
7413       (geometry_a->base_width != geometry_b->base_width ||
7414        geometry_a->base_height != geometry_b->base_height))
7415     return FALSE;
7416
7417   if ((flags_a & GDK_HINT_ASPECT) &&
7418       (geometry_a->min_aspect != geometry_b->min_aspect ||
7419        geometry_a->max_aspect != geometry_b->max_aspect))
7420     return FALSE;
7421
7422   if ((flags_a & GDK_HINT_RESIZE_INC) &&
7423       (geometry_a->width_inc != geometry_b->width_inc ||
7424        geometry_a->height_inc != geometry_b->height_inc))
7425     return FALSE;
7426
7427   if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7428       geometry_a->win_gravity != geometry_b->win_gravity)
7429     return FALSE;
7430
7431   return TRUE;
7432 }
7433
7434 void
7435 _gtk_window_constrain_size (GtkWindow   *window,
7436                             gint         width,
7437                             gint         height,
7438                             gint        *new_width,
7439                             gint        *new_height)
7440 {
7441   GtkWindowPrivate *priv;
7442   GtkWindowGeometryInfo *info;
7443
7444   g_return_if_fail (GTK_IS_WINDOW (window));
7445
7446   priv = window->priv;
7447
7448   info = priv->geometry_info;
7449   if (info)
7450     {
7451       GdkWindowHints flags = info->last.flags;
7452       GdkGeometry *geometry = &info->last.geometry;
7453       
7454       gtk_window_constrain_size (window,
7455                                  geometry,
7456                                  flags,
7457                                  width,
7458                                  height,
7459                                  new_width,
7460                                  new_height);
7461     }
7462 }
7463
7464 static void 
7465 gtk_window_constrain_size (GtkWindow   *window,
7466                            GdkGeometry *geometry,
7467                            guint        flags,
7468                            gint         width,
7469                            gint         height,
7470                            gint        *new_width,
7471                            gint        *new_height)
7472 {
7473   gdk_window_constrain_size (geometry, flags, width, height,
7474                              new_width, new_height);
7475 }
7476
7477 /* Compute the set of geometry hints and flags for a window
7478  * based on the application set geometry, and requisition
7479  * of the window. gtk_widget_get_preferred_size() must have been
7480  * called first.
7481  */
7482 static void
7483 gtk_window_compute_hints (GtkWindow   *window,
7484                           GdkGeometry *new_geometry,
7485                           guint       *new_flags)
7486 {
7487   GtkWindowPrivate *priv = window->priv;
7488   GtkWidget *widget;
7489   gint extra_width = 0;
7490   gint extra_height = 0;
7491   GtkWindowGeometryInfo *geometry_info;
7492   GtkRequisition requisition;
7493
7494   widget = GTK_WIDGET (window);
7495
7496   gtk_widget_get_preferred_size (widget, &requisition, NULL);
7497   geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7498
7499   if (geometry_info)
7500     {
7501       *new_flags = geometry_info->mask;
7502       *new_geometry = geometry_info->geometry;
7503     }
7504   else
7505     {
7506       *new_flags = 0;
7507     }
7508   
7509   if (geometry_info && geometry_info->widget)
7510     {
7511       /* If the geometry widget is set, then the hints really apply to that
7512        * widget. This is pretty much meaningless unless the window layout
7513        * is such that the rest of the window adds fixed size borders to
7514        * the geometry widget. Our job is to figure the size of the borders;
7515        * We do that by asking how big the toplevel would be if the
7516        * geometry widget was *really big*.
7517        *
7518        *  +----------+
7519        *  |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7520        *  |GGGGG    B| in the border can confuse things
7521        *  |GGGGG    B|
7522        *  |         B|
7523        *  +----------+
7524        *
7525        *  +-----------+
7526        *  |AAAAAAAAA  | When the geometry widget is large, things are
7527        *  |GGGGGGGGGGB| clearer.
7528        *  |GGGGGGGGGGB|
7529        *  |GGGGGGGGGG |
7530        *  +-----------+
7531        */
7532 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7533       GtkRequisition requisition;
7534       int current_width, current_height;
7535
7536       _gtk_widget_override_size_request (geometry_info->widget,
7537                                          TEMPORARY_SIZE, TEMPORARY_SIZE,
7538                                          &current_width, &current_height);
7539       gtk_widget_get_preferred_size (widget,
7540                                      &requisition, NULL);
7541       _gtk_widget_restore_size_request (geometry_info->widget,
7542                                         current_width, current_height);
7543
7544       extra_width = requisition.width - TEMPORARY_SIZE;
7545       extra_height = requisition.height - TEMPORARY_SIZE;
7546
7547       if (extra_width < 0 || extra_height < 0)
7548         {
7549           g_warning("Toplevel size doesn't seem to directly depend on the "
7550                     "size of the geometry widget from gtk_window_set_geometry_hints(). "
7551                     "The geometry widget might not be in the window, or it might not "
7552                     "be packed into the window appropriately");
7553           extra_width = MAX(extra_width, 0);
7554           extra_height = MAX(extra_height, 0);
7555         }
7556 #undef TEMPORARY_SIZE
7557     }
7558
7559   /* We don't want to set GDK_HINT_POS in here, we just set it
7560    * in gtk_window_move_resize() when we want the position
7561    * honored.
7562    */
7563   
7564   if (*new_flags & GDK_HINT_BASE_SIZE)
7565     {
7566       new_geometry->base_width += extra_width;
7567       new_geometry->base_height += extra_height;
7568     }
7569   else
7570     {
7571       /* For simplicity, we always set the base hint, even when we
7572        * don't expect it to have any visible effect.
7573        * (Note: geometry_size_to_pixels() depends on this.)
7574        */
7575       *new_flags |= GDK_HINT_BASE_SIZE;
7576
7577       new_geometry->base_width = extra_width;
7578       new_geometry->base_height = extra_height;
7579
7580       /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7581        * base size is the minimum size */
7582       if (*new_flags & GDK_HINT_MIN_SIZE)
7583         {
7584           if (new_geometry->min_width > 0)
7585             new_geometry->base_width += new_geometry->min_width;
7586           if (new_geometry->min_height > 0)
7587             new_geometry->base_height += new_geometry->min_height;
7588         }
7589     }
7590
7591   /* Please use a good size for unresizable widgets, not the minimum one. */
7592   if (!priv->resizable)
7593     gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7594
7595   if (*new_flags & GDK_HINT_MIN_SIZE)
7596     {
7597       if (new_geometry->min_width < 0)
7598         new_geometry->min_width = requisition.width;
7599       else
7600         new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7601
7602       if (new_geometry->min_height < 0)
7603         new_geometry->min_height = requisition.height;
7604       else
7605         new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7606     }
7607   else
7608     {
7609       *new_flags |= GDK_HINT_MIN_SIZE;
7610       
7611       new_geometry->min_width = requisition.width;
7612       new_geometry->min_height = requisition.height;
7613     }
7614   
7615   if (*new_flags & GDK_HINT_MAX_SIZE)
7616     {
7617       if (new_geometry->max_width < 0)
7618         new_geometry->max_width = requisition.width;
7619       else
7620         new_geometry->max_width += extra_width;
7621
7622       if (new_geometry->max_height < 0)
7623         new_geometry->max_height = requisition.height;
7624       else
7625         new_geometry->max_height += extra_height;
7626     }
7627   else if (!priv->resizable)
7628     {
7629       *new_flags |= GDK_HINT_MAX_SIZE;
7630       
7631       new_geometry->max_width = requisition.width;
7632       new_geometry->max_height = requisition.height;
7633     }
7634
7635   *new_flags |= GDK_HINT_WIN_GRAVITY;
7636   new_geometry->win_gravity = priv->gravity;
7637 }
7638
7639 /***********************
7640  * Redrawing functions *
7641  ***********************/
7642
7643 static gboolean
7644 gtk_window_draw (GtkWidget *widget,
7645                  cairo_t   *cr)
7646 {
7647   GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7648   GtkStyleContext *context;
7649   gboolean ret = FALSE;
7650
7651   context = gtk_widget_get_style_context (widget);
7652
7653   if (!gtk_widget_get_app_paintable (widget) &&
7654       gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
7655     {
7656       gtk_style_context_save (context);
7657
7658       gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7659       gtk_render_background (context, cr, 0, 0,
7660                              gtk_widget_get_allocated_width (widget),
7661                              gtk_widget_get_allocated_height (widget));
7662
7663       gtk_style_context_restore (context);
7664     }
7665
7666   if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7667     ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7668
7669   if (priv->grip_window &&
7670       gtk_cairo_should_draw_window (cr, priv->grip_window))
7671     {
7672       GdkRectangle rect;
7673
7674       gtk_style_context_save (context);
7675       cairo_save (cr);
7676
7677       gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7678       gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7679
7680       gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7681       gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7682       gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7683
7684       cairo_restore (cr);
7685       gtk_style_context_restore (context);
7686     }
7687
7688   return ret;
7689 }
7690
7691 /**
7692  * gtk_window_present:
7693  * @window: a #GtkWindow
7694  *
7695  * Presents a window to the user. This may mean raising the window
7696  * in the stacking order, deiconifying it, moving it to the current
7697  * desktop, and/or giving it the keyboard focus, possibly dependent
7698  * on the user's platform, window manager, and preferences.
7699  *
7700  * If @window is hidden, this function calls gtk_widget_show()
7701  * as well.
7702  * 
7703  * This function should be used when the user tries to open a window
7704  * that's already open. Say for example the preferences dialog is
7705  * currently open, and the user chooses Preferences from the menu
7706  * a second time; use gtk_window_present() to move the already-open dialog
7707  * where the user can see it.
7708  *
7709  * If you are calling this function in response to a user interaction,
7710  * it is preferable to use gtk_window_present_with_time().
7711  * 
7712  **/
7713 void
7714 gtk_window_present (GtkWindow *window)
7715 {
7716   gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7717 }
7718
7719 /**
7720  * gtk_window_present_with_time:
7721  * @window: a #GtkWindow
7722  * @timestamp: the timestamp of the user interaction (typically a 
7723  *   button or key press event) which triggered this call
7724  *
7725  * Presents a window to the user in response to a user interaction.
7726  * If you need to present a window without a timestamp, use 
7727  * gtk_window_present(). See gtk_window_present() for details. 
7728  * 
7729  * Since: 2.8
7730  **/
7731 void
7732 gtk_window_present_with_time (GtkWindow *window,
7733                               guint32    timestamp)
7734 {
7735   GtkWindowPrivate *priv;
7736   GtkWidget *widget;
7737   GdkWindow *gdk_window;
7738
7739   g_return_if_fail (GTK_IS_WINDOW (window));
7740
7741   priv = window->priv;
7742   widget = GTK_WIDGET (window);
7743
7744   if (gtk_widget_get_visible (widget))
7745     {
7746       gdk_window = gtk_widget_get_window (widget);
7747
7748       g_assert (gdk_window != NULL);
7749
7750       gdk_window_show (gdk_window);
7751
7752       /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7753       if (timestamp == GDK_CURRENT_TIME)
7754         {
7755 #ifdef GDK_WINDOWING_X11
7756           if (GDK_IS_X11_WINDOW(gdk_window))
7757             {
7758               GdkDisplay *display;
7759
7760               display = gtk_widget_get_display (GTK_WIDGET (window));
7761               timestamp = gdk_x11_display_get_user_time (display);
7762             }
7763           else
7764 #endif
7765             timestamp = gtk_get_current_event_time ();
7766         }
7767
7768       gdk_window_focus (gdk_window, timestamp);
7769     }
7770   else
7771     {
7772       priv->initial_timestamp = timestamp;
7773       gtk_widget_show (widget);
7774     }
7775 }
7776
7777 /**
7778  * gtk_window_iconify:
7779  * @window: a #GtkWindow
7780  *
7781  * Asks to iconify (i.e. minimize) the specified @window. Note that
7782  * you shouldn't assume the window is definitely iconified afterward,
7783  * because other entities (e.g. the user or <link
7784  * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7785  * again, or there may not be a window manager in which case
7786  * iconification isn't possible, etc. But normally the window will end
7787  * up iconified. Just don't write code that crashes if not.
7788  *
7789  * It's permitted to call this function before showing a window,
7790  * in which case the window will be iconified before it ever appears
7791  * onscreen.
7792  *
7793  * You can track iconification via the "window-state-event" signal
7794  * on #GtkWidget.
7795  * 
7796  **/
7797 void
7798 gtk_window_iconify (GtkWindow *window)
7799 {
7800   GtkWindowPrivate *priv;
7801   GtkWidget *widget;
7802   GdkWindow *toplevel;
7803   
7804   g_return_if_fail (GTK_IS_WINDOW (window));
7805
7806   priv = window->priv;
7807   widget = GTK_WIDGET (window);
7808
7809   priv->iconify_initially = TRUE;
7810
7811   toplevel = gtk_widget_get_window (widget);
7812
7813   if (toplevel != NULL)
7814     gdk_window_iconify (toplevel);
7815 }
7816
7817 /**
7818  * gtk_window_deiconify:
7819  * @window: a #GtkWindow
7820  *
7821  * Asks to deiconify (i.e. unminimize) the specified @window. Note
7822  * that you shouldn't assume the window is definitely deiconified
7823  * afterward, because other entities (e.g. the user or <link
7824  * linkend="gtk-X11-arch">window manager</link>) could iconify it
7825  * again before your code which assumes deiconification gets to run.
7826  *
7827  * You can track iconification via the "window-state-event" signal
7828  * on #GtkWidget.
7829  **/
7830 void
7831 gtk_window_deiconify (GtkWindow *window)
7832 {
7833   GtkWindowPrivate *priv;
7834   GtkWidget *widget;
7835   GdkWindow *toplevel;
7836   
7837   g_return_if_fail (GTK_IS_WINDOW (window));
7838
7839   priv = window->priv;
7840   widget = GTK_WIDGET (window);
7841
7842   priv->iconify_initially = FALSE;
7843
7844   toplevel = gtk_widget_get_window (widget);
7845
7846   if (toplevel != NULL)
7847     gdk_window_deiconify (toplevel);
7848 }
7849
7850 /**
7851  * gtk_window_stick:
7852  * @window: a #GtkWindow
7853  *
7854  * Asks to stick @window, which means that it will appear on all user
7855  * desktops. Note that you shouldn't assume the window is definitely
7856  * stuck afterward, because other entities (e.g. the user or <link
7857  * linkend="gtk-X11-arch">window manager</link>) could unstick it
7858  * again, and some window managers do not support sticking
7859  * windows. But normally the window will end up stuck. Just don't
7860  * write code that crashes if not.
7861  *
7862  * It's permitted to call this function before showing a window.
7863  *
7864  * You can track stickiness via the "window-state-event" signal
7865  * on #GtkWidget.
7866  * 
7867  **/
7868 void
7869 gtk_window_stick (GtkWindow *window)
7870 {
7871   GtkWindowPrivate *priv;
7872   GtkWidget *widget;
7873   GdkWindow *toplevel;
7874   
7875   g_return_if_fail (GTK_IS_WINDOW (window));
7876
7877   priv = window->priv;
7878   widget = GTK_WIDGET (window);
7879
7880   priv->stick_initially = TRUE;
7881
7882   toplevel = gtk_widget_get_window (widget);
7883
7884   if (toplevel != NULL)
7885     gdk_window_stick (toplevel);
7886 }
7887
7888 /**
7889  * gtk_window_unstick:
7890  * @window: a #GtkWindow
7891  *
7892  * Asks to unstick @window, which means that it will appear on only
7893  * one of the user's desktops. Note that you shouldn't assume the
7894  * window is definitely unstuck afterward, because other entities
7895  * (e.g. the user or <link linkend="gtk-X11-arch">window
7896  * manager</link>) could stick it again. But normally the window will
7897  * end up stuck. Just don't write code that crashes if not.
7898  *
7899  * You can track stickiness via the "window-state-event" signal
7900  * on #GtkWidget.
7901  * 
7902  **/
7903 void
7904 gtk_window_unstick (GtkWindow *window)
7905 {
7906   GtkWindowPrivate *priv;
7907   GtkWidget *widget;
7908   GdkWindow *toplevel;
7909   
7910   g_return_if_fail (GTK_IS_WINDOW (window));
7911
7912   priv = window->priv;
7913   widget = GTK_WIDGET (window);
7914
7915   priv->stick_initially = FALSE;
7916
7917   toplevel = gtk_widget_get_window (widget);
7918
7919   if (toplevel != NULL)
7920     gdk_window_unstick (toplevel);
7921 }
7922
7923 /**
7924  * gtk_window_maximize:
7925  * @window: a #GtkWindow
7926  *
7927  * Asks to maximize @window, so that it becomes full-screen. Note that
7928  * you shouldn't assume the window is definitely maximized afterward,
7929  * because other entities (e.g. the user or <link
7930  * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7931  * again, and not all window managers support maximization. But
7932  * normally the window will end up maximized. Just don't write code
7933  * that crashes if not.
7934  *
7935  * It's permitted to call this function before showing a window,
7936  * in which case the window will be maximized when it appears onscreen
7937  * initially.
7938  *
7939  * You can track maximization via the "window-state-event" signal
7940  * on #GtkWidget.
7941  * 
7942  **/
7943 void
7944 gtk_window_maximize (GtkWindow *window)
7945 {
7946   GtkWindowPrivate *priv;
7947   GtkWidget *widget;
7948   GdkWindow *toplevel;
7949   
7950   g_return_if_fail (GTK_IS_WINDOW (window));
7951
7952   priv = window->priv;
7953   widget = GTK_WIDGET (window);
7954
7955   priv->maximize_initially = TRUE;
7956
7957   toplevel = gtk_widget_get_window (widget);
7958
7959   if (toplevel != NULL)
7960     gdk_window_maximize (toplevel);
7961 }
7962
7963 /**
7964  * gtk_window_unmaximize:
7965  * @window: a #GtkWindow
7966  *
7967  * Asks to unmaximize @window. Note that you shouldn't assume the
7968  * window is definitely unmaximized afterward, because other entities
7969  * (e.g. the user or <link linkend="gtk-X11-arch">window
7970  * manager</link>) could maximize it again, and not all window
7971  * managers honor requests to unmaximize. But normally the window will
7972  * end up unmaximized. Just don't write code that crashes if not.
7973  *
7974  * You can track maximization via the "window-state-event" signal
7975  * on #GtkWidget.
7976  * 
7977  **/
7978 void
7979 gtk_window_unmaximize (GtkWindow *window)
7980 {
7981   GtkWindowPrivate *priv;
7982   GtkWidget *widget;
7983   GdkWindow *toplevel;
7984   
7985   g_return_if_fail (GTK_IS_WINDOW (window));
7986
7987   priv = window->priv;
7988   widget = GTK_WIDGET (window);
7989
7990   priv->maximize_initially = FALSE;
7991
7992   toplevel = gtk_widget_get_window (widget);
7993
7994   if (toplevel != NULL)
7995     gdk_window_unmaximize (toplevel);
7996 }
7997
7998 /**
7999  * gtk_window_fullscreen:
8000  * @window: a #GtkWindow
8001  *
8002  * Asks to place @window in the fullscreen state. Note that you
8003  * shouldn't assume the window is definitely full screen afterward,
8004  * because other entities (e.g. the user or <link
8005  * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
8006  * again, and not all window managers honor requests to fullscreen
8007  * windows. But normally the window will end up fullscreen. Just
8008  * don't write code that crashes if not.
8009  *
8010  * You can track the fullscreen state via the "window-state-event" signal
8011  * on #GtkWidget.
8012  * 
8013  * Since: 2.2
8014  **/
8015 void
8016 gtk_window_fullscreen (GtkWindow *window)
8017 {
8018   GtkWindowPrivate *priv;
8019   GtkWidget *widget;
8020   GdkWindow *toplevel;
8021
8022   g_return_if_fail (GTK_IS_WINDOW (window));
8023
8024   priv = window->priv;
8025   widget = GTK_WIDGET (window);
8026
8027   priv->fullscreen_initially = TRUE;
8028
8029   toplevel = gtk_widget_get_window (widget);
8030
8031   if (toplevel != NULL)
8032     gdk_window_fullscreen (toplevel);
8033 }
8034
8035 /**
8036  * gtk_window_unfullscreen:
8037  * @window: a #GtkWindow
8038  *
8039  * Asks to toggle off the fullscreen state for @window. Note that you
8040  * shouldn't assume the window is definitely not full screen
8041  * afterward, because other entities (e.g. the user or <link
8042  * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
8043  * again, and not all window managers honor requests to unfullscreen
8044  * windows. But normally the window will end up restored to its normal
8045  * state. Just don't write code that crashes if not.
8046  *
8047  * You can track the fullscreen state via the "window-state-event" signal
8048  * on #GtkWidget.
8049  * 
8050  * Since: 2.2
8051  **/
8052 void
8053 gtk_window_unfullscreen (GtkWindow *window)
8054 {
8055   GtkWidget *widget;
8056   GdkWindow *toplevel;
8057   GtkWindowPrivate *priv;
8058
8059   g_return_if_fail (GTK_IS_WINDOW (window));
8060
8061   priv = window->priv;
8062   widget = GTK_WIDGET (window);
8063
8064   priv->fullscreen_initially = FALSE;
8065
8066   toplevel = gtk_widget_get_window (widget);
8067
8068   if (toplevel != NULL)
8069     gdk_window_unfullscreen (toplevel);
8070 }
8071
8072 /**
8073  * gtk_window_set_keep_above:
8074  * @window: a #GtkWindow
8075  * @setting: whether to keep @window above other windows
8076  *
8077  * Asks to keep @window above, so that it stays on top. Note that
8078  * you shouldn't assume the window is definitely above afterward,
8079  * because other entities (e.g. the user or <link
8080  * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
8081  * and not all window managers support keeping windows above. But
8082  * normally the window will end kept above. Just don't write code
8083  * that crashes if not.
8084  *
8085  * It's permitted to call this function before showing a window,
8086  * in which case the window will be kept above when it appears onscreen
8087  * initially.
8088  *
8089  * You can track the above state via the "window-state-event" signal
8090  * on #GtkWidget.
8091  *
8092  * Note that, according to the <ulink 
8093  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
8094  * Manager Hints</ulink> specification, the above state is mainly meant 
8095  * for user preferences and should not be used by applications e.g. for 
8096  * drawing attention to their dialogs.
8097  *
8098  * Since: 2.4
8099  **/
8100 void
8101 gtk_window_set_keep_above (GtkWindow *window,
8102                            gboolean   setting)
8103 {
8104   GtkWidget *widget;
8105   GtkWindowPrivate *priv;
8106   GdkWindow *toplevel;
8107
8108   g_return_if_fail (GTK_IS_WINDOW (window));
8109
8110   priv = window->priv;
8111   widget = GTK_WIDGET (window);
8112
8113   priv->above_initially = setting != FALSE;
8114   if (setting)
8115     priv->below_initially = FALSE;
8116
8117   toplevel = gtk_widget_get_window (widget);
8118
8119   if (toplevel != NULL)
8120     gdk_window_set_keep_above (toplevel, setting);
8121 }
8122
8123 /**
8124  * gtk_window_set_keep_below:
8125  * @window: a #GtkWindow
8126  * @setting: whether to keep @window below other windows
8127  *
8128  * Asks to keep @window below, so that it stays in bottom. Note that
8129  * you shouldn't assume the window is definitely below afterward,
8130  * because other entities (e.g. the user or <link
8131  * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8132  * and not all window managers support putting windows below. But
8133  * normally the window will be kept below. Just don't write code
8134  * that crashes if not.
8135  *
8136  * It's permitted to call this function before showing a window,
8137  * in which case the window will be kept below when it appears onscreen
8138  * initially.
8139  *
8140  * You can track the below state via the "window-state-event" signal
8141  * on #GtkWidget.
8142  *
8143  * Note that, according to the <ulink 
8144  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
8145  * Manager Hints</ulink> specification, the above state is mainly meant 
8146  * for user preferences and should not be used by applications e.g. for 
8147  * drawing attention to their dialogs.
8148  *
8149  * Since: 2.4
8150  **/
8151 void
8152 gtk_window_set_keep_below (GtkWindow *window,
8153                            gboolean   setting)
8154 {
8155   GtkWidget *widget;
8156   GtkWindowPrivate *priv;
8157   GdkWindow *toplevel;
8158
8159   g_return_if_fail (GTK_IS_WINDOW (window));
8160
8161   priv = window->priv;
8162   widget = GTK_WIDGET (window);
8163
8164   priv->below_initially = setting != FALSE;
8165   if (setting)
8166     priv->above_initially = FALSE;
8167
8168   toplevel = gtk_widget_get_window (widget);
8169
8170   if (toplevel != NULL)
8171     gdk_window_set_keep_below (toplevel, setting);
8172 }
8173
8174 /**
8175  * gtk_window_set_resizable:
8176  * @window: a #GtkWindow
8177  * @resizable: %TRUE if the user can resize this window
8178  *
8179  * Sets whether the user can resize a window. Windows are user resizable
8180  * by default.
8181  **/
8182 void
8183 gtk_window_set_resizable (GtkWindow *window,
8184                           gboolean   resizable)
8185 {
8186   GtkWindowPrivate *priv;
8187
8188   g_return_if_fail (GTK_IS_WINDOW (window));
8189
8190   priv = window->priv;
8191
8192   resizable = (resizable != FALSE);
8193
8194   if (priv->resizable != resizable)
8195     {
8196       priv->resizable = (resizable != FALSE);
8197
8198       update_grip_visibility (window);
8199
8200       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8201
8202       g_object_notify (G_OBJECT (window), "resizable");
8203     }
8204 }
8205
8206 /**
8207  * gtk_window_get_resizable:
8208  * @window: a #GtkWindow
8209  *
8210  * Gets the value set by gtk_window_set_resizable().
8211  *
8212  * Return value: %TRUE if the user can resize the window
8213  **/
8214 gboolean
8215 gtk_window_get_resizable (GtkWindow *window)
8216 {
8217   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8218
8219   return window->priv->resizable;
8220 }
8221
8222 /**
8223  * gtk_window_set_gravity:
8224  * @window: a #GtkWindow
8225  * @gravity: window gravity
8226  *
8227  * Window gravity defines the meaning of coordinates passed to
8228  * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8229  * more details.
8230  *
8231  * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8232  * typically "do what you mean."
8233  *
8234  **/
8235 void
8236 gtk_window_set_gravity (GtkWindow *window,
8237                         GdkGravity gravity)
8238 {
8239   GtkWindowPrivate *priv;
8240
8241   g_return_if_fail (GTK_IS_WINDOW (window));
8242
8243   priv = window->priv;
8244
8245   if (gravity != priv->gravity)
8246     {
8247       priv->gravity = gravity;
8248
8249       /* gtk_window_move_resize() will adapt gravity
8250        */
8251       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8252
8253       g_object_notify (G_OBJECT (window), "gravity");
8254     }
8255 }
8256
8257 /**
8258  * gtk_window_get_gravity:
8259  * @window: a #GtkWindow
8260  *
8261  * Gets the value set by gtk_window_set_gravity().
8262  *
8263  * Return value: (transfer none): window gravity
8264  **/
8265 GdkGravity
8266 gtk_window_get_gravity (GtkWindow *window)
8267 {
8268   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8269
8270   return window->priv->gravity;
8271 }
8272
8273 /**
8274  * gtk_window_begin_resize_drag:
8275  * @window: a #GtkWindow
8276  * @button: mouse button that initiated the drag
8277  * @edge: position of the resize control
8278  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8279  * @root_y: Y position where the user clicked to initiate the drag
8280  * @timestamp: timestamp from the click event that initiated the drag
8281  *
8282  * Starts resizing a window. This function is used if an application
8283  * has window resizing controls. When GDK can support it, the resize
8284  * will be done using the standard mechanism for the <link
8285  * linkend="gtk-X11-arch">window manager</link> or windowing
8286  * system. Otherwise, GDK will try to emulate window resizing,
8287  * potentially not all that well, depending on the windowing system.
8288  * 
8289  **/
8290 void
8291 gtk_window_begin_resize_drag  (GtkWindow    *window,
8292                                GdkWindowEdge edge,
8293                                gint          button,
8294                                gint          root_x,
8295                                gint          root_y,
8296                                guint32       timestamp)
8297 {
8298   GtkWidget *widget;
8299   GdkWindow *toplevel;
8300
8301   g_return_if_fail (GTK_IS_WINDOW (window));
8302   widget = GTK_WIDGET (window);
8303   g_return_if_fail (gtk_widget_get_visible (widget));
8304
8305   toplevel = gtk_widget_get_window (widget);
8306
8307   gdk_window_begin_resize_drag (toplevel,
8308                                 edge, button,
8309                                 root_x, root_y,
8310                                 timestamp);
8311 }
8312
8313 /**
8314  * gtk_window_begin_move_drag:
8315  * @window: a #GtkWindow
8316  * @button: mouse button that initiated the drag
8317  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8318  * @root_y: Y position where the user clicked to initiate the drag
8319  * @timestamp: timestamp from the click event that initiated the drag
8320  *
8321  * Starts moving a window. This function is used if an application has
8322  * window movement grips. When GDK can support it, the window movement
8323  * will be done using the standard mechanism for the <link
8324  * linkend="gtk-X11-arch">window manager</link> or windowing
8325  * system. Otherwise, GDK will try to emulate window movement,
8326  * potentially not all that well, depending on the windowing system.
8327  * 
8328  **/
8329 void
8330 gtk_window_begin_move_drag  (GtkWindow *window,
8331                              gint       button,
8332                              gint       root_x,
8333                              gint       root_y,
8334                              guint32    timestamp)
8335 {
8336   GtkWidget *widget;
8337   GdkWindow *toplevel;
8338
8339   g_return_if_fail (GTK_IS_WINDOW (window));
8340   widget = GTK_WIDGET (window);
8341   g_return_if_fail (gtk_widget_get_visible (widget));
8342
8343   toplevel = gtk_widget_get_window (widget);
8344
8345   gdk_window_begin_move_drag (toplevel,
8346                               button,
8347                               root_x, root_y,
8348                               timestamp);
8349 }
8350
8351 /**
8352  * gtk_window_set_screen:
8353  * @window: a #GtkWindow.
8354  * @screen: a #GdkScreen.
8355  *
8356  * Sets the #GdkScreen where the @window is displayed; if
8357  * the window is already mapped, it will be unmapped, and
8358  * then remapped on the new screen.
8359  *
8360  * Since: 2.2
8361  */
8362 void
8363 gtk_window_set_screen (GtkWindow *window,
8364                        GdkScreen *screen)
8365 {
8366   GtkWindowPrivate *priv;
8367   GtkWidget *widget;
8368   GdkScreen *previous_screen;
8369   gboolean was_mapped;
8370
8371   g_return_if_fail (GTK_IS_WINDOW (window));
8372   g_return_if_fail (GDK_IS_SCREEN (screen));
8373
8374   priv = window->priv;
8375
8376   if (screen == priv->screen)
8377     return;
8378
8379   widget = GTK_WIDGET (window);
8380
8381   previous_screen = priv->screen;
8382   was_mapped = gtk_widget_get_mapped (widget);
8383
8384   if (was_mapped)
8385     gtk_widget_unmap (widget);
8386   if (gtk_widget_get_realized (widget))
8387     gtk_widget_unrealize (widget);
8388
8389   gtk_window_free_key_hash (window);
8390   priv->screen = screen;
8391   gtk_widget_reset_rc_styles (widget);
8392   if (screen != previous_screen)
8393     {
8394       if (previous_screen)
8395         {
8396           g_signal_handlers_disconnect_by_func (previous_screen,
8397                                                 gtk_window_on_composited_changed, window);
8398 #ifdef GDK_WINDOWING_X11
8399           g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8400                                                 gtk_window_on_theme_variant_changed, window);
8401 #endif
8402         }
8403       g_signal_connect (screen, "composited-changed",
8404                         G_CALLBACK (gtk_window_on_composited_changed), window);
8405 #ifdef GDK_WINDOWING_X11
8406       g_signal_connect (gtk_settings_get_for_screen (screen),
8407                         "notify::gtk-application-prefer-dark-theme",
8408                         G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8409 #endif
8410
8411       _gtk_widget_propagate_screen_changed (widget, previous_screen);
8412       _gtk_widget_propagate_composited_changed (widget);
8413     }
8414   g_object_notify (G_OBJECT (window), "screen");
8415
8416   if (was_mapped)
8417     gtk_widget_map (widget);
8418 }
8419
8420 static void
8421 gtk_window_set_theme_variant (GtkWindow *window)
8422 {
8423 #ifdef GDK_WINDOWING_X11
8424   GdkWindow *gdk_window;
8425   gboolean   dark_theme_requested;
8426
8427   g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8428                 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8429                 NULL);
8430
8431   gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8432
8433   if (GDK_IS_X11_WINDOW (gdk_window))
8434     gdk_x11_window_set_theme_variant (gdk_window,
8435                                       dark_theme_requested ? "dark" : NULL);
8436 #endif
8437 }
8438
8439 static void
8440 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8441                                      GParamSpec  *pspec,
8442                                      GtkWindow   *window)
8443 {
8444   if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8445     gtk_window_set_theme_variant (window);
8446 }
8447
8448 static void
8449 gtk_window_on_composited_changed (GdkScreen *screen,
8450                                   GtkWindow *window)
8451 {
8452   gtk_widget_queue_draw (GTK_WIDGET (window));
8453   
8454   _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8455 }
8456
8457 static GdkScreen *
8458 gtk_window_check_screen (GtkWindow *window)
8459 {
8460   GtkWindowPrivate *priv = window->priv;
8461
8462   if (priv->screen)
8463     return priv->screen;
8464   else
8465     {
8466       g_warning ("Screen for GtkWindow not set; you must always set\n"
8467                  "a screen for a GtkWindow before using the window");
8468       return NULL;
8469     }
8470 }
8471
8472 /**
8473  * gtk_window_get_screen:
8474  * @window: a #GtkWindow.
8475  *
8476  * Returns the #GdkScreen associated with @window.
8477  *
8478  * Return value: (transfer none): a #GdkScreen.
8479  *
8480  * Since: 2.2
8481  */
8482 GdkScreen*
8483 gtk_window_get_screen (GtkWindow *window)
8484 {
8485   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8486
8487   return window->priv->screen;
8488 }
8489
8490 /**
8491  * gtk_window_is_active:
8492  * @window: a #GtkWindow
8493  * 
8494  * Returns whether the window is part of the current active toplevel.
8495  * (That is, the toplevel window receiving keystrokes.)
8496  * The return value is %TRUE if the window is active toplevel
8497  * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8498  * You might use this function if you wanted to draw a widget
8499  * differently in an active window from a widget in an inactive window.
8500  * See gtk_window_has_toplevel_focus()
8501  * 
8502  * Return value: %TRUE if the window part of the current active window.
8503  *
8504  * Since: 2.4
8505  **/
8506 gboolean
8507 gtk_window_is_active (GtkWindow *window)
8508 {
8509   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8510
8511   return window->priv->is_active;
8512 }
8513
8514 /**
8515  * gtk_window_has_toplevel_focus:
8516  * @window: a #GtkWindow
8517  * 
8518  * Returns whether the input focus is within this GtkWindow.
8519  * For real toplevel windows, this is identical to gtk_window_is_active(),
8520  * but for embedded windows, like #GtkPlug, the results will differ.
8521  * 
8522  * Return value: %TRUE if the input focus is within this GtkWindow
8523  *
8524  * Since: 2.4
8525  **/
8526 gboolean
8527 gtk_window_has_toplevel_focus (GtkWindow *window)
8528 {
8529   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8530
8531   return window->priv->has_toplevel_focus;
8532 }
8533
8534
8535 /**
8536  * SECTION:gtkwindowgroup
8537  * @Short_description: Limit the effect of grabs
8538  * @Title: GtkWindowGroup
8539  *
8540  * #GtkWindowGroup objects are referenced by each window in the group,
8541  * so once you have added all windows to a #GtkWindowGroup, you can drop
8542  * the initial reference to the window group with g_object_unref(). If the
8543  * windows in the window group are subsequently destroyed, then they will
8544  * be removed from the window group and drop their references on the window
8545  * group; when all window have been removed, the window group will be
8546  * freed.
8547  */
8548
8549 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8550
8551 static void
8552 gtk_window_group_init (GtkWindowGroup *group)
8553 {
8554   group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8555                                              GTK_TYPE_WINDOW_GROUP,
8556                                              GtkWindowGroupPrivate);
8557 }
8558
8559 static void
8560 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8561 {
8562   g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8563 }
8564
8565 /**
8566  * gtk_window_group_new:
8567  * 
8568  * Creates a new #GtkWindowGroup object. Grabs added with
8569  * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8570  * 
8571  * Return value: a new #GtkWindowGroup. 
8572  **/
8573 GtkWindowGroup *
8574 gtk_window_group_new (void)
8575 {
8576   return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8577 }
8578
8579 static void
8580 window_group_cleanup_grabs (GtkWindowGroup *group,
8581                             GtkWindow      *window)
8582 {
8583   GtkWindowGroupPrivate *priv;
8584   GtkDeviceGrabInfo *info;
8585   GSList *tmp_list;
8586   GSList *to_remove = NULL;
8587
8588   priv = group->priv;
8589
8590   tmp_list = priv->grabs;
8591   while (tmp_list)
8592     {
8593       if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8594         to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8595       tmp_list = tmp_list->next;
8596     }
8597
8598   while (to_remove)
8599     {
8600       gtk_grab_remove (to_remove->data);
8601       g_object_unref (to_remove->data);
8602       to_remove = g_slist_delete_link (to_remove, to_remove);
8603     }
8604
8605   tmp_list = priv->device_grabs;
8606
8607   while (tmp_list)
8608     {
8609       info = tmp_list->data;
8610
8611       if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8612         to_remove = g_slist_prepend (to_remove, info);
8613
8614       tmp_list = tmp_list->next;
8615     }
8616
8617   while (to_remove)
8618     {
8619       info = to_remove->data;
8620
8621       gtk_device_grab_remove (info->widget, info->device);
8622       to_remove = g_slist_delete_link (to_remove, to_remove);
8623     }
8624 }
8625
8626 /**
8627  * gtk_window_group_add_window:
8628  * @window_group: a #GtkWindowGroup
8629  * @window: the #GtkWindow to add
8630  * 
8631  * Adds a window to a #GtkWindowGroup. 
8632  **/
8633 void
8634 gtk_window_group_add_window (GtkWindowGroup *window_group,
8635                              GtkWindow      *window)
8636 {
8637   GtkWindowPrivate *priv;
8638
8639   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8640   g_return_if_fail (GTK_IS_WINDOW (window));
8641
8642   priv = window->priv;
8643
8644   if (priv->group != window_group)
8645     {
8646       g_object_ref (window);
8647       g_object_ref (window_group);
8648
8649       if (priv->group)
8650         gtk_window_group_remove_window (priv->group, window);
8651       else
8652         window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8653
8654       priv->group = window_group;
8655
8656       g_object_unref (window);
8657     }
8658 }
8659
8660 /**
8661  * gtk_window_group_remove_window:
8662  * @window_group: a #GtkWindowGroup
8663  * @window: the #GtkWindow to remove
8664  * 
8665  * Removes a window from a #GtkWindowGroup.
8666  **/
8667 void
8668 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8669                                 GtkWindow      *window)
8670 {
8671   GtkWindowPrivate *priv;
8672
8673   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8674   g_return_if_fail (GTK_IS_WINDOW (window));
8675   priv = window->priv;
8676   g_return_if_fail (priv->group == window_group);
8677
8678   g_object_ref (window);
8679
8680   window_group_cleanup_grabs (window_group, window);
8681   priv->group = NULL;
8682
8683   g_object_unref (window_group);
8684   g_object_unref (window);
8685 }
8686
8687 /**
8688  * gtk_window_group_list_windows:
8689  * @window_group: a #GtkWindowGroup
8690  *
8691  * Returns a list of the #GtkWindows that belong to @window_group.
8692  *
8693  * Returns: (element-type GtkWindow) (transfer container): A
8694  *   newly-allocated list of windows inside the group.
8695  *
8696  * Since: 2.14
8697  **/
8698 GList *
8699 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8700 {
8701   GList *toplevels, *toplevel, *group_windows;
8702
8703   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8704
8705   group_windows = NULL;
8706   toplevels = gtk_window_list_toplevels ();
8707
8708   for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8709     {
8710       GtkWindow *window = toplevel->data;
8711
8712       if (window_group == window->priv->group)
8713         group_windows = g_list_prepend (group_windows, window);
8714     }
8715
8716   g_list_free (toplevels);
8717
8718   return g_list_reverse (group_windows);
8719 }
8720
8721 /**
8722  * gtk_window_get_group:
8723  * @window: (allow-none): a #GtkWindow, or %NULL
8724  *
8725  * Returns the group for @window or the default group, if
8726  * @window is %NULL or if @window does not have an explicit
8727  * window group.
8728  *
8729  * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8730  *
8731  * Since: 2.10
8732  */
8733 GtkWindowGroup *
8734 gtk_window_get_group (GtkWindow *window)
8735 {
8736   if (window && window->priv->group)
8737     return window->priv->group;
8738   else
8739     {
8740       static GtkWindowGroup *default_group = NULL;
8741
8742       if (!default_group)
8743         default_group = gtk_window_group_new ();
8744
8745       return default_group;
8746     }
8747 }
8748
8749 /**
8750  * gtk_window_has_group:
8751  * @window: a #GtkWindow
8752  *
8753  * Returns whether @window has an explicit window group.
8754  *
8755  * Return value: %TRUE if @window has an explicit window group.
8756  *
8757  * Since 2.22
8758  **/
8759 gboolean
8760 gtk_window_has_group (GtkWindow *window)
8761 {
8762   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8763
8764   return window->priv->group != NULL;
8765 }
8766
8767 /**
8768  * gtk_window_group_get_current_grab:
8769  * @window_group: a #GtkWindowGroup
8770  *
8771  * Gets the current grab widget of the given group,
8772  * see gtk_grab_add().
8773  *
8774  * Returns: (transfer none): the current grab widget of the group
8775  *
8776  * Since: 2.22
8777  */
8778 GtkWidget *
8779 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8780 {
8781   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8782
8783   if (window_group->priv->grabs)
8784     return GTK_WIDGET (window_group->priv->grabs->data);
8785   return NULL;
8786 }
8787
8788 void
8789 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8790                             GtkWidget      *widget)
8791 {
8792   GtkWindowGroupPrivate *priv;
8793
8794   priv = window_group->priv;
8795   priv->grabs = g_slist_prepend (priv->grabs, widget);
8796 }
8797
8798 void
8799 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8800                                GtkWidget      *widget)
8801 {
8802   GtkWindowGroupPrivate *priv;
8803
8804   priv = window_group->priv;
8805   priv->grabs = g_slist_remove (priv->grabs, widget);
8806 }
8807
8808
8809 void
8810 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8811                                    GtkWidget      *widget,
8812                                    GdkDevice      *device,
8813                                    gboolean        block_others)
8814 {
8815   GtkWindowGroupPrivate *priv;
8816   GtkDeviceGrabInfo *info;
8817
8818   priv = window_group->priv;
8819
8820   info = g_slice_new0 (GtkDeviceGrabInfo);
8821   info->widget = widget;
8822   info->device = device;
8823   info->block_others = block_others;
8824
8825   priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8826 }
8827
8828 void
8829 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8830                                       GtkWidget      *widget,
8831                                       GdkDevice      *device)
8832 {
8833   GtkWindowGroupPrivate *priv;
8834   GtkDeviceGrabInfo *info;
8835   GSList *list, *node = NULL;
8836   GdkDevice *other_device;
8837
8838   priv = window_group->priv;
8839   other_device = gdk_device_get_associated_device (device);
8840   list = priv->device_grabs;
8841
8842   while (list)
8843     {
8844       info = list->data;
8845
8846       if (info->widget == widget &&
8847           (info->device == device ||
8848            info->device == other_device))
8849         {
8850           node = list;
8851           break;
8852         }
8853
8854       list = list->next;
8855     }
8856
8857   if (node)
8858     {
8859       info = node->data;
8860
8861       priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8862       g_slice_free (GtkDeviceGrabInfo, info);
8863     }
8864 }
8865
8866 /**
8867  * gtk_window_group_get_current_device_grab:
8868  * @window_group: a #GtkWindowGroup
8869  * @device: a #GdkDevice
8870  *
8871  * Returns the current grab widget for @device, or %NULL if none.
8872  *
8873  * Returns: (transfer none): The grab widget, or %NULL
8874  *
8875  * Since: 3.0
8876  */
8877 GtkWidget *
8878 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8879                                           GdkDevice      *device)
8880 {
8881   GtkWindowGroupPrivate *priv;
8882   GtkDeviceGrabInfo *info;
8883   GdkDevice *other_device;
8884   GSList *list;
8885
8886   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8887   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8888
8889   priv = window_group->priv;
8890   list = priv->device_grabs;
8891   other_device = gdk_device_get_associated_device (device);
8892
8893   while (list)
8894     {
8895       info = list->data;
8896       list = list->next;
8897
8898       if (info->device == device ||
8899           info->device == other_device)
8900         return info->widget;
8901     }
8902
8903   return NULL;
8904 }
8905
8906 gboolean
8907 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8908                                                 GtkWidget      *widget,
8909                                                 GdkDevice      *device)
8910 {
8911   GtkWindowGroupPrivate *priv;
8912   GtkDeviceGrabInfo *info;
8913   GdkDevice *other_device;
8914   GSList *list;
8915
8916   priv = window_group->priv;
8917   other_device = gdk_device_get_associated_device (device);
8918   list = priv->device_grabs;
8919
8920   while (list)
8921     {
8922       info = list->data;
8923       list = list->next;
8924
8925       /* Look for blocking grabs on other device pairs
8926        * that have the passed widget within the GTK+ grab.
8927        */
8928       if (info->block_others &&
8929           info->device != device &&
8930           info->device != other_device &&
8931           (info->widget == widget ||
8932            gtk_widget_is_ancestor (widget, info->widget)))
8933         return TRUE;
8934     }
8935
8936   return FALSE;
8937 }
8938
8939 /*
8940   Derived from XParseGeometry() in XFree86  
8941
8942   Copyright 1985, 1986, 1987,1998  The Open Group
8943
8944   All Rights Reserved.
8945
8946   The above copyright notice and this permission notice shall be included
8947   in all copies or substantial portions of the Software.
8948
8949   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8950   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8951   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8952   IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8953   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8954   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8955   OTHER DEALINGS IN THE SOFTWARE.
8956
8957   Except as contained in this notice, the name of The Open Group shall
8958   not be used in advertising or otherwise to promote the sale, use or
8959   other dealings in this Software without prior written authorization
8960   from The Open Group.
8961 */
8962
8963
8964 /*
8965  *    XParseGeometry parses strings of the form
8966  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8967  *   width, height, xoffset, and yoffset are unsigned integers.
8968  *   Example:  "=80x24+300-49"
8969  *   The equal sign is optional.
8970  *   It returns a bitmask that indicates which of the four values
8971  *   were actually found in the string.  For each value found,
8972  *   the corresponding argument is updated;  for each value
8973  *   not found, the corresponding argument is left unchanged. 
8974  */
8975
8976 /* The following code is from Xlib, and is minimally modified, so we
8977  * can track any upstream changes if required.  Don't change this
8978  * code. Or if you do, put in a huge comment marking which thing
8979  * changed.
8980  */
8981
8982 static int
8983 read_int (gchar   *string,
8984           gchar  **next)
8985 {
8986   int result = 0;
8987   int sign = 1;
8988   
8989   if (*string == '+')
8990     string++;
8991   else if (*string == '-')
8992     {
8993       string++;
8994       sign = -1;
8995     }
8996
8997   for (; (*string >= '0') && (*string <= '9'); string++)
8998     {
8999       result = (result * 10) + (*string - '0');
9000     }
9001
9002   *next = string;
9003
9004   if (sign >= 0)
9005     return (result);
9006   else
9007     return (-result);
9008 }
9009
9010 /* 
9011  * Bitmask returned by XParseGeometry().  Each bit tells if the corresponding
9012  * value (x, y, width, height) was found in the parsed string.
9013  */
9014 #define NoValue         0x0000
9015 #define XValue          0x0001
9016 #define YValue          0x0002
9017 #define WidthValue      0x0004
9018 #define HeightValue     0x0008
9019 #define AllValues       0x000F
9020 #define XNegative       0x0010
9021 #define YNegative       0x0020
9022
9023 /* Try not to reformat/modify, so we can compare/sync with X sources */
9024 static int
9025 gtk_XParseGeometry (const char   *string,
9026                     int          *x,
9027                     int          *y,
9028                     unsigned int *width,   
9029                     unsigned int *height)  
9030 {
9031   int mask = NoValue;
9032   char *strind;
9033   unsigned int tempWidth, tempHeight;
9034   int tempX, tempY;
9035   char *nextCharacter;
9036
9037   /* These initializations are just to silence gcc */
9038   tempWidth = 0;
9039   tempHeight = 0;
9040   tempX = 0;
9041   tempY = 0;
9042   
9043   if ( (string == NULL) || (*string == '\0')) return(mask);
9044   if (*string == '=')
9045     string++;  /* ignore possible '=' at beg of geometry spec */
9046
9047   strind = (char *)string;
9048   if (*strind != '+' && *strind != '-' && *strind != 'x') {
9049     tempWidth = read_int(strind, &nextCharacter);
9050     if (strind == nextCharacter) 
9051       return (0);
9052     strind = nextCharacter;
9053     mask |= WidthValue;
9054   }
9055
9056   if (*strind == 'x' || *strind == 'X') {       
9057     strind++;
9058     tempHeight = read_int(strind, &nextCharacter);
9059     if (strind == nextCharacter)
9060       return (0);
9061     strind = nextCharacter;
9062     mask |= HeightValue;
9063   }
9064
9065   if ((*strind == '+') || (*strind == '-')) {
9066     if (*strind == '-') {
9067       strind++;
9068       tempX = -read_int(strind, &nextCharacter);
9069       if (strind == nextCharacter)
9070         return (0);
9071       strind = nextCharacter;
9072       mask |= XNegative;
9073
9074     }
9075     else
9076       { strind++;
9077       tempX = read_int(strind, &nextCharacter);
9078       if (strind == nextCharacter)
9079         return(0);
9080       strind = nextCharacter;
9081       }
9082     mask |= XValue;
9083     if ((*strind == '+') || (*strind == '-')) {
9084       if (*strind == '-') {
9085         strind++;
9086         tempY = -read_int(strind, &nextCharacter);
9087         if (strind == nextCharacter)
9088           return(0);
9089         strind = nextCharacter;
9090         mask |= YNegative;
9091
9092       }
9093       else
9094         {
9095           strind++;
9096           tempY = read_int(strind, &nextCharacter);
9097           if (strind == nextCharacter)
9098             return(0);
9099           strind = nextCharacter;
9100         }
9101       mask |= YValue;
9102     }
9103   }
9104         
9105   /* If strind isn't at the end of the string the it's an invalid
9106                 geometry specification. */
9107
9108   if (*strind != '\0') return (0);
9109
9110   if (mask & XValue)
9111     *x = tempX;
9112   if (mask & YValue)
9113     *y = tempY;
9114   if (mask & WidthValue)
9115     *width = tempWidth;
9116   if (mask & HeightValue)
9117     *height = tempHeight;
9118   return (mask);
9119 }
9120
9121 /**
9122  * gtk_window_parse_geometry:
9123  * @window: a #GtkWindow
9124  * @geometry: geometry string
9125  * 
9126  * Parses a standard X Window System geometry string - see the
9127  * manual page for X (type 'man X') for details on this.
9128  * gtk_window_parse_geometry() does work on all GTK+ ports
9129  * including Win32 but is primarily intended for an X environment.
9130  *
9131  * If either a size or a position can be extracted from the
9132  * geometry string, gtk_window_parse_geometry() returns %TRUE
9133  * and calls gtk_window_set_default_size() and/or gtk_window_move()
9134  * to resize/move the window.
9135  *
9136  * If gtk_window_parse_geometry() returns %TRUE, it will also
9137  * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9138  * indicating to the window manager that the size/position of
9139  * the window was user-specified. This causes most window
9140  * managers to honor the geometry.
9141  *
9142  * Note that for gtk_window_parse_geometry() to work as expected, it has
9143  * to be called when the window has its "final" size, i.e. after calling
9144  * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9145  * on the window.
9146  * |[
9147  * #include <gtk/gtk.h>
9148  *    
9149  * static void
9150  * fill_with_content (GtkWidget *vbox)
9151  * {
9152  *   /&ast; fill with content... &ast;/
9153  * }
9154  *    
9155  * int
9156  * main (int argc, char *argv[])
9157  * {
9158  *   GtkWidget *window, *vbox;
9159  *   GdkGeometry size_hints = {
9160  *     100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST  
9161  *   };
9162  *    
9163  *   gtk_init (&argc, &argv);
9164  *   
9165  *   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9166  *   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9167  *   
9168  *   gtk_container_add (GTK_CONTAINER (window), vbox);
9169  *   fill_with_content (vbox);
9170  *   gtk_widget_show_all (vbox);
9171  *   
9172  *   gtk_window_set_geometry_hints (GTK_WINDOW (window),
9173  *                                  window,
9174  *                                  &size_hints,
9175  *                                  GDK_HINT_MIN_SIZE | 
9176  *                                  GDK_HINT_BASE_SIZE | 
9177  *                                  GDK_HINT_RESIZE_INC);
9178  *   
9179  *   if (argc &gt; 1)
9180  *     {
9181  *       if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9182  *         fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9183  *     }
9184  *    
9185  *   gtk_widget_show_all (window);
9186  *   gtk_main ();
9187  *    
9188  *   return 0;
9189  * }
9190  * ]|
9191  *
9192  * Return value: %TRUE if string was parsed successfully
9193  **/
9194 gboolean
9195 gtk_window_parse_geometry (GtkWindow   *window,
9196                            const gchar *geometry)
9197 {
9198   gint result, x = 0, y = 0;
9199   guint w, h;
9200   GtkWidget *child;
9201   GdkGravity grav;
9202   gboolean size_set, pos_set;
9203   GdkScreen *screen;
9204   
9205   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9206   g_return_val_if_fail (geometry != NULL, FALSE);
9207
9208   child = gtk_bin_get_child (GTK_BIN (window));
9209   if (!child || !gtk_widget_get_visible (child))
9210     g_warning ("gtk_window_parse_geometry() called on a window with no "
9211                "visible children; the window should be set up before "
9212                "gtk_window_parse_geometry() is called.");
9213
9214   screen = gtk_window_check_screen (window);
9215   
9216   result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9217
9218   size_set = FALSE;
9219   if ((result & WidthValue) || (result & HeightValue))
9220     {
9221       gtk_window_set_default_size_internal (window, 
9222                                             TRUE, result & WidthValue ? w : -1,
9223                                             TRUE, result & HeightValue ? h : -1, 
9224                                             TRUE);
9225       size_set = TRUE;
9226     }
9227
9228   gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9229   
9230   grav = GDK_GRAVITY_NORTH_WEST;
9231
9232   if ((result & XNegative) && (result & YNegative))
9233     grav = GDK_GRAVITY_SOUTH_EAST;
9234   else if (result & XNegative)
9235     grav = GDK_GRAVITY_NORTH_EAST;
9236   else if (result & YNegative)
9237     grav = GDK_GRAVITY_SOUTH_WEST;
9238
9239   if ((result & XValue) == 0)
9240     x = 0;
9241
9242   if ((result & YValue) == 0)
9243     y = 0;
9244
9245   if (grav == GDK_GRAVITY_SOUTH_WEST ||
9246       grav == GDK_GRAVITY_SOUTH_EAST)
9247     y = gdk_screen_get_height (screen) - h + y;
9248
9249   if (grav == GDK_GRAVITY_SOUTH_EAST ||
9250       grav == GDK_GRAVITY_NORTH_EAST)
9251     x = gdk_screen_get_width (screen) - w + x;
9252
9253   /* we don't let you put a window offscreen; maybe some people would
9254    * prefer to be able to, but it's kind of a bogus thing to do.
9255    */
9256   if (y < 0)
9257     y = 0;
9258
9259   if (x < 0)
9260     x = 0;
9261
9262   pos_set = FALSE;
9263   if ((result & XValue) || (result & YValue))
9264     {
9265       gtk_window_set_gravity (window, grav);
9266       gtk_window_move (window, x, y);
9267       pos_set = TRUE;
9268     }
9269
9270   if (size_set || pos_set)
9271     {
9272       /* Set USSize, USPosition hints */
9273       GtkWindowGeometryInfo *info;
9274
9275       info = gtk_window_get_geometry_info (window, TRUE);
9276
9277       if (pos_set)
9278         info->mask |= GDK_HINT_USER_POS;
9279       if (size_set)
9280         info->mask |= GDK_HINT_USER_SIZE;
9281     }
9282   
9283   return result != 0;
9284 }
9285
9286 static void
9287 gtk_window_mnemonic_hash_foreach (guint      keyval,
9288                                   GSList    *targets,
9289                                   gpointer   data)
9290 {
9291   struct {
9292     GtkWindow *window;
9293     GtkWindowKeysForeachFunc func;
9294     gpointer func_data;
9295   } *info = data;
9296
9297   (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9298 }
9299
9300 void
9301 _gtk_window_keys_foreach (GtkWindow                *window,
9302                           GtkWindowKeysForeachFunc func,
9303                           gpointer                 func_data)
9304 {
9305   GSList *groups;
9306   GtkMnemonicHash *mnemonic_hash;
9307
9308   struct {
9309     GtkWindow *window;
9310     GtkWindowKeysForeachFunc func;
9311     gpointer func_data;
9312   } info;
9313
9314   info.window = window;
9315   info.func = func;
9316   info.func_data = func_data;
9317
9318   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9319   if (mnemonic_hash)
9320     _gtk_mnemonic_hash_foreach (mnemonic_hash,
9321                                 gtk_window_mnemonic_hash_foreach, &info);
9322
9323   groups = gtk_accel_groups_from_object (G_OBJECT (window));
9324   while (groups)
9325     {
9326       GtkAccelGroup *group = groups->data;
9327       gint i;
9328
9329       for (i = 0; i < group->priv->n_accels; i++)
9330         {
9331           GtkAccelKey *key = &group->priv->priv_accels[i].key;
9332           
9333           if (key->accel_key)
9334             (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9335         }
9336       
9337       groups = groups->next;
9338     }
9339 }
9340
9341 static void
9342 gtk_window_keys_changed (GtkWindow *window)
9343 {
9344   gtk_window_free_key_hash (window);
9345   gtk_window_get_key_hash (window);
9346 }
9347
9348 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9349
9350 struct _GtkWindowKeyEntry
9351 {
9352   guint keyval;
9353   guint modifiers;
9354   guint is_mnemonic : 1;
9355 };
9356
9357 static void 
9358 window_key_entry_destroy (gpointer data)
9359 {
9360   g_slice_free (GtkWindowKeyEntry, data);
9361 }
9362
9363 static void
9364 add_to_key_hash (GtkWindow      *window,
9365                  guint           keyval,
9366                  GdkModifierType modifiers,
9367                  gboolean        is_mnemonic,
9368                  gpointer        data)
9369 {
9370   GtkKeyHash *key_hash = data;
9371
9372   GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9373
9374   entry->keyval = keyval;
9375   entry->modifiers = modifiers;
9376   entry->is_mnemonic = is_mnemonic;
9377
9378   /* GtkAccelGroup stores lowercased accelerators. To deal
9379    * with this, if <Shift> was specified, uppercase.
9380    */
9381   if (modifiers & GDK_SHIFT_MASK)
9382     {
9383       if (keyval == GDK_KEY_Tab)
9384         keyval = GDK_KEY_ISO_Left_Tab;
9385       else
9386         keyval = gdk_keyval_to_upper (keyval);
9387     }
9388   
9389   _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9390 }
9391
9392 static GtkKeyHash *
9393 gtk_window_get_key_hash (GtkWindow *window)
9394 {
9395   GdkScreen *screen = gtk_window_check_screen (window);
9396   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9397   
9398   if (key_hash)
9399     return key_hash;
9400   
9401   key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9402                                 (GDestroyNotify)window_key_entry_destroy);
9403   _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9404   g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9405
9406   return key_hash;
9407 }
9408
9409 static void
9410 gtk_window_free_key_hash (GtkWindow *window)
9411 {
9412   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9413   if (key_hash)
9414     {
9415       _gtk_key_hash_free (key_hash);
9416       g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9417     }
9418 }
9419
9420 /**
9421  * gtk_window_activate_key:
9422  * @window:  a #GtkWindow
9423  * @event:   a #GdkEventKey
9424  *
9425  * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9426  * called by the default ::key_press_event handler for toplevel windows,
9427  * however in some cases it may be useful to call this directly when
9428  * overriding the standard key handling for a toplevel window.
9429  *
9430  * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9431  *
9432  * Since: 2.4
9433  */
9434 gboolean
9435 gtk_window_activate_key (GtkWindow   *window,
9436                          GdkEventKey *event)
9437 {
9438   GtkKeyHash *key_hash;
9439   GtkWindowKeyEntry *found_entry = NULL;
9440   gboolean enable_mnemonics;
9441   gboolean enable_accels;
9442
9443   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9444   g_return_val_if_fail (event != NULL, FALSE);
9445
9446   key_hash = gtk_window_get_key_hash (window);
9447
9448   if (key_hash)
9449     {
9450       GSList *tmp_list;
9451       GSList *entries = _gtk_key_hash_lookup (key_hash,
9452                                               event->hardware_keycode,
9453                                               event->state,
9454                                               gtk_accelerator_get_default_mod_mask (),
9455                                               event->group);
9456
9457       g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9458                     "gtk-enable-mnemonics", &enable_mnemonics,
9459                     "gtk-enable-accels", &enable_accels,
9460                     NULL);
9461
9462       for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9463         {
9464           GtkWindowKeyEntry *entry = tmp_list->data;
9465           if (entry->is_mnemonic)
9466             {
9467               if (enable_mnemonics)
9468                 {
9469                   found_entry = entry;
9470                   break;
9471                 }
9472             }
9473           else 
9474             {
9475               if (enable_accels && !found_entry)
9476                 {
9477                   found_entry = entry;
9478                 }
9479             }
9480         }
9481
9482       g_slist_free (entries);
9483     }
9484
9485   if (found_entry)
9486     {
9487       if (found_entry->is_mnemonic)
9488         {
9489           if (enable_mnemonics)
9490             return gtk_window_mnemonic_activate (window, found_entry->keyval,
9491                                                  found_entry->modifiers);
9492         }
9493       else
9494         {
9495           if (enable_accels)
9496             return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9497                                               found_entry->modifiers);
9498         }
9499     }
9500
9501   return FALSE;
9502 }
9503
9504 static void
9505 window_update_has_focus (GtkWindow *window)
9506 {
9507   GtkWindowPrivate *priv = window->priv;
9508   GtkWidget *widget = GTK_WIDGET (window);
9509   gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9510
9511   if (has_focus != priv->has_focus)
9512     {
9513       priv->has_focus = has_focus;
9514
9515       if (has_focus)
9516         {
9517           if (priv->focus_widget &&
9518               priv->focus_widget != widget &&
9519               !gtk_widget_has_focus (priv->focus_widget))
9520             do_focus_change (priv->focus_widget, TRUE);
9521         }
9522       else
9523         {
9524           if (priv->focus_widget &&
9525               priv->focus_widget != widget &&
9526               gtk_widget_has_focus (priv->focus_widget))
9527             do_focus_change (priv->focus_widget, FALSE);
9528         }
9529     }
9530 }
9531
9532 /**
9533  * _gtk_window_set_is_active:
9534  * @window: a #GtkWindow
9535  * @is_active: %TRUE if the window is in the currently active toplevel
9536  * 
9537  * Internal function that sets whether the #GtkWindow is part
9538  * of the currently active toplevel window (taking into account inter-process
9539  * embedding.)
9540  **/
9541 void
9542 _gtk_window_set_is_active (GtkWindow *window,
9543                            gboolean   is_active)
9544 {
9545   GtkWindowPrivate *priv;
9546
9547   g_return_if_fail (GTK_IS_WINDOW (window));
9548
9549   priv = window->priv;
9550
9551   is_active = is_active != FALSE;
9552
9553   if (is_active != priv->is_active)
9554     {
9555       priv->is_active = is_active;
9556       window_update_has_focus (window);
9557
9558       g_object_notify (G_OBJECT (window), "is-active");
9559     }
9560 }
9561
9562 /**
9563  * _gtk_window_set_is_toplevel:
9564  * @window: a #GtkWindow
9565  * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9566  * child of the root window); %FALSE if it is not (for example, for an
9567  * in-process, parented GtkPlug)
9568  *
9569  * Internal function used by #GtkPlug when it gets parented/unparented by a
9570  * #GtkSocket.  This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9571  * global list of toplevel windows.
9572  */
9573 void
9574 _gtk_window_set_is_toplevel (GtkWindow *window,
9575                              gboolean   is_toplevel)
9576 {
9577   GtkWidget *widget;
9578   GtkWidget *toplevel;
9579
9580   widget = GTK_WIDGET (window);
9581
9582   if (gtk_widget_is_toplevel (widget))
9583     g_assert (g_slist_find (toplevel_list, window) != NULL);
9584   else
9585     g_assert (g_slist_find (toplevel_list, window) == NULL);
9586
9587   if (is_toplevel == gtk_widget_is_toplevel (widget))
9588     return;
9589
9590   if (is_toplevel)
9591     {
9592       /* Pass through regular pathways of an embedded toplevel
9593        * to go through unmapping and hiding the widget before
9594        * becomming a toplevel again.
9595        *
9596        * We remain hidden after becomming toplevel in order to
9597        * avoid problems during an embedded toplevel's dispose cycle
9598        * (When a toplevel window is shown it tries to grab focus again,
9599        * this causes problems while disposing).
9600        */
9601       gtk_widget_hide (widget);
9602
9603       /* Save the toplevel this widget was previously anchored into before
9604        * propagating a hierarchy-changed.
9605        *
9606        * Usually this happens by way of gtk_widget_unparent() and we are
9607        * already unanchored at this point, just adding this clause incase
9608        * things happen differently.
9609        */
9610       toplevel = gtk_widget_get_toplevel (widget);
9611       if (!gtk_widget_is_toplevel (toplevel))
9612         toplevel = NULL;
9613
9614       _gtk_widget_set_is_toplevel (widget, TRUE);
9615
9616       /* When a window becomes toplevel after being embedded and anchored
9617        * into another window we need to unset its anchored flag so that
9618        * the hierarchy changed signal kicks in properly.
9619        */
9620       _gtk_widget_set_anchored (widget, FALSE);
9621       _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9622
9623       toplevel_list = g_slist_prepend (toplevel_list, window);
9624     }
9625   else
9626     {
9627       _gtk_widget_set_is_toplevel (widget, FALSE);
9628       toplevel_list = g_slist_remove (toplevel_list, window);
9629
9630       _gtk_widget_propagate_hierarchy_changed (widget, widget);
9631     }
9632 }
9633
9634 /**
9635  * _gtk_window_set_has_toplevel_focus:
9636  * @window: a #GtkWindow
9637  * @has_toplevel_focus: %TRUE if the in
9638  * 
9639  * Internal function that sets whether the keyboard focus for the
9640  * toplevel window (taking into account inter-process embedding.)
9641  **/
9642 void
9643 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9644                                    gboolean   has_toplevel_focus)
9645 {
9646   GtkWindowPrivate *priv;
9647
9648   g_return_if_fail (GTK_IS_WINDOW (window));
9649
9650   priv = window->priv;
9651
9652   has_toplevel_focus = has_toplevel_focus != FALSE;
9653
9654   if (has_toplevel_focus != priv->has_toplevel_focus)
9655     {
9656       priv->has_toplevel_focus = has_toplevel_focus;
9657       window_update_has_focus (window);
9658
9659       g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9660     }
9661 }
9662
9663 /**
9664  * gtk_window_set_auto_startup_notification:
9665  * @setting: %TRUE to automatically do startup notification
9666  *
9667  * By default, after showing the first #GtkWindow, GTK+ calls 
9668  * gdk_notify_startup_complete().  Call this function to disable 
9669  * the automatic startup notification. You might do this if your 
9670  * first window is a splash screen, and you want to delay notification 
9671  * until after your real main window has been shown, for example.
9672  *
9673  * In that example, you would disable startup notification
9674  * temporarily, show your splash screen, then re-enable it so that
9675  * showing the main window would automatically result in notification.
9676  * 
9677  * Since: 2.2
9678  **/
9679 void
9680 gtk_window_set_auto_startup_notification (gboolean setting)
9681 {
9682   disable_startup_notification = !setting;
9683 }
9684
9685 /**
9686  * gtk_window_get_window_type:
9687  * @window: a #GtkWindow
9688  *
9689  * Gets the type of the window. See #GtkWindowType.
9690  *
9691  * Return value: the type of the window
9692  *
9693  * Since: 2.20
9694  **/
9695 GtkWindowType
9696 gtk_window_get_window_type (GtkWindow *window)
9697 {
9698   g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9699
9700   return window->priv->type;
9701 }
9702
9703 /**
9704  * gtk_window_get_mnemonics_visible:
9705  * @window: a #GtkWindow
9706  *
9707  * Gets the value of the #GtkWindow:mnemonics-visible property.
9708  *
9709  * Returns: %TRUE if mnemonics are supposed to be visible
9710  * in this window.
9711  *
9712  * Since: 2.20
9713  */
9714 gboolean
9715 gtk_window_get_mnemonics_visible (GtkWindow *window)
9716 {
9717   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9718
9719   return window->priv->mnemonics_visible;
9720 }
9721
9722 /**
9723  * gtk_window_set_mnemonics_visible:
9724  * @window: a #GtkWindow
9725  * @setting: the new value
9726  *
9727  * Sets the #GtkWindow:mnemonics-visible property.
9728  *
9729  * Since: 2.20
9730  */
9731 void
9732 gtk_window_set_mnemonics_visible (GtkWindow *window,
9733                                   gboolean   setting)
9734 {
9735   GtkWindowPrivate *priv;
9736
9737   g_return_if_fail (GTK_IS_WINDOW (window));
9738
9739   priv = window->priv;
9740
9741   setting = setting != FALSE;
9742
9743   if (priv->mnemonics_visible != setting)
9744     {
9745       priv->mnemonics_visible = setting;
9746       g_object_notify (G_OBJECT (window), "mnemonics-visible");
9747     }
9748
9749   priv->mnemonics_visible_set = TRUE;
9750 }
9751
9752 /**
9753  * gtk_window_get_focus_visible:
9754  * @window: a #GtkWindow
9755  *
9756  * Gets the value of the #GtkWindow:focus-visible property.
9757  *
9758  * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9759  *     in this window.
9760  *
9761  * Since: 3.2
9762  */
9763 gboolean
9764 gtk_window_get_focus_visible (GtkWindow *window)
9765 {
9766   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9767
9768   return window->priv->focus_visible;
9769 }
9770
9771 /**
9772  * gtk_window_set_focus_visible:
9773  * @window: a #GtkWindow
9774  * @setting: the new value
9775  *
9776  * Sets the #GtkWindow:focus-visible property.
9777  *
9778  * Since: 3.2
9779  */
9780 void
9781 gtk_window_set_focus_visible (GtkWindow *window,
9782                               gboolean   setting)
9783 {
9784   GtkWindowPrivate *priv;
9785
9786   g_return_if_fail (GTK_IS_WINDOW (window));
9787
9788   priv = window->priv;
9789
9790   setting = setting != FALSE;
9791
9792   if (priv->focus_visible != setting)
9793     {
9794       priv->focus_visible = setting;
9795       g_object_notify (G_OBJECT (window), "focus-visible");
9796     }
9797 }
9798
9799 void
9800 _gtk_window_get_wmclass (GtkWindow  *window,
9801                          gchar     **wmclass_name,
9802                          gchar     **wmclass_class)
9803 {
9804   GtkWindowPrivate *priv = window->priv;
9805
9806   *wmclass_name = priv->wmclass_name;
9807   *wmclass_class = priv->wmclass_class;
9808 }
9809
9810 /**
9811  * gtk_window_set_has_user_ref_count:
9812  * @window: a #GtkWindow
9813  * @setting: the new value
9814  *
9815  * Tells GTK+ whether to drop its extra reference to the window
9816  * when gtk_window_destroy() is called.
9817  *
9818  * This function is only exported for the benefit of language
9819  * bindings which may need to keep the window alive until their
9820  * wrapper object is garbage collected. There is no justification
9821  * for ever calling this function in an application.
9822  *
9823  * Since: 3.0
9824  */
9825 void
9826 gtk_window_set_has_user_ref_count (GtkWindow *window,
9827                                    gboolean   setting)
9828 {
9829   g_return_if_fail (GTK_IS_WINDOW (window));
9830
9831   window->priv->has_user_ref_count = setting;
9832 }
9833
9834 static void
9835 ensure_state_flag_backdrop (GtkWidget *widget)
9836 {
9837   GdkWindow *window;
9838   gboolean window_focused = TRUE;
9839
9840   window = gtk_widget_get_window (widget);
9841
9842   window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9843
9844   if (!window_focused)
9845     gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
9846   else
9847     gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
9848
9849   gtk_widget_queue_draw (widget);
9850 }