1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 #include "gtkwindow.h"
34 #include "gtkprivate.h"
35 #include "gtkwindowprivate.h"
36 #include "gtkaccelgroupprivate.h"
37 #include "gtkbindings.h"
38 #include "gtkkeyhash.h"
40 #include "gtkmnemonichash.h"
41 #include "gtkmenubar.h"
42 #include "gtkiconfactory.h"
43 #include "gtkicontheme.h"
44 #include "gtkmarshalers.h"
46 #include "gtkbuildable.h"
47 #include "gtkwidgetprivate.h"
48 #include "gtkcontainerprivate.h"
50 #include "gtkstylecontextprivate.h"
51 #include "gtktypebuiltins.h"
52 #include "a11y/gtkwindowaccessible.h"
54 #include "deprecated/gtkstyle.h"
56 #ifdef GDK_WINDOWING_X11
63 * @short_description: Toplevel which can contain other widgets
65 * A GtkWindow is a toplevel window which can contain other widgets.
66 * Windows normally have decorations that are under the control
67 * of the windowing system and allow the user to manipulate the window
68 * (resize it, move it, close it,...).
70 * GTK+ also allows windows to have a resize grip (a small area in the lower
71 * right or left corner) which can be clicked to reszie the window. To
72 * control whether a window has a resize grip, use
73 * gtk_window_set_has_resize_grip().
75 * <refsect2 id="GtkWindow-BUILDER-UI">
76 * <title>GtkWindow as GtkBuildable</title>
78 * The GtkWindow implementation of the GtkBuildable interface supports a
79 * custom <tag class="starttag">accel-groups</tag> element, which supports
80 * any number of <tag class="starttag">group</tag> elements representing the
81 * #GtkAccelGroup objects you want to add to your window (synonymous with
82 * gtk_window_add_accel_group().
85 * <title>A UI definition fragment with accel groups</title>
86 * <programlisting><![CDATA[
87 * <object class="GtkWindow">
89 * <group name="accelgroup1"/>
95 * <object class="GtkAccelGroup" id="accelgroup1"/>
96 * ]]></programlisting>
101 #define AUTO_MNEMONICS_DELAY 300 /* ms */
103 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
105 struct _GtkWindowPrivate
107 GtkMnemonicHash *mnemonic_hash;
109 GtkWidget *attach_widget;
110 GtkWidget *default_widget;
111 GtkWidget *focus_widget;
112 GtkWindow *transient_parent;
113 GtkWindowGeometryInfo *geometry_info;
114 GtkWindowGroup *group;
116 GtkApplication *application;
118 GdkModifierType mnemonic_modifier;
119 GdkWindowTypeHint gdk_type_hint;
123 GdkWindow *grip_window;
127 gchar *wmclass_class;
131 guint keys_changed_handler;
133 guint32 initial_timestamp;
135 guint16 configure_request_count;
137 guint auto_mnemonics_timeout_id;
139 /* The following flags are initially TRUE (before a window is mapped).
140 * They cause us to compute a configure request that involves
141 * default-only parameters. Once mapped, we set them to FALSE.
142 * Then we set them to TRUE again on unmap (for position)
143 * and on unrealize (for size).
145 guint need_default_position : 1;
146 guint need_default_size : 1;
148 guint above_initially : 1;
149 guint accept_focus : 1;
150 guint below_initially : 1;
151 guint builder_visible : 1;
152 guint configure_notify_received : 1;
155 guint destroy_with_parent : 1;
156 guint focus_on_map : 1;
157 guint fullscreen_initially : 1;
159 guint has_user_ref_count : 1;
160 guint has_toplevel_focus : 1;
161 guint hide_titlebar_when_maximized : 1;
162 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
164 guint maximize_initially : 1;
165 guint mnemonics_visible : 1;
166 guint mnemonics_visible_set : 1;
167 guint focus_visible : 1;
169 guint opacity_set : 1;
171 guint reset_type_hint : 1;
173 guint skips_pager : 1;
174 guint skips_taskbar : 1;
175 guint stick_initially : 1;
176 guint transient_parent_group : 1;
177 guint type : 4; /* GtkWindowType */
178 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
179 * one of the original eight. If not,
181 * GDK_WINDOW_TYPE_HINT_NORMAL
184 guint has_resize_grip : 1;
185 guint resize_grip_visible : 1; /* don't use, just for "resize-
186 * grip-visible" notification
188 guint gravity : 5; /* GdkGravity */
215 PROP_DESTROY_WITH_PARENT,
216 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
221 PROP_SKIP_TASKBAR_HINT,
222 PROP_SKIP_PAGER_HINT,
232 PROP_HAS_RESIZE_GRIP,
233 PROP_RESIZE_GRIP_VISIBLE,
235 /* Readonly properties */
237 PROP_HAS_TOPLEVEL_FOCUS,
239 /* Writeonly properties */
242 PROP_MNEMONICS_VISIBLE,
253 guint using_default_icon : 1;
254 guint using_parent_icon : 1;
255 guint using_themed_icon : 1;
259 GdkGeometry geometry; /* Last set of geometry hints we set */
260 GdkWindowHints flags;
261 GdkRectangle configure_request;
262 } GtkWindowLastGeometryInfo;
264 struct _GtkWindowGeometryInfo
266 /* Properties that the app has set on the window
268 GdkGeometry geometry; /* Geometry hints */
270 GtkWidget *widget; /* subwidget to which hints apply */
271 /* from last gtk_window_resize () - if > 0, indicates that
272 * we should resize to this size.
277 /* From last gtk_window_move () prior to mapping -
278 * only used if initial_pos_set
283 /* Default size - used only the FIRST time we map a window,
288 /* whether to use initial_x, initial_y */
289 guint initial_pos_set : 1;
290 /* CENTER_ALWAYS or other position constraint changed since
291 * we sent the last configure request.
293 guint position_constraints_changed : 1;
295 /* if true, default_width, height should be multiplied by the
296 * increments and affect the geometry widget only
298 guint default_is_geometry : 1;
300 /* if true, resize_width, height should be multiplied by the
301 * increments and affect the geometry widget only
303 guint resize_is_geometry : 1;
305 GtkWindowLastGeometryInfo last;
309 struct _GtkDeviceGrabInfo
313 guint block_others : 1;
316 struct _GtkWindowGroupPrivate
319 GSList *device_grabs;
322 static void gtk_window_dispose (GObject *object);
323 static void gtk_window_finalize (GObject *object);
324 static void gtk_window_destroy (GtkWidget *widget);
325 static void gtk_window_show (GtkWidget *widget);
326 static void gtk_window_hide (GtkWidget *widget);
327 static void gtk_window_map (GtkWidget *widget);
328 static void gtk_window_unmap (GtkWidget *widget);
329 static void gtk_window_realize (GtkWidget *widget);
330 static void gtk_window_unrealize (GtkWidget *widget);
331 static void gtk_window_size_allocate (GtkWidget *widget,
332 GtkAllocation *allocation);
333 static gboolean gtk_window_map_event (GtkWidget *widget,
335 static gint gtk_window_configure_event (GtkWidget *widget,
336 GdkEventConfigure *event);
337 static gint gtk_window_key_press_event (GtkWidget *widget,
339 static gint gtk_window_key_release_event (GtkWidget *widget,
341 static gint gtk_window_button_press_event (GtkWidget *widget,
342 GdkEventButton *event);
343 static gint gtk_window_enter_notify_event (GtkWidget *widget,
344 GdkEventCrossing *event);
345 static gint gtk_window_leave_notify_event (GtkWidget *widget,
346 GdkEventCrossing *event);
347 static gint gtk_window_focus_in_event (GtkWidget *widget,
348 GdkEventFocus *event);
349 static gint gtk_window_focus_out_event (GtkWidget *widget,
350 GdkEventFocus *event);
351 static void gtk_window_style_updated (GtkWidget *widget);
352 static gboolean gtk_window_state_event (GtkWidget *widget,
353 GdkEventWindowState *event);
354 static void gtk_window_check_resize (GtkContainer *container);
355 static gint gtk_window_focus (GtkWidget *widget,
356 GtkDirectionType direction);
357 static void gtk_window_move_focus (GtkWidget *widget,
358 GtkDirectionType dir);
359 static void gtk_window_real_set_focus (GtkWindow *window,
361 static void gtk_window_direction_changed (GtkWidget *widget,
362 GtkTextDirection prev_dir);
363 static void gtk_window_state_changed (GtkWidget *widget,
364 GtkStateType previous_state);
366 static void gtk_window_real_activate_default (GtkWindow *window);
367 static void gtk_window_real_activate_focus (GtkWindow *window);
368 static void gtk_window_keys_changed (GtkWindow *window);
369 static gint gtk_window_draw (GtkWidget *widget,
371 static void gtk_window_unset_transient_for (GtkWindow *window);
372 static void gtk_window_transient_parent_realized (GtkWidget *parent,
374 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
377 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
379 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
382 static void gtk_window_move_resize (GtkWindow *window);
383 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
385 GdkGeometry *geometry_b,
387 static void gtk_window_constrain_size (GtkWindow *window,
388 GdkGeometry *geometry,
394 static void gtk_window_constrain_position (GtkWindow *window,
399 static void gtk_window_compute_hints (GtkWindow *window,
400 GdkGeometry *new_geometry,
402 static void gtk_window_compute_configure_request (GtkWindow *window,
403 GdkRectangle *request,
404 GdkGeometry *geometry,
407 static void gtk_window_set_default_size_internal (GtkWindow *window,
408 gboolean change_width,
410 gboolean change_height,
412 gboolean is_geometry);
414 static void update_themed_icon (GtkIconTheme *theme,
416 static GList *icon_list_from_theme (GtkWidget *widget,
418 static void gtk_window_realize_icon (GtkWindow *window);
419 static void gtk_window_unrealize_icon (GtkWindow *window);
420 static void resize_grip_create_window (GtkWindow *window);
421 static void resize_grip_destroy_window (GtkWindow *window);
422 static void update_grip_visibility (GtkWindow *window);
424 static void gtk_window_notify_keys_changed (GtkWindow *window);
425 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
426 static void gtk_window_free_key_hash (GtkWindow *window);
427 static void gtk_window_on_composited_changed (GdkScreen *screen,
429 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
432 static void gtk_window_set_theme_variant (GtkWindow *window);
434 static GSList *toplevel_list = NULL;
435 static guint window_signals[LAST_SIGNAL] = { 0 };
436 static GList *default_icon_list = NULL;
437 static gchar *default_icon_name = NULL;
438 static guint default_icon_serial = 0;
439 static gboolean disable_startup_notification = FALSE;
440 static gboolean sent_startup_notification = FALSE;
442 static GQuark quark_gtk_embedded = 0;
443 static GQuark quark_gtk_window_key_hash = 0;
444 static GQuark quark_gtk_window_icon_info = 0;
445 static GQuark quark_gtk_buildable_accels = 0;
447 static GtkBuildableIface *parent_buildable_iface;
449 static void gtk_window_set_property (GObject *object,
453 static void gtk_window_get_property (GObject *object,
459 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
460 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
463 const GValue *value);
464 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
465 GtkBuilder *builder);
466 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
469 const gchar *tagname,
470 GMarkupParser *parser,
472 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
475 const gchar *tagname,
479 static void gtk_window_get_preferred_width (GtkWidget *widget,
482 static void gtk_window_get_preferred_height (GtkWidget *widget,
486 static void ensure_state_flag_backdrop (GtkWidget *widget);
488 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
489 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
490 gtk_window_buildable_interface_init))
493 add_tab_bindings (GtkBindingSet *binding_set,
494 GdkModifierType modifiers,
495 GtkDirectionType direction)
497 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
499 GTK_TYPE_DIRECTION_TYPE, direction);
500 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
502 GTK_TYPE_DIRECTION_TYPE, direction);
506 add_arrow_bindings (GtkBindingSet *binding_set,
508 GtkDirectionType direction)
510 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
512 gtk_binding_entry_add_signal (binding_set, keysym, 0,
514 GTK_TYPE_DIRECTION_TYPE, direction);
515 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
517 GTK_TYPE_DIRECTION_TYPE, direction);
518 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
520 GTK_TYPE_DIRECTION_TYPE, direction);
521 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
523 GTK_TYPE_DIRECTION_TYPE, direction);
527 extract_time_from_startup_id (const gchar* startup_id)
529 gchar *timestr = g_strrstr (startup_id, "_TIME");
530 guint32 retval = GDK_CURRENT_TIME;
537 /* Skip past the "_TIME" part */
542 timestamp = g_ascii_strtoull (timestr, &end, 0);
543 if (errno == 0 && end != timestr)
551 startup_id_is_fake (const gchar* startup_id)
553 return strncmp (startup_id, "_TIME", 5) == 0;
557 gtk_window_class_init (GtkWindowClass *klass)
559 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
560 GtkWidgetClass *widget_class;
561 GtkContainerClass *container_class;
562 GtkBindingSet *binding_set;
564 widget_class = (GtkWidgetClass*) klass;
565 container_class = (GtkContainerClass*) klass;
567 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
568 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
569 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
570 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
572 gobject_class->dispose = gtk_window_dispose;
573 gobject_class->finalize = gtk_window_finalize;
575 gobject_class->set_property = gtk_window_set_property;
576 gobject_class->get_property = gtk_window_get_property;
578 widget_class->destroy = gtk_window_destroy;
579 widget_class->show = gtk_window_show;
580 widget_class->hide = gtk_window_hide;
581 widget_class->map = gtk_window_map;
582 widget_class->map_event = gtk_window_map_event;
583 widget_class->unmap = gtk_window_unmap;
584 widget_class->realize = gtk_window_realize;
585 widget_class->unrealize = gtk_window_unrealize;
586 widget_class->size_allocate = gtk_window_size_allocate;
587 widget_class->configure_event = gtk_window_configure_event;
588 widget_class->key_press_event = gtk_window_key_press_event;
589 widget_class->key_release_event = gtk_window_key_release_event;
590 widget_class->enter_notify_event = gtk_window_enter_notify_event;
591 widget_class->leave_notify_event = gtk_window_leave_notify_event;
592 widget_class->focus_in_event = gtk_window_focus_in_event;
593 widget_class->button_press_event = gtk_window_button_press_event;
594 widget_class->focus_out_event = gtk_window_focus_out_event;
595 widget_class->focus = gtk_window_focus;
596 widget_class->move_focus = gtk_window_move_focus;
597 widget_class->draw = gtk_window_draw;
598 widget_class->get_preferred_width = gtk_window_get_preferred_width;
599 widget_class->get_preferred_height = gtk_window_get_preferred_height;
600 widget_class->window_state_event = gtk_window_state_event;
601 widget_class->direction_changed = gtk_window_direction_changed;
602 widget_class->state_changed = gtk_window_state_changed;
603 widget_class->style_updated = gtk_window_style_updated;
605 container_class->check_resize = gtk_window_check_resize;
607 klass->set_focus = gtk_window_real_set_focus;
609 klass->activate_default = gtk_window_real_activate_default;
610 klass->activate_focus = gtk_window_real_activate_focus;
611 klass->keys_changed = gtk_window_keys_changed;
613 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
616 g_object_class_install_property (gobject_class,
618 g_param_spec_enum ("type",
620 P_("The type of the window"),
621 GTK_TYPE_WINDOW_TYPE,
623 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
625 g_object_class_install_property (gobject_class,
627 g_param_spec_string ("title",
629 P_("The title of the window"),
631 GTK_PARAM_READWRITE));
633 g_object_class_install_property (gobject_class,
635 g_param_spec_string ("role",
637 P_("Unique identifier for the window to be used when restoring a session"),
639 GTK_PARAM_READWRITE));
642 * GtkWindow:startup-id:
644 * The :startup-id is a write-only property for setting window's
645 * startup notification identifier. See gtk_window_set_startup_id()
650 g_object_class_install_property (gobject_class,
652 g_param_spec_string ("startup-id",
654 P_("Unique startup identifier for the window used by startup-notification"),
656 GTK_PARAM_WRITABLE));
658 g_object_class_install_property (gobject_class,
660 g_param_spec_boolean ("resizable",
662 P_("If TRUE, users can resize the window"),
664 GTK_PARAM_READWRITE));
666 g_object_class_install_property (gobject_class,
668 g_param_spec_boolean ("modal",
670 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
672 GTK_PARAM_READWRITE));
674 g_object_class_install_property (gobject_class,
676 g_param_spec_enum ("window-position",
677 P_("Window Position"),
678 P_("The initial position of the window"),
679 GTK_TYPE_WINDOW_POSITION,
681 GTK_PARAM_READWRITE));
683 g_object_class_install_property (gobject_class,
685 g_param_spec_int ("default-width",
687 P_("The default width of the window, used when initially showing the window"),
691 GTK_PARAM_READWRITE));
693 g_object_class_install_property (gobject_class,
695 g_param_spec_int ("default-height",
696 P_("Default Height"),
697 P_("The default height of the window, used when initially showing the window"),
701 GTK_PARAM_READWRITE));
703 g_object_class_install_property (gobject_class,
704 PROP_DESTROY_WITH_PARENT,
705 g_param_spec_boolean ("destroy-with-parent",
706 P_("Destroy with Parent"),
707 P_("If this window should be destroyed when the parent is destroyed"),
709 GTK_PARAM_READWRITE));
712 * GtkWindow:hide-titlebar-when-maximized:
714 * Whether the titlebar should be hidden during maximization.
718 g_object_class_install_property (gobject_class,
719 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
720 g_param_spec_boolean ("hide-titlebar-when-maximized",
721 P_("Hide the titlebar during maximization"),
722 P_("If this window's titlebar should be hidden when the window is maximized"),
724 GTK_PARAM_READWRITE));
726 g_object_class_install_property (gobject_class,
728 g_param_spec_object ("icon",
730 P_("Icon for this window"),
732 GTK_PARAM_READWRITE));
735 * GtkWindow:mnemonics-visible:
737 * Whether mnemonics are currently visible in this window.
739 * This property is maintained by GTK+ based on the
740 * #GtkSettings:gtk-auto-mnemonics setting and user input,
741 * and should not be set by applications.
745 g_object_class_install_property (gobject_class,
746 PROP_MNEMONICS_VISIBLE,
747 g_param_spec_boolean ("mnemonics-visible",
748 P_("Mnemonics Visible"),
749 P_("Whether mnemonics are currently visible in this window"),
751 GTK_PARAM_READWRITE));
754 * GtkWindow:focus-visible:
756 * Whether 'focus rectangles' are currently visible in this window.
758 * This property is maintained by GTK+ based on the
759 * #GtkSettings:gtk-visible-focus setting and user input
760 * and should not be set by applications.
764 g_object_class_install_property (gobject_class,
766 g_param_spec_boolean ("focus-visible",
768 P_("Whether focus rectangles are currently visible in this window"),
770 GTK_PARAM_READWRITE));
773 * GtkWindow:icon-name:
775 * The :icon-name property specifies the name of the themed icon to
776 * use as the window icon. See #GtkIconTheme for more details.
780 g_object_class_install_property (gobject_class,
782 g_param_spec_string ("icon-name",
784 P_("Name of the themed icon for this window"),
786 GTK_PARAM_READWRITE));
788 g_object_class_install_property (gobject_class,
790 g_param_spec_object ("screen",
792 P_("The screen where this window will be displayed"),
794 GTK_PARAM_READWRITE));
796 g_object_class_install_property (gobject_class,
798 g_param_spec_boolean ("is-active",
800 P_("Whether the toplevel is the current active window"),
802 GTK_PARAM_READABLE));
804 g_object_class_install_property (gobject_class,
805 PROP_HAS_TOPLEVEL_FOCUS,
806 g_param_spec_boolean ("has-toplevel-focus",
807 P_("Focus in Toplevel"),
808 P_("Whether the input focus is within this GtkWindow"),
810 GTK_PARAM_READABLE));
812 g_object_class_install_property (gobject_class,
814 g_param_spec_enum ("type-hint",
816 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
817 GDK_TYPE_WINDOW_TYPE_HINT,
818 GDK_WINDOW_TYPE_HINT_NORMAL,
819 GTK_PARAM_READWRITE));
821 g_object_class_install_property (gobject_class,
822 PROP_SKIP_TASKBAR_HINT,
823 g_param_spec_boolean ("skip-taskbar-hint",
825 P_("TRUE if the window should not be in the task bar."),
827 GTK_PARAM_READWRITE));
829 g_object_class_install_property (gobject_class,
830 PROP_SKIP_PAGER_HINT,
831 g_param_spec_boolean ("skip-pager-hint",
833 P_("TRUE if the window should not be in the pager."),
835 GTK_PARAM_READWRITE));
837 g_object_class_install_property (gobject_class,
839 g_param_spec_boolean ("urgency-hint",
841 P_("TRUE if the window should be brought to the user's attention."),
843 GTK_PARAM_READWRITE));
846 * GtkWindow:accept-focus:
848 * Whether the window should receive the input focus.
852 g_object_class_install_property (gobject_class,
854 g_param_spec_boolean ("accept-focus",
856 P_("TRUE if the window should receive the input focus."),
858 GTK_PARAM_READWRITE));
861 * GtkWindow:focus-on-map:
863 * Whether the window should receive the input focus when mapped.
867 g_object_class_install_property (gobject_class,
869 g_param_spec_boolean ("focus-on-map",
871 P_("TRUE if the window should receive the input focus when mapped."),
873 GTK_PARAM_READWRITE));
876 * GtkWindow:decorated:
878 * Whether the window should be decorated by the window manager.
882 g_object_class_install_property (gobject_class,
884 g_param_spec_boolean ("decorated",
886 P_("Whether the window should be decorated by the window manager"),
888 GTK_PARAM_READWRITE));
891 * GtkWindow:deletable:
893 * Whether the window frame should have a close button.
897 g_object_class_install_property (gobject_class,
899 g_param_spec_boolean ("deletable",
901 P_("Whether the window frame should have a close button"),
903 GTK_PARAM_READWRITE));
906 * GtkWindow:has-resize-grip:
908 * Whether the window has a corner resize grip.
910 * Note that the resize grip is only shown if the window is
911 * actually resizable and not maximized. Use
912 * #GtkWindow:resize-grip-visible to find out if the resize
913 * grip is currently shown.
917 g_object_class_install_property (gobject_class,
918 PROP_HAS_RESIZE_GRIP,
919 g_param_spec_boolean ("has-resize-grip",
921 P_("Specifies whether the window should have a resize grip"),
923 GTK_PARAM_READWRITE));
926 * GtkWindow:resize-grip-visible:
928 * Whether a corner resize grip is currently shown.
932 g_object_class_install_property (gobject_class,
933 PROP_RESIZE_GRIP_VISIBLE,
934 g_param_spec_boolean ("resize-grip-visible",
935 P_("Resize grip is visible"),
936 P_("Specifies whether the window's resize grip is visible."),
938 GTK_PARAM_READABLE));
944 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
945 * more details about window gravity.
949 g_object_class_install_property (gobject_class,
951 g_param_spec_enum ("gravity",
953 P_("The window gravity of the window"),
955 GDK_GRAVITY_NORTH_WEST,
956 GTK_PARAM_READWRITE));
960 * GtkWindow:transient-for:
962 * The transient parent of the window. See gtk_window_set_transient_for() for
963 * more details about transient windows.
967 g_object_class_install_property (gobject_class,
969 g_param_spec_object ("transient-for",
970 P_("Transient for Window"),
971 P_("The transient parent of the dialog"),
973 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
976 * GtkWindow:attached-to:
978 * The widget to which this window is attached.
979 * See gtk_window_set_attached_to().
981 * Examples of places where specifying this relation is useful are
982 * for instance a #GtkMenu created by a #GtkComboBox, a completion
983 * popup window created by #GtkEntry or a typeahead search entry
984 * created by #GtkTreeView.
988 g_object_class_install_property (gobject_class,
990 g_param_spec_object ("attached-to",
991 P_("Attached to Widget"),
992 P_("The widget where the window is attached"),
994 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
999 * The requested opacity of the window. See gtk_window_set_opacity() for
1000 * more details about window opacity.
1004 g_object_class_install_property (gobject_class,
1006 g_param_spec_double ("opacity",
1007 P_("Opacity for Window"),
1008 P_("The opacity of the window, from 0 to 1"),
1012 GTK_PARAM_READWRITE));
1014 /* Style properties.
1016 gtk_widget_class_install_style_property (widget_class,
1017 g_param_spec_int ("resize-grip-width",
1018 P_("Width of resize grip"),
1019 P_("Width of resize grip"),
1020 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1022 gtk_widget_class_install_style_property (widget_class,
1023 g_param_spec_int ("resize-grip-height",
1024 P_("Height of resize grip"),
1025 P_("Height of resize grip"),
1026 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1030 * GtkWindow:application:
1032 * The #GtkApplication associated with the window.
1034 * The application will be kept alive for at least as long as it
1035 * has any windows associated with it (see g_application_hold()
1036 * for a way to keep it alive without windows).
1038 * Normally, the connection between the application and the window
1039 * will remain until the window is destroyed, but you can explicitly
1040 * remove it by setting the ::application property to %NULL.
1044 g_object_class_install_property (gobject_class,
1046 g_param_spec_object ("application",
1047 P_("GtkApplication"),
1048 P_("The GtkApplication for the window"),
1049 GTK_TYPE_APPLICATION,
1050 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1052 window_signals[SET_FOCUS] =
1053 g_signal_new (I_("set-focus"),
1054 G_TYPE_FROM_CLASS (gobject_class),
1056 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1058 _gtk_marshal_VOID__OBJECT,
1063 * GtkWindow::activate-focus:
1064 * @window: the window which received the signal
1066 * The ::activate-focus signal is a
1067 * <link linkend="keybinding-signals">keybinding signal</link>
1068 * which gets emitted when the user activates the currently
1069 * focused widget of @window.
1071 window_signals[ACTIVATE_FOCUS] =
1072 g_signal_new (I_("activate-focus"),
1073 G_TYPE_FROM_CLASS (gobject_class),
1074 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1075 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1077 _gtk_marshal_VOID__VOID,
1082 * GtkWindow::activate-default:
1083 * @window: the window which received the signal
1085 * The ::activate-default signal is a
1086 * <link linkend="keybinding-signals">keybinding signal</link>
1087 * which gets emitted when the user activates the default widget
1090 window_signals[ACTIVATE_DEFAULT] =
1091 g_signal_new (I_("activate-default"),
1092 G_TYPE_FROM_CLASS (gobject_class),
1093 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1094 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1096 _gtk_marshal_VOID__VOID,
1101 * GtkWindow::keys-changed:
1102 * @window: the window which received the signal
1104 * The ::keys-changed signal gets emitted when the set of accelerators
1105 * or mnemonics that are associated with @window changes.
1107 window_signals[KEYS_CHANGED] =
1108 g_signal_new (I_("keys-changed"),
1109 G_TYPE_FROM_CLASS (gobject_class),
1111 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1113 _gtk_marshal_VOID__VOID,
1121 binding_set = gtk_binding_set_by_class (klass);
1123 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1124 "activate-focus", 0);
1125 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1126 "activate-focus", 0);
1128 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1129 "activate-default", 0);
1130 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1131 "activate-default", 0);
1132 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1133 "activate-default", 0);
1135 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1136 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1137 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1138 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1140 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1141 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1142 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1143 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1145 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1149 gtk_window_init (GtkWindow *window)
1151 GtkWindowPrivate *priv;
1153 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1156 priv = window->priv;
1158 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1159 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1161 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1163 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1166 priv->wmclass_name = g_strdup (g_get_prgname ());
1167 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1168 priv->wm_role = NULL;
1169 priv->geometry_info = NULL;
1170 priv->type = GTK_WINDOW_TOPLEVEL;
1171 priv->focus_widget = NULL;
1172 priv->default_widget = NULL;
1173 priv->configure_request_count = 0;
1174 priv->resizable = TRUE;
1175 priv->configure_notify_received = FALSE;
1176 priv->position = GTK_WIN_POS_NONE;
1177 priv->need_default_size = TRUE;
1178 priv->need_default_position = TRUE;
1179 priv->modal = FALSE;
1180 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1181 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1182 priv->decorated = TRUE;
1183 priv->mnemonic_modifier = GDK_MOD1_MASK;
1184 priv->screen = gdk_screen_get_default ();
1186 priv->accept_focus = TRUE;
1187 priv->focus_on_map = TRUE;
1188 priv->deletable = TRUE;
1189 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1190 priv->opacity = 1.0;
1191 priv->startup_id = NULL;
1192 priv->initial_timestamp = GDK_CURRENT_TIME;
1193 priv->has_resize_grip = TRUE;
1194 priv->mnemonics_visible = TRUE;
1195 priv->focus_visible = TRUE;
1197 g_object_ref_sink (window);
1198 priv->has_user_ref_count = TRUE;
1199 toplevel_list = g_slist_prepend (toplevel_list, window);
1202 g_signal_connect (priv->screen, "composited-changed",
1203 G_CALLBACK (gtk_window_on_composited_changed), window);
1205 #ifdef GDK_WINDOWING_X11
1206 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1207 "notify::gtk-application-prefer-dark-theme",
1208 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1213 gtk_window_set_property (GObject *object,
1215 const GValue *value,
1218 GtkWindow *window = GTK_WINDOW (object);
1219 GtkWindowPrivate *priv = window->priv;
1224 priv->type = g_value_get_enum (value);
1227 gtk_window_set_title (window, g_value_get_string (value));
1230 gtk_window_set_role (window, g_value_get_string (value));
1232 case PROP_STARTUP_ID:
1233 gtk_window_set_startup_id (window, g_value_get_string (value));
1235 case PROP_RESIZABLE:
1236 gtk_window_set_resizable (window, g_value_get_boolean (value));
1239 gtk_window_set_modal (window, g_value_get_boolean (value));
1242 gtk_window_set_position (window, g_value_get_enum (value));
1244 case PROP_DEFAULT_WIDTH:
1245 gtk_window_set_default_size_internal (window,
1246 TRUE, g_value_get_int (value),
1249 case PROP_DEFAULT_HEIGHT:
1250 gtk_window_set_default_size_internal (window,
1252 TRUE, g_value_get_int (value), FALSE);
1254 case PROP_DESTROY_WITH_PARENT:
1255 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1257 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1258 gtk_window_set_hide_titlebar_when_maximized (window, g_value_get_boolean (value));
1261 gtk_window_set_icon (window,
1262 g_value_get_object (value));
1264 case PROP_ICON_NAME:
1265 gtk_window_set_icon_name (window, g_value_get_string (value));
1268 gtk_window_set_screen (window, g_value_get_object (value));
1270 case PROP_TYPE_HINT:
1271 gtk_window_set_type_hint (window,
1272 g_value_get_enum (value));
1274 case PROP_SKIP_TASKBAR_HINT:
1275 gtk_window_set_skip_taskbar_hint (window,
1276 g_value_get_boolean (value));
1278 case PROP_SKIP_PAGER_HINT:
1279 gtk_window_set_skip_pager_hint (window,
1280 g_value_get_boolean (value));
1282 case PROP_URGENCY_HINT:
1283 gtk_window_set_urgency_hint (window,
1284 g_value_get_boolean (value));
1286 case PROP_ACCEPT_FOCUS:
1287 gtk_window_set_accept_focus (window,
1288 g_value_get_boolean (value));
1290 case PROP_FOCUS_ON_MAP:
1291 gtk_window_set_focus_on_map (window,
1292 g_value_get_boolean (value));
1294 case PROP_DECORATED:
1295 gtk_window_set_decorated (window, g_value_get_boolean (value));
1297 case PROP_DELETABLE:
1298 gtk_window_set_deletable (window, g_value_get_boolean (value));
1301 gtk_window_set_gravity (window, g_value_get_enum (value));
1303 case PROP_TRANSIENT_FOR:
1304 gtk_window_set_transient_for (window, g_value_get_object (value));
1306 case PROP_ATTACHED_TO:
1307 gtk_window_set_attached_to (window, g_value_get_object (value));
1310 gtk_window_set_opacity (window, g_value_get_double (value));
1312 case PROP_HAS_RESIZE_GRIP:
1313 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1315 case PROP_APPLICATION:
1316 gtk_window_set_application (window, g_value_get_object (value));
1318 case PROP_MNEMONICS_VISIBLE:
1319 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1321 case PROP_FOCUS_VISIBLE:
1322 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1325 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1331 gtk_window_get_property (GObject *object,
1336 GtkWindow *window = GTK_WINDOW (object);
1337 GtkWindowPrivate *priv = window->priv;
1341 GtkWindowGeometryInfo *info;
1343 g_value_set_enum (value, priv->type);
1346 g_value_set_string (value, priv->wm_role);
1349 g_value_set_string (value, priv->title);
1351 case PROP_RESIZABLE:
1352 g_value_set_boolean (value, priv->resizable);
1355 g_value_set_boolean (value, priv->modal);
1358 g_value_set_enum (value, priv->position);
1360 case PROP_DEFAULT_WIDTH:
1361 info = gtk_window_get_geometry_info (window, FALSE);
1363 g_value_set_int (value, -1);
1365 g_value_set_int (value, info->default_width);
1367 case PROP_DEFAULT_HEIGHT:
1368 info = gtk_window_get_geometry_info (window, FALSE);
1370 g_value_set_int (value, -1);
1372 g_value_set_int (value, info->default_height);
1374 case PROP_DESTROY_WITH_PARENT:
1375 g_value_set_boolean (value, priv->destroy_with_parent);
1377 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1378 g_value_set_boolean (value, priv->hide_titlebar_when_maximized);
1381 g_value_set_object (value, gtk_window_get_icon (window));
1383 case PROP_ICON_NAME:
1384 g_value_set_string (value, gtk_window_get_icon_name (window));
1387 g_value_set_object (value, priv->screen);
1389 case PROP_IS_ACTIVE:
1390 g_value_set_boolean (value, priv->is_active);
1392 case PROP_HAS_TOPLEVEL_FOCUS:
1393 g_value_set_boolean (value, priv->has_toplevel_focus);
1395 case PROP_TYPE_HINT:
1396 g_value_set_enum (value, priv->type_hint);
1398 case PROP_SKIP_TASKBAR_HINT:
1399 g_value_set_boolean (value,
1400 gtk_window_get_skip_taskbar_hint (window));
1402 case PROP_SKIP_PAGER_HINT:
1403 g_value_set_boolean (value,
1404 gtk_window_get_skip_pager_hint (window));
1406 case PROP_URGENCY_HINT:
1407 g_value_set_boolean (value,
1408 gtk_window_get_urgency_hint (window));
1410 case PROP_ACCEPT_FOCUS:
1411 g_value_set_boolean (value,
1412 gtk_window_get_accept_focus (window));
1414 case PROP_FOCUS_ON_MAP:
1415 g_value_set_boolean (value,
1416 gtk_window_get_focus_on_map (window));
1418 case PROP_DECORATED:
1419 g_value_set_boolean (value, gtk_window_get_decorated (window));
1421 case PROP_DELETABLE:
1422 g_value_set_boolean (value, gtk_window_get_deletable (window));
1425 g_value_set_enum (value, gtk_window_get_gravity (window));
1427 case PROP_TRANSIENT_FOR:
1428 g_value_set_object (value, gtk_window_get_transient_for (window));
1430 case PROP_ATTACHED_TO:
1431 g_value_set_object (value, gtk_window_get_attached_to (window));
1434 g_value_set_double (value, gtk_window_get_opacity (window));
1436 case PROP_HAS_RESIZE_GRIP:
1437 g_value_set_boolean (value, priv->has_resize_grip);
1439 case PROP_RESIZE_GRIP_VISIBLE:
1440 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1442 case PROP_APPLICATION:
1443 g_value_set_object (value, gtk_window_get_application (window));
1445 case PROP_MNEMONICS_VISIBLE:
1446 g_value_set_boolean (value, priv->mnemonics_visible);
1448 case PROP_FOCUS_VISIBLE:
1449 g_value_set_boolean (value, priv->focus_visible);
1452 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1458 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1460 parent_buildable_iface = g_type_interface_peek_parent (iface);
1461 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1462 iface->parser_finished = gtk_window_buildable_parser_finished;
1463 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1464 iface->custom_finished = gtk_window_buildable_custom_finished;
1468 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1469 GtkBuilder *builder,
1471 const GValue *value)
1473 GtkWindow *window = GTK_WINDOW (buildable);
1474 GtkWindowPrivate *priv = window->priv;
1476 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1477 priv->builder_visible = TRUE;
1479 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1483 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1484 GtkBuilder *builder)
1486 GtkWindow *window = GTK_WINDOW (buildable);
1487 GtkWindowPrivate *priv = window->priv;
1491 if (priv->builder_visible)
1492 gtk_widget_show (GTK_WIDGET (buildable));
1494 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1495 for (l = accels; l; l = l->next)
1497 object = gtk_builder_get_object (builder, l->data);
1500 g_warning ("Unknown accel group %s specified in window %s",
1501 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1504 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1505 GTK_ACCEL_GROUP (object));
1509 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1511 parent_buildable_iface->parser_finished (buildable, builder);
1517 } GSListSubParserData;
1520 window_start_element (GMarkupParseContext *context,
1521 const gchar *element_name,
1522 const gchar **names,
1523 const gchar **values,
1528 GSListSubParserData *data = (GSListSubParserData*)user_data;
1530 if (strcmp (element_name, "group") == 0)
1532 for (i = 0; names[i]; i++)
1534 if (strcmp (names[i], "name") == 0)
1535 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1538 else if (strcmp (element_name, "accel-groups") == 0)
1541 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1546 static const GMarkupParser window_parser =
1548 window_start_element
1552 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1553 GtkBuilder *builder,
1555 const gchar *tagname,
1556 GMarkupParser *parser,
1559 GSListSubParserData *parser_data;
1561 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1562 tagname, parser, data))
1565 if (strcmp (tagname, "accel-groups") == 0)
1567 parser_data = g_slice_new0 (GSListSubParserData);
1568 parser_data->items = NULL;
1569 parser_data->object = G_OBJECT (buildable);
1571 *parser = window_parser;
1572 *data = parser_data;
1580 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1581 GtkBuilder *builder,
1583 const gchar *tagname,
1586 GSListSubParserData *data;
1588 parent_buildable_iface->custom_finished (buildable, builder, child,
1589 tagname, user_data);
1591 if (strcmp (tagname, "accel-groups") != 0)
1594 data = (GSListSubParserData*)user_data;
1596 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1597 data->items, (GDestroyNotify) g_slist_free);
1599 g_slice_free (GSListSubParserData, data);
1604 * @type: type of window
1606 * Creates a new #GtkWindow, which is a toplevel window that can
1607 * contain other widgets. Nearly always, the type of the window should
1608 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1609 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1610 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1611 * dialogs, though in some other toolkits dialogs are called "popups".
1612 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1613 * On X11, popup windows are not controlled by the <link
1614 * linkend="gtk-X11-arch">window manager</link>.
1616 * If you simply want an undecorated window (no window borders), use
1617 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1619 * Return value: a new #GtkWindow.
1622 gtk_window_new (GtkWindowType type)
1624 GtkWindowPrivate *priv;
1627 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1629 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1630 priv = window->priv;
1634 return GTK_WIDGET (window);
1638 * gtk_window_set_title:
1639 * @window: a #GtkWindow
1640 * @title: title of the window
1642 * Sets the title of the #GtkWindow. The title of a window will be
1643 * displayed in its title bar; on the X Window System, the title bar
1644 * is rendered by the <link linkend="gtk-X11-arch">window
1645 * manager</link>, so exactly how the title appears to users may vary
1646 * according to a user's exact configuration. The title should help a
1647 * user distinguish this window from other windows they may have
1648 * open. A good title might include the application name and current
1649 * document filename, for example.
1653 gtk_window_set_title (GtkWindow *window,
1656 GtkWindowPrivate *priv;
1660 g_return_if_fail (GTK_IS_WINDOW (window));
1662 priv = window->priv;
1663 widget = GTK_WIDGET (window);
1665 new_title = g_strdup (title);
1666 g_free (priv->title);
1667 priv->title = new_title;
1669 if (gtk_widget_get_realized (widget))
1671 gdk_window_set_title (gtk_widget_get_window (widget),
1675 g_object_notify (G_OBJECT (window), "title");
1679 * gtk_window_get_title:
1680 * @window: a #GtkWindow
1682 * Retrieves the title of the window. See gtk_window_set_title().
1684 * Return value: the title of the window, or %NULL if none has
1685 * been set explicitely. The returned string is owned by the widget
1686 * and must not be modified or freed.
1689 gtk_window_get_title (GtkWindow *window)
1691 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1693 return window->priv->title;
1697 * gtk_window_set_wmclass:
1698 * @window: a #GtkWindow
1699 * @wmclass_name: window name hint
1700 * @wmclass_class: window class hint
1702 * Don't use this function. It sets the X Window System "class" and
1703 * "name" hints for a window. According to the ICCCM, you should
1704 * always set these to the same value for all windows in an
1705 * application, and GTK+ sets them to that value by default, so calling
1706 * this function is sort of pointless. However, you may want to call
1707 * gtk_window_set_role() on each window in your application, for the
1708 * benefit of the session manager. Setting the role allows the window
1709 * manager to restore window positions when loading a saved session.
1713 gtk_window_set_wmclass (GtkWindow *window,
1714 const gchar *wmclass_name,
1715 const gchar *wmclass_class)
1717 GtkWindowPrivate *priv;
1719 g_return_if_fail (GTK_IS_WINDOW (window));
1721 priv = window->priv;
1723 g_free (priv->wmclass_name);
1724 priv->wmclass_name = g_strdup (wmclass_name);
1726 g_free (priv->wmclass_class);
1727 priv->wmclass_class = g_strdup (wmclass_class);
1729 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1730 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1734 * gtk_window_set_role:
1735 * @window: a #GtkWindow
1736 * @role: unique identifier for the window to be used when restoring a session
1738 * This function is only useful on X11, not with other GTK+ targets.
1740 * In combination with the window title, the window role allows a
1741 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1742 * same" window when an application is restarted. So for example you
1743 * might set the "toolbox" role on your app's toolbox window, so that
1744 * when the user restarts their session, the window manager can put
1745 * the toolbox back in the same place.
1747 * If a window already has a unique title, you don't need to set the
1748 * role, since the WM can use the title to identify the window when
1749 * restoring the session.
1753 gtk_window_set_role (GtkWindow *window,
1756 GtkWindowPrivate *priv;
1759 g_return_if_fail (GTK_IS_WINDOW (window));
1761 priv = window->priv;
1763 new_role = g_strdup (role);
1764 g_free (priv->wm_role);
1765 priv->wm_role = new_role;
1767 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1768 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1771 g_object_notify (G_OBJECT (window), "role");
1775 * gtk_window_set_startup_id:
1776 * @window: a #GtkWindow
1777 * @startup_id: a string with startup-notification identifier
1779 * Startup notification identifiers are used by desktop environment to
1780 * track application startup, to provide user feedback and other
1781 * features. This function changes the corresponding property on the
1782 * underlying GdkWindow. Normally, startup identifier is managed
1783 * automatically and you should only use this function in special cases
1784 * like transferring focus from other processes. You should use this
1785 * function before calling gtk_window_present() or any equivalent
1786 * function generating a window map event.
1788 * This function is only useful on X11, not with other GTK+ targets.
1793 gtk_window_set_startup_id (GtkWindow *window,
1794 const gchar *startup_id)
1796 GtkWindowPrivate *priv;
1799 g_return_if_fail (GTK_IS_WINDOW (window));
1801 priv = window->priv;
1802 widget = GTK_WIDGET (window);
1804 g_free (priv->startup_id);
1805 priv->startup_id = g_strdup (startup_id);
1807 if (gtk_widget_get_realized (widget))
1809 GdkWindow *gdk_window;
1810 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1812 gdk_window = gtk_widget_get_window (widget);
1814 #ifdef GDK_WINDOWING_X11
1815 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1816 gdk_x11_window_set_user_time (gdk_window, timestamp);
1819 /* Here we differentiate real and "fake" startup notification IDs,
1820 * constructed on purpose just to pass interaction timestamp
1822 if (startup_id_is_fake (priv->startup_id))
1823 gtk_window_present_with_time (window, timestamp);
1826 gdk_window_set_startup_id (gdk_window,
1829 /* If window is mapped, terminate the startup-notification too */
1830 if (gtk_widget_get_mapped (widget) &&
1831 !disable_startup_notification)
1832 gdk_notify_startup_complete_with_id (priv->startup_id);
1836 g_object_notify (G_OBJECT (window), "startup-id");
1840 * gtk_window_get_role:
1841 * @window: a #GtkWindow
1843 * Returns the role of the window. See gtk_window_set_role() for
1844 * further explanation.
1846 * Return value: the role of the window if set, or %NULL. The
1847 * returned is owned by the widget and must not be modified
1851 gtk_window_get_role (GtkWindow *window)
1853 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1855 return window->priv->wm_role;
1859 * gtk_window_set_focus:
1860 * @window: a #GtkWindow
1861 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1862 * any focus widget for the toplevel window.
1864 * If @focus is not the current focus widget, and is focusable, sets
1865 * it as the focus widget for the window. If @focus is %NULL, unsets
1866 * the focus widget for this window. To set the focus to a particular
1867 * widget in the toplevel, it is usually more convenient to use
1868 * gtk_widget_grab_focus() instead of this function.
1871 gtk_window_set_focus (GtkWindow *window,
1874 GtkWindowPrivate *priv;
1877 g_return_if_fail (GTK_IS_WINDOW (window));
1879 priv = window->priv;
1883 g_return_if_fail (GTK_IS_WIDGET (focus));
1884 g_return_if_fail (gtk_widget_get_can_focus (focus));
1888 gtk_widget_grab_focus (focus);
1891 /* Clear the existing focus chain, so that when we focus into
1892 * the window again, we start at the beginnning.
1894 GtkWidget *widget = priv->focus_widget;
1897 while ((parent = gtk_widget_get_parent (widget)))
1900 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1904 _gtk_window_internal_set_focus (window, NULL);
1909 _gtk_window_internal_set_focus (GtkWindow *window,
1912 GtkWindowPrivate *priv;
1914 g_return_if_fail (GTK_IS_WINDOW (window));
1916 priv = window->priv;
1918 if ((priv->focus_widget != focus) ||
1919 (focus && !gtk_widget_has_focus (focus)))
1920 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1924 * gtk_window_set_default:
1925 * @window: a #GtkWindow
1926 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1927 * default widget for the toplevel.
1929 * The default widget is the widget that's activated when the user
1930 * presses Enter in a dialog (for example). This function sets or
1931 * unsets the default widget for a #GtkWindow about. When setting
1932 * (rather than unsetting) the default widget it's generally easier to
1933 * call gtk_widget_grab_focus() on the widget. Before making a widget
1934 * the default widget, you must call gtk_widget_set_can_default() on the
1935 * widget you'd like to make the default.
1938 gtk_window_set_default (GtkWindow *window,
1939 GtkWidget *default_widget)
1941 GtkWindowPrivate *priv;
1943 g_return_if_fail (GTK_IS_WINDOW (window));
1945 priv = window->priv;
1948 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1950 if (priv->default_widget != default_widget)
1952 GtkWidget *old_default_widget = NULL;
1955 g_object_ref (default_widget);
1957 if (priv->default_widget)
1959 old_default_widget = priv->default_widget;
1961 if (priv->focus_widget != priv->default_widget ||
1962 !gtk_widget_get_receives_default (priv->default_widget))
1963 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1965 gtk_widget_queue_draw (priv->default_widget);
1968 priv->default_widget = default_widget;
1970 if (priv->default_widget)
1972 if (priv->focus_widget == NULL ||
1973 !gtk_widget_get_receives_default (priv->focus_widget))
1974 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1976 gtk_widget_queue_draw (priv->default_widget);
1979 if (old_default_widget)
1980 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1984 g_object_notify (G_OBJECT (default_widget), "has-default");
1985 g_object_unref (default_widget);
1991 * gtk_window_get_default_widget:
1992 * @window: a #GtkWindow
1994 * Returns the default widget for @window. See gtk_window_set_default()
1997 * Returns: (transfer none): the default widget, or %NULL if there is none.
2002 gtk_window_get_default_widget (GtkWindow *window)
2004 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2006 return window->priv->default_widget;
2010 handle_keys_changed (gpointer data)
2012 GtkWindow *window = GTK_WINDOW (data);
2013 GtkWindowPrivate *priv = window->priv;
2015 if (priv->keys_changed_handler)
2017 g_source_remove (priv->keys_changed_handler);
2018 priv->keys_changed_handler = 0;
2021 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
2027 gtk_window_notify_keys_changed (GtkWindow *window)
2029 GtkWindowPrivate *priv = window->priv;
2031 if (!priv->keys_changed_handler)
2032 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
2036 * gtk_window_add_accel_group:
2037 * @window: window to attach accelerator group to
2038 * @accel_group: a #GtkAccelGroup
2040 * Associate @accel_group with @window, such that calling
2041 * gtk_accel_groups_activate() on @window will activate accelerators
2045 gtk_window_add_accel_group (GtkWindow *window,
2046 GtkAccelGroup *accel_group)
2048 g_return_if_fail (GTK_IS_WINDOW (window));
2049 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2051 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
2052 g_signal_connect_object (accel_group, "accel-changed",
2053 G_CALLBACK (gtk_window_notify_keys_changed),
2054 window, G_CONNECT_SWAPPED);
2055 gtk_window_notify_keys_changed (window);
2059 * gtk_window_remove_accel_group:
2060 * @window: a #GtkWindow
2061 * @accel_group: a #GtkAccelGroup
2063 * Reverses the effects of gtk_window_add_accel_group().
2066 gtk_window_remove_accel_group (GtkWindow *window,
2067 GtkAccelGroup *accel_group)
2069 g_return_if_fail (GTK_IS_WINDOW (window));
2070 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2072 g_signal_handlers_disconnect_by_func (accel_group,
2073 gtk_window_notify_keys_changed,
2075 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2076 gtk_window_notify_keys_changed (window);
2079 static GtkMnemonicHash *
2080 gtk_window_get_mnemonic_hash (GtkWindow *window,
2083 GtkWindowPrivate *private = window->priv;
2085 if (!private->mnemonic_hash && create)
2086 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2088 return private->mnemonic_hash;
2092 * gtk_window_add_mnemonic:
2093 * @window: a #GtkWindow
2094 * @keyval: the mnemonic
2095 * @target: the widget that gets activated by the mnemonic
2097 * Adds a mnemonic to this window.
2100 gtk_window_add_mnemonic (GtkWindow *window,
2104 g_return_if_fail (GTK_IS_WINDOW (window));
2105 g_return_if_fail (GTK_IS_WIDGET (target));
2107 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2109 gtk_window_notify_keys_changed (window);
2113 * gtk_window_remove_mnemonic:
2114 * @window: a #GtkWindow
2115 * @keyval: the mnemonic
2116 * @target: the widget that gets activated by the mnemonic
2118 * Removes a mnemonic from this window.
2121 gtk_window_remove_mnemonic (GtkWindow *window,
2125 g_return_if_fail (GTK_IS_WINDOW (window));
2126 g_return_if_fail (GTK_IS_WIDGET (target));
2128 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2130 gtk_window_notify_keys_changed (window);
2134 * gtk_window_mnemonic_activate:
2135 * @window: a #GtkWindow
2136 * @keyval: the mnemonic
2137 * @modifier: the modifiers
2139 * Activates the targets associated with the mnemonic.
2141 * Returns: %TRUE if the activation is done.
2144 gtk_window_mnemonic_activate (GtkWindow *window,
2146 GdkModifierType modifier)
2148 GtkWindowPrivate *priv;
2150 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2152 priv = window->priv;
2154 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2156 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2158 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2165 * gtk_window_set_mnemonic_modifier:
2166 * @window: a #GtkWindow
2167 * @modifier: the modifier mask used to activate
2168 * mnemonics on this window.
2170 * Sets the mnemonic modifier for this window.
2173 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2174 GdkModifierType modifier)
2176 GtkWindowPrivate *priv;
2178 g_return_if_fail (GTK_IS_WINDOW (window));
2179 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2181 priv = window->priv;
2183 priv->mnemonic_modifier = modifier;
2184 gtk_window_notify_keys_changed (window);
2188 * gtk_window_get_mnemonic_modifier:
2189 * @window: a #GtkWindow
2191 * Returns the mnemonic modifier for this window. See
2192 * gtk_window_set_mnemonic_modifier().
2194 * Return value: the modifier mask used to activate
2195 * mnemonics on this window.
2198 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2200 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2202 return window->priv->mnemonic_modifier;
2206 * gtk_window_set_position:
2207 * @window: a #GtkWindow.
2208 * @position: a position constraint.
2210 * Sets a position constraint for this window. If the old or new
2211 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2212 * the window to be repositioned to satisfy the new constraint.
2215 gtk_window_set_position (GtkWindow *window,
2216 GtkWindowPosition position)
2218 GtkWindowPrivate *priv;
2220 g_return_if_fail (GTK_IS_WINDOW (window));
2222 priv = window->priv;
2224 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2225 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2227 GtkWindowGeometryInfo *info;
2229 info = gtk_window_get_geometry_info (window, TRUE);
2231 /* this flag causes us to re-request the CENTER_ALWAYS
2232 * constraint in gtk_window_move_resize(), see
2233 * comment in that function.
2235 info->position_constraints_changed = TRUE;
2237 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2240 priv->position = position;
2242 g_object_notify (G_OBJECT (window), "window-position");
2246 * gtk_window_activate_focus:
2247 * @window: a #GtkWindow
2249 * Activates the current focused widget within the window.
2251 * Return value: %TRUE if a widget got activated.
2254 gtk_window_activate_focus (GtkWindow *window)
2256 GtkWindowPrivate *priv;
2258 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2260 priv = window->priv;
2262 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2263 return gtk_widget_activate (priv->focus_widget);
2269 * gtk_window_get_focus:
2270 * @window: a #GtkWindow
2272 * Retrieves the current focused widget within the window.
2273 * Note that this is the widget that would have the focus
2274 * if the toplevel window focused; if the toplevel window
2275 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2276 * not be %TRUE for the widget.
2278 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2281 gtk_window_get_focus (GtkWindow *window)
2283 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2285 return window->priv->focus_widget;
2289 * gtk_window_activate_default:
2290 * @window: a #GtkWindow
2292 * Activates the default widget for the window, unless the current
2293 * focused widget has been configured to receive the default action
2294 * (see gtk_widget_set_receives_default()), in which case the
2295 * focused widget is activated.
2297 * Return value: %TRUE if a widget got activated.
2300 gtk_window_activate_default (GtkWindow *window)
2302 GtkWindowPrivate *priv;
2304 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2306 priv = window->priv;
2308 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2309 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2310 return gtk_widget_activate (priv->default_widget);
2311 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2312 return gtk_widget_activate (priv->focus_widget);
2318 * gtk_window_set_modal:
2319 * @window: a #GtkWindow
2320 * @modal: whether the window is modal
2322 * Sets a window modal or non-modal. Modal windows prevent interaction
2323 * with other windows in the same application. To keep modal dialogs
2324 * on top of main application windows, use
2325 * gtk_window_set_transient_for() to make the dialog transient for the
2326 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2327 * will then disallow lowering the dialog below the parent.
2332 gtk_window_set_modal (GtkWindow *window,
2335 GtkWindowPrivate *priv;
2338 g_return_if_fail (GTK_IS_WINDOW (window));
2340 priv = window->priv;
2342 modal = modal != FALSE;
2343 if (priv->modal == modal)
2346 priv->modal = modal;
2347 widget = GTK_WIDGET (window);
2349 /* adjust desired modality state */
2350 if (gtk_widget_get_realized (widget))
2353 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2355 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2358 if (gtk_widget_get_visible (widget))
2361 gtk_grab_add (widget);
2363 gtk_grab_remove (widget);
2366 g_object_notify (G_OBJECT (window), "modal");
2370 * gtk_window_get_modal:
2371 * @window: a #GtkWindow
2373 * Returns whether the window is modal. See gtk_window_set_modal().
2375 * Return value: %TRUE if the window is set to be modal and
2376 * establishes a grab when shown
2379 gtk_window_get_modal (GtkWindow *window)
2381 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2383 return window->priv->modal;
2387 * gtk_window_list_toplevels:
2389 * Returns a list of all existing toplevel windows. The widgets
2390 * in the list are not individually referenced. If you want
2391 * to iterate through the list and perform actions involving
2392 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2393 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2394 * then unref all the widgets afterwards.
2396 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2399 gtk_window_list_toplevels (void)
2404 for (slist = toplevel_list; slist; slist = slist->next)
2405 list = g_list_prepend (list, slist->data);
2411 remove_attach_widget (GtkWindow *window)
2413 GtkWindowPrivate *priv = window->priv;
2415 if (priv->attach_widget)
2417 _gtk_widget_remove_attached_window (priv->attach_widget, window);
2419 g_object_unref (priv->attach_widget);
2420 priv->attach_widget = NULL;
2425 gtk_window_dispose (GObject *object)
2427 GtkWindow *window = GTK_WINDOW (object);
2429 gtk_window_set_focus (window, NULL);
2430 gtk_window_set_default (window, NULL);
2432 remove_attach_widget (GTK_WINDOW (object));
2434 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2438 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2440 gtk_widget_destroy (GTK_WIDGET (child));
2444 connect_parent_destroyed (GtkWindow *window)
2446 GtkWindowPrivate *priv = window->priv;
2448 if (priv->transient_parent)
2450 g_signal_connect (priv->transient_parent,
2452 G_CALLBACK (parent_destroyed_callback),
2458 disconnect_parent_destroyed (GtkWindow *window)
2460 GtkWindowPrivate *priv = window->priv;
2462 if (priv->transient_parent)
2464 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2465 parent_destroyed_callback,
2471 gtk_window_transient_parent_realized (GtkWidget *parent,
2474 if (gtk_widget_get_realized (window))
2475 gdk_window_set_transient_for (gtk_widget_get_window (window),
2476 gtk_widget_get_window (parent));
2480 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2483 if (gtk_widget_get_realized (window))
2484 gdk_property_delete (gtk_widget_get_window (window),
2485 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2489 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2493 gtk_window_set_screen (window, parent->priv->screen);
2497 gtk_window_unset_transient_for (GtkWindow *window)
2499 GtkWindowPrivate *priv = window->priv;
2501 if (priv->transient_parent)
2503 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2504 gtk_window_transient_parent_realized,
2506 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2507 gtk_window_transient_parent_unrealized,
2509 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2510 gtk_window_transient_parent_screen_changed,
2512 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2513 gtk_widget_destroyed,
2514 &priv->transient_parent);
2516 if (priv->destroy_with_parent)
2517 disconnect_parent_destroyed (window);
2519 priv->transient_parent = NULL;
2521 if (priv->transient_parent_group)
2523 priv->transient_parent_group = FALSE;
2524 gtk_window_group_remove_window (priv->group,
2531 * gtk_window_set_transient_for:
2532 * @window: a #GtkWindow
2533 * @parent: (allow-none): parent window, or %NULL
2535 * Dialog windows should be set transient for the main application
2536 * window they were spawned from. This allows <link
2537 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2538 * dialog on top of the main window, or center the dialog over the
2539 * main window. gtk_dialog_new_with_buttons() and other convenience
2540 * functions in GTK+ will sometimes call
2541 * gtk_window_set_transient_for() on your behalf.
2543 * Passing %NULL for @parent unsets the current transient window.
2545 * On Windows, this function puts the child window on top of the parent,
2546 * much as the window manager would have done on X.
2549 gtk_window_set_transient_for (GtkWindow *window,
2552 GtkWindowPrivate *priv;
2554 g_return_if_fail (GTK_IS_WINDOW (window));
2555 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2556 g_return_if_fail (window != parent);
2558 priv = window->priv;
2560 if (priv->transient_parent)
2562 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2563 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2564 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2565 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2566 GTK_WIDGET (window));
2568 gtk_window_unset_transient_for (window);
2571 priv->transient_parent = parent;
2575 g_signal_connect (parent, "destroy",
2576 G_CALLBACK (gtk_widget_destroyed),
2577 &priv->transient_parent);
2578 g_signal_connect (parent, "realize",
2579 G_CALLBACK (gtk_window_transient_parent_realized),
2581 g_signal_connect (parent, "unrealize",
2582 G_CALLBACK (gtk_window_transient_parent_unrealized),
2584 g_signal_connect (parent, "notify::screen",
2585 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2588 gtk_window_set_screen (window, parent->priv->screen);
2590 if (priv->destroy_with_parent)
2591 connect_parent_destroyed (window);
2593 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2594 gtk_widget_get_realized (GTK_WIDGET (parent)))
2595 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2596 GTK_WIDGET (window));
2598 if (parent->priv->group)
2600 gtk_window_group_add_window (parent->priv->group, window);
2601 priv->transient_parent_group = TRUE;
2607 * gtk_window_get_transient_for:
2608 * @window: a #GtkWindow
2610 * Fetches the transient parent for this window. See
2611 * gtk_window_set_transient_for().
2613 * Return value: (transfer none): the transient parent for this window, or %NULL
2614 * if no transient parent has been set.
2617 gtk_window_get_transient_for (GtkWindow *window)
2619 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2621 return window->priv->transient_parent;
2625 * gtk_window_set_attached_to:
2626 * @window: a #GtkWindow
2627 * @attach_widget: (allow-none): a #GtkWidget, or %NULL
2629 * Marks @window as attached to @attach_widget. This creates a logical binding
2630 * between the window and the widget it belongs to, which is used by GTK+ to
2631 * propagate information such as styling or accessibility to @window as if it
2632 * was a children of @attach_widget.
2634 * Examples of places where specifying this relation is useful are for instance
2635 * a #GtkMenu created by a #GtkComboBox, a completion popup window
2636 * created by #GtkEntry or a typeahead search entry created by #GtkTreeView.
2638 * Note that this function should not be confused with
2639 * gtk_window_set_transient_for(), which specifies a window manager relation
2640 * between two toplevels instead.
2642 * Passing %NULL for @attach_widget detaches the window.
2647 gtk_window_set_attached_to (GtkWindow *window,
2648 GtkWidget *attach_widget)
2650 GtkStyleContext *context;
2651 GtkWindowPrivate *priv;
2653 g_return_if_fail (GTK_IS_WINDOW (window));
2654 g_return_if_fail (GTK_WIDGET (window) != attach_widget);
2656 priv = window->priv;
2658 if (priv->attach_widget == attach_widget)
2661 remove_attach_widget (window);
2663 priv->attach_widget = attach_widget;
2665 if (priv->attach_widget)
2667 _gtk_widget_add_attached_window (priv->attach_widget, window);
2669 g_object_ref (priv->attach_widget);
2672 /* Update the style, as the widget path might change. */
2673 context = gtk_widget_get_style_context (GTK_WIDGET (window));
2674 if (priv->attach_widget)
2675 gtk_style_context_set_parent (context, gtk_widget_get_style_context (priv->attach_widget));
2677 gtk_style_context_set_parent (context, NULL);
2681 * gtk_window_get_attached_to:
2682 * @window: a #GtkWindow
2684 * Fetches the attach widget for this window. See
2685 * gtk_window_set_attached_to().
2687 * Return value: (transfer none): the widget where the window is attached,
2688 * or %NULL if the window is not attached to any widget.
2693 gtk_window_get_attached_to (GtkWindow *window)
2695 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2697 return window->priv->attach_widget;
2701 * gtk_window_set_opacity:
2702 * @window: a #GtkWindow
2703 * @opacity: desired opacity, between 0 and 1
2705 * Request the windowing system to make @window partially transparent,
2706 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2707 * of the opacity parameter are clamped to the [0,1] range.) On X11
2708 * this has any effect only on X screens with a compositing manager
2709 * running. See gtk_widget_is_composited(). On Windows it should work
2712 * Note that setting a window's opacity after the window has been
2713 * shown causes it to flicker once on Windows.
2718 gtk_window_set_opacity (GtkWindow *window,
2721 GtkWindowPrivate *priv;
2723 g_return_if_fail (GTK_IS_WINDOW (window));
2725 priv = window->priv;
2729 else if (opacity > 1.0)
2732 priv->opacity_set = TRUE;
2733 priv->opacity = opacity;
2735 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2736 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2741 * gtk_window_get_opacity:
2742 * @window: a #GtkWindow
2744 * Fetches the requested opacity for this window. See
2745 * gtk_window_set_opacity().
2747 * Return value: the requested opacity for this window.
2752 gtk_window_get_opacity (GtkWindow *window)
2754 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2756 return window->priv->opacity;
2760 * gtk_window_get_application:
2761 * @window: a #GtkWindow
2763 * Gets the #GtkApplication associated with the window (if any).
2765 * Return value: (transfer none): a #GtkApplication, or %NULL
2770 gtk_window_get_application (GtkWindow *window)
2772 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2774 return window->priv->application;
2778 gtk_window_release_application (GtkWindow *window)
2780 if (window->priv->application)
2782 GtkApplication *application;
2784 /* steal reference into temp variable */
2785 application = window->priv->application;
2786 window->priv->application = NULL;
2788 gtk_application_remove_window (application, window);
2789 g_object_unref (application);
2794 * gtk_window_set_application:
2795 * @window: a #GtkWindow
2796 * @application: (allow-none): a #GtkApplication, or %NULL
2798 * Sets or unsets the #GtkApplication associated with the window.
2800 * The application will be kept alive for at least as long as the window
2806 gtk_window_set_application (GtkWindow *window,
2807 GtkApplication *application)
2809 GtkWindowPrivate *priv;
2811 g_return_if_fail (GTK_IS_WINDOW (window));
2813 priv = window->priv;
2814 if (priv->application != application)
2816 gtk_window_release_application (window);
2818 priv->application = application;
2820 if (priv->application != NULL)
2822 g_object_ref (priv->application);
2824 gtk_application_add_window (priv->application, window);
2827 /* don't use a normal cast: application may be NULL */
2828 gtk_widget_insert_action_group (GTK_WIDGET (window), "app", (GActionGroup *) application);
2830 g_object_notify (G_OBJECT (window), "application");
2835 * gtk_window_set_type_hint:
2836 * @window: a #GtkWindow
2837 * @hint: the window type
2839 * By setting the type hint for the window, you allow the window
2840 * manager to decorate and handle the window in a way which is
2841 * suitable to the function of the window in your application.
2843 * This function should be called before the window becomes visible.
2845 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2846 * will sometimes call gtk_window_set_type_hint() on your behalf.
2850 gtk_window_set_type_hint (GtkWindow *window,
2851 GdkWindowTypeHint hint)
2853 GtkWindowPrivate *priv;
2855 g_return_if_fail (GTK_IS_WINDOW (window));
2856 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2858 priv = window->priv;
2860 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2861 priv->type_hint = hint;
2863 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2865 priv->reset_type_hint = TRUE;
2866 priv->gdk_type_hint = hint;
2870 * gtk_window_get_type_hint:
2871 * @window: a #GtkWindow
2873 * Gets the type hint for this window. See gtk_window_set_type_hint().
2875 * Return value: the type hint for @window.
2878 gtk_window_get_type_hint (GtkWindow *window)
2880 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2882 return window->priv->gdk_type_hint;
2886 * gtk_window_set_skip_taskbar_hint:
2887 * @window: a #GtkWindow
2888 * @setting: %TRUE to keep this window from appearing in the task bar
2890 * Windows may set a hint asking the desktop environment not to display
2891 * the window in the task bar. This function sets this hint.
2896 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2899 GtkWindowPrivate *priv;
2901 g_return_if_fail (GTK_IS_WINDOW (window));
2903 priv = window->priv;
2905 setting = setting != FALSE;
2907 if (priv->skips_taskbar != setting)
2909 priv->skips_taskbar = setting;
2910 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2911 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2912 priv->skips_taskbar);
2913 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2918 * gtk_window_get_skip_taskbar_hint:
2919 * @window: a #GtkWindow
2921 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2923 * Return value: %TRUE if window shouldn't be in taskbar
2928 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2930 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2932 return window->priv->skips_taskbar;
2936 * gtk_window_set_skip_pager_hint:
2937 * @window: a #GtkWindow
2938 * @setting: %TRUE to keep this window from appearing in the pager
2940 * Windows may set a hint asking the desktop environment not to display
2941 * the window in the pager. This function sets this hint.
2942 * (A "pager" is any desktop navigation tool such as a workspace
2943 * switcher that displays a thumbnail representation of the windows
2949 gtk_window_set_skip_pager_hint (GtkWindow *window,
2952 GtkWindowPrivate *priv;
2954 g_return_if_fail (GTK_IS_WINDOW (window));
2956 priv = window->priv;
2958 setting = setting != FALSE;
2960 if (priv->skips_pager != setting)
2962 priv->skips_pager = setting;
2963 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2964 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2966 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2971 * gtk_window_get_skip_pager_hint:
2972 * @window: a #GtkWindow
2974 * Gets the value set by gtk_window_set_skip_pager_hint().
2976 * Return value: %TRUE if window shouldn't be in pager
2981 gtk_window_get_skip_pager_hint (GtkWindow *window)
2983 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2985 return window->priv->skips_pager;
2989 * gtk_window_set_urgency_hint:
2990 * @window: a #GtkWindow
2991 * @setting: %TRUE to mark this window as urgent
2993 * Windows may set a hint asking the desktop environment to draw
2994 * the users attention to the window. This function sets this hint.
2999 gtk_window_set_urgency_hint (GtkWindow *window,
3002 GtkWindowPrivate *priv;
3004 g_return_if_fail (GTK_IS_WINDOW (window));
3006 priv = window->priv;
3008 setting = setting != FALSE;
3010 if (priv->urgent != setting)
3012 priv->urgent = setting;
3013 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3014 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
3016 g_object_notify (G_OBJECT (window), "urgency-hint");
3021 * gtk_window_get_urgency_hint:
3022 * @window: a #GtkWindow
3024 * Gets the value set by gtk_window_set_urgency_hint()
3026 * Return value: %TRUE if window is urgent
3031 gtk_window_get_urgency_hint (GtkWindow *window)
3033 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3035 return window->priv->urgent;
3039 * gtk_window_set_accept_focus:
3040 * @window: a #GtkWindow
3041 * @setting: %TRUE to let this window receive input focus
3043 * Windows may set a hint asking the desktop environment not to receive
3044 * the input focus. This function sets this hint.
3049 gtk_window_set_accept_focus (GtkWindow *window,
3052 GtkWindowPrivate *priv;
3054 g_return_if_fail (GTK_IS_WINDOW (window));
3056 priv = window->priv;
3058 setting = setting != FALSE;
3060 if (priv->accept_focus != setting)
3062 priv->accept_focus = setting;
3063 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3064 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
3065 priv->accept_focus);
3066 g_object_notify (G_OBJECT (window), "accept-focus");
3071 * gtk_window_get_accept_focus:
3072 * @window: a #GtkWindow
3074 * Gets the value set by gtk_window_set_accept_focus().
3076 * Return value: %TRUE if window should receive the input focus
3081 gtk_window_get_accept_focus (GtkWindow *window)
3083 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3085 return window->priv->accept_focus;
3089 * gtk_window_set_focus_on_map:
3090 * @window: a #GtkWindow
3091 * @setting: %TRUE to let this window receive input focus on map
3093 * Windows may set a hint asking the desktop environment not to receive
3094 * the input focus when the window is mapped. This function sets this
3100 gtk_window_set_focus_on_map (GtkWindow *window,
3103 GtkWindowPrivate *priv;
3105 g_return_if_fail (GTK_IS_WINDOW (window));
3107 priv = window->priv;
3109 setting = setting != FALSE;
3111 if (priv->focus_on_map != setting)
3113 priv->focus_on_map = setting;
3114 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3115 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
3116 priv->focus_on_map);
3117 g_object_notify (G_OBJECT (window), "focus-on-map");
3122 * gtk_window_get_focus_on_map:
3123 * @window: a #GtkWindow
3125 * Gets the value set by gtk_window_set_focus_on_map().
3127 * Return value: %TRUE if window should receive the input focus when
3133 gtk_window_get_focus_on_map (GtkWindow *window)
3135 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3137 return window->priv->focus_on_map;
3141 * gtk_window_set_destroy_with_parent:
3142 * @window: a #GtkWindow
3143 * @setting: whether to destroy @window with its transient parent
3145 * If @setting is %TRUE, then destroying the transient parent of @window
3146 * will also destroy @window itself. This is useful for dialogs that
3147 * shouldn't persist beyond the lifetime of the main window they're
3148 * associated with, for example.
3151 gtk_window_set_destroy_with_parent (GtkWindow *window,
3154 GtkWindowPrivate *priv;
3156 g_return_if_fail (GTK_IS_WINDOW (window));
3158 priv = window->priv;
3160 if (priv->destroy_with_parent == (setting != FALSE))
3163 if (priv->destroy_with_parent)
3165 disconnect_parent_destroyed (window);
3169 connect_parent_destroyed (window);
3172 priv->destroy_with_parent = setting;
3174 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3178 * gtk_window_get_destroy_with_parent:
3179 * @window: a #GtkWindow
3181 * Returns whether the window will be destroyed with its transient parent. See
3182 * gtk_window_set_destroy_with_parent ().
3184 * Return value: %TRUE if the window will be destroyed with its transient parent.
3187 gtk_window_get_destroy_with_parent (GtkWindow *window)
3189 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3191 return window->priv->destroy_with_parent;
3195 * gtk_window_set_hide_titlebar_when_maximized:
3196 * @window: a #GtkWindow
3197 * @setting: whether to hide the titlebar when @window is maximized
3199 * If @setting is %TRUE, then @window will request that it's titlebar
3200 * should be hidden when maximized.
3201 * This is useful for windows that don't convey any information other
3202 * than the application name in the titlebar, to put the available
3203 * screen space to better use. If the underlying window system does not
3204 * support the request, the setting will not have any effect.
3209 gtk_window_set_hide_titlebar_when_maximized (GtkWindow *window,
3212 g_return_if_fail (GTK_IS_WINDOW (window));
3214 #ifdef GDK_WINDOWING_X11
3216 GdkWindow *gdk_window;
3218 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3220 if (GDK_IS_X11_WINDOW (gdk_window))
3221 gdk_x11_window_set_hide_titlebar_when_maximized (gdk_window, setting);
3225 window->priv->hide_titlebar_when_maximized = setting;
3226 g_object_notify (G_OBJECT (window), "hide-titlebar-when-maximized");
3230 * gtk_window_get_hide_titlebar_when_maximized:
3231 * @window: a #GtkWindow
3233 * Returns whether the window has requested to have its titlebar hidden
3234 * when maximized. See gtk_window_set_hide_titlebar_when_maximized ().
3236 * Return value: %TRUE if the window has requested to have its titlebar
3237 * hidden when maximized
3242 gtk_window_get_hide_titlebar_when_maximized (GtkWindow *window)
3244 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3246 return window->priv->hide_titlebar_when_maximized;
3249 static GtkWindowGeometryInfo*
3250 gtk_window_get_geometry_info (GtkWindow *window,
3253 GtkWindowPrivate *priv = window->priv;
3254 GtkWindowGeometryInfo *info;
3256 info = priv->geometry_info;
3257 if (!info && create)
3259 info = g_new0 (GtkWindowGeometryInfo, 1);
3261 info->default_width = -1;
3262 info->default_height = -1;
3263 info->resize_width = -1;
3264 info->resize_height = -1;
3265 info->initial_x = 0;
3266 info->initial_y = 0;
3267 info->initial_pos_set = FALSE;
3268 info->default_is_geometry = FALSE;
3269 info->position_constraints_changed = FALSE;
3270 info->last.configure_request.x = 0;
3271 info->last.configure_request.y = 0;
3272 info->last.configure_request.width = -1;
3273 info->last.configure_request.height = -1;
3274 info->widget = NULL;
3276 priv->geometry_info = info;
3283 * gtk_window_set_geometry_hints:
3284 * @window: a #GtkWindow
3285 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3286 * @geometry: (allow-none): struct containing geometry information or %NULL
3287 * @geom_mask: mask indicating which struct fields should be paid attention to
3289 * This function sets up hints about how a window can be resized by
3290 * the user. You can set a minimum and maximum size; allowed resize
3291 * increments (e.g. for xterm, you can only resize by the size of a
3292 * character); aspect ratios; and more. See the #GdkGeometry struct.
3296 gtk_window_set_geometry_hints (GtkWindow *window,
3297 GtkWidget *geometry_widget,
3298 GdkGeometry *geometry,
3299 GdkWindowHints geom_mask)
3301 GtkWindowGeometryInfo *info;
3303 g_return_if_fail (GTK_IS_WINDOW (window));
3304 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3306 info = gtk_window_get_geometry_info (window, TRUE);
3309 g_signal_handlers_disconnect_by_func (info->widget,
3310 gtk_widget_destroyed,
3313 info->widget = geometry_widget;
3315 g_signal_connect (geometry_widget, "destroy",
3316 G_CALLBACK (gtk_widget_destroyed),
3320 info->geometry = *geometry;
3322 /* We store gravity in priv->gravity not in the hints. */
3323 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3325 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3327 gtk_window_set_gravity (window, geometry->win_gravity);
3330 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3334 * gtk_window_set_decorated:
3335 * @window: a #GtkWindow
3336 * @setting: %TRUE to decorate the window
3338 * By default, windows are decorated with a title bar, resize
3339 * controls, etc. Some <link linkend="gtk-X11-arch">window
3340 * managers</link> allow GTK+ to disable these decorations, creating a
3341 * borderless window. If you set the decorated property to %FALSE
3342 * using this function, GTK+ will do its best to convince the window
3343 * manager not to decorate the window. Depending on the system, this
3344 * function may not have any effect when called on a window that is
3345 * already visible, so you should call it before calling gtk_widget_show().
3347 * On Windows, this function always works, since there's no window manager
3352 gtk_window_set_decorated (GtkWindow *window,
3355 GtkWindowPrivate *priv;
3356 GdkWindow *gdk_window;
3358 g_return_if_fail (GTK_IS_WINDOW (window));
3360 priv = window->priv;
3362 setting = setting != FALSE;
3364 if (setting == priv->decorated)
3367 priv->decorated = setting;
3369 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3372 if (priv->decorated)
3373 gdk_window_set_decorations (gdk_window,
3376 gdk_window_set_decorations (gdk_window,
3380 g_object_notify (G_OBJECT (window), "decorated");
3384 * gtk_window_get_decorated:
3385 * @window: a #GtkWindow
3387 * Returns whether the window has been set to have decorations
3388 * such as a title bar via gtk_window_set_decorated().
3390 * Return value: %TRUE if the window has been set to have decorations
3393 gtk_window_get_decorated (GtkWindow *window)
3395 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3397 return window->priv->decorated;
3401 * gtk_window_set_deletable:
3402 * @window: a #GtkWindow
3403 * @setting: %TRUE to decorate the window as deletable
3405 * By default, windows have a close button in the window frame. Some
3406 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3407 * disable this button. If you set the deletable property to %FALSE
3408 * using this function, GTK+ will do its best to convince the window
3409 * manager not to show a close button. Depending on the system, this
3410 * function may not have any effect when called on a window that is
3411 * already visible, so you should call it before calling gtk_widget_show().
3413 * On Windows, this function always works, since there's no window manager
3419 gtk_window_set_deletable (GtkWindow *window,
3422 GtkWindowPrivate *priv;
3423 GdkWindow *gdk_window;
3425 g_return_if_fail (GTK_IS_WINDOW (window));
3427 priv = window->priv;
3429 setting = setting != FALSE;
3431 if (setting == priv->deletable)
3434 priv->deletable = setting;
3436 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3439 if (priv->deletable)
3440 gdk_window_set_functions (gdk_window,
3443 gdk_window_set_functions (gdk_window,
3444 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3447 g_object_notify (G_OBJECT (window), "deletable");
3451 * gtk_window_get_deletable:
3452 * @window: a #GtkWindow
3454 * Returns whether the window has been set to have a close button
3455 * via gtk_window_set_deletable().
3457 * Return value: %TRUE if the window has been set to have a close button
3462 gtk_window_get_deletable (GtkWindow *window)
3464 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3466 return window->priv->deletable;
3469 static GtkWindowIconInfo*
3470 get_icon_info (GtkWindow *window)
3472 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3476 free_icon_info (GtkWindowIconInfo *info)
3478 g_free (info->icon_name);
3479 g_slice_free (GtkWindowIconInfo, info);
3483 static GtkWindowIconInfo*
3484 ensure_icon_info (GtkWindow *window)
3486 GtkWindowIconInfo *info;
3488 info = get_icon_info (window);
3492 info = g_slice_new0 (GtkWindowIconInfo);
3493 g_object_set_qdata_full (G_OBJECT (window),
3494 quark_gtk_window_icon_info,
3496 (GDestroyNotify)free_icon_info);
3503 icon_list_from_theme (GtkWidget *widget,
3508 GtkIconTheme *icon_theme;
3513 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3515 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3518 for (i = 0; sizes[i]; i++)
3521 * We need an EWMH extension to handle scalable icons
3522 * by passing their name to the WM. For now just use a
3526 icon = gtk_icon_theme_load_icon (icon_theme, name,
3529 icon = gtk_icon_theme_load_icon (icon_theme, name,
3532 list = g_list_append (list, icon);
3542 gtk_window_realize_icon (GtkWindow *window)
3544 GtkWindowPrivate *priv = window->priv;
3546 GtkWindowIconInfo *info;
3547 GdkWindow *gdk_window;
3550 widget = GTK_WIDGET (window);
3551 gdk_window = gtk_widget_get_window (widget);
3553 g_return_if_fail (gdk_window != NULL);
3555 /* no point setting an icon on override-redirect */
3556 if (priv->type == GTK_WINDOW_POPUP)
3561 info = ensure_icon_info (window);
3566 info->using_default_icon = FALSE;
3567 info->using_parent_icon = FALSE;
3568 info->using_themed_icon = FALSE;
3570 icon_list = info->icon_list;
3572 /* Look up themed icon */
3573 if (icon_list == NULL && info->icon_name)
3575 icon_list = icon_list_from_theme (widget, info->icon_name);
3577 info->using_themed_icon = TRUE;
3580 /* Inherit from transient parent */
3581 if (icon_list == NULL && priv->transient_parent)
3583 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3585 info->using_parent_icon = TRUE;
3588 /* Inherit from default */
3589 if (icon_list == NULL)
3591 icon_list = default_icon_list;
3593 info->using_default_icon = TRUE;
3596 /* Look up themed icon */
3597 if (icon_list == NULL && default_icon_name)
3599 icon_list = icon_list_from_theme (widget, default_icon_name);
3600 info->using_default_icon = TRUE;
3601 info->using_themed_icon = TRUE;
3604 info->realized = TRUE;
3606 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3608 if (info->using_themed_icon)
3610 GtkIconTheme *icon_theme;
3612 g_list_free_full (icon_list, g_object_unref);
3614 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3615 g_signal_connect (icon_theme, "changed",
3616 G_CALLBACK (update_themed_icon), window);
3621 gtk_window_unrealize_icon (GtkWindow *window)
3623 GtkWindowIconInfo *info;
3625 info = get_icon_info (window);
3630 if (info->using_themed_icon)
3632 GtkIconTheme *icon_theme;
3634 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3636 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3639 /* We don't clear the properties on the window, just figure the
3640 * window is going away.
3643 info->realized = FALSE;
3648 * gtk_window_set_icon_list:
3649 * @window: a #GtkWindow
3650 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3652 * Sets up the icon representing a #GtkWindow. The icon is used when
3653 * the window is minimized (also known as iconified). Some window
3654 * managers or desktop environments may also place it in the window
3655 * frame, or display it in other contexts.
3657 * gtk_window_set_icon_list() allows you to pass in the same icon in
3658 * several hand-drawn sizes. The list should contain the natural sizes
3659 * your icon is available in; that is, don't scale the image before
3660 * passing it to GTK+. Scaling is postponed until the last minute,
3661 * when the desired final size is known, to allow best quality.
3663 * By passing several sizes, you may improve the final image quality
3664 * of the icon, by reducing or eliminating automatic image scaling.
3666 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3667 * larger images (64x64, 128x128) if you have them.
3669 * See also gtk_window_set_default_icon_list() to set the icon
3670 * for all windows in your application in one go.
3672 * Note that transient windows (those who have been set transient for another
3673 * window using gtk_window_set_transient_for()) will inherit their
3674 * icon from their transient parent. So there's no need to explicitly
3675 * set the icon on transient windows.
3678 gtk_window_set_icon_list (GtkWindow *window,
3681 GtkWindowIconInfo *info;
3683 g_return_if_fail (GTK_IS_WINDOW (window));
3685 info = ensure_icon_info (window);
3687 if (info->icon_list == list) /* check for NULL mostly */
3690 g_list_foreach (list,
3691 (GFunc) g_object_ref, NULL);
3693 g_list_free_full (info->icon_list, g_object_unref);
3695 info->icon_list = g_list_copy (list);
3697 g_object_notify (G_OBJECT (window), "icon");
3699 gtk_window_unrealize_icon (window);
3701 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3702 gtk_window_realize_icon (window);
3704 /* We could try to update our transient children, but I don't think
3705 * it's really worth it. If we did it, the best way would probably
3706 * be to have children connect to notify::icon-list
3711 * gtk_window_get_icon_list:
3712 * @window: a #GtkWindow
3714 * Retrieves the list of icons set by gtk_window_set_icon_list().
3715 * The list is copied, but the reference count on each
3716 * member won't be incremented.
3718 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3721 gtk_window_get_icon_list (GtkWindow *window)
3723 GtkWindowIconInfo *info;
3725 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3727 info = get_icon_info (window);
3730 return g_list_copy (info->icon_list);
3736 * gtk_window_set_icon:
3737 * @window: a #GtkWindow
3738 * @icon: (allow-none): icon image, or %NULL
3740 * Sets up the icon representing a #GtkWindow. This icon is used when
3741 * the window is minimized (also known as iconified). Some window
3742 * managers or desktop environments may also place it in the window
3743 * frame, or display it in other contexts.
3745 * The icon should be provided in whatever size it was naturally
3746 * drawn; that is, don't scale the image before passing it to
3747 * GTK+. Scaling is postponed until the last minute, when the desired
3748 * final size is known, to allow best quality.
3750 * If you have your icon hand-drawn in multiple sizes, use
3751 * gtk_window_set_icon_list(). Then the best size will be used.
3753 * This function is equivalent to calling gtk_window_set_icon_list()
3754 * with a 1-element list.
3756 * See also gtk_window_set_default_icon_list() to set the icon
3757 * for all windows in your application in one go.
3760 gtk_window_set_icon (GtkWindow *window,
3765 g_return_if_fail (GTK_IS_WINDOW (window));
3766 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3771 list = g_list_append (list, icon);
3773 gtk_window_set_icon_list (window, list);
3779 update_themed_icon (GtkIconTheme *icon_theme,
3782 g_object_notify (G_OBJECT (window), "icon");
3784 gtk_window_unrealize_icon (window);
3786 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3787 gtk_window_realize_icon (window);
3791 * gtk_window_set_icon_name:
3792 * @window: a #GtkWindow
3793 * @name: (allow-none): the name of the themed icon
3795 * Sets the icon for the window from a named themed icon. See
3796 * the docs for #GtkIconTheme for more details.
3798 * Note that this has nothing to do with the WM_ICON_NAME
3799 * property which is mentioned in the ICCCM.
3804 gtk_window_set_icon_name (GtkWindow *window,
3807 GtkWindowIconInfo *info;
3810 g_return_if_fail (GTK_IS_WINDOW (window));
3812 info = ensure_icon_info (window);
3814 if (g_strcmp0 (info->icon_name, name) == 0)
3817 tmp = info->icon_name;
3818 info->icon_name = g_strdup (name);
3821 g_list_free_full (info->icon_list, g_object_unref);
3822 info->icon_list = NULL;
3824 update_themed_icon (NULL, window);
3826 g_object_notify (G_OBJECT (window), "icon-name");
3830 * gtk_window_get_icon_name:
3831 * @window: a #GtkWindow
3833 * Returns the name of the themed icon for the window,
3834 * see gtk_window_set_icon_name().
3836 * Returns: the icon name or %NULL if the window has
3842 gtk_window_get_icon_name (GtkWindow *window)
3844 GtkWindowIconInfo *info;
3846 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3848 info = ensure_icon_info (window);
3850 return info->icon_name;
3854 * gtk_window_get_icon:
3855 * @window: a #GtkWindow
3857 * Gets the value set by gtk_window_set_icon() (or if you've
3858 * called gtk_window_set_icon_list(), gets the first icon in
3861 * Return value: (transfer none): icon for window
3864 gtk_window_get_icon (GtkWindow *window)
3866 GtkWindowIconInfo *info;
3868 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3870 info = get_icon_info (window);
3871 if (info && info->icon_list)
3872 return GDK_PIXBUF (info->icon_list->data);
3877 /* Load pixbuf, printing warning on failure if error == NULL
3880 load_pixbuf_verbosely (const char *filename,
3883 GError *local_err = NULL;
3886 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3894 g_warning ("Error loading icon from file '%s':\n\t%s",
3895 filename, local_err->message);
3896 g_error_free (local_err);
3904 * gtk_window_set_icon_from_file:
3905 * @window: a #GtkWindow
3906 * @filename: (type filename): location of icon file
3907 * @err: (allow-none): location to store error, or %NULL.
3909 * Sets the icon for @window.
3910 * Warns on failure if @err is %NULL.
3912 * This function is equivalent to calling gtk_window_set_icon()
3913 * with a pixbuf created by loading the image from @filename.
3915 * Returns: %TRUE if setting the icon succeeded.
3920 gtk_window_set_icon_from_file (GtkWindow *window,
3921 const gchar *filename,
3924 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3928 gtk_window_set_icon (window, pixbuf);
3929 g_object_unref (pixbuf);
3938 * gtk_window_set_default_icon_list:
3939 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3941 * Sets an icon list to be used as fallback for windows that haven't
3942 * had gtk_window_set_icon_list() called on them to set up a
3943 * window-specific icon list. This function allows you to set up the
3944 * icon for all windows in your app at once.
3946 * See gtk_window_set_icon_list() for more details.
3950 gtk_window_set_default_icon_list (GList *list)
3954 if (list == default_icon_list)
3957 /* Update serial so we don't used cached pixmaps/masks
3959 default_icon_serial++;
3961 g_list_foreach (list,
3962 (GFunc) g_object_ref, NULL);
3964 g_list_free_full (default_icon_list, g_object_unref);
3966 default_icon_list = g_list_copy (list);
3968 /* Update all toplevels */
3969 toplevels = gtk_window_list_toplevels ();
3970 tmp_list = toplevels;
3971 while (tmp_list != NULL)
3973 GtkWindowIconInfo *info;
3974 GtkWindow *w = tmp_list->data;
3976 info = get_icon_info (w);
3977 if (info && info->using_default_icon)
3979 gtk_window_unrealize_icon (w);
3980 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3981 gtk_window_realize_icon (w);
3984 tmp_list = tmp_list->next;
3986 g_list_free (toplevels);
3990 * gtk_window_set_default_icon:
3993 * Sets an icon to be used as fallback for windows that haven't
3994 * had gtk_window_set_icon() called on them from a pixbuf.
3999 gtk_window_set_default_icon (GdkPixbuf *icon)
4003 g_return_if_fail (GDK_IS_PIXBUF (icon));
4005 list = g_list_prepend (NULL, icon);
4006 gtk_window_set_default_icon_list (list);
4011 * gtk_window_set_default_icon_name:
4012 * @name: the name of the themed icon
4014 * Sets an icon to be used as fallback for windows that haven't
4015 * had gtk_window_set_icon_list() called on them from a named
4016 * themed icon, see gtk_window_set_icon_name().
4021 gtk_window_set_default_icon_name (const gchar *name)
4026 /* Update serial so we don't used cached pixmaps/masks
4028 default_icon_serial++;
4030 g_free (default_icon_name);
4031 default_icon_name = g_strdup (name);
4033 g_list_free_full (default_icon_list, g_object_unref);
4034 default_icon_list = NULL;
4036 /* Update all toplevels */
4037 toplevels = gtk_window_list_toplevels ();
4038 tmp_list = toplevels;
4039 while (tmp_list != NULL)
4041 GtkWindowIconInfo *info;
4042 GtkWindow *w = tmp_list->data;
4044 info = get_icon_info (w);
4045 if (info && info->using_default_icon && info->using_themed_icon)
4047 gtk_window_unrealize_icon (w);
4048 if (gtk_widget_get_realized (GTK_WIDGET (w)))
4049 gtk_window_realize_icon (w);
4052 tmp_list = tmp_list->next;
4054 g_list_free (toplevels);
4058 * gtk_window_get_default_icon_name:
4060 * Returns the fallback icon name for windows that has been set
4061 * with gtk_window_set_default_icon_name(). The returned
4062 * string is owned by GTK+ and should not be modified. It
4063 * is only valid until the next call to
4064 * gtk_window_set_default_icon_name().
4066 * Returns: the fallback icon name for windows
4071 gtk_window_get_default_icon_name (void)
4073 return default_icon_name;
4077 * gtk_window_set_default_icon_from_file:
4078 * @filename: (type filename): location of icon file
4079 * @err: (allow-none): location to store error, or %NULL.
4081 * Sets an icon to be used as fallback for windows that haven't
4082 * had gtk_window_set_icon_list() called on them from a file
4083 * on disk. Warns on failure if @err is %NULL.
4085 * Returns: %TRUE if setting the icon succeeded.
4090 gtk_window_set_default_icon_from_file (const gchar *filename,
4093 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
4097 gtk_window_set_default_icon (pixbuf);
4098 g_object_unref (pixbuf);
4107 * gtk_window_get_default_icon_list:
4109 * Gets the value set by gtk_window_set_default_icon_list().
4110 * The list is a copy and should be freed with g_list_free(),
4111 * but the pixbufs in the list have not had their reference count
4114 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
4117 gtk_window_get_default_icon_list (void)
4119 return g_list_copy (default_icon_list);
4123 gtk_window_set_default_size_internal (GtkWindow *window,
4124 gboolean change_width,
4126 gboolean change_height,
4128 gboolean is_geometry)
4130 GtkWindowGeometryInfo *info;
4132 g_return_if_fail (change_width == FALSE || width >= -1);
4133 g_return_if_fail (change_height == FALSE || height >= -1);
4135 info = gtk_window_get_geometry_info (window, TRUE);
4137 g_object_freeze_notify (G_OBJECT (window));
4139 info->default_is_geometry = is_geometry != FALSE;
4149 info->default_width = width;
4151 g_object_notify (G_OBJECT (window), "default-width");
4162 info->default_height = height;
4164 g_object_notify (G_OBJECT (window), "default-height");
4167 g_object_thaw_notify (G_OBJECT (window));
4169 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4173 * gtk_window_set_default_size:
4174 * @window: a #GtkWindow
4175 * @width: width in pixels, or -1 to unset the default width
4176 * @height: height in pixels, or -1 to unset the default height
4178 * Sets the default size of a window. If the window's "natural" size
4179 * (its size request) is larger than the default, the default will be
4180 * ignored. More generally, if the default size does not obey the
4181 * geometry hints for the window (gtk_window_set_geometry_hints() can
4182 * be used to set these explicitly), the default size will be clamped
4183 * to the nearest permitted size.
4185 * Unlike gtk_widget_set_size_request(), which sets a size request for
4186 * a widget and thus would keep users from shrinking the window, this
4187 * function only sets the initial size, just as if the user had
4188 * resized the window themselves. Users can still shrink the window
4189 * again as they normally would. Setting a default size of -1 means to
4190 * use the "natural" default size (the size request of the window).
4192 * For more control over a window's initial size and how resizing works,
4193 * investigate gtk_window_set_geometry_hints().
4195 * For some uses, gtk_window_resize() is a more appropriate function.
4196 * gtk_window_resize() changes the current size of the window, rather
4197 * than the size to be used on initial display. gtk_window_resize() always
4198 * affects the window itself, not the geometry widget.
4200 * The default size of a window only affects the first time a window is
4201 * shown; if a window is hidden and re-shown, it will remember the size
4202 * it had prior to hiding, rather than using the default size.
4204 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4205 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4208 gtk_window_set_default_size (GtkWindow *window,
4212 g_return_if_fail (GTK_IS_WINDOW (window));
4213 g_return_if_fail (width >= -1);
4214 g_return_if_fail (height >= -1);
4216 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4220 * gtk_window_set_default_geometry:
4221 * @window: a #GtkWindow
4222 * @width: width in resize increments, or -1 to unset the default width
4223 * @height: height in resize increments, or -1 to unset the default height
4225 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4226 * in terms of the base size and increment set with
4227 * gtk_window_set_geometry_hints.
4232 gtk_window_set_default_geometry (GtkWindow *window,
4236 g_return_if_fail (GTK_IS_WINDOW (window));
4237 g_return_if_fail (width >= -1);
4238 g_return_if_fail (height >= -1);
4240 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4244 * gtk_window_get_default_size:
4245 * @window: a #GtkWindow
4246 * @width: (out) (allow-none): location to store the default width, or %NULL
4247 * @height: (out) (allow-none): location to store the default height, or %NULL
4249 * Gets the default size of the window. A value of -1 for the width or
4250 * height indicates that a default size has not been explicitly set
4251 * for that dimension, so the "natural" size of the window will be
4256 gtk_window_get_default_size (GtkWindow *window,
4260 GtkWindowGeometryInfo *info;
4262 g_return_if_fail (GTK_IS_WINDOW (window));
4264 info = gtk_window_get_geometry_info (window, FALSE);
4267 *width = info ? info->default_width : -1;
4270 *height = info ? info->default_height : -1;
4274 * gtk_window_resize:
4275 * @window: a #GtkWindow
4276 * @width: width in pixels to resize the window to
4277 * @height: height in pixels to resize the window to
4279 * Resizes the window as if the user had done so, obeying geometry
4280 * constraints. The default geometry constraint is that windows may
4281 * not be smaller than their size request; to override this
4282 * constraint, call gtk_widget_set_size_request() to set the window's
4283 * request to a smaller value.
4285 * If gtk_window_resize() is called before showing a window for the
4286 * first time, it overrides any default size set with
4287 * gtk_window_set_default_size().
4289 * Windows may not be resized smaller than 1 by 1 pixels.
4293 gtk_window_resize (GtkWindow *window,
4297 GtkWindowGeometryInfo *info;
4299 g_return_if_fail (GTK_IS_WINDOW (window));
4300 g_return_if_fail (width > 0);
4301 g_return_if_fail (height > 0);
4303 info = gtk_window_get_geometry_info (window, TRUE);
4305 info->resize_width = width;
4306 info->resize_height = height;
4307 info->resize_is_geometry = FALSE;
4309 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4313 * gtk_window_resize_to_geometry:
4314 * @window: a #GtkWindow
4315 * @width: width in resize increments to resize the window to
4316 * @height: height in resize increments to resize the window to
4318 * Like gtk_window_resize(), but @width and @height are interpreted
4319 * in terms of the base size and increment set with
4320 * gtk_window_set_geometry_hints.
4325 gtk_window_resize_to_geometry (GtkWindow *window,
4329 GtkWindowGeometryInfo *info;
4331 g_return_if_fail (GTK_IS_WINDOW (window));
4332 g_return_if_fail (width > 0);
4333 g_return_if_fail (height > 0);
4335 info = gtk_window_get_geometry_info (window, TRUE);
4337 info->resize_width = width;
4338 info->resize_height = height;
4339 info->resize_is_geometry = TRUE;
4341 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4345 * gtk_window_get_size:
4346 * @window: a #GtkWindow
4347 * @width: (out) (allow-none): return location for width, or %NULL
4348 * @height: (out) (allow-none): return location for height, or %NULL
4350 * Obtains the current size of @window. If @window is not onscreen,
4351 * it returns the size GTK+ will suggest to the <link
4352 * linkend="gtk-X11-arch">window manager</link> for the initial window
4353 * size (but this is not reliably the same as the size the window
4354 * manager will actually select). The size obtained by
4355 * gtk_window_get_size() is the last size received in a
4356 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4357 * rather than querying the X server for the size. As a result, if you
4358 * call gtk_window_resize() then immediately call
4359 * gtk_window_get_size(), the size won't have taken effect yet. After
4360 * the window manager processes the resize request, GTK+ receives
4361 * notification that the size has changed via a configure event, and
4362 * the size of the window gets updated.
4364 * Note 1: Nearly any use of this function creates a race condition,
4365 * because the size of the window may change between the time that you
4366 * get the size and the time that you perform some action assuming
4367 * that size is the current size. To avoid race conditions, connect to
4368 * "configure-event" on the window and adjust your size-dependent
4369 * state to match the size delivered in the #GdkEventConfigure.
4371 * Note 2: The returned size does <emphasis>not</emphasis> include the
4372 * size of the window manager decorations (aka the window frame or
4373 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4374 * method of determining their size.
4376 * Note 3: If you are getting a window size in order to position
4377 * the window onscreen, there may be a better way. The preferred
4378 * way is to simply set the window's semantic type with
4379 * gtk_window_set_type_hint(), which allows the window manager to
4380 * e.g. center dialogs. Also, if you set the transient parent of
4381 * dialogs with gtk_window_set_transient_for() window managers
4382 * will often center the dialog over its parent window. It's
4383 * much preferred to let the window manager handle these
4384 * things rather than doing it yourself, because all apps will
4385 * behave consistently and according to user prefs if the window
4386 * manager handles it. Also, the window manager can take the size
4387 * of the window decorations/border into account, while your
4388 * application cannot.
4390 * In any case, if you insist on application-specified window
4391 * positioning, there's <emphasis>still</emphasis> a better way than
4392 * doing it yourself - gtk_window_set_position() will frequently
4393 * handle the details for you.
4397 gtk_window_get_size (GtkWindow *window,
4403 g_return_if_fail (GTK_IS_WINDOW (window));
4405 if (width == NULL && height == NULL)
4408 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4410 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4411 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4415 GdkRectangle configure_request;
4417 gtk_window_compute_configure_request (window,
4421 w = configure_request.width;
4422 h = configure_request.height;
4433 * @window: a #GtkWindow
4434 * @x: X coordinate to move window to
4435 * @y: Y coordinate to move window to
4437 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4438 * @window to the given position. Window managers are free to ignore
4439 * this; most window managers ignore requests for initial window
4440 * positions (instead using a user-defined placement algorithm) and
4441 * honor requests after the window has already been shown.
4443 * Note: the position is the position of the gravity-determined
4444 * reference point for the window. The gravity determines two things:
4445 * first, the location of the reference point in root window
4446 * coordinates; and second, which point on the window is positioned at
4447 * the reference point.
4449 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4450 * point is simply the @x, @y supplied to gtk_window_move(). The
4451 * top-left corner of the window decorations (aka window frame or
4452 * border) will be placed at @x, @y. Therefore, to position a window
4453 * at the top left of the screen, you want to use the default gravity
4454 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4456 * To position a window at the bottom right corner of the screen, you
4457 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4458 * point is at @x + the window width and @y + the window height, and
4459 * the bottom-right corner of the window border will be placed at that
4460 * reference point. So, to place a window in the bottom right corner
4461 * you would first set gravity to south east, then write:
4462 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4463 * gdk_screen_height () - window_height)</literal> (note that this
4464 * example does not take multi-head scenarios into account).
4466 * The Extended Window Manager Hints specification at <ulink
4467 * url="http://www.freedesktop.org/Standards/wm-spec">
4468 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4469 * nice table of gravities in the "implementation notes" section.
4471 * The gtk_window_get_position() documentation may also be relevant.
4474 gtk_window_move (GtkWindow *window,
4478 GtkWindowGeometryInfo *info;
4481 g_return_if_fail (GTK_IS_WINDOW (window));
4483 widget = GTK_WIDGET (window);
4485 info = gtk_window_get_geometry_info (window, TRUE);
4487 if (gtk_widget_get_mapped (widget))
4489 GtkAllocation allocation;
4491 gtk_widget_get_allocation (widget, &allocation);
4493 /* we have now sent a request with this position
4494 * with currently-active constraints, so toggle flag.
4496 info->position_constraints_changed = FALSE;
4498 /* we only constrain if mapped - if not mapped,
4499 * then gtk_window_compute_configure_request()
4500 * will apply the constraints later, and we
4501 * don't want to lose information about
4502 * what position the user set before then.
4503 * i.e. if you do a move() then turn off POS_CENTER
4504 * then show the window, your move() will work.
4506 gtk_window_constrain_position (window,
4507 allocation.width, allocation.height,
4510 /* Note that this request doesn't go through our standard request
4511 * framework, e.g. doesn't increment configure_request_count,
4512 * doesn't set info->last, etc.; that's because
4513 * we don't save the info needed to arrive at this same request
4516 * To gtk_window_move_resize(), this will end up looking exactly
4517 * the same as the position being changed by the window
4520 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4524 /* Save this position to apply on mapping */
4525 info->initial_x = x;
4526 info->initial_y = y;
4527 info->initial_pos_set = TRUE;
4532 * gtk_window_get_position:
4533 * @window: a #GtkWindow
4534 * @root_x: (out) (allow-none): return location for X coordinate of
4535 * gravity-determined reference point, or %NULL
4536 * @root_y: (out) (allow-none): return location for Y coordinate of
4537 * gravity-determined reference point, or %NULL
4539 * This function returns the position you need to pass to
4540 * gtk_window_move() to keep @window in its current position.
4541 * This means that the meaning of the returned value varies with
4542 * window gravity. See gtk_window_move() for more details.
4544 * If you haven't changed the window gravity, its gravity will be
4545 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4546 * gets the position of the top-left corner of the window manager
4547 * frame for the window. gtk_window_move() sets the position of this
4548 * same top-left corner.
4550 * gtk_window_get_position() is not 100% reliable because the X Window System
4551 * does not specify a way to obtain the geometry of the
4552 * decorations placed on a window by the window manager.
4553 * Thus GTK+ is using a "best guess" that works with most
4556 * Moreover, nearly all window managers are historically broken with
4557 * respect to their handling of window gravity. So moving a window to
4558 * its current position as returned by gtk_window_get_position() tends
4559 * to result in moving the window slightly. Window managers are
4560 * slowly getting better over time.
4562 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4563 * frame is not relevant, and thus gtk_window_get_position() will
4564 * always produce accurate results. However you can't use static
4565 * gravity to do things like place a window in a corner of the screen,
4566 * because static gravity ignores the window manager decorations.
4568 * If you are saving and restoring your application's window
4569 * positions, you should know that it's impossible for applications to
4570 * do this without getting it somewhat wrong because applications do
4571 * not have sufficient knowledge of window manager state. The Correct
4572 * Mechanism is to support the session management protocol (see the
4573 * "GnomeClient" object in the GNOME libraries for example) and allow
4574 * the window manager to save your window sizes and positions.
4579 gtk_window_get_position (GtkWindow *window,
4583 GtkWindowPrivate *priv;
4585 GdkWindow *gdk_window;
4587 g_return_if_fail (GTK_IS_WINDOW (window));
4589 priv = window->priv;
4590 widget = GTK_WIDGET (window);
4591 gdk_window = gtk_widget_get_window (widget);
4593 if (priv->gravity == GDK_GRAVITY_STATIC)
4595 if (gtk_widget_get_mapped (widget))
4597 /* This does a server round-trip, which is sort of wrong;
4598 * but a server round-trip is inevitable for
4599 * gdk_window_get_frame_extents() in the usual
4600 * NorthWestGravity case below, so not sure what else to
4601 * do. We should likely be consistent about whether we get
4602 * the client-side info or the server-side info.
4604 gdk_window_get_origin (gdk_window, root_x, root_y);
4608 GdkRectangle configure_request;
4610 gtk_window_compute_configure_request (window,
4614 *root_x = configure_request.x;
4615 *root_y = configure_request.y;
4620 GdkRectangle frame_extents;
4625 if (gtk_widget_get_mapped (widget))
4627 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4628 x = frame_extents.x;
4629 y = frame_extents.y;
4630 gtk_window_get_size (window, &w, &h);
4634 /* We just say the frame has 0 size on all sides.
4635 * Not sure what else to do.
4637 gtk_window_compute_configure_request (window,
4640 x = frame_extents.x;
4641 y = frame_extents.y;
4642 w = frame_extents.width;
4643 h = frame_extents.height;
4646 switch (priv->gravity)
4648 case GDK_GRAVITY_NORTH:
4649 case GDK_GRAVITY_CENTER:
4650 case GDK_GRAVITY_SOUTH:
4651 /* Find center of frame. */
4652 x += frame_extents.width / 2;
4653 /* Center client window on that point. */
4657 case GDK_GRAVITY_SOUTH_EAST:
4658 case GDK_GRAVITY_EAST:
4659 case GDK_GRAVITY_NORTH_EAST:
4660 /* Find right edge of frame */
4661 x += frame_extents.width;
4662 /* Align left edge of client at that point. */
4669 switch (priv->gravity)
4671 case GDK_GRAVITY_WEST:
4672 case GDK_GRAVITY_CENTER:
4673 case GDK_GRAVITY_EAST:
4674 /* Find center of frame. */
4675 y += frame_extents.height / 2;
4676 /* Center client window there. */
4679 case GDK_GRAVITY_SOUTH_WEST:
4680 case GDK_GRAVITY_SOUTH:
4681 case GDK_GRAVITY_SOUTH_EAST:
4682 /* Find south edge of frame */
4683 y += frame_extents.height;
4684 /* Place bottom edge of client there */
4699 * gtk_window_reshow_with_initial_size:
4700 * @window: a #GtkWindow
4702 * Hides @window, then reshows it, resetting the
4703 * default size and position of the window. Used
4704 * by GUI builders only.
4707 gtk_window_reshow_with_initial_size (GtkWindow *window)
4711 g_return_if_fail (GTK_IS_WINDOW (window));
4713 widget = GTK_WIDGET (window);
4715 gtk_widget_hide (widget);
4716 gtk_widget_unrealize (widget);
4717 gtk_widget_show (widget);
4721 gtk_window_destroy (GtkWidget *widget)
4723 GtkWindow *window = GTK_WINDOW (widget);
4724 GtkWindowPrivate *priv = window->priv;
4726 gtk_window_release_application (window);
4728 toplevel_list = g_slist_remove (toplevel_list, window);
4730 if (priv->transient_parent)
4731 gtk_window_set_transient_for (window, NULL);
4733 remove_attach_widget (GTK_WINDOW (widget));
4735 /* frees the icons */
4736 gtk_window_set_icon_list (window, NULL);
4738 if (priv->has_user_ref_count)
4740 priv->has_user_ref_count = FALSE;
4741 g_object_unref (window);
4745 gtk_window_group_remove_window (priv->group, window);
4747 gtk_window_free_key_hash (window);
4749 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4753 gtk_window_finalize (GObject *object)
4755 GtkWindow *window = GTK_WINDOW (object);
4756 GtkWindowPrivate *priv = window->priv;
4757 GtkMnemonicHash *mnemonic_hash;
4759 g_free (priv->title);
4760 g_free (priv->wmclass_name);
4761 g_free (priv->wmclass_class);
4762 g_free (priv->wm_role);
4763 gtk_window_release_application (window);
4765 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4767 _gtk_mnemonic_hash_free (mnemonic_hash);
4769 if (priv->geometry_info)
4771 if (priv->geometry_info->widget)
4772 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4773 gtk_widget_destroyed,
4774 &priv->geometry_info->widget);
4775 g_free (priv->geometry_info);
4778 if (priv->keys_changed_handler)
4780 g_source_remove (priv->keys_changed_handler);
4781 priv->keys_changed_handler = 0;
4785 g_signal_handlers_disconnect_by_func (priv->screen,
4786 gtk_window_on_composited_changed, window);
4788 g_free (priv->startup_id);
4790 if (priv->auto_mnemonics_timeout_id)
4792 g_source_remove (priv->auto_mnemonics_timeout_id);
4793 priv->auto_mnemonics_timeout_id = 0;
4796 #ifdef GDK_WINDOWING_X11
4797 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4798 gtk_window_on_theme_variant_changed,
4802 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4806 gtk_window_show (GtkWidget *widget)
4808 GtkWindow *window = GTK_WINDOW (widget);
4809 GtkWindowPrivate *priv = window->priv;
4810 GtkContainer *container = GTK_CONTAINER (window);
4812 gboolean need_resize;
4815 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4817 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4821 _gtk_widget_set_visible_flag (widget, TRUE);
4823 need_resize = _gtk_widget_get_alloc_needed (widget) || !gtk_widget_get_realized (widget);
4825 empty = _gtk_bitmask_new ();
4826 _gtk_style_context_validate (gtk_widget_get_style_context (widget),
4827 g_get_monotonic_time (),
4830 _gtk_bitmask_free (empty);
4834 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4835 GtkAllocation allocation = { 0, 0 };
4836 GdkRectangle configure_request;
4837 GdkGeometry new_geometry;
4839 gboolean was_realized;
4841 /* We are going to go ahead and perform this configure request
4842 * and then emulate a configure notify by going ahead and
4843 * doing a size allocate. Sort of a synchronous
4844 * mini-copy of gtk_window_move_resize() here.
4846 gtk_window_compute_configure_request (window,
4851 /* We update this because we are going to go ahead
4852 * and gdk_window_resize() below, rather than
4855 info->last.configure_request.width = configure_request.width;
4856 info->last.configure_request.height = configure_request.height;
4858 /* and allocate the window - this is normally done
4859 * in move_resize in response to configure notify
4861 allocation.width = configure_request.width;
4862 allocation.height = configure_request.height;
4863 gtk_widget_size_allocate (widget, &allocation);
4865 /* Then we guarantee we have a realize */
4866 was_realized = FALSE;
4867 if (!gtk_widget_get_realized (widget))
4869 gtk_widget_realize (widget);
4870 was_realized = TRUE;
4873 /* We only send configure request if we didn't just finish
4874 * creating the window; if we just created the window
4875 * then we created it with widget->allocation anyhow.
4878 gdk_window_move_resize (gtk_widget_get_window (widget),
4879 configure_request.x,
4880 configure_request.y,
4881 configure_request.width,
4882 configure_request.height);
4885 gtk_container_check_resize (container);
4887 gtk_widget_map (widget);
4889 /* Try to make sure that we have some focused widget
4891 #ifdef GDK_WINDOWING_X11
4892 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4893 GTK_IS_PLUG (window);
4897 if (!priv->focus_widget && !is_plug)
4898 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4901 gtk_grab_add (widget);
4905 gtk_window_hide (GtkWidget *widget)
4907 GtkWindow *window = GTK_WINDOW (widget);
4908 GtkWindowPrivate *priv = window->priv;
4910 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4912 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4916 _gtk_widget_set_visible_flag (widget, FALSE);
4917 gtk_widget_unmap (widget);
4920 gtk_grab_remove (widget);
4924 gtk_window_map (GtkWidget *widget)
4927 GtkWindow *window = GTK_WINDOW (widget);
4928 GtkWindowPrivate *priv = window->priv;
4929 GdkWindow *gdk_window;
4930 gboolean auto_mnemonics;
4931 GtkPolicyType visible_focus;
4933 if (!gtk_widget_is_toplevel (widget))
4935 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4939 gtk_widget_set_mapped (widget, TRUE);
4941 child = gtk_bin_get_child (&(window->bin));
4943 gtk_widget_get_visible (child) &&
4944 !gtk_widget_get_mapped (child))
4945 gtk_widget_map (child);
4947 gdk_window = gtk_widget_get_window (widget);
4949 if (priv->maximize_initially)
4950 gdk_window_maximize (gdk_window);
4952 gdk_window_unmaximize (gdk_window);
4954 if (priv->stick_initially)
4955 gdk_window_stick (gdk_window);
4957 gdk_window_unstick (gdk_window);
4959 if (priv->iconify_initially)
4960 gdk_window_iconify (gdk_window);
4962 gdk_window_deiconify (gdk_window);
4964 if (priv->fullscreen_initially)
4965 gdk_window_fullscreen (gdk_window);
4967 gdk_window_unfullscreen (gdk_window);
4969 gdk_window_set_keep_above (gdk_window, priv->above_initially);
4971 gdk_window_set_keep_below (gdk_window, priv->below_initially);
4973 if (priv->type == GTK_WINDOW_TOPLEVEL)
4975 gtk_window_set_theme_variant (window);
4976 gtk_window_set_hide_titlebar_when_maximized (window,
4977 priv->hide_titlebar_when_maximized);
4980 /* No longer use the default settings */
4981 priv->need_default_size = FALSE;
4982 priv->need_default_position = FALSE;
4984 if (priv->reset_type_hint)
4986 /* We should only reset the type hint when the application
4987 * used gtk_window_set_type_hint() to change the hint.
4988 * Some applications use X directly to change the properties;
4989 * in that case, we shouldn't overwrite what they did.
4991 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4992 priv->reset_type_hint = FALSE;
4995 gdk_window_show (gdk_window);
4997 if (priv->grip_window)
4998 gdk_window_show (priv->grip_window);
5000 if (!disable_startup_notification)
5002 /* Do we have a custom startup-notification id? */
5003 if (priv->startup_id != NULL)
5005 /* Make sure we have a "real" id */
5006 if (!startup_id_is_fake (priv->startup_id))
5007 gdk_notify_startup_complete_with_id (priv->startup_id);
5009 g_free (priv->startup_id);
5010 priv->startup_id = NULL;
5012 else if (!sent_startup_notification)
5014 sent_startup_notification = TRUE;
5015 gdk_notify_startup_complete ();
5019 /* if auto-mnemonics is enabled and mnemonics visible is not already set
5020 * (as in the case of popup menus), then hide mnemonics initially
5022 g_object_get (gtk_widget_get_settings (widget),
5023 "gtk-auto-mnemonics", &auto_mnemonics,
5024 "gtk-visible-focus", &visible_focus,
5027 if (auto_mnemonics && !priv->mnemonics_visible_set)
5028 gtk_window_set_mnemonics_visible (window, FALSE);
5030 /* inherit from transient parent, so that a dialog that is
5031 * opened via keynav shows focus initially
5033 if (priv->transient_parent)
5034 gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
5036 gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
5040 gtk_window_map_event (GtkWidget *widget,
5043 if (!gtk_widget_get_mapped (widget))
5045 /* we should be be unmapped, but are getting a MapEvent, this may happen
5046 * to toplevel XWindows if mapping was intercepted by a window manager
5047 * and an unmap request occoured while the MapRequestEvent was still
5048 * being handled. we work around this situaiton here by re-requesting
5049 * the window being unmapped. more details can be found in:
5050 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
5052 gdk_window_hide (gtk_widget_get_window (widget));
5058 gtk_window_unmap (GtkWidget *widget)
5060 GtkWindow *window = GTK_WINDOW (widget);
5061 GtkWindowPrivate *priv = window->priv;
5063 GtkWindowGeometryInfo *info;
5064 GdkWindow *gdk_window;
5065 GdkWindowState state;
5067 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5069 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
5073 gdk_window = gtk_widget_get_window (widget);
5075 gtk_widget_set_mapped (widget, FALSE);
5076 gdk_window_withdraw (gdk_window);
5078 priv->configure_request_count = 0;
5079 priv->configure_notify_received = FALSE;
5081 /* on unmap, we reset the default positioning of the window,
5082 * so it's placed again, but we don't reset the default
5083 * size of the window, so it's remembered.
5085 priv->need_default_position = TRUE;
5087 info = gtk_window_get_geometry_info (window, FALSE);
5090 info->initial_pos_set = FALSE;
5091 info->position_constraints_changed = FALSE;
5094 state = gdk_window_get_state (gdk_window);
5095 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
5096 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
5097 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
5098 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
5099 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
5101 child = gtk_bin_get_child (&(window->bin));
5103 gtk_widget_unmap (child);
5106 /* (Note: Replace "size" with "width" or "height". Also, the request
5107 * mode is honoured.)
5108 * For selecting the default window size, the following conditions
5109 * should hold (in order of importance):
5110 * - the size is not below the minimum size
5111 * Windows cannot be resized below their minimum size, so we must
5112 * ensure we don't do that either.
5113 * - the size is not above the natural size
5114 * It seems weird to allocate more than this in an initial guess.
5115 * - the size does not exceed that of a maximized window
5116 * We want to see the whole window after all.
5117 * (Note that this may not be possible to achieve due to imperfect
5118 * information from the windowing system.)
5121 /* We use these for now to not make windows too big by accident. Note
5122 * that we still clamp these numbers by screen size. Also note that
5123 * minimum size still overrides this. So keep your windows small! :)
5125 #define MAX_DEFAULT_WINDOW_WIDTH 640
5126 #define MAX_DEFAULT_WINDOW_HEIGHT 480
5129 gtk_window_guess_default_size (GtkWindow *window,
5133 GtkWidget *widget = GTK_WIDGET (window);
5135 int minimum, natural;
5137 screen = gtk_widget_get_screen (widget);
5139 *width = gdk_screen_get_width (screen);
5140 *height = gdk_screen_get_height (screen);
5142 if (*width >= *height)
5145 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
5146 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
5151 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
5152 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
5155 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
5157 gtk_widget_get_preferred_height (widget, &minimum, &natural);
5158 *height = MAX (minimum, MIN (*height, natural));
5160 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
5161 *width = MAX (minimum, MIN (*width, natural));
5163 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
5165 gtk_widget_get_preferred_width (widget, &minimum, &natural);
5166 *width = MAX (minimum, MIN (*width, natural));
5168 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
5169 *height = MAX (minimum, MIN (*height, natural));
5174 gtk_window_realize (GtkWidget *widget)
5176 GtkAllocation allocation;
5178 GdkWindow *parent_window;
5179 GdkWindow *gdk_window;
5180 GdkWindowAttr attributes;
5181 gint attributes_mask;
5182 GtkWindowPrivate *priv;
5183 GtkStyleContext *context;
5185 window = GTK_WINDOW (widget);
5186 priv = window->priv;
5188 gtk_widget_get_allocation (widget, &allocation);
5190 if (gtk_widget_get_parent_window (widget))
5192 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
5194 gtk_widget_set_realized (widget, TRUE);
5196 attributes.x = allocation.x;
5197 attributes.y = allocation.y;
5198 attributes.width = allocation.width;
5199 attributes.height = allocation.height;
5200 attributes.window_type = GDK_WINDOW_CHILD;
5202 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
5204 attributes.visual = gtk_widget_get_visual (widget);
5205 attributes.wclass = GDK_INPUT_OUTPUT;
5207 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
5209 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
5210 &attributes, attributes_mask);
5211 gtk_widget_set_window (widget, gdk_window);
5212 gdk_window_set_user_data (gdk_window, widget);
5214 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
5216 gdk_window_enable_synchronized_configure (gdk_window);
5220 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5222 /* ensure widget tree is properly size allocated */
5223 if (allocation.x == -1 &&
5224 allocation.y == -1 &&
5225 allocation.width == 1 &&
5226 allocation.height == 1)
5232 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5233 if (allocation.width == 0 || allocation.height == 0)
5235 /* non-empty window */
5236 allocation.width = 200;
5237 allocation.height = 200;
5239 gtk_widget_size_allocate (widget, &allocation);
5241 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5243 g_return_if_fail (!gtk_widget_get_realized (widget));
5246 gtk_widget_set_realized (widget, TRUE);
5250 case GTK_WINDOW_TOPLEVEL:
5251 attributes.window_type = GDK_WINDOW_TOPLEVEL;
5253 case GTK_WINDOW_POPUP:
5254 attributes.window_type = GDK_WINDOW_TEMP;
5257 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5261 attributes.title = priv->title;
5262 attributes.wmclass_name = priv->wmclass_name;
5263 attributes.wmclass_class = priv->wmclass_class;
5264 attributes.wclass = GDK_INPUT_OUTPUT;
5265 attributes.visual = gtk_widget_get_visual (widget);
5267 attributes_mask = 0;
5268 parent_window = gtk_widget_get_root_window (widget);
5270 gtk_widget_get_allocation (widget, &allocation);
5271 attributes.width = allocation.width;
5272 attributes.height = allocation.height;
5273 attributes.event_mask = gtk_widget_get_events (widget);
5274 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5275 GDK_KEY_PRESS_MASK |
5276 GDK_KEY_RELEASE_MASK |
5277 GDK_ENTER_NOTIFY_MASK |
5278 GDK_LEAVE_NOTIFY_MASK |
5279 GDK_FOCUS_CHANGE_MASK |
5280 GDK_STRUCTURE_MASK);
5281 attributes.type_hint = priv->type_hint;
5283 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5284 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5285 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5287 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5288 gtk_widget_set_window (widget, gdk_window);
5290 if (priv->opacity_set)
5291 gdk_window_set_opacity (gdk_window, priv->opacity);
5293 gdk_window_enable_synchronized_configure (gdk_window);
5295 gdk_window_set_user_data (gdk_window, window);
5297 context = gtk_widget_get_style_context (widget);
5298 gtk_style_context_set_background (context, gdk_window);
5301 if (priv->transient_parent &&
5302 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5303 gdk_window_set_transient_for (gdk_window,
5304 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5307 gdk_window_set_role (gdk_window, priv->wm_role);
5309 if (!priv->decorated)
5310 gdk_window_set_decorations (gdk_window, 0);
5312 if (!priv->deletable)
5313 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5315 if (gtk_window_get_skip_pager_hint (window))
5316 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5318 if (gtk_window_get_skip_taskbar_hint (window))
5319 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5321 if (gtk_window_get_accept_focus (window))
5322 gdk_window_set_accept_focus (gdk_window, TRUE);
5324 gdk_window_set_accept_focus (gdk_window, FALSE);
5326 if (gtk_window_get_focus_on_map (window))
5327 gdk_window_set_focus_on_map (gdk_window, TRUE);
5329 gdk_window_set_focus_on_map (gdk_window, FALSE);
5332 gdk_window_set_modal_hint (gdk_window, TRUE);
5334 gdk_window_set_modal_hint (gdk_window, FALSE);
5336 if (priv->startup_id)
5338 #ifdef GDK_WINDOWING_X11
5339 if (GDK_IS_X11_WINDOW (gdk_window))
5341 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5342 if (timestamp != GDK_CURRENT_TIME)
5343 gdk_x11_window_set_user_time (gdk_window, timestamp);
5346 if (!startup_id_is_fake (priv->startup_id))
5347 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5350 #ifdef GDK_WINDOWING_X11
5351 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5353 if (GDK_IS_X11_WINDOW (gdk_window))
5354 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5359 gtk_window_realize_icon (window);
5361 if (priv->has_resize_grip)
5362 resize_grip_create_window (window);
5366 gtk_window_unrealize (GtkWidget *widget)
5368 GtkWindow *window = GTK_WINDOW (widget);
5369 GtkWindowPrivate *priv = window->priv;
5370 GtkWindowGeometryInfo *info;
5372 /* On unrealize, we reset the size of the window such
5373 * that we will re-apply the default sizing stuff
5374 * next time we show the window.
5376 * Default positioning is reset on unmap, instead of unrealize.
5378 priv->need_default_size = TRUE;
5379 info = gtk_window_get_geometry_info (window, FALSE);
5382 info->resize_width = -1;
5383 info->resize_height = -1;
5384 info->last.configure_request.x = 0;
5385 info->last.configure_request.y = 0;
5386 info->last.configure_request.width = -1;
5387 info->last.configure_request.height = -1;
5388 /* be sure we reset geom hints on re-realize */
5389 info->last.flags = 0;
5393 gtk_window_unrealize_icon (window);
5395 if (priv->grip_window != NULL)
5396 resize_grip_destroy_window (window);
5398 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5401 static GtkJunctionSides
5402 get_grip_junction (GtkWidget *widget)
5404 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5405 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5407 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5411 get_drag_edge (GtkWidget *widget,
5412 GdkWindowEdge *edge)
5414 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5415 gboolean hresizable;
5416 gboolean vresizable;
5417 GtkTextDirection dir;
5418 GtkWindowGeometryInfo *info;
5423 info = priv->geometry_info;
5426 GdkWindowHints flags = info->last.flags;
5427 GdkGeometry *geometry = &info->last.geometry;
5429 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5431 hresizable = geometry->min_width < geometry->max_width;
5432 vresizable = geometry->min_height < geometry->max_height;
5436 dir = gtk_widget_get_direction (widget);
5438 if (hresizable && vresizable)
5439 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5440 else if (hresizable)
5441 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5442 else if (vresizable)
5443 *edge = GDK_WINDOW_EDGE_SOUTH;
5451 set_grip_cursor (GtkWindow *window)
5453 GtkWidget *widget = GTK_WIDGET (window);
5454 GtkWindowPrivate *priv = window->priv;
5456 if (priv->grip_window == NULL)
5459 if (gtk_widget_is_sensitive (widget))
5462 GdkDisplay *display;
5463 GdkCursorType cursor_type;
5466 cursor_type = GDK_LEFT_PTR;
5468 if (get_drag_edge (widget, &edge))
5472 case GDK_WINDOW_EDGE_EAST:
5473 cursor_type = GDK_RIGHT_SIDE;
5475 case GDK_WINDOW_EDGE_SOUTH_EAST:
5476 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5478 case GDK_WINDOW_EDGE_SOUTH:
5479 cursor_type = GDK_BOTTOM_SIDE;
5481 case GDK_WINDOW_EDGE_SOUTH_WEST:
5482 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5484 case GDK_WINDOW_EDGE_WEST:
5485 cursor_type = GDK_LEFT_SIDE;
5491 display = gtk_widget_get_display (widget);
5492 cursor = gdk_cursor_new_for_display (display, cursor_type);
5493 gdk_window_set_cursor (priv->grip_window, cursor);
5494 g_object_unref (cursor);
5497 gdk_window_set_cursor (priv->grip_window, NULL);
5501 set_grip_shape (GtkWindow *window)
5503 GtkWindowPrivate *priv = window->priv;
5504 cairo_region_t *region;
5505 cairo_surface_t *surface;
5507 double width, height;
5509 if (priv->grip_window == NULL)
5512 width = gdk_window_get_width (priv->grip_window);
5513 height = gdk_window_get_height (priv->grip_window);
5514 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
5516 cr = cairo_create (surface);
5517 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5519 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5520 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5522 cairo_move_to (cr, width, 0.0);
5523 cairo_line_to (cr, width, height);
5524 cairo_line_to (cr, 0.0, height);
5528 cairo_move_to (cr, 0.0, 0.0);
5529 cairo_line_to (cr, width, height);
5530 cairo_line_to (cr, 0.0, height);
5532 cairo_close_path (cr);
5535 region = gdk_cairo_region_create_from_surface (surface);
5536 cairo_surface_destroy (surface);
5538 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5539 cairo_region_destroy (region);
5543 set_grip_position (GtkWindow *window)
5545 GtkWindowPrivate *priv = window->priv;
5548 if (priv->grip_window == NULL)
5551 gtk_window_get_resize_grip_area (window, &rect);
5552 gdk_window_raise (priv->grip_window);
5553 gdk_window_move_resize (priv->grip_window,
5555 rect.width, rect.height);
5558 /* _gtk_window_set_allocation:
5559 * @window: a #GtkWindow
5560 * @allocation: the new allocation
5562 * This function is like gtk_widget_set_allocation()
5563 * but does the necessary extra work to update
5564 * the resize grip positioning, etc.
5566 * Call this instead of gtk_widget_set_allocation()
5567 * when overriding ::size_allocate in a GtkWindow
5568 * subclass without chaining up.
5571 _gtk_window_set_allocation (GtkWindow *window,
5572 GtkAllocation *allocation)
5574 GtkWidget *widget = (GtkWidget *)window;
5576 gtk_widget_set_allocation (widget, allocation);
5578 if (gtk_widget_get_realized (widget))
5580 /* If it's not a toplevel we're embedded, we need to resize
5581 * the window's window and skip the grip.
5583 if (!gtk_widget_is_toplevel (widget))
5585 gdk_window_move_resize (gtk_widget_get_window (widget),
5586 allocation->x, allocation->y,
5587 allocation->width, allocation->height);
5591 update_grip_visibility (window);
5592 set_grip_position (window);
5598 gtk_window_size_allocate (GtkWidget *widget,
5599 GtkAllocation *allocation)
5601 GtkWindow *window = GTK_WINDOW (widget);
5602 GtkAllocation child_allocation;
5606 _gtk_window_set_allocation (window, allocation);
5608 child = gtk_bin_get_child (&(window->bin));
5609 if (child && gtk_widget_get_visible (child))
5611 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5612 child_allocation.x = border_width;
5613 child_allocation.y = border_width;
5614 child_allocation.width = MAX (1, allocation->width - border_width * 2);
5615 child_allocation.height = MAX (1, allocation->height - border_width * 2);
5617 gtk_widget_size_allocate (child, &child_allocation);
5622 gtk_window_configure_event (GtkWidget *widget,
5623 GdkEventConfigure *event)
5625 GtkAllocation allocation;
5626 GtkWindow *window = GTK_WINDOW (widget);
5627 GtkWindowPrivate *priv = window->priv;
5628 gboolean expected_reply = priv->configure_request_count > 0;
5630 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5632 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5633 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5635 gdk_window_configure_finished (gtk_widget_get_window (widget));
5639 /* priv->configure_request_count incremented for each
5640 * configure request, and decremented to a min of 0 for
5641 * each configure notify.
5643 * All it means is that we know we will get at least
5644 * priv->configure_request_count more configure notifies.
5645 * We could get more configure notifies than that; some
5646 * of the configure notifies we get may be unrelated to
5647 * the configure requests. But we will get at least
5648 * priv->configure_request_count notifies.
5651 if (priv->configure_request_count > 0)
5653 priv->configure_request_count -= 1;
5654 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5657 /* As an optimization, we avoid a resize when possible.
5659 * The only times we can avoid a resize are:
5660 * - we know only the position changed, not the size
5661 * - we know we have made more requests and so will get more
5662 * notifies and can wait to resize when we get them
5664 gtk_widget_get_allocation (widget, &allocation);
5665 if (!expected_reply &&
5666 (allocation.width == event->width &&
5667 allocation.height == event->height))
5669 gdk_window_configure_finished (gtk_widget_get_window (widget));
5674 * If we do need to resize, we do that by:
5675 * - filling in widget->allocation with the new size
5676 * - setting configure_notify_received to TRUE
5677 * for use in gtk_window_move_resize()
5678 * - queueing a resize, leading to invocation of
5679 * gtk_window_move_resize() in an idle handler
5683 priv->configure_notify_received = TRUE;
5685 allocation.width = event->width;
5686 allocation.height = event->height;
5687 gtk_widget_set_allocation (widget, &allocation);
5689 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5691 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5697 gtk_window_state_event (GtkWidget *widget,
5698 GdkEventWindowState *event)
5700 update_grip_visibility (GTK_WINDOW (widget));
5702 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
5703 ensure_state_flag_backdrop (widget);
5709 gtk_window_direction_changed (GtkWidget *widget,
5710 GtkTextDirection prev_dir)
5712 GtkWindow *window = GTK_WINDOW (widget);
5714 set_grip_cursor (window);
5715 set_grip_position (window);
5716 set_grip_shape (window);
5720 gtk_window_state_changed (GtkWidget *widget,
5721 GtkStateType previous_state)
5723 GtkWindow *window = GTK_WINDOW (widget);
5725 update_grip_visibility (window);
5729 gtk_window_style_updated (GtkWidget *widget)
5731 GtkWindow *window = GTK_WINDOW (widget);
5732 GtkWindowPrivate *priv = window->priv;
5735 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5737 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5739 gdk_window_move_resize (priv->grip_window,
5741 rect.width, rect.height);
5743 set_grip_shape (window);
5744 gtk_widget_queue_resize (widget);
5749 resize_grip_create_window (GtkWindow *window)
5752 GtkWindowPrivate *priv;
5753 GdkWindowAttr attributes;
5754 gint attributes_mask;
5756 GdkRGBA transparent = {0, 0, 0, 0};
5758 priv = window->priv;
5759 widget = GTK_WIDGET (window);
5761 g_return_if_fail (gtk_widget_get_realized (widget));
5762 g_return_if_fail (priv->grip_window == NULL);
5764 gtk_window_get_resize_grip_area (window, &rect);
5766 attributes.x = rect.x;
5767 attributes.y = rect.y;
5768 attributes.width = rect.width;
5769 attributes.height = rect.height;
5770 attributes.window_type = GDK_WINDOW_CHILD;
5771 attributes.wclass = GDK_INPUT_OUTPUT;
5772 attributes.event_mask = gtk_widget_get_events (widget) |
5774 GDK_BUTTON_PRESS_MASK;
5776 attributes_mask = GDK_WA_X | GDK_WA_Y;
5778 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5781 gdk_window_set_background_rgba (priv->grip_window, &transparent);
5783 gdk_window_set_user_data (priv->grip_window, widget);
5785 gdk_window_raise (priv->grip_window);
5787 set_grip_shape (window);
5788 update_grip_visibility (window);
5792 resize_grip_destroy_window (GtkWindow *window)
5794 GtkWindowPrivate *priv = window->priv;
5796 gdk_window_set_user_data (priv->grip_window, NULL);
5797 gdk_window_destroy (priv->grip_window);
5798 priv->grip_window = NULL;
5799 update_grip_visibility (window);
5803 * gtk_window_set_has_resize_grip:
5804 * @window: a #GtkWindow
5805 * @value: %TRUE to allow a resize grip
5807 * Sets whether @window has a corner resize grip.
5809 * Note that the resize grip is only shown if the window
5810 * is actually resizable and not maximized. Use
5811 * gtk_window_resize_grip_is_visible() to find out if the
5812 * resize grip is currently shown.
5817 gtk_window_set_has_resize_grip (GtkWindow *window,
5820 GtkWidget *widget = GTK_WIDGET (window);
5821 GtkWindowPrivate *priv = window->priv;
5823 value = value != FALSE;
5825 if (value != priv->has_resize_grip)
5827 priv->has_resize_grip = value;
5828 gtk_widget_queue_draw (widget);
5830 if (gtk_widget_get_realized (widget) &&
5831 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5833 if (priv->has_resize_grip && priv->grip_window == NULL)
5834 resize_grip_create_window (window);
5835 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5836 resize_grip_destroy_window (window);
5839 g_object_notify (G_OBJECT (window), "has-resize-grip");
5844 update_grip_visibility (GtkWindow *window)
5846 GtkWindowPrivate *priv = window->priv;
5849 val = gtk_window_resize_grip_is_visible (window);
5851 if (priv->grip_window != NULL)
5855 gdk_window_show (priv->grip_window);
5856 set_grip_cursor (window);
5860 gdk_window_hide (priv->grip_window);
5864 if (priv->resize_grip_visible != val)
5866 priv->resize_grip_visible = val;
5868 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5873 * gtk_window_resize_grip_is_visible:
5874 * @window: a #GtkWindow
5876 * Determines whether a resize grip is visible for the specified window.
5878 * Returns: %TRUE if a resize grip exists and is visible
5883 gtk_window_resize_grip_is_visible (GtkWindow *window)
5886 GtkWindowPrivate *priv;
5889 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5891 priv = window->priv;
5892 widget = GTK_WIDGET (window);
5894 if (priv->type == GTK_WINDOW_POPUP)
5897 if (!priv->resizable)
5900 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5903 if (gtk_widget_get_realized (widget))
5905 GdkWindowState state;
5907 state = gdk_window_get_state (gtk_widget_get_window (widget));
5909 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5913 if (!get_drag_edge (widget, &edge))
5916 return window->priv->has_resize_grip;
5920 * gtk_window_get_has_resize_grip:
5921 * @window: a #GtkWindow
5923 * Determines whether the window may have a resize grip.
5925 * Returns: %TRUE if the window has a resize grip
5930 gtk_window_get_has_resize_grip (GtkWindow *window)
5932 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5934 return window->priv->has_resize_grip;
5938 * gtk_window_get_resize_grip_area:
5939 * @window: a #GtkWindow
5940 * @rect: (out): a pointer to a #GdkRectangle which we should store
5941 * the resize grip area
5943 * If a window has a resize grip, this will retrieve the grip
5944 * position, width and height into the specified #GdkRectangle.
5946 * Returns: %TRUE if the resize grip's area was retrieved
5951 gtk_window_get_resize_grip_area (GtkWindow *window,
5954 GtkWidget *widget = GTK_WIDGET (window);
5955 GtkAllocation allocation;
5959 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5961 if (!window->priv->has_resize_grip)
5964 gtk_widget_get_allocation (widget, &allocation);
5966 gtk_widget_style_get (widget,
5967 "resize-grip-width", &grip_width,
5968 "resize-grip-height", &grip_height,
5971 if (grip_width > allocation.width)
5972 grip_width = allocation.width;
5974 if (grip_height > allocation.height)
5975 grip_height = allocation.height;
5977 rect->width = grip_width;
5978 rect->height = grip_height;
5979 rect->y = allocation.y + allocation.height - grip_height;
5981 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5982 rect->x = allocation.x + allocation.width - grip_width;
5984 rect->x = allocation.x;
5989 /* the accel_key and accel_mods fields of the key have to be setup
5990 * upon calling this function. it'll then return whether that key
5991 * is at all used as accelerator, and if so will OR in the
5992 * accel_flags member of the key.
5995 _gtk_window_query_nonaccels (GtkWindow *window,
5997 GdkModifierType accel_mods)
5999 GtkWindowPrivate *priv;
6001 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6003 priv = window->priv;
6005 /* movement keys are considered locked accels */
6008 static const guint bindings[] = {
6009 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,
6010 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,
6014 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
6015 if (bindings[i] == accel_key)
6019 /* mnemonics are considered locked accels */
6020 if (accel_mods == priv->mnemonic_modifier)
6022 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
6023 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
6031 * gtk_window_propagate_key_event:
6032 * @window: a #GtkWindow
6033 * @event: a #GdkEventKey
6035 * Propagate a key press or release event to the focus widget and
6036 * up the focus container chain until a widget handles @event.
6037 * This is normally called by the default ::key_press_event and
6038 * ::key_release_event handlers for toplevel windows,
6039 * however in some cases it may be useful to call this directly when
6040 * overriding the standard key handling for a toplevel window.
6042 * Return value: %TRUE if a widget in the focus chain handled the event.
6047 gtk_window_propagate_key_event (GtkWindow *window,
6050 GtkWindowPrivate *priv;
6051 gboolean handled = FALSE;
6052 GtkWidget *widget, *focus;
6054 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6056 priv = window->priv;
6057 widget = GTK_WIDGET (window);
6059 focus = priv->focus_widget;
6061 g_object_ref (focus);
6064 focus && focus != widget &&
6065 gtk_widget_get_toplevel (focus) == widget)
6069 if (gtk_widget_is_sensitive (focus))
6070 handled = gtk_widget_event (focus, (GdkEvent*) event);
6072 parent = gtk_widget_get_parent (focus);
6074 g_object_ref (parent);
6076 g_object_unref (focus);
6082 g_object_unref (focus);
6088 gtk_window_key_press_event (GtkWidget *widget,
6091 GtkWindow *window = GTK_WINDOW (widget);
6092 gboolean handled = FALSE;
6094 /* handle mnemonics and accelerators */
6096 handled = gtk_window_activate_key (window, event);
6098 /* handle focus widget key events */
6100 handled = gtk_window_propagate_key_event (window, event);
6102 /* Chain up, invokes binding set */
6104 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
6110 gtk_window_key_release_event (GtkWidget *widget,
6113 GtkWindow *window = GTK_WINDOW (widget);
6114 gboolean handled = FALSE;
6116 /* handle focus widget key events */
6118 handled = gtk_window_propagate_key_event (window, event);
6120 /* Chain up, invokes binding set */
6122 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
6128 gtk_window_button_press_event (GtkWidget *widget,
6129 GdkEventButton *event)
6131 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
6134 if (event->window == priv->grip_window)
6136 if (get_drag_edge (widget, &edge))
6137 gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
6139 gdk_event_get_device ((GdkEvent *) event),
6152 gtk_window_real_activate_default (GtkWindow *window)
6154 gtk_window_activate_default (window);
6158 gtk_window_real_activate_focus (GtkWindow *window)
6160 gtk_window_activate_focus (window);
6164 gtk_window_enter_notify_event (GtkWidget *widget,
6165 GdkEventCrossing *event)
6171 gtk_window_leave_notify_event (GtkWidget *widget,
6172 GdkEventCrossing *event)
6178 do_focus_change (GtkWidget *widget,
6182 GdkDeviceManager *device_manager;
6185 g_object_ref (widget);
6187 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
6188 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6189 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
6190 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
6192 for (d = devices; d; d = d->next)
6194 GdkDevice *dev = d->data;
6197 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
6200 /* Skip non-master keyboards that haven't
6201 * selected for events from this window
6203 window = gtk_widget_get_window (widget);
6204 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
6205 window && !gdk_window_get_device_events (window, dev))
6208 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
6210 fevent->focus_change.type = GDK_FOCUS_CHANGE;
6211 fevent->focus_change.window = window;
6213 g_object_ref (window);
6214 fevent->focus_change.in = in;
6215 gdk_event_set_device (fevent, dev);
6217 gtk_widget_send_focus_change (widget, fevent);
6219 gdk_event_free (fevent);
6222 g_list_free (devices);
6223 g_object_unref (widget);
6227 maybe_set_mnemonics_visible (GtkWindow *window)
6230 GdkDeviceManager *device_manager;
6232 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
6233 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6235 for (d = devices; d; d = d->next)
6237 GdkDevice *dev = d->data;
6239 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6241 GdkModifierType mask;
6243 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6245 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6247 gtk_window_set_mnemonics_visible (window, TRUE);
6253 g_list_free (devices);
6257 gtk_window_focus_in_event (GtkWidget *widget,
6258 GdkEventFocus *event)
6260 GtkWindow *window = GTK_WINDOW (widget);
6261 gboolean auto_mnemonics;
6263 /* It appears spurious focus in events can occur when
6264 * the window is hidden. So we'll just check to see if
6265 * the window is visible before actually handling the
6268 if (gtk_widget_get_visible (widget))
6270 _gtk_window_set_has_toplevel_focus (window, TRUE);
6271 _gtk_window_set_is_active (window, TRUE);
6273 g_object_get (gtk_widget_get_settings (widget),
6274 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6276 maybe_set_mnemonics_visible (window);
6283 gtk_window_focus_out_event (GtkWidget *widget,
6284 GdkEventFocus *event)
6286 GtkWindow *window = GTK_WINDOW (widget);
6287 gboolean auto_mnemonics;
6289 _gtk_window_set_has_toplevel_focus (window, FALSE);
6290 _gtk_window_set_is_active (window, FALSE);
6292 /* set the mnemonic-visible property to false */
6293 g_object_get (gtk_widget_get_settings (widget),
6294 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6296 gtk_window_set_mnemonics_visible (window, FALSE);
6302 gtk_window_check_resize (GtkContainer *container)
6304 /* If the window is not toplevel anymore than it's embedded somewhere,
6305 * so handle it like a normal window */
6306 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6307 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6308 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6309 gtk_window_move_resize (GTK_WINDOW (container));
6313 gtk_window_focus (GtkWidget *widget,
6314 GtkDirectionType direction)
6316 GtkWindowPrivate *priv;
6319 GtkContainer *container;
6321 GtkWidget *old_focus_child;
6324 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6325 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6327 container = GTK_CONTAINER (widget);
6328 window = GTK_WINDOW (widget);
6329 priv = window->priv;
6330 bin = GTK_BIN (widget);
6332 old_focus_child = gtk_container_get_focus_child (container);
6334 /* We need a special implementation here to deal properly with wrapping
6335 * around in the tab chain without the danger of going into an
6338 if (old_focus_child)
6340 if (gtk_widget_child_focus (old_focus_child, direction))
6344 if (priv->focus_widget)
6346 if (direction == GTK_DIR_LEFT ||
6347 direction == GTK_DIR_RIGHT ||
6348 direction == GTK_DIR_UP ||
6349 direction == GTK_DIR_DOWN)
6354 /* Wrapped off the end, clear the focus setting for the toplpevel */
6355 parent = gtk_widget_get_parent (priv->focus_widget);
6358 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6359 parent = gtk_widget_get_parent (parent);
6362 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6365 /* Now try to focus the first widget in the window */
6366 child = gtk_bin_get_child (bin);
6369 if (gtk_widget_child_focus (child, direction))
6377 gtk_window_move_focus (GtkWidget *widget,
6378 GtkDirectionType dir)
6380 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6382 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6386 gtk_widget_child_focus (widget, dir);
6388 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6389 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6393 gtk_window_real_set_focus (GtkWindow *window,
6396 GtkWindowPrivate *priv = window->priv;
6397 GtkWidget *old_focus = priv->focus_widget;
6398 gboolean had_default = FALSE;
6399 gboolean focus_had_default = FALSE;
6400 gboolean old_focus_had_default = FALSE;
6404 g_object_ref (old_focus);
6405 g_object_freeze_notify (G_OBJECT (old_focus));
6406 old_focus_had_default = gtk_widget_has_default (old_focus);
6410 g_object_ref (focus);
6411 g_object_freeze_notify (G_OBJECT (focus));
6412 focus_had_default = gtk_widget_has_default (focus);
6415 if (priv->default_widget)
6416 had_default = gtk_widget_has_default (priv->default_widget);
6418 if (priv->focus_widget)
6420 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6421 (priv->focus_widget != priv->default_widget))
6423 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6424 gtk_widget_queue_draw (priv->focus_widget);
6426 if (priv->default_widget)
6427 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6430 priv->focus_widget = NULL;
6432 if (priv->has_focus)
6433 do_focus_change (old_focus, FALSE);
6435 g_object_notify (G_OBJECT (old_focus), "is-focus");
6438 /* The above notifications may have set a new focus widget,
6439 * if so, we don't want to override it.
6441 if (focus && !priv->focus_widget)
6443 priv->focus_widget = focus;
6445 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6446 (priv->focus_widget != priv->default_widget))
6448 if (gtk_widget_get_can_default (priv->focus_widget))
6449 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6451 if (priv->default_widget)
6452 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6455 if (priv->has_focus)
6456 do_focus_change (priv->focus_widget, TRUE);
6458 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6461 /* If the default widget changed, a redraw will have been queued
6462 * on the old and new default widgets by gtk_window_set_default(), so
6463 * we only have to worry about the case where it didn't change.
6464 * We'll sometimes queue a draw twice on the new widget but that
6467 if (priv->default_widget &&
6468 (had_default != gtk_widget_has_default (priv->default_widget)))
6469 gtk_widget_queue_draw (priv->default_widget);
6473 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6474 gtk_widget_queue_draw (old_focus);
6476 g_object_thaw_notify (G_OBJECT (old_focus));
6477 g_object_unref (old_focus);
6481 if (focus_had_default != gtk_widget_has_default (focus))
6482 gtk_widget_queue_draw (focus);
6484 g_object_thaw_notify (G_OBJECT (focus));
6485 g_object_unref (focus);
6491 gtk_window_get_preferred_width (GtkWidget *widget,
6499 window = GTK_WINDOW (widget);
6500 child = gtk_bin_get_child (GTK_BIN (window));
6502 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6503 *minimum_size = border_width * 2;
6504 *natural_size = border_width * 2;
6506 if (child && gtk_widget_get_visible (child))
6508 gint child_min, child_nat;
6509 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6511 *minimum_size += child_min;
6512 *natural_size += child_nat;
6517 gtk_window_get_preferred_height (GtkWidget *widget,
6525 window = GTK_WINDOW (widget);
6526 child = gtk_bin_get_child (GTK_BIN (window));
6528 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6529 *minimum_size = border_width * 2;
6530 *natural_size = border_width * 2;
6532 if (child && gtk_widget_get_visible (child))
6534 gint child_min, child_nat;
6535 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6537 *minimum_size += child_min;
6538 *natural_size += child_nat;
6544 * _gtk_window_unset_focus_and_default:
6545 * @window: a #GtkWindow
6546 * @widget: a widget inside of @window
6548 * Checks whether the focus and default widgets of @window are
6549 * @widget or a descendent of @widget, and if so, unset them.
6552 _gtk_window_unset_focus_and_default (GtkWindow *window,
6556 GtkWindowPrivate *priv = window->priv;
6560 g_object_ref (window);
6561 g_object_ref (widget);
6563 parent = gtk_widget_get_parent (widget);
6564 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6566 child = priv->focus_widget;
6568 while (child && child != widget)
6569 child = gtk_widget_get_parent (child);
6571 if (child == widget)
6572 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6575 child = priv->default_widget;
6577 while (child && child != widget)
6578 child = gtk_widget_get_parent (child);
6580 if (child == widget)
6581 gtk_window_set_default (window, NULL);
6583 g_object_unref (widget);
6584 g_object_unref (window);
6587 /*********************************
6588 * Functions related to resizing *
6589 *********************************/
6592 geometry_size_to_pixels (GdkGeometry *geometry,
6597 gint base_width = 0;
6598 gint base_height = 0;
6600 gint min_height = 0;
6602 gint height_inc = 1;
6604 if (flags & GDK_HINT_BASE_SIZE)
6606 base_width = geometry->base_width;
6607 base_height = geometry->base_height;
6609 if (flags & GDK_HINT_MIN_SIZE)
6611 min_width = geometry->min_width;
6612 min_height = geometry->min_height;
6614 if (flags & GDK_HINT_RESIZE_INC)
6616 width_inc = geometry->width_inc;
6617 height_inc = geometry->height_inc;
6621 *width = MAX (*width * width_inc + base_width, min_width);
6623 *height = MAX (*height * height_inc + base_height, min_height);
6626 /* This function doesn't constrain to geometry hints */
6628 gtk_window_compute_configure_request_size (GtkWindow *window,
6629 GdkGeometry *geometry,
6634 GtkWindowPrivate *priv = window->priv;
6635 GtkWindowGeometryInfo *info;
6638 * - we've done a size request
6641 info = gtk_window_get_geometry_info (window, FALSE);
6643 if (priv->need_default_size)
6645 gtk_window_guess_default_size (window, width, height);
6647 /* If window is empty so requests 0, default to random nonzero size */
6648 if (*width == 0 && *height == 0)
6654 /* Override with default size */
6658 if (info->default_width > 0)
6659 *width = info->default_width;
6660 if (info->default_height > 0)
6661 *height = info->default_height;
6663 if (info->default_is_geometry)
6664 geometry_size_to_pixels (geometry, flags,
6665 info->default_width > 0 ? width : NULL,
6666 info->default_height > 0 ? height : NULL);
6671 GtkAllocation allocation;
6673 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6675 /* Default to keeping current size */
6676 *width = allocation.width;
6677 *height = allocation.height;
6680 /* Override any size with gtk_window_resize() values */
6683 if (info->resize_width > 0)
6684 *width = info->resize_width;
6685 if (info->resize_height > 0)
6686 *height = info->resize_height;
6688 if (info->resize_is_geometry)
6689 geometry_size_to_pixels (geometry, flags,
6690 info->resize_width > 0 ? width : NULL,
6691 info->resize_height > 0 ? height : NULL);
6694 /* Don't ever request zero width or height, its not supported by
6695 gdk. The size allocation code will round it to 1 anyway but if
6696 we do it then the value returned from this function will is
6697 not comparable to the size allocation read from the GtkWindow. */
6698 *width = MAX (*width, 1);
6699 *height = MAX (*height, 1);
6702 static GtkWindowPosition
6703 get_effective_position (GtkWindow *window)
6705 GtkWindowPrivate *priv = window->priv;
6706 GtkWindowPosition pos = priv->position;
6708 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6709 (priv->transient_parent == NULL ||
6710 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6711 pos = GTK_WIN_POS_NONE;
6717 get_center_monitor_of_window (GtkWindow *window)
6719 /* We could try to sort out the relative positions of the monitors and
6720 * stuff, or we could just be losers and assume you have a row
6721 * or column of monitors.
6723 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6727 get_monitor_containing_pointer (GtkWindow *window)
6731 GdkScreen *window_screen;
6732 GdkScreen *pointer_screen;
6733 GdkDisplay *display;
6734 GdkDeviceManager *device_manager;
6737 window_screen = gtk_window_check_screen (window);
6738 display = gdk_screen_get_display (window_screen);
6739 device_manager = gdk_display_get_device_manager (display);
6740 pointer = gdk_device_manager_get_client_pointer (device_manager);
6742 gdk_device_get_position (pointer,
6746 if (pointer_screen == window_screen)
6747 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6755 center_window_on_monitor (GtkWindow *window,
6761 GdkRectangle monitor;
6764 monitor_num = get_monitor_containing_pointer (window);
6766 if (monitor_num == -1)
6767 monitor_num = get_center_monitor_of_window (window);
6769 gdk_screen_get_monitor_workarea (gtk_window_check_screen (window),
6770 monitor_num, &monitor);
6772 *x = (monitor.width - w) / 2 + monitor.x;
6773 *y = (monitor.height - h) / 2 + monitor.y;
6775 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6776 * and WM decorations.
6790 if (extent > clamp_extent)
6792 *base = clamp_base + clamp_extent/2 - extent/2;
6793 else if (*base < clamp_base)
6795 else if (*base + extent > clamp_base + clamp_extent)
6796 *base = clamp_base + clamp_extent - extent;
6800 clamp_window_to_rectangle (gint *x,
6804 const GdkRectangle *rect)
6806 #ifdef DEBUGGING_OUTPUT
6807 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);
6810 /* If it is too large, center it. If it fits on the monitor but is
6811 * partially outside, move it to the closest edge. Do this
6812 * separately in x and y directions.
6814 clamp (x, w, rect->x, rect->width);
6815 clamp (y, h, rect->y, rect->height);
6816 #ifdef DEBUGGING_OUTPUT
6817 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6823 gtk_window_compute_configure_request (GtkWindow *window,
6824 GdkRectangle *request,
6825 GdkGeometry *geometry,
6828 GtkWindowPrivate *priv = window->priv;
6829 GdkGeometry new_geometry;
6832 GtkWindowPosition pos;
6833 GtkWidget *parent_widget;
6834 GtkWindowGeometryInfo *info;
6838 screen = gtk_window_check_screen (window);
6840 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6841 gtk_window_compute_configure_request_size (window,
6842 &new_geometry, new_flags,
6845 gtk_window_constrain_size (window,
6846 &new_geometry, new_flags,
6850 parent_widget = (GtkWidget*) priv->transient_parent;
6852 pos = get_effective_position (window);
6853 info = gtk_window_get_geometry_info (window, FALSE);
6855 /* by default, don't change position requested */
6858 x = info->last.configure_request.x;
6859 y = info->last.configure_request.y;
6868 if (priv->need_default_position)
6871 /* FIXME this all interrelates with window gravity.
6872 * For most of them I think we want to set GRAVITY_CENTER.
6874 * Not sure how to go about that.
6878 /* here we are only handling CENTER_ALWAYS
6879 * as it relates to default positioning,
6880 * where it's equivalent to simply CENTER
6882 case GTK_WIN_POS_CENTER_ALWAYS:
6883 case GTK_WIN_POS_CENTER:
6884 center_window_on_monitor (window, w, h, &x, &y);
6887 case GTK_WIN_POS_CENTER_ON_PARENT:
6889 GtkAllocation allocation;
6890 GdkWindow *gdk_window;
6892 GdkRectangle monitor;
6895 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6897 gdk_window = gtk_widget_get_window (parent_widget);
6899 if (gdk_window != NULL)
6900 monitor_num = gdk_screen_get_monitor_at_window (screen,
6905 gdk_window_get_origin (gdk_window,
6908 gtk_widget_get_allocation (parent_widget, &allocation);
6909 x = ox + (allocation.width - w) / 2;
6910 y = oy + (allocation.height - h) / 2;
6912 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6913 * WM decorations. If parent wasn't on a monitor, just
6916 if (monitor_num >= 0)
6918 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6919 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6924 case GTK_WIN_POS_MOUSE:
6926 gint screen_width = gdk_screen_get_width (screen);
6927 gint screen_height = gdk_screen_get_height (screen);
6929 GdkRectangle monitor;
6930 GdkDisplay *display;
6931 GdkDeviceManager *device_manager;
6933 GdkScreen *pointer_screen;
6936 display = gdk_screen_get_display (screen);
6937 device_manager = gdk_display_get_device_manager (display);
6938 pointer = gdk_device_manager_get_client_pointer (device_manager);
6940 gdk_device_get_position (pointer,
6944 if (pointer_screen == screen)
6945 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6951 x = CLAMP (x, 0, screen_width - w);
6952 y = CLAMP (y, 0, screen_height - h);
6954 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6955 * WM decorations. Don't try to figure out what's going
6956 * on if the mouse wasn't inside a monitor.
6958 if (monitor_num >= 0)
6960 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6961 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6969 } /* if (priv->need_default_position) */
6971 if (priv->need_default_position && info &&
6972 info->initial_pos_set)
6974 x = info->initial_x;
6975 y = info->initial_y;
6976 gtk_window_constrain_position (window, w, h, &x, &y);
6982 request->height = h;
6985 *geometry = new_geometry;
6991 gtk_window_constrain_position (GtkWindow *window,
6997 GtkWindowPrivate *priv = window->priv;
6999 /* See long comments in gtk_window_move_resize()
7000 * on when it's safe to call this function.
7002 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
7004 gint center_x, center_y;
7006 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
7014 gtk_window_move_resize (GtkWindow *window)
7018 * First we determine whether any information has changed that would
7019 * cause us to revise our last configure request. If we would send
7020 * a different configure request from last time, then
7021 * configure_request_size_changed = TRUE or
7022 * configure_request_pos_changed = TRUE. configure_request_size_changed
7023 * may be true due to new hints, a gtk_window_resize(), or whatever.
7024 * configure_request_pos_changed may be true due to gtk_window_set_position()
7025 * or gtk_window_move().
7027 * If the configure request has changed, we send off a new one. To
7028 * ensure GTK+ invariants are maintained (resize queue does what it
7029 * should), we go ahead and size_allocate the requested size in this
7032 * If the configure request has not changed, we don't ever resend
7033 * it, because it could mean fighting the user or window manager.
7036 * To prepare the configure request, we come up with a base size/pos:
7037 * - the one from gtk_window_move()/gtk_window_resize()
7038 * - else default_width, default_height if we haven't ever
7040 * - else the size request if we haven't ever been mapped,
7041 * as a substitute default size
7042 * - else the current size of the window, as received from
7043 * configure notifies (i.e. the current allocation)
7045 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
7046 * the position request to be centered.
7048 GtkWindowPrivate *priv = window->priv;
7049 GtkAllocation allocation;
7051 GtkContainer *container;
7052 GtkWindowGeometryInfo *info;
7053 GdkGeometry new_geometry;
7054 GdkWindow *gdk_window;
7056 GdkRectangle new_request;
7057 gboolean configure_request_size_changed;
7058 gboolean configure_request_pos_changed;
7059 gboolean hints_changed; /* do we need to send these again */
7060 GtkWindowLastGeometryInfo saved_last_info;
7062 widget = GTK_WIDGET (window);
7064 gdk_window = gtk_widget_get_window (widget);
7065 container = GTK_CONTAINER (widget);
7066 info = gtk_window_get_geometry_info (window, TRUE);
7068 configure_request_size_changed = FALSE;
7069 configure_request_pos_changed = FALSE;
7071 gtk_window_compute_configure_request (window, &new_request,
7072 &new_geometry, &new_flags);
7074 /* This check implies the invariant that we never set info->last
7075 * without setting the hints and sending off a configure request.
7077 * If we change info->last without sending the request, we may
7080 if (info->last.configure_request.x != new_request.x ||
7081 info->last.configure_request.y != new_request.y)
7082 configure_request_pos_changed = TRUE;
7084 if ((info->last.configure_request.width != new_request.width ||
7085 info->last.configure_request.height != new_request.height))
7086 configure_request_size_changed = TRUE;
7088 hints_changed = FALSE;
7090 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
7091 &new_geometry, new_flags))
7093 hints_changed = TRUE;
7096 /* Position Constraints
7097 * ====================
7099 * POS_CENTER_ALWAYS is conceptually a constraint rather than
7100 * a default. The other POS_ values are used only when the
7101 * window is shown, not after that.
7103 * However, we can't implement a position constraint as
7104 * "anytime the window size changes, center the window"
7105 * because this may well end up fighting the WM or user. In
7106 * fact it gets in an infinite loop with at least one WM.
7108 * Basically, applications are in no way in a position to
7109 * constrain the position of a window, with one exception:
7110 * override redirect windows. (Really the intended purpose
7111 * of CENTER_ALWAYS anyhow, I would think.)
7113 * So the way we implement this "constraint" is to say that when WE
7114 * cause a move or resize, i.e. we make a configure request changing
7115 * window size, we recompute the CENTER_ALWAYS position to reflect
7116 * the new window size, and include it in our request. Also, if we
7117 * just turned on CENTER_ALWAYS we snap to center with a new
7118 * request. Otherwise, if we are just NOTIFIED of a move or resize
7119 * done by someone else e.g. the window manager, we do NOT send a
7120 * new configure request.
7122 * For override redirect windows, this works fine; all window
7123 * sizes are from our configure requests. For managed windows,
7124 * it is at least semi-sane, though who knows what the
7125 * app author is thinking.
7128 /* This condition should be kept in sync with the condition later on
7129 * that determines whether we send a configure request. i.e. we
7130 * should do this position constraining anytime we were going to
7131 * send a configure request anyhow, plus when constraints have
7134 if (configure_request_pos_changed ||
7135 configure_request_size_changed ||
7137 info->position_constraints_changed)
7139 /* We request the constrained position if:
7140 * - we were changing position, and need to clamp
7141 * the change to the constraint
7142 * - we're changing the size anyway
7143 * - set_position() was called to toggle CENTER_ALWAYS on
7146 gtk_window_constrain_position (window,
7152 /* Update whether we need to request a move */
7153 if (info->last.configure_request.x != new_request.x ||
7154 info->last.configure_request.y != new_request.y)
7155 configure_request_pos_changed = TRUE;
7157 configure_request_pos_changed = FALSE;
7161 if (priv->type == GTK_WINDOW_TOPLEVEL)
7163 int notify_x, notify_y;
7165 /* this is the position from the last configure notify */
7166 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
7168 g_message ("--- %s ---\n"
7169 "last : %d,%d\t%d x %d\n"
7170 "this : %d,%d\t%d x %d\n"
7171 "alloc : %d,%d\t%d x %d\n"
7173 "resize: \t%d x %d\n"
7174 "size_changed: %d pos_changed: %d hints_changed: %d\n"
7175 "configure_notify_received: %d\n"
7176 "configure_request_count: %d\n"
7177 "position_constraints_changed: %d\n",
7178 priv->title ? priv->title : "(no title)",
7179 info->last.configure_request.x,
7180 info->last.configure_request.y,
7181 info->last.configure_request.width,
7182 info->last.configure_request.height,
7188 widget->allocation.width,
7189 widget->allocation.height,
7190 widget->requisition.width,
7191 widget->requisition.height,
7193 info->resize_height,
7194 configure_request_pos_changed,
7195 configure_request_size_changed,
7197 priv->configure_notify_received,
7198 priv->configure_request_count,
7199 info->position_constraints_changed);
7203 saved_last_info = info->last;
7204 info->last.geometry = new_geometry;
7205 info->last.flags = new_flags;
7206 info->last.configure_request = new_request;
7208 /* need to set PPosition so the WM will look at our position,
7209 * but we don't want to count PPosition coming and going as a hints
7210 * change for future iterations. So we saved info->last prior to
7214 /* Also, if the initial position was explicitly set, then we always
7215 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
7219 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
7220 * this is an initial map
7223 if ((configure_request_pos_changed ||
7224 info->initial_pos_set ||
7225 (priv->need_default_position &&
7226 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
7227 (new_flags & GDK_HINT_POS) == 0)
7229 new_flags |= GDK_HINT_POS;
7230 hints_changed = TRUE;
7233 /* Set hints if necessary
7236 gdk_window_set_geometry_hints (gdk_window,
7240 gtk_widget_get_allocation (widget, &allocation);
7242 /* handle resizing/moving and widget tree allocation
7244 if (priv->configure_notify_received)
7246 /* If we have received a configure event since
7247 * the last time in this function, we need to
7248 * accept our new size and size_allocate child widgets.
7249 * (see gtk_window_configure_event() for more details).
7251 * 1 or more configure notifies may have been received.
7252 * Also, configure_notify_received will only be TRUE
7253 * if all expected configure notifies have been received
7254 * (one per configure request), as an optimization.
7257 priv->configure_notify_received = FALSE;
7259 /* gtk_window_configure_event() filled in widget->allocation */
7260 gtk_widget_size_allocate (widget, &allocation);
7262 set_grip_position (window);
7263 update_grip_visibility (window);
7265 gdk_window_process_updates (gdk_window, TRUE);
7267 gdk_window_configure_finished (gdk_window);
7269 /* If the configure request changed, it means that
7271 * 1) coincidentally changed hints or widget properties
7272 * impacting the configure request before getting
7273 * a configure notify, or
7274 * 2) some broken widget is changing its size request
7275 * during size allocation, resulting in
7276 * a false appearance of changed configure request.
7278 * For 1), we could just go ahead and ask for the
7279 * new size right now, but doing that for 2)
7280 * might well be fighting the user (and can even
7281 * trigger a loop). Since we really don't want to
7282 * do that, we requeue a resize in hopes that
7283 * by the time it gets handled, the child has seen
7284 * the light and is willing to go along with the
7285 * new size. (this happens for the zvt widget, since
7286 * the size_allocate() above will have stored the
7287 * requisition corresponding to the new size in the
7290 * This doesn't buy us anything for 1), but it shouldn't
7291 * hurt us too badly, since it is what would have
7292 * happened if we had gotten the configure event before
7293 * the new size had been set.
7296 if (configure_request_size_changed ||
7297 configure_request_pos_changed)
7299 /* Don't change the recorded last info after all, because we
7300 * haven't actually updated to the new info yet - we decided
7301 * to postpone our configure request until later.
7303 info->last = saved_last_info;
7305 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7308 return; /* Bail out, we didn't really process the move/resize */
7310 else if ((configure_request_size_changed || hints_changed) &&
7311 (allocation.width != new_request.width || allocation.height != new_request.height))
7314 /* We are in one of the following situations:
7315 * A. configure_request_size_changed
7316 * our requisition has changed and we need a different window size,
7317 * so we request it from the window manager.
7318 * B. !configure_request_size_changed && hints_changed
7319 * the window manager rejects our size, but we have just changed the
7320 * window manager hints, so there's a chance our request will
7321 * be honoured this time, so we try again.
7323 * However, if the new requisition is the same as the current allocation,
7324 * we don't request it again, since we won't get a ConfigureNotify back from
7325 * the window manager unless it decides to change our requisition. If
7326 * we don't get the ConfigureNotify back, the resize queue will never be run.
7329 /* Now send the configure request */
7330 if (configure_request_pos_changed)
7332 gdk_window_move_resize (gdk_window,
7333 new_request.x, new_request.y,
7334 new_request.width, new_request.height);
7336 else /* only size changed */
7338 gdk_window_resize (gdk_window,
7339 new_request.width, new_request.height);
7342 if (priv->type == GTK_WINDOW_POPUP)
7344 GtkAllocation allocation;
7346 /* Directly size allocate for override redirect (popup) windows. */
7349 allocation.width = new_request.width;
7350 allocation.height = new_request.height;
7352 gtk_widget_size_allocate (widget, &allocation);
7354 gdk_window_process_updates (gdk_window, TRUE);
7356 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7357 gtk_widget_queue_draw (widget);
7361 /* Increment the number of have-not-yet-received-notify requests */
7362 priv->configure_request_count += 1;
7363 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7365 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7366 * configure event in response to our resizing request.
7367 * the configure event will cause a new resize with
7368 * ->configure_notify_received=TRUE.
7369 * until then, we want to
7370 * - discard expose events
7371 * - coalesce resizes for our children
7372 * - defer any window resizes until the configure event arrived
7373 * to achieve this, we queue a resize for the window, but remove its
7374 * resizing handler, so resizing will not be handled from the next
7375 * idle handler but when the configure event arrives.
7377 * FIXME: we should also dequeue the pending redraws here, since
7378 * we handle those ourselves upon ->configure_notify_received==TRUE.
7380 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7382 gtk_widget_queue_resize_no_redraw (widget);
7383 _gtk_container_dequeue_resize_handler (container);
7389 /* Handle any position changes.
7391 if (configure_request_pos_changed)
7393 gdk_window_move (gdk_window,
7394 new_request.x, new_request.y);
7397 /* And run the resize queue.
7399 gtk_container_resize_children (container);
7402 /* We have now processed a move/resize since the last position
7403 * constraint change, setting of the initial position, or resize.
7404 * (Not resetting these flags here can lead to infinite loops for
7405 * GTK_RESIZE_IMMEDIATE containers)
7407 info->position_constraints_changed = FALSE;
7408 info->initial_pos_set = FALSE;
7409 info->resize_width = -1;
7410 info->resize_height = -1;
7413 /* Compare two sets of Geometry hints for equality.
7416 gtk_window_compare_hints (GdkGeometry *geometry_a,
7418 GdkGeometry *geometry_b,
7421 if (flags_a != flags_b)
7424 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7425 (geometry_a->min_width != geometry_b->min_width ||
7426 geometry_a->min_height != geometry_b->min_height))
7429 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7430 (geometry_a->max_width != geometry_b->max_width ||
7431 geometry_a->max_height != geometry_b->max_height))
7434 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7435 (geometry_a->base_width != geometry_b->base_width ||
7436 geometry_a->base_height != geometry_b->base_height))
7439 if ((flags_a & GDK_HINT_ASPECT) &&
7440 (geometry_a->min_aspect != geometry_b->min_aspect ||
7441 geometry_a->max_aspect != geometry_b->max_aspect))
7444 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7445 (geometry_a->width_inc != geometry_b->width_inc ||
7446 geometry_a->height_inc != geometry_b->height_inc))
7449 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7450 geometry_a->win_gravity != geometry_b->win_gravity)
7457 _gtk_window_constrain_size (GtkWindow *window,
7463 GtkWindowPrivate *priv;
7464 GtkWindowGeometryInfo *info;
7466 g_return_if_fail (GTK_IS_WINDOW (window));
7468 priv = window->priv;
7470 info = priv->geometry_info;
7473 GdkWindowHints flags = info->last.flags;
7474 GdkGeometry *geometry = &info->last.geometry;
7476 gtk_window_constrain_size (window,
7487 gtk_window_constrain_size (GtkWindow *window,
7488 GdkGeometry *geometry,
7495 gdk_window_constrain_size (geometry, flags, width, height,
7496 new_width, new_height);
7499 /* Compute the set of geometry hints and flags for a window
7500 * based on the application set geometry, and requisition
7501 * of the window. gtk_widget_get_preferred_size() must have been
7505 gtk_window_compute_hints (GtkWindow *window,
7506 GdkGeometry *new_geometry,
7509 GtkWindowPrivate *priv = window->priv;
7511 gint extra_width = 0;
7512 gint extra_height = 0;
7513 GtkWindowGeometryInfo *geometry_info;
7514 GtkRequisition requisition;
7516 widget = GTK_WIDGET (window);
7518 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7519 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7523 *new_flags = geometry_info->mask;
7524 *new_geometry = geometry_info->geometry;
7531 if (geometry_info && geometry_info->widget)
7533 /* If the geometry widget is set, then the hints really apply to that
7534 * widget. This is pretty much meaningless unless the window layout
7535 * is such that the rest of the window adds fixed size borders to
7536 * the geometry widget. Our job is to figure the size of the borders;
7537 * We do that by asking how big the toplevel would be if the
7538 * geometry widget was *really big*.
7541 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7542 * |GGGGG B| in the border can confuse things
7548 * |AAAAAAAAA | When the geometry widget is large, things are
7549 * |GGGGGGGGGGB| clearer.
7554 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7555 GtkRequisition requisition;
7556 int current_width, current_height;
7558 _gtk_widget_override_size_request (geometry_info->widget,
7559 TEMPORARY_SIZE, TEMPORARY_SIZE,
7560 ¤t_width, ¤t_height);
7561 gtk_widget_get_preferred_size (widget,
7562 &requisition, NULL);
7563 _gtk_widget_restore_size_request (geometry_info->widget,
7564 current_width, current_height);
7566 extra_width = requisition.width - TEMPORARY_SIZE;
7567 extra_height = requisition.height - TEMPORARY_SIZE;
7569 if (extra_width < 0 || extra_height < 0)
7571 g_warning("Toplevel size doesn't seem to directly depend on the "
7572 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7573 "The geometry widget might not be in the window, or it might not "
7574 "be packed into the window appropriately");
7575 extra_width = MAX(extra_width, 0);
7576 extra_height = MAX(extra_height, 0);
7578 #undef TEMPORARY_SIZE
7581 /* We don't want to set GDK_HINT_POS in here, we just set it
7582 * in gtk_window_move_resize() when we want the position
7586 if (*new_flags & GDK_HINT_BASE_SIZE)
7588 new_geometry->base_width += extra_width;
7589 new_geometry->base_height += extra_height;
7593 /* For simplicity, we always set the base hint, even when we
7594 * don't expect it to have any visible effect.
7595 * (Note: geometry_size_to_pixels() depends on this.)
7597 *new_flags |= GDK_HINT_BASE_SIZE;
7599 new_geometry->base_width = extra_width;
7600 new_geometry->base_height = extra_height;
7602 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7603 * base size is the minimum size */
7604 if (*new_flags & GDK_HINT_MIN_SIZE)
7606 if (new_geometry->min_width > 0)
7607 new_geometry->base_width += new_geometry->min_width;
7608 if (new_geometry->min_height > 0)
7609 new_geometry->base_height += new_geometry->min_height;
7613 /* Please use a good size for unresizable widgets, not the minimum one. */
7614 if (!priv->resizable)
7615 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7617 if (*new_flags & GDK_HINT_MIN_SIZE)
7619 if (new_geometry->min_width < 0)
7620 new_geometry->min_width = requisition.width;
7622 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7624 if (new_geometry->min_height < 0)
7625 new_geometry->min_height = requisition.height;
7627 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7631 *new_flags |= GDK_HINT_MIN_SIZE;
7633 new_geometry->min_width = requisition.width;
7634 new_geometry->min_height = requisition.height;
7637 if (*new_flags & GDK_HINT_MAX_SIZE)
7639 if (new_geometry->max_width < 0)
7640 new_geometry->max_width = requisition.width;
7642 new_geometry->max_width += extra_width;
7644 if (new_geometry->max_height < 0)
7645 new_geometry->max_height = requisition.height;
7647 new_geometry->max_height += extra_height;
7649 else if (!priv->resizable)
7651 *new_flags |= GDK_HINT_MAX_SIZE;
7653 new_geometry->max_width = requisition.width;
7654 new_geometry->max_height = requisition.height;
7657 *new_flags |= GDK_HINT_WIN_GRAVITY;
7658 new_geometry->win_gravity = priv->gravity;
7661 /***********************
7662 * Redrawing functions *
7663 ***********************/
7666 gtk_window_draw (GtkWidget *widget,
7669 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7670 GtkStyleContext *context;
7671 gboolean ret = FALSE;
7673 context = gtk_widget_get_style_context (widget);
7675 if (!gtk_widget_get_app_paintable (widget) &&
7676 gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
7678 gtk_style_context_save (context);
7680 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7681 gtk_render_background (context, cr, 0, 0,
7682 gtk_widget_get_allocated_width (widget),
7683 gtk_widget_get_allocated_height (widget));
7685 gtk_style_context_restore (context);
7688 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7689 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7691 if (priv->grip_window &&
7692 gtk_cairo_should_draw_window (cr, priv->grip_window))
7696 gtk_style_context_save (context);
7699 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7700 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7702 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7703 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7704 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7707 gtk_style_context_restore (context);
7714 * gtk_window_present:
7715 * @window: a #GtkWindow
7717 * Presents a window to the user. This may mean raising the window
7718 * in the stacking order, deiconifying it, moving it to the current
7719 * desktop, and/or giving it the keyboard focus, possibly dependent
7720 * on the user's platform, window manager, and preferences.
7722 * If @window is hidden, this function calls gtk_widget_show()
7725 * This function should be used when the user tries to open a window
7726 * that's already open. Say for example the preferences dialog is
7727 * currently open, and the user chooses Preferences from the menu
7728 * a second time; use gtk_window_present() to move the already-open dialog
7729 * where the user can see it.
7731 * If you are calling this function in response to a user interaction,
7732 * it is preferable to use gtk_window_present_with_time().
7736 gtk_window_present (GtkWindow *window)
7738 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7742 * gtk_window_present_with_time:
7743 * @window: a #GtkWindow
7744 * @timestamp: the timestamp of the user interaction (typically a
7745 * button or key press event) which triggered this call
7747 * Presents a window to the user in response to a user interaction.
7748 * If you need to present a window without a timestamp, use
7749 * gtk_window_present(). See gtk_window_present() for details.
7754 gtk_window_present_with_time (GtkWindow *window,
7757 GtkWindowPrivate *priv;
7759 GdkWindow *gdk_window;
7761 g_return_if_fail (GTK_IS_WINDOW (window));
7763 priv = window->priv;
7764 widget = GTK_WIDGET (window);
7766 if (gtk_widget_get_visible (widget))
7768 gdk_window = gtk_widget_get_window (widget);
7770 g_assert (gdk_window != NULL);
7772 gdk_window_show (gdk_window);
7774 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7775 if (timestamp == GDK_CURRENT_TIME)
7777 #ifdef GDK_WINDOWING_X11
7778 if (GDK_IS_X11_WINDOW(gdk_window))
7780 GdkDisplay *display;
7782 display = gtk_widget_get_display (GTK_WIDGET (window));
7783 timestamp = gdk_x11_display_get_user_time (display);
7787 timestamp = gtk_get_current_event_time ();
7790 gdk_window_focus (gdk_window, timestamp);
7794 priv->initial_timestamp = timestamp;
7795 gtk_widget_show (widget);
7800 * gtk_window_iconify:
7801 * @window: a #GtkWindow
7803 * Asks to iconify (i.e. minimize) the specified @window. Note that
7804 * you shouldn't assume the window is definitely iconified afterward,
7805 * because other entities (e.g. the user or <link
7806 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7807 * again, or there may not be a window manager in which case
7808 * iconification isn't possible, etc. But normally the window will end
7809 * up iconified. Just don't write code that crashes if not.
7811 * It's permitted to call this function before showing a window,
7812 * in which case the window will be iconified before it ever appears
7815 * You can track iconification via the "window-state-event" signal
7820 gtk_window_iconify (GtkWindow *window)
7822 GtkWindowPrivate *priv;
7824 GdkWindow *toplevel;
7826 g_return_if_fail (GTK_IS_WINDOW (window));
7828 priv = window->priv;
7829 widget = GTK_WIDGET (window);
7831 priv->iconify_initially = TRUE;
7833 toplevel = gtk_widget_get_window (widget);
7835 if (toplevel != NULL)
7836 gdk_window_iconify (toplevel);
7840 * gtk_window_deiconify:
7841 * @window: a #GtkWindow
7843 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7844 * that you shouldn't assume the window is definitely deiconified
7845 * afterward, because other entities (e.g. the user or <link
7846 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7847 * again before your code which assumes deiconification gets to run.
7849 * You can track iconification via the "window-state-event" signal
7853 gtk_window_deiconify (GtkWindow *window)
7855 GtkWindowPrivate *priv;
7857 GdkWindow *toplevel;
7859 g_return_if_fail (GTK_IS_WINDOW (window));
7861 priv = window->priv;
7862 widget = GTK_WIDGET (window);
7864 priv->iconify_initially = FALSE;
7866 toplevel = gtk_widget_get_window (widget);
7868 if (toplevel != NULL)
7869 gdk_window_deiconify (toplevel);
7874 * @window: a #GtkWindow
7876 * Asks to stick @window, which means that it will appear on all user
7877 * desktops. Note that you shouldn't assume the window is definitely
7878 * stuck afterward, because other entities (e.g. the user or <link
7879 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7880 * again, and some window managers do not support sticking
7881 * windows. But normally the window will end up stuck. Just don't
7882 * write code that crashes if not.
7884 * It's permitted to call this function before showing a window.
7886 * You can track stickiness via the "window-state-event" signal
7891 gtk_window_stick (GtkWindow *window)
7893 GtkWindowPrivate *priv;
7895 GdkWindow *toplevel;
7897 g_return_if_fail (GTK_IS_WINDOW (window));
7899 priv = window->priv;
7900 widget = GTK_WIDGET (window);
7902 priv->stick_initially = TRUE;
7904 toplevel = gtk_widget_get_window (widget);
7906 if (toplevel != NULL)
7907 gdk_window_stick (toplevel);
7911 * gtk_window_unstick:
7912 * @window: a #GtkWindow
7914 * Asks to unstick @window, which means that it will appear on only
7915 * one of the user's desktops. Note that you shouldn't assume the
7916 * window is definitely unstuck afterward, because other entities
7917 * (e.g. the user or <link linkend="gtk-X11-arch">window
7918 * manager</link>) could stick it again. But normally the window will
7919 * end up stuck. Just don't write code that crashes if not.
7921 * You can track stickiness via the "window-state-event" signal
7926 gtk_window_unstick (GtkWindow *window)
7928 GtkWindowPrivate *priv;
7930 GdkWindow *toplevel;
7932 g_return_if_fail (GTK_IS_WINDOW (window));
7934 priv = window->priv;
7935 widget = GTK_WIDGET (window);
7937 priv->stick_initially = FALSE;
7939 toplevel = gtk_widget_get_window (widget);
7941 if (toplevel != NULL)
7942 gdk_window_unstick (toplevel);
7946 * gtk_window_maximize:
7947 * @window: a #GtkWindow
7949 * Asks to maximize @window, so that it becomes full-screen. Note that
7950 * you shouldn't assume the window is definitely maximized afterward,
7951 * because other entities (e.g. the user or <link
7952 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7953 * again, and not all window managers support maximization. But
7954 * normally the window will end up maximized. Just don't write code
7955 * that crashes if not.
7957 * It's permitted to call this function before showing a window,
7958 * in which case the window will be maximized when it appears onscreen
7961 * You can track maximization via the "window-state-event" signal
7966 gtk_window_maximize (GtkWindow *window)
7968 GtkWindowPrivate *priv;
7970 GdkWindow *toplevel;
7972 g_return_if_fail (GTK_IS_WINDOW (window));
7974 priv = window->priv;
7975 widget = GTK_WIDGET (window);
7977 priv->maximize_initially = TRUE;
7979 toplevel = gtk_widget_get_window (widget);
7981 if (toplevel != NULL)
7982 gdk_window_maximize (toplevel);
7986 * gtk_window_unmaximize:
7987 * @window: a #GtkWindow
7989 * Asks to unmaximize @window. Note that you shouldn't assume the
7990 * window is definitely unmaximized afterward, because other entities
7991 * (e.g. the user or <link linkend="gtk-X11-arch">window
7992 * manager</link>) could maximize it again, and not all window
7993 * managers honor requests to unmaximize. But normally the window will
7994 * end up unmaximized. Just don't write code that crashes if not.
7996 * You can track maximization via the "window-state-event" signal
8001 gtk_window_unmaximize (GtkWindow *window)
8003 GtkWindowPrivate *priv;
8005 GdkWindow *toplevel;
8007 g_return_if_fail (GTK_IS_WINDOW (window));
8009 priv = window->priv;
8010 widget = GTK_WIDGET (window);
8012 priv->maximize_initially = FALSE;
8014 toplevel = gtk_widget_get_window (widget);
8016 if (toplevel != NULL)
8017 gdk_window_unmaximize (toplevel);
8021 * gtk_window_fullscreen:
8022 * @window: a #GtkWindow
8024 * Asks to place @window in the fullscreen state. Note that you
8025 * shouldn't assume the window is definitely full screen afterward,
8026 * because other entities (e.g. the user or <link
8027 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
8028 * again, and not all window managers honor requests to fullscreen
8029 * windows. But normally the window will end up fullscreen. Just
8030 * don't write code that crashes if not.
8032 * You can track the fullscreen state via the "window-state-event" signal
8038 gtk_window_fullscreen (GtkWindow *window)
8040 GtkWindowPrivate *priv;
8042 GdkWindow *toplevel;
8044 g_return_if_fail (GTK_IS_WINDOW (window));
8046 priv = window->priv;
8047 widget = GTK_WIDGET (window);
8049 priv->fullscreen_initially = TRUE;
8051 toplevel = gtk_widget_get_window (widget);
8053 if (toplevel != NULL)
8054 gdk_window_fullscreen (toplevel);
8058 * gtk_window_unfullscreen:
8059 * @window: a #GtkWindow
8061 * Asks to toggle off the fullscreen state for @window. Note that you
8062 * shouldn't assume the window is definitely not full screen
8063 * afterward, because other entities (e.g. the user or <link
8064 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
8065 * again, and not all window managers honor requests to unfullscreen
8066 * windows. But normally the window will end up restored to its normal
8067 * state. Just don't write code that crashes if not.
8069 * You can track the fullscreen state via the "window-state-event" signal
8075 gtk_window_unfullscreen (GtkWindow *window)
8078 GdkWindow *toplevel;
8079 GtkWindowPrivate *priv;
8081 g_return_if_fail (GTK_IS_WINDOW (window));
8083 priv = window->priv;
8084 widget = GTK_WIDGET (window);
8086 priv->fullscreen_initially = FALSE;
8088 toplevel = gtk_widget_get_window (widget);
8090 if (toplevel != NULL)
8091 gdk_window_unfullscreen (toplevel);
8095 * gtk_window_set_keep_above:
8096 * @window: a #GtkWindow
8097 * @setting: whether to keep @window above other windows
8099 * Asks to keep @window above, so that it stays on top. Note that
8100 * you shouldn't assume the window is definitely above afterward,
8101 * because other entities (e.g. the user or <link
8102 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
8103 * and not all window managers support keeping windows above. But
8104 * normally the window will end kept above. Just don't write code
8105 * that crashes if not.
8107 * It's permitted to call this function before showing a window,
8108 * in which case the window will be kept above when it appears onscreen
8111 * You can track the above state via the "window-state-event" signal
8114 * Note that, according to the <ulink
8115 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8116 * Manager Hints</ulink> specification, the above state is mainly meant
8117 * for user preferences and should not be used by applications e.g. for
8118 * drawing attention to their dialogs.
8123 gtk_window_set_keep_above (GtkWindow *window,
8127 GtkWindowPrivate *priv;
8128 GdkWindow *toplevel;
8130 g_return_if_fail (GTK_IS_WINDOW (window));
8132 priv = window->priv;
8133 widget = GTK_WIDGET (window);
8135 priv->above_initially = setting != FALSE;
8137 priv->below_initially = FALSE;
8139 toplevel = gtk_widget_get_window (widget);
8141 if (toplevel != NULL)
8142 gdk_window_set_keep_above (toplevel, setting);
8146 * gtk_window_set_keep_below:
8147 * @window: a #GtkWindow
8148 * @setting: whether to keep @window below other windows
8150 * Asks to keep @window below, so that it stays in bottom. Note that
8151 * you shouldn't assume the window is definitely below afterward,
8152 * because other entities (e.g. the user or <link
8153 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8154 * and not all window managers support putting windows below. But
8155 * normally the window will be kept below. Just don't write code
8156 * that crashes if not.
8158 * It's permitted to call this function before showing a window,
8159 * in which case the window will be kept below when it appears onscreen
8162 * You can track the below state via the "window-state-event" signal
8165 * Note that, according to the <ulink
8166 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8167 * Manager Hints</ulink> specification, the above state is mainly meant
8168 * for user preferences and should not be used by applications e.g. for
8169 * drawing attention to their dialogs.
8174 gtk_window_set_keep_below (GtkWindow *window,
8178 GtkWindowPrivate *priv;
8179 GdkWindow *toplevel;
8181 g_return_if_fail (GTK_IS_WINDOW (window));
8183 priv = window->priv;
8184 widget = GTK_WIDGET (window);
8186 priv->below_initially = setting != FALSE;
8188 priv->above_initially = FALSE;
8190 toplevel = gtk_widget_get_window (widget);
8192 if (toplevel != NULL)
8193 gdk_window_set_keep_below (toplevel, setting);
8197 * gtk_window_set_resizable:
8198 * @window: a #GtkWindow
8199 * @resizable: %TRUE if the user can resize this window
8201 * Sets whether the user can resize a window. Windows are user resizable
8205 gtk_window_set_resizable (GtkWindow *window,
8208 GtkWindowPrivate *priv;
8210 g_return_if_fail (GTK_IS_WINDOW (window));
8212 priv = window->priv;
8214 resizable = (resizable != FALSE);
8216 if (priv->resizable != resizable)
8218 priv->resizable = resizable;
8220 update_grip_visibility (window);
8222 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8224 g_object_notify (G_OBJECT (window), "resizable");
8229 * gtk_window_get_resizable:
8230 * @window: a #GtkWindow
8232 * Gets the value set by gtk_window_set_resizable().
8234 * Return value: %TRUE if the user can resize the window
8237 gtk_window_get_resizable (GtkWindow *window)
8239 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8241 return window->priv->resizable;
8245 * gtk_window_set_gravity:
8246 * @window: a #GtkWindow
8247 * @gravity: window gravity
8249 * Window gravity defines the meaning of coordinates passed to
8250 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8253 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8254 * typically "do what you mean."
8258 gtk_window_set_gravity (GtkWindow *window,
8261 GtkWindowPrivate *priv;
8263 g_return_if_fail (GTK_IS_WINDOW (window));
8265 priv = window->priv;
8267 if (gravity != priv->gravity)
8269 priv->gravity = gravity;
8271 /* gtk_window_move_resize() will adapt gravity
8273 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8275 g_object_notify (G_OBJECT (window), "gravity");
8280 * gtk_window_get_gravity:
8281 * @window: a #GtkWindow
8283 * Gets the value set by gtk_window_set_gravity().
8285 * Return value: (transfer none): window gravity
8288 gtk_window_get_gravity (GtkWindow *window)
8290 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8292 return window->priv->gravity;
8296 * gtk_window_begin_resize_drag:
8297 * @window: a #GtkWindow
8298 * @button: mouse button that initiated the drag
8299 * @edge: position of the resize control
8300 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8301 * @root_y: Y position where the user clicked to initiate the drag
8302 * @timestamp: timestamp from the click event that initiated the drag
8304 * Starts resizing a window. This function is used if an application
8305 * has window resizing controls. When GDK can support it, the resize
8306 * will be done using the standard mechanism for the <link
8307 * linkend="gtk-X11-arch">window manager</link> or windowing
8308 * system. Otherwise, GDK will try to emulate window resizing,
8309 * potentially not all that well, depending on the windowing system.
8313 gtk_window_begin_resize_drag (GtkWindow *window,
8321 GdkWindow *toplevel;
8323 g_return_if_fail (GTK_IS_WINDOW (window));
8324 widget = GTK_WIDGET (window);
8325 g_return_if_fail (gtk_widget_get_visible (widget));
8327 toplevel = gtk_widget_get_window (widget);
8329 gdk_window_begin_resize_drag (toplevel,
8336 * gtk_window_begin_move_drag:
8337 * @window: a #GtkWindow
8338 * @button: mouse button that initiated the drag
8339 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8340 * @root_y: Y position where the user clicked to initiate the drag
8341 * @timestamp: timestamp from the click event that initiated the drag
8343 * Starts moving a window. This function is used if an application has
8344 * window movement grips. When GDK can support it, the window movement
8345 * will be done using the standard mechanism for the <link
8346 * linkend="gtk-X11-arch">window manager</link> or windowing
8347 * system. Otherwise, GDK will try to emulate window movement,
8348 * potentially not all that well, depending on the windowing system.
8352 gtk_window_begin_move_drag (GtkWindow *window,
8359 GdkWindow *toplevel;
8361 g_return_if_fail (GTK_IS_WINDOW (window));
8362 widget = GTK_WIDGET (window);
8363 g_return_if_fail (gtk_widget_get_visible (widget));
8365 toplevel = gtk_widget_get_window (widget);
8367 gdk_window_begin_move_drag (toplevel,
8374 * gtk_window_set_screen:
8375 * @window: a #GtkWindow.
8376 * @screen: a #GdkScreen.
8378 * Sets the #GdkScreen where the @window is displayed; if
8379 * the window is already mapped, it will be unmapped, and
8380 * then remapped on the new screen.
8385 gtk_window_set_screen (GtkWindow *window,
8388 GtkWindowPrivate *priv;
8390 GdkScreen *previous_screen;
8391 gboolean was_mapped;
8393 g_return_if_fail (GTK_IS_WINDOW (window));
8394 g_return_if_fail (GDK_IS_SCREEN (screen));
8396 priv = window->priv;
8398 if (screen == priv->screen)
8401 widget = GTK_WIDGET (window);
8403 previous_screen = priv->screen;
8404 was_mapped = gtk_widget_get_mapped (widget);
8407 gtk_widget_unmap (widget);
8408 if (gtk_widget_get_realized (widget))
8409 gtk_widget_unrealize (widget);
8411 gtk_window_free_key_hash (window);
8412 priv->screen = screen;
8413 gtk_widget_reset_rc_styles (widget);
8414 if (screen != previous_screen)
8416 if (previous_screen)
8418 g_signal_handlers_disconnect_by_func (previous_screen,
8419 gtk_window_on_composited_changed, window);
8420 #ifdef GDK_WINDOWING_X11
8421 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8422 gtk_window_on_theme_variant_changed, window);
8425 g_signal_connect (screen, "composited-changed",
8426 G_CALLBACK (gtk_window_on_composited_changed), window);
8427 #ifdef GDK_WINDOWING_X11
8428 g_signal_connect (gtk_settings_get_for_screen (screen),
8429 "notify::gtk-application-prefer-dark-theme",
8430 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8433 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8434 _gtk_widget_propagate_composited_changed (widget);
8436 g_object_notify (G_OBJECT (window), "screen");
8439 gtk_widget_map (widget);
8443 gtk_window_set_theme_variant (GtkWindow *window)
8445 #ifdef GDK_WINDOWING_X11
8446 GdkWindow *gdk_window;
8447 gboolean dark_theme_requested;
8449 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8450 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8453 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8455 if (GDK_IS_X11_WINDOW (gdk_window))
8456 gdk_x11_window_set_theme_variant (gdk_window,
8457 dark_theme_requested ? "dark" : NULL);
8462 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8466 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8467 gtk_window_set_theme_variant (window);
8471 gtk_window_on_composited_changed (GdkScreen *screen,
8474 gtk_widget_queue_draw (GTK_WIDGET (window));
8476 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8480 gtk_window_check_screen (GtkWindow *window)
8482 GtkWindowPrivate *priv = window->priv;
8485 return priv->screen;
8488 g_warning ("Screen for GtkWindow not set; you must always set\n"
8489 "a screen for a GtkWindow before using the window");
8495 * gtk_window_get_screen:
8496 * @window: a #GtkWindow.
8498 * Returns the #GdkScreen associated with @window.
8500 * Return value: (transfer none): a #GdkScreen.
8505 gtk_window_get_screen (GtkWindow *window)
8507 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8509 return window->priv->screen;
8513 * gtk_window_is_active:
8514 * @window: a #GtkWindow
8516 * Returns whether the window is part of the current active toplevel.
8517 * (That is, the toplevel window receiving keystrokes.)
8518 * The return value is %TRUE if the window is active toplevel
8519 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8520 * You might use this function if you wanted to draw a widget
8521 * differently in an active window from a widget in an inactive window.
8522 * See gtk_window_has_toplevel_focus()
8524 * Return value: %TRUE if the window part of the current active window.
8529 gtk_window_is_active (GtkWindow *window)
8531 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8533 return window->priv->is_active;
8537 * gtk_window_has_toplevel_focus:
8538 * @window: a #GtkWindow
8540 * Returns whether the input focus is within this GtkWindow.
8541 * For real toplevel windows, this is identical to gtk_window_is_active(),
8542 * but for embedded windows, like #GtkPlug, the results will differ.
8544 * Return value: %TRUE if the input focus is within this GtkWindow
8549 gtk_window_has_toplevel_focus (GtkWindow *window)
8551 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8553 return window->priv->has_toplevel_focus;
8558 * SECTION:gtkwindowgroup
8559 * @Short_description: Limit the effect of grabs
8560 * @Title: GtkWindowGroup
8562 * #GtkWindowGroup objects are referenced by each window in the group,
8563 * so once you have added all windows to a #GtkWindowGroup, you can drop
8564 * the initial reference to the window group with g_object_unref(). If the
8565 * windows in the window group are subsequently destroyed, then they will
8566 * be removed from the window group and drop their references on the window
8567 * group; when all window have been removed, the window group will be
8571 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8574 gtk_window_group_init (GtkWindowGroup *group)
8576 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8577 GTK_TYPE_WINDOW_GROUP,
8578 GtkWindowGroupPrivate);
8582 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8584 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8588 * gtk_window_group_new:
8590 * Creates a new #GtkWindowGroup object. Grabs added with
8591 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8593 * Return value: a new #GtkWindowGroup.
8596 gtk_window_group_new (void)
8598 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8602 window_group_cleanup_grabs (GtkWindowGroup *group,
8605 GtkWindowGroupPrivate *priv;
8606 GtkDeviceGrabInfo *info;
8608 GSList *to_remove = NULL;
8612 tmp_list = priv->grabs;
8615 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8616 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8617 tmp_list = tmp_list->next;
8622 gtk_grab_remove (to_remove->data);
8623 g_object_unref (to_remove->data);
8624 to_remove = g_slist_delete_link (to_remove, to_remove);
8627 tmp_list = priv->device_grabs;
8631 info = tmp_list->data;
8633 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8634 to_remove = g_slist_prepend (to_remove, info);
8636 tmp_list = tmp_list->next;
8641 info = to_remove->data;
8643 gtk_device_grab_remove (info->widget, info->device);
8644 to_remove = g_slist_delete_link (to_remove, to_remove);
8649 * gtk_window_group_add_window:
8650 * @window_group: a #GtkWindowGroup
8651 * @window: the #GtkWindow to add
8653 * Adds a window to a #GtkWindowGroup.
8656 gtk_window_group_add_window (GtkWindowGroup *window_group,
8659 GtkWindowPrivate *priv;
8661 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8662 g_return_if_fail (GTK_IS_WINDOW (window));
8664 priv = window->priv;
8666 if (priv->group != window_group)
8668 g_object_ref (window);
8669 g_object_ref (window_group);
8672 gtk_window_group_remove_window (priv->group, window);
8674 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8676 priv->group = window_group;
8678 g_object_unref (window);
8683 * gtk_window_group_remove_window:
8684 * @window_group: a #GtkWindowGroup
8685 * @window: the #GtkWindow to remove
8687 * Removes a window from a #GtkWindowGroup.
8690 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8693 GtkWindowPrivate *priv;
8695 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8696 g_return_if_fail (GTK_IS_WINDOW (window));
8697 priv = window->priv;
8698 g_return_if_fail (priv->group == window_group);
8700 g_object_ref (window);
8702 window_group_cleanup_grabs (window_group, window);
8705 g_object_unref (window_group);
8706 g_object_unref (window);
8710 * gtk_window_group_list_windows:
8711 * @window_group: a #GtkWindowGroup
8713 * Returns a list of the #GtkWindows that belong to @window_group.
8715 * Returns: (element-type GtkWindow) (transfer container): A
8716 * newly-allocated list of windows inside the group.
8721 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8723 GList *toplevels, *toplevel, *group_windows;
8725 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8727 group_windows = NULL;
8728 toplevels = gtk_window_list_toplevels ();
8730 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8732 GtkWindow *window = toplevel->data;
8734 if (window_group == window->priv->group)
8735 group_windows = g_list_prepend (group_windows, window);
8738 g_list_free (toplevels);
8740 return g_list_reverse (group_windows);
8744 * gtk_window_get_group:
8745 * @window: (allow-none): a #GtkWindow, or %NULL
8747 * Returns the group for @window or the default group, if
8748 * @window is %NULL or if @window does not have an explicit
8751 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8756 gtk_window_get_group (GtkWindow *window)
8758 if (window && window->priv->group)
8759 return window->priv->group;
8762 static GtkWindowGroup *default_group = NULL;
8765 default_group = gtk_window_group_new ();
8767 return default_group;
8772 * gtk_window_has_group:
8773 * @window: a #GtkWindow
8775 * Returns whether @window has an explicit window group.
8777 * Return value: %TRUE if @window has an explicit window group.
8782 gtk_window_has_group (GtkWindow *window)
8784 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8786 return window->priv->group != NULL;
8790 * gtk_window_group_get_current_grab:
8791 * @window_group: a #GtkWindowGroup
8793 * Gets the current grab widget of the given group,
8794 * see gtk_grab_add().
8796 * Returns: (transfer none): the current grab widget of the group
8801 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8803 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8805 if (window_group->priv->grabs)
8806 return GTK_WIDGET (window_group->priv->grabs->data);
8811 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8814 GtkWindowGroupPrivate *priv;
8816 priv = window_group->priv;
8817 priv->grabs = g_slist_prepend (priv->grabs, widget);
8821 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8824 GtkWindowGroupPrivate *priv;
8826 priv = window_group->priv;
8827 priv->grabs = g_slist_remove (priv->grabs, widget);
8832 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8835 gboolean block_others)
8837 GtkWindowGroupPrivate *priv;
8838 GtkDeviceGrabInfo *info;
8840 priv = window_group->priv;
8842 info = g_slice_new0 (GtkDeviceGrabInfo);
8843 info->widget = widget;
8844 info->device = device;
8845 info->block_others = block_others;
8847 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8851 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8855 GtkWindowGroupPrivate *priv;
8856 GtkDeviceGrabInfo *info;
8857 GSList *list, *node = NULL;
8858 GdkDevice *other_device;
8860 priv = window_group->priv;
8861 other_device = gdk_device_get_associated_device (device);
8862 list = priv->device_grabs;
8868 if (info->widget == widget &&
8869 (info->device == device ||
8870 info->device == other_device))
8883 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8884 g_slice_free (GtkDeviceGrabInfo, info);
8889 * gtk_window_group_get_current_device_grab:
8890 * @window_group: a #GtkWindowGroup
8891 * @device: a #GdkDevice
8893 * Returns the current grab widget for @device, or %NULL if none.
8895 * Returns: (transfer none): The grab widget, or %NULL
8900 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8903 GtkWindowGroupPrivate *priv;
8904 GtkDeviceGrabInfo *info;
8905 GdkDevice *other_device;
8908 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8909 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8911 priv = window_group->priv;
8912 list = priv->device_grabs;
8913 other_device = gdk_device_get_associated_device (device);
8920 if (info->device == device ||
8921 info->device == other_device)
8922 return info->widget;
8929 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8933 GtkWindowGroupPrivate *priv;
8934 GtkDeviceGrabInfo *info;
8935 GdkDevice *other_device;
8938 priv = window_group->priv;
8939 other_device = gdk_device_get_associated_device (device);
8940 list = priv->device_grabs;
8947 /* Look for blocking grabs on other device pairs
8948 * that have the passed widget within the GTK+ grab.
8950 if (info->block_others &&
8951 info->device != device &&
8952 info->device != other_device &&
8953 (info->widget == widget ||
8954 gtk_widget_is_ancestor (widget, info->widget)))
8962 Derived from XParseGeometry() in XFree86
8964 Copyright 1985, 1986, 1987,1998 The Open Group
8966 All Rights Reserved.
8968 The above copyright notice and this permission notice shall be included
8969 in all copies or substantial portions of the Software.
8971 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8972 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8973 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8974 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8975 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8976 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8977 OTHER DEALINGS IN THE SOFTWARE.
8979 Except as contained in this notice, the name of The Open Group shall
8980 not be used in advertising or otherwise to promote the sale, use or
8981 other dealings in this Software without prior written authorization
8982 from The Open Group.
8987 * XParseGeometry parses strings of the form
8988 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8989 * width, height, xoffset, and yoffset are unsigned integers.
8990 * Example: "=80x24+300-49"
8991 * The equal sign is optional.
8992 * It returns a bitmask that indicates which of the four values
8993 * were actually found in the string. For each value found,
8994 * the corresponding argument is updated; for each value
8995 * not found, the corresponding argument is left unchanged.
8998 /* The following code is from Xlib, and is minimally modified, so we
8999 * can track any upstream changes if required. Don't change this
9000 * code. Or if you do, put in a huge comment marking which thing
9005 read_int (gchar *string,
9013 else if (*string == '-')
9019 for (; (*string >= '0') && (*string <= '9'); string++)
9021 result = (result * 10) + (*string - '0');
9033 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
9034 * value (x, y, width, height) was found in the parsed string.
9036 #define NoValue 0x0000
9037 #define XValue 0x0001
9038 #define YValue 0x0002
9039 #define WidthValue 0x0004
9040 #define HeightValue 0x0008
9041 #define AllValues 0x000F
9042 #define XNegative 0x0010
9043 #define YNegative 0x0020
9045 /* Try not to reformat/modify, so we can compare/sync with X sources */
9047 gtk_XParseGeometry (const char *string,
9050 unsigned int *width,
9051 unsigned int *height)
9055 unsigned int tempWidth, tempHeight;
9057 char *nextCharacter;
9059 /* These initializations are just to silence gcc */
9065 if ( (string == NULL) || (*string == '\0')) return(mask);
9067 string++; /* ignore possible '=' at beg of geometry spec */
9069 strind = (char *)string;
9070 if (*strind != '+' && *strind != '-' && *strind != 'x') {
9071 tempWidth = read_int(strind, &nextCharacter);
9072 if (strind == nextCharacter)
9074 strind = nextCharacter;
9078 if (*strind == 'x' || *strind == 'X') {
9080 tempHeight = read_int(strind, &nextCharacter);
9081 if (strind == nextCharacter)
9083 strind = nextCharacter;
9084 mask |= HeightValue;
9087 if ((*strind == '+') || (*strind == '-')) {
9088 if (*strind == '-') {
9090 tempX = -read_int(strind, &nextCharacter);
9091 if (strind == nextCharacter)
9093 strind = nextCharacter;
9099 tempX = read_int(strind, &nextCharacter);
9100 if (strind == nextCharacter)
9102 strind = nextCharacter;
9105 if ((*strind == '+') || (*strind == '-')) {
9106 if (*strind == '-') {
9108 tempY = -read_int(strind, &nextCharacter);
9109 if (strind == nextCharacter)
9111 strind = nextCharacter;
9118 tempY = read_int(strind, &nextCharacter);
9119 if (strind == nextCharacter)
9121 strind = nextCharacter;
9127 /* If strind isn't at the end of the string the it's an invalid
9128 geometry specification. */
9130 if (*strind != '\0') return (0);
9136 if (mask & WidthValue)
9138 if (mask & HeightValue)
9139 *height = tempHeight;
9144 * gtk_window_parse_geometry:
9145 * @window: a #GtkWindow
9146 * @geometry: geometry string
9148 * Parses a standard X Window System geometry string - see the
9149 * manual page for X (type 'man X') for details on this.
9150 * gtk_window_parse_geometry() does work on all GTK+ ports
9151 * including Win32 but is primarily intended for an X environment.
9153 * If either a size or a position can be extracted from the
9154 * geometry string, gtk_window_parse_geometry() returns %TRUE
9155 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9156 * to resize/move the window.
9158 * If gtk_window_parse_geometry() returns %TRUE, it will also
9159 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9160 * indicating to the window manager that the size/position of
9161 * the window was user-specified. This causes most window
9162 * managers to honor the geometry.
9164 * Note that for gtk_window_parse_geometry() to work as expected, it has
9165 * to be called when the window has its "final" size, i.e. after calling
9166 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9169 * #include <gtk/gtk.h>
9172 * fill_with_content (GtkWidget *vbox)
9174 * /* fill with content... */
9178 * main (int argc, char *argv[])
9180 * GtkWidget *window, *vbox;
9181 * GdkGeometry size_hints = {
9182 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9185 * gtk_init (&argc, &argv);
9187 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9188 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9190 * gtk_container_add (GTK_CONTAINER (window), vbox);
9191 * fill_with_content (vbox);
9192 * gtk_widget_show_all (vbox);
9194 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9197 * GDK_HINT_MIN_SIZE |
9198 * GDK_HINT_BASE_SIZE |
9199 * GDK_HINT_RESIZE_INC);
9203 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9204 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9207 * gtk_widget_show_all (window);
9214 * Return value: %TRUE if string was parsed successfully
9217 gtk_window_parse_geometry (GtkWindow *window,
9218 const gchar *geometry)
9220 gint result, x = 0, y = 0;
9224 gboolean size_set, pos_set;
9227 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9228 g_return_val_if_fail (geometry != NULL, FALSE);
9230 child = gtk_bin_get_child (GTK_BIN (window));
9231 if (!child || !gtk_widget_get_visible (child))
9232 g_warning ("gtk_window_parse_geometry() called on a window with no "
9233 "visible children; the window should be set up before "
9234 "gtk_window_parse_geometry() is called.");
9236 screen = gtk_window_check_screen (window);
9238 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9241 if ((result & WidthValue) || (result & HeightValue))
9243 gtk_window_set_default_size_internal (window,
9244 TRUE, result & WidthValue ? w : -1,
9245 TRUE, result & HeightValue ? h : -1,
9250 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9252 grav = GDK_GRAVITY_NORTH_WEST;
9254 if ((result & XNegative) && (result & YNegative))
9255 grav = GDK_GRAVITY_SOUTH_EAST;
9256 else if (result & XNegative)
9257 grav = GDK_GRAVITY_NORTH_EAST;
9258 else if (result & YNegative)
9259 grav = GDK_GRAVITY_SOUTH_WEST;
9261 if ((result & XValue) == 0)
9264 if ((result & YValue) == 0)
9267 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9268 grav == GDK_GRAVITY_SOUTH_EAST)
9269 y = gdk_screen_get_height (screen) - h + y;
9271 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9272 grav == GDK_GRAVITY_NORTH_EAST)
9273 x = gdk_screen_get_width (screen) - w + x;
9275 /* we don't let you put a window offscreen; maybe some people would
9276 * prefer to be able to, but it's kind of a bogus thing to do.
9285 if ((result & XValue) || (result & YValue))
9287 gtk_window_set_gravity (window, grav);
9288 gtk_window_move (window, x, y);
9292 if (size_set || pos_set)
9294 /* Set USSize, USPosition hints */
9295 GtkWindowGeometryInfo *info;
9297 info = gtk_window_get_geometry_info (window, TRUE);
9300 info->mask |= GDK_HINT_USER_POS;
9302 info->mask |= GDK_HINT_USER_SIZE;
9309 gtk_window_mnemonic_hash_foreach (guint keyval,
9315 GtkWindowKeysForeachFunc func;
9319 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9323 _gtk_window_keys_foreach (GtkWindow *window,
9324 GtkWindowKeysForeachFunc func,
9328 GtkMnemonicHash *mnemonic_hash;
9332 GtkWindowKeysForeachFunc func;
9336 info.window = window;
9338 info.func_data = func_data;
9340 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9342 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9343 gtk_window_mnemonic_hash_foreach, &info);
9345 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9348 GtkAccelGroup *group = groups->data;
9351 for (i = 0; i < group->priv->n_accels; i++)
9353 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9356 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9359 groups = groups->next;
9364 gtk_window_keys_changed (GtkWindow *window)
9366 gtk_window_free_key_hash (window);
9367 gtk_window_get_key_hash (window);
9370 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9372 struct _GtkWindowKeyEntry
9376 guint is_mnemonic : 1;
9380 window_key_entry_destroy (gpointer data)
9382 g_slice_free (GtkWindowKeyEntry, data);
9386 add_to_key_hash (GtkWindow *window,
9388 GdkModifierType modifiers,
9389 gboolean is_mnemonic,
9392 GtkKeyHash *key_hash = data;
9394 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9396 entry->keyval = keyval;
9397 entry->modifiers = modifiers;
9398 entry->is_mnemonic = is_mnemonic;
9400 /* GtkAccelGroup stores lowercased accelerators. To deal
9401 * with this, if <Shift> was specified, uppercase.
9403 if (modifiers & GDK_SHIFT_MASK)
9405 if (keyval == GDK_KEY_Tab)
9406 keyval = GDK_KEY_ISO_Left_Tab;
9408 keyval = gdk_keyval_to_upper (keyval);
9411 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9415 gtk_window_get_key_hash (GtkWindow *window)
9417 GdkScreen *screen = gtk_window_check_screen (window);
9418 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9423 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9424 (GDestroyNotify)window_key_entry_destroy);
9425 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9426 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9432 gtk_window_free_key_hash (GtkWindow *window)
9434 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9437 _gtk_key_hash_free (key_hash);
9438 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9443 * gtk_window_activate_key:
9444 * @window: a #GtkWindow
9445 * @event: a #GdkEventKey
9447 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9448 * called by the default ::key_press_event handler for toplevel windows,
9449 * however in some cases it may be useful to call this directly when
9450 * overriding the standard key handling for a toplevel window.
9452 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9457 gtk_window_activate_key (GtkWindow *window,
9460 GtkKeyHash *key_hash;
9461 GtkWindowKeyEntry *found_entry = NULL;
9462 gboolean enable_mnemonics;
9463 gboolean enable_accels;
9465 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9466 g_return_val_if_fail (event != NULL, FALSE);
9468 key_hash = gtk_window_get_key_hash (window);
9473 GSList *entries = _gtk_key_hash_lookup (key_hash,
9474 event->hardware_keycode,
9476 gtk_accelerator_get_default_mod_mask (),
9479 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9480 "gtk-enable-mnemonics", &enable_mnemonics,
9481 "gtk-enable-accels", &enable_accels,
9484 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9486 GtkWindowKeyEntry *entry = tmp_list->data;
9487 if (entry->is_mnemonic)
9489 if (enable_mnemonics)
9491 found_entry = entry;
9497 if (enable_accels && !found_entry)
9499 found_entry = entry;
9504 g_slist_free (entries);
9509 if (found_entry->is_mnemonic)
9511 if (enable_mnemonics)
9512 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9513 found_entry->modifiers);
9518 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9519 found_entry->modifiers);
9527 window_update_has_focus (GtkWindow *window)
9529 GtkWindowPrivate *priv = window->priv;
9530 GtkWidget *widget = GTK_WIDGET (window);
9531 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9533 if (has_focus != priv->has_focus)
9535 priv->has_focus = has_focus;
9539 if (priv->focus_widget &&
9540 priv->focus_widget != widget &&
9541 !gtk_widget_has_focus (priv->focus_widget))
9542 do_focus_change (priv->focus_widget, TRUE);
9546 if (priv->focus_widget &&
9547 priv->focus_widget != widget &&
9548 gtk_widget_has_focus (priv->focus_widget))
9549 do_focus_change (priv->focus_widget, FALSE);
9555 * _gtk_window_set_is_active:
9556 * @window: a #GtkWindow
9557 * @is_active: %TRUE if the window is in the currently active toplevel
9559 * Internal function that sets whether the #GtkWindow is part
9560 * of the currently active toplevel window (taking into account inter-process
9564 _gtk_window_set_is_active (GtkWindow *window,
9567 GtkWindowPrivate *priv;
9569 g_return_if_fail (GTK_IS_WINDOW (window));
9571 priv = window->priv;
9573 is_active = is_active != FALSE;
9575 if (is_active != priv->is_active)
9577 priv->is_active = is_active;
9578 window_update_has_focus (window);
9580 g_object_notify (G_OBJECT (window), "is-active");
9585 * _gtk_window_set_is_toplevel:
9586 * @window: a #GtkWindow
9587 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9588 * child of the root window); %FALSE if it is not (for example, for an
9589 * in-process, parented GtkPlug)
9591 * Internal function used by #GtkPlug when it gets parented/unparented by a
9592 * #GtkSocket. This keeps the @window's #GTK_WINDOW_TOPLEVEL flag in sync
9593 * with the global list of toplevel windows.
9596 _gtk_window_set_is_toplevel (GtkWindow *window,
9597 gboolean is_toplevel)
9600 GtkWidget *toplevel;
9602 widget = GTK_WIDGET (window);
9604 if (gtk_widget_is_toplevel (widget))
9605 g_assert (g_slist_find (toplevel_list, window) != NULL);
9607 g_assert (g_slist_find (toplevel_list, window) == NULL);
9609 if (is_toplevel == gtk_widget_is_toplevel (widget))
9614 /* Pass through regular pathways of an embedded toplevel
9615 * to go through unmapping and hiding the widget before
9616 * becomming a toplevel again.
9618 * We remain hidden after becomming toplevel in order to
9619 * avoid problems during an embedded toplevel's dispose cycle
9620 * (When a toplevel window is shown it tries to grab focus again,
9621 * this causes problems while disposing).
9623 gtk_widget_hide (widget);
9625 /* Save the toplevel this widget was previously anchored into before
9626 * propagating a hierarchy-changed.
9628 * Usually this happens by way of gtk_widget_unparent() and we are
9629 * already unanchored at this point, just adding this clause incase
9630 * things happen differently.
9632 toplevel = gtk_widget_get_toplevel (widget);
9633 if (!gtk_widget_is_toplevel (toplevel))
9636 _gtk_widget_set_is_toplevel (widget, TRUE);
9638 /* When a window becomes toplevel after being embedded and anchored
9639 * into another window we need to unset its anchored flag so that
9640 * the hierarchy changed signal kicks in properly.
9642 _gtk_widget_set_anchored (widget, FALSE);
9643 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9645 toplevel_list = g_slist_prepend (toplevel_list, window);
9649 _gtk_widget_set_is_toplevel (widget, FALSE);
9650 toplevel_list = g_slist_remove (toplevel_list, window);
9652 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9657 * _gtk_window_set_has_toplevel_focus:
9658 * @window: a #GtkWindow
9659 * @has_toplevel_focus: %TRUE if the in
9661 * Internal function that sets whether the keyboard focus for the
9662 * toplevel window (taking into account inter-process embedding.)
9665 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9666 gboolean has_toplevel_focus)
9668 GtkWindowPrivate *priv;
9670 g_return_if_fail (GTK_IS_WINDOW (window));
9672 priv = window->priv;
9674 has_toplevel_focus = has_toplevel_focus != FALSE;
9676 if (has_toplevel_focus != priv->has_toplevel_focus)
9678 priv->has_toplevel_focus = has_toplevel_focus;
9679 window_update_has_focus (window);
9681 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9686 * gtk_window_set_auto_startup_notification:
9687 * @setting: %TRUE to automatically do startup notification
9689 * By default, after showing the first #GtkWindow, GTK+ calls
9690 * gdk_notify_startup_complete(). Call this function to disable
9691 * the automatic startup notification. You might do this if your
9692 * first window is a splash screen, and you want to delay notification
9693 * until after your real main window has been shown, for example.
9695 * In that example, you would disable startup notification
9696 * temporarily, show your splash screen, then re-enable it so that
9697 * showing the main window would automatically result in notification.
9702 gtk_window_set_auto_startup_notification (gboolean setting)
9704 disable_startup_notification = !setting;
9708 * gtk_window_get_window_type:
9709 * @window: a #GtkWindow
9711 * Gets the type of the window. See #GtkWindowType.
9713 * Return value: the type of the window
9718 gtk_window_get_window_type (GtkWindow *window)
9720 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9722 return window->priv->type;
9726 * gtk_window_get_mnemonics_visible:
9727 * @window: a #GtkWindow
9729 * Gets the value of the #GtkWindow:mnemonics-visible property.
9731 * Returns: %TRUE if mnemonics are supposed to be visible
9737 gtk_window_get_mnemonics_visible (GtkWindow *window)
9739 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9741 return window->priv->mnemonics_visible;
9745 * gtk_window_set_mnemonics_visible:
9746 * @window: a #GtkWindow
9747 * @setting: the new value
9749 * Sets the #GtkWindow:mnemonics-visible property.
9754 gtk_window_set_mnemonics_visible (GtkWindow *window,
9757 GtkWindowPrivate *priv;
9759 g_return_if_fail (GTK_IS_WINDOW (window));
9761 priv = window->priv;
9763 setting = setting != FALSE;
9765 if (priv->mnemonics_visible != setting)
9767 priv->mnemonics_visible = setting;
9768 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9771 if (priv->auto_mnemonics_timeout_id)
9773 g_source_remove (priv->auto_mnemonics_timeout_id);
9774 priv->auto_mnemonics_timeout_id = 0;
9777 priv->mnemonics_visible_set = TRUE;
9781 set_auto_mnemonics_visible_cb (gpointer data)
9783 GtkWindow *window = data;
9785 gtk_window_set_mnemonics_visible (window, TRUE);
9787 window->priv->auto_mnemonics_timeout_id = 0;
9793 _gtk_window_set_auto_mnemonics_visible (GtkWindow *window)
9795 g_return_if_fail (GTK_IS_WINDOW (window));
9797 if (window->priv->auto_mnemonics_timeout_id)
9800 window->priv->auto_mnemonics_timeout_id =
9801 gdk_threads_add_timeout (AUTO_MNEMONICS_DELAY, set_auto_mnemonics_visible_cb, window);
9805 * gtk_window_get_focus_visible:
9806 * @window: a #GtkWindow
9808 * Gets the value of the #GtkWindow:focus-visible property.
9810 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9816 gtk_window_get_focus_visible (GtkWindow *window)
9818 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9820 return window->priv->focus_visible;
9824 * gtk_window_set_focus_visible:
9825 * @window: a #GtkWindow
9826 * @setting: the new value
9828 * Sets the #GtkWindow:focus-visible property.
9833 gtk_window_set_focus_visible (GtkWindow *window,
9836 GtkWindowPrivate *priv;
9838 g_return_if_fail (GTK_IS_WINDOW (window));
9840 priv = window->priv;
9842 setting = setting != FALSE;
9844 if (priv->focus_visible != setting)
9846 priv->focus_visible = setting;
9847 g_object_notify (G_OBJECT (window), "focus-visible");
9852 _gtk_window_get_wmclass (GtkWindow *window,
9853 gchar **wmclass_name,
9854 gchar **wmclass_class)
9856 GtkWindowPrivate *priv = window->priv;
9858 *wmclass_name = priv->wmclass_name;
9859 *wmclass_class = priv->wmclass_class;
9863 * gtk_window_set_has_user_ref_count:
9864 * @window: a #GtkWindow
9865 * @setting: the new value
9867 * Tells GTK+ whether to drop its extra reference to the window
9868 * when gtk_widget_destroy() is called.
9870 * This function is only exported for the benefit of language
9871 * bindings which may need to keep the window alive until their
9872 * wrapper object is garbage collected. There is no justification
9873 * for ever calling this function in an application.
9878 gtk_window_set_has_user_ref_count (GtkWindow *window,
9881 g_return_if_fail (GTK_IS_WINDOW (window));
9883 window->priv->has_user_ref_count = setting;
9887 ensure_state_flag_backdrop (GtkWidget *widget)
9890 gboolean window_focused = TRUE;
9892 window = gtk_widget_get_window (widget);
9894 window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9896 if (!window_focused)
9897 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
9899 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
9901 gtk_widget_queue_draw (widget);