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