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