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