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