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 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
103 struct _GtkWindowPrivate
105 GtkMnemonicHash *mnemonic_hash;
107 GtkWidget *attach_widget;
108 GtkWidget *default_widget;
109 GtkWidget *focus_widget;
110 GtkWindow *transient_parent;
111 GtkWindowGeometryInfo *geometry_info;
112 GtkWindowGroup *group;
114 GtkApplication *application;
116 GdkModifierType mnemonic_modifier;
117 GdkWindowTypeHint gdk_type_hint;
121 GdkWindow *grip_window;
125 gchar *wmclass_class;
129 guint keys_changed_handler;
131 guint32 initial_timestamp;
133 guint16 configure_request_count;
135 /* The following flags are initially TRUE (before a window is mapped).
136 * They cause us to compute a configure request that involves
137 * default-only parameters. Once mapped, we set them to FALSE.
138 * Then we set them to TRUE again on unmap (for position)
139 * and on unrealize (for size).
141 guint need_default_position : 1;
142 guint need_default_size : 1;
144 guint above_initially : 1;
145 guint accept_focus : 1;
146 guint below_initially : 1;
147 guint builder_visible : 1;
148 guint configure_notify_received : 1;
151 guint destroy_with_parent : 1;
152 guint focus_on_map : 1;
153 guint fullscreen_initially : 1;
155 guint has_user_ref_count : 1;
156 guint has_toplevel_focus : 1;
157 guint hide_titlebar_when_maximized : 1;
158 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
160 guint maximize_initially : 1;
161 guint mnemonics_visible : 1;
162 guint mnemonics_visible_set : 1;
163 guint focus_visible : 1;
165 guint opacity_set : 1;
167 guint reset_type_hint : 1;
169 guint skips_pager : 1;
170 guint skips_taskbar : 1;
171 guint stick_initially : 1;
172 guint transient_parent_group : 1;
173 guint type : 4; /* GtkWindowType */
174 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
175 * one of the original eight. If not,
177 * GDK_WINDOW_TYPE_HINT_NORMAL
180 guint has_resize_grip : 1;
181 guint resize_grip_visible : 1; /* don't use, just for "resize-
182 * grip-visible" notification
184 guint gravity : 5; /* GdkGravity */
211 PROP_DESTROY_WITH_PARENT,
212 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
217 PROP_SKIP_TASKBAR_HINT,
218 PROP_SKIP_PAGER_HINT,
228 PROP_HAS_RESIZE_GRIP,
229 PROP_RESIZE_GRIP_VISIBLE,
231 /* Readonly properties */
233 PROP_HAS_TOPLEVEL_FOCUS,
235 /* Writeonly properties */
238 PROP_MNEMONICS_VISIBLE,
249 guint using_default_icon : 1;
250 guint using_parent_icon : 1;
251 guint using_themed_icon : 1;
255 GdkGeometry geometry; /* Last set of geometry hints we set */
256 GdkWindowHints flags;
257 GdkRectangle configure_request;
258 } GtkWindowLastGeometryInfo;
260 struct _GtkWindowGeometryInfo
262 /* Properties that the app has set on the window
264 GdkGeometry geometry; /* Geometry hints */
266 GtkWidget *widget; /* subwidget to which hints apply */
267 /* from last gtk_window_resize () - if > 0, indicates that
268 * we should resize to this size.
273 /* From last gtk_window_move () prior to mapping -
274 * only used if initial_pos_set
279 /* Default size - used only the FIRST time we map a window,
284 /* whether to use initial_x, initial_y */
285 guint initial_pos_set : 1;
286 /* CENTER_ALWAYS or other position constraint changed since
287 * we sent the last configure request.
289 guint position_constraints_changed : 1;
291 /* if true, default_width, height should be multiplied by the
292 * increments and affect the geometry widget only
294 guint default_is_geometry : 1;
296 /* if true, resize_width, height should be multiplied by the
297 * increments and affect the geometry widget only
299 guint resize_is_geometry : 1;
301 GtkWindowLastGeometryInfo last;
305 struct _GtkDeviceGrabInfo
309 guint block_others : 1;
312 struct _GtkWindowGroupPrivate
315 GSList *device_grabs;
318 static void gtk_window_dispose (GObject *object);
319 static void gtk_window_finalize (GObject *object);
320 static void gtk_window_destroy (GtkWidget *widget);
321 static void gtk_window_show (GtkWidget *widget);
322 static void gtk_window_hide (GtkWidget *widget);
323 static void gtk_window_map (GtkWidget *widget);
324 static void gtk_window_unmap (GtkWidget *widget);
325 static void gtk_window_realize (GtkWidget *widget);
326 static void gtk_window_unrealize (GtkWidget *widget);
327 static void gtk_window_size_allocate (GtkWidget *widget,
328 GtkAllocation *allocation);
329 static gboolean gtk_window_map_event (GtkWidget *widget,
331 static gint gtk_window_configure_event (GtkWidget *widget,
332 GdkEventConfigure *event);
333 static gint gtk_window_key_press_event (GtkWidget *widget,
335 static gint gtk_window_key_release_event (GtkWidget *widget,
337 static gint gtk_window_button_press_event (GtkWidget *widget,
338 GdkEventButton *event);
339 static gint gtk_window_enter_notify_event (GtkWidget *widget,
340 GdkEventCrossing *event);
341 static gint gtk_window_leave_notify_event (GtkWidget *widget,
342 GdkEventCrossing *event);
343 static gint gtk_window_focus_in_event (GtkWidget *widget,
344 GdkEventFocus *event);
345 static gint gtk_window_focus_out_event (GtkWidget *widget,
346 GdkEventFocus *event);
347 static void gtk_window_style_updated (GtkWidget *widget);
348 static gboolean gtk_window_state_event (GtkWidget *widget,
349 GdkEventWindowState *event);
350 static void gtk_window_check_resize (GtkContainer *container);
351 static gint gtk_window_focus (GtkWidget *widget,
352 GtkDirectionType direction);
353 static void gtk_window_move_focus (GtkWidget *widget,
354 GtkDirectionType dir);
355 static void gtk_window_real_set_focus (GtkWindow *window,
357 static void gtk_window_direction_changed (GtkWidget *widget,
358 GtkTextDirection prev_dir);
359 static void gtk_window_state_changed (GtkWidget *widget,
360 GtkStateType previous_state);
362 static void gtk_window_real_activate_default (GtkWindow *window);
363 static void gtk_window_real_activate_focus (GtkWindow *window);
364 static void gtk_window_keys_changed (GtkWindow *window);
365 static gint gtk_window_draw (GtkWidget *widget,
367 static void gtk_window_unset_transient_for (GtkWindow *window);
368 static void gtk_window_transient_parent_realized (GtkWidget *parent,
370 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
373 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
375 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
378 static void gtk_window_move_resize (GtkWindow *window);
379 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
381 GdkGeometry *geometry_b,
383 static void gtk_window_constrain_size (GtkWindow *window,
384 GdkGeometry *geometry,
390 static void gtk_window_constrain_position (GtkWindow *window,
395 static void gtk_window_compute_hints (GtkWindow *window,
396 GdkGeometry *new_geometry,
398 static void gtk_window_compute_configure_request (GtkWindow *window,
399 GdkRectangle *request,
400 GdkGeometry *geometry,
403 static void gtk_window_set_default_size_internal (GtkWindow *window,
404 gboolean change_width,
406 gboolean change_height,
408 gboolean is_geometry);
410 static void update_themed_icon (GtkIconTheme *theme,
412 static GList *icon_list_from_theme (GtkWidget *widget,
414 static void gtk_window_realize_icon (GtkWindow *window);
415 static void gtk_window_unrealize_icon (GtkWindow *window);
416 static void resize_grip_create_window (GtkWindow *window);
417 static void resize_grip_destroy_window (GtkWindow *window);
418 static void update_grip_visibility (GtkWindow *window);
420 static void gtk_window_notify_keys_changed (GtkWindow *window);
421 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
422 static void gtk_window_free_key_hash (GtkWindow *window);
423 static void gtk_window_on_composited_changed (GdkScreen *screen,
425 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
428 static void gtk_window_set_theme_variant (GtkWindow *window);
430 static GSList *toplevel_list = NULL;
431 static guint window_signals[LAST_SIGNAL] = { 0 };
432 static GList *default_icon_list = NULL;
433 static gchar *default_icon_name = NULL;
434 static guint default_icon_serial = 0;
435 static gboolean disable_startup_notification = FALSE;
436 static gboolean sent_startup_notification = FALSE;
438 static GQuark quark_gtk_embedded = 0;
439 static GQuark quark_gtk_window_key_hash = 0;
440 static GQuark quark_gtk_window_icon_info = 0;
441 static GQuark quark_gtk_buildable_accels = 0;
443 static GtkBuildableIface *parent_buildable_iface;
445 static void gtk_window_set_property (GObject *object,
449 static void gtk_window_get_property (GObject *object,
455 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
456 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
459 const GValue *value);
460 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
461 GtkBuilder *builder);
462 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
465 const gchar *tagname,
466 GMarkupParser *parser,
468 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
471 const gchar *tagname,
475 static void gtk_window_get_preferred_width (GtkWidget *widget,
478 static void gtk_window_get_preferred_height (GtkWidget *widget,
482 static void ensure_state_flag_backdrop (GtkWidget *widget);
484 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
485 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
486 gtk_window_buildable_interface_init))
489 add_tab_bindings (GtkBindingSet *binding_set,
490 GdkModifierType modifiers,
491 GtkDirectionType direction)
493 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
495 GTK_TYPE_DIRECTION_TYPE, direction);
496 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
498 GTK_TYPE_DIRECTION_TYPE, direction);
502 add_arrow_bindings (GtkBindingSet *binding_set,
504 GtkDirectionType direction)
506 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
508 gtk_binding_entry_add_signal (binding_set, keysym, 0,
510 GTK_TYPE_DIRECTION_TYPE, direction);
511 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
513 GTK_TYPE_DIRECTION_TYPE, direction);
514 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
516 GTK_TYPE_DIRECTION_TYPE, direction);
517 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
519 GTK_TYPE_DIRECTION_TYPE, direction);
523 extract_time_from_startup_id (const gchar* startup_id)
525 gchar *timestr = g_strrstr (startup_id, "_TIME");
526 guint32 retval = GDK_CURRENT_TIME;
533 /* Skip past the "_TIME" part */
538 timestamp = g_ascii_strtoull (timestr, &end, 0);
539 if (errno == 0 && end != timestr)
547 startup_id_is_fake (const gchar* startup_id)
549 return strncmp (startup_id, "_TIME", 5) == 0;
553 gtk_window_class_init (GtkWindowClass *klass)
555 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
556 GtkWidgetClass *widget_class;
557 GtkContainerClass *container_class;
558 GtkBindingSet *binding_set;
560 widget_class = (GtkWidgetClass*) klass;
561 container_class = (GtkContainerClass*) klass;
563 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
564 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
565 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
566 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
568 gobject_class->dispose = gtk_window_dispose;
569 gobject_class->finalize = gtk_window_finalize;
571 gobject_class->set_property = gtk_window_set_property;
572 gobject_class->get_property = gtk_window_get_property;
574 widget_class->destroy = gtk_window_destroy;
575 widget_class->show = gtk_window_show;
576 widget_class->hide = gtk_window_hide;
577 widget_class->map = gtk_window_map;
578 widget_class->map_event = gtk_window_map_event;
579 widget_class->unmap = gtk_window_unmap;
580 widget_class->realize = gtk_window_realize;
581 widget_class->unrealize = gtk_window_unrealize;
582 widget_class->size_allocate = gtk_window_size_allocate;
583 widget_class->configure_event = gtk_window_configure_event;
584 widget_class->key_press_event = gtk_window_key_press_event;
585 widget_class->key_release_event = gtk_window_key_release_event;
586 widget_class->enter_notify_event = gtk_window_enter_notify_event;
587 widget_class->leave_notify_event = gtk_window_leave_notify_event;
588 widget_class->focus_in_event = gtk_window_focus_in_event;
589 widget_class->button_press_event = gtk_window_button_press_event;
590 widget_class->focus_out_event = gtk_window_focus_out_event;
591 widget_class->focus = gtk_window_focus;
592 widget_class->move_focus = gtk_window_move_focus;
593 widget_class->draw = gtk_window_draw;
594 widget_class->get_preferred_width = gtk_window_get_preferred_width;
595 widget_class->get_preferred_height = gtk_window_get_preferred_height;
596 widget_class->window_state_event = gtk_window_state_event;
597 widget_class->direction_changed = gtk_window_direction_changed;
598 widget_class->state_changed = gtk_window_state_changed;
599 widget_class->style_updated = gtk_window_style_updated;
601 container_class->check_resize = gtk_window_check_resize;
603 klass->set_focus = gtk_window_real_set_focus;
605 klass->activate_default = gtk_window_real_activate_default;
606 klass->activate_focus = gtk_window_real_activate_focus;
607 klass->keys_changed = gtk_window_keys_changed;
609 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
612 g_object_class_install_property (gobject_class,
614 g_param_spec_enum ("type",
616 P_("The type of the window"),
617 GTK_TYPE_WINDOW_TYPE,
619 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
621 g_object_class_install_property (gobject_class,
623 g_param_spec_string ("title",
625 P_("The title of the window"),
627 GTK_PARAM_READWRITE));
629 g_object_class_install_property (gobject_class,
631 g_param_spec_string ("role",
633 P_("Unique identifier for the window to be used when restoring a session"),
635 GTK_PARAM_READWRITE));
638 * GtkWindow:startup-id:
640 * The :startup-id is a write-only property for setting window's
641 * startup notification identifier. See gtk_window_set_startup_id()
646 g_object_class_install_property (gobject_class,
648 g_param_spec_string ("startup-id",
650 P_("Unique startup identifier for the window used by startup-notification"),
652 GTK_PARAM_WRITABLE));
654 g_object_class_install_property (gobject_class,
656 g_param_spec_boolean ("resizable",
658 P_("If TRUE, users can resize the window"),
660 GTK_PARAM_READWRITE));
662 g_object_class_install_property (gobject_class,
664 g_param_spec_boolean ("modal",
666 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
668 GTK_PARAM_READWRITE));
670 g_object_class_install_property (gobject_class,
672 g_param_spec_enum ("window-position",
673 P_("Window Position"),
674 P_("The initial position of the window"),
675 GTK_TYPE_WINDOW_POSITION,
677 GTK_PARAM_READWRITE));
679 g_object_class_install_property (gobject_class,
681 g_param_spec_int ("default-width",
683 P_("The default width of the window, used when initially showing the window"),
687 GTK_PARAM_READWRITE));
689 g_object_class_install_property (gobject_class,
691 g_param_spec_int ("default-height",
692 P_("Default Height"),
693 P_("The default height of the window, used when initially showing the window"),
697 GTK_PARAM_READWRITE));
699 g_object_class_install_property (gobject_class,
700 PROP_DESTROY_WITH_PARENT,
701 g_param_spec_boolean ("destroy-with-parent",
702 P_("Destroy with Parent"),
703 P_("If this window should be destroyed when the parent is destroyed"),
705 GTK_PARAM_READWRITE));
708 * GtkWindow:hide-titlebar-when-maximized:
710 * Whether the titlebar should be hidden during maximization.
714 g_object_class_install_property (gobject_class,
715 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
716 g_param_spec_boolean ("hide-titlebar-when-maximized",
717 P_("Hide the titlebar during maximization"),
718 P_("If this window's titlebar should be hidden when the window is maximized"),
720 GTK_PARAM_READWRITE));
722 g_object_class_install_property (gobject_class,
724 g_param_spec_object ("icon",
726 P_("Icon for this window"),
728 GTK_PARAM_READWRITE));
731 * GtkWindow:mnemonics-visible:
733 * Whether mnemonics are currently visible in this window.
735 * This property is maintained by GTK+ based on the
736 * #GtkSettings:gtk-auto-mnemonics setting and user input,
737 * and should not be set by applications.
741 g_object_class_install_property (gobject_class,
742 PROP_MNEMONICS_VISIBLE,
743 g_param_spec_boolean ("mnemonics-visible",
744 P_("Mnemonics Visible"),
745 P_("Whether mnemonics are currently visible in this window"),
747 GTK_PARAM_READWRITE));
750 * GtkWindow:focus-visible:
752 * Whether 'focus rectangles' are currently visible in this window.
754 * This property is maintained by GTK+ based on the
755 * #GtkSettings:gtk-visible-focus setting and user input
756 * and should not be set by applications.
760 g_object_class_install_property (gobject_class,
762 g_param_spec_boolean ("focus-visible",
764 P_("Whether focus rectangles are currently visible in this window"),
766 GTK_PARAM_READWRITE));
769 * GtkWindow:icon-name:
771 * The :icon-name property specifies the name of the themed icon to
772 * use as the window icon. See #GtkIconTheme for more details.
776 g_object_class_install_property (gobject_class,
778 g_param_spec_string ("icon-name",
780 P_("Name of the themed icon for this window"),
782 GTK_PARAM_READWRITE));
784 g_object_class_install_property (gobject_class,
786 g_param_spec_object ("screen",
788 P_("The screen where this window will be displayed"),
790 GTK_PARAM_READWRITE));
792 g_object_class_install_property (gobject_class,
794 g_param_spec_boolean ("is-active",
796 P_("Whether the toplevel is the current active window"),
798 GTK_PARAM_READABLE));
800 g_object_class_install_property (gobject_class,
801 PROP_HAS_TOPLEVEL_FOCUS,
802 g_param_spec_boolean ("has-toplevel-focus",
803 P_("Focus in Toplevel"),
804 P_("Whether the input focus is within this GtkWindow"),
806 GTK_PARAM_READABLE));
808 g_object_class_install_property (gobject_class,
810 g_param_spec_enum ("type-hint",
812 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
813 GDK_TYPE_WINDOW_TYPE_HINT,
814 GDK_WINDOW_TYPE_HINT_NORMAL,
815 GTK_PARAM_READWRITE));
817 g_object_class_install_property (gobject_class,
818 PROP_SKIP_TASKBAR_HINT,
819 g_param_spec_boolean ("skip-taskbar-hint",
821 P_("TRUE if the window should not be in the task bar."),
823 GTK_PARAM_READWRITE));
825 g_object_class_install_property (gobject_class,
826 PROP_SKIP_PAGER_HINT,
827 g_param_spec_boolean ("skip-pager-hint",
829 P_("TRUE if the window should not be in the pager."),
831 GTK_PARAM_READWRITE));
833 g_object_class_install_property (gobject_class,
835 g_param_spec_boolean ("urgency-hint",
837 P_("TRUE if the window should be brought to the user's attention."),
839 GTK_PARAM_READWRITE));
842 * GtkWindow:accept-focus:
844 * Whether the window should receive the input focus.
848 g_object_class_install_property (gobject_class,
850 g_param_spec_boolean ("accept-focus",
852 P_("TRUE if the window should receive the input focus."),
854 GTK_PARAM_READWRITE));
857 * GtkWindow:focus-on-map:
859 * Whether the window should receive the input focus when mapped.
863 g_object_class_install_property (gobject_class,
865 g_param_spec_boolean ("focus-on-map",
867 P_("TRUE if the window should receive the input focus when mapped."),
869 GTK_PARAM_READWRITE));
872 * GtkWindow:decorated:
874 * Whether the window should be decorated by the window manager.
878 g_object_class_install_property (gobject_class,
880 g_param_spec_boolean ("decorated",
882 P_("Whether the window should be decorated by the window manager"),
884 GTK_PARAM_READWRITE));
887 * GtkWindow:deletable:
889 * Whether the window frame should have a close button.
893 g_object_class_install_property (gobject_class,
895 g_param_spec_boolean ("deletable",
897 P_("Whether the window frame should have a close button"),
899 GTK_PARAM_READWRITE));
902 * GtkWindow:has-resize-grip:
904 * Whether the window has a corner resize grip.
906 * Note that the resize grip is only shown if the window is
907 * actually resizable and not maximized. Use
908 * #GtkWindow:resize-grip-visible to find out if the resize
909 * grip is currently shown.
913 g_object_class_install_property (gobject_class,
914 PROP_HAS_RESIZE_GRIP,
915 g_param_spec_boolean ("has-resize-grip",
917 P_("Specifies whether the window should have a resize grip"),
919 GTK_PARAM_READWRITE));
922 * GtkWindow:resize-grip-visible:
924 * Whether a corner resize grip is currently shown.
928 g_object_class_install_property (gobject_class,
929 PROP_RESIZE_GRIP_VISIBLE,
930 g_param_spec_boolean ("resize-grip-visible",
931 P_("Resize grip is visible"),
932 P_("Specifies whether the window's resize grip is visible."),
934 GTK_PARAM_READABLE));
940 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
941 * more details about window gravity.
945 g_object_class_install_property (gobject_class,
947 g_param_spec_enum ("gravity",
949 P_("The window gravity of the window"),
951 GDK_GRAVITY_NORTH_WEST,
952 GTK_PARAM_READWRITE));
956 * GtkWindow:transient-for:
958 * The transient parent of the window. See gtk_window_set_transient_for() for
959 * more details about transient windows.
963 g_object_class_install_property (gobject_class,
965 g_param_spec_object ("transient-for",
966 P_("Transient for Window"),
967 P_("The transient parent of the dialog"),
969 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
972 * GtkWindow:attached-to:
974 * The widget to which this window is attached.
975 * See gtk_window_set_attached_to().
977 * Examples of places where specifying this relation is useful are
978 * for instance a #GtkMenu created by a #GtkComboBox, a completion
979 * popup window created by #GtkEntry or a typeahead search entry
980 * created by #GtkTreeView.
984 g_object_class_install_property (gobject_class,
986 g_param_spec_object ("attached-to",
987 P_("Attached to Widget"),
988 P_("The widget where the window is attached"),
990 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
995 * The requested opacity of the window. See gtk_window_set_opacity() for
996 * more details about window opacity.
1000 g_object_class_install_property (gobject_class,
1002 g_param_spec_double ("opacity",
1003 P_("Opacity for Window"),
1004 P_("The opacity of the window, from 0 to 1"),
1008 GTK_PARAM_READWRITE));
1010 /* Style properties.
1012 gtk_widget_class_install_style_property (widget_class,
1013 g_param_spec_int ("resize-grip-width",
1014 P_("Width of resize grip"),
1015 P_("Width of resize grip"),
1016 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1018 gtk_widget_class_install_style_property (widget_class,
1019 g_param_spec_int ("resize-grip-height",
1020 P_("Height of resize grip"),
1021 P_("Height of resize grip"),
1022 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1026 * GtkWindow:application:
1028 * The #GtkApplication associated with the window.
1030 * The application will be kept alive for at least as long as it
1031 * has any windows associated with it (see g_application_hold()
1032 * for a way to keep it alive without windows).
1034 * Normally, the connection between the application and the window
1035 * will remain until the window is destroyed, but you can explicitly
1036 * remove it by setting the ::application property to %NULL.
1040 g_object_class_install_property (gobject_class,
1042 g_param_spec_object ("application",
1043 P_("GtkApplication"),
1044 P_("The GtkApplication for the window"),
1045 GTK_TYPE_APPLICATION,
1046 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1048 window_signals[SET_FOCUS] =
1049 g_signal_new (I_("set-focus"),
1050 G_TYPE_FROM_CLASS (gobject_class),
1052 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1054 _gtk_marshal_VOID__OBJECT,
1059 * GtkWindow::activate-focus:
1060 * @window: the window which received the signal
1062 * The ::activate-focus signal is a
1063 * <link linkend="keybinding-signals">keybinding signal</link>
1064 * which gets emitted when the user activates the currently
1065 * focused widget of @window.
1067 window_signals[ACTIVATE_FOCUS] =
1068 g_signal_new (I_("activate-focus"),
1069 G_TYPE_FROM_CLASS (gobject_class),
1070 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1071 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1073 _gtk_marshal_VOID__VOID,
1078 * GtkWindow::activate-default:
1079 * @window: the window which received the signal
1081 * The ::activate-default signal is a
1082 * <link linkend="keybinding-signals">keybinding signal</link>
1083 * which gets emitted when the user activates the default widget
1086 window_signals[ACTIVATE_DEFAULT] =
1087 g_signal_new (I_("activate-default"),
1088 G_TYPE_FROM_CLASS (gobject_class),
1089 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1090 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1092 _gtk_marshal_VOID__VOID,
1097 * GtkWindow::keys-changed:
1098 * @window: the window which received the signal
1100 * The ::keys-changed signal gets emitted when the set of accelerators
1101 * or mnemonics that are associated with @window changes.
1103 window_signals[KEYS_CHANGED] =
1104 g_signal_new (I_("keys-changed"),
1105 G_TYPE_FROM_CLASS (gobject_class),
1107 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1109 _gtk_marshal_VOID__VOID,
1117 binding_set = gtk_binding_set_by_class (klass);
1119 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1120 "activate-focus", 0);
1121 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1122 "activate-focus", 0);
1124 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1125 "activate-default", 0);
1126 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1127 "activate-default", 0);
1128 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1129 "activate-default", 0);
1131 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1132 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1133 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1134 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1136 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1137 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1138 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1139 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1141 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1145 gtk_window_init (GtkWindow *window)
1147 GtkWindowPrivate *priv;
1149 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1152 priv = window->priv;
1154 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1155 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1157 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1159 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1162 priv->wmclass_name = g_strdup (g_get_prgname ());
1163 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1164 priv->wm_role = NULL;
1165 priv->geometry_info = NULL;
1166 priv->type = GTK_WINDOW_TOPLEVEL;
1167 priv->focus_widget = NULL;
1168 priv->default_widget = NULL;
1169 priv->configure_request_count = 0;
1170 priv->resizable = TRUE;
1171 priv->configure_notify_received = FALSE;
1172 priv->position = GTK_WIN_POS_NONE;
1173 priv->need_default_size = TRUE;
1174 priv->need_default_position = TRUE;
1175 priv->modal = FALSE;
1176 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1177 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1178 priv->decorated = TRUE;
1179 priv->mnemonic_modifier = GDK_MOD1_MASK;
1180 priv->screen = gdk_screen_get_default ();
1182 priv->accept_focus = TRUE;
1183 priv->focus_on_map = TRUE;
1184 priv->deletable = TRUE;
1185 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1186 priv->opacity = 1.0;
1187 priv->startup_id = NULL;
1188 priv->initial_timestamp = GDK_CURRENT_TIME;
1189 priv->has_resize_grip = TRUE;
1190 priv->mnemonics_visible = TRUE;
1191 priv->focus_visible = TRUE;
1193 g_object_ref_sink (window);
1194 priv->has_user_ref_count = TRUE;
1195 toplevel_list = g_slist_prepend (toplevel_list, window);
1198 g_signal_connect (priv->screen, "composited-changed",
1199 G_CALLBACK (gtk_window_on_composited_changed), window);
1201 #ifdef GDK_WINDOWING_X11
1202 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1203 "notify::gtk-application-prefer-dark-theme",
1204 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1209 gtk_window_set_property (GObject *object,
1211 const GValue *value,
1214 GtkWindow *window = GTK_WINDOW (object);
1215 GtkWindowPrivate *priv = window->priv;
1220 priv->type = g_value_get_enum (value);
1223 gtk_window_set_title (window, g_value_get_string (value));
1226 gtk_window_set_role (window, g_value_get_string (value));
1228 case PROP_STARTUP_ID:
1229 gtk_window_set_startup_id (window, g_value_get_string (value));
1231 case PROP_RESIZABLE:
1232 gtk_window_set_resizable (window, g_value_get_boolean (value));
1235 gtk_window_set_modal (window, g_value_get_boolean (value));
1238 gtk_window_set_position (window, g_value_get_enum (value));
1240 case PROP_DEFAULT_WIDTH:
1241 gtk_window_set_default_size_internal (window,
1242 TRUE, g_value_get_int (value),
1245 case PROP_DEFAULT_HEIGHT:
1246 gtk_window_set_default_size_internal (window,
1248 TRUE, g_value_get_int (value), FALSE);
1250 case PROP_DESTROY_WITH_PARENT:
1251 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1253 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1254 gtk_window_set_hide_titlebar_when_maximized (window, g_value_get_boolean (value));
1257 gtk_window_set_icon (window,
1258 g_value_get_object (value));
1260 case PROP_ICON_NAME:
1261 gtk_window_set_icon_name (window, g_value_get_string (value));
1264 gtk_window_set_screen (window, g_value_get_object (value));
1266 case PROP_TYPE_HINT:
1267 gtk_window_set_type_hint (window,
1268 g_value_get_enum (value));
1270 case PROP_SKIP_TASKBAR_HINT:
1271 gtk_window_set_skip_taskbar_hint (window,
1272 g_value_get_boolean (value));
1274 case PROP_SKIP_PAGER_HINT:
1275 gtk_window_set_skip_pager_hint (window,
1276 g_value_get_boolean (value));
1278 case PROP_URGENCY_HINT:
1279 gtk_window_set_urgency_hint (window,
1280 g_value_get_boolean (value));
1282 case PROP_ACCEPT_FOCUS:
1283 gtk_window_set_accept_focus (window,
1284 g_value_get_boolean (value));
1286 case PROP_FOCUS_ON_MAP:
1287 gtk_window_set_focus_on_map (window,
1288 g_value_get_boolean (value));
1290 case PROP_DECORATED:
1291 gtk_window_set_decorated (window, g_value_get_boolean (value));
1293 case PROP_DELETABLE:
1294 gtk_window_set_deletable (window, g_value_get_boolean (value));
1297 gtk_window_set_gravity (window, g_value_get_enum (value));
1299 case PROP_TRANSIENT_FOR:
1300 gtk_window_set_transient_for (window, g_value_get_object (value));
1302 case PROP_ATTACHED_TO:
1303 gtk_window_set_attached_to (window, g_value_get_object (value));
1306 gtk_window_set_opacity (window, g_value_get_double (value));
1308 case PROP_HAS_RESIZE_GRIP:
1309 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1311 case PROP_APPLICATION:
1312 gtk_window_set_application (window, g_value_get_object (value));
1314 case PROP_MNEMONICS_VISIBLE:
1315 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1317 case PROP_FOCUS_VISIBLE:
1318 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1321 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1327 gtk_window_get_property (GObject *object,
1332 GtkWindow *window = GTK_WINDOW (object);
1333 GtkWindowPrivate *priv = window->priv;
1337 GtkWindowGeometryInfo *info;
1339 g_value_set_enum (value, priv->type);
1342 g_value_set_string (value, priv->wm_role);
1345 g_value_set_string (value, priv->title);
1347 case PROP_RESIZABLE:
1348 g_value_set_boolean (value, priv->resizable);
1351 g_value_set_boolean (value, priv->modal);
1354 g_value_set_enum (value, priv->position);
1356 case PROP_DEFAULT_WIDTH:
1357 info = gtk_window_get_geometry_info (window, FALSE);
1359 g_value_set_int (value, -1);
1361 g_value_set_int (value, info->default_width);
1363 case PROP_DEFAULT_HEIGHT:
1364 info = gtk_window_get_geometry_info (window, FALSE);
1366 g_value_set_int (value, -1);
1368 g_value_set_int (value, info->default_height);
1370 case PROP_DESTROY_WITH_PARENT:
1371 g_value_set_boolean (value, priv->destroy_with_parent);
1373 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1374 g_value_set_boolean (value, priv->hide_titlebar_when_maximized);
1377 g_value_set_object (value, gtk_window_get_icon (window));
1379 case PROP_ICON_NAME:
1380 g_value_set_string (value, gtk_window_get_icon_name (window));
1383 g_value_set_object (value, priv->screen);
1385 case PROP_IS_ACTIVE:
1386 g_value_set_boolean (value, priv->is_active);
1388 case PROP_HAS_TOPLEVEL_FOCUS:
1389 g_value_set_boolean (value, priv->has_toplevel_focus);
1391 case PROP_TYPE_HINT:
1392 g_value_set_enum (value, priv->type_hint);
1394 case PROP_SKIP_TASKBAR_HINT:
1395 g_value_set_boolean (value,
1396 gtk_window_get_skip_taskbar_hint (window));
1398 case PROP_SKIP_PAGER_HINT:
1399 g_value_set_boolean (value,
1400 gtk_window_get_skip_pager_hint (window));
1402 case PROP_URGENCY_HINT:
1403 g_value_set_boolean (value,
1404 gtk_window_get_urgency_hint (window));
1406 case PROP_ACCEPT_FOCUS:
1407 g_value_set_boolean (value,
1408 gtk_window_get_accept_focus (window));
1410 case PROP_FOCUS_ON_MAP:
1411 g_value_set_boolean (value,
1412 gtk_window_get_focus_on_map (window));
1414 case PROP_DECORATED:
1415 g_value_set_boolean (value, gtk_window_get_decorated (window));
1417 case PROP_DELETABLE:
1418 g_value_set_boolean (value, gtk_window_get_deletable (window));
1421 g_value_set_enum (value, gtk_window_get_gravity (window));
1423 case PROP_TRANSIENT_FOR:
1424 g_value_set_object (value, gtk_window_get_transient_for (window));
1426 case PROP_ATTACHED_TO:
1427 g_value_set_object (value, gtk_window_get_attached_to (window));
1430 g_value_set_double (value, gtk_window_get_opacity (window));
1432 case PROP_HAS_RESIZE_GRIP:
1433 g_value_set_boolean (value, priv->has_resize_grip);
1435 case PROP_RESIZE_GRIP_VISIBLE:
1436 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1438 case PROP_APPLICATION:
1439 g_value_set_object (value, gtk_window_get_application (window));
1441 case PROP_MNEMONICS_VISIBLE:
1442 g_value_set_boolean (value, priv->mnemonics_visible);
1444 case PROP_FOCUS_VISIBLE:
1445 g_value_set_boolean (value, priv->focus_visible);
1448 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1454 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1456 parent_buildable_iface = g_type_interface_peek_parent (iface);
1457 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1458 iface->parser_finished = gtk_window_buildable_parser_finished;
1459 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1460 iface->custom_finished = gtk_window_buildable_custom_finished;
1464 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1465 GtkBuilder *builder,
1467 const GValue *value)
1469 GtkWindow *window = GTK_WINDOW (buildable);
1470 GtkWindowPrivate *priv = window->priv;
1472 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1473 priv->builder_visible = TRUE;
1475 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1479 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1480 GtkBuilder *builder)
1482 GtkWindow *window = GTK_WINDOW (buildable);
1483 GtkWindowPrivate *priv = window->priv;
1487 if (priv->builder_visible)
1488 gtk_widget_show (GTK_WIDGET (buildable));
1490 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1491 for (l = accels; l; l = l->next)
1493 object = gtk_builder_get_object (builder, l->data);
1496 g_warning ("Unknown accel group %s specified in window %s",
1497 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1500 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1501 GTK_ACCEL_GROUP (object));
1505 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1507 parent_buildable_iface->parser_finished (buildable, builder);
1513 } GSListSubParserData;
1516 window_start_element (GMarkupParseContext *context,
1517 const gchar *element_name,
1518 const gchar **names,
1519 const gchar **values,
1524 GSListSubParserData *data = (GSListSubParserData*)user_data;
1526 if (strcmp (element_name, "group") == 0)
1528 for (i = 0; names[i]; i++)
1530 if (strcmp (names[i], "name") == 0)
1531 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1534 else if (strcmp (element_name, "accel-groups") == 0)
1537 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1542 static const GMarkupParser window_parser =
1544 window_start_element
1548 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1549 GtkBuilder *builder,
1551 const gchar *tagname,
1552 GMarkupParser *parser,
1555 GSListSubParserData *parser_data;
1557 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1558 tagname, parser, data))
1561 if (strcmp (tagname, "accel-groups") == 0)
1563 parser_data = g_slice_new0 (GSListSubParserData);
1564 parser_data->items = NULL;
1565 parser_data->object = G_OBJECT (buildable);
1567 *parser = window_parser;
1568 *data = parser_data;
1576 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1577 GtkBuilder *builder,
1579 const gchar *tagname,
1582 GSListSubParserData *data;
1584 parent_buildable_iface->custom_finished (buildable, builder, child,
1585 tagname, user_data);
1587 if (strcmp (tagname, "accel-groups") != 0)
1590 data = (GSListSubParserData*)user_data;
1592 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1593 data->items, (GDestroyNotify) g_slist_free);
1595 g_slice_free (GSListSubParserData, data);
1600 * @type: type of window
1602 * Creates a new #GtkWindow, which is a toplevel window that can
1603 * contain other widgets. Nearly always, the type of the window should
1604 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1605 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1606 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1607 * dialogs, though in some other toolkits dialogs are called "popups".
1608 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1609 * On X11, popup windows are not controlled by the <link
1610 * linkend="gtk-X11-arch">window manager</link>.
1612 * If you simply want an undecorated window (no window borders), use
1613 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1615 * Return value: a new #GtkWindow.
1618 gtk_window_new (GtkWindowType type)
1620 GtkWindowPrivate *priv;
1623 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1625 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1626 priv = window->priv;
1630 return GTK_WIDGET (window);
1634 * gtk_window_set_title:
1635 * @window: a #GtkWindow
1636 * @title: title of the window
1638 * Sets the title of the #GtkWindow. The title of a window will be
1639 * displayed in its title bar; on the X Window System, the title bar
1640 * is rendered by the <link linkend="gtk-X11-arch">window
1641 * manager</link>, so exactly how the title appears to users may vary
1642 * according to a user's exact configuration. The title should help a
1643 * user distinguish this window from other windows they may have
1644 * open. A good title might include the application name and current
1645 * document filename, for example.
1649 gtk_window_set_title (GtkWindow *window,
1652 GtkWindowPrivate *priv;
1656 g_return_if_fail (GTK_IS_WINDOW (window));
1658 priv = window->priv;
1659 widget = GTK_WIDGET (window);
1661 new_title = g_strdup (title);
1662 g_free (priv->title);
1663 priv->title = new_title;
1665 if (gtk_widget_get_realized (widget))
1667 gdk_window_set_title (gtk_widget_get_window (widget),
1671 g_object_notify (G_OBJECT (window), "title");
1675 * gtk_window_get_title:
1676 * @window: a #GtkWindow
1678 * Retrieves the title of the window. See gtk_window_set_title().
1680 * Return value: the title of the window, or %NULL if none has
1681 * been set explicitely. The returned string is owned by the widget
1682 * and must not be modified or freed.
1685 gtk_window_get_title (GtkWindow *window)
1687 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1689 return window->priv->title;
1693 * gtk_window_set_wmclass:
1694 * @window: a #GtkWindow
1695 * @wmclass_name: window name hint
1696 * @wmclass_class: window class hint
1698 * Don't use this function. It sets the X Window System "class" and
1699 * "name" hints for a window. According to the ICCCM, you should
1700 * always set these to the same value for all windows in an
1701 * application, and GTK+ sets them to that value by default, so calling
1702 * this function is sort of pointless. However, you may want to call
1703 * gtk_window_set_role() on each window in your application, for the
1704 * benefit of the session manager. Setting the role allows the window
1705 * manager to restore window positions when loading a saved session.
1709 gtk_window_set_wmclass (GtkWindow *window,
1710 const gchar *wmclass_name,
1711 const gchar *wmclass_class)
1713 GtkWindowPrivate *priv;
1715 g_return_if_fail (GTK_IS_WINDOW (window));
1717 priv = window->priv;
1719 g_free (priv->wmclass_name);
1720 priv->wmclass_name = g_strdup (wmclass_name);
1722 g_free (priv->wmclass_class);
1723 priv->wmclass_class = g_strdup (wmclass_class);
1725 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1726 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1730 * gtk_window_set_role:
1731 * @window: a #GtkWindow
1732 * @role: unique identifier for the window to be used when restoring a session
1734 * This function is only useful on X11, not with other GTK+ targets.
1736 * In combination with the window title, the window role allows a
1737 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1738 * same" window when an application is restarted. So for example you
1739 * might set the "toolbox" role on your app's toolbox window, so that
1740 * when the user restarts their session, the window manager can put
1741 * the toolbox back in the same place.
1743 * If a window already has a unique title, you don't need to set the
1744 * role, since the WM can use the title to identify the window when
1745 * restoring the session.
1749 gtk_window_set_role (GtkWindow *window,
1752 GtkWindowPrivate *priv;
1755 g_return_if_fail (GTK_IS_WINDOW (window));
1757 priv = window->priv;
1759 new_role = g_strdup (role);
1760 g_free (priv->wm_role);
1761 priv->wm_role = new_role;
1763 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1764 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1767 g_object_notify (G_OBJECT (window), "role");
1771 * gtk_window_set_startup_id:
1772 * @window: a #GtkWindow
1773 * @startup_id: a string with startup-notification identifier
1775 * Startup notification identifiers are used by desktop environment to
1776 * track application startup, to provide user feedback and other
1777 * features. This function changes the corresponding property on the
1778 * underlying GdkWindow. Normally, startup identifier is managed
1779 * automatically and you should only use this function in special cases
1780 * like transferring focus from other processes. You should use this
1781 * function before calling gtk_window_present() or any equivalent
1782 * function generating a window map event.
1784 * This function is only useful on X11, not with other GTK+ targets.
1789 gtk_window_set_startup_id (GtkWindow *window,
1790 const gchar *startup_id)
1792 GtkWindowPrivate *priv;
1795 g_return_if_fail (GTK_IS_WINDOW (window));
1797 priv = window->priv;
1798 widget = GTK_WIDGET (window);
1800 g_free (priv->startup_id);
1801 priv->startup_id = g_strdup (startup_id);
1803 if (gtk_widget_get_realized (widget))
1805 GdkWindow *gdk_window;
1806 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1808 gdk_window = gtk_widget_get_window (widget);
1810 #ifdef GDK_WINDOWING_X11
1811 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1812 gdk_x11_window_set_user_time (gdk_window, timestamp);
1815 /* Here we differentiate real and "fake" startup notification IDs,
1816 * constructed on purpose just to pass interaction timestamp
1818 if (startup_id_is_fake (priv->startup_id))
1819 gtk_window_present_with_time (window, timestamp);
1822 gdk_window_set_startup_id (gdk_window,
1825 /* If window is mapped, terminate the startup-notification too */
1826 if (gtk_widget_get_mapped (widget) &&
1827 !disable_startup_notification)
1828 gdk_notify_startup_complete_with_id (priv->startup_id);
1832 g_object_notify (G_OBJECT (window), "startup-id");
1836 * gtk_window_get_role:
1837 * @window: a #GtkWindow
1839 * Returns the role of the window. See gtk_window_set_role() for
1840 * further explanation.
1842 * Return value: the role of the window if set, or %NULL. The
1843 * returned is owned by the widget and must not be modified
1847 gtk_window_get_role (GtkWindow *window)
1849 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1851 return window->priv->wm_role;
1855 * gtk_window_set_focus:
1856 * @window: a #GtkWindow
1857 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1858 * any focus widget for the toplevel window.
1860 * If @focus is not the current focus widget, and is focusable, sets
1861 * it as the focus widget for the window. If @focus is %NULL, unsets
1862 * the focus widget for this window. To set the focus to a particular
1863 * widget in the toplevel, it is usually more convenient to use
1864 * gtk_widget_grab_focus() instead of this function.
1867 gtk_window_set_focus (GtkWindow *window,
1870 GtkWindowPrivate *priv;
1873 g_return_if_fail (GTK_IS_WINDOW (window));
1875 priv = window->priv;
1879 g_return_if_fail (GTK_IS_WIDGET (focus));
1880 g_return_if_fail (gtk_widget_get_can_focus (focus));
1884 gtk_widget_grab_focus (focus);
1887 /* Clear the existing focus chain, so that when we focus into
1888 * the window again, we start at the beginnning.
1890 GtkWidget *widget = priv->focus_widget;
1893 while ((parent = gtk_widget_get_parent (widget)))
1896 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1900 _gtk_window_internal_set_focus (window, NULL);
1905 _gtk_window_internal_set_focus (GtkWindow *window,
1908 GtkWindowPrivate *priv;
1910 g_return_if_fail (GTK_IS_WINDOW (window));
1912 priv = window->priv;
1914 if ((priv->focus_widget != focus) ||
1915 (focus && !gtk_widget_has_focus (focus)))
1916 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1920 * gtk_window_set_default:
1921 * @window: a #GtkWindow
1922 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1923 * default widget for the toplevel.
1925 * The default widget is the widget that's activated when the user
1926 * presses Enter in a dialog (for example). This function sets or
1927 * unsets the default widget for a #GtkWindow about. When setting
1928 * (rather than unsetting) the default widget it's generally easier to
1929 * call gtk_widget_grab_focus() on the widget. Before making a widget
1930 * the default widget, you must call gtk_widget_set_can_default() on the
1931 * widget you'd like to make the default.
1934 gtk_window_set_default (GtkWindow *window,
1935 GtkWidget *default_widget)
1937 GtkWindowPrivate *priv;
1939 g_return_if_fail (GTK_IS_WINDOW (window));
1941 priv = window->priv;
1944 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1946 if (priv->default_widget != default_widget)
1948 GtkWidget *old_default_widget = NULL;
1951 g_object_ref (default_widget);
1953 if (priv->default_widget)
1955 old_default_widget = priv->default_widget;
1957 if (priv->focus_widget != priv->default_widget ||
1958 !gtk_widget_get_receives_default (priv->default_widget))
1959 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1961 gtk_widget_queue_draw (priv->default_widget);
1964 priv->default_widget = default_widget;
1966 if (priv->default_widget)
1968 if (priv->focus_widget == NULL ||
1969 !gtk_widget_get_receives_default (priv->focus_widget))
1970 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1972 gtk_widget_queue_draw (priv->default_widget);
1975 if (old_default_widget)
1976 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1980 g_object_notify (G_OBJECT (default_widget), "has-default");
1981 g_object_unref (default_widget);
1987 * gtk_window_get_default_widget:
1988 * @window: a #GtkWindow
1990 * Returns the default widget for @window. See gtk_window_set_default()
1993 * Returns: (transfer none): the default widget, or %NULL if there is none.
1998 gtk_window_get_default_widget (GtkWindow *window)
2000 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2002 return window->priv->default_widget;
2006 handle_keys_changed (gpointer data)
2008 GtkWindow *window = GTK_WINDOW (data);
2009 GtkWindowPrivate *priv = window->priv;
2011 if (priv->keys_changed_handler)
2013 g_source_remove (priv->keys_changed_handler);
2014 priv->keys_changed_handler = 0;
2017 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
2023 gtk_window_notify_keys_changed (GtkWindow *window)
2025 GtkWindowPrivate *priv = window->priv;
2027 if (!priv->keys_changed_handler)
2028 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
2032 * gtk_window_add_accel_group:
2033 * @window: window to attach accelerator group to
2034 * @accel_group: a #GtkAccelGroup
2036 * Associate @accel_group with @window, such that calling
2037 * gtk_accel_groups_activate() on @window will activate accelerators
2041 gtk_window_add_accel_group (GtkWindow *window,
2042 GtkAccelGroup *accel_group)
2044 g_return_if_fail (GTK_IS_WINDOW (window));
2045 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2047 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
2048 g_signal_connect_object (accel_group, "accel-changed",
2049 G_CALLBACK (gtk_window_notify_keys_changed),
2050 window, G_CONNECT_SWAPPED);
2051 gtk_window_notify_keys_changed (window);
2055 * gtk_window_remove_accel_group:
2056 * @window: a #GtkWindow
2057 * @accel_group: a #GtkAccelGroup
2059 * Reverses the effects of gtk_window_add_accel_group().
2062 gtk_window_remove_accel_group (GtkWindow *window,
2063 GtkAccelGroup *accel_group)
2065 g_return_if_fail (GTK_IS_WINDOW (window));
2066 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2068 g_signal_handlers_disconnect_by_func (accel_group,
2069 gtk_window_notify_keys_changed,
2071 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2072 gtk_window_notify_keys_changed (window);
2075 static GtkMnemonicHash *
2076 gtk_window_get_mnemonic_hash (GtkWindow *window,
2079 GtkWindowPrivate *private = window->priv;
2081 if (!private->mnemonic_hash && create)
2082 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2084 return private->mnemonic_hash;
2088 * gtk_window_add_mnemonic:
2089 * @window: a #GtkWindow
2090 * @keyval: the mnemonic
2091 * @target: the widget that gets activated by the mnemonic
2093 * Adds a mnemonic to this window.
2096 gtk_window_add_mnemonic (GtkWindow *window,
2100 g_return_if_fail (GTK_IS_WINDOW (window));
2101 g_return_if_fail (GTK_IS_WIDGET (target));
2103 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2105 gtk_window_notify_keys_changed (window);
2109 * gtk_window_remove_mnemonic:
2110 * @window: a #GtkWindow
2111 * @keyval: the mnemonic
2112 * @target: the widget that gets activated by the mnemonic
2114 * Removes a mnemonic from this window.
2117 gtk_window_remove_mnemonic (GtkWindow *window,
2121 g_return_if_fail (GTK_IS_WINDOW (window));
2122 g_return_if_fail (GTK_IS_WIDGET (target));
2124 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2126 gtk_window_notify_keys_changed (window);
2130 * gtk_window_mnemonic_activate:
2131 * @window: a #GtkWindow
2132 * @keyval: the mnemonic
2133 * @modifier: the modifiers
2135 * Activates the targets associated with the mnemonic.
2137 * Returns: %TRUE if the activation is done.
2140 gtk_window_mnemonic_activate (GtkWindow *window,
2142 GdkModifierType modifier)
2144 GtkWindowPrivate *priv;
2146 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2148 priv = window->priv;
2150 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2152 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2154 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2161 * gtk_window_set_mnemonic_modifier:
2162 * @window: a #GtkWindow
2163 * @modifier: the modifier mask used to activate
2164 * mnemonics on this window.
2166 * Sets the mnemonic modifier for this window.
2169 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2170 GdkModifierType modifier)
2172 GtkWindowPrivate *priv;
2174 g_return_if_fail (GTK_IS_WINDOW (window));
2175 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2177 priv = window->priv;
2179 priv->mnemonic_modifier = modifier;
2180 gtk_window_notify_keys_changed (window);
2184 * gtk_window_get_mnemonic_modifier:
2185 * @window: a #GtkWindow
2187 * Returns the mnemonic modifier for this window. See
2188 * gtk_window_set_mnemonic_modifier().
2190 * Return value: the modifier mask used to activate
2191 * mnemonics on this window.
2194 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2196 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2198 return window->priv->mnemonic_modifier;
2202 * gtk_window_set_position:
2203 * @window: a #GtkWindow.
2204 * @position: a position constraint.
2206 * Sets a position constraint for this window. If the old or new
2207 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2208 * the window to be repositioned to satisfy the new constraint.
2211 gtk_window_set_position (GtkWindow *window,
2212 GtkWindowPosition position)
2214 GtkWindowPrivate *priv;
2216 g_return_if_fail (GTK_IS_WINDOW (window));
2218 priv = window->priv;
2220 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2221 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2223 GtkWindowGeometryInfo *info;
2225 info = gtk_window_get_geometry_info (window, TRUE);
2227 /* this flag causes us to re-request the CENTER_ALWAYS
2228 * constraint in gtk_window_move_resize(), see
2229 * comment in that function.
2231 info->position_constraints_changed = TRUE;
2233 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2236 priv->position = position;
2238 g_object_notify (G_OBJECT (window), "window-position");
2242 * gtk_window_activate_focus:
2243 * @window: a #GtkWindow
2245 * Activates the current focused widget within the window.
2247 * Return value: %TRUE if a widget got activated.
2250 gtk_window_activate_focus (GtkWindow *window)
2252 GtkWindowPrivate *priv;
2254 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2256 priv = window->priv;
2258 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2259 return gtk_widget_activate (priv->focus_widget);
2265 * gtk_window_get_focus:
2266 * @window: a #GtkWindow
2268 * Retrieves the current focused widget within the window.
2269 * Note that this is the widget that would have the focus
2270 * if the toplevel window focused; if the toplevel window
2271 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2272 * not be %TRUE for the widget.
2274 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2277 gtk_window_get_focus (GtkWindow *window)
2279 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2281 return window->priv->focus_widget;
2285 * gtk_window_activate_default:
2286 * @window: a #GtkWindow
2288 * Activates the default widget for the window, unless the current
2289 * focused widget has been configured to receive the default action
2290 * (see gtk_widget_set_receives_default()), in which case the
2291 * focused widget is activated.
2293 * Return value: %TRUE if a widget got activated.
2296 gtk_window_activate_default (GtkWindow *window)
2298 GtkWindowPrivate *priv;
2300 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2302 priv = window->priv;
2304 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2305 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2306 return gtk_widget_activate (priv->default_widget);
2307 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2308 return gtk_widget_activate (priv->focus_widget);
2314 * gtk_window_set_modal:
2315 * @window: a #GtkWindow
2316 * @modal: whether the window is modal
2318 * Sets a window modal or non-modal. Modal windows prevent interaction
2319 * with other windows in the same application. To keep modal dialogs
2320 * on top of main application windows, use
2321 * gtk_window_set_transient_for() to make the dialog transient for the
2322 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2323 * will then disallow lowering the dialog below the parent.
2328 gtk_window_set_modal (GtkWindow *window,
2331 GtkWindowPrivate *priv;
2334 g_return_if_fail (GTK_IS_WINDOW (window));
2336 priv = window->priv;
2338 modal = modal != FALSE;
2339 if (priv->modal == modal)
2342 priv->modal = modal;
2343 widget = GTK_WIDGET (window);
2345 /* adjust desired modality state */
2346 if (gtk_widget_get_realized (widget))
2349 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2351 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2354 if (gtk_widget_get_visible (widget))
2357 gtk_grab_add (widget);
2359 gtk_grab_remove (widget);
2362 g_object_notify (G_OBJECT (window), "modal");
2366 * gtk_window_get_modal:
2367 * @window: a #GtkWindow
2369 * Returns whether the window is modal. See gtk_window_set_modal().
2371 * Return value: %TRUE if the window is set to be modal and
2372 * establishes a grab when shown
2375 gtk_window_get_modal (GtkWindow *window)
2377 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2379 return window->priv->modal;
2383 * gtk_window_list_toplevels:
2385 * Returns a list of all existing toplevel windows. The widgets
2386 * in the list are not individually referenced. If you want
2387 * to iterate through the list and perform actions involving
2388 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2389 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2390 * then unref all the widgets afterwards.
2392 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2395 gtk_window_list_toplevels (void)
2400 for (slist = toplevel_list; slist; slist = slist->next)
2401 list = g_list_prepend (list, slist->data);
2407 remove_attach_widget (GtkWindow *window)
2409 GtkWindowPrivate *priv = window->priv;
2411 if (priv->attach_widget)
2413 _gtk_widget_remove_attached_window (priv->attach_widget, window);
2415 g_object_unref (priv->attach_widget);
2416 priv->attach_widget = NULL;
2421 gtk_window_dispose (GObject *object)
2423 GtkWindow *window = GTK_WINDOW (object);
2425 gtk_window_set_focus (window, NULL);
2426 gtk_window_set_default (window, NULL);
2428 remove_attach_widget (GTK_WINDOW (object));
2430 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2434 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2436 gtk_widget_destroy (GTK_WIDGET (child));
2440 connect_parent_destroyed (GtkWindow *window)
2442 GtkWindowPrivate *priv = window->priv;
2444 if (priv->transient_parent)
2446 g_signal_connect (priv->transient_parent,
2448 G_CALLBACK (parent_destroyed_callback),
2454 disconnect_parent_destroyed (GtkWindow *window)
2456 GtkWindowPrivate *priv = window->priv;
2458 if (priv->transient_parent)
2460 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2461 parent_destroyed_callback,
2467 gtk_window_transient_parent_realized (GtkWidget *parent,
2470 if (gtk_widget_get_realized (window))
2471 gdk_window_set_transient_for (gtk_widget_get_window (window),
2472 gtk_widget_get_window (parent));
2476 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2479 if (gtk_widget_get_realized (window))
2480 gdk_property_delete (gtk_widget_get_window (window),
2481 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2485 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2489 gtk_window_set_screen (window, parent->priv->screen);
2493 gtk_window_unset_transient_for (GtkWindow *window)
2495 GtkWindowPrivate *priv = window->priv;
2497 if (priv->transient_parent)
2499 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2500 gtk_window_transient_parent_realized,
2502 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2503 gtk_window_transient_parent_unrealized,
2505 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2506 gtk_window_transient_parent_screen_changed,
2508 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2509 gtk_widget_destroyed,
2510 &priv->transient_parent);
2512 if (priv->destroy_with_parent)
2513 disconnect_parent_destroyed (window);
2515 priv->transient_parent = NULL;
2517 if (priv->transient_parent_group)
2519 priv->transient_parent_group = FALSE;
2520 gtk_window_group_remove_window (priv->group,
2527 * gtk_window_set_transient_for:
2528 * @window: a #GtkWindow
2529 * @parent: (allow-none): parent window, or %NULL
2531 * Dialog windows should be set transient for the main application
2532 * window they were spawned from. This allows <link
2533 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2534 * dialog on top of the main window, or center the dialog over the
2535 * main window. gtk_dialog_new_with_buttons() and other convenience
2536 * functions in GTK+ will sometimes call
2537 * gtk_window_set_transient_for() on your behalf.
2539 * Passing %NULL for @parent unsets the current transient window.
2541 * On Windows, this function puts the child window on top of the parent,
2542 * much as the window manager would have done on X.
2545 gtk_window_set_transient_for (GtkWindow *window,
2548 GtkWindowPrivate *priv;
2550 g_return_if_fail (GTK_IS_WINDOW (window));
2551 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2552 g_return_if_fail (window != parent);
2554 priv = window->priv;
2556 if (priv->transient_parent)
2558 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2559 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2560 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2561 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2562 GTK_WIDGET (window));
2564 gtk_window_unset_transient_for (window);
2567 priv->transient_parent = parent;
2571 g_signal_connect (parent, "destroy",
2572 G_CALLBACK (gtk_widget_destroyed),
2573 &priv->transient_parent);
2574 g_signal_connect (parent, "realize",
2575 G_CALLBACK (gtk_window_transient_parent_realized),
2577 g_signal_connect (parent, "unrealize",
2578 G_CALLBACK (gtk_window_transient_parent_unrealized),
2580 g_signal_connect (parent, "notify::screen",
2581 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2584 gtk_window_set_screen (window, parent->priv->screen);
2586 if (priv->destroy_with_parent)
2587 connect_parent_destroyed (window);
2589 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2590 gtk_widget_get_realized (GTK_WIDGET (parent)))
2591 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2592 GTK_WIDGET (window));
2594 if (parent->priv->group)
2596 gtk_window_group_add_window (parent->priv->group, window);
2597 priv->transient_parent_group = TRUE;
2603 * gtk_window_get_transient_for:
2604 * @window: a #GtkWindow
2606 * Fetches the transient parent for this window. See
2607 * gtk_window_set_transient_for().
2609 * Return value: (transfer none): the transient parent for this window, or %NULL
2610 * if no transient parent has been set.
2613 gtk_window_get_transient_for (GtkWindow *window)
2615 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2617 return window->priv->transient_parent;
2621 * gtk_window_set_attached_to:
2622 * @window: a #GtkWindow
2623 * @attach_widget: (allow-none): a #GtkWidget, or %NULL
2625 * Marks @window as attached to @attach_widget. This creates a logical binding
2626 * between the window and the widget it belongs to, which is used by GTK+ to
2627 * propagate information such as styling or accessibility to @window as if it
2628 * was a children of @attach_widget.
2630 * Examples of places where specifying this relation is useful are for instance
2631 * a #GtkMenu created by a #GtkComboBox, a completion popup window
2632 * created by #GtkEntry or a typeahead search entry created by #GtkTreeView.
2634 * Note that this function should not be confused with
2635 * gtk_window_set_transient_for(), which specifies a window manager relation
2636 * between two toplevels instead.
2638 * Passing %NULL for @attach_widget detaches the window.
2643 gtk_window_set_attached_to (GtkWindow *window,
2644 GtkWidget *attach_widget)
2646 GtkStyleContext *context;
2647 GtkWindowPrivate *priv;
2649 g_return_if_fail (GTK_IS_WINDOW (window));
2650 g_return_if_fail (GTK_WIDGET (window) != attach_widget);
2652 priv = window->priv;
2654 if (priv->attach_widget == attach_widget)
2657 remove_attach_widget (window);
2659 priv->attach_widget = attach_widget;
2661 if (priv->attach_widget)
2663 _gtk_widget_add_attached_window (priv->attach_widget, window);
2665 g_object_ref (priv->attach_widget);
2668 /* Update the style, as the widget path might change. */
2669 context = gtk_widget_get_style_context (GTK_WIDGET (window));
2670 if (priv->attach_widget)
2671 gtk_style_context_set_parent (context, gtk_widget_get_style_context (priv->attach_widget));
2673 gtk_style_context_set_parent (context, NULL);
2677 * gtk_window_get_attached_to:
2678 * @window: a #GtkWindow
2680 * Fetches the attach widget for this window. See
2681 * gtk_window_set_attached_to().
2683 * Return value: (transfer none): the widget where the window is attached,
2684 * or %NULL if the window is not attached to any widget.
2689 gtk_window_get_attached_to (GtkWindow *window)
2691 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2693 return window->priv->attach_widget;
2697 * gtk_window_set_opacity:
2698 * @window: a #GtkWindow
2699 * @opacity: desired opacity, between 0 and 1
2701 * Request the windowing system to make @window partially transparent,
2702 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2703 * of the opacity parameter are clamped to the [0,1] range.) On X11
2704 * this has any effect only on X screens with a compositing manager
2705 * running. See gtk_widget_is_composited(). On Windows it should work
2708 * Note that setting a window's opacity after the window has been
2709 * shown causes it to flicker once on Windows.
2714 gtk_window_set_opacity (GtkWindow *window,
2717 GtkWindowPrivate *priv;
2719 g_return_if_fail (GTK_IS_WINDOW (window));
2721 priv = window->priv;
2725 else if (opacity > 1.0)
2728 priv->opacity_set = TRUE;
2729 priv->opacity = opacity;
2731 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2732 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2737 * gtk_window_get_opacity:
2738 * @window: a #GtkWindow
2740 * Fetches the requested opacity for this window. See
2741 * gtk_window_set_opacity().
2743 * Return value: the requested opacity for this window.
2748 gtk_window_get_opacity (GtkWindow *window)
2750 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2752 return window->priv->opacity;
2756 * gtk_window_get_application:
2757 * @window: a #GtkWindow
2759 * Gets the #GtkApplication associated with the window (if any).
2761 * Return value: (transfer none): a #GtkApplication, or %NULL
2766 gtk_window_get_application (GtkWindow *window)
2768 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2770 return window->priv->application;
2774 gtk_window_release_application (GtkWindow *window)
2776 if (window->priv->application)
2778 GtkApplication *application;
2780 /* steal reference into temp variable */
2781 application = window->priv->application;
2782 window->priv->application = NULL;
2784 gtk_application_remove_window (application, window);
2785 g_object_unref (application);
2790 * gtk_window_set_application:
2791 * @window: a #GtkWindow
2792 * @application: (allow-none): a #GtkApplication, or %NULL
2794 * Sets or unsets the #GtkApplication associated with the window.
2796 * The application will be kept alive for at least as long as the window
2802 gtk_window_set_application (GtkWindow *window,
2803 GtkApplication *application)
2805 GtkWindowPrivate *priv;
2807 g_return_if_fail (GTK_IS_WINDOW (window));
2809 priv = window->priv;
2810 if (priv->application != application)
2812 gtk_window_release_application (window);
2814 priv->application = application;
2816 if (priv->application != NULL)
2818 g_object_ref (priv->application);
2820 gtk_application_add_window (priv->application, window);
2823 g_object_notify (G_OBJECT (window), "application");
2828 * gtk_window_set_type_hint:
2829 * @window: a #GtkWindow
2830 * @hint: the window type
2832 * By setting the type hint for the window, you allow the window
2833 * manager to decorate and handle the window in a way which is
2834 * suitable to the function of the window in your application.
2836 * This function should be called before the window becomes visible.
2838 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2839 * will sometimes call gtk_window_set_type_hint() on your behalf.
2843 gtk_window_set_type_hint (GtkWindow *window,
2844 GdkWindowTypeHint hint)
2846 GtkWindowPrivate *priv;
2848 g_return_if_fail (GTK_IS_WINDOW (window));
2849 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2851 priv = window->priv;
2853 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2854 priv->type_hint = hint;
2856 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2858 priv->reset_type_hint = TRUE;
2859 priv->gdk_type_hint = hint;
2863 * gtk_window_get_type_hint:
2864 * @window: a #GtkWindow
2866 * Gets the type hint for this window. See gtk_window_set_type_hint().
2868 * Return value: the type hint for @window.
2871 gtk_window_get_type_hint (GtkWindow *window)
2873 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2875 return window->priv->gdk_type_hint;
2879 * gtk_window_set_skip_taskbar_hint:
2880 * @window: a #GtkWindow
2881 * @setting: %TRUE to keep this window from appearing in the task bar
2883 * Windows may set a hint asking the desktop environment not to display
2884 * the window in the task bar. This function sets this hint.
2889 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2892 GtkWindowPrivate *priv;
2894 g_return_if_fail (GTK_IS_WINDOW (window));
2896 priv = window->priv;
2898 setting = setting != FALSE;
2900 if (priv->skips_taskbar != setting)
2902 priv->skips_taskbar = setting;
2903 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2904 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2905 priv->skips_taskbar);
2906 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2911 * gtk_window_get_skip_taskbar_hint:
2912 * @window: a #GtkWindow
2914 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2916 * Return value: %TRUE if window shouldn't be in taskbar
2921 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2923 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2925 return window->priv->skips_taskbar;
2929 * gtk_window_set_skip_pager_hint:
2930 * @window: a #GtkWindow
2931 * @setting: %TRUE to keep this window from appearing in the pager
2933 * Windows may set a hint asking the desktop environment not to display
2934 * the window in the pager. This function sets this hint.
2935 * (A "pager" is any desktop navigation tool such as a workspace
2936 * switcher that displays a thumbnail representation of the windows
2942 gtk_window_set_skip_pager_hint (GtkWindow *window,
2945 GtkWindowPrivate *priv;
2947 g_return_if_fail (GTK_IS_WINDOW (window));
2949 priv = window->priv;
2951 setting = setting != FALSE;
2953 if (priv->skips_pager != setting)
2955 priv->skips_pager = setting;
2956 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2957 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2959 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2964 * gtk_window_get_skip_pager_hint:
2965 * @window: a #GtkWindow
2967 * Gets the value set by gtk_window_set_skip_pager_hint().
2969 * Return value: %TRUE if window shouldn't be in pager
2974 gtk_window_get_skip_pager_hint (GtkWindow *window)
2976 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2978 return window->priv->skips_pager;
2982 * gtk_window_set_urgency_hint:
2983 * @window: a #GtkWindow
2984 * @setting: %TRUE to mark this window as urgent
2986 * Windows may set a hint asking the desktop environment to draw
2987 * the users attention to the window. This function sets this hint.
2992 gtk_window_set_urgency_hint (GtkWindow *window,
2995 GtkWindowPrivate *priv;
2997 g_return_if_fail (GTK_IS_WINDOW (window));
2999 priv = window->priv;
3001 setting = setting != FALSE;
3003 if (priv->urgent != setting)
3005 priv->urgent = setting;
3006 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3007 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
3009 g_object_notify (G_OBJECT (window), "urgency-hint");
3014 * gtk_window_get_urgency_hint:
3015 * @window: a #GtkWindow
3017 * Gets the value set by gtk_window_set_urgency_hint()
3019 * Return value: %TRUE if window is urgent
3024 gtk_window_get_urgency_hint (GtkWindow *window)
3026 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3028 return window->priv->urgent;
3032 * gtk_window_set_accept_focus:
3033 * @window: a #GtkWindow
3034 * @setting: %TRUE to let this window receive input focus
3036 * Windows may set a hint asking the desktop environment not to receive
3037 * the input focus. This function sets this hint.
3042 gtk_window_set_accept_focus (GtkWindow *window,
3045 GtkWindowPrivate *priv;
3047 g_return_if_fail (GTK_IS_WINDOW (window));
3049 priv = window->priv;
3051 setting = setting != FALSE;
3053 if (priv->accept_focus != setting)
3055 priv->accept_focus = setting;
3056 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3057 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
3058 priv->accept_focus);
3059 g_object_notify (G_OBJECT (window), "accept-focus");
3064 * gtk_window_get_accept_focus:
3065 * @window: a #GtkWindow
3067 * Gets the value set by gtk_window_set_accept_focus().
3069 * Return value: %TRUE if window should receive the input focus
3074 gtk_window_get_accept_focus (GtkWindow *window)
3076 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3078 return window->priv->accept_focus;
3082 * gtk_window_set_focus_on_map:
3083 * @window: a #GtkWindow
3084 * @setting: %TRUE to let this window receive input focus on map
3086 * Windows may set a hint asking the desktop environment not to receive
3087 * the input focus when the window is mapped. This function sets this
3093 gtk_window_set_focus_on_map (GtkWindow *window,
3096 GtkWindowPrivate *priv;
3098 g_return_if_fail (GTK_IS_WINDOW (window));
3100 priv = window->priv;
3102 setting = setting != FALSE;
3104 if (priv->focus_on_map != setting)
3106 priv->focus_on_map = setting;
3107 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3108 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
3109 priv->focus_on_map);
3110 g_object_notify (G_OBJECT (window), "focus-on-map");
3115 * gtk_window_get_focus_on_map:
3116 * @window: a #GtkWindow
3118 * Gets the value set by gtk_window_set_focus_on_map().
3120 * Return value: %TRUE if window should receive the input focus when
3126 gtk_window_get_focus_on_map (GtkWindow *window)
3128 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3130 return window->priv->focus_on_map;
3134 * gtk_window_set_destroy_with_parent:
3135 * @window: a #GtkWindow
3136 * @setting: whether to destroy @window with its transient parent
3138 * If @setting is %TRUE, then destroying the transient parent of @window
3139 * will also destroy @window itself. This is useful for dialogs that
3140 * shouldn't persist beyond the lifetime of the main window they're
3141 * associated with, for example.
3144 gtk_window_set_destroy_with_parent (GtkWindow *window,
3147 GtkWindowPrivate *priv;
3149 g_return_if_fail (GTK_IS_WINDOW (window));
3151 priv = window->priv;
3153 if (priv->destroy_with_parent == (setting != FALSE))
3156 if (priv->destroy_with_parent)
3158 disconnect_parent_destroyed (window);
3162 connect_parent_destroyed (window);
3165 priv->destroy_with_parent = setting;
3167 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3171 * gtk_window_get_destroy_with_parent:
3172 * @window: a #GtkWindow
3174 * Returns whether the window will be destroyed with its transient parent. See
3175 * gtk_window_set_destroy_with_parent ().
3177 * Return value: %TRUE if the window will be destroyed with its transient parent.
3180 gtk_window_get_destroy_with_parent (GtkWindow *window)
3182 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3184 return window->priv->destroy_with_parent;
3188 * gtk_window_set_hide_titlebar_when_maximized:
3189 * @window: a #GtkWindow
3190 * @setting: whether to hide the titlebar when @window is maximized
3192 * If @setting is %TRUE, then @window will request that it's titlebar
3193 * should be hidden when maximized.
3194 * This is useful for windows that don't convey any information other
3195 * than the application name in the titlebar, to put the available
3196 * screen space to better use. If the underlying window system does not
3197 * support the request, the setting will not have any effect.
3202 gtk_window_set_hide_titlebar_when_maximized (GtkWindow *window,
3205 g_return_if_fail (GTK_IS_WINDOW (window));
3207 #ifdef GDK_WINDOWING_X11
3209 GdkWindow *gdk_window;
3211 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3213 if (GDK_IS_X11_WINDOW (gdk_window))
3214 gdk_x11_window_set_hide_titlebar_when_maximized (gdk_window, setting);
3218 window->priv->hide_titlebar_when_maximized = setting;
3219 g_object_notify (G_OBJECT (window), "hide-titlebar-when-maximized");
3223 * gtk_window_get_hide_titlebar_when_maximized:
3224 * @window: a #GtkWindow
3226 * Returns whether the window has requested to have its titlebar hidden
3227 * when maximized. See gtk_window_set_hide_titlebar_when_maximized ().
3229 * Return value: %TRUE if the window has requested to have its titlebar
3230 * hidden when maximized
3235 gtk_window_get_hide_titlebar_when_maximized (GtkWindow *window)
3237 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3239 return window->priv->hide_titlebar_when_maximized;
3242 static GtkWindowGeometryInfo*
3243 gtk_window_get_geometry_info (GtkWindow *window,
3246 GtkWindowPrivate *priv = window->priv;
3247 GtkWindowGeometryInfo *info;
3249 info = priv->geometry_info;
3250 if (!info && create)
3252 info = g_new0 (GtkWindowGeometryInfo, 1);
3254 info->default_width = -1;
3255 info->default_height = -1;
3256 info->resize_width = -1;
3257 info->resize_height = -1;
3258 info->initial_x = 0;
3259 info->initial_y = 0;
3260 info->initial_pos_set = FALSE;
3261 info->default_is_geometry = FALSE;
3262 info->position_constraints_changed = FALSE;
3263 info->last.configure_request.x = 0;
3264 info->last.configure_request.y = 0;
3265 info->last.configure_request.width = -1;
3266 info->last.configure_request.height = -1;
3267 info->widget = NULL;
3269 priv->geometry_info = info;
3276 * gtk_window_set_geometry_hints:
3277 * @window: a #GtkWindow
3278 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3279 * @geometry: (allow-none): struct containing geometry information or %NULL
3280 * @geom_mask: mask indicating which struct fields should be paid attention to
3282 * This function sets up hints about how a window can be resized by
3283 * the user. You can set a minimum and maximum size; allowed resize
3284 * increments (e.g. for xterm, you can only resize by the size of a
3285 * character); aspect ratios; and more. See the #GdkGeometry struct.
3289 gtk_window_set_geometry_hints (GtkWindow *window,
3290 GtkWidget *geometry_widget,
3291 GdkGeometry *geometry,
3292 GdkWindowHints geom_mask)
3294 GtkWindowGeometryInfo *info;
3296 g_return_if_fail (GTK_IS_WINDOW (window));
3297 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3299 info = gtk_window_get_geometry_info (window, TRUE);
3302 g_signal_handlers_disconnect_by_func (info->widget,
3303 gtk_widget_destroyed,
3306 info->widget = geometry_widget;
3308 g_signal_connect (geometry_widget, "destroy",
3309 G_CALLBACK (gtk_widget_destroyed),
3313 info->geometry = *geometry;
3315 /* We store gravity in priv->gravity not in the hints. */
3316 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3318 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3320 gtk_window_set_gravity (window, geometry->win_gravity);
3323 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3327 * gtk_window_set_decorated:
3328 * @window: a #GtkWindow
3329 * @setting: %TRUE to decorate the window
3331 * By default, windows are decorated with a title bar, resize
3332 * controls, etc. Some <link linkend="gtk-X11-arch">window
3333 * managers</link> allow GTK+ to disable these decorations, creating a
3334 * borderless window. If you set the decorated property to %FALSE
3335 * using this function, GTK+ will do its best to convince the window
3336 * manager not to decorate the window. Depending on the system, this
3337 * function may not have any effect when called on a window that is
3338 * already visible, so you should call it before calling gtk_widget_show().
3340 * On Windows, this function always works, since there's no window manager
3345 gtk_window_set_decorated (GtkWindow *window,
3348 GtkWindowPrivate *priv;
3349 GdkWindow *gdk_window;
3351 g_return_if_fail (GTK_IS_WINDOW (window));
3353 priv = window->priv;
3355 setting = setting != FALSE;
3357 if (setting == priv->decorated)
3360 priv->decorated = setting;
3362 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3365 if (priv->decorated)
3366 gdk_window_set_decorations (gdk_window,
3369 gdk_window_set_decorations (gdk_window,
3373 g_object_notify (G_OBJECT (window), "decorated");
3377 * gtk_window_get_decorated:
3378 * @window: a #GtkWindow
3380 * Returns whether the window has been set to have decorations
3381 * such as a title bar via gtk_window_set_decorated().
3383 * Return value: %TRUE if the window has been set to have decorations
3386 gtk_window_get_decorated (GtkWindow *window)
3388 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3390 return window->priv->decorated;
3394 * gtk_window_set_deletable:
3395 * @window: a #GtkWindow
3396 * @setting: %TRUE to decorate the window as deletable
3398 * By default, windows have a close button in the window frame. Some
3399 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3400 * disable this button. If you set the deletable property to %FALSE
3401 * using this function, GTK+ will do its best to convince the window
3402 * manager not to show a close button. Depending on the system, this
3403 * function may not have any effect when called on a window that is
3404 * already visible, so you should call it before calling gtk_widget_show().
3406 * On Windows, this function always works, since there's no window manager
3412 gtk_window_set_deletable (GtkWindow *window,
3415 GtkWindowPrivate *priv;
3416 GdkWindow *gdk_window;
3418 g_return_if_fail (GTK_IS_WINDOW (window));
3420 priv = window->priv;
3422 setting = setting != FALSE;
3424 if (setting == priv->deletable)
3427 priv->deletable = setting;
3429 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3432 if (priv->deletable)
3433 gdk_window_set_functions (gdk_window,
3436 gdk_window_set_functions (gdk_window,
3437 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3440 g_object_notify (G_OBJECT (window), "deletable");
3444 * gtk_window_get_deletable:
3445 * @window: a #GtkWindow
3447 * Returns whether the window has been set to have a close button
3448 * via gtk_window_set_deletable().
3450 * Return value: %TRUE if the window has been set to have a close button
3455 gtk_window_get_deletable (GtkWindow *window)
3457 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3459 return window->priv->deletable;
3462 static GtkWindowIconInfo*
3463 get_icon_info (GtkWindow *window)
3465 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3469 free_icon_info (GtkWindowIconInfo *info)
3471 g_free (info->icon_name);
3472 g_slice_free (GtkWindowIconInfo, info);
3476 static GtkWindowIconInfo*
3477 ensure_icon_info (GtkWindow *window)
3479 GtkWindowIconInfo *info;
3481 info = get_icon_info (window);
3485 info = g_slice_new0 (GtkWindowIconInfo);
3486 g_object_set_qdata_full (G_OBJECT (window),
3487 quark_gtk_window_icon_info,
3489 (GDestroyNotify)free_icon_info);
3496 icon_list_from_theme (GtkWidget *widget,
3501 GtkIconTheme *icon_theme;
3506 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3508 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3511 for (i = 0; sizes[i]; i++)
3514 * We need an EWMH extension to handle scalable icons
3515 * by passing their name to the WM. For now just use a
3519 icon = gtk_icon_theme_load_icon (icon_theme, name,
3522 icon = gtk_icon_theme_load_icon (icon_theme, name,
3525 list = g_list_append (list, icon);
3535 gtk_window_realize_icon (GtkWindow *window)
3537 GtkWindowPrivate *priv = window->priv;
3539 GtkWindowIconInfo *info;
3540 GdkWindow *gdk_window;
3543 widget = GTK_WIDGET (window);
3544 gdk_window = gtk_widget_get_window (widget);
3546 g_return_if_fail (gdk_window != NULL);
3548 /* no point setting an icon on override-redirect */
3549 if (priv->type == GTK_WINDOW_POPUP)
3554 info = ensure_icon_info (window);
3559 info->using_default_icon = FALSE;
3560 info->using_parent_icon = FALSE;
3561 info->using_themed_icon = FALSE;
3563 icon_list = info->icon_list;
3565 /* Look up themed icon */
3566 if (icon_list == NULL && info->icon_name)
3568 icon_list = icon_list_from_theme (widget, info->icon_name);
3570 info->using_themed_icon = TRUE;
3573 /* Inherit from transient parent */
3574 if (icon_list == NULL && priv->transient_parent)
3576 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3578 info->using_parent_icon = TRUE;
3581 /* Inherit from default */
3582 if (icon_list == NULL)
3584 icon_list = default_icon_list;
3586 info->using_default_icon = TRUE;
3589 /* Look up themed icon */
3590 if (icon_list == NULL && default_icon_name)
3592 icon_list = icon_list_from_theme (widget, default_icon_name);
3593 info->using_default_icon = TRUE;
3594 info->using_themed_icon = TRUE;
3597 info->realized = TRUE;
3599 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3601 if (info->using_themed_icon)
3603 GtkIconTheme *icon_theme;
3605 g_list_free_full (icon_list, g_object_unref);
3607 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3608 g_signal_connect (icon_theme, "changed",
3609 G_CALLBACK (update_themed_icon), window);
3614 gtk_window_unrealize_icon (GtkWindow *window)
3616 GtkWindowIconInfo *info;
3618 info = get_icon_info (window);
3623 if (info->using_themed_icon)
3625 GtkIconTheme *icon_theme;
3627 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3629 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3632 /* We don't clear the properties on the window, just figure the
3633 * window is going away.
3636 info->realized = FALSE;
3641 * gtk_window_set_icon_list:
3642 * @window: a #GtkWindow
3643 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3645 * Sets up the icon representing a #GtkWindow. The icon is used when
3646 * the window is minimized (also known as iconified). Some window
3647 * managers or desktop environments may also place it in the window
3648 * frame, or display it in other contexts.
3650 * gtk_window_set_icon_list() allows you to pass in the same icon in
3651 * several hand-drawn sizes. The list should contain the natural sizes
3652 * your icon is available in; that is, don't scale the image before
3653 * passing it to GTK+. Scaling is postponed until the last minute,
3654 * when the desired final size is known, to allow best quality.
3656 * By passing several sizes, you may improve the final image quality
3657 * of the icon, by reducing or eliminating automatic image scaling.
3659 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3660 * larger images (64x64, 128x128) if you have them.
3662 * See also gtk_window_set_default_icon_list() to set the icon
3663 * for all windows in your application in one go.
3665 * Note that transient windows (those who have been set transient for another
3666 * window using gtk_window_set_transient_for()) will inherit their
3667 * icon from their transient parent. So there's no need to explicitly
3668 * set the icon on transient windows.
3671 gtk_window_set_icon_list (GtkWindow *window,
3674 GtkWindowIconInfo *info;
3676 g_return_if_fail (GTK_IS_WINDOW (window));
3678 info = ensure_icon_info (window);
3680 if (info->icon_list == list) /* check for NULL mostly */
3683 g_list_foreach (list,
3684 (GFunc) g_object_ref, NULL);
3686 g_list_free_full (info->icon_list, g_object_unref);
3688 info->icon_list = g_list_copy (list);
3690 g_object_notify (G_OBJECT (window), "icon");
3692 gtk_window_unrealize_icon (window);
3694 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3695 gtk_window_realize_icon (window);
3697 /* We could try to update our transient children, but I don't think
3698 * it's really worth it. If we did it, the best way would probably
3699 * be to have children connect to notify::icon-list
3704 * gtk_window_get_icon_list:
3705 * @window: a #GtkWindow
3707 * Retrieves the list of icons set by gtk_window_set_icon_list().
3708 * The list is copied, but the reference count on each
3709 * member won't be incremented.
3711 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3714 gtk_window_get_icon_list (GtkWindow *window)
3716 GtkWindowIconInfo *info;
3718 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3720 info = get_icon_info (window);
3723 return g_list_copy (info->icon_list);
3729 * gtk_window_set_icon:
3730 * @window: a #GtkWindow
3731 * @icon: (allow-none): icon image, or %NULL
3733 * Sets up the icon representing a #GtkWindow. This icon is used when
3734 * the window is minimized (also known as iconified). Some window
3735 * managers or desktop environments may also place it in the window
3736 * frame, or display it in other contexts.
3738 * The icon should be provided in whatever size it was naturally
3739 * drawn; that is, don't scale the image before passing it to
3740 * GTK+. Scaling is postponed until the last minute, when the desired
3741 * final size is known, to allow best quality.
3743 * If you have your icon hand-drawn in multiple sizes, use
3744 * gtk_window_set_icon_list(). Then the best size will be used.
3746 * This function is equivalent to calling gtk_window_set_icon_list()
3747 * with a 1-element list.
3749 * See also gtk_window_set_default_icon_list() to set the icon
3750 * for all windows in your application in one go.
3753 gtk_window_set_icon (GtkWindow *window,
3758 g_return_if_fail (GTK_IS_WINDOW (window));
3759 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3764 list = g_list_append (list, icon);
3766 gtk_window_set_icon_list (window, list);
3772 update_themed_icon (GtkIconTheme *icon_theme,
3775 g_object_notify (G_OBJECT (window), "icon");
3777 gtk_window_unrealize_icon (window);
3779 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3780 gtk_window_realize_icon (window);
3784 * gtk_window_set_icon_name:
3785 * @window: a #GtkWindow
3786 * @name: (allow-none): the name of the themed icon
3788 * Sets the icon for the window from a named themed icon. See
3789 * the docs for #GtkIconTheme for more details.
3791 * Note that this has nothing to do with the WM_ICON_NAME
3792 * property which is mentioned in the ICCCM.
3797 gtk_window_set_icon_name (GtkWindow *window,
3800 GtkWindowIconInfo *info;
3803 g_return_if_fail (GTK_IS_WINDOW (window));
3805 info = ensure_icon_info (window);
3807 if (g_strcmp0 (info->icon_name, name) == 0)
3810 tmp = info->icon_name;
3811 info->icon_name = g_strdup (name);
3814 g_list_free_full (info->icon_list, g_object_unref);
3815 info->icon_list = NULL;
3817 update_themed_icon (NULL, window);
3819 g_object_notify (G_OBJECT (window), "icon-name");
3823 * gtk_window_get_icon_name:
3824 * @window: a #GtkWindow
3826 * Returns the name of the themed icon for the window,
3827 * see gtk_window_set_icon_name().
3829 * Returns: the icon name or %NULL if the window has
3835 gtk_window_get_icon_name (GtkWindow *window)
3837 GtkWindowIconInfo *info;
3839 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3841 info = ensure_icon_info (window);
3843 return info->icon_name;
3847 * gtk_window_get_icon:
3848 * @window: a #GtkWindow
3850 * Gets the value set by gtk_window_set_icon() (or if you've
3851 * called gtk_window_set_icon_list(), gets the first icon in
3854 * Return value: (transfer none): icon for window
3857 gtk_window_get_icon (GtkWindow *window)
3859 GtkWindowIconInfo *info;
3861 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3863 info = get_icon_info (window);
3864 if (info && info->icon_list)
3865 return GDK_PIXBUF (info->icon_list->data);
3870 /* Load pixbuf, printing warning on failure if error == NULL
3873 load_pixbuf_verbosely (const char *filename,
3876 GError *local_err = NULL;
3879 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3887 g_warning ("Error loading icon from file '%s':\n\t%s",
3888 filename, local_err->message);
3889 g_error_free (local_err);
3897 * gtk_window_set_icon_from_file:
3898 * @window: a #GtkWindow
3899 * @filename: (type filename): location of icon file
3900 * @err: (allow-none): location to store error, or %NULL.
3902 * Sets the icon for @window.
3903 * Warns on failure if @err is %NULL.
3905 * This function is equivalent to calling gtk_window_set_icon()
3906 * with a pixbuf created by loading the image from @filename.
3908 * Returns: %TRUE if setting the icon succeeded.
3913 gtk_window_set_icon_from_file (GtkWindow *window,
3914 const gchar *filename,
3917 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3921 gtk_window_set_icon (window, pixbuf);
3922 g_object_unref (pixbuf);
3931 * gtk_window_set_default_icon_list:
3932 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3934 * Sets an icon list to be used as fallback for windows that haven't
3935 * had gtk_window_set_icon_list() called on them to set up a
3936 * window-specific icon list. This function allows you to set up the
3937 * icon for all windows in your app at once.
3939 * See gtk_window_set_icon_list() for more details.
3943 gtk_window_set_default_icon_list (GList *list)
3947 if (list == default_icon_list)
3950 /* Update serial so we don't used cached pixmaps/masks
3952 default_icon_serial++;
3954 g_list_foreach (list,
3955 (GFunc) g_object_ref, NULL);
3957 g_list_free_full (default_icon_list, g_object_unref);
3959 default_icon_list = g_list_copy (list);
3961 /* Update all toplevels */
3962 toplevels = gtk_window_list_toplevels ();
3963 tmp_list = toplevels;
3964 while (tmp_list != NULL)
3966 GtkWindowIconInfo *info;
3967 GtkWindow *w = tmp_list->data;
3969 info = get_icon_info (w);
3970 if (info && info->using_default_icon)
3972 gtk_window_unrealize_icon (w);
3973 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3974 gtk_window_realize_icon (w);
3977 tmp_list = tmp_list->next;
3979 g_list_free (toplevels);
3983 * gtk_window_set_default_icon:
3986 * Sets an icon to be used as fallback for windows that haven't
3987 * had gtk_window_set_icon() called on them from a pixbuf.
3992 gtk_window_set_default_icon (GdkPixbuf *icon)
3996 g_return_if_fail (GDK_IS_PIXBUF (icon));
3998 list = g_list_prepend (NULL, icon);
3999 gtk_window_set_default_icon_list (list);
4004 * gtk_window_set_default_icon_name:
4005 * @name: the name of the themed icon
4007 * Sets an icon to be used as fallback for windows that haven't
4008 * had gtk_window_set_icon_list() called on them from a named
4009 * themed icon, see gtk_window_set_icon_name().
4014 gtk_window_set_default_icon_name (const gchar *name)
4019 /* Update serial so we don't used cached pixmaps/masks
4021 default_icon_serial++;
4023 g_free (default_icon_name);
4024 default_icon_name = g_strdup (name);
4026 g_list_free_full (default_icon_list, g_object_unref);
4027 default_icon_list = NULL;
4029 /* Update all toplevels */
4030 toplevels = gtk_window_list_toplevels ();
4031 tmp_list = toplevels;
4032 while (tmp_list != NULL)
4034 GtkWindowIconInfo *info;
4035 GtkWindow *w = tmp_list->data;
4037 info = get_icon_info (w);
4038 if (info && info->using_default_icon && info->using_themed_icon)
4040 gtk_window_unrealize_icon (w);
4041 if (gtk_widget_get_realized (GTK_WIDGET (w)))
4042 gtk_window_realize_icon (w);
4045 tmp_list = tmp_list->next;
4047 g_list_free (toplevels);
4051 * gtk_window_get_default_icon_name:
4053 * Returns the fallback icon name for windows that has been set
4054 * with gtk_window_set_default_icon_name(). The returned
4055 * string is owned by GTK+ and should not be modified. It
4056 * is only valid until the next call to
4057 * gtk_window_set_default_icon_name().
4059 * Returns: the fallback icon name for windows
4064 gtk_window_get_default_icon_name (void)
4066 return default_icon_name;
4070 * gtk_window_set_default_icon_from_file:
4071 * @filename: (type filename): location of icon file
4072 * @err: (allow-none): location to store error, or %NULL.
4074 * Sets an icon to be used as fallback for windows that haven't
4075 * had gtk_window_set_icon_list() called on them from a file
4076 * on disk. Warns on failure if @err is %NULL.
4078 * Returns: %TRUE if setting the icon succeeded.
4083 gtk_window_set_default_icon_from_file (const gchar *filename,
4086 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
4090 gtk_window_set_default_icon (pixbuf);
4091 g_object_unref (pixbuf);
4100 * gtk_window_get_default_icon_list:
4102 * Gets the value set by gtk_window_set_default_icon_list().
4103 * The list is a copy and should be freed with g_list_free(),
4104 * but the pixbufs in the list have not had their reference count
4107 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
4110 gtk_window_get_default_icon_list (void)
4112 return g_list_copy (default_icon_list);
4116 gtk_window_set_default_size_internal (GtkWindow *window,
4117 gboolean change_width,
4119 gboolean change_height,
4121 gboolean is_geometry)
4123 GtkWindowGeometryInfo *info;
4125 g_return_if_fail (change_width == FALSE || width >= -1);
4126 g_return_if_fail (change_height == FALSE || height >= -1);
4128 info = gtk_window_get_geometry_info (window, TRUE);
4130 g_object_freeze_notify (G_OBJECT (window));
4132 info->default_is_geometry = is_geometry != FALSE;
4142 info->default_width = width;
4144 g_object_notify (G_OBJECT (window), "default-width");
4155 info->default_height = height;
4157 g_object_notify (G_OBJECT (window), "default-height");
4160 g_object_thaw_notify (G_OBJECT (window));
4162 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4166 * gtk_window_set_default_size:
4167 * @window: a #GtkWindow
4168 * @width: width in pixels, or -1 to unset the default width
4169 * @height: height in pixels, or -1 to unset the default height
4171 * Sets the default size of a window. If the window's "natural" size
4172 * (its size request) is larger than the default, the default will be
4173 * ignored. More generally, if the default size does not obey the
4174 * geometry hints for the window (gtk_window_set_geometry_hints() can
4175 * be used to set these explicitly), the default size will be clamped
4176 * to the nearest permitted size.
4178 * Unlike gtk_widget_set_size_request(), which sets a size request for
4179 * a widget and thus would keep users from shrinking the window, this
4180 * function only sets the initial size, just as if the user had
4181 * resized the window themselves. Users can still shrink the window
4182 * again as they normally would. Setting a default size of -1 means to
4183 * use the "natural" default size (the size request of the window).
4185 * For more control over a window's initial size and how resizing works,
4186 * investigate gtk_window_set_geometry_hints().
4188 * For some uses, gtk_window_resize() is a more appropriate function.
4189 * gtk_window_resize() changes the current size of the window, rather
4190 * than the size to be used on initial display. gtk_window_resize() always
4191 * affects the window itself, not the geometry widget.
4193 * The default size of a window only affects the first time a window is
4194 * shown; if a window is hidden and re-shown, it will remember the size
4195 * it had prior to hiding, rather than using the default size.
4197 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4198 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4201 gtk_window_set_default_size (GtkWindow *window,
4205 g_return_if_fail (GTK_IS_WINDOW (window));
4206 g_return_if_fail (width >= -1);
4207 g_return_if_fail (height >= -1);
4209 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4213 * gtk_window_set_default_geometry:
4214 * @window: a #GtkWindow
4215 * @width: width in resize increments, or -1 to unset the default width
4216 * @height: height in resize increments, or -1 to unset the default height
4218 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4219 * in terms of the base size and increment set with
4220 * gtk_window_set_geometry_hints.
4225 gtk_window_set_default_geometry (GtkWindow *window,
4229 g_return_if_fail (GTK_IS_WINDOW (window));
4230 g_return_if_fail (width >= -1);
4231 g_return_if_fail (height >= -1);
4233 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4237 * gtk_window_get_default_size:
4238 * @window: a #GtkWindow
4239 * @width: (out) (allow-none): location to store the default width, or %NULL
4240 * @height: (out) (allow-none): location to store the default height, or %NULL
4242 * Gets the default size of the window. A value of -1 for the width or
4243 * height indicates that a default size has not been explicitly set
4244 * for that dimension, so the "natural" size of the window will be
4249 gtk_window_get_default_size (GtkWindow *window,
4253 GtkWindowGeometryInfo *info;
4255 g_return_if_fail (GTK_IS_WINDOW (window));
4257 info = gtk_window_get_geometry_info (window, FALSE);
4260 *width = info ? info->default_width : -1;
4263 *height = info ? info->default_height : -1;
4267 * gtk_window_resize:
4268 * @window: a #GtkWindow
4269 * @width: width in pixels to resize the window to
4270 * @height: height in pixels to resize the window to
4272 * Resizes the window as if the user had done so, obeying geometry
4273 * constraints. The default geometry constraint is that windows may
4274 * not be smaller than their size request; to override this
4275 * constraint, call gtk_widget_set_size_request() to set the window's
4276 * request to a smaller value.
4278 * If gtk_window_resize() is called before showing a window for the
4279 * first time, it overrides any default size set with
4280 * gtk_window_set_default_size().
4282 * Windows may not be resized smaller than 1 by 1 pixels.
4286 gtk_window_resize (GtkWindow *window,
4290 GtkWindowGeometryInfo *info;
4292 g_return_if_fail (GTK_IS_WINDOW (window));
4293 g_return_if_fail (width > 0);
4294 g_return_if_fail (height > 0);
4296 info = gtk_window_get_geometry_info (window, TRUE);
4298 info->resize_width = width;
4299 info->resize_height = height;
4300 info->resize_is_geometry = FALSE;
4302 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4306 * gtk_window_resize_to_geometry:
4307 * @window: a #GtkWindow
4308 * @width: width in resize increments to resize the window to
4309 * @height: height in resize increments to resize the window to
4311 * Like gtk_window_resize(), but @width and @height are interpreted
4312 * in terms of the base size and increment set with
4313 * gtk_window_set_geometry_hints.
4318 gtk_window_resize_to_geometry (GtkWindow *window,
4322 GtkWindowGeometryInfo *info;
4324 g_return_if_fail (GTK_IS_WINDOW (window));
4325 g_return_if_fail (width > 0);
4326 g_return_if_fail (height > 0);
4328 info = gtk_window_get_geometry_info (window, TRUE);
4330 info->resize_width = width;
4331 info->resize_height = height;
4332 info->resize_is_geometry = TRUE;
4334 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4338 * gtk_window_get_size:
4339 * @window: a #GtkWindow
4340 * @width: (out) (allow-none): return location for width, or %NULL
4341 * @height: (out) (allow-none): return location for height, or %NULL
4343 * Obtains the current size of @window. If @window is not onscreen,
4344 * it returns the size GTK+ will suggest to the <link
4345 * linkend="gtk-X11-arch">window manager</link> for the initial window
4346 * size (but this is not reliably the same as the size the window
4347 * manager will actually select). The size obtained by
4348 * gtk_window_get_size() is the last size received in a
4349 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4350 * rather than querying the X server for the size. As a result, if you
4351 * call gtk_window_resize() then immediately call
4352 * gtk_window_get_size(), the size won't have taken effect yet. After
4353 * the window manager processes the resize request, GTK+ receives
4354 * notification that the size has changed via a configure event, and
4355 * the size of the window gets updated.
4357 * Note 1: Nearly any use of this function creates a race condition,
4358 * because the size of the window may change between the time that you
4359 * get the size and the time that you perform some action assuming
4360 * that size is the current size. To avoid race conditions, connect to
4361 * "configure-event" on the window and adjust your size-dependent
4362 * state to match the size delivered in the #GdkEventConfigure.
4364 * Note 2: The returned size does <emphasis>not</emphasis> include the
4365 * size of the window manager decorations (aka the window frame or
4366 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4367 * method of determining their size.
4369 * Note 3: If you are getting a window size in order to position
4370 * the window onscreen, there may be a better way. The preferred
4371 * way is to simply set the window's semantic type with
4372 * gtk_window_set_type_hint(), which allows the window manager to
4373 * e.g. center dialogs. Also, if you set the transient parent of
4374 * dialogs with gtk_window_set_transient_for() window managers
4375 * will often center the dialog over its parent window. It's
4376 * much preferred to let the window manager handle these
4377 * things rather than doing it yourself, because all apps will
4378 * behave consistently and according to user prefs if the window
4379 * manager handles it. Also, the window manager can take the size
4380 * of the window decorations/border into account, while your
4381 * application cannot.
4383 * In any case, if you insist on application-specified window
4384 * positioning, there's <emphasis>still</emphasis> a better way than
4385 * doing it yourself - gtk_window_set_position() will frequently
4386 * handle the details for you.
4390 gtk_window_get_size (GtkWindow *window,
4396 g_return_if_fail (GTK_IS_WINDOW (window));
4398 if (width == NULL && height == NULL)
4401 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4403 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4404 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4408 GdkRectangle configure_request;
4410 gtk_window_compute_configure_request (window,
4414 w = configure_request.width;
4415 h = configure_request.height;
4426 * @window: a #GtkWindow
4427 * @x: X coordinate to move window to
4428 * @y: Y coordinate to move window to
4430 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4431 * @window to the given position. Window managers are free to ignore
4432 * this; most window managers ignore requests for initial window
4433 * positions (instead using a user-defined placement algorithm) and
4434 * honor requests after the window has already been shown.
4436 * Note: the position is the position of the gravity-determined
4437 * reference point for the window. The gravity determines two things:
4438 * first, the location of the reference point in root window
4439 * coordinates; and second, which point on the window is positioned at
4440 * the reference point.
4442 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4443 * point is simply the @x, @y supplied to gtk_window_move(). The
4444 * top-left corner of the window decorations (aka window frame or
4445 * border) will be placed at @x, @y. Therefore, to position a window
4446 * at the top left of the screen, you want to use the default gravity
4447 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4449 * To position a window at the bottom right corner of the screen, you
4450 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4451 * point is at @x + the window width and @y + the window height, and
4452 * the bottom-right corner of the window border will be placed at that
4453 * reference point. So, to place a window in the bottom right corner
4454 * you would first set gravity to south east, then write:
4455 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4456 * gdk_screen_height () - window_height)</literal> (note that this
4457 * example does not take multi-head scenarios into account).
4459 * The Extended Window Manager Hints specification at <ulink
4460 * url="http://www.freedesktop.org/Standards/wm-spec">
4461 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4462 * nice table of gravities in the "implementation notes" section.
4464 * The gtk_window_get_position() documentation may also be relevant.
4467 gtk_window_move (GtkWindow *window,
4471 GtkWindowGeometryInfo *info;
4474 g_return_if_fail (GTK_IS_WINDOW (window));
4476 widget = GTK_WIDGET (window);
4478 info = gtk_window_get_geometry_info (window, TRUE);
4480 if (gtk_widget_get_mapped (widget))
4482 GtkAllocation allocation;
4484 gtk_widget_get_allocation (widget, &allocation);
4486 /* we have now sent a request with this position
4487 * with currently-active constraints, so toggle flag.
4489 info->position_constraints_changed = FALSE;
4491 /* we only constrain if mapped - if not mapped,
4492 * then gtk_window_compute_configure_request()
4493 * will apply the constraints later, and we
4494 * don't want to lose information about
4495 * what position the user set before then.
4496 * i.e. if you do a move() then turn off POS_CENTER
4497 * then show the window, your move() will work.
4499 gtk_window_constrain_position (window,
4500 allocation.width, allocation.height,
4503 /* Note that this request doesn't go through our standard request
4504 * framework, e.g. doesn't increment configure_request_count,
4505 * doesn't set info->last, etc.; that's because
4506 * we don't save the info needed to arrive at this same request
4509 * To gtk_window_move_resize(), this will end up looking exactly
4510 * the same as the position being changed by the window
4513 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4517 /* Save this position to apply on mapping */
4518 info->initial_x = x;
4519 info->initial_y = y;
4520 info->initial_pos_set = TRUE;
4525 * gtk_window_get_position:
4526 * @window: a #GtkWindow
4527 * @root_x: (out) (allow-none): return location for X coordinate of
4528 * gravity-determined reference point, or %NULL
4529 * @root_y: (out) (allow-none): return location for Y coordinate of
4530 * gravity-determined reference point, or %NULL
4532 * This function returns the position you need to pass to
4533 * gtk_window_move() to keep @window in its current position.
4534 * This means that the meaning of the returned value varies with
4535 * window gravity. See gtk_window_move() for more details.
4537 * If you haven't changed the window gravity, its gravity will be
4538 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4539 * gets the position of the top-left corner of the window manager
4540 * frame for the window. gtk_window_move() sets the position of this
4541 * same top-left corner.
4543 * gtk_window_get_position() is not 100% reliable because the X Window System
4544 * does not specify a way to obtain the geometry of the
4545 * decorations placed on a window by the window manager.
4546 * Thus GTK+ is using a "best guess" that works with most
4549 * Moreover, nearly all window managers are historically broken with
4550 * respect to their handling of window gravity. So moving a window to
4551 * its current position as returned by gtk_window_get_position() tends
4552 * to result in moving the window slightly. Window managers are
4553 * slowly getting better over time.
4555 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4556 * frame is not relevant, and thus gtk_window_get_position() will
4557 * always produce accurate results. However you can't use static
4558 * gravity to do things like place a window in a corner of the screen,
4559 * because static gravity ignores the window manager decorations.
4561 * If you are saving and restoring your application's window
4562 * positions, you should know that it's impossible for applications to
4563 * do this without getting it somewhat wrong because applications do
4564 * not have sufficient knowledge of window manager state. The Correct
4565 * Mechanism is to support the session management protocol (see the
4566 * "GnomeClient" object in the GNOME libraries for example) and allow
4567 * the window manager to save your window sizes and positions.
4572 gtk_window_get_position (GtkWindow *window,
4576 GtkWindowPrivate *priv;
4578 GdkWindow *gdk_window;
4580 g_return_if_fail (GTK_IS_WINDOW (window));
4582 priv = window->priv;
4583 widget = GTK_WIDGET (window);
4584 gdk_window = gtk_widget_get_window (widget);
4586 if (priv->gravity == GDK_GRAVITY_STATIC)
4588 if (gtk_widget_get_mapped (widget))
4590 /* This does a server round-trip, which is sort of wrong;
4591 * but a server round-trip is inevitable for
4592 * gdk_window_get_frame_extents() in the usual
4593 * NorthWestGravity case below, so not sure what else to
4594 * do. We should likely be consistent about whether we get
4595 * the client-side info or the server-side info.
4597 gdk_window_get_origin (gdk_window, root_x, root_y);
4601 GdkRectangle configure_request;
4603 gtk_window_compute_configure_request (window,
4607 *root_x = configure_request.x;
4608 *root_y = configure_request.y;
4613 GdkRectangle frame_extents;
4618 if (gtk_widget_get_mapped (widget))
4620 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4621 x = frame_extents.x;
4622 y = frame_extents.y;
4623 gtk_window_get_size (window, &w, &h);
4627 /* We just say the frame has 0 size on all sides.
4628 * Not sure what else to do.
4630 gtk_window_compute_configure_request (window,
4633 x = frame_extents.x;
4634 y = frame_extents.y;
4635 w = frame_extents.width;
4636 h = frame_extents.height;
4639 switch (priv->gravity)
4641 case GDK_GRAVITY_NORTH:
4642 case GDK_GRAVITY_CENTER:
4643 case GDK_GRAVITY_SOUTH:
4644 /* Find center of frame. */
4645 x += frame_extents.width / 2;
4646 /* Center client window on that point. */
4650 case GDK_GRAVITY_SOUTH_EAST:
4651 case GDK_GRAVITY_EAST:
4652 case GDK_GRAVITY_NORTH_EAST:
4653 /* Find right edge of frame */
4654 x += frame_extents.width;
4655 /* Align left edge of client at that point. */
4662 switch (priv->gravity)
4664 case GDK_GRAVITY_WEST:
4665 case GDK_GRAVITY_CENTER:
4666 case GDK_GRAVITY_EAST:
4667 /* Find center of frame. */
4668 y += frame_extents.height / 2;
4669 /* Center client window there. */
4672 case GDK_GRAVITY_SOUTH_WEST:
4673 case GDK_GRAVITY_SOUTH:
4674 case GDK_GRAVITY_SOUTH_EAST:
4675 /* Find south edge of frame */
4676 y += frame_extents.height;
4677 /* Place bottom edge of client there */
4692 * gtk_window_reshow_with_initial_size:
4693 * @window: a #GtkWindow
4695 * Hides @window, then reshows it, resetting the
4696 * default size and position of the window. Used
4697 * by GUI builders only.
4700 gtk_window_reshow_with_initial_size (GtkWindow *window)
4704 g_return_if_fail (GTK_IS_WINDOW (window));
4706 widget = GTK_WIDGET (window);
4708 gtk_widget_hide (widget);
4709 gtk_widget_unrealize (widget);
4710 gtk_widget_show (widget);
4714 gtk_window_destroy (GtkWidget *widget)
4716 GtkWindow *window = GTK_WINDOW (widget);
4717 GtkWindowPrivate *priv = window->priv;
4719 gtk_window_release_application (window);
4721 toplevel_list = g_slist_remove (toplevel_list, window);
4723 if (priv->transient_parent)
4724 gtk_window_set_transient_for (window, NULL);
4726 remove_attach_widget (GTK_WINDOW (widget));
4728 /* frees the icons */
4729 gtk_window_set_icon_list (window, NULL);
4731 if (priv->has_user_ref_count)
4733 priv->has_user_ref_count = FALSE;
4734 g_object_unref (window);
4738 gtk_window_group_remove_window (priv->group, window);
4740 gtk_window_free_key_hash (window);
4742 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4746 gtk_window_finalize (GObject *object)
4748 GtkWindow *window = GTK_WINDOW (object);
4749 GtkWindowPrivate *priv = window->priv;
4750 GtkMnemonicHash *mnemonic_hash;
4752 g_free (priv->title);
4753 g_free (priv->wmclass_name);
4754 g_free (priv->wmclass_class);
4755 g_free (priv->wm_role);
4756 gtk_window_release_application (window);
4758 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4760 _gtk_mnemonic_hash_free (mnemonic_hash);
4762 if (priv->geometry_info)
4764 if (priv->geometry_info->widget)
4765 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4766 gtk_widget_destroyed,
4767 &priv->geometry_info->widget);
4768 g_free (priv->geometry_info);
4771 if (priv->keys_changed_handler)
4773 g_source_remove (priv->keys_changed_handler);
4774 priv->keys_changed_handler = 0;
4778 g_signal_handlers_disconnect_by_func (priv->screen,
4779 gtk_window_on_composited_changed, window);
4781 g_free (priv->startup_id);
4783 #ifdef GDK_WINDOWING_X11
4784 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4785 gtk_window_on_theme_variant_changed,
4789 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4793 gtk_window_show (GtkWidget *widget)
4795 GtkWindow *window = GTK_WINDOW (widget);
4796 GtkWindowPrivate *priv = window->priv;
4797 GtkContainer *container = GTK_CONTAINER (window);
4798 gboolean need_resize;
4801 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4803 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4807 _gtk_widget_set_visible_flag (widget, TRUE);
4809 need_resize = _gtk_widget_get_alloc_needed (widget) || !gtk_widget_get_realized (widget);
4811 _gtk_style_context_validate (gtk_widget_get_style_context (widget),
4812 g_get_monotonic_time (),
4817 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4818 GtkAllocation allocation = { 0, 0 };
4819 GdkRectangle configure_request;
4820 GdkGeometry new_geometry;
4822 gboolean was_realized;
4824 /* We are going to go ahead and perform this configure request
4825 * and then emulate a configure notify by going ahead and
4826 * doing a size allocate. Sort of a synchronous
4827 * mini-copy of gtk_window_move_resize() here.
4829 gtk_window_compute_configure_request (window,
4834 /* We update this because we are going to go ahead
4835 * and gdk_window_resize() below, rather than
4838 info->last.configure_request.width = configure_request.width;
4839 info->last.configure_request.height = configure_request.height;
4841 /* and allocate the window - this is normally done
4842 * in move_resize in response to configure notify
4844 allocation.width = configure_request.width;
4845 allocation.height = configure_request.height;
4846 gtk_widget_size_allocate (widget, &allocation);
4848 /* Then we guarantee we have a realize */
4849 was_realized = FALSE;
4850 if (!gtk_widget_get_realized (widget))
4852 gtk_widget_realize (widget);
4853 was_realized = TRUE;
4856 /* We only send configure request if we didn't just finish
4857 * creating the window; if we just created the window
4858 * then we created it with widget->allocation anyhow.
4861 gdk_window_move_resize (gtk_widget_get_window (widget),
4862 configure_request.x,
4863 configure_request.y,
4864 configure_request.width,
4865 configure_request.height);
4868 gtk_container_check_resize (container);
4870 gtk_widget_map (widget);
4872 /* Try to make sure that we have some focused widget
4874 #ifdef GDK_WINDOWING_X11
4875 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4876 GTK_IS_PLUG (window);
4880 if (!priv->focus_widget && !is_plug)
4881 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4884 gtk_grab_add (widget);
4888 gtk_window_hide (GtkWidget *widget)
4890 GtkWindow *window = GTK_WINDOW (widget);
4891 GtkWindowPrivate *priv = window->priv;
4893 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4895 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4899 _gtk_widget_set_visible_flag (widget, FALSE);
4900 gtk_widget_unmap (widget);
4903 gtk_grab_remove (widget);
4907 gtk_window_map (GtkWidget *widget)
4910 GtkWindow *window = GTK_WINDOW (widget);
4911 GtkWindowPrivate *priv = window->priv;
4912 GdkWindow *gdk_window;
4913 gboolean auto_mnemonics;
4914 GtkPolicyType visible_focus;
4916 if (!gtk_widget_is_toplevel (widget))
4918 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4922 gtk_widget_set_mapped (widget, TRUE);
4924 child = gtk_bin_get_child (&(window->bin));
4926 gtk_widget_get_visible (child) &&
4927 !gtk_widget_get_mapped (child))
4928 gtk_widget_map (child);
4930 gdk_window = gtk_widget_get_window (widget);
4932 if (priv->maximize_initially)
4933 gdk_window_maximize (gdk_window);
4935 gdk_window_unmaximize (gdk_window);
4937 if (priv->stick_initially)
4938 gdk_window_stick (gdk_window);
4940 gdk_window_unstick (gdk_window);
4942 if (priv->iconify_initially)
4943 gdk_window_iconify (gdk_window);
4945 gdk_window_deiconify (gdk_window);
4947 if (priv->fullscreen_initially)
4948 gdk_window_fullscreen (gdk_window);
4950 gdk_window_unfullscreen (gdk_window);
4952 gdk_window_set_keep_above (gdk_window, priv->above_initially);
4954 gdk_window_set_keep_below (gdk_window, priv->below_initially);
4956 if (priv->type == GTK_WINDOW_TOPLEVEL)
4958 gtk_window_set_theme_variant (window);
4959 gtk_window_set_hide_titlebar_when_maximized (window,
4960 priv->hide_titlebar_when_maximized);
4963 /* No longer use the default settings */
4964 priv->need_default_size = FALSE;
4965 priv->need_default_position = FALSE;
4967 if (priv->reset_type_hint)
4969 /* We should only reset the type hint when the application
4970 * used gtk_window_set_type_hint() to change the hint.
4971 * Some applications use X directly to change the properties;
4972 * in that case, we shouldn't overwrite what they did.
4974 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4975 priv->reset_type_hint = FALSE;
4978 gdk_window_show (gdk_window);
4980 if (priv->grip_window)
4981 gdk_window_show (priv->grip_window);
4983 if (!disable_startup_notification)
4985 /* Do we have a custom startup-notification id? */
4986 if (priv->startup_id != NULL)
4988 /* Make sure we have a "real" id */
4989 if (!startup_id_is_fake (priv->startup_id))
4990 gdk_notify_startup_complete_with_id (priv->startup_id);
4992 g_free (priv->startup_id);
4993 priv->startup_id = NULL;
4995 else if (!sent_startup_notification)
4997 sent_startup_notification = TRUE;
4998 gdk_notify_startup_complete ();
5002 /* if auto-mnemonics is enabled and mnemonics visible is not already set
5003 * (as in the case of popup menus), then hide mnemonics initially
5005 g_object_get (gtk_widget_get_settings (widget),
5006 "gtk-auto-mnemonics", &auto_mnemonics,
5007 "gtk-visible-focus", &visible_focus,
5010 if (auto_mnemonics && !priv->mnemonics_visible_set)
5011 gtk_window_set_mnemonics_visible (window, FALSE);
5013 /* inherit from transient parent, so that a dialog that is
5014 * opened via keynav shows focus initially
5016 if (priv->transient_parent)
5017 gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
5019 gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
5023 gtk_window_map_event (GtkWidget *widget,
5026 if (!gtk_widget_get_mapped (widget))
5028 /* we should be be unmapped, but are getting a MapEvent, this may happen
5029 * to toplevel XWindows if mapping was intercepted by a window manager
5030 * and an unmap request occoured while the MapRequestEvent was still
5031 * being handled. we work around this situaiton here by re-requesting
5032 * the window being unmapped. more details can be found in:
5033 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
5035 gdk_window_hide (gtk_widget_get_window (widget));
5041 gtk_window_unmap (GtkWidget *widget)
5043 GtkWindow *window = GTK_WINDOW (widget);
5044 GtkWindowPrivate *priv = window->priv;
5046 GtkWindowGeometryInfo *info;
5047 GdkWindow *gdk_window;
5048 GdkWindowState state;
5050 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5052 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
5056 gdk_window = gtk_widget_get_window (widget);
5058 gtk_widget_set_mapped (widget, FALSE);
5059 gdk_window_withdraw (gdk_window);
5061 priv->configure_request_count = 0;
5062 priv->configure_notify_received = FALSE;
5064 /* on unmap, we reset the default positioning of the window,
5065 * so it's placed again, but we don't reset the default
5066 * size of the window, so it's remembered.
5068 priv->need_default_position = TRUE;
5070 info = gtk_window_get_geometry_info (window, FALSE);
5073 info->initial_pos_set = FALSE;
5074 info->position_constraints_changed = FALSE;
5077 state = gdk_window_get_state (gdk_window);
5078 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
5079 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
5080 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
5081 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
5082 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
5084 child = gtk_bin_get_child (&(window->bin));
5086 gtk_widget_unmap (child);
5089 /* (Note: Replace "size" with "width" or "height". Also, the request
5090 * mode is honoured.)
5091 * For selecting the default window size, the following conditions
5092 * should hold (in order of importance):
5093 * - the size is not below the minimum size
5094 * Windows cannot be resized below their minimum size, so we must
5095 * ensure we don't do that either.
5096 * - the size is not above the natural size
5097 * It seems weird to allocate more than this in an initial guess.
5098 * - the size does not exceed that of a maximized window
5099 * We want to see the whole window after all.
5100 * (Note that this may not be possible to achieve due to imperfect
5101 * information from the windowing system.)
5104 /* We use these for now to not make windows too big by accident. Note
5105 * that we still clamp these numbers by screen size. Also note that
5106 * minimum size still overrides this. So keep your windows small! :)
5108 #define MAX_DEFAULT_WINDOW_WIDTH 640
5109 #define MAX_DEFAULT_WINDOW_HEIGHT 480
5112 gtk_window_guess_default_size (GtkWindow *window,
5116 GtkWidget *widget = GTK_WIDGET (window);
5118 int minimum, natural;
5120 screen = gtk_widget_get_screen (widget);
5122 *width = gdk_screen_get_width (screen);
5123 *height = gdk_screen_get_height (screen);
5125 if (*width >= *height)
5128 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
5129 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
5134 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
5135 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
5138 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
5140 gtk_widget_get_preferred_height (widget, &minimum, &natural);
5141 *height = MAX (minimum, MIN (*height, natural));
5143 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
5144 *width = MAX (minimum, MIN (*width, natural));
5146 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
5148 gtk_widget_get_preferred_width (widget, &minimum, &natural);
5149 *width = MAX (minimum, MIN (*width, natural));
5151 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
5152 *height = MAX (minimum, MIN (*height, natural));
5157 gtk_window_realize (GtkWidget *widget)
5159 GtkAllocation allocation;
5161 GdkWindow *parent_window;
5162 GdkWindow *gdk_window;
5163 GdkWindowAttr attributes;
5164 gint attributes_mask;
5165 GtkWindowPrivate *priv;
5166 GtkStyleContext *context;
5168 window = GTK_WINDOW (widget);
5169 priv = window->priv;
5171 gtk_widget_get_allocation (widget, &allocation);
5173 if (gtk_widget_get_parent_window (widget))
5175 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
5177 gtk_widget_set_realized (widget, TRUE);
5179 attributes.x = allocation.x;
5180 attributes.y = allocation.y;
5181 attributes.width = allocation.width;
5182 attributes.height = allocation.height;
5183 attributes.window_type = GDK_WINDOW_CHILD;
5185 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
5187 attributes.visual = gtk_widget_get_visual (widget);
5188 attributes.wclass = GDK_INPUT_OUTPUT;
5190 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
5192 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
5193 &attributes, attributes_mask);
5194 gtk_widget_set_window (widget, gdk_window);
5195 gdk_window_set_user_data (gdk_window, widget);
5197 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
5199 gdk_window_enable_synchronized_configure (gdk_window);
5203 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5205 /* ensure widget tree is properly size allocated */
5206 if (allocation.x == -1 &&
5207 allocation.y == -1 &&
5208 allocation.width == 1 &&
5209 allocation.height == 1)
5215 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5216 if (allocation.width == 0 || allocation.height == 0)
5218 /* non-empty window */
5219 allocation.width = 200;
5220 allocation.height = 200;
5222 gtk_widget_size_allocate (widget, &allocation);
5224 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5226 g_return_if_fail (!gtk_widget_get_realized (widget));
5229 gtk_widget_set_realized (widget, TRUE);
5233 case GTK_WINDOW_TOPLEVEL:
5234 attributes.window_type = GDK_WINDOW_TOPLEVEL;
5236 case GTK_WINDOW_POPUP:
5237 attributes.window_type = GDK_WINDOW_TEMP;
5240 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5244 attributes.title = priv->title;
5245 attributes.wmclass_name = priv->wmclass_name;
5246 attributes.wmclass_class = priv->wmclass_class;
5247 attributes.wclass = GDK_INPUT_OUTPUT;
5248 attributes.visual = gtk_widget_get_visual (widget);
5250 attributes_mask = 0;
5251 parent_window = gtk_widget_get_root_window (widget);
5253 gtk_widget_get_allocation (widget, &allocation);
5254 attributes.width = allocation.width;
5255 attributes.height = allocation.height;
5256 attributes.event_mask = gtk_widget_get_events (widget);
5257 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5258 GDK_KEY_PRESS_MASK |
5259 GDK_KEY_RELEASE_MASK |
5260 GDK_ENTER_NOTIFY_MASK |
5261 GDK_LEAVE_NOTIFY_MASK |
5262 GDK_FOCUS_CHANGE_MASK |
5263 GDK_STRUCTURE_MASK);
5264 attributes.type_hint = priv->type_hint;
5266 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5267 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5268 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5270 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5271 gtk_widget_set_window (widget, gdk_window);
5273 if (priv->opacity_set)
5274 gdk_window_set_opacity (gdk_window, priv->opacity);
5276 gdk_window_enable_synchronized_configure (gdk_window);
5278 gdk_window_set_user_data (gdk_window, window);
5280 context = gtk_widget_get_style_context (widget);
5281 gtk_style_context_set_background (context, gdk_window);
5284 if (priv->transient_parent &&
5285 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5286 gdk_window_set_transient_for (gdk_window,
5287 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5290 gdk_window_set_role (gdk_window, priv->wm_role);
5292 if (!priv->decorated)
5293 gdk_window_set_decorations (gdk_window, 0);
5295 if (!priv->deletable)
5296 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5298 if (gtk_window_get_skip_pager_hint (window))
5299 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5301 if (gtk_window_get_skip_taskbar_hint (window))
5302 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5304 if (gtk_window_get_accept_focus (window))
5305 gdk_window_set_accept_focus (gdk_window, TRUE);
5307 gdk_window_set_accept_focus (gdk_window, FALSE);
5309 if (gtk_window_get_focus_on_map (window))
5310 gdk_window_set_focus_on_map (gdk_window, TRUE);
5312 gdk_window_set_focus_on_map (gdk_window, FALSE);
5315 gdk_window_set_modal_hint (gdk_window, TRUE);
5317 gdk_window_set_modal_hint (gdk_window, FALSE);
5319 if (priv->startup_id)
5321 #ifdef GDK_WINDOWING_X11
5322 if (GDK_IS_X11_WINDOW (gdk_window))
5324 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5325 if (timestamp != GDK_CURRENT_TIME)
5326 gdk_x11_window_set_user_time (gdk_window, timestamp);
5329 if (!startup_id_is_fake (priv->startup_id))
5330 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5333 #ifdef GDK_WINDOWING_X11
5334 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5336 if (GDK_IS_X11_WINDOW (gdk_window))
5337 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5342 gtk_window_realize_icon (window);
5344 if (priv->has_resize_grip)
5345 resize_grip_create_window (window);
5349 gtk_window_unrealize (GtkWidget *widget)
5351 GtkWindow *window = GTK_WINDOW (widget);
5352 GtkWindowPrivate *priv = window->priv;
5353 GtkWindowGeometryInfo *info;
5355 /* On unrealize, we reset the size of the window such
5356 * that we will re-apply the default sizing stuff
5357 * next time we show the window.
5359 * Default positioning is reset on unmap, instead of unrealize.
5361 priv->need_default_size = TRUE;
5362 info = gtk_window_get_geometry_info (window, FALSE);
5365 info->resize_width = -1;
5366 info->resize_height = -1;
5367 info->last.configure_request.x = 0;
5368 info->last.configure_request.y = 0;
5369 info->last.configure_request.width = -1;
5370 info->last.configure_request.height = -1;
5371 /* be sure we reset geom hints on re-realize */
5372 info->last.flags = 0;
5376 gtk_window_unrealize_icon (window);
5378 if (priv->grip_window != NULL)
5379 resize_grip_destroy_window (window);
5381 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5384 static GtkJunctionSides
5385 get_grip_junction (GtkWidget *widget)
5387 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5388 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5390 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5394 get_drag_edge (GtkWidget *widget,
5395 GdkWindowEdge *edge)
5397 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5398 gboolean hresizable;
5399 gboolean vresizable;
5400 GtkTextDirection dir;
5401 GtkWindowGeometryInfo *info;
5406 info = priv->geometry_info;
5409 GdkWindowHints flags = info->last.flags;
5410 GdkGeometry *geometry = &info->last.geometry;
5412 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5414 hresizable = geometry->min_width < geometry->max_width;
5415 vresizable = geometry->min_height < geometry->max_height;
5419 dir = gtk_widget_get_direction (widget);
5421 if (hresizable && vresizable)
5422 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5423 else if (hresizable)
5424 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5425 else if (vresizable)
5426 *edge = GDK_WINDOW_EDGE_SOUTH;
5434 set_grip_cursor (GtkWindow *window)
5436 GtkWidget *widget = GTK_WIDGET (window);
5437 GtkWindowPrivate *priv = window->priv;
5439 if (priv->grip_window == NULL)
5442 if (gtk_widget_is_sensitive (widget))
5445 GdkDisplay *display;
5446 GdkCursorType cursor_type;
5449 cursor_type = GDK_LEFT_PTR;
5451 if (get_drag_edge (widget, &edge))
5455 case GDK_WINDOW_EDGE_EAST:
5456 cursor_type = GDK_RIGHT_SIDE;
5458 case GDK_WINDOW_EDGE_SOUTH_EAST:
5459 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5461 case GDK_WINDOW_EDGE_SOUTH:
5462 cursor_type = GDK_BOTTOM_SIDE;
5464 case GDK_WINDOW_EDGE_SOUTH_WEST:
5465 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5467 case GDK_WINDOW_EDGE_WEST:
5468 cursor_type = GDK_LEFT_SIDE;
5474 display = gtk_widget_get_display (widget);
5475 cursor = gdk_cursor_new_for_display (display, cursor_type);
5476 gdk_window_set_cursor (priv->grip_window, cursor);
5477 g_object_unref (cursor);
5480 gdk_window_set_cursor (priv->grip_window, NULL);
5484 set_grip_shape (GtkWindow *window)
5486 GtkWindowPrivate *priv = window->priv;
5487 cairo_region_t *region;
5488 cairo_surface_t *surface;
5490 double width, height;
5492 if (priv->grip_window == NULL)
5495 width = gdk_window_get_width (priv->grip_window);
5496 height = gdk_window_get_height (priv->grip_window);
5497 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
5499 cr = cairo_create (surface);
5500 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5502 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5503 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5505 cairo_move_to (cr, width, 0.0);
5506 cairo_line_to (cr, width, height);
5507 cairo_line_to (cr, 0.0, height);
5511 cairo_move_to (cr, 0.0, 0.0);
5512 cairo_line_to (cr, width, height);
5513 cairo_line_to (cr, 0.0, height);
5515 cairo_close_path (cr);
5518 region = gdk_cairo_region_create_from_surface (surface);
5519 cairo_surface_destroy (surface);
5521 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5522 cairo_region_destroy (region);
5526 set_grip_position (GtkWindow *window)
5528 GtkWindowPrivate *priv = window->priv;
5531 if (priv->grip_window == NULL)
5534 gtk_window_get_resize_grip_area (window, &rect);
5535 gdk_window_raise (priv->grip_window);
5536 gdk_window_move_resize (priv->grip_window,
5538 rect.width, rect.height);
5541 /* _gtk_window_set_allocation:
5542 * @window: a #GtkWindow
5543 * @allocation: the new allocation
5545 * This function is like gtk_widget_set_allocation()
5546 * but does the necessary extra work to update
5547 * the resize grip positioning, etc.
5549 * Call this instead of gtk_widget_set_allocation()
5550 * when overriding ::size_allocate in a GtkWindow
5551 * subclass without chaining up.
5554 _gtk_window_set_allocation (GtkWindow *window,
5555 GtkAllocation *allocation)
5557 GtkWidget *widget = (GtkWidget *)window;
5559 gtk_widget_set_allocation (widget, allocation);
5561 if (gtk_widget_get_realized (widget))
5563 /* If it's not a toplevel we're embedded, we need to resize
5564 * the window's window and skip the grip.
5566 if (!gtk_widget_is_toplevel (widget))
5568 gdk_window_move_resize (gtk_widget_get_window (widget),
5569 allocation->x, allocation->y,
5570 allocation->width, allocation->height);
5574 update_grip_visibility (window);
5575 set_grip_position (window);
5581 gtk_window_size_allocate (GtkWidget *widget,
5582 GtkAllocation *allocation)
5584 GtkWindow *window = GTK_WINDOW (widget);
5585 GtkAllocation child_allocation;
5589 _gtk_window_set_allocation (window, allocation);
5591 child = gtk_bin_get_child (&(window->bin));
5592 if (child && gtk_widget_get_visible (child))
5594 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5595 child_allocation.x = border_width;
5596 child_allocation.y = border_width;
5597 child_allocation.width = MAX (1, allocation->width - border_width * 2);
5598 child_allocation.height = MAX (1, allocation->height - border_width * 2);
5600 gtk_widget_size_allocate (child, &child_allocation);
5605 gtk_window_configure_event (GtkWidget *widget,
5606 GdkEventConfigure *event)
5608 GtkAllocation allocation;
5609 GtkWindow *window = GTK_WINDOW (widget);
5610 GtkWindowPrivate *priv = window->priv;
5611 gboolean expected_reply = priv->configure_request_count > 0;
5613 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5615 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5616 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5618 gdk_window_configure_finished (gtk_widget_get_window (widget));
5622 /* priv->configure_request_count incremented for each
5623 * configure request, and decremented to a min of 0 for
5624 * each configure notify.
5626 * All it means is that we know we will get at least
5627 * priv->configure_request_count more configure notifies.
5628 * We could get more configure notifies than that; some
5629 * of the configure notifies we get may be unrelated to
5630 * the configure requests. But we will get at least
5631 * priv->configure_request_count notifies.
5634 if (priv->configure_request_count > 0)
5636 priv->configure_request_count -= 1;
5637 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5640 /* As an optimization, we avoid a resize when possible.
5642 * The only times we can avoid a resize are:
5643 * - we know only the position changed, not the size
5644 * - we know we have made more requests and so will get more
5645 * notifies and can wait to resize when we get them
5647 gtk_widget_get_allocation (widget, &allocation);
5648 if (!expected_reply &&
5649 (allocation.width == event->width &&
5650 allocation.height == event->height))
5652 gdk_window_configure_finished (gtk_widget_get_window (widget));
5657 * If we do need to resize, we do that by:
5658 * - filling in widget->allocation with the new size
5659 * - setting configure_notify_received to TRUE
5660 * for use in gtk_window_move_resize()
5661 * - queueing a resize, leading to invocation of
5662 * gtk_window_move_resize() in an idle handler
5666 priv->configure_notify_received = TRUE;
5668 allocation.width = event->width;
5669 allocation.height = event->height;
5670 gtk_widget_set_allocation (widget, &allocation);
5672 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5674 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5680 gtk_window_state_event (GtkWidget *widget,
5681 GdkEventWindowState *event)
5683 update_grip_visibility (GTK_WINDOW (widget));
5685 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
5686 ensure_state_flag_backdrop (widget);
5692 gtk_window_direction_changed (GtkWidget *widget,
5693 GtkTextDirection prev_dir)
5695 GtkWindow *window = GTK_WINDOW (widget);
5697 set_grip_cursor (window);
5698 set_grip_position (window);
5699 set_grip_shape (window);
5703 gtk_window_state_changed (GtkWidget *widget,
5704 GtkStateType previous_state)
5706 GtkWindow *window = GTK_WINDOW (widget);
5708 update_grip_visibility (window);
5712 gtk_window_style_updated (GtkWidget *widget)
5714 GtkWindow *window = GTK_WINDOW (widget);
5715 GtkWindowPrivate *priv = window->priv;
5718 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5720 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5722 gdk_window_move_resize (priv->grip_window,
5724 rect.width, rect.height);
5726 set_grip_shape (window);
5727 gtk_widget_queue_resize (widget);
5732 resize_grip_create_window (GtkWindow *window)
5735 GtkWindowPrivate *priv;
5736 GdkWindowAttr attributes;
5737 gint attributes_mask;
5739 GdkRGBA transparent = {0, 0, 0, 0};
5741 priv = window->priv;
5742 widget = GTK_WIDGET (window);
5744 g_return_if_fail (gtk_widget_get_realized (widget));
5745 g_return_if_fail (priv->grip_window == NULL);
5747 gtk_window_get_resize_grip_area (window, &rect);
5749 attributes.x = rect.x;
5750 attributes.y = rect.y;
5751 attributes.width = rect.width;
5752 attributes.height = rect.height;
5753 attributes.window_type = GDK_WINDOW_CHILD;
5754 attributes.wclass = GDK_INPUT_OUTPUT;
5755 attributes.event_mask = gtk_widget_get_events (widget) |
5757 GDK_BUTTON_PRESS_MASK;
5759 attributes_mask = GDK_WA_X | GDK_WA_Y;
5761 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5764 gdk_window_set_background_rgba (priv->grip_window, &transparent);
5766 gdk_window_set_user_data (priv->grip_window, widget);
5768 gdk_window_raise (priv->grip_window);
5770 set_grip_shape (window);
5771 update_grip_visibility (window);
5775 resize_grip_destroy_window (GtkWindow *window)
5777 GtkWindowPrivate *priv = window->priv;
5779 gdk_window_set_user_data (priv->grip_window, NULL);
5780 gdk_window_destroy (priv->grip_window);
5781 priv->grip_window = NULL;
5782 update_grip_visibility (window);
5786 * gtk_window_set_has_resize_grip:
5787 * @window: a #GtkWindow
5788 * @value: %TRUE to allow a resize grip
5790 * Sets whether @window has a corner resize grip.
5792 * Note that the resize grip is only shown if the window
5793 * is actually resizable and not maximized. Use
5794 * gtk_window_resize_grip_is_visible() to find out if the
5795 * resize grip is currently shown.
5800 gtk_window_set_has_resize_grip (GtkWindow *window,
5803 GtkWidget *widget = GTK_WIDGET (window);
5804 GtkWindowPrivate *priv = window->priv;
5806 value = value != FALSE;
5808 if (value != priv->has_resize_grip)
5810 priv->has_resize_grip = value;
5811 gtk_widget_queue_draw (widget);
5813 if (gtk_widget_get_realized (widget) &&
5814 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5816 if (priv->has_resize_grip && priv->grip_window == NULL)
5817 resize_grip_create_window (window);
5818 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5819 resize_grip_destroy_window (window);
5822 g_object_notify (G_OBJECT (window), "has-resize-grip");
5827 update_grip_visibility (GtkWindow *window)
5829 GtkWindowPrivate *priv = window->priv;
5832 val = gtk_window_resize_grip_is_visible (window);
5834 if (priv->grip_window != NULL)
5838 gdk_window_show (priv->grip_window);
5839 set_grip_cursor (window);
5843 gdk_window_hide (priv->grip_window);
5847 if (priv->resize_grip_visible != val)
5849 priv->resize_grip_visible = val;
5851 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5856 * gtk_window_resize_grip_is_visible:
5857 * @window: a #GtkWindow
5859 * Determines whether a resize grip is visible for the specified window.
5861 * Returns: %TRUE if a resize grip exists and is visible
5866 gtk_window_resize_grip_is_visible (GtkWindow *window)
5869 GtkWindowPrivate *priv;
5872 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5874 priv = window->priv;
5875 widget = GTK_WIDGET (window);
5877 if (priv->type == GTK_WINDOW_POPUP)
5880 if (!priv->resizable)
5883 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5886 if (gtk_widget_get_realized (widget))
5888 GdkWindowState state;
5890 state = gdk_window_get_state (gtk_widget_get_window (widget));
5892 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5896 if (!get_drag_edge (widget, &edge))
5899 return window->priv->has_resize_grip;
5903 * gtk_window_get_has_resize_grip:
5904 * @window: a #GtkWindow
5906 * Determines whether the window may have a resize grip.
5908 * Returns: %TRUE if the window has a resize grip
5913 gtk_window_get_has_resize_grip (GtkWindow *window)
5915 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5917 return window->priv->has_resize_grip;
5921 * gtk_window_get_resize_grip_area:
5922 * @window: a #GtkWindow
5923 * @rect: (out): a pointer to a #GdkRectangle which we should store
5924 * the resize grip area
5926 * If a window has a resize grip, this will retrieve the grip
5927 * position, width and height into the specified #GdkRectangle.
5929 * Returns: %TRUE if the resize grip's area was retrieved
5934 gtk_window_get_resize_grip_area (GtkWindow *window,
5937 GtkWidget *widget = GTK_WIDGET (window);
5938 GtkAllocation allocation;
5942 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5944 if (!window->priv->has_resize_grip)
5947 gtk_widget_get_allocation (widget, &allocation);
5949 gtk_widget_style_get (widget,
5950 "resize-grip-width", &grip_width,
5951 "resize-grip-height", &grip_height,
5954 if (grip_width > allocation.width)
5955 grip_width = allocation.width;
5957 if (grip_height > allocation.height)
5958 grip_height = allocation.height;
5960 rect->width = grip_width;
5961 rect->height = grip_height;
5962 rect->y = allocation.y + allocation.height - grip_height;
5964 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5965 rect->x = allocation.x + allocation.width - grip_width;
5967 rect->x = allocation.x;
5972 /* the accel_key and accel_mods fields of the key have to be setup
5973 * upon calling this function. it'll then return whether that key
5974 * is at all used as accelerator, and if so will OR in the
5975 * accel_flags member of the key.
5978 _gtk_window_query_nonaccels (GtkWindow *window,
5980 GdkModifierType accel_mods)
5982 GtkWindowPrivate *priv;
5984 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5986 priv = window->priv;
5988 /* movement keys are considered locked accels */
5991 static const guint bindings[] = {
5992 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,
5993 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,
5997 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5998 if (bindings[i] == accel_key)
6002 /* mnemonics are considered locked accels */
6003 if (accel_mods == priv->mnemonic_modifier)
6005 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
6006 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
6014 * gtk_window_propagate_key_event:
6015 * @window: a #GtkWindow
6016 * @event: a #GdkEventKey
6018 * Propagate a key press or release event to the focus widget and
6019 * up the focus container chain until a widget handles @event.
6020 * This is normally called by the default ::key_press_event and
6021 * ::key_release_event handlers for toplevel windows,
6022 * however in some cases it may be useful to call this directly when
6023 * overriding the standard key handling for a toplevel window.
6025 * Return value: %TRUE if a widget in the focus chain handled the event.
6030 gtk_window_propagate_key_event (GtkWindow *window,
6033 GtkWindowPrivate *priv;
6034 gboolean handled = FALSE;
6035 GtkWidget *widget, *focus;
6037 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6039 priv = window->priv;
6040 widget = GTK_WIDGET (window);
6042 focus = priv->focus_widget;
6044 g_object_ref (focus);
6047 focus && focus != widget &&
6048 gtk_widget_get_toplevel (focus) == widget)
6052 if (gtk_widget_is_sensitive (focus))
6053 handled = gtk_widget_event (focus, (GdkEvent*) event);
6055 parent = gtk_widget_get_parent (focus);
6057 g_object_ref (parent);
6059 g_object_unref (focus);
6065 g_object_unref (focus);
6071 gtk_window_key_press_event (GtkWidget *widget,
6074 GtkWindow *window = GTK_WINDOW (widget);
6075 gboolean handled = FALSE;
6077 /* handle mnemonics and accelerators */
6079 handled = gtk_window_activate_key (window, event);
6081 /* handle focus widget key events */
6083 handled = gtk_window_propagate_key_event (window, event);
6085 /* Chain up, invokes binding set */
6087 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
6093 gtk_window_key_release_event (GtkWidget *widget,
6096 GtkWindow *window = GTK_WINDOW (widget);
6097 gboolean handled = FALSE;
6099 /* handle focus widget key events */
6101 handled = gtk_window_propagate_key_event (window, event);
6103 /* Chain up, invokes binding set */
6105 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
6111 gtk_window_button_press_event (GtkWidget *widget,
6112 GdkEventButton *event)
6114 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
6117 if (event->window == priv->grip_window)
6119 if (get_drag_edge (widget, &edge))
6120 gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
6122 gdk_event_get_device ((GdkEvent *) event),
6135 gtk_window_real_activate_default (GtkWindow *window)
6137 gtk_window_activate_default (window);
6141 gtk_window_real_activate_focus (GtkWindow *window)
6143 gtk_window_activate_focus (window);
6147 gtk_window_enter_notify_event (GtkWidget *widget,
6148 GdkEventCrossing *event)
6154 gtk_window_leave_notify_event (GtkWidget *widget,
6155 GdkEventCrossing *event)
6161 do_focus_change (GtkWidget *widget,
6165 GdkDeviceManager *device_manager;
6168 g_object_ref (widget);
6170 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
6171 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6172 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
6173 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
6175 for (d = devices; d; d = d->next)
6177 GdkDevice *dev = d->data;
6180 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
6183 /* Skip non-master keyboards that haven't
6184 * selected for events from this window
6186 window = gtk_widget_get_window (widget);
6187 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
6188 window && !gdk_window_get_device_events (window, dev))
6191 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
6193 fevent->focus_change.type = GDK_FOCUS_CHANGE;
6194 fevent->focus_change.window = window;
6196 g_object_ref (window);
6197 fevent->focus_change.in = in;
6198 gdk_event_set_device (fevent, dev);
6200 gtk_widget_send_focus_change (widget, fevent);
6202 gdk_event_free (fevent);
6205 g_list_free (devices);
6206 g_object_unref (widget);
6210 maybe_set_mnemonics_visible (GtkWindow *window)
6213 GdkDeviceManager *device_manager;
6215 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
6216 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6218 for (d = devices; d; d = d->next)
6220 GdkDevice *dev = d->data;
6222 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6224 GdkModifierType mask;
6226 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6228 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6230 gtk_window_set_mnemonics_visible (window, TRUE);
6236 g_list_free (devices);
6240 gtk_window_focus_in_event (GtkWidget *widget,
6241 GdkEventFocus *event)
6243 GtkWindow *window = GTK_WINDOW (widget);
6244 gboolean auto_mnemonics;
6246 /* It appears spurious focus in events can occur when
6247 * the window is hidden. So we'll just check to see if
6248 * the window is visible before actually handling the
6251 if (gtk_widget_get_visible (widget))
6253 _gtk_window_set_has_toplevel_focus (window, TRUE);
6254 _gtk_window_set_is_active (window, TRUE);
6256 g_object_get (gtk_widget_get_settings (widget),
6257 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6259 maybe_set_mnemonics_visible (window);
6266 gtk_window_focus_out_event (GtkWidget *widget,
6267 GdkEventFocus *event)
6269 GtkWindow *window = GTK_WINDOW (widget);
6270 gboolean auto_mnemonics;
6272 _gtk_window_set_has_toplevel_focus (window, FALSE);
6273 _gtk_window_set_is_active (window, FALSE);
6275 /* set the mnemonic-visible property to false */
6276 g_object_get (gtk_widget_get_settings (widget),
6277 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6279 gtk_window_set_mnemonics_visible (window, FALSE);
6285 gtk_window_check_resize (GtkContainer *container)
6287 /* If the window is not toplevel anymore than it's embedded somewhere,
6288 * so handle it like a normal window */
6289 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6290 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6291 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6292 gtk_window_move_resize (GTK_WINDOW (container));
6296 gtk_window_focus (GtkWidget *widget,
6297 GtkDirectionType direction)
6299 GtkWindowPrivate *priv;
6302 GtkContainer *container;
6304 GtkWidget *old_focus_child;
6307 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6308 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6310 container = GTK_CONTAINER (widget);
6311 window = GTK_WINDOW (widget);
6312 priv = window->priv;
6313 bin = GTK_BIN (widget);
6315 old_focus_child = gtk_container_get_focus_child (container);
6317 /* We need a special implementation here to deal properly with wrapping
6318 * around in the tab chain without the danger of going into an
6321 if (old_focus_child)
6323 if (gtk_widget_child_focus (old_focus_child, direction))
6327 if (priv->focus_widget)
6329 if (direction == GTK_DIR_LEFT ||
6330 direction == GTK_DIR_RIGHT ||
6331 direction == GTK_DIR_UP ||
6332 direction == GTK_DIR_DOWN)
6337 /* Wrapped off the end, clear the focus setting for the toplpevel */
6338 parent = gtk_widget_get_parent (priv->focus_widget);
6341 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6342 parent = gtk_widget_get_parent (parent);
6345 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6348 /* Now try to focus the first widget in the window */
6349 child = gtk_bin_get_child (bin);
6352 if (gtk_widget_child_focus (child, direction))
6360 gtk_window_move_focus (GtkWidget *widget,
6361 GtkDirectionType dir)
6363 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6365 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6369 gtk_widget_child_focus (widget, dir);
6371 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6372 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6376 gtk_window_real_set_focus (GtkWindow *window,
6379 GtkWindowPrivate *priv = window->priv;
6380 GtkWidget *old_focus = priv->focus_widget;
6381 gboolean had_default = FALSE;
6382 gboolean focus_had_default = FALSE;
6383 gboolean old_focus_had_default = FALSE;
6387 g_object_ref (old_focus);
6388 g_object_freeze_notify (G_OBJECT (old_focus));
6389 old_focus_had_default = gtk_widget_has_default (old_focus);
6393 g_object_ref (focus);
6394 g_object_freeze_notify (G_OBJECT (focus));
6395 focus_had_default = gtk_widget_has_default (focus);
6398 if (priv->default_widget)
6399 had_default = gtk_widget_has_default (priv->default_widget);
6401 if (priv->focus_widget)
6403 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6404 (priv->focus_widget != priv->default_widget))
6406 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6407 gtk_widget_queue_draw (priv->focus_widget);
6409 if (priv->default_widget)
6410 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6413 priv->focus_widget = NULL;
6415 if (priv->has_focus)
6416 do_focus_change (old_focus, FALSE);
6418 g_object_notify (G_OBJECT (old_focus), "is-focus");
6421 /* The above notifications may have set a new focus widget,
6422 * if so, we don't want to override it.
6424 if (focus && !priv->focus_widget)
6426 priv->focus_widget = focus;
6428 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6429 (priv->focus_widget != priv->default_widget))
6431 if (gtk_widget_get_can_default (priv->focus_widget))
6432 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6434 if (priv->default_widget)
6435 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6438 if (priv->has_focus)
6439 do_focus_change (priv->focus_widget, TRUE);
6441 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6444 /* If the default widget changed, a redraw will have been queued
6445 * on the old and new default widgets by gtk_window_set_default(), so
6446 * we only have to worry about the case where it didn't change.
6447 * We'll sometimes queue a draw twice on the new widget but that
6450 if (priv->default_widget &&
6451 (had_default != gtk_widget_has_default (priv->default_widget)))
6452 gtk_widget_queue_draw (priv->default_widget);
6456 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6457 gtk_widget_queue_draw (old_focus);
6459 g_object_thaw_notify (G_OBJECT (old_focus));
6460 g_object_unref (old_focus);
6464 if (focus_had_default != gtk_widget_has_default (focus))
6465 gtk_widget_queue_draw (focus);
6467 g_object_thaw_notify (G_OBJECT (focus));
6468 g_object_unref (focus);
6474 gtk_window_get_preferred_width (GtkWidget *widget,
6482 window = GTK_WINDOW (widget);
6483 child = gtk_bin_get_child (GTK_BIN (window));
6485 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6486 *minimum_size = border_width * 2;
6487 *natural_size = border_width * 2;
6489 if (child && gtk_widget_get_visible (child))
6491 gint child_min, child_nat;
6492 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6494 *minimum_size += child_min;
6495 *natural_size += child_nat;
6500 gtk_window_get_preferred_height (GtkWidget *widget,
6508 window = GTK_WINDOW (widget);
6509 child = gtk_bin_get_child (GTK_BIN (window));
6511 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6512 *minimum_size = border_width * 2;
6513 *natural_size = border_width * 2;
6515 if (child && gtk_widget_get_visible (child))
6517 gint child_min, child_nat;
6518 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6520 *minimum_size += child_min;
6521 *natural_size += child_nat;
6527 * _gtk_window_unset_focus_and_default:
6528 * @window: a #GtkWindow
6529 * @widget: a widget inside of @window
6531 * Checks whether the focus and default widgets of @window are
6532 * @widget or a descendent of @widget, and if so, unset them.
6535 _gtk_window_unset_focus_and_default (GtkWindow *window,
6539 GtkWindowPrivate *priv = window->priv;
6543 g_object_ref (window);
6544 g_object_ref (widget);
6546 parent = gtk_widget_get_parent (widget);
6547 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6549 child = priv->focus_widget;
6551 while (child && child != widget)
6552 child = gtk_widget_get_parent (child);
6554 if (child == widget)
6555 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6558 child = priv->default_widget;
6560 while (child && child != widget)
6561 child = gtk_widget_get_parent (child);
6563 if (child == widget)
6564 gtk_window_set_default (window, NULL);
6566 g_object_unref (widget);
6567 g_object_unref (window);
6570 /*********************************
6571 * Functions related to resizing *
6572 *********************************/
6575 geometry_size_to_pixels (GdkGeometry *geometry,
6580 gint base_width = 0;
6581 gint base_height = 0;
6583 gint min_height = 0;
6585 gint height_inc = 1;
6587 if (flags & GDK_HINT_BASE_SIZE)
6589 base_width = geometry->base_width;
6590 base_height = geometry->base_height;
6592 if (flags & GDK_HINT_MIN_SIZE)
6594 min_width = geometry->min_width;
6595 min_height = geometry->min_height;
6597 if (flags & GDK_HINT_RESIZE_INC)
6599 width_inc = geometry->width_inc;
6600 height_inc = geometry->height_inc;
6604 *width = MAX (*width * width_inc + base_width, min_width);
6606 *height = MAX (*height * height_inc + base_height, min_height);
6609 /* This function doesn't constrain to geometry hints */
6611 gtk_window_compute_configure_request_size (GtkWindow *window,
6612 GdkGeometry *geometry,
6617 GtkWindowPrivate *priv = window->priv;
6618 GtkWindowGeometryInfo *info;
6621 * - we've done a size request
6624 info = gtk_window_get_geometry_info (window, FALSE);
6626 if (priv->need_default_size)
6628 gtk_window_guess_default_size (window, width, height);
6630 /* If window is empty so requests 0, default to random nonzero size */
6631 if (*width == 0 && *height == 0)
6637 /* Override with default size */
6641 if (info->default_width > 0)
6642 *width = info->default_width;
6643 if (info->default_height > 0)
6644 *height = info->default_height;
6646 if (info->default_is_geometry)
6647 geometry_size_to_pixels (geometry, flags,
6648 info->default_width > 0 ? width : NULL,
6649 info->default_height > 0 ? height : NULL);
6654 GtkAllocation allocation;
6656 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6658 /* Default to keeping current size */
6659 *width = allocation.width;
6660 *height = allocation.height;
6663 /* Override any size with gtk_window_resize() values */
6666 if (info->resize_width > 0)
6667 *width = info->resize_width;
6668 if (info->resize_height > 0)
6669 *height = info->resize_height;
6671 if (info->resize_is_geometry)
6672 geometry_size_to_pixels (geometry, flags,
6673 info->resize_width > 0 ? width : NULL,
6674 info->resize_height > 0 ? height : NULL);
6677 /* Don't ever request zero width or height, its not supported by
6678 gdk. The size allocation code will round it to 1 anyway but if
6679 we do it then the value returned from this function will is
6680 not comparable to the size allocation read from the GtkWindow. */
6681 *width = MAX (*width, 1);
6682 *height = MAX (*height, 1);
6685 static GtkWindowPosition
6686 get_effective_position (GtkWindow *window)
6688 GtkWindowPrivate *priv = window->priv;
6689 GtkWindowPosition pos = priv->position;
6691 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6692 (priv->transient_parent == NULL ||
6693 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6694 pos = GTK_WIN_POS_NONE;
6700 get_center_monitor_of_window (GtkWindow *window)
6702 /* We could try to sort out the relative positions of the monitors and
6703 * stuff, or we could just be losers and assume you have a row
6704 * or column of monitors.
6706 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6710 get_monitor_containing_pointer (GtkWindow *window)
6714 GdkScreen *window_screen;
6715 GdkScreen *pointer_screen;
6716 GdkDisplay *display;
6717 GdkDeviceManager *device_manager;
6720 window_screen = gtk_window_check_screen (window);
6721 display = gdk_screen_get_display (window_screen);
6722 device_manager = gdk_display_get_device_manager (display);
6723 pointer = gdk_device_manager_get_client_pointer (device_manager);
6725 gdk_device_get_position (pointer,
6729 if (pointer_screen == window_screen)
6730 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6738 center_window_on_monitor (GtkWindow *window,
6744 GdkRectangle monitor;
6747 monitor_num = get_monitor_containing_pointer (window);
6749 if (monitor_num == -1)
6750 monitor_num = get_center_monitor_of_window (window);
6752 gdk_screen_get_monitor_workarea (gtk_window_check_screen (window),
6753 monitor_num, &monitor);
6755 *x = (monitor.width - w) / 2 + monitor.x;
6756 *y = (monitor.height - h) / 2 + monitor.y;
6758 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6759 * and WM decorations.
6773 if (extent > clamp_extent)
6775 *base = clamp_base + clamp_extent/2 - extent/2;
6776 else if (*base < clamp_base)
6778 else if (*base + extent > clamp_base + clamp_extent)
6779 *base = clamp_base + clamp_extent - extent;
6783 clamp_window_to_rectangle (gint *x,
6787 const GdkRectangle *rect)
6789 #ifdef DEBUGGING_OUTPUT
6790 g_print ("%s: %+d%+d %dx%d: %+d%+d: %dx%d", G_STRFUNC, rect->x, rect->y, rect->width, rect->height, *x, *y, w, h);
6793 /* If it is too large, center it. If it fits on the monitor but is
6794 * partially outside, move it to the closest edge. Do this
6795 * separately in x and y directions.
6797 clamp (x, w, rect->x, rect->width);
6798 clamp (y, h, rect->y, rect->height);
6799 #ifdef DEBUGGING_OUTPUT
6800 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6806 gtk_window_compute_configure_request (GtkWindow *window,
6807 GdkRectangle *request,
6808 GdkGeometry *geometry,
6811 GtkWindowPrivate *priv = window->priv;
6812 GdkGeometry new_geometry;
6815 GtkWindowPosition pos;
6816 GtkWidget *parent_widget;
6817 GtkWindowGeometryInfo *info;
6821 screen = gtk_window_check_screen (window);
6823 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6824 gtk_window_compute_configure_request_size (window,
6825 &new_geometry, new_flags,
6828 gtk_window_constrain_size (window,
6829 &new_geometry, new_flags,
6833 parent_widget = (GtkWidget*) priv->transient_parent;
6835 pos = get_effective_position (window);
6836 info = gtk_window_get_geometry_info (window, FALSE);
6838 /* by default, don't change position requested */
6841 x = info->last.configure_request.x;
6842 y = info->last.configure_request.y;
6851 if (priv->need_default_position)
6854 /* FIXME this all interrelates with window gravity.
6855 * For most of them I think we want to set GRAVITY_CENTER.
6857 * Not sure how to go about that.
6861 /* here we are only handling CENTER_ALWAYS
6862 * as it relates to default positioning,
6863 * where it's equivalent to simply CENTER
6865 case GTK_WIN_POS_CENTER_ALWAYS:
6866 case GTK_WIN_POS_CENTER:
6867 center_window_on_monitor (window, w, h, &x, &y);
6870 case GTK_WIN_POS_CENTER_ON_PARENT:
6872 GtkAllocation allocation;
6873 GdkWindow *gdk_window;
6875 GdkRectangle monitor;
6878 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6880 gdk_window = gtk_widget_get_window (parent_widget);
6882 if (gdk_window != NULL)
6883 monitor_num = gdk_screen_get_monitor_at_window (screen,
6888 gdk_window_get_origin (gdk_window,
6891 gtk_widget_get_allocation (parent_widget, &allocation);
6892 x = ox + (allocation.width - w) / 2;
6893 y = oy + (allocation.height - h) / 2;
6895 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6896 * WM decorations. If parent wasn't on a monitor, just
6899 if (monitor_num >= 0)
6901 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6902 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6907 case GTK_WIN_POS_MOUSE:
6909 gint screen_width = gdk_screen_get_width (screen);
6910 gint screen_height = gdk_screen_get_height (screen);
6912 GdkRectangle monitor;
6913 GdkDisplay *display;
6914 GdkDeviceManager *device_manager;
6916 GdkScreen *pointer_screen;
6919 display = gdk_screen_get_display (screen);
6920 device_manager = gdk_display_get_device_manager (display);
6921 pointer = gdk_device_manager_get_client_pointer (device_manager);
6923 gdk_device_get_position (pointer,
6927 if (pointer_screen == screen)
6928 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6934 x = CLAMP (x, 0, screen_width - w);
6935 y = CLAMP (y, 0, screen_height - h);
6937 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6938 * WM decorations. Don't try to figure out what's going
6939 * on if the mouse wasn't inside a monitor.
6941 if (monitor_num >= 0)
6943 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6944 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6952 } /* if (priv->need_default_position) */
6954 if (priv->need_default_position && info &&
6955 info->initial_pos_set)
6957 x = info->initial_x;
6958 y = info->initial_y;
6959 gtk_window_constrain_position (window, w, h, &x, &y);
6965 request->height = h;
6968 *geometry = new_geometry;
6974 gtk_window_constrain_position (GtkWindow *window,
6980 GtkWindowPrivate *priv = window->priv;
6982 /* See long comments in gtk_window_move_resize()
6983 * on when it's safe to call this function.
6985 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6987 gint center_x, center_y;
6989 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6997 gtk_window_move_resize (GtkWindow *window)
7001 * First we determine whether any information has changed that would
7002 * cause us to revise our last configure request. If we would send
7003 * a different configure request from last time, then
7004 * configure_request_size_changed = TRUE or
7005 * configure_request_pos_changed = TRUE. configure_request_size_changed
7006 * may be true due to new hints, a gtk_window_resize(), or whatever.
7007 * configure_request_pos_changed may be true due to gtk_window_set_position()
7008 * or gtk_window_move().
7010 * If the configure request has changed, we send off a new one. To
7011 * ensure GTK+ invariants are maintained (resize queue does what it
7012 * should), we go ahead and size_allocate the requested size in this
7015 * If the configure request has not changed, we don't ever resend
7016 * it, because it could mean fighting the user or window manager.
7019 * To prepare the configure request, we come up with a base size/pos:
7020 * - the one from gtk_window_move()/gtk_window_resize()
7021 * - else default_width, default_height if we haven't ever
7023 * - else the size request if we haven't ever been mapped,
7024 * as a substitute default size
7025 * - else the current size of the window, as received from
7026 * configure notifies (i.e. the current allocation)
7028 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
7029 * the position request to be centered.
7031 GtkWindowPrivate *priv = window->priv;
7032 GtkAllocation allocation;
7034 GtkContainer *container;
7035 GtkWindowGeometryInfo *info;
7036 GdkGeometry new_geometry;
7037 GdkWindow *gdk_window;
7039 GdkRectangle new_request;
7040 gboolean configure_request_size_changed;
7041 gboolean configure_request_pos_changed;
7042 gboolean hints_changed; /* do we need to send these again */
7043 GtkWindowLastGeometryInfo saved_last_info;
7045 widget = GTK_WIDGET (window);
7047 gdk_window = gtk_widget_get_window (widget);
7048 container = GTK_CONTAINER (widget);
7049 info = gtk_window_get_geometry_info (window, TRUE);
7051 configure_request_size_changed = FALSE;
7052 configure_request_pos_changed = FALSE;
7054 gtk_window_compute_configure_request (window, &new_request,
7055 &new_geometry, &new_flags);
7057 /* This check implies the invariant that we never set info->last
7058 * without setting the hints and sending off a configure request.
7060 * If we change info->last without sending the request, we may
7063 if (info->last.configure_request.x != new_request.x ||
7064 info->last.configure_request.y != new_request.y)
7065 configure_request_pos_changed = TRUE;
7067 if ((info->last.configure_request.width != new_request.width ||
7068 info->last.configure_request.height != new_request.height))
7069 configure_request_size_changed = TRUE;
7071 hints_changed = FALSE;
7073 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
7074 &new_geometry, new_flags))
7076 hints_changed = TRUE;
7079 /* Position Constraints
7080 * ====================
7082 * POS_CENTER_ALWAYS is conceptually a constraint rather than
7083 * a default. The other POS_ values are used only when the
7084 * window is shown, not after that.
7086 * However, we can't implement a position constraint as
7087 * "anytime the window size changes, center the window"
7088 * because this may well end up fighting the WM or user. In
7089 * fact it gets in an infinite loop with at least one WM.
7091 * Basically, applications are in no way in a position to
7092 * constrain the position of a window, with one exception:
7093 * override redirect windows. (Really the intended purpose
7094 * of CENTER_ALWAYS anyhow, I would think.)
7096 * So the way we implement this "constraint" is to say that when WE
7097 * cause a move or resize, i.e. we make a configure request changing
7098 * window size, we recompute the CENTER_ALWAYS position to reflect
7099 * the new window size, and include it in our request. Also, if we
7100 * just turned on CENTER_ALWAYS we snap to center with a new
7101 * request. Otherwise, if we are just NOTIFIED of a move or resize
7102 * done by someone else e.g. the window manager, we do NOT send a
7103 * new configure request.
7105 * For override redirect windows, this works fine; all window
7106 * sizes are from our configure requests. For managed windows,
7107 * it is at least semi-sane, though who knows what the
7108 * app author is thinking.
7111 /* This condition should be kept in sync with the condition later on
7112 * that determines whether we send a configure request. i.e. we
7113 * should do this position constraining anytime we were going to
7114 * send a configure request anyhow, plus when constraints have
7117 if (configure_request_pos_changed ||
7118 configure_request_size_changed ||
7120 info->position_constraints_changed)
7122 /* We request the constrained position if:
7123 * - we were changing position, and need to clamp
7124 * the change to the constraint
7125 * - we're changing the size anyway
7126 * - set_position() was called to toggle CENTER_ALWAYS on
7129 gtk_window_constrain_position (window,
7135 /* Update whether we need to request a move */
7136 if (info->last.configure_request.x != new_request.x ||
7137 info->last.configure_request.y != new_request.y)
7138 configure_request_pos_changed = TRUE;
7140 configure_request_pos_changed = FALSE;
7144 if (priv->type == GTK_WINDOW_TOPLEVEL)
7146 int notify_x, notify_y;
7148 /* this is the position from the last configure notify */
7149 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
7151 g_message ("--- %s ---\n"
7152 "last : %d,%d\t%d x %d\n"
7153 "this : %d,%d\t%d x %d\n"
7154 "alloc : %d,%d\t%d x %d\n"
7156 "resize: \t%d x %d\n"
7157 "size_changed: %d pos_changed: %d hints_changed: %d\n"
7158 "configure_notify_received: %d\n"
7159 "configure_request_count: %d\n"
7160 "position_constraints_changed: %d\n",
7161 priv->title ? priv->title : "(no title)",
7162 info->last.configure_request.x,
7163 info->last.configure_request.y,
7164 info->last.configure_request.width,
7165 info->last.configure_request.height,
7171 widget->allocation.width,
7172 widget->allocation.height,
7173 widget->requisition.width,
7174 widget->requisition.height,
7176 info->resize_height,
7177 configure_request_pos_changed,
7178 configure_request_size_changed,
7180 priv->configure_notify_received,
7181 priv->configure_request_count,
7182 info->position_constraints_changed);
7186 saved_last_info = info->last;
7187 info->last.geometry = new_geometry;
7188 info->last.flags = new_flags;
7189 info->last.configure_request = new_request;
7191 /* need to set PPosition so the WM will look at our position,
7192 * but we don't want to count PPosition coming and going as a hints
7193 * change for future iterations. So we saved info->last prior to
7197 /* Also, if the initial position was explicitly set, then we always
7198 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
7202 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
7203 * this is an initial map
7206 if ((configure_request_pos_changed ||
7207 info->initial_pos_set ||
7208 (priv->need_default_position &&
7209 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
7210 (new_flags & GDK_HINT_POS) == 0)
7212 new_flags |= GDK_HINT_POS;
7213 hints_changed = TRUE;
7216 /* Set hints if necessary
7219 gdk_window_set_geometry_hints (gdk_window,
7223 gtk_widget_get_allocation (widget, &allocation);
7225 /* handle resizing/moving and widget tree allocation
7227 if (priv->configure_notify_received)
7229 /* If we have received a configure event since
7230 * the last time in this function, we need to
7231 * accept our new size and size_allocate child widgets.
7232 * (see gtk_window_configure_event() for more details).
7234 * 1 or more configure notifies may have been received.
7235 * Also, configure_notify_received will only be TRUE
7236 * if all expected configure notifies have been received
7237 * (one per configure request), as an optimization.
7240 priv->configure_notify_received = FALSE;
7242 /* gtk_window_configure_event() filled in widget->allocation */
7243 gtk_widget_size_allocate (widget, &allocation);
7245 set_grip_position (window);
7246 update_grip_visibility (window);
7248 gdk_window_process_updates (gdk_window, TRUE);
7250 gdk_window_configure_finished (gdk_window);
7252 /* If the configure request changed, it means that
7254 * 1) coincidentally changed hints or widget properties
7255 * impacting the configure request before getting
7256 * a configure notify, or
7257 * 2) some broken widget is changing its size request
7258 * during size allocation, resulting in
7259 * a false appearance of changed configure request.
7261 * For 1), we could just go ahead and ask for the
7262 * new size right now, but doing that for 2)
7263 * might well be fighting the user (and can even
7264 * trigger a loop). Since we really don't want to
7265 * do that, we requeue a resize in hopes that
7266 * by the time it gets handled, the child has seen
7267 * the light and is willing to go along with the
7268 * new size. (this happens for the zvt widget, since
7269 * the size_allocate() above will have stored the
7270 * requisition corresponding to the new size in the
7273 * This doesn't buy us anything for 1), but it shouldn't
7274 * hurt us too badly, since it is what would have
7275 * happened if we had gotten the configure event before
7276 * the new size had been set.
7279 if (configure_request_size_changed ||
7280 configure_request_pos_changed)
7282 /* Don't change the recorded last info after all, because we
7283 * haven't actually updated to the new info yet - we decided
7284 * to postpone our configure request until later.
7286 info->last = saved_last_info;
7288 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7291 return; /* Bail out, we didn't really process the move/resize */
7293 else if ((configure_request_size_changed || hints_changed) &&
7294 (allocation.width != new_request.width || allocation.height != new_request.height))
7297 /* We are in one of the following situations:
7298 * A. configure_request_size_changed
7299 * our requisition has changed and we need a different window size,
7300 * so we request it from the window manager.
7301 * B. !configure_request_size_changed && hints_changed
7302 * the window manager rejects our size, but we have just changed the
7303 * window manager hints, so there's a chance our request will
7304 * be honoured this time, so we try again.
7306 * However, if the new requisition is the same as the current allocation,
7307 * we don't request it again, since we won't get a ConfigureNotify back from
7308 * the window manager unless it decides to change our requisition. If
7309 * we don't get the ConfigureNotify back, the resize queue will never be run.
7312 /* Now send the configure request */
7313 if (configure_request_pos_changed)
7315 gdk_window_move_resize (gdk_window,
7316 new_request.x, new_request.y,
7317 new_request.width, new_request.height);
7319 else /* only size changed */
7321 gdk_window_resize (gdk_window,
7322 new_request.width, new_request.height);
7325 if (priv->type == GTK_WINDOW_POPUP)
7327 GtkAllocation allocation;
7329 /* Directly size allocate for override redirect (popup) windows. */
7332 allocation.width = new_request.width;
7333 allocation.height = new_request.height;
7335 gtk_widget_size_allocate (widget, &allocation);
7337 gdk_window_process_updates (gdk_window, TRUE);
7339 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7340 gtk_widget_queue_draw (widget);
7344 /* Increment the number of have-not-yet-received-notify requests */
7345 priv->configure_request_count += 1;
7346 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7348 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7349 * configure event in response to our resizing request.
7350 * the configure event will cause a new resize with
7351 * ->configure_notify_received=TRUE.
7352 * until then, we want to
7353 * - discard expose events
7354 * - coalesce resizes for our children
7355 * - defer any window resizes until the configure event arrived
7356 * to achieve this, we queue a resize for the window, but remove its
7357 * resizing handler, so resizing will not be handled from the next
7358 * idle handler but when the configure event arrives.
7360 * FIXME: we should also dequeue the pending redraws here, since
7361 * we handle those ourselves upon ->configure_notify_received==TRUE.
7363 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7365 gtk_widget_queue_resize_no_redraw (widget);
7366 _gtk_container_dequeue_resize_handler (container);
7372 /* Handle any position changes.
7374 if (configure_request_pos_changed)
7376 gdk_window_move (gdk_window,
7377 new_request.x, new_request.y);
7380 /* And run the resize queue.
7382 gtk_container_resize_children (container);
7385 /* We have now processed a move/resize since the last position
7386 * constraint change, setting of the initial position, or resize.
7387 * (Not resetting these flags here can lead to infinite loops for
7388 * GTK_RESIZE_IMMEDIATE containers)
7390 info->position_constraints_changed = FALSE;
7391 info->initial_pos_set = FALSE;
7392 info->resize_width = -1;
7393 info->resize_height = -1;
7396 /* Compare two sets of Geometry hints for equality.
7399 gtk_window_compare_hints (GdkGeometry *geometry_a,
7401 GdkGeometry *geometry_b,
7404 if (flags_a != flags_b)
7407 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7408 (geometry_a->min_width != geometry_b->min_width ||
7409 geometry_a->min_height != geometry_b->min_height))
7412 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7413 (geometry_a->max_width != geometry_b->max_width ||
7414 geometry_a->max_height != geometry_b->max_height))
7417 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7418 (geometry_a->base_width != geometry_b->base_width ||
7419 geometry_a->base_height != geometry_b->base_height))
7422 if ((flags_a & GDK_HINT_ASPECT) &&
7423 (geometry_a->min_aspect != geometry_b->min_aspect ||
7424 geometry_a->max_aspect != geometry_b->max_aspect))
7427 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7428 (geometry_a->width_inc != geometry_b->width_inc ||
7429 geometry_a->height_inc != geometry_b->height_inc))
7432 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7433 geometry_a->win_gravity != geometry_b->win_gravity)
7440 _gtk_window_constrain_size (GtkWindow *window,
7446 GtkWindowPrivate *priv;
7447 GtkWindowGeometryInfo *info;
7449 g_return_if_fail (GTK_IS_WINDOW (window));
7451 priv = window->priv;
7453 info = priv->geometry_info;
7456 GdkWindowHints flags = info->last.flags;
7457 GdkGeometry *geometry = &info->last.geometry;
7459 gtk_window_constrain_size (window,
7470 gtk_window_constrain_size (GtkWindow *window,
7471 GdkGeometry *geometry,
7478 gdk_window_constrain_size (geometry, flags, width, height,
7479 new_width, new_height);
7482 /* Compute the set of geometry hints and flags for a window
7483 * based on the application set geometry, and requisition
7484 * of the window. gtk_widget_get_preferred_size() must have been
7488 gtk_window_compute_hints (GtkWindow *window,
7489 GdkGeometry *new_geometry,
7492 GtkWindowPrivate *priv = window->priv;
7494 gint extra_width = 0;
7495 gint extra_height = 0;
7496 GtkWindowGeometryInfo *geometry_info;
7497 GtkRequisition requisition;
7499 widget = GTK_WIDGET (window);
7501 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7502 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7506 *new_flags = geometry_info->mask;
7507 *new_geometry = geometry_info->geometry;
7514 if (geometry_info && geometry_info->widget)
7516 /* If the geometry widget is set, then the hints really apply to that
7517 * widget. This is pretty much meaningless unless the window layout
7518 * is such that the rest of the window adds fixed size borders to
7519 * the geometry widget. Our job is to figure the size of the borders;
7520 * We do that by asking how big the toplevel would be if the
7521 * geometry widget was *really big*.
7524 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7525 * |GGGGG B| in the border can confuse things
7531 * |AAAAAAAAA | When the geometry widget is large, things are
7532 * |GGGGGGGGGGB| clearer.
7537 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7538 GtkRequisition requisition;
7539 int current_width, current_height;
7541 _gtk_widget_override_size_request (geometry_info->widget,
7542 TEMPORARY_SIZE, TEMPORARY_SIZE,
7543 ¤t_width, ¤t_height);
7544 gtk_widget_get_preferred_size (widget,
7545 &requisition, NULL);
7546 _gtk_widget_restore_size_request (geometry_info->widget,
7547 current_width, current_height);
7549 extra_width = requisition.width - TEMPORARY_SIZE;
7550 extra_height = requisition.height - TEMPORARY_SIZE;
7552 if (extra_width < 0 || extra_height < 0)
7554 g_warning("Toplevel size doesn't seem to directly depend on the "
7555 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7556 "The geometry widget might not be in the window, or it might not "
7557 "be packed into the window appropriately");
7558 extra_width = MAX(extra_width, 0);
7559 extra_height = MAX(extra_height, 0);
7561 #undef TEMPORARY_SIZE
7564 /* We don't want to set GDK_HINT_POS in here, we just set it
7565 * in gtk_window_move_resize() when we want the position
7569 if (*new_flags & GDK_HINT_BASE_SIZE)
7571 new_geometry->base_width += extra_width;
7572 new_geometry->base_height += extra_height;
7576 /* For simplicity, we always set the base hint, even when we
7577 * don't expect it to have any visible effect.
7578 * (Note: geometry_size_to_pixels() depends on this.)
7580 *new_flags |= GDK_HINT_BASE_SIZE;
7582 new_geometry->base_width = extra_width;
7583 new_geometry->base_height = extra_height;
7585 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7586 * base size is the minimum size */
7587 if (*new_flags & GDK_HINT_MIN_SIZE)
7589 if (new_geometry->min_width > 0)
7590 new_geometry->base_width += new_geometry->min_width;
7591 if (new_geometry->min_height > 0)
7592 new_geometry->base_height += new_geometry->min_height;
7596 /* Please use a good size for unresizable widgets, not the minimum one. */
7597 if (!priv->resizable)
7598 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7600 if (*new_flags & GDK_HINT_MIN_SIZE)
7602 if (new_geometry->min_width < 0)
7603 new_geometry->min_width = requisition.width;
7605 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7607 if (new_geometry->min_height < 0)
7608 new_geometry->min_height = requisition.height;
7610 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7614 *new_flags |= GDK_HINT_MIN_SIZE;
7616 new_geometry->min_width = requisition.width;
7617 new_geometry->min_height = requisition.height;
7620 if (*new_flags & GDK_HINT_MAX_SIZE)
7622 if (new_geometry->max_width < 0)
7623 new_geometry->max_width = requisition.width;
7625 new_geometry->max_width += extra_width;
7627 if (new_geometry->max_height < 0)
7628 new_geometry->max_height = requisition.height;
7630 new_geometry->max_height += extra_height;
7632 else if (!priv->resizable)
7634 *new_flags |= GDK_HINT_MAX_SIZE;
7636 new_geometry->max_width = requisition.width;
7637 new_geometry->max_height = requisition.height;
7640 *new_flags |= GDK_HINT_WIN_GRAVITY;
7641 new_geometry->win_gravity = priv->gravity;
7644 /***********************
7645 * Redrawing functions *
7646 ***********************/
7649 gtk_window_draw (GtkWidget *widget,
7652 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7653 GtkStyleContext *context;
7654 gboolean ret = FALSE;
7656 context = gtk_widget_get_style_context (widget);
7658 if (!gtk_widget_get_app_paintable (widget) &&
7659 gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
7661 gtk_style_context_save (context);
7663 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7664 gtk_render_background (context, cr, 0, 0,
7665 gtk_widget_get_allocated_width (widget),
7666 gtk_widget_get_allocated_height (widget));
7668 gtk_style_context_restore (context);
7671 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7672 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7674 if (priv->grip_window &&
7675 gtk_cairo_should_draw_window (cr, priv->grip_window))
7679 gtk_style_context_save (context);
7682 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7683 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7685 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7686 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7687 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7690 gtk_style_context_restore (context);
7697 * gtk_window_present:
7698 * @window: a #GtkWindow
7700 * Presents a window to the user. This may mean raising the window
7701 * in the stacking order, deiconifying it, moving it to the current
7702 * desktop, and/or giving it the keyboard focus, possibly dependent
7703 * on the user's platform, window manager, and preferences.
7705 * If @window is hidden, this function calls gtk_widget_show()
7708 * This function should be used when the user tries to open a window
7709 * that's already open. Say for example the preferences dialog is
7710 * currently open, and the user chooses Preferences from the menu
7711 * a second time; use gtk_window_present() to move the already-open dialog
7712 * where the user can see it.
7714 * If you are calling this function in response to a user interaction,
7715 * it is preferable to use gtk_window_present_with_time().
7719 gtk_window_present (GtkWindow *window)
7721 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7725 * gtk_window_present_with_time:
7726 * @window: a #GtkWindow
7727 * @timestamp: the timestamp of the user interaction (typically a
7728 * button or key press event) which triggered this call
7730 * Presents a window to the user in response to a user interaction.
7731 * If you need to present a window without a timestamp, use
7732 * gtk_window_present(). See gtk_window_present() for details.
7737 gtk_window_present_with_time (GtkWindow *window,
7740 GtkWindowPrivate *priv;
7742 GdkWindow *gdk_window;
7744 g_return_if_fail (GTK_IS_WINDOW (window));
7746 priv = window->priv;
7747 widget = GTK_WIDGET (window);
7749 if (gtk_widget_get_visible (widget))
7751 gdk_window = gtk_widget_get_window (widget);
7753 g_assert (gdk_window != NULL);
7755 gdk_window_show (gdk_window);
7757 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7758 if (timestamp == GDK_CURRENT_TIME)
7760 #ifdef GDK_WINDOWING_X11
7761 if (GDK_IS_X11_WINDOW(gdk_window))
7763 GdkDisplay *display;
7765 display = gtk_widget_get_display (GTK_WIDGET (window));
7766 timestamp = gdk_x11_display_get_user_time (display);
7770 timestamp = gtk_get_current_event_time ();
7773 gdk_window_focus (gdk_window, timestamp);
7777 priv->initial_timestamp = timestamp;
7778 gtk_widget_show (widget);
7783 * gtk_window_iconify:
7784 * @window: a #GtkWindow
7786 * Asks to iconify (i.e. minimize) the specified @window. Note that
7787 * you shouldn't assume the window is definitely iconified afterward,
7788 * because other entities (e.g. the user or <link
7789 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7790 * again, or there may not be a window manager in which case
7791 * iconification isn't possible, etc. But normally the window will end
7792 * up iconified. Just don't write code that crashes if not.
7794 * It's permitted to call this function before showing a window,
7795 * in which case the window will be iconified before it ever appears
7798 * You can track iconification via the "window-state-event" signal
7803 gtk_window_iconify (GtkWindow *window)
7805 GtkWindowPrivate *priv;
7807 GdkWindow *toplevel;
7809 g_return_if_fail (GTK_IS_WINDOW (window));
7811 priv = window->priv;
7812 widget = GTK_WIDGET (window);
7814 priv->iconify_initially = TRUE;
7816 toplevel = gtk_widget_get_window (widget);
7818 if (toplevel != NULL)
7819 gdk_window_iconify (toplevel);
7823 * gtk_window_deiconify:
7824 * @window: a #GtkWindow
7826 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7827 * that you shouldn't assume the window is definitely deiconified
7828 * afterward, because other entities (e.g. the user or <link
7829 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7830 * again before your code which assumes deiconification gets to run.
7832 * You can track iconification via the "window-state-event" signal
7836 gtk_window_deiconify (GtkWindow *window)
7838 GtkWindowPrivate *priv;
7840 GdkWindow *toplevel;
7842 g_return_if_fail (GTK_IS_WINDOW (window));
7844 priv = window->priv;
7845 widget = GTK_WIDGET (window);
7847 priv->iconify_initially = FALSE;
7849 toplevel = gtk_widget_get_window (widget);
7851 if (toplevel != NULL)
7852 gdk_window_deiconify (toplevel);
7857 * @window: a #GtkWindow
7859 * Asks to stick @window, which means that it will appear on all user
7860 * desktops. Note that you shouldn't assume the window is definitely
7861 * stuck afterward, because other entities (e.g. the user or <link
7862 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7863 * again, and some window managers do not support sticking
7864 * windows. But normally the window will end up stuck. Just don't
7865 * write code that crashes if not.
7867 * It's permitted to call this function before showing a window.
7869 * You can track stickiness via the "window-state-event" signal
7874 gtk_window_stick (GtkWindow *window)
7876 GtkWindowPrivate *priv;
7878 GdkWindow *toplevel;
7880 g_return_if_fail (GTK_IS_WINDOW (window));
7882 priv = window->priv;
7883 widget = GTK_WIDGET (window);
7885 priv->stick_initially = TRUE;
7887 toplevel = gtk_widget_get_window (widget);
7889 if (toplevel != NULL)
7890 gdk_window_stick (toplevel);
7894 * gtk_window_unstick:
7895 * @window: a #GtkWindow
7897 * Asks to unstick @window, which means that it will appear on only
7898 * one of the user's desktops. Note that you shouldn't assume the
7899 * window is definitely unstuck afterward, because other entities
7900 * (e.g. the user or <link linkend="gtk-X11-arch">window
7901 * manager</link>) could stick it again. But normally the window will
7902 * end up stuck. Just don't write code that crashes if not.
7904 * You can track stickiness via the "window-state-event" signal
7909 gtk_window_unstick (GtkWindow *window)
7911 GtkWindowPrivate *priv;
7913 GdkWindow *toplevel;
7915 g_return_if_fail (GTK_IS_WINDOW (window));
7917 priv = window->priv;
7918 widget = GTK_WIDGET (window);
7920 priv->stick_initially = FALSE;
7922 toplevel = gtk_widget_get_window (widget);
7924 if (toplevel != NULL)
7925 gdk_window_unstick (toplevel);
7929 * gtk_window_maximize:
7930 * @window: a #GtkWindow
7932 * Asks to maximize @window, so that it becomes full-screen. Note that
7933 * you shouldn't assume the window is definitely maximized afterward,
7934 * because other entities (e.g. the user or <link
7935 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7936 * again, and not all window managers support maximization. But
7937 * normally the window will end up maximized. Just don't write code
7938 * that crashes if not.
7940 * It's permitted to call this function before showing a window,
7941 * in which case the window will be maximized when it appears onscreen
7944 * You can track maximization via the "window-state-event" signal
7949 gtk_window_maximize (GtkWindow *window)
7951 GtkWindowPrivate *priv;
7953 GdkWindow *toplevel;
7955 g_return_if_fail (GTK_IS_WINDOW (window));
7957 priv = window->priv;
7958 widget = GTK_WIDGET (window);
7960 priv->maximize_initially = TRUE;
7962 toplevel = gtk_widget_get_window (widget);
7964 if (toplevel != NULL)
7965 gdk_window_maximize (toplevel);
7969 * gtk_window_unmaximize:
7970 * @window: a #GtkWindow
7972 * Asks to unmaximize @window. Note that you shouldn't assume the
7973 * window is definitely unmaximized afterward, because other entities
7974 * (e.g. the user or <link linkend="gtk-X11-arch">window
7975 * manager</link>) could maximize it again, and not all window
7976 * managers honor requests to unmaximize. But normally the window will
7977 * end up unmaximized. Just don't write code that crashes if not.
7979 * You can track maximization via the "window-state-event" signal
7984 gtk_window_unmaximize (GtkWindow *window)
7986 GtkWindowPrivate *priv;
7988 GdkWindow *toplevel;
7990 g_return_if_fail (GTK_IS_WINDOW (window));
7992 priv = window->priv;
7993 widget = GTK_WIDGET (window);
7995 priv->maximize_initially = FALSE;
7997 toplevel = gtk_widget_get_window (widget);
7999 if (toplevel != NULL)
8000 gdk_window_unmaximize (toplevel);
8004 * gtk_window_fullscreen:
8005 * @window: a #GtkWindow
8007 * Asks to place @window in the fullscreen state. Note that you
8008 * shouldn't assume the window is definitely full screen afterward,
8009 * because other entities (e.g. the user or <link
8010 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
8011 * again, and not all window managers honor requests to fullscreen
8012 * windows. But normally the window will end up fullscreen. Just
8013 * don't write code that crashes if not.
8015 * You can track the fullscreen state via the "window-state-event" signal
8021 gtk_window_fullscreen (GtkWindow *window)
8023 GtkWindowPrivate *priv;
8025 GdkWindow *toplevel;
8027 g_return_if_fail (GTK_IS_WINDOW (window));
8029 priv = window->priv;
8030 widget = GTK_WIDGET (window);
8032 priv->fullscreen_initially = TRUE;
8034 toplevel = gtk_widget_get_window (widget);
8036 if (toplevel != NULL)
8037 gdk_window_fullscreen (toplevel);
8041 * gtk_window_unfullscreen:
8042 * @window: a #GtkWindow
8044 * Asks to toggle off the fullscreen state for @window. Note that you
8045 * shouldn't assume the window is definitely not full screen
8046 * afterward, because other entities (e.g. the user or <link
8047 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
8048 * again, and not all window managers honor requests to unfullscreen
8049 * windows. But normally the window will end up restored to its normal
8050 * state. Just don't write code that crashes if not.
8052 * You can track the fullscreen state via the "window-state-event" signal
8058 gtk_window_unfullscreen (GtkWindow *window)
8061 GdkWindow *toplevel;
8062 GtkWindowPrivate *priv;
8064 g_return_if_fail (GTK_IS_WINDOW (window));
8066 priv = window->priv;
8067 widget = GTK_WIDGET (window);
8069 priv->fullscreen_initially = FALSE;
8071 toplevel = gtk_widget_get_window (widget);
8073 if (toplevel != NULL)
8074 gdk_window_unfullscreen (toplevel);
8078 * gtk_window_set_keep_above:
8079 * @window: a #GtkWindow
8080 * @setting: whether to keep @window above other windows
8082 * Asks to keep @window above, so that it stays on top. Note that
8083 * you shouldn't assume the window is definitely above afterward,
8084 * because other entities (e.g. the user or <link
8085 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
8086 * and not all window managers support keeping windows above. But
8087 * normally the window will end kept above. Just don't write code
8088 * that crashes if not.
8090 * It's permitted to call this function before showing a window,
8091 * in which case the window will be kept above when it appears onscreen
8094 * You can track the above state via the "window-state-event" signal
8097 * Note that, according to the <ulink
8098 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8099 * Manager Hints</ulink> specification, the above state is mainly meant
8100 * for user preferences and should not be used by applications e.g. for
8101 * drawing attention to their dialogs.
8106 gtk_window_set_keep_above (GtkWindow *window,
8110 GtkWindowPrivate *priv;
8111 GdkWindow *toplevel;
8113 g_return_if_fail (GTK_IS_WINDOW (window));
8115 priv = window->priv;
8116 widget = GTK_WIDGET (window);
8118 priv->above_initially = setting != FALSE;
8120 priv->below_initially = FALSE;
8122 toplevel = gtk_widget_get_window (widget);
8124 if (toplevel != NULL)
8125 gdk_window_set_keep_above (toplevel, setting);
8129 * gtk_window_set_keep_below:
8130 * @window: a #GtkWindow
8131 * @setting: whether to keep @window below other windows
8133 * Asks to keep @window below, so that it stays in bottom. Note that
8134 * you shouldn't assume the window is definitely below afterward,
8135 * because other entities (e.g. the user or <link
8136 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8137 * and not all window managers support putting windows below. But
8138 * normally the window will be kept below. Just don't write code
8139 * that crashes if not.
8141 * It's permitted to call this function before showing a window,
8142 * in which case the window will be kept below when it appears onscreen
8145 * You can track the below state via the "window-state-event" signal
8148 * Note that, according to the <ulink
8149 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8150 * Manager Hints</ulink> specification, the above state is mainly meant
8151 * for user preferences and should not be used by applications e.g. for
8152 * drawing attention to their dialogs.
8157 gtk_window_set_keep_below (GtkWindow *window,
8161 GtkWindowPrivate *priv;
8162 GdkWindow *toplevel;
8164 g_return_if_fail (GTK_IS_WINDOW (window));
8166 priv = window->priv;
8167 widget = GTK_WIDGET (window);
8169 priv->below_initially = setting != FALSE;
8171 priv->above_initially = FALSE;
8173 toplevel = gtk_widget_get_window (widget);
8175 if (toplevel != NULL)
8176 gdk_window_set_keep_below (toplevel, setting);
8180 * gtk_window_set_resizable:
8181 * @window: a #GtkWindow
8182 * @resizable: %TRUE if the user can resize this window
8184 * Sets whether the user can resize a window. Windows are user resizable
8188 gtk_window_set_resizable (GtkWindow *window,
8191 GtkWindowPrivate *priv;
8193 g_return_if_fail (GTK_IS_WINDOW (window));
8195 priv = window->priv;
8197 resizable = (resizable != FALSE);
8199 if (priv->resizable != resizable)
8201 priv->resizable = resizable;
8203 update_grip_visibility (window);
8205 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8207 g_object_notify (G_OBJECT (window), "resizable");
8212 * gtk_window_get_resizable:
8213 * @window: a #GtkWindow
8215 * Gets the value set by gtk_window_set_resizable().
8217 * Return value: %TRUE if the user can resize the window
8220 gtk_window_get_resizable (GtkWindow *window)
8222 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8224 return window->priv->resizable;
8228 * gtk_window_set_gravity:
8229 * @window: a #GtkWindow
8230 * @gravity: window gravity
8232 * Window gravity defines the meaning of coordinates passed to
8233 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8236 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8237 * typically "do what you mean."
8241 gtk_window_set_gravity (GtkWindow *window,
8244 GtkWindowPrivate *priv;
8246 g_return_if_fail (GTK_IS_WINDOW (window));
8248 priv = window->priv;
8250 if (gravity != priv->gravity)
8252 priv->gravity = gravity;
8254 /* gtk_window_move_resize() will adapt gravity
8256 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8258 g_object_notify (G_OBJECT (window), "gravity");
8263 * gtk_window_get_gravity:
8264 * @window: a #GtkWindow
8266 * Gets the value set by gtk_window_set_gravity().
8268 * Return value: (transfer none): window gravity
8271 gtk_window_get_gravity (GtkWindow *window)
8273 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8275 return window->priv->gravity;
8279 * gtk_window_begin_resize_drag:
8280 * @window: a #GtkWindow
8281 * @button: mouse button that initiated the drag
8282 * @edge: position of the resize control
8283 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8284 * @root_y: Y position where the user clicked to initiate the drag
8285 * @timestamp: timestamp from the click event that initiated the drag
8287 * Starts resizing a window. This function is used if an application
8288 * has window resizing controls. When GDK can support it, the resize
8289 * will be done using the standard mechanism for the <link
8290 * linkend="gtk-X11-arch">window manager</link> or windowing
8291 * system. Otherwise, GDK will try to emulate window resizing,
8292 * potentially not all that well, depending on the windowing system.
8296 gtk_window_begin_resize_drag (GtkWindow *window,
8304 GdkWindow *toplevel;
8306 g_return_if_fail (GTK_IS_WINDOW (window));
8307 widget = GTK_WIDGET (window);
8308 g_return_if_fail (gtk_widget_get_visible (widget));
8310 toplevel = gtk_widget_get_window (widget);
8312 gdk_window_begin_resize_drag (toplevel,
8319 * gtk_window_begin_move_drag:
8320 * @window: a #GtkWindow
8321 * @button: mouse button that initiated the drag
8322 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8323 * @root_y: Y position where the user clicked to initiate the drag
8324 * @timestamp: timestamp from the click event that initiated the drag
8326 * Starts moving a window. This function is used if an application has
8327 * window movement grips. When GDK can support it, the window movement
8328 * will be done using the standard mechanism for the <link
8329 * linkend="gtk-X11-arch">window manager</link> or windowing
8330 * system. Otherwise, GDK will try to emulate window movement,
8331 * potentially not all that well, depending on the windowing system.
8335 gtk_window_begin_move_drag (GtkWindow *window,
8342 GdkWindow *toplevel;
8344 g_return_if_fail (GTK_IS_WINDOW (window));
8345 widget = GTK_WIDGET (window);
8346 g_return_if_fail (gtk_widget_get_visible (widget));
8348 toplevel = gtk_widget_get_window (widget);
8350 gdk_window_begin_move_drag (toplevel,
8357 * gtk_window_set_screen:
8358 * @window: a #GtkWindow.
8359 * @screen: a #GdkScreen.
8361 * Sets the #GdkScreen where the @window is displayed; if
8362 * the window is already mapped, it will be unmapped, and
8363 * then remapped on the new screen.
8368 gtk_window_set_screen (GtkWindow *window,
8371 GtkWindowPrivate *priv;
8373 GdkScreen *previous_screen;
8374 gboolean was_mapped;
8376 g_return_if_fail (GTK_IS_WINDOW (window));
8377 g_return_if_fail (GDK_IS_SCREEN (screen));
8379 priv = window->priv;
8381 if (screen == priv->screen)
8384 widget = GTK_WIDGET (window);
8386 previous_screen = priv->screen;
8387 was_mapped = gtk_widget_get_mapped (widget);
8390 gtk_widget_unmap (widget);
8391 if (gtk_widget_get_realized (widget))
8392 gtk_widget_unrealize (widget);
8394 gtk_window_free_key_hash (window);
8395 priv->screen = screen;
8396 gtk_widget_reset_rc_styles (widget);
8397 if (screen != previous_screen)
8399 if (previous_screen)
8401 g_signal_handlers_disconnect_by_func (previous_screen,
8402 gtk_window_on_composited_changed, window);
8403 #ifdef GDK_WINDOWING_X11
8404 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8405 gtk_window_on_theme_variant_changed, window);
8408 g_signal_connect (screen, "composited-changed",
8409 G_CALLBACK (gtk_window_on_composited_changed), window);
8410 #ifdef GDK_WINDOWING_X11
8411 g_signal_connect (gtk_settings_get_for_screen (screen),
8412 "notify::gtk-application-prefer-dark-theme",
8413 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8416 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8417 _gtk_widget_propagate_composited_changed (widget);
8419 g_object_notify (G_OBJECT (window), "screen");
8422 gtk_widget_map (widget);
8426 gtk_window_set_theme_variant (GtkWindow *window)
8428 #ifdef GDK_WINDOWING_X11
8429 GdkWindow *gdk_window;
8430 gboolean dark_theme_requested;
8432 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8433 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8436 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8438 if (GDK_IS_X11_WINDOW (gdk_window))
8439 gdk_x11_window_set_theme_variant (gdk_window,
8440 dark_theme_requested ? "dark" : NULL);
8445 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8449 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8450 gtk_window_set_theme_variant (window);
8454 gtk_window_on_composited_changed (GdkScreen *screen,
8457 gtk_widget_queue_draw (GTK_WIDGET (window));
8459 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8463 gtk_window_check_screen (GtkWindow *window)
8465 GtkWindowPrivate *priv = window->priv;
8468 return priv->screen;
8471 g_warning ("Screen for GtkWindow not set; you must always set\n"
8472 "a screen for a GtkWindow before using the window");
8478 * gtk_window_get_screen:
8479 * @window: a #GtkWindow.
8481 * Returns the #GdkScreen associated with @window.
8483 * Return value: (transfer none): a #GdkScreen.
8488 gtk_window_get_screen (GtkWindow *window)
8490 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8492 return window->priv->screen;
8496 * gtk_window_is_active:
8497 * @window: a #GtkWindow
8499 * Returns whether the window is part of the current active toplevel.
8500 * (That is, the toplevel window receiving keystrokes.)
8501 * The return value is %TRUE if the window is active toplevel
8502 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8503 * You might use this function if you wanted to draw a widget
8504 * differently in an active window from a widget in an inactive window.
8505 * See gtk_window_has_toplevel_focus()
8507 * Return value: %TRUE if the window part of the current active window.
8512 gtk_window_is_active (GtkWindow *window)
8514 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8516 return window->priv->is_active;
8520 * gtk_window_has_toplevel_focus:
8521 * @window: a #GtkWindow
8523 * Returns whether the input focus is within this GtkWindow.
8524 * For real toplevel windows, this is identical to gtk_window_is_active(),
8525 * but for embedded windows, like #GtkPlug, the results will differ.
8527 * Return value: %TRUE if the input focus is within this GtkWindow
8532 gtk_window_has_toplevel_focus (GtkWindow *window)
8534 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8536 return window->priv->has_toplevel_focus;
8541 * SECTION:gtkwindowgroup
8542 * @Short_description: Limit the effect of grabs
8543 * @Title: GtkWindowGroup
8545 * #GtkWindowGroup objects are referenced by each window in the group,
8546 * so once you have added all windows to a #GtkWindowGroup, you can drop
8547 * the initial reference to the window group with g_object_unref(). If the
8548 * windows in the window group are subsequently destroyed, then they will
8549 * be removed from the window group and drop their references on the window
8550 * group; when all window have been removed, the window group will be
8554 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8557 gtk_window_group_init (GtkWindowGroup *group)
8559 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8560 GTK_TYPE_WINDOW_GROUP,
8561 GtkWindowGroupPrivate);
8565 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8567 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8571 * gtk_window_group_new:
8573 * Creates a new #GtkWindowGroup object. Grabs added with
8574 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8576 * Return value: a new #GtkWindowGroup.
8579 gtk_window_group_new (void)
8581 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8585 window_group_cleanup_grabs (GtkWindowGroup *group,
8588 GtkWindowGroupPrivate *priv;
8589 GtkDeviceGrabInfo *info;
8591 GSList *to_remove = NULL;
8595 tmp_list = priv->grabs;
8598 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8599 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8600 tmp_list = tmp_list->next;
8605 gtk_grab_remove (to_remove->data);
8606 g_object_unref (to_remove->data);
8607 to_remove = g_slist_delete_link (to_remove, to_remove);
8610 tmp_list = priv->device_grabs;
8614 info = tmp_list->data;
8616 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8617 to_remove = g_slist_prepend (to_remove, info);
8619 tmp_list = tmp_list->next;
8624 info = to_remove->data;
8626 gtk_device_grab_remove (info->widget, info->device);
8627 to_remove = g_slist_delete_link (to_remove, to_remove);
8632 * gtk_window_group_add_window:
8633 * @window_group: a #GtkWindowGroup
8634 * @window: the #GtkWindow to add
8636 * Adds a window to a #GtkWindowGroup.
8639 gtk_window_group_add_window (GtkWindowGroup *window_group,
8642 GtkWindowPrivate *priv;
8644 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8645 g_return_if_fail (GTK_IS_WINDOW (window));
8647 priv = window->priv;
8649 if (priv->group != window_group)
8651 g_object_ref (window);
8652 g_object_ref (window_group);
8655 gtk_window_group_remove_window (priv->group, window);
8657 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8659 priv->group = window_group;
8661 g_object_unref (window);
8666 * gtk_window_group_remove_window:
8667 * @window_group: a #GtkWindowGroup
8668 * @window: the #GtkWindow to remove
8670 * Removes a window from a #GtkWindowGroup.
8673 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8676 GtkWindowPrivate *priv;
8678 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8679 g_return_if_fail (GTK_IS_WINDOW (window));
8680 priv = window->priv;
8681 g_return_if_fail (priv->group == window_group);
8683 g_object_ref (window);
8685 window_group_cleanup_grabs (window_group, window);
8688 g_object_unref (window_group);
8689 g_object_unref (window);
8693 * gtk_window_group_list_windows:
8694 * @window_group: a #GtkWindowGroup
8696 * Returns a list of the #GtkWindows that belong to @window_group.
8698 * Returns: (element-type GtkWindow) (transfer container): A
8699 * newly-allocated list of windows inside the group.
8704 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8706 GList *toplevels, *toplevel, *group_windows;
8708 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8710 group_windows = NULL;
8711 toplevels = gtk_window_list_toplevels ();
8713 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8715 GtkWindow *window = toplevel->data;
8717 if (window_group == window->priv->group)
8718 group_windows = g_list_prepend (group_windows, window);
8721 g_list_free (toplevels);
8723 return g_list_reverse (group_windows);
8727 * gtk_window_get_group:
8728 * @window: (allow-none): a #GtkWindow, or %NULL
8730 * Returns the group for @window or the default group, if
8731 * @window is %NULL or if @window does not have an explicit
8734 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8739 gtk_window_get_group (GtkWindow *window)
8741 if (window && window->priv->group)
8742 return window->priv->group;
8745 static GtkWindowGroup *default_group = NULL;
8748 default_group = gtk_window_group_new ();
8750 return default_group;
8755 * gtk_window_has_group:
8756 * @window: a #GtkWindow
8758 * Returns whether @window has an explicit window group.
8760 * Return value: %TRUE if @window has an explicit window group.
8765 gtk_window_has_group (GtkWindow *window)
8767 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8769 return window->priv->group != NULL;
8773 * gtk_window_group_get_current_grab:
8774 * @window_group: a #GtkWindowGroup
8776 * Gets the current grab widget of the given group,
8777 * see gtk_grab_add().
8779 * Returns: (transfer none): the current grab widget of the group
8784 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8786 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8788 if (window_group->priv->grabs)
8789 return GTK_WIDGET (window_group->priv->grabs->data);
8794 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8797 GtkWindowGroupPrivate *priv;
8799 priv = window_group->priv;
8800 priv->grabs = g_slist_prepend (priv->grabs, widget);
8804 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8807 GtkWindowGroupPrivate *priv;
8809 priv = window_group->priv;
8810 priv->grabs = g_slist_remove (priv->grabs, widget);
8815 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8818 gboolean block_others)
8820 GtkWindowGroupPrivate *priv;
8821 GtkDeviceGrabInfo *info;
8823 priv = window_group->priv;
8825 info = g_slice_new0 (GtkDeviceGrabInfo);
8826 info->widget = widget;
8827 info->device = device;
8828 info->block_others = block_others;
8830 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8834 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8838 GtkWindowGroupPrivate *priv;
8839 GtkDeviceGrabInfo *info;
8840 GSList *list, *node = NULL;
8841 GdkDevice *other_device;
8843 priv = window_group->priv;
8844 other_device = gdk_device_get_associated_device (device);
8845 list = priv->device_grabs;
8851 if (info->widget == widget &&
8852 (info->device == device ||
8853 info->device == other_device))
8866 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8867 g_slice_free (GtkDeviceGrabInfo, info);
8872 * gtk_window_group_get_current_device_grab:
8873 * @window_group: a #GtkWindowGroup
8874 * @device: a #GdkDevice
8876 * Returns the current grab widget for @device, or %NULL if none.
8878 * Returns: (transfer none): The grab widget, or %NULL
8883 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8886 GtkWindowGroupPrivate *priv;
8887 GtkDeviceGrabInfo *info;
8888 GdkDevice *other_device;
8891 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8892 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8894 priv = window_group->priv;
8895 list = priv->device_grabs;
8896 other_device = gdk_device_get_associated_device (device);
8903 if (info->device == device ||
8904 info->device == other_device)
8905 return info->widget;
8912 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8916 GtkWindowGroupPrivate *priv;
8917 GtkDeviceGrabInfo *info;
8918 GdkDevice *other_device;
8921 priv = window_group->priv;
8922 other_device = gdk_device_get_associated_device (device);
8923 list = priv->device_grabs;
8930 /* Look for blocking grabs on other device pairs
8931 * that have the passed widget within the GTK+ grab.
8933 if (info->block_others &&
8934 info->device != device &&
8935 info->device != other_device &&
8936 (info->widget == widget ||
8937 gtk_widget_is_ancestor (widget, info->widget)))
8945 Derived from XParseGeometry() in XFree86
8947 Copyright 1985, 1986, 1987,1998 The Open Group
8949 All Rights Reserved.
8951 The above copyright notice and this permission notice shall be included
8952 in all copies or substantial portions of the Software.
8954 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8955 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8956 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8957 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8958 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8959 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8960 OTHER DEALINGS IN THE SOFTWARE.
8962 Except as contained in this notice, the name of The Open Group shall
8963 not be used in advertising or otherwise to promote the sale, use or
8964 other dealings in this Software without prior written authorization
8965 from The Open Group.
8970 * XParseGeometry parses strings of the form
8971 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8972 * width, height, xoffset, and yoffset are unsigned integers.
8973 * Example: "=80x24+300-49"
8974 * The equal sign is optional.
8975 * It returns a bitmask that indicates which of the four values
8976 * were actually found in the string. For each value found,
8977 * the corresponding argument is updated; for each value
8978 * not found, the corresponding argument is left unchanged.
8981 /* The following code is from Xlib, and is minimally modified, so we
8982 * can track any upstream changes if required. Don't change this
8983 * code. Or if you do, put in a huge comment marking which thing
8988 read_int (gchar *string,
8996 else if (*string == '-')
9002 for (; (*string >= '0') && (*string <= '9'); string++)
9004 result = (result * 10) + (*string - '0');
9016 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
9017 * value (x, y, width, height) was found in the parsed string.
9019 #define NoValue 0x0000
9020 #define XValue 0x0001
9021 #define YValue 0x0002
9022 #define WidthValue 0x0004
9023 #define HeightValue 0x0008
9024 #define AllValues 0x000F
9025 #define XNegative 0x0010
9026 #define YNegative 0x0020
9028 /* Try not to reformat/modify, so we can compare/sync with X sources */
9030 gtk_XParseGeometry (const char *string,
9033 unsigned int *width,
9034 unsigned int *height)
9038 unsigned int tempWidth, tempHeight;
9040 char *nextCharacter;
9042 /* These initializations are just to silence gcc */
9048 if ( (string == NULL) || (*string == '\0')) return(mask);
9050 string++; /* ignore possible '=' at beg of geometry spec */
9052 strind = (char *)string;
9053 if (*strind != '+' && *strind != '-' && *strind != 'x') {
9054 tempWidth = read_int(strind, &nextCharacter);
9055 if (strind == nextCharacter)
9057 strind = nextCharacter;
9061 if (*strind == 'x' || *strind == 'X') {
9063 tempHeight = read_int(strind, &nextCharacter);
9064 if (strind == nextCharacter)
9066 strind = nextCharacter;
9067 mask |= HeightValue;
9070 if ((*strind == '+') || (*strind == '-')) {
9071 if (*strind == '-') {
9073 tempX = -read_int(strind, &nextCharacter);
9074 if (strind == nextCharacter)
9076 strind = nextCharacter;
9082 tempX = read_int(strind, &nextCharacter);
9083 if (strind == nextCharacter)
9085 strind = nextCharacter;
9088 if ((*strind == '+') || (*strind == '-')) {
9089 if (*strind == '-') {
9091 tempY = -read_int(strind, &nextCharacter);
9092 if (strind == nextCharacter)
9094 strind = nextCharacter;
9101 tempY = read_int(strind, &nextCharacter);
9102 if (strind == nextCharacter)
9104 strind = nextCharacter;
9110 /* If strind isn't at the end of the string the it's an invalid
9111 geometry specification. */
9113 if (*strind != '\0') return (0);
9119 if (mask & WidthValue)
9121 if (mask & HeightValue)
9122 *height = tempHeight;
9127 * gtk_window_parse_geometry:
9128 * @window: a #GtkWindow
9129 * @geometry: geometry string
9131 * Parses a standard X Window System geometry string - see the
9132 * manual page for X (type 'man X') for details on this.
9133 * gtk_window_parse_geometry() does work on all GTK+ ports
9134 * including Win32 but is primarily intended for an X environment.
9136 * If either a size or a position can be extracted from the
9137 * geometry string, gtk_window_parse_geometry() returns %TRUE
9138 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9139 * to resize/move the window.
9141 * If gtk_window_parse_geometry() returns %TRUE, it will also
9142 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9143 * indicating to the window manager that the size/position of
9144 * the window was user-specified. This causes most window
9145 * managers to honor the geometry.
9147 * Note that for gtk_window_parse_geometry() to work as expected, it has
9148 * to be called when the window has its "final" size, i.e. after calling
9149 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9152 * #include <gtk/gtk.h>
9155 * fill_with_content (GtkWidget *vbox)
9157 * /* fill with content... */
9161 * main (int argc, char *argv[])
9163 * GtkWidget *window, *vbox;
9164 * GdkGeometry size_hints = {
9165 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9168 * gtk_init (&argc, &argv);
9170 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9171 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9173 * gtk_container_add (GTK_CONTAINER (window), vbox);
9174 * fill_with_content (vbox);
9175 * gtk_widget_show_all (vbox);
9177 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9180 * GDK_HINT_MIN_SIZE |
9181 * GDK_HINT_BASE_SIZE |
9182 * GDK_HINT_RESIZE_INC);
9186 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9187 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9190 * gtk_widget_show_all (window);
9197 * Return value: %TRUE if string was parsed successfully
9200 gtk_window_parse_geometry (GtkWindow *window,
9201 const gchar *geometry)
9203 gint result, x = 0, y = 0;
9207 gboolean size_set, pos_set;
9210 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9211 g_return_val_if_fail (geometry != NULL, FALSE);
9213 child = gtk_bin_get_child (GTK_BIN (window));
9214 if (!child || !gtk_widget_get_visible (child))
9215 g_warning ("gtk_window_parse_geometry() called on a window with no "
9216 "visible children; the window should be set up before "
9217 "gtk_window_parse_geometry() is called.");
9219 screen = gtk_window_check_screen (window);
9221 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9224 if ((result & WidthValue) || (result & HeightValue))
9226 gtk_window_set_default_size_internal (window,
9227 TRUE, result & WidthValue ? w : -1,
9228 TRUE, result & HeightValue ? h : -1,
9233 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9235 grav = GDK_GRAVITY_NORTH_WEST;
9237 if ((result & XNegative) && (result & YNegative))
9238 grav = GDK_GRAVITY_SOUTH_EAST;
9239 else if (result & XNegative)
9240 grav = GDK_GRAVITY_NORTH_EAST;
9241 else if (result & YNegative)
9242 grav = GDK_GRAVITY_SOUTH_WEST;
9244 if ((result & XValue) == 0)
9247 if ((result & YValue) == 0)
9250 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9251 grav == GDK_GRAVITY_SOUTH_EAST)
9252 y = gdk_screen_get_height (screen) - h + y;
9254 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9255 grav == GDK_GRAVITY_NORTH_EAST)
9256 x = gdk_screen_get_width (screen) - w + x;
9258 /* we don't let you put a window offscreen; maybe some people would
9259 * prefer to be able to, but it's kind of a bogus thing to do.
9268 if ((result & XValue) || (result & YValue))
9270 gtk_window_set_gravity (window, grav);
9271 gtk_window_move (window, x, y);
9275 if (size_set || pos_set)
9277 /* Set USSize, USPosition hints */
9278 GtkWindowGeometryInfo *info;
9280 info = gtk_window_get_geometry_info (window, TRUE);
9283 info->mask |= GDK_HINT_USER_POS;
9285 info->mask |= GDK_HINT_USER_SIZE;
9292 gtk_window_mnemonic_hash_foreach (guint keyval,
9298 GtkWindowKeysForeachFunc func;
9302 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9306 _gtk_window_keys_foreach (GtkWindow *window,
9307 GtkWindowKeysForeachFunc func,
9311 GtkMnemonicHash *mnemonic_hash;
9315 GtkWindowKeysForeachFunc func;
9319 info.window = window;
9321 info.func_data = func_data;
9323 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9325 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9326 gtk_window_mnemonic_hash_foreach, &info);
9328 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9331 GtkAccelGroup *group = groups->data;
9334 for (i = 0; i < group->priv->n_accels; i++)
9336 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9339 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9342 groups = groups->next;
9347 gtk_window_keys_changed (GtkWindow *window)
9349 gtk_window_free_key_hash (window);
9350 gtk_window_get_key_hash (window);
9353 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9355 struct _GtkWindowKeyEntry
9359 guint is_mnemonic : 1;
9363 window_key_entry_destroy (gpointer data)
9365 g_slice_free (GtkWindowKeyEntry, data);
9369 add_to_key_hash (GtkWindow *window,
9371 GdkModifierType modifiers,
9372 gboolean is_mnemonic,
9375 GtkKeyHash *key_hash = data;
9377 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9379 entry->keyval = keyval;
9380 entry->modifiers = modifiers;
9381 entry->is_mnemonic = is_mnemonic;
9383 /* GtkAccelGroup stores lowercased accelerators. To deal
9384 * with this, if <Shift> was specified, uppercase.
9386 if (modifiers & GDK_SHIFT_MASK)
9388 if (keyval == GDK_KEY_Tab)
9389 keyval = GDK_KEY_ISO_Left_Tab;
9391 keyval = gdk_keyval_to_upper (keyval);
9394 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9398 gtk_window_get_key_hash (GtkWindow *window)
9400 GdkScreen *screen = gtk_window_check_screen (window);
9401 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9406 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9407 (GDestroyNotify)window_key_entry_destroy);
9408 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9409 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9415 gtk_window_free_key_hash (GtkWindow *window)
9417 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9420 _gtk_key_hash_free (key_hash);
9421 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9426 * gtk_window_activate_key:
9427 * @window: a #GtkWindow
9428 * @event: a #GdkEventKey
9430 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9431 * called by the default ::key_press_event handler for toplevel windows,
9432 * however in some cases it may be useful to call this directly when
9433 * overriding the standard key handling for a toplevel window.
9435 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9440 gtk_window_activate_key (GtkWindow *window,
9443 GtkKeyHash *key_hash;
9444 GtkWindowKeyEntry *found_entry = NULL;
9445 gboolean enable_mnemonics;
9446 gboolean enable_accels;
9448 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9449 g_return_val_if_fail (event != NULL, FALSE);
9451 key_hash = gtk_window_get_key_hash (window);
9456 GSList *entries = _gtk_key_hash_lookup (key_hash,
9457 event->hardware_keycode,
9459 gtk_accelerator_get_default_mod_mask (),
9462 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9463 "gtk-enable-mnemonics", &enable_mnemonics,
9464 "gtk-enable-accels", &enable_accels,
9467 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9469 GtkWindowKeyEntry *entry = tmp_list->data;
9470 if (entry->is_mnemonic)
9472 if (enable_mnemonics)
9474 found_entry = entry;
9480 if (enable_accels && !found_entry)
9482 found_entry = entry;
9487 g_slist_free (entries);
9492 if (found_entry->is_mnemonic)
9494 if (enable_mnemonics)
9495 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9496 found_entry->modifiers);
9501 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9502 found_entry->modifiers);
9510 window_update_has_focus (GtkWindow *window)
9512 GtkWindowPrivate *priv = window->priv;
9513 GtkWidget *widget = GTK_WIDGET (window);
9514 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9516 if (has_focus != priv->has_focus)
9518 priv->has_focus = has_focus;
9522 if (priv->focus_widget &&
9523 priv->focus_widget != widget &&
9524 !gtk_widget_has_focus (priv->focus_widget))
9525 do_focus_change (priv->focus_widget, TRUE);
9529 if (priv->focus_widget &&
9530 priv->focus_widget != widget &&
9531 gtk_widget_has_focus (priv->focus_widget))
9532 do_focus_change (priv->focus_widget, FALSE);
9538 * _gtk_window_set_is_active:
9539 * @window: a #GtkWindow
9540 * @is_active: %TRUE if the window is in the currently active toplevel
9542 * Internal function that sets whether the #GtkWindow is part
9543 * of the currently active toplevel window (taking into account inter-process
9547 _gtk_window_set_is_active (GtkWindow *window,
9550 GtkWindowPrivate *priv;
9552 g_return_if_fail (GTK_IS_WINDOW (window));
9554 priv = window->priv;
9556 is_active = is_active != FALSE;
9558 if (is_active != priv->is_active)
9560 priv->is_active = is_active;
9561 window_update_has_focus (window);
9563 g_object_notify (G_OBJECT (window), "is-active");
9568 * _gtk_window_set_is_toplevel:
9569 * @window: a #GtkWindow
9570 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9571 * child of the root window); %FALSE if it is not (for example, for an
9572 * in-process, parented GtkPlug)
9574 * Internal function used by #GtkPlug when it gets parented/unparented by a
9575 * #GtkSocket. This keeps the @window's #GTK_WINDOW_TOPLEVEL flag in sync
9576 * with the global list of toplevel windows.
9579 _gtk_window_set_is_toplevel (GtkWindow *window,
9580 gboolean is_toplevel)
9583 GtkWidget *toplevel;
9585 widget = GTK_WIDGET (window);
9587 if (gtk_widget_is_toplevel (widget))
9588 g_assert (g_slist_find (toplevel_list, window) != NULL);
9590 g_assert (g_slist_find (toplevel_list, window) == NULL);
9592 if (is_toplevel == gtk_widget_is_toplevel (widget))
9597 /* Pass through regular pathways of an embedded toplevel
9598 * to go through unmapping and hiding the widget before
9599 * becomming a toplevel again.
9601 * We remain hidden after becomming toplevel in order to
9602 * avoid problems during an embedded toplevel's dispose cycle
9603 * (When a toplevel window is shown it tries to grab focus again,
9604 * this causes problems while disposing).
9606 gtk_widget_hide (widget);
9608 /* Save the toplevel this widget was previously anchored into before
9609 * propagating a hierarchy-changed.
9611 * Usually this happens by way of gtk_widget_unparent() and we are
9612 * already unanchored at this point, just adding this clause incase
9613 * things happen differently.
9615 toplevel = gtk_widget_get_toplevel (widget);
9616 if (!gtk_widget_is_toplevel (toplevel))
9619 _gtk_widget_set_is_toplevel (widget, TRUE);
9621 /* When a window becomes toplevel after being embedded and anchored
9622 * into another window we need to unset its anchored flag so that
9623 * the hierarchy changed signal kicks in properly.
9625 _gtk_widget_set_anchored (widget, FALSE);
9626 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9628 toplevel_list = g_slist_prepend (toplevel_list, window);
9632 _gtk_widget_set_is_toplevel (widget, FALSE);
9633 toplevel_list = g_slist_remove (toplevel_list, window);
9635 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9640 * _gtk_window_set_has_toplevel_focus:
9641 * @window: a #GtkWindow
9642 * @has_toplevel_focus: %TRUE if the in
9644 * Internal function that sets whether the keyboard focus for the
9645 * toplevel window (taking into account inter-process embedding.)
9648 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9649 gboolean has_toplevel_focus)
9651 GtkWindowPrivate *priv;
9653 g_return_if_fail (GTK_IS_WINDOW (window));
9655 priv = window->priv;
9657 has_toplevel_focus = has_toplevel_focus != FALSE;
9659 if (has_toplevel_focus != priv->has_toplevel_focus)
9661 priv->has_toplevel_focus = has_toplevel_focus;
9662 window_update_has_focus (window);
9664 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9669 * gtk_window_set_auto_startup_notification:
9670 * @setting: %TRUE to automatically do startup notification
9672 * By default, after showing the first #GtkWindow, GTK+ calls
9673 * gdk_notify_startup_complete(). Call this function to disable
9674 * the automatic startup notification. You might do this if your
9675 * first window is a splash screen, and you want to delay notification
9676 * until after your real main window has been shown, for example.
9678 * In that example, you would disable startup notification
9679 * temporarily, show your splash screen, then re-enable it so that
9680 * showing the main window would automatically result in notification.
9685 gtk_window_set_auto_startup_notification (gboolean setting)
9687 disable_startup_notification = !setting;
9691 * gtk_window_get_window_type:
9692 * @window: a #GtkWindow
9694 * Gets the type of the window. See #GtkWindowType.
9696 * Return value: the type of the window
9701 gtk_window_get_window_type (GtkWindow *window)
9703 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9705 return window->priv->type;
9709 * gtk_window_get_mnemonics_visible:
9710 * @window: a #GtkWindow
9712 * Gets the value of the #GtkWindow:mnemonics-visible property.
9714 * Returns: %TRUE if mnemonics are supposed to be visible
9720 gtk_window_get_mnemonics_visible (GtkWindow *window)
9722 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9724 return window->priv->mnemonics_visible;
9728 * gtk_window_set_mnemonics_visible:
9729 * @window: a #GtkWindow
9730 * @setting: the new value
9732 * Sets the #GtkWindow:mnemonics-visible property.
9737 gtk_window_set_mnemonics_visible (GtkWindow *window,
9740 GtkWindowPrivate *priv;
9742 g_return_if_fail (GTK_IS_WINDOW (window));
9744 priv = window->priv;
9746 setting = setting != FALSE;
9748 if (priv->mnemonics_visible != setting)
9750 priv->mnemonics_visible = setting;
9751 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9754 priv->mnemonics_visible_set = TRUE;
9758 * gtk_window_get_focus_visible:
9759 * @window: a #GtkWindow
9761 * Gets the value of the #GtkWindow:focus-visible property.
9763 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9769 gtk_window_get_focus_visible (GtkWindow *window)
9771 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9773 return window->priv->focus_visible;
9777 * gtk_window_set_focus_visible:
9778 * @window: a #GtkWindow
9779 * @setting: the new value
9781 * Sets the #GtkWindow:focus-visible property.
9786 gtk_window_set_focus_visible (GtkWindow *window,
9789 GtkWindowPrivate *priv;
9791 g_return_if_fail (GTK_IS_WINDOW (window));
9793 priv = window->priv;
9795 setting = setting != FALSE;
9797 if (priv->focus_visible != setting)
9799 priv->focus_visible = setting;
9800 g_object_notify (G_OBJECT (window), "focus-visible");
9805 _gtk_window_get_wmclass (GtkWindow *window,
9806 gchar **wmclass_name,
9807 gchar **wmclass_class)
9809 GtkWindowPrivate *priv = window->priv;
9811 *wmclass_name = priv->wmclass_name;
9812 *wmclass_class = priv->wmclass_class;
9816 * gtk_window_set_has_user_ref_count:
9817 * @window: a #GtkWindow
9818 * @setting: the new value
9820 * Tells GTK+ whether to drop its extra reference to the window
9821 * when gtk_widget_destroy() is called.
9823 * This function is only exported for the benefit of language
9824 * bindings which may need to keep the window alive until their
9825 * wrapper object is garbage collected. There is no justification
9826 * for ever calling this function in an application.
9831 gtk_window_set_has_user_ref_count (GtkWindow *window,
9834 g_return_if_fail (GTK_IS_WINDOW (window));
9836 window->priv->has_user_ref_count = setting;
9840 ensure_state_flag_backdrop (GtkWidget *widget)
9843 gboolean window_focused = TRUE;
9845 window = gtk_widget_get_window (widget);
9847 window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9849 if (!window_focused)
9850 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
9852 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
9854 gtk_widget_queue_draw (widget);