]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
cssvalue: Remove NULL check
[~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   gdk_window_get_position (gdk_window, &allocation.x, &allocation.y);
7175   allocation.width = gdk_window_get_width (gdk_window);
7176   allocation.height = gdk_window_get_height (gdk_window);
7177
7178   /* handle resizing/moving and widget tree allocation
7179    */
7180   if (priv->configure_notify_received)
7181     { 
7182       /* If we have received a configure event since
7183        * the last time in this function, we need to
7184        * accept our new size and size_allocate child widgets.
7185        * (see gtk_window_configure_event() for more details).
7186        *
7187        * 1 or more configure notifies may have been received.
7188        * Also, configure_notify_received will only be TRUE
7189        * if all expected configure notifies have been received
7190        * (one per configure request), as an optimization.
7191        *
7192        */
7193       priv->configure_notify_received = FALSE;
7194
7195       /* gtk_window_configure_event() filled in widget->allocation */
7196       gtk_widget_size_allocate (widget, &allocation);
7197
7198       set_grip_position (window);
7199       update_grip_visibility (window);
7200
7201       gdk_window_process_updates (gdk_window, TRUE);
7202
7203       gdk_window_configure_finished (gdk_window);
7204
7205       /* If the configure request changed, it means that
7206        * we either:
7207        *   1) coincidentally changed hints or widget properties
7208        *      impacting the configure request before getting
7209        *      a configure notify, or
7210        *   2) some broken widget is changing its size request
7211        *      during size allocation, resulting in
7212        *      a false appearance of changed configure request.
7213        *
7214        * For 1), we could just go ahead and ask for the
7215        * new size right now, but doing that for 2)
7216        * might well be fighting the user (and can even
7217        * trigger a loop). Since we really don't want to
7218        * do that, we requeue a resize in hopes that
7219        * by the time it gets handled, the child has seen
7220        * the light and is willing to go along with the
7221        * new size. (this happens for the zvt widget, since
7222        * the size_allocate() above will have stored the
7223        * requisition corresponding to the new size in the
7224        * zvt widget)
7225        *
7226        * This doesn't buy us anything for 1), but it shouldn't
7227        * hurt us too badly, since it is what would have
7228        * happened if we had gotten the configure event before
7229        * the new size had been set.
7230        */
7231
7232       if (configure_request_size_changed ||
7233           configure_request_pos_changed)
7234         {
7235           /* Don't change the recorded last info after all, because we
7236            * haven't actually updated to the new info yet - we decided
7237            * to postpone our configure request until later.
7238            */
7239           info->last = saved_last_info;
7240           
7241           gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7242         }
7243
7244       return;                   /* Bail out, we didn't really process the move/resize */
7245     }
7246   else if ((configure_request_size_changed || hints_changed) &&
7247            (allocation.width != new_request.width || allocation.height != new_request.height))
7248
7249     {
7250       /* We are in one of the following situations:
7251        * A. configure_request_size_changed
7252        *    our requisition has changed and we need a different window size,
7253        *    so we request it from the window manager.
7254        * B. !configure_request_size_changed && hints_changed
7255        *    the window manager rejects our size, but we have just changed the
7256        *    window manager hints, so there's a chance our request will
7257        *    be honoured this time, so we try again.
7258        *
7259        * However, if the new requisition is the same as the current allocation,
7260        * we don't request it again, since we won't get a ConfigureNotify back from
7261        * the window manager unless it decides to change our requisition. If
7262        * we don't get the ConfigureNotify back, the resize queue will never be run.
7263        */
7264
7265       /* Now send the configure request */
7266       if (configure_request_pos_changed)
7267         {
7268           gdk_window_move_resize (gdk_window,
7269                                   new_request.x, new_request.y,
7270                                   new_request.width, new_request.height);
7271         }
7272       else  /* only size changed */
7273         {
7274           gdk_window_resize (gdk_window,
7275                              new_request.width, new_request.height);
7276         }
7277
7278       if (priv->type == GTK_WINDOW_POPUP)
7279         {
7280           GtkAllocation allocation;
7281
7282           /* Directly size allocate for override redirect (popup) windows. */
7283           allocation.x = 0;
7284           allocation.y = 0;
7285           allocation.width = new_request.width;
7286           allocation.height = new_request.height;
7287
7288           gtk_widget_size_allocate (widget, &allocation);
7289
7290           gdk_window_process_updates (gdk_window, TRUE);
7291
7292           if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7293             gtk_widget_queue_draw (widget);
7294         }
7295       else
7296         {
7297           /* Increment the number of have-not-yet-received-notify requests */
7298           priv->configure_request_count += 1;
7299           gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7300
7301           /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7302            * configure event in response to our resizing request.
7303            * the configure event will cause a new resize with
7304            * ->configure_notify_received=TRUE.
7305            * until then, we want to
7306            * - discard expose events
7307            * - coalesce resizes for our children
7308            * - defer any window resizes until the configure event arrived
7309            * to achieve this, we queue a resize for the window, but remove its
7310            * resizing handler, so resizing will not be handled from the next
7311            * idle handler but when the configure event arrives.
7312            *
7313            * FIXME: we should also dequeue the pending redraws here, since
7314            * we handle those ourselves upon ->configure_notify_received==TRUE.
7315            */
7316           if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7317             {
7318               gtk_widget_queue_resize_no_redraw (widget);
7319               _gtk_container_dequeue_resize_handler (container);
7320             }
7321         }
7322     }
7323   else
7324     {
7325       /* Handle any position changes.
7326        */
7327       if (configure_request_pos_changed)
7328         {
7329           gdk_window_move (gdk_window,
7330                            new_request.x, new_request.y);
7331         }
7332
7333       /* And run the resize queue.
7334        */
7335       gtk_container_resize_children (container);
7336     }
7337   
7338   /* We have now processed a move/resize since the last position
7339    * constraint change, setting of the initial position, or resize.
7340    * (Not resetting these flags here can lead to infinite loops for
7341    * GTK_RESIZE_IMMEDIATE containers)
7342    */
7343   info->position_constraints_changed = FALSE;
7344   info->initial_pos_set = FALSE;
7345   info->resize_width = -1;
7346   info->resize_height = -1;
7347 }
7348
7349 /* Compare two sets of Geometry hints for equality.
7350  */
7351 static gboolean
7352 gtk_window_compare_hints (GdkGeometry *geometry_a,
7353                           guint        flags_a,
7354                           GdkGeometry *geometry_b,
7355                           guint        flags_b)
7356 {
7357   if (flags_a != flags_b)
7358     return FALSE;
7359   
7360   if ((flags_a & GDK_HINT_MIN_SIZE) &&
7361       (geometry_a->min_width != geometry_b->min_width ||
7362        geometry_a->min_height != geometry_b->min_height))
7363     return FALSE;
7364
7365   if ((flags_a & GDK_HINT_MAX_SIZE) &&
7366       (geometry_a->max_width != geometry_b->max_width ||
7367        geometry_a->max_height != geometry_b->max_height))
7368     return FALSE;
7369
7370   if ((flags_a & GDK_HINT_BASE_SIZE) &&
7371       (geometry_a->base_width != geometry_b->base_width ||
7372        geometry_a->base_height != geometry_b->base_height))
7373     return FALSE;
7374
7375   if ((flags_a & GDK_HINT_ASPECT) &&
7376       (geometry_a->min_aspect != geometry_b->min_aspect ||
7377        geometry_a->max_aspect != geometry_b->max_aspect))
7378     return FALSE;
7379
7380   if ((flags_a & GDK_HINT_RESIZE_INC) &&
7381       (geometry_a->width_inc != geometry_b->width_inc ||
7382        geometry_a->height_inc != geometry_b->height_inc))
7383     return FALSE;
7384
7385   if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7386       geometry_a->win_gravity != geometry_b->win_gravity)
7387     return FALSE;
7388
7389   return TRUE;
7390 }
7391
7392 void
7393 _gtk_window_constrain_size (GtkWindow   *window,
7394                             gint         width,
7395                             gint         height,
7396                             gint        *new_width,
7397                             gint        *new_height)
7398 {
7399   GtkWindowPrivate *priv;
7400   GtkWindowGeometryInfo *info;
7401
7402   g_return_if_fail (GTK_IS_WINDOW (window));
7403
7404   priv = window->priv;
7405
7406   info = priv->geometry_info;
7407   if (info)
7408     {
7409       GdkWindowHints flags = info->last.flags;
7410       GdkGeometry *geometry = &info->last.geometry;
7411       
7412       gtk_window_constrain_size (window,
7413                                  geometry,
7414                                  flags,
7415                                  width,
7416                                  height,
7417                                  new_width,
7418                                  new_height);
7419     }
7420 }
7421
7422 static void 
7423 gtk_window_constrain_size (GtkWindow   *window,
7424                            GdkGeometry *geometry,
7425                            guint        flags,
7426                            gint         width,
7427                            gint         height,
7428                            gint        *new_width,
7429                            gint        *new_height)
7430 {
7431   gdk_window_constrain_size (geometry, flags, width, height,
7432                              new_width, new_height);
7433 }
7434
7435 /* Compute the set of geometry hints and flags for a window
7436  * based on the application set geometry, and requisition
7437  * of the window. gtk_widget_get_preferred_size() must have been
7438  * called first.
7439  */
7440 static void
7441 gtk_window_compute_hints (GtkWindow   *window,
7442                           GdkGeometry *new_geometry,
7443                           guint       *new_flags)
7444 {
7445   GtkWindowPrivate *priv = window->priv;
7446   GtkWidget *widget;
7447   gint extra_width = 0;
7448   gint extra_height = 0;
7449   GtkWindowGeometryInfo *geometry_info;
7450   GtkRequisition requisition;
7451
7452   widget = GTK_WIDGET (window);
7453
7454   gtk_widget_get_preferred_size (widget, &requisition, NULL);
7455   geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7456
7457   if (geometry_info)
7458     {
7459       *new_flags = geometry_info->mask;
7460       *new_geometry = geometry_info->geometry;
7461     }
7462   else
7463     {
7464       *new_flags = 0;
7465     }
7466   
7467   if (geometry_info && geometry_info->widget)
7468     {
7469       /* If the geometry widget is set, then the hints really apply to that
7470        * widget. This is pretty much meaningless unless the window layout
7471        * is such that the rest of the window adds fixed size borders to
7472        * the geometry widget. Our job is to figure the size of the borders;
7473        * We do that by asking how big the toplevel would be if the
7474        * geometry widget was *really big*.
7475        *
7476        *  +----------+
7477        *  |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7478        *  |GGGGG    B| in the border can confuse things
7479        *  |GGGGG    B|
7480        *  |         B|
7481        *  +----------+
7482        *
7483        *  +-----------+
7484        *  |AAAAAAAAA  | When the geometry widget is large, things are
7485        *  |GGGGGGGGGGB| clearer.
7486        *  |GGGGGGGGGGB|
7487        *  |GGGGGGGGGG |
7488        *  +-----------+
7489        */
7490 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7491       GtkRequisition requisition;
7492       int current_width, current_height;
7493
7494       _gtk_widget_override_size_request (geometry_info->widget,
7495                                          TEMPORARY_SIZE, TEMPORARY_SIZE,
7496                                          &current_width, &current_height);
7497       gtk_widget_get_preferred_size (widget,
7498                                      &requisition, NULL);
7499       _gtk_widget_restore_size_request (geometry_info->widget,
7500                                         current_width, current_height);
7501
7502       extra_width = requisition.width - TEMPORARY_SIZE;
7503       extra_height = requisition.height - TEMPORARY_SIZE;
7504
7505       if (extra_width < 0 || extra_height < 0)
7506         {
7507           g_warning("Toplevel size doesn't seem to directly depend on the "
7508                     "size of the geometry widget from gtk_window_set_geometry_hints(). "
7509                     "The geometry widget might not be in the window, or it might not "
7510                     "be packed into the window appropriately");
7511           extra_width = MAX(extra_width, 0);
7512           extra_height = MAX(extra_height, 0);
7513         }
7514 #undef TEMPORARY_SIZE
7515     }
7516
7517   /* We don't want to set GDK_HINT_POS in here, we just set it
7518    * in gtk_window_move_resize() when we want the position
7519    * honored.
7520    */
7521   
7522   if (*new_flags & GDK_HINT_BASE_SIZE)
7523     {
7524       new_geometry->base_width += extra_width;
7525       new_geometry->base_height += extra_height;
7526     }
7527   else
7528     {
7529       /* For simplicity, we always set the base hint, even when we
7530        * don't expect it to have any visible effect.
7531        * (Note: geometry_size_to_pixels() depends on this.)
7532        */
7533       *new_flags |= GDK_HINT_BASE_SIZE;
7534
7535       new_geometry->base_width = extra_width;
7536       new_geometry->base_height = extra_height;
7537
7538       /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7539        * base size is the minimum size */
7540       if (*new_flags & GDK_HINT_MIN_SIZE)
7541         {
7542           if (new_geometry->min_width > 0)
7543             new_geometry->base_width += new_geometry->min_width;
7544           if (new_geometry->min_height > 0)
7545             new_geometry->base_height += new_geometry->min_height;
7546         }
7547     }
7548
7549   /* Please use a good size for unresizable widgets, not the minimum one. */
7550   if (!priv->resizable)
7551     gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7552
7553   if (*new_flags & GDK_HINT_MIN_SIZE)
7554     {
7555       if (new_geometry->min_width < 0)
7556         new_geometry->min_width = requisition.width;
7557       else
7558         new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7559
7560       if (new_geometry->min_height < 0)
7561         new_geometry->min_height = requisition.height;
7562       else
7563         new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7564     }
7565   else
7566     {
7567       *new_flags |= GDK_HINT_MIN_SIZE;
7568       
7569       new_geometry->min_width = requisition.width;
7570       new_geometry->min_height = requisition.height;
7571     }
7572   
7573   if (*new_flags & GDK_HINT_MAX_SIZE)
7574     {
7575       if (new_geometry->max_width < 0)
7576         new_geometry->max_width = requisition.width;
7577       else
7578         new_geometry->max_width += extra_width;
7579
7580       if (new_geometry->max_height < 0)
7581         new_geometry->max_height = requisition.height;
7582       else
7583         new_geometry->max_height += extra_height;
7584     }
7585   else if (!priv->resizable)
7586     {
7587       *new_flags |= GDK_HINT_MAX_SIZE;
7588       
7589       new_geometry->max_width = requisition.width;
7590       new_geometry->max_height = requisition.height;
7591     }
7592
7593   *new_flags |= GDK_HINT_WIN_GRAVITY;
7594   new_geometry->win_gravity = priv->gravity;
7595 }
7596
7597 /***********************
7598  * Redrawing functions *
7599  ***********************/
7600
7601 static gboolean
7602 gtk_window_draw (GtkWidget *widget,
7603                  cairo_t   *cr)
7604 {
7605   GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7606   GtkStyleContext *context;
7607   gboolean ret = FALSE;
7608
7609   context = gtk_widget_get_style_context (widget);
7610
7611   if (!gtk_widget_get_app_paintable (widget) &&
7612       gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
7613     {
7614       gtk_render_background (context, cr, 0, 0,
7615                              gtk_widget_get_allocated_width (widget),
7616                              gtk_widget_get_allocated_height (widget));
7617     }
7618
7619   if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7620     ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7621
7622   if (priv->grip_window &&
7623       gtk_cairo_should_draw_window (cr, priv->grip_window))
7624     {
7625       GdkRectangle rect;
7626
7627       gtk_style_context_save (context);
7628       cairo_save (cr);
7629
7630       gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7631       gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7632
7633       gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND);
7634       gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7635       gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7636       gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7637
7638       cairo_restore (cr);
7639       gtk_style_context_restore (context);
7640     }
7641
7642   return ret;
7643 }
7644
7645 /**
7646  * gtk_window_present:
7647  * @window: a #GtkWindow
7648  *
7649  * Presents a window to the user. This may mean raising the window
7650  * in the stacking order, deiconifying it, moving it to the current
7651  * desktop, and/or giving it the keyboard focus, possibly dependent
7652  * on the user's platform, window manager, and preferences.
7653  *
7654  * If @window is hidden, this function calls gtk_widget_show()
7655  * as well.
7656  * 
7657  * This function should be used when the user tries to open a window
7658  * that's already open. Say for example the preferences dialog is
7659  * currently open, and the user chooses Preferences from the menu
7660  * a second time; use gtk_window_present() to move the already-open dialog
7661  * where the user can see it.
7662  *
7663  * If you are calling this function in response to a user interaction,
7664  * it is preferable to use gtk_window_present_with_time().
7665  * 
7666  **/
7667 void
7668 gtk_window_present (GtkWindow *window)
7669 {
7670   gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7671 }
7672
7673 /**
7674  * gtk_window_present_with_time:
7675  * @window: a #GtkWindow
7676  * @timestamp: the timestamp of the user interaction (typically a 
7677  *   button or key press event) which triggered this call
7678  *
7679  * Presents a window to the user in response to a user interaction.
7680  * If you need to present a window without a timestamp, use 
7681  * gtk_window_present(). See gtk_window_present() for details. 
7682  * 
7683  * Since: 2.8
7684  **/
7685 void
7686 gtk_window_present_with_time (GtkWindow *window,
7687                               guint32    timestamp)
7688 {
7689   GtkWindowPrivate *priv;
7690   GtkWidget *widget;
7691   GdkWindow *gdk_window;
7692
7693   g_return_if_fail (GTK_IS_WINDOW (window));
7694
7695   priv = window->priv;
7696   widget = GTK_WIDGET (window);
7697
7698   if (gtk_widget_get_visible (widget))
7699     {
7700       gdk_window = gtk_widget_get_window (widget);
7701
7702       g_assert (gdk_window != NULL);
7703
7704       gdk_window_show (gdk_window);
7705
7706       /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7707       if (timestamp == GDK_CURRENT_TIME)
7708         {
7709 #ifdef GDK_WINDOWING_X11
7710           if (GDK_IS_X11_WINDOW(gdk_window))
7711             {
7712               GdkDisplay *display;
7713
7714               display = gtk_widget_get_display (GTK_WIDGET (window));
7715               timestamp = gdk_x11_display_get_user_time (display);
7716             }
7717           else
7718 #endif
7719             timestamp = gtk_get_current_event_time ();
7720         }
7721
7722       gdk_window_focus (gdk_window, timestamp);
7723     }
7724   else
7725     {
7726       priv->initial_timestamp = timestamp;
7727       gtk_widget_show (widget);
7728     }
7729 }
7730
7731 /**
7732  * gtk_window_iconify:
7733  * @window: a #GtkWindow
7734  *
7735  * Asks to iconify (i.e. minimize) the specified @window. Note that
7736  * you shouldn't assume the window is definitely iconified afterward,
7737  * because other entities (e.g. the user or <link
7738  * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7739  * again, or there may not be a window manager in which case
7740  * iconification isn't possible, etc. But normally the window will end
7741  * up iconified. Just don't write code that crashes if not.
7742  *
7743  * It's permitted to call this function before showing a window,
7744  * in which case the window will be iconified before it ever appears
7745  * onscreen.
7746  *
7747  * You can track iconification via the "window-state-event" signal
7748  * on #GtkWidget.
7749  * 
7750  **/
7751 void
7752 gtk_window_iconify (GtkWindow *window)
7753 {
7754   GtkWindowPrivate *priv;
7755   GtkWidget *widget;
7756   GdkWindow *toplevel;
7757   
7758   g_return_if_fail (GTK_IS_WINDOW (window));
7759
7760   priv = window->priv;
7761   widget = GTK_WIDGET (window);
7762
7763   priv->iconify_initially = TRUE;
7764
7765   toplevel = gtk_widget_get_window (widget);
7766
7767   if (toplevel != NULL)
7768     gdk_window_iconify (toplevel);
7769 }
7770
7771 /**
7772  * gtk_window_deiconify:
7773  * @window: a #GtkWindow
7774  *
7775  * Asks to deiconify (i.e. unminimize) the specified @window. Note
7776  * that you shouldn't assume the window is definitely deiconified
7777  * afterward, because other entities (e.g. the user or <link
7778  * linkend="gtk-X11-arch">window manager</link>) could iconify it
7779  * again before your code which assumes deiconification gets to run.
7780  *
7781  * You can track iconification via the "window-state-event" signal
7782  * on #GtkWidget.
7783  **/
7784 void
7785 gtk_window_deiconify (GtkWindow *window)
7786 {
7787   GtkWindowPrivate *priv;
7788   GtkWidget *widget;
7789   GdkWindow *toplevel;
7790   
7791   g_return_if_fail (GTK_IS_WINDOW (window));
7792
7793   priv = window->priv;
7794   widget = GTK_WIDGET (window);
7795
7796   priv->iconify_initially = FALSE;
7797
7798   toplevel = gtk_widget_get_window (widget);
7799
7800   if (toplevel != NULL)
7801     gdk_window_deiconify (toplevel);
7802 }
7803
7804 /**
7805  * gtk_window_stick:
7806  * @window: a #GtkWindow
7807  *
7808  * Asks to stick @window, which means that it will appear on all user
7809  * desktops. Note that you shouldn't assume the window is definitely
7810  * stuck afterward, because other entities (e.g. the user or <link
7811  * linkend="gtk-X11-arch">window manager</link>) could unstick it
7812  * again, and some window managers do not support sticking
7813  * windows. But normally the window will end up stuck. Just don't
7814  * write code that crashes if not.
7815  *
7816  * It's permitted to call this function before showing a window.
7817  *
7818  * You can track stickiness via the "window-state-event" signal
7819  * on #GtkWidget.
7820  * 
7821  **/
7822 void
7823 gtk_window_stick (GtkWindow *window)
7824 {
7825   GtkWindowPrivate *priv;
7826   GtkWidget *widget;
7827   GdkWindow *toplevel;
7828   
7829   g_return_if_fail (GTK_IS_WINDOW (window));
7830
7831   priv = window->priv;
7832   widget = GTK_WIDGET (window);
7833
7834   priv->stick_initially = TRUE;
7835
7836   toplevel = gtk_widget_get_window (widget);
7837
7838   if (toplevel != NULL)
7839     gdk_window_stick (toplevel);
7840 }
7841
7842 /**
7843  * gtk_window_unstick:
7844  * @window: a #GtkWindow
7845  *
7846  * Asks to unstick @window, which means that it will appear on only
7847  * one of the user's desktops. Note that you shouldn't assume the
7848  * window is definitely unstuck afterward, because other entities
7849  * (e.g. the user or <link linkend="gtk-X11-arch">window
7850  * manager</link>) could stick it again. But normally the window will
7851  * end up stuck. Just don't write code that crashes if not.
7852  *
7853  * You can track stickiness via the "window-state-event" signal
7854  * on #GtkWidget.
7855  * 
7856  **/
7857 void
7858 gtk_window_unstick (GtkWindow *window)
7859 {
7860   GtkWindowPrivate *priv;
7861   GtkWidget *widget;
7862   GdkWindow *toplevel;
7863   
7864   g_return_if_fail (GTK_IS_WINDOW (window));
7865
7866   priv = window->priv;
7867   widget = GTK_WIDGET (window);
7868
7869   priv->stick_initially = FALSE;
7870
7871   toplevel = gtk_widget_get_window (widget);
7872
7873   if (toplevel != NULL)
7874     gdk_window_unstick (toplevel);
7875 }
7876
7877 /**
7878  * gtk_window_maximize:
7879  * @window: a #GtkWindow
7880  *
7881  * Asks to maximize @window, so that it becomes full-screen. Note that
7882  * you shouldn't assume the window is definitely maximized afterward,
7883  * because other entities (e.g. the user or <link
7884  * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7885  * again, and not all window managers support maximization. But
7886  * normally the window will end up maximized. Just don't write code
7887  * that crashes if not.
7888  *
7889  * It's permitted to call this function before showing a window,
7890  * in which case the window will be maximized when it appears onscreen
7891  * initially.
7892  *
7893  * You can track maximization via the "window-state-event" signal
7894  * on #GtkWidget.
7895  * 
7896  **/
7897 void
7898 gtk_window_maximize (GtkWindow *window)
7899 {
7900   GtkWindowPrivate *priv;
7901   GtkWidget *widget;
7902   GdkWindow *toplevel;
7903   
7904   g_return_if_fail (GTK_IS_WINDOW (window));
7905
7906   priv = window->priv;
7907   widget = GTK_WIDGET (window);
7908
7909   priv->maximize_initially = TRUE;
7910
7911   toplevel = gtk_widget_get_window (widget);
7912
7913   if (toplevel != NULL)
7914     gdk_window_maximize (toplevel);
7915 }
7916
7917 /**
7918  * gtk_window_unmaximize:
7919  * @window: a #GtkWindow
7920  *
7921  * Asks to unmaximize @window. Note that you shouldn't assume the
7922  * window is definitely unmaximized afterward, because other entities
7923  * (e.g. the user or <link linkend="gtk-X11-arch">window
7924  * manager</link>) could maximize it again, and not all window
7925  * managers honor requests to unmaximize. But normally the window will
7926  * end up unmaximized. Just don't write code that crashes if not.
7927  *
7928  * You can track maximization via the "window-state-event" signal
7929  * on #GtkWidget.
7930  * 
7931  **/
7932 void
7933 gtk_window_unmaximize (GtkWindow *window)
7934 {
7935   GtkWindowPrivate *priv;
7936   GtkWidget *widget;
7937   GdkWindow *toplevel;
7938   
7939   g_return_if_fail (GTK_IS_WINDOW (window));
7940
7941   priv = window->priv;
7942   widget = GTK_WIDGET (window);
7943
7944   priv->maximize_initially = FALSE;
7945
7946   toplevel = gtk_widget_get_window (widget);
7947
7948   if (toplevel != NULL)
7949     gdk_window_unmaximize (toplevel);
7950 }
7951
7952 /**
7953  * gtk_window_fullscreen:
7954  * @window: a #GtkWindow
7955  *
7956  * Asks to place @window in the fullscreen state. Note that you
7957  * shouldn't assume the window is definitely full screen afterward,
7958  * because other entities (e.g. the user or <link
7959  * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7960  * again, and not all window managers honor requests to fullscreen
7961  * windows. But normally the window will end up fullscreen. Just
7962  * don't write code that crashes if not.
7963  *
7964  * You can track the fullscreen state via the "window-state-event" signal
7965  * on #GtkWidget.
7966  * 
7967  * Since: 2.2
7968  **/
7969 void
7970 gtk_window_fullscreen (GtkWindow *window)
7971 {
7972   GtkWindowPrivate *priv;
7973   GtkWidget *widget;
7974   GdkWindow *toplevel;
7975
7976   g_return_if_fail (GTK_IS_WINDOW (window));
7977
7978   priv = window->priv;
7979   widget = GTK_WIDGET (window);
7980
7981   priv->fullscreen_initially = TRUE;
7982
7983   toplevel = gtk_widget_get_window (widget);
7984
7985   if (toplevel != NULL)
7986     gdk_window_fullscreen (toplevel);
7987 }
7988
7989 /**
7990  * gtk_window_unfullscreen:
7991  * @window: a #GtkWindow
7992  *
7993  * Asks to toggle off the fullscreen state for @window. Note that you
7994  * shouldn't assume the window is definitely not full screen
7995  * afterward, because other entities (e.g. the user or <link
7996  * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7997  * again, and not all window managers honor requests to unfullscreen
7998  * windows. But normally the window will end up restored to its normal
7999  * state. Just don't write code that crashes if not.
8000  *
8001  * You can track the fullscreen state via the "window-state-event" signal
8002  * on #GtkWidget.
8003  * 
8004  * Since: 2.2
8005  **/
8006 void
8007 gtk_window_unfullscreen (GtkWindow *window)
8008 {
8009   GtkWidget *widget;
8010   GdkWindow *toplevel;
8011   GtkWindowPrivate *priv;
8012
8013   g_return_if_fail (GTK_IS_WINDOW (window));
8014
8015   priv = window->priv;
8016   widget = GTK_WIDGET (window);
8017
8018   priv->fullscreen_initially = FALSE;
8019
8020   toplevel = gtk_widget_get_window (widget);
8021
8022   if (toplevel != NULL)
8023     gdk_window_unfullscreen (toplevel);
8024 }
8025
8026 /**
8027  * gtk_window_set_keep_above:
8028  * @window: a #GtkWindow
8029  * @setting: whether to keep @window above other windows
8030  *
8031  * Asks to keep @window above, so that it stays on top. Note that
8032  * you shouldn't assume the window is definitely above afterward,
8033  * because other entities (e.g. the user or <link
8034  * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
8035  * and not all window managers support keeping windows above. But
8036  * normally the window will end kept above. Just don't write code
8037  * that crashes if not.
8038  *
8039  * It's permitted to call this function before showing a window,
8040  * in which case the window will be kept above when it appears onscreen
8041  * initially.
8042  *
8043  * You can track the above state via the "window-state-event" signal
8044  * on #GtkWidget.
8045  *
8046  * Note that, according to the <ulink 
8047  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
8048  * Manager Hints</ulink> specification, the above state is mainly meant 
8049  * for user preferences and should not be used by applications e.g. for 
8050  * drawing attention to their dialogs.
8051  *
8052  * Since: 2.4
8053  **/
8054 void
8055 gtk_window_set_keep_above (GtkWindow *window,
8056                            gboolean   setting)
8057 {
8058   GtkWidget *widget;
8059   GtkWindowPrivate *priv;
8060   GdkWindow *toplevel;
8061
8062   g_return_if_fail (GTK_IS_WINDOW (window));
8063
8064   priv = window->priv;
8065   widget = GTK_WIDGET (window);
8066
8067   priv->above_initially = setting != FALSE;
8068   if (setting)
8069     priv->below_initially = FALSE;
8070
8071   toplevel = gtk_widget_get_window (widget);
8072
8073   if (toplevel != NULL)
8074     gdk_window_set_keep_above (toplevel, setting);
8075 }
8076
8077 /**
8078  * gtk_window_set_keep_below:
8079  * @window: a #GtkWindow
8080  * @setting: whether to keep @window below other windows
8081  *
8082  * Asks to keep @window below, so that it stays in bottom. Note that
8083  * you shouldn't assume the window is definitely below afterward,
8084  * because other entities (e.g. the user or <link
8085  * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8086  * and not all window managers support putting windows below. But
8087  * normally the window will be kept below. Just don't write code
8088  * that crashes if not.
8089  *
8090  * It's permitted to call this function before showing a window,
8091  * in which case the window will be kept below when it appears onscreen
8092  * initially.
8093  *
8094  * You can track the below state via the "window-state-event" signal
8095  * on #GtkWidget.
8096  *
8097  * Note that, according to the <ulink 
8098  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
8099  * Manager Hints</ulink> specification, the above state is mainly meant 
8100  * for user preferences and should not be used by applications e.g. for 
8101  * drawing attention to their dialogs.
8102  *
8103  * Since: 2.4
8104  **/
8105 void
8106 gtk_window_set_keep_below (GtkWindow *window,
8107                            gboolean   setting)
8108 {
8109   GtkWidget *widget;
8110   GtkWindowPrivate *priv;
8111   GdkWindow *toplevel;
8112
8113   g_return_if_fail (GTK_IS_WINDOW (window));
8114
8115   priv = window->priv;
8116   widget = GTK_WIDGET (window);
8117
8118   priv->below_initially = setting != FALSE;
8119   if (setting)
8120     priv->above_initially = FALSE;
8121
8122   toplevel = gtk_widget_get_window (widget);
8123
8124   if (toplevel != NULL)
8125     gdk_window_set_keep_below (toplevel, setting);
8126 }
8127
8128 /**
8129  * gtk_window_set_resizable:
8130  * @window: a #GtkWindow
8131  * @resizable: %TRUE if the user can resize this window
8132  *
8133  * Sets whether the user can resize a window. Windows are user resizable
8134  * by default.
8135  **/
8136 void
8137 gtk_window_set_resizable (GtkWindow *window,
8138                           gboolean   resizable)
8139 {
8140   GtkWindowPrivate *priv;
8141
8142   g_return_if_fail (GTK_IS_WINDOW (window));
8143
8144   priv = window->priv;
8145
8146   resizable = (resizable != FALSE);
8147
8148   if (priv->resizable != resizable)
8149     {
8150       priv->resizable = resizable;
8151
8152       update_grip_visibility (window);
8153
8154       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8155
8156       g_object_notify (G_OBJECT (window), "resizable");
8157     }
8158 }
8159
8160 /**
8161  * gtk_window_get_resizable:
8162  * @window: a #GtkWindow
8163  *
8164  * Gets the value set by gtk_window_set_resizable().
8165  *
8166  * Return value: %TRUE if the user can resize the window
8167  **/
8168 gboolean
8169 gtk_window_get_resizable (GtkWindow *window)
8170 {
8171   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8172
8173   return window->priv->resizable;
8174 }
8175
8176 /**
8177  * gtk_window_set_gravity:
8178  * @window: a #GtkWindow
8179  * @gravity: window gravity
8180  *
8181  * Window gravity defines the meaning of coordinates passed to
8182  * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8183  * more details.
8184  *
8185  * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8186  * typically "do what you mean."
8187  *
8188  **/
8189 void
8190 gtk_window_set_gravity (GtkWindow *window,
8191                         GdkGravity gravity)
8192 {
8193   GtkWindowPrivate *priv;
8194
8195   g_return_if_fail (GTK_IS_WINDOW (window));
8196
8197   priv = window->priv;
8198
8199   if (gravity != priv->gravity)
8200     {
8201       priv->gravity = gravity;
8202
8203       /* gtk_window_move_resize() will adapt gravity
8204        */
8205       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8206
8207       g_object_notify (G_OBJECT (window), "gravity");
8208     }
8209 }
8210
8211 /**
8212  * gtk_window_get_gravity:
8213  * @window: a #GtkWindow
8214  *
8215  * Gets the value set by gtk_window_set_gravity().
8216  *
8217  * Return value: (transfer none): window gravity
8218  **/
8219 GdkGravity
8220 gtk_window_get_gravity (GtkWindow *window)
8221 {
8222   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8223
8224   return window->priv->gravity;
8225 }
8226
8227 /**
8228  * gtk_window_begin_resize_drag:
8229  * @window: a #GtkWindow
8230  * @button: mouse button that initiated the drag
8231  * @edge: position of the resize control
8232  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8233  * @root_y: Y position where the user clicked to initiate the drag
8234  * @timestamp: timestamp from the click event that initiated the drag
8235  *
8236  * Starts resizing a window. This function is used if an application
8237  * has window resizing controls. When GDK can support it, the resize
8238  * will be done using the standard mechanism for the <link
8239  * linkend="gtk-X11-arch">window manager</link> or windowing
8240  * system. Otherwise, GDK will try to emulate window resizing,
8241  * potentially not all that well, depending on the windowing system.
8242  * 
8243  **/
8244 void
8245 gtk_window_begin_resize_drag  (GtkWindow    *window,
8246                                GdkWindowEdge edge,
8247                                gint          button,
8248                                gint          root_x,
8249                                gint          root_y,
8250                                guint32       timestamp)
8251 {
8252   GtkWidget *widget;
8253   GdkWindow *toplevel;
8254
8255   g_return_if_fail (GTK_IS_WINDOW (window));
8256   widget = GTK_WIDGET (window);
8257   g_return_if_fail (gtk_widget_get_visible (widget));
8258
8259   toplevel = gtk_widget_get_window (widget);
8260
8261   gdk_window_begin_resize_drag (toplevel,
8262                                 edge, button,
8263                                 root_x, root_y,
8264                                 timestamp);
8265 }
8266
8267 /**
8268  * gtk_window_begin_move_drag:
8269  * @window: a #GtkWindow
8270  * @button: mouse button that initiated the drag
8271  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8272  * @root_y: Y position where the user clicked to initiate the drag
8273  * @timestamp: timestamp from the click event that initiated the drag
8274  *
8275  * Starts moving a window. This function is used if an application has
8276  * window movement grips. When GDK can support it, the window movement
8277  * will be done using the standard mechanism for the <link
8278  * linkend="gtk-X11-arch">window manager</link> or windowing
8279  * system. Otherwise, GDK will try to emulate window movement,
8280  * potentially not all that well, depending on the windowing system.
8281  * 
8282  **/
8283 void
8284 gtk_window_begin_move_drag  (GtkWindow *window,
8285                              gint       button,
8286                              gint       root_x,
8287                              gint       root_y,
8288                              guint32    timestamp)
8289 {
8290   GtkWidget *widget;
8291   GdkWindow *toplevel;
8292
8293   g_return_if_fail (GTK_IS_WINDOW (window));
8294   widget = GTK_WIDGET (window);
8295   g_return_if_fail (gtk_widget_get_visible (widget));
8296
8297   toplevel = gtk_widget_get_window (widget);
8298
8299   gdk_window_begin_move_drag (toplevel,
8300                               button,
8301                               root_x, root_y,
8302                               timestamp);
8303 }
8304
8305 /**
8306  * gtk_window_set_screen:
8307  * @window: a #GtkWindow.
8308  * @screen: a #GdkScreen.
8309  *
8310  * Sets the #GdkScreen where the @window is displayed; if
8311  * the window is already mapped, it will be unmapped, and
8312  * then remapped on the new screen.
8313  *
8314  * Since: 2.2
8315  */
8316 void
8317 gtk_window_set_screen (GtkWindow *window,
8318                        GdkScreen *screen)
8319 {
8320   GtkWindowPrivate *priv;
8321   GtkWidget *widget;
8322   GdkScreen *previous_screen;
8323   gboolean was_mapped;
8324
8325   g_return_if_fail (GTK_IS_WINDOW (window));
8326   g_return_if_fail (GDK_IS_SCREEN (screen));
8327
8328   priv = window->priv;
8329
8330   if (screen == priv->screen)
8331     return;
8332
8333   widget = GTK_WIDGET (window);
8334
8335   previous_screen = priv->screen;
8336   was_mapped = gtk_widget_get_mapped (widget);
8337
8338   if (was_mapped)
8339     gtk_widget_unmap (widget);
8340   if (gtk_widget_get_realized (widget))
8341     gtk_widget_unrealize (widget);
8342
8343   gtk_window_free_key_hash (window);
8344   priv->screen = screen;
8345   gtk_widget_reset_rc_styles (widget);
8346   if (screen != previous_screen)
8347     {
8348       if (previous_screen)
8349         {
8350           g_signal_handlers_disconnect_by_func (previous_screen,
8351                                                 gtk_window_on_composited_changed, window);
8352 #ifdef GDK_WINDOWING_X11
8353           g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8354                                                 gtk_window_on_theme_variant_changed, window);
8355 #endif
8356         }
8357       g_signal_connect (screen, "composited-changed",
8358                         G_CALLBACK (gtk_window_on_composited_changed), window);
8359 #ifdef GDK_WINDOWING_X11
8360       g_signal_connect (gtk_settings_get_for_screen (screen),
8361                         "notify::gtk-application-prefer-dark-theme",
8362                         G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8363 #endif
8364
8365       _gtk_widget_propagate_screen_changed (widget, previous_screen);
8366       _gtk_widget_propagate_composited_changed (widget);
8367     }
8368   g_object_notify (G_OBJECT (window), "screen");
8369
8370   if (was_mapped)
8371     gtk_widget_map (widget);
8372 }
8373
8374 static void
8375 gtk_window_set_theme_variant (GtkWindow *window)
8376 {
8377 #ifdef GDK_WINDOWING_X11
8378   GdkWindow *gdk_window;
8379   gboolean   dark_theme_requested;
8380
8381   g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8382                 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8383                 NULL);
8384
8385   gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8386
8387   if (GDK_IS_X11_WINDOW (gdk_window))
8388     gdk_x11_window_set_theme_variant (gdk_window,
8389                                       dark_theme_requested ? "dark" : NULL);
8390 #endif
8391 }
8392
8393 static void
8394 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8395                                      GParamSpec  *pspec,
8396                                      GtkWindow   *window)
8397 {
8398   if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8399     gtk_window_set_theme_variant (window);
8400 }
8401
8402 static void
8403 gtk_window_on_composited_changed (GdkScreen *screen,
8404                                   GtkWindow *window)
8405 {
8406   gtk_widget_queue_draw (GTK_WIDGET (window));
8407   
8408   _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8409 }
8410
8411 static GdkScreen *
8412 gtk_window_check_screen (GtkWindow *window)
8413 {
8414   GtkWindowPrivate *priv = window->priv;
8415
8416   if (priv->screen)
8417     return priv->screen;
8418   else
8419     {
8420       g_warning ("Screen for GtkWindow not set; you must always set\n"
8421                  "a screen for a GtkWindow before using the window");
8422       return NULL;
8423     }
8424 }
8425
8426 /**
8427  * gtk_window_get_screen:
8428  * @window: a #GtkWindow.
8429  *
8430  * Returns the #GdkScreen associated with @window.
8431  *
8432  * Return value: (transfer none): a #GdkScreen.
8433  *
8434  * Since: 2.2
8435  */
8436 GdkScreen*
8437 gtk_window_get_screen (GtkWindow *window)
8438 {
8439   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8440
8441   return window->priv->screen;
8442 }
8443
8444 /**
8445  * gtk_window_is_active:
8446  * @window: a #GtkWindow
8447  * 
8448  * Returns whether the window is part of the current active toplevel.
8449  * (That is, the toplevel window receiving keystrokes.)
8450  * The return value is %TRUE if the window is active toplevel
8451  * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8452  * You might use this function if you wanted to draw a widget
8453  * differently in an active window from a widget in an inactive window.
8454  * See gtk_window_has_toplevel_focus()
8455  * 
8456  * Return value: %TRUE if the window part of the current active window.
8457  *
8458  * Since: 2.4
8459  **/
8460 gboolean
8461 gtk_window_is_active (GtkWindow *window)
8462 {
8463   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8464
8465   return window->priv->is_active;
8466 }
8467
8468 /**
8469  * gtk_window_has_toplevel_focus:
8470  * @window: a #GtkWindow
8471  * 
8472  * Returns whether the input focus is within this GtkWindow.
8473  * For real toplevel windows, this is identical to gtk_window_is_active(),
8474  * but for embedded windows, like #GtkPlug, the results will differ.
8475  * 
8476  * Return value: %TRUE if the input focus is within this GtkWindow
8477  *
8478  * Since: 2.4
8479  **/
8480 gboolean
8481 gtk_window_has_toplevel_focus (GtkWindow *window)
8482 {
8483   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8484
8485   return window->priv->has_toplevel_focus;
8486 }
8487
8488
8489 /**
8490  * SECTION:gtkwindowgroup
8491  * @Short_description: Limit the effect of grabs
8492  * @Title: GtkWindowGroup
8493  *
8494  * #GtkWindowGroup objects are referenced by each window in the group,
8495  * so once you have added all windows to a #GtkWindowGroup, you can drop
8496  * the initial reference to the window group with g_object_unref(). If the
8497  * windows in the window group are subsequently destroyed, then they will
8498  * be removed from the window group and drop their references on the window
8499  * group; when all window have been removed, the window group will be
8500  * freed.
8501  */
8502
8503 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8504
8505 static void
8506 gtk_window_group_init (GtkWindowGroup *group)
8507 {
8508   group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8509                                              GTK_TYPE_WINDOW_GROUP,
8510                                              GtkWindowGroupPrivate);
8511 }
8512
8513 static void
8514 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8515 {
8516   g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8517 }
8518
8519 /**
8520  * gtk_window_group_new:
8521  * 
8522  * Creates a new #GtkWindowGroup object. Grabs added with
8523  * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8524  * 
8525  * Return value: a new #GtkWindowGroup. 
8526  **/
8527 GtkWindowGroup *
8528 gtk_window_group_new (void)
8529 {
8530   return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8531 }
8532
8533 static void
8534 window_group_cleanup_grabs (GtkWindowGroup *group,
8535                             GtkWindow      *window)
8536 {
8537   GtkWindowGroupPrivate *priv;
8538   GtkDeviceGrabInfo *info;
8539   GSList *tmp_list;
8540   GSList *to_remove = NULL;
8541
8542   priv = group->priv;
8543
8544   tmp_list = priv->grabs;
8545   while (tmp_list)
8546     {
8547       if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8548         to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8549       tmp_list = tmp_list->next;
8550     }
8551
8552   while (to_remove)
8553     {
8554       gtk_grab_remove (to_remove->data);
8555       g_object_unref (to_remove->data);
8556       to_remove = g_slist_delete_link (to_remove, to_remove);
8557     }
8558
8559   tmp_list = priv->device_grabs;
8560
8561   while (tmp_list)
8562     {
8563       info = tmp_list->data;
8564
8565       if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8566         to_remove = g_slist_prepend (to_remove, info);
8567
8568       tmp_list = tmp_list->next;
8569     }
8570
8571   while (to_remove)
8572     {
8573       info = to_remove->data;
8574
8575       gtk_device_grab_remove (info->widget, info->device);
8576       to_remove = g_slist_delete_link (to_remove, to_remove);
8577     }
8578 }
8579
8580 /**
8581  * gtk_window_group_add_window:
8582  * @window_group: a #GtkWindowGroup
8583  * @window: the #GtkWindow to add
8584  * 
8585  * Adds a window to a #GtkWindowGroup. 
8586  **/
8587 void
8588 gtk_window_group_add_window (GtkWindowGroup *window_group,
8589                              GtkWindow      *window)
8590 {
8591   GtkWindowPrivate *priv;
8592
8593   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8594   g_return_if_fail (GTK_IS_WINDOW (window));
8595
8596   priv = window->priv;
8597
8598   if (priv->group != window_group)
8599     {
8600       g_object_ref (window);
8601       g_object_ref (window_group);
8602
8603       if (priv->group)
8604         gtk_window_group_remove_window (priv->group, window);
8605       else
8606         window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8607
8608       priv->group = window_group;
8609
8610       g_object_unref (window);
8611     }
8612 }
8613
8614 /**
8615  * gtk_window_group_remove_window:
8616  * @window_group: a #GtkWindowGroup
8617  * @window: the #GtkWindow to remove
8618  * 
8619  * Removes a window from a #GtkWindowGroup.
8620  **/
8621 void
8622 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8623                                 GtkWindow      *window)
8624 {
8625   GtkWindowPrivate *priv;
8626
8627   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8628   g_return_if_fail (GTK_IS_WINDOW (window));
8629   priv = window->priv;
8630   g_return_if_fail (priv->group == window_group);
8631
8632   g_object_ref (window);
8633
8634   window_group_cleanup_grabs (window_group, window);
8635   priv->group = NULL;
8636
8637   g_object_unref (window_group);
8638   g_object_unref (window);
8639 }
8640
8641 /**
8642  * gtk_window_group_list_windows:
8643  * @window_group: a #GtkWindowGroup
8644  *
8645  * Returns a list of the #GtkWindows that belong to @window_group.
8646  *
8647  * Returns: (element-type GtkWindow) (transfer container): A
8648  *   newly-allocated list of windows inside the group.
8649  *
8650  * Since: 2.14
8651  **/
8652 GList *
8653 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8654 {
8655   GList *toplevels, *toplevel, *group_windows;
8656
8657   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8658
8659   group_windows = NULL;
8660   toplevels = gtk_window_list_toplevels ();
8661
8662   for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8663     {
8664       GtkWindow *window = toplevel->data;
8665
8666       if (window_group == window->priv->group)
8667         group_windows = g_list_prepend (group_windows, window);
8668     }
8669
8670   g_list_free (toplevels);
8671
8672   return g_list_reverse (group_windows);
8673 }
8674
8675 /**
8676  * gtk_window_get_group:
8677  * @window: (allow-none): a #GtkWindow, or %NULL
8678  *
8679  * Returns the group for @window or the default group, if
8680  * @window is %NULL or if @window does not have an explicit
8681  * window group.
8682  *
8683  * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8684  *
8685  * Since: 2.10
8686  */
8687 GtkWindowGroup *
8688 gtk_window_get_group (GtkWindow *window)
8689 {
8690   if (window && window->priv->group)
8691     return window->priv->group;
8692   else
8693     {
8694       static GtkWindowGroup *default_group = NULL;
8695
8696       if (!default_group)
8697         default_group = gtk_window_group_new ();
8698
8699       return default_group;
8700     }
8701 }
8702
8703 /**
8704  * gtk_window_has_group:
8705  * @window: a #GtkWindow
8706  *
8707  * Returns whether @window has an explicit window group.
8708  *
8709  * Return value: %TRUE if @window has an explicit window group.
8710  *
8711  * Since 2.22
8712  **/
8713 gboolean
8714 gtk_window_has_group (GtkWindow *window)
8715 {
8716   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8717
8718   return window->priv->group != NULL;
8719 }
8720
8721 /**
8722  * gtk_window_group_get_current_grab:
8723  * @window_group: a #GtkWindowGroup
8724  *
8725  * Gets the current grab widget of the given group,
8726  * see gtk_grab_add().
8727  *
8728  * Returns: (transfer none): the current grab widget of the group
8729  *
8730  * Since: 2.22
8731  */
8732 GtkWidget *
8733 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8734 {
8735   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8736
8737   if (window_group->priv->grabs)
8738     return GTK_WIDGET (window_group->priv->grabs->data);
8739   return NULL;
8740 }
8741
8742 void
8743 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8744                             GtkWidget      *widget)
8745 {
8746   GtkWindowGroupPrivate *priv;
8747
8748   priv = window_group->priv;
8749   priv->grabs = g_slist_prepend (priv->grabs, widget);
8750 }
8751
8752 void
8753 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8754                                GtkWidget      *widget)
8755 {
8756   GtkWindowGroupPrivate *priv;
8757
8758   priv = window_group->priv;
8759   priv->grabs = g_slist_remove (priv->grabs, widget);
8760 }
8761
8762
8763 void
8764 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8765                                    GtkWidget      *widget,
8766                                    GdkDevice      *device,
8767                                    gboolean        block_others)
8768 {
8769   GtkWindowGroupPrivate *priv;
8770   GtkDeviceGrabInfo *info;
8771
8772   priv = window_group->priv;
8773
8774   info = g_slice_new0 (GtkDeviceGrabInfo);
8775   info->widget = widget;
8776   info->device = device;
8777   info->block_others = block_others;
8778
8779   priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8780 }
8781
8782 void
8783 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8784                                       GtkWidget      *widget,
8785                                       GdkDevice      *device)
8786 {
8787   GtkWindowGroupPrivate *priv;
8788   GtkDeviceGrabInfo *info;
8789   GSList *list, *node = NULL;
8790   GdkDevice *other_device;
8791
8792   priv = window_group->priv;
8793   other_device = gdk_device_get_associated_device (device);
8794   list = priv->device_grabs;
8795
8796   while (list)
8797     {
8798       info = list->data;
8799
8800       if (info->widget == widget &&
8801           (info->device == device ||
8802            info->device == other_device))
8803         {
8804           node = list;
8805           break;
8806         }
8807
8808       list = list->next;
8809     }
8810
8811   if (node)
8812     {
8813       info = node->data;
8814
8815       priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8816       g_slice_free (GtkDeviceGrabInfo, info);
8817     }
8818 }
8819
8820 /**
8821  * gtk_window_group_get_current_device_grab:
8822  * @window_group: a #GtkWindowGroup
8823  * @device: a #GdkDevice
8824  *
8825  * Returns the current grab widget for @device, or %NULL if none.
8826  *
8827  * Returns: (transfer none): The grab widget, or %NULL
8828  *
8829  * Since: 3.0
8830  */
8831 GtkWidget *
8832 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8833                                           GdkDevice      *device)
8834 {
8835   GtkWindowGroupPrivate *priv;
8836   GtkDeviceGrabInfo *info;
8837   GdkDevice *other_device;
8838   GSList *list;
8839
8840   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8841   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8842
8843   priv = window_group->priv;
8844   list = priv->device_grabs;
8845   other_device = gdk_device_get_associated_device (device);
8846
8847   while (list)
8848     {
8849       info = list->data;
8850       list = list->next;
8851
8852       if (info->device == device ||
8853           info->device == other_device)
8854         return info->widget;
8855     }
8856
8857   return NULL;
8858 }
8859
8860 gboolean
8861 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8862                                                 GtkWidget      *widget,
8863                                                 GdkDevice      *device)
8864 {
8865   GtkWindowGroupPrivate *priv;
8866   GtkDeviceGrabInfo *info;
8867   GdkDevice *other_device;
8868   GSList *list;
8869
8870   priv = window_group->priv;
8871   other_device = gdk_device_get_associated_device (device);
8872   list = priv->device_grabs;
8873
8874   while (list)
8875     {
8876       info = list->data;
8877       list = list->next;
8878
8879       /* Look for blocking grabs on other device pairs
8880        * that have the passed widget within the GTK+ grab.
8881        */
8882       if (info->block_others &&
8883           info->device != device &&
8884           info->device != other_device &&
8885           (info->widget == widget ||
8886            gtk_widget_is_ancestor (widget, info->widget)))
8887         return TRUE;
8888     }
8889
8890   return FALSE;
8891 }
8892
8893 /*
8894   Derived from XParseGeometry() in XFree86  
8895
8896   Copyright 1985, 1986, 1987,1998  The Open Group
8897
8898   All Rights Reserved.
8899
8900   The above copyright notice and this permission notice shall be included
8901   in all copies or substantial portions of the Software.
8902
8903   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8904   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8905   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8906   IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8907   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8908   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8909   OTHER DEALINGS IN THE SOFTWARE.
8910
8911   Except as contained in this notice, the name of The Open Group shall
8912   not be used in advertising or otherwise to promote the sale, use or
8913   other dealings in this Software without prior written authorization
8914   from The Open Group.
8915 */
8916
8917
8918 /*
8919  *    XParseGeometry parses strings of the form
8920  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8921  *   width, height, xoffset, and yoffset are unsigned integers.
8922  *   Example:  "=80x24+300-49"
8923  *   The equal sign is optional.
8924  *   It returns a bitmask that indicates which of the four values
8925  *   were actually found in the string.  For each value found,
8926  *   the corresponding argument is updated;  for each value
8927  *   not found, the corresponding argument is left unchanged. 
8928  */
8929
8930 /* The following code is from Xlib, and is minimally modified, so we
8931  * can track any upstream changes if required.  Don't change this
8932  * code. Or if you do, put in a huge comment marking which thing
8933  * changed.
8934  */
8935
8936 static int
8937 read_int (gchar   *string,
8938           gchar  **next)
8939 {
8940   int result = 0;
8941   int sign = 1;
8942   
8943   if (*string == '+')
8944     string++;
8945   else if (*string == '-')
8946     {
8947       string++;
8948       sign = -1;
8949     }
8950
8951   for (; (*string >= '0') && (*string <= '9'); string++)
8952     {
8953       result = (result * 10) + (*string - '0');
8954     }
8955
8956   *next = string;
8957
8958   if (sign >= 0)
8959     return (result);
8960   else
8961     return (-result);
8962 }
8963
8964 /* 
8965  * Bitmask returned by XParseGeometry().  Each bit tells if the corresponding
8966  * value (x, y, width, height) was found in the parsed string.
8967  */
8968 #define NoValue         0x0000
8969 #define XValue          0x0001
8970 #define YValue          0x0002
8971 #define WidthValue      0x0004
8972 #define HeightValue     0x0008
8973 #define AllValues       0x000F
8974 #define XNegative       0x0010
8975 #define YNegative       0x0020
8976
8977 /* Try not to reformat/modify, so we can compare/sync with X sources */
8978 static int
8979 gtk_XParseGeometry (const char   *string,
8980                     int          *x,
8981                     int          *y,
8982                     unsigned int *width,   
8983                     unsigned int *height)  
8984 {
8985   int mask = NoValue;
8986   char *strind;
8987   unsigned int tempWidth, tempHeight;
8988   int tempX, tempY;
8989   char *nextCharacter;
8990
8991   /* These initializations are just to silence gcc */
8992   tempWidth = 0;
8993   tempHeight = 0;
8994   tempX = 0;
8995   tempY = 0;
8996   
8997   if ( (string == NULL) || (*string == '\0')) return(mask);
8998   if (*string == '=')
8999     string++;  /* ignore possible '=' at beg of geometry spec */
9000
9001   strind = (char *)string;
9002   if (*strind != '+' && *strind != '-' && *strind != 'x') {
9003     tempWidth = read_int(strind, &nextCharacter);
9004     if (strind == nextCharacter) 
9005       return (0);
9006     strind = nextCharacter;
9007     mask |= WidthValue;
9008   }
9009
9010   if (*strind == 'x' || *strind == 'X') {       
9011     strind++;
9012     tempHeight = read_int(strind, &nextCharacter);
9013     if (strind == nextCharacter)
9014       return (0);
9015     strind = nextCharacter;
9016     mask |= HeightValue;
9017   }
9018
9019   if ((*strind == '+') || (*strind == '-')) {
9020     if (*strind == '-') {
9021       strind++;
9022       tempX = -read_int(strind, &nextCharacter);
9023       if (strind == nextCharacter)
9024         return (0);
9025       strind = nextCharacter;
9026       mask |= XNegative;
9027
9028     }
9029     else
9030       { strind++;
9031       tempX = read_int(strind, &nextCharacter);
9032       if (strind == nextCharacter)
9033         return(0);
9034       strind = nextCharacter;
9035       }
9036     mask |= XValue;
9037     if ((*strind == '+') || (*strind == '-')) {
9038       if (*strind == '-') {
9039         strind++;
9040         tempY = -read_int(strind, &nextCharacter);
9041         if (strind == nextCharacter)
9042           return(0);
9043         strind = nextCharacter;
9044         mask |= YNegative;
9045
9046       }
9047       else
9048         {
9049           strind++;
9050           tempY = read_int(strind, &nextCharacter);
9051           if (strind == nextCharacter)
9052             return(0);
9053           strind = nextCharacter;
9054         }
9055       mask |= YValue;
9056     }
9057   }
9058         
9059   /* If strind isn't at the end of the string the it's an invalid
9060                 geometry specification. */
9061
9062   if (*strind != '\0') return (0);
9063
9064   if (mask & XValue)
9065     *x = tempX;
9066   if (mask & YValue)
9067     *y = tempY;
9068   if (mask & WidthValue)
9069     *width = tempWidth;
9070   if (mask & HeightValue)
9071     *height = tempHeight;
9072   return (mask);
9073 }
9074
9075 /**
9076  * gtk_window_parse_geometry:
9077  * @window: a #GtkWindow
9078  * @geometry: geometry string
9079  * 
9080  * Parses a standard X Window System geometry string - see the
9081  * manual page for X (type 'man X') for details on this.
9082  * gtk_window_parse_geometry() does work on all GTK+ ports
9083  * including Win32 but is primarily intended for an X environment.
9084  *
9085  * If either a size or a position can be extracted from the
9086  * geometry string, gtk_window_parse_geometry() returns %TRUE
9087  * and calls gtk_window_set_default_size() and/or gtk_window_move()
9088  * to resize/move the window.
9089  *
9090  * If gtk_window_parse_geometry() returns %TRUE, it will also
9091  * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9092  * indicating to the window manager that the size/position of
9093  * the window was user-specified. This causes most window
9094  * managers to honor the geometry.
9095  *
9096  * Note that for gtk_window_parse_geometry() to work as expected, it has
9097  * to be called when the window has its "final" size, i.e. after calling
9098  * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9099  * on the window.
9100  * |[
9101  * #include <gtk/gtk.h>
9102  *    
9103  * static void
9104  * fill_with_content (GtkWidget *vbox)
9105  * {
9106  *   /&ast; fill with content... &ast;/
9107  * }
9108  *    
9109  * int
9110  * main (int argc, char *argv[])
9111  * {
9112  *   GtkWidget *window, *vbox;
9113  *   GdkGeometry size_hints = {
9114  *     100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST  
9115  *   };
9116  *    
9117  *   gtk_init (&argc, &argv);
9118  *   
9119  *   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9120  *   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9121  *   
9122  *   gtk_container_add (GTK_CONTAINER (window), vbox);
9123  *   fill_with_content (vbox);
9124  *   gtk_widget_show_all (vbox);
9125  *   
9126  *   gtk_window_set_geometry_hints (GTK_WINDOW (window),
9127  *                                  window,
9128  *                                  &size_hints,
9129  *                                  GDK_HINT_MIN_SIZE | 
9130  *                                  GDK_HINT_BASE_SIZE | 
9131  *                                  GDK_HINT_RESIZE_INC);
9132  *   
9133  *   if (argc &gt; 1)
9134  *     {
9135  *       if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9136  *         fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9137  *     }
9138  *    
9139  *   gtk_widget_show_all (window);
9140  *   gtk_main ();
9141  *    
9142  *   return 0;
9143  * }
9144  * ]|
9145  *
9146  * Return value: %TRUE if string was parsed successfully
9147  **/
9148 gboolean
9149 gtk_window_parse_geometry (GtkWindow   *window,
9150                            const gchar *geometry)
9151 {
9152   gint result, x = 0, y = 0;
9153   guint w, h;
9154   GtkWidget *child;
9155   GdkGravity grav;
9156   gboolean size_set, pos_set;
9157   GdkScreen *screen;
9158   
9159   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9160   g_return_val_if_fail (geometry != NULL, FALSE);
9161
9162   child = gtk_bin_get_child (GTK_BIN (window));
9163   if (!child || !gtk_widget_get_visible (child))
9164     g_warning ("gtk_window_parse_geometry() called on a window with no "
9165                "visible children; the window should be set up before "
9166                "gtk_window_parse_geometry() is called.");
9167
9168   screen = gtk_window_check_screen (window);
9169   
9170   result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9171
9172   size_set = FALSE;
9173   if ((result & WidthValue) || (result & HeightValue))
9174     {
9175       gtk_window_set_default_size_internal (window, 
9176                                             TRUE, result & WidthValue ? w : -1,
9177                                             TRUE, result & HeightValue ? h : -1, 
9178                                             TRUE);
9179       size_set = TRUE;
9180     }
9181
9182   gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9183   
9184   grav = GDK_GRAVITY_NORTH_WEST;
9185
9186   if ((result & XNegative) && (result & YNegative))
9187     grav = GDK_GRAVITY_SOUTH_EAST;
9188   else if (result & XNegative)
9189     grav = GDK_GRAVITY_NORTH_EAST;
9190   else if (result & YNegative)
9191     grav = GDK_GRAVITY_SOUTH_WEST;
9192
9193   if ((result & XValue) == 0)
9194     x = 0;
9195
9196   if ((result & YValue) == 0)
9197     y = 0;
9198
9199   if (grav == GDK_GRAVITY_SOUTH_WEST ||
9200       grav == GDK_GRAVITY_SOUTH_EAST)
9201     y = gdk_screen_get_height (screen) - h + y;
9202
9203   if (grav == GDK_GRAVITY_SOUTH_EAST ||
9204       grav == GDK_GRAVITY_NORTH_EAST)
9205     x = gdk_screen_get_width (screen) - w + x;
9206
9207   /* we don't let you put a window offscreen; maybe some people would
9208    * prefer to be able to, but it's kind of a bogus thing to do.
9209    */
9210   if (y < 0)
9211     y = 0;
9212
9213   if (x < 0)
9214     x = 0;
9215
9216   pos_set = FALSE;
9217   if ((result & XValue) || (result & YValue))
9218     {
9219       gtk_window_set_gravity (window, grav);
9220       gtk_window_move (window, x, y);
9221       pos_set = TRUE;
9222     }
9223
9224   if (size_set || pos_set)
9225     {
9226       /* Set USSize, USPosition hints */
9227       GtkWindowGeometryInfo *info;
9228
9229       info = gtk_window_get_geometry_info (window, TRUE);
9230
9231       if (pos_set)
9232         info->mask |= GDK_HINT_USER_POS;
9233       if (size_set)
9234         info->mask |= GDK_HINT_USER_SIZE;
9235     }
9236   
9237   return result != 0;
9238 }
9239
9240 static void
9241 gtk_window_mnemonic_hash_foreach (guint      keyval,
9242                                   GSList    *targets,
9243                                   gpointer   data)
9244 {
9245   struct {
9246     GtkWindow *window;
9247     GtkWindowKeysForeachFunc func;
9248     gpointer func_data;
9249   } *info = data;
9250
9251   (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9252 }
9253
9254 void
9255 _gtk_window_keys_foreach (GtkWindow                *window,
9256                           GtkWindowKeysForeachFunc func,
9257                           gpointer                 func_data)
9258 {
9259   GSList *groups;
9260   GtkMnemonicHash *mnemonic_hash;
9261
9262   struct {
9263     GtkWindow *window;
9264     GtkWindowKeysForeachFunc func;
9265     gpointer func_data;
9266   } info;
9267
9268   info.window = window;
9269   info.func = func;
9270   info.func_data = func_data;
9271
9272   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9273   if (mnemonic_hash)
9274     _gtk_mnemonic_hash_foreach (mnemonic_hash,
9275                                 gtk_window_mnemonic_hash_foreach, &info);
9276
9277   groups = gtk_accel_groups_from_object (G_OBJECT (window));
9278   while (groups)
9279     {
9280       GtkAccelGroup *group = groups->data;
9281       gint i;
9282
9283       for (i = 0; i < group->priv->n_accels; i++)
9284         {
9285           GtkAccelKey *key = &group->priv->priv_accels[i].key;
9286           
9287           if (key->accel_key)
9288             (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9289         }
9290       
9291       groups = groups->next;
9292     }
9293 }
9294
9295 static void
9296 gtk_window_keys_changed (GtkWindow *window)
9297 {
9298   gtk_window_free_key_hash (window);
9299   gtk_window_get_key_hash (window);
9300 }
9301
9302 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9303
9304 struct _GtkWindowKeyEntry
9305 {
9306   guint keyval;
9307   guint modifiers;
9308   guint is_mnemonic : 1;
9309 };
9310
9311 static void 
9312 window_key_entry_destroy (gpointer data)
9313 {
9314   g_slice_free (GtkWindowKeyEntry, data);
9315 }
9316
9317 static void
9318 add_to_key_hash (GtkWindow      *window,
9319                  guint           keyval,
9320                  GdkModifierType modifiers,
9321                  gboolean        is_mnemonic,
9322                  gpointer        data)
9323 {
9324   GtkKeyHash *key_hash = data;
9325
9326   GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9327
9328   entry->keyval = keyval;
9329   entry->modifiers = modifiers;
9330   entry->is_mnemonic = is_mnemonic;
9331
9332   /* GtkAccelGroup stores lowercased accelerators. To deal
9333    * with this, if <Shift> was specified, uppercase.
9334    */
9335   if (modifiers & GDK_SHIFT_MASK)
9336     {
9337       if (keyval == GDK_KEY_Tab)
9338         keyval = GDK_KEY_ISO_Left_Tab;
9339       else
9340         keyval = gdk_keyval_to_upper (keyval);
9341     }
9342   
9343   _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9344 }
9345
9346 static GtkKeyHash *
9347 gtk_window_get_key_hash (GtkWindow *window)
9348 {
9349   GdkScreen *screen = gtk_window_check_screen (window);
9350   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9351   
9352   if (key_hash)
9353     return key_hash;
9354   
9355   key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9356                                 (GDestroyNotify)window_key_entry_destroy);
9357   _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9358   g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9359
9360   return key_hash;
9361 }
9362
9363 static void
9364 gtk_window_free_key_hash (GtkWindow *window)
9365 {
9366   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9367   if (key_hash)
9368     {
9369       _gtk_key_hash_free (key_hash);
9370       g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9371     }
9372 }
9373
9374 /**
9375  * gtk_window_activate_key:
9376  * @window:  a #GtkWindow
9377  * @event:   a #GdkEventKey
9378  *
9379  * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9380  * called by the default ::key_press_event handler for toplevel windows,
9381  * however in some cases it may be useful to call this directly when
9382  * overriding the standard key handling for a toplevel window.
9383  *
9384  * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9385  *
9386  * Since: 2.4
9387  */
9388 gboolean
9389 gtk_window_activate_key (GtkWindow   *window,
9390                          GdkEventKey *event)
9391 {
9392   GtkKeyHash *key_hash;
9393   GtkWindowKeyEntry *found_entry = NULL;
9394   gboolean enable_mnemonics;
9395   gboolean enable_accels;
9396
9397   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9398   g_return_val_if_fail (event != NULL, FALSE);
9399
9400   key_hash = gtk_window_get_key_hash (window);
9401
9402   if (key_hash)
9403     {
9404       GSList *tmp_list;
9405       GSList *entries = _gtk_key_hash_lookup (key_hash,
9406                                               event->hardware_keycode,
9407                                               event->state,
9408                                               gtk_accelerator_get_default_mod_mask (),
9409                                               event->group);
9410
9411       g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9412                     "gtk-enable-mnemonics", &enable_mnemonics,
9413                     "gtk-enable-accels", &enable_accels,
9414                     NULL);
9415
9416       for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9417         {
9418           GtkWindowKeyEntry *entry = tmp_list->data;
9419           if (entry->is_mnemonic)
9420             {
9421               if (enable_mnemonics)
9422                 {
9423                   found_entry = entry;
9424                   break;
9425                 }
9426             }
9427           else 
9428             {
9429               if (enable_accels && !found_entry)
9430                 {
9431                   found_entry = entry;
9432                 }
9433             }
9434         }
9435
9436       g_slist_free (entries);
9437     }
9438
9439   if (found_entry)
9440     {
9441       if (found_entry->is_mnemonic)
9442         {
9443           if (enable_mnemonics)
9444             return gtk_window_mnemonic_activate (window, found_entry->keyval,
9445                                                  found_entry->modifiers);
9446         }
9447       else
9448         {
9449           if (enable_accels)
9450             return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9451                                               found_entry->modifiers);
9452         }
9453     }
9454
9455   return FALSE;
9456 }
9457
9458 static void
9459 window_update_has_focus (GtkWindow *window)
9460 {
9461   GtkWindowPrivate *priv = window->priv;
9462   GtkWidget *widget = GTK_WIDGET (window);
9463   gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9464
9465   if (has_focus != priv->has_focus)
9466     {
9467       priv->has_focus = has_focus;
9468
9469       if (has_focus)
9470         {
9471           if (priv->focus_widget &&
9472               priv->focus_widget != widget &&
9473               !gtk_widget_has_focus (priv->focus_widget))
9474             do_focus_change (priv->focus_widget, TRUE);
9475         }
9476       else
9477         {
9478           if (priv->focus_widget &&
9479               priv->focus_widget != widget &&
9480               gtk_widget_has_focus (priv->focus_widget))
9481             do_focus_change (priv->focus_widget, FALSE);
9482         }
9483     }
9484 }
9485
9486 /**
9487  * _gtk_window_set_is_active:
9488  * @window: a #GtkWindow
9489  * @is_active: %TRUE if the window is in the currently active toplevel
9490  * 
9491  * Internal function that sets whether the #GtkWindow is part
9492  * of the currently active toplevel window (taking into account inter-process
9493  * embedding.)
9494  **/
9495 void
9496 _gtk_window_set_is_active (GtkWindow *window,
9497                            gboolean   is_active)
9498 {
9499   GtkWindowPrivate *priv;
9500
9501   g_return_if_fail (GTK_IS_WINDOW (window));
9502
9503   priv = window->priv;
9504
9505   is_active = is_active != FALSE;
9506
9507   if (is_active != priv->is_active)
9508     {
9509       priv->is_active = is_active;
9510       window_update_has_focus (window);
9511
9512       g_object_notify (G_OBJECT (window), "is-active");
9513     }
9514 }
9515
9516 /**
9517  * _gtk_window_set_is_toplevel:
9518  * @window: a #GtkWindow
9519  * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9520  * child of the root window); %FALSE if it is not (for example, for an
9521  * in-process, parented GtkPlug)
9522  *
9523  * Internal function used by #GtkPlug when it gets parented/unparented by a
9524  * #GtkSocket.  This keeps the @window's #GTK_WINDOW_TOPLEVEL flag in sync
9525  * with the global list of toplevel windows.
9526  */
9527 void
9528 _gtk_window_set_is_toplevel (GtkWindow *window,
9529                              gboolean   is_toplevel)
9530 {
9531   GtkWidget *widget;
9532   GtkWidget *toplevel;
9533
9534   widget = GTK_WIDGET (window);
9535
9536   if (gtk_widget_is_toplevel (widget))
9537     g_assert (g_slist_find (toplevel_list, window) != NULL);
9538   else
9539     g_assert (g_slist_find (toplevel_list, window) == NULL);
9540
9541   if (is_toplevel == gtk_widget_is_toplevel (widget))
9542     return;
9543
9544   if (is_toplevel)
9545     {
9546       /* Pass through regular pathways of an embedded toplevel
9547        * to go through unmapping and hiding the widget before
9548        * becomming a toplevel again.
9549        *
9550        * We remain hidden after becomming toplevel in order to
9551        * avoid problems during an embedded toplevel's dispose cycle
9552        * (When a toplevel window is shown it tries to grab focus again,
9553        * this causes problems while disposing).
9554        */
9555       gtk_widget_hide (widget);
9556
9557       /* Save the toplevel this widget was previously anchored into before
9558        * propagating a hierarchy-changed.
9559        *
9560        * Usually this happens by way of gtk_widget_unparent() and we are
9561        * already unanchored at this point, just adding this clause incase
9562        * things happen differently.
9563        */
9564       toplevel = gtk_widget_get_toplevel (widget);
9565       if (!gtk_widget_is_toplevel (toplevel))
9566         toplevel = NULL;
9567
9568       _gtk_widget_set_is_toplevel (widget, TRUE);
9569
9570       /* When a window becomes toplevel after being embedded and anchored
9571        * into another window we need to unset its anchored flag so that
9572        * the hierarchy changed signal kicks in properly.
9573        */
9574       _gtk_widget_set_anchored (widget, FALSE);
9575       _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9576
9577       toplevel_list = g_slist_prepend (toplevel_list, window);
9578     }
9579   else
9580     {
9581       _gtk_widget_set_is_toplevel (widget, FALSE);
9582       toplevel_list = g_slist_remove (toplevel_list, window);
9583
9584       _gtk_widget_propagate_hierarchy_changed (widget, widget);
9585     }
9586 }
9587
9588 /**
9589  * _gtk_window_set_has_toplevel_focus:
9590  * @window: a #GtkWindow
9591  * @has_toplevel_focus: %TRUE if the in
9592  * 
9593  * Internal function that sets whether the keyboard focus for the
9594  * toplevel window (taking into account inter-process embedding.)
9595  **/
9596 void
9597 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9598                                    gboolean   has_toplevel_focus)
9599 {
9600   GtkWindowPrivate *priv;
9601
9602   g_return_if_fail (GTK_IS_WINDOW (window));
9603
9604   priv = window->priv;
9605
9606   has_toplevel_focus = has_toplevel_focus != FALSE;
9607
9608   if (has_toplevel_focus != priv->has_toplevel_focus)
9609     {
9610       priv->has_toplevel_focus = has_toplevel_focus;
9611       window_update_has_focus (window);
9612
9613       g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9614     }
9615 }
9616
9617 /**
9618  * gtk_window_set_auto_startup_notification:
9619  * @setting: %TRUE to automatically do startup notification
9620  *
9621  * By default, after showing the first #GtkWindow, GTK+ calls 
9622  * gdk_notify_startup_complete().  Call this function to disable 
9623  * the automatic startup notification. You might do this if your 
9624  * first window is a splash screen, and you want to delay notification 
9625  * until after your real main window has been shown, for example.
9626  *
9627  * In that example, you would disable startup notification
9628  * temporarily, show your splash screen, then re-enable it so that
9629  * showing the main window would automatically result in notification.
9630  * 
9631  * Since: 2.2
9632  **/
9633 void
9634 gtk_window_set_auto_startup_notification (gboolean setting)
9635 {
9636   disable_startup_notification = !setting;
9637 }
9638
9639 /**
9640  * gtk_window_get_window_type:
9641  * @window: a #GtkWindow
9642  *
9643  * Gets the type of the window. See #GtkWindowType.
9644  *
9645  * Return value: the type of the window
9646  *
9647  * Since: 2.20
9648  **/
9649 GtkWindowType
9650 gtk_window_get_window_type (GtkWindow *window)
9651 {
9652   g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9653
9654   return window->priv->type;
9655 }
9656
9657 /**
9658  * gtk_window_get_mnemonics_visible:
9659  * @window: a #GtkWindow
9660  *
9661  * Gets the value of the #GtkWindow:mnemonics-visible property.
9662  *
9663  * Returns: %TRUE if mnemonics are supposed to be visible
9664  * in this window.
9665  *
9666  * Since: 2.20
9667  */
9668 gboolean
9669 gtk_window_get_mnemonics_visible (GtkWindow *window)
9670 {
9671   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9672
9673   return window->priv->mnemonics_visible;
9674 }
9675
9676 /**
9677  * gtk_window_set_mnemonics_visible:
9678  * @window: a #GtkWindow
9679  * @setting: the new value
9680  *
9681  * Sets the #GtkWindow:mnemonics-visible property.
9682  *
9683  * Since: 2.20
9684  */
9685 void
9686 gtk_window_set_mnemonics_visible (GtkWindow *window,
9687                                   gboolean   setting)
9688 {
9689   GtkWindowPrivate *priv;
9690
9691   g_return_if_fail (GTK_IS_WINDOW (window));
9692
9693   priv = window->priv;
9694
9695   setting = setting != FALSE;
9696
9697   if (priv->mnemonics_visible != setting)
9698     {
9699       priv->mnemonics_visible = setting;
9700       g_object_notify (G_OBJECT (window), "mnemonics-visible");
9701     }
9702
9703   if (priv->auto_mnemonics_timeout_id)
9704     {
9705       g_source_remove (priv->auto_mnemonics_timeout_id);
9706       priv->auto_mnemonics_timeout_id = 0;
9707     }
9708
9709   priv->mnemonics_visible_set = TRUE;
9710 }
9711
9712 static gboolean
9713 set_auto_mnemonics_visible_cb (gpointer data)
9714 {
9715   GtkWindow *window = data;
9716
9717   gtk_window_set_mnemonics_visible (window, TRUE);
9718
9719   window->priv->auto_mnemonics_timeout_id = 0;
9720
9721   return FALSE;
9722 }
9723
9724 void
9725 _gtk_window_set_auto_mnemonics_visible (GtkWindow *window)
9726 {
9727   g_return_if_fail (GTK_IS_WINDOW (window));
9728
9729   if (window->priv->auto_mnemonics_timeout_id)
9730     return;
9731
9732   window->priv->auto_mnemonics_timeout_id =
9733     gdk_threads_add_timeout (AUTO_MNEMONICS_DELAY, set_auto_mnemonics_visible_cb, window);
9734 }
9735
9736 /**
9737  * gtk_window_get_focus_visible:
9738  * @window: a #GtkWindow
9739  *
9740  * Gets the value of the #GtkWindow:focus-visible property.
9741  *
9742  * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9743  *     in this window.
9744  *
9745  * Since: 3.2
9746  */
9747 gboolean
9748 gtk_window_get_focus_visible (GtkWindow *window)
9749 {
9750   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9751
9752   return window->priv->focus_visible;
9753 }
9754
9755 /**
9756  * gtk_window_set_focus_visible:
9757  * @window: a #GtkWindow
9758  * @setting: the new value
9759  *
9760  * Sets the #GtkWindow:focus-visible property.
9761  *
9762  * Since: 3.2
9763  */
9764 void
9765 gtk_window_set_focus_visible (GtkWindow *window,
9766                               gboolean   setting)
9767 {
9768   GtkWindowPrivate *priv;
9769
9770   g_return_if_fail (GTK_IS_WINDOW (window));
9771
9772   priv = window->priv;
9773
9774   setting = setting != FALSE;
9775
9776   if (priv->focus_visible != setting)
9777     {
9778       priv->focus_visible = setting;
9779       g_object_notify (G_OBJECT (window), "focus-visible");
9780     }
9781 }
9782
9783 void
9784 _gtk_window_get_wmclass (GtkWindow  *window,
9785                          gchar     **wmclass_name,
9786                          gchar     **wmclass_class)
9787 {
9788   GtkWindowPrivate *priv = window->priv;
9789
9790   *wmclass_name = priv->wmclass_name;
9791   *wmclass_class = priv->wmclass_class;
9792 }
9793
9794 /**
9795  * gtk_window_set_has_user_ref_count:
9796  * @window: a #GtkWindow
9797  * @setting: the new value
9798  *
9799  * Tells GTK+ whether to drop its extra reference to the window
9800  * when gtk_widget_destroy() is called.
9801  *
9802  * This function is only exported for the benefit of language
9803  * bindings which may need to keep the window alive until their
9804  * wrapper object is garbage collected. There is no justification
9805  * for ever calling this function in an application.
9806  *
9807  * Since: 3.0
9808  */
9809 void
9810 gtk_window_set_has_user_ref_count (GtkWindow *window,
9811                                    gboolean   setting)
9812 {
9813   g_return_if_fail (GTK_IS_WINDOW (window));
9814
9815   window->priv->has_user_ref_count = setting;
9816 }
9817
9818 static void
9819 ensure_state_flag_backdrop (GtkWidget *widget)
9820 {
9821   GdkWindow *window;
9822   gboolean window_focused = TRUE;
9823
9824   window = gtk_widget_get_window (widget);
9825
9826   window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9827
9828   if (!window_focused)
9829     gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
9830   else
9831     gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
9832
9833   gtk_widget_queue_draw (widget);
9834 }