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