1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 #include "gtkwindow.h"
34 #include "gtkprivate.h"
35 #include "gtkwindowprivate.h"
36 #include "gtkaccelgroupprivate.h"
37 #include "gtkbindings.h"
38 #include "gtkkeyhash.h"
40 #include "gtkmnemonichash.h"
41 #include "gtkmenubar.h"
42 #include "gtkiconfactory.h"
43 #include "gtkicontheme.h"
44 #include "gtkmarshalers.h"
46 #include "gtkbuildable.h"
47 #include "gtkwidgetprivate.h"
48 #include "gtkcontainerprivate.h"
50 #include "gtkstylecontextprivate.h"
51 #include "gtktypebuiltins.h"
52 #include "a11y/gtkwindowaccessible.h"
54 #include "deprecated/gtkstyle.h"
56 #ifdef GDK_WINDOWING_X11
63 * @short_description: Toplevel which can contain other widgets
65 * A GtkWindow is a toplevel window which can contain other widgets.
66 * Windows normally have decorations that are under the control
67 * of the windowing system and allow the user to manipulate the window
68 * (resize it, move it, close it,...).
70 * GTK+ also allows windows to have a resize grip (a small area in the lower
71 * right or left corner) which can be clicked to reszie the window. To
72 * control whether a window has a resize grip, use
73 * gtk_window_set_has_resize_grip().
75 * <refsect2 id="GtkWindow-BUILDER-UI">
76 * <title>GtkWindow as GtkBuildable</title>
78 * The GtkWindow implementation of the GtkBuildable interface supports a
79 * custom <tag class="starttag">accel-groups</tag> element, which supports
80 * any number of <tag class="starttag">group</tag> elements representing the
81 * #GtkAccelGroup objects you want to add to your window (synonymous with
82 * gtk_window_add_accel_group().
85 * <title>A UI definition fragment with accel groups</title>
86 * <programlisting><![CDATA[
87 * <object class="GtkWindow">
89 * <group name="accelgroup1"/>
95 * <object class="GtkAccelGroup" id="accelgroup1"/>
96 * ]]></programlisting>
101 #define AUTO_MNEMONICS_DELAY 300 /* ms */
103 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
105 struct _GtkWindowPrivate
107 GtkMnemonicHash *mnemonic_hash;
109 GtkWidget *attach_widget;
110 GtkWidget *default_widget;
111 GtkWidget *focus_widget;
112 GtkWindow *transient_parent;
113 GtkWindowGeometryInfo *geometry_info;
114 GtkWindowGroup *group;
116 GtkApplication *application;
118 GdkModifierType mnemonic_modifier;
119 GdkWindowTypeHint gdk_type_hint;
123 GdkWindow *grip_window;
127 gchar *wmclass_class;
131 guint keys_changed_handler;
133 guint32 initial_timestamp;
135 guint16 configure_request_count;
137 guint auto_mnemonics_timeout_id;
139 /* The following flags are initially TRUE (before a window is mapped).
140 * They cause us to compute a configure request that involves
141 * default-only parameters. Once mapped, we set them to FALSE.
142 * Then we set them to TRUE again on unmap (for position)
143 * and on unrealize (for size).
145 guint need_default_position : 1;
146 guint need_default_size : 1;
148 guint above_initially : 1;
149 guint accept_focus : 1;
150 guint below_initially : 1;
151 guint builder_visible : 1;
152 guint configure_notify_received : 1;
155 guint destroy_with_parent : 1;
156 guint focus_on_map : 1;
157 guint fullscreen_initially : 1;
159 guint has_user_ref_count : 1;
160 guint has_toplevel_focus : 1;
161 guint hide_titlebar_when_maximized : 1;
162 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
164 guint maximize_initially : 1;
165 guint mnemonics_visible : 1;
166 guint mnemonics_visible_set : 1;
167 guint focus_visible : 1;
169 guint opacity_set : 1;
171 guint reset_type_hint : 1;
173 guint skips_pager : 1;
174 guint skips_taskbar : 1;
175 guint stick_initially : 1;
176 guint transient_parent_group : 1;
177 guint type : 4; /* GtkWindowType */
178 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
179 * one of the original eight. If not,
181 * GDK_WINDOW_TYPE_HINT_NORMAL
184 guint has_resize_grip : 1;
185 guint resize_grip_visible : 1; /* don't use, just for "resize-
186 * grip-visible" notification
188 guint gravity : 5; /* GdkGravity */
215 PROP_DESTROY_WITH_PARENT,
216 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
221 PROP_SKIP_TASKBAR_HINT,
222 PROP_SKIP_PAGER_HINT,
232 PROP_HAS_RESIZE_GRIP,
233 PROP_RESIZE_GRIP_VISIBLE,
235 /* Readonly properties */
237 PROP_HAS_TOPLEVEL_FOCUS,
239 /* Writeonly properties */
242 PROP_MNEMONICS_VISIBLE,
253 guint using_default_icon : 1;
254 guint using_parent_icon : 1;
255 guint using_themed_icon : 1;
259 GdkGeometry geometry; /* Last set of geometry hints we set */
260 GdkWindowHints flags;
261 GdkRectangle configure_request;
262 } GtkWindowLastGeometryInfo;
264 struct _GtkWindowGeometryInfo
266 /* Properties that the app has set on the window
268 GdkGeometry geometry; /* Geometry hints */
270 GtkWidget *widget; /* subwidget to which hints apply */
271 /* from last gtk_window_resize () - if > 0, indicates that
272 * we should resize to this size.
277 /* From last gtk_window_move () prior to mapping -
278 * only used if initial_pos_set
283 /* Default size - used only the FIRST time we map a window,
288 /* whether to use initial_x, initial_y */
289 guint initial_pos_set : 1;
290 /* CENTER_ALWAYS or other position constraint changed since
291 * we sent the last configure request.
293 guint position_constraints_changed : 1;
295 /* if true, default_width, height should be multiplied by the
296 * increments and affect the geometry widget only
298 guint default_is_geometry : 1;
300 /* if true, resize_width, height should be multiplied by the
301 * increments and affect the geometry widget only
303 guint resize_is_geometry : 1;
305 GtkWindowLastGeometryInfo last;
309 struct _GtkDeviceGrabInfo
313 guint block_others : 1;
316 struct _GtkWindowGroupPrivate
319 GSList *device_grabs;
322 static void gtk_window_dispose (GObject *object);
323 static void gtk_window_finalize (GObject *object);
324 static void gtk_window_destroy (GtkWidget *widget);
325 static void gtk_window_show (GtkWidget *widget);
326 static void gtk_window_hide (GtkWidget *widget);
327 static void gtk_window_map (GtkWidget *widget);
328 static void gtk_window_unmap (GtkWidget *widget);
329 static void gtk_window_realize (GtkWidget *widget);
330 static void gtk_window_unrealize (GtkWidget *widget);
331 static void gtk_window_size_allocate (GtkWidget *widget,
332 GtkAllocation *allocation);
333 static gboolean gtk_window_map_event (GtkWidget *widget,
335 static gint gtk_window_configure_event (GtkWidget *widget,
336 GdkEventConfigure *event);
337 static gint gtk_window_key_press_event (GtkWidget *widget,
339 static gint gtk_window_key_release_event (GtkWidget *widget,
341 static gint gtk_window_button_press_event (GtkWidget *widget,
342 GdkEventButton *event);
343 static gint gtk_window_enter_notify_event (GtkWidget *widget,
344 GdkEventCrossing *event);
345 static gint gtk_window_leave_notify_event (GtkWidget *widget,
346 GdkEventCrossing *event);
347 static gint gtk_window_focus_in_event (GtkWidget *widget,
348 GdkEventFocus *event);
349 static gint gtk_window_focus_out_event (GtkWidget *widget,
350 GdkEventFocus *event);
351 static void gtk_window_style_updated (GtkWidget *widget);
352 static gboolean gtk_window_state_event (GtkWidget *widget,
353 GdkEventWindowState *event);
354 static void gtk_window_check_resize (GtkContainer *container);
355 static gint gtk_window_focus (GtkWidget *widget,
356 GtkDirectionType direction);
357 static void gtk_window_move_focus (GtkWidget *widget,
358 GtkDirectionType dir);
359 static void gtk_window_real_set_focus (GtkWindow *window,
361 static void gtk_window_direction_changed (GtkWidget *widget,
362 GtkTextDirection prev_dir);
363 static void gtk_window_state_changed (GtkWidget *widget,
364 GtkStateType previous_state);
366 static void gtk_window_real_activate_default (GtkWindow *window);
367 static void gtk_window_real_activate_focus (GtkWindow *window);
368 static void gtk_window_keys_changed (GtkWindow *window);
369 static gint gtk_window_draw (GtkWidget *widget,
371 static void gtk_window_unset_transient_for (GtkWindow *window);
372 static void gtk_window_transient_parent_realized (GtkWidget *parent,
374 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
377 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
379 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
382 static void gtk_window_move_resize (GtkWindow *window);
383 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
385 GdkGeometry *geometry_b,
387 static void gtk_window_constrain_size (GtkWindow *window,
388 GdkGeometry *geometry,
394 static void gtk_window_constrain_position (GtkWindow *window,
399 static void gtk_window_compute_hints (GtkWindow *window,
400 GdkGeometry *new_geometry,
402 static void gtk_window_compute_configure_request (GtkWindow *window,
403 GdkRectangle *request,
404 GdkGeometry *geometry,
407 static void gtk_window_set_default_size_internal (GtkWindow *window,
408 gboolean change_width,
410 gboolean change_height,
412 gboolean is_geometry);
414 static void update_themed_icon (GtkIconTheme *theme,
416 static GList *icon_list_from_theme (GtkWidget *widget,
418 static void gtk_window_realize_icon (GtkWindow *window);
419 static void gtk_window_unrealize_icon (GtkWindow *window);
420 static void resize_grip_create_window (GtkWindow *window);
421 static void resize_grip_destroy_window (GtkWindow *window);
422 static void update_grip_visibility (GtkWindow *window);
424 static void gtk_window_notify_keys_changed (GtkWindow *window);
425 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
426 static void gtk_window_free_key_hash (GtkWindow *window);
427 static void gtk_window_on_composited_changed (GdkScreen *screen,
429 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
432 static void gtk_window_set_theme_variant (GtkWindow *window);
434 static GSList *toplevel_list = NULL;
435 static guint window_signals[LAST_SIGNAL] = { 0 };
436 static GList *default_icon_list = NULL;
437 static gchar *default_icon_name = NULL;
438 static guint default_icon_serial = 0;
439 static gboolean disable_startup_notification = FALSE;
440 static gboolean sent_startup_notification = FALSE;
442 static GQuark quark_gtk_embedded = 0;
443 static GQuark quark_gtk_window_key_hash = 0;
444 static GQuark quark_gtk_window_icon_info = 0;
445 static GQuark quark_gtk_buildable_accels = 0;
447 static GtkBuildableIface *parent_buildable_iface;
449 static void gtk_window_set_property (GObject *object,
453 static void gtk_window_get_property (GObject *object,
459 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
460 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
463 const GValue *value);
464 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
465 GtkBuilder *builder);
466 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
469 const gchar *tagname,
470 GMarkupParser *parser,
472 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
475 const gchar *tagname,
478 static void ensure_state_flag_backdrop (GtkWidget *widget);
480 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
481 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
482 gtk_window_buildable_interface_init))
485 add_tab_bindings (GtkBindingSet *binding_set,
486 GdkModifierType modifiers,
487 GtkDirectionType direction)
489 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
491 GTK_TYPE_DIRECTION_TYPE, direction);
492 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
494 GTK_TYPE_DIRECTION_TYPE, direction);
498 add_arrow_bindings (GtkBindingSet *binding_set,
500 GtkDirectionType direction)
502 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
504 gtk_binding_entry_add_signal (binding_set, keysym, 0,
506 GTK_TYPE_DIRECTION_TYPE, direction);
507 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
509 GTK_TYPE_DIRECTION_TYPE, direction);
510 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
512 GTK_TYPE_DIRECTION_TYPE, direction);
513 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
515 GTK_TYPE_DIRECTION_TYPE, direction);
519 extract_time_from_startup_id (const gchar* startup_id)
521 gchar *timestr = g_strrstr (startup_id, "_TIME");
522 guint32 retval = GDK_CURRENT_TIME;
529 /* Skip past the "_TIME" part */
534 timestamp = g_ascii_strtoull (timestr, &end, 0);
535 if (errno == 0 && end != timestr)
543 startup_id_is_fake (const gchar* startup_id)
545 return strncmp (startup_id, "_TIME", 5) == 0;
549 gtk_window_class_init (GtkWindowClass *klass)
551 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
552 GtkWidgetClass *widget_class;
553 GtkContainerClass *container_class;
554 GtkBindingSet *binding_set;
556 widget_class = (GtkWidgetClass*) klass;
557 container_class = (GtkContainerClass*) klass;
559 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
560 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
561 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
562 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
564 gobject_class->dispose = gtk_window_dispose;
565 gobject_class->finalize = gtk_window_finalize;
567 gobject_class->set_property = gtk_window_set_property;
568 gobject_class->get_property = gtk_window_get_property;
570 widget_class->destroy = gtk_window_destroy;
571 widget_class->show = gtk_window_show;
572 widget_class->hide = gtk_window_hide;
573 widget_class->map = gtk_window_map;
574 widget_class->map_event = gtk_window_map_event;
575 widget_class->unmap = gtk_window_unmap;
576 widget_class->realize = gtk_window_realize;
577 widget_class->unrealize = gtk_window_unrealize;
578 widget_class->size_allocate = gtk_window_size_allocate;
579 widget_class->configure_event = gtk_window_configure_event;
580 widget_class->key_press_event = gtk_window_key_press_event;
581 widget_class->key_release_event = gtk_window_key_release_event;
582 widget_class->enter_notify_event = gtk_window_enter_notify_event;
583 widget_class->leave_notify_event = gtk_window_leave_notify_event;
584 widget_class->focus_in_event = gtk_window_focus_in_event;
585 widget_class->button_press_event = gtk_window_button_press_event;
586 widget_class->focus_out_event = gtk_window_focus_out_event;
587 widget_class->focus = gtk_window_focus;
588 widget_class->move_focus = gtk_window_move_focus;
589 widget_class->draw = gtk_window_draw;
590 widget_class->window_state_event = gtk_window_state_event;
591 widget_class->direction_changed = gtk_window_direction_changed;
592 widget_class->state_changed = gtk_window_state_changed;
593 widget_class->style_updated = gtk_window_style_updated;
595 container_class->check_resize = gtk_window_check_resize;
597 klass->set_focus = gtk_window_real_set_focus;
599 klass->activate_default = gtk_window_real_activate_default;
600 klass->activate_focus = gtk_window_real_activate_focus;
601 klass->keys_changed = gtk_window_keys_changed;
603 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
606 g_object_class_install_property (gobject_class,
608 g_param_spec_enum ("type",
610 P_("The type of the window"),
611 GTK_TYPE_WINDOW_TYPE,
613 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
615 g_object_class_install_property (gobject_class,
617 g_param_spec_string ("title",
619 P_("The title of the window"),
621 GTK_PARAM_READWRITE));
623 g_object_class_install_property (gobject_class,
625 g_param_spec_string ("role",
627 P_("Unique identifier for the window to be used when restoring a session"),
629 GTK_PARAM_READWRITE));
632 * GtkWindow:startup-id:
634 * The :startup-id is a write-only property for setting window's
635 * startup notification identifier. See gtk_window_set_startup_id()
640 g_object_class_install_property (gobject_class,
642 g_param_spec_string ("startup-id",
644 P_("Unique startup identifier for the window used by startup-notification"),
646 GTK_PARAM_WRITABLE));
648 g_object_class_install_property (gobject_class,
650 g_param_spec_boolean ("resizable",
652 P_("If TRUE, users can resize the window"),
654 GTK_PARAM_READWRITE));
656 g_object_class_install_property (gobject_class,
658 g_param_spec_boolean ("modal",
660 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
662 GTK_PARAM_READWRITE));
664 g_object_class_install_property (gobject_class,
666 g_param_spec_enum ("window-position",
667 P_("Window Position"),
668 P_("The initial position of the window"),
669 GTK_TYPE_WINDOW_POSITION,
671 GTK_PARAM_READWRITE));
673 g_object_class_install_property (gobject_class,
675 g_param_spec_int ("default-width",
677 P_("The default width of the window, used when initially showing the window"),
681 GTK_PARAM_READWRITE));
683 g_object_class_install_property (gobject_class,
685 g_param_spec_int ("default-height",
686 P_("Default Height"),
687 P_("The default height of the window, used when initially showing the window"),
691 GTK_PARAM_READWRITE));
693 g_object_class_install_property (gobject_class,
694 PROP_DESTROY_WITH_PARENT,
695 g_param_spec_boolean ("destroy-with-parent",
696 P_("Destroy with Parent"),
697 P_("If this window should be destroyed when the parent is destroyed"),
699 GTK_PARAM_READWRITE));
702 * GtkWindow:hide-titlebar-when-maximized:
704 * Whether the titlebar should be hidden during maximization.
708 g_object_class_install_property (gobject_class,
709 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
710 g_param_spec_boolean ("hide-titlebar-when-maximized",
711 P_("Hide the titlebar during maximization"),
712 P_("If this window's titlebar should be hidden when the window is maximized"),
714 GTK_PARAM_READWRITE));
716 g_object_class_install_property (gobject_class,
718 g_param_spec_object ("icon",
720 P_("Icon for this window"),
722 GTK_PARAM_READWRITE));
725 * GtkWindow:mnemonics-visible:
727 * Whether mnemonics are currently visible in this window.
729 * This property is maintained by GTK+ based on the
730 * #GtkSettings:gtk-auto-mnemonics setting and user input,
731 * and should not be set by applications.
735 g_object_class_install_property (gobject_class,
736 PROP_MNEMONICS_VISIBLE,
737 g_param_spec_boolean ("mnemonics-visible",
738 P_("Mnemonics Visible"),
739 P_("Whether mnemonics are currently visible in this window"),
741 GTK_PARAM_READWRITE));
744 * GtkWindow:focus-visible:
746 * Whether 'focus rectangles' are currently visible in this window.
748 * This property is maintained by GTK+ based on the
749 * #GtkSettings:gtk-visible-focus setting and user input
750 * and should not be set by applications.
754 g_object_class_install_property (gobject_class,
756 g_param_spec_boolean ("focus-visible",
758 P_("Whether focus rectangles are currently visible in this window"),
760 GTK_PARAM_READWRITE));
763 * GtkWindow:icon-name:
765 * The :icon-name property specifies the name of the themed icon to
766 * use as the window icon. See #GtkIconTheme for more details.
770 g_object_class_install_property (gobject_class,
772 g_param_spec_string ("icon-name",
774 P_("Name of the themed icon for this window"),
776 GTK_PARAM_READWRITE));
778 g_object_class_install_property (gobject_class,
780 g_param_spec_object ("screen",
782 P_("The screen where this window will be displayed"),
784 GTK_PARAM_READWRITE));
786 g_object_class_install_property (gobject_class,
788 g_param_spec_boolean ("is-active",
790 P_("Whether the toplevel is the current active window"),
792 GTK_PARAM_READABLE));
794 g_object_class_install_property (gobject_class,
795 PROP_HAS_TOPLEVEL_FOCUS,
796 g_param_spec_boolean ("has-toplevel-focus",
797 P_("Focus in Toplevel"),
798 P_("Whether the input focus is within this GtkWindow"),
800 GTK_PARAM_READABLE));
802 g_object_class_install_property (gobject_class,
804 g_param_spec_enum ("type-hint",
806 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
807 GDK_TYPE_WINDOW_TYPE_HINT,
808 GDK_WINDOW_TYPE_HINT_NORMAL,
809 GTK_PARAM_READWRITE));
811 g_object_class_install_property (gobject_class,
812 PROP_SKIP_TASKBAR_HINT,
813 g_param_spec_boolean ("skip-taskbar-hint",
815 P_("TRUE if the window should not be in the task bar."),
817 GTK_PARAM_READWRITE));
819 g_object_class_install_property (gobject_class,
820 PROP_SKIP_PAGER_HINT,
821 g_param_spec_boolean ("skip-pager-hint",
823 P_("TRUE if the window should not be in the pager."),
825 GTK_PARAM_READWRITE));
827 g_object_class_install_property (gobject_class,
829 g_param_spec_boolean ("urgency-hint",
831 P_("TRUE if the window should be brought to the user's attention."),
833 GTK_PARAM_READWRITE));
836 * GtkWindow:accept-focus:
838 * Whether the window should receive the input focus.
842 g_object_class_install_property (gobject_class,
844 g_param_spec_boolean ("accept-focus",
846 P_("TRUE if the window should receive the input focus."),
848 GTK_PARAM_READWRITE));
851 * GtkWindow:focus-on-map:
853 * Whether the window should receive the input focus when mapped.
857 g_object_class_install_property (gobject_class,
859 g_param_spec_boolean ("focus-on-map",
861 P_("TRUE if the window should receive the input focus when mapped."),
863 GTK_PARAM_READWRITE));
866 * GtkWindow:decorated:
868 * Whether the window should be decorated by the window manager.
872 g_object_class_install_property (gobject_class,
874 g_param_spec_boolean ("decorated",
876 P_("Whether the window should be decorated by the window manager"),
878 GTK_PARAM_READWRITE));
881 * GtkWindow:deletable:
883 * Whether the window frame should have a close button.
887 g_object_class_install_property (gobject_class,
889 g_param_spec_boolean ("deletable",
891 P_("Whether the window frame should have a close button"),
893 GTK_PARAM_READWRITE));
896 * GtkWindow:has-resize-grip:
898 * Whether the window has a corner resize grip.
900 * Note that the resize grip is only shown if the window is
901 * actually resizable and not maximized. Use
902 * #GtkWindow:resize-grip-visible to find out if the resize
903 * grip is currently shown.
907 g_object_class_install_property (gobject_class,
908 PROP_HAS_RESIZE_GRIP,
909 g_param_spec_boolean ("has-resize-grip",
911 P_("Specifies whether the window should have a resize grip"),
913 GTK_PARAM_READWRITE));
916 * GtkWindow:resize-grip-visible:
918 * Whether a corner resize grip is currently shown.
922 g_object_class_install_property (gobject_class,
923 PROP_RESIZE_GRIP_VISIBLE,
924 g_param_spec_boolean ("resize-grip-visible",
925 P_("Resize grip is visible"),
926 P_("Specifies whether the window's resize grip is visible."),
928 GTK_PARAM_READABLE));
934 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
935 * more details about window gravity.
939 g_object_class_install_property (gobject_class,
941 g_param_spec_enum ("gravity",
943 P_("The window gravity of the window"),
945 GDK_GRAVITY_NORTH_WEST,
946 GTK_PARAM_READWRITE));
950 * GtkWindow:transient-for:
952 * The transient parent of the window. See gtk_window_set_transient_for() for
953 * more details about transient windows.
957 g_object_class_install_property (gobject_class,
959 g_param_spec_object ("transient-for",
960 P_("Transient for Window"),
961 P_("The transient parent of the dialog"),
963 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
966 * GtkWindow:attached-to:
968 * The widget to which this window is attached.
969 * See gtk_window_set_attached_to().
971 * Examples of places where specifying this relation is useful are
972 * for instance a #GtkMenu created by a #GtkComboBox, a completion
973 * popup window created by #GtkEntry or a typeahead search entry
974 * created by #GtkTreeView.
978 g_object_class_install_property (gobject_class,
980 g_param_spec_object ("attached-to",
981 P_("Attached to Widget"),
982 P_("The widget where the window is attached"),
984 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
989 * The requested opacity of the window. See gtk_window_set_opacity() for
990 * more details about window opacity.
994 g_object_class_install_property (gobject_class,
996 g_param_spec_double ("opacity",
997 P_("Opacity for Window"),
998 P_("The opacity of the window, from 0 to 1"),
1002 GTK_PARAM_READWRITE));
1004 /* Style properties.
1006 gtk_widget_class_install_style_property (widget_class,
1007 g_param_spec_int ("resize-grip-width",
1008 P_("Width of resize grip"),
1009 P_("Width of resize grip"),
1010 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1012 gtk_widget_class_install_style_property (widget_class,
1013 g_param_spec_int ("resize-grip-height",
1014 P_("Height of resize grip"),
1015 P_("Height of resize grip"),
1016 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1020 * GtkWindow:application:
1022 * The #GtkApplication associated with the window.
1024 * The application will be kept alive for at least as long as it
1025 * has any windows associated with it (see g_application_hold()
1026 * for a way to keep it alive without windows).
1028 * Normally, the connection between the application and the window
1029 * will remain until the window is destroyed, but you can explicitly
1030 * remove it by setting the ::application property to %NULL.
1034 g_object_class_install_property (gobject_class,
1036 g_param_spec_object ("application",
1037 P_("GtkApplication"),
1038 P_("The GtkApplication for the window"),
1039 GTK_TYPE_APPLICATION,
1040 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1042 window_signals[SET_FOCUS] =
1043 g_signal_new (I_("set-focus"),
1044 G_TYPE_FROM_CLASS (gobject_class),
1046 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1048 _gtk_marshal_VOID__OBJECT,
1053 * GtkWindow::activate-focus:
1054 * @window: the window which received the signal
1056 * The ::activate-focus signal is a
1057 * <link linkend="keybinding-signals">keybinding signal</link>
1058 * which gets emitted when the user activates the currently
1059 * focused widget of @window.
1061 window_signals[ACTIVATE_FOCUS] =
1062 g_signal_new (I_("activate-focus"),
1063 G_TYPE_FROM_CLASS (gobject_class),
1064 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1065 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1067 _gtk_marshal_VOID__VOID,
1072 * GtkWindow::activate-default:
1073 * @window: the window which received the signal
1075 * The ::activate-default signal is a
1076 * <link linkend="keybinding-signals">keybinding signal</link>
1077 * which gets emitted when the user activates the default widget
1080 window_signals[ACTIVATE_DEFAULT] =
1081 g_signal_new (I_("activate-default"),
1082 G_TYPE_FROM_CLASS (gobject_class),
1083 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1084 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1086 _gtk_marshal_VOID__VOID,
1091 * GtkWindow::keys-changed:
1092 * @window: the window which received the signal
1094 * The ::keys-changed signal gets emitted when the set of accelerators
1095 * or mnemonics that are associated with @window changes.
1097 window_signals[KEYS_CHANGED] =
1098 g_signal_new (I_("keys-changed"),
1099 G_TYPE_FROM_CLASS (gobject_class),
1101 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1103 _gtk_marshal_VOID__VOID,
1111 binding_set = gtk_binding_set_by_class (klass);
1113 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1114 "activate-focus", 0);
1115 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1116 "activate-focus", 0);
1118 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1119 "activate-default", 0);
1120 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1121 "activate-default", 0);
1122 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1123 "activate-default", 0);
1125 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1126 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1127 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1128 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1130 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1131 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1132 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1133 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1135 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1139 gtk_window_init (GtkWindow *window)
1141 GtkStyleContext *context;
1142 GtkWindowPrivate *priv;
1144 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1147 priv = window->priv;
1149 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1150 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1152 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1154 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1157 priv->wmclass_name = g_strdup (g_get_prgname ());
1158 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1159 priv->wm_role = NULL;
1160 priv->geometry_info = NULL;
1161 priv->type = GTK_WINDOW_TOPLEVEL;
1162 priv->focus_widget = NULL;
1163 priv->default_widget = NULL;
1164 priv->configure_request_count = 0;
1165 priv->resizable = TRUE;
1166 priv->configure_notify_received = FALSE;
1167 priv->position = GTK_WIN_POS_NONE;
1168 priv->need_default_size = TRUE;
1169 priv->need_default_position = TRUE;
1170 priv->modal = FALSE;
1171 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1172 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1173 priv->decorated = TRUE;
1174 priv->mnemonic_modifier = GDK_MOD1_MASK;
1175 priv->screen = gdk_screen_get_default ();
1177 priv->accept_focus = TRUE;
1178 priv->focus_on_map = TRUE;
1179 priv->deletable = TRUE;
1180 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1181 priv->opacity = 1.0;
1182 priv->startup_id = NULL;
1183 priv->initial_timestamp = GDK_CURRENT_TIME;
1184 priv->has_resize_grip = TRUE;
1185 priv->mnemonics_visible = TRUE;
1186 priv->focus_visible = TRUE;
1188 g_object_ref_sink (window);
1189 priv->has_user_ref_count = TRUE;
1190 toplevel_list = g_slist_prepend (toplevel_list, window);
1193 g_signal_connect (priv->screen, "composited-changed",
1194 G_CALLBACK (gtk_window_on_composited_changed), window);
1196 #ifdef GDK_WINDOWING_X11
1197 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1198 "notify::gtk-application-prefer-dark-theme",
1199 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1202 context = gtk_widget_get_style_context (GTK_WIDGET (window));
1203 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
1207 gtk_window_set_property (GObject *object,
1209 const GValue *value,
1212 GtkWindow *window = GTK_WINDOW (object);
1213 GtkWindowPrivate *priv = window->priv;
1218 priv->type = g_value_get_enum (value);
1221 gtk_window_set_title (window, g_value_get_string (value));
1224 gtk_window_set_role (window, g_value_get_string (value));
1226 case PROP_STARTUP_ID:
1227 gtk_window_set_startup_id (window, g_value_get_string (value));
1229 case PROP_RESIZABLE:
1230 gtk_window_set_resizable (window, g_value_get_boolean (value));
1233 gtk_window_set_modal (window, g_value_get_boolean (value));
1236 gtk_window_set_position (window, g_value_get_enum (value));
1238 case PROP_DEFAULT_WIDTH:
1239 gtk_window_set_default_size_internal (window,
1240 TRUE, g_value_get_int (value),
1243 case PROP_DEFAULT_HEIGHT:
1244 gtk_window_set_default_size_internal (window,
1246 TRUE, g_value_get_int (value), FALSE);
1248 case PROP_DESTROY_WITH_PARENT:
1249 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1251 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1252 gtk_window_set_hide_titlebar_when_maximized (window, g_value_get_boolean (value));
1255 gtk_window_set_icon (window,
1256 g_value_get_object (value));
1258 case PROP_ICON_NAME:
1259 gtk_window_set_icon_name (window, g_value_get_string (value));
1262 gtk_window_set_screen (window, g_value_get_object (value));
1264 case PROP_TYPE_HINT:
1265 gtk_window_set_type_hint (window,
1266 g_value_get_enum (value));
1268 case PROP_SKIP_TASKBAR_HINT:
1269 gtk_window_set_skip_taskbar_hint (window,
1270 g_value_get_boolean (value));
1272 case PROP_SKIP_PAGER_HINT:
1273 gtk_window_set_skip_pager_hint (window,
1274 g_value_get_boolean (value));
1276 case PROP_URGENCY_HINT:
1277 gtk_window_set_urgency_hint (window,
1278 g_value_get_boolean (value));
1280 case PROP_ACCEPT_FOCUS:
1281 gtk_window_set_accept_focus (window,
1282 g_value_get_boolean (value));
1284 case PROP_FOCUS_ON_MAP:
1285 gtk_window_set_focus_on_map (window,
1286 g_value_get_boolean (value));
1288 case PROP_DECORATED:
1289 gtk_window_set_decorated (window, g_value_get_boolean (value));
1291 case PROP_DELETABLE:
1292 gtk_window_set_deletable (window, g_value_get_boolean (value));
1295 gtk_window_set_gravity (window, g_value_get_enum (value));
1297 case PROP_TRANSIENT_FOR:
1298 gtk_window_set_transient_for (window, g_value_get_object (value));
1300 case PROP_ATTACHED_TO:
1301 gtk_window_set_attached_to (window, g_value_get_object (value));
1304 gtk_window_set_opacity (window, g_value_get_double (value));
1306 case PROP_HAS_RESIZE_GRIP:
1307 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1309 case PROP_APPLICATION:
1310 gtk_window_set_application (window, g_value_get_object (value));
1312 case PROP_MNEMONICS_VISIBLE:
1313 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1315 case PROP_FOCUS_VISIBLE:
1316 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1319 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1325 gtk_window_get_property (GObject *object,
1330 GtkWindow *window = GTK_WINDOW (object);
1331 GtkWindowPrivate *priv = window->priv;
1335 GtkWindowGeometryInfo *info;
1337 g_value_set_enum (value, priv->type);
1340 g_value_set_string (value, priv->wm_role);
1343 g_value_set_string (value, priv->title);
1345 case PROP_RESIZABLE:
1346 g_value_set_boolean (value, priv->resizable);
1349 g_value_set_boolean (value, priv->modal);
1352 g_value_set_enum (value, priv->position);
1354 case PROP_DEFAULT_WIDTH:
1355 info = gtk_window_get_geometry_info (window, FALSE);
1357 g_value_set_int (value, -1);
1359 g_value_set_int (value, info->default_width);
1361 case PROP_DEFAULT_HEIGHT:
1362 info = gtk_window_get_geometry_info (window, FALSE);
1364 g_value_set_int (value, -1);
1366 g_value_set_int (value, info->default_height);
1368 case PROP_DESTROY_WITH_PARENT:
1369 g_value_set_boolean (value, priv->destroy_with_parent);
1371 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1372 g_value_set_boolean (value, priv->hide_titlebar_when_maximized);
1375 g_value_set_object (value, gtk_window_get_icon (window));
1377 case PROP_ICON_NAME:
1378 g_value_set_string (value, gtk_window_get_icon_name (window));
1381 g_value_set_object (value, priv->screen);
1383 case PROP_IS_ACTIVE:
1384 g_value_set_boolean (value, priv->is_active);
1386 case PROP_HAS_TOPLEVEL_FOCUS:
1387 g_value_set_boolean (value, priv->has_toplevel_focus);
1389 case PROP_TYPE_HINT:
1390 g_value_set_enum (value, priv->type_hint);
1392 case PROP_SKIP_TASKBAR_HINT:
1393 g_value_set_boolean (value,
1394 gtk_window_get_skip_taskbar_hint (window));
1396 case PROP_SKIP_PAGER_HINT:
1397 g_value_set_boolean (value,
1398 gtk_window_get_skip_pager_hint (window));
1400 case PROP_URGENCY_HINT:
1401 g_value_set_boolean (value,
1402 gtk_window_get_urgency_hint (window));
1404 case PROP_ACCEPT_FOCUS:
1405 g_value_set_boolean (value,
1406 gtk_window_get_accept_focus (window));
1408 case PROP_FOCUS_ON_MAP:
1409 g_value_set_boolean (value,
1410 gtk_window_get_focus_on_map (window));
1412 case PROP_DECORATED:
1413 g_value_set_boolean (value, gtk_window_get_decorated (window));
1415 case PROP_DELETABLE:
1416 g_value_set_boolean (value, gtk_window_get_deletable (window));
1419 g_value_set_enum (value, gtk_window_get_gravity (window));
1421 case PROP_TRANSIENT_FOR:
1422 g_value_set_object (value, gtk_window_get_transient_for (window));
1424 case PROP_ATTACHED_TO:
1425 g_value_set_object (value, gtk_window_get_attached_to (window));
1428 g_value_set_double (value, gtk_window_get_opacity (window));
1430 case PROP_HAS_RESIZE_GRIP:
1431 g_value_set_boolean (value, priv->has_resize_grip);
1433 case PROP_RESIZE_GRIP_VISIBLE:
1434 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1436 case PROP_APPLICATION:
1437 g_value_set_object (value, gtk_window_get_application (window));
1439 case PROP_MNEMONICS_VISIBLE:
1440 g_value_set_boolean (value, priv->mnemonics_visible);
1442 case PROP_FOCUS_VISIBLE:
1443 g_value_set_boolean (value, priv->focus_visible);
1446 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1452 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1454 parent_buildable_iface = g_type_interface_peek_parent (iface);
1455 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1456 iface->parser_finished = gtk_window_buildable_parser_finished;
1457 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1458 iface->custom_finished = gtk_window_buildable_custom_finished;
1462 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1463 GtkBuilder *builder,
1465 const GValue *value)
1467 GtkWindow *window = GTK_WINDOW (buildable);
1468 GtkWindowPrivate *priv = window->priv;
1470 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1471 priv->builder_visible = TRUE;
1473 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1477 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1478 GtkBuilder *builder)
1480 GtkWindow *window = GTK_WINDOW (buildable);
1481 GtkWindowPrivate *priv = window->priv;
1485 if (priv->builder_visible)
1486 gtk_widget_show (GTK_WIDGET (buildable));
1488 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1489 for (l = accels; l; l = l->next)
1491 object = gtk_builder_get_object (builder, l->data);
1494 g_warning ("Unknown accel group %s specified in window %s",
1495 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1498 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1499 GTK_ACCEL_GROUP (object));
1503 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1505 parent_buildable_iface->parser_finished (buildable, builder);
1511 } GSListSubParserData;
1514 window_start_element (GMarkupParseContext *context,
1515 const gchar *element_name,
1516 const gchar **names,
1517 const gchar **values,
1522 GSListSubParserData *data = (GSListSubParserData*)user_data;
1524 if (strcmp (element_name, "group") == 0)
1526 for (i = 0; names[i]; i++)
1528 if (strcmp (names[i], "name") == 0)
1529 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1532 else if (strcmp (element_name, "accel-groups") == 0)
1535 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1540 static const GMarkupParser window_parser =
1542 window_start_element
1546 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1547 GtkBuilder *builder,
1549 const gchar *tagname,
1550 GMarkupParser *parser,
1553 GSListSubParserData *parser_data;
1555 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1556 tagname, parser, data))
1559 if (strcmp (tagname, "accel-groups") == 0)
1561 parser_data = g_slice_new0 (GSListSubParserData);
1562 parser_data->items = NULL;
1563 parser_data->object = G_OBJECT (buildable);
1565 *parser = window_parser;
1566 *data = parser_data;
1574 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1575 GtkBuilder *builder,
1577 const gchar *tagname,
1580 GSListSubParserData *data;
1582 parent_buildable_iface->custom_finished (buildable, builder, child,
1583 tagname, user_data);
1585 if (strcmp (tagname, "accel-groups") != 0)
1588 data = (GSListSubParserData*)user_data;
1590 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1591 data->items, (GDestroyNotify) g_slist_free);
1593 g_slice_free (GSListSubParserData, data);
1598 * @type: type of window
1600 * Creates a new #GtkWindow, which is a toplevel window that can
1601 * contain other widgets. Nearly always, the type of the window should
1602 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1603 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1604 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1605 * dialogs, though in some other toolkits dialogs are called "popups".
1606 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1607 * On X11, popup windows are not controlled by the <link
1608 * linkend="gtk-X11-arch">window manager</link>.
1610 * If you simply want an undecorated window (no window borders), use
1611 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1613 * Return value: a new #GtkWindow.
1616 gtk_window_new (GtkWindowType type)
1618 GtkWindowPrivate *priv;
1621 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1623 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1624 priv = window->priv;
1628 return GTK_WIDGET (window);
1632 * gtk_window_set_title:
1633 * @window: a #GtkWindow
1634 * @title: title of the window
1636 * Sets the title of the #GtkWindow. The title of a window will be
1637 * displayed in its title bar; on the X Window System, the title bar
1638 * is rendered by the <link linkend="gtk-X11-arch">window
1639 * manager</link>, so exactly how the title appears to users may vary
1640 * according to a user's exact configuration. The title should help a
1641 * user distinguish this window from other windows they may have
1642 * open. A good title might include the application name and current
1643 * document filename, for example.
1647 gtk_window_set_title (GtkWindow *window,
1650 GtkWindowPrivate *priv;
1654 g_return_if_fail (GTK_IS_WINDOW (window));
1656 priv = window->priv;
1657 widget = GTK_WIDGET (window);
1659 new_title = g_strdup (title);
1660 g_free (priv->title);
1661 priv->title = new_title;
1663 if (gtk_widget_get_realized (widget))
1665 gdk_window_set_title (gtk_widget_get_window (widget),
1669 g_object_notify (G_OBJECT (window), "title");
1673 * gtk_window_get_title:
1674 * @window: a #GtkWindow
1676 * Retrieves the title of the window. See gtk_window_set_title().
1678 * Return value: the title of the window, or %NULL if none has
1679 * been set explicitely. The returned string is owned by the widget
1680 * and must not be modified or freed.
1683 gtk_window_get_title (GtkWindow *window)
1685 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1687 return window->priv->title;
1691 * gtk_window_set_wmclass:
1692 * @window: a #GtkWindow
1693 * @wmclass_name: window name hint
1694 * @wmclass_class: window class hint
1696 * Don't use this function. It sets the X Window System "class" and
1697 * "name" hints for a window. According to the ICCCM, you should
1698 * always set these to the same value for all windows in an
1699 * application, and GTK+ sets them to that value by default, so calling
1700 * this function is sort of pointless. However, you may want to call
1701 * gtk_window_set_role() on each window in your application, for the
1702 * benefit of the session manager. Setting the role allows the window
1703 * manager to restore window positions when loading a saved session.
1707 gtk_window_set_wmclass (GtkWindow *window,
1708 const gchar *wmclass_name,
1709 const gchar *wmclass_class)
1711 GtkWindowPrivate *priv;
1713 g_return_if_fail (GTK_IS_WINDOW (window));
1715 priv = window->priv;
1717 g_free (priv->wmclass_name);
1718 priv->wmclass_name = g_strdup (wmclass_name);
1720 g_free (priv->wmclass_class);
1721 priv->wmclass_class = g_strdup (wmclass_class);
1723 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1724 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1728 * gtk_window_set_role:
1729 * @window: a #GtkWindow
1730 * @role: unique identifier for the window to be used when restoring a session
1732 * This function is only useful on X11, not with other GTK+ targets.
1734 * In combination with the window title, the window role allows a
1735 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1736 * same" window when an application is restarted. So for example you
1737 * might set the "toolbox" role on your app's toolbox window, so that
1738 * when the user restarts their session, the window manager can put
1739 * the toolbox back in the same place.
1741 * If a window already has a unique title, you don't need to set the
1742 * role, since the WM can use the title to identify the window when
1743 * restoring the session.
1747 gtk_window_set_role (GtkWindow *window,
1750 GtkWindowPrivate *priv;
1753 g_return_if_fail (GTK_IS_WINDOW (window));
1755 priv = window->priv;
1757 new_role = g_strdup (role);
1758 g_free (priv->wm_role);
1759 priv->wm_role = new_role;
1761 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1762 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1765 g_object_notify (G_OBJECT (window), "role");
1769 * gtk_window_set_startup_id:
1770 * @window: a #GtkWindow
1771 * @startup_id: a string with startup-notification identifier
1773 * Startup notification identifiers are used by desktop environment to
1774 * track application startup, to provide user feedback and other
1775 * features. This function changes the corresponding property on the
1776 * underlying GdkWindow. Normally, startup identifier is managed
1777 * automatically and you should only use this function in special cases
1778 * like transferring focus from other processes. You should use this
1779 * function before calling gtk_window_present() or any equivalent
1780 * function generating a window map event.
1782 * This function is only useful on X11, not with other GTK+ targets.
1787 gtk_window_set_startup_id (GtkWindow *window,
1788 const gchar *startup_id)
1790 GtkWindowPrivate *priv;
1793 g_return_if_fail (GTK_IS_WINDOW (window));
1795 priv = window->priv;
1796 widget = GTK_WIDGET (window);
1798 g_free (priv->startup_id);
1799 priv->startup_id = g_strdup (startup_id);
1801 if (gtk_widget_get_realized (widget))
1803 GdkWindow *gdk_window;
1804 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1806 gdk_window = gtk_widget_get_window (widget);
1808 #ifdef GDK_WINDOWING_X11
1809 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1810 gdk_x11_window_set_user_time (gdk_window, timestamp);
1813 /* Here we differentiate real and "fake" startup notification IDs,
1814 * constructed on purpose just to pass interaction timestamp
1816 if (startup_id_is_fake (priv->startup_id))
1817 gtk_window_present_with_time (window, timestamp);
1820 gdk_window_set_startup_id (gdk_window,
1823 /* If window is mapped, terminate the startup-notification too */
1824 if (gtk_widget_get_mapped (widget) &&
1825 !disable_startup_notification)
1826 gdk_notify_startup_complete_with_id (priv->startup_id);
1830 g_object_notify (G_OBJECT (window), "startup-id");
1834 * gtk_window_get_role:
1835 * @window: a #GtkWindow
1837 * Returns the role of the window. See gtk_window_set_role() for
1838 * further explanation.
1840 * Return value: the role of the window if set, or %NULL. The
1841 * returned is owned by the widget and must not be modified
1845 gtk_window_get_role (GtkWindow *window)
1847 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1849 return window->priv->wm_role;
1853 * gtk_window_set_focus:
1854 * @window: a #GtkWindow
1855 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1856 * any focus widget for the toplevel window.
1858 * If @focus is not the current focus widget, and is focusable, sets
1859 * it as the focus widget for the window. If @focus is %NULL, unsets
1860 * the focus widget for this window. To set the focus to a particular
1861 * widget in the toplevel, it is usually more convenient to use
1862 * gtk_widget_grab_focus() instead of this function.
1865 gtk_window_set_focus (GtkWindow *window,
1868 GtkWindowPrivate *priv;
1871 g_return_if_fail (GTK_IS_WINDOW (window));
1873 priv = window->priv;
1877 g_return_if_fail (GTK_IS_WIDGET (focus));
1878 g_return_if_fail (gtk_widget_get_can_focus (focus));
1882 gtk_widget_grab_focus (focus);
1885 /* Clear the existing focus chain, so that when we focus into
1886 * the window again, we start at the beginnning.
1888 GtkWidget *widget = priv->focus_widget;
1891 while ((parent = gtk_widget_get_parent (widget)))
1894 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1898 _gtk_window_internal_set_focus (window, NULL);
1903 _gtk_window_internal_set_focus (GtkWindow *window,
1906 GtkWindowPrivate *priv;
1908 g_return_if_fail (GTK_IS_WINDOW (window));
1910 priv = window->priv;
1912 if ((priv->focus_widget != focus) ||
1913 (focus && !gtk_widget_has_focus (focus)))
1914 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1918 * gtk_window_set_default:
1919 * @window: a #GtkWindow
1920 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1921 * default widget for the toplevel.
1923 * The default widget is the widget that's activated when the user
1924 * presses Enter in a dialog (for example). This function sets or
1925 * unsets the default widget for a #GtkWindow about. When setting
1926 * (rather than unsetting) the default widget it's generally easier to
1927 * call gtk_widget_grab_focus() on the widget. Before making a widget
1928 * the default widget, you must call gtk_widget_set_can_default() on the
1929 * widget you'd like to make the default.
1932 gtk_window_set_default (GtkWindow *window,
1933 GtkWidget *default_widget)
1935 GtkWindowPrivate *priv;
1937 g_return_if_fail (GTK_IS_WINDOW (window));
1939 priv = window->priv;
1942 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1944 if (priv->default_widget != default_widget)
1946 GtkWidget *old_default_widget = NULL;
1949 g_object_ref (default_widget);
1951 if (priv->default_widget)
1953 old_default_widget = priv->default_widget;
1955 if (priv->focus_widget != priv->default_widget ||
1956 !gtk_widget_get_receives_default (priv->default_widget))
1957 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1959 gtk_widget_queue_draw (priv->default_widget);
1962 priv->default_widget = default_widget;
1964 if (priv->default_widget)
1966 if (priv->focus_widget == NULL ||
1967 !gtk_widget_get_receives_default (priv->focus_widget))
1968 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1970 gtk_widget_queue_draw (priv->default_widget);
1973 if (old_default_widget)
1974 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1978 g_object_notify (G_OBJECT (default_widget), "has-default");
1979 g_object_unref (default_widget);
1985 * gtk_window_get_default_widget:
1986 * @window: a #GtkWindow
1988 * Returns the default widget for @window. See gtk_window_set_default()
1991 * Returns: (transfer none): the default widget, or %NULL if there is none.
1996 gtk_window_get_default_widget (GtkWindow *window)
1998 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2000 return window->priv->default_widget;
2004 handle_keys_changed (gpointer data)
2006 GtkWindow *window = GTK_WINDOW (data);
2007 GtkWindowPrivate *priv = window->priv;
2009 if (priv->keys_changed_handler)
2011 g_source_remove (priv->keys_changed_handler);
2012 priv->keys_changed_handler = 0;
2015 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
2021 gtk_window_notify_keys_changed (GtkWindow *window)
2023 GtkWindowPrivate *priv = window->priv;
2025 if (!priv->keys_changed_handler)
2026 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
2030 * gtk_window_add_accel_group:
2031 * @window: window to attach accelerator group to
2032 * @accel_group: a #GtkAccelGroup
2034 * Associate @accel_group with @window, such that calling
2035 * gtk_accel_groups_activate() on @window will activate accelerators
2039 gtk_window_add_accel_group (GtkWindow *window,
2040 GtkAccelGroup *accel_group)
2042 g_return_if_fail (GTK_IS_WINDOW (window));
2043 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2045 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
2046 g_signal_connect_object (accel_group, "accel-changed",
2047 G_CALLBACK (gtk_window_notify_keys_changed),
2048 window, G_CONNECT_SWAPPED);
2049 gtk_window_notify_keys_changed (window);
2053 * gtk_window_remove_accel_group:
2054 * @window: a #GtkWindow
2055 * @accel_group: a #GtkAccelGroup
2057 * Reverses the effects of gtk_window_add_accel_group().
2060 gtk_window_remove_accel_group (GtkWindow *window,
2061 GtkAccelGroup *accel_group)
2063 g_return_if_fail (GTK_IS_WINDOW (window));
2064 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2066 g_signal_handlers_disconnect_by_func (accel_group,
2067 gtk_window_notify_keys_changed,
2069 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2070 gtk_window_notify_keys_changed (window);
2073 static GtkMnemonicHash *
2074 gtk_window_get_mnemonic_hash (GtkWindow *window,
2077 GtkWindowPrivate *private = window->priv;
2079 if (!private->mnemonic_hash && create)
2080 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2082 return private->mnemonic_hash;
2086 * gtk_window_add_mnemonic:
2087 * @window: a #GtkWindow
2088 * @keyval: the mnemonic
2089 * @target: the widget that gets activated by the mnemonic
2091 * Adds a mnemonic to this window.
2094 gtk_window_add_mnemonic (GtkWindow *window,
2098 g_return_if_fail (GTK_IS_WINDOW (window));
2099 g_return_if_fail (GTK_IS_WIDGET (target));
2101 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2103 gtk_window_notify_keys_changed (window);
2107 * gtk_window_remove_mnemonic:
2108 * @window: a #GtkWindow
2109 * @keyval: the mnemonic
2110 * @target: the widget that gets activated by the mnemonic
2112 * Removes a mnemonic from this window.
2115 gtk_window_remove_mnemonic (GtkWindow *window,
2119 g_return_if_fail (GTK_IS_WINDOW (window));
2120 g_return_if_fail (GTK_IS_WIDGET (target));
2122 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2124 gtk_window_notify_keys_changed (window);
2128 * gtk_window_mnemonic_activate:
2129 * @window: a #GtkWindow
2130 * @keyval: the mnemonic
2131 * @modifier: the modifiers
2133 * Activates the targets associated with the mnemonic.
2135 * Returns: %TRUE if the activation is done.
2138 gtk_window_mnemonic_activate (GtkWindow *window,
2140 GdkModifierType modifier)
2142 GtkWindowPrivate *priv;
2144 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2146 priv = window->priv;
2148 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2150 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2152 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2159 * gtk_window_set_mnemonic_modifier:
2160 * @window: a #GtkWindow
2161 * @modifier: the modifier mask used to activate
2162 * mnemonics on this window.
2164 * Sets the mnemonic modifier for this window.
2167 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2168 GdkModifierType modifier)
2170 GtkWindowPrivate *priv;
2172 g_return_if_fail (GTK_IS_WINDOW (window));
2173 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2175 priv = window->priv;
2177 priv->mnemonic_modifier = modifier;
2178 gtk_window_notify_keys_changed (window);
2182 * gtk_window_get_mnemonic_modifier:
2183 * @window: a #GtkWindow
2185 * Returns the mnemonic modifier for this window. See
2186 * gtk_window_set_mnemonic_modifier().
2188 * Return value: the modifier mask used to activate
2189 * mnemonics on this window.
2192 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2194 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2196 return window->priv->mnemonic_modifier;
2200 * gtk_window_set_position:
2201 * @window: a #GtkWindow.
2202 * @position: a position constraint.
2204 * Sets a position constraint for this window. If the old or new
2205 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2206 * the window to be repositioned to satisfy the new constraint.
2209 gtk_window_set_position (GtkWindow *window,
2210 GtkWindowPosition position)
2212 GtkWindowPrivate *priv;
2214 g_return_if_fail (GTK_IS_WINDOW (window));
2216 priv = window->priv;
2218 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2219 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2221 GtkWindowGeometryInfo *info;
2223 info = gtk_window_get_geometry_info (window, TRUE);
2225 /* this flag causes us to re-request the CENTER_ALWAYS
2226 * constraint in gtk_window_move_resize(), see
2227 * comment in that function.
2229 info->position_constraints_changed = TRUE;
2231 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2234 priv->position = position;
2236 g_object_notify (G_OBJECT (window), "window-position");
2240 * gtk_window_activate_focus:
2241 * @window: a #GtkWindow
2243 * Activates the current focused widget within the window.
2245 * Return value: %TRUE if a widget got activated.
2248 gtk_window_activate_focus (GtkWindow *window)
2250 GtkWindowPrivate *priv;
2252 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2254 priv = window->priv;
2256 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2257 return gtk_widget_activate (priv->focus_widget);
2263 * gtk_window_get_focus:
2264 * @window: a #GtkWindow
2266 * Retrieves the current focused widget within the window.
2267 * Note that this is the widget that would have the focus
2268 * if the toplevel window focused; if the toplevel window
2269 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2270 * not be %TRUE for the widget.
2272 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2275 gtk_window_get_focus (GtkWindow *window)
2277 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2279 return window->priv->focus_widget;
2283 * gtk_window_activate_default:
2284 * @window: a #GtkWindow
2286 * Activates the default widget for the window, unless the current
2287 * focused widget has been configured to receive the default action
2288 * (see gtk_widget_set_receives_default()), in which case the
2289 * focused widget is activated.
2291 * Return value: %TRUE if a widget got activated.
2294 gtk_window_activate_default (GtkWindow *window)
2296 GtkWindowPrivate *priv;
2298 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2300 priv = window->priv;
2302 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2303 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2304 return gtk_widget_activate (priv->default_widget);
2305 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2306 return gtk_widget_activate (priv->focus_widget);
2312 * gtk_window_set_modal:
2313 * @window: a #GtkWindow
2314 * @modal: whether the window is modal
2316 * Sets a window modal or non-modal. Modal windows prevent interaction
2317 * with other windows in the same application. To keep modal dialogs
2318 * on top of main application windows, use
2319 * gtk_window_set_transient_for() to make the dialog transient for the
2320 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2321 * will then disallow lowering the dialog below the parent.
2326 gtk_window_set_modal (GtkWindow *window,
2329 GtkWindowPrivate *priv;
2332 g_return_if_fail (GTK_IS_WINDOW (window));
2334 priv = window->priv;
2336 modal = modal != FALSE;
2337 if (priv->modal == modal)
2340 priv->modal = modal;
2341 widget = GTK_WIDGET (window);
2343 /* adjust desired modality state */
2344 if (gtk_widget_get_realized (widget))
2347 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2349 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2352 if (gtk_widget_get_visible (widget))
2355 gtk_grab_add (widget);
2357 gtk_grab_remove (widget);
2360 g_object_notify (G_OBJECT (window), "modal");
2364 * gtk_window_get_modal:
2365 * @window: a #GtkWindow
2367 * Returns whether the window is modal. See gtk_window_set_modal().
2369 * Return value: %TRUE if the window is set to be modal and
2370 * establishes a grab when shown
2373 gtk_window_get_modal (GtkWindow *window)
2375 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2377 return window->priv->modal;
2381 * gtk_window_list_toplevels:
2383 * Returns a list of all existing toplevel windows. The widgets
2384 * in the list are not individually referenced. If you want
2385 * to iterate through the list and perform actions involving
2386 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2387 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2388 * then unref all the widgets afterwards.
2390 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2393 gtk_window_list_toplevels (void)
2398 for (slist = toplevel_list; slist; slist = slist->next)
2399 list = g_list_prepend (list, slist->data);
2405 remove_attach_widget (GtkWindow *window)
2407 GtkWindowPrivate *priv = window->priv;
2409 if (priv->attach_widget)
2411 _gtk_widget_remove_attached_window (priv->attach_widget, window);
2413 g_object_unref (priv->attach_widget);
2414 priv->attach_widget = NULL;
2419 gtk_window_dispose (GObject *object)
2421 GtkWindow *window = GTK_WINDOW (object);
2423 gtk_window_set_focus (window, NULL);
2424 gtk_window_set_default (window, NULL);
2426 remove_attach_widget (GTK_WINDOW (object));
2428 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2432 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2434 gtk_widget_destroy (GTK_WIDGET (child));
2438 connect_parent_destroyed (GtkWindow *window)
2440 GtkWindowPrivate *priv = window->priv;
2442 if (priv->transient_parent)
2444 g_signal_connect (priv->transient_parent,
2446 G_CALLBACK (parent_destroyed_callback),
2452 disconnect_parent_destroyed (GtkWindow *window)
2454 GtkWindowPrivate *priv = window->priv;
2456 if (priv->transient_parent)
2458 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2459 parent_destroyed_callback,
2465 gtk_window_transient_parent_realized (GtkWidget *parent,
2468 if (gtk_widget_get_realized (window))
2469 gdk_window_set_transient_for (gtk_widget_get_window (window),
2470 gtk_widget_get_window (parent));
2474 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2477 if (gtk_widget_get_realized (window))
2478 gdk_property_delete (gtk_widget_get_window (window),
2479 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2483 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2487 gtk_window_set_screen (window, parent->priv->screen);
2491 gtk_window_unset_transient_for (GtkWindow *window)
2493 GtkWindowPrivate *priv = window->priv;
2495 if (priv->transient_parent)
2497 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2498 gtk_window_transient_parent_realized,
2500 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2501 gtk_window_transient_parent_unrealized,
2503 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2504 gtk_window_transient_parent_screen_changed,
2506 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2507 gtk_widget_destroyed,
2508 &priv->transient_parent);
2510 if (priv->destroy_with_parent)
2511 disconnect_parent_destroyed (window);
2513 priv->transient_parent = NULL;
2515 if (priv->transient_parent_group)
2517 priv->transient_parent_group = FALSE;
2518 gtk_window_group_remove_window (priv->group,
2525 * gtk_window_set_transient_for:
2526 * @window: a #GtkWindow
2527 * @parent: (allow-none): parent window, or %NULL
2529 * Dialog windows should be set transient for the main application
2530 * window they were spawned from. This allows <link
2531 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2532 * dialog on top of the main window, or center the dialog over the
2533 * main window. gtk_dialog_new_with_buttons() and other convenience
2534 * functions in GTK+ will sometimes call
2535 * gtk_window_set_transient_for() on your behalf.
2537 * Passing %NULL for @parent unsets the current transient window.
2539 * On Windows, this function puts the child window on top of the parent,
2540 * much as the window manager would have done on X.
2543 gtk_window_set_transient_for (GtkWindow *window,
2546 GtkWindowPrivate *priv;
2548 g_return_if_fail (GTK_IS_WINDOW (window));
2549 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2550 g_return_if_fail (window != parent);
2552 priv = window->priv;
2554 if (priv->transient_parent)
2556 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2557 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2558 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2559 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2560 GTK_WIDGET (window));
2562 gtk_window_unset_transient_for (window);
2565 priv->transient_parent = parent;
2569 g_signal_connect (parent, "destroy",
2570 G_CALLBACK (gtk_widget_destroyed),
2571 &priv->transient_parent);
2572 g_signal_connect (parent, "realize",
2573 G_CALLBACK (gtk_window_transient_parent_realized),
2575 g_signal_connect (parent, "unrealize",
2576 G_CALLBACK (gtk_window_transient_parent_unrealized),
2578 g_signal_connect (parent, "notify::screen",
2579 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2582 gtk_window_set_screen (window, parent->priv->screen);
2584 if (priv->destroy_with_parent)
2585 connect_parent_destroyed (window);
2587 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2588 gtk_widget_get_realized (GTK_WIDGET (parent)))
2589 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2590 GTK_WIDGET (window));
2592 if (parent->priv->group)
2594 gtk_window_group_add_window (parent->priv->group, window);
2595 priv->transient_parent_group = TRUE;
2601 * gtk_window_get_transient_for:
2602 * @window: a #GtkWindow
2604 * Fetches the transient parent for this window. See
2605 * gtk_window_set_transient_for().
2607 * Return value: (transfer none): the transient parent for this window, or %NULL
2608 * if no transient parent has been set.
2611 gtk_window_get_transient_for (GtkWindow *window)
2613 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2615 return window->priv->transient_parent;
2619 * gtk_window_set_attached_to:
2620 * @window: a #GtkWindow
2621 * @attach_widget: (allow-none): a #GtkWidget, or %NULL
2623 * Marks @window as attached to @attach_widget. This creates a logical binding
2624 * between the window and the widget it belongs to, which is used by GTK+ to
2625 * propagate information such as styling or accessibility to @window as if it
2626 * was a children of @attach_widget.
2628 * Examples of places where specifying this relation is useful are for instance
2629 * a #GtkMenu created by a #GtkComboBox, a completion popup window
2630 * created by #GtkEntry or a typeahead search entry created by #GtkTreeView.
2632 * Note that this function should not be confused with
2633 * gtk_window_set_transient_for(), which specifies a window manager relation
2634 * between two toplevels instead.
2636 * Passing %NULL for @attach_widget detaches the window.
2641 gtk_window_set_attached_to (GtkWindow *window,
2642 GtkWidget *attach_widget)
2644 GtkStyleContext *context;
2645 GtkWindowPrivate *priv;
2647 g_return_if_fail (GTK_IS_WINDOW (window));
2648 g_return_if_fail (GTK_WIDGET (window) != attach_widget);
2650 priv = window->priv;
2652 if (priv->attach_widget == attach_widget)
2655 remove_attach_widget (window);
2657 priv->attach_widget = attach_widget;
2659 if (priv->attach_widget)
2661 _gtk_widget_add_attached_window (priv->attach_widget, window);
2663 g_object_ref (priv->attach_widget);
2666 /* Update the style, as the widget path might change. */
2667 context = gtk_widget_get_style_context (GTK_WIDGET (window));
2668 if (priv->attach_widget)
2669 gtk_style_context_set_parent (context, gtk_widget_get_style_context (priv->attach_widget));
2671 gtk_style_context_set_parent (context, NULL);
2675 * gtk_window_get_attached_to:
2676 * @window: a #GtkWindow
2678 * Fetches the attach widget for this window. See
2679 * gtk_window_set_attached_to().
2681 * Return value: (transfer none): the widget where the window is attached,
2682 * or %NULL if the window is not attached to any widget.
2687 gtk_window_get_attached_to (GtkWindow *window)
2689 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2691 return window->priv->attach_widget;
2695 * gtk_window_set_opacity:
2696 * @window: a #GtkWindow
2697 * @opacity: desired opacity, between 0 and 1
2699 * Request the windowing system to make @window partially transparent,
2700 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2701 * of the opacity parameter are clamped to the [0,1] range.) On X11
2702 * this has any effect only on X screens with a compositing manager
2703 * running. See gtk_widget_is_composited(). On Windows it should work
2706 * Note that setting a window's opacity after the window has been
2707 * shown causes it to flicker once on Windows.
2712 gtk_window_set_opacity (GtkWindow *window,
2715 GtkWindowPrivate *priv;
2717 g_return_if_fail (GTK_IS_WINDOW (window));
2719 priv = window->priv;
2723 else if (opacity > 1.0)
2726 priv->opacity_set = TRUE;
2727 priv->opacity = opacity;
2729 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2730 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2735 * gtk_window_get_opacity:
2736 * @window: a #GtkWindow
2738 * Fetches the requested opacity for this window. See
2739 * gtk_window_set_opacity().
2741 * Return value: the requested opacity for this window.
2746 gtk_window_get_opacity (GtkWindow *window)
2748 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2750 return window->priv->opacity;
2754 * gtk_window_get_application:
2755 * @window: a #GtkWindow
2757 * Gets the #GtkApplication associated with the window (if any).
2759 * Return value: (transfer none): a #GtkApplication, or %NULL
2764 gtk_window_get_application (GtkWindow *window)
2766 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2768 return window->priv->application;
2772 gtk_window_release_application (GtkWindow *window)
2774 if (window->priv->application)
2776 GtkApplication *application;
2778 /* steal reference into temp variable */
2779 application = window->priv->application;
2780 window->priv->application = NULL;
2782 gtk_application_remove_window (application, window);
2783 g_object_unref (application);
2788 * gtk_window_set_application:
2789 * @window: a #GtkWindow
2790 * @application: (allow-none): a #GtkApplication, or %NULL
2792 * Sets or unsets the #GtkApplication associated with the window.
2794 * The application will be kept alive for at least as long as the window
2800 gtk_window_set_application (GtkWindow *window,
2801 GtkApplication *application)
2803 GtkWindowPrivate *priv;
2805 g_return_if_fail (GTK_IS_WINDOW (window));
2807 priv = window->priv;
2808 if (priv->application != application)
2810 gtk_window_release_application (window);
2812 priv->application = application;
2814 if (priv->application != NULL)
2816 g_object_ref (priv->application);
2818 gtk_application_add_window (priv->application, window);
2821 /* don't use a normal cast: application may be NULL */
2822 gtk_widget_insert_action_group (GTK_WIDGET (window), "app", (GActionGroup *) application);
2824 g_object_notify (G_OBJECT (window), "application");
2829 * gtk_window_set_type_hint:
2830 * @window: a #GtkWindow
2831 * @hint: the window type
2833 * By setting the type hint for the window, you allow the window
2834 * manager to decorate and handle the window in a way which is
2835 * suitable to the function of the window in your application.
2837 * This function should be called before the window becomes visible.
2839 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2840 * will sometimes call gtk_window_set_type_hint() on your behalf.
2844 gtk_window_set_type_hint (GtkWindow *window,
2845 GdkWindowTypeHint hint)
2847 GtkWindowPrivate *priv;
2849 g_return_if_fail (GTK_IS_WINDOW (window));
2850 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2852 priv = window->priv;
2854 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2855 priv->type_hint = hint;
2857 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2859 priv->reset_type_hint = TRUE;
2860 priv->gdk_type_hint = hint;
2864 * gtk_window_get_type_hint:
2865 * @window: a #GtkWindow
2867 * Gets the type hint for this window. See gtk_window_set_type_hint().
2869 * Return value: the type hint for @window.
2872 gtk_window_get_type_hint (GtkWindow *window)
2874 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2876 return window->priv->gdk_type_hint;
2880 * gtk_window_set_skip_taskbar_hint:
2881 * @window: a #GtkWindow
2882 * @setting: %TRUE to keep this window from appearing in the task bar
2884 * Windows may set a hint asking the desktop environment not to display
2885 * the window in the task bar. This function sets this hint.
2890 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2893 GtkWindowPrivate *priv;
2895 g_return_if_fail (GTK_IS_WINDOW (window));
2897 priv = window->priv;
2899 setting = setting != FALSE;
2901 if (priv->skips_taskbar != setting)
2903 priv->skips_taskbar = setting;
2904 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2905 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2906 priv->skips_taskbar);
2907 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2912 * gtk_window_get_skip_taskbar_hint:
2913 * @window: a #GtkWindow
2915 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2917 * Return value: %TRUE if window shouldn't be in taskbar
2922 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2924 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2926 return window->priv->skips_taskbar;
2930 * gtk_window_set_skip_pager_hint:
2931 * @window: a #GtkWindow
2932 * @setting: %TRUE to keep this window from appearing in the pager
2934 * Windows may set a hint asking the desktop environment not to display
2935 * the window in the pager. This function sets this hint.
2936 * (A "pager" is any desktop navigation tool such as a workspace
2937 * switcher that displays a thumbnail representation of the windows
2943 gtk_window_set_skip_pager_hint (GtkWindow *window,
2946 GtkWindowPrivate *priv;
2948 g_return_if_fail (GTK_IS_WINDOW (window));
2950 priv = window->priv;
2952 setting = setting != FALSE;
2954 if (priv->skips_pager != setting)
2956 priv->skips_pager = setting;
2957 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2958 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2960 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2965 * gtk_window_get_skip_pager_hint:
2966 * @window: a #GtkWindow
2968 * Gets the value set by gtk_window_set_skip_pager_hint().
2970 * Return value: %TRUE if window shouldn't be in pager
2975 gtk_window_get_skip_pager_hint (GtkWindow *window)
2977 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2979 return window->priv->skips_pager;
2983 * gtk_window_set_urgency_hint:
2984 * @window: a #GtkWindow
2985 * @setting: %TRUE to mark this window as urgent
2987 * Windows may set a hint asking the desktop environment to draw
2988 * the users attention to the window. This function sets this hint.
2993 gtk_window_set_urgency_hint (GtkWindow *window,
2996 GtkWindowPrivate *priv;
2998 g_return_if_fail (GTK_IS_WINDOW (window));
3000 priv = window->priv;
3002 setting = setting != FALSE;
3004 if (priv->urgent != setting)
3006 priv->urgent = setting;
3007 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3008 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
3010 g_object_notify (G_OBJECT (window), "urgency-hint");
3015 * gtk_window_get_urgency_hint:
3016 * @window: a #GtkWindow
3018 * Gets the value set by gtk_window_set_urgency_hint()
3020 * Return value: %TRUE if window is urgent
3025 gtk_window_get_urgency_hint (GtkWindow *window)
3027 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3029 return window->priv->urgent;
3033 * gtk_window_set_accept_focus:
3034 * @window: a #GtkWindow
3035 * @setting: %TRUE to let this window receive input focus
3037 * Windows may set a hint asking the desktop environment not to receive
3038 * the input focus. This function sets this hint.
3043 gtk_window_set_accept_focus (GtkWindow *window,
3046 GtkWindowPrivate *priv;
3048 g_return_if_fail (GTK_IS_WINDOW (window));
3050 priv = window->priv;
3052 setting = setting != FALSE;
3054 if (priv->accept_focus != setting)
3056 priv->accept_focus = setting;
3057 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3058 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
3059 priv->accept_focus);
3060 g_object_notify (G_OBJECT (window), "accept-focus");
3065 * gtk_window_get_accept_focus:
3066 * @window: a #GtkWindow
3068 * Gets the value set by gtk_window_set_accept_focus().
3070 * Return value: %TRUE if window should receive the input focus
3075 gtk_window_get_accept_focus (GtkWindow *window)
3077 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3079 return window->priv->accept_focus;
3083 * gtk_window_set_focus_on_map:
3084 * @window: a #GtkWindow
3085 * @setting: %TRUE to let this window receive input focus on map
3087 * Windows may set a hint asking the desktop environment not to receive
3088 * the input focus when the window is mapped. This function sets this
3094 gtk_window_set_focus_on_map (GtkWindow *window,
3097 GtkWindowPrivate *priv;
3099 g_return_if_fail (GTK_IS_WINDOW (window));
3101 priv = window->priv;
3103 setting = setting != FALSE;
3105 if (priv->focus_on_map != setting)
3107 priv->focus_on_map = setting;
3108 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3109 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
3110 priv->focus_on_map);
3111 g_object_notify (G_OBJECT (window), "focus-on-map");
3116 * gtk_window_get_focus_on_map:
3117 * @window: a #GtkWindow
3119 * Gets the value set by gtk_window_set_focus_on_map().
3121 * Return value: %TRUE if window should receive the input focus when
3127 gtk_window_get_focus_on_map (GtkWindow *window)
3129 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3131 return window->priv->focus_on_map;
3135 * gtk_window_set_destroy_with_parent:
3136 * @window: a #GtkWindow
3137 * @setting: whether to destroy @window with its transient parent
3139 * If @setting is %TRUE, then destroying the transient parent of @window
3140 * will also destroy @window itself. This is useful for dialogs that
3141 * shouldn't persist beyond the lifetime of the main window they're
3142 * associated with, for example.
3145 gtk_window_set_destroy_with_parent (GtkWindow *window,
3148 GtkWindowPrivate *priv;
3150 g_return_if_fail (GTK_IS_WINDOW (window));
3152 priv = window->priv;
3154 if (priv->destroy_with_parent == (setting != FALSE))
3157 if (priv->destroy_with_parent)
3159 disconnect_parent_destroyed (window);
3163 connect_parent_destroyed (window);
3166 priv->destroy_with_parent = setting;
3168 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3172 * gtk_window_get_destroy_with_parent:
3173 * @window: a #GtkWindow
3175 * Returns whether the window will be destroyed with its transient parent. See
3176 * gtk_window_set_destroy_with_parent ().
3178 * Return value: %TRUE if the window will be destroyed with its transient parent.
3181 gtk_window_get_destroy_with_parent (GtkWindow *window)
3183 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3185 return window->priv->destroy_with_parent;
3189 * gtk_window_set_hide_titlebar_when_maximized:
3190 * @window: a #GtkWindow
3191 * @setting: whether to hide the titlebar when @window is maximized
3193 * If @setting is %TRUE, then @window will request that it's titlebar
3194 * should be hidden when maximized.
3195 * This is useful for windows that don't convey any information other
3196 * than the application name in the titlebar, to put the available
3197 * screen space to better use. If the underlying window system does not
3198 * support the request, the setting will not have any effect.
3203 gtk_window_set_hide_titlebar_when_maximized (GtkWindow *window,
3206 g_return_if_fail (GTK_IS_WINDOW (window));
3208 #ifdef GDK_WINDOWING_X11
3210 GdkWindow *gdk_window;
3212 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3214 if (GDK_IS_X11_WINDOW (gdk_window))
3215 gdk_x11_window_set_hide_titlebar_when_maximized (gdk_window, setting);
3219 window->priv->hide_titlebar_when_maximized = setting;
3220 g_object_notify (G_OBJECT (window), "hide-titlebar-when-maximized");
3224 * gtk_window_get_hide_titlebar_when_maximized:
3225 * @window: a #GtkWindow
3227 * Returns whether the window has requested to have its titlebar hidden
3228 * when maximized. See gtk_window_set_hide_titlebar_when_maximized ().
3230 * Return value: %TRUE if the window has requested to have its titlebar
3231 * hidden when maximized
3236 gtk_window_get_hide_titlebar_when_maximized (GtkWindow *window)
3238 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3240 return window->priv->hide_titlebar_when_maximized;
3243 static GtkWindowGeometryInfo*
3244 gtk_window_get_geometry_info (GtkWindow *window,
3247 GtkWindowPrivate *priv = window->priv;
3248 GtkWindowGeometryInfo *info;
3250 info = priv->geometry_info;
3251 if (!info && create)
3253 info = g_new0 (GtkWindowGeometryInfo, 1);
3255 info->default_width = -1;
3256 info->default_height = -1;
3257 info->resize_width = -1;
3258 info->resize_height = -1;
3259 info->initial_x = 0;
3260 info->initial_y = 0;
3261 info->initial_pos_set = FALSE;
3262 info->default_is_geometry = FALSE;
3263 info->position_constraints_changed = FALSE;
3264 info->last.configure_request.x = 0;
3265 info->last.configure_request.y = 0;
3266 info->last.configure_request.width = -1;
3267 info->last.configure_request.height = -1;
3268 info->widget = NULL;
3270 priv->geometry_info = info;
3277 * gtk_window_set_geometry_hints:
3278 * @window: a #GtkWindow
3279 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3280 * @geometry: (allow-none): struct containing geometry information or %NULL
3281 * @geom_mask: mask indicating which struct fields should be paid attention to
3283 * This function sets up hints about how a window can be resized by
3284 * the user. You can set a minimum and maximum size; allowed resize
3285 * increments (e.g. for xterm, you can only resize by the size of a
3286 * character); aspect ratios; and more. See the #GdkGeometry struct.
3290 gtk_window_set_geometry_hints (GtkWindow *window,
3291 GtkWidget *geometry_widget,
3292 GdkGeometry *geometry,
3293 GdkWindowHints geom_mask)
3295 GtkWindowGeometryInfo *info;
3297 g_return_if_fail (GTK_IS_WINDOW (window));
3298 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3300 info = gtk_window_get_geometry_info (window, TRUE);
3303 g_signal_handlers_disconnect_by_func (info->widget,
3304 gtk_widget_destroyed,
3307 info->widget = geometry_widget;
3309 g_signal_connect (geometry_widget, "destroy",
3310 G_CALLBACK (gtk_widget_destroyed),
3314 info->geometry = *geometry;
3316 /* We store gravity in priv->gravity not in the hints. */
3317 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3319 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3321 gtk_window_set_gravity (window, geometry->win_gravity);
3324 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3328 * gtk_window_set_decorated:
3329 * @window: a #GtkWindow
3330 * @setting: %TRUE to decorate the window
3332 * By default, windows are decorated with a title bar, resize
3333 * controls, etc. Some <link linkend="gtk-X11-arch">window
3334 * managers</link> allow GTK+ to disable these decorations, creating a
3335 * borderless window. If you set the decorated property to %FALSE
3336 * using this function, GTK+ will do its best to convince the window
3337 * manager not to decorate the window. Depending on the system, this
3338 * function may not have any effect when called on a window that is
3339 * already visible, so you should call it before calling gtk_widget_show().
3341 * On Windows, this function always works, since there's no window manager
3346 gtk_window_set_decorated (GtkWindow *window,
3349 GtkWindowPrivate *priv;
3350 GdkWindow *gdk_window;
3352 g_return_if_fail (GTK_IS_WINDOW (window));
3354 priv = window->priv;
3356 setting = setting != FALSE;
3358 if (setting == priv->decorated)
3361 priv->decorated = setting;
3363 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3366 if (priv->decorated)
3367 gdk_window_set_decorations (gdk_window,
3370 gdk_window_set_decorations (gdk_window,
3374 g_object_notify (G_OBJECT (window), "decorated");
3378 * gtk_window_get_decorated:
3379 * @window: a #GtkWindow
3381 * Returns whether the window has been set to have decorations
3382 * such as a title bar via gtk_window_set_decorated().
3384 * Return value: %TRUE if the window has been set to have decorations
3387 gtk_window_get_decorated (GtkWindow *window)
3389 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3391 return window->priv->decorated;
3395 * gtk_window_set_deletable:
3396 * @window: a #GtkWindow
3397 * @setting: %TRUE to decorate the window as deletable
3399 * By default, windows have a close button in the window frame. Some
3400 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3401 * disable this button. If you set the deletable property to %FALSE
3402 * using this function, GTK+ will do its best to convince the window
3403 * manager not to show a close button. Depending on the system, this
3404 * function may not have any effect when called on a window that is
3405 * already visible, so you should call it before calling gtk_widget_show().
3407 * On Windows, this function always works, since there's no window manager
3413 gtk_window_set_deletable (GtkWindow *window,
3416 GtkWindowPrivate *priv;
3417 GdkWindow *gdk_window;
3419 g_return_if_fail (GTK_IS_WINDOW (window));
3421 priv = window->priv;
3423 setting = setting != FALSE;
3425 if (setting == priv->deletable)
3428 priv->deletable = setting;
3430 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3433 if (priv->deletable)
3434 gdk_window_set_functions (gdk_window,
3437 gdk_window_set_functions (gdk_window,
3438 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3441 g_object_notify (G_OBJECT (window), "deletable");
3445 * gtk_window_get_deletable:
3446 * @window: a #GtkWindow
3448 * Returns whether the window has been set to have a close button
3449 * via gtk_window_set_deletable().
3451 * Return value: %TRUE if the window has been set to have a close button
3456 gtk_window_get_deletable (GtkWindow *window)
3458 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3460 return window->priv->deletable;
3463 static GtkWindowIconInfo*
3464 get_icon_info (GtkWindow *window)
3466 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3470 free_icon_info (GtkWindowIconInfo *info)
3472 g_free (info->icon_name);
3473 g_slice_free (GtkWindowIconInfo, info);
3477 static GtkWindowIconInfo*
3478 ensure_icon_info (GtkWindow *window)
3480 GtkWindowIconInfo *info;
3482 info = get_icon_info (window);
3486 info = g_slice_new0 (GtkWindowIconInfo);
3487 g_object_set_qdata_full (G_OBJECT (window),
3488 quark_gtk_window_icon_info,
3490 (GDestroyNotify)free_icon_info);
3497 icon_list_from_theme (GtkWidget *widget,
3502 GtkIconTheme *icon_theme;
3507 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3509 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3512 for (i = 0; sizes[i]; i++)
3515 * We need an EWMH extension to handle scalable icons
3516 * by passing their name to the WM. For now just use a
3520 icon = gtk_icon_theme_load_icon (icon_theme, name,
3523 icon = gtk_icon_theme_load_icon (icon_theme, name,
3526 list = g_list_append (list, icon);
3536 gtk_window_realize_icon (GtkWindow *window)
3538 GtkWindowPrivate *priv = window->priv;
3540 GtkWindowIconInfo *info;
3541 GdkWindow *gdk_window;
3544 widget = GTK_WIDGET (window);
3545 gdk_window = gtk_widget_get_window (widget);
3547 g_return_if_fail (gdk_window != NULL);
3549 /* no point setting an icon on override-redirect */
3550 if (priv->type == GTK_WINDOW_POPUP)
3555 info = ensure_icon_info (window);
3560 info->using_default_icon = FALSE;
3561 info->using_parent_icon = FALSE;
3562 info->using_themed_icon = FALSE;
3564 icon_list = info->icon_list;
3566 /* Look up themed icon */
3567 if (icon_list == NULL && info->icon_name)
3569 icon_list = icon_list_from_theme (widget, info->icon_name);
3571 info->using_themed_icon = TRUE;
3574 /* Inherit from transient parent */
3575 if (icon_list == NULL && priv->transient_parent)
3577 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3579 info->using_parent_icon = TRUE;
3582 /* Inherit from default */
3583 if (icon_list == NULL)
3585 icon_list = default_icon_list;
3587 info->using_default_icon = TRUE;
3590 /* Look up themed icon */
3591 if (icon_list == NULL && default_icon_name)
3593 icon_list = icon_list_from_theme (widget, default_icon_name);
3594 info->using_default_icon = TRUE;
3595 info->using_themed_icon = TRUE;
3598 info->realized = TRUE;
3600 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3602 if (info->using_themed_icon)
3604 GtkIconTheme *icon_theme;
3606 g_list_free_full (icon_list, g_object_unref);
3608 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3609 g_signal_connect (icon_theme, "changed",
3610 G_CALLBACK (update_themed_icon), window);
3615 gtk_window_unrealize_icon (GtkWindow *window)
3617 GtkWindowIconInfo *info;
3619 info = get_icon_info (window);
3624 if (info->using_themed_icon)
3626 GtkIconTheme *icon_theme;
3628 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3630 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3633 /* We don't clear the properties on the window, just figure the
3634 * window is going away.
3637 info->realized = FALSE;
3642 * gtk_window_set_icon_list:
3643 * @window: a #GtkWindow
3644 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3646 * Sets up the icon representing a #GtkWindow. The icon is used when
3647 * the window is minimized (also known as iconified). Some window
3648 * managers or desktop environments may also place it in the window
3649 * frame, or display it in other contexts.
3651 * gtk_window_set_icon_list() allows you to pass in the same icon in
3652 * several hand-drawn sizes. The list should contain the natural sizes
3653 * your icon is available in; that is, don't scale the image before
3654 * passing it to GTK+. Scaling is postponed until the last minute,
3655 * when the desired final size is known, to allow best quality.
3657 * By passing several sizes, you may improve the final image quality
3658 * of the icon, by reducing or eliminating automatic image scaling.
3660 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3661 * larger images (64x64, 128x128) if you have them.
3663 * See also gtk_window_set_default_icon_list() to set the icon
3664 * for all windows in your application in one go.
3666 * Note that transient windows (those who have been set transient for another
3667 * window using gtk_window_set_transient_for()) will inherit their
3668 * icon from their transient parent. So there's no need to explicitly
3669 * set the icon on transient windows.
3672 gtk_window_set_icon_list (GtkWindow *window,
3675 GtkWindowIconInfo *info;
3677 g_return_if_fail (GTK_IS_WINDOW (window));
3679 info = ensure_icon_info (window);
3681 if (info->icon_list == list) /* check for NULL mostly */
3684 g_list_foreach (list,
3685 (GFunc) g_object_ref, NULL);
3687 g_list_free_full (info->icon_list, g_object_unref);
3689 info->icon_list = g_list_copy (list);
3691 g_object_notify (G_OBJECT (window), "icon");
3693 gtk_window_unrealize_icon (window);
3695 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3696 gtk_window_realize_icon (window);
3698 /* We could try to update our transient children, but I don't think
3699 * it's really worth it. If we did it, the best way would probably
3700 * be to have children connect to notify::icon-list
3705 * gtk_window_get_icon_list:
3706 * @window: a #GtkWindow
3708 * Retrieves the list of icons set by gtk_window_set_icon_list().
3709 * The list is copied, but the reference count on each
3710 * member won't be incremented.
3712 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3715 gtk_window_get_icon_list (GtkWindow *window)
3717 GtkWindowIconInfo *info;
3719 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3721 info = get_icon_info (window);
3724 return g_list_copy (info->icon_list);
3730 * gtk_window_set_icon:
3731 * @window: a #GtkWindow
3732 * @icon: (allow-none): icon image, or %NULL
3734 * Sets up the icon representing a #GtkWindow. This icon is used when
3735 * the window is minimized (also known as iconified). Some window
3736 * managers or desktop environments may also place it in the window
3737 * frame, or display it in other contexts.
3739 * The icon should be provided in whatever size it was naturally
3740 * drawn; that is, don't scale the image before passing it to
3741 * GTK+. Scaling is postponed until the last minute, when the desired
3742 * final size is known, to allow best quality.
3744 * If you have your icon hand-drawn in multiple sizes, use
3745 * gtk_window_set_icon_list(). Then the best size will be used.
3747 * This function is equivalent to calling gtk_window_set_icon_list()
3748 * with a 1-element list.
3750 * See also gtk_window_set_default_icon_list() to set the icon
3751 * for all windows in your application in one go.
3754 gtk_window_set_icon (GtkWindow *window,
3759 g_return_if_fail (GTK_IS_WINDOW (window));
3760 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3765 list = g_list_append (list, icon);
3767 gtk_window_set_icon_list (window, list);
3773 update_themed_icon (GtkIconTheme *icon_theme,
3776 g_object_notify (G_OBJECT (window), "icon");
3778 gtk_window_unrealize_icon (window);
3780 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3781 gtk_window_realize_icon (window);
3785 * gtk_window_set_icon_name:
3786 * @window: a #GtkWindow
3787 * @name: (allow-none): the name of the themed icon
3789 * Sets the icon for the window from a named themed icon. See
3790 * the docs for #GtkIconTheme for more details.
3792 * Note that this has nothing to do with the WM_ICON_NAME
3793 * property which is mentioned in the ICCCM.
3798 gtk_window_set_icon_name (GtkWindow *window,
3801 GtkWindowIconInfo *info;
3804 g_return_if_fail (GTK_IS_WINDOW (window));
3806 info = ensure_icon_info (window);
3808 if (g_strcmp0 (info->icon_name, name) == 0)
3811 tmp = info->icon_name;
3812 info->icon_name = g_strdup (name);
3815 g_list_free_full (info->icon_list, g_object_unref);
3816 info->icon_list = NULL;
3818 update_themed_icon (NULL, window);
3820 g_object_notify (G_OBJECT (window), "icon-name");
3824 * gtk_window_get_icon_name:
3825 * @window: a #GtkWindow
3827 * Returns the name of the themed icon for the window,
3828 * see gtk_window_set_icon_name().
3830 * Returns: the icon name or %NULL if the window has
3836 gtk_window_get_icon_name (GtkWindow *window)
3838 GtkWindowIconInfo *info;
3840 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3842 info = ensure_icon_info (window);
3844 return info->icon_name;
3848 * gtk_window_get_icon:
3849 * @window: a #GtkWindow
3851 * Gets the value set by gtk_window_set_icon() (or if you've
3852 * called gtk_window_set_icon_list(), gets the first icon in
3855 * Return value: (transfer none): icon for window
3858 gtk_window_get_icon (GtkWindow *window)
3860 GtkWindowIconInfo *info;
3862 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3864 info = get_icon_info (window);
3865 if (info && info->icon_list)
3866 return GDK_PIXBUF (info->icon_list->data);
3871 /* Load pixbuf, printing warning on failure if error == NULL
3874 load_pixbuf_verbosely (const char *filename,
3877 GError *local_err = NULL;
3880 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3888 g_warning ("Error loading icon from file '%s':\n\t%s",
3889 filename, local_err->message);
3890 g_error_free (local_err);
3898 * gtk_window_set_icon_from_file:
3899 * @window: a #GtkWindow
3900 * @filename: (type filename): location of icon file
3901 * @err: (allow-none): location to store error, or %NULL.
3903 * Sets the icon for @window.
3904 * Warns on failure if @err is %NULL.
3906 * This function is equivalent to calling gtk_window_set_icon()
3907 * with a pixbuf created by loading the image from @filename.
3909 * Returns: %TRUE if setting the icon succeeded.
3914 gtk_window_set_icon_from_file (GtkWindow *window,
3915 const gchar *filename,
3918 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3922 gtk_window_set_icon (window, pixbuf);
3923 g_object_unref (pixbuf);
3932 * gtk_window_set_default_icon_list:
3933 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3935 * Sets an icon list to be used as fallback for windows that haven't
3936 * had gtk_window_set_icon_list() called on them to set up a
3937 * window-specific icon list. This function allows you to set up the
3938 * icon for all windows in your app at once.
3940 * See gtk_window_set_icon_list() for more details.
3944 gtk_window_set_default_icon_list (GList *list)
3948 if (list == default_icon_list)
3951 /* Update serial so we don't used cached pixmaps/masks
3953 default_icon_serial++;
3955 g_list_foreach (list,
3956 (GFunc) g_object_ref, NULL);
3958 g_list_free_full (default_icon_list, g_object_unref);
3960 default_icon_list = g_list_copy (list);
3962 /* Update all toplevels */
3963 toplevels = gtk_window_list_toplevels ();
3964 tmp_list = toplevels;
3965 while (tmp_list != NULL)
3967 GtkWindowIconInfo *info;
3968 GtkWindow *w = tmp_list->data;
3970 info = get_icon_info (w);
3971 if (info && info->using_default_icon)
3973 gtk_window_unrealize_icon (w);
3974 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3975 gtk_window_realize_icon (w);
3978 tmp_list = tmp_list->next;
3980 g_list_free (toplevels);
3984 * gtk_window_set_default_icon:
3987 * Sets an icon to be used as fallback for windows that haven't
3988 * had gtk_window_set_icon() called on them from a pixbuf.
3993 gtk_window_set_default_icon (GdkPixbuf *icon)
3997 g_return_if_fail (GDK_IS_PIXBUF (icon));
3999 list = g_list_prepend (NULL, icon);
4000 gtk_window_set_default_icon_list (list);
4005 * gtk_window_set_default_icon_name:
4006 * @name: the name of the themed icon
4008 * Sets an icon to be used as fallback for windows that haven't
4009 * had gtk_window_set_icon_list() called on them from a named
4010 * themed icon, see gtk_window_set_icon_name().
4015 gtk_window_set_default_icon_name (const gchar *name)
4020 /* Update serial so we don't used cached pixmaps/masks
4022 default_icon_serial++;
4024 g_free (default_icon_name);
4025 default_icon_name = g_strdup (name);
4027 g_list_free_full (default_icon_list, g_object_unref);
4028 default_icon_list = NULL;
4030 /* Update all toplevels */
4031 toplevels = gtk_window_list_toplevels ();
4032 tmp_list = toplevels;
4033 while (tmp_list != NULL)
4035 GtkWindowIconInfo *info;
4036 GtkWindow *w = tmp_list->data;
4038 info = get_icon_info (w);
4039 if (info && info->using_default_icon && info->using_themed_icon)
4041 gtk_window_unrealize_icon (w);
4042 if (gtk_widget_get_realized (GTK_WIDGET (w)))
4043 gtk_window_realize_icon (w);
4046 tmp_list = tmp_list->next;
4048 g_list_free (toplevels);
4052 * gtk_window_get_default_icon_name:
4054 * Returns the fallback icon name for windows that has been set
4055 * with gtk_window_set_default_icon_name(). The returned
4056 * string is owned by GTK+ and should not be modified. It
4057 * is only valid until the next call to
4058 * gtk_window_set_default_icon_name().
4060 * Returns: the fallback icon name for windows
4065 gtk_window_get_default_icon_name (void)
4067 return default_icon_name;
4071 * gtk_window_set_default_icon_from_file:
4072 * @filename: (type filename): location of icon file
4073 * @err: (allow-none): location to store error, or %NULL.
4075 * Sets an icon to be used as fallback for windows that haven't
4076 * had gtk_window_set_icon_list() called on them from a file
4077 * on disk. Warns on failure if @err is %NULL.
4079 * Returns: %TRUE if setting the icon succeeded.
4084 gtk_window_set_default_icon_from_file (const gchar *filename,
4087 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
4091 gtk_window_set_default_icon (pixbuf);
4092 g_object_unref (pixbuf);
4101 * gtk_window_get_default_icon_list:
4103 * Gets the value set by gtk_window_set_default_icon_list().
4104 * The list is a copy and should be freed with g_list_free(),
4105 * but the pixbufs in the list have not had their reference count
4108 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
4111 gtk_window_get_default_icon_list (void)
4113 return g_list_copy (default_icon_list);
4117 gtk_window_set_default_size_internal (GtkWindow *window,
4118 gboolean change_width,
4120 gboolean change_height,
4122 gboolean is_geometry)
4124 GtkWindowGeometryInfo *info;
4126 g_return_if_fail (change_width == FALSE || width >= -1);
4127 g_return_if_fail (change_height == FALSE || height >= -1);
4129 info = gtk_window_get_geometry_info (window, TRUE);
4131 g_object_freeze_notify (G_OBJECT (window));
4133 info->default_is_geometry = is_geometry != FALSE;
4143 info->default_width = width;
4145 g_object_notify (G_OBJECT (window), "default-width");
4156 info->default_height = height;
4158 g_object_notify (G_OBJECT (window), "default-height");
4161 g_object_thaw_notify (G_OBJECT (window));
4163 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4167 * gtk_window_set_default_size:
4168 * @window: a #GtkWindow
4169 * @width: width in pixels, or -1 to unset the default width
4170 * @height: height in pixels, or -1 to unset the default height
4172 * Sets the default size of a window. If the window's "natural" size
4173 * (its size request) is larger than the default, the default will be
4174 * ignored. More generally, if the default size does not obey the
4175 * geometry hints for the window (gtk_window_set_geometry_hints() can
4176 * be used to set these explicitly), the default size will be clamped
4177 * to the nearest permitted size.
4179 * Unlike gtk_widget_set_size_request(), which sets a size request for
4180 * a widget and thus would keep users from shrinking the window, this
4181 * function only sets the initial size, just as if the user had
4182 * resized the window themselves. Users can still shrink the window
4183 * again as they normally would. Setting a default size of -1 means to
4184 * use the "natural" default size (the size request of the window).
4186 * For more control over a window's initial size and how resizing works,
4187 * investigate gtk_window_set_geometry_hints().
4189 * For some uses, gtk_window_resize() is a more appropriate function.
4190 * gtk_window_resize() changes the current size of the window, rather
4191 * than the size to be used on initial display. gtk_window_resize() always
4192 * affects the window itself, not the geometry widget.
4194 * The default size of a window only affects the first time a window is
4195 * shown; if a window is hidden and re-shown, it will remember the size
4196 * it had prior to hiding, rather than using the default size.
4198 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4199 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4202 gtk_window_set_default_size (GtkWindow *window,
4206 g_return_if_fail (GTK_IS_WINDOW (window));
4207 g_return_if_fail (width >= -1);
4208 g_return_if_fail (height >= -1);
4210 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4214 * gtk_window_set_default_geometry:
4215 * @window: a #GtkWindow
4216 * @width: width in resize increments, or -1 to unset the default width
4217 * @height: height in resize increments, or -1 to unset the default height
4219 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4220 * in terms of the base size and increment set with
4221 * gtk_window_set_geometry_hints.
4226 gtk_window_set_default_geometry (GtkWindow *window,
4230 g_return_if_fail (GTK_IS_WINDOW (window));
4231 g_return_if_fail (width >= -1);
4232 g_return_if_fail (height >= -1);
4234 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4238 * gtk_window_get_default_size:
4239 * @window: a #GtkWindow
4240 * @width: (out) (allow-none): location to store the default width, or %NULL
4241 * @height: (out) (allow-none): location to store the default height, or %NULL
4243 * Gets the default size of the window. A value of -1 for the width or
4244 * height indicates that a default size has not been explicitly set
4245 * for that dimension, so the "natural" size of the window will be
4250 gtk_window_get_default_size (GtkWindow *window,
4254 GtkWindowGeometryInfo *info;
4256 g_return_if_fail (GTK_IS_WINDOW (window));
4258 info = gtk_window_get_geometry_info (window, FALSE);
4261 *width = info ? info->default_width : -1;
4264 *height = info ? info->default_height : -1;
4268 * gtk_window_resize:
4269 * @window: a #GtkWindow
4270 * @width: width in pixels to resize the window to
4271 * @height: height in pixels to resize the window to
4273 * Resizes the window as if the user had done so, obeying geometry
4274 * constraints. The default geometry constraint is that windows may
4275 * not be smaller than their size request; to override this
4276 * constraint, call gtk_widget_set_size_request() to set the window's
4277 * request to a smaller value.
4279 * If gtk_window_resize() is called before showing a window for the
4280 * first time, it overrides any default size set with
4281 * gtk_window_set_default_size().
4283 * Windows may not be resized smaller than 1 by 1 pixels.
4287 gtk_window_resize (GtkWindow *window,
4291 GtkWindowGeometryInfo *info;
4293 g_return_if_fail (GTK_IS_WINDOW (window));
4294 g_return_if_fail (width > 0);
4295 g_return_if_fail (height > 0);
4297 info = gtk_window_get_geometry_info (window, TRUE);
4299 info->resize_width = width;
4300 info->resize_height = height;
4301 info->resize_is_geometry = FALSE;
4303 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4307 * gtk_window_resize_to_geometry:
4308 * @window: a #GtkWindow
4309 * @width: width in resize increments to resize the window to
4310 * @height: height in resize increments to resize the window to
4312 * Like gtk_window_resize(), but @width and @height are interpreted
4313 * in terms of the base size and increment set with
4314 * gtk_window_set_geometry_hints.
4319 gtk_window_resize_to_geometry (GtkWindow *window,
4323 GtkWindowGeometryInfo *info;
4325 g_return_if_fail (GTK_IS_WINDOW (window));
4326 g_return_if_fail (width > 0);
4327 g_return_if_fail (height > 0);
4329 info = gtk_window_get_geometry_info (window, TRUE);
4331 info->resize_width = width;
4332 info->resize_height = height;
4333 info->resize_is_geometry = TRUE;
4335 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4339 * gtk_window_get_size:
4340 * @window: a #GtkWindow
4341 * @width: (out) (allow-none): return location for width, or %NULL
4342 * @height: (out) (allow-none): return location for height, or %NULL
4344 * Obtains the current size of @window. If @window is not onscreen,
4345 * it returns the size GTK+ will suggest to the <link
4346 * linkend="gtk-X11-arch">window manager</link> for the initial window
4347 * size (but this is not reliably the same as the size the window
4348 * manager will actually select). The size obtained by
4349 * gtk_window_get_size() is the last size received in a
4350 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4351 * rather than querying the X server for the size. As a result, if you
4352 * call gtk_window_resize() then immediately call
4353 * gtk_window_get_size(), the size won't have taken effect yet. After
4354 * the window manager processes the resize request, GTK+ receives
4355 * notification that the size has changed via a configure event, and
4356 * the size of the window gets updated.
4358 * Note 1: Nearly any use of this function creates a race condition,
4359 * because the size of the window may change between the time that you
4360 * get the size and the time that you perform some action assuming
4361 * that size is the current size. To avoid race conditions, connect to
4362 * "configure-event" on the window and adjust your size-dependent
4363 * state to match the size delivered in the #GdkEventConfigure.
4365 * Note 2: The returned size does <emphasis>not</emphasis> include the
4366 * size of the window manager decorations (aka the window frame or
4367 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4368 * method of determining their size.
4370 * Note 3: If you are getting a window size in order to position
4371 * the window onscreen, there may be a better way. The preferred
4372 * way is to simply set the window's semantic type with
4373 * gtk_window_set_type_hint(), which allows the window manager to
4374 * e.g. center dialogs. Also, if you set the transient parent of
4375 * dialogs with gtk_window_set_transient_for() window managers
4376 * will often center the dialog over its parent window. It's
4377 * much preferred to let the window manager handle these
4378 * things rather than doing it yourself, because all apps will
4379 * behave consistently and according to user prefs if the window
4380 * manager handles it. Also, the window manager can take the size
4381 * of the window decorations/border into account, while your
4382 * application cannot.
4384 * In any case, if you insist on application-specified window
4385 * positioning, there's <emphasis>still</emphasis> a better way than
4386 * doing it yourself - gtk_window_set_position() will frequently
4387 * handle the details for you.
4391 gtk_window_get_size (GtkWindow *window,
4397 g_return_if_fail (GTK_IS_WINDOW (window));
4399 if (width == NULL && height == NULL)
4402 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4404 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4405 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4409 GdkRectangle configure_request;
4411 gtk_window_compute_configure_request (window,
4415 w = configure_request.width;
4416 h = configure_request.height;
4427 * @window: a #GtkWindow
4428 * @x: X coordinate to move window to
4429 * @y: Y coordinate to move window to
4431 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4432 * @window to the given position. Window managers are free to ignore
4433 * this; most window managers ignore requests for initial window
4434 * positions (instead using a user-defined placement algorithm) and
4435 * honor requests after the window has already been shown.
4437 * Note: the position is the position of the gravity-determined
4438 * reference point for the window. The gravity determines two things:
4439 * first, the location of the reference point in root window
4440 * coordinates; and second, which point on the window is positioned at
4441 * the reference point.
4443 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4444 * point is simply the @x, @y supplied to gtk_window_move(). The
4445 * top-left corner of the window decorations (aka window frame or
4446 * border) will be placed at @x, @y. Therefore, to position a window
4447 * at the top left of the screen, you want to use the default gravity
4448 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4450 * To position a window at the bottom right corner of the screen, you
4451 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4452 * point is at @x + the window width and @y + the window height, and
4453 * the bottom-right corner of the window border will be placed at that
4454 * reference point. So, to place a window in the bottom right corner
4455 * you would first set gravity to south east, then write:
4456 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4457 * gdk_screen_height () - window_height)</literal> (note that this
4458 * example does not take multi-head scenarios into account).
4460 * The Extended Window Manager Hints specification at <ulink
4461 * url="http://www.freedesktop.org/Standards/wm-spec">
4462 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4463 * nice table of gravities in the "implementation notes" section.
4465 * The gtk_window_get_position() documentation may also be relevant.
4468 gtk_window_move (GtkWindow *window,
4472 GtkWindowGeometryInfo *info;
4475 g_return_if_fail (GTK_IS_WINDOW (window));
4477 widget = GTK_WIDGET (window);
4479 info = gtk_window_get_geometry_info (window, TRUE);
4481 if (gtk_widget_get_mapped (widget))
4483 GtkAllocation allocation;
4485 gtk_widget_get_allocation (widget, &allocation);
4487 /* we have now sent a request with this position
4488 * with currently-active constraints, so toggle flag.
4490 info->position_constraints_changed = FALSE;
4492 /* we only constrain if mapped - if not mapped,
4493 * then gtk_window_compute_configure_request()
4494 * will apply the constraints later, and we
4495 * don't want to lose information about
4496 * what position the user set before then.
4497 * i.e. if you do a move() then turn off POS_CENTER
4498 * then show the window, your move() will work.
4500 gtk_window_constrain_position (window,
4501 allocation.width, allocation.height,
4504 /* Note that this request doesn't go through our standard request
4505 * framework, e.g. doesn't increment configure_request_count,
4506 * doesn't set info->last, etc.; that's because
4507 * we don't save the info needed to arrive at this same request
4510 * To gtk_window_move_resize(), this will end up looking exactly
4511 * the same as the position being changed by the window
4514 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4518 /* Save this position to apply on mapping */
4519 info->initial_x = x;
4520 info->initial_y = y;
4521 info->initial_pos_set = TRUE;
4526 * gtk_window_get_position:
4527 * @window: a #GtkWindow
4528 * @root_x: (out) (allow-none): return location for X coordinate of
4529 * gravity-determined reference point, or %NULL
4530 * @root_y: (out) (allow-none): return location for Y coordinate of
4531 * gravity-determined reference point, or %NULL
4533 * This function returns the position you need to pass to
4534 * gtk_window_move() to keep @window in its current position.
4535 * This means that the meaning of the returned value varies with
4536 * window gravity. See gtk_window_move() for more details.
4538 * If you haven't changed the window gravity, its gravity will be
4539 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4540 * gets the position of the top-left corner of the window manager
4541 * frame for the window. gtk_window_move() sets the position of this
4542 * same top-left corner.
4544 * gtk_window_get_position() is not 100% reliable because the X Window System
4545 * does not specify a way to obtain the geometry of the
4546 * decorations placed on a window by the window manager.
4547 * Thus GTK+ is using a "best guess" that works with most
4550 * Moreover, nearly all window managers are historically broken with
4551 * respect to their handling of window gravity. So moving a window to
4552 * its current position as returned by gtk_window_get_position() tends
4553 * to result in moving the window slightly. Window managers are
4554 * slowly getting better over time.
4556 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4557 * frame is not relevant, and thus gtk_window_get_position() will
4558 * always produce accurate results. However you can't use static
4559 * gravity to do things like place a window in a corner of the screen,
4560 * because static gravity ignores the window manager decorations.
4562 * If you are saving and restoring your application's window
4563 * positions, you should know that it's impossible for applications to
4564 * do this without getting it somewhat wrong because applications do
4565 * not have sufficient knowledge of window manager state. The Correct
4566 * Mechanism is to support the session management protocol (see the
4567 * "GnomeClient" object in the GNOME libraries for example) and allow
4568 * the window manager to save your window sizes and positions.
4573 gtk_window_get_position (GtkWindow *window,
4577 GtkWindowPrivate *priv;
4579 GdkWindow *gdk_window;
4581 g_return_if_fail (GTK_IS_WINDOW (window));
4583 priv = window->priv;
4584 widget = GTK_WIDGET (window);
4585 gdk_window = gtk_widget_get_window (widget);
4587 if (priv->gravity == GDK_GRAVITY_STATIC)
4589 if (gtk_widget_get_mapped (widget))
4591 /* This does a server round-trip, which is sort of wrong;
4592 * but a server round-trip is inevitable for
4593 * gdk_window_get_frame_extents() in the usual
4594 * NorthWestGravity case below, so not sure what else to
4595 * do. We should likely be consistent about whether we get
4596 * the client-side info or the server-side info.
4598 gdk_window_get_origin (gdk_window, root_x, root_y);
4602 GdkRectangle configure_request;
4604 gtk_window_compute_configure_request (window,
4608 *root_x = configure_request.x;
4609 *root_y = configure_request.y;
4614 GdkRectangle frame_extents;
4619 if (gtk_widget_get_mapped (widget))
4621 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4622 x = frame_extents.x;
4623 y = frame_extents.y;
4624 gtk_window_get_size (window, &w, &h);
4628 /* We just say the frame has 0 size on all sides.
4629 * Not sure what else to do.
4631 gtk_window_compute_configure_request (window,
4634 x = frame_extents.x;
4635 y = frame_extents.y;
4636 w = frame_extents.width;
4637 h = frame_extents.height;
4640 switch (priv->gravity)
4642 case GDK_GRAVITY_NORTH:
4643 case GDK_GRAVITY_CENTER:
4644 case GDK_GRAVITY_SOUTH:
4645 /* Find center of frame. */
4646 x += frame_extents.width / 2;
4647 /* Center client window on that point. */
4651 case GDK_GRAVITY_SOUTH_EAST:
4652 case GDK_GRAVITY_EAST:
4653 case GDK_GRAVITY_NORTH_EAST:
4654 /* Find right edge of frame */
4655 x += frame_extents.width;
4656 /* Align left edge of client at that point. */
4663 switch (priv->gravity)
4665 case GDK_GRAVITY_WEST:
4666 case GDK_GRAVITY_CENTER:
4667 case GDK_GRAVITY_EAST:
4668 /* Find center of frame. */
4669 y += frame_extents.height / 2;
4670 /* Center client window there. */
4673 case GDK_GRAVITY_SOUTH_WEST:
4674 case GDK_GRAVITY_SOUTH:
4675 case GDK_GRAVITY_SOUTH_EAST:
4676 /* Find south edge of frame */
4677 y += frame_extents.height;
4678 /* Place bottom edge of client there */
4693 * gtk_window_reshow_with_initial_size:
4694 * @window: a #GtkWindow
4696 * Hides @window, then reshows it, resetting the
4697 * default size and position of the window. Used
4698 * by GUI builders only.
4701 gtk_window_reshow_with_initial_size (GtkWindow *window)
4705 g_return_if_fail (GTK_IS_WINDOW (window));
4707 widget = GTK_WIDGET (window);
4709 gtk_widget_hide (widget);
4710 gtk_widget_unrealize (widget);
4711 gtk_widget_show (widget);
4715 gtk_window_destroy (GtkWidget *widget)
4717 GtkWindow *window = GTK_WINDOW (widget);
4718 GtkWindowPrivate *priv = window->priv;
4720 gtk_window_release_application (window);
4722 toplevel_list = g_slist_remove (toplevel_list, window);
4724 if (priv->transient_parent)
4725 gtk_window_set_transient_for (window, NULL);
4727 remove_attach_widget (GTK_WINDOW (widget));
4729 /* frees the icons */
4730 gtk_window_set_icon_list (window, NULL);
4732 if (priv->has_user_ref_count)
4734 priv->has_user_ref_count = FALSE;
4735 g_object_unref (window);
4739 gtk_window_group_remove_window (priv->group, window);
4741 gtk_window_free_key_hash (window);
4743 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4747 gtk_window_finalize (GObject *object)
4749 GtkWindow *window = GTK_WINDOW (object);
4750 GtkWindowPrivate *priv = window->priv;
4751 GtkMnemonicHash *mnemonic_hash;
4753 g_free (priv->title);
4754 g_free (priv->wmclass_name);
4755 g_free (priv->wmclass_class);
4756 g_free (priv->wm_role);
4757 gtk_window_release_application (window);
4759 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4761 _gtk_mnemonic_hash_free (mnemonic_hash);
4763 if (priv->geometry_info)
4765 if (priv->geometry_info->widget)
4766 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4767 gtk_widget_destroyed,
4768 &priv->geometry_info->widget);
4769 g_free (priv->geometry_info);
4772 if (priv->keys_changed_handler)
4774 g_source_remove (priv->keys_changed_handler);
4775 priv->keys_changed_handler = 0;
4779 g_signal_handlers_disconnect_by_func (priv->screen,
4780 gtk_window_on_composited_changed, window);
4782 g_free (priv->startup_id);
4784 if (priv->auto_mnemonics_timeout_id)
4786 g_source_remove (priv->auto_mnemonics_timeout_id);
4787 priv->auto_mnemonics_timeout_id = 0;
4790 #ifdef GDK_WINDOWING_X11
4791 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4792 gtk_window_on_theme_variant_changed,
4796 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4800 gtk_window_show (GtkWidget *widget)
4802 GtkWindow *window = GTK_WINDOW (widget);
4803 GtkWindowPrivate *priv = window->priv;
4804 GtkContainer *container = GTK_CONTAINER (window);
4806 gboolean need_resize;
4809 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4811 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4815 _gtk_widget_set_visible_flag (widget, TRUE);
4817 need_resize = _gtk_widget_get_alloc_needed (widget) || !gtk_widget_get_realized (widget);
4819 empty = _gtk_bitmask_new ();
4820 _gtk_style_context_validate (gtk_widget_get_style_context (widget),
4821 g_get_monotonic_time (),
4824 _gtk_bitmask_free (empty);
4828 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4829 GtkAllocation allocation = { 0, 0 };
4830 GdkRectangle configure_request;
4831 GdkGeometry new_geometry;
4833 gboolean was_realized;
4835 /* We are going to go ahead and perform this configure request
4836 * and then emulate a configure notify by going ahead and
4837 * doing a size allocate. Sort of a synchronous
4838 * mini-copy of gtk_window_move_resize() here.
4840 gtk_window_compute_configure_request (window,
4845 /* We update this because we are going to go ahead
4846 * and gdk_window_resize() below, rather than
4849 info->last.configure_request.width = configure_request.width;
4850 info->last.configure_request.height = configure_request.height;
4852 /* and allocate the window - this is normally done
4853 * in move_resize in response to configure notify
4855 allocation.width = configure_request.width;
4856 allocation.height = configure_request.height;
4857 gtk_widget_size_allocate (widget, &allocation);
4859 /* Then we guarantee we have a realize */
4860 was_realized = FALSE;
4861 if (!gtk_widget_get_realized (widget))
4863 gtk_widget_realize (widget);
4864 was_realized = TRUE;
4867 /* We only send configure request if we didn't just finish
4868 * creating the window; if we just created the window
4869 * then we created it with widget->allocation anyhow.
4872 gdk_window_move_resize (gtk_widget_get_window (widget),
4873 configure_request.x,
4874 configure_request.y,
4875 configure_request.width,
4876 configure_request.height);
4879 gtk_container_check_resize (container);
4881 gtk_widget_map (widget);
4883 /* Try to make sure that we have some focused widget
4885 #ifdef GDK_WINDOWING_X11
4886 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4887 GTK_IS_PLUG (window);
4891 if (!priv->focus_widget && !is_plug)
4892 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4895 gtk_grab_add (widget);
4899 gtk_window_hide (GtkWidget *widget)
4901 GtkWindow *window = GTK_WINDOW (widget);
4902 GtkWindowPrivate *priv = window->priv;
4904 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4906 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4910 _gtk_widget_set_visible_flag (widget, FALSE);
4911 gtk_widget_unmap (widget);
4914 gtk_grab_remove (widget);
4918 gtk_window_map (GtkWidget *widget)
4921 GtkWindow *window = GTK_WINDOW (widget);
4922 GtkWindowPrivate *priv = window->priv;
4923 GdkWindow *gdk_window;
4924 gboolean auto_mnemonics;
4925 GtkPolicyType visible_focus;
4927 if (!gtk_widget_is_toplevel (widget))
4929 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4933 gtk_widget_set_mapped (widget, TRUE);
4935 child = gtk_bin_get_child (&(window->bin));
4937 gtk_widget_get_visible (child) &&
4938 !gtk_widget_get_mapped (child))
4939 gtk_widget_map (child);
4941 gdk_window = gtk_widget_get_window (widget);
4943 if (priv->maximize_initially)
4944 gdk_window_maximize (gdk_window);
4946 gdk_window_unmaximize (gdk_window);
4948 if (priv->stick_initially)
4949 gdk_window_stick (gdk_window);
4951 gdk_window_unstick (gdk_window);
4953 if (priv->iconify_initially)
4954 gdk_window_iconify (gdk_window);
4956 gdk_window_deiconify (gdk_window);
4958 if (priv->fullscreen_initially)
4959 gdk_window_fullscreen (gdk_window);
4961 gdk_window_unfullscreen (gdk_window);
4963 gdk_window_set_keep_above (gdk_window, priv->above_initially);
4965 gdk_window_set_keep_below (gdk_window, priv->below_initially);
4967 if (priv->type == GTK_WINDOW_TOPLEVEL)
4969 gtk_window_set_theme_variant (window);
4970 gtk_window_set_hide_titlebar_when_maximized (window,
4971 priv->hide_titlebar_when_maximized);
4974 /* No longer use the default settings */
4975 priv->need_default_size = FALSE;
4976 priv->need_default_position = FALSE;
4978 if (priv->reset_type_hint)
4980 /* We should only reset the type hint when the application
4981 * used gtk_window_set_type_hint() to change the hint.
4982 * Some applications use X directly to change the properties;
4983 * in that case, we shouldn't overwrite what they did.
4985 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4986 priv->reset_type_hint = FALSE;
4989 gdk_window_show (gdk_window);
4991 if (priv->grip_window)
4992 gdk_window_show (priv->grip_window);
4994 if (!disable_startup_notification)
4996 /* Do we have a custom startup-notification id? */
4997 if (priv->startup_id != NULL)
4999 /* Make sure we have a "real" id */
5000 if (!startup_id_is_fake (priv->startup_id))
5001 gdk_notify_startup_complete_with_id (priv->startup_id);
5003 g_free (priv->startup_id);
5004 priv->startup_id = NULL;
5006 else if (!sent_startup_notification)
5008 sent_startup_notification = TRUE;
5009 gdk_notify_startup_complete ();
5013 /* if auto-mnemonics is enabled and mnemonics visible is not already set
5014 * (as in the case of popup menus), then hide mnemonics initially
5016 g_object_get (gtk_widget_get_settings (widget),
5017 "gtk-auto-mnemonics", &auto_mnemonics,
5018 "gtk-visible-focus", &visible_focus,
5021 if (auto_mnemonics && !priv->mnemonics_visible_set)
5022 gtk_window_set_mnemonics_visible (window, FALSE);
5024 /* inherit from transient parent, so that a dialog that is
5025 * opened via keynav shows focus initially
5027 if (priv->transient_parent)
5028 gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
5030 gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
5034 gtk_window_map_event (GtkWidget *widget,
5037 if (!gtk_widget_get_mapped (widget))
5039 /* we should be be unmapped, but are getting a MapEvent, this may happen
5040 * to toplevel XWindows if mapping was intercepted by a window manager
5041 * and an unmap request occoured while the MapRequestEvent was still
5042 * being handled. we work around this situaiton here by re-requesting
5043 * the window being unmapped. more details can be found in:
5044 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
5046 gdk_window_hide (gtk_widget_get_window (widget));
5052 gtk_window_unmap (GtkWidget *widget)
5054 GtkWindow *window = GTK_WINDOW (widget);
5055 GtkWindowPrivate *priv = window->priv;
5057 GtkWindowGeometryInfo *info;
5058 GdkWindow *gdk_window;
5059 GdkWindowState state;
5061 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5063 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
5067 gdk_window = gtk_widget_get_window (widget);
5069 gtk_widget_set_mapped (widget, FALSE);
5070 gdk_window_withdraw (gdk_window);
5072 priv->configure_request_count = 0;
5073 priv->configure_notify_received = FALSE;
5075 /* on unmap, we reset the default positioning of the window,
5076 * so it's placed again, but we don't reset the default
5077 * size of the window, so it's remembered.
5079 priv->need_default_position = TRUE;
5081 info = gtk_window_get_geometry_info (window, FALSE);
5084 info->initial_pos_set = FALSE;
5085 info->position_constraints_changed = FALSE;
5088 state = gdk_window_get_state (gdk_window);
5089 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
5090 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
5091 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
5092 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
5093 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
5095 child = gtk_bin_get_child (&(window->bin));
5097 gtk_widget_unmap (child);
5100 /* (Note: Replace "size" with "width" or "height". Also, the request
5101 * mode is honoured.)
5102 * For selecting the default window size, the following conditions
5103 * should hold (in order of importance):
5104 * - the size is not below the minimum size
5105 * Windows cannot be resized below their minimum size, so we must
5106 * ensure we don't do that either.
5107 * - the size is not above the natural size
5108 * It seems weird to allocate more than this in an initial guess.
5109 * - the size does not exceed that of a maximized window
5110 * We want to see the whole window after all.
5111 * (Note that this may not be possible to achieve due to imperfect
5112 * information from the windowing system.)
5115 /* We use these for now to not make windows too big by accident. Note
5116 * that we still clamp these numbers by screen size. Also note that
5117 * minimum size still overrides this. So keep your windows small! :)
5119 #define MAX_DEFAULT_WINDOW_WIDTH 640
5120 #define MAX_DEFAULT_WINDOW_HEIGHT 480
5123 gtk_window_guess_default_size (GtkWindow *window,
5127 GtkWidget *widget = GTK_WIDGET (window);
5129 int minimum, natural;
5131 screen = gtk_widget_get_screen (widget);
5133 *width = gdk_screen_get_width (screen);
5134 *height = gdk_screen_get_height (screen);
5136 if (*width >= *height)
5139 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
5140 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
5145 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
5146 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
5149 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
5151 gtk_widget_get_preferred_height (widget, &minimum, &natural);
5152 *height = MAX (minimum, MIN (*height, natural));
5154 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
5155 *width = MAX (minimum, MIN (*width, natural));
5157 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
5159 gtk_widget_get_preferred_width (widget, &minimum, &natural);
5160 *width = MAX (minimum, MIN (*width, natural));
5162 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
5163 *height = MAX (minimum, MIN (*height, natural));
5168 gtk_window_realize (GtkWidget *widget)
5170 GtkAllocation allocation;
5172 GdkWindow *parent_window;
5173 GdkWindow *gdk_window;
5174 GdkWindowAttr attributes;
5175 gint attributes_mask;
5176 GtkWindowPrivate *priv;
5177 GtkStyleContext *context;
5179 window = GTK_WINDOW (widget);
5180 priv = window->priv;
5182 gtk_widget_get_allocation (widget, &allocation);
5184 if (gtk_widget_get_parent_window (widget))
5186 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
5188 gtk_widget_set_realized (widget, TRUE);
5190 attributes.x = allocation.x;
5191 attributes.y = allocation.y;
5192 attributes.width = allocation.width;
5193 attributes.height = allocation.height;
5194 attributes.window_type = GDK_WINDOW_CHILD;
5196 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
5198 attributes.visual = gtk_widget_get_visual (widget);
5199 attributes.wclass = GDK_INPUT_OUTPUT;
5201 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
5203 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
5204 &attributes, attributes_mask);
5205 gtk_widget_set_window (widget, gdk_window);
5206 gdk_window_set_user_data (gdk_window, widget);
5208 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
5210 gdk_window_enable_synchronized_configure (gdk_window);
5214 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5216 /* ensure widget tree is properly size allocated */
5217 if (allocation.x == -1 &&
5218 allocation.y == -1 &&
5219 allocation.width == 1 &&
5220 allocation.height == 1)
5226 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5227 if (allocation.width == 0 || allocation.height == 0)
5229 /* non-empty window */
5230 allocation.width = 200;
5231 allocation.height = 200;
5233 gtk_widget_size_allocate (widget, &allocation);
5235 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5237 g_return_if_fail (!gtk_widget_get_realized (widget));
5240 gtk_widget_set_realized (widget, TRUE);
5244 case GTK_WINDOW_TOPLEVEL:
5245 attributes.window_type = GDK_WINDOW_TOPLEVEL;
5247 case GTK_WINDOW_POPUP:
5248 attributes.window_type = GDK_WINDOW_TEMP;
5251 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5255 attributes.title = priv->title;
5256 attributes.wmclass_name = priv->wmclass_name;
5257 attributes.wmclass_class = priv->wmclass_class;
5258 attributes.wclass = GDK_INPUT_OUTPUT;
5259 attributes.visual = gtk_widget_get_visual (widget);
5261 attributes_mask = 0;
5262 parent_window = gtk_widget_get_root_window (widget);
5264 gtk_widget_get_allocation (widget, &allocation);
5265 attributes.width = allocation.width;
5266 attributes.height = allocation.height;
5267 attributes.event_mask = gtk_widget_get_events (widget);
5268 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5269 GDK_KEY_PRESS_MASK |
5270 GDK_KEY_RELEASE_MASK |
5271 GDK_ENTER_NOTIFY_MASK |
5272 GDK_LEAVE_NOTIFY_MASK |
5273 GDK_FOCUS_CHANGE_MASK |
5274 GDK_STRUCTURE_MASK);
5275 attributes.type_hint = priv->type_hint;
5277 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5278 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5279 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5281 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5282 gtk_widget_set_window (widget, gdk_window);
5284 if (priv->opacity_set)
5285 gdk_window_set_opacity (gdk_window, priv->opacity);
5287 gdk_window_enable_synchronized_configure (gdk_window);
5289 gdk_window_set_user_data (gdk_window, window);
5291 context = gtk_widget_get_style_context (widget);
5292 gtk_style_context_set_background (context, gdk_window);
5295 if (priv->transient_parent &&
5296 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5297 gdk_window_set_transient_for (gdk_window,
5298 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5301 gdk_window_set_role (gdk_window, priv->wm_role);
5303 if (!priv->decorated)
5304 gdk_window_set_decorations (gdk_window, 0);
5306 if (!priv->deletable)
5307 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5309 if (gtk_window_get_skip_pager_hint (window))
5310 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5312 if (gtk_window_get_skip_taskbar_hint (window))
5313 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5315 if (gtk_window_get_accept_focus (window))
5316 gdk_window_set_accept_focus (gdk_window, TRUE);
5318 gdk_window_set_accept_focus (gdk_window, FALSE);
5320 if (gtk_window_get_focus_on_map (window))
5321 gdk_window_set_focus_on_map (gdk_window, TRUE);
5323 gdk_window_set_focus_on_map (gdk_window, FALSE);
5326 gdk_window_set_modal_hint (gdk_window, TRUE);
5328 gdk_window_set_modal_hint (gdk_window, FALSE);
5330 if (priv->startup_id)
5332 #ifdef GDK_WINDOWING_X11
5333 if (GDK_IS_X11_WINDOW (gdk_window))
5335 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5336 if (timestamp != GDK_CURRENT_TIME)
5337 gdk_x11_window_set_user_time (gdk_window, timestamp);
5340 if (!startup_id_is_fake (priv->startup_id))
5341 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5344 #ifdef GDK_WINDOWING_X11
5345 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5347 if (GDK_IS_X11_WINDOW (gdk_window))
5348 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5353 gtk_window_realize_icon (window);
5355 if (priv->has_resize_grip)
5356 resize_grip_create_window (window);
5360 gtk_window_unrealize (GtkWidget *widget)
5362 GtkWindow *window = GTK_WINDOW (widget);
5363 GtkWindowPrivate *priv = window->priv;
5364 GtkWindowGeometryInfo *info;
5366 /* On unrealize, we reset the size of the window such
5367 * that we will re-apply the default sizing stuff
5368 * next time we show the window.
5370 * Default positioning is reset on unmap, instead of unrealize.
5372 priv->need_default_size = TRUE;
5373 info = gtk_window_get_geometry_info (window, FALSE);
5376 info->resize_width = -1;
5377 info->resize_height = -1;
5378 info->last.configure_request.x = 0;
5379 info->last.configure_request.y = 0;
5380 info->last.configure_request.width = -1;
5381 info->last.configure_request.height = -1;
5382 /* be sure we reset geom hints on re-realize */
5383 info->last.flags = 0;
5387 gtk_window_unrealize_icon (window);
5389 if (priv->grip_window != NULL)
5390 resize_grip_destroy_window (window);
5392 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5395 static GtkJunctionSides
5396 get_grip_junction (GtkWidget *widget)
5398 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5399 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5401 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5405 get_drag_edge (GtkWidget *widget,
5406 GdkWindowEdge *edge)
5408 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5409 gboolean hresizable;
5410 gboolean vresizable;
5411 GtkTextDirection dir;
5412 GtkWindowGeometryInfo *info;
5417 info = priv->geometry_info;
5420 GdkWindowHints flags = info->last.flags;
5421 GdkGeometry *geometry = &info->last.geometry;
5423 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5425 hresizable = geometry->min_width < geometry->max_width;
5426 vresizable = geometry->min_height < geometry->max_height;
5430 dir = gtk_widget_get_direction (widget);
5432 if (hresizable && vresizable)
5433 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5434 else if (hresizable)
5435 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5436 else if (vresizable)
5437 *edge = GDK_WINDOW_EDGE_SOUTH;
5445 set_grip_cursor (GtkWindow *window)
5447 GtkWidget *widget = GTK_WIDGET (window);
5448 GtkWindowPrivate *priv = window->priv;
5450 if (priv->grip_window == NULL)
5453 if (gtk_widget_is_sensitive (widget))
5456 GdkDisplay *display;
5457 GdkCursorType cursor_type;
5460 cursor_type = GDK_LEFT_PTR;
5462 if (get_drag_edge (widget, &edge))
5466 case GDK_WINDOW_EDGE_EAST:
5467 cursor_type = GDK_RIGHT_SIDE;
5469 case GDK_WINDOW_EDGE_SOUTH_EAST:
5470 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5472 case GDK_WINDOW_EDGE_SOUTH:
5473 cursor_type = GDK_BOTTOM_SIDE;
5475 case GDK_WINDOW_EDGE_SOUTH_WEST:
5476 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5478 case GDK_WINDOW_EDGE_WEST:
5479 cursor_type = GDK_LEFT_SIDE;
5485 display = gtk_widget_get_display (widget);
5486 cursor = gdk_cursor_new_for_display (display, cursor_type);
5487 gdk_window_set_cursor (priv->grip_window, cursor);
5488 g_object_unref (cursor);
5491 gdk_window_set_cursor (priv->grip_window, NULL);
5495 set_grip_shape (GtkWindow *window)
5497 GtkWindowPrivate *priv = window->priv;
5498 cairo_region_t *region;
5499 cairo_surface_t *surface;
5501 double width, height;
5503 if (priv->grip_window == NULL)
5506 width = gdk_window_get_width (priv->grip_window);
5507 height = gdk_window_get_height (priv->grip_window);
5508 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
5510 cr = cairo_create (surface);
5511 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5513 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5514 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5516 cairo_move_to (cr, width, 0.0);
5517 cairo_line_to (cr, width, height);
5518 cairo_line_to (cr, 0.0, height);
5522 cairo_move_to (cr, 0.0, 0.0);
5523 cairo_line_to (cr, width, height);
5524 cairo_line_to (cr, 0.0, height);
5526 cairo_close_path (cr);
5529 region = gdk_cairo_region_create_from_surface (surface);
5530 cairo_surface_destroy (surface);
5532 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5533 cairo_region_destroy (region);
5537 set_grip_position (GtkWindow *window)
5539 GtkWindowPrivate *priv = window->priv;
5542 if (priv->grip_window == NULL)
5545 gtk_window_get_resize_grip_area (window, &rect);
5546 gdk_window_raise (priv->grip_window);
5547 gdk_window_move_resize (priv->grip_window,
5549 rect.width, rect.height);
5552 /* _gtk_window_set_allocation:
5553 * @window: a #GtkWindow
5554 * @allocation: the new allocation
5556 * This function is like gtk_widget_set_allocation()
5557 * but does the necessary extra work to update
5558 * the resize grip positioning, etc.
5560 * Call this instead of gtk_widget_set_allocation()
5561 * when overriding ::size_allocate in a GtkWindow
5562 * subclass without chaining up.
5565 _gtk_window_set_allocation (GtkWindow *window,
5566 GtkAllocation *allocation)
5568 GtkWidget *widget = (GtkWidget *)window;
5570 gtk_widget_set_allocation (widget, allocation);
5572 if (gtk_widget_get_realized (widget))
5574 /* If it's not a toplevel we're embedded, we need to resize
5575 * the window's window and skip the grip.
5577 if (!gtk_widget_is_toplevel (widget))
5579 gdk_window_move_resize (gtk_widget_get_window (widget),
5580 allocation->x, allocation->y,
5581 allocation->width, allocation->height);
5585 update_grip_visibility (window);
5586 set_grip_position (window);
5592 gtk_window_size_allocate (GtkWidget *widget,
5593 GtkAllocation *allocation)
5595 GtkWindow *window = GTK_WINDOW (widget);
5596 GtkAllocation child_allocation;
5600 _gtk_window_set_allocation (window, allocation);
5602 child = gtk_bin_get_child (&(window->bin));
5603 if (child && gtk_widget_get_visible (child))
5605 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5606 child_allocation.x = border_width;
5607 child_allocation.y = border_width;
5608 child_allocation.width = MAX (1, allocation->width - border_width * 2);
5609 child_allocation.height = MAX (1, allocation->height - border_width * 2);
5611 gtk_widget_size_allocate (child, &child_allocation);
5616 gtk_window_configure_event (GtkWidget *widget,
5617 GdkEventConfigure *event)
5619 GtkAllocation allocation;
5620 GtkWindow *window = GTK_WINDOW (widget);
5621 GtkWindowPrivate *priv = window->priv;
5622 gboolean expected_reply = priv->configure_request_count > 0;
5624 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5626 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5627 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5629 gdk_window_configure_finished (gtk_widget_get_window (widget));
5633 /* priv->configure_request_count incremented for each
5634 * configure request, and decremented to a min of 0 for
5635 * each configure notify.
5637 * All it means is that we know we will get at least
5638 * priv->configure_request_count more configure notifies.
5639 * We could get more configure notifies than that; some
5640 * of the configure notifies we get may be unrelated to
5641 * the configure requests. But we will get at least
5642 * priv->configure_request_count notifies.
5645 if (priv->configure_request_count > 0)
5647 priv->configure_request_count -= 1;
5648 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5651 /* As an optimization, we avoid a resize when possible.
5653 * The only times we can avoid a resize are:
5654 * - we know only the position changed, not the size
5655 * - we know we have made more requests and so will get more
5656 * notifies and can wait to resize when we get them
5658 gtk_widget_get_allocation (widget, &allocation);
5659 if (!expected_reply &&
5660 (allocation.width == event->width &&
5661 allocation.height == event->height))
5663 gdk_window_configure_finished (gtk_widget_get_window (widget));
5668 * If we do need to resize, we do that by:
5669 * - setting configure_notify_received to TRUE
5670 * for use in gtk_window_move_resize()
5671 * - queueing a resize, leading to invocation of
5672 * gtk_window_move_resize() in an idle handler
5676 priv->configure_notify_received = TRUE;
5678 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5680 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5686 gtk_window_state_event (GtkWidget *widget,
5687 GdkEventWindowState *event)
5689 update_grip_visibility (GTK_WINDOW (widget));
5691 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
5692 ensure_state_flag_backdrop (widget);
5698 gtk_window_direction_changed (GtkWidget *widget,
5699 GtkTextDirection prev_dir)
5701 GtkWindow *window = GTK_WINDOW (widget);
5703 set_grip_cursor (window);
5704 set_grip_position (window);
5705 set_grip_shape (window);
5709 gtk_window_state_changed (GtkWidget *widget,
5710 GtkStateType previous_state)
5712 GtkWindow *window = GTK_WINDOW (widget);
5714 update_grip_visibility (window);
5718 gtk_window_style_updated (GtkWidget *widget)
5720 GtkWindow *window = GTK_WINDOW (widget);
5721 GtkWindowPrivate *priv = window->priv;
5724 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5726 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5728 gdk_window_move_resize (priv->grip_window,
5730 rect.width, rect.height);
5732 set_grip_shape (window);
5737 resize_grip_create_window (GtkWindow *window)
5740 GtkWindowPrivate *priv;
5741 GdkWindowAttr attributes;
5742 gint attributes_mask;
5744 GdkRGBA transparent = {0, 0, 0, 0};
5746 priv = window->priv;
5747 widget = GTK_WIDGET (window);
5749 g_return_if_fail (gtk_widget_get_realized (widget));
5750 g_return_if_fail (priv->grip_window == NULL);
5752 gtk_window_get_resize_grip_area (window, &rect);
5754 attributes.x = rect.x;
5755 attributes.y = rect.y;
5756 attributes.width = rect.width;
5757 attributes.height = rect.height;
5758 attributes.window_type = GDK_WINDOW_CHILD;
5759 attributes.wclass = GDK_INPUT_OUTPUT;
5760 attributes.event_mask = gtk_widget_get_events (widget) |
5762 GDK_BUTTON_PRESS_MASK;
5764 attributes_mask = GDK_WA_X | GDK_WA_Y;
5766 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5769 gdk_window_set_background_rgba (priv->grip_window, &transparent);
5771 gdk_window_set_user_data (priv->grip_window, widget);
5773 gdk_window_raise (priv->grip_window);
5775 set_grip_shape (window);
5776 update_grip_visibility (window);
5780 resize_grip_destroy_window (GtkWindow *window)
5782 GtkWindowPrivate *priv = window->priv;
5784 gdk_window_set_user_data (priv->grip_window, NULL);
5785 gdk_window_destroy (priv->grip_window);
5786 priv->grip_window = NULL;
5787 update_grip_visibility (window);
5791 * gtk_window_set_has_resize_grip:
5792 * @window: a #GtkWindow
5793 * @value: %TRUE to allow a resize grip
5795 * Sets whether @window has a corner resize grip.
5797 * Note that the resize grip is only shown if the window
5798 * is actually resizable and not maximized. Use
5799 * gtk_window_resize_grip_is_visible() to find out if the
5800 * resize grip is currently shown.
5805 gtk_window_set_has_resize_grip (GtkWindow *window,
5808 GtkWidget *widget = GTK_WIDGET (window);
5809 GtkWindowPrivate *priv = window->priv;
5811 value = value != FALSE;
5813 if (value != priv->has_resize_grip)
5815 priv->has_resize_grip = value;
5816 gtk_widget_queue_draw (widget);
5818 if (gtk_widget_get_realized (widget) &&
5819 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5821 if (priv->has_resize_grip && priv->grip_window == NULL)
5822 resize_grip_create_window (window);
5823 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5824 resize_grip_destroy_window (window);
5827 g_object_notify (G_OBJECT (window), "has-resize-grip");
5832 update_grip_visibility (GtkWindow *window)
5834 GtkWindowPrivate *priv = window->priv;
5837 val = gtk_window_resize_grip_is_visible (window);
5839 if (priv->grip_window != NULL)
5843 gdk_window_show (priv->grip_window);
5844 set_grip_cursor (window);
5848 gdk_window_hide (priv->grip_window);
5852 if (priv->resize_grip_visible != val)
5854 priv->resize_grip_visible = val;
5856 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5861 * gtk_window_resize_grip_is_visible:
5862 * @window: a #GtkWindow
5864 * Determines whether a resize grip is visible for the specified window.
5866 * Returns: %TRUE if a resize grip exists and is visible
5871 gtk_window_resize_grip_is_visible (GtkWindow *window)
5874 GtkWindowPrivate *priv;
5877 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5879 priv = window->priv;
5880 widget = GTK_WIDGET (window);
5882 if (priv->type == GTK_WINDOW_POPUP)
5885 if (!priv->resizable)
5888 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5891 if (gtk_widget_get_realized (widget))
5893 GdkWindowState state;
5895 state = gdk_window_get_state (gtk_widget_get_window (widget));
5897 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5901 if (!get_drag_edge (widget, &edge))
5904 return window->priv->has_resize_grip;
5908 * gtk_window_get_has_resize_grip:
5909 * @window: a #GtkWindow
5911 * Determines whether the window may have a resize grip.
5913 * Returns: %TRUE if the window has a resize grip
5918 gtk_window_get_has_resize_grip (GtkWindow *window)
5920 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5922 return window->priv->has_resize_grip;
5926 * gtk_window_get_resize_grip_area:
5927 * @window: a #GtkWindow
5928 * @rect: (out): a pointer to a #GdkRectangle which we should store
5929 * the resize grip area
5931 * If a window has a resize grip, this will retrieve the grip
5932 * position, width and height into the specified #GdkRectangle.
5934 * Returns: %TRUE if the resize grip's area was retrieved
5939 gtk_window_get_resize_grip_area (GtkWindow *window,
5942 GtkWidget *widget = GTK_WIDGET (window);
5943 GtkAllocation allocation;
5947 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5949 if (!window->priv->has_resize_grip)
5952 gtk_widget_get_allocation (widget, &allocation);
5954 gtk_widget_style_get (widget,
5955 "resize-grip-width", &grip_width,
5956 "resize-grip-height", &grip_height,
5959 if (grip_width > allocation.width)
5960 grip_width = allocation.width;
5962 if (grip_height > allocation.height)
5963 grip_height = allocation.height;
5965 rect->width = grip_width;
5966 rect->height = grip_height;
5967 rect->y = allocation.y + allocation.height - grip_height;
5969 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5970 rect->x = allocation.x + allocation.width - grip_width;
5972 rect->x = allocation.x;
5977 /* the accel_key and accel_mods fields of the key have to be setup
5978 * upon calling this function. it'll then return whether that key
5979 * is at all used as accelerator, and if so will OR in the
5980 * accel_flags member of the key.
5983 _gtk_window_query_nonaccels (GtkWindow *window,
5985 GdkModifierType accel_mods)
5987 GtkWindowPrivate *priv;
5989 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5991 priv = window->priv;
5993 /* movement keys are considered locked accels */
5996 static const guint bindings[] = {
5997 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,
5998 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,
6002 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
6003 if (bindings[i] == accel_key)
6007 /* mnemonics are considered locked accels */
6008 if (accel_mods == priv->mnemonic_modifier)
6010 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
6011 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
6019 * gtk_window_propagate_key_event:
6020 * @window: a #GtkWindow
6021 * @event: a #GdkEventKey
6023 * Propagate a key press or release event to the focus widget and
6024 * up the focus container chain until a widget handles @event.
6025 * This is normally called by the default ::key_press_event and
6026 * ::key_release_event handlers for toplevel windows,
6027 * however in some cases it may be useful to call this directly when
6028 * overriding the standard key handling for a toplevel window.
6030 * Return value: %TRUE if a widget in the focus chain handled the event.
6035 gtk_window_propagate_key_event (GtkWindow *window,
6038 GtkWindowPrivate *priv;
6039 gboolean handled = FALSE;
6040 GtkWidget *widget, *focus;
6042 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6044 priv = window->priv;
6045 widget = GTK_WIDGET (window);
6047 focus = priv->focus_widget;
6049 g_object_ref (focus);
6052 focus && focus != widget &&
6053 gtk_widget_get_toplevel (focus) == widget)
6057 if (gtk_widget_is_sensitive (focus))
6058 handled = gtk_widget_event (focus, (GdkEvent*) event);
6060 parent = gtk_widget_get_parent (focus);
6062 g_object_ref (parent);
6064 g_object_unref (focus);
6070 g_object_unref (focus);
6076 gtk_window_key_press_event (GtkWidget *widget,
6079 GtkWindow *window = GTK_WINDOW (widget);
6080 gboolean handled = FALSE;
6082 /* handle mnemonics and accelerators */
6084 handled = gtk_window_activate_key (window, event);
6086 /* handle focus widget key events */
6088 handled = gtk_window_propagate_key_event (window, event);
6090 /* Chain up, invokes binding set */
6092 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
6098 gtk_window_key_release_event (GtkWidget *widget,
6101 GtkWindow *window = GTK_WINDOW (widget);
6102 gboolean handled = FALSE;
6104 /* handle focus widget key events */
6106 handled = gtk_window_propagate_key_event (window, event);
6108 /* Chain up, invokes binding set */
6110 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
6116 gtk_window_button_press_event (GtkWidget *widget,
6117 GdkEventButton *event)
6119 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
6122 if (event->window == priv->grip_window)
6124 if (get_drag_edge (widget, &edge))
6125 gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
6127 gdk_event_get_device ((GdkEvent *) event),
6140 gtk_window_real_activate_default (GtkWindow *window)
6142 gtk_window_activate_default (window);
6146 gtk_window_real_activate_focus (GtkWindow *window)
6148 gtk_window_activate_focus (window);
6152 gtk_window_enter_notify_event (GtkWidget *widget,
6153 GdkEventCrossing *event)
6159 gtk_window_leave_notify_event (GtkWidget *widget,
6160 GdkEventCrossing *event)
6166 do_focus_change (GtkWidget *widget,
6170 GdkDeviceManager *device_manager;
6173 g_object_ref (widget);
6175 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
6176 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6177 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
6178 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
6180 for (d = devices; d; d = d->next)
6182 GdkDevice *dev = d->data;
6185 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
6188 /* Skip non-master keyboards that haven't
6189 * selected for events from this window
6191 window = gtk_widget_get_window (widget);
6192 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
6193 window && !gdk_window_get_device_events (window, dev))
6196 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
6198 fevent->focus_change.type = GDK_FOCUS_CHANGE;
6199 fevent->focus_change.window = window;
6201 g_object_ref (window);
6202 fevent->focus_change.in = in;
6203 gdk_event_set_device (fevent, dev);
6205 gtk_widget_send_focus_change (widget, fevent);
6207 gdk_event_free (fevent);
6210 g_list_free (devices);
6211 g_object_unref (widget);
6215 maybe_set_mnemonics_visible (GtkWindow *window)
6218 GdkDeviceManager *device_manager;
6220 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
6221 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6223 for (d = devices; d; d = d->next)
6225 GdkDevice *dev = d->data;
6227 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6229 GdkModifierType mask;
6231 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6233 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6235 _gtk_window_set_auto_mnemonics_visible (window);
6241 g_list_free (devices);
6245 gtk_window_focus_in_event (GtkWidget *widget,
6246 GdkEventFocus *event)
6248 GtkWindow *window = GTK_WINDOW (widget);
6249 gboolean auto_mnemonics;
6251 /* It appears spurious focus in events can occur when
6252 * the window is hidden. So we'll just check to see if
6253 * the window is visible before actually handling the
6256 if (gtk_widget_get_visible (widget))
6258 _gtk_window_set_has_toplevel_focus (window, TRUE);
6259 _gtk_window_set_is_active (window, TRUE);
6261 g_object_get (gtk_widget_get_settings (widget),
6262 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6264 maybe_set_mnemonics_visible (window);
6271 gtk_window_focus_out_event (GtkWidget *widget,
6272 GdkEventFocus *event)
6274 GtkWindow *window = GTK_WINDOW (widget);
6275 gboolean auto_mnemonics;
6277 _gtk_window_set_has_toplevel_focus (window, FALSE);
6278 _gtk_window_set_is_active (window, FALSE);
6280 /* set the mnemonic-visible property to false */
6281 g_object_get (gtk_widget_get_settings (widget),
6282 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6284 gtk_window_set_mnemonics_visible (window, FALSE);
6290 gtk_window_check_resize (GtkContainer *container)
6292 /* If the window is not toplevel anymore than it's embedded somewhere,
6293 * so handle it like a normal window */
6294 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6295 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6296 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6297 gtk_window_move_resize (GTK_WINDOW (container));
6301 gtk_window_focus (GtkWidget *widget,
6302 GtkDirectionType direction)
6304 GtkWindowPrivate *priv;
6307 GtkContainer *container;
6309 GtkWidget *old_focus_child;
6312 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6313 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6315 container = GTK_CONTAINER (widget);
6316 window = GTK_WINDOW (widget);
6317 priv = window->priv;
6318 bin = GTK_BIN (widget);
6320 old_focus_child = gtk_container_get_focus_child (container);
6322 /* We need a special implementation here to deal properly with wrapping
6323 * around in the tab chain without the danger of going into an
6326 if (old_focus_child)
6328 if (gtk_widget_child_focus (old_focus_child, direction))
6332 if (priv->focus_widget)
6334 if (direction == GTK_DIR_LEFT ||
6335 direction == GTK_DIR_RIGHT ||
6336 direction == GTK_DIR_UP ||
6337 direction == GTK_DIR_DOWN)
6342 /* Wrapped off the end, clear the focus setting for the toplpevel */
6343 parent = gtk_widget_get_parent (priv->focus_widget);
6346 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6347 parent = gtk_widget_get_parent (parent);
6350 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6353 /* Now try to focus the first widget in the window */
6354 child = gtk_bin_get_child (bin);
6357 if (gtk_widget_child_focus (child, direction))
6365 gtk_window_move_focus (GtkWidget *widget,
6366 GtkDirectionType dir)
6368 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6370 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6374 gtk_widget_child_focus (widget, dir);
6376 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6377 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6381 gtk_window_real_set_focus (GtkWindow *window,
6384 GtkWindowPrivate *priv = window->priv;
6385 GtkWidget *old_focus = priv->focus_widget;
6386 gboolean had_default = FALSE;
6387 gboolean focus_had_default = FALSE;
6388 gboolean old_focus_had_default = FALSE;
6392 g_object_ref (old_focus);
6393 g_object_freeze_notify (G_OBJECT (old_focus));
6394 old_focus_had_default = gtk_widget_has_default (old_focus);
6398 g_object_ref (focus);
6399 g_object_freeze_notify (G_OBJECT (focus));
6400 focus_had_default = gtk_widget_has_default (focus);
6403 if (priv->default_widget)
6404 had_default = gtk_widget_has_default (priv->default_widget);
6406 if (priv->focus_widget)
6408 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6409 (priv->focus_widget != priv->default_widget))
6411 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6412 gtk_widget_queue_draw (priv->focus_widget);
6414 if (priv->default_widget)
6415 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6418 priv->focus_widget = NULL;
6420 if (priv->has_focus)
6421 do_focus_change (old_focus, FALSE);
6423 g_object_notify (G_OBJECT (old_focus), "is-focus");
6426 /* The above notifications may have set a new focus widget,
6427 * if so, we don't want to override it.
6429 if (focus && !priv->focus_widget)
6431 priv->focus_widget = focus;
6433 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6434 (priv->focus_widget != priv->default_widget))
6436 if (gtk_widget_get_can_default (priv->focus_widget))
6437 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6439 if (priv->default_widget)
6440 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6443 if (priv->has_focus)
6444 do_focus_change (priv->focus_widget, TRUE);
6446 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6449 /* If the default widget changed, a redraw will have been queued
6450 * on the old and new default widgets by gtk_window_set_default(), so
6451 * we only have to worry about the case where it didn't change.
6452 * We'll sometimes queue a draw twice on the new widget but that
6455 if (priv->default_widget &&
6456 (had_default != gtk_widget_has_default (priv->default_widget)))
6457 gtk_widget_queue_draw (priv->default_widget);
6461 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6462 gtk_widget_queue_draw (old_focus);
6464 g_object_thaw_notify (G_OBJECT (old_focus));
6465 g_object_unref (old_focus);
6469 if (focus_had_default != gtk_widget_has_default (focus))
6470 gtk_widget_queue_draw (focus);
6472 g_object_thaw_notify (G_OBJECT (focus));
6473 g_object_unref (focus);
6478 * _gtk_window_unset_focus_and_default:
6479 * @window: a #GtkWindow
6480 * @widget: a widget inside of @window
6482 * Checks whether the focus and default widgets of @window are
6483 * @widget or a descendent of @widget, and if so, unset them.
6486 _gtk_window_unset_focus_and_default (GtkWindow *window,
6490 GtkWindowPrivate *priv = window->priv;
6494 g_object_ref (window);
6495 g_object_ref (widget);
6497 parent = gtk_widget_get_parent (widget);
6498 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6500 child = priv->focus_widget;
6502 while (child && child != widget)
6503 child = gtk_widget_get_parent (child);
6505 if (child == widget)
6506 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6509 child = priv->default_widget;
6511 while (child && child != widget)
6512 child = gtk_widget_get_parent (child);
6514 if (child == widget)
6515 gtk_window_set_default (window, NULL);
6517 g_object_unref (widget);
6518 g_object_unref (window);
6521 /*********************************
6522 * Functions related to resizing *
6523 *********************************/
6526 geometry_size_to_pixels (GdkGeometry *geometry,
6531 gint base_width = 0;
6532 gint base_height = 0;
6534 gint min_height = 0;
6536 gint height_inc = 1;
6538 if (flags & GDK_HINT_BASE_SIZE)
6540 base_width = geometry->base_width;
6541 base_height = geometry->base_height;
6543 if (flags & GDK_HINT_MIN_SIZE)
6545 min_width = geometry->min_width;
6546 min_height = geometry->min_height;
6548 if (flags & GDK_HINT_RESIZE_INC)
6550 width_inc = geometry->width_inc;
6551 height_inc = geometry->height_inc;
6555 *width = MAX (*width * width_inc + base_width, min_width);
6557 *height = MAX (*height * height_inc + base_height, min_height);
6560 /* This function doesn't constrain to geometry hints */
6562 gtk_window_compute_configure_request_size (GtkWindow *window,
6563 GdkGeometry *geometry,
6568 GtkWindowPrivate *priv = window->priv;
6569 GtkWindowGeometryInfo *info;
6572 * - we've done a size request
6575 info = gtk_window_get_geometry_info (window, FALSE);
6577 if (priv->need_default_size)
6579 gtk_window_guess_default_size (window, width, height);
6581 /* If window is empty so requests 0, default to random nonzero size */
6582 if (*width == 0 && *height == 0)
6588 /* Override with default size */
6592 if (info->default_width > 0)
6593 *width = info->default_width;
6594 if (info->default_height > 0)
6595 *height = info->default_height;
6597 if (info->default_is_geometry)
6598 geometry_size_to_pixels (geometry, flags,
6599 info->default_width > 0 ? width : NULL,
6600 info->default_height > 0 ? height : NULL);
6605 GtkAllocation allocation;
6607 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6609 /* Default to keeping current size */
6610 *width = allocation.width;
6611 *height = allocation.height;
6614 /* Override any size with gtk_window_resize() values */
6617 if (info->resize_width > 0)
6618 *width = info->resize_width;
6619 if (info->resize_height > 0)
6620 *height = info->resize_height;
6622 if (info->resize_is_geometry)
6623 geometry_size_to_pixels (geometry, flags,
6624 info->resize_width > 0 ? width : NULL,
6625 info->resize_height > 0 ? height : NULL);
6628 /* Don't ever request zero width or height, its not supported by
6629 gdk. The size allocation code will round it to 1 anyway but if
6630 we do it then the value returned from this function will is
6631 not comparable to the size allocation read from the GtkWindow. */
6632 *width = MAX (*width, 1);
6633 *height = MAX (*height, 1);
6636 static GtkWindowPosition
6637 get_effective_position (GtkWindow *window)
6639 GtkWindowPrivate *priv = window->priv;
6640 GtkWindowPosition pos = priv->position;
6642 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6643 (priv->transient_parent == NULL ||
6644 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6645 pos = GTK_WIN_POS_NONE;
6651 get_center_monitor_of_window (GtkWindow *window)
6653 /* We could try to sort out the relative positions of the monitors and
6654 * stuff, or we could just be losers and assume you have a row
6655 * or column of monitors.
6657 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6661 get_monitor_containing_pointer (GtkWindow *window)
6665 GdkScreen *window_screen;
6666 GdkScreen *pointer_screen;
6667 GdkDisplay *display;
6668 GdkDeviceManager *device_manager;
6671 window_screen = gtk_window_check_screen (window);
6672 display = gdk_screen_get_display (window_screen);
6673 device_manager = gdk_display_get_device_manager (display);
6674 pointer = gdk_device_manager_get_client_pointer (device_manager);
6676 gdk_device_get_position (pointer,
6680 if (pointer_screen == window_screen)
6681 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6689 center_window_on_monitor (GtkWindow *window,
6695 GdkRectangle monitor;
6698 monitor_num = get_monitor_containing_pointer (window);
6700 if (monitor_num == -1)
6701 monitor_num = get_center_monitor_of_window (window);
6703 gdk_screen_get_monitor_workarea (gtk_window_check_screen (window),
6704 monitor_num, &monitor);
6706 *x = (monitor.width - w) / 2 + monitor.x;
6707 *y = (monitor.height - h) / 2 + monitor.y;
6709 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6710 * and WM decorations.
6724 if (extent > clamp_extent)
6726 *base = clamp_base + clamp_extent/2 - extent/2;
6727 else if (*base < clamp_base)
6729 else if (*base + extent > clamp_base + clamp_extent)
6730 *base = clamp_base + clamp_extent - extent;
6734 clamp_window_to_rectangle (gint *x,
6738 const GdkRectangle *rect)
6740 #ifdef DEBUGGING_OUTPUT
6741 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);
6744 /* If it is too large, center it. If it fits on the monitor but is
6745 * partially outside, move it to the closest edge. Do this
6746 * separately in x and y directions.
6748 clamp (x, w, rect->x, rect->width);
6749 clamp (y, h, rect->y, rect->height);
6750 #ifdef DEBUGGING_OUTPUT
6751 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6757 gtk_window_compute_configure_request (GtkWindow *window,
6758 GdkRectangle *request,
6759 GdkGeometry *geometry,
6762 GtkWindowPrivate *priv = window->priv;
6763 GdkGeometry new_geometry;
6766 GtkWindowPosition pos;
6767 GtkWidget *parent_widget;
6768 GtkWindowGeometryInfo *info;
6772 screen = gtk_window_check_screen (window);
6774 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6775 gtk_window_compute_configure_request_size (window,
6776 &new_geometry, new_flags,
6779 gtk_window_constrain_size (window,
6780 &new_geometry, new_flags,
6784 parent_widget = (GtkWidget*) priv->transient_parent;
6786 pos = get_effective_position (window);
6787 info = gtk_window_get_geometry_info (window, FALSE);
6789 /* by default, don't change position requested */
6792 x = info->last.configure_request.x;
6793 y = info->last.configure_request.y;
6802 if (priv->need_default_position)
6805 /* FIXME this all interrelates with window gravity.
6806 * For most of them I think we want to set GRAVITY_CENTER.
6808 * Not sure how to go about that.
6812 /* here we are only handling CENTER_ALWAYS
6813 * as it relates to default positioning,
6814 * where it's equivalent to simply CENTER
6816 case GTK_WIN_POS_CENTER_ALWAYS:
6817 case GTK_WIN_POS_CENTER:
6818 center_window_on_monitor (window, w, h, &x, &y);
6821 case GTK_WIN_POS_CENTER_ON_PARENT:
6823 GtkAllocation allocation;
6824 GdkWindow *gdk_window;
6826 GdkRectangle monitor;
6829 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6831 gdk_window = gtk_widget_get_window (parent_widget);
6833 if (gdk_window != NULL)
6834 monitor_num = gdk_screen_get_monitor_at_window (screen,
6839 gdk_window_get_origin (gdk_window,
6842 gtk_widget_get_allocation (parent_widget, &allocation);
6843 x = ox + (allocation.width - w) / 2;
6844 y = oy + (allocation.height - h) / 2;
6846 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6847 * WM decorations. If parent wasn't on a monitor, just
6850 if (monitor_num >= 0)
6852 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6853 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6858 case GTK_WIN_POS_MOUSE:
6860 gint screen_width = gdk_screen_get_width (screen);
6861 gint screen_height = gdk_screen_get_height (screen);
6863 GdkRectangle monitor;
6864 GdkDisplay *display;
6865 GdkDeviceManager *device_manager;
6867 GdkScreen *pointer_screen;
6870 display = gdk_screen_get_display (screen);
6871 device_manager = gdk_display_get_device_manager (display);
6872 pointer = gdk_device_manager_get_client_pointer (device_manager);
6874 gdk_device_get_position (pointer,
6878 if (pointer_screen == screen)
6879 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6885 x = CLAMP (x, 0, screen_width - w);
6886 y = CLAMP (y, 0, screen_height - h);
6888 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6889 * WM decorations. Don't try to figure out what's going
6890 * on if the mouse wasn't inside a monitor.
6892 if (monitor_num >= 0)
6894 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6895 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6903 } /* if (priv->need_default_position) */
6905 if (priv->need_default_position && info &&
6906 info->initial_pos_set)
6908 x = info->initial_x;
6909 y = info->initial_y;
6910 gtk_window_constrain_position (window, w, h, &x, &y);
6916 request->height = h;
6919 *geometry = new_geometry;
6925 gtk_window_constrain_position (GtkWindow *window,
6931 GtkWindowPrivate *priv = window->priv;
6933 /* See long comments in gtk_window_move_resize()
6934 * on when it's safe to call this function.
6936 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6938 gint center_x, center_y;
6940 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6948 gtk_window_move_resize (GtkWindow *window)
6952 * First we determine whether any information has changed that would
6953 * cause us to revise our last configure request. If we would send
6954 * a different configure request from last time, then
6955 * configure_request_size_changed = TRUE or
6956 * configure_request_pos_changed = TRUE. configure_request_size_changed
6957 * may be true due to new hints, a gtk_window_resize(), or whatever.
6958 * configure_request_pos_changed may be true due to gtk_window_set_position()
6959 * or gtk_window_move().
6961 * If the configure request has changed, we send off a new one. To
6962 * ensure GTK+ invariants are maintained (resize queue does what it
6963 * should), we go ahead and size_allocate the requested size in this
6966 * If the configure request has not changed, we don't ever resend
6967 * it, because it could mean fighting the user or window manager.
6970 * To prepare the configure request, we come up with a base size/pos:
6971 * - the one from gtk_window_move()/gtk_window_resize()
6972 * - else default_width, default_height if we haven't ever
6974 * - else the size request if we haven't ever been mapped,
6975 * as a substitute default size
6976 * - else the current size of the window, as received from
6977 * configure notifies (i.e. the current allocation)
6979 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6980 * the position request to be centered.
6982 GtkWindowPrivate *priv = window->priv;
6983 GtkAllocation allocation;
6985 GtkContainer *container;
6986 GtkWindowGeometryInfo *info;
6987 GdkGeometry new_geometry;
6988 GdkWindow *gdk_window;
6990 GdkRectangle new_request;
6991 gboolean configure_request_size_changed;
6992 gboolean configure_request_pos_changed;
6993 gboolean hints_changed; /* do we need to send these again */
6994 GtkWindowLastGeometryInfo saved_last_info;
6996 widget = GTK_WIDGET (window);
6998 gdk_window = gtk_widget_get_window (widget);
6999 container = GTK_CONTAINER (widget);
7000 info = gtk_window_get_geometry_info (window, TRUE);
7002 configure_request_size_changed = FALSE;
7003 configure_request_pos_changed = FALSE;
7005 gtk_window_compute_configure_request (window, &new_request,
7006 &new_geometry, &new_flags);
7008 /* This check implies the invariant that we never set info->last
7009 * without setting the hints and sending off a configure request.
7011 * If we change info->last without sending the request, we may
7014 if (info->last.configure_request.x != new_request.x ||
7015 info->last.configure_request.y != new_request.y)
7016 configure_request_pos_changed = TRUE;
7018 if ((info->last.configure_request.width != new_request.width ||
7019 info->last.configure_request.height != new_request.height))
7020 configure_request_size_changed = TRUE;
7022 hints_changed = FALSE;
7024 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
7025 &new_geometry, new_flags))
7027 hints_changed = TRUE;
7030 /* Position Constraints
7031 * ====================
7033 * POS_CENTER_ALWAYS is conceptually a constraint rather than
7034 * a default. The other POS_ values are used only when the
7035 * window is shown, not after that.
7037 * However, we can't implement a position constraint as
7038 * "anytime the window size changes, center the window"
7039 * because this may well end up fighting the WM or user. In
7040 * fact it gets in an infinite loop with at least one WM.
7042 * Basically, applications are in no way in a position to
7043 * constrain the position of a window, with one exception:
7044 * override redirect windows. (Really the intended purpose
7045 * of CENTER_ALWAYS anyhow, I would think.)
7047 * So the way we implement this "constraint" is to say that when WE
7048 * cause a move or resize, i.e. we make a configure request changing
7049 * window size, we recompute the CENTER_ALWAYS position to reflect
7050 * the new window size, and include it in our request. Also, if we
7051 * just turned on CENTER_ALWAYS we snap to center with a new
7052 * request. Otherwise, if we are just NOTIFIED of a move or resize
7053 * done by someone else e.g. the window manager, we do NOT send a
7054 * new configure request.
7056 * For override redirect windows, this works fine; all window
7057 * sizes are from our configure requests. For managed windows,
7058 * it is at least semi-sane, though who knows what the
7059 * app author is thinking.
7062 /* This condition should be kept in sync with the condition later on
7063 * that determines whether we send a configure request. i.e. we
7064 * should do this position constraining anytime we were going to
7065 * send a configure request anyhow, plus when constraints have
7068 if (configure_request_pos_changed ||
7069 configure_request_size_changed ||
7071 info->position_constraints_changed)
7073 /* We request the constrained position if:
7074 * - we were changing position, and need to clamp
7075 * the change to the constraint
7076 * - we're changing the size anyway
7077 * - set_position() was called to toggle CENTER_ALWAYS on
7080 gtk_window_constrain_position (window,
7086 /* Update whether we need to request a move */
7087 if (info->last.configure_request.x != new_request.x ||
7088 info->last.configure_request.y != new_request.y)
7089 configure_request_pos_changed = TRUE;
7091 configure_request_pos_changed = FALSE;
7095 if (priv->type == GTK_WINDOW_TOPLEVEL)
7097 int notify_x, notify_y;
7099 /* this is the position from the last configure notify */
7100 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
7102 g_message ("--- %s ---\n"
7103 "last : %d,%d\t%d x %d\n"
7104 "this : %d,%d\t%d x %d\n"
7105 "alloc : %d,%d\t%d x %d\n"
7107 "resize: \t%d x %d\n"
7108 "size_changed: %d pos_changed: %d hints_changed: %d\n"
7109 "configure_notify_received: %d\n"
7110 "configure_request_count: %d\n"
7111 "position_constraints_changed: %d\n",
7112 priv->title ? priv->title : "(no title)",
7113 info->last.configure_request.x,
7114 info->last.configure_request.y,
7115 info->last.configure_request.width,
7116 info->last.configure_request.height,
7122 widget->allocation.width,
7123 widget->allocation.height,
7124 widget->requisition.width,
7125 widget->requisition.height,
7127 info->resize_height,
7128 configure_request_pos_changed,
7129 configure_request_size_changed,
7131 priv->configure_notify_received,
7132 priv->configure_request_count,
7133 info->position_constraints_changed);
7137 saved_last_info = info->last;
7138 info->last.geometry = new_geometry;
7139 info->last.flags = new_flags;
7140 info->last.configure_request = new_request;
7142 /* need to set PPosition so the WM will look at our position,
7143 * but we don't want to count PPosition coming and going as a hints
7144 * change for future iterations. So we saved info->last prior to
7148 /* Also, if the initial position was explicitly set, then we always
7149 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
7153 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
7154 * this is an initial map
7157 if ((configure_request_pos_changed ||
7158 info->initial_pos_set ||
7159 (priv->need_default_position &&
7160 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
7161 (new_flags & GDK_HINT_POS) == 0)
7163 new_flags |= GDK_HINT_POS;
7164 hints_changed = TRUE;
7167 /* Set hints if necessary
7170 gdk_window_set_geometry_hints (gdk_window,
7176 allocation.width = gdk_window_get_width (gdk_window);
7177 allocation.height = gdk_window_get_height (gdk_window);
7179 /* handle resizing/moving and widget tree allocation
7181 if (priv->configure_notify_received)
7183 /* If we have received a configure event since
7184 * the last time in this function, we need to
7185 * accept our new size and size_allocate child widgets.
7186 * (see gtk_window_configure_event() for more details).
7188 * 1 or more configure notifies may have been received.
7189 * Also, configure_notify_received will only be TRUE
7190 * if all expected configure notifies have been received
7191 * (one per configure request), as an optimization.
7194 priv->configure_notify_received = FALSE;
7196 /* gtk_window_configure_event() filled in widget->allocation */
7197 gtk_widget_size_allocate (widget, &allocation);
7199 set_grip_position (window);
7200 update_grip_visibility (window);
7202 gdk_window_process_updates (gdk_window, TRUE);
7204 gdk_window_configure_finished (gdk_window);
7206 /* If the configure request changed, it means that
7208 * 1) coincidentally changed hints or widget properties
7209 * impacting the configure request before getting
7210 * a configure notify, or
7211 * 2) some broken widget is changing its size request
7212 * during size allocation, resulting in
7213 * a false appearance of changed configure request.
7215 * For 1), we could just go ahead and ask for the
7216 * new size right now, but doing that for 2)
7217 * might well be fighting the user (and can even
7218 * trigger a loop). Since we really don't want to
7219 * do that, we requeue a resize in hopes that
7220 * by the time it gets handled, the child has seen
7221 * the light and is willing to go along with the
7222 * new size. (this happens for the zvt widget, since
7223 * the size_allocate() above will have stored the
7224 * requisition corresponding to the new size in the
7227 * This doesn't buy us anything for 1), but it shouldn't
7228 * hurt us too badly, since it is what would have
7229 * happened if we had gotten the configure event before
7230 * the new size had been set.
7233 if (configure_request_size_changed ||
7234 configure_request_pos_changed)
7236 /* Don't change the recorded last info after all, because we
7237 * haven't actually updated to the new info yet - we decided
7238 * to postpone our configure request until later.
7240 info->last = saved_last_info;
7242 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7245 return; /* Bail out, we didn't really process the move/resize */
7247 else if ((configure_request_size_changed || hints_changed) &&
7248 (allocation.width != new_request.width || allocation.height != new_request.height))
7251 /* We are in one of the following situations:
7252 * A. configure_request_size_changed
7253 * our requisition has changed and we need a different window size,
7254 * so we request it from the window manager.
7255 * B. !configure_request_size_changed && hints_changed
7256 * the window manager rejects our size, but we have just changed the
7257 * window manager hints, so there's a chance our request will
7258 * be honoured this time, so we try again.
7260 * However, if the new requisition is the same as the current allocation,
7261 * we don't request it again, since we won't get a ConfigureNotify back from
7262 * the window manager unless it decides to change our requisition. If
7263 * we don't get the ConfigureNotify back, the resize queue will never be run.
7266 /* Now send the configure request */
7267 if (configure_request_pos_changed)
7269 gdk_window_move_resize (gdk_window,
7270 new_request.x, new_request.y,
7271 new_request.width, new_request.height);
7273 else /* only size changed */
7275 gdk_window_resize (gdk_window,
7276 new_request.width, new_request.height);
7279 if (priv->type == GTK_WINDOW_POPUP)
7281 GtkAllocation allocation;
7283 /* Directly size allocate for override redirect (popup) windows. */
7286 allocation.width = new_request.width;
7287 allocation.height = new_request.height;
7289 gtk_widget_size_allocate (widget, &allocation);
7291 gdk_window_process_updates (gdk_window, TRUE);
7293 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7294 gtk_widget_queue_draw (widget);
7298 /* Increment the number of have-not-yet-received-notify requests */
7299 priv->configure_request_count += 1;
7300 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7302 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7303 * configure event in response to our resizing request.
7304 * the configure event will cause a new resize with
7305 * ->configure_notify_received=TRUE.
7306 * until then, we want to
7307 * - discard expose events
7308 * - coalesce resizes for our children
7309 * - defer any window resizes until the configure event arrived
7310 * to achieve this, we queue a resize for the window, but remove its
7311 * resizing handler, so resizing will not be handled from the next
7312 * idle handler but when the configure event arrives.
7314 * FIXME: we should also dequeue the pending redraws here, since
7315 * we handle those ourselves upon ->configure_notify_received==TRUE.
7317 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7319 gtk_widget_queue_resize_no_redraw (widget);
7320 _gtk_container_dequeue_resize_handler (container);
7326 /* Handle any position changes.
7328 if (configure_request_pos_changed)
7330 gdk_window_move (gdk_window,
7331 new_request.x, new_request.y);
7334 /* And run the resize queue.
7336 gtk_container_resize_children (container);
7339 /* We have now processed a move/resize since the last position
7340 * constraint change, setting of the initial position, or resize.
7341 * (Not resetting these flags here can lead to infinite loops for
7342 * GTK_RESIZE_IMMEDIATE containers)
7344 info->position_constraints_changed = FALSE;
7345 info->initial_pos_set = FALSE;
7346 info->resize_width = -1;
7347 info->resize_height = -1;
7350 /* Compare two sets of Geometry hints for equality.
7353 gtk_window_compare_hints (GdkGeometry *geometry_a,
7355 GdkGeometry *geometry_b,
7358 if (flags_a != flags_b)
7361 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7362 (geometry_a->min_width != geometry_b->min_width ||
7363 geometry_a->min_height != geometry_b->min_height))
7366 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7367 (geometry_a->max_width != geometry_b->max_width ||
7368 geometry_a->max_height != geometry_b->max_height))
7371 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7372 (geometry_a->base_width != geometry_b->base_width ||
7373 geometry_a->base_height != geometry_b->base_height))
7376 if ((flags_a & GDK_HINT_ASPECT) &&
7377 (geometry_a->min_aspect != geometry_b->min_aspect ||
7378 geometry_a->max_aspect != geometry_b->max_aspect))
7381 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7382 (geometry_a->width_inc != geometry_b->width_inc ||
7383 geometry_a->height_inc != geometry_b->height_inc))
7386 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7387 geometry_a->win_gravity != geometry_b->win_gravity)
7394 _gtk_window_constrain_size (GtkWindow *window,
7400 GtkWindowPrivate *priv;
7401 GtkWindowGeometryInfo *info;
7403 g_return_if_fail (GTK_IS_WINDOW (window));
7405 priv = window->priv;
7407 info = priv->geometry_info;
7410 GdkWindowHints flags = info->last.flags;
7411 GdkGeometry *geometry = &info->last.geometry;
7413 gtk_window_constrain_size (window,
7424 gtk_window_constrain_size (GtkWindow *window,
7425 GdkGeometry *geometry,
7432 gdk_window_constrain_size (geometry, flags, width, height,
7433 new_width, new_height);
7436 /* Compute the set of geometry hints and flags for a window
7437 * based on the application set geometry, and requisition
7438 * of the window. gtk_widget_get_preferred_size() must have been
7442 gtk_window_compute_hints (GtkWindow *window,
7443 GdkGeometry *new_geometry,
7446 GtkWindowPrivate *priv = window->priv;
7448 gint extra_width = 0;
7449 gint extra_height = 0;
7450 GtkWindowGeometryInfo *geometry_info;
7451 GtkRequisition requisition;
7453 widget = GTK_WIDGET (window);
7455 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7456 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7460 *new_flags = geometry_info->mask;
7461 *new_geometry = geometry_info->geometry;
7468 if (geometry_info && geometry_info->widget)
7470 /* If the geometry widget is set, then the hints really apply to that
7471 * widget. This is pretty much meaningless unless the window layout
7472 * is such that the rest of the window adds fixed size borders to
7473 * the geometry widget. Our job is to figure the size of the borders;
7474 * We do that by asking how big the toplevel would be if the
7475 * geometry widget was *really big*.
7478 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7479 * |GGGGG B| in the border can confuse things
7485 * |AAAAAAAAA | When the geometry widget is large, things are
7486 * |GGGGGGGGGGB| clearer.
7491 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7492 GtkRequisition requisition;
7493 int current_width, current_height;
7495 _gtk_widget_override_size_request (geometry_info->widget,
7496 TEMPORARY_SIZE, TEMPORARY_SIZE,
7497 ¤t_width, ¤t_height);
7498 gtk_widget_get_preferred_size (widget,
7499 &requisition, NULL);
7500 _gtk_widget_restore_size_request (geometry_info->widget,
7501 current_width, current_height);
7503 extra_width = requisition.width - TEMPORARY_SIZE;
7504 extra_height = requisition.height - TEMPORARY_SIZE;
7506 if (extra_width < 0 || extra_height < 0)
7508 g_warning("Toplevel size doesn't seem to directly depend on the "
7509 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7510 "The geometry widget might not be in the window, or it might not "
7511 "be packed into the window appropriately");
7512 extra_width = MAX(extra_width, 0);
7513 extra_height = MAX(extra_height, 0);
7515 #undef TEMPORARY_SIZE
7518 /* We don't want to set GDK_HINT_POS in here, we just set it
7519 * in gtk_window_move_resize() when we want the position
7523 if (*new_flags & GDK_HINT_BASE_SIZE)
7525 new_geometry->base_width += extra_width;
7526 new_geometry->base_height += extra_height;
7530 /* For simplicity, we always set the base hint, even when we
7531 * don't expect it to have any visible effect.
7532 * (Note: geometry_size_to_pixels() depends on this.)
7534 *new_flags |= GDK_HINT_BASE_SIZE;
7536 new_geometry->base_width = extra_width;
7537 new_geometry->base_height = extra_height;
7539 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7540 * base size is the minimum size */
7541 if (*new_flags & GDK_HINT_MIN_SIZE)
7543 if (new_geometry->min_width > 0)
7544 new_geometry->base_width += new_geometry->min_width;
7545 if (new_geometry->min_height > 0)
7546 new_geometry->base_height += new_geometry->min_height;
7550 /* Please use a good size for unresizable widgets, not the minimum one. */
7551 if (!priv->resizable)
7552 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7554 if (*new_flags & GDK_HINT_MIN_SIZE)
7556 if (new_geometry->min_width < 0)
7557 new_geometry->min_width = requisition.width;
7559 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7561 if (new_geometry->min_height < 0)
7562 new_geometry->min_height = requisition.height;
7564 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7568 *new_flags |= GDK_HINT_MIN_SIZE;
7570 new_geometry->min_width = requisition.width;
7571 new_geometry->min_height = requisition.height;
7574 if (*new_flags & GDK_HINT_MAX_SIZE)
7576 if (new_geometry->max_width < 0)
7577 new_geometry->max_width = requisition.width;
7579 new_geometry->max_width += extra_width;
7581 if (new_geometry->max_height < 0)
7582 new_geometry->max_height = requisition.height;
7584 new_geometry->max_height += extra_height;
7586 else if (!priv->resizable)
7588 *new_flags |= GDK_HINT_MAX_SIZE;
7590 new_geometry->max_width = requisition.width;
7591 new_geometry->max_height = requisition.height;
7594 *new_flags |= GDK_HINT_WIN_GRAVITY;
7595 new_geometry->win_gravity = priv->gravity;
7598 /***********************
7599 * Redrawing functions *
7600 ***********************/
7603 gtk_window_draw (GtkWidget *widget,
7606 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7607 GtkStyleContext *context;
7608 gboolean ret = FALSE;
7610 context = gtk_widget_get_style_context (widget);
7612 if (!gtk_widget_get_app_paintable (widget) &&
7613 gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
7615 gtk_render_background (context, cr, 0, 0,
7616 gtk_widget_get_allocated_width (widget),
7617 gtk_widget_get_allocated_height (widget));
7620 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7621 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7623 if (priv->grip_window &&
7624 gtk_cairo_should_draw_window (cr, priv->grip_window))
7628 gtk_style_context_save (context);
7631 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7632 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7634 gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND);
7635 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7636 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7637 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7640 gtk_style_context_restore (context);
7647 * gtk_window_present:
7648 * @window: a #GtkWindow
7650 * Presents a window to the user. This may mean raising the window
7651 * in the stacking order, deiconifying it, moving it to the current
7652 * desktop, and/or giving it the keyboard focus, possibly dependent
7653 * on the user's platform, window manager, and preferences.
7655 * If @window is hidden, this function calls gtk_widget_show()
7658 * This function should be used when the user tries to open a window
7659 * that's already open. Say for example the preferences dialog is
7660 * currently open, and the user chooses Preferences from the menu
7661 * a second time; use gtk_window_present() to move the already-open dialog
7662 * where the user can see it.
7664 * If you are calling this function in response to a user interaction,
7665 * it is preferable to use gtk_window_present_with_time().
7669 gtk_window_present (GtkWindow *window)
7671 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7675 * gtk_window_present_with_time:
7676 * @window: a #GtkWindow
7677 * @timestamp: the timestamp of the user interaction (typically a
7678 * button or key press event) which triggered this call
7680 * Presents a window to the user in response to a user interaction.
7681 * If you need to present a window without a timestamp, use
7682 * gtk_window_present(). See gtk_window_present() for details.
7687 gtk_window_present_with_time (GtkWindow *window,
7690 GtkWindowPrivate *priv;
7692 GdkWindow *gdk_window;
7694 g_return_if_fail (GTK_IS_WINDOW (window));
7696 priv = window->priv;
7697 widget = GTK_WIDGET (window);
7699 if (gtk_widget_get_visible (widget))
7701 gdk_window = gtk_widget_get_window (widget);
7703 g_assert (gdk_window != NULL);
7705 gdk_window_show (gdk_window);
7707 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7708 if (timestamp == GDK_CURRENT_TIME)
7710 #ifdef GDK_WINDOWING_X11
7711 if (GDK_IS_X11_WINDOW(gdk_window))
7713 GdkDisplay *display;
7715 display = gtk_widget_get_display (GTK_WIDGET (window));
7716 timestamp = gdk_x11_display_get_user_time (display);
7720 timestamp = gtk_get_current_event_time ();
7723 gdk_window_focus (gdk_window, timestamp);
7727 priv->initial_timestamp = timestamp;
7728 gtk_widget_show (widget);
7733 * gtk_window_iconify:
7734 * @window: a #GtkWindow
7736 * Asks to iconify (i.e. minimize) the specified @window. Note that
7737 * you shouldn't assume the window is definitely iconified afterward,
7738 * because other entities (e.g. the user or <link
7739 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7740 * again, or there may not be a window manager in which case
7741 * iconification isn't possible, etc. But normally the window will end
7742 * up iconified. Just don't write code that crashes if not.
7744 * It's permitted to call this function before showing a window,
7745 * in which case the window will be iconified before it ever appears
7748 * You can track iconification via the "window-state-event" signal
7753 gtk_window_iconify (GtkWindow *window)
7755 GtkWindowPrivate *priv;
7757 GdkWindow *toplevel;
7759 g_return_if_fail (GTK_IS_WINDOW (window));
7761 priv = window->priv;
7762 widget = GTK_WIDGET (window);
7764 priv->iconify_initially = TRUE;
7766 toplevel = gtk_widget_get_window (widget);
7768 if (toplevel != NULL)
7769 gdk_window_iconify (toplevel);
7773 * gtk_window_deiconify:
7774 * @window: a #GtkWindow
7776 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7777 * that you shouldn't assume the window is definitely deiconified
7778 * afterward, because other entities (e.g. the user or <link
7779 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7780 * again before your code which assumes deiconification gets to run.
7782 * You can track iconification via the "window-state-event" signal
7786 gtk_window_deiconify (GtkWindow *window)
7788 GtkWindowPrivate *priv;
7790 GdkWindow *toplevel;
7792 g_return_if_fail (GTK_IS_WINDOW (window));
7794 priv = window->priv;
7795 widget = GTK_WIDGET (window);
7797 priv->iconify_initially = FALSE;
7799 toplevel = gtk_widget_get_window (widget);
7801 if (toplevel != NULL)
7802 gdk_window_deiconify (toplevel);
7807 * @window: a #GtkWindow
7809 * Asks to stick @window, which means that it will appear on all user
7810 * desktops. Note that you shouldn't assume the window is definitely
7811 * stuck afterward, because other entities (e.g. the user or <link
7812 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7813 * again, and some window managers do not support sticking
7814 * windows. But normally the window will end up stuck. Just don't
7815 * write code that crashes if not.
7817 * It's permitted to call this function before showing a window.
7819 * You can track stickiness via the "window-state-event" signal
7824 gtk_window_stick (GtkWindow *window)
7826 GtkWindowPrivate *priv;
7828 GdkWindow *toplevel;
7830 g_return_if_fail (GTK_IS_WINDOW (window));
7832 priv = window->priv;
7833 widget = GTK_WIDGET (window);
7835 priv->stick_initially = TRUE;
7837 toplevel = gtk_widget_get_window (widget);
7839 if (toplevel != NULL)
7840 gdk_window_stick (toplevel);
7844 * gtk_window_unstick:
7845 * @window: a #GtkWindow
7847 * Asks to unstick @window, which means that it will appear on only
7848 * one of the user's desktops. Note that you shouldn't assume the
7849 * window is definitely unstuck afterward, because other entities
7850 * (e.g. the user or <link linkend="gtk-X11-arch">window
7851 * manager</link>) could stick it again. But normally the window will
7852 * end up stuck. Just don't write code that crashes if not.
7854 * You can track stickiness via the "window-state-event" signal
7859 gtk_window_unstick (GtkWindow *window)
7861 GtkWindowPrivate *priv;
7863 GdkWindow *toplevel;
7865 g_return_if_fail (GTK_IS_WINDOW (window));
7867 priv = window->priv;
7868 widget = GTK_WIDGET (window);
7870 priv->stick_initially = FALSE;
7872 toplevel = gtk_widget_get_window (widget);
7874 if (toplevel != NULL)
7875 gdk_window_unstick (toplevel);
7879 * gtk_window_maximize:
7880 * @window: a #GtkWindow
7882 * Asks to maximize @window, so that it becomes full-screen. Note that
7883 * you shouldn't assume the window is definitely maximized afterward,
7884 * because other entities (e.g. the user or <link
7885 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7886 * again, and not all window managers support maximization. But
7887 * normally the window will end up maximized. Just don't write code
7888 * that crashes if not.
7890 * It's permitted to call this function before showing a window,
7891 * in which case the window will be maximized when it appears onscreen
7894 * You can track maximization via the "window-state-event" signal
7899 gtk_window_maximize (GtkWindow *window)
7901 GtkWindowPrivate *priv;
7903 GdkWindow *toplevel;
7905 g_return_if_fail (GTK_IS_WINDOW (window));
7907 priv = window->priv;
7908 widget = GTK_WIDGET (window);
7910 priv->maximize_initially = TRUE;
7912 toplevel = gtk_widget_get_window (widget);
7914 if (toplevel != NULL)
7915 gdk_window_maximize (toplevel);
7919 * gtk_window_unmaximize:
7920 * @window: a #GtkWindow
7922 * Asks to unmaximize @window. Note that you shouldn't assume the
7923 * window is definitely unmaximized afterward, because other entities
7924 * (e.g. the user or <link linkend="gtk-X11-arch">window
7925 * manager</link>) could maximize it again, and not all window
7926 * managers honor requests to unmaximize. But normally the window will
7927 * end up unmaximized. Just don't write code that crashes if not.
7929 * You can track maximization via the "window-state-event" signal
7934 gtk_window_unmaximize (GtkWindow *window)
7936 GtkWindowPrivate *priv;
7938 GdkWindow *toplevel;
7940 g_return_if_fail (GTK_IS_WINDOW (window));
7942 priv = window->priv;
7943 widget = GTK_WIDGET (window);
7945 priv->maximize_initially = FALSE;
7947 toplevel = gtk_widget_get_window (widget);
7949 if (toplevel != NULL)
7950 gdk_window_unmaximize (toplevel);
7954 * gtk_window_fullscreen:
7955 * @window: a #GtkWindow
7957 * Asks to place @window in the fullscreen state. Note that you
7958 * shouldn't assume the window is definitely full screen afterward,
7959 * because other entities (e.g. the user or <link
7960 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7961 * again, and not all window managers honor requests to fullscreen
7962 * windows. But normally the window will end up fullscreen. Just
7963 * don't write code that crashes if not.
7965 * You can track the fullscreen state via the "window-state-event" signal
7971 gtk_window_fullscreen (GtkWindow *window)
7973 GtkWindowPrivate *priv;
7975 GdkWindow *toplevel;
7977 g_return_if_fail (GTK_IS_WINDOW (window));
7979 priv = window->priv;
7980 widget = GTK_WIDGET (window);
7982 priv->fullscreen_initially = TRUE;
7984 toplevel = gtk_widget_get_window (widget);
7986 if (toplevel != NULL)
7987 gdk_window_fullscreen (toplevel);
7991 * gtk_window_unfullscreen:
7992 * @window: a #GtkWindow
7994 * Asks to toggle off the fullscreen state for @window. Note that you
7995 * shouldn't assume the window is definitely not full screen
7996 * afterward, because other entities (e.g. the user or <link
7997 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7998 * again, and not all window managers honor requests to unfullscreen
7999 * windows. But normally the window will end up restored to its normal
8000 * state. Just don't write code that crashes if not.
8002 * You can track the fullscreen state via the "window-state-event" signal
8008 gtk_window_unfullscreen (GtkWindow *window)
8011 GdkWindow *toplevel;
8012 GtkWindowPrivate *priv;
8014 g_return_if_fail (GTK_IS_WINDOW (window));
8016 priv = window->priv;
8017 widget = GTK_WIDGET (window);
8019 priv->fullscreen_initially = FALSE;
8021 toplevel = gtk_widget_get_window (widget);
8023 if (toplevel != NULL)
8024 gdk_window_unfullscreen (toplevel);
8028 * gtk_window_set_keep_above:
8029 * @window: a #GtkWindow
8030 * @setting: whether to keep @window above other windows
8032 * Asks to keep @window above, so that it stays on top. Note that
8033 * you shouldn't assume the window is definitely above afterward,
8034 * because other entities (e.g. the user or <link
8035 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
8036 * and not all window managers support keeping windows above. But
8037 * normally the window will end kept above. Just don't write code
8038 * that crashes if not.
8040 * It's permitted to call this function before showing a window,
8041 * in which case the window will be kept above when it appears onscreen
8044 * You can track the above state via the "window-state-event" signal
8047 * Note that, according to the <ulink
8048 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8049 * Manager Hints</ulink> specification, the above state is mainly meant
8050 * for user preferences and should not be used by applications e.g. for
8051 * drawing attention to their dialogs.
8056 gtk_window_set_keep_above (GtkWindow *window,
8060 GtkWindowPrivate *priv;
8061 GdkWindow *toplevel;
8063 g_return_if_fail (GTK_IS_WINDOW (window));
8065 priv = window->priv;
8066 widget = GTK_WIDGET (window);
8068 priv->above_initially = setting != FALSE;
8070 priv->below_initially = FALSE;
8072 toplevel = gtk_widget_get_window (widget);
8074 if (toplevel != NULL)
8075 gdk_window_set_keep_above (toplevel, setting);
8079 * gtk_window_set_keep_below:
8080 * @window: a #GtkWindow
8081 * @setting: whether to keep @window below other windows
8083 * Asks to keep @window below, so that it stays in bottom. Note that
8084 * you shouldn't assume the window is definitely below afterward,
8085 * because other entities (e.g. the user or <link
8086 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8087 * and not all window managers support putting windows below. But
8088 * normally the window will be kept below. Just don't write code
8089 * that crashes if not.
8091 * It's permitted to call this function before showing a window,
8092 * in which case the window will be kept below when it appears onscreen
8095 * You can track the below state via the "window-state-event" signal
8098 * Note that, according to the <ulink
8099 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8100 * Manager Hints</ulink> specification, the above state is mainly meant
8101 * for user preferences and should not be used by applications e.g. for
8102 * drawing attention to their dialogs.
8107 gtk_window_set_keep_below (GtkWindow *window,
8111 GtkWindowPrivate *priv;
8112 GdkWindow *toplevel;
8114 g_return_if_fail (GTK_IS_WINDOW (window));
8116 priv = window->priv;
8117 widget = GTK_WIDGET (window);
8119 priv->below_initially = setting != FALSE;
8121 priv->above_initially = FALSE;
8123 toplevel = gtk_widget_get_window (widget);
8125 if (toplevel != NULL)
8126 gdk_window_set_keep_below (toplevel, setting);
8130 * gtk_window_set_resizable:
8131 * @window: a #GtkWindow
8132 * @resizable: %TRUE if the user can resize this window
8134 * Sets whether the user can resize a window. Windows are user resizable
8138 gtk_window_set_resizable (GtkWindow *window,
8141 GtkWindowPrivate *priv;
8143 g_return_if_fail (GTK_IS_WINDOW (window));
8145 priv = window->priv;
8147 resizable = (resizable != FALSE);
8149 if (priv->resizable != resizable)
8151 priv->resizable = resizable;
8153 update_grip_visibility (window);
8155 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8157 g_object_notify (G_OBJECT (window), "resizable");
8162 * gtk_window_get_resizable:
8163 * @window: a #GtkWindow
8165 * Gets the value set by gtk_window_set_resizable().
8167 * Return value: %TRUE if the user can resize the window
8170 gtk_window_get_resizable (GtkWindow *window)
8172 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8174 return window->priv->resizable;
8178 * gtk_window_set_gravity:
8179 * @window: a #GtkWindow
8180 * @gravity: window gravity
8182 * Window gravity defines the meaning of coordinates passed to
8183 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8186 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8187 * typically "do what you mean."
8191 gtk_window_set_gravity (GtkWindow *window,
8194 GtkWindowPrivate *priv;
8196 g_return_if_fail (GTK_IS_WINDOW (window));
8198 priv = window->priv;
8200 if (gravity != priv->gravity)
8202 priv->gravity = gravity;
8204 /* gtk_window_move_resize() will adapt gravity
8206 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8208 g_object_notify (G_OBJECT (window), "gravity");
8213 * gtk_window_get_gravity:
8214 * @window: a #GtkWindow
8216 * Gets the value set by gtk_window_set_gravity().
8218 * Return value: (transfer none): window gravity
8221 gtk_window_get_gravity (GtkWindow *window)
8223 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8225 return window->priv->gravity;
8229 * gtk_window_begin_resize_drag:
8230 * @window: a #GtkWindow
8231 * @button: mouse button that initiated the drag
8232 * @edge: position of the resize control
8233 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8234 * @root_y: Y position where the user clicked to initiate the drag
8235 * @timestamp: timestamp from the click event that initiated the drag
8237 * Starts resizing a window. This function is used if an application
8238 * has window resizing controls. When GDK can support it, the resize
8239 * will be done using the standard mechanism for the <link
8240 * linkend="gtk-X11-arch">window manager</link> or windowing
8241 * system. Otherwise, GDK will try to emulate window resizing,
8242 * potentially not all that well, depending on the windowing system.
8246 gtk_window_begin_resize_drag (GtkWindow *window,
8254 GdkWindow *toplevel;
8256 g_return_if_fail (GTK_IS_WINDOW (window));
8257 widget = GTK_WIDGET (window);
8258 g_return_if_fail (gtk_widget_get_visible (widget));
8260 toplevel = gtk_widget_get_window (widget);
8262 gdk_window_begin_resize_drag (toplevel,
8269 * gtk_window_begin_move_drag:
8270 * @window: a #GtkWindow
8271 * @button: mouse button that initiated the drag
8272 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8273 * @root_y: Y position where the user clicked to initiate the drag
8274 * @timestamp: timestamp from the click event that initiated the drag
8276 * Starts moving a window. This function is used if an application has
8277 * window movement grips. When GDK can support it, the window movement
8278 * will be done using the standard mechanism for the <link
8279 * linkend="gtk-X11-arch">window manager</link> or windowing
8280 * system. Otherwise, GDK will try to emulate window movement,
8281 * potentially not all that well, depending on the windowing system.
8285 gtk_window_begin_move_drag (GtkWindow *window,
8292 GdkWindow *toplevel;
8294 g_return_if_fail (GTK_IS_WINDOW (window));
8295 widget = GTK_WIDGET (window);
8296 g_return_if_fail (gtk_widget_get_visible (widget));
8298 toplevel = gtk_widget_get_window (widget);
8300 gdk_window_begin_move_drag (toplevel,
8307 * gtk_window_set_screen:
8308 * @window: a #GtkWindow.
8309 * @screen: a #GdkScreen.
8311 * Sets the #GdkScreen where the @window is displayed; if
8312 * the window is already mapped, it will be unmapped, and
8313 * then remapped on the new screen.
8318 gtk_window_set_screen (GtkWindow *window,
8321 GtkWindowPrivate *priv;
8323 GdkScreen *previous_screen;
8324 gboolean was_mapped;
8326 g_return_if_fail (GTK_IS_WINDOW (window));
8327 g_return_if_fail (GDK_IS_SCREEN (screen));
8329 priv = window->priv;
8331 if (screen == priv->screen)
8334 widget = GTK_WIDGET (window);
8336 previous_screen = priv->screen;
8337 was_mapped = gtk_widget_get_mapped (widget);
8340 gtk_widget_unmap (widget);
8341 if (gtk_widget_get_realized (widget))
8342 gtk_widget_unrealize (widget);
8344 gtk_window_free_key_hash (window);
8345 priv->screen = screen;
8346 gtk_widget_reset_rc_styles (widget);
8347 if (screen != previous_screen)
8349 if (previous_screen)
8351 g_signal_handlers_disconnect_by_func (previous_screen,
8352 gtk_window_on_composited_changed, window);
8353 #ifdef GDK_WINDOWING_X11
8354 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8355 gtk_window_on_theme_variant_changed, window);
8358 g_signal_connect (screen, "composited-changed",
8359 G_CALLBACK (gtk_window_on_composited_changed), window);
8360 #ifdef GDK_WINDOWING_X11
8361 g_signal_connect (gtk_settings_get_for_screen (screen),
8362 "notify::gtk-application-prefer-dark-theme",
8363 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8366 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8367 _gtk_widget_propagate_composited_changed (widget);
8369 g_object_notify (G_OBJECT (window), "screen");
8372 gtk_widget_map (widget);
8376 gtk_window_set_theme_variant (GtkWindow *window)
8378 #ifdef GDK_WINDOWING_X11
8379 GdkWindow *gdk_window;
8380 gboolean dark_theme_requested;
8382 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8383 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8386 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8388 if (GDK_IS_X11_WINDOW (gdk_window))
8389 gdk_x11_window_set_theme_variant (gdk_window,
8390 dark_theme_requested ? "dark" : NULL);
8395 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8399 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8400 gtk_window_set_theme_variant (window);
8404 gtk_window_on_composited_changed (GdkScreen *screen,
8407 gtk_widget_queue_draw (GTK_WIDGET (window));
8409 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8413 gtk_window_check_screen (GtkWindow *window)
8415 GtkWindowPrivate *priv = window->priv;
8418 return priv->screen;
8421 g_warning ("Screen for GtkWindow not set; you must always set\n"
8422 "a screen for a GtkWindow before using the window");
8428 * gtk_window_get_screen:
8429 * @window: a #GtkWindow.
8431 * Returns the #GdkScreen associated with @window.
8433 * Return value: (transfer none): a #GdkScreen.
8438 gtk_window_get_screen (GtkWindow *window)
8440 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8442 return window->priv->screen;
8446 * gtk_window_is_active:
8447 * @window: a #GtkWindow
8449 * Returns whether the window is part of the current active toplevel.
8450 * (That is, the toplevel window receiving keystrokes.)
8451 * The return value is %TRUE if the window is active toplevel
8452 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8453 * You might use this function if you wanted to draw a widget
8454 * differently in an active window from a widget in an inactive window.
8455 * See gtk_window_has_toplevel_focus()
8457 * Return value: %TRUE if the window part of the current active window.
8462 gtk_window_is_active (GtkWindow *window)
8464 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8466 return window->priv->is_active;
8470 * gtk_window_has_toplevel_focus:
8471 * @window: a #GtkWindow
8473 * Returns whether the input focus is within this GtkWindow.
8474 * For real toplevel windows, this is identical to gtk_window_is_active(),
8475 * but for embedded windows, like #GtkPlug, the results will differ.
8477 * Return value: %TRUE if the input focus is within this GtkWindow
8482 gtk_window_has_toplevel_focus (GtkWindow *window)
8484 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8486 return window->priv->has_toplevel_focus;
8491 * SECTION:gtkwindowgroup
8492 * @Short_description: Limit the effect of grabs
8493 * @Title: GtkWindowGroup
8495 * #GtkWindowGroup objects are referenced by each window in the group,
8496 * so once you have added all windows to a #GtkWindowGroup, you can drop
8497 * the initial reference to the window group with g_object_unref(). If the
8498 * windows in the window group are subsequently destroyed, then they will
8499 * be removed from the window group and drop their references on the window
8500 * group; when all window have been removed, the window group will be
8504 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8507 gtk_window_group_init (GtkWindowGroup *group)
8509 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8510 GTK_TYPE_WINDOW_GROUP,
8511 GtkWindowGroupPrivate);
8515 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8517 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8521 * gtk_window_group_new:
8523 * Creates a new #GtkWindowGroup object. Grabs added with
8524 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8526 * Return value: a new #GtkWindowGroup.
8529 gtk_window_group_new (void)
8531 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8535 window_group_cleanup_grabs (GtkWindowGroup *group,
8538 GtkWindowGroupPrivate *priv;
8539 GtkDeviceGrabInfo *info;
8541 GSList *to_remove = NULL;
8545 tmp_list = priv->grabs;
8548 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8549 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8550 tmp_list = tmp_list->next;
8555 gtk_grab_remove (to_remove->data);
8556 g_object_unref (to_remove->data);
8557 to_remove = g_slist_delete_link (to_remove, to_remove);
8560 tmp_list = priv->device_grabs;
8564 info = tmp_list->data;
8566 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8567 to_remove = g_slist_prepend (to_remove, info);
8569 tmp_list = tmp_list->next;
8574 info = to_remove->data;
8576 gtk_device_grab_remove (info->widget, info->device);
8577 to_remove = g_slist_delete_link (to_remove, to_remove);
8582 * gtk_window_group_add_window:
8583 * @window_group: a #GtkWindowGroup
8584 * @window: the #GtkWindow to add
8586 * Adds a window to a #GtkWindowGroup.
8589 gtk_window_group_add_window (GtkWindowGroup *window_group,
8592 GtkWindowPrivate *priv;
8594 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8595 g_return_if_fail (GTK_IS_WINDOW (window));
8597 priv = window->priv;
8599 if (priv->group != window_group)
8601 g_object_ref (window);
8602 g_object_ref (window_group);
8605 gtk_window_group_remove_window (priv->group, window);
8607 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8609 priv->group = window_group;
8611 g_object_unref (window);
8616 * gtk_window_group_remove_window:
8617 * @window_group: a #GtkWindowGroup
8618 * @window: the #GtkWindow to remove
8620 * Removes a window from a #GtkWindowGroup.
8623 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8626 GtkWindowPrivate *priv;
8628 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8629 g_return_if_fail (GTK_IS_WINDOW (window));
8630 priv = window->priv;
8631 g_return_if_fail (priv->group == window_group);
8633 g_object_ref (window);
8635 window_group_cleanup_grabs (window_group, window);
8638 g_object_unref (window_group);
8639 g_object_unref (window);
8643 * gtk_window_group_list_windows:
8644 * @window_group: a #GtkWindowGroup
8646 * Returns a list of the #GtkWindows that belong to @window_group.
8648 * Returns: (element-type GtkWindow) (transfer container): A
8649 * newly-allocated list of windows inside the group.
8654 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8656 GList *toplevels, *toplevel, *group_windows;
8658 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8660 group_windows = NULL;
8661 toplevels = gtk_window_list_toplevels ();
8663 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8665 GtkWindow *window = toplevel->data;
8667 if (window_group == window->priv->group)
8668 group_windows = g_list_prepend (group_windows, window);
8671 g_list_free (toplevels);
8673 return g_list_reverse (group_windows);
8677 * gtk_window_get_group:
8678 * @window: (allow-none): a #GtkWindow, or %NULL
8680 * Returns the group for @window or the default group, if
8681 * @window is %NULL or if @window does not have an explicit
8684 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8689 gtk_window_get_group (GtkWindow *window)
8691 if (window && window->priv->group)
8692 return window->priv->group;
8695 static GtkWindowGroup *default_group = NULL;
8698 default_group = gtk_window_group_new ();
8700 return default_group;
8705 * gtk_window_has_group:
8706 * @window: a #GtkWindow
8708 * Returns whether @window has an explicit window group.
8710 * Return value: %TRUE if @window has an explicit window group.
8715 gtk_window_has_group (GtkWindow *window)
8717 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8719 return window->priv->group != NULL;
8723 * gtk_window_group_get_current_grab:
8724 * @window_group: a #GtkWindowGroup
8726 * Gets the current grab widget of the given group,
8727 * see gtk_grab_add().
8729 * Returns: (transfer none): the current grab widget of the group
8734 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8736 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8738 if (window_group->priv->grabs)
8739 return GTK_WIDGET (window_group->priv->grabs->data);
8744 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8747 GtkWindowGroupPrivate *priv;
8749 priv = window_group->priv;
8750 priv->grabs = g_slist_prepend (priv->grabs, widget);
8754 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8757 GtkWindowGroupPrivate *priv;
8759 priv = window_group->priv;
8760 priv->grabs = g_slist_remove (priv->grabs, widget);
8765 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8768 gboolean block_others)
8770 GtkWindowGroupPrivate *priv;
8771 GtkDeviceGrabInfo *info;
8773 priv = window_group->priv;
8775 info = g_slice_new0 (GtkDeviceGrabInfo);
8776 info->widget = widget;
8777 info->device = device;
8778 info->block_others = block_others;
8780 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8784 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8788 GtkWindowGroupPrivate *priv;
8789 GtkDeviceGrabInfo *info;
8790 GSList *list, *node = NULL;
8791 GdkDevice *other_device;
8793 priv = window_group->priv;
8794 other_device = gdk_device_get_associated_device (device);
8795 list = priv->device_grabs;
8801 if (info->widget == widget &&
8802 (info->device == device ||
8803 info->device == other_device))
8816 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8817 g_slice_free (GtkDeviceGrabInfo, info);
8822 * gtk_window_group_get_current_device_grab:
8823 * @window_group: a #GtkWindowGroup
8824 * @device: a #GdkDevice
8826 * Returns the current grab widget for @device, or %NULL if none.
8828 * Returns: (transfer none): The grab widget, or %NULL
8833 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8836 GtkWindowGroupPrivate *priv;
8837 GtkDeviceGrabInfo *info;
8838 GdkDevice *other_device;
8841 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8842 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8844 priv = window_group->priv;
8845 list = priv->device_grabs;
8846 other_device = gdk_device_get_associated_device (device);
8853 if (info->device == device ||
8854 info->device == other_device)
8855 return info->widget;
8862 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8866 GtkWindowGroupPrivate *priv;
8867 GtkDeviceGrabInfo *info;
8868 GdkDevice *other_device;
8871 priv = window_group->priv;
8872 other_device = gdk_device_get_associated_device (device);
8873 list = priv->device_grabs;
8880 /* Look for blocking grabs on other device pairs
8881 * that have the passed widget within the GTK+ grab.
8883 if (info->block_others &&
8884 info->device != device &&
8885 info->device != other_device &&
8886 (info->widget == widget ||
8887 gtk_widget_is_ancestor (widget, info->widget)))
8895 Derived from XParseGeometry() in XFree86
8897 Copyright 1985, 1986, 1987,1998 The Open Group
8899 All Rights Reserved.
8901 The above copyright notice and this permission notice shall be included
8902 in all copies or substantial portions of the Software.
8904 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8905 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8906 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8907 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8908 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8909 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8910 OTHER DEALINGS IN THE SOFTWARE.
8912 Except as contained in this notice, the name of The Open Group shall
8913 not be used in advertising or otherwise to promote the sale, use or
8914 other dealings in this Software without prior written authorization
8915 from The Open Group.
8920 * XParseGeometry parses strings of the form
8921 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8922 * width, height, xoffset, and yoffset are unsigned integers.
8923 * Example: "=80x24+300-49"
8924 * The equal sign is optional.
8925 * It returns a bitmask that indicates which of the four values
8926 * were actually found in the string. For each value found,
8927 * the corresponding argument is updated; for each value
8928 * not found, the corresponding argument is left unchanged.
8931 /* The following code is from Xlib, and is minimally modified, so we
8932 * can track any upstream changes if required. Don't change this
8933 * code. Or if you do, put in a huge comment marking which thing
8938 read_int (gchar *string,
8946 else if (*string == '-')
8952 for (; (*string >= '0') && (*string <= '9'); string++)
8954 result = (result * 10) + (*string - '0');
8966 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8967 * value (x, y, width, height) was found in the parsed string.
8969 #define NoValue 0x0000
8970 #define XValue 0x0001
8971 #define YValue 0x0002
8972 #define WidthValue 0x0004
8973 #define HeightValue 0x0008
8974 #define AllValues 0x000F
8975 #define XNegative 0x0010
8976 #define YNegative 0x0020
8978 /* Try not to reformat/modify, so we can compare/sync with X sources */
8980 gtk_XParseGeometry (const char *string,
8983 unsigned int *width,
8984 unsigned int *height)
8988 unsigned int tempWidth, tempHeight;
8990 char *nextCharacter;
8992 /* These initializations are just to silence gcc */
8998 if ( (string == NULL) || (*string == '\0')) return(mask);
9000 string++; /* ignore possible '=' at beg of geometry spec */
9002 strind = (char *)string;
9003 if (*strind != '+' && *strind != '-' && *strind != 'x') {
9004 tempWidth = read_int(strind, &nextCharacter);
9005 if (strind == nextCharacter)
9007 strind = nextCharacter;
9011 if (*strind == 'x' || *strind == 'X') {
9013 tempHeight = read_int(strind, &nextCharacter);
9014 if (strind == nextCharacter)
9016 strind = nextCharacter;
9017 mask |= HeightValue;
9020 if ((*strind == '+') || (*strind == '-')) {
9021 if (*strind == '-') {
9023 tempX = -read_int(strind, &nextCharacter);
9024 if (strind == nextCharacter)
9026 strind = nextCharacter;
9032 tempX = read_int(strind, &nextCharacter);
9033 if (strind == nextCharacter)
9035 strind = nextCharacter;
9038 if ((*strind == '+') || (*strind == '-')) {
9039 if (*strind == '-') {
9041 tempY = -read_int(strind, &nextCharacter);
9042 if (strind == nextCharacter)
9044 strind = nextCharacter;
9051 tempY = read_int(strind, &nextCharacter);
9052 if (strind == nextCharacter)
9054 strind = nextCharacter;
9060 /* If strind isn't at the end of the string the it's an invalid
9061 geometry specification. */
9063 if (*strind != '\0') return (0);
9069 if (mask & WidthValue)
9071 if (mask & HeightValue)
9072 *height = tempHeight;
9077 * gtk_window_parse_geometry:
9078 * @window: a #GtkWindow
9079 * @geometry: geometry string
9081 * Parses a standard X Window System geometry string - see the
9082 * manual page for X (type 'man X') for details on this.
9083 * gtk_window_parse_geometry() does work on all GTK+ ports
9084 * including Win32 but is primarily intended for an X environment.
9086 * If either a size or a position can be extracted from the
9087 * geometry string, gtk_window_parse_geometry() returns %TRUE
9088 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9089 * to resize/move the window.
9091 * If gtk_window_parse_geometry() returns %TRUE, it will also
9092 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9093 * indicating to the window manager that the size/position of
9094 * the window was user-specified. This causes most window
9095 * managers to honor the geometry.
9097 * Note that for gtk_window_parse_geometry() to work as expected, it has
9098 * to be called when the window has its "final" size, i.e. after calling
9099 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9102 * #include <gtk/gtk.h>
9105 * fill_with_content (GtkWidget *vbox)
9107 * /* fill with content... */
9111 * main (int argc, char *argv[])
9113 * GtkWidget *window, *vbox;
9114 * GdkGeometry size_hints = {
9115 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9118 * gtk_init (&argc, &argv);
9120 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9121 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9123 * gtk_container_add (GTK_CONTAINER (window), vbox);
9124 * fill_with_content (vbox);
9125 * gtk_widget_show_all (vbox);
9127 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9130 * GDK_HINT_MIN_SIZE |
9131 * GDK_HINT_BASE_SIZE |
9132 * GDK_HINT_RESIZE_INC);
9136 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9137 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9140 * gtk_widget_show_all (window);
9147 * Return value: %TRUE if string was parsed successfully
9150 gtk_window_parse_geometry (GtkWindow *window,
9151 const gchar *geometry)
9153 gint result, x = 0, y = 0;
9157 gboolean size_set, pos_set;
9160 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9161 g_return_val_if_fail (geometry != NULL, FALSE);
9163 child = gtk_bin_get_child (GTK_BIN (window));
9164 if (!child || !gtk_widget_get_visible (child))
9165 g_warning ("gtk_window_parse_geometry() called on a window with no "
9166 "visible children; the window should be set up before "
9167 "gtk_window_parse_geometry() is called.");
9169 screen = gtk_window_check_screen (window);
9171 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9174 if ((result & WidthValue) || (result & HeightValue))
9176 gtk_window_set_default_size_internal (window,
9177 TRUE, result & WidthValue ? w : -1,
9178 TRUE, result & HeightValue ? h : -1,
9183 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9185 grav = GDK_GRAVITY_NORTH_WEST;
9187 if ((result & XNegative) && (result & YNegative))
9188 grav = GDK_GRAVITY_SOUTH_EAST;
9189 else if (result & XNegative)
9190 grav = GDK_GRAVITY_NORTH_EAST;
9191 else if (result & YNegative)
9192 grav = GDK_GRAVITY_SOUTH_WEST;
9194 if ((result & XValue) == 0)
9197 if ((result & YValue) == 0)
9200 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9201 grav == GDK_GRAVITY_SOUTH_EAST)
9202 y = gdk_screen_get_height (screen) - h + y;
9204 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9205 grav == GDK_GRAVITY_NORTH_EAST)
9206 x = gdk_screen_get_width (screen) - w + x;
9208 /* we don't let you put a window offscreen; maybe some people would
9209 * prefer to be able to, but it's kind of a bogus thing to do.
9218 if ((result & XValue) || (result & YValue))
9220 gtk_window_set_gravity (window, grav);
9221 gtk_window_move (window, x, y);
9225 if (size_set || pos_set)
9227 /* Set USSize, USPosition hints */
9228 GtkWindowGeometryInfo *info;
9230 info = gtk_window_get_geometry_info (window, TRUE);
9233 info->mask |= GDK_HINT_USER_POS;
9235 info->mask |= GDK_HINT_USER_SIZE;
9242 gtk_window_mnemonic_hash_foreach (guint keyval,
9248 GtkWindowKeysForeachFunc func;
9252 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9256 _gtk_window_keys_foreach (GtkWindow *window,
9257 GtkWindowKeysForeachFunc func,
9261 GtkMnemonicHash *mnemonic_hash;
9265 GtkWindowKeysForeachFunc func;
9269 info.window = window;
9271 info.func_data = func_data;
9273 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9275 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9276 gtk_window_mnemonic_hash_foreach, &info);
9278 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9281 GtkAccelGroup *group = groups->data;
9284 for (i = 0; i < group->priv->n_accels; i++)
9286 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9289 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9292 groups = groups->next;
9297 gtk_window_keys_changed (GtkWindow *window)
9299 gtk_window_free_key_hash (window);
9300 gtk_window_get_key_hash (window);
9303 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9305 struct _GtkWindowKeyEntry
9309 guint is_mnemonic : 1;
9313 window_key_entry_destroy (gpointer data)
9315 g_slice_free (GtkWindowKeyEntry, data);
9319 add_to_key_hash (GtkWindow *window,
9321 GdkModifierType modifiers,
9322 gboolean is_mnemonic,
9325 GtkKeyHash *key_hash = data;
9327 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9329 entry->keyval = keyval;
9330 entry->modifiers = modifiers;
9331 entry->is_mnemonic = is_mnemonic;
9333 /* GtkAccelGroup stores lowercased accelerators. To deal
9334 * with this, if <Shift> was specified, uppercase.
9336 if (modifiers & GDK_SHIFT_MASK)
9338 if (keyval == GDK_KEY_Tab)
9339 keyval = GDK_KEY_ISO_Left_Tab;
9341 keyval = gdk_keyval_to_upper (keyval);
9344 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9348 gtk_window_get_key_hash (GtkWindow *window)
9350 GdkScreen *screen = gtk_window_check_screen (window);
9351 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9356 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9357 (GDestroyNotify)window_key_entry_destroy);
9358 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9359 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9365 gtk_window_free_key_hash (GtkWindow *window)
9367 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9370 _gtk_key_hash_free (key_hash);
9371 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9376 * gtk_window_activate_key:
9377 * @window: a #GtkWindow
9378 * @event: a #GdkEventKey
9380 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9381 * called by the default ::key_press_event handler for toplevel windows,
9382 * however in some cases it may be useful to call this directly when
9383 * overriding the standard key handling for a toplevel window.
9385 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9390 gtk_window_activate_key (GtkWindow *window,
9393 GtkKeyHash *key_hash;
9394 GtkWindowKeyEntry *found_entry = NULL;
9395 gboolean enable_mnemonics;
9396 gboolean enable_accels;
9398 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9399 g_return_val_if_fail (event != NULL, FALSE);
9401 key_hash = gtk_window_get_key_hash (window);
9406 GSList *entries = _gtk_key_hash_lookup (key_hash,
9407 event->hardware_keycode,
9409 gtk_accelerator_get_default_mod_mask (),
9412 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9413 "gtk-enable-mnemonics", &enable_mnemonics,
9414 "gtk-enable-accels", &enable_accels,
9417 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9419 GtkWindowKeyEntry *entry = tmp_list->data;
9420 if (entry->is_mnemonic)
9422 if (enable_mnemonics)
9424 found_entry = entry;
9430 if (enable_accels && !found_entry)
9432 found_entry = entry;
9437 g_slist_free (entries);
9442 if (found_entry->is_mnemonic)
9444 if (enable_mnemonics)
9445 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9446 found_entry->modifiers);
9451 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9452 found_entry->modifiers);
9460 window_update_has_focus (GtkWindow *window)
9462 GtkWindowPrivate *priv = window->priv;
9463 GtkWidget *widget = GTK_WIDGET (window);
9464 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9466 if (has_focus != priv->has_focus)
9468 priv->has_focus = has_focus;
9472 if (priv->focus_widget &&
9473 priv->focus_widget != widget &&
9474 !gtk_widget_has_focus (priv->focus_widget))
9475 do_focus_change (priv->focus_widget, TRUE);
9479 if (priv->focus_widget &&
9480 priv->focus_widget != widget &&
9481 gtk_widget_has_focus (priv->focus_widget))
9482 do_focus_change (priv->focus_widget, FALSE);
9488 * _gtk_window_set_is_active:
9489 * @window: a #GtkWindow
9490 * @is_active: %TRUE if the window is in the currently active toplevel
9492 * Internal function that sets whether the #GtkWindow is part
9493 * of the currently active toplevel window (taking into account inter-process
9497 _gtk_window_set_is_active (GtkWindow *window,
9500 GtkWindowPrivate *priv;
9502 g_return_if_fail (GTK_IS_WINDOW (window));
9504 priv = window->priv;
9506 is_active = is_active != FALSE;
9508 if (is_active != priv->is_active)
9510 priv->is_active = is_active;
9511 window_update_has_focus (window);
9513 g_object_notify (G_OBJECT (window), "is-active");
9518 * _gtk_window_set_is_toplevel:
9519 * @window: a #GtkWindow
9520 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9521 * child of the root window); %FALSE if it is not (for example, for an
9522 * in-process, parented GtkPlug)
9524 * Internal function used by #GtkPlug when it gets parented/unparented by a
9525 * #GtkSocket. This keeps the @window's #GTK_WINDOW_TOPLEVEL flag in sync
9526 * with the global list of toplevel windows.
9529 _gtk_window_set_is_toplevel (GtkWindow *window,
9530 gboolean is_toplevel)
9533 GtkWidget *toplevel;
9535 widget = GTK_WIDGET (window);
9537 if (gtk_widget_is_toplevel (widget))
9538 g_assert (g_slist_find (toplevel_list, window) != NULL);
9540 g_assert (g_slist_find (toplevel_list, window) == NULL);
9542 if (is_toplevel == gtk_widget_is_toplevel (widget))
9547 /* Pass through regular pathways of an embedded toplevel
9548 * to go through unmapping and hiding the widget before
9549 * becomming a toplevel again.
9551 * We remain hidden after becomming toplevel in order to
9552 * avoid problems during an embedded toplevel's dispose cycle
9553 * (When a toplevel window is shown it tries to grab focus again,
9554 * this causes problems while disposing).
9556 gtk_widget_hide (widget);
9558 /* Save the toplevel this widget was previously anchored into before
9559 * propagating a hierarchy-changed.
9561 * Usually this happens by way of gtk_widget_unparent() and we are
9562 * already unanchored at this point, just adding this clause incase
9563 * things happen differently.
9565 toplevel = gtk_widget_get_toplevel (widget);
9566 if (!gtk_widget_is_toplevel (toplevel))
9569 _gtk_widget_set_is_toplevel (widget, TRUE);
9571 /* When a window becomes toplevel after being embedded and anchored
9572 * into another window we need to unset its anchored flag so that
9573 * the hierarchy changed signal kicks in properly.
9575 _gtk_widget_set_anchored (widget, FALSE);
9576 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9578 toplevel_list = g_slist_prepend (toplevel_list, window);
9582 _gtk_widget_set_is_toplevel (widget, FALSE);
9583 toplevel_list = g_slist_remove (toplevel_list, window);
9585 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9590 * _gtk_window_set_has_toplevel_focus:
9591 * @window: a #GtkWindow
9592 * @has_toplevel_focus: %TRUE if the in
9594 * Internal function that sets whether the keyboard focus for the
9595 * toplevel window (taking into account inter-process embedding.)
9598 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9599 gboolean has_toplevel_focus)
9601 GtkWindowPrivate *priv;
9603 g_return_if_fail (GTK_IS_WINDOW (window));
9605 priv = window->priv;
9607 has_toplevel_focus = has_toplevel_focus != FALSE;
9609 if (has_toplevel_focus != priv->has_toplevel_focus)
9611 priv->has_toplevel_focus = has_toplevel_focus;
9612 window_update_has_focus (window);
9614 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9619 * gtk_window_set_auto_startup_notification:
9620 * @setting: %TRUE to automatically do startup notification
9622 * By default, after showing the first #GtkWindow, GTK+ calls
9623 * gdk_notify_startup_complete(). Call this function to disable
9624 * the automatic startup notification. You might do this if your
9625 * first window is a splash screen, and you want to delay notification
9626 * until after your real main window has been shown, for example.
9628 * In that example, you would disable startup notification
9629 * temporarily, show your splash screen, then re-enable it so that
9630 * showing the main window would automatically result in notification.
9635 gtk_window_set_auto_startup_notification (gboolean setting)
9637 disable_startup_notification = !setting;
9641 * gtk_window_get_window_type:
9642 * @window: a #GtkWindow
9644 * Gets the type of the window. See #GtkWindowType.
9646 * Return value: the type of the window
9651 gtk_window_get_window_type (GtkWindow *window)
9653 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9655 return window->priv->type;
9659 * gtk_window_get_mnemonics_visible:
9660 * @window: a #GtkWindow
9662 * Gets the value of the #GtkWindow:mnemonics-visible property.
9664 * Returns: %TRUE if mnemonics are supposed to be visible
9670 gtk_window_get_mnemonics_visible (GtkWindow *window)
9672 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9674 return window->priv->mnemonics_visible;
9678 * gtk_window_set_mnemonics_visible:
9679 * @window: a #GtkWindow
9680 * @setting: the new value
9682 * Sets the #GtkWindow:mnemonics-visible property.
9687 gtk_window_set_mnemonics_visible (GtkWindow *window,
9690 GtkWindowPrivate *priv;
9692 g_return_if_fail (GTK_IS_WINDOW (window));
9694 priv = window->priv;
9696 setting = setting != FALSE;
9698 if (priv->mnemonics_visible != setting)
9700 priv->mnemonics_visible = setting;
9701 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9704 if (priv->auto_mnemonics_timeout_id)
9706 g_source_remove (priv->auto_mnemonics_timeout_id);
9707 priv->auto_mnemonics_timeout_id = 0;
9710 priv->mnemonics_visible_set = TRUE;
9714 set_auto_mnemonics_visible_cb (gpointer data)
9716 GtkWindow *window = data;
9718 gtk_window_set_mnemonics_visible (window, TRUE);
9720 window->priv->auto_mnemonics_timeout_id = 0;
9726 _gtk_window_set_auto_mnemonics_visible (GtkWindow *window)
9728 g_return_if_fail (GTK_IS_WINDOW (window));
9730 if (window->priv->auto_mnemonics_timeout_id)
9733 window->priv->auto_mnemonics_timeout_id =
9734 gdk_threads_add_timeout (AUTO_MNEMONICS_DELAY, set_auto_mnemonics_visible_cb, window);
9738 * gtk_window_get_focus_visible:
9739 * @window: a #GtkWindow
9741 * Gets the value of the #GtkWindow:focus-visible property.
9743 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9749 gtk_window_get_focus_visible (GtkWindow *window)
9751 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9753 return window->priv->focus_visible;
9757 * gtk_window_set_focus_visible:
9758 * @window: a #GtkWindow
9759 * @setting: the new value
9761 * Sets the #GtkWindow:focus-visible property.
9766 gtk_window_set_focus_visible (GtkWindow *window,
9769 GtkWindowPrivate *priv;
9771 g_return_if_fail (GTK_IS_WINDOW (window));
9773 priv = window->priv;
9775 setting = setting != FALSE;
9777 if (priv->focus_visible != setting)
9779 priv->focus_visible = setting;
9780 g_object_notify (G_OBJECT (window), "focus-visible");
9785 _gtk_window_get_wmclass (GtkWindow *window,
9786 gchar **wmclass_name,
9787 gchar **wmclass_class)
9789 GtkWindowPrivate *priv = window->priv;
9791 *wmclass_name = priv->wmclass_name;
9792 *wmclass_class = priv->wmclass_class;
9796 * gtk_window_set_has_user_ref_count:
9797 * @window: a #GtkWindow
9798 * @setting: the new value
9800 * Tells GTK+ whether to drop its extra reference to the window
9801 * when gtk_widget_destroy() is called.
9803 * This function is only exported for the benefit of language
9804 * bindings which may need to keep the window alive until their
9805 * wrapper object is garbage collected. There is no justification
9806 * for ever calling this function in an application.
9811 gtk_window_set_has_user_ref_count (GtkWindow *window,
9814 g_return_if_fail (GTK_IS_WINDOW (window));
9816 window->priv->has_user_ref_count = setting;
9820 ensure_state_flag_backdrop (GtkWidget *widget)
9823 gboolean window_focused = TRUE;
9825 window = gtk_widget_get_window (widget);
9827 window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9829 if (!window_focused)
9830 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
9832 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
9834 gtk_widget_queue_draw (widget);