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, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gtkwindow.h"
36 #include "gtkprivate.h"
37 #include "gtkwindowprivate.h"
38 #include "gtkaccelgroupprivate.h"
39 #include "gtkbindings.h"
40 #include "gtkkeyhash.h"
42 #include "gtkmnemonichash.h"
43 #include "gtkmenubar.h"
44 #include "gtkiconfactory.h"
45 #include "gtkicontheme.h"
46 #include "gtkmarshalers.h"
48 #include "gtkbuildable.h"
49 #include "gtkwidgetprivate.h"
50 #include "gtkcontainerprivate.h"
52 #include "gtktypebuiltins.h"
53 #include "a11y/gtkwindowaccessible.h"
55 #include "deprecated/gtkstyle.h"
57 #ifdef GDK_WINDOWING_X11
64 * @short_description: Toplevel which can contain other widgets
66 * A GtkWindow is a toplevel window which can contain other widgets.
67 * Windows normally have decorations that are under the control
68 * of the windowing system and allow the user to manipulate the window
69 * (resize it, move it, close it,...).
71 * GTK+ also allows windows to have a resize grip (a small area in the lower
72 * right or left corner) which can be clicked to reszie the window. To
73 * control whether a window has a resize grip, use
74 * gtk_window_set_has_resize_grip().
76 * <refsect2 id="GtkWindow-BUILDER-UI">
77 * <title>GtkWindow as GtkBuildable</title>
79 * The GtkWindow implementation of the GtkBuildable interface supports a
80 * custom <tag class="starttag">accel-groups</tag> element, which supports
81 * any number of <tag class="starttag">group</tag> elements representing the
82 * #GtkAccelGroup objects you want to add to your window (synonymous with
83 * gtk_window_add_accel_group().
86 * <title>A UI definition fragment with accel groups</title>
87 * <programlisting><![CDATA[
88 * <object class="GtkWindow">
90 * <group name="accelgroup1"/>
96 * <object class="GtkAccelGroup" id="accelgroup1"/>
97 * ]]></programlisting>
102 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
104 struct _GtkWindowPrivate
106 GtkMnemonicHash *mnemonic_hash;
108 GtkWidget *attach_widget;
109 GtkWidget *default_widget;
110 GtkWidget *focus_widget;
111 GtkWindow *transient_parent;
112 GtkWindowGeometryInfo *geometry_info;
113 GtkWindowGroup *group;
115 GtkApplication *application;
117 GdkModifierType mnemonic_modifier;
118 GdkWindowTypeHint gdk_type_hint;
122 GdkWindow *grip_window;
126 gchar *wmclass_class;
130 guint keys_changed_handler;
132 guint32 initial_timestamp;
134 guint16 configure_request_count;
136 /* The following flags are initially TRUE (before a window is mapped).
137 * They cause us to compute a configure request that involves
138 * default-only parameters. Once mapped, we set them to FALSE.
139 * Then we set them to TRUE again on unmap (for position)
140 * and on unrealize (for size).
142 guint need_default_position : 1;
143 guint need_default_size : 1;
145 guint above_initially : 1;
146 guint accept_focus : 1;
147 guint below_initially : 1;
148 guint builder_visible : 1;
149 guint configure_notify_received : 1;
152 guint destroy_with_parent : 1;
153 guint focus_on_map : 1;
154 guint fullscreen_initially : 1;
156 guint has_user_ref_count : 1;
157 guint has_toplevel_focus : 1;
158 guint hide_titlebar_when_maximized : 1;
159 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
161 guint maximize_initially : 1;
162 guint mnemonics_visible : 1;
163 guint mnemonics_visible_set : 1;
164 guint focus_visible : 1;
166 guint opacity_set : 1;
168 guint reset_type_hint : 1;
170 guint skips_pager : 1;
171 guint skips_taskbar : 1;
172 guint stick_initially : 1;
173 guint transient_parent_group : 1;
174 guint type : 4; /* GtkWindowType */
175 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
176 * one of the original eight. If not,
178 * GDK_WINDOW_TYPE_HINT_NORMAL
181 guint has_resize_grip : 1;
182 guint resize_grip_visible : 1; /* don't use, just for "resize-
183 * grip-visible" notification
185 guint gravity : 5; /* GdkGravity */
212 PROP_DESTROY_WITH_PARENT,
213 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
218 PROP_SKIP_TASKBAR_HINT,
219 PROP_SKIP_PAGER_HINT,
229 PROP_HAS_RESIZE_GRIP,
230 PROP_RESIZE_GRIP_VISIBLE,
232 /* Readonly properties */
234 PROP_HAS_TOPLEVEL_FOCUS,
236 /* Writeonly properties */
239 PROP_MNEMONICS_VISIBLE,
250 guint using_default_icon : 1;
251 guint using_parent_icon : 1;
252 guint using_themed_icon : 1;
256 GdkGeometry geometry; /* Last set of geometry hints we set */
257 GdkWindowHints flags;
258 GdkRectangle configure_request;
259 } GtkWindowLastGeometryInfo;
261 struct _GtkWindowGeometryInfo
263 /* Properties that the app has set on the window
265 GdkGeometry geometry; /* Geometry hints */
267 GtkWidget *widget; /* subwidget to which hints apply */
268 /* from last gtk_window_resize () - if > 0, indicates that
269 * we should resize to this size.
274 /* From last gtk_window_move () prior to mapping -
275 * only used if initial_pos_set
280 /* Default size - used only the FIRST time we map a window,
285 /* whether to use initial_x, initial_y */
286 guint initial_pos_set : 1;
287 /* CENTER_ALWAYS or other position constraint changed since
288 * we sent the last configure request.
290 guint position_constraints_changed : 1;
292 /* if true, default_width, height should be multiplied by the
293 * increments and affect the geometry widget only
295 guint default_is_geometry : 1;
297 /* if true, resize_width, height should be multiplied by the
298 * increments and affect the geometry widget only
300 guint resize_is_geometry : 1;
302 GtkWindowLastGeometryInfo last;
306 struct _GtkDeviceGrabInfo
310 guint block_others : 1;
313 struct _GtkWindowGroupPrivate
316 GSList *device_grabs;
319 static void gtk_window_dispose (GObject *object);
320 static void gtk_window_finalize (GObject *object);
321 static void gtk_window_destroy (GtkWidget *widget);
322 static void gtk_window_show (GtkWidget *widget);
323 static void gtk_window_hide (GtkWidget *widget);
324 static void gtk_window_map (GtkWidget *widget);
325 static void gtk_window_unmap (GtkWidget *widget);
326 static void gtk_window_realize (GtkWidget *widget);
327 static void gtk_window_unrealize (GtkWidget *widget);
328 static void gtk_window_size_allocate (GtkWidget *widget,
329 GtkAllocation *allocation);
330 static gboolean gtk_window_map_event (GtkWidget *widget,
332 static gint gtk_window_configure_event (GtkWidget *widget,
333 GdkEventConfigure *event);
334 static gint gtk_window_key_press_event (GtkWidget *widget,
336 static gint gtk_window_key_release_event (GtkWidget *widget,
338 static gint gtk_window_button_press_event (GtkWidget *widget,
339 GdkEventButton *event);
340 static gint gtk_window_enter_notify_event (GtkWidget *widget,
341 GdkEventCrossing *event);
342 static gint gtk_window_leave_notify_event (GtkWidget *widget,
343 GdkEventCrossing *event);
344 static gint gtk_window_focus_in_event (GtkWidget *widget,
345 GdkEventFocus *event);
346 static gint gtk_window_focus_out_event (GtkWidget *widget,
347 GdkEventFocus *event);
348 static void gtk_window_style_updated (GtkWidget *widget);
349 static gboolean gtk_window_state_event (GtkWidget *widget,
350 GdkEventWindowState *event);
351 static void gtk_window_check_resize (GtkContainer *container);
352 static gint gtk_window_focus (GtkWidget *widget,
353 GtkDirectionType direction);
354 static void gtk_window_move_focus (GtkWidget *widget,
355 GtkDirectionType dir);
356 static void gtk_window_real_set_focus (GtkWindow *window,
358 static void gtk_window_direction_changed (GtkWidget *widget,
359 GtkTextDirection prev_dir);
360 static void gtk_window_state_changed (GtkWidget *widget,
361 GtkStateType previous_state);
363 static void gtk_window_real_activate_default (GtkWindow *window);
364 static void gtk_window_real_activate_focus (GtkWindow *window);
365 static void gtk_window_keys_changed (GtkWindow *window);
366 static gint gtk_window_draw (GtkWidget *widget,
368 static void gtk_window_unset_transient_for (GtkWindow *window);
369 static void gtk_window_transient_parent_realized (GtkWidget *parent,
371 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
374 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
376 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
379 static void gtk_window_move_resize (GtkWindow *window);
380 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
382 GdkGeometry *geometry_b,
384 static void gtk_window_constrain_size (GtkWindow *window,
385 GdkGeometry *geometry,
391 static void gtk_window_constrain_position (GtkWindow *window,
396 static void gtk_window_compute_hints (GtkWindow *window,
397 GdkGeometry *new_geometry,
399 static void gtk_window_compute_configure_request (GtkWindow *window,
400 GdkRectangle *request,
401 GdkGeometry *geometry,
404 static void gtk_window_set_default_size_internal (GtkWindow *window,
405 gboolean change_width,
407 gboolean change_height,
409 gboolean is_geometry);
411 static void update_themed_icon (GtkIconTheme *theme,
413 static GList *icon_list_from_theme (GtkWidget *widget,
415 static void gtk_window_realize_icon (GtkWindow *window);
416 static void gtk_window_unrealize_icon (GtkWindow *window);
417 static void resize_grip_create_window (GtkWindow *window);
418 static void resize_grip_destroy_window (GtkWindow *window);
419 static void update_grip_visibility (GtkWindow *window);
421 static void gtk_window_notify_keys_changed (GtkWindow *window);
422 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
423 static void gtk_window_free_key_hash (GtkWindow *window);
424 static void gtk_window_on_composited_changed (GdkScreen *screen,
426 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
429 static void gtk_window_set_theme_variant (GtkWindow *window);
431 static GSList *toplevel_list = NULL;
432 static guint window_signals[LAST_SIGNAL] = { 0 };
433 static GList *default_icon_list = NULL;
434 static gchar *default_icon_name = NULL;
435 static guint default_icon_serial = 0;
436 static gboolean disable_startup_notification = FALSE;
437 static gboolean sent_startup_notification = FALSE;
439 static GQuark quark_gtk_embedded = 0;
440 static GQuark quark_gtk_window_key_hash = 0;
441 static GQuark quark_gtk_window_icon_info = 0;
442 static GQuark quark_gtk_buildable_accels = 0;
444 static GtkBuildableIface *parent_buildable_iface;
446 static void gtk_window_set_property (GObject *object,
450 static void gtk_window_get_property (GObject *object,
456 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
457 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
460 const GValue *value);
461 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
462 GtkBuilder *builder);
463 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
466 const gchar *tagname,
467 GMarkupParser *parser,
469 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
472 const gchar *tagname,
476 static void gtk_window_get_preferred_width (GtkWidget *widget,
479 static void gtk_window_get_preferred_height (GtkWidget *widget,
483 static void ensure_state_flag_backdrop (GtkWidget *widget);
485 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
486 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
487 gtk_window_buildable_interface_init))
490 add_tab_bindings (GtkBindingSet *binding_set,
491 GdkModifierType modifiers,
492 GtkDirectionType direction)
494 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
496 GTK_TYPE_DIRECTION_TYPE, direction);
497 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
499 GTK_TYPE_DIRECTION_TYPE, direction);
503 add_arrow_bindings (GtkBindingSet *binding_set,
505 GtkDirectionType direction)
507 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
509 gtk_binding_entry_add_signal (binding_set, keysym, 0,
511 GTK_TYPE_DIRECTION_TYPE, direction);
512 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
514 GTK_TYPE_DIRECTION_TYPE, direction);
515 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
517 GTK_TYPE_DIRECTION_TYPE, direction);
518 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
520 GTK_TYPE_DIRECTION_TYPE, direction);
524 extract_time_from_startup_id (const gchar* startup_id)
526 gchar *timestr = g_strrstr (startup_id, "_TIME");
527 guint32 retval = GDK_CURRENT_TIME;
534 /* Skip past the "_TIME" part */
539 timestamp = g_ascii_strtoull (timestr, &end, 0);
540 if (errno == 0 && end != timestr)
548 startup_id_is_fake (const gchar* startup_id)
550 return strncmp (startup_id, "_TIME", 5) == 0;
554 gtk_window_class_init (GtkWindowClass *klass)
556 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
557 GtkWidgetClass *widget_class;
558 GtkContainerClass *container_class;
559 GtkBindingSet *binding_set;
561 widget_class = (GtkWidgetClass*) klass;
562 container_class = (GtkContainerClass*) klass;
564 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
565 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
566 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
567 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
569 gobject_class->dispose = gtk_window_dispose;
570 gobject_class->finalize = gtk_window_finalize;
572 gobject_class->set_property = gtk_window_set_property;
573 gobject_class->get_property = gtk_window_get_property;
575 widget_class->destroy = gtk_window_destroy;
576 widget_class->show = gtk_window_show;
577 widget_class->hide = gtk_window_hide;
578 widget_class->map = gtk_window_map;
579 widget_class->map_event = gtk_window_map_event;
580 widget_class->unmap = gtk_window_unmap;
581 widget_class->realize = gtk_window_realize;
582 widget_class->unrealize = gtk_window_unrealize;
583 widget_class->size_allocate = gtk_window_size_allocate;
584 widget_class->configure_event = gtk_window_configure_event;
585 widget_class->key_press_event = gtk_window_key_press_event;
586 widget_class->key_release_event = gtk_window_key_release_event;
587 widget_class->enter_notify_event = gtk_window_enter_notify_event;
588 widget_class->leave_notify_event = gtk_window_leave_notify_event;
589 widget_class->focus_in_event = gtk_window_focus_in_event;
590 widget_class->button_press_event = gtk_window_button_press_event;
591 widget_class->focus_out_event = gtk_window_focus_out_event;
592 widget_class->focus = gtk_window_focus;
593 widget_class->move_focus = gtk_window_move_focus;
594 widget_class->draw = gtk_window_draw;
595 widget_class->get_preferred_width = gtk_window_get_preferred_width;
596 widget_class->get_preferred_height = gtk_window_get_preferred_height;
597 widget_class->window_state_event = gtk_window_state_event;
598 widget_class->direction_changed = gtk_window_direction_changed;
599 widget_class->state_changed = gtk_window_state_changed;
600 widget_class->style_updated = gtk_window_style_updated;
602 container_class->check_resize = gtk_window_check_resize;
604 klass->set_focus = gtk_window_real_set_focus;
606 klass->activate_default = gtk_window_real_activate_default;
607 klass->activate_focus = gtk_window_real_activate_focus;
608 klass->keys_changed = gtk_window_keys_changed;
610 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
613 g_object_class_install_property (gobject_class,
615 g_param_spec_enum ("type",
617 P_("The type of the window"),
618 GTK_TYPE_WINDOW_TYPE,
620 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
622 g_object_class_install_property (gobject_class,
624 g_param_spec_string ("title",
626 P_("The title of the window"),
628 GTK_PARAM_READWRITE));
630 g_object_class_install_property (gobject_class,
632 g_param_spec_string ("role",
634 P_("Unique identifier for the window to be used when restoring a session"),
636 GTK_PARAM_READWRITE));
639 * GtkWindow:startup-id:
641 * The :startup-id is a write-only property for setting window's
642 * startup notification identifier. See gtk_window_set_startup_id()
647 g_object_class_install_property (gobject_class,
649 g_param_spec_string ("startup-id",
651 P_("Unique startup identifier for the window used by startup-notification"),
653 GTK_PARAM_WRITABLE));
655 g_object_class_install_property (gobject_class,
657 g_param_spec_boolean ("resizable",
659 P_("If TRUE, users can resize the window"),
661 GTK_PARAM_READWRITE));
663 g_object_class_install_property (gobject_class,
665 g_param_spec_boolean ("modal",
667 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
669 GTK_PARAM_READWRITE));
671 g_object_class_install_property (gobject_class,
673 g_param_spec_enum ("window-position",
674 P_("Window Position"),
675 P_("The initial position of the window"),
676 GTK_TYPE_WINDOW_POSITION,
678 GTK_PARAM_READWRITE));
680 g_object_class_install_property (gobject_class,
682 g_param_spec_int ("default-width",
684 P_("The default width of the window, used when initially showing the window"),
688 GTK_PARAM_READWRITE));
690 g_object_class_install_property (gobject_class,
692 g_param_spec_int ("default-height",
693 P_("Default Height"),
694 P_("The default height of the window, used when initially showing the window"),
698 GTK_PARAM_READWRITE));
700 g_object_class_install_property (gobject_class,
701 PROP_DESTROY_WITH_PARENT,
702 g_param_spec_boolean ("destroy-with-parent",
703 P_("Destroy with Parent"),
704 P_("If this window should be destroyed when the parent is destroyed"),
706 GTK_PARAM_READWRITE));
709 * GtkWindow:hide-titlebar-when-maximized:
711 * Whether the titlebar should be hidden during maximization.
715 g_object_class_install_property (gobject_class,
716 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
717 g_param_spec_boolean ("hide-titlebar-when-maximized",
718 P_("Hide the titlebar during maximization"),
719 P_("If this window's titlebar should be hidden when the window is maximized"),
721 GTK_PARAM_READWRITE));
723 g_object_class_install_property (gobject_class,
725 g_param_spec_object ("icon",
727 P_("Icon for this window"),
729 GTK_PARAM_READWRITE));
732 * GtkWindow:mnemonics-visible:
734 * Whether mnemonics are currently visible in this window.
736 * This property is maintained by GTK+ based on the
737 * #GtkSettings:gtk-auto-mnemonics setting and user input,
738 * and should not be set by applications.
742 g_object_class_install_property (gobject_class,
743 PROP_MNEMONICS_VISIBLE,
744 g_param_spec_boolean ("mnemonics-visible",
745 P_("Mnemonics Visible"),
746 P_("Whether mnemonics are currently visible in this window"),
748 GTK_PARAM_READWRITE));
751 * GtkWindow:focus-visible:
753 * Whether 'focus rectangles' are currently visible in this window.
755 * This property is maintained by GTK+ based on the
756 * #GtkSettings:gtk-visible-focus setting and user input
757 * and should not be set by applications.
761 g_object_class_install_property (gobject_class,
763 g_param_spec_boolean ("focus-visible",
765 P_("Whether focus rectangles are currently visible in this window"),
767 GTK_PARAM_READWRITE));
770 * GtkWindow:icon-name:
772 * The :icon-name property specifies the name of the themed icon to
773 * use as the window icon. See #GtkIconTheme for more details.
777 g_object_class_install_property (gobject_class,
779 g_param_spec_string ("icon-name",
781 P_("Name of the themed icon for this window"),
783 GTK_PARAM_READWRITE));
785 g_object_class_install_property (gobject_class,
787 g_param_spec_object ("screen",
789 P_("The screen where this window will be displayed"),
791 GTK_PARAM_READWRITE));
793 g_object_class_install_property (gobject_class,
795 g_param_spec_boolean ("is-active",
797 P_("Whether the toplevel is the current active window"),
799 GTK_PARAM_READABLE));
801 g_object_class_install_property (gobject_class,
802 PROP_HAS_TOPLEVEL_FOCUS,
803 g_param_spec_boolean ("has-toplevel-focus",
804 P_("Focus in Toplevel"),
805 P_("Whether the input focus is within this GtkWindow"),
807 GTK_PARAM_READABLE));
809 g_object_class_install_property (gobject_class,
811 g_param_spec_enum ("type-hint",
813 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
814 GDK_TYPE_WINDOW_TYPE_HINT,
815 GDK_WINDOW_TYPE_HINT_NORMAL,
816 GTK_PARAM_READWRITE));
818 g_object_class_install_property (gobject_class,
819 PROP_SKIP_TASKBAR_HINT,
820 g_param_spec_boolean ("skip-taskbar-hint",
822 P_("TRUE if the window should not be in the task bar."),
824 GTK_PARAM_READWRITE));
826 g_object_class_install_property (gobject_class,
827 PROP_SKIP_PAGER_HINT,
828 g_param_spec_boolean ("skip-pager-hint",
830 P_("TRUE if the window should not be in the pager."),
832 GTK_PARAM_READWRITE));
834 g_object_class_install_property (gobject_class,
836 g_param_spec_boolean ("urgency-hint",
838 P_("TRUE if the window should be brought to the user's attention."),
840 GTK_PARAM_READWRITE));
843 * GtkWindow:accept-focus:
845 * Whether the window should receive the input focus.
849 g_object_class_install_property (gobject_class,
851 g_param_spec_boolean ("accept-focus",
853 P_("TRUE if the window should receive the input focus."),
855 GTK_PARAM_READWRITE));
858 * GtkWindow:focus-on-map:
860 * Whether the window should receive the input focus when mapped.
864 g_object_class_install_property (gobject_class,
866 g_param_spec_boolean ("focus-on-map",
868 P_("TRUE if the window should receive the input focus when mapped."),
870 GTK_PARAM_READWRITE));
873 * GtkWindow:decorated:
875 * Whether the window should be decorated by the window manager.
879 g_object_class_install_property (gobject_class,
881 g_param_spec_boolean ("decorated",
883 P_("Whether the window should be decorated by the window manager"),
885 GTK_PARAM_READWRITE));
888 * GtkWindow:deletable:
890 * Whether the window frame should have a close button.
894 g_object_class_install_property (gobject_class,
896 g_param_spec_boolean ("deletable",
898 P_("Whether the window frame should have a close button"),
900 GTK_PARAM_READWRITE));
903 * GtkWindow:has-resize-grip
905 * Whether the window has a corner resize grip.
907 * Note that the resize grip is only shown if the window is
908 * actually resizable and not maximized. Use
909 * #GtkWindow:resize-grip-visible to find out if the resize
910 * grip is currently shown.
914 g_object_class_install_property (gobject_class,
915 PROP_HAS_RESIZE_GRIP,
916 g_param_spec_boolean ("has-resize-grip",
918 P_("Specifies whether the window should have a resize grip"),
920 GTK_PARAM_READWRITE));
923 * GtkWindow:resize-grip-visible:
925 * Whether a corner resize grip is currently shown.
929 g_object_class_install_property (gobject_class,
930 PROP_RESIZE_GRIP_VISIBLE,
931 g_param_spec_boolean ("resize-grip-visible",
932 P_("Resize grip is visible"),
933 P_("Specifies whether the window's resize grip is visible."),
935 GTK_PARAM_READABLE));
941 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
942 * more details about window gravity.
946 g_object_class_install_property (gobject_class,
948 g_param_spec_enum ("gravity",
950 P_("The window gravity of the window"),
952 GDK_GRAVITY_NORTH_WEST,
953 GTK_PARAM_READWRITE));
957 * GtkWindow:transient-for:
959 * The transient parent of the window. See gtk_window_set_transient_for() for
960 * more details about transient windows.
964 g_object_class_install_property (gobject_class,
966 g_param_spec_object ("transient-for",
967 P_("Transient for Window"),
968 P_("The transient parent of the dialog"),
970 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
973 * GtkWindow:attached-to:
975 * The widget to which this window is attached.
976 * See gtk_window_set_attached_to().
978 * Examples of places where specifying this relation is useful are
979 * for instance a #GtkMenu created by a #GtkComboBox, a completion
980 * popup window created by #GtkEntry or a typeahead search entry
981 * created by #GtkTreeView.
985 g_object_class_install_property (gobject_class,
987 g_param_spec_object ("attached-to",
988 P_("Attached to Widget"),
989 P_("The widget where the window is attached"),
991 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
996 * The requested opacity of the window. See gtk_window_set_opacity() for
997 * more details about window opacity.
1001 g_object_class_install_property (gobject_class,
1003 g_param_spec_double ("opacity",
1004 P_("Opacity for Window"),
1005 P_("The opacity of the window, from 0 to 1"),
1009 GTK_PARAM_READWRITE));
1011 /* Style properties.
1013 gtk_widget_class_install_style_property (widget_class,
1014 g_param_spec_int ("resize-grip-width",
1015 P_("Width of resize grip"),
1016 P_("Width of resize grip"),
1017 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1019 gtk_widget_class_install_style_property (widget_class,
1020 g_param_spec_int ("resize-grip-height",
1021 P_("Height of resize grip"),
1022 P_("Height of resize grip"),
1023 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1027 * GtkWindow:application:
1029 * The #GtkApplication associated with the window.
1031 * The application will be kept alive for at least as long as it
1032 * has any windows associated with it (see g_application_hold()
1033 * for a way to keep it alive without windows).
1035 * Normally, the connection between the application and the window
1036 * will remain until the window is destroyed, but you can explicitly
1037 * remove it by setting the ::application property to %NULL.
1041 g_object_class_install_property (gobject_class,
1043 g_param_spec_object ("application",
1044 P_("GtkApplication"),
1045 P_("The GtkApplication for the window"),
1046 GTK_TYPE_APPLICATION,
1047 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1049 window_signals[SET_FOCUS] =
1050 g_signal_new (I_("set-focus"),
1051 G_TYPE_FROM_CLASS (gobject_class),
1053 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1055 _gtk_marshal_VOID__OBJECT,
1060 * GtkWindow::activate-focus:
1061 * @window: the window which received the signal
1063 * The ::activate-focus signal is a
1064 * <link linkend="keybinding-signals">keybinding signal</link>
1065 * which gets emitted when the user activates the currently
1066 * focused widget of @window.
1068 window_signals[ACTIVATE_FOCUS] =
1069 g_signal_new (I_("activate-focus"),
1070 G_TYPE_FROM_CLASS (gobject_class),
1071 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1072 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1074 _gtk_marshal_VOID__VOID,
1079 * GtkWindow::activate-default:
1080 * @window: the window which received the signal
1082 * The ::activate-default signal is a
1083 * <link linkend="keybinding-signals">keybinding signal</link>
1084 * which gets emitted when the user activates the default widget
1087 window_signals[ACTIVATE_DEFAULT] =
1088 g_signal_new (I_("activate-default"),
1089 G_TYPE_FROM_CLASS (gobject_class),
1090 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1091 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1093 _gtk_marshal_VOID__VOID,
1098 * GtkWindow::keys-changed:
1099 * @window: the window which received the signal
1101 * The ::keys-changed signal gets emitted when the set of accelerators
1102 * or mnemonics that are associated with @window changes.
1104 window_signals[KEYS_CHANGED] =
1105 g_signal_new (I_("keys-changed"),
1106 G_TYPE_FROM_CLASS (gobject_class),
1108 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1110 _gtk_marshal_VOID__VOID,
1118 binding_set = gtk_binding_set_by_class (klass);
1120 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1121 "activate-focus", 0);
1122 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1123 "activate-focus", 0);
1125 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1126 "activate-default", 0);
1127 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1128 "activate-default", 0);
1129 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1130 "activate-default", 0);
1132 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1133 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1134 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1135 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1137 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1138 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1139 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1140 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1142 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1146 gtk_window_init (GtkWindow *window)
1148 GtkWindowPrivate *priv;
1150 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1153 priv = window->priv;
1155 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1156 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1158 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1160 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1163 priv->wmclass_name = g_strdup (g_get_prgname ());
1164 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1165 priv->wm_role = NULL;
1166 priv->geometry_info = NULL;
1167 priv->type = GTK_WINDOW_TOPLEVEL;
1168 priv->focus_widget = NULL;
1169 priv->default_widget = NULL;
1170 priv->configure_request_count = 0;
1171 priv->resizable = TRUE;
1172 priv->configure_notify_received = FALSE;
1173 priv->position = GTK_WIN_POS_NONE;
1174 priv->need_default_size = TRUE;
1175 priv->need_default_position = TRUE;
1176 priv->modal = FALSE;
1177 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1178 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1179 priv->decorated = TRUE;
1180 priv->mnemonic_modifier = GDK_MOD1_MASK;
1181 priv->screen = gdk_screen_get_default ();
1183 priv->accept_focus = TRUE;
1184 priv->focus_on_map = TRUE;
1185 priv->deletable = TRUE;
1186 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1187 priv->opacity = 1.0;
1188 priv->startup_id = NULL;
1189 priv->initial_timestamp = GDK_CURRENT_TIME;
1190 priv->has_resize_grip = TRUE;
1191 priv->mnemonics_visible = TRUE;
1192 priv->focus_visible = TRUE;
1194 g_object_ref_sink (window);
1195 priv->has_user_ref_count = TRUE;
1196 toplevel_list = g_slist_prepend (toplevel_list, window);
1199 g_signal_connect (priv->screen, "composited-changed",
1200 G_CALLBACK (gtk_window_on_composited_changed), window);
1202 #ifdef GDK_WINDOWING_X11
1203 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1204 "notify::gtk-application-prefer-dark-theme",
1205 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1210 gtk_window_set_property (GObject *object,
1212 const GValue *value,
1215 GtkWindow *window = GTK_WINDOW (object);
1216 GtkWindowPrivate *priv = window->priv;
1221 priv->type = g_value_get_enum (value);
1224 gtk_window_set_title (window, g_value_get_string (value));
1227 gtk_window_set_role (window, g_value_get_string (value));
1229 case PROP_STARTUP_ID:
1230 gtk_window_set_startup_id (window, g_value_get_string (value));
1232 case PROP_RESIZABLE:
1233 gtk_window_set_resizable (window, g_value_get_boolean (value));
1236 gtk_window_set_modal (window, g_value_get_boolean (value));
1239 gtk_window_set_position (window, g_value_get_enum (value));
1241 case PROP_DEFAULT_WIDTH:
1242 gtk_window_set_default_size_internal (window,
1243 TRUE, g_value_get_int (value),
1246 case PROP_DEFAULT_HEIGHT:
1247 gtk_window_set_default_size_internal (window,
1249 TRUE, g_value_get_int (value), FALSE);
1251 case PROP_DESTROY_WITH_PARENT:
1252 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1254 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1255 gtk_window_set_hide_titlebar_when_maximized (window, g_value_get_boolean (value));
1258 gtk_window_set_icon (window,
1259 g_value_get_object (value));
1261 case PROP_ICON_NAME:
1262 gtk_window_set_icon_name (window, g_value_get_string (value));
1265 gtk_window_set_screen (window, g_value_get_object (value));
1267 case PROP_TYPE_HINT:
1268 gtk_window_set_type_hint (window,
1269 g_value_get_enum (value));
1271 case PROP_SKIP_TASKBAR_HINT:
1272 gtk_window_set_skip_taskbar_hint (window,
1273 g_value_get_boolean (value));
1275 case PROP_SKIP_PAGER_HINT:
1276 gtk_window_set_skip_pager_hint (window,
1277 g_value_get_boolean (value));
1279 case PROP_URGENCY_HINT:
1280 gtk_window_set_urgency_hint (window,
1281 g_value_get_boolean (value));
1283 case PROP_ACCEPT_FOCUS:
1284 gtk_window_set_accept_focus (window,
1285 g_value_get_boolean (value));
1287 case PROP_FOCUS_ON_MAP:
1288 gtk_window_set_focus_on_map (window,
1289 g_value_get_boolean (value));
1291 case PROP_DECORATED:
1292 gtk_window_set_decorated (window, g_value_get_boolean (value));
1294 case PROP_DELETABLE:
1295 gtk_window_set_deletable (window, g_value_get_boolean (value));
1298 gtk_window_set_gravity (window, g_value_get_enum (value));
1300 case PROP_TRANSIENT_FOR:
1301 gtk_window_set_transient_for (window, g_value_get_object (value));
1303 case PROP_ATTACHED_TO:
1304 gtk_window_set_attached_to (window, g_value_get_object (value));
1307 gtk_window_set_opacity (window, g_value_get_double (value));
1309 case PROP_HAS_RESIZE_GRIP:
1310 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1312 case PROP_APPLICATION:
1313 gtk_window_set_application (window, g_value_get_object (value));
1315 case PROP_MNEMONICS_VISIBLE:
1316 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1318 case PROP_FOCUS_VISIBLE:
1319 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1322 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1328 gtk_window_get_property (GObject *object,
1333 GtkWindow *window = GTK_WINDOW (object);
1334 GtkWindowPrivate *priv = window->priv;
1338 GtkWindowGeometryInfo *info;
1340 g_value_set_enum (value, priv->type);
1343 g_value_set_string (value, priv->wm_role);
1346 g_value_set_string (value, priv->title);
1348 case PROP_RESIZABLE:
1349 g_value_set_boolean (value, priv->resizable);
1352 g_value_set_boolean (value, priv->modal);
1355 g_value_set_enum (value, priv->position);
1357 case PROP_DEFAULT_WIDTH:
1358 info = gtk_window_get_geometry_info (window, FALSE);
1360 g_value_set_int (value, -1);
1362 g_value_set_int (value, info->default_width);
1364 case PROP_DEFAULT_HEIGHT:
1365 info = gtk_window_get_geometry_info (window, FALSE);
1367 g_value_set_int (value, -1);
1369 g_value_set_int (value, info->default_height);
1371 case PROP_DESTROY_WITH_PARENT:
1372 g_value_set_boolean (value, priv->destroy_with_parent);
1374 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1375 g_value_set_boolean (value, priv->hide_titlebar_when_maximized);
1378 g_value_set_object (value, gtk_window_get_icon (window));
1380 case PROP_ICON_NAME:
1381 g_value_set_string (value, gtk_window_get_icon_name (window));
1384 g_value_set_object (value, priv->screen);
1386 case PROP_IS_ACTIVE:
1387 g_value_set_boolean (value, priv->is_active);
1389 case PROP_HAS_TOPLEVEL_FOCUS:
1390 g_value_set_boolean (value, priv->has_toplevel_focus);
1392 case PROP_TYPE_HINT:
1393 g_value_set_enum (value, priv->type_hint);
1395 case PROP_SKIP_TASKBAR_HINT:
1396 g_value_set_boolean (value,
1397 gtk_window_get_skip_taskbar_hint (window));
1399 case PROP_SKIP_PAGER_HINT:
1400 g_value_set_boolean (value,
1401 gtk_window_get_skip_pager_hint (window));
1403 case PROP_URGENCY_HINT:
1404 g_value_set_boolean (value,
1405 gtk_window_get_urgency_hint (window));
1407 case PROP_ACCEPT_FOCUS:
1408 g_value_set_boolean (value,
1409 gtk_window_get_accept_focus (window));
1411 case PROP_FOCUS_ON_MAP:
1412 g_value_set_boolean (value,
1413 gtk_window_get_focus_on_map (window));
1415 case PROP_DECORATED:
1416 g_value_set_boolean (value, gtk_window_get_decorated (window));
1418 case PROP_DELETABLE:
1419 g_value_set_boolean (value, gtk_window_get_deletable (window));
1422 g_value_set_enum (value, gtk_window_get_gravity (window));
1424 case PROP_TRANSIENT_FOR:
1425 g_value_set_object (value, gtk_window_get_transient_for (window));
1427 case PROP_ATTACHED_TO:
1428 g_value_set_object (value, gtk_window_get_attached_to (window));
1431 g_value_set_double (value, gtk_window_get_opacity (window));
1433 case PROP_HAS_RESIZE_GRIP:
1434 g_value_set_boolean (value, priv->has_resize_grip);
1436 case PROP_RESIZE_GRIP_VISIBLE:
1437 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1439 case PROP_APPLICATION:
1440 g_value_set_object (value, gtk_window_get_application (window));
1442 case PROP_MNEMONICS_VISIBLE:
1443 g_value_set_boolean (value, priv->mnemonics_visible);
1445 case PROP_FOCUS_VISIBLE:
1446 g_value_set_boolean (value, priv->focus_visible);
1449 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1455 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1457 parent_buildable_iface = g_type_interface_peek_parent (iface);
1458 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1459 iface->parser_finished = gtk_window_buildable_parser_finished;
1460 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1461 iface->custom_finished = gtk_window_buildable_custom_finished;
1465 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1466 GtkBuilder *builder,
1468 const GValue *value)
1470 GtkWindow *window = GTK_WINDOW (buildable);
1471 GtkWindowPrivate *priv = window->priv;
1473 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1474 priv->builder_visible = TRUE;
1476 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1480 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1481 GtkBuilder *builder)
1483 GtkWindow *window = GTK_WINDOW (buildable);
1484 GtkWindowPrivate *priv = window->priv;
1488 if (priv->builder_visible)
1489 gtk_widget_show (GTK_WIDGET (buildable));
1491 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1492 for (l = accels; l; l = l->next)
1494 object = gtk_builder_get_object (builder, l->data);
1497 g_warning ("Unknown accel group %s specified in window %s",
1498 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1501 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1502 GTK_ACCEL_GROUP (object));
1506 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1508 parent_buildable_iface->parser_finished (buildable, builder);
1514 } GSListSubParserData;
1517 window_start_element (GMarkupParseContext *context,
1518 const gchar *element_name,
1519 const gchar **names,
1520 const gchar **values,
1525 GSListSubParserData *data = (GSListSubParserData*)user_data;
1527 if (strcmp (element_name, "group") == 0)
1529 for (i = 0; names[i]; i++)
1531 if (strcmp (names[i], "name") == 0)
1532 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1535 else if (strcmp (element_name, "accel-groups") == 0)
1538 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1543 static const GMarkupParser window_parser =
1545 window_start_element
1549 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1550 GtkBuilder *builder,
1552 const gchar *tagname,
1553 GMarkupParser *parser,
1556 GSListSubParserData *parser_data;
1558 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1559 tagname, parser, data))
1562 if (strcmp (tagname, "accel-groups") == 0)
1564 parser_data = g_slice_new0 (GSListSubParserData);
1565 parser_data->items = NULL;
1566 parser_data->object = G_OBJECT (buildable);
1568 *parser = window_parser;
1569 *data = parser_data;
1577 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1578 GtkBuilder *builder,
1580 const gchar *tagname,
1583 GSListSubParserData *data;
1585 parent_buildable_iface->custom_finished (buildable, builder, child,
1586 tagname, user_data);
1588 if (strcmp (tagname, "accel-groups") != 0)
1591 data = (GSListSubParserData*)user_data;
1593 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1594 data->items, (GDestroyNotify) g_slist_free);
1596 g_slice_free (GSListSubParserData, data);
1601 * @type: type of window
1603 * Creates a new #GtkWindow, which is a toplevel window that can
1604 * contain other widgets. Nearly always, the type of the window should
1605 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1606 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1607 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1608 * dialogs, though in some other toolkits dialogs are called "popups".
1609 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1610 * On X11, popup windows are not controlled by the <link
1611 * linkend="gtk-X11-arch">window manager</link>.
1613 * If you simply want an undecorated window (no window borders), use
1614 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1616 * Return value: a new #GtkWindow.
1619 gtk_window_new (GtkWindowType type)
1621 GtkWindowPrivate *priv;
1624 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1626 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1627 priv = window->priv;
1631 return GTK_WIDGET (window);
1635 * gtk_window_set_title:
1636 * @window: a #GtkWindow
1637 * @title: title of the window
1639 * Sets the title of the #GtkWindow. The title of a window will be
1640 * displayed in its title bar; on the X Window System, the title bar
1641 * is rendered by the <link linkend="gtk-X11-arch">window
1642 * manager</link>, so exactly how the title appears to users may vary
1643 * according to a user's exact configuration. The title should help a
1644 * user distinguish this window from other windows they may have
1645 * open. A good title might include the application name and current
1646 * document filename, for example.
1650 gtk_window_set_title (GtkWindow *window,
1653 GtkWindowPrivate *priv;
1657 g_return_if_fail (GTK_IS_WINDOW (window));
1659 priv = window->priv;
1660 widget = GTK_WIDGET (window);
1662 new_title = g_strdup (title);
1663 g_free (priv->title);
1664 priv->title = new_title;
1666 if (gtk_widget_get_realized (widget))
1668 gdk_window_set_title (gtk_widget_get_window (widget),
1672 g_object_notify (G_OBJECT (window), "title");
1676 * gtk_window_get_title:
1677 * @window: a #GtkWindow
1679 * Retrieves the title of the window. See gtk_window_set_title().
1681 * Return value: the title of the window, or %NULL if none has
1682 * been set explicitely. The returned string is owned by the widget
1683 * and must not be modified or freed.
1686 gtk_window_get_title (GtkWindow *window)
1688 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1690 return window->priv->title;
1694 * gtk_window_set_wmclass:
1695 * @window: a #GtkWindow
1696 * @wmclass_name: window name hint
1697 * @wmclass_class: window class hint
1699 * Don't use this function. It sets the X Window System "class" and
1700 * "name" hints for a window. According to the ICCCM, you should
1701 * always set these to the same value for all windows in an
1702 * application, and GTK+ sets them to that value by default, so calling
1703 * this function is sort of pointless. However, you may want to call
1704 * gtk_window_set_role() on each window in your application, for the
1705 * benefit of the session manager. Setting the role allows the window
1706 * manager to restore window positions when loading a saved session.
1710 gtk_window_set_wmclass (GtkWindow *window,
1711 const gchar *wmclass_name,
1712 const gchar *wmclass_class)
1714 GtkWindowPrivate *priv;
1716 g_return_if_fail (GTK_IS_WINDOW (window));
1718 priv = window->priv;
1720 g_free (priv->wmclass_name);
1721 priv->wmclass_name = g_strdup (wmclass_name);
1723 g_free (priv->wmclass_class);
1724 priv->wmclass_class = g_strdup (wmclass_class);
1726 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1727 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1731 * gtk_window_set_role:
1732 * @window: a #GtkWindow
1733 * @role: unique identifier for the window to be used when restoring a session
1735 * This function is only useful on X11, not with other GTK+ targets.
1737 * In combination with the window title, the window role allows a
1738 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1739 * same" window when an application is restarted. So for example you
1740 * might set the "toolbox" role on your app's toolbox window, so that
1741 * when the user restarts their session, the window manager can put
1742 * the toolbox back in the same place.
1744 * If a window already has a unique title, you don't need to set the
1745 * role, since the WM can use the title to identify the window when
1746 * restoring the session.
1750 gtk_window_set_role (GtkWindow *window,
1753 GtkWindowPrivate *priv;
1756 g_return_if_fail (GTK_IS_WINDOW (window));
1758 priv = window->priv;
1760 new_role = g_strdup (role);
1761 g_free (priv->wm_role);
1762 priv->wm_role = new_role;
1764 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1765 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1768 g_object_notify (G_OBJECT (window), "role");
1772 * gtk_window_set_startup_id:
1773 * @window: a #GtkWindow
1774 * @startup_id: a string with startup-notification identifier
1776 * Startup notification identifiers are used by desktop environment to
1777 * track application startup, to provide user feedback and other
1778 * features. This function changes the corresponding property on the
1779 * underlying GdkWindow. Normally, startup identifier is managed
1780 * automatically and you should only use this function in special cases
1781 * like transferring focus from other processes. You should use this
1782 * function before calling gtk_window_present() or any equivalent
1783 * function generating a window map event.
1785 * This function is only useful on X11, not with other GTK+ targets.
1790 gtk_window_set_startup_id (GtkWindow *window,
1791 const gchar *startup_id)
1793 GtkWindowPrivate *priv;
1796 g_return_if_fail (GTK_IS_WINDOW (window));
1798 priv = window->priv;
1799 widget = GTK_WIDGET (window);
1801 g_free (priv->startup_id);
1802 priv->startup_id = g_strdup (startup_id);
1804 if (gtk_widget_get_realized (widget))
1806 GdkWindow *gdk_window;
1807 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1809 gdk_window = gtk_widget_get_window (widget);
1811 #ifdef GDK_WINDOWING_X11
1812 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1813 gdk_x11_window_set_user_time (gdk_window, timestamp);
1816 /* Here we differentiate real and "fake" startup notification IDs,
1817 * constructed on purpose just to pass interaction timestamp
1819 if (startup_id_is_fake (priv->startup_id))
1820 gtk_window_present_with_time (window, timestamp);
1823 gdk_window_set_startup_id (gdk_window,
1826 /* If window is mapped, terminate the startup-notification too */
1827 if (gtk_widget_get_mapped (widget) &&
1828 !disable_startup_notification)
1829 gdk_notify_startup_complete_with_id (priv->startup_id);
1833 g_object_notify (G_OBJECT (window), "startup-id");
1837 * gtk_window_get_role:
1838 * @window: a #GtkWindow
1840 * Returns the role of the window. See gtk_window_set_role() for
1841 * further explanation.
1843 * Return value: the role of the window if set, or %NULL. The
1844 * returned is owned by the widget and must not be modified
1848 gtk_window_get_role (GtkWindow *window)
1850 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1852 return window->priv->wm_role;
1856 * gtk_window_set_focus:
1857 * @window: a #GtkWindow
1858 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1859 * any focus widget for the toplevel window.
1861 * If @focus is not the current focus widget, and is focusable, sets
1862 * it as the focus widget for the window. If @focus is %NULL, unsets
1863 * the focus widget for this window. To set the focus to a particular
1864 * widget in the toplevel, it is usually more convenient to use
1865 * gtk_widget_grab_focus() instead of this function.
1868 gtk_window_set_focus (GtkWindow *window,
1871 GtkWindowPrivate *priv;
1874 g_return_if_fail (GTK_IS_WINDOW (window));
1876 priv = window->priv;
1880 g_return_if_fail (GTK_IS_WIDGET (focus));
1881 g_return_if_fail (gtk_widget_get_can_focus (focus));
1885 gtk_widget_grab_focus (focus);
1888 /* Clear the existing focus chain, so that when we focus into
1889 * the window again, we start at the beginnning.
1891 GtkWidget *widget = priv->focus_widget;
1894 while ((parent = gtk_widget_get_parent (widget)))
1897 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1901 _gtk_window_internal_set_focus (window, NULL);
1906 _gtk_window_internal_set_focus (GtkWindow *window,
1909 GtkWindowPrivate *priv;
1911 g_return_if_fail (GTK_IS_WINDOW (window));
1913 priv = window->priv;
1915 if ((priv->focus_widget != focus) ||
1916 (focus && !gtk_widget_has_focus (focus)))
1917 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1921 * gtk_window_set_default:
1922 * @window: a #GtkWindow
1923 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1924 * default widget for the toplevel.
1926 * The default widget is the widget that's activated when the user
1927 * presses Enter in a dialog (for example). This function sets or
1928 * unsets the default widget for a #GtkWindow about. When setting
1929 * (rather than unsetting) the default widget it's generally easier to
1930 * call gtk_widget_grab_focus() on the widget. Before making a widget
1931 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1932 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1935 gtk_window_set_default (GtkWindow *window,
1936 GtkWidget *default_widget)
1938 GtkWindowPrivate *priv;
1940 g_return_if_fail (GTK_IS_WINDOW (window));
1942 priv = window->priv;
1945 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1947 if (priv->default_widget != default_widget)
1949 GtkWidget *old_default_widget = NULL;
1952 g_object_ref (default_widget);
1954 if (priv->default_widget)
1956 old_default_widget = priv->default_widget;
1958 if (priv->focus_widget != priv->default_widget ||
1959 !gtk_widget_get_receives_default (priv->default_widget))
1960 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1962 gtk_widget_queue_draw (priv->default_widget);
1965 priv->default_widget = default_widget;
1967 if (priv->default_widget)
1969 if (priv->focus_widget == NULL ||
1970 !gtk_widget_get_receives_default (priv->focus_widget))
1971 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1973 gtk_widget_queue_draw (priv->default_widget);
1976 if (old_default_widget)
1977 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1981 g_object_notify (G_OBJECT (default_widget), "has-default");
1982 g_object_unref (default_widget);
1988 * gtk_window_get_default_widget:
1989 * @window: a #GtkWindow
1991 * Returns the default widget for @window. See gtk_window_set_default()
1994 * Returns: (transfer none): the default widget, or %NULL if there is none.
1999 gtk_window_get_default_widget (GtkWindow *window)
2001 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2003 return window->priv->default_widget;
2007 handle_keys_changed (gpointer data)
2009 GtkWindow *window = GTK_WINDOW (data);
2010 GtkWindowPrivate *priv = window->priv;
2012 if (priv->keys_changed_handler)
2014 g_source_remove (priv->keys_changed_handler);
2015 priv->keys_changed_handler = 0;
2018 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
2024 gtk_window_notify_keys_changed (GtkWindow *window)
2026 GtkWindowPrivate *priv = window->priv;
2028 if (!priv->keys_changed_handler)
2029 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
2033 * gtk_window_add_accel_group:
2034 * @window: window to attach accelerator group to
2035 * @accel_group: a #GtkAccelGroup
2037 * Associate @accel_group with @window, such that calling
2038 * gtk_accel_groups_activate() on @window will activate accelerators
2042 gtk_window_add_accel_group (GtkWindow *window,
2043 GtkAccelGroup *accel_group)
2045 g_return_if_fail (GTK_IS_WINDOW (window));
2046 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2048 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
2049 g_signal_connect_object (accel_group, "accel-changed",
2050 G_CALLBACK (gtk_window_notify_keys_changed),
2051 window, G_CONNECT_SWAPPED);
2052 gtk_window_notify_keys_changed (window);
2056 * gtk_window_remove_accel_group:
2057 * @window: a #GtkWindow
2058 * @accel_group: a #GtkAccelGroup
2060 * Reverses the effects of gtk_window_add_accel_group().
2063 gtk_window_remove_accel_group (GtkWindow *window,
2064 GtkAccelGroup *accel_group)
2066 g_return_if_fail (GTK_IS_WINDOW (window));
2067 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2069 g_signal_handlers_disconnect_by_func (accel_group,
2070 gtk_window_notify_keys_changed,
2072 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2073 gtk_window_notify_keys_changed (window);
2076 static GtkMnemonicHash *
2077 gtk_window_get_mnemonic_hash (GtkWindow *window,
2080 GtkWindowPrivate *private = window->priv;
2082 if (!private->mnemonic_hash && create)
2083 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2085 return private->mnemonic_hash;
2089 * gtk_window_add_mnemonic:
2090 * @window: a #GtkWindow
2091 * @keyval: the mnemonic
2092 * @target: the widget that gets activated by the mnemonic
2094 * Adds a mnemonic to this window.
2097 gtk_window_add_mnemonic (GtkWindow *window,
2101 g_return_if_fail (GTK_IS_WINDOW (window));
2102 g_return_if_fail (GTK_IS_WIDGET (target));
2104 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2106 gtk_window_notify_keys_changed (window);
2110 * gtk_window_remove_mnemonic:
2111 * @window: a #GtkWindow
2112 * @keyval: the mnemonic
2113 * @target: the widget that gets activated by the mnemonic
2115 * Removes a mnemonic from this window.
2118 gtk_window_remove_mnemonic (GtkWindow *window,
2122 g_return_if_fail (GTK_IS_WINDOW (window));
2123 g_return_if_fail (GTK_IS_WIDGET (target));
2125 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2127 gtk_window_notify_keys_changed (window);
2131 * gtk_window_mnemonic_activate:
2132 * @window: a #GtkWindow
2133 * @keyval: the mnemonic
2134 * @modifier: the modifiers
2136 * Activates the targets associated with the mnemonic.
2138 * Returns: %TRUE if the activation is done.
2141 gtk_window_mnemonic_activate (GtkWindow *window,
2143 GdkModifierType modifier)
2145 GtkWindowPrivate *priv;
2147 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2149 priv = window->priv;
2151 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2153 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2155 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2162 * gtk_window_set_mnemonic_modifier:
2163 * @window: a #GtkWindow
2164 * @modifier: the modifier mask used to activate
2165 * mnemonics on this window.
2167 * Sets the mnemonic modifier for this window.
2170 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2171 GdkModifierType modifier)
2173 GtkWindowPrivate *priv;
2175 g_return_if_fail (GTK_IS_WINDOW (window));
2176 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2178 priv = window->priv;
2180 priv->mnemonic_modifier = modifier;
2181 gtk_window_notify_keys_changed (window);
2185 * gtk_window_get_mnemonic_modifier:
2186 * @window: a #GtkWindow
2188 * Returns the mnemonic modifier for this window. See
2189 * gtk_window_set_mnemonic_modifier().
2191 * Return value: the modifier mask used to activate
2192 * mnemonics on this window.
2195 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2197 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2199 return window->priv->mnemonic_modifier;
2203 * gtk_window_set_position:
2204 * @window: a #GtkWindow.
2205 * @position: a position constraint.
2207 * Sets a position constraint for this window. If the old or new
2208 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2209 * the window to be repositioned to satisfy the new constraint.
2212 gtk_window_set_position (GtkWindow *window,
2213 GtkWindowPosition position)
2215 GtkWindowPrivate *priv;
2217 g_return_if_fail (GTK_IS_WINDOW (window));
2219 priv = window->priv;
2221 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2222 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2224 GtkWindowGeometryInfo *info;
2226 info = gtk_window_get_geometry_info (window, TRUE);
2228 /* this flag causes us to re-request the CENTER_ALWAYS
2229 * constraint in gtk_window_move_resize(), see
2230 * comment in that function.
2232 info->position_constraints_changed = TRUE;
2234 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2237 priv->position = position;
2239 g_object_notify (G_OBJECT (window), "window-position");
2243 * gtk_window_activate_focus:
2244 * @window: a #GtkWindow
2246 * Activates the current focused widget within the window.
2248 * Return value: %TRUE if a widget got activated.
2251 gtk_window_activate_focus (GtkWindow *window)
2253 GtkWindowPrivate *priv;
2255 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2257 priv = window->priv;
2259 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2260 return gtk_widget_activate (priv->focus_widget);
2266 * gtk_window_get_focus:
2267 * @window: a #GtkWindow
2269 * Retrieves the current focused widget within the window.
2270 * Note that this is the widget that would have the focus
2271 * if the toplevel window focused; if the toplevel window
2272 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2273 * not be %TRUE for the widget.
2275 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2278 gtk_window_get_focus (GtkWindow *window)
2280 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2282 return window->priv->focus_widget;
2286 * gtk_window_activate_default:
2287 * @window: a #GtkWindow
2289 * Activates the default widget for the window, unless the current
2290 * focused widget has been configured to receive the default action
2291 * (see gtk_widget_set_receives_default()), in which case the
2292 * focused widget is activated.
2294 * Return value: %TRUE if a widget got activated.
2297 gtk_window_activate_default (GtkWindow *window)
2299 GtkWindowPrivate *priv;
2301 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2303 priv = window->priv;
2305 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2306 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2307 return gtk_widget_activate (priv->default_widget);
2308 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2309 return gtk_widget_activate (priv->focus_widget);
2315 * gtk_window_set_modal:
2316 * @window: a #GtkWindow
2317 * @modal: whether the window is modal
2319 * Sets a window modal or non-modal. Modal windows prevent interaction
2320 * with other windows in the same application. To keep modal dialogs
2321 * on top of main application windows, use
2322 * gtk_window_set_transient_for() to make the dialog transient for the
2323 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2324 * will then disallow lowering the dialog below the parent.
2329 gtk_window_set_modal (GtkWindow *window,
2332 GtkWindowPrivate *priv;
2335 g_return_if_fail (GTK_IS_WINDOW (window));
2337 priv = window->priv;
2339 modal = modal != FALSE;
2340 if (priv->modal == modal)
2343 priv->modal = modal;
2344 widget = GTK_WIDGET (window);
2346 /* adjust desired modality state */
2347 if (gtk_widget_get_realized (widget))
2350 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2352 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2355 if (gtk_widget_get_visible (widget))
2358 gtk_grab_add (widget);
2360 gtk_grab_remove (widget);
2363 g_object_notify (G_OBJECT (window), "modal");
2367 * gtk_window_get_modal:
2368 * @window: a #GtkWindow
2370 * Returns whether the window is modal. See gtk_window_set_modal().
2372 * Return value: %TRUE if the window is set to be modal and
2373 * establishes a grab when shown
2376 gtk_window_get_modal (GtkWindow *window)
2378 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2380 return window->priv->modal;
2384 * gtk_window_list_toplevels:
2386 * Returns a list of all existing toplevel windows. The widgets
2387 * in the list are not individually referenced. If you want
2388 * to iterate through the list and perform actions involving
2389 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2390 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2391 * then unref all the widgets afterwards.
2393 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2396 gtk_window_list_toplevels (void)
2401 for (slist = toplevel_list; slist; slist = slist->next)
2402 list = g_list_prepend (list, slist->data);
2408 remove_attach_widget (GtkWindow *window)
2410 GtkWindowPrivate *priv = window->priv;
2412 if (priv->attach_widget)
2414 _gtk_widget_remove_attached_window (priv->attach_widget, window);
2416 g_object_unref (priv->attach_widget);
2417 priv->attach_widget = NULL;
2422 gtk_window_dispose (GObject *object)
2424 GtkWindow *window = GTK_WINDOW (object);
2426 gtk_window_set_focus (window, NULL);
2427 gtk_window_set_default (window, NULL);
2429 remove_attach_widget (GTK_WINDOW (object));
2431 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2435 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2437 gtk_widget_destroy (GTK_WIDGET (child));
2441 connect_parent_destroyed (GtkWindow *window)
2443 GtkWindowPrivate *priv = window->priv;
2445 if (priv->transient_parent)
2447 g_signal_connect (priv->transient_parent,
2449 G_CALLBACK (parent_destroyed_callback),
2455 disconnect_parent_destroyed (GtkWindow *window)
2457 GtkWindowPrivate *priv = window->priv;
2459 if (priv->transient_parent)
2461 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2462 parent_destroyed_callback,
2468 gtk_window_transient_parent_realized (GtkWidget *parent,
2471 if (gtk_widget_get_realized (window))
2472 gdk_window_set_transient_for (gtk_widget_get_window (window),
2473 gtk_widget_get_window (parent));
2477 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2480 if (gtk_widget_get_realized (window))
2481 gdk_property_delete (gtk_widget_get_window (window),
2482 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2486 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2490 gtk_window_set_screen (window, parent->priv->screen);
2494 gtk_window_unset_transient_for (GtkWindow *window)
2496 GtkWindowPrivate *priv = window->priv;
2498 if (priv->transient_parent)
2500 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2501 gtk_window_transient_parent_realized,
2503 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2504 gtk_window_transient_parent_unrealized,
2506 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2507 gtk_window_transient_parent_screen_changed,
2509 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2510 gtk_widget_destroyed,
2511 &priv->transient_parent);
2513 if (priv->destroy_with_parent)
2514 disconnect_parent_destroyed (window);
2516 priv->transient_parent = NULL;
2518 if (priv->transient_parent_group)
2520 priv->transient_parent_group = FALSE;
2521 gtk_window_group_remove_window (priv->group,
2528 * gtk_window_set_transient_for:
2529 * @window: a #GtkWindow
2530 * @parent: (allow-none): parent window, or %NULL
2532 * Dialog windows should be set transient for the main application
2533 * window they were spawned from. This allows <link
2534 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2535 * dialog on top of the main window, or center the dialog over the
2536 * main window. gtk_dialog_new_with_buttons() and other convenience
2537 * functions in GTK+ will sometimes call
2538 * gtk_window_set_transient_for() on your behalf.
2540 * Passing %NULL for @parent unsets the current transient window.
2542 * On Windows, this function puts the child window on top of the parent,
2543 * much as the window manager would have done on X.
2546 gtk_window_set_transient_for (GtkWindow *window,
2549 GtkWindowPrivate *priv;
2551 g_return_if_fail (GTK_IS_WINDOW (window));
2552 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2553 g_return_if_fail (window != parent);
2555 priv = window->priv;
2557 if (priv->transient_parent)
2559 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2560 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2561 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2562 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2563 GTK_WIDGET (window));
2565 gtk_window_unset_transient_for (window);
2568 priv->transient_parent = parent;
2572 g_signal_connect (parent, "destroy",
2573 G_CALLBACK (gtk_widget_destroyed),
2574 &priv->transient_parent);
2575 g_signal_connect (parent, "realize",
2576 G_CALLBACK (gtk_window_transient_parent_realized),
2578 g_signal_connect (parent, "unrealize",
2579 G_CALLBACK (gtk_window_transient_parent_unrealized),
2581 g_signal_connect (parent, "notify::screen",
2582 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2585 gtk_window_set_screen (window, parent->priv->screen);
2587 if (priv->destroy_with_parent)
2588 connect_parent_destroyed (window);
2590 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2591 gtk_widget_get_realized (GTK_WIDGET (parent)))
2592 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2593 GTK_WIDGET (window));
2595 if (parent->priv->group)
2597 gtk_window_group_add_window (parent->priv->group, window);
2598 priv->transient_parent_group = TRUE;
2604 * gtk_window_get_transient_for:
2605 * @window: a #GtkWindow
2607 * Fetches the transient parent for this window. See
2608 * gtk_window_set_transient_for().
2610 * Return value: (transfer none): the transient parent for this window, or %NULL
2611 * if no transient parent has been set.
2614 gtk_window_get_transient_for (GtkWindow *window)
2616 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2618 return window->priv->transient_parent;
2622 * gtk_window_set_attached_to:
2623 * @window: a #GtkWindow
2624 * @attach_widget: (allow-none): a #GtkWidget, or %NULL
2626 * Marks @window as attached to @attach_widget. This creates a logical binding
2627 * between the window and the widget it belongs to, which is used by GTK+ to
2628 * propagate information such as styling or accessibility to @window as if it
2629 * was a children of @attach_widget.
2631 * Examples of places where specifying this relation is useful are for instance
2632 * a #GtkMenu created by a #GtkComboBox, a completion popup window
2633 * created by #GtkEntry or a typeahead search entry created by #GtkTreeView.
2635 * Note that this function should not be confused with
2636 * gtk_window_set_transient_for(), which specifies a window manager relation
2637 * between two toplevels instead.
2639 * Passing %NULL for @attach_widget detaches the window.
2644 gtk_window_set_attached_to (GtkWindow *window,
2645 GtkWidget *attach_widget)
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 gtk_widget_reset_style (GTK_WIDGET (window));
2673 * gtk_window_get_attached_to:
2674 * @window: a #GtkWindow
2676 * Fetches the attach widget for this window. See
2677 * gtk_window_set_attached_to().
2679 * Return value: (transfer none): the widget where the window is attached,
2680 * or %NULL if the window is not attached to any widget.
2685 gtk_window_get_attached_to (GtkWindow *window)
2687 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2689 return window->priv->attach_widget;
2693 * gtk_window_set_opacity:
2694 * @window: a #GtkWindow
2695 * @opacity: desired opacity, between 0 and 1
2697 * Request the windowing system to make @window partially transparent,
2698 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2699 * of the opacity parameter are clamped to the [0,1] range.) On X11
2700 * this has any effect only on X screens with a compositing manager
2701 * running. See gtk_widget_is_composited(). On Windows it should work
2704 * Note that setting a window's opacity after the window has been
2705 * shown causes it to flicker once on Windows.
2710 gtk_window_set_opacity (GtkWindow *window,
2713 GtkWindowPrivate *priv;
2715 g_return_if_fail (GTK_IS_WINDOW (window));
2717 priv = window->priv;
2721 else if (opacity > 1.0)
2724 priv->opacity_set = TRUE;
2725 priv->opacity = opacity;
2727 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2728 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2733 * gtk_window_get_opacity:
2734 * @window: a #GtkWindow
2736 * Fetches the requested opacity for this window. See
2737 * gtk_window_set_opacity().
2739 * Return value: the requested opacity for this window.
2744 gtk_window_get_opacity (GtkWindow *window)
2746 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2748 return window->priv->opacity;
2752 * gtk_window_get_application:
2753 * @window: a #GtkWindow
2755 * Gets the #GtkApplication associated with the window (if any).
2757 * Return value: (transfer none): a #GtkApplication, or %NULL
2762 gtk_window_get_application (GtkWindow *window)
2764 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2766 return window->priv->application;
2770 gtk_window_release_application (GtkWindow *window)
2772 if (window->priv->application)
2774 GtkApplication *application;
2776 /* steal reference into temp variable */
2777 application = window->priv->application;
2778 window->priv->application = NULL;
2780 gtk_application_remove_window (application, window);
2781 g_object_unref (application);
2786 * gtk_window_set_application:
2787 * @window: a #GtkWindow
2788 * @application: (allow-none): a #GtkApplication, or %NULL
2790 * Sets or unsets the #GtkApplication associated with the window.
2792 * The application will be kept alive for at least as long as the window
2798 gtk_window_set_application (GtkWindow *window,
2799 GtkApplication *application)
2801 GtkWindowPrivate *priv;
2803 g_return_if_fail (GTK_IS_WINDOW (window));
2805 priv = window->priv;
2806 if (priv->application != application)
2808 gtk_window_release_application (window);
2810 priv->application = application;
2812 if (priv->application != NULL)
2814 g_object_ref (priv->application);
2816 gtk_application_add_window (priv->application, window);
2819 g_object_notify (G_OBJECT (window), "application");
2824 * gtk_window_set_type_hint:
2825 * @window: a #GtkWindow
2826 * @hint: the window type
2828 * By setting the type hint for the window, you allow the window
2829 * manager to decorate and handle the window in a way which is
2830 * suitable to the function of the window in your application.
2832 * This function should be called before the window becomes visible.
2834 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2835 * will sometimes call gtk_window_set_type_hint() on your behalf.
2839 gtk_window_set_type_hint (GtkWindow *window,
2840 GdkWindowTypeHint hint)
2842 GtkWindowPrivate *priv;
2844 g_return_if_fail (GTK_IS_WINDOW (window));
2845 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2847 priv = window->priv;
2849 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2850 priv->type_hint = hint;
2852 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2854 priv->reset_type_hint = TRUE;
2855 priv->gdk_type_hint = hint;
2859 * gtk_window_get_type_hint:
2860 * @window: a #GtkWindow
2862 * Gets the type hint for this window. See gtk_window_set_type_hint().
2864 * Return value: the type hint for @window.
2867 gtk_window_get_type_hint (GtkWindow *window)
2869 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2871 return window->priv->gdk_type_hint;
2875 * gtk_window_set_skip_taskbar_hint:
2876 * @window: a #GtkWindow
2877 * @setting: %TRUE to keep this window from appearing in the task bar
2879 * Windows may set a hint asking the desktop environment not to display
2880 * the window in the task bar. This function sets this hint.
2885 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2888 GtkWindowPrivate *priv;
2890 g_return_if_fail (GTK_IS_WINDOW (window));
2892 priv = window->priv;
2894 setting = setting != FALSE;
2896 if (priv->skips_taskbar != setting)
2898 priv->skips_taskbar = setting;
2899 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2900 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2901 priv->skips_taskbar);
2902 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2907 * gtk_window_get_skip_taskbar_hint:
2908 * @window: a #GtkWindow
2910 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2912 * Return value: %TRUE if window shouldn't be in taskbar
2917 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2919 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2921 return window->priv->skips_taskbar;
2925 * gtk_window_set_skip_pager_hint:
2926 * @window: a #GtkWindow
2927 * @setting: %TRUE to keep this window from appearing in the pager
2929 * Windows may set a hint asking the desktop environment not to display
2930 * the window in the pager. This function sets this hint.
2931 * (A "pager" is any desktop navigation tool such as a workspace
2932 * switcher that displays a thumbnail representation of the windows
2938 gtk_window_set_skip_pager_hint (GtkWindow *window,
2941 GtkWindowPrivate *priv;
2943 g_return_if_fail (GTK_IS_WINDOW (window));
2945 priv = window->priv;
2947 setting = setting != FALSE;
2949 if (priv->skips_pager != setting)
2951 priv->skips_pager = setting;
2952 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2953 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2955 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2960 * gtk_window_get_skip_pager_hint:
2961 * @window: a #GtkWindow
2963 * Gets the value set by gtk_window_set_skip_pager_hint().
2965 * Return value: %TRUE if window shouldn't be in pager
2970 gtk_window_get_skip_pager_hint (GtkWindow *window)
2972 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2974 return window->priv->skips_pager;
2978 * gtk_window_set_urgency_hint:
2979 * @window: a #GtkWindow
2980 * @setting: %TRUE to mark this window as urgent
2982 * Windows may set a hint asking the desktop environment to draw
2983 * the users attention to the window. This function sets this hint.
2988 gtk_window_set_urgency_hint (GtkWindow *window,
2991 GtkWindowPrivate *priv;
2993 g_return_if_fail (GTK_IS_WINDOW (window));
2995 priv = window->priv;
2997 setting = setting != FALSE;
2999 if (priv->urgent != setting)
3001 priv->urgent = setting;
3002 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3003 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
3005 g_object_notify (G_OBJECT (window), "urgency-hint");
3010 * gtk_window_get_urgency_hint:
3011 * @window: a #GtkWindow
3013 * Gets the value set by gtk_window_set_urgency_hint()
3015 * Return value: %TRUE if window is urgent
3020 gtk_window_get_urgency_hint (GtkWindow *window)
3022 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3024 return window->priv->urgent;
3028 * gtk_window_set_accept_focus:
3029 * @window: a #GtkWindow
3030 * @setting: %TRUE to let this window receive input focus
3032 * Windows may set a hint asking the desktop environment not to receive
3033 * the input focus. This function sets this hint.
3038 gtk_window_set_accept_focus (GtkWindow *window,
3041 GtkWindowPrivate *priv;
3043 g_return_if_fail (GTK_IS_WINDOW (window));
3045 priv = window->priv;
3047 setting = setting != FALSE;
3049 if (priv->accept_focus != setting)
3051 priv->accept_focus = setting;
3052 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3053 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
3054 priv->accept_focus);
3055 g_object_notify (G_OBJECT (window), "accept-focus");
3060 * gtk_window_get_accept_focus:
3061 * @window: a #GtkWindow
3063 * Gets the value set by gtk_window_set_accept_focus().
3065 * Return value: %TRUE if window should receive the input focus
3070 gtk_window_get_accept_focus (GtkWindow *window)
3072 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3074 return window->priv->accept_focus;
3078 * gtk_window_set_focus_on_map:
3079 * @window: a #GtkWindow
3080 * @setting: %TRUE to let this window receive input focus on map
3082 * Windows may set a hint asking the desktop environment not to receive
3083 * the input focus when the window is mapped. This function sets this
3089 gtk_window_set_focus_on_map (GtkWindow *window,
3092 GtkWindowPrivate *priv;
3094 g_return_if_fail (GTK_IS_WINDOW (window));
3096 priv = window->priv;
3098 setting = setting != FALSE;
3100 if (priv->focus_on_map != setting)
3102 priv->focus_on_map = setting;
3103 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3104 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
3105 priv->focus_on_map);
3106 g_object_notify (G_OBJECT (window), "focus-on-map");
3111 * gtk_window_get_focus_on_map:
3112 * @window: a #GtkWindow
3114 * Gets the value set by gtk_window_set_focus_on_map().
3116 * Return value: %TRUE if window should receive the input focus when
3122 gtk_window_get_focus_on_map (GtkWindow *window)
3124 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3126 return window->priv->focus_on_map;
3130 * gtk_window_set_destroy_with_parent:
3131 * @window: a #GtkWindow
3132 * @setting: whether to destroy @window with its transient parent
3134 * If @setting is %TRUE, then destroying the transient parent of @window
3135 * will also destroy @window itself. This is useful for dialogs that
3136 * shouldn't persist beyond the lifetime of the main window they're
3137 * associated with, for example.
3140 gtk_window_set_destroy_with_parent (GtkWindow *window,
3143 GtkWindowPrivate *priv;
3145 g_return_if_fail (GTK_IS_WINDOW (window));
3147 priv = window->priv;
3149 if (priv->destroy_with_parent == (setting != FALSE))
3152 if (priv->destroy_with_parent)
3154 disconnect_parent_destroyed (window);
3158 connect_parent_destroyed (window);
3161 priv->destroy_with_parent = setting;
3163 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3167 * gtk_window_get_destroy_with_parent:
3168 * @window: a #GtkWindow
3170 * Returns whether the window will be destroyed with its transient parent. See
3171 * gtk_window_set_destroy_with_parent ().
3173 * Return value: %TRUE if the window will be destroyed with its transient parent.
3176 gtk_window_get_destroy_with_parent (GtkWindow *window)
3178 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3180 return window->priv->destroy_with_parent;
3184 * gtk_window_set_hide_titlebar_when_maximized:
3185 * @window: a #GtkWindow
3186 * @setting: whether to hide the titlebar when @window is maximized
3188 * If @setting is %TRUE, then @window will request that it's titlebar
3189 * should be hidden when maximized.
3190 * This is useful for windows that don't convey any information other
3191 * than the application name in the titlebar, to put the available
3192 * screen space to better use. If the underlying window system does not
3193 * support the request, the setting will not have any effect.
3198 gtk_window_set_hide_titlebar_when_maximized (GtkWindow *window,
3201 g_return_if_fail (GTK_IS_WINDOW (window));
3203 #ifdef GDK_WINDOWING_X11
3205 GdkWindow *gdk_window;
3207 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3209 if (GDK_IS_X11_WINDOW (gdk_window))
3210 gdk_x11_window_set_hide_titlebar_when_maximized (gdk_window, setting);
3214 window->priv->hide_titlebar_when_maximized = setting;
3215 g_object_notify (G_OBJECT (window), "hide-titlebar-when-maximized");
3219 * gtk_window_get_hide_titlebar_when_maximized:
3220 * @window: a #GtkWindow
3222 * Returns whether the window has requested to have its titlebar hidden
3223 * when maximized. See gtk_window_set_hide_titlebar_when_maximized ().
3225 * Return value: %TRUE if the window has requested to have its titlebar
3226 * hidden when maximized
3231 gtk_window_get_hide_titlebar_when_maximized (GtkWindow *window)
3233 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3235 return window->priv->hide_titlebar_when_maximized;
3238 static GtkWindowGeometryInfo*
3239 gtk_window_get_geometry_info (GtkWindow *window,
3242 GtkWindowPrivate *priv = window->priv;
3243 GtkWindowGeometryInfo *info;
3245 info = priv->geometry_info;
3246 if (!info && create)
3248 info = g_new0 (GtkWindowGeometryInfo, 1);
3250 info->default_width = -1;
3251 info->default_height = -1;
3252 info->resize_width = -1;
3253 info->resize_height = -1;
3254 info->initial_x = 0;
3255 info->initial_y = 0;
3256 info->initial_pos_set = FALSE;
3257 info->default_is_geometry = FALSE;
3258 info->position_constraints_changed = FALSE;
3259 info->last.configure_request.x = 0;
3260 info->last.configure_request.y = 0;
3261 info->last.configure_request.width = -1;
3262 info->last.configure_request.height = -1;
3263 info->widget = NULL;
3265 priv->geometry_info = info;
3272 * gtk_window_set_geometry_hints:
3273 * @window: a #GtkWindow
3274 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3275 * @geometry: (allow-none): struct containing geometry information or %NULL
3276 * @geom_mask: mask indicating which struct fields should be paid attention to
3278 * This function sets up hints about how a window can be resized by
3279 * the user. You can set a minimum and maximum size; allowed resize
3280 * increments (e.g. for xterm, you can only resize by the size of a
3281 * character); aspect ratios; and more. See the #GdkGeometry struct.
3285 gtk_window_set_geometry_hints (GtkWindow *window,
3286 GtkWidget *geometry_widget,
3287 GdkGeometry *geometry,
3288 GdkWindowHints geom_mask)
3290 GtkWindowGeometryInfo *info;
3292 g_return_if_fail (GTK_IS_WINDOW (window));
3293 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3295 info = gtk_window_get_geometry_info (window, TRUE);
3298 g_signal_handlers_disconnect_by_func (info->widget,
3299 gtk_widget_destroyed,
3302 info->widget = geometry_widget;
3304 g_signal_connect (geometry_widget, "destroy",
3305 G_CALLBACK (gtk_widget_destroyed),
3309 info->geometry = *geometry;
3311 /* We store gravity in priv->gravity not in the hints. */
3312 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3314 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3316 gtk_window_set_gravity (window, geometry->win_gravity);
3319 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3323 * gtk_window_set_decorated:
3324 * @window: a #GtkWindow
3325 * @setting: %TRUE to decorate the window
3327 * By default, windows are decorated with a title bar, resize
3328 * controls, etc. Some <link linkend="gtk-X11-arch">window
3329 * managers</link> allow GTK+ to disable these decorations, creating a
3330 * borderless window. If you set the decorated property to %FALSE
3331 * using this function, GTK+ will do its best to convince the window
3332 * manager not to decorate the window. Depending on the system, this
3333 * function may not have any effect when called on a window that is
3334 * already visible, so you should call it before calling gtk_widget_show().
3336 * On Windows, this function always works, since there's no window manager
3341 gtk_window_set_decorated (GtkWindow *window,
3344 GtkWindowPrivate *priv;
3345 GdkWindow *gdk_window;
3347 g_return_if_fail (GTK_IS_WINDOW (window));
3349 priv = window->priv;
3351 setting = setting != FALSE;
3353 if (setting == priv->decorated)
3356 priv->decorated = setting;
3358 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3361 if (priv->decorated)
3362 gdk_window_set_decorations (gdk_window,
3365 gdk_window_set_decorations (gdk_window,
3369 g_object_notify (G_OBJECT (window), "decorated");
3373 * gtk_window_get_decorated:
3374 * @window: a #GtkWindow
3376 * Returns whether the window has been set to have decorations
3377 * such as a title bar via gtk_window_set_decorated().
3379 * Return value: %TRUE if the window has been set to have decorations
3382 gtk_window_get_decorated (GtkWindow *window)
3384 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3386 return window->priv->decorated;
3390 * gtk_window_set_deletable:
3391 * @window: a #GtkWindow
3392 * @setting: %TRUE to decorate the window as deletable
3394 * By default, windows have a close button in the window frame. Some
3395 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3396 * disable this button. If you set the deletable property to %FALSE
3397 * using this function, GTK+ will do its best to convince the window
3398 * manager not to show a close button. Depending on the system, this
3399 * function may not have any effect when called on a window that is
3400 * already visible, so you should call it before calling gtk_window_show().
3402 * On Windows, this function always works, since there's no window manager
3408 gtk_window_set_deletable (GtkWindow *window,
3411 GtkWindowPrivate *priv;
3412 GdkWindow *gdk_window;
3414 g_return_if_fail (GTK_IS_WINDOW (window));
3416 priv = window->priv;
3418 setting = setting != FALSE;
3420 if (setting == priv->deletable)
3423 priv->deletable = setting;
3425 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3428 if (priv->deletable)
3429 gdk_window_set_functions (gdk_window,
3432 gdk_window_set_functions (gdk_window,
3433 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3436 g_object_notify (G_OBJECT (window), "deletable");
3440 * gtk_window_get_deletable:
3441 * @window: a #GtkWindow
3443 * Returns whether the window has been set to have a close button
3444 * via gtk_window_set_deletable().
3446 * Return value: %TRUE if the window has been set to have a close button
3451 gtk_window_get_deletable (GtkWindow *window)
3453 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3455 return window->priv->deletable;
3458 static GtkWindowIconInfo*
3459 get_icon_info (GtkWindow *window)
3461 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3465 free_icon_info (GtkWindowIconInfo *info)
3467 g_free (info->icon_name);
3468 g_slice_free (GtkWindowIconInfo, info);
3472 static GtkWindowIconInfo*
3473 ensure_icon_info (GtkWindow *window)
3475 GtkWindowIconInfo *info;
3477 info = get_icon_info (window);
3481 info = g_slice_new0 (GtkWindowIconInfo);
3482 g_object_set_qdata_full (G_OBJECT (window),
3483 quark_gtk_window_icon_info,
3485 (GDestroyNotify)free_icon_info);
3492 icon_list_from_theme (GtkWidget *widget,
3497 GtkIconTheme *icon_theme;
3502 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3504 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3507 for (i = 0; sizes[i]; i++)
3510 * We need an EWMH extension to handle scalable icons
3511 * by passing their name to the WM. For now just use a
3515 icon = gtk_icon_theme_load_icon (icon_theme, name,
3518 icon = gtk_icon_theme_load_icon (icon_theme, name,
3521 list = g_list_append (list, icon);
3531 gtk_window_realize_icon (GtkWindow *window)
3533 GtkWindowPrivate *priv = window->priv;
3535 GtkWindowIconInfo *info;
3536 GdkWindow *gdk_window;
3539 widget = GTK_WIDGET (window);
3540 gdk_window = gtk_widget_get_window (widget);
3542 g_return_if_fail (gdk_window != NULL);
3544 /* no point setting an icon on override-redirect */
3545 if (priv->type == GTK_WINDOW_POPUP)
3550 info = ensure_icon_info (window);
3555 info->using_default_icon = FALSE;
3556 info->using_parent_icon = FALSE;
3557 info->using_themed_icon = FALSE;
3559 icon_list = info->icon_list;
3561 /* Look up themed icon */
3562 if (icon_list == NULL && info->icon_name)
3564 icon_list = icon_list_from_theme (widget, info->icon_name);
3566 info->using_themed_icon = TRUE;
3569 /* Inherit from transient parent */
3570 if (icon_list == NULL && priv->transient_parent)
3572 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3574 info->using_parent_icon = TRUE;
3577 /* Inherit from default */
3578 if (icon_list == NULL)
3580 icon_list = default_icon_list;
3582 info->using_default_icon = TRUE;
3585 /* Look up themed icon */
3586 if (icon_list == NULL && default_icon_name)
3588 icon_list = icon_list_from_theme (widget, default_icon_name);
3589 info->using_default_icon = TRUE;
3590 info->using_themed_icon = TRUE;
3593 info->realized = TRUE;
3595 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3597 if (info->using_themed_icon)
3599 GtkIconTheme *icon_theme;
3601 g_list_free_full (icon_list, g_object_unref);
3603 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3604 g_signal_connect (icon_theme, "changed",
3605 G_CALLBACK (update_themed_icon), window);
3610 gtk_window_unrealize_icon (GtkWindow *window)
3612 GtkWindowIconInfo *info;
3614 info = get_icon_info (window);
3619 if (info->using_themed_icon)
3621 GtkIconTheme *icon_theme;
3623 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3625 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3628 /* We don't clear the properties on the window, just figure the
3629 * window is going away.
3632 info->realized = FALSE;
3637 * gtk_window_set_icon_list:
3638 * @window: a #GtkWindow
3639 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3641 * Sets up the icon representing a #GtkWindow. The icon is used when
3642 * the window is minimized (also known as iconified). Some window
3643 * managers or desktop environments may also place it in the window
3644 * frame, or display it in other contexts.
3646 * gtk_window_set_icon_list() allows you to pass in the same icon in
3647 * several hand-drawn sizes. The list should contain the natural sizes
3648 * your icon is available in; that is, don't scale the image before
3649 * passing it to GTK+. Scaling is postponed until the last minute,
3650 * when the desired final size is known, to allow best quality.
3652 * By passing several sizes, you may improve the final image quality
3653 * of the icon, by reducing or eliminating automatic image scaling.
3655 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3656 * larger images (64x64, 128x128) if you have them.
3658 * See also gtk_window_set_default_icon_list() to set the icon
3659 * for all windows in your application in one go.
3661 * Note that transient windows (those who have been set transient for another
3662 * window using gtk_window_set_transient_for()) will inherit their
3663 * icon from their transient parent. So there's no need to explicitly
3664 * set the icon on transient windows.
3667 gtk_window_set_icon_list (GtkWindow *window,
3670 GtkWindowIconInfo *info;
3672 g_return_if_fail (GTK_IS_WINDOW (window));
3674 info = ensure_icon_info (window);
3676 if (info->icon_list == list) /* check for NULL mostly */
3679 g_list_foreach (list,
3680 (GFunc) g_object_ref, NULL);
3682 g_list_free_full (info->icon_list, g_object_unref);
3684 info->icon_list = g_list_copy (list);
3686 g_object_notify (G_OBJECT (window), "icon");
3688 gtk_window_unrealize_icon (window);
3690 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3691 gtk_window_realize_icon (window);
3693 /* We could try to update our transient children, but I don't think
3694 * it's really worth it. If we did it, the best way would probably
3695 * be to have children connect to notify::icon-list
3700 * gtk_window_get_icon_list:
3701 * @window: a #GtkWindow
3703 * Retrieves the list of icons set by gtk_window_set_icon_list().
3704 * The list is copied, but the reference count on each
3705 * member won't be incremented.
3707 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3710 gtk_window_get_icon_list (GtkWindow *window)
3712 GtkWindowIconInfo *info;
3714 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3716 info = get_icon_info (window);
3719 return g_list_copy (info->icon_list);
3725 * gtk_window_set_icon:
3726 * @window: a #GtkWindow
3727 * @icon: (allow-none): icon image, or %NULL
3729 * Sets up the icon representing a #GtkWindow. This icon is used when
3730 * the window is minimized (also known as iconified). Some window
3731 * managers or desktop environments may also place it in the window
3732 * frame, or display it in other contexts.
3734 * The icon should be provided in whatever size it was naturally
3735 * drawn; that is, don't scale the image before passing it to
3736 * GTK+. Scaling is postponed until the last minute, when the desired
3737 * final size is known, to allow best quality.
3739 * If you have your icon hand-drawn in multiple sizes, use
3740 * gtk_window_set_icon_list(). Then the best size will be used.
3742 * This function is equivalent to calling gtk_window_set_icon_list()
3743 * with a 1-element list.
3745 * See also gtk_window_set_default_icon_list() to set the icon
3746 * for all windows in your application in one go.
3749 gtk_window_set_icon (GtkWindow *window,
3754 g_return_if_fail (GTK_IS_WINDOW (window));
3755 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3760 list = g_list_append (list, icon);
3762 gtk_window_set_icon_list (window, list);
3768 update_themed_icon (GtkIconTheme *icon_theme,
3771 g_object_notify (G_OBJECT (window), "icon");
3773 gtk_window_unrealize_icon (window);
3775 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3776 gtk_window_realize_icon (window);
3780 * gtk_window_set_icon_name:
3781 * @window: a #GtkWindow
3782 * @name: (allow-none): the name of the themed icon
3784 * Sets the icon for the window from a named themed icon. See
3785 * the docs for #GtkIconTheme for more details.
3787 * Note that this has nothing to do with the WM_ICON_NAME
3788 * property which is mentioned in the ICCCM.
3793 gtk_window_set_icon_name (GtkWindow *window,
3796 GtkWindowIconInfo *info;
3799 g_return_if_fail (GTK_IS_WINDOW (window));
3801 info = ensure_icon_info (window);
3803 if (g_strcmp0 (info->icon_name, name) == 0)
3806 tmp = info->icon_name;
3807 info->icon_name = g_strdup (name);
3810 g_list_free_full (info->icon_list, g_object_unref);
3811 info->icon_list = NULL;
3813 update_themed_icon (NULL, window);
3815 g_object_notify (G_OBJECT (window), "icon-name");
3819 * gtk_window_get_icon_name:
3820 * @window: a #GtkWindow
3822 * Returns the name of the themed icon for the window,
3823 * see gtk_window_set_icon_name().
3825 * Returns: the icon name or %NULL if the window has
3831 gtk_window_get_icon_name (GtkWindow *window)
3833 GtkWindowIconInfo *info;
3835 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3837 info = ensure_icon_info (window);
3839 return info->icon_name;
3843 * gtk_window_get_icon:
3844 * @window: a #GtkWindow
3846 * Gets the value set by gtk_window_set_icon() (or if you've
3847 * called gtk_window_set_icon_list(), gets the first icon in
3850 * Return value: (transfer none): icon for window
3853 gtk_window_get_icon (GtkWindow *window)
3855 GtkWindowIconInfo *info;
3857 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3859 info = get_icon_info (window);
3860 if (info && info->icon_list)
3861 return GDK_PIXBUF (info->icon_list->data);
3866 /* Load pixbuf, printing warning on failure if error == NULL
3869 load_pixbuf_verbosely (const char *filename,
3872 GError *local_err = NULL;
3875 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3883 g_warning ("Error loading icon from file '%s':\n\t%s",
3884 filename, local_err->message);
3885 g_error_free (local_err);
3893 * gtk_window_set_icon_from_file:
3894 * @window: a #GtkWindow
3895 * @filename: (type filename): location of icon file
3896 * @err: (allow-none): location to store error, or %NULL.
3898 * Sets the icon for @window.
3899 * Warns on failure if @err is %NULL.
3901 * This function is equivalent to calling gtk_window_set_icon()
3902 * with a pixbuf created by loading the image from @filename.
3904 * Returns: %TRUE if setting the icon succeeded.
3909 gtk_window_set_icon_from_file (GtkWindow *window,
3910 const gchar *filename,
3913 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3917 gtk_window_set_icon (window, pixbuf);
3918 g_object_unref (pixbuf);
3927 * gtk_window_set_default_icon_list:
3928 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3930 * Sets an icon list to be used as fallback for windows that haven't
3931 * had gtk_window_set_icon_list() called on them to set up a
3932 * window-specific icon list. This function allows you to set up the
3933 * icon for all windows in your app at once.
3935 * See gtk_window_set_icon_list() for more details.
3939 gtk_window_set_default_icon_list (GList *list)
3943 if (list == default_icon_list)
3946 /* Update serial so we don't used cached pixmaps/masks
3948 default_icon_serial++;
3950 g_list_foreach (list,
3951 (GFunc) g_object_ref, NULL);
3953 g_list_free_full (default_icon_list, g_object_unref);
3955 default_icon_list = g_list_copy (list);
3957 /* Update all toplevels */
3958 toplevels = gtk_window_list_toplevels ();
3959 tmp_list = toplevels;
3960 while (tmp_list != NULL)
3962 GtkWindowIconInfo *info;
3963 GtkWindow *w = tmp_list->data;
3965 info = get_icon_info (w);
3966 if (info && info->using_default_icon)
3968 gtk_window_unrealize_icon (w);
3969 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3970 gtk_window_realize_icon (w);
3973 tmp_list = tmp_list->next;
3975 g_list_free (toplevels);
3979 * gtk_window_set_default_icon:
3982 * Sets an icon to be used as fallback for windows that haven't
3983 * had gtk_window_set_icon() called on them from a pixbuf.
3988 gtk_window_set_default_icon (GdkPixbuf *icon)
3992 g_return_if_fail (GDK_IS_PIXBUF (icon));
3994 list = g_list_prepend (NULL, icon);
3995 gtk_window_set_default_icon_list (list);
4000 * gtk_window_set_default_icon_name:
4001 * @name: the name of the themed icon
4003 * Sets an icon to be used as fallback for windows that haven't
4004 * had gtk_window_set_icon_list() called on them from a named
4005 * themed icon, see gtk_window_set_icon_name().
4010 gtk_window_set_default_icon_name (const gchar *name)
4015 /* Update serial so we don't used cached pixmaps/masks
4017 default_icon_serial++;
4019 g_free (default_icon_name);
4020 default_icon_name = g_strdup (name);
4022 g_list_free_full (default_icon_list, g_object_unref);
4023 default_icon_list = NULL;
4025 /* Update all toplevels */
4026 toplevels = gtk_window_list_toplevels ();
4027 tmp_list = toplevels;
4028 while (tmp_list != NULL)
4030 GtkWindowIconInfo *info;
4031 GtkWindow *w = tmp_list->data;
4033 info = get_icon_info (w);
4034 if (info && info->using_default_icon && info->using_themed_icon)
4036 gtk_window_unrealize_icon (w);
4037 if (gtk_widget_get_realized (GTK_WIDGET (w)))
4038 gtk_window_realize_icon (w);
4041 tmp_list = tmp_list->next;
4043 g_list_free (toplevels);
4047 * gtk_window_get_default_icon_name:
4049 * Returns the fallback icon name for windows that has been set
4050 * with gtk_window_set_default_icon_name(). The returned
4051 * string is owned by GTK+ and should not be modified. It
4052 * is only valid until the next call to
4053 * gtk_window_set_default_icon_name().
4055 * Returns: the fallback icon name for windows
4060 gtk_window_get_default_icon_name (void)
4062 return default_icon_name;
4066 * gtk_window_set_default_icon_from_file:
4067 * @filename: (type filename): location of icon file
4068 * @err: (allow-none): location to store error, or %NULL.
4070 * Sets an icon to be used as fallback for windows that haven't
4071 * had gtk_window_set_icon_list() called on them from a file
4072 * on disk. Warns on failure if @err is %NULL.
4074 * Returns: %TRUE if setting the icon succeeded.
4079 gtk_window_set_default_icon_from_file (const gchar *filename,
4082 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
4086 gtk_window_set_default_icon (pixbuf);
4087 g_object_unref (pixbuf);
4096 * gtk_window_get_default_icon_list:
4098 * Gets the value set by gtk_window_set_default_icon_list().
4099 * The list is a copy and should be freed with g_list_free(),
4100 * but the pixbufs in the list have not had their reference count
4103 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
4106 gtk_window_get_default_icon_list (void)
4108 return g_list_copy (default_icon_list);
4112 gtk_window_set_default_size_internal (GtkWindow *window,
4113 gboolean change_width,
4115 gboolean change_height,
4117 gboolean is_geometry)
4119 GtkWindowGeometryInfo *info;
4121 g_return_if_fail (change_width == FALSE || width >= -1);
4122 g_return_if_fail (change_height == FALSE || height >= -1);
4124 info = gtk_window_get_geometry_info (window, TRUE);
4126 g_object_freeze_notify (G_OBJECT (window));
4128 info->default_is_geometry = is_geometry != FALSE;
4138 info->default_width = width;
4140 g_object_notify (G_OBJECT (window), "default-width");
4151 info->default_height = height;
4153 g_object_notify (G_OBJECT (window), "default-height");
4156 g_object_thaw_notify (G_OBJECT (window));
4158 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4162 * gtk_window_set_default_size:
4163 * @window: a #GtkWindow
4164 * @width: width in pixels, or -1 to unset the default width
4165 * @height: height in pixels, or -1 to unset the default height
4167 * Sets the default size of a window. If the window's "natural" size
4168 * (its size request) is larger than the default, the default will be
4169 * ignored. More generally, if the default size does not obey the
4170 * geometry hints for the window (gtk_window_set_geometry_hints() can
4171 * be used to set these explicitly), the default size will be clamped
4172 * to the nearest permitted size.
4174 * Unlike gtk_widget_set_size_request(), which sets a size request for
4175 * a widget and thus would keep users from shrinking the window, this
4176 * function only sets the initial size, just as if the user had
4177 * resized the window themselves. Users can still shrink the window
4178 * again as they normally would. Setting a default size of -1 means to
4179 * use the "natural" default size (the size request of the window).
4181 * For more control over a window's initial size and how resizing works,
4182 * investigate gtk_window_set_geometry_hints().
4184 * For some uses, gtk_window_resize() is a more appropriate function.
4185 * gtk_window_resize() changes the current size of the window, rather
4186 * than the size to be used on initial display. gtk_window_resize() always
4187 * affects the window itself, not the geometry widget.
4189 * The default size of a window only affects the first time a window is
4190 * shown; if a window is hidden and re-shown, it will remember the size
4191 * it had prior to hiding, rather than using the default size.
4193 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4194 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4197 gtk_window_set_default_size (GtkWindow *window,
4201 g_return_if_fail (GTK_IS_WINDOW (window));
4202 g_return_if_fail (width >= -1);
4203 g_return_if_fail (height >= -1);
4205 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4209 * gtk_window_set_default_geometry:
4210 * @window: a #GtkWindow
4211 * @width: width in resize increments, or -1 to unset the default width
4212 * @height: height in resize increments, or -1 to unset the default height
4214 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4215 * in terms of the base size and increment set with
4216 * gtk_window_set_geometry_hints.
4221 gtk_window_set_default_geometry (GtkWindow *window,
4225 g_return_if_fail (GTK_IS_WINDOW (window));
4226 g_return_if_fail (width >= -1);
4227 g_return_if_fail (height >= -1);
4229 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4233 * gtk_window_get_default_size:
4234 * @window: a #GtkWindow
4235 * @width: (out) (allow-none): location to store the default width, or %NULL
4236 * @height: (out) (allow-none): location to store the default height, or %NULL
4238 * Gets the default size of the window. A value of -1 for the width or
4239 * height indicates that a default size has not been explicitly set
4240 * for that dimension, so the "natural" size of the window will be
4245 gtk_window_get_default_size (GtkWindow *window,
4249 GtkWindowGeometryInfo *info;
4251 g_return_if_fail (GTK_IS_WINDOW (window));
4253 info = gtk_window_get_geometry_info (window, FALSE);
4256 *width = info ? info->default_width : -1;
4259 *height = info ? info->default_height : -1;
4263 * gtk_window_resize:
4264 * @window: a #GtkWindow
4265 * @width: width in pixels to resize the window to
4266 * @height: height in pixels to resize the window to
4268 * Resizes the window as if the user had done so, obeying geometry
4269 * constraints. The default geometry constraint is that windows may
4270 * not be smaller than their size request; to override this
4271 * constraint, call gtk_widget_set_size_request() to set the window's
4272 * request to a smaller value.
4274 * If gtk_window_resize() is called before showing a window for the
4275 * first time, it overrides any default size set with
4276 * gtk_window_set_default_size().
4278 * Windows may not be resized smaller than 1 by 1 pixels.
4282 gtk_window_resize (GtkWindow *window,
4286 GtkWindowGeometryInfo *info;
4288 g_return_if_fail (GTK_IS_WINDOW (window));
4289 g_return_if_fail (width > 0);
4290 g_return_if_fail (height > 0);
4292 info = gtk_window_get_geometry_info (window, TRUE);
4294 info->resize_width = width;
4295 info->resize_height = height;
4296 info->resize_is_geometry = FALSE;
4298 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4302 * gtk_window_resize_to_geometry:
4303 * @window: a #GtkWindow
4304 * @width: width in resize increments to resize the window to
4305 * @height: height in resize increments to resize the window to
4307 * Like gtk_window_resize(), but @width and @height are interpreted
4308 * in terms of the base size and increment set with
4309 * gtk_window_set_geometry_hints.
4314 gtk_window_resize_to_geometry (GtkWindow *window,
4318 GtkWindowGeometryInfo *info;
4320 g_return_if_fail (GTK_IS_WINDOW (window));
4321 g_return_if_fail (width > 0);
4322 g_return_if_fail (height > 0);
4324 info = gtk_window_get_geometry_info (window, TRUE);
4326 info->resize_width = width;
4327 info->resize_height = height;
4328 info->resize_is_geometry = TRUE;
4330 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4334 * gtk_window_get_size:
4335 * @window: a #GtkWindow
4336 * @width: (out) (allow-none): return location for width, or %NULL
4337 * @height: (out) (allow-none): return location for height, or %NULL
4339 * Obtains the current size of @window. If @window is not onscreen,
4340 * it returns the size GTK+ will suggest to the <link
4341 * linkend="gtk-X11-arch">window manager</link> for the initial window
4342 * size (but this is not reliably the same as the size the window
4343 * manager will actually select). The size obtained by
4344 * gtk_window_get_size() is the last size received in a
4345 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4346 * rather than querying the X server for the size. As a result, if you
4347 * call gtk_window_resize() then immediately call
4348 * gtk_window_get_size(), the size won't have taken effect yet. After
4349 * the window manager processes the resize request, GTK+ receives
4350 * notification that the size has changed via a configure event, and
4351 * the size of the window gets updated.
4353 * Note 1: Nearly any use of this function creates a race condition,
4354 * because the size of the window may change between the time that you
4355 * get the size and the time that you perform some action assuming
4356 * that size is the current size. To avoid race conditions, connect to
4357 * "configure-event" on the window and adjust your size-dependent
4358 * state to match the size delivered in the #GdkEventConfigure.
4360 * Note 2: The returned size does <emphasis>not</emphasis> include the
4361 * size of the window manager decorations (aka the window frame or
4362 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4363 * method of determining their size.
4365 * Note 3: If you are getting a window size in order to position
4366 * the window onscreen, there may be a better way. The preferred
4367 * way is to simply set the window's semantic type with
4368 * gtk_window_set_type_hint(), which allows the window manager to
4369 * e.g. center dialogs. Also, if you set the transient parent of
4370 * dialogs with gtk_window_set_transient_for() window managers
4371 * will often center the dialog over its parent window. It's
4372 * much preferred to let the window manager handle these
4373 * things rather than doing it yourself, because all apps will
4374 * behave consistently and according to user prefs if the window
4375 * manager handles it. Also, the window manager can take the size
4376 * of the window decorations/border into account, while your
4377 * application cannot.
4379 * In any case, if you insist on application-specified window
4380 * positioning, there's <emphasis>still</emphasis> a better way than
4381 * doing it yourself - gtk_window_set_position() will frequently
4382 * handle the details for you.
4386 gtk_window_get_size (GtkWindow *window,
4392 g_return_if_fail (GTK_IS_WINDOW (window));
4394 if (width == NULL && height == NULL)
4397 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4399 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4400 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4404 GdkRectangle configure_request;
4406 gtk_window_compute_configure_request (window,
4410 w = configure_request.width;
4411 h = configure_request.height;
4422 * @window: a #GtkWindow
4423 * @x: X coordinate to move window to
4424 * @y: Y coordinate to move window to
4426 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4427 * @window to the given position. Window managers are free to ignore
4428 * this; most window managers ignore requests for initial window
4429 * positions (instead using a user-defined placement algorithm) and
4430 * honor requests after the window has already been shown.
4432 * Note: the position is the position of the gravity-determined
4433 * reference point for the window. The gravity determines two things:
4434 * first, the location of the reference point in root window
4435 * coordinates; and second, which point on the window is positioned at
4436 * the reference point.
4438 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4439 * point is simply the @x, @y supplied to gtk_window_move(). The
4440 * top-left corner of the window decorations (aka window frame or
4441 * border) will be placed at @x, @y. Therefore, to position a window
4442 * at the top left of the screen, you want to use the default gravity
4443 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4445 * To position a window at the bottom right corner of the screen, you
4446 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4447 * point is at @x + the window width and @y + the window height, and
4448 * the bottom-right corner of the window border will be placed at that
4449 * reference point. So, to place a window in the bottom right corner
4450 * you would first set gravity to south east, then write:
4451 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4452 * gdk_screen_height () - window_height)</literal> (note that this
4453 * example does not take multi-head scenarios into account).
4455 * The Extended Window Manager Hints specification at <ulink
4456 * url="http://www.freedesktop.org/Standards/wm-spec">
4457 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4458 * nice table of gravities in the "implementation notes" section.
4460 * The gtk_window_get_position() documentation may also be relevant.
4463 gtk_window_move (GtkWindow *window,
4467 GtkWindowGeometryInfo *info;
4470 g_return_if_fail (GTK_IS_WINDOW (window));
4472 widget = GTK_WIDGET (window);
4474 info = gtk_window_get_geometry_info (window, TRUE);
4476 if (gtk_widget_get_mapped (widget))
4478 GtkAllocation allocation;
4480 gtk_widget_get_allocation (widget, &allocation);
4482 /* we have now sent a request with this position
4483 * with currently-active constraints, so toggle flag.
4485 info->position_constraints_changed = FALSE;
4487 /* we only constrain if mapped - if not mapped,
4488 * then gtk_window_compute_configure_request()
4489 * will apply the constraints later, and we
4490 * don't want to lose information about
4491 * what position the user set before then.
4492 * i.e. if you do a move() then turn off POS_CENTER
4493 * then show the window, your move() will work.
4495 gtk_window_constrain_position (window,
4496 allocation.width, allocation.height,
4499 /* Note that this request doesn't go through our standard request
4500 * framework, e.g. doesn't increment configure_request_count,
4501 * doesn't set info->last, etc.; that's because
4502 * we don't save the info needed to arrive at this same request
4505 * To gtk_window_move_resize(), this will end up looking exactly
4506 * the same as the position being changed by the window
4509 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4513 /* Save this position to apply on mapping */
4514 info->initial_x = x;
4515 info->initial_y = y;
4516 info->initial_pos_set = TRUE;
4521 * gtk_window_get_position:
4522 * @window: a #GtkWindow
4523 * @root_x: (out) (allow-none): return location for X coordinate of
4524 * gravity-determined reference point, or %NULL
4525 * @root_y: (out) (allow-none): return location for Y coordinate of
4526 * gravity-determined reference point, or %NULL
4528 * This function returns the position you need to pass to
4529 * gtk_window_move() to keep @window in its current position.
4530 * This means that the meaning of the returned value varies with
4531 * window gravity. See gtk_window_move() for more details.
4533 * If you haven't changed the window gravity, its gravity will be
4534 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4535 * gets the position of the top-left corner of the window manager
4536 * frame for the window. gtk_window_move() sets the position of this
4537 * same top-left corner.
4539 * gtk_window_get_position() is not 100% reliable because the X Window System
4540 * does not specify a way to obtain the geometry of the
4541 * decorations placed on a window by the window manager.
4542 * Thus GTK+ is using a "best guess" that works with most
4545 * Moreover, nearly all window managers are historically broken with
4546 * respect to their handling of window gravity. So moving a window to
4547 * its current position as returned by gtk_window_get_position() tends
4548 * to result in moving the window slightly. Window managers are
4549 * slowly getting better over time.
4551 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4552 * frame is not relevant, and thus gtk_window_get_position() will
4553 * always produce accurate results. However you can't use static
4554 * gravity to do things like place a window in a corner of the screen,
4555 * because static gravity ignores the window manager decorations.
4557 * If you are saving and restoring your application's window
4558 * positions, you should know that it's impossible for applications to
4559 * do this without getting it somewhat wrong because applications do
4560 * not have sufficient knowledge of window manager state. The Correct
4561 * Mechanism is to support the session management protocol (see the
4562 * "GnomeClient" object in the GNOME libraries for example) and allow
4563 * the window manager to save your window sizes and positions.
4568 gtk_window_get_position (GtkWindow *window,
4572 GtkWindowPrivate *priv;
4574 GdkWindow *gdk_window;
4576 g_return_if_fail (GTK_IS_WINDOW (window));
4578 priv = window->priv;
4579 widget = GTK_WIDGET (window);
4580 gdk_window = gtk_widget_get_window (widget);
4582 if (priv->gravity == GDK_GRAVITY_STATIC)
4584 if (gtk_widget_get_mapped (widget))
4586 /* This does a server round-trip, which is sort of wrong;
4587 * but a server round-trip is inevitable for
4588 * gdk_window_get_frame_extents() in the usual
4589 * NorthWestGravity case below, so not sure what else to
4590 * do. We should likely be consistent about whether we get
4591 * the client-side info or the server-side info.
4593 gdk_window_get_origin (gdk_window, root_x, root_y);
4597 GdkRectangle configure_request;
4599 gtk_window_compute_configure_request (window,
4603 *root_x = configure_request.x;
4604 *root_y = configure_request.y;
4609 GdkRectangle frame_extents;
4614 if (gtk_widget_get_mapped (widget))
4616 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4617 x = frame_extents.x;
4618 y = frame_extents.y;
4619 gtk_window_get_size (window, &w, &h);
4623 /* We just say the frame has 0 size on all sides.
4624 * Not sure what else to do.
4626 gtk_window_compute_configure_request (window,
4629 x = frame_extents.x;
4630 y = frame_extents.y;
4631 w = frame_extents.width;
4632 h = frame_extents.height;
4635 switch (priv->gravity)
4637 case GDK_GRAVITY_NORTH:
4638 case GDK_GRAVITY_CENTER:
4639 case GDK_GRAVITY_SOUTH:
4640 /* Find center of frame. */
4641 x += frame_extents.width / 2;
4642 /* Center client window on that point. */
4646 case GDK_GRAVITY_SOUTH_EAST:
4647 case GDK_GRAVITY_EAST:
4648 case GDK_GRAVITY_NORTH_EAST:
4649 /* Find right edge of frame */
4650 x += frame_extents.width;
4651 /* Align left edge of client at that point. */
4658 switch (priv->gravity)
4660 case GDK_GRAVITY_WEST:
4661 case GDK_GRAVITY_CENTER:
4662 case GDK_GRAVITY_EAST:
4663 /* Find center of frame. */
4664 y += frame_extents.height / 2;
4665 /* Center client window there. */
4668 case GDK_GRAVITY_SOUTH_WEST:
4669 case GDK_GRAVITY_SOUTH:
4670 case GDK_GRAVITY_SOUTH_EAST:
4671 /* Find south edge of frame */
4672 y += frame_extents.height;
4673 /* Place bottom edge of client there */
4688 * gtk_window_reshow_with_initial_size:
4689 * @window: a #GtkWindow
4691 * Hides @window, then reshows it, resetting the
4692 * default size and position of the window. Used
4693 * by GUI builders only.
4696 gtk_window_reshow_with_initial_size (GtkWindow *window)
4700 g_return_if_fail (GTK_IS_WINDOW (window));
4702 widget = GTK_WIDGET (window);
4704 gtk_widget_hide (widget);
4705 gtk_widget_unrealize (widget);
4706 gtk_widget_show (widget);
4710 gtk_window_destroy (GtkWidget *widget)
4712 GtkWindow *window = GTK_WINDOW (widget);
4713 GtkWindowPrivate *priv = window->priv;
4715 gtk_window_release_application (window);
4717 toplevel_list = g_slist_remove (toplevel_list, window);
4719 if (priv->transient_parent)
4720 gtk_window_set_transient_for (window, NULL);
4722 remove_attach_widget (GTK_WINDOW (widget));
4724 /* frees the icons */
4725 gtk_window_set_icon_list (window, NULL);
4727 if (priv->has_user_ref_count)
4729 priv->has_user_ref_count = FALSE;
4730 g_object_unref (window);
4734 gtk_window_group_remove_window (priv->group, window);
4736 gtk_window_free_key_hash (window);
4738 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4742 gtk_window_finalize (GObject *object)
4744 GtkWindow *window = GTK_WINDOW (object);
4745 GtkWindowPrivate *priv = window->priv;
4746 GtkMnemonicHash *mnemonic_hash;
4748 g_free (priv->title);
4749 g_free (priv->wmclass_name);
4750 g_free (priv->wmclass_class);
4751 g_free (priv->wm_role);
4752 gtk_window_release_application (window);
4754 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4756 _gtk_mnemonic_hash_free (mnemonic_hash);
4758 if (priv->geometry_info)
4760 if (priv->geometry_info->widget)
4761 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4762 gtk_widget_destroyed,
4763 &priv->geometry_info->widget);
4764 g_free (priv->geometry_info);
4767 if (priv->keys_changed_handler)
4769 g_source_remove (priv->keys_changed_handler);
4770 priv->keys_changed_handler = 0;
4774 g_signal_handlers_disconnect_by_func (priv->screen,
4775 gtk_window_on_composited_changed, window);
4777 g_free (priv->startup_id);
4779 #ifdef GDK_WINDOWING_X11
4780 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4781 gtk_window_on_theme_variant_changed,
4785 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4789 gtk_window_show (GtkWidget *widget)
4791 GtkWindow *window = GTK_WINDOW (widget);
4792 GtkWindowPrivate *priv = window->priv;
4793 GtkContainer *container = GTK_CONTAINER (window);
4794 gboolean need_resize;
4797 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4799 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4803 _gtk_widget_set_visible_flag (widget, TRUE);
4805 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4806 _gtk_container_set_need_resize (container, FALSE);
4810 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4811 GtkAllocation allocation = { 0, 0 };
4812 GdkRectangle configure_request;
4813 GdkGeometry new_geometry;
4815 gboolean was_realized;
4817 /* We are going to go ahead and perform this configure request
4818 * and then emulate a configure notify by going ahead and
4819 * doing a size allocate. Sort of a synchronous
4820 * mini-copy of gtk_window_move_resize() here.
4822 gtk_window_compute_configure_request (window,
4827 /* We update this because we are going to go ahead
4828 * and gdk_window_resize() below, rather than
4831 info->last.configure_request.width = configure_request.width;
4832 info->last.configure_request.height = configure_request.height;
4834 /* and allocate the window - this is normally done
4835 * in move_resize in response to configure notify
4837 allocation.width = configure_request.width;
4838 allocation.height = configure_request.height;
4839 gtk_widget_size_allocate (widget, &allocation);
4841 /* Then we guarantee we have a realize */
4842 was_realized = FALSE;
4843 if (!gtk_widget_get_realized (widget))
4845 gtk_widget_realize (widget);
4846 was_realized = TRUE;
4849 /* We only send configure request if we didn't just finish
4850 * creating the window; if we just created the window
4851 * then we created it with widget->allocation anyhow.
4854 gdk_window_move_resize (gtk_widget_get_window (widget),
4855 configure_request.x,
4856 configure_request.y,
4857 configure_request.width,
4858 configure_request.height);
4861 gtk_container_check_resize (container);
4863 gtk_widget_map (widget);
4865 /* Try to make sure that we have some focused widget
4867 #ifdef GDK_WINDOWING_X11
4868 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4869 GTK_IS_PLUG (window);
4873 if (!priv->focus_widget && !is_plug)
4874 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4877 gtk_grab_add (widget);
4881 gtk_window_hide (GtkWidget *widget)
4883 GtkWindow *window = GTK_WINDOW (widget);
4884 GtkWindowPrivate *priv = window->priv;
4886 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4888 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4892 _gtk_widget_set_visible_flag (widget, FALSE);
4893 gtk_widget_unmap (widget);
4896 gtk_grab_remove (widget);
4900 gtk_window_map (GtkWidget *widget)
4903 GtkWindow *window = GTK_WINDOW (widget);
4904 GtkWindowPrivate *priv = window->priv;
4905 GdkWindow *gdk_window;
4906 gboolean auto_mnemonics;
4907 GtkPolicyType visible_focus;
4909 if (!gtk_widget_is_toplevel (widget))
4911 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4915 gtk_widget_set_mapped (widget, TRUE);
4917 child = gtk_bin_get_child (&(window->bin));
4919 gtk_widget_get_visible (child) &&
4920 !gtk_widget_get_mapped (child))
4921 gtk_widget_map (child);
4923 gdk_window = gtk_widget_get_window (widget);
4925 if (priv->maximize_initially)
4926 gdk_window_maximize (gdk_window);
4928 gdk_window_unmaximize (gdk_window);
4930 if (priv->stick_initially)
4931 gdk_window_stick (gdk_window);
4933 gdk_window_unstick (gdk_window);
4935 if (priv->iconify_initially)
4936 gdk_window_iconify (gdk_window);
4938 gdk_window_deiconify (gdk_window);
4940 if (priv->fullscreen_initially)
4941 gdk_window_fullscreen (gdk_window);
4943 gdk_window_unfullscreen (gdk_window);
4945 gdk_window_set_keep_above (gdk_window, priv->above_initially);
4947 gdk_window_set_keep_below (gdk_window, priv->below_initially);
4949 if (priv->type == GTK_WINDOW_TOPLEVEL)
4951 gtk_window_set_theme_variant (window);
4952 gtk_window_set_hide_titlebar_when_maximized (window,
4953 priv->hide_titlebar_when_maximized);
4956 /* No longer use the default settings */
4957 priv->need_default_size = FALSE;
4958 priv->need_default_position = FALSE;
4960 if (priv->reset_type_hint)
4962 /* We should only reset the type hint when the application
4963 * used gtk_window_set_type_hint() to change the hint.
4964 * Some applications use X directly to change the properties;
4965 * in that case, we shouldn't overwrite what they did.
4967 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4968 priv->reset_type_hint = FALSE;
4971 gdk_window_show (gdk_window);
4973 if (priv->grip_window)
4974 gdk_window_show (priv->grip_window);
4976 if (!disable_startup_notification)
4978 /* Do we have a custom startup-notification id? */
4979 if (priv->startup_id != NULL)
4981 /* Make sure we have a "real" id */
4982 if (!startup_id_is_fake (priv->startup_id))
4983 gdk_notify_startup_complete_with_id (priv->startup_id);
4985 g_free (priv->startup_id);
4986 priv->startup_id = NULL;
4988 else if (!sent_startup_notification)
4990 sent_startup_notification = TRUE;
4991 gdk_notify_startup_complete ();
4995 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4996 * (as in the case of popup menus), then hide mnemonics initially
4998 g_object_get (gtk_widget_get_settings (widget),
4999 "gtk-auto-mnemonics", &auto_mnemonics,
5000 "gtk-visible-focus", &visible_focus,
5003 if (auto_mnemonics && !priv->mnemonics_visible_set)
5004 gtk_window_set_mnemonics_visible (window, FALSE);
5006 /* inherit from transient parent, so that a dialog that is
5007 * opened via keynav shows focus initially
5009 if (priv->transient_parent)
5010 gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
5012 gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
5014 ensure_state_flag_backdrop (widget);
5018 gtk_window_map_event (GtkWidget *widget,
5021 if (!gtk_widget_get_mapped (widget))
5023 /* we should be be unmapped, but are getting a MapEvent, this may happen
5024 * to toplevel XWindows if mapping was intercepted by a window manager
5025 * and an unmap request occoured while the MapRequestEvent was still
5026 * being handled. we work around this situaiton here by re-requesting
5027 * the window being unmapped. more details can be found in:
5028 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
5030 gdk_window_hide (gtk_widget_get_window (widget));
5036 gtk_window_unmap (GtkWidget *widget)
5038 GtkWindow *window = GTK_WINDOW (widget);
5039 GtkWindowPrivate *priv = window->priv;
5041 GtkWindowGeometryInfo *info;
5042 GdkWindow *gdk_window;
5043 GdkWindowState state;
5045 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5047 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
5051 gdk_window = gtk_widget_get_window (widget);
5053 gtk_widget_set_mapped (widget, FALSE);
5054 gdk_window_withdraw (gdk_window);
5056 priv->configure_request_count = 0;
5057 priv->configure_notify_received = FALSE;
5059 /* on unmap, we reset the default positioning of the window,
5060 * so it's placed again, but we don't reset the default
5061 * size of the window, so it's remembered.
5063 priv->need_default_position = TRUE;
5065 info = gtk_window_get_geometry_info (window, FALSE);
5068 info->initial_pos_set = FALSE;
5069 info->position_constraints_changed = FALSE;
5072 state = gdk_window_get_state (gdk_window);
5073 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
5074 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
5075 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
5076 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
5077 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
5079 child = gtk_bin_get_child (&(window->bin));
5081 gtk_widget_unmap (child);
5084 /* (Note: Replace "size" with "width" or "height". Also, the request
5085 * mode is honoured.)
5086 * For selecting the default window size, the following conditions
5087 * should hold (in order of importance):
5088 * - the size is not below the minimum size
5089 * Windows cannot be resized below their minimum size, so we must
5090 * ensure we don't do that either.
5091 * - the size is not above the natural size
5092 * It seems weird to allocate more than this in an initial guess.
5093 * - the size does not exceed that of a maximized window
5094 * We want to see the whole window after all.
5095 * (Note that this may not be possible to achieve due to imperfect
5096 * information from the windowing system.)
5099 /* We use these for now to not make windows too big by accident. Note
5100 * that we still clamp these numbers by screen size. Also note that
5101 * minimum size still overrides this. So keep your windows small! :)
5103 #define MAX_DEFAULT_WINDOW_WIDTH 640
5104 #define MAX_DEFAULT_WINDOW_HEIGHT 480
5107 gtk_window_guess_default_size (GtkWindow *window,
5111 GtkWidget *widget = GTK_WIDGET (window);
5113 int minimum, natural;
5115 screen = gtk_widget_get_screen (widget);
5117 *width = gdk_screen_get_width (screen);
5118 *height = gdk_screen_get_height (screen);
5120 if (*width >= *height)
5123 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
5124 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
5129 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
5130 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
5133 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
5135 gtk_widget_get_preferred_height (widget, &minimum, &natural);
5136 *height = MAX (minimum, MIN (*height, natural));
5138 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
5139 *width = MAX (minimum, MIN (*width, natural));
5141 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
5143 gtk_widget_get_preferred_width (widget, &minimum, &natural);
5144 *width = MAX (minimum, MIN (*width, natural));
5146 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
5147 *height = MAX (minimum, MIN (*height, natural));
5152 gtk_window_realize (GtkWidget *widget)
5154 GtkAllocation allocation;
5156 GdkWindow *parent_window;
5157 GdkWindow *gdk_window;
5158 GdkWindowAttr attributes;
5159 gint attributes_mask;
5160 GtkWindowPrivate *priv;
5161 GtkStyleContext *context;
5163 window = GTK_WINDOW (widget);
5164 priv = window->priv;
5166 gtk_widget_get_allocation (widget, &allocation);
5168 if (gtk_widget_get_parent_window (widget))
5170 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
5172 gtk_widget_set_realized (widget, TRUE);
5174 attributes.x = allocation.x;
5175 attributes.y = allocation.y;
5176 attributes.width = allocation.width;
5177 attributes.height = allocation.height;
5178 attributes.window_type = GDK_WINDOW_CHILD;
5180 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
5182 attributes.visual = gtk_widget_get_visual (widget);
5183 attributes.wclass = GDK_INPUT_OUTPUT;
5185 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
5187 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
5188 &attributes, attributes_mask);
5189 gtk_widget_set_window (widget, gdk_window);
5190 gdk_window_set_user_data (gdk_window, widget);
5192 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
5194 gdk_window_enable_synchronized_configure (gdk_window);
5198 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5200 /* ensure widget tree is properly size allocated */
5201 if (allocation.x == -1 &&
5202 allocation.y == -1 &&
5203 allocation.width == 1 &&
5204 allocation.height == 1)
5210 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5211 if (allocation.width == 0 || allocation.height == 0)
5213 /* non-empty window */
5214 allocation.width = 200;
5215 allocation.height = 200;
5217 gtk_widget_size_allocate (widget, &allocation);
5219 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5221 g_return_if_fail (!gtk_widget_get_realized (widget));
5224 gtk_widget_set_realized (widget, TRUE);
5228 case GTK_WINDOW_TOPLEVEL:
5229 attributes.window_type = GDK_WINDOW_TOPLEVEL;
5231 case GTK_WINDOW_POPUP:
5232 attributes.window_type = GDK_WINDOW_TEMP;
5235 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5239 attributes.title = priv->title;
5240 attributes.wmclass_name = priv->wmclass_name;
5241 attributes.wmclass_class = priv->wmclass_class;
5242 attributes.wclass = GDK_INPUT_OUTPUT;
5243 attributes.visual = gtk_widget_get_visual (widget);
5245 attributes_mask = 0;
5246 parent_window = gtk_widget_get_root_window (widget);
5248 gtk_widget_get_allocation (widget, &allocation);
5249 attributes.width = allocation.width;
5250 attributes.height = allocation.height;
5251 attributes.event_mask = gtk_widget_get_events (widget);
5252 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5253 GDK_KEY_PRESS_MASK |
5254 GDK_KEY_RELEASE_MASK |
5255 GDK_ENTER_NOTIFY_MASK |
5256 GDK_LEAVE_NOTIFY_MASK |
5257 GDK_FOCUS_CHANGE_MASK |
5258 GDK_STRUCTURE_MASK);
5259 attributes.type_hint = priv->type_hint;
5261 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5262 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5263 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5265 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5266 gtk_widget_set_window (widget, gdk_window);
5268 if (priv->opacity_set)
5269 gdk_window_set_opacity (gdk_window, priv->opacity);
5271 gdk_window_enable_synchronized_configure (gdk_window);
5273 gdk_window_set_user_data (gdk_window, window);
5275 context = gtk_widget_get_style_context (widget);
5276 gtk_style_context_set_background (context, gdk_window);
5279 if (priv->transient_parent &&
5280 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5281 gdk_window_set_transient_for (gdk_window,
5282 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5285 gdk_window_set_role (gdk_window, priv->wm_role);
5287 if (!priv->decorated)
5288 gdk_window_set_decorations (gdk_window, 0);
5290 if (!priv->deletable)
5291 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5293 if (gtk_window_get_skip_pager_hint (window))
5294 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5296 if (gtk_window_get_skip_taskbar_hint (window))
5297 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5299 if (gtk_window_get_accept_focus (window))
5300 gdk_window_set_accept_focus (gdk_window, TRUE);
5302 gdk_window_set_accept_focus (gdk_window, FALSE);
5304 if (gtk_window_get_focus_on_map (window))
5305 gdk_window_set_focus_on_map (gdk_window, TRUE);
5307 gdk_window_set_focus_on_map (gdk_window, FALSE);
5310 gdk_window_set_modal_hint (gdk_window, TRUE);
5312 gdk_window_set_modal_hint (gdk_window, FALSE);
5314 if (priv->startup_id)
5316 #ifdef GDK_WINDOWING_X11
5317 if (GDK_IS_X11_WINDOW (gdk_window))
5319 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5320 if (timestamp != GDK_CURRENT_TIME)
5321 gdk_x11_window_set_user_time (gdk_window, timestamp);
5324 if (!startup_id_is_fake (priv->startup_id))
5325 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5328 #ifdef GDK_WINDOWING_X11
5329 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5331 if (GDK_IS_X11_WINDOW (gdk_window))
5332 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5337 gtk_window_realize_icon (window);
5339 if (priv->has_resize_grip)
5340 resize_grip_create_window (window);
5344 gtk_window_unrealize (GtkWidget *widget)
5346 GtkWindow *window = GTK_WINDOW (widget);
5347 GtkWindowPrivate *priv = window->priv;
5348 GtkWindowGeometryInfo *info;
5350 /* On unrealize, we reset the size of the window such
5351 * that we will re-apply the default sizing stuff
5352 * next time we show the window.
5354 * Default positioning is reset on unmap, instead of unrealize.
5356 priv->need_default_size = TRUE;
5357 info = gtk_window_get_geometry_info (window, FALSE);
5360 info->resize_width = -1;
5361 info->resize_height = -1;
5362 info->last.configure_request.x = 0;
5363 info->last.configure_request.y = 0;
5364 info->last.configure_request.width = -1;
5365 info->last.configure_request.height = -1;
5366 /* be sure we reset geom hints on re-realize */
5367 info->last.flags = 0;
5371 gtk_window_unrealize_icon (window);
5373 if (priv->grip_window != NULL)
5374 resize_grip_destroy_window (window);
5376 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5379 static GtkJunctionSides
5380 get_grip_junction (GtkWidget *widget)
5382 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5383 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5385 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5389 get_drag_edge (GtkWidget *widget,
5390 GdkWindowEdge *edge)
5392 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5393 gboolean hresizable;
5394 gboolean vresizable;
5395 GtkTextDirection dir;
5396 GtkWindowGeometryInfo *info;
5401 info = priv->geometry_info;
5404 GdkWindowHints flags = info->last.flags;
5405 GdkGeometry *geometry = &info->last.geometry;
5407 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5409 hresizable = geometry->min_width < geometry->max_width;
5410 vresizable = geometry->min_height < geometry->max_height;
5414 dir = gtk_widget_get_direction (widget);
5416 if (hresizable && vresizable)
5417 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5418 else if (hresizable)
5419 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5420 else if (vresizable)
5421 *edge = GDK_WINDOW_EDGE_SOUTH;
5429 set_grip_cursor (GtkWindow *window)
5431 GtkWidget *widget = GTK_WIDGET (window);
5432 GtkWindowPrivate *priv = window->priv;
5434 if (priv->grip_window == NULL)
5437 if (gtk_widget_is_sensitive (widget))
5440 GdkDisplay *display;
5441 GdkCursorType cursor_type;
5444 cursor_type = GDK_LEFT_PTR;
5446 if (get_drag_edge (widget, &edge))
5450 case GDK_WINDOW_EDGE_EAST:
5451 cursor_type = GDK_RIGHT_SIDE;
5453 case GDK_WINDOW_EDGE_SOUTH_EAST:
5454 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5456 case GDK_WINDOW_EDGE_SOUTH:
5457 cursor_type = GDK_BOTTOM_SIDE;
5459 case GDK_WINDOW_EDGE_SOUTH_WEST:
5460 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5462 case GDK_WINDOW_EDGE_WEST:
5463 cursor_type = GDK_LEFT_SIDE;
5469 display = gtk_widget_get_display (widget);
5470 cursor = gdk_cursor_new_for_display (display, cursor_type);
5471 gdk_window_set_cursor (priv->grip_window, cursor);
5472 g_object_unref (cursor);
5475 gdk_window_set_cursor (priv->grip_window, NULL);
5479 set_grip_shape (GtkWindow *window)
5481 GtkWindowPrivate *priv = window->priv;
5482 cairo_region_t *region;
5483 cairo_surface_t *surface;
5485 double width, height;
5487 if (priv->grip_window == NULL)
5490 width = gdk_window_get_width (priv->grip_window);
5491 height = gdk_window_get_height (priv->grip_window);
5492 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
5494 cr = cairo_create (surface);
5495 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5497 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5498 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5500 cairo_move_to (cr, width, 0.0);
5501 cairo_line_to (cr, width, height);
5502 cairo_line_to (cr, 0.0, height);
5506 cairo_move_to (cr, 0.0, 0.0);
5507 cairo_line_to (cr, width, height);
5508 cairo_line_to (cr, 0.0, height);
5510 cairo_close_path (cr);
5513 region = gdk_cairo_region_create_from_surface (surface);
5514 cairo_surface_destroy (surface);
5516 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5517 cairo_region_destroy (region);
5521 set_grip_position (GtkWindow *window)
5523 GtkWindowPrivate *priv = window->priv;
5526 if (priv->grip_window == NULL)
5529 gtk_window_get_resize_grip_area (window, &rect);
5530 gdk_window_raise (priv->grip_window);
5531 gdk_window_move_resize (priv->grip_window,
5533 rect.width, rect.height);
5536 /* _gtk_window_set_allocation:
5537 * @window: a #GtkWindow
5538 * @allocation: the new allocation
5540 * This function is like gtk_widget_set_allocation()
5541 * but does the necessary extra work to update
5542 * the resize grip positioning, etc.
5544 * Call this instead of gtk_widget_set_allocation()
5545 * when overriding ::size_allocate in a GtkWindow
5546 * subclass without chaining up.
5549 _gtk_window_set_allocation (GtkWindow *window,
5550 GtkAllocation *allocation)
5552 GtkWidget *widget = (GtkWidget *)window;
5554 gtk_widget_set_allocation (widget, allocation);
5556 if (gtk_widget_get_realized (widget))
5558 /* If it's not a toplevel we're embedded, we need to resize
5559 * the window's window and skip the grip.
5561 if (!gtk_widget_is_toplevel (widget))
5563 gdk_window_move_resize (gtk_widget_get_window (widget),
5564 allocation->x, allocation->y,
5565 allocation->width, allocation->height);
5569 update_grip_visibility (window);
5570 set_grip_position (window);
5576 gtk_window_size_allocate (GtkWidget *widget,
5577 GtkAllocation *allocation)
5579 GtkWindow *window = GTK_WINDOW (widget);
5580 GtkAllocation child_allocation;
5584 _gtk_window_set_allocation (window, allocation);
5586 child = gtk_bin_get_child (&(window->bin));
5587 if (child && gtk_widget_get_visible (child))
5589 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5590 child_allocation.x = border_width;
5591 child_allocation.y = border_width;
5592 child_allocation.width = MAX (1, allocation->width - border_width * 2);
5593 child_allocation.height = MAX (1, allocation->height - border_width * 2);
5595 gtk_widget_size_allocate (child, &child_allocation);
5600 gtk_window_configure_event (GtkWidget *widget,
5601 GdkEventConfigure *event)
5603 GtkAllocation allocation;
5604 GtkWindow *window = GTK_WINDOW (widget);
5605 GtkWindowPrivate *priv = window->priv;
5606 gboolean expected_reply = priv->configure_request_count > 0;
5608 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5610 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5611 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5613 gdk_window_configure_finished (gtk_widget_get_window (widget));
5617 /* priv->configure_request_count incremented for each
5618 * configure request, and decremented to a min of 0 for
5619 * each configure notify.
5621 * All it means is that we know we will get at least
5622 * priv->configure_request_count more configure notifies.
5623 * We could get more configure notifies than that; some
5624 * of the configure notifies we get may be unrelated to
5625 * the configure requests. But we will get at least
5626 * priv->configure_request_count notifies.
5629 if (priv->configure_request_count > 0)
5631 priv->configure_request_count -= 1;
5632 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5635 /* As an optimization, we avoid a resize when possible.
5637 * The only times we can avoid a resize are:
5638 * - we know only the position changed, not the size
5639 * - we know we have made more requests and so will get more
5640 * notifies and can wait to resize when we get them
5642 gtk_widget_get_allocation (widget, &allocation);
5643 if (!expected_reply &&
5644 (allocation.width == event->width &&
5645 allocation.height == event->height))
5647 gdk_window_configure_finished (gtk_widget_get_window (widget));
5652 * If we do need to resize, we do that by:
5653 * - filling in widget->allocation with the new size
5654 * - setting configure_notify_received to TRUE
5655 * for use in gtk_window_move_resize()
5656 * - queueing a resize, leading to invocation of
5657 * gtk_window_move_resize() in an idle handler
5661 priv->configure_notify_received = TRUE;
5663 allocation.width = event->width;
5664 allocation.height = event->height;
5665 gtk_widget_set_allocation (widget, &allocation);
5667 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5669 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5675 gtk_window_state_event (GtkWidget *widget,
5676 GdkEventWindowState *event)
5678 update_grip_visibility (GTK_WINDOW (widget));
5680 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
5681 ensure_state_flag_backdrop (widget);
5687 gtk_window_direction_changed (GtkWidget *widget,
5688 GtkTextDirection prev_dir)
5690 GtkWindow *window = GTK_WINDOW (widget);
5692 set_grip_cursor (window);
5693 set_grip_position (window);
5694 set_grip_shape (window);
5698 gtk_window_state_changed (GtkWidget *widget,
5699 GtkStateType previous_state)
5701 GtkWindow *window = GTK_WINDOW (widget);
5703 update_grip_visibility (window);
5707 gtk_window_style_updated (GtkWidget *widget)
5709 GtkWindow *window = GTK_WINDOW (widget);
5710 GtkWindowPrivate *priv = window->priv;
5713 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5715 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5717 gdk_window_move_resize (priv->grip_window,
5719 rect.width, rect.height);
5721 set_grip_shape (window);
5722 gtk_widget_queue_resize (widget);
5727 resize_grip_create_window (GtkWindow *window)
5730 GtkWindowPrivate *priv;
5731 GdkWindowAttr attributes;
5732 gint attributes_mask;
5734 GdkRGBA transparent = {0, 0, 0, 0};
5736 priv = window->priv;
5737 widget = GTK_WIDGET (window);
5739 g_return_if_fail (gtk_widget_get_realized (widget));
5740 g_return_if_fail (priv->grip_window == NULL);
5742 gtk_window_get_resize_grip_area (window, &rect);
5744 attributes.x = rect.x;
5745 attributes.y = rect.y;
5746 attributes.width = rect.width;
5747 attributes.height = rect.height;
5748 attributes.window_type = GDK_WINDOW_CHILD;
5749 attributes.wclass = GDK_INPUT_OUTPUT;
5750 attributes.event_mask = gtk_widget_get_events (widget) |
5752 GDK_BUTTON_PRESS_MASK;
5754 attributes_mask = GDK_WA_X | GDK_WA_Y;
5756 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5759 gdk_window_set_background_rgba (priv->grip_window, &transparent);
5761 gdk_window_set_user_data (priv->grip_window, widget);
5763 gdk_window_raise (priv->grip_window);
5765 set_grip_shape (window);
5766 update_grip_visibility (window);
5770 resize_grip_destroy_window (GtkWindow *window)
5772 GtkWindowPrivate *priv = window->priv;
5774 gdk_window_set_user_data (priv->grip_window, NULL);
5775 gdk_window_destroy (priv->grip_window);
5776 priv->grip_window = NULL;
5777 update_grip_visibility (window);
5781 * gtk_window_set_has_resize_grip:
5782 * @window: a #GtkWindow
5783 * @value: %TRUE to allow a resize grip
5785 * Sets whether @window has a corner resize grip.
5787 * Note that the resize grip is only shown if the window
5788 * is actually resizable and not maximized. Use
5789 * gtk_window_resize_grip_is_visible() to find out if the
5790 * resize grip is currently shown.
5795 gtk_window_set_has_resize_grip (GtkWindow *window,
5798 GtkWidget *widget = GTK_WIDGET (window);
5799 GtkWindowPrivate *priv = window->priv;
5801 value = value != FALSE;
5803 if (value != priv->has_resize_grip)
5805 priv->has_resize_grip = value;
5806 gtk_widget_queue_draw (widget);
5808 if (gtk_widget_get_realized (widget) &&
5809 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5811 if (priv->has_resize_grip && priv->grip_window == NULL)
5812 resize_grip_create_window (window);
5813 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5814 resize_grip_destroy_window (window);
5817 g_object_notify (G_OBJECT (window), "has-resize-grip");
5822 update_grip_visibility (GtkWindow *window)
5824 GtkWindowPrivate *priv = window->priv;
5827 val = gtk_window_resize_grip_is_visible (window);
5829 if (priv->grip_window != NULL)
5833 gdk_window_show (priv->grip_window);
5834 set_grip_cursor (window);
5838 gdk_window_hide (priv->grip_window);
5842 if (priv->resize_grip_visible != val)
5844 priv->resize_grip_visible = val;
5846 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5851 * gtk_window_resize_grip_is_visible:
5852 * @window: a #GtkWindow
5854 * Determines whether a resize grip is visible for the specified window.
5856 * Returns: %TRUE if a resize grip exists and is visible
5861 gtk_window_resize_grip_is_visible (GtkWindow *window)
5864 GtkWindowPrivate *priv;
5867 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5869 priv = window->priv;
5870 widget = GTK_WIDGET (window);
5872 if (priv->type == GTK_WINDOW_POPUP)
5875 if (!priv->resizable)
5878 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5881 if (gtk_widget_get_realized (widget))
5883 GdkWindowState state;
5885 state = gdk_window_get_state (gtk_widget_get_window (widget));
5887 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5891 if (!get_drag_edge (widget, &edge))
5894 return window->priv->has_resize_grip;
5898 * gtk_window_get_has_resize_grip:
5899 * @window: a #GtkWindow
5901 * Determines whether the window may have a resize grip.
5903 * Returns: %TRUE if the window has a resize grip
5908 gtk_window_get_has_resize_grip (GtkWindow *window)
5910 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5912 return window->priv->has_resize_grip;
5916 * gtk_window_get_resize_grip_area:
5917 * @window: a #GtkWindow
5918 * @rect: (out): a pointer to a #GdkRectangle which we should store
5919 * the resize grip area
5921 * If a window has a resize grip, this will retrieve the grip
5922 * position, width and height into the specified #GdkRectangle.
5924 * Returns: %TRUE if the resize grip's area was retrieved
5929 gtk_window_get_resize_grip_area (GtkWindow *window,
5932 GtkWidget *widget = GTK_WIDGET (window);
5933 GtkAllocation allocation;
5937 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5939 if (!window->priv->has_resize_grip)
5942 gtk_widget_get_allocation (widget, &allocation);
5944 gtk_widget_style_get (widget,
5945 "resize-grip-width", &grip_width,
5946 "resize-grip-height", &grip_height,
5949 if (grip_width > allocation.width)
5950 grip_width = allocation.width;
5952 if (grip_height > allocation.height)
5953 grip_height = allocation.height;
5955 rect->width = grip_width;
5956 rect->height = grip_height;
5957 rect->y = allocation.y + allocation.height - grip_height;
5959 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5960 rect->x = allocation.x + allocation.width - grip_width;
5962 rect->x = allocation.x;
5967 /* the accel_key and accel_mods fields of the key have to be setup
5968 * upon calling this function. it'll then return whether that key
5969 * is at all used as accelerator, and if so will OR in the
5970 * accel_flags member of the key.
5973 _gtk_window_query_nonaccels (GtkWindow *window,
5975 GdkModifierType accel_mods)
5977 GtkWindowPrivate *priv;
5979 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5981 priv = window->priv;
5983 /* movement keys are considered locked accels */
5986 static const guint bindings[] = {
5987 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,
5988 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,
5992 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5993 if (bindings[i] == accel_key)
5997 /* mnemonics are considered locked accels */
5998 if (accel_mods == priv->mnemonic_modifier)
6000 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
6001 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
6009 * gtk_window_propagate_key_event:
6010 * @window: a #GtkWindow
6011 * @event: a #GdkEventKey
6013 * Propagate a key press or release event to the focus widget and
6014 * up the focus container chain until a widget handles @event.
6015 * This is normally called by the default ::key_press_event and
6016 * ::key_release_event handlers for toplevel windows,
6017 * however in some cases it may be useful to call this directly when
6018 * overriding the standard key handling for a toplevel window.
6020 * Return value: %TRUE if a widget in the focus chain handled the event.
6025 gtk_window_propagate_key_event (GtkWindow *window,
6028 GtkWindowPrivate *priv;
6029 gboolean handled = FALSE;
6030 GtkWidget *widget, *focus;
6032 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6034 priv = window->priv;
6035 widget = GTK_WIDGET (window);
6037 focus = priv->focus_widget;
6039 g_object_ref (focus);
6042 focus && focus != widget &&
6043 gtk_widget_get_toplevel (focus) == widget)
6047 if (gtk_widget_is_sensitive (focus))
6048 handled = gtk_widget_event (focus, (GdkEvent*) event);
6050 parent = gtk_widget_get_parent (focus);
6052 g_object_ref (parent);
6054 g_object_unref (focus);
6060 g_object_unref (focus);
6066 gtk_window_key_press_event (GtkWidget *widget,
6069 GtkWindow *window = GTK_WINDOW (widget);
6070 gboolean handled = FALSE;
6072 /* handle mnemonics and accelerators */
6074 handled = gtk_window_activate_key (window, event);
6076 /* handle focus widget key events */
6078 handled = gtk_window_propagate_key_event (window, event);
6080 /* Chain up, invokes binding set */
6082 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
6088 gtk_window_key_release_event (GtkWidget *widget,
6091 GtkWindow *window = GTK_WINDOW (widget);
6092 gboolean handled = FALSE;
6094 /* handle focus widget key events */
6096 handled = gtk_window_propagate_key_event (window, event);
6098 /* Chain up, invokes binding set */
6100 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
6106 gtk_window_button_press_event (GtkWidget *widget,
6107 GdkEventButton *event)
6109 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
6112 if (event->window == priv->grip_window)
6114 if (get_drag_edge (widget, &edge))
6115 gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
6117 gdk_event_get_device ((GdkEvent *) event),
6130 gtk_window_real_activate_default (GtkWindow *window)
6132 gtk_window_activate_default (window);
6136 gtk_window_real_activate_focus (GtkWindow *window)
6138 gtk_window_activate_focus (window);
6142 gtk_window_enter_notify_event (GtkWidget *widget,
6143 GdkEventCrossing *event)
6149 gtk_window_leave_notify_event (GtkWidget *widget,
6150 GdkEventCrossing *event)
6156 do_focus_change (GtkWidget *widget,
6160 GdkDeviceManager *device_manager;
6163 g_object_ref (widget);
6165 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
6166 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6167 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
6168 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
6170 for (d = devices; d; d = d->next)
6172 GdkDevice *dev = d->data;
6175 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
6178 /* Skip non-master keyboards that haven't
6179 * selected for events from this window
6181 window = gtk_widget_get_window (widget);
6182 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
6183 window && !gdk_window_get_device_events (window, dev))
6186 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
6188 fevent->focus_change.type = GDK_FOCUS_CHANGE;
6189 fevent->focus_change.window = window;
6191 g_object_ref (window);
6192 fevent->focus_change.in = in;
6193 gdk_event_set_device (fevent, dev);
6195 gtk_widget_send_focus_change (widget, fevent);
6197 gdk_event_free (fevent);
6200 g_list_free (devices);
6201 g_object_unref (widget);
6205 maybe_set_mnemonics_visible (GtkWindow *window)
6208 GdkDeviceManager *device_manager;
6210 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
6211 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6213 for (d = devices; d; d = d->next)
6215 GdkDevice *dev = d->data;
6217 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6219 GdkModifierType mask;
6221 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6223 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6225 gtk_window_set_mnemonics_visible (window, TRUE);
6231 g_list_free (devices);
6235 gtk_window_focus_in_event (GtkWidget *widget,
6236 GdkEventFocus *event)
6238 GtkWindow *window = GTK_WINDOW (widget);
6239 gboolean auto_mnemonics;
6241 /* It appears spurious focus in events can occur when
6242 * the window is hidden. So we'll just check to see if
6243 * the window is visible before actually handling the
6246 if (gtk_widget_get_visible (widget))
6248 _gtk_window_set_has_toplevel_focus (window, TRUE);
6249 _gtk_window_set_is_active (window, TRUE);
6251 g_object_get (gtk_widget_get_settings (widget),
6252 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6254 maybe_set_mnemonics_visible (window);
6261 gtk_window_focus_out_event (GtkWidget *widget,
6262 GdkEventFocus *event)
6264 GtkWindow *window = GTK_WINDOW (widget);
6265 gboolean auto_mnemonics;
6267 _gtk_window_set_has_toplevel_focus (window, FALSE);
6268 _gtk_window_set_is_active (window, FALSE);
6270 /* set the mnemonic-visible property to false */
6271 g_object_get (gtk_widget_get_settings (widget),
6272 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6274 gtk_window_set_mnemonics_visible (window, FALSE);
6280 gtk_window_check_resize (GtkContainer *container)
6282 /* If the window is not toplevel anymore than it's embedded somewhere,
6283 * so handle it like a normal window */
6284 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6285 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6286 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6287 gtk_window_move_resize (GTK_WINDOW (container));
6291 gtk_window_focus (GtkWidget *widget,
6292 GtkDirectionType direction)
6294 GtkWindowPrivate *priv;
6297 GtkContainer *container;
6299 GtkWidget *old_focus_child;
6302 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6303 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6305 container = GTK_CONTAINER (widget);
6306 window = GTK_WINDOW (widget);
6307 priv = window->priv;
6308 bin = GTK_BIN (widget);
6310 old_focus_child = gtk_container_get_focus_child (container);
6312 /* We need a special implementation here to deal properly with wrapping
6313 * around in the tab chain without the danger of going into an
6316 if (old_focus_child)
6318 if (gtk_widget_child_focus (old_focus_child, direction))
6322 if (priv->focus_widget)
6324 if (direction == GTK_DIR_LEFT ||
6325 direction == GTK_DIR_RIGHT ||
6326 direction == GTK_DIR_UP ||
6327 direction == GTK_DIR_DOWN)
6332 /* Wrapped off the end, clear the focus setting for the toplpevel */
6333 parent = gtk_widget_get_parent (priv->focus_widget);
6336 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6337 parent = gtk_widget_get_parent (parent);
6340 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6343 /* Now try to focus the first widget in the window */
6344 child = gtk_bin_get_child (bin);
6347 if (gtk_widget_child_focus (child, direction))
6355 gtk_window_move_focus (GtkWidget *widget,
6356 GtkDirectionType dir)
6358 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6360 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6364 gtk_widget_child_focus (widget, dir);
6366 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6367 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6371 gtk_window_real_set_focus (GtkWindow *window,
6374 GtkWindowPrivate *priv = window->priv;
6375 GtkWidget *old_focus = priv->focus_widget;
6376 gboolean had_default = FALSE;
6377 gboolean focus_had_default = FALSE;
6378 gboolean old_focus_had_default = FALSE;
6382 g_object_ref (old_focus);
6383 g_object_freeze_notify (G_OBJECT (old_focus));
6384 old_focus_had_default = gtk_widget_has_default (old_focus);
6388 g_object_ref (focus);
6389 g_object_freeze_notify (G_OBJECT (focus));
6390 focus_had_default = gtk_widget_has_default (focus);
6393 if (priv->default_widget)
6394 had_default = gtk_widget_has_default (priv->default_widget);
6396 if (priv->focus_widget)
6398 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6399 (priv->focus_widget != priv->default_widget))
6401 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6402 gtk_widget_queue_draw (priv->focus_widget);
6404 if (priv->default_widget)
6405 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6408 priv->focus_widget = NULL;
6410 if (priv->has_focus)
6411 do_focus_change (old_focus, FALSE);
6413 g_object_notify (G_OBJECT (old_focus), "is-focus");
6416 /* The above notifications may have set a new focus widget,
6417 * if so, we don't want to override it.
6419 if (focus && !priv->focus_widget)
6421 priv->focus_widget = focus;
6423 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6424 (priv->focus_widget != priv->default_widget))
6426 if (gtk_widget_get_can_default (priv->focus_widget))
6427 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6429 if (priv->default_widget)
6430 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6433 if (priv->has_focus)
6434 do_focus_change (priv->focus_widget, TRUE);
6436 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6439 /* If the default widget changed, a redraw will have been queued
6440 * on the old and new default widgets by gtk_window_set_default(), so
6441 * we only have to worry about the case where it didn't change.
6442 * We'll sometimes queue a draw twice on the new widget but that
6445 if (priv->default_widget &&
6446 (had_default != gtk_widget_has_default (priv->default_widget)))
6447 gtk_widget_queue_draw (priv->default_widget);
6451 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6452 gtk_widget_queue_draw (old_focus);
6454 g_object_thaw_notify (G_OBJECT (old_focus));
6455 g_object_unref (old_focus);
6459 if (focus_had_default != gtk_widget_has_default (focus))
6460 gtk_widget_queue_draw (focus);
6462 g_object_thaw_notify (G_OBJECT (focus));
6463 g_object_unref (focus);
6469 gtk_window_get_preferred_width (GtkWidget *widget,
6477 window = GTK_WINDOW (widget);
6478 child = gtk_bin_get_child (GTK_BIN (window));
6480 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6481 *minimum_size = border_width * 2;
6482 *natural_size = border_width * 2;
6484 if (child && gtk_widget_get_visible (child))
6486 gint child_min, child_nat;
6487 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6489 *minimum_size += child_min;
6490 *natural_size += child_nat;
6495 gtk_window_get_preferred_height (GtkWidget *widget,
6503 window = GTK_WINDOW (widget);
6504 child = gtk_bin_get_child (GTK_BIN (window));
6506 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6507 *minimum_size = border_width * 2;
6508 *natural_size = border_width * 2;
6510 if (child && gtk_widget_get_visible (child))
6512 gint child_min, child_nat;
6513 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6515 *minimum_size += child_min;
6516 *natural_size += child_nat;
6522 * _gtk_window_unset_focus_and_default:
6523 * @window: a #GtkWindow
6524 * @widget: a widget inside of @window
6526 * Checks whether the focus and default widgets of @window are
6527 * @widget or a descendent of @widget, and if so, unset them.
6530 _gtk_window_unset_focus_and_default (GtkWindow *window,
6534 GtkWindowPrivate *priv = window->priv;
6538 g_object_ref (window);
6539 g_object_ref (widget);
6541 parent = gtk_widget_get_parent (widget);
6542 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6544 child = priv->focus_widget;
6546 while (child && child != widget)
6547 child = gtk_widget_get_parent (child);
6549 if (child == widget)
6550 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6553 child = priv->default_widget;
6555 while (child && child != widget)
6556 child = gtk_widget_get_parent (child);
6558 if (child == widget)
6559 gtk_window_set_default (window, NULL);
6561 g_object_unref (widget);
6562 g_object_unref (window);
6565 /*********************************
6566 * Functions related to resizing *
6567 *********************************/
6570 geometry_size_to_pixels (GdkGeometry *geometry,
6575 gint base_width = 0;
6576 gint base_height = 0;
6578 gint min_height = 0;
6580 gint height_inc = 1;
6582 if (flags & GDK_HINT_BASE_SIZE)
6584 base_width = geometry->base_width;
6585 base_height = geometry->base_height;
6587 if (flags & GDK_HINT_MIN_SIZE)
6589 min_width = geometry->min_width;
6590 min_height = geometry->min_height;
6592 if (flags & GDK_HINT_RESIZE_INC)
6594 width_inc = geometry->width_inc;
6595 height_inc = geometry->height_inc;
6599 *width = MAX (*width * width_inc + base_width, min_width);
6601 *height = MAX (*height * height_inc + base_height, min_height);
6604 /* This function doesn't constrain to geometry hints */
6606 gtk_window_compute_configure_request_size (GtkWindow *window,
6607 GdkGeometry *geometry,
6612 GtkWindowPrivate *priv = window->priv;
6613 GtkWindowGeometryInfo *info;
6616 * - we've done a size request
6619 info = gtk_window_get_geometry_info (window, FALSE);
6621 if (priv->need_default_size)
6623 gtk_window_guess_default_size (window, width, height);
6625 /* If window is empty so requests 0, default to random nonzero size */
6626 if (*width == 0 && *height == 0)
6632 /* Override with default size */
6636 if (info->default_width > 0)
6637 *width = info->default_width;
6638 if (info->default_height > 0)
6639 *height = info->default_height;
6641 if (info->default_is_geometry)
6642 geometry_size_to_pixels (geometry, flags,
6643 info->default_width > 0 ? width : NULL,
6644 info->default_height > 0 ? height : NULL);
6649 GtkAllocation allocation;
6651 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6653 /* Default to keeping current size */
6654 *width = allocation.width;
6655 *height = allocation.height;
6658 /* Override any size with gtk_window_resize() values */
6661 if (info->resize_width > 0)
6662 *width = info->resize_width;
6663 if (info->resize_height > 0)
6664 *height = info->resize_height;
6666 if (info->resize_is_geometry)
6667 geometry_size_to_pixels (geometry, flags,
6668 info->resize_width > 0 ? width : NULL,
6669 info->resize_height > 0 ? height : NULL);
6672 /* Don't ever request zero width or height, its not supported by
6673 gdk. The size allocation code will round it to 1 anyway but if
6674 we do it then the value returned from this function will is
6675 not comparable to the size allocation read from the GtkWindow. */
6676 *width = MAX (*width, 1);
6677 *height = MAX (*height, 1);
6680 static GtkWindowPosition
6681 get_effective_position (GtkWindow *window)
6683 GtkWindowPrivate *priv = window->priv;
6684 GtkWindowPosition pos = priv->position;
6686 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6687 (priv->transient_parent == NULL ||
6688 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6689 pos = GTK_WIN_POS_NONE;
6695 get_center_monitor_of_window (GtkWindow *window)
6697 /* We could try to sort out the relative positions of the monitors and
6698 * stuff, or we could just be losers and assume you have a row
6699 * or column of monitors.
6701 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6705 get_monitor_containing_pointer (GtkWindow *window)
6709 GdkScreen *window_screen;
6710 GdkScreen *pointer_screen;
6711 GdkDisplay *display;
6712 GdkDeviceManager *device_manager;
6715 window_screen = gtk_window_check_screen (window);
6716 display = gdk_screen_get_display (window_screen);
6717 device_manager = gdk_display_get_device_manager (display);
6718 pointer = gdk_device_manager_get_client_pointer (device_manager);
6720 gdk_device_get_position (pointer,
6724 if (pointer_screen == window_screen)
6725 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6733 center_window_on_monitor (GtkWindow *window,
6739 GdkRectangle monitor;
6742 monitor_num = get_monitor_containing_pointer (window);
6744 if (monitor_num == -1)
6745 monitor_num = get_center_monitor_of_window (window);
6747 gdk_screen_get_monitor_workarea (gtk_window_check_screen (window),
6748 monitor_num, &monitor);
6750 *x = (monitor.width - w) / 2 + monitor.x;
6751 *y = (monitor.height - h) / 2 + monitor.y;
6753 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6754 * and WM decorations.
6768 if (extent > clamp_extent)
6770 *base = clamp_base + clamp_extent/2 - extent/2;
6771 else if (*base < clamp_base)
6773 else if (*base + extent > clamp_base + clamp_extent)
6774 *base = clamp_base + clamp_extent - extent;
6778 clamp_window_to_rectangle (gint *x,
6782 const GdkRectangle *rect)
6784 #ifdef DEBUGGING_OUTPUT
6785 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);
6788 /* If it is too large, center it. If it fits on the monitor but is
6789 * partially outside, move it to the closest edge. Do this
6790 * separately in x and y directions.
6792 clamp (x, w, rect->x, rect->width);
6793 clamp (y, h, rect->y, rect->height);
6794 #ifdef DEBUGGING_OUTPUT
6795 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6801 gtk_window_compute_configure_request (GtkWindow *window,
6802 GdkRectangle *request,
6803 GdkGeometry *geometry,
6806 GtkWindowPrivate *priv = window->priv;
6807 GdkGeometry new_geometry;
6810 GtkWindowPosition pos;
6811 GtkWidget *parent_widget;
6812 GtkWindowGeometryInfo *info;
6816 screen = gtk_window_check_screen (window);
6818 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6819 gtk_window_compute_configure_request_size (window,
6820 &new_geometry, new_flags,
6823 gtk_window_constrain_size (window,
6824 &new_geometry, new_flags,
6828 parent_widget = (GtkWidget*) priv->transient_parent;
6830 pos = get_effective_position (window);
6831 info = gtk_window_get_geometry_info (window, FALSE);
6833 /* by default, don't change position requested */
6836 x = info->last.configure_request.x;
6837 y = info->last.configure_request.y;
6846 if (priv->need_default_position)
6849 /* FIXME this all interrelates with window gravity.
6850 * For most of them I think we want to set GRAVITY_CENTER.
6852 * Not sure how to go about that.
6856 /* here we are only handling CENTER_ALWAYS
6857 * as it relates to default positioning,
6858 * where it's equivalent to simply CENTER
6860 case GTK_WIN_POS_CENTER_ALWAYS:
6861 case GTK_WIN_POS_CENTER:
6862 center_window_on_monitor (window, w, h, &x, &y);
6865 case GTK_WIN_POS_CENTER_ON_PARENT:
6867 GtkAllocation allocation;
6868 GdkWindow *gdk_window;
6870 GdkRectangle monitor;
6873 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6875 gdk_window = gtk_widget_get_window (parent_widget);
6877 if (gdk_window != NULL)
6878 monitor_num = gdk_screen_get_monitor_at_window (screen,
6883 gdk_window_get_origin (gdk_window,
6886 gtk_widget_get_allocation (parent_widget, &allocation);
6887 x = ox + (allocation.width - w) / 2;
6888 y = oy + (allocation.height - h) / 2;
6890 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6891 * WM decorations. If parent wasn't on a monitor, just
6894 if (monitor_num >= 0)
6896 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6897 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6902 case GTK_WIN_POS_MOUSE:
6904 gint screen_width = gdk_screen_get_width (screen);
6905 gint screen_height = gdk_screen_get_height (screen);
6907 GdkRectangle monitor;
6908 GdkDisplay *display;
6909 GdkDeviceManager *device_manager;
6911 GdkScreen *pointer_screen;
6914 display = gdk_screen_get_display (screen);
6915 device_manager = gdk_display_get_device_manager (display);
6916 pointer = gdk_device_manager_get_client_pointer (device_manager);
6918 gdk_device_get_position (pointer,
6922 if (pointer_screen == screen)
6923 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6929 x = CLAMP (x, 0, screen_width - w);
6930 y = CLAMP (y, 0, screen_height - h);
6932 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6933 * WM decorations. Don't try to figure out what's going
6934 * on if the mouse wasn't inside a monitor.
6936 if (monitor_num >= 0)
6938 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6939 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6947 } /* if (priv->need_default_position) */
6949 if (priv->need_default_position && info &&
6950 info->initial_pos_set)
6952 x = info->initial_x;
6953 y = info->initial_y;
6954 gtk_window_constrain_position (window, w, h, &x, &y);
6960 request->height = h;
6963 *geometry = new_geometry;
6969 gtk_window_constrain_position (GtkWindow *window,
6975 GtkWindowPrivate *priv = window->priv;
6977 /* See long comments in gtk_window_move_resize()
6978 * on when it's safe to call this function.
6980 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6982 gint center_x, center_y;
6984 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6992 gtk_window_move_resize (GtkWindow *window)
6996 * First we determine whether any information has changed that would
6997 * cause us to revise our last configure request. If we would send
6998 * a different configure request from last time, then
6999 * configure_request_size_changed = TRUE or
7000 * configure_request_pos_changed = TRUE. configure_request_size_changed
7001 * may be true due to new hints, a gtk_window_resize(), or whatever.
7002 * configure_request_pos_changed may be true due to gtk_window_set_position()
7003 * or gtk_window_move().
7005 * If the configure request has changed, we send off a new one. To
7006 * ensure GTK+ invariants are maintained (resize queue does what it
7007 * should), we go ahead and size_allocate the requested size in this
7010 * If the configure request has not changed, we don't ever resend
7011 * it, because it could mean fighting the user or window manager.
7014 * To prepare the configure request, we come up with a base size/pos:
7015 * - the one from gtk_window_move()/gtk_window_resize()
7016 * - else default_width, default_height if we haven't ever
7018 * - else the size request if we haven't ever been mapped,
7019 * as a substitute default size
7020 * - else the current size of the window, as received from
7021 * configure notifies (i.e. the current allocation)
7023 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
7024 * the position request to be centered.
7026 GtkWindowPrivate *priv = window->priv;
7027 GtkAllocation allocation;
7029 GtkContainer *container;
7030 GtkWindowGeometryInfo *info;
7031 GdkGeometry new_geometry;
7032 GdkWindow *gdk_window;
7034 GdkRectangle new_request;
7035 gboolean configure_request_size_changed;
7036 gboolean configure_request_pos_changed;
7037 gboolean hints_changed; /* do we need to send these again */
7038 GtkWindowLastGeometryInfo saved_last_info;
7040 widget = GTK_WIDGET (window);
7042 gdk_window = gtk_widget_get_window (widget);
7043 container = GTK_CONTAINER (widget);
7044 info = gtk_window_get_geometry_info (window, TRUE);
7046 configure_request_size_changed = FALSE;
7047 configure_request_pos_changed = FALSE;
7049 gtk_window_compute_configure_request (window, &new_request,
7050 &new_geometry, &new_flags);
7052 /* This check implies the invariant that we never set info->last
7053 * without setting the hints and sending off a configure request.
7055 * If we change info->last without sending the request, we may
7058 if (info->last.configure_request.x != new_request.x ||
7059 info->last.configure_request.y != new_request.y)
7060 configure_request_pos_changed = TRUE;
7062 if ((info->last.configure_request.width != new_request.width ||
7063 info->last.configure_request.height != new_request.height))
7064 configure_request_size_changed = TRUE;
7066 hints_changed = FALSE;
7068 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
7069 &new_geometry, new_flags))
7071 hints_changed = TRUE;
7074 /* Position Constraints
7075 * ====================
7077 * POS_CENTER_ALWAYS is conceptually a constraint rather than
7078 * a default. The other POS_ values are used only when the
7079 * window is shown, not after that.
7081 * However, we can't implement a position constraint as
7082 * "anytime the window size changes, center the window"
7083 * because this may well end up fighting the WM or user. In
7084 * fact it gets in an infinite loop with at least one WM.
7086 * Basically, applications are in no way in a position to
7087 * constrain the position of a window, with one exception:
7088 * override redirect windows. (Really the intended purpose
7089 * of CENTER_ALWAYS anyhow, I would think.)
7091 * So the way we implement this "constraint" is to say that when WE
7092 * cause a move or resize, i.e. we make a configure request changing
7093 * window size, we recompute the CENTER_ALWAYS position to reflect
7094 * the new window size, and include it in our request. Also, if we
7095 * just turned on CENTER_ALWAYS we snap to center with a new
7096 * request. Otherwise, if we are just NOTIFIED of a move or resize
7097 * done by someone else e.g. the window manager, we do NOT send a
7098 * new configure request.
7100 * For override redirect windows, this works fine; all window
7101 * sizes are from our configure requests. For managed windows,
7102 * it is at least semi-sane, though who knows what the
7103 * app author is thinking.
7106 /* This condition should be kept in sync with the condition later on
7107 * that determines whether we send a configure request. i.e. we
7108 * should do this position constraining anytime we were going to
7109 * send a configure request anyhow, plus when constraints have
7112 if (configure_request_pos_changed ||
7113 configure_request_size_changed ||
7115 info->position_constraints_changed)
7117 /* We request the constrained position if:
7118 * - we were changing position, and need to clamp
7119 * the change to the constraint
7120 * - we're changing the size anyway
7121 * - set_position() was called to toggle CENTER_ALWAYS on
7124 gtk_window_constrain_position (window,
7130 /* Update whether we need to request a move */
7131 if (info->last.configure_request.x != new_request.x ||
7132 info->last.configure_request.y != new_request.y)
7133 configure_request_pos_changed = TRUE;
7135 configure_request_pos_changed = FALSE;
7139 if (priv->type == GTK_WINDOW_TOPLEVEL)
7141 int notify_x, notify_y;
7143 /* this is the position from the last configure notify */
7144 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
7146 g_message ("--- %s ---\n"
7147 "last : %d,%d\t%d x %d\n"
7148 "this : %d,%d\t%d x %d\n"
7149 "alloc : %d,%d\t%d x %d\n"
7151 "resize: \t%d x %d\n"
7152 "size_changed: %d pos_changed: %d hints_changed: %d\n"
7153 "configure_notify_received: %d\n"
7154 "configure_request_count: %d\n"
7155 "position_constraints_changed: %d\n",
7156 priv->title ? priv->title : "(no title)",
7157 info->last.configure_request.x,
7158 info->last.configure_request.y,
7159 info->last.configure_request.width,
7160 info->last.configure_request.height,
7166 widget->allocation.width,
7167 widget->allocation.height,
7168 widget->requisition.width,
7169 widget->requisition.height,
7171 info->resize_height,
7172 configure_request_pos_changed,
7173 configure_request_size_changed,
7175 priv->configure_notify_received,
7176 priv->configure_request_count,
7177 info->position_constraints_changed);
7181 saved_last_info = info->last;
7182 info->last.geometry = new_geometry;
7183 info->last.flags = new_flags;
7184 info->last.configure_request = new_request;
7186 /* need to set PPosition so the WM will look at our position,
7187 * but we don't want to count PPosition coming and going as a hints
7188 * change for future iterations. So we saved info->last prior to
7192 /* Also, if the initial position was explicitly set, then we always
7193 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
7197 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
7198 * this is an initial map
7201 if ((configure_request_pos_changed ||
7202 info->initial_pos_set ||
7203 (priv->need_default_position &&
7204 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
7205 (new_flags & GDK_HINT_POS) == 0)
7207 new_flags |= GDK_HINT_POS;
7208 hints_changed = TRUE;
7211 /* Set hints if necessary
7214 gdk_window_set_geometry_hints (gdk_window,
7218 gtk_widget_get_allocation (widget, &allocation);
7220 /* handle resizing/moving and widget tree allocation
7222 if (priv->configure_notify_received)
7224 /* If we have received a configure event since
7225 * the last time in this function, we need to
7226 * accept our new size and size_allocate child widgets.
7227 * (see gtk_window_configure_event() for more details).
7229 * 1 or more configure notifies may have been received.
7230 * Also, configure_notify_received will only be TRUE
7231 * if all expected configure notifies have been received
7232 * (one per configure request), as an optimization.
7235 priv->configure_notify_received = FALSE;
7237 /* gtk_window_configure_event() filled in widget->allocation */
7238 gtk_widget_size_allocate (widget, &allocation);
7240 set_grip_position (window);
7241 update_grip_visibility (window);
7243 gdk_window_process_updates (gdk_window, TRUE);
7245 gdk_window_configure_finished (gdk_window);
7247 /* If the configure request changed, it means that
7249 * 1) coincidentally changed hints or widget properties
7250 * impacting the configure request before getting
7251 * a configure notify, or
7252 * 2) some broken widget is changing its size request
7253 * during size allocation, resulting in
7254 * a false appearance of changed configure request.
7256 * For 1), we could just go ahead and ask for the
7257 * new size right now, but doing that for 2)
7258 * might well be fighting the user (and can even
7259 * trigger a loop). Since we really don't want to
7260 * do that, we requeue a resize in hopes that
7261 * by the time it gets handled, the child has seen
7262 * the light and is willing to go along with the
7263 * new size. (this happens for the zvt widget, since
7264 * the size_allocate() above will have stored the
7265 * requisition corresponding to the new size in the
7268 * This doesn't buy us anything for 1), but it shouldn't
7269 * hurt us too badly, since it is what would have
7270 * happened if we had gotten the configure event before
7271 * the new size had been set.
7274 if (configure_request_size_changed ||
7275 configure_request_pos_changed)
7277 /* Don't change the recorded last info after all, because we
7278 * haven't actually updated to the new info yet - we decided
7279 * to postpone our configure request until later.
7281 info->last = saved_last_info;
7283 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7286 return; /* Bail out, we didn't really process the move/resize */
7288 else if ((configure_request_size_changed || hints_changed) &&
7289 (allocation.width != new_request.width || allocation.height != new_request.height))
7292 /* We are in one of the following situations:
7293 * A. configure_request_size_changed
7294 * our requisition has changed and we need a different window size,
7295 * so we request it from the window manager.
7296 * B. !configure_request_size_changed && hints_changed
7297 * the window manager rejects our size, but we have just changed the
7298 * window manager hints, so there's a chance our request will
7299 * be honoured this time, so we try again.
7301 * However, if the new requisition is the same as the current allocation,
7302 * we don't request it again, since we won't get a ConfigureNotify back from
7303 * the window manager unless it decides to change our requisition. If
7304 * we don't get the ConfigureNotify back, the resize queue will never be run.
7307 /* Now send the configure request */
7308 if (configure_request_pos_changed)
7310 gdk_window_move_resize (gdk_window,
7311 new_request.x, new_request.y,
7312 new_request.width, new_request.height);
7314 else /* only size changed */
7316 gdk_window_resize (gdk_window,
7317 new_request.width, new_request.height);
7320 if (priv->type == GTK_WINDOW_POPUP)
7322 GtkAllocation allocation;
7324 /* Directly size allocate for override redirect (popup) windows. */
7327 allocation.width = new_request.width;
7328 allocation.height = new_request.height;
7330 gtk_widget_size_allocate (widget, &allocation);
7332 gdk_window_process_updates (gdk_window, TRUE);
7334 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7335 gtk_widget_queue_draw (widget);
7339 /* Increment the number of have-not-yet-received-notify requests */
7340 priv->configure_request_count += 1;
7341 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7343 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7344 * configure event in response to our resizing request.
7345 * the configure event will cause a new resize with
7346 * ->configure_notify_received=TRUE.
7347 * until then, we want to
7348 * - discard expose events
7349 * - coalesce resizes for our children
7350 * - defer any window resizes until the configure event arrived
7351 * to achieve this, we queue a resize for the window, but remove its
7352 * resizing handler, so resizing will not be handled from the next
7353 * idle handler but when the configure event arrives.
7355 * FIXME: we should also dequeue the pending redraws here, since
7356 * we handle those ourselves upon ->configure_notify_received==TRUE.
7358 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7360 gtk_widget_queue_resize_no_redraw (widget);
7361 _gtk_container_dequeue_resize_handler (container);
7367 /* Handle any position changes.
7369 if (configure_request_pos_changed)
7371 gdk_window_move (gdk_window,
7372 new_request.x, new_request.y);
7375 /* And run the resize queue.
7377 gtk_container_resize_children (container);
7380 /* We have now processed a move/resize since the last position
7381 * constraint change, setting of the initial position, or resize.
7382 * (Not resetting these flags here can lead to infinite loops for
7383 * GTK_RESIZE_IMMEDIATE containers)
7385 info->position_constraints_changed = FALSE;
7386 info->initial_pos_set = FALSE;
7387 info->resize_width = -1;
7388 info->resize_height = -1;
7391 /* Compare two sets of Geometry hints for equality.
7394 gtk_window_compare_hints (GdkGeometry *geometry_a,
7396 GdkGeometry *geometry_b,
7399 if (flags_a != flags_b)
7402 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7403 (geometry_a->min_width != geometry_b->min_width ||
7404 geometry_a->min_height != geometry_b->min_height))
7407 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7408 (geometry_a->max_width != geometry_b->max_width ||
7409 geometry_a->max_height != geometry_b->max_height))
7412 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7413 (geometry_a->base_width != geometry_b->base_width ||
7414 geometry_a->base_height != geometry_b->base_height))
7417 if ((flags_a & GDK_HINT_ASPECT) &&
7418 (geometry_a->min_aspect != geometry_b->min_aspect ||
7419 geometry_a->max_aspect != geometry_b->max_aspect))
7422 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7423 (geometry_a->width_inc != geometry_b->width_inc ||
7424 geometry_a->height_inc != geometry_b->height_inc))
7427 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7428 geometry_a->win_gravity != geometry_b->win_gravity)
7435 _gtk_window_constrain_size (GtkWindow *window,
7441 GtkWindowPrivate *priv;
7442 GtkWindowGeometryInfo *info;
7444 g_return_if_fail (GTK_IS_WINDOW (window));
7446 priv = window->priv;
7448 info = priv->geometry_info;
7451 GdkWindowHints flags = info->last.flags;
7452 GdkGeometry *geometry = &info->last.geometry;
7454 gtk_window_constrain_size (window,
7465 gtk_window_constrain_size (GtkWindow *window,
7466 GdkGeometry *geometry,
7473 gdk_window_constrain_size (geometry, flags, width, height,
7474 new_width, new_height);
7477 /* Compute the set of geometry hints and flags for a window
7478 * based on the application set geometry, and requisition
7479 * of the window. gtk_widget_get_preferred_size() must have been
7483 gtk_window_compute_hints (GtkWindow *window,
7484 GdkGeometry *new_geometry,
7487 GtkWindowPrivate *priv = window->priv;
7489 gint extra_width = 0;
7490 gint extra_height = 0;
7491 GtkWindowGeometryInfo *geometry_info;
7492 GtkRequisition requisition;
7494 widget = GTK_WIDGET (window);
7496 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7497 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7501 *new_flags = geometry_info->mask;
7502 *new_geometry = geometry_info->geometry;
7509 if (geometry_info && geometry_info->widget)
7511 /* If the geometry widget is set, then the hints really apply to that
7512 * widget. This is pretty much meaningless unless the window layout
7513 * is such that the rest of the window adds fixed size borders to
7514 * the geometry widget. Our job is to figure the size of the borders;
7515 * We do that by asking how big the toplevel would be if the
7516 * geometry widget was *really big*.
7519 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7520 * |GGGGG B| in the border can confuse things
7526 * |AAAAAAAAA | When the geometry widget is large, things are
7527 * |GGGGGGGGGGB| clearer.
7532 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7533 GtkRequisition requisition;
7534 int current_width, current_height;
7536 _gtk_widget_override_size_request (geometry_info->widget,
7537 TEMPORARY_SIZE, TEMPORARY_SIZE,
7538 ¤t_width, ¤t_height);
7539 gtk_widget_get_preferred_size (widget,
7540 &requisition, NULL);
7541 _gtk_widget_restore_size_request (geometry_info->widget,
7542 current_width, current_height);
7544 extra_width = requisition.width - TEMPORARY_SIZE;
7545 extra_height = requisition.height - TEMPORARY_SIZE;
7547 if (extra_width < 0 || extra_height < 0)
7549 g_warning("Toplevel size doesn't seem to directly depend on the "
7550 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7551 "The geometry widget might not be in the window, or it might not "
7552 "be packed into the window appropriately");
7553 extra_width = MAX(extra_width, 0);
7554 extra_height = MAX(extra_height, 0);
7556 #undef TEMPORARY_SIZE
7559 /* We don't want to set GDK_HINT_POS in here, we just set it
7560 * in gtk_window_move_resize() when we want the position
7564 if (*new_flags & GDK_HINT_BASE_SIZE)
7566 new_geometry->base_width += extra_width;
7567 new_geometry->base_height += extra_height;
7571 /* For simplicity, we always set the base hint, even when we
7572 * don't expect it to have any visible effect.
7573 * (Note: geometry_size_to_pixels() depends on this.)
7575 *new_flags |= GDK_HINT_BASE_SIZE;
7577 new_geometry->base_width = extra_width;
7578 new_geometry->base_height = extra_height;
7580 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7581 * base size is the minimum size */
7582 if (*new_flags & GDK_HINT_MIN_SIZE)
7584 if (new_geometry->min_width > 0)
7585 new_geometry->base_width += new_geometry->min_width;
7586 if (new_geometry->min_height > 0)
7587 new_geometry->base_height += new_geometry->min_height;
7591 /* Please use a good size for unresizable widgets, not the minimum one. */
7592 if (!priv->resizable)
7593 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7595 if (*new_flags & GDK_HINT_MIN_SIZE)
7597 if (new_geometry->min_width < 0)
7598 new_geometry->min_width = requisition.width;
7600 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7602 if (new_geometry->min_height < 0)
7603 new_geometry->min_height = requisition.height;
7605 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7609 *new_flags |= GDK_HINT_MIN_SIZE;
7611 new_geometry->min_width = requisition.width;
7612 new_geometry->min_height = requisition.height;
7615 if (*new_flags & GDK_HINT_MAX_SIZE)
7617 if (new_geometry->max_width < 0)
7618 new_geometry->max_width = requisition.width;
7620 new_geometry->max_width += extra_width;
7622 if (new_geometry->max_height < 0)
7623 new_geometry->max_height = requisition.height;
7625 new_geometry->max_height += extra_height;
7627 else if (!priv->resizable)
7629 *new_flags |= GDK_HINT_MAX_SIZE;
7631 new_geometry->max_width = requisition.width;
7632 new_geometry->max_height = requisition.height;
7635 *new_flags |= GDK_HINT_WIN_GRAVITY;
7636 new_geometry->win_gravity = priv->gravity;
7639 /***********************
7640 * Redrawing functions *
7641 ***********************/
7644 gtk_window_draw (GtkWidget *widget,
7647 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7648 GtkStyleContext *context;
7649 gboolean ret = FALSE;
7651 context = gtk_widget_get_style_context (widget);
7653 if (!gtk_widget_get_app_paintable (widget) &&
7654 gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
7656 gtk_style_context_save (context);
7658 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7659 gtk_render_background (context, cr, 0, 0,
7660 gtk_widget_get_allocated_width (widget),
7661 gtk_widget_get_allocated_height (widget));
7663 gtk_style_context_restore (context);
7666 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7667 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7669 if (priv->grip_window &&
7670 gtk_cairo_should_draw_window (cr, priv->grip_window))
7674 gtk_style_context_save (context);
7677 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7678 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7680 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7681 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7682 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7685 gtk_style_context_restore (context);
7692 * gtk_window_present:
7693 * @window: a #GtkWindow
7695 * Presents a window to the user. This may mean raising the window
7696 * in the stacking order, deiconifying it, moving it to the current
7697 * desktop, and/or giving it the keyboard focus, possibly dependent
7698 * on the user's platform, window manager, and preferences.
7700 * If @window is hidden, this function calls gtk_widget_show()
7703 * This function should be used when the user tries to open a window
7704 * that's already open. Say for example the preferences dialog is
7705 * currently open, and the user chooses Preferences from the menu
7706 * a second time; use gtk_window_present() to move the already-open dialog
7707 * where the user can see it.
7709 * If you are calling this function in response to a user interaction,
7710 * it is preferable to use gtk_window_present_with_time().
7714 gtk_window_present (GtkWindow *window)
7716 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7720 * gtk_window_present_with_time:
7721 * @window: a #GtkWindow
7722 * @timestamp: the timestamp of the user interaction (typically a
7723 * button or key press event) which triggered this call
7725 * Presents a window to the user in response to a user interaction.
7726 * If you need to present a window without a timestamp, use
7727 * gtk_window_present(). See gtk_window_present() for details.
7732 gtk_window_present_with_time (GtkWindow *window,
7735 GtkWindowPrivate *priv;
7737 GdkWindow *gdk_window;
7739 g_return_if_fail (GTK_IS_WINDOW (window));
7741 priv = window->priv;
7742 widget = GTK_WIDGET (window);
7744 if (gtk_widget_get_visible (widget))
7746 gdk_window = gtk_widget_get_window (widget);
7748 g_assert (gdk_window != NULL);
7750 gdk_window_show (gdk_window);
7752 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7753 if (timestamp == GDK_CURRENT_TIME)
7755 #ifdef GDK_WINDOWING_X11
7756 if (GDK_IS_X11_WINDOW(gdk_window))
7758 GdkDisplay *display;
7760 display = gtk_widget_get_display (GTK_WIDGET (window));
7761 timestamp = gdk_x11_display_get_user_time (display);
7765 timestamp = gtk_get_current_event_time ();
7768 gdk_window_focus (gdk_window, timestamp);
7772 priv->initial_timestamp = timestamp;
7773 gtk_widget_show (widget);
7778 * gtk_window_iconify:
7779 * @window: a #GtkWindow
7781 * Asks to iconify (i.e. minimize) the specified @window. Note that
7782 * you shouldn't assume the window is definitely iconified afterward,
7783 * because other entities (e.g. the user or <link
7784 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7785 * again, or there may not be a window manager in which case
7786 * iconification isn't possible, etc. But normally the window will end
7787 * up iconified. Just don't write code that crashes if not.
7789 * It's permitted to call this function before showing a window,
7790 * in which case the window will be iconified before it ever appears
7793 * You can track iconification via the "window-state-event" signal
7798 gtk_window_iconify (GtkWindow *window)
7800 GtkWindowPrivate *priv;
7802 GdkWindow *toplevel;
7804 g_return_if_fail (GTK_IS_WINDOW (window));
7806 priv = window->priv;
7807 widget = GTK_WIDGET (window);
7809 priv->iconify_initially = TRUE;
7811 toplevel = gtk_widget_get_window (widget);
7813 if (toplevel != NULL)
7814 gdk_window_iconify (toplevel);
7818 * gtk_window_deiconify:
7819 * @window: a #GtkWindow
7821 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7822 * that you shouldn't assume the window is definitely deiconified
7823 * afterward, because other entities (e.g. the user or <link
7824 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7825 * again before your code which assumes deiconification gets to run.
7827 * You can track iconification via the "window-state-event" signal
7831 gtk_window_deiconify (GtkWindow *window)
7833 GtkWindowPrivate *priv;
7835 GdkWindow *toplevel;
7837 g_return_if_fail (GTK_IS_WINDOW (window));
7839 priv = window->priv;
7840 widget = GTK_WIDGET (window);
7842 priv->iconify_initially = FALSE;
7844 toplevel = gtk_widget_get_window (widget);
7846 if (toplevel != NULL)
7847 gdk_window_deiconify (toplevel);
7852 * @window: a #GtkWindow
7854 * Asks to stick @window, which means that it will appear on all user
7855 * desktops. Note that you shouldn't assume the window is definitely
7856 * stuck afterward, because other entities (e.g. the user or <link
7857 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7858 * again, and some window managers do not support sticking
7859 * windows. But normally the window will end up stuck. Just don't
7860 * write code that crashes if not.
7862 * It's permitted to call this function before showing a window.
7864 * You can track stickiness via the "window-state-event" signal
7869 gtk_window_stick (GtkWindow *window)
7871 GtkWindowPrivate *priv;
7873 GdkWindow *toplevel;
7875 g_return_if_fail (GTK_IS_WINDOW (window));
7877 priv = window->priv;
7878 widget = GTK_WIDGET (window);
7880 priv->stick_initially = TRUE;
7882 toplevel = gtk_widget_get_window (widget);
7884 if (toplevel != NULL)
7885 gdk_window_stick (toplevel);
7889 * gtk_window_unstick:
7890 * @window: a #GtkWindow
7892 * Asks to unstick @window, which means that it will appear on only
7893 * one of the user's desktops. Note that you shouldn't assume the
7894 * window is definitely unstuck afterward, because other entities
7895 * (e.g. the user or <link linkend="gtk-X11-arch">window
7896 * manager</link>) could stick it again. But normally the window will
7897 * end up stuck. Just don't write code that crashes if not.
7899 * You can track stickiness via the "window-state-event" signal
7904 gtk_window_unstick (GtkWindow *window)
7906 GtkWindowPrivate *priv;
7908 GdkWindow *toplevel;
7910 g_return_if_fail (GTK_IS_WINDOW (window));
7912 priv = window->priv;
7913 widget = GTK_WIDGET (window);
7915 priv->stick_initially = FALSE;
7917 toplevel = gtk_widget_get_window (widget);
7919 if (toplevel != NULL)
7920 gdk_window_unstick (toplevel);
7924 * gtk_window_maximize:
7925 * @window: a #GtkWindow
7927 * Asks to maximize @window, so that it becomes full-screen. Note that
7928 * you shouldn't assume the window is definitely maximized afterward,
7929 * because other entities (e.g. the user or <link
7930 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7931 * again, and not all window managers support maximization. But
7932 * normally the window will end up maximized. Just don't write code
7933 * that crashes if not.
7935 * It's permitted to call this function before showing a window,
7936 * in which case the window will be maximized when it appears onscreen
7939 * You can track maximization via the "window-state-event" signal
7944 gtk_window_maximize (GtkWindow *window)
7946 GtkWindowPrivate *priv;
7948 GdkWindow *toplevel;
7950 g_return_if_fail (GTK_IS_WINDOW (window));
7952 priv = window->priv;
7953 widget = GTK_WIDGET (window);
7955 priv->maximize_initially = TRUE;
7957 toplevel = gtk_widget_get_window (widget);
7959 if (toplevel != NULL)
7960 gdk_window_maximize (toplevel);
7964 * gtk_window_unmaximize:
7965 * @window: a #GtkWindow
7967 * Asks to unmaximize @window. Note that you shouldn't assume the
7968 * window is definitely unmaximized afterward, because other entities
7969 * (e.g. the user or <link linkend="gtk-X11-arch">window
7970 * manager</link>) could maximize it again, and not all window
7971 * managers honor requests to unmaximize. But normally the window will
7972 * end up unmaximized. Just don't write code that crashes if not.
7974 * You can track maximization via the "window-state-event" signal
7979 gtk_window_unmaximize (GtkWindow *window)
7981 GtkWindowPrivate *priv;
7983 GdkWindow *toplevel;
7985 g_return_if_fail (GTK_IS_WINDOW (window));
7987 priv = window->priv;
7988 widget = GTK_WIDGET (window);
7990 priv->maximize_initially = FALSE;
7992 toplevel = gtk_widget_get_window (widget);
7994 if (toplevel != NULL)
7995 gdk_window_unmaximize (toplevel);
7999 * gtk_window_fullscreen:
8000 * @window: a #GtkWindow
8002 * Asks to place @window in the fullscreen state. Note that you
8003 * shouldn't assume the window is definitely full screen afterward,
8004 * because other entities (e.g. the user or <link
8005 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
8006 * again, and not all window managers honor requests to fullscreen
8007 * windows. But normally the window will end up fullscreen. Just
8008 * don't write code that crashes if not.
8010 * You can track the fullscreen state via the "window-state-event" signal
8016 gtk_window_fullscreen (GtkWindow *window)
8018 GtkWindowPrivate *priv;
8020 GdkWindow *toplevel;
8022 g_return_if_fail (GTK_IS_WINDOW (window));
8024 priv = window->priv;
8025 widget = GTK_WIDGET (window);
8027 priv->fullscreen_initially = TRUE;
8029 toplevel = gtk_widget_get_window (widget);
8031 if (toplevel != NULL)
8032 gdk_window_fullscreen (toplevel);
8036 * gtk_window_unfullscreen:
8037 * @window: a #GtkWindow
8039 * Asks to toggle off the fullscreen state for @window. Note that you
8040 * shouldn't assume the window is definitely not full screen
8041 * afterward, because other entities (e.g. the user or <link
8042 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
8043 * again, and not all window managers honor requests to unfullscreen
8044 * windows. But normally the window will end up restored to its normal
8045 * state. Just don't write code that crashes if not.
8047 * You can track the fullscreen state via the "window-state-event" signal
8053 gtk_window_unfullscreen (GtkWindow *window)
8056 GdkWindow *toplevel;
8057 GtkWindowPrivate *priv;
8059 g_return_if_fail (GTK_IS_WINDOW (window));
8061 priv = window->priv;
8062 widget = GTK_WIDGET (window);
8064 priv->fullscreen_initially = FALSE;
8066 toplevel = gtk_widget_get_window (widget);
8068 if (toplevel != NULL)
8069 gdk_window_unfullscreen (toplevel);
8073 * gtk_window_set_keep_above:
8074 * @window: a #GtkWindow
8075 * @setting: whether to keep @window above other windows
8077 * Asks to keep @window above, so that it stays on top. Note that
8078 * you shouldn't assume the window is definitely above afterward,
8079 * because other entities (e.g. the user or <link
8080 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
8081 * and not all window managers support keeping windows above. But
8082 * normally the window will end kept above. Just don't write code
8083 * that crashes if not.
8085 * It's permitted to call this function before showing a window,
8086 * in which case the window will be kept above when it appears onscreen
8089 * You can track the above state via the "window-state-event" signal
8092 * Note that, according to the <ulink
8093 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8094 * Manager Hints</ulink> specification, the above state is mainly meant
8095 * for user preferences and should not be used by applications e.g. for
8096 * drawing attention to their dialogs.
8101 gtk_window_set_keep_above (GtkWindow *window,
8105 GtkWindowPrivate *priv;
8106 GdkWindow *toplevel;
8108 g_return_if_fail (GTK_IS_WINDOW (window));
8110 priv = window->priv;
8111 widget = GTK_WIDGET (window);
8113 priv->above_initially = setting != FALSE;
8115 priv->below_initially = FALSE;
8117 toplevel = gtk_widget_get_window (widget);
8119 if (toplevel != NULL)
8120 gdk_window_set_keep_above (toplevel, setting);
8124 * gtk_window_set_keep_below:
8125 * @window: a #GtkWindow
8126 * @setting: whether to keep @window below other windows
8128 * Asks to keep @window below, so that it stays in bottom. Note that
8129 * you shouldn't assume the window is definitely below afterward,
8130 * because other entities (e.g. the user or <link
8131 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8132 * and not all window managers support putting windows below. But
8133 * normally the window will be kept below. Just don't write code
8134 * that crashes if not.
8136 * It's permitted to call this function before showing a window,
8137 * in which case the window will be kept below when it appears onscreen
8140 * You can track the below state via the "window-state-event" signal
8143 * Note that, according to the <ulink
8144 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8145 * Manager Hints</ulink> specification, the above state is mainly meant
8146 * for user preferences and should not be used by applications e.g. for
8147 * drawing attention to their dialogs.
8152 gtk_window_set_keep_below (GtkWindow *window,
8156 GtkWindowPrivate *priv;
8157 GdkWindow *toplevel;
8159 g_return_if_fail (GTK_IS_WINDOW (window));
8161 priv = window->priv;
8162 widget = GTK_WIDGET (window);
8164 priv->below_initially = setting != FALSE;
8166 priv->above_initially = FALSE;
8168 toplevel = gtk_widget_get_window (widget);
8170 if (toplevel != NULL)
8171 gdk_window_set_keep_below (toplevel, setting);
8175 * gtk_window_set_resizable:
8176 * @window: a #GtkWindow
8177 * @resizable: %TRUE if the user can resize this window
8179 * Sets whether the user can resize a window. Windows are user resizable
8183 gtk_window_set_resizable (GtkWindow *window,
8186 GtkWindowPrivate *priv;
8188 g_return_if_fail (GTK_IS_WINDOW (window));
8190 priv = window->priv;
8192 resizable = (resizable != FALSE);
8194 if (priv->resizable != resizable)
8196 priv->resizable = (resizable != FALSE);
8198 update_grip_visibility (window);
8200 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8202 g_object_notify (G_OBJECT (window), "resizable");
8207 * gtk_window_get_resizable:
8208 * @window: a #GtkWindow
8210 * Gets the value set by gtk_window_set_resizable().
8212 * Return value: %TRUE if the user can resize the window
8215 gtk_window_get_resizable (GtkWindow *window)
8217 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8219 return window->priv->resizable;
8223 * gtk_window_set_gravity:
8224 * @window: a #GtkWindow
8225 * @gravity: window gravity
8227 * Window gravity defines the meaning of coordinates passed to
8228 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8231 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8232 * typically "do what you mean."
8236 gtk_window_set_gravity (GtkWindow *window,
8239 GtkWindowPrivate *priv;
8241 g_return_if_fail (GTK_IS_WINDOW (window));
8243 priv = window->priv;
8245 if (gravity != priv->gravity)
8247 priv->gravity = gravity;
8249 /* gtk_window_move_resize() will adapt gravity
8251 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8253 g_object_notify (G_OBJECT (window), "gravity");
8258 * gtk_window_get_gravity:
8259 * @window: a #GtkWindow
8261 * Gets the value set by gtk_window_set_gravity().
8263 * Return value: (transfer none): window gravity
8266 gtk_window_get_gravity (GtkWindow *window)
8268 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8270 return window->priv->gravity;
8274 * gtk_window_begin_resize_drag:
8275 * @window: a #GtkWindow
8276 * @button: mouse button that initiated the drag
8277 * @edge: position of the resize control
8278 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8279 * @root_y: Y position where the user clicked to initiate the drag
8280 * @timestamp: timestamp from the click event that initiated the drag
8282 * Starts resizing a window. This function is used if an application
8283 * has window resizing controls. When GDK can support it, the resize
8284 * will be done using the standard mechanism for the <link
8285 * linkend="gtk-X11-arch">window manager</link> or windowing
8286 * system. Otherwise, GDK will try to emulate window resizing,
8287 * potentially not all that well, depending on the windowing system.
8291 gtk_window_begin_resize_drag (GtkWindow *window,
8299 GdkWindow *toplevel;
8301 g_return_if_fail (GTK_IS_WINDOW (window));
8302 widget = GTK_WIDGET (window);
8303 g_return_if_fail (gtk_widget_get_visible (widget));
8305 toplevel = gtk_widget_get_window (widget);
8307 gdk_window_begin_resize_drag (toplevel,
8314 * gtk_window_begin_move_drag:
8315 * @window: a #GtkWindow
8316 * @button: mouse button that initiated the drag
8317 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8318 * @root_y: Y position where the user clicked to initiate the drag
8319 * @timestamp: timestamp from the click event that initiated the drag
8321 * Starts moving a window. This function is used if an application has
8322 * window movement grips. When GDK can support it, the window movement
8323 * will be done using the standard mechanism for the <link
8324 * linkend="gtk-X11-arch">window manager</link> or windowing
8325 * system. Otherwise, GDK will try to emulate window movement,
8326 * potentially not all that well, depending on the windowing system.
8330 gtk_window_begin_move_drag (GtkWindow *window,
8337 GdkWindow *toplevel;
8339 g_return_if_fail (GTK_IS_WINDOW (window));
8340 widget = GTK_WIDGET (window);
8341 g_return_if_fail (gtk_widget_get_visible (widget));
8343 toplevel = gtk_widget_get_window (widget);
8345 gdk_window_begin_move_drag (toplevel,
8352 * gtk_window_set_screen:
8353 * @window: a #GtkWindow.
8354 * @screen: a #GdkScreen.
8356 * Sets the #GdkScreen where the @window is displayed; if
8357 * the window is already mapped, it will be unmapped, and
8358 * then remapped on the new screen.
8363 gtk_window_set_screen (GtkWindow *window,
8366 GtkWindowPrivate *priv;
8368 GdkScreen *previous_screen;
8369 gboolean was_mapped;
8371 g_return_if_fail (GTK_IS_WINDOW (window));
8372 g_return_if_fail (GDK_IS_SCREEN (screen));
8374 priv = window->priv;
8376 if (screen == priv->screen)
8379 widget = GTK_WIDGET (window);
8381 previous_screen = priv->screen;
8382 was_mapped = gtk_widget_get_mapped (widget);
8385 gtk_widget_unmap (widget);
8386 if (gtk_widget_get_realized (widget))
8387 gtk_widget_unrealize (widget);
8389 gtk_window_free_key_hash (window);
8390 priv->screen = screen;
8391 gtk_widget_reset_rc_styles (widget);
8392 if (screen != previous_screen)
8394 if (previous_screen)
8396 g_signal_handlers_disconnect_by_func (previous_screen,
8397 gtk_window_on_composited_changed, window);
8398 #ifdef GDK_WINDOWING_X11
8399 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8400 gtk_window_on_theme_variant_changed, window);
8403 g_signal_connect (screen, "composited-changed",
8404 G_CALLBACK (gtk_window_on_composited_changed), window);
8405 #ifdef GDK_WINDOWING_X11
8406 g_signal_connect (gtk_settings_get_for_screen (screen),
8407 "notify::gtk-application-prefer-dark-theme",
8408 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8411 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8412 _gtk_widget_propagate_composited_changed (widget);
8414 g_object_notify (G_OBJECT (window), "screen");
8417 gtk_widget_map (widget);
8421 gtk_window_set_theme_variant (GtkWindow *window)
8423 #ifdef GDK_WINDOWING_X11
8424 GdkWindow *gdk_window;
8425 gboolean dark_theme_requested;
8427 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8428 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8431 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8433 if (GDK_IS_X11_WINDOW (gdk_window))
8434 gdk_x11_window_set_theme_variant (gdk_window,
8435 dark_theme_requested ? "dark" : NULL);
8440 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8444 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8445 gtk_window_set_theme_variant (window);
8449 gtk_window_on_composited_changed (GdkScreen *screen,
8452 gtk_widget_queue_draw (GTK_WIDGET (window));
8454 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8458 gtk_window_check_screen (GtkWindow *window)
8460 GtkWindowPrivate *priv = window->priv;
8463 return priv->screen;
8466 g_warning ("Screen for GtkWindow not set; you must always set\n"
8467 "a screen for a GtkWindow before using the window");
8473 * gtk_window_get_screen:
8474 * @window: a #GtkWindow.
8476 * Returns the #GdkScreen associated with @window.
8478 * Return value: (transfer none): a #GdkScreen.
8483 gtk_window_get_screen (GtkWindow *window)
8485 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8487 return window->priv->screen;
8491 * gtk_window_is_active:
8492 * @window: a #GtkWindow
8494 * Returns whether the window is part of the current active toplevel.
8495 * (That is, the toplevel window receiving keystrokes.)
8496 * The return value is %TRUE if the window is active toplevel
8497 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8498 * You might use this function if you wanted to draw a widget
8499 * differently in an active window from a widget in an inactive window.
8500 * See gtk_window_has_toplevel_focus()
8502 * Return value: %TRUE if the window part of the current active window.
8507 gtk_window_is_active (GtkWindow *window)
8509 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8511 return window->priv->is_active;
8515 * gtk_window_has_toplevel_focus:
8516 * @window: a #GtkWindow
8518 * Returns whether the input focus is within this GtkWindow.
8519 * For real toplevel windows, this is identical to gtk_window_is_active(),
8520 * but for embedded windows, like #GtkPlug, the results will differ.
8522 * Return value: %TRUE if the input focus is within this GtkWindow
8527 gtk_window_has_toplevel_focus (GtkWindow *window)
8529 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8531 return window->priv->has_toplevel_focus;
8536 * SECTION:gtkwindowgroup
8537 * @Short_description: Limit the effect of grabs
8538 * @Title: GtkWindowGroup
8540 * #GtkWindowGroup objects are referenced by each window in the group,
8541 * so once you have added all windows to a #GtkWindowGroup, you can drop
8542 * the initial reference to the window group with g_object_unref(). If the
8543 * windows in the window group are subsequently destroyed, then they will
8544 * be removed from the window group and drop their references on the window
8545 * group; when all window have been removed, the window group will be
8549 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8552 gtk_window_group_init (GtkWindowGroup *group)
8554 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8555 GTK_TYPE_WINDOW_GROUP,
8556 GtkWindowGroupPrivate);
8560 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8562 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8566 * gtk_window_group_new:
8568 * Creates a new #GtkWindowGroup object. Grabs added with
8569 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8571 * Return value: a new #GtkWindowGroup.
8574 gtk_window_group_new (void)
8576 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8580 window_group_cleanup_grabs (GtkWindowGroup *group,
8583 GtkWindowGroupPrivate *priv;
8584 GtkDeviceGrabInfo *info;
8586 GSList *to_remove = NULL;
8590 tmp_list = priv->grabs;
8593 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8594 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8595 tmp_list = tmp_list->next;
8600 gtk_grab_remove (to_remove->data);
8601 g_object_unref (to_remove->data);
8602 to_remove = g_slist_delete_link (to_remove, to_remove);
8605 tmp_list = priv->device_grabs;
8609 info = tmp_list->data;
8611 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8612 to_remove = g_slist_prepend (to_remove, info);
8614 tmp_list = tmp_list->next;
8619 info = to_remove->data;
8621 gtk_device_grab_remove (info->widget, info->device);
8622 to_remove = g_slist_delete_link (to_remove, to_remove);
8627 * gtk_window_group_add_window:
8628 * @window_group: a #GtkWindowGroup
8629 * @window: the #GtkWindow to add
8631 * Adds a window to a #GtkWindowGroup.
8634 gtk_window_group_add_window (GtkWindowGroup *window_group,
8637 GtkWindowPrivate *priv;
8639 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8640 g_return_if_fail (GTK_IS_WINDOW (window));
8642 priv = window->priv;
8644 if (priv->group != window_group)
8646 g_object_ref (window);
8647 g_object_ref (window_group);
8650 gtk_window_group_remove_window (priv->group, window);
8652 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8654 priv->group = window_group;
8656 g_object_unref (window);
8661 * gtk_window_group_remove_window:
8662 * @window_group: a #GtkWindowGroup
8663 * @window: the #GtkWindow to remove
8665 * Removes a window from a #GtkWindowGroup.
8668 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8671 GtkWindowPrivate *priv;
8673 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8674 g_return_if_fail (GTK_IS_WINDOW (window));
8675 priv = window->priv;
8676 g_return_if_fail (priv->group == window_group);
8678 g_object_ref (window);
8680 window_group_cleanup_grabs (window_group, window);
8683 g_object_unref (window_group);
8684 g_object_unref (window);
8688 * gtk_window_group_list_windows:
8689 * @window_group: a #GtkWindowGroup
8691 * Returns a list of the #GtkWindows that belong to @window_group.
8693 * Returns: (element-type GtkWindow) (transfer container): A
8694 * newly-allocated list of windows inside the group.
8699 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8701 GList *toplevels, *toplevel, *group_windows;
8703 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8705 group_windows = NULL;
8706 toplevels = gtk_window_list_toplevels ();
8708 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8710 GtkWindow *window = toplevel->data;
8712 if (window_group == window->priv->group)
8713 group_windows = g_list_prepend (group_windows, window);
8716 g_list_free (toplevels);
8718 return g_list_reverse (group_windows);
8722 * gtk_window_get_group:
8723 * @window: (allow-none): a #GtkWindow, or %NULL
8725 * Returns the group for @window or the default group, if
8726 * @window is %NULL or if @window does not have an explicit
8729 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8734 gtk_window_get_group (GtkWindow *window)
8736 if (window && window->priv->group)
8737 return window->priv->group;
8740 static GtkWindowGroup *default_group = NULL;
8743 default_group = gtk_window_group_new ();
8745 return default_group;
8750 * gtk_window_has_group:
8751 * @window: a #GtkWindow
8753 * Returns whether @window has an explicit window group.
8755 * Return value: %TRUE if @window has an explicit window group.
8760 gtk_window_has_group (GtkWindow *window)
8762 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8764 return window->priv->group != NULL;
8768 * gtk_window_group_get_current_grab:
8769 * @window_group: a #GtkWindowGroup
8771 * Gets the current grab widget of the given group,
8772 * see gtk_grab_add().
8774 * Returns: (transfer none): the current grab widget of the group
8779 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8781 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8783 if (window_group->priv->grabs)
8784 return GTK_WIDGET (window_group->priv->grabs->data);
8789 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8792 GtkWindowGroupPrivate *priv;
8794 priv = window_group->priv;
8795 priv->grabs = g_slist_prepend (priv->grabs, widget);
8799 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8802 GtkWindowGroupPrivate *priv;
8804 priv = window_group->priv;
8805 priv->grabs = g_slist_remove (priv->grabs, widget);
8810 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8813 gboolean block_others)
8815 GtkWindowGroupPrivate *priv;
8816 GtkDeviceGrabInfo *info;
8818 priv = window_group->priv;
8820 info = g_slice_new0 (GtkDeviceGrabInfo);
8821 info->widget = widget;
8822 info->device = device;
8823 info->block_others = block_others;
8825 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8829 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8833 GtkWindowGroupPrivate *priv;
8834 GtkDeviceGrabInfo *info;
8835 GSList *list, *node = NULL;
8836 GdkDevice *other_device;
8838 priv = window_group->priv;
8839 other_device = gdk_device_get_associated_device (device);
8840 list = priv->device_grabs;
8846 if (info->widget == widget &&
8847 (info->device == device ||
8848 info->device == other_device))
8861 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8862 g_slice_free (GtkDeviceGrabInfo, info);
8867 * gtk_window_group_get_current_device_grab:
8868 * @window_group: a #GtkWindowGroup
8869 * @device: a #GdkDevice
8871 * Returns the current grab widget for @device, or %NULL if none.
8873 * Returns: (transfer none): The grab widget, or %NULL
8878 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8881 GtkWindowGroupPrivate *priv;
8882 GtkDeviceGrabInfo *info;
8883 GdkDevice *other_device;
8886 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8887 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8889 priv = window_group->priv;
8890 list = priv->device_grabs;
8891 other_device = gdk_device_get_associated_device (device);
8898 if (info->device == device ||
8899 info->device == other_device)
8900 return info->widget;
8907 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8911 GtkWindowGroupPrivate *priv;
8912 GtkDeviceGrabInfo *info;
8913 GdkDevice *other_device;
8916 priv = window_group->priv;
8917 other_device = gdk_device_get_associated_device (device);
8918 list = priv->device_grabs;
8925 /* Look for blocking grabs on other device pairs
8926 * that have the passed widget within the GTK+ grab.
8928 if (info->block_others &&
8929 info->device != device &&
8930 info->device != other_device &&
8931 (info->widget == widget ||
8932 gtk_widget_is_ancestor (widget, info->widget)))
8940 Derived from XParseGeometry() in XFree86
8942 Copyright 1985, 1986, 1987,1998 The Open Group
8944 All Rights Reserved.
8946 The above copyright notice and this permission notice shall be included
8947 in all copies or substantial portions of the Software.
8949 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8950 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8951 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8952 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8953 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8954 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8955 OTHER DEALINGS IN THE SOFTWARE.
8957 Except as contained in this notice, the name of The Open Group shall
8958 not be used in advertising or otherwise to promote the sale, use or
8959 other dealings in this Software without prior written authorization
8960 from The Open Group.
8965 * XParseGeometry parses strings of the form
8966 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8967 * width, height, xoffset, and yoffset are unsigned integers.
8968 * Example: "=80x24+300-49"
8969 * The equal sign is optional.
8970 * It returns a bitmask that indicates which of the four values
8971 * were actually found in the string. For each value found,
8972 * the corresponding argument is updated; for each value
8973 * not found, the corresponding argument is left unchanged.
8976 /* The following code is from Xlib, and is minimally modified, so we
8977 * can track any upstream changes if required. Don't change this
8978 * code. Or if you do, put in a huge comment marking which thing
8983 read_int (gchar *string,
8991 else if (*string == '-')
8997 for (; (*string >= '0') && (*string <= '9'); string++)
8999 result = (result * 10) + (*string - '0');
9011 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
9012 * value (x, y, width, height) was found in the parsed string.
9014 #define NoValue 0x0000
9015 #define XValue 0x0001
9016 #define YValue 0x0002
9017 #define WidthValue 0x0004
9018 #define HeightValue 0x0008
9019 #define AllValues 0x000F
9020 #define XNegative 0x0010
9021 #define YNegative 0x0020
9023 /* Try not to reformat/modify, so we can compare/sync with X sources */
9025 gtk_XParseGeometry (const char *string,
9028 unsigned int *width,
9029 unsigned int *height)
9033 unsigned int tempWidth, tempHeight;
9035 char *nextCharacter;
9037 /* These initializations are just to silence gcc */
9043 if ( (string == NULL) || (*string == '\0')) return(mask);
9045 string++; /* ignore possible '=' at beg of geometry spec */
9047 strind = (char *)string;
9048 if (*strind != '+' && *strind != '-' && *strind != 'x') {
9049 tempWidth = read_int(strind, &nextCharacter);
9050 if (strind == nextCharacter)
9052 strind = nextCharacter;
9056 if (*strind == 'x' || *strind == 'X') {
9058 tempHeight = read_int(strind, &nextCharacter);
9059 if (strind == nextCharacter)
9061 strind = nextCharacter;
9062 mask |= HeightValue;
9065 if ((*strind == '+') || (*strind == '-')) {
9066 if (*strind == '-') {
9068 tempX = -read_int(strind, &nextCharacter);
9069 if (strind == nextCharacter)
9071 strind = nextCharacter;
9077 tempX = read_int(strind, &nextCharacter);
9078 if (strind == nextCharacter)
9080 strind = nextCharacter;
9083 if ((*strind == '+') || (*strind == '-')) {
9084 if (*strind == '-') {
9086 tempY = -read_int(strind, &nextCharacter);
9087 if (strind == nextCharacter)
9089 strind = nextCharacter;
9096 tempY = read_int(strind, &nextCharacter);
9097 if (strind == nextCharacter)
9099 strind = nextCharacter;
9105 /* If strind isn't at the end of the string the it's an invalid
9106 geometry specification. */
9108 if (*strind != '\0') return (0);
9114 if (mask & WidthValue)
9116 if (mask & HeightValue)
9117 *height = tempHeight;
9122 * gtk_window_parse_geometry:
9123 * @window: a #GtkWindow
9124 * @geometry: geometry string
9126 * Parses a standard X Window System geometry string - see the
9127 * manual page for X (type 'man X') for details on this.
9128 * gtk_window_parse_geometry() does work on all GTK+ ports
9129 * including Win32 but is primarily intended for an X environment.
9131 * If either a size or a position can be extracted from the
9132 * geometry string, gtk_window_parse_geometry() returns %TRUE
9133 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9134 * to resize/move the window.
9136 * If gtk_window_parse_geometry() returns %TRUE, it will also
9137 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9138 * indicating to the window manager that the size/position of
9139 * the window was user-specified. This causes most window
9140 * managers to honor the geometry.
9142 * Note that for gtk_window_parse_geometry() to work as expected, it has
9143 * to be called when the window has its "final" size, i.e. after calling
9144 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9147 * #include <gtk/gtk.h>
9150 * fill_with_content (GtkWidget *vbox)
9152 * /* fill with content... */
9156 * main (int argc, char *argv[])
9158 * GtkWidget *window, *vbox;
9159 * GdkGeometry size_hints = {
9160 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9163 * gtk_init (&argc, &argv);
9165 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9166 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9168 * gtk_container_add (GTK_CONTAINER (window), vbox);
9169 * fill_with_content (vbox);
9170 * gtk_widget_show_all (vbox);
9172 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9175 * GDK_HINT_MIN_SIZE |
9176 * GDK_HINT_BASE_SIZE |
9177 * GDK_HINT_RESIZE_INC);
9181 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9182 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9185 * gtk_widget_show_all (window);
9192 * Return value: %TRUE if string was parsed successfully
9195 gtk_window_parse_geometry (GtkWindow *window,
9196 const gchar *geometry)
9198 gint result, x = 0, y = 0;
9202 gboolean size_set, pos_set;
9205 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9206 g_return_val_if_fail (geometry != NULL, FALSE);
9208 child = gtk_bin_get_child (GTK_BIN (window));
9209 if (!child || !gtk_widget_get_visible (child))
9210 g_warning ("gtk_window_parse_geometry() called on a window with no "
9211 "visible children; the window should be set up before "
9212 "gtk_window_parse_geometry() is called.");
9214 screen = gtk_window_check_screen (window);
9216 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9219 if ((result & WidthValue) || (result & HeightValue))
9221 gtk_window_set_default_size_internal (window,
9222 TRUE, result & WidthValue ? w : -1,
9223 TRUE, result & HeightValue ? h : -1,
9228 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9230 grav = GDK_GRAVITY_NORTH_WEST;
9232 if ((result & XNegative) && (result & YNegative))
9233 grav = GDK_GRAVITY_SOUTH_EAST;
9234 else if (result & XNegative)
9235 grav = GDK_GRAVITY_NORTH_EAST;
9236 else if (result & YNegative)
9237 grav = GDK_GRAVITY_SOUTH_WEST;
9239 if ((result & XValue) == 0)
9242 if ((result & YValue) == 0)
9245 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9246 grav == GDK_GRAVITY_SOUTH_EAST)
9247 y = gdk_screen_get_height (screen) - h + y;
9249 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9250 grav == GDK_GRAVITY_NORTH_EAST)
9251 x = gdk_screen_get_width (screen) - w + x;
9253 /* we don't let you put a window offscreen; maybe some people would
9254 * prefer to be able to, but it's kind of a bogus thing to do.
9263 if ((result & XValue) || (result & YValue))
9265 gtk_window_set_gravity (window, grav);
9266 gtk_window_move (window, x, y);
9270 if (size_set || pos_set)
9272 /* Set USSize, USPosition hints */
9273 GtkWindowGeometryInfo *info;
9275 info = gtk_window_get_geometry_info (window, TRUE);
9278 info->mask |= GDK_HINT_USER_POS;
9280 info->mask |= GDK_HINT_USER_SIZE;
9287 gtk_window_mnemonic_hash_foreach (guint keyval,
9293 GtkWindowKeysForeachFunc func;
9297 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9301 _gtk_window_keys_foreach (GtkWindow *window,
9302 GtkWindowKeysForeachFunc func,
9306 GtkMnemonicHash *mnemonic_hash;
9310 GtkWindowKeysForeachFunc func;
9314 info.window = window;
9316 info.func_data = func_data;
9318 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9320 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9321 gtk_window_mnemonic_hash_foreach, &info);
9323 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9326 GtkAccelGroup *group = groups->data;
9329 for (i = 0; i < group->priv->n_accels; i++)
9331 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9334 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9337 groups = groups->next;
9342 gtk_window_keys_changed (GtkWindow *window)
9344 gtk_window_free_key_hash (window);
9345 gtk_window_get_key_hash (window);
9348 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9350 struct _GtkWindowKeyEntry
9354 guint is_mnemonic : 1;
9358 window_key_entry_destroy (gpointer data)
9360 g_slice_free (GtkWindowKeyEntry, data);
9364 add_to_key_hash (GtkWindow *window,
9366 GdkModifierType modifiers,
9367 gboolean is_mnemonic,
9370 GtkKeyHash *key_hash = data;
9372 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9374 entry->keyval = keyval;
9375 entry->modifiers = modifiers;
9376 entry->is_mnemonic = is_mnemonic;
9378 /* GtkAccelGroup stores lowercased accelerators. To deal
9379 * with this, if <Shift> was specified, uppercase.
9381 if (modifiers & GDK_SHIFT_MASK)
9383 if (keyval == GDK_KEY_Tab)
9384 keyval = GDK_KEY_ISO_Left_Tab;
9386 keyval = gdk_keyval_to_upper (keyval);
9389 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9393 gtk_window_get_key_hash (GtkWindow *window)
9395 GdkScreen *screen = gtk_window_check_screen (window);
9396 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9401 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9402 (GDestroyNotify)window_key_entry_destroy);
9403 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9404 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9410 gtk_window_free_key_hash (GtkWindow *window)
9412 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9415 _gtk_key_hash_free (key_hash);
9416 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9421 * gtk_window_activate_key:
9422 * @window: a #GtkWindow
9423 * @event: a #GdkEventKey
9425 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9426 * called by the default ::key_press_event handler for toplevel windows,
9427 * however in some cases it may be useful to call this directly when
9428 * overriding the standard key handling for a toplevel window.
9430 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9435 gtk_window_activate_key (GtkWindow *window,
9438 GtkKeyHash *key_hash;
9439 GtkWindowKeyEntry *found_entry = NULL;
9440 gboolean enable_mnemonics;
9441 gboolean enable_accels;
9443 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9444 g_return_val_if_fail (event != NULL, FALSE);
9446 key_hash = gtk_window_get_key_hash (window);
9451 GSList *entries = _gtk_key_hash_lookup (key_hash,
9452 event->hardware_keycode,
9454 gtk_accelerator_get_default_mod_mask (),
9457 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9458 "gtk-enable-mnemonics", &enable_mnemonics,
9459 "gtk-enable-accels", &enable_accels,
9462 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9464 GtkWindowKeyEntry *entry = tmp_list->data;
9465 if (entry->is_mnemonic)
9467 if (enable_mnemonics)
9469 found_entry = entry;
9475 if (enable_accels && !found_entry)
9477 found_entry = entry;
9482 g_slist_free (entries);
9487 if (found_entry->is_mnemonic)
9489 if (enable_mnemonics)
9490 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9491 found_entry->modifiers);
9496 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9497 found_entry->modifiers);
9505 window_update_has_focus (GtkWindow *window)
9507 GtkWindowPrivate *priv = window->priv;
9508 GtkWidget *widget = GTK_WIDGET (window);
9509 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9511 if (has_focus != priv->has_focus)
9513 priv->has_focus = has_focus;
9517 if (priv->focus_widget &&
9518 priv->focus_widget != widget &&
9519 !gtk_widget_has_focus (priv->focus_widget))
9520 do_focus_change (priv->focus_widget, TRUE);
9524 if (priv->focus_widget &&
9525 priv->focus_widget != widget &&
9526 gtk_widget_has_focus (priv->focus_widget))
9527 do_focus_change (priv->focus_widget, FALSE);
9533 * _gtk_window_set_is_active:
9534 * @window: a #GtkWindow
9535 * @is_active: %TRUE if the window is in the currently active toplevel
9537 * Internal function that sets whether the #GtkWindow is part
9538 * of the currently active toplevel window (taking into account inter-process
9542 _gtk_window_set_is_active (GtkWindow *window,
9545 GtkWindowPrivate *priv;
9547 g_return_if_fail (GTK_IS_WINDOW (window));
9549 priv = window->priv;
9551 is_active = is_active != FALSE;
9553 if (is_active != priv->is_active)
9555 priv->is_active = is_active;
9556 window_update_has_focus (window);
9558 g_object_notify (G_OBJECT (window), "is-active");
9563 * _gtk_window_set_is_toplevel:
9564 * @window: a #GtkWindow
9565 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9566 * child of the root window); %FALSE if it is not (for example, for an
9567 * in-process, parented GtkPlug)
9569 * Internal function used by #GtkPlug when it gets parented/unparented by a
9570 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9571 * global list of toplevel windows.
9574 _gtk_window_set_is_toplevel (GtkWindow *window,
9575 gboolean is_toplevel)
9578 GtkWidget *toplevel;
9580 widget = GTK_WIDGET (window);
9582 if (gtk_widget_is_toplevel (widget))
9583 g_assert (g_slist_find (toplevel_list, window) != NULL);
9585 g_assert (g_slist_find (toplevel_list, window) == NULL);
9587 if (is_toplevel == gtk_widget_is_toplevel (widget))
9592 /* Pass through regular pathways of an embedded toplevel
9593 * to go through unmapping and hiding the widget before
9594 * becomming a toplevel again.
9596 * We remain hidden after becomming toplevel in order to
9597 * avoid problems during an embedded toplevel's dispose cycle
9598 * (When a toplevel window is shown it tries to grab focus again,
9599 * this causes problems while disposing).
9601 gtk_widget_hide (widget);
9603 /* Save the toplevel this widget was previously anchored into before
9604 * propagating a hierarchy-changed.
9606 * Usually this happens by way of gtk_widget_unparent() and we are
9607 * already unanchored at this point, just adding this clause incase
9608 * things happen differently.
9610 toplevel = gtk_widget_get_toplevel (widget);
9611 if (!gtk_widget_is_toplevel (toplevel))
9614 _gtk_widget_set_is_toplevel (widget, TRUE);
9616 /* When a window becomes toplevel after being embedded and anchored
9617 * into another window we need to unset its anchored flag so that
9618 * the hierarchy changed signal kicks in properly.
9620 _gtk_widget_set_anchored (widget, FALSE);
9621 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9623 toplevel_list = g_slist_prepend (toplevel_list, window);
9627 _gtk_widget_set_is_toplevel (widget, FALSE);
9628 toplevel_list = g_slist_remove (toplevel_list, window);
9630 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9635 * _gtk_window_set_has_toplevel_focus:
9636 * @window: a #GtkWindow
9637 * @has_toplevel_focus: %TRUE if the in
9639 * Internal function that sets whether the keyboard focus for the
9640 * toplevel window (taking into account inter-process embedding.)
9643 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9644 gboolean has_toplevel_focus)
9646 GtkWindowPrivate *priv;
9648 g_return_if_fail (GTK_IS_WINDOW (window));
9650 priv = window->priv;
9652 has_toplevel_focus = has_toplevel_focus != FALSE;
9654 if (has_toplevel_focus != priv->has_toplevel_focus)
9656 priv->has_toplevel_focus = has_toplevel_focus;
9657 window_update_has_focus (window);
9659 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9664 * gtk_window_set_auto_startup_notification:
9665 * @setting: %TRUE to automatically do startup notification
9667 * By default, after showing the first #GtkWindow, GTK+ calls
9668 * gdk_notify_startup_complete(). Call this function to disable
9669 * the automatic startup notification. You might do this if your
9670 * first window is a splash screen, and you want to delay notification
9671 * until after your real main window has been shown, for example.
9673 * In that example, you would disable startup notification
9674 * temporarily, show your splash screen, then re-enable it so that
9675 * showing the main window would automatically result in notification.
9680 gtk_window_set_auto_startup_notification (gboolean setting)
9682 disable_startup_notification = !setting;
9686 * gtk_window_get_window_type:
9687 * @window: a #GtkWindow
9689 * Gets the type of the window. See #GtkWindowType.
9691 * Return value: the type of the window
9696 gtk_window_get_window_type (GtkWindow *window)
9698 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9700 return window->priv->type;
9704 * gtk_window_get_mnemonics_visible:
9705 * @window: a #GtkWindow
9707 * Gets the value of the #GtkWindow:mnemonics-visible property.
9709 * Returns: %TRUE if mnemonics are supposed to be visible
9715 gtk_window_get_mnemonics_visible (GtkWindow *window)
9717 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9719 return window->priv->mnemonics_visible;
9723 * gtk_window_set_mnemonics_visible:
9724 * @window: a #GtkWindow
9725 * @setting: the new value
9727 * Sets the #GtkWindow:mnemonics-visible property.
9732 gtk_window_set_mnemonics_visible (GtkWindow *window,
9735 GtkWindowPrivate *priv;
9737 g_return_if_fail (GTK_IS_WINDOW (window));
9739 priv = window->priv;
9741 setting = setting != FALSE;
9743 if (priv->mnemonics_visible != setting)
9745 priv->mnemonics_visible = setting;
9746 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9749 priv->mnemonics_visible_set = TRUE;
9753 * gtk_window_get_focus_visible:
9754 * @window: a #GtkWindow
9756 * Gets the value of the #GtkWindow:focus-visible property.
9758 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9764 gtk_window_get_focus_visible (GtkWindow *window)
9766 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9768 return window->priv->focus_visible;
9772 * gtk_window_set_focus_visible:
9773 * @window: a #GtkWindow
9774 * @setting: the new value
9776 * Sets the #GtkWindow:focus-visible property.
9781 gtk_window_set_focus_visible (GtkWindow *window,
9784 GtkWindowPrivate *priv;
9786 g_return_if_fail (GTK_IS_WINDOW (window));
9788 priv = window->priv;
9790 setting = setting != FALSE;
9792 if (priv->focus_visible != setting)
9794 priv->focus_visible = setting;
9795 g_object_notify (G_OBJECT (window), "focus-visible");
9800 _gtk_window_get_wmclass (GtkWindow *window,
9801 gchar **wmclass_name,
9802 gchar **wmclass_class)
9804 GtkWindowPrivate *priv = window->priv;
9806 *wmclass_name = priv->wmclass_name;
9807 *wmclass_class = priv->wmclass_class;
9811 * gtk_window_set_has_user_ref_count:
9812 * @window: a #GtkWindow
9813 * @setting: the new value
9815 * Tells GTK+ whether to drop its extra reference to the window
9816 * when gtk_window_destroy() is called.
9818 * This function is only exported for the benefit of language
9819 * bindings which may need to keep the window alive until their
9820 * wrapper object is garbage collected. There is no justification
9821 * for ever calling this function in an application.
9826 gtk_window_set_has_user_ref_count (GtkWindow *window,
9829 g_return_if_fail (GTK_IS_WINDOW (window));
9831 window->priv->has_user_ref_count = setting;
9835 ensure_state_flag_backdrop (GtkWidget *widget)
9838 gboolean window_focused = TRUE;
9840 window = gtk_widget_get_window (widget);
9842 window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9844 if (!window_focused)
9845 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
9847 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
9849 gtk_widget_queue_draw (widget);