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