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 * - filling in widget->allocation with the new size
5670 * - setting configure_notify_received to TRUE
5671 * for use in gtk_window_move_resize()
5672 * - queueing a resize, leading to invocation of
5673 * gtk_window_move_resize() in an idle handler
5677 priv->configure_notify_received = TRUE;
5679 allocation.width = event->width;
5680 allocation.height = event->height;
5681 gtk_widget_set_allocation (widget, &allocation);
5683 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5685 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5691 gtk_window_state_event (GtkWidget *widget,
5692 GdkEventWindowState *event)
5694 update_grip_visibility (GTK_WINDOW (widget));
5696 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
5697 ensure_state_flag_backdrop (widget);
5703 gtk_window_direction_changed (GtkWidget *widget,
5704 GtkTextDirection prev_dir)
5706 GtkWindow *window = GTK_WINDOW (widget);
5708 set_grip_cursor (window);
5709 set_grip_position (window);
5710 set_grip_shape (window);
5714 gtk_window_state_changed (GtkWidget *widget,
5715 GtkStateType previous_state)
5717 GtkWindow *window = GTK_WINDOW (widget);
5719 update_grip_visibility (window);
5723 gtk_window_style_updated (GtkWidget *widget)
5725 GtkWindow *window = GTK_WINDOW (widget);
5726 GtkWindowPrivate *priv = window->priv;
5729 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5731 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5733 gdk_window_move_resize (priv->grip_window,
5735 rect.width, rect.height);
5737 set_grip_shape (window);
5742 resize_grip_create_window (GtkWindow *window)
5745 GtkWindowPrivate *priv;
5746 GdkWindowAttr attributes;
5747 gint attributes_mask;
5749 GdkRGBA transparent = {0, 0, 0, 0};
5751 priv = window->priv;
5752 widget = GTK_WIDGET (window);
5754 g_return_if_fail (gtk_widget_get_realized (widget));
5755 g_return_if_fail (priv->grip_window == NULL);
5757 gtk_window_get_resize_grip_area (window, &rect);
5759 attributes.x = rect.x;
5760 attributes.y = rect.y;
5761 attributes.width = rect.width;
5762 attributes.height = rect.height;
5763 attributes.window_type = GDK_WINDOW_CHILD;
5764 attributes.wclass = GDK_INPUT_OUTPUT;
5765 attributes.event_mask = gtk_widget_get_events (widget) |
5767 GDK_BUTTON_PRESS_MASK;
5769 attributes_mask = GDK_WA_X | GDK_WA_Y;
5771 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5774 gdk_window_set_background_rgba (priv->grip_window, &transparent);
5776 gdk_window_set_user_data (priv->grip_window, widget);
5778 gdk_window_raise (priv->grip_window);
5780 set_grip_shape (window);
5781 update_grip_visibility (window);
5785 resize_grip_destroy_window (GtkWindow *window)
5787 GtkWindowPrivate *priv = window->priv;
5789 gdk_window_set_user_data (priv->grip_window, NULL);
5790 gdk_window_destroy (priv->grip_window);
5791 priv->grip_window = NULL;
5792 update_grip_visibility (window);
5796 * gtk_window_set_has_resize_grip:
5797 * @window: a #GtkWindow
5798 * @value: %TRUE to allow a resize grip
5800 * Sets whether @window has a corner resize grip.
5802 * Note that the resize grip is only shown if the window
5803 * is actually resizable and not maximized. Use
5804 * gtk_window_resize_grip_is_visible() to find out if the
5805 * resize grip is currently shown.
5810 gtk_window_set_has_resize_grip (GtkWindow *window,
5813 GtkWidget *widget = GTK_WIDGET (window);
5814 GtkWindowPrivate *priv = window->priv;
5816 value = value != FALSE;
5818 if (value != priv->has_resize_grip)
5820 priv->has_resize_grip = value;
5821 gtk_widget_queue_draw (widget);
5823 if (gtk_widget_get_realized (widget) &&
5824 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5826 if (priv->has_resize_grip && priv->grip_window == NULL)
5827 resize_grip_create_window (window);
5828 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5829 resize_grip_destroy_window (window);
5832 g_object_notify (G_OBJECT (window), "has-resize-grip");
5837 update_grip_visibility (GtkWindow *window)
5839 GtkWindowPrivate *priv = window->priv;
5842 val = gtk_window_resize_grip_is_visible (window);
5844 if (priv->grip_window != NULL)
5848 gdk_window_show (priv->grip_window);
5849 set_grip_cursor (window);
5853 gdk_window_hide (priv->grip_window);
5857 if (priv->resize_grip_visible != val)
5859 priv->resize_grip_visible = val;
5861 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5866 * gtk_window_resize_grip_is_visible:
5867 * @window: a #GtkWindow
5869 * Determines whether a resize grip is visible for the specified window.
5871 * Returns: %TRUE if a resize grip exists and is visible
5876 gtk_window_resize_grip_is_visible (GtkWindow *window)
5879 GtkWindowPrivate *priv;
5882 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5884 priv = window->priv;
5885 widget = GTK_WIDGET (window);
5887 if (priv->type == GTK_WINDOW_POPUP)
5890 if (!priv->resizable)
5893 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5896 if (gtk_widget_get_realized (widget))
5898 GdkWindowState state;
5900 state = gdk_window_get_state (gtk_widget_get_window (widget));
5902 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5906 if (!get_drag_edge (widget, &edge))
5909 return window->priv->has_resize_grip;
5913 * gtk_window_get_has_resize_grip:
5914 * @window: a #GtkWindow
5916 * Determines whether the window may have a resize grip.
5918 * Returns: %TRUE if the window has a resize grip
5923 gtk_window_get_has_resize_grip (GtkWindow *window)
5925 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5927 return window->priv->has_resize_grip;
5931 * gtk_window_get_resize_grip_area:
5932 * @window: a #GtkWindow
5933 * @rect: (out): a pointer to a #GdkRectangle which we should store
5934 * the resize grip area
5936 * If a window has a resize grip, this will retrieve the grip
5937 * position, width and height into the specified #GdkRectangle.
5939 * Returns: %TRUE if the resize grip's area was retrieved
5944 gtk_window_get_resize_grip_area (GtkWindow *window,
5947 GtkWidget *widget = GTK_WIDGET (window);
5948 GtkAllocation allocation;
5952 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5954 if (!window->priv->has_resize_grip)
5957 gtk_widget_get_allocation (widget, &allocation);
5959 gtk_widget_style_get (widget,
5960 "resize-grip-width", &grip_width,
5961 "resize-grip-height", &grip_height,
5964 if (grip_width > allocation.width)
5965 grip_width = allocation.width;
5967 if (grip_height > allocation.height)
5968 grip_height = allocation.height;
5970 rect->width = grip_width;
5971 rect->height = grip_height;
5972 rect->y = allocation.y + allocation.height - grip_height;
5974 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5975 rect->x = allocation.x + allocation.width - grip_width;
5977 rect->x = allocation.x;
5982 /* the accel_key and accel_mods fields of the key have to be setup
5983 * upon calling this function. it'll then return whether that key
5984 * is at all used as accelerator, and if so will OR in the
5985 * accel_flags member of the key.
5988 _gtk_window_query_nonaccels (GtkWindow *window,
5990 GdkModifierType accel_mods)
5992 GtkWindowPrivate *priv;
5994 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5996 priv = window->priv;
5998 /* movement keys are considered locked accels */
6001 static const guint bindings[] = {
6002 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,
6003 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,
6007 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
6008 if (bindings[i] == accel_key)
6012 /* mnemonics are considered locked accels */
6013 if (accel_mods == priv->mnemonic_modifier)
6015 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
6016 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
6024 * gtk_window_propagate_key_event:
6025 * @window: a #GtkWindow
6026 * @event: a #GdkEventKey
6028 * Propagate a key press or release event to the focus widget and
6029 * up the focus container chain until a widget handles @event.
6030 * This is normally called by the default ::key_press_event and
6031 * ::key_release_event handlers for toplevel windows,
6032 * however in some cases it may be useful to call this directly when
6033 * overriding the standard key handling for a toplevel window.
6035 * Return value: %TRUE if a widget in the focus chain handled the event.
6040 gtk_window_propagate_key_event (GtkWindow *window,
6043 GtkWindowPrivate *priv;
6044 gboolean handled = FALSE;
6045 GtkWidget *widget, *focus;
6047 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6049 priv = window->priv;
6050 widget = GTK_WIDGET (window);
6052 focus = priv->focus_widget;
6054 g_object_ref (focus);
6057 focus && focus != widget &&
6058 gtk_widget_get_toplevel (focus) == widget)
6062 if (gtk_widget_is_sensitive (focus))
6063 handled = gtk_widget_event (focus, (GdkEvent*) event);
6065 parent = gtk_widget_get_parent (focus);
6067 g_object_ref (parent);
6069 g_object_unref (focus);
6075 g_object_unref (focus);
6081 gtk_window_key_press_event (GtkWidget *widget,
6084 GtkWindow *window = GTK_WINDOW (widget);
6085 gboolean handled = FALSE;
6087 /* handle mnemonics and accelerators */
6089 handled = gtk_window_activate_key (window, event);
6091 /* handle focus widget key events */
6093 handled = gtk_window_propagate_key_event (window, event);
6095 /* Chain up, invokes binding set */
6097 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
6103 gtk_window_key_release_event (GtkWidget *widget,
6106 GtkWindow *window = GTK_WINDOW (widget);
6107 gboolean handled = FALSE;
6109 /* handle focus widget key events */
6111 handled = gtk_window_propagate_key_event (window, event);
6113 /* Chain up, invokes binding set */
6115 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
6121 gtk_window_button_press_event (GtkWidget *widget,
6122 GdkEventButton *event)
6124 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
6127 if (event->window == priv->grip_window)
6129 if (get_drag_edge (widget, &edge))
6130 gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
6132 gdk_event_get_device ((GdkEvent *) event),
6145 gtk_window_real_activate_default (GtkWindow *window)
6147 gtk_window_activate_default (window);
6151 gtk_window_real_activate_focus (GtkWindow *window)
6153 gtk_window_activate_focus (window);
6157 gtk_window_enter_notify_event (GtkWidget *widget,
6158 GdkEventCrossing *event)
6164 gtk_window_leave_notify_event (GtkWidget *widget,
6165 GdkEventCrossing *event)
6171 do_focus_change (GtkWidget *widget,
6175 GdkDeviceManager *device_manager;
6178 g_object_ref (widget);
6180 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
6181 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6182 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
6183 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
6185 for (d = devices; d; d = d->next)
6187 GdkDevice *dev = d->data;
6190 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
6193 /* Skip non-master keyboards that haven't
6194 * selected for events from this window
6196 window = gtk_widget_get_window (widget);
6197 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
6198 window && !gdk_window_get_device_events (window, dev))
6201 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
6203 fevent->focus_change.type = GDK_FOCUS_CHANGE;
6204 fevent->focus_change.window = window;
6206 g_object_ref (window);
6207 fevent->focus_change.in = in;
6208 gdk_event_set_device (fevent, dev);
6210 gtk_widget_send_focus_change (widget, fevent);
6212 gdk_event_free (fevent);
6215 g_list_free (devices);
6216 g_object_unref (widget);
6220 maybe_set_mnemonics_visible (GtkWindow *window)
6223 GdkDeviceManager *device_manager;
6225 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
6226 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6228 for (d = devices; d; d = d->next)
6230 GdkDevice *dev = d->data;
6232 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6234 GdkModifierType mask;
6236 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6238 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6240 _gtk_window_set_auto_mnemonics_visible (window);
6246 g_list_free (devices);
6250 gtk_window_focus_in_event (GtkWidget *widget,
6251 GdkEventFocus *event)
6253 GtkWindow *window = GTK_WINDOW (widget);
6254 gboolean auto_mnemonics;
6256 /* It appears spurious focus in events can occur when
6257 * the window is hidden. So we'll just check to see if
6258 * the window is visible before actually handling the
6261 if (gtk_widget_get_visible (widget))
6263 _gtk_window_set_has_toplevel_focus (window, TRUE);
6264 _gtk_window_set_is_active (window, TRUE);
6266 g_object_get (gtk_widget_get_settings (widget),
6267 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6269 maybe_set_mnemonics_visible (window);
6276 gtk_window_focus_out_event (GtkWidget *widget,
6277 GdkEventFocus *event)
6279 GtkWindow *window = GTK_WINDOW (widget);
6280 gboolean auto_mnemonics;
6282 _gtk_window_set_has_toplevel_focus (window, FALSE);
6283 _gtk_window_set_is_active (window, FALSE);
6285 /* set the mnemonic-visible property to false */
6286 g_object_get (gtk_widget_get_settings (widget),
6287 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6289 gtk_window_set_mnemonics_visible (window, FALSE);
6295 gtk_window_check_resize (GtkContainer *container)
6297 /* If the window is not toplevel anymore than it's embedded somewhere,
6298 * so handle it like a normal window */
6299 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6300 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6301 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6302 gtk_window_move_resize (GTK_WINDOW (container));
6306 gtk_window_focus (GtkWidget *widget,
6307 GtkDirectionType direction)
6309 GtkWindowPrivate *priv;
6312 GtkContainer *container;
6314 GtkWidget *old_focus_child;
6317 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6318 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6320 container = GTK_CONTAINER (widget);
6321 window = GTK_WINDOW (widget);
6322 priv = window->priv;
6323 bin = GTK_BIN (widget);
6325 old_focus_child = gtk_container_get_focus_child (container);
6327 /* We need a special implementation here to deal properly with wrapping
6328 * around in the tab chain without the danger of going into an
6331 if (old_focus_child)
6333 if (gtk_widget_child_focus (old_focus_child, direction))
6337 if (priv->focus_widget)
6339 if (direction == GTK_DIR_LEFT ||
6340 direction == GTK_DIR_RIGHT ||
6341 direction == GTK_DIR_UP ||
6342 direction == GTK_DIR_DOWN)
6347 /* Wrapped off the end, clear the focus setting for the toplpevel */
6348 parent = gtk_widget_get_parent (priv->focus_widget);
6351 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6352 parent = gtk_widget_get_parent (parent);
6355 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6358 /* Now try to focus the first widget in the window */
6359 child = gtk_bin_get_child (bin);
6362 if (gtk_widget_child_focus (child, direction))
6370 gtk_window_move_focus (GtkWidget *widget,
6371 GtkDirectionType dir)
6373 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6375 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6379 gtk_widget_child_focus (widget, dir);
6381 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6382 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6386 gtk_window_real_set_focus (GtkWindow *window,
6389 GtkWindowPrivate *priv = window->priv;
6390 GtkWidget *old_focus = priv->focus_widget;
6391 gboolean had_default = FALSE;
6392 gboolean focus_had_default = FALSE;
6393 gboolean old_focus_had_default = FALSE;
6397 g_object_ref (old_focus);
6398 g_object_freeze_notify (G_OBJECT (old_focus));
6399 old_focus_had_default = gtk_widget_has_default (old_focus);
6403 g_object_ref (focus);
6404 g_object_freeze_notify (G_OBJECT (focus));
6405 focus_had_default = gtk_widget_has_default (focus);
6408 if (priv->default_widget)
6409 had_default = gtk_widget_has_default (priv->default_widget);
6411 if (priv->focus_widget)
6413 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6414 (priv->focus_widget != priv->default_widget))
6416 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6417 gtk_widget_queue_draw (priv->focus_widget);
6419 if (priv->default_widget)
6420 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6423 priv->focus_widget = NULL;
6425 if (priv->has_focus)
6426 do_focus_change (old_focus, FALSE);
6428 g_object_notify (G_OBJECT (old_focus), "is-focus");
6431 /* The above notifications may have set a new focus widget,
6432 * if so, we don't want to override it.
6434 if (focus && !priv->focus_widget)
6436 priv->focus_widget = focus;
6438 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6439 (priv->focus_widget != priv->default_widget))
6441 if (gtk_widget_get_can_default (priv->focus_widget))
6442 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6444 if (priv->default_widget)
6445 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6448 if (priv->has_focus)
6449 do_focus_change (priv->focus_widget, TRUE);
6451 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6454 /* If the default widget changed, a redraw will have been queued
6455 * on the old and new default widgets by gtk_window_set_default(), so
6456 * we only have to worry about the case where it didn't change.
6457 * We'll sometimes queue a draw twice on the new widget but that
6460 if (priv->default_widget &&
6461 (had_default != gtk_widget_has_default (priv->default_widget)))
6462 gtk_widget_queue_draw (priv->default_widget);
6466 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6467 gtk_widget_queue_draw (old_focus);
6469 g_object_thaw_notify (G_OBJECT (old_focus));
6470 g_object_unref (old_focus);
6474 if (focus_had_default != gtk_widget_has_default (focus))
6475 gtk_widget_queue_draw (focus);
6477 g_object_thaw_notify (G_OBJECT (focus));
6478 g_object_unref (focus);
6483 * _gtk_window_unset_focus_and_default:
6484 * @window: a #GtkWindow
6485 * @widget: a widget inside of @window
6487 * Checks whether the focus and default widgets of @window are
6488 * @widget or a descendent of @widget, and if so, unset them.
6491 _gtk_window_unset_focus_and_default (GtkWindow *window,
6495 GtkWindowPrivate *priv = window->priv;
6499 g_object_ref (window);
6500 g_object_ref (widget);
6502 parent = gtk_widget_get_parent (widget);
6503 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6505 child = priv->focus_widget;
6507 while (child && child != widget)
6508 child = gtk_widget_get_parent (child);
6510 if (child == widget)
6511 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6514 child = priv->default_widget;
6516 while (child && child != widget)
6517 child = gtk_widget_get_parent (child);
6519 if (child == widget)
6520 gtk_window_set_default (window, NULL);
6522 g_object_unref (widget);
6523 g_object_unref (window);
6526 /*********************************
6527 * Functions related to resizing *
6528 *********************************/
6531 geometry_size_to_pixels (GdkGeometry *geometry,
6536 gint base_width = 0;
6537 gint base_height = 0;
6539 gint min_height = 0;
6541 gint height_inc = 1;
6543 if (flags & GDK_HINT_BASE_SIZE)
6545 base_width = geometry->base_width;
6546 base_height = geometry->base_height;
6548 if (flags & GDK_HINT_MIN_SIZE)
6550 min_width = geometry->min_width;
6551 min_height = geometry->min_height;
6553 if (flags & GDK_HINT_RESIZE_INC)
6555 width_inc = geometry->width_inc;
6556 height_inc = geometry->height_inc;
6560 *width = MAX (*width * width_inc + base_width, min_width);
6562 *height = MAX (*height * height_inc + base_height, min_height);
6565 /* This function doesn't constrain to geometry hints */
6567 gtk_window_compute_configure_request_size (GtkWindow *window,
6568 GdkGeometry *geometry,
6573 GtkWindowPrivate *priv = window->priv;
6574 GtkWindowGeometryInfo *info;
6577 * - we've done a size request
6580 info = gtk_window_get_geometry_info (window, FALSE);
6582 if (priv->need_default_size)
6584 gtk_window_guess_default_size (window, width, height);
6586 /* If window is empty so requests 0, default to random nonzero size */
6587 if (*width == 0 && *height == 0)
6593 /* Override with default size */
6597 if (info->default_width > 0)
6598 *width = info->default_width;
6599 if (info->default_height > 0)
6600 *height = info->default_height;
6602 if (info->default_is_geometry)
6603 geometry_size_to_pixels (geometry, flags,
6604 info->default_width > 0 ? width : NULL,
6605 info->default_height > 0 ? height : NULL);
6610 GtkAllocation allocation;
6612 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6614 /* Default to keeping current size */
6615 *width = allocation.width;
6616 *height = allocation.height;
6619 /* Override any size with gtk_window_resize() values */
6622 if (info->resize_width > 0)
6623 *width = info->resize_width;
6624 if (info->resize_height > 0)
6625 *height = info->resize_height;
6627 if (info->resize_is_geometry)
6628 geometry_size_to_pixels (geometry, flags,
6629 info->resize_width > 0 ? width : NULL,
6630 info->resize_height > 0 ? height : NULL);
6633 /* Don't ever request zero width or height, its not supported by
6634 gdk. The size allocation code will round it to 1 anyway but if
6635 we do it then the value returned from this function will is
6636 not comparable to the size allocation read from the GtkWindow. */
6637 *width = MAX (*width, 1);
6638 *height = MAX (*height, 1);
6641 static GtkWindowPosition
6642 get_effective_position (GtkWindow *window)
6644 GtkWindowPrivate *priv = window->priv;
6645 GtkWindowPosition pos = priv->position;
6647 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6648 (priv->transient_parent == NULL ||
6649 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6650 pos = GTK_WIN_POS_NONE;
6656 get_center_monitor_of_window (GtkWindow *window)
6658 /* We could try to sort out the relative positions of the monitors and
6659 * stuff, or we could just be losers and assume you have a row
6660 * or column of monitors.
6662 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6666 get_monitor_containing_pointer (GtkWindow *window)
6670 GdkScreen *window_screen;
6671 GdkScreen *pointer_screen;
6672 GdkDisplay *display;
6673 GdkDeviceManager *device_manager;
6676 window_screen = gtk_window_check_screen (window);
6677 display = gdk_screen_get_display (window_screen);
6678 device_manager = gdk_display_get_device_manager (display);
6679 pointer = gdk_device_manager_get_client_pointer (device_manager);
6681 gdk_device_get_position (pointer,
6685 if (pointer_screen == window_screen)
6686 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6694 center_window_on_monitor (GtkWindow *window,
6700 GdkRectangle monitor;
6703 monitor_num = get_monitor_containing_pointer (window);
6705 if (monitor_num == -1)
6706 monitor_num = get_center_monitor_of_window (window);
6708 gdk_screen_get_monitor_workarea (gtk_window_check_screen (window),
6709 monitor_num, &monitor);
6711 *x = (monitor.width - w) / 2 + monitor.x;
6712 *y = (monitor.height - h) / 2 + monitor.y;
6714 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6715 * and WM decorations.
6729 if (extent > clamp_extent)
6731 *base = clamp_base + clamp_extent/2 - extent/2;
6732 else if (*base < clamp_base)
6734 else if (*base + extent > clamp_base + clamp_extent)
6735 *base = clamp_base + clamp_extent - extent;
6739 clamp_window_to_rectangle (gint *x,
6743 const GdkRectangle *rect)
6745 #ifdef DEBUGGING_OUTPUT
6746 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);
6749 /* If it is too large, center it. If it fits on the monitor but is
6750 * partially outside, move it to the closest edge. Do this
6751 * separately in x and y directions.
6753 clamp (x, w, rect->x, rect->width);
6754 clamp (y, h, rect->y, rect->height);
6755 #ifdef DEBUGGING_OUTPUT
6756 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6762 gtk_window_compute_configure_request (GtkWindow *window,
6763 GdkRectangle *request,
6764 GdkGeometry *geometry,
6767 GtkWindowPrivate *priv = window->priv;
6768 GdkGeometry new_geometry;
6771 GtkWindowPosition pos;
6772 GtkWidget *parent_widget;
6773 GtkWindowGeometryInfo *info;
6777 screen = gtk_window_check_screen (window);
6779 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6780 gtk_window_compute_configure_request_size (window,
6781 &new_geometry, new_flags,
6784 gtk_window_constrain_size (window,
6785 &new_geometry, new_flags,
6789 parent_widget = (GtkWidget*) priv->transient_parent;
6791 pos = get_effective_position (window);
6792 info = gtk_window_get_geometry_info (window, FALSE);
6794 /* by default, don't change position requested */
6797 x = info->last.configure_request.x;
6798 y = info->last.configure_request.y;
6807 if (priv->need_default_position)
6810 /* FIXME this all interrelates with window gravity.
6811 * For most of them I think we want to set GRAVITY_CENTER.
6813 * Not sure how to go about that.
6817 /* here we are only handling CENTER_ALWAYS
6818 * as it relates to default positioning,
6819 * where it's equivalent to simply CENTER
6821 case GTK_WIN_POS_CENTER_ALWAYS:
6822 case GTK_WIN_POS_CENTER:
6823 center_window_on_monitor (window, w, h, &x, &y);
6826 case GTK_WIN_POS_CENTER_ON_PARENT:
6828 GtkAllocation allocation;
6829 GdkWindow *gdk_window;
6831 GdkRectangle monitor;
6834 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6836 gdk_window = gtk_widget_get_window (parent_widget);
6838 if (gdk_window != NULL)
6839 monitor_num = gdk_screen_get_monitor_at_window (screen,
6844 gdk_window_get_origin (gdk_window,
6847 gtk_widget_get_allocation (parent_widget, &allocation);
6848 x = ox + (allocation.width - w) / 2;
6849 y = oy + (allocation.height - h) / 2;
6851 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6852 * WM decorations. If parent wasn't on a monitor, just
6855 if (monitor_num >= 0)
6857 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6858 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6863 case GTK_WIN_POS_MOUSE:
6865 gint screen_width = gdk_screen_get_width (screen);
6866 gint screen_height = gdk_screen_get_height (screen);
6868 GdkRectangle monitor;
6869 GdkDisplay *display;
6870 GdkDeviceManager *device_manager;
6872 GdkScreen *pointer_screen;
6875 display = gdk_screen_get_display (screen);
6876 device_manager = gdk_display_get_device_manager (display);
6877 pointer = gdk_device_manager_get_client_pointer (device_manager);
6879 gdk_device_get_position (pointer,
6883 if (pointer_screen == screen)
6884 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6890 x = CLAMP (x, 0, screen_width - w);
6891 y = CLAMP (y, 0, screen_height - h);
6893 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6894 * WM decorations. Don't try to figure out what's going
6895 * on if the mouse wasn't inside a monitor.
6897 if (monitor_num >= 0)
6899 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6900 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6908 } /* if (priv->need_default_position) */
6910 if (priv->need_default_position && info &&
6911 info->initial_pos_set)
6913 x = info->initial_x;
6914 y = info->initial_y;
6915 gtk_window_constrain_position (window, w, h, &x, &y);
6921 request->height = h;
6924 *geometry = new_geometry;
6930 gtk_window_constrain_position (GtkWindow *window,
6936 GtkWindowPrivate *priv = window->priv;
6938 /* See long comments in gtk_window_move_resize()
6939 * on when it's safe to call this function.
6941 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6943 gint center_x, center_y;
6945 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6953 gtk_window_move_resize (GtkWindow *window)
6957 * First we determine whether any information has changed that would
6958 * cause us to revise our last configure request. If we would send
6959 * a different configure request from last time, then
6960 * configure_request_size_changed = TRUE or
6961 * configure_request_pos_changed = TRUE. configure_request_size_changed
6962 * may be true due to new hints, a gtk_window_resize(), or whatever.
6963 * configure_request_pos_changed may be true due to gtk_window_set_position()
6964 * or gtk_window_move().
6966 * If the configure request has changed, we send off a new one. To
6967 * ensure GTK+ invariants are maintained (resize queue does what it
6968 * should), we go ahead and size_allocate the requested size in this
6971 * If the configure request has not changed, we don't ever resend
6972 * it, because it could mean fighting the user or window manager.
6975 * To prepare the configure request, we come up with a base size/pos:
6976 * - the one from gtk_window_move()/gtk_window_resize()
6977 * - else default_width, default_height if we haven't ever
6979 * - else the size request if we haven't ever been mapped,
6980 * as a substitute default size
6981 * - else the current size of the window, as received from
6982 * configure notifies (i.e. the current allocation)
6984 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6985 * the position request to be centered.
6987 GtkWindowPrivate *priv = window->priv;
6988 GtkAllocation allocation;
6990 GtkContainer *container;
6991 GtkWindowGeometryInfo *info;
6992 GdkGeometry new_geometry;
6993 GdkWindow *gdk_window;
6995 GdkRectangle new_request;
6996 gboolean configure_request_size_changed;
6997 gboolean configure_request_pos_changed;
6998 gboolean hints_changed; /* do we need to send these again */
6999 GtkWindowLastGeometryInfo saved_last_info;
7001 widget = GTK_WIDGET (window);
7003 gdk_window = gtk_widget_get_window (widget);
7004 container = GTK_CONTAINER (widget);
7005 info = gtk_window_get_geometry_info (window, TRUE);
7007 configure_request_size_changed = FALSE;
7008 configure_request_pos_changed = FALSE;
7010 gtk_window_compute_configure_request (window, &new_request,
7011 &new_geometry, &new_flags);
7013 /* This check implies the invariant that we never set info->last
7014 * without setting the hints and sending off a configure request.
7016 * If we change info->last without sending the request, we may
7019 if (info->last.configure_request.x != new_request.x ||
7020 info->last.configure_request.y != new_request.y)
7021 configure_request_pos_changed = TRUE;
7023 if ((info->last.configure_request.width != new_request.width ||
7024 info->last.configure_request.height != new_request.height))
7025 configure_request_size_changed = TRUE;
7027 hints_changed = FALSE;
7029 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
7030 &new_geometry, new_flags))
7032 hints_changed = TRUE;
7035 /* Position Constraints
7036 * ====================
7038 * POS_CENTER_ALWAYS is conceptually a constraint rather than
7039 * a default. The other POS_ values are used only when the
7040 * window is shown, not after that.
7042 * However, we can't implement a position constraint as
7043 * "anytime the window size changes, center the window"
7044 * because this may well end up fighting the WM or user. In
7045 * fact it gets in an infinite loop with at least one WM.
7047 * Basically, applications are in no way in a position to
7048 * constrain the position of a window, with one exception:
7049 * override redirect windows. (Really the intended purpose
7050 * of CENTER_ALWAYS anyhow, I would think.)
7052 * So the way we implement this "constraint" is to say that when WE
7053 * cause a move or resize, i.e. we make a configure request changing
7054 * window size, we recompute the CENTER_ALWAYS position to reflect
7055 * the new window size, and include it in our request. Also, if we
7056 * just turned on CENTER_ALWAYS we snap to center with a new
7057 * request. Otherwise, if we are just NOTIFIED of a move or resize
7058 * done by someone else e.g. the window manager, we do NOT send a
7059 * new configure request.
7061 * For override redirect windows, this works fine; all window
7062 * sizes are from our configure requests. For managed windows,
7063 * it is at least semi-sane, though who knows what the
7064 * app author is thinking.
7067 /* This condition should be kept in sync with the condition later on
7068 * that determines whether we send a configure request. i.e. we
7069 * should do this position constraining anytime we were going to
7070 * send a configure request anyhow, plus when constraints have
7073 if (configure_request_pos_changed ||
7074 configure_request_size_changed ||
7076 info->position_constraints_changed)
7078 /* We request the constrained position if:
7079 * - we were changing position, and need to clamp
7080 * the change to the constraint
7081 * - we're changing the size anyway
7082 * - set_position() was called to toggle CENTER_ALWAYS on
7085 gtk_window_constrain_position (window,
7091 /* Update whether we need to request a move */
7092 if (info->last.configure_request.x != new_request.x ||
7093 info->last.configure_request.y != new_request.y)
7094 configure_request_pos_changed = TRUE;
7096 configure_request_pos_changed = FALSE;
7100 if (priv->type == GTK_WINDOW_TOPLEVEL)
7102 int notify_x, notify_y;
7104 /* this is the position from the last configure notify */
7105 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
7107 g_message ("--- %s ---\n"
7108 "last : %d,%d\t%d x %d\n"
7109 "this : %d,%d\t%d x %d\n"
7110 "alloc : %d,%d\t%d x %d\n"
7112 "resize: \t%d x %d\n"
7113 "size_changed: %d pos_changed: %d hints_changed: %d\n"
7114 "configure_notify_received: %d\n"
7115 "configure_request_count: %d\n"
7116 "position_constraints_changed: %d\n",
7117 priv->title ? priv->title : "(no title)",
7118 info->last.configure_request.x,
7119 info->last.configure_request.y,
7120 info->last.configure_request.width,
7121 info->last.configure_request.height,
7127 widget->allocation.width,
7128 widget->allocation.height,
7129 widget->requisition.width,
7130 widget->requisition.height,
7132 info->resize_height,
7133 configure_request_pos_changed,
7134 configure_request_size_changed,
7136 priv->configure_notify_received,
7137 priv->configure_request_count,
7138 info->position_constraints_changed);
7142 saved_last_info = info->last;
7143 info->last.geometry = new_geometry;
7144 info->last.flags = new_flags;
7145 info->last.configure_request = new_request;
7147 /* need to set PPosition so the WM will look at our position,
7148 * but we don't want to count PPosition coming and going as a hints
7149 * change for future iterations. So we saved info->last prior to
7153 /* Also, if the initial position was explicitly set, then we always
7154 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
7158 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
7159 * this is an initial map
7162 if ((configure_request_pos_changed ||
7163 info->initial_pos_set ||
7164 (priv->need_default_position &&
7165 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
7166 (new_flags & GDK_HINT_POS) == 0)
7168 new_flags |= GDK_HINT_POS;
7169 hints_changed = TRUE;
7172 /* Set hints if necessary
7175 gdk_window_set_geometry_hints (gdk_window,
7179 gtk_widget_get_allocation (widget, &allocation);
7181 /* handle resizing/moving and widget tree allocation
7183 if (priv->configure_notify_received)
7185 /* If we have received a configure event since
7186 * the last time in this function, we need to
7187 * accept our new size and size_allocate child widgets.
7188 * (see gtk_window_configure_event() for more details).
7190 * 1 or more configure notifies may have been received.
7191 * Also, configure_notify_received will only be TRUE
7192 * if all expected configure notifies have been received
7193 * (one per configure request), as an optimization.
7196 priv->configure_notify_received = FALSE;
7198 /* gtk_window_configure_event() filled in widget->allocation */
7199 gtk_widget_size_allocate (widget, &allocation);
7201 set_grip_position (window);
7202 update_grip_visibility (window);
7204 gdk_window_process_updates (gdk_window, TRUE);
7206 gdk_window_configure_finished (gdk_window);
7208 /* If the configure request changed, it means that
7210 * 1) coincidentally changed hints or widget properties
7211 * impacting the configure request before getting
7212 * a configure notify, or
7213 * 2) some broken widget is changing its size request
7214 * during size allocation, resulting in
7215 * a false appearance of changed configure request.
7217 * For 1), we could just go ahead and ask for the
7218 * new size right now, but doing that for 2)
7219 * might well be fighting the user (and can even
7220 * trigger a loop). Since we really don't want to
7221 * do that, we requeue a resize in hopes that
7222 * by the time it gets handled, the child has seen
7223 * the light and is willing to go along with the
7224 * new size. (this happens for the zvt widget, since
7225 * the size_allocate() above will have stored the
7226 * requisition corresponding to the new size in the
7229 * This doesn't buy us anything for 1), but it shouldn't
7230 * hurt us too badly, since it is what would have
7231 * happened if we had gotten the configure event before
7232 * the new size had been set.
7235 if (configure_request_size_changed ||
7236 configure_request_pos_changed)
7238 /* Don't change the recorded last info after all, because we
7239 * haven't actually updated to the new info yet - we decided
7240 * to postpone our configure request until later.
7242 info->last = saved_last_info;
7244 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7247 return; /* Bail out, we didn't really process the move/resize */
7249 else if ((configure_request_size_changed || hints_changed) &&
7250 (allocation.width != new_request.width || allocation.height != new_request.height))
7253 /* We are in one of the following situations:
7254 * A. configure_request_size_changed
7255 * our requisition has changed and we need a different window size,
7256 * so we request it from the window manager.
7257 * B. !configure_request_size_changed && hints_changed
7258 * the window manager rejects our size, but we have just changed the
7259 * window manager hints, so there's a chance our request will
7260 * be honoured this time, so we try again.
7262 * However, if the new requisition is the same as the current allocation,
7263 * we don't request it again, since we won't get a ConfigureNotify back from
7264 * the window manager unless it decides to change our requisition. If
7265 * we don't get the ConfigureNotify back, the resize queue will never be run.
7268 /* Now send the configure request */
7269 if (configure_request_pos_changed)
7271 gdk_window_move_resize (gdk_window,
7272 new_request.x, new_request.y,
7273 new_request.width, new_request.height);
7275 else /* only size changed */
7277 gdk_window_resize (gdk_window,
7278 new_request.width, new_request.height);
7281 if (priv->type == GTK_WINDOW_POPUP)
7283 GtkAllocation allocation;
7285 /* Directly size allocate for override redirect (popup) windows. */
7288 allocation.width = new_request.width;
7289 allocation.height = new_request.height;
7291 gtk_widget_size_allocate (widget, &allocation);
7293 gdk_window_process_updates (gdk_window, TRUE);
7295 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7296 gtk_widget_queue_draw (widget);
7300 /* Increment the number of have-not-yet-received-notify requests */
7301 priv->configure_request_count += 1;
7302 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7304 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7305 * configure event in response to our resizing request.
7306 * the configure event will cause a new resize with
7307 * ->configure_notify_received=TRUE.
7308 * until then, we want to
7309 * - discard expose events
7310 * - coalesce resizes for our children
7311 * - defer any window resizes until the configure event arrived
7312 * to achieve this, we queue a resize for the window, but remove its
7313 * resizing handler, so resizing will not be handled from the next
7314 * idle handler but when the configure event arrives.
7316 * FIXME: we should also dequeue the pending redraws here, since
7317 * we handle those ourselves upon ->configure_notify_received==TRUE.
7319 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7321 gtk_widget_queue_resize_no_redraw (widget);
7322 _gtk_container_dequeue_resize_handler (container);
7328 /* Handle any position changes.
7330 if (configure_request_pos_changed)
7332 gdk_window_move (gdk_window,
7333 new_request.x, new_request.y);
7336 /* And run the resize queue.
7338 gtk_container_resize_children (container);
7341 /* We have now processed a move/resize since the last position
7342 * constraint change, setting of the initial position, or resize.
7343 * (Not resetting these flags here can lead to infinite loops for
7344 * GTK_RESIZE_IMMEDIATE containers)
7346 info->position_constraints_changed = FALSE;
7347 info->initial_pos_set = FALSE;
7348 info->resize_width = -1;
7349 info->resize_height = -1;
7352 /* Compare two sets of Geometry hints for equality.
7355 gtk_window_compare_hints (GdkGeometry *geometry_a,
7357 GdkGeometry *geometry_b,
7360 if (flags_a != flags_b)
7363 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7364 (geometry_a->min_width != geometry_b->min_width ||
7365 geometry_a->min_height != geometry_b->min_height))
7368 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7369 (geometry_a->max_width != geometry_b->max_width ||
7370 geometry_a->max_height != geometry_b->max_height))
7373 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7374 (geometry_a->base_width != geometry_b->base_width ||
7375 geometry_a->base_height != geometry_b->base_height))
7378 if ((flags_a & GDK_HINT_ASPECT) &&
7379 (geometry_a->min_aspect != geometry_b->min_aspect ||
7380 geometry_a->max_aspect != geometry_b->max_aspect))
7383 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7384 (geometry_a->width_inc != geometry_b->width_inc ||
7385 geometry_a->height_inc != geometry_b->height_inc))
7388 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7389 geometry_a->win_gravity != geometry_b->win_gravity)
7396 _gtk_window_constrain_size (GtkWindow *window,
7402 GtkWindowPrivate *priv;
7403 GtkWindowGeometryInfo *info;
7405 g_return_if_fail (GTK_IS_WINDOW (window));
7407 priv = window->priv;
7409 info = priv->geometry_info;
7412 GdkWindowHints flags = info->last.flags;
7413 GdkGeometry *geometry = &info->last.geometry;
7415 gtk_window_constrain_size (window,
7426 gtk_window_constrain_size (GtkWindow *window,
7427 GdkGeometry *geometry,
7434 gdk_window_constrain_size (geometry, flags, width, height,
7435 new_width, new_height);
7438 /* Compute the set of geometry hints and flags for a window
7439 * based on the application set geometry, and requisition
7440 * of the window. gtk_widget_get_preferred_size() must have been
7444 gtk_window_compute_hints (GtkWindow *window,
7445 GdkGeometry *new_geometry,
7448 GtkWindowPrivate *priv = window->priv;
7450 gint extra_width = 0;
7451 gint extra_height = 0;
7452 GtkWindowGeometryInfo *geometry_info;
7453 GtkRequisition requisition;
7455 widget = GTK_WIDGET (window);
7457 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7458 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7462 *new_flags = geometry_info->mask;
7463 *new_geometry = geometry_info->geometry;
7470 if (geometry_info && geometry_info->widget)
7472 /* If the geometry widget is set, then the hints really apply to that
7473 * widget. This is pretty much meaningless unless the window layout
7474 * is such that the rest of the window adds fixed size borders to
7475 * the geometry widget. Our job is to figure the size of the borders;
7476 * We do that by asking how big the toplevel would be if the
7477 * geometry widget was *really big*.
7480 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7481 * |GGGGG B| in the border can confuse things
7487 * |AAAAAAAAA | When the geometry widget is large, things are
7488 * |GGGGGGGGGGB| clearer.
7493 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7494 GtkRequisition requisition;
7495 int current_width, current_height;
7497 _gtk_widget_override_size_request (geometry_info->widget,
7498 TEMPORARY_SIZE, TEMPORARY_SIZE,
7499 ¤t_width, ¤t_height);
7500 gtk_widget_get_preferred_size (widget,
7501 &requisition, NULL);
7502 _gtk_widget_restore_size_request (geometry_info->widget,
7503 current_width, current_height);
7505 extra_width = requisition.width - TEMPORARY_SIZE;
7506 extra_height = requisition.height - TEMPORARY_SIZE;
7508 if (extra_width < 0 || extra_height < 0)
7510 g_warning("Toplevel size doesn't seem to directly depend on the "
7511 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7512 "The geometry widget might not be in the window, or it might not "
7513 "be packed into the window appropriately");
7514 extra_width = MAX(extra_width, 0);
7515 extra_height = MAX(extra_height, 0);
7517 #undef TEMPORARY_SIZE
7520 /* We don't want to set GDK_HINT_POS in here, we just set it
7521 * in gtk_window_move_resize() when we want the position
7525 if (*new_flags & GDK_HINT_BASE_SIZE)
7527 new_geometry->base_width += extra_width;
7528 new_geometry->base_height += extra_height;
7532 /* For simplicity, we always set the base hint, even when we
7533 * don't expect it to have any visible effect.
7534 * (Note: geometry_size_to_pixels() depends on this.)
7536 *new_flags |= GDK_HINT_BASE_SIZE;
7538 new_geometry->base_width = extra_width;
7539 new_geometry->base_height = extra_height;
7541 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7542 * base size is the minimum size */
7543 if (*new_flags & GDK_HINT_MIN_SIZE)
7545 if (new_geometry->min_width > 0)
7546 new_geometry->base_width += new_geometry->min_width;
7547 if (new_geometry->min_height > 0)
7548 new_geometry->base_height += new_geometry->min_height;
7552 /* Please use a good size for unresizable widgets, not the minimum one. */
7553 if (!priv->resizable)
7554 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7556 if (*new_flags & GDK_HINT_MIN_SIZE)
7558 if (new_geometry->min_width < 0)
7559 new_geometry->min_width = requisition.width;
7561 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7563 if (new_geometry->min_height < 0)
7564 new_geometry->min_height = requisition.height;
7566 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7570 *new_flags |= GDK_HINT_MIN_SIZE;
7572 new_geometry->min_width = requisition.width;
7573 new_geometry->min_height = requisition.height;
7576 if (*new_flags & GDK_HINT_MAX_SIZE)
7578 if (new_geometry->max_width < 0)
7579 new_geometry->max_width = requisition.width;
7581 new_geometry->max_width += extra_width;
7583 if (new_geometry->max_height < 0)
7584 new_geometry->max_height = requisition.height;
7586 new_geometry->max_height += extra_height;
7588 else if (!priv->resizable)
7590 *new_flags |= GDK_HINT_MAX_SIZE;
7592 new_geometry->max_width = requisition.width;
7593 new_geometry->max_height = requisition.height;
7596 *new_flags |= GDK_HINT_WIN_GRAVITY;
7597 new_geometry->win_gravity = priv->gravity;
7600 /***********************
7601 * Redrawing functions *
7602 ***********************/
7605 gtk_window_draw (GtkWidget *widget,
7608 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7609 GtkStyleContext *context;
7610 gboolean ret = FALSE;
7612 context = gtk_widget_get_style_context (widget);
7614 if (!gtk_widget_get_app_paintable (widget) &&
7615 gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
7617 gtk_render_background (context, cr, 0, 0,
7618 gtk_widget_get_allocated_width (widget),
7619 gtk_widget_get_allocated_height (widget));
7622 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7623 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7625 if (priv->grip_window &&
7626 gtk_cairo_should_draw_window (cr, priv->grip_window))
7630 gtk_style_context_save (context);
7633 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7634 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7636 gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND);
7637 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7638 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7639 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7642 gtk_style_context_restore (context);
7649 * gtk_window_present:
7650 * @window: a #GtkWindow
7652 * Presents a window to the user. This may mean raising the window
7653 * in the stacking order, deiconifying it, moving it to the current
7654 * desktop, and/or giving it the keyboard focus, possibly dependent
7655 * on the user's platform, window manager, and preferences.
7657 * If @window is hidden, this function calls gtk_widget_show()
7660 * This function should be used when the user tries to open a window
7661 * that's already open. Say for example the preferences dialog is
7662 * currently open, and the user chooses Preferences from the menu
7663 * a second time; use gtk_window_present() to move the already-open dialog
7664 * where the user can see it.
7666 * If you are calling this function in response to a user interaction,
7667 * it is preferable to use gtk_window_present_with_time().
7671 gtk_window_present (GtkWindow *window)
7673 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7677 * gtk_window_present_with_time:
7678 * @window: a #GtkWindow
7679 * @timestamp: the timestamp of the user interaction (typically a
7680 * button or key press event) which triggered this call
7682 * Presents a window to the user in response to a user interaction.
7683 * If you need to present a window without a timestamp, use
7684 * gtk_window_present(). See gtk_window_present() for details.
7689 gtk_window_present_with_time (GtkWindow *window,
7692 GtkWindowPrivate *priv;
7694 GdkWindow *gdk_window;
7696 g_return_if_fail (GTK_IS_WINDOW (window));
7698 priv = window->priv;
7699 widget = GTK_WIDGET (window);
7701 if (gtk_widget_get_visible (widget))
7703 gdk_window = gtk_widget_get_window (widget);
7705 g_assert (gdk_window != NULL);
7707 gdk_window_show (gdk_window);
7709 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7710 if (timestamp == GDK_CURRENT_TIME)
7712 #ifdef GDK_WINDOWING_X11
7713 if (GDK_IS_X11_WINDOW(gdk_window))
7715 GdkDisplay *display;
7717 display = gtk_widget_get_display (GTK_WIDGET (window));
7718 timestamp = gdk_x11_display_get_user_time (display);
7722 timestamp = gtk_get_current_event_time ();
7725 gdk_window_focus (gdk_window, timestamp);
7729 priv->initial_timestamp = timestamp;
7730 gtk_widget_show (widget);
7735 * gtk_window_iconify:
7736 * @window: a #GtkWindow
7738 * Asks to iconify (i.e. minimize) the specified @window. Note that
7739 * you shouldn't assume the window is definitely iconified afterward,
7740 * because other entities (e.g. the user or <link
7741 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7742 * again, or there may not be a window manager in which case
7743 * iconification isn't possible, etc. But normally the window will end
7744 * up iconified. Just don't write code that crashes if not.
7746 * It's permitted to call this function before showing a window,
7747 * in which case the window will be iconified before it ever appears
7750 * You can track iconification via the "window-state-event" signal
7755 gtk_window_iconify (GtkWindow *window)
7757 GtkWindowPrivate *priv;
7759 GdkWindow *toplevel;
7761 g_return_if_fail (GTK_IS_WINDOW (window));
7763 priv = window->priv;
7764 widget = GTK_WIDGET (window);
7766 priv->iconify_initially = TRUE;
7768 toplevel = gtk_widget_get_window (widget);
7770 if (toplevel != NULL)
7771 gdk_window_iconify (toplevel);
7775 * gtk_window_deiconify:
7776 * @window: a #GtkWindow
7778 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7779 * that you shouldn't assume the window is definitely deiconified
7780 * afterward, because other entities (e.g. the user or <link
7781 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7782 * again before your code which assumes deiconification gets to run.
7784 * You can track iconification via the "window-state-event" signal
7788 gtk_window_deiconify (GtkWindow *window)
7790 GtkWindowPrivate *priv;
7792 GdkWindow *toplevel;
7794 g_return_if_fail (GTK_IS_WINDOW (window));
7796 priv = window->priv;
7797 widget = GTK_WIDGET (window);
7799 priv->iconify_initially = FALSE;
7801 toplevel = gtk_widget_get_window (widget);
7803 if (toplevel != NULL)
7804 gdk_window_deiconify (toplevel);
7809 * @window: a #GtkWindow
7811 * Asks to stick @window, which means that it will appear on all user
7812 * desktops. Note that you shouldn't assume the window is definitely
7813 * stuck afterward, because other entities (e.g. the user or <link
7814 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7815 * again, and some window managers do not support sticking
7816 * windows. But normally the window will end up stuck. Just don't
7817 * write code that crashes if not.
7819 * It's permitted to call this function before showing a window.
7821 * You can track stickiness via the "window-state-event" signal
7826 gtk_window_stick (GtkWindow *window)
7828 GtkWindowPrivate *priv;
7830 GdkWindow *toplevel;
7832 g_return_if_fail (GTK_IS_WINDOW (window));
7834 priv = window->priv;
7835 widget = GTK_WIDGET (window);
7837 priv->stick_initially = TRUE;
7839 toplevel = gtk_widget_get_window (widget);
7841 if (toplevel != NULL)
7842 gdk_window_stick (toplevel);
7846 * gtk_window_unstick:
7847 * @window: a #GtkWindow
7849 * Asks to unstick @window, which means that it will appear on only
7850 * one of the user's desktops. Note that you shouldn't assume the
7851 * window is definitely unstuck afterward, because other entities
7852 * (e.g. the user or <link linkend="gtk-X11-arch">window
7853 * manager</link>) could stick it again. But normally the window will
7854 * end up stuck. Just don't write code that crashes if not.
7856 * You can track stickiness via the "window-state-event" signal
7861 gtk_window_unstick (GtkWindow *window)
7863 GtkWindowPrivate *priv;
7865 GdkWindow *toplevel;
7867 g_return_if_fail (GTK_IS_WINDOW (window));
7869 priv = window->priv;
7870 widget = GTK_WIDGET (window);
7872 priv->stick_initially = FALSE;
7874 toplevel = gtk_widget_get_window (widget);
7876 if (toplevel != NULL)
7877 gdk_window_unstick (toplevel);
7881 * gtk_window_maximize:
7882 * @window: a #GtkWindow
7884 * Asks to maximize @window, so that it becomes full-screen. Note that
7885 * you shouldn't assume the window is definitely maximized afterward,
7886 * because other entities (e.g. the user or <link
7887 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7888 * again, and not all window managers support maximization. But
7889 * normally the window will end up maximized. Just don't write code
7890 * that crashes if not.
7892 * It's permitted to call this function before showing a window,
7893 * in which case the window will be maximized when it appears onscreen
7896 * You can track maximization via the "window-state-event" signal
7901 gtk_window_maximize (GtkWindow *window)
7903 GtkWindowPrivate *priv;
7905 GdkWindow *toplevel;
7907 g_return_if_fail (GTK_IS_WINDOW (window));
7909 priv = window->priv;
7910 widget = GTK_WIDGET (window);
7912 priv->maximize_initially = TRUE;
7914 toplevel = gtk_widget_get_window (widget);
7916 if (toplevel != NULL)
7917 gdk_window_maximize (toplevel);
7921 * gtk_window_unmaximize:
7922 * @window: a #GtkWindow
7924 * Asks to unmaximize @window. Note that you shouldn't assume the
7925 * window is definitely unmaximized afterward, because other entities
7926 * (e.g. the user or <link linkend="gtk-X11-arch">window
7927 * manager</link>) could maximize it again, and not all window
7928 * managers honor requests to unmaximize. But normally the window will
7929 * end up unmaximized. Just don't write code that crashes if not.
7931 * You can track maximization via the "window-state-event" signal
7936 gtk_window_unmaximize (GtkWindow *window)
7938 GtkWindowPrivate *priv;
7940 GdkWindow *toplevel;
7942 g_return_if_fail (GTK_IS_WINDOW (window));
7944 priv = window->priv;
7945 widget = GTK_WIDGET (window);
7947 priv->maximize_initially = FALSE;
7949 toplevel = gtk_widget_get_window (widget);
7951 if (toplevel != NULL)
7952 gdk_window_unmaximize (toplevel);
7956 * gtk_window_fullscreen:
7957 * @window: a #GtkWindow
7959 * Asks to place @window in the fullscreen state. Note that you
7960 * shouldn't assume the window is definitely full screen afterward,
7961 * because other entities (e.g. the user or <link
7962 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7963 * again, and not all window managers honor requests to fullscreen
7964 * windows. But normally the window will end up fullscreen. Just
7965 * don't write code that crashes if not.
7967 * You can track the fullscreen state via the "window-state-event" signal
7973 gtk_window_fullscreen (GtkWindow *window)
7975 GtkWindowPrivate *priv;
7977 GdkWindow *toplevel;
7979 g_return_if_fail (GTK_IS_WINDOW (window));
7981 priv = window->priv;
7982 widget = GTK_WIDGET (window);
7984 priv->fullscreen_initially = TRUE;
7986 toplevel = gtk_widget_get_window (widget);
7988 if (toplevel != NULL)
7989 gdk_window_fullscreen (toplevel);
7993 * gtk_window_unfullscreen:
7994 * @window: a #GtkWindow
7996 * Asks to toggle off the fullscreen state for @window. Note that you
7997 * shouldn't assume the window is definitely not full screen
7998 * afterward, because other entities (e.g. the user or <link
7999 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
8000 * again, and not all window managers honor requests to unfullscreen
8001 * windows. But normally the window will end up restored to its normal
8002 * state. Just don't write code that crashes if not.
8004 * You can track the fullscreen state via the "window-state-event" signal
8010 gtk_window_unfullscreen (GtkWindow *window)
8013 GdkWindow *toplevel;
8014 GtkWindowPrivate *priv;
8016 g_return_if_fail (GTK_IS_WINDOW (window));
8018 priv = window->priv;
8019 widget = GTK_WIDGET (window);
8021 priv->fullscreen_initially = FALSE;
8023 toplevel = gtk_widget_get_window (widget);
8025 if (toplevel != NULL)
8026 gdk_window_unfullscreen (toplevel);
8030 * gtk_window_set_keep_above:
8031 * @window: a #GtkWindow
8032 * @setting: whether to keep @window above other windows
8034 * Asks to keep @window above, so that it stays on top. Note that
8035 * you shouldn't assume the window is definitely above afterward,
8036 * because other entities (e.g. the user or <link
8037 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
8038 * and not all window managers support keeping windows above. But
8039 * normally the window will end kept above. Just don't write code
8040 * that crashes if not.
8042 * It's permitted to call this function before showing a window,
8043 * in which case the window will be kept above when it appears onscreen
8046 * You can track the above state via the "window-state-event" signal
8049 * Note that, according to the <ulink
8050 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8051 * Manager Hints</ulink> specification, the above state is mainly meant
8052 * for user preferences and should not be used by applications e.g. for
8053 * drawing attention to their dialogs.
8058 gtk_window_set_keep_above (GtkWindow *window,
8062 GtkWindowPrivate *priv;
8063 GdkWindow *toplevel;
8065 g_return_if_fail (GTK_IS_WINDOW (window));
8067 priv = window->priv;
8068 widget = GTK_WIDGET (window);
8070 priv->above_initially = setting != FALSE;
8072 priv->below_initially = FALSE;
8074 toplevel = gtk_widget_get_window (widget);
8076 if (toplevel != NULL)
8077 gdk_window_set_keep_above (toplevel, setting);
8081 * gtk_window_set_keep_below:
8082 * @window: a #GtkWindow
8083 * @setting: whether to keep @window below other windows
8085 * Asks to keep @window below, so that it stays in bottom. Note that
8086 * you shouldn't assume the window is definitely below afterward,
8087 * because other entities (e.g. the user or <link
8088 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8089 * and not all window managers support putting windows below. But
8090 * normally the window will be kept below. Just don't write code
8091 * that crashes if not.
8093 * It's permitted to call this function before showing a window,
8094 * in which case the window will be kept below when it appears onscreen
8097 * You can track the below state via the "window-state-event" signal
8100 * Note that, according to the <ulink
8101 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8102 * Manager Hints</ulink> specification, the above state is mainly meant
8103 * for user preferences and should not be used by applications e.g. for
8104 * drawing attention to their dialogs.
8109 gtk_window_set_keep_below (GtkWindow *window,
8113 GtkWindowPrivate *priv;
8114 GdkWindow *toplevel;
8116 g_return_if_fail (GTK_IS_WINDOW (window));
8118 priv = window->priv;
8119 widget = GTK_WIDGET (window);
8121 priv->below_initially = setting != FALSE;
8123 priv->above_initially = FALSE;
8125 toplevel = gtk_widget_get_window (widget);
8127 if (toplevel != NULL)
8128 gdk_window_set_keep_below (toplevel, setting);
8132 * gtk_window_set_resizable:
8133 * @window: a #GtkWindow
8134 * @resizable: %TRUE if the user can resize this window
8136 * Sets whether the user can resize a window. Windows are user resizable
8140 gtk_window_set_resizable (GtkWindow *window,
8143 GtkWindowPrivate *priv;
8145 g_return_if_fail (GTK_IS_WINDOW (window));
8147 priv = window->priv;
8149 resizable = (resizable != FALSE);
8151 if (priv->resizable != resizable)
8153 priv->resizable = resizable;
8155 update_grip_visibility (window);
8157 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8159 g_object_notify (G_OBJECT (window), "resizable");
8164 * gtk_window_get_resizable:
8165 * @window: a #GtkWindow
8167 * Gets the value set by gtk_window_set_resizable().
8169 * Return value: %TRUE if the user can resize the window
8172 gtk_window_get_resizable (GtkWindow *window)
8174 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8176 return window->priv->resizable;
8180 * gtk_window_set_gravity:
8181 * @window: a #GtkWindow
8182 * @gravity: window gravity
8184 * Window gravity defines the meaning of coordinates passed to
8185 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8188 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8189 * typically "do what you mean."
8193 gtk_window_set_gravity (GtkWindow *window,
8196 GtkWindowPrivate *priv;
8198 g_return_if_fail (GTK_IS_WINDOW (window));
8200 priv = window->priv;
8202 if (gravity != priv->gravity)
8204 priv->gravity = gravity;
8206 /* gtk_window_move_resize() will adapt gravity
8208 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8210 g_object_notify (G_OBJECT (window), "gravity");
8215 * gtk_window_get_gravity:
8216 * @window: a #GtkWindow
8218 * Gets the value set by gtk_window_set_gravity().
8220 * Return value: (transfer none): window gravity
8223 gtk_window_get_gravity (GtkWindow *window)
8225 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8227 return window->priv->gravity;
8231 * gtk_window_begin_resize_drag:
8232 * @window: a #GtkWindow
8233 * @button: mouse button that initiated the drag
8234 * @edge: position of the resize control
8235 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8236 * @root_y: Y position where the user clicked to initiate the drag
8237 * @timestamp: timestamp from the click event that initiated the drag
8239 * Starts resizing a window. This function is used if an application
8240 * has window resizing controls. When GDK can support it, the resize
8241 * will be done using the standard mechanism for the <link
8242 * linkend="gtk-X11-arch">window manager</link> or windowing
8243 * system. Otherwise, GDK will try to emulate window resizing,
8244 * potentially not all that well, depending on the windowing system.
8248 gtk_window_begin_resize_drag (GtkWindow *window,
8256 GdkWindow *toplevel;
8258 g_return_if_fail (GTK_IS_WINDOW (window));
8259 widget = GTK_WIDGET (window);
8260 g_return_if_fail (gtk_widget_get_visible (widget));
8262 toplevel = gtk_widget_get_window (widget);
8264 gdk_window_begin_resize_drag (toplevel,
8271 * gtk_window_begin_move_drag:
8272 * @window: a #GtkWindow
8273 * @button: mouse button that initiated the drag
8274 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8275 * @root_y: Y position where the user clicked to initiate the drag
8276 * @timestamp: timestamp from the click event that initiated the drag
8278 * Starts moving a window. This function is used if an application has
8279 * window movement grips. When GDK can support it, the window movement
8280 * will be done using the standard mechanism for the <link
8281 * linkend="gtk-X11-arch">window manager</link> or windowing
8282 * system. Otherwise, GDK will try to emulate window movement,
8283 * potentially not all that well, depending on the windowing system.
8287 gtk_window_begin_move_drag (GtkWindow *window,
8294 GdkWindow *toplevel;
8296 g_return_if_fail (GTK_IS_WINDOW (window));
8297 widget = GTK_WIDGET (window);
8298 g_return_if_fail (gtk_widget_get_visible (widget));
8300 toplevel = gtk_widget_get_window (widget);
8302 gdk_window_begin_move_drag (toplevel,
8309 * gtk_window_set_screen:
8310 * @window: a #GtkWindow.
8311 * @screen: a #GdkScreen.
8313 * Sets the #GdkScreen where the @window is displayed; if
8314 * the window is already mapped, it will be unmapped, and
8315 * then remapped on the new screen.
8320 gtk_window_set_screen (GtkWindow *window,
8323 GtkWindowPrivate *priv;
8325 GdkScreen *previous_screen;
8326 gboolean was_mapped;
8328 g_return_if_fail (GTK_IS_WINDOW (window));
8329 g_return_if_fail (GDK_IS_SCREEN (screen));
8331 priv = window->priv;
8333 if (screen == priv->screen)
8336 widget = GTK_WIDGET (window);
8338 previous_screen = priv->screen;
8339 was_mapped = gtk_widget_get_mapped (widget);
8342 gtk_widget_unmap (widget);
8343 if (gtk_widget_get_realized (widget))
8344 gtk_widget_unrealize (widget);
8346 gtk_window_free_key_hash (window);
8347 priv->screen = screen;
8348 gtk_widget_reset_rc_styles (widget);
8349 if (screen != previous_screen)
8351 if (previous_screen)
8353 g_signal_handlers_disconnect_by_func (previous_screen,
8354 gtk_window_on_composited_changed, window);
8355 #ifdef GDK_WINDOWING_X11
8356 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8357 gtk_window_on_theme_variant_changed, window);
8360 g_signal_connect (screen, "composited-changed",
8361 G_CALLBACK (gtk_window_on_composited_changed), window);
8362 #ifdef GDK_WINDOWING_X11
8363 g_signal_connect (gtk_settings_get_for_screen (screen),
8364 "notify::gtk-application-prefer-dark-theme",
8365 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8368 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8369 _gtk_widget_propagate_composited_changed (widget);
8371 g_object_notify (G_OBJECT (window), "screen");
8374 gtk_widget_map (widget);
8378 gtk_window_set_theme_variant (GtkWindow *window)
8380 #ifdef GDK_WINDOWING_X11
8381 GdkWindow *gdk_window;
8382 gboolean dark_theme_requested;
8384 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8385 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8388 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8390 if (GDK_IS_X11_WINDOW (gdk_window))
8391 gdk_x11_window_set_theme_variant (gdk_window,
8392 dark_theme_requested ? "dark" : NULL);
8397 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8401 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8402 gtk_window_set_theme_variant (window);
8406 gtk_window_on_composited_changed (GdkScreen *screen,
8409 gtk_widget_queue_draw (GTK_WIDGET (window));
8411 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8415 gtk_window_check_screen (GtkWindow *window)
8417 GtkWindowPrivate *priv = window->priv;
8420 return priv->screen;
8423 g_warning ("Screen for GtkWindow not set; you must always set\n"
8424 "a screen for a GtkWindow before using the window");
8430 * gtk_window_get_screen:
8431 * @window: a #GtkWindow.
8433 * Returns the #GdkScreen associated with @window.
8435 * Return value: (transfer none): a #GdkScreen.
8440 gtk_window_get_screen (GtkWindow *window)
8442 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8444 return window->priv->screen;
8448 * gtk_window_is_active:
8449 * @window: a #GtkWindow
8451 * Returns whether the window is part of the current active toplevel.
8452 * (That is, the toplevel window receiving keystrokes.)
8453 * The return value is %TRUE if the window is active toplevel
8454 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8455 * You might use this function if you wanted to draw a widget
8456 * differently in an active window from a widget in an inactive window.
8457 * See gtk_window_has_toplevel_focus()
8459 * Return value: %TRUE if the window part of the current active window.
8464 gtk_window_is_active (GtkWindow *window)
8466 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8468 return window->priv->is_active;
8472 * gtk_window_has_toplevel_focus:
8473 * @window: a #GtkWindow
8475 * Returns whether the input focus is within this GtkWindow.
8476 * For real toplevel windows, this is identical to gtk_window_is_active(),
8477 * but for embedded windows, like #GtkPlug, the results will differ.
8479 * Return value: %TRUE if the input focus is within this GtkWindow
8484 gtk_window_has_toplevel_focus (GtkWindow *window)
8486 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8488 return window->priv->has_toplevel_focus;
8493 * SECTION:gtkwindowgroup
8494 * @Short_description: Limit the effect of grabs
8495 * @Title: GtkWindowGroup
8497 * #GtkWindowGroup objects are referenced by each window in the group,
8498 * so once you have added all windows to a #GtkWindowGroup, you can drop
8499 * the initial reference to the window group with g_object_unref(). If the
8500 * windows in the window group are subsequently destroyed, then they will
8501 * be removed from the window group and drop their references on the window
8502 * group; when all window have been removed, the window group will be
8506 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8509 gtk_window_group_init (GtkWindowGroup *group)
8511 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8512 GTK_TYPE_WINDOW_GROUP,
8513 GtkWindowGroupPrivate);
8517 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8519 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8523 * gtk_window_group_new:
8525 * Creates a new #GtkWindowGroup object. Grabs added with
8526 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8528 * Return value: a new #GtkWindowGroup.
8531 gtk_window_group_new (void)
8533 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8537 window_group_cleanup_grabs (GtkWindowGroup *group,
8540 GtkWindowGroupPrivate *priv;
8541 GtkDeviceGrabInfo *info;
8543 GSList *to_remove = NULL;
8547 tmp_list = priv->grabs;
8550 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8551 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8552 tmp_list = tmp_list->next;
8557 gtk_grab_remove (to_remove->data);
8558 g_object_unref (to_remove->data);
8559 to_remove = g_slist_delete_link (to_remove, to_remove);
8562 tmp_list = priv->device_grabs;
8566 info = tmp_list->data;
8568 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8569 to_remove = g_slist_prepend (to_remove, info);
8571 tmp_list = tmp_list->next;
8576 info = to_remove->data;
8578 gtk_device_grab_remove (info->widget, info->device);
8579 to_remove = g_slist_delete_link (to_remove, to_remove);
8584 * gtk_window_group_add_window:
8585 * @window_group: a #GtkWindowGroup
8586 * @window: the #GtkWindow to add
8588 * Adds a window to a #GtkWindowGroup.
8591 gtk_window_group_add_window (GtkWindowGroup *window_group,
8594 GtkWindowPrivate *priv;
8596 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8597 g_return_if_fail (GTK_IS_WINDOW (window));
8599 priv = window->priv;
8601 if (priv->group != window_group)
8603 g_object_ref (window);
8604 g_object_ref (window_group);
8607 gtk_window_group_remove_window (priv->group, window);
8609 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8611 priv->group = window_group;
8613 g_object_unref (window);
8618 * gtk_window_group_remove_window:
8619 * @window_group: a #GtkWindowGroup
8620 * @window: the #GtkWindow to remove
8622 * Removes a window from a #GtkWindowGroup.
8625 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8628 GtkWindowPrivate *priv;
8630 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8631 g_return_if_fail (GTK_IS_WINDOW (window));
8632 priv = window->priv;
8633 g_return_if_fail (priv->group == window_group);
8635 g_object_ref (window);
8637 window_group_cleanup_grabs (window_group, window);
8640 g_object_unref (window_group);
8641 g_object_unref (window);
8645 * gtk_window_group_list_windows:
8646 * @window_group: a #GtkWindowGroup
8648 * Returns a list of the #GtkWindows that belong to @window_group.
8650 * Returns: (element-type GtkWindow) (transfer container): A
8651 * newly-allocated list of windows inside the group.
8656 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8658 GList *toplevels, *toplevel, *group_windows;
8660 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8662 group_windows = NULL;
8663 toplevels = gtk_window_list_toplevels ();
8665 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8667 GtkWindow *window = toplevel->data;
8669 if (window_group == window->priv->group)
8670 group_windows = g_list_prepend (group_windows, window);
8673 g_list_free (toplevels);
8675 return g_list_reverse (group_windows);
8679 * gtk_window_get_group:
8680 * @window: (allow-none): a #GtkWindow, or %NULL
8682 * Returns the group for @window or the default group, if
8683 * @window is %NULL or if @window does not have an explicit
8686 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8691 gtk_window_get_group (GtkWindow *window)
8693 if (window && window->priv->group)
8694 return window->priv->group;
8697 static GtkWindowGroup *default_group = NULL;
8700 default_group = gtk_window_group_new ();
8702 return default_group;
8707 * gtk_window_has_group:
8708 * @window: a #GtkWindow
8710 * Returns whether @window has an explicit window group.
8712 * Return value: %TRUE if @window has an explicit window group.
8717 gtk_window_has_group (GtkWindow *window)
8719 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8721 return window->priv->group != NULL;
8725 * gtk_window_group_get_current_grab:
8726 * @window_group: a #GtkWindowGroup
8728 * Gets the current grab widget of the given group,
8729 * see gtk_grab_add().
8731 * Returns: (transfer none): the current grab widget of the group
8736 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8738 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8740 if (window_group->priv->grabs)
8741 return GTK_WIDGET (window_group->priv->grabs->data);
8746 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8749 GtkWindowGroupPrivate *priv;
8751 priv = window_group->priv;
8752 priv->grabs = g_slist_prepend (priv->grabs, widget);
8756 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8759 GtkWindowGroupPrivate *priv;
8761 priv = window_group->priv;
8762 priv->grabs = g_slist_remove (priv->grabs, widget);
8767 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8770 gboolean block_others)
8772 GtkWindowGroupPrivate *priv;
8773 GtkDeviceGrabInfo *info;
8775 priv = window_group->priv;
8777 info = g_slice_new0 (GtkDeviceGrabInfo);
8778 info->widget = widget;
8779 info->device = device;
8780 info->block_others = block_others;
8782 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8786 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8790 GtkWindowGroupPrivate *priv;
8791 GtkDeviceGrabInfo *info;
8792 GSList *list, *node = NULL;
8793 GdkDevice *other_device;
8795 priv = window_group->priv;
8796 other_device = gdk_device_get_associated_device (device);
8797 list = priv->device_grabs;
8803 if (info->widget == widget &&
8804 (info->device == device ||
8805 info->device == other_device))
8818 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8819 g_slice_free (GtkDeviceGrabInfo, info);
8824 * gtk_window_group_get_current_device_grab:
8825 * @window_group: a #GtkWindowGroup
8826 * @device: a #GdkDevice
8828 * Returns the current grab widget for @device, or %NULL if none.
8830 * Returns: (transfer none): The grab widget, or %NULL
8835 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8838 GtkWindowGroupPrivate *priv;
8839 GtkDeviceGrabInfo *info;
8840 GdkDevice *other_device;
8843 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8844 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8846 priv = window_group->priv;
8847 list = priv->device_grabs;
8848 other_device = gdk_device_get_associated_device (device);
8855 if (info->device == device ||
8856 info->device == other_device)
8857 return info->widget;
8864 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8868 GtkWindowGroupPrivate *priv;
8869 GtkDeviceGrabInfo *info;
8870 GdkDevice *other_device;
8873 priv = window_group->priv;
8874 other_device = gdk_device_get_associated_device (device);
8875 list = priv->device_grabs;
8882 /* Look for blocking grabs on other device pairs
8883 * that have the passed widget within the GTK+ grab.
8885 if (info->block_others &&
8886 info->device != device &&
8887 info->device != other_device &&
8888 (info->widget == widget ||
8889 gtk_widget_is_ancestor (widget, info->widget)))
8897 Derived from XParseGeometry() in XFree86
8899 Copyright 1985, 1986, 1987,1998 The Open Group
8901 All Rights Reserved.
8903 The above copyright notice and this permission notice shall be included
8904 in all copies or substantial portions of the Software.
8906 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8907 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8908 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8909 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8910 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8911 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8912 OTHER DEALINGS IN THE SOFTWARE.
8914 Except as contained in this notice, the name of The Open Group shall
8915 not be used in advertising or otherwise to promote the sale, use or
8916 other dealings in this Software without prior written authorization
8917 from The Open Group.
8922 * XParseGeometry parses strings of the form
8923 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8924 * width, height, xoffset, and yoffset are unsigned integers.
8925 * Example: "=80x24+300-49"
8926 * The equal sign is optional.
8927 * It returns a bitmask that indicates which of the four values
8928 * were actually found in the string. For each value found,
8929 * the corresponding argument is updated; for each value
8930 * not found, the corresponding argument is left unchanged.
8933 /* The following code is from Xlib, and is minimally modified, so we
8934 * can track any upstream changes if required. Don't change this
8935 * code. Or if you do, put in a huge comment marking which thing
8940 read_int (gchar *string,
8948 else if (*string == '-')
8954 for (; (*string >= '0') && (*string <= '9'); string++)
8956 result = (result * 10) + (*string - '0');
8968 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8969 * value (x, y, width, height) was found in the parsed string.
8971 #define NoValue 0x0000
8972 #define XValue 0x0001
8973 #define YValue 0x0002
8974 #define WidthValue 0x0004
8975 #define HeightValue 0x0008
8976 #define AllValues 0x000F
8977 #define XNegative 0x0010
8978 #define YNegative 0x0020
8980 /* Try not to reformat/modify, so we can compare/sync with X sources */
8982 gtk_XParseGeometry (const char *string,
8985 unsigned int *width,
8986 unsigned int *height)
8990 unsigned int tempWidth, tempHeight;
8992 char *nextCharacter;
8994 /* These initializations are just to silence gcc */
9000 if ( (string == NULL) || (*string == '\0')) return(mask);
9002 string++; /* ignore possible '=' at beg of geometry spec */
9004 strind = (char *)string;
9005 if (*strind != '+' && *strind != '-' && *strind != 'x') {
9006 tempWidth = read_int(strind, &nextCharacter);
9007 if (strind == nextCharacter)
9009 strind = nextCharacter;
9013 if (*strind == 'x' || *strind == 'X') {
9015 tempHeight = read_int(strind, &nextCharacter);
9016 if (strind == nextCharacter)
9018 strind = nextCharacter;
9019 mask |= HeightValue;
9022 if ((*strind == '+') || (*strind == '-')) {
9023 if (*strind == '-') {
9025 tempX = -read_int(strind, &nextCharacter);
9026 if (strind == nextCharacter)
9028 strind = nextCharacter;
9034 tempX = read_int(strind, &nextCharacter);
9035 if (strind == nextCharacter)
9037 strind = nextCharacter;
9040 if ((*strind == '+') || (*strind == '-')) {
9041 if (*strind == '-') {
9043 tempY = -read_int(strind, &nextCharacter);
9044 if (strind == nextCharacter)
9046 strind = nextCharacter;
9053 tempY = read_int(strind, &nextCharacter);
9054 if (strind == nextCharacter)
9056 strind = nextCharacter;
9062 /* If strind isn't at the end of the string the it's an invalid
9063 geometry specification. */
9065 if (*strind != '\0') return (0);
9071 if (mask & WidthValue)
9073 if (mask & HeightValue)
9074 *height = tempHeight;
9079 * gtk_window_parse_geometry:
9080 * @window: a #GtkWindow
9081 * @geometry: geometry string
9083 * Parses a standard X Window System geometry string - see the
9084 * manual page for X (type 'man X') for details on this.
9085 * gtk_window_parse_geometry() does work on all GTK+ ports
9086 * including Win32 but is primarily intended for an X environment.
9088 * If either a size or a position can be extracted from the
9089 * geometry string, gtk_window_parse_geometry() returns %TRUE
9090 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9091 * to resize/move the window.
9093 * If gtk_window_parse_geometry() returns %TRUE, it will also
9094 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9095 * indicating to the window manager that the size/position of
9096 * the window was user-specified. This causes most window
9097 * managers to honor the geometry.
9099 * Note that for gtk_window_parse_geometry() to work as expected, it has
9100 * to be called when the window has its "final" size, i.e. after calling
9101 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9104 * #include <gtk/gtk.h>
9107 * fill_with_content (GtkWidget *vbox)
9109 * /* fill with content... */
9113 * main (int argc, char *argv[])
9115 * GtkWidget *window, *vbox;
9116 * GdkGeometry size_hints = {
9117 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9120 * gtk_init (&argc, &argv);
9122 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9123 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9125 * gtk_container_add (GTK_CONTAINER (window), vbox);
9126 * fill_with_content (vbox);
9127 * gtk_widget_show_all (vbox);
9129 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9132 * GDK_HINT_MIN_SIZE |
9133 * GDK_HINT_BASE_SIZE |
9134 * GDK_HINT_RESIZE_INC);
9138 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9139 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9142 * gtk_widget_show_all (window);
9149 * Return value: %TRUE if string was parsed successfully
9152 gtk_window_parse_geometry (GtkWindow *window,
9153 const gchar *geometry)
9155 gint result, x = 0, y = 0;
9159 gboolean size_set, pos_set;
9162 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9163 g_return_val_if_fail (geometry != NULL, FALSE);
9165 child = gtk_bin_get_child (GTK_BIN (window));
9166 if (!child || !gtk_widget_get_visible (child))
9167 g_warning ("gtk_window_parse_geometry() called on a window with no "
9168 "visible children; the window should be set up before "
9169 "gtk_window_parse_geometry() is called.");
9171 screen = gtk_window_check_screen (window);
9173 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9176 if ((result & WidthValue) || (result & HeightValue))
9178 gtk_window_set_default_size_internal (window,
9179 TRUE, result & WidthValue ? w : -1,
9180 TRUE, result & HeightValue ? h : -1,
9185 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9187 grav = GDK_GRAVITY_NORTH_WEST;
9189 if ((result & XNegative) && (result & YNegative))
9190 grav = GDK_GRAVITY_SOUTH_EAST;
9191 else if (result & XNegative)
9192 grav = GDK_GRAVITY_NORTH_EAST;
9193 else if (result & YNegative)
9194 grav = GDK_GRAVITY_SOUTH_WEST;
9196 if ((result & XValue) == 0)
9199 if ((result & YValue) == 0)
9202 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9203 grav == GDK_GRAVITY_SOUTH_EAST)
9204 y = gdk_screen_get_height (screen) - h + y;
9206 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9207 grav == GDK_GRAVITY_NORTH_EAST)
9208 x = gdk_screen_get_width (screen) - w + x;
9210 /* we don't let you put a window offscreen; maybe some people would
9211 * prefer to be able to, but it's kind of a bogus thing to do.
9220 if ((result & XValue) || (result & YValue))
9222 gtk_window_set_gravity (window, grav);
9223 gtk_window_move (window, x, y);
9227 if (size_set || pos_set)
9229 /* Set USSize, USPosition hints */
9230 GtkWindowGeometryInfo *info;
9232 info = gtk_window_get_geometry_info (window, TRUE);
9235 info->mask |= GDK_HINT_USER_POS;
9237 info->mask |= GDK_HINT_USER_SIZE;
9244 gtk_window_mnemonic_hash_foreach (guint keyval,
9250 GtkWindowKeysForeachFunc func;
9254 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9258 _gtk_window_keys_foreach (GtkWindow *window,
9259 GtkWindowKeysForeachFunc func,
9263 GtkMnemonicHash *mnemonic_hash;
9267 GtkWindowKeysForeachFunc func;
9271 info.window = window;
9273 info.func_data = func_data;
9275 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9277 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9278 gtk_window_mnemonic_hash_foreach, &info);
9280 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9283 GtkAccelGroup *group = groups->data;
9286 for (i = 0; i < group->priv->n_accels; i++)
9288 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9291 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9294 groups = groups->next;
9299 gtk_window_keys_changed (GtkWindow *window)
9301 gtk_window_free_key_hash (window);
9302 gtk_window_get_key_hash (window);
9305 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9307 struct _GtkWindowKeyEntry
9311 guint is_mnemonic : 1;
9315 window_key_entry_destroy (gpointer data)
9317 g_slice_free (GtkWindowKeyEntry, data);
9321 add_to_key_hash (GtkWindow *window,
9323 GdkModifierType modifiers,
9324 gboolean is_mnemonic,
9327 GtkKeyHash *key_hash = data;
9329 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9331 entry->keyval = keyval;
9332 entry->modifiers = modifiers;
9333 entry->is_mnemonic = is_mnemonic;
9335 /* GtkAccelGroup stores lowercased accelerators. To deal
9336 * with this, if <Shift> was specified, uppercase.
9338 if (modifiers & GDK_SHIFT_MASK)
9340 if (keyval == GDK_KEY_Tab)
9341 keyval = GDK_KEY_ISO_Left_Tab;
9343 keyval = gdk_keyval_to_upper (keyval);
9346 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9350 gtk_window_get_key_hash (GtkWindow *window)
9352 GdkScreen *screen = gtk_window_check_screen (window);
9353 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9358 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9359 (GDestroyNotify)window_key_entry_destroy);
9360 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9361 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9367 gtk_window_free_key_hash (GtkWindow *window)
9369 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9372 _gtk_key_hash_free (key_hash);
9373 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9378 * gtk_window_activate_key:
9379 * @window: a #GtkWindow
9380 * @event: a #GdkEventKey
9382 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9383 * called by the default ::key_press_event handler for toplevel windows,
9384 * however in some cases it may be useful to call this directly when
9385 * overriding the standard key handling for a toplevel window.
9387 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9392 gtk_window_activate_key (GtkWindow *window,
9395 GtkKeyHash *key_hash;
9396 GtkWindowKeyEntry *found_entry = NULL;
9397 gboolean enable_mnemonics;
9398 gboolean enable_accels;
9400 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9401 g_return_val_if_fail (event != NULL, FALSE);
9403 key_hash = gtk_window_get_key_hash (window);
9408 GSList *entries = _gtk_key_hash_lookup (key_hash,
9409 event->hardware_keycode,
9411 gtk_accelerator_get_default_mod_mask (),
9414 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9415 "gtk-enable-mnemonics", &enable_mnemonics,
9416 "gtk-enable-accels", &enable_accels,
9419 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9421 GtkWindowKeyEntry *entry = tmp_list->data;
9422 if (entry->is_mnemonic)
9424 if (enable_mnemonics)
9426 found_entry = entry;
9432 if (enable_accels && !found_entry)
9434 found_entry = entry;
9439 g_slist_free (entries);
9444 if (found_entry->is_mnemonic)
9446 if (enable_mnemonics)
9447 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9448 found_entry->modifiers);
9453 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9454 found_entry->modifiers);
9462 window_update_has_focus (GtkWindow *window)
9464 GtkWindowPrivate *priv = window->priv;
9465 GtkWidget *widget = GTK_WIDGET (window);
9466 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9468 if (has_focus != priv->has_focus)
9470 priv->has_focus = has_focus;
9474 if (priv->focus_widget &&
9475 priv->focus_widget != widget &&
9476 !gtk_widget_has_focus (priv->focus_widget))
9477 do_focus_change (priv->focus_widget, TRUE);
9481 if (priv->focus_widget &&
9482 priv->focus_widget != widget &&
9483 gtk_widget_has_focus (priv->focus_widget))
9484 do_focus_change (priv->focus_widget, FALSE);
9490 * _gtk_window_set_is_active:
9491 * @window: a #GtkWindow
9492 * @is_active: %TRUE if the window is in the currently active toplevel
9494 * Internal function that sets whether the #GtkWindow is part
9495 * of the currently active toplevel window (taking into account inter-process
9499 _gtk_window_set_is_active (GtkWindow *window,
9502 GtkWindowPrivate *priv;
9504 g_return_if_fail (GTK_IS_WINDOW (window));
9506 priv = window->priv;
9508 is_active = is_active != FALSE;
9510 if (is_active != priv->is_active)
9512 priv->is_active = is_active;
9513 window_update_has_focus (window);
9515 g_object_notify (G_OBJECT (window), "is-active");
9520 * _gtk_window_set_is_toplevel:
9521 * @window: a #GtkWindow
9522 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9523 * child of the root window); %FALSE if it is not (for example, for an
9524 * in-process, parented GtkPlug)
9526 * Internal function used by #GtkPlug when it gets parented/unparented by a
9527 * #GtkSocket. This keeps the @window's #GTK_WINDOW_TOPLEVEL flag in sync
9528 * with the global list of toplevel windows.
9531 _gtk_window_set_is_toplevel (GtkWindow *window,
9532 gboolean is_toplevel)
9535 GtkWidget *toplevel;
9537 widget = GTK_WIDGET (window);
9539 if (gtk_widget_is_toplevel (widget))
9540 g_assert (g_slist_find (toplevel_list, window) != NULL);
9542 g_assert (g_slist_find (toplevel_list, window) == NULL);
9544 if (is_toplevel == gtk_widget_is_toplevel (widget))
9549 /* Pass through regular pathways of an embedded toplevel
9550 * to go through unmapping and hiding the widget before
9551 * becomming a toplevel again.
9553 * We remain hidden after becomming toplevel in order to
9554 * avoid problems during an embedded toplevel's dispose cycle
9555 * (When a toplevel window is shown it tries to grab focus again,
9556 * this causes problems while disposing).
9558 gtk_widget_hide (widget);
9560 /* Save the toplevel this widget was previously anchored into before
9561 * propagating a hierarchy-changed.
9563 * Usually this happens by way of gtk_widget_unparent() and we are
9564 * already unanchored at this point, just adding this clause incase
9565 * things happen differently.
9567 toplevel = gtk_widget_get_toplevel (widget);
9568 if (!gtk_widget_is_toplevel (toplevel))
9571 _gtk_widget_set_is_toplevel (widget, TRUE);
9573 /* When a window becomes toplevel after being embedded and anchored
9574 * into another window we need to unset its anchored flag so that
9575 * the hierarchy changed signal kicks in properly.
9577 _gtk_widget_set_anchored (widget, FALSE);
9578 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9580 toplevel_list = g_slist_prepend (toplevel_list, window);
9584 _gtk_widget_set_is_toplevel (widget, FALSE);
9585 toplevel_list = g_slist_remove (toplevel_list, window);
9587 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9592 * _gtk_window_set_has_toplevel_focus:
9593 * @window: a #GtkWindow
9594 * @has_toplevel_focus: %TRUE if the in
9596 * Internal function that sets whether the keyboard focus for the
9597 * toplevel window (taking into account inter-process embedding.)
9600 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9601 gboolean has_toplevel_focus)
9603 GtkWindowPrivate *priv;
9605 g_return_if_fail (GTK_IS_WINDOW (window));
9607 priv = window->priv;
9609 has_toplevel_focus = has_toplevel_focus != FALSE;
9611 if (has_toplevel_focus != priv->has_toplevel_focus)
9613 priv->has_toplevel_focus = has_toplevel_focus;
9614 window_update_has_focus (window);
9616 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9621 * gtk_window_set_auto_startup_notification:
9622 * @setting: %TRUE to automatically do startup notification
9624 * By default, after showing the first #GtkWindow, GTK+ calls
9625 * gdk_notify_startup_complete(). Call this function to disable
9626 * the automatic startup notification. You might do this if your
9627 * first window is a splash screen, and you want to delay notification
9628 * until after your real main window has been shown, for example.
9630 * In that example, you would disable startup notification
9631 * temporarily, show your splash screen, then re-enable it so that
9632 * showing the main window would automatically result in notification.
9637 gtk_window_set_auto_startup_notification (gboolean setting)
9639 disable_startup_notification = !setting;
9643 * gtk_window_get_window_type:
9644 * @window: a #GtkWindow
9646 * Gets the type of the window. See #GtkWindowType.
9648 * Return value: the type of the window
9653 gtk_window_get_window_type (GtkWindow *window)
9655 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9657 return window->priv->type;
9661 * gtk_window_get_mnemonics_visible:
9662 * @window: a #GtkWindow
9664 * Gets the value of the #GtkWindow:mnemonics-visible property.
9666 * Returns: %TRUE if mnemonics are supposed to be visible
9672 gtk_window_get_mnemonics_visible (GtkWindow *window)
9674 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9676 return window->priv->mnemonics_visible;
9680 * gtk_window_set_mnemonics_visible:
9681 * @window: a #GtkWindow
9682 * @setting: the new value
9684 * Sets the #GtkWindow:mnemonics-visible property.
9689 gtk_window_set_mnemonics_visible (GtkWindow *window,
9692 GtkWindowPrivate *priv;
9694 g_return_if_fail (GTK_IS_WINDOW (window));
9696 priv = window->priv;
9698 setting = setting != FALSE;
9700 if (priv->mnemonics_visible != setting)
9702 priv->mnemonics_visible = setting;
9703 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9706 if (priv->auto_mnemonics_timeout_id)
9708 g_source_remove (priv->auto_mnemonics_timeout_id);
9709 priv->auto_mnemonics_timeout_id = 0;
9712 priv->mnemonics_visible_set = TRUE;
9716 set_auto_mnemonics_visible_cb (gpointer data)
9718 GtkWindow *window = data;
9720 gtk_window_set_mnemonics_visible (window, TRUE);
9722 window->priv->auto_mnemonics_timeout_id = 0;
9728 _gtk_window_set_auto_mnemonics_visible (GtkWindow *window)
9730 g_return_if_fail (GTK_IS_WINDOW (window));
9732 if (window->priv->auto_mnemonics_timeout_id)
9735 window->priv->auto_mnemonics_timeout_id =
9736 gdk_threads_add_timeout (AUTO_MNEMONICS_DELAY, set_auto_mnemonics_visible_cb, window);
9740 * gtk_window_get_focus_visible:
9741 * @window: a #GtkWindow
9743 * Gets the value of the #GtkWindow:focus-visible property.
9745 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9751 gtk_window_get_focus_visible (GtkWindow *window)
9753 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9755 return window->priv->focus_visible;
9759 * gtk_window_set_focus_visible:
9760 * @window: a #GtkWindow
9761 * @setting: the new value
9763 * Sets the #GtkWindow:focus-visible property.
9768 gtk_window_set_focus_visible (GtkWindow *window,
9771 GtkWindowPrivate *priv;
9773 g_return_if_fail (GTK_IS_WINDOW (window));
9775 priv = window->priv;
9777 setting = setting != FALSE;
9779 if (priv->focus_visible != setting)
9781 priv->focus_visible = setting;
9782 g_object_notify (G_OBJECT (window), "focus-visible");
9787 _gtk_window_get_wmclass (GtkWindow *window,
9788 gchar **wmclass_name,
9789 gchar **wmclass_class)
9791 GtkWindowPrivate *priv = window->priv;
9793 *wmclass_name = priv->wmclass_name;
9794 *wmclass_class = priv->wmclass_class;
9798 * gtk_window_set_has_user_ref_count:
9799 * @window: a #GtkWindow
9800 * @setting: the new value
9802 * Tells GTK+ whether to drop its extra reference to the window
9803 * when gtk_widget_destroy() is called.
9805 * This function is only exported for the benefit of language
9806 * bindings which may need to keep the window alive until their
9807 * wrapper object is garbage collected. There is no justification
9808 * for ever calling this function in an application.
9813 gtk_window_set_has_user_ref_count (GtkWindow *window,
9816 g_return_if_fail (GTK_IS_WINDOW (window));
9818 window->priv->has_user_ref_count = setting;
9822 ensure_state_flag_backdrop (GtkWidget *widget)
9825 gboolean window_focused = TRUE;
9827 window = gtk_widget_get_window (widget);
9829 window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9831 if (!window_focused)
9832 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
9834 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
9836 gtk_widget_queue_draw (widget);