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;
121 GdkWindow *grip_window;
125 gchar *wmclass_class;
129 guint keys_changed_handler;
131 guint32 initial_timestamp;
133 guint16 configure_request_count;
135 guint auto_mnemonics_timeout_id;
137 /* The following flags are initially TRUE (before a window is mapped).
138 * They cause us to compute a configure request that involves
139 * default-only parameters. Once mapped, we set them to FALSE.
140 * Then we set them to TRUE again on unmap (for position)
141 * and on unrealize (for size).
143 guint need_default_position : 1;
144 guint need_default_size : 1;
146 guint above_initially : 1;
147 guint accept_focus : 1;
148 guint below_initially : 1;
149 guint builder_visible : 1;
150 guint configure_notify_received : 1;
153 guint destroy_with_parent : 1;
154 guint focus_on_map : 1;
155 guint fullscreen_initially : 1;
157 guint has_user_ref_count : 1;
158 guint has_toplevel_focus : 1;
159 guint hide_titlebar_when_maximized : 1;
160 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
162 guint maximize_initially : 1;
163 guint mnemonics_visible : 1;
164 guint mnemonics_visible_set : 1;
165 guint focus_visible : 1;
168 guint reset_type_hint : 1;
170 guint skips_pager : 1;
171 guint skips_taskbar : 1;
172 guint stick_initially : 1;
173 guint transient_parent_group : 1;
174 guint type : 4; /* GtkWindowType */
175 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
176 * one of the original eight. If not,
178 * GDK_WINDOW_TYPE_HINT_NORMAL
181 guint has_resize_grip : 1;
182 guint resize_grip_visible : 1; /* don't use, just for "resize-
183 * grip-visible" notification
185 guint gravity : 5; /* GdkGravity */
212 PROP_DESTROY_WITH_PARENT,
213 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
218 PROP_SKIP_TASKBAR_HINT,
219 PROP_SKIP_PAGER_HINT,
228 PROP_HAS_RESIZE_GRIP,
229 PROP_RESIZE_GRIP_VISIBLE,
231 /* Readonly properties */
233 PROP_HAS_TOPLEVEL_FOCUS,
235 /* Writeonly properties */
238 PROP_MNEMONICS_VISIBLE,
249 guint using_default_icon : 1;
250 guint using_parent_icon : 1;
251 guint using_themed_icon : 1;
255 GdkGeometry geometry; /* Last set of geometry hints we set */
256 GdkWindowHints flags;
257 GdkRectangle configure_request;
258 } GtkWindowLastGeometryInfo;
260 struct _GtkWindowGeometryInfo
262 /* Properties that the app has set on the window
264 GdkGeometry geometry; /* Geometry hints */
266 GtkWidget *widget; /* subwidget to which hints apply */
267 /* from last gtk_window_resize () - if > 0, indicates that
268 * we should resize to this size.
273 /* From last gtk_window_move () prior to mapping -
274 * only used if initial_pos_set
279 /* Default size - used only the FIRST time we map a window,
284 /* whether to use initial_x, initial_y */
285 guint initial_pos_set : 1;
286 /* CENTER_ALWAYS or other position constraint changed since
287 * we sent the last configure request.
289 guint position_constraints_changed : 1;
291 /* if true, default_width, height should be multiplied by the
292 * increments and affect the geometry widget only
294 guint default_is_geometry : 1;
296 /* if true, resize_width, height should be multiplied by the
297 * increments and affect the geometry widget only
299 guint resize_is_geometry : 1;
301 GtkWindowLastGeometryInfo last;
305 struct _GtkDeviceGrabInfo
309 guint block_others : 1;
312 struct _GtkWindowGroupPrivate
315 GSList *device_grabs;
318 static void gtk_window_dispose (GObject *object);
319 static void gtk_window_finalize (GObject *object);
320 static void gtk_window_destroy (GtkWidget *widget);
321 static void gtk_window_show (GtkWidget *widget);
322 static void gtk_window_hide (GtkWidget *widget);
323 static void gtk_window_map (GtkWidget *widget);
324 static void gtk_window_unmap (GtkWidget *widget);
325 static void gtk_window_realize (GtkWidget *widget);
326 static void gtk_window_unrealize (GtkWidget *widget);
327 static void gtk_window_size_allocate (GtkWidget *widget,
328 GtkAllocation *allocation);
329 static gboolean gtk_window_map_event (GtkWidget *widget,
331 static gint gtk_window_configure_event (GtkWidget *widget,
332 GdkEventConfigure *event);
333 static gint gtk_window_key_press_event (GtkWidget *widget,
335 static gint gtk_window_key_release_event (GtkWidget *widget,
337 static gint gtk_window_button_press_event (GtkWidget *widget,
338 GdkEventButton *event);
339 static gint gtk_window_enter_notify_event (GtkWidget *widget,
340 GdkEventCrossing *event);
341 static gint gtk_window_leave_notify_event (GtkWidget *widget,
342 GdkEventCrossing *event);
343 static gint gtk_window_focus_in_event (GtkWidget *widget,
344 GdkEventFocus *event);
345 static gint gtk_window_focus_out_event (GtkWidget *widget,
346 GdkEventFocus *event);
347 static void gtk_window_style_updated (GtkWidget *widget);
348 static gboolean gtk_window_state_event (GtkWidget *widget,
349 GdkEventWindowState *event);
350 static void gtk_window_check_resize (GtkContainer *container);
351 static gint gtk_window_focus (GtkWidget *widget,
352 GtkDirectionType direction);
353 static void gtk_window_move_focus (GtkWidget *widget,
354 GtkDirectionType dir);
355 static void gtk_window_real_set_focus (GtkWindow *window,
357 static void gtk_window_direction_changed (GtkWidget *widget,
358 GtkTextDirection prev_dir);
359 static void gtk_window_state_changed (GtkWidget *widget,
360 GtkStateType previous_state);
362 static void gtk_window_real_activate_default (GtkWindow *window);
363 static void gtk_window_real_activate_focus (GtkWindow *window);
364 static void gtk_window_keys_changed (GtkWindow *window);
365 static gint gtk_window_draw (GtkWidget *widget,
367 static void gtk_window_unset_transient_for (GtkWindow *window);
368 static void gtk_window_transient_parent_realized (GtkWidget *parent,
370 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
373 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
375 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
378 static void gtk_window_move_resize (GtkWindow *window);
379 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
381 GdkGeometry *geometry_b,
383 static void gtk_window_constrain_size (GtkWindow *window,
384 GdkGeometry *geometry,
390 static void gtk_window_constrain_position (GtkWindow *window,
395 static void gtk_window_compute_hints (GtkWindow *window,
396 GdkGeometry *new_geometry,
398 static void gtk_window_compute_configure_request (GtkWindow *window,
399 GdkRectangle *request,
400 GdkGeometry *geometry,
403 static void gtk_window_set_default_size_internal (GtkWindow *window,
404 gboolean change_width,
406 gboolean change_height,
408 gboolean is_geometry);
410 static void update_themed_icon (GtkIconTheme *theme,
412 static GList *icon_list_from_theme (GtkWidget *widget,
414 static void gtk_window_realize_icon (GtkWindow *window);
415 static void gtk_window_unrealize_icon (GtkWindow *window);
416 static void resize_grip_create_window (GtkWindow *window);
417 static void resize_grip_destroy_window (GtkWindow *window);
418 static void update_grip_visibility (GtkWindow *window);
420 static void gtk_window_notify_keys_changed (GtkWindow *window);
421 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
422 static void gtk_window_free_key_hash (GtkWindow *window);
423 static void gtk_window_on_composited_changed (GdkScreen *screen,
425 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
428 static void gtk_window_set_theme_variant (GtkWindow *window);
430 static GSList *toplevel_list = NULL;
431 static guint window_signals[LAST_SIGNAL] = { 0 };
432 static GList *default_icon_list = NULL;
433 static gchar *default_icon_name = NULL;
434 static guint default_icon_serial = 0;
435 static gboolean disable_startup_notification = FALSE;
436 static gboolean sent_startup_notification = FALSE;
438 static GQuark quark_gtk_embedded = 0;
439 static GQuark quark_gtk_window_key_hash = 0;
440 static GQuark quark_gtk_window_icon_info = 0;
441 static GQuark quark_gtk_buildable_accels = 0;
443 static GtkBuildableIface *parent_buildable_iface;
445 static void gtk_window_set_property (GObject *object,
449 static void gtk_window_get_property (GObject *object,
455 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
456 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
459 const GValue *value);
460 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
461 GtkBuilder *builder);
462 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
465 const gchar *tagname,
466 GMarkupParser *parser,
468 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
471 const gchar *tagname,
474 static void ensure_state_flag_backdrop (GtkWidget *widget);
476 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
477 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
478 gtk_window_buildable_interface_init))
481 add_tab_bindings (GtkBindingSet *binding_set,
482 GdkModifierType modifiers,
483 GtkDirectionType direction)
485 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
487 GTK_TYPE_DIRECTION_TYPE, direction);
488 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
490 GTK_TYPE_DIRECTION_TYPE, direction);
494 add_arrow_bindings (GtkBindingSet *binding_set,
496 GtkDirectionType direction)
498 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
500 gtk_binding_entry_add_signal (binding_set, keysym, 0,
502 GTK_TYPE_DIRECTION_TYPE, direction);
503 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
505 GTK_TYPE_DIRECTION_TYPE, direction);
506 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
508 GTK_TYPE_DIRECTION_TYPE, direction);
509 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
511 GTK_TYPE_DIRECTION_TYPE, direction);
515 extract_time_from_startup_id (const gchar* startup_id)
517 gchar *timestr = g_strrstr (startup_id, "_TIME");
518 guint32 retval = GDK_CURRENT_TIME;
525 /* Skip past the "_TIME" part */
530 timestamp = g_ascii_strtoull (timestr, &end, 0);
531 if (errno == 0 && end != timestr)
539 startup_id_is_fake (const gchar* startup_id)
541 return strncmp (startup_id, "_TIME", 5) == 0;
545 gtk_window_class_init (GtkWindowClass *klass)
547 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
548 GtkWidgetClass *widget_class;
549 GtkContainerClass *container_class;
550 GtkBindingSet *binding_set;
552 widget_class = (GtkWidgetClass*) klass;
553 container_class = (GtkContainerClass*) klass;
555 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
556 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
557 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
558 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
560 gobject_class->dispose = gtk_window_dispose;
561 gobject_class->finalize = gtk_window_finalize;
563 gobject_class->set_property = gtk_window_set_property;
564 gobject_class->get_property = gtk_window_get_property;
566 widget_class->destroy = gtk_window_destroy;
567 widget_class->show = gtk_window_show;
568 widget_class->hide = gtk_window_hide;
569 widget_class->map = gtk_window_map;
570 widget_class->map_event = gtk_window_map_event;
571 widget_class->unmap = gtk_window_unmap;
572 widget_class->realize = gtk_window_realize;
573 widget_class->unrealize = gtk_window_unrealize;
574 widget_class->size_allocate = gtk_window_size_allocate;
575 widget_class->configure_event = gtk_window_configure_event;
576 widget_class->key_press_event = gtk_window_key_press_event;
577 widget_class->key_release_event = gtk_window_key_release_event;
578 widget_class->enter_notify_event = gtk_window_enter_notify_event;
579 widget_class->leave_notify_event = gtk_window_leave_notify_event;
580 widget_class->focus_in_event = gtk_window_focus_in_event;
581 widget_class->button_press_event = gtk_window_button_press_event;
582 widget_class->focus_out_event = gtk_window_focus_out_event;
583 widget_class->focus = gtk_window_focus;
584 widget_class->move_focus = gtk_window_move_focus;
585 widget_class->draw = gtk_window_draw;
586 widget_class->window_state_event = gtk_window_state_event;
587 widget_class->direction_changed = gtk_window_direction_changed;
588 widget_class->state_changed = gtk_window_state_changed;
589 widget_class->style_updated = gtk_window_style_updated;
591 container_class->check_resize = gtk_window_check_resize;
593 klass->set_focus = gtk_window_real_set_focus;
595 klass->activate_default = gtk_window_real_activate_default;
596 klass->activate_focus = gtk_window_real_activate_focus;
597 klass->keys_changed = gtk_window_keys_changed;
599 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
602 g_object_class_install_property (gobject_class,
604 g_param_spec_enum ("type",
606 P_("The type of the window"),
607 GTK_TYPE_WINDOW_TYPE,
609 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
611 g_object_class_install_property (gobject_class,
613 g_param_spec_string ("title",
615 P_("The title of the window"),
617 GTK_PARAM_READWRITE));
619 g_object_class_install_property (gobject_class,
621 g_param_spec_string ("role",
623 P_("Unique identifier for the window to be used when restoring a session"),
625 GTK_PARAM_READWRITE));
628 * GtkWindow:startup-id:
630 * The :startup-id is a write-only property for setting window's
631 * startup notification identifier. See gtk_window_set_startup_id()
636 g_object_class_install_property (gobject_class,
638 g_param_spec_string ("startup-id",
640 P_("Unique startup identifier for the window used by startup-notification"),
642 GTK_PARAM_WRITABLE));
644 g_object_class_install_property (gobject_class,
646 g_param_spec_boolean ("resizable",
648 P_("If TRUE, users can resize the window"),
650 GTK_PARAM_READWRITE));
652 g_object_class_install_property (gobject_class,
654 g_param_spec_boolean ("modal",
656 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
658 GTK_PARAM_READWRITE));
660 g_object_class_install_property (gobject_class,
662 g_param_spec_enum ("window-position",
663 P_("Window Position"),
664 P_("The initial position of the window"),
665 GTK_TYPE_WINDOW_POSITION,
667 GTK_PARAM_READWRITE));
669 g_object_class_install_property (gobject_class,
671 g_param_spec_int ("default-width",
673 P_("The default width of the window, used when initially showing the window"),
677 GTK_PARAM_READWRITE));
679 g_object_class_install_property (gobject_class,
681 g_param_spec_int ("default-height",
682 P_("Default Height"),
683 P_("The default height of the window, used when initially showing the window"),
687 GTK_PARAM_READWRITE));
689 g_object_class_install_property (gobject_class,
690 PROP_DESTROY_WITH_PARENT,
691 g_param_spec_boolean ("destroy-with-parent",
692 P_("Destroy with Parent"),
693 P_("If this window should be destroyed when the parent is destroyed"),
695 GTK_PARAM_READWRITE));
698 * GtkWindow:hide-titlebar-when-maximized:
700 * Whether the titlebar should be hidden during maximization.
704 g_object_class_install_property (gobject_class,
705 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
706 g_param_spec_boolean ("hide-titlebar-when-maximized",
707 P_("Hide the titlebar during maximization"),
708 P_("If this window's titlebar should be hidden when the window is maximized"),
710 GTK_PARAM_READWRITE));
712 g_object_class_install_property (gobject_class,
714 g_param_spec_object ("icon",
716 P_("Icon for this window"),
718 GTK_PARAM_READWRITE));
721 * GtkWindow:mnemonics-visible:
723 * Whether mnemonics are currently visible in this window.
725 * This property is maintained by GTK+ based on the
726 * #GtkSettings:gtk-auto-mnemonics setting and user input,
727 * and should not be set by applications.
731 g_object_class_install_property (gobject_class,
732 PROP_MNEMONICS_VISIBLE,
733 g_param_spec_boolean ("mnemonics-visible",
734 P_("Mnemonics Visible"),
735 P_("Whether mnemonics are currently visible in this window"),
737 GTK_PARAM_READWRITE));
740 * GtkWindow:focus-visible:
742 * Whether 'focus rectangles' are currently visible in this window.
744 * This property is maintained by GTK+ based on the
745 * #GtkSettings:gtk-visible-focus setting and user input
746 * and should not be set by applications.
750 g_object_class_install_property (gobject_class,
752 g_param_spec_boolean ("focus-visible",
754 P_("Whether focus rectangles are currently visible in this window"),
756 GTK_PARAM_READWRITE));
759 * GtkWindow:icon-name:
761 * The :icon-name property specifies the name of the themed icon to
762 * use as the window icon. See #GtkIconTheme for more details.
766 g_object_class_install_property (gobject_class,
768 g_param_spec_string ("icon-name",
770 P_("Name of the themed icon for this window"),
772 GTK_PARAM_READWRITE));
774 g_object_class_install_property (gobject_class,
776 g_param_spec_object ("screen",
778 P_("The screen where this window will be displayed"),
780 GTK_PARAM_READWRITE));
782 g_object_class_install_property (gobject_class,
784 g_param_spec_boolean ("is-active",
786 P_("Whether the toplevel is the current active window"),
788 GTK_PARAM_READABLE));
790 g_object_class_install_property (gobject_class,
791 PROP_HAS_TOPLEVEL_FOCUS,
792 g_param_spec_boolean ("has-toplevel-focus",
793 P_("Focus in Toplevel"),
794 P_("Whether the input focus is within this GtkWindow"),
796 GTK_PARAM_READABLE));
798 g_object_class_install_property (gobject_class,
800 g_param_spec_enum ("type-hint",
802 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
803 GDK_TYPE_WINDOW_TYPE_HINT,
804 GDK_WINDOW_TYPE_HINT_NORMAL,
805 GTK_PARAM_READWRITE));
807 g_object_class_install_property (gobject_class,
808 PROP_SKIP_TASKBAR_HINT,
809 g_param_spec_boolean ("skip-taskbar-hint",
811 P_("TRUE if the window should not be in the task bar."),
813 GTK_PARAM_READWRITE));
815 g_object_class_install_property (gobject_class,
816 PROP_SKIP_PAGER_HINT,
817 g_param_spec_boolean ("skip-pager-hint",
819 P_("TRUE if the window should not be in the pager."),
821 GTK_PARAM_READWRITE));
823 g_object_class_install_property (gobject_class,
825 g_param_spec_boolean ("urgency-hint",
827 P_("TRUE if the window should be brought to the user's attention."),
829 GTK_PARAM_READWRITE));
832 * GtkWindow:accept-focus:
834 * Whether the window should receive the input focus.
838 g_object_class_install_property (gobject_class,
840 g_param_spec_boolean ("accept-focus",
842 P_("TRUE if the window should receive the input focus."),
844 GTK_PARAM_READWRITE));
847 * GtkWindow:focus-on-map:
849 * Whether the window should receive the input focus when mapped.
853 g_object_class_install_property (gobject_class,
855 g_param_spec_boolean ("focus-on-map",
857 P_("TRUE if the window should receive the input focus when mapped."),
859 GTK_PARAM_READWRITE));
862 * GtkWindow:decorated:
864 * Whether the window should be decorated by the window manager.
868 g_object_class_install_property (gobject_class,
870 g_param_spec_boolean ("decorated",
872 P_("Whether the window should be decorated by the window manager"),
874 GTK_PARAM_READWRITE));
877 * GtkWindow:deletable:
879 * Whether the window frame should have a close button.
883 g_object_class_install_property (gobject_class,
885 g_param_spec_boolean ("deletable",
887 P_("Whether the window frame should have a close button"),
889 GTK_PARAM_READWRITE));
892 * GtkWindow:has-resize-grip:
894 * Whether the window has a corner resize grip.
896 * Note that the resize grip is only shown if the window is
897 * actually resizable and not maximized. Use
898 * #GtkWindow:resize-grip-visible to find out if the resize
899 * grip is currently shown.
903 g_object_class_install_property (gobject_class,
904 PROP_HAS_RESIZE_GRIP,
905 g_param_spec_boolean ("has-resize-grip",
907 P_("Specifies whether the window should have a resize grip"),
909 GTK_PARAM_READWRITE));
912 * GtkWindow:resize-grip-visible:
914 * Whether a corner resize grip is currently shown.
918 g_object_class_install_property (gobject_class,
919 PROP_RESIZE_GRIP_VISIBLE,
920 g_param_spec_boolean ("resize-grip-visible",
921 P_("Resize grip is visible"),
922 P_("Specifies whether the window's resize grip is visible."),
924 GTK_PARAM_READABLE));
930 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
931 * more details about window gravity.
935 g_object_class_install_property (gobject_class,
937 g_param_spec_enum ("gravity",
939 P_("The window gravity of the window"),
941 GDK_GRAVITY_NORTH_WEST,
942 GTK_PARAM_READWRITE));
946 * GtkWindow:transient-for:
948 * The transient parent of the window. See gtk_window_set_transient_for() for
949 * more details about transient windows.
953 g_object_class_install_property (gobject_class,
955 g_param_spec_object ("transient-for",
956 P_("Transient for Window"),
957 P_("The transient parent of the dialog"),
959 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
962 * GtkWindow:attached-to:
964 * The widget to which this window is attached.
965 * See gtk_window_set_attached_to().
967 * Examples of places where specifying this relation is useful are
968 * for instance a #GtkMenu created by a #GtkComboBox, a completion
969 * popup window created by #GtkEntry or a typeahead search entry
970 * created by #GtkTreeView.
974 g_object_class_install_property (gobject_class,
976 g_param_spec_object ("attached-to",
977 P_("Attached to Widget"),
978 P_("The widget where the window is attached"),
980 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
984 gtk_widget_class_install_style_property (widget_class,
985 g_param_spec_int ("resize-grip-width",
986 P_("Width of resize grip"),
987 P_("Width of resize grip"),
988 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
990 gtk_widget_class_install_style_property (widget_class,
991 g_param_spec_int ("resize-grip-height",
992 P_("Height of resize grip"),
993 P_("Height of resize grip"),
994 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
998 * GtkWindow:application:
1000 * The #GtkApplication associated with the window.
1002 * The application will be kept alive for at least as long as it
1003 * has any windows associated with it (see g_application_hold()
1004 * for a way to keep it alive without windows).
1006 * Normally, the connection between the application and the window
1007 * will remain until the window is destroyed, but you can explicitly
1008 * remove it by setting the ::application property to %NULL.
1012 g_object_class_install_property (gobject_class,
1014 g_param_spec_object ("application",
1015 P_("GtkApplication"),
1016 P_("The GtkApplication for the window"),
1017 GTK_TYPE_APPLICATION,
1018 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1020 window_signals[SET_FOCUS] =
1021 g_signal_new (I_("set-focus"),
1022 G_TYPE_FROM_CLASS (gobject_class),
1024 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1026 _gtk_marshal_VOID__OBJECT,
1031 * GtkWindow::activate-focus:
1032 * @window: the window which received the signal
1034 * The ::activate-focus signal is a
1035 * <link linkend="keybinding-signals">keybinding signal</link>
1036 * which gets emitted when the user activates the currently
1037 * focused widget of @window.
1039 window_signals[ACTIVATE_FOCUS] =
1040 g_signal_new (I_("activate-focus"),
1041 G_TYPE_FROM_CLASS (gobject_class),
1042 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1043 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1045 _gtk_marshal_VOID__VOID,
1050 * GtkWindow::activate-default:
1051 * @window: the window which received the signal
1053 * The ::activate-default signal is a
1054 * <link linkend="keybinding-signals">keybinding signal</link>
1055 * which gets emitted when the user activates the default widget
1058 window_signals[ACTIVATE_DEFAULT] =
1059 g_signal_new (I_("activate-default"),
1060 G_TYPE_FROM_CLASS (gobject_class),
1061 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1062 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1064 _gtk_marshal_VOID__VOID,
1069 * GtkWindow::keys-changed:
1070 * @window: the window which received the signal
1072 * The ::keys-changed signal gets emitted when the set of accelerators
1073 * or mnemonics that are associated with @window changes.
1075 window_signals[KEYS_CHANGED] =
1076 g_signal_new (I_("keys-changed"),
1077 G_TYPE_FROM_CLASS (gobject_class),
1079 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1081 _gtk_marshal_VOID__VOID,
1089 binding_set = gtk_binding_set_by_class (klass);
1091 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1092 "activate-focus", 0);
1093 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1094 "activate-focus", 0);
1096 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1097 "activate-default", 0);
1098 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1099 "activate-default", 0);
1100 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1101 "activate-default", 0);
1103 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1104 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1105 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1106 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1108 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1109 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1110 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1111 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1113 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1117 gtk_window_init (GtkWindow *window)
1119 GtkStyleContext *context;
1120 GtkWindowPrivate *priv;
1122 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1125 priv = window->priv;
1127 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1128 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1130 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1132 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1135 priv->wmclass_name = g_strdup (g_get_prgname ());
1136 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1137 priv->wm_role = NULL;
1138 priv->geometry_info = NULL;
1139 priv->type = GTK_WINDOW_TOPLEVEL;
1140 priv->focus_widget = NULL;
1141 priv->default_widget = NULL;
1142 priv->configure_request_count = 0;
1143 priv->resizable = TRUE;
1144 priv->configure_notify_received = FALSE;
1145 priv->position = GTK_WIN_POS_NONE;
1146 priv->need_default_size = TRUE;
1147 priv->need_default_position = TRUE;
1148 priv->modal = FALSE;
1149 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1150 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1151 priv->decorated = TRUE;
1152 priv->mnemonic_modifier = GDK_MOD1_MASK;
1153 priv->screen = gdk_screen_get_default ();
1155 priv->accept_focus = TRUE;
1156 priv->focus_on_map = TRUE;
1157 priv->deletable = TRUE;
1158 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1159 priv->startup_id = NULL;
1160 priv->initial_timestamp = GDK_CURRENT_TIME;
1161 priv->has_resize_grip = TRUE;
1162 priv->mnemonics_visible = TRUE;
1163 priv->focus_visible = TRUE;
1165 g_object_ref_sink (window);
1166 priv->has_user_ref_count = TRUE;
1167 toplevel_list = g_slist_prepend (toplevel_list, window);
1170 g_signal_connect (priv->screen, "composited-changed",
1171 G_CALLBACK (gtk_window_on_composited_changed), window);
1173 #ifdef GDK_WINDOWING_X11
1174 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1175 "notify::gtk-application-prefer-dark-theme",
1176 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1179 context = gtk_widget_get_style_context (GTK_WIDGET (window));
1180 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
1184 gtk_window_set_property (GObject *object,
1186 const GValue *value,
1189 GtkWindow *window = GTK_WINDOW (object);
1190 GtkWindowPrivate *priv = window->priv;
1195 priv->type = g_value_get_enum (value);
1198 gtk_window_set_title (window, g_value_get_string (value));
1201 gtk_window_set_role (window, g_value_get_string (value));
1203 case PROP_STARTUP_ID:
1204 gtk_window_set_startup_id (window, g_value_get_string (value));
1206 case PROP_RESIZABLE:
1207 gtk_window_set_resizable (window, g_value_get_boolean (value));
1210 gtk_window_set_modal (window, g_value_get_boolean (value));
1213 gtk_window_set_position (window, g_value_get_enum (value));
1215 case PROP_DEFAULT_WIDTH:
1216 gtk_window_set_default_size_internal (window,
1217 TRUE, g_value_get_int (value),
1220 case PROP_DEFAULT_HEIGHT:
1221 gtk_window_set_default_size_internal (window,
1223 TRUE, g_value_get_int (value), FALSE);
1225 case PROP_DESTROY_WITH_PARENT:
1226 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1228 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1229 gtk_window_set_hide_titlebar_when_maximized (window, g_value_get_boolean (value));
1232 gtk_window_set_icon (window,
1233 g_value_get_object (value));
1235 case PROP_ICON_NAME:
1236 gtk_window_set_icon_name (window, g_value_get_string (value));
1239 gtk_window_set_screen (window, g_value_get_object (value));
1241 case PROP_TYPE_HINT:
1242 gtk_window_set_type_hint (window,
1243 g_value_get_enum (value));
1245 case PROP_SKIP_TASKBAR_HINT:
1246 gtk_window_set_skip_taskbar_hint (window,
1247 g_value_get_boolean (value));
1249 case PROP_SKIP_PAGER_HINT:
1250 gtk_window_set_skip_pager_hint (window,
1251 g_value_get_boolean (value));
1253 case PROP_URGENCY_HINT:
1254 gtk_window_set_urgency_hint (window,
1255 g_value_get_boolean (value));
1257 case PROP_ACCEPT_FOCUS:
1258 gtk_window_set_accept_focus (window,
1259 g_value_get_boolean (value));
1261 case PROP_FOCUS_ON_MAP:
1262 gtk_window_set_focus_on_map (window,
1263 g_value_get_boolean (value));
1265 case PROP_DECORATED:
1266 gtk_window_set_decorated (window, g_value_get_boolean (value));
1268 case PROP_DELETABLE:
1269 gtk_window_set_deletable (window, g_value_get_boolean (value));
1272 gtk_window_set_gravity (window, g_value_get_enum (value));
1274 case PROP_TRANSIENT_FOR:
1275 gtk_window_set_transient_for (window, g_value_get_object (value));
1277 case PROP_ATTACHED_TO:
1278 gtk_window_set_attached_to (window, g_value_get_object (value));
1280 case PROP_HAS_RESIZE_GRIP:
1281 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1283 case PROP_APPLICATION:
1284 gtk_window_set_application (window, g_value_get_object (value));
1286 case PROP_MNEMONICS_VISIBLE:
1287 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1289 case PROP_FOCUS_VISIBLE:
1290 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1293 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1299 gtk_window_get_property (GObject *object,
1304 GtkWindow *window = GTK_WINDOW (object);
1305 GtkWindowPrivate *priv = window->priv;
1309 GtkWindowGeometryInfo *info;
1311 g_value_set_enum (value, priv->type);
1314 g_value_set_string (value, priv->wm_role);
1317 g_value_set_string (value, priv->title);
1319 case PROP_RESIZABLE:
1320 g_value_set_boolean (value, priv->resizable);
1323 g_value_set_boolean (value, priv->modal);
1326 g_value_set_enum (value, priv->position);
1328 case PROP_DEFAULT_WIDTH:
1329 info = gtk_window_get_geometry_info (window, FALSE);
1331 g_value_set_int (value, -1);
1333 g_value_set_int (value, info->default_width);
1335 case PROP_DEFAULT_HEIGHT:
1336 info = gtk_window_get_geometry_info (window, FALSE);
1338 g_value_set_int (value, -1);
1340 g_value_set_int (value, info->default_height);
1342 case PROP_DESTROY_WITH_PARENT:
1343 g_value_set_boolean (value, priv->destroy_with_parent);
1345 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1346 g_value_set_boolean (value, priv->hide_titlebar_when_maximized);
1349 g_value_set_object (value, gtk_window_get_icon (window));
1351 case PROP_ICON_NAME:
1352 g_value_set_string (value, gtk_window_get_icon_name (window));
1355 g_value_set_object (value, priv->screen);
1357 case PROP_IS_ACTIVE:
1358 g_value_set_boolean (value, priv->is_active);
1360 case PROP_HAS_TOPLEVEL_FOCUS:
1361 g_value_set_boolean (value, priv->has_toplevel_focus);
1363 case PROP_TYPE_HINT:
1364 g_value_set_enum (value, priv->type_hint);
1366 case PROP_SKIP_TASKBAR_HINT:
1367 g_value_set_boolean (value,
1368 gtk_window_get_skip_taskbar_hint (window));
1370 case PROP_SKIP_PAGER_HINT:
1371 g_value_set_boolean (value,
1372 gtk_window_get_skip_pager_hint (window));
1374 case PROP_URGENCY_HINT:
1375 g_value_set_boolean (value,
1376 gtk_window_get_urgency_hint (window));
1378 case PROP_ACCEPT_FOCUS:
1379 g_value_set_boolean (value,
1380 gtk_window_get_accept_focus (window));
1382 case PROP_FOCUS_ON_MAP:
1383 g_value_set_boolean (value,
1384 gtk_window_get_focus_on_map (window));
1386 case PROP_DECORATED:
1387 g_value_set_boolean (value, gtk_window_get_decorated (window));
1389 case PROP_DELETABLE:
1390 g_value_set_boolean (value, gtk_window_get_deletable (window));
1393 g_value_set_enum (value, gtk_window_get_gravity (window));
1395 case PROP_TRANSIENT_FOR:
1396 g_value_set_object (value, gtk_window_get_transient_for (window));
1398 case PROP_ATTACHED_TO:
1399 g_value_set_object (value, gtk_window_get_attached_to (window));
1401 case PROP_HAS_RESIZE_GRIP:
1402 g_value_set_boolean (value, priv->has_resize_grip);
1404 case PROP_RESIZE_GRIP_VISIBLE:
1405 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1407 case PROP_APPLICATION:
1408 g_value_set_object (value, gtk_window_get_application (window));
1410 case PROP_MNEMONICS_VISIBLE:
1411 g_value_set_boolean (value, priv->mnemonics_visible);
1413 case PROP_FOCUS_VISIBLE:
1414 g_value_set_boolean (value, priv->focus_visible);
1417 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1423 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1425 parent_buildable_iface = g_type_interface_peek_parent (iface);
1426 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1427 iface->parser_finished = gtk_window_buildable_parser_finished;
1428 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1429 iface->custom_finished = gtk_window_buildable_custom_finished;
1433 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1434 GtkBuilder *builder,
1436 const GValue *value)
1438 GtkWindow *window = GTK_WINDOW (buildable);
1439 GtkWindowPrivate *priv = window->priv;
1441 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1442 priv->builder_visible = TRUE;
1444 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1448 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1449 GtkBuilder *builder)
1451 GtkWindow *window = GTK_WINDOW (buildable);
1452 GtkWindowPrivate *priv = window->priv;
1456 if (priv->builder_visible)
1457 gtk_widget_show (GTK_WIDGET (buildable));
1459 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1460 for (l = accels; l; l = l->next)
1462 object = gtk_builder_get_object (builder, l->data);
1465 g_warning ("Unknown accel group %s specified in window %s",
1466 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1469 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1470 GTK_ACCEL_GROUP (object));
1474 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1476 parent_buildable_iface->parser_finished (buildable, builder);
1482 } GSListSubParserData;
1485 window_start_element (GMarkupParseContext *context,
1486 const gchar *element_name,
1487 const gchar **names,
1488 const gchar **values,
1493 GSListSubParserData *data = (GSListSubParserData*)user_data;
1495 if (strcmp (element_name, "group") == 0)
1497 for (i = 0; names[i]; i++)
1499 if (strcmp (names[i], "name") == 0)
1500 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1503 else if (strcmp (element_name, "accel-groups") == 0)
1506 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1511 static const GMarkupParser window_parser =
1513 window_start_element
1517 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1518 GtkBuilder *builder,
1520 const gchar *tagname,
1521 GMarkupParser *parser,
1524 GSListSubParserData *parser_data;
1526 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1527 tagname, parser, data))
1530 if (strcmp (tagname, "accel-groups") == 0)
1532 parser_data = g_slice_new0 (GSListSubParserData);
1533 parser_data->items = NULL;
1534 parser_data->object = G_OBJECT (buildable);
1536 *parser = window_parser;
1537 *data = parser_data;
1545 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1546 GtkBuilder *builder,
1548 const gchar *tagname,
1551 GSListSubParserData *data;
1553 parent_buildable_iface->custom_finished (buildable, builder, child,
1554 tagname, user_data);
1556 if (strcmp (tagname, "accel-groups") != 0)
1559 data = (GSListSubParserData*)user_data;
1561 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1562 data->items, (GDestroyNotify) g_slist_free);
1564 g_slice_free (GSListSubParserData, data);
1569 * @type: type of window
1571 * Creates a new #GtkWindow, which is a toplevel window that can
1572 * contain other widgets. Nearly always, the type of the window should
1573 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1574 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1575 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1576 * dialogs, though in some other toolkits dialogs are called "popups".
1577 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1578 * On X11, popup windows are not controlled by the <link
1579 * linkend="gtk-X11-arch">window manager</link>.
1581 * If you simply want an undecorated window (no window borders), use
1582 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1584 * Return value: a new #GtkWindow.
1587 gtk_window_new (GtkWindowType type)
1589 GtkWindowPrivate *priv;
1592 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1594 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1595 priv = window->priv;
1599 return GTK_WIDGET (window);
1603 * gtk_window_set_title:
1604 * @window: a #GtkWindow
1605 * @title: title of the window
1607 * Sets the title of the #GtkWindow. The title of a window will be
1608 * displayed in its title bar; on the X Window System, the title bar
1609 * is rendered by the <link linkend="gtk-X11-arch">window
1610 * manager</link>, so exactly how the title appears to users may vary
1611 * according to a user's exact configuration. The title should help a
1612 * user distinguish this window from other windows they may have
1613 * open. A good title might include the application name and current
1614 * document filename, for example.
1618 gtk_window_set_title (GtkWindow *window,
1621 GtkWindowPrivate *priv;
1625 g_return_if_fail (GTK_IS_WINDOW (window));
1627 priv = window->priv;
1628 widget = GTK_WIDGET (window);
1630 new_title = g_strdup (title);
1631 g_free (priv->title);
1632 priv->title = new_title;
1634 if (gtk_widget_get_realized (widget))
1636 gdk_window_set_title (gtk_widget_get_window (widget),
1640 g_object_notify (G_OBJECT (window), "title");
1644 * gtk_window_get_title:
1645 * @window: a #GtkWindow
1647 * Retrieves the title of the window. See gtk_window_set_title().
1649 * Return value: the title of the window, or %NULL if none has
1650 * been set explicitely. The returned string is owned by the widget
1651 * and must not be modified or freed.
1654 gtk_window_get_title (GtkWindow *window)
1656 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1658 return window->priv->title;
1662 * gtk_window_set_wmclass:
1663 * @window: a #GtkWindow
1664 * @wmclass_name: window name hint
1665 * @wmclass_class: window class hint
1667 * Don't use this function. It sets the X Window System "class" and
1668 * "name" hints for a window. According to the ICCCM, you should
1669 * always set these to the same value for all windows in an
1670 * application, and GTK+ sets them to that value by default, so calling
1671 * this function is sort of pointless. However, you may want to call
1672 * gtk_window_set_role() on each window in your application, for the
1673 * benefit of the session manager. Setting the role allows the window
1674 * manager to restore window positions when loading a saved session.
1678 gtk_window_set_wmclass (GtkWindow *window,
1679 const gchar *wmclass_name,
1680 const gchar *wmclass_class)
1682 GtkWindowPrivate *priv;
1684 g_return_if_fail (GTK_IS_WINDOW (window));
1686 priv = window->priv;
1688 g_free (priv->wmclass_name);
1689 priv->wmclass_name = g_strdup (wmclass_name);
1691 g_free (priv->wmclass_class);
1692 priv->wmclass_class = g_strdup (wmclass_class);
1694 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1695 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1699 * gtk_window_set_role:
1700 * @window: a #GtkWindow
1701 * @role: unique identifier for the window to be used when restoring a session
1703 * This function is only useful on X11, not with other GTK+ targets.
1705 * In combination with the window title, the window role allows a
1706 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1707 * same" window when an application is restarted. So for example you
1708 * might set the "toolbox" role on your app's toolbox window, so that
1709 * when the user restarts their session, the window manager can put
1710 * the toolbox back in the same place.
1712 * If a window already has a unique title, you don't need to set the
1713 * role, since the WM can use the title to identify the window when
1714 * restoring the session.
1718 gtk_window_set_role (GtkWindow *window,
1721 GtkWindowPrivate *priv;
1724 g_return_if_fail (GTK_IS_WINDOW (window));
1726 priv = window->priv;
1728 new_role = g_strdup (role);
1729 g_free (priv->wm_role);
1730 priv->wm_role = new_role;
1732 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1733 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1736 g_object_notify (G_OBJECT (window), "role");
1740 * gtk_window_set_startup_id:
1741 * @window: a #GtkWindow
1742 * @startup_id: a string with startup-notification identifier
1744 * Startup notification identifiers are used by desktop environment to
1745 * track application startup, to provide user feedback and other
1746 * features. This function changes the corresponding property on the
1747 * underlying GdkWindow. Normally, startup identifier is managed
1748 * automatically and you should only use this function in special cases
1749 * like transferring focus from other processes. You should use this
1750 * function before calling gtk_window_present() or any equivalent
1751 * function generating a window map event.
1753 * This function is only useful on X11, not with other GTK+ targets.
1758 gtk_window_set_startup_id (GtkWindow *window,
1759 const gchar *startup_id)
1761 GtkWindowPrivate *priv;
1764 g_return_if_fail (GTK_IS_WINDOW (window));
1766 priv = window->priv;
1767 widget = GTK_WIDGET (window);
1769 g_free (priv->startup_id);
1770 priv->startup_id = g_strdup (startup_id);
1772 if (gtk_widget_get_realized (widget))
1774 GdkWindow *gdk_window;
1775 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1777 gdk_window = gtk_widget_get_window (widget);
1779 #ifdef GDK_WINDOWING_X11
1780 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1781 gdk_x11_window_set_user_time (gdk_window, timestamp);
1784 /* Here we differentiate real and "fake" startup notification IDs,
1785 * constructed on purpose just to pass interaction timestamp
1787 if (startup_id_is_fake (priv->startup_id))
1788 gtk_window_present_with_time (window, timestamp);
1791 gdk_window_set_startup_id (gdk_window,
1794 /* If window is mapped, terminate the startup-notification too */
1795 if (gtk_widget_get_mapped (widget) &&
1796 !disable_startup_notification)
1797 gdk_notify_startup_complete_with_id (priv->startup_id);
1801 g_object_notify (G_OBJECT (window), "startup-id");
1805 * gtk_window_get_role:
1806 * @window: a #GtkWindow
1808 * Returns the role of the window. See gtk_window_set_role() for
1809 * further explanation.
1811 * Return value: the role of the window if set, or %NULL. The
1812 * returned is owned by the widget and must not be modified
1816 gtk_window_get_role (GtkWindow *window)
1818 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1820 return window->priv->wm_role;
1824 * gtk_window_set_focus:
1825 * @window: a #GtkWindow
1826 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1827 * any focus widget for the toplevel window.
1829 * If @focus is not the current focus widget, and is focusable, sets
1830 * it as the focus widget for the window. If @focus is %NULL, unsets
1831 * the focus widget for this window. To set the focus to a particular
1832 * widget in the toplevel, it is usually more convenient to use
1833 * gtk_widget_grab_focus() instead of this function.
1836 gtk_window_set_focus (GtkWindow *window,
1839 GtkWindowPrivate *priv;
1842 g_return_if_fail (GTK_IS_WINDOW (window));
1844 priv = window->priv;
1848 g_return_if_fail (GTK_IS_WIDGET (focus));
1849 g_return_if_fail (gtk_widget_get_can_focus (focus));
1853 gtk_widget_grab_focus (focus);
1856 /* Clear the existing focus chain, so that when we focus into
1857 * the window again, we start at the beginnning.
1859 GtkWidget *widget = priv->focus_widget;
1862 while ((parent = gtk_widget_get_parent (widget)))
1865 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1869 _gtk_window_internal_set_focus (window, NULL);
1874 _gtk_window_internal_set_focus (GtkWindow *window,
1877 GtkWindowPrivate *priv;
1879 g_return_if_fail (GTK_IS_WINDOW (window));
1881 priv = window->priv;
1883 if ((priv->focus_widget != focus) ||
1884 (focus && !gtk_widget_has_focus (focus)))
1885 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1889 * gtk_window_set_default:
1890 * @window: a #GtkWindow
1891 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1892 * default widget for the toplevel.
1894 * The default widget is the widget that's activated when the user
1895 * presses Enter in a dialog (for example). This function sets or
1896 * unsets the default widget for a #GtkWindow about. When setting
1897 * (rather than unsetting) the default widget it's generally easier to
1898 * call gtk_widget_grab_focus() on the widget. Before making a widget
1899 * the default widget, you must call gtk_widget_set_can_default() on the
1900 * widget you'd like to make the default.
1903 gtk_window_set_default (GtkWindow *window,
1904 GtkWidget *default_widget)
1906 GtkWindowPrivate *priv;
1908 g_return_if_fail (GTK_IS_WINDOW (window));
1910 priv = window->priv;
1913 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1915 if (priv->default_widget != default_widget)
1917 GtkWidget *old_default_widget = NULL;
1920 g_object_ref (default_widget);
1922 if (priv->default_widget)
1924 old_default_widget = priv->default_widget;
1926 if (priv->focus_widget != priv->default_widget ||
1927 !gtk_widget_get_receives_default (priv->default_widget))
1928 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1930 gtk_widget_queue_draw (priv->default_widget);
1933 priv->default_widget = default_widget;
1935 if (priv->default_widget)
1937 if (priv->focus_widget == NULL ||
1938 !gtk_widget_get_receives_default (priv->focus_widget))
1939 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1941 gtk_widget_queue_draw (priv->default_widget);
1944 if (old_default_widget)
1945 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1949 g_object_notify (G_OBJECT (default_widget), "has-default");
1950 g_object_unref (default_widget);
1956 * gtk_window_get_default_widget:
1957 * @window: a #GtkWindow
1959 * Returns the default widget for @window. See gtk_window_set_default()
1962 * Returns: (transfer none): the default widget, or %NULL if there is none.
1967 gtk_window_get_default_widget (GtkWindow *window)
1969 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1971 return window->priv->default_widget;
1975 handle_keys_changed (gpointer data)
1977 GtkWindow *window = GTK_WINDOW (data);
1978 GtkWindowPrivate *priv = window->priv;
1980 if (priv->keys_changed_handler)
1982 g_source_remove (priv->keys_changed_handler);
1983 priv->keys_changed_handler = 0;
1986 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1992 gtk_window_notify_keys_changed (GtkWindow *window)
1994 GtkWindowPrivate *priv = window->priv;
1996 if (!priv->keys_changed_handler)
1997 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
2001 * gtk_window_add_accel_group:
2002 * @window: window to attach accelerator group to
2003 * @accel_group: a #GtkAccelGroup
2005 * Associate @accel_group with @window, such that calling
2006 * gtk_accel_groups_activate() on @window will activate accelerators
2010 gtk_window_add_accel_group (GtkWindow *window,
2011 GtkAccelGroup *accel_group)
2013 g_return_if_fail (GTK_IS_WINDOW (window));
2014 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2016 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
2017 g_signal_connect_object (accel_group, "accel-changed",
2018 G_CALLBACK (gtk_window_notify_keys_changed),
2019 window, G_CONNECT_SWAPPED);
2020 gtk_window_notify_keys_changed (window);
2024 * gtk_window_remove_accel_group:
2025 * @window: a #GtkWindow
2026 * @accel_group: a #GtkAccelGroup
2028 * Reverses the effects of gtk_window_add_accel_group().
2031 gtk_window_remove_accel_group (GtkWindow *window,
2032 GtkAccelGroup *accel_group)
2034 g_return_if_fail (GTK_IS_WINDOW (window));
2035 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2037 g_signal_handlers_disconnect_by_func (accel_group,
2038 gtk_window_notify_keys_changed,
2040 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2041 gtk_window_notify_keys_changed (window);
2044 static GtkMnemonicHash *
2045 gtk_window_get_mnemonic_hash (GtkWindow *window,
2048 GtkWindowPrivate *private = window->priv;
2050 if (!private->mnemonic_hash && create)
2051 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2053 return private->mnemonic_hash;
2057 * gtk_window_add_mnemonic:
2058 * @window: a #GtkWindow
2059 * @keyval: the mnemonic
2060 * @target: the widget that gets activated by the mnemonic
2062 * Adds a mnemonic to this window.
2065 gtk_window_add_mnemonic (GtkWindow *window,
2069 g_return_if_fail (GTK_IS_WINDOW (window));
2070 g_return_if_fail (GTK_IS_WIDGET (target));
2072 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2074 gtk_window_notify_keys_changed (window);
2078 * gtk_window_remove_mnemonic:
2079 * @window: a #GtkWindow
2080 * @keyval: the mnemonic
2081 * @target: the widget that gets activated by the mnemonic
2083 * Removes a mnemonic from this window.
2086 gtk_window_remove_mnemonic (GtkWindow *window,
2090 g_return_if_fail (GTK_IS_WINDOW (window));
2091 g_return_if_fail (GTK_IS_WIDGET (target));
2093 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2095 gtk_window_notify_keys_changed (window);
2099 * gtk_window_mnemonic_activate:
2100 * @window: a #GtkWindow
2101 * @keyval: the mnemonic
2102 * @modifier: the modifiers
2104 * Activates the targets associated with the mnemonic.
2106 * Returns: %TRUE if the activation is done.
2109 gtk_window_mnemonic_activate (GtkWindow *window,
2111 GdkModifierType modifier)
2113 GtkWindowPrivate *priv;
2115 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2117 priv = window->priv;
2119 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2121 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2123 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2130 * gtk_window_set_mnemonic_modifier:
2131 * @window: a #GtkWindow
2132 * @modifier: the modifier mask used to activate
2133 * mnemonics on this window.
2135 * Sets the mnemonic modifier for this window.
2138 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2139 GdkModifierType modifier)
2141 GtkWindowPrivate *priv;
2143 g_return_if_fail (GTK_IS_WINDOW (window));
2144 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2146 priv = window->priv;
2148 priv->mnemonic_modifier = modifier;
2149 gtk_window_notify_keys_changed (window);
2153 * gtk_window_get_mnemonic_modifier:
2154 * @window: a #GtkWindow
2156 * Returns the mnemonic modifier for this window. See
2157 * gtk_window_set_mnemonic_modifier().
2159 * Return value: the modifier mask used to activate
2160 * mnemonics on this window.
2163 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2165 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2167 return window->priv->mnemonic_modifier;
2171 * gtk_window_set_position:
2172 * @window: a #GtkWindow.
2173 * @position: a position constraint.
2175 * Sets a position constraint for this window. If the old or new
2176 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2177 * the window to be repositioned to satisfy the new constraint.
2180 gtk_window_set_position (GtkWindow *window,
2181 GtkWindowPosition position)
2183 GtkWindowPrivate *priv;
2185 g_return_if_fail (GTK_IS_WINDOW (window));
2187 priv = window->priv;
2189 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2190 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2192 GtkWindowGeometryInfo *info;
2194 info = gtk_window_get_geometry_info (window, TRUE);
2196 /* this flag causes us to re-request the CENTER_ALWAYS
2197 * constraint in gtk_window_move_resize(), see
2198 * comment in that function.
2200 info->position_constraints_changed = TRUE;
2202 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2205 priv->position = position;
2207 g_object_notify (G_OBJECT (window), "window-position");
2211 * gtk_window_activate_focus:
2212 * @window: a #GtkWindow
2214 * Activates the current focused widget within the window.
2216 * Return value: %TRUE if a widget got activated.
2219 gtk_window_activate_focus (GtkWindow *window)
2221 GtkWindowPrivate *priv;
2223 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2225 priv = window->priv;
2227 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2228 return gtk_widget_activate (priv->focus_widget);
2234 * gtk_window_get_focus:
2235 * @window: a #GtkWindow
2237 * Retrieves the current focused widget within the window.
2238 * Note that this is the widget that would have the focus
2239 * if the toplevel window focused; if the toplevel window
2240 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2241 * not be %TRUE for the widget.
2243 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2246 gtk_window_get_focus (GtkWindow *window)
2248 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2250 return window->priv->focus_widget;
2254 * gtk_window_activate_default:
2255 * @window: a #GtkWindow
2257 * Activates the default widget for the window, unless the current
2258 * focused widget has been configured to receive the default action
2259 * (see gtk_widget_set_receives_default()), in which case the
2260 * focused widget is activated.
2262 * Return value: %TRUE if a widget got activated.
2265 gtk_window_activate_default (GtkWindow *window)
2267 GtkWindowPrivate *priv;
2269 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2271 priv = window->priv;
2273 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2274 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2275 return gtk_widget_activate (priv->default_widget);
2276 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2277 return gtk_widget_activate (priv->focus_widget);
2283 * gtk_window_set_modal:
2284 * @window: a #GtkWindow
2285 * @modal: whether the window is modal
2287 * Sets a window modal or non-modal. Modal windows prevent interaction
2288 * with other windows in the same application. To keep modal dialogs
2289 * on top of main application windows, use
2290 * gtk_window_set_transient_for() to make the dialog transient for the
2291 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2292 * will then disallow lowering the dialog below the parent.
2297 gtk_window_set_modal (GtkWindow *window,
2300 GtkWindowPrivate *priv;
2303 g_return_if_fail (GTK_IS_WINDOW (window));
2305 priv = window->priv;
2307 modal = modal != FALSE;
2308 if (priv->modal == modal)
2311 priv->modal = modal;
2312 widget = GTK_WIDGET (window);
2314 /* adjust desired modality state */
2315 if (gtk_widget_get_realized (widget))
2318 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2320 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2323 if (gtk_widget_get_visible (widget))
2326 gtk_grab_add (widget);
2328 gtk_grab_remove (widget);
2331 g_object_notify (G_OBJECT (window), "modal");
2335 * gtk_window_get_modal:
2336 * @window: a #GtkWindow
2338 * Returns whether the window is modal. See gtk_window_set_modal().
2340 * Return value: %TRUE if the window is set to be modal and
2341 * establishes a grab when shown
2344 gtk_window_get_modal (GtkWindow *window)
2346 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2348 return window->priv->modal;
2352 * gtk_window_list_toplevels:
2354 * Returns a list of all existing toplevel windows. The widgets
2355 * in the list are not individually referenced. If you want
2356 * to iterate through the list and perform actions involving
2357 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2358 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2359 * then unref all the widgets afterwards.
2361 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2364 gtk_window_list_toplevels (void)
2369 for (slist = toplevel_list; slist; slist = slist->next)
2370 list = g_list_prepend (list, slist->data);
2376 remove_attach_widget (GtkWindow *window)
2378 GtkWindowPrivate *priv = window->priv;
2380 if (priv->attach_widget)
2382 _gtk_widget_remove_attached_window (priv->attach_widget, window);
2384 g_object_unref (priv->attach_widget);
2385 priv->attach_widget = NULL;
2390 gtk_window_dispose (GObject *object)
2392 GtkWindow *window = GTK_WINDOW (object);
2394 gtk_window_set_focus (window, NULL);
2395 gtk_window_set_default (window, NULL);
2397 remove_attach_widget (GTK_WINDOW (object));
2399 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2403 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2405 gtk_widget_destroy (GTK_WIDGET (child));
2409 connect_parent_destroyed (GtkWindow *window)
2411 GtkWindowPrivate *priv = window->priv;
2413 if (priv->transient_parent)
2415 g_signal_connect (priv->transient_parent,
2417 G_CALLBACK (parent_destroyed_callback),
2423 disconnect_parent_destroyed (GtkWindow *window)
2425 GtkWindowPrivate *priv = window->priv;
2427 if (priv->transient_parent)
2429 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2430 parent_destroyed_callback,
2436 gtk_window_transient_parent_realized (GtkWidget *parent,
2439 if (gtk_widget_get_realized (window))
2440 gdk_window_set_transient_for (gtk_widget_get_window (window),
2441 gtk_widget_get_window (parent));
2445 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2448 if (gtk_widget_get_realized (window))
2449 gdk_property_delete (gtk_widget_get_window (window),
2450 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2454 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2458 gtk_window_set_screen (window, parent->priv->screen);
2462 gtk_window_unset_transient_for (GtkWindow *window)
2464 GtkWindowPrivate *priv = window->priv;
2466 if (priv->transient_parent)
2468 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2469 gtk_window_transient_parent_realized,
2471 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2472 gtk_window_transient_parent_unrealized,
2474 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2475 gtk_window_transient_parent_screen_changed,
2477 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2478 gtk_widget_destroyed,
2479 &priv->transient_parent);
2481 if (priv->destroy_with_parent)
2482 disconnect_parent_destroyed (window);
2484 priv->transient_parent = NULL;
2486 if (priv->transient_parent_group)
2488 priv->transient_parent_group = FALSE;
2489 gtk_window_group_remove_window (priv->group,
2496 * gtk_window_set_transient_for:
2497 * @window: a #GtkWindow
2498 * @parent: (allow-none): parent window, or %NULL
2500 * Dialog windows should be set transient for the main application
2501 * window they were spawned from. This allows <link
2502 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2503 * dialog on top of the main window, or center the dialog over the
2504 * main window. gtk_dialog_new_with_buttons() and other convenience
2505 * functions in GTK+ will sometimes call
2506 * gtk_window_set_transient_for() on your behalf.
2508 * Passing %NULL for @parent unsets the current transient window.
2510 * On Windows, this function puts the child window on top of the parent,
2511 * much as the window manager would have done on X.
2514 gtk_window_set_transient_for (GtkWindow *window,
2517 GtkWindowPrivate *priv;
2519 g_return_if_fail (GTK_IS_WINDOW (window));
2520 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2521 g_return_if_fail (window != parent);
2523 priv = window->priv;
2525 if (priv->transient_parent)
2527 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2528 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2529 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2530 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2531 GTK_WIDGET (window));
2533 gtk_window_unset_transient_for (window);
2536 priv->transient_parent = parent;
2540 g_signal_connect (parent, "destroy",
2541 G_CALLBACK (gtk_widget_destroyed),
2542 &priv->transient_parent);
2543 g_signal_connect (parent, "realize",
2544 G_CALLBACK (gtk_window_transient_parent_realized),
2546 g_signal_connect (parent, "unrealize",
2547 G_CALLBACK (gtk_window_transient_parent_unrealized),
2549 g_signal_connect (parent, "notify::screen",
2550 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2553 gtk_window_set_screen (window, parent->priv->screen);
2555 if (priv->destroy_with_parent)
2556 connect_parent_destroyed (window);
2558 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2559 gtk_widget_get_realized (GTK_WIDGET (parent)))
2560 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2561 GTK_WIDGET (window));
2563 if (parent->priv->group)
2565 gtk_window_group_add_window (parent->priv->group, window);
2566 priv->transient_parent_group = TRUE;
2572 * gtk_window_get_transient_for:
2573 * @window: a #GtkWindow
2575 * Fetches the transient parent for this window. See
2576 * gtk_window_set_transient_for().
2578 * Return value: (transfer none): the transient parent for this window, or %NULL
2579 * if no transient parent has been set.
2582 gtk_window_get_transient_for (GtkWindow *window)
2584 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2586 return window->priv->transient_parent;
2590 * gtk_window_set_attached_to:
2591 * @window: a #GtkWindow
2592 * @attach_widget: (allow-none): a #GtkWidget, or %NULL
2594 * Marks @window as attached to @attach_widget. This creates a logical binding
2595 * between the window and the widget it belongs to, which is used by GTK+ to
2596 * propagate information such as styling or accessibility to @window as if it
2597 * was a children of @attach_widget.
2599 * Examples of places where specifying this relation is useful are for instance
2600 * a #GtkMenu created by a #GtkComboBox, a completion popup window
2601 * created by #GtkEntry or a typeahead search entry created by #GtkTreeView.
2603 * Note that this function should not be confused with
2604 * gtk_window_set_transient_for(), which specifies a window manager relation
2605 * between two toplevels instead.
2607 * Passing %NULL for @attach_widget detaches the window.
2612 gtk_window_set_attached_to (GtkWindow *window,
2613 GtkWidget *attach_widget)
2615 GtkStyleContext *context;
2616 GtkWindowPrivate *priv;
2618 g_return_if_fail (GTK_IS_WINDOW (window));
2619 g_return_if_fail (GTK_WIDGET (window) != attach_widget);
2621 priv = window->priv;
2623 if (priv->attach_widget == attach_widget)
2626 remove_attach_widget (window);
2628 priv->attach_widget = attach_widget;
2630 if (priv->attach_widget)
2632 _gtk_widget_add_attached_window (priv->attach_widget, window);
2634 g_object_ref (priv->attach_widget);
2637 /* Update the style, as the widget path might change. */
2638 context = gtk_widget_get_style_context (GTK_WIDGET (window));
2639 if (priv->attach_widget)
2640 gtk_style_context_set_parent (context, gtk_widget_get_style_context (priv->attach_widget));
2642 gtk_style_context_set_parent (context, NULL);
2646 * gtk_window_get_attached_to:
2647 * @window: a #GtkWindow
2649 * Fetches the attach widget for this window. See
2650 * gtk_window_set_attached_to().
2652 * Return value: (transfer none): the widget where the window is attached,
2653 * or %NULL if the window is not attached to any widget.
2658 gtk_window_get_attached_to (GtkWindow *window)
2660 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2662 return window->priv->attach_widget;
2666 * gtk_window_set_opacity:
2667 * @window: a #GtkWindow
2668 * @opacity: desired opacity, between 0 and 1
2670 * Request the windowing system to make @window partially transparent,
2671 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2672 * of the opacity parameter are clamped to the [0,1] range.) On X11
2673 * this has any effect only on X screens with a compositing manager
2674 * running. See gtk_widget_is_composited(). On Windows it should work
2677 * Note that setting a window's opacity after the window has been
2678 * shown causes it to flicker once on Windows.
2681 * Deprecated: 3.8: Use gtk_widget_set_opacity instead.
2684 gtk_window_set_opacity (GtkWindow *window,
2687 gtk_widget_set_opacity (GTK_WIDGET (window), opacity);
2691 * gtk_window_get_opacity:
2692 * @window: a #GtkWindow
2694 * Fetches the requested opacity for this window. See
2695 * gtk_window_set_opacity().
2697 * Return value: the requested opacity for this window.
2700 * Deprecated: 3.8: Use gtk_widget_get_opacity instead.
2703 gtk_window_get_opacity (GtkWindow *window)
2705 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2707 return gtk_widget_get_opacity (GTK_WIDGET (window));
2711 * gtk_window_get_application:
2712 * @window: a #GtkWindow
2714 * Gets the #GtkApplication associated with the window (if any).
2716 * Return value: (transfer none): a #GtkApplication, or %NULL
2721 gtk_window_get_application (GtkWindow *window)
2723 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2725 return window->priv->application;
2729 gtk_window_release_application (GtkWindow *window)
2731 if (window->priv->application)
2733 GtkApplication *application;
2735 /* steal reference into temp variable */
2736 application = window->priv->application;
2737 window->priv->application = NULL;
2739 gtk_application_remove_window (application, window);
2740 g_object_unref (application);
2745 * gtk_window_set_application:
2746 * @window: a #GtkWindow
2747 * @application: (allow-none): a #GtkApplication, or %NULL
2749 * Sets or unsets the #GtkApplication associated with the window.
2751 * The application will be kept alive for at least as long as the window
2757 gtk_window_set_application (GtkWindow *window,
2758 GtkApplication *application)
2760 GtkWindowPrivate *priv;
2762 g_return_if_fail (GTK_IS_WINDOW (window));
2764 priv = window->priv;
2765 if (priv->application != application)
2767 gtk_window_release_application (window);
2769 priv->application = application;
2771 if (priv->application != NULL)
2773 g_object_ref (priv->application);
2775 gtk_application_add_window (priv->application, window);
2778 /* don't use a normal cast: application may be NULL */
2779 gtk_widget_insert_action_group (GTK_WIDGET (window), "app", (GActionGroup *) application);
2781 g_object_notify (G_OBJECT (window), "application");
2786 * gtk_window_set_type_hint:
2787 * @window: a #GtkWindow
2788 * @hint: the window type
2790 * By setting the type hint for the window, you allow the window
2791 * manager to decorate and handle the window in a way which is
2792 * suitable to the function of the window in your application.
2794 * This function should be called before the window becomes visible.
2796 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2797 * will sometimes call gtk_window_set_type_hint() on your behalf.
2801 gtk_window_set_type_hint (GtkWindow *window,
2802 GdkWindowTypeHint hint)
2804 GtkWindowPrivate *priv;
2806 g_return_if_fail (GTK_IS_WINDOW (window));
2807 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2809 priv = window->priv;
2811 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2812 priv->type_hint = hint;
2814 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2816 priv->reset_type_hint = TRUE;
2817 priv->gdk_type_hint = hint;
2821 * gtk_window_get_type_hint:
2822 * @window: a #GtkWindow
2824 * Gets the type hint for this window. See gtk_window_set_type_hint().
2826 * Return value: the type hint for @window.
2829 gtk_window_get_type_hint (GtkWindow *window)
2831 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2833 return window->priv->gdk_type_hint;
2837 * gtk_window_set_skip_taskbar_hint:
2838 * @window: a #GtkWindow
2839 * @setting: %TRUE to keep this window from appearing in the task bar
2841 * Windows may set a hint asking the desktop environment not to display
2842 * the window in the task bar. This function sets this hint.
2847 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2850 GtkWindowPrivate *priv;
2852 g_return_if_fail (GTK_IS_WINDOW (window));
2854 priv = window->priv;
2856 setting = setting != FALSE;
2858 if (priv->skips_taskbar != setting)
2860 priv->skips_taskbar = setting;
2861 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2862 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2863 priv->skips_taskbar);
2864 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2869 * gtk_window_get_skip_taskbar_hint:
2870 * @window: a #GtkWindow
2872 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2874 * Return value: %TRUE if window shouldn't be in taskbar
2879 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2881 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2883 return window->priv->skips_taskbar;
2887 * gtk_window_set_skip_pager_hint:
2888 * @window: a #GtkWindow
2889 * @setting: %TRUE to keep this window from appearing in the pager
2891 * Windows may set a hint asking the desktop environment not to display
2892 * the window in the pager. This function sets this hint.
2893 * (A "pager" is any desktop navigation tool such as a workspace
2894 * switcher that displays a thumbnail representation of the windows
2900 gtk_window_set_skip_pager_hint (GtkWindow *window,
2903 GtkWindowPrivate *priv;
2905 g_return_if_fail (GTK_IS_WINDOW (window));
2907 priv = window->priv;
2909 setting = setting != FALSE;
2911 if (priv->skips_pager != setting)
2913 priv->skips_pager = setting;
2914 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2915 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2917 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2922 * gtk_window_get_skip_pager_hint:
2923 * @window: a #GtkWindow
2925 * Gets the value set by gtk_window_set_skip_pager_hint().
2927 * Return value: %TRUE if window shouldn't be in pager
2932 gtk_window_get_skip_pager_hint (GtkWindow *window)
2934 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2936 return window->priv->skips_pager;
2940 * gtk_window_set_urgency_hint:
2941 * @window: a #GtkWindow
2942 * @setting: %TRUE to mark this window as urgent
2944 * Windows may set a hint asking the desktop environment to draw
2945 * the users attention to the window. This function sets this hint.
2950 gtk_window_set_urgency_hint (GtkWindow *window,
2953 GtkWindowPrivate *priv;
2955 g_return_if_fail (GTK_IS_WINDOW (window));
2957 priv = window->priv;
2959 setting = setting != FALSE;
2961 if (priv->urgent != setting)
2963 priv->urgent = setting;
2964 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2965 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2967 g_object_notify (G_OBJECT (window), "urgency-hint");
2972 * gtk_window_get_urgency_hint:
2973 * @window: a #GtkWindow
2975 * Gets the value set by gtk_window_set_urgency_hint()
2977 * Return value: %TRUE if window is urgent
2982 gtk_window_get_urgency_hint (GtkWindow *window)
2984 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2986 return window->priv->urgent;
2990 * gtk_window_set_accept_focus:
2991 * @window: a #GtkWindow
2992 * @setting: %TRUE to let this window receive input focus
2994 * Windows may set a hint asking the desktop environment not to receive
2995 * the input focus. This function sets this hint.
3000 gtk_window_set_accept_focus (GtkWindow *window,
3003 GtkWindowPrivate *priv;
3005 g_return_if_fail (GTK_IS_WINDOW (window));
3007 priv = window->priv;
3009 setting = setting != FALSE;
3011 if (priv->accept_focus != setting)
3013 priv->accept_focus = setting;
3014 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3015 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
3016 priv->accept_focus);
3017 g_object_notify (G_OBJECT (window), "accept-focus");
3022 * gtk_window_get_accept_focus:
3023 * @window: a #GtkWindow
3025 * Gets the value set by gtk_window_set_accept_focus().
3027 * Return value: %TRUE if window should receive the input focus
3032 gtk_window_get_accept_focus (GtkWindow *window)
3034 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3036 return window->priv->accept_focus;
3040 * gtk_window_set_focus_on_map:
3041 * @window: a #GtkWindow
3042 * @setting: %TRUE to let this window receive input focus on map
3044 * Windows may set a hint asking the desktop environment not to receive
3045 * the input focus when the window is mapped. This function sets this
3051 gtk_window_set_focus_on_map (GtkWindow *window,
3054 GtkWindowPrivate *priv;
3056 g_return_if_fail (GTK_IS_WINDOW (window));
3058 priv = window->priv;
3060 setting = setting != FALSE;
3062 if (priv->focus_on_map != setting)
3064 priv->focus_on_map = setting;
3065 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3066 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
3067 priv->focus_on_map);
3068 g_object_notify (G_OBJECT (window), "focus-on-map");
3073 * gtk_window_get_focus_on_map:
3074 * @window: a #GtkWindow
3076 * Gets the value set by gtk_window_set_focus_on_map().
3078 * Return value: %TRUE if window should receive the input focus when
3084 gtk_window_get_focus_on_map (GtkWindow *window)
3086 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3088 return window->priv->focus_on_map;
3092 * gtk_window_set_destroy_with_parent:
3093 * @window: a #GtkWindow
3094 * @setting: whether to destroy @window with its transient parent
3096 * If @setting is %TRUE, then destroying the transient parent of @window
3097 * will also destroy @window itself. This is useful for dialogs that
3098 * shouldn't persist beyond the lifetime of the main window they're
3099 * associated with, for example.
3102 gtk_window_set_destroy_with_parent (GtkWindow *window,
3105 GtkWindowPrivate *priv;
3107 g_return_if_fail (GTK_IS_WINDOW (window));
3109 priv = window->priv;
3111 if (priv->destroy_with_parent == (setting != FALSE))
3114 if (priv->destroy_with_parent)
3116 disconnect_parent_destroyed (window);
3120 connect_parent_destroyed (window);
3123 priv->destroy_with_parent = setting;
3125 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3129 * gtk_window_get_destroy_with_parent:
3130 * @window: a #GtkWindow
3132 * Returns whether the window will be destroyed with its transient parent. See
3133 * gtk_window_set_destroy_with_parent ().
3135 * Return value: %TRUE if the window will be destroyed with its transient parent.
3138 gtk_window_get_destroy_with_parent (GtkWindow *window)
3140 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3142 return window->priv->destroy_with_parent;
3146 * gtk_window_set_hide_titlebar_when_maximized:
3147 * @window: a #GtkWindow
3148 * @setting: whether to hide the titlebar when @window is maximized
3150 * If @setting is %TRUE, then @window will request that it's titlebar
3151 * should be hidden when maximized.
3152 * This is useful for windows that don't convey any information other
3153 * than the application name in the titlebar, to put the available
3154 * screen space to better use. If the underlying window system does not
3155 * support the request, the setting will not have any effect.
3160 gtk_window_set_hide_titlebar_when_maximized (GtkWindow *window,
3163 g_return_if_fail (GTK_IS_WINDOW (window));
3165 #ifdef GDK_WINDOWING_X11
3167 GdkWindow *gdk_window;
3169 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3171 if (GDK_IS_X11_WINDOW (gdk_window))
3172 gdk_x11_window_set_hide_titlebar_when_maximized (gdk_window, setting);
3176 window->priv->hide_titlebar_when_maximized = setting;
3177 g_object_notify (G_OBJECT (window), "hide-titlebar-when-maximized");
3181 * gtk_window_get_hide_titlebar_when_maximized:
3182 * @window: a #GtkWindow
3184 * Returns whether the window has requested to have its titlebar hidden
3185 * when maximized. See gtk_window_set_hide_titlebar_when_maximized ().
3187 * Return value: %TRUE if the window has requested to have its titlebar
3188 * hidden when maximized
3193 gtk_window_get_hide_titlebar_when_maximized (GtkWindow *window)
3195 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3197 return window->priv->hide_titlebar_when_maximized;
3200 static GtkWindowGeometryInfo*
3201 gtk_window_get_geometry_info (GtkWindow *window,
3204 GtkWindowPrivate *priv = window->priv;
3205 GtkWindowGeometryInfo *info;
3207 info = priv->geometry_info;
3208 if (!info && create)
3210 info = g_new0 (GtkWindowGeometryInfo, 1);
3212 info->default_width = -1;
3213 info->default_height = -1;
3214 info->resize_width = -1;
3215 info->resize_height = -1;
3216 info->initial_x = 0;
3217 info->initial_y = 0;
3218 info->initial_pos_set = FALSE;
3219 info->default_is_geometry = FALSE;
3220 info->position_constraints_changed = FALSE;
3221 info->last.configure_request.x = 0;
3222 info->last.configure_request.y = 0;
3223 info->last.configure_request.width = -1;
3224 info->last.configure_request.height = -1;
3225 info->widget = NULL;
3227 priv->geometry_info = info;
3234 * gtk_window_set_geometry_hints:
3235 * @window: a #GtkWindow
3236 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3237 * @geometry: (allow-none): struct containing geometry information or %NULL
3238 * @geom_mask: mask indicating which struct fields should be paid attention to
3240 * This function sets up hints about how a window can be resized by
3241 * the user. You can set a minimum and maximum size; allowed resize
3242 * increments (e.g. for xterm, you can only resize by the size of a
3243 * character); aspect ratios; and more. See the #GdkGeometry struct.
3247 gtk_window_set_geometry_hints (GtkWindow *window,
3248 GtkWidget *geometry_widget,
3249 GdkGeometry *geometry,
3250 GdkWindowHints geom_mask)
3252 GtkWindowGeometryInfo *info;
3254 g_return_if_fail (GTK_IS_WINDOW (window));
3255 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3257 info = gtk_window_get_geometry_info (window, TRUE);
3260 g_signal_handlers_disconnect_by_func (info->widget,
3261 gtk_widget_destroyed,
3264 info->widget = geometry_widget;
3266 g_signal_connect (geometry_widget, "destroy",
3267 G_CALLBACK (gtk_widget_destroyed),
3271 info->geometry = *geometry;
3273 /* We store gravity in priv->gravity not in the hints. */
3274 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3276 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3278 gtk_window_set_gravity (window, geometry->win_gravity);
3281 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3285 * gtk_window_set_decorated:
3286 * @window: a #GtkWindow
3287 * @setting: %TRUE to decorate the window
3289 * By default, windows are decorated with a title bar, resize
3290 * controls, etc. Some <link linkend="gtk-X11-arch">window
3291 * managers</link> allow GTK+ to disable these decorations, creating a
3292 * borderless window. If you set the decorated property to %FALSE
3293 * using this function, GTK+ will do its best to convince the window
3294 * manager not to decorate the window. Depending on the system, this
3295 * function may not have any effect when called on a window that is
3296 * already visible, so you should call it before calling gtk_widget_show().
3298 * On Windows, this function always works, since there's no window manager
3303 gtk_window_set_decorated (GtkWindow *window,
3306 GtkWindowPrivate *priv;
3307 GdkWindow *gdk_window;
3309 g_return_if_fail (GTK_IS_WINDOW (window));
3311 priv = window->priv;
3313 setting = setting != FALSE;
3315 if (setting == priv->decorated)
3318 priv->decorated = setting;
3320 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3323 if (priv->decorated)
3324 gdk_window_set_decorations (gdk_window,
3327 gdk_window_set_decorations (gdk_window,
3331 g_object_notify (G_OBJECT (window), "decorated");
3335 * gtk_window_get_decorated:
3336 * @window: a #GtkWindow
3338 * Returns whether the window has been set to have decorations
3339 * such as a title bar via gtk_window_set_decorated().
3341 * Return value: %TRUE if the window has been set to have decorations
3344 gtk_window_get_decorated (GtkWindow *window)
3346 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3348 return window->priv->decorated;
3352 * gtk_window_set_deletable:
3353 * @window: a #GtkWindow
3354 * @setting: %TRUE to decorate the window as deletable
3356 * By default, windows have a close button in the window frame. Some
3357 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3358 * disable this button. If you set the deletable property to %FALSE
3359 * using this function, GTK+ will do its best to convince the window
3360 * manager not to show a close button. Depending on the system, this
3361 * function may not have any effect when called on a window that is
3362 * already visible, so you should call it before calling gtk_widget_show().
3364 * On Windows, this function always works, since there's no window manager
3370 gtk_window_set_deletable (GtkWindow *window,
3373 GtkWindowPrivate *priv;
3374 GdkWindow *gdk_window;
3376 g_return_if_fail (GTK_IS_WINDOW (window));
3378 priv = window->priv;
3380 setting = setting != FALSE;
3382 if (setting == priv->deletable)
3385 priv->deletable = setting;
3387 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3390 if (priv->deletable)
3391 gdk_window_set_functions (gdk_window,
3394 gdk_window_set_functions (gdk_window,
3395 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3398 g_object_notify (G_OBJECT (window), "deletable");
3402 * gtk_window_get_deletable:
3403 * @window: a #GtkWindow
3405 * Returns whether the window has been set to have a close button
3406 * via gtk_window_set_deletable().
3408 * Return value: %TRUE if the window has been set to have a close button
3413 gtk_window_get_deletable (GtkWindow *window)
3415 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3417 return window->priv->deletable;
3420 static GtkWindowIconInfo*
3421 get_icon_info (GtkWindow *window)
3423 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3427 free_icon_info (GtkWindowIconInfo *info)
3429 g_free (info->icon_name);
3430 g_slice_free (GtkWindowIconInfo, info);
3434 static GtkWindowIconInfo*
3435 ensure_icon_info (GtkWindow *window)
3437 GtkWindowIconInfo *info;
3439 info = get_icon_info (window);
3443 info = g_slice_new0 (GtkWindowIconInfo);
3444 g_object_set_qdata_full (G_OBJECT (window),
3445 quark_gtk_window_icon_info,
3447 (GDestroyNotify)free_icon_info);
3454 icon_list_from_theme (GtkWidget *widget,
3459 GtkIconTheme *icon_theme;
3464 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3466 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3469 for (i = 0; sizes[i]; i++)
3472 * We need an EWMH extension to handle scalable icons
3473 * by passing their name to the WM. For now just use a
3477 icon = gtk_icon_theme_load_icon (icon_theme, name,
3480 icon = gtk_icon_theme_load_icon (icon_theme, name,
3483 list = g_list_append (list, icon);
3493 gtk_window_realize_icon (GtkWindow *window)
3495 GtkWindowPrivate *priv = window->priv;
3497 GtkWindowIconInfo *info;
3498 GdkWindow *gdk_window;
3501 widget = GTK_WIDGET (window);
3502 gdk_window = gtk_widget_get_window (widget);
3504 g_return_if_fail (gdk_window != NULL);
3506 /* no point setting an icon on override-redirect */
3507 if (priv->type == GTK_WINDOW_POPUP)
3512 info = ensure_icon_info (window);
3517 info->using_default_icon = FALSE;
3518 info->using_parent_icon = FALSE;
3519 info->using_themed_icon = FALSE;
3521 icon_list = info->icon_list;
3523 /* Look up themed icon */
3524 if (icon_list == NULL && info->icon_name)
3526 icon_list = icon_list_from_theme (widget, info->icon_name);
3528 info->using_themed_icon = TRUE;
3531 /* Inherit from transient parent */
3532 if (icon_list == NULL && priv->transient_parent)
3534 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3536 info->using_parent_icon = TRUE;
3539 /* Inherit from default */
3540 if (icon_list == NULL)
3542 icon_list = default_icon_list;
3544 info->using_default_icon = TRUE;
3547 /* Look up themed icon */
3548 if (icon_list == NULL && default_icon_name)
3550 icon_list = icon_list_from_theme (widget, default_icon_name);
3551 info->using_default_icon = TRUE;
3552 info->using_themed_icon = TRUE;
3555 info->realized = TRUE;
3557 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3559 if (info->using_themed_icon)
3561 GtkIconTheme *icon_theme;
3563 g_list_free_full (icon_list, g_object_unref);
3565 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3566 g_signal_connect (icon_theme, "changed",
3567 G_CALLBACK (update_themed_icon), window);
3572 gtk_window_unrealize_icon (GtkWindow *window)
3574 GtkWindowIconInfo *info;
3576 info = get_icon_info (window);
3581 if (info->using_themed_icon)
3583 GtkIconTheme *icon_theme;
3585 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3587 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3590 /* We don't clear the properties on the window, just figure the
3591 * window is going away.
3594 info->realized = FALSE;
3599 * gtk_window_set_icon_list:
3600 * @window: a #GtkWindow
3601 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3603 * Sets up the icon representing a #GtkWindow. The icon is used when
3604 * the window is minimized (also known as iconified). Some window
3605 * managers or desktop environments may also place it in the window
3606 * frame, or display it in other contexts.
3608 * gtk_window_set_icon_list() allows you to pass in the same icon in
3609 * several hand-drawn sizes. The list should contain the natural sizes
3610 * your icon is available in; that is, don't scale the image before
3611 * passing it to GTK+. Scaling is postponed until the last minute,
3612 * when the desired final size is known, to allow best quality.
3614 * By passing several sizes, you may improve the final image quality
3615 * of the icon, by reducing or eliminating automatic image scaling.
3617 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3618 * larger images (64x64, 128x128) if you have them.
3620 * See also gtk_window_set_default_icon_list() to set the icon
3621 * for all windows in your application in one go.
3623 * Note that transient windows (those who have been set transient for another
3624 * window using gtk_window_set_transient_for()) will inherit their
3625 * icon from their transient parent. So there's no need to explicitly
3626 * set the icon on transient windows.
3629 gtk_window_set_icon_list (GtkWindow *window,
3632 GtkWindowIconInfo *info;
3634 g_return_if_fail (GTK_IS_WINDOW (window));
3636 info = ensure_icon_info (window);
3638 if (info->icon_list == list) /* check for NULL mostly */
3641 g_list_foreach (list,
3642 (GFunc) g_object_ref, NULL);
3644 g_list_free_full (info->icon_list, g_object_unref);
3646 info->icon_list = g_list_copy (list);
3648 g_object_notify (G_OBJECT (window), "icon");
3650 gtk_window_unrealize_icon (window);
3652 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3653 gtk_window_realize_icon (window);
3655 /* We could try to update our transient children, but I don't think
3656 * it's really worth it. If we did it, the best way would probably
3657 * be to have children connect to notify::icon-list
3662 * gtk_window_get_icon_list:
3663 * @window: a #GtkWindow
3665 * Retrieves the list of icons set by gtk_window_set_icon_list().
3666 * The list is copied, but the reference count on each
3667 * member won't be incremented.
3669 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3672 gtk_window_get_icon_list (GtkWindow *window)
3674 GtkWindowIconInfo *info;
3676 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3678 info = get_icon_info (window);
3681 return g_list_copy (info->icon_list);
3687 * gtk_window_set_icon:
3688 * @window: a #GtkWindow
3689 * @icon: (allow-none): icon image, or %NULL
3691 * Sets up the icon representing a #GtkWindow. This icon is used when
3692 * the window is minimized (also known as iconified). Some window
3693 * managers or desktop environments may also place it in the window
3694 * frame, or display it in other contexts.
3696 * The icon should be provided in whatever size it was naturally
3697 * drawn; that is, don't scale the image before passing it to
3698 * GTK+. Scaling is postponed until the last minute, when the desired
3699 * final size is known, to allow best quality.
3701 * If you have your icon hand-drawn in multiple sizes, use
3702 * gtk_window_set_icon_list(). Then the best size will be used.
3704 * This function is equivalent to calling gtk_window_set_icon_list()
3705 * with a 1-element list.
3707 * See also gtk_window_set_default_icon_list() to set the icon
3708 * for all windows in your application in one go.
3711 gtk_window_set_icon (GtkWindow *window,
3716 g_return_if_fail (GTK_IS_WINDOW (window));
3717 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3722 list = g_list_append (list, icon);
3724 gtk_window_set_icon_list (window, list);
3730 update_themed_icon (GtkIconTheme *icon_theme,
3733 g_object_notify (G_OBJECT (window), "icon");
3735 gtk_window_unrealize_icon (window);
3737 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3738 gtk_window_realize_icon (window);
3742 * gtk_window_set_icon_name:
3743 * @window: a #GtkWindow
3744 * @name: (allow-none): the name of the themed icon
3746 * Sets the icon for the window from a named themed icon. See
3747 * the docs for #GtkIconTheme for more details.
3749 * Note that this has nothing to do with the WM_ICON_NAME
3750 * property which is mentioned in the ICCCM.
3755 gtk_window_set_icon_name (GtkWindow *window,
3758 GtkWindowIconInfo *info;
3761 g_return_if_fail (GTK_IS_WINDOW (window));
3763 info = ensure_icon_info (window);
3765 if (g_strcmp0 (info->icon_name, name) == 0)
3768 tmp = info->icon_name;
3769 info->icon_name = g_strdup (name);
3772 g_list_free_full (info->icon_list, g_object_unref);
3773 info->icon_list = NULL;
3775 update_themed_icon (NULL, window);
3777 g_object_notify (G_OBJECT (window), "icon-name");
3781 * gtk_window_get_icon_name:
3782 * @window: a #GtkWindow
3784 * Returns the name of the themed icon for the window,
3785 * see gtk_window_set_icon_name().
3787 * Returns: the icon name or %NULL if the window has
3793 gtk_window_get_icon_name (GtkWindow *window)
3795 GtkWindowIconInfo *info;
3797 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3799 info = ensure_icon_info (window);
3801 return info->icon_name;
3805 * gtk_window_get_icon:
3806 * @window: a #GtkWindow
3808 * Gets the value set by gtk_window_set_icon() (or if you've
3809 * called gtk_window_set_icon_list(), gets the first icon in
3812 * Return value: (transfer none): icon for window
3815 gtk_window_get_icon (GtkWindow *window)
3817 GtkWindowIconInfo *info;
3819 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3821 info = get_icon_info (window);
3822 if (info && info->icon_list)
3823 return GDK_PIXBUF (info->icon_list->data);
3828 /* Load pixbuf, printing warning on failure if error == NULL
3831 load_pixbuf_verbosely (const char *filename,
3834 GError *local_err = NULL;
3837 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3845 g_warning ("Error loading icon from file '%s':\n\t%s",
3846 filename, local_err->message);
3847 g_error_free (local_err);
3855 * gtk_window_set_icon_from_file:
3856 * @window: a #GtkWindow
3857 * @filename: (type filename): location of icon file
3858 * @err: (allow-none): location to store error, or %NULL.
3860 * Sets the icon for @window.
3861 * Warns on failure if @err is %NULL.
3863 * This function is equivalent to calling gtk_window_set_icon()
3864 * with a pixbuf created by loading the image from @filename.
3866 * Returns: %TRUE if setting the icon succeeded.
3871 gtk_window_set_icon_from_file (GtkWindow *window,
3872 const gchar *filename,
3875 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3879 gtk_window_set_icon (window, pixbuf);
3880 g_object_unref (pixbuf);
3889 * gtk_window_set_default_icon_list:
3890 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3892 * Sets an icon list to be used as fallback for windows that haven't
3893 * had gtk_window_set_icon_list() called on them to set up a
3894 * window-specific icon list. This function allows you to set up the
3895 * icon for all windows in your app at once.
3897 * See gtk_window_set_icon_list() for more details.
3901 gtk_window_set_default_icon_list (GList *list)
3905 if (list == default_icon_list)
3908 /* Update serial so we don't used cached pixmaps/masks
3910 default_icon_serial++;
3912 g_list_foreach (list,
3913 (GFunc) g_object_ref, NULL);
3915 g_list_free_full (default_icon_list, g_object_unref);
3917 default_icon_list = g_list_copy (list);
3919 /* Update all toplevels */
3920 toplevels = gtk_window_list_toplevels ();
3921 tmp_list = toplevels;
3922 while (tmp_list != NULL)
3924 GtkWindowIconInfo *info;
3925 GtkWindow *w = tmp_list->data;
3927 info = get_icon_info (w);
3928 if (info && info->using_default_icon)
3930 gtk_window_unrealize_icon (w);
3931 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3932 gtk_window_realize_icon (w);
3935 tmp_list = tmp_list->next;
3937 g_list_free (toplevels);
3941 * gtk_window_set_default_icon:
3944 * Sets an icon to be used as fallback for windows that haven't
3945 * had gtk_window_set_icon() called on them from a pixbuf.
3950 gtk_window_set_default_icon (GdkPixbuf *icon)
3954 g_return_if_fail (GDK_IS_PIXBUF (icon));
3956 list = g_list_prepend (NULL, icon);
3957 gtk_window_set_default_icon_list (list);
3962 * gtk_window_set_default_icon_name:
3963 * @name: the name of the themed icon
3965 * Sets an icon to be used as fallback for windows that haven't
3966 * had gtk_window_set_icon_list() called on them from a named
3967 * themed icon, see gtk_window_set_icon_name().
3972 gtk_window_set_default_icon_name (const gchar *name)
3977 /* Update serial so we don't used cached pixmaps/masks
3979 default_icon_serial++;
3981 g_free (default_icon_name);
3982 default_icon_name = g_strdup (name);
3984 g_list_free_full (default_icon_list, g_object_unref);
3985 default_icon_list = NULL;
3987 /* Update all toplevels */
3988 toplevels = gtk_window_list_toplevels ();
3989 tmp_list = toplevels;
3990 while (tmp_list != NULL)
3992 GtkWindowIconInfo *info;
3993 GtkWindow *w = tmp_list->data;
3995 info = get_icon_info (w);
3996 if (info && info->using_default_icon && info->using_themed_icon)
3998 gtk_window_unrealize_icon (w);
3999 if (gtk_widget_get_realized (GTK_WIDGET (w)))
4000 gtk_window_realize_icon (w);
4003 tmp_list = tmp_list->next;
4005 g_list_free (toplevels);
4009 * gtk_window_get_default_icon_name:
4011 * Returns the fallback icon name for windows that has been set
4012 * with gtk_window_set_default_icon_name(). The returned
4013 * string is owned by GTK+ and should not be modified. It
4014 * is only valid until the next call to
4015 * gtk_window_set_default_icon_name().
4017 * Returns: the fallback icon name for windows
4022 gtk_window_get_default_icon_name (void)
4024 return default_icon_name;
4028 * gtk_window_set_default_icon_from_file:
4029 * @filename: (type filename): location of icon file
4030 * @err: (allow-none): location to store error, or %NULL.
4032 * Sets an icon to be used as fallback for windows that haven't
4033 * had gtk_window_set_icon_list() called on them from a file
4034 * on disk. Warns on failure if @err is %NULL.
4036 * Returns: %TRUE if setting the icon succeeded.
4041 gtk_window_set_default_icon_from_file (const gchar *filename,
4044 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
4048 gtk_window_set_default_icon (pixbuf);
4049 g_object_unref (pixbuf);
4058 * gtk_window_get_default_icon_list:
4060 * Gets the value set by gtk_window_set_default_icon_list().
4061 * The list is a copy and should be freed with g_list_free(),
4062 * but the pixbufs in the list have not had their reference count
4065 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
4068 gtk_window_get_default_icon_list (void)
4070 return g_list_copy (default_icon_list);
4074 gtk_window_set_default_size_internal (GtkWindow *window,
4075 gboolean change_width,
4077 gboolean change_height,
4079 gboolean is_geometry)
4081 GtkWindowGeometryInfo *info;
4083 g_return_if_fail (change_width == FALSE || width >= -1);
4084 g_return_if_fail (change_height == FALSE || height >= -1);
4086 info = gtk_window_get_geometry_info (window, TRUE);
4088 g_object_freeze_notify (G_OBJECT (window));
4090 info->default_is_geometry = is_geometry != FALSE;
4100 info->default_width = width;
4102 g_object_notify (G_OBJECT (window), "default-width");
4113 info->default_height = height;
4115 g_object_notify (G_OBJECT (window), "default-height");
4118 g_object_thaw_notify (G_OBJECT (window));
4120 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4124 * gtk_window_set_default_size:
4125 * @window: a #GtkWindow
4126 * @width: width in pixels, or -1 to unset the default width
4127 * @height: height in pixels, or -1 to unset the default height
4129 * Sets the default size of a window. If the window's "natural" size
4130 * (its size request) is larger than the default, the default will be
4131 * ignored. More generally, if the default size does not obey the
4132 * geometry hints for the window (gtk_window_set_geometry_hints() can
4133 * be used to set these explicitly), the default size will be clamped
4134 * to the nearest permitted size.
4136 * Unlike gtk_widget_set_size_request(), which sets a size request for
4137 * a widget and thus would keep users from shrinking the window, this
4138 * function only sets the initial size, just as if the user had
4139 * resized the window themselves. Users can still shrink the window
4140 * again as they normally would. Setting a default size of -1 means to
4141 * use the "natural" default size (the size request of the window).
4143 * For more control over a window's initial size and how resizing works,
4144 * investigate gtk_window_set_geometry_hints().
4146 * For some uses, gtk_window_resize() is a more appropriate function.
4147 * gtk_window_resize() changes the current size of the window, rather
4148 * than the size to be used on initial display. gtk_window_resize() always
4149 * affects the window itself, not the geometry widget.
4151 * The default size of a window only affects the first time a window is
4152 * shown; if a window is hidden and re-shown, it will remember the size
4153 * it had prior to hiding, rather than using the default size.
4155 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4156 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4159 gtk_window_set_default_size (GtkWindow *window,
4163 g_return_if_fail (GTK_IS_WINDOW (window));
4164 g_return_if_fail (width >= -1);
4165 g_return_if_fail (height >= -1);
4167 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4171 * gtk_window_set_default_geometry:
4172 * @window: a #GtkWindow
4173 * @width: width in resize increments, or -1 to unset the default width
4174 * @height: height in resize increments, or -1 to unset the default height
4176 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4177 * in terms of the base size and increment set with
4178 * gtk_window_set_geometry_hints.
4183 gtk_window_set_default_geometry (GtkWindow *window,
4187 g_return_if_fail (GTK_IS_WINDOW (window));
4188 g_return_if_fail (width >= -1);
4189 g_return_if_fail (height >= -1);
4191 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4195 * gtk_window_get_default_size:
4196 * @window: a #GtkWindow
4197 * @width: (out) (allow-none): location to store the default width, or %NULL
4198 * @height: (out) (allow-none): location to store the default height, or %NULL
4200 * Gets the default size of the window. A value of -1 for the width or
4201 * height indicates that a default size has not been explicitly set
4202 * for that dimension, so the "natural" size of the window will be
4207 gtk_window_get_default_size (GtkWindow *window,
4211 GtkWindowGeometryInfo *info;
4213 g_return_if_fail (GTK_IS_WINDOW (window));
4215 info = gtk_window_get_geometry_info (window, FALSE);
4218 *width = info ? info->default_width : -1;
4221 *height = info ? info->default_height : -1;
4225 * gtk_window_resize:
4226 * @window: a #GtkWindow
4227 * @width: width in pixels to resize the window to
4228 * @height: height in pixels to resize the window to
4230 * Resizes the window as if the user had done so, obeying geometry
4231 * constraints. The default geometry constraint is that windows may
4232 * not be smaller than their size request; to override this
4233 * constraint, call gtk_widget_set_size_request() to set the window's
4234 * request to a smaller value.
4236 * If gtk_window_resize() is called before showing a window for the
4237 * first time, it overrides any default size set with
4238 * gtk_window_set_default_size().
4240 * Windows may not be resized smaller than 1 by 1 pixels.
4244 gtk_window_resize (GtkWindow *window,
4248 GtkWindowGeometryInfo *info;
4250 g_return_if_fail (GTK_IS_WINDOW (window));
4251 g_return_if_fail (width > 0);
4252 g_return_if_fail (height > 0);
4254 info = gtk_window_get_geometry_info (window, TRUE);
4256 info->resize_width = width;
4257 info->resize_height = height;
4258 info->resize_is_geometry = FALSE;
4260 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4264 * gtk_window_resize_to_geometry:
4265 * @window: a #GtkWindow
4266 * @width: width in resize increments to resize the window to
4267 * @height: height in resize increments to resize the window to
4269 * Like gtk_window_resize(), but @width and @height are interpreted
4270 * in terms of the base size and increment set with
4271 * gtk_window_set_geometry_hints.
4276 gtk_window_resize_to_geometry (GtkWindow *window,
4280 GtkWindowGeometryInfo *info;
4282 g_return_if_fail (GTK_IS_WINDOW (window));
4283 g_return_if_fail (width > 0);
4284 g_return_if_fail (height > 0);
4286 info = gtk_window_get_geometry_info (window, TRUE);
4288 info->resize_width = width;
4289 info->resize_height = height;
4290 info->resize_is_geometry = TRUE;
4292 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4296 * gtk_window_get_size:
4297 * @window: a #GtkWindow
4298 * @width: (out) (allow-none): return location for width, or %NULL
4299 * @height: (out) (allow-none): return location for height, or %NULL
4301 * Obtains the current size of @window. If @window is not onscreen,
4302 * it returns the size GTK+ will suggest to the <link
4303 * linkend="gtk-X11-arch">window manager</link> for the initial window
4304 * size (but this is not reliably the same as the size the window
4305 * manager will actually select). The size obtained by
4306 * gtk_window_get_size() is the last size received in a
4307 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4308 * rather than querying the X server for the size. As a result, if you
4309 * call gtk_window_resize() then immediately call
4310 * gtk_window_get_size(), the size won't have taken effect yet. After
4311 * the window manager processes the resize request, GTK+ receives
4312 * notification that the size has changed via a configure event, and
4313 * the size of the window gets updated.
4315 * Note 1: Nearly any use of this function creates a race condition,
4316 * because the size of the window may change between the time that you
4317 * get the size and the time that you perform some action assuming
4318 * that size is the current size. To avoid race conditions, connect to
4319 * "configure-event" on the window and adjust your size-dependent
4320 * state to match the size delivered in the #GdkEventConfigure.
4322 * Note 2: The returned size does <emphasis>not</emphasis> include the
4323 * size of the window manager decorations (aka the window frame or
4324 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4325 * method of determining their size.
4327 * Note 3: If you are getting a window size in order to position
4328 * the window onscreen, there may be a better way. The preferred
4329 * way is to simply set the window's semantic type with
4330 * gtk_window_set_type_hint(), which allows the window manager to
4331 * e.g. center dialogs. Also, if you set the transient parent of
4332 * dialogs with gtk_window_set_transient_for() window managers
4333 * will often center the dialog over its parent window. It's
4334 * much preferred to let the window manager handle these
4335 * things rather than doing it yourself, because all apps will
4336 * behave consistently and according to user prefs if the window
4337 * manager handles it. Also, the window manager can take the size
4338 * of the window decorations/border into account, while your
4339 * application cannot.
4341 * In any case, if you insist on application-specified window
4342 * positioning, there's <emphasis>still</emphasis> a better way than
4343 * doing it yourself - gtk_window_set_position() will frequently
4344 * handle the details for you.
4348 gtk_window_get_size (GtkWindow *window,
4354 g_return_if_fail (GTK_IS_WINDOW (window));
4356 if (width == NULL && height == NULL)
4359 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4361 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4362 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4366 GdkRectangle configure_request;
4368 gtk_window_compute_configure_request (window,
4372 w = configure_request.width;
4373 h = configure_request.height;
4384 * @window: a #GtkWindow
4385 * @x: X coordinate to move window to
4386 * @y: Y coordinate to move window to
4388 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4389 * @window to the given position. Window managers are free to ignore
4390 * this; most window managers ignore requests for initial window
4391 * positions (instead using a user-defined placement algorithm) and
4392 * honor requests after the window has already been shown.
4394 * Note: the position is the position of the gravity-determined
4395 * reference point for the window. The gravity determines two things:
4396 * first, the location of the reference point in root window
4397 * coordinates; and second, which point on the window is positioned at
4398 * the reference point.
4400 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4401 * point is simply the @x, @y supplied to gtk_window_move(). The
4402 * top-left corner of the window decorations (aka window frame or
4403 * border) will be placed at @x, @y. Therefore, to position a window
4404 * at the top left of the screen, you want to use the default gravity
4405 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4407 * To position a window at the bottom right corner of the screen, you
4408 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4409 * point is at @x + the window width and @y + the window height, and
4410 * the bottom-right corner of the window border will be placed at that
4411 * reference point. So, to place a window in the bottom right corner
4412 * you would first set gravity to south east, then write:
4413 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4414 * gdk_screen_height () - window_height)</literal> (note that this
4415 * example does not take multi-head scenarios into account).
4417 * The Extended Window Manager Hints specification at <ulink
4418 * url="http://www.freedesktop.org/Standards/wm-spec">
4419 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4420 * nice table of gravities in the "implementation notes" section.
4422 * The gtk_window_get_position() documentation may also be relevant.
4425 gtk_window_move (GtkWindow *window,
4429 GtkWindowGeometryInfo *info;
4432 g_return_if_fail (GTK_IS_WINDOW (window));
4434 widget = GTK_WIDGET (window);
4436 info = gtk_window_get_geometry_info (window, TRUE);
4438 if (gtk_widget_get_mapped (widget))
4440 GtkAllocation allocation;
4442 gtk_widget_get_allocation (widget, &allocation);
4444 /* we have now sent a request with this position
4445 * with currently-active constraints, so toggle flag.
4447 info->position_constraints_changed = FALSE;
4449 /* we only constrain if mapped - if not mapped,
4450 * then gtk_window_compute_configure_request()
4451 * will apply the constraints later, and we
4452 * don't want to lose information about
4453 * what position the user set before then.
4454 * i.e. if you do a move() then turn off POS_CENTER
4455 * then show the window, your move() will work.
4457 gtk_window_constrain_position (window,
4458 allocation.width, allocation.height,
4461 /* Note that this request doesn't go through our standard request
4462 * framework, e.g. doesn't increment configure_request_count,
4463 * doesn't set info->last, etc.; that's because
4464 * we don't save the info needed to arrive at this same request
4467 * To gtk_window_move_resize(), this will end up looking exactly
4468 * the same as the position being changed by the window
4471 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4475 /* Save this position to apply on mapping */
4476 info->initial_x = x;
4477 info->initial_y = y;
4478 info->initial_pos_set = TRUE;
4483 * gtk_window_get_position:
4484 * @window: a #GtkWindow
4485 * @root_x: (out) (allow-none): return location for X coordinate of
4486 * gravity-determined reference point, or %NULL
4487 * @root_y: (out) (allow-none): return location for Y coordinate of
4488 * gravity-determined reference point, or %NULL
4490 * This function returns the position you need to pass to
4491 * gtk_window_move() to keep @window in its current position.
4492 * This means that the meaning of the returned value varies with
4493 * window gravity. See gtk_window_move() for more details.
4495 * If you haven't changed the window gravity, its gravity will be
4496 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4497 * gets the position of the top-left corner of the window manager
4498 * frame for the window. gtk_window_move() sets the position of this
4499 * same top-left corner.
4501 * gtk_window_get_position() is not 100% reliable because the X Window System
4502 * does not specify a way to obtain the geometry of the
4503 * decorations placed on a window by the window manager.
4504 * Thus GTK+ is using a "best guess" that works with most
4507 * Moreover, nearly all window managers are historically broken with
4508 * respect to their handling of window gravity. So moving a window to
4509 * its current position as returned by gtk_window_get_position() tends
4510 * to result in moving the window slightly. Window managers are
4511 * slowly getting better over time.
4513 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4514 * frame is not relevant, and thus gtk_window_get_position() will
4515 * always produce accurate results. However you can't use static
4516 * gravity to do things like place a window in a corner of the screen,
4517 * because static gravity ignores the window manager decorations.
4519 * If you are saving and restoring your application's window
4520 * positions, you should know that it's impossible for applications to
4521 * do this without getting it somewhat wrong because applications do
4522 * not have sufficient knowledge of window manager state. The Correct
4523 * Mechanism is to support the session management protocol (see the
4524 * "GnomeClient" object in the GNOME libraries for example) and allow
4525 * the window manager to save your window sizes and positions.
4530 gtk_window_get_position (GtkWindow *window,
4534 GtkWindowPrivate *priv;
4536 GdkWindow *gdk_window;
4538 g_return_if_fail (GTK_IS_WINDOW (window));
4540 priv = window->priv;
4541 widget = GTK_WIDGET (window);
4542 gdk_window = gtk_widget_get_window (widget);
4544 if (priv->gravity == GDK_GRAVITY_STATIC)
4546 if (gtk_widget_get_mapped (widget))
4548 /* This does a server round-trip, which is sort of wrong;
4549 * but a server round-trip is inevitable for
4550 * gdk_window_get_frame_extents() in the usual
4551 * NorthWestGravity case below, so not sure what else to
4552 * do. We should likely be consistent about whether we get
4553 * the client-side info or the server-side info.
4555 gdk_window_get_origin (gdk_window, root_x, root_y);
4559 GdkRectangle configure_request;
4561 gtk_window_compute_configure_request (window,
4565 *root_x = configure_request.x;
4566 *root_y = configure_request.y;
4571 GdkRectangle frame_extents;
4576 if (gtk_widget_get_mapped (widget))
4578 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4579 x = frame_extents.x;
4580 y = frame_extents.y;
4581 gtk_window_get_size (window, &w, &h);
4585 /* We just say the frame has 0 size on all sides.
4586 * Not sure what else to do.
4588 gtk_window_compute_configure_request (window,
4591 x = frame_extents.x;
4592 y = frame_extents.y;
4593 w = frame_extents.width;
4594 h = frame_extents.height;
4597 switch (priv->gravity)
4599 case GDK_GRAVITY_NORTH:
4600 case GDK_GRAVITY_CENTER:
4601 case GDK_GRAVITY_SOUTH:
4602 /* Find center of frame. */
4603 x += frame_extents.width / 2;
4604 /* Center client window on that point. */
4608 case GDK_GRAVITY_SOUTH_EAST:
4609 case GDK_GRAVITY_EAST:
4610 case GDK_GRAVITY_NORTH_EAST:
4611 /* Find right edge of frame */
4612 x += frame_extents.width;
4613 /* Align left edge of client at that point. */
4620 switch (priv->gravity)
4622 case GDK_GRAVITY_WEST:
4623 case GDK_GRAVITY_CENTER:
4624 case GDK_GRAVITY_EAST:
4625 /* Find center of frame. */
4626 y += frame_extents.height / 2;
4627 /* Center client window there. */
4630 case GDK_GRAVITY_SOUTH_WEST:
4631 case GDK_GRAVITY_SOUTH:
4632 case GDK_GRAVITY_SOUTH_EAST:
4633 /* Find south edge of frame */
4634 y += frame_extents.height;
4635 /* Place bottom edge of client there */
4650 * gtk_window_reshow_with_initial_size:
4651 * @window: a #GtkWindow
4653 * Hides @window, then reshows it, resetting the
4654 * default size and position of the window. Used
4655 * by GUI builders only.
4658 gtk_window_reshow_with_initial_size (GtkWindow *window)
4662 g_return_if_fail (GTK_IS_WINDOW (window));
4664 widget = GTK_WIDGET (window);
4666 gtk_widget_hide (widget);
4667 gtk_widget_unrealize (widget);
4668 gtk_widget_show (widget);
4672 gtk_window_destroy (GtkWidget *widget)
4674 GtkWindow *window = GTK_WINDOW (widget);
4675 GtkWindowPrivate *priv = window->priv;
4677 gtk_window_release_application (window);
4679 toplevel_list = g_slist_remove (toplevel_list, window);
4681 if (priv->transient_parent)
4682 gtk_window_set_transient_for (window, NULL);
4684 remove_attach_widget (GTK_WINDOW (widget));
4686 /* frees the icons */
4687 gtk_window_set_icon_list (window, NULL);
4689 if (priv->has_user_ref_count)
4691 priv->has_user_ref_count = FALSE;
4692 g_object_unref (window);
4696 gtk_window_group_remove_window (priv->group, window);
4698 gtk_window_free_key_hash (window);
4700 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4704 gtk_window_finalize (GObject *object)
4706 GtkWindow *window = GTK_WINDOW (object);
4707 GtkWindowPrivate *priv = window->priv;
4708 GtkMnemonicHash *mnemonic_hash;
4710 g_free (priv->title);
4711 g_free (priv->wmclass_name);
4712 g_free (priv->wmclass_class);
4713 g_free (priv->wm_role);
4714 gtk_window_release_application (window);
4716 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4718 _gtk_mnemonic_hash_free (mnemonic_hash);
4720 if (priv->geometry_info)
4722 if (priv->geometry_info->widget)
4723 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4724 gtk_widget_destroyed,
4725 &priv->geometry_info->widget);
4726 g_free (priv->geometry_info);
4729 if (priv->keys_changed_handler)
4731 g_source_remove (priv->keys_changed_handler);
4732 priv->keys_changed_handler = 0;
4736 g_signal_handlers_disconnect_by_func (priv->screen,
4737 gtk_window_on_composited_changed, window);
4739 g_free (priv->startup_id);
4741 if (priv->auto_mnemonics_timeout_id)
4743 g_source_remove (priv->auto_mnemonics_timeout_id);
4744 priv->auto_mnemonics_timeout_id = 0;
4747 #ifdef GDK_WINDOWING_X11
4748 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4749 gtk_window_on_theme_variant_changed,
4753 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4757 gtk_window_show (GtkWidget *widget)
4759 GtkWindow *window = GTK_WINDOW (widget);
4760 GtkWindowPrivate *priv = window->priv;
4761 GtkContainer *container = GTK_CONTAINER (window);
4763 gboolean need_resize;
4766 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4768 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4772 _gtk_widget_set_visible_flag (widget, TRUE);
4774 need_resize = _gtk_widget_get_alloc_needed (widget) || !gtk_widget_get_realized (widget);
4776 empty = _gtk_bitmask_new ();
4777 _gtk_style_context_validate (gtk_widget_get_style_context (widget),
4778 g_get_monotonic_time (),
4781 _gtk_bitmask_free (empty);
4785 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4786 GtkAllocation allocation = { 0, 0 };
4787 GdkRectangle configure_request;
4788 GdkGeometry new_geometry;
4790 gboolean was_realized;
4792 /* We are going to go ahead and perform this configure request
4793 * and then emulate a configure notify by going ahead and
4794 * doing a size allocate. Sort of a synchronous
4795 * mini-copy of gtk_window_move_resize() here.
4797 gtk_window_compute_configure_request (window,
4802 /* We update this because we are going to go ahead
4803 * and gdk_window_resize() below, rather than
4806 info->last.configure_request.width = configure_request.width;
4807 info->last.configure_request.height = configure_request.height;
4809 /* and allocate the window - this is normally done
4810 * in move_resize in response to configure notify
4812 allocation.width = configure_request.width;
4813 allocation.height = configure_request.height;
4814 gtk_widget_size_allocate (widget, &allocation);
4816 /* Then we guarantee we have a realize */
4817 was_realized = FALSE;
4818 if (!gtk_widget_get_realized (widget))
4820 gtk_widget_realize (widget);
4821 was_realized = TRUE;
4824 /* We only send configure request if we didn't just finish
4825 * creating the window; if we just created the window
4826 * then we created it with widget->allocation anyhow.
4829 gdk_window_move_resize (gtk_widget_get_window (widget),
4830 configure_request.x,
4831 configure_request.y,
4832 configure_request.width,
4833 configure_request.height);
4836 gtk_container_check_resize (container);
4838 gtk_widget_map (widget);
4840 /* Try to make sure that we have some focused widget
4842 #ifdef GDK_WINDOWING_X11
4843 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4844 GTK_IS_PLUG (window);
4848 if (!priv->focus_widget && !is_plug)
4849 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4852 gtk_grab_add (widget);
4856 gtk_window_hide (GtkWidget *widget)
4858 GtkWindow *window = GTK_WINDOW (widget);
4859 GtkWindowPrivate *priv = window->priv;
4861 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4863 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4867 _gtk_widget_set_visible_flag (widget, FALSE);
4868 gtk_widget_unmap (widget);
4871 gtk_grab_remove (widget);
4875 gtk_window_map (GtkWidget *widget)
4878 GtkWindow *window = GTK_WINDOW (widget);
4879 GtkWindowPrivate *priv = window->priv;
4880 GdkWindow *gdk_window;
4881 gboolean auto_mnemonics;
4882 GtkPolicyType visible_focus;
4884 if (!gtk_widget_is_toplevel (widget))
4886 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4890 gtk_widget_set_mapped (widget, TRUE);
4892 child = gtk_bin_get_child (&(window->bin));
4894 gtk_widget_get_visible (child) &&
4895 !gtk_widget_get_mapped (child))
4896 gtk_widget_map (child);
4898 gdk_window = gtk_widget_get_window (widget);
4900 if (priv->maximize_initially)
4901 gdk_window_maximize (gdk_window);
4903 gdk_window_unmaximize (gdk_window);
4905 if (priv->stick_initially)
4906 gdk_window_stick (gdk_window);
4908 gdk_window_unstick (gdk_window);
4910 if (priv->iconify_initially)
4911 gdk_window_iconify (gdk_window);
4913 gdk_window_deiconify (gdk_window);
4915 if (priv->fullscreen_initially)
4916 gdk_window_fullscreen (gdk_window);
4918 gdk_window_unfullscreen (gdk_window);
4920 gdk_window_set_keep_above (gdk_window, priv->above_initially);
4922 gdk_window_set_keep_below (gdk_window, priv->below_initially);
4924 if (priv->type == GTK_WINDOW_TOPLEVEL)
4926 gtk_window_set_theme_variant (window);
4927 gtk_window_set_hide_titlebar_when_maximized (window,
4928 priv->hide_titlebar_when_maximized);
4931 /* No longer use the default settings */
4932 priv->need_default_size = FALSE;
4933 priv->need_default_position = FALSE;
4935 if (priv->reset_type_hint)
4937 /* We should only reset the type hint when the application
4938 * used gtk_window_set_type_hint() to change the hint.
4939 * Some applications use X directly to change the properties;
4940 * in that case, we shouldn't overwrite what they did.
4942 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4943 priv->reset_type_hint = FALSE;
4946 gdk_window_show (gdk_window);
4948 if (priv->grip_window)
4949 gdk_window_show (priv->grip_window);
4951 if (!disable_startup_notification)
4953 /* Do we have a custom startup-notification id? */
4954 if (priv->startup_id != NULL)
4956 /* Make sure we have a "real" id */
4957 if (!startup_id_is_fake (priv->startup_id))
4958 gdk_notify_startup_complete_with_id (priv->startup_id);
4960 g_free (priv->startup_id);
4961 priv->startup_id = NULL;
4963 else if (!sent_startup_notification)
4965 sent_startup_notification = TRUE;
4966 gdk_notify_startup_complete ();
4970 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4971 * (as in the case of popup menus), then hide mnemonics initially
4973 g_object_get (gtk_widget_get_settings (widget),
4974 "gtk-auto-mnemonics", &auto_mnemonics,
4975 "gtk-visible-focus", &visible_focus,
4978 if (auto_mnemonics && !priv->mnemonics_visible_set)
4979 gtk_window_set_mnemonics_visible (window, FALSE);
4981 /* inherit from transient parent, so that a dialog that is
4982 * opened via keynav shows focus initially
4984 if (priv->transient_parent)
4985 gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
4987 gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
4991 gtk_window_map_event (GtkWidget *widget,
4994 if (!gtk_widget_get_mapped (widget))
4996 /* we should be be unmapped, but are getting a MapEvent, this may happen
4997 * to toplevel XWindows if mapping was intercepted by a window manager
4998 * and an unmap request occoured while the MapRequestEvent was still
4999 * being handled. we work around this situaiton here by re-requesting
5000 * the window being unmapped. more details can be found in:
5001 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
5003 gdk_window_hide (gtk_widget_get_window (widget));
5009 gtk_window_unmap (GtkWidget *widget)
5011 GtkWindow *window = GTK_WINDOW (widget);
5012 GtkWindowPrivate *priv = window->priv;
5014 GtkWindowGeometryInfo *info;
5015 GdkWindow *gdk_window;
5016 GdkWindowState state;
5018 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5020 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
5024 gdk_window = gtk_widget_get_window (widget);
5026 gtk_widget_set_mapped (widget, FALSE);
5027 gdk_window_withdraw (gdk_window);
5029 priv->configure_request_count = 0;
5030 priv->configure_notify_received = FALSE;
5032 /* on unmap, we reset the default positioning of the window,
5033 * so it's placed again, but we don't reset the default
5034 * size of the window, so it's remembered.
5036 priv->need_default_position = TRUE;
5038 info = gtk_window_get_geometry_info (window, FALSE);
5041 info->initial_pos_set = FALSE;
5042 info->position_constraints_changed = FALSE;
5045 state = gdk_window_get_state (gdk_window);
5046 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
5047 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
5048 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
5049 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
5050 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
5052 child = gtk_bin_get_child (&(window->bin));
5054 gtk_widget_unmap (child);
5057 /* (Note: Replace "size" with "width" or "height". Also, the request
5058 * mode is honoured.)
5059 * For selecting the default window size, the following conditions
5060 * should hold (in order of importance):
5061 * - the size is not below the minimum size
5062 * Windows cannot be resized below their minimum size, so we must
5063 * ensure we don't do that either.
5064 * - the size is not above the natural size
5065 * It seems weird to allocate more than this in an initial guess.
5066 * - the size does not exceed that of a maximized window
5067 * We want to see the whole window after all.
5068 * (Note that this may not be possible to achieve due to imperfect
5069 * information from the windowing system.)
5072 /* We use these for now to not make windows too big by accident. Note
5073 * that we still clamp these numbers by screen size. Also note that
5074 * minimum size still overrides this. So keep your windows small! :)
5076 #define MAX_DEFAULT_WINDOW_WIDTH 640
5077 #define MAX_DEFAULT_WINDOW_HEIGHT 480
5080 gtk_window_guess_default_size (GtkWindow *window,
5084 GtkWidget *widget = GTK_WIDGET (window);
5086 int minimum, natural;
5088 screen = gtk_widget_get_screen (widget);
5090 *width = gdk_screen_get_width (screen);
5091 *height = gdk_screen_get_height (screen);
5093 if (*width >= *height)
5096 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
5097 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
5102 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
5103 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
5106 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
5108 gtk_widget_get_preferred_height (widget, &minimum, &natural);
5109 *height = MAX (minimum, MIN (*height, natural));
5111 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
5112 *width = MAX (minimum, MIN (*width, natural));
5114 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
5116 gtk_widget_get_preferred_width (widget, &minimum, &natural);
5117 *width = MAX (minimum, MIN (*width, natural));
5119 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
5120 *height = MAX (minimum, MIN (*height, natural));
5125 gtk_window_realize (GtkWidget *widget)
5127 GtkAllocation allocation;
5129 GdkWindow *parent_window;
5130 GdkWindow *gdk_window;
5131 GdkWindowAttr attributes;
5132 gint attributes_mask;
5133 GtkWindowPrivate *priv;
5134 GtkStyleContext *context;
5136 window = GTK_WINDOW (widget);
5137 priv = window->priv;
5139 gtk_widget_get_allocation (widget, &allocation);
5141 if (gtk_widget_get_parent_window (widget))
5143 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
5145 gtk_widget_set_realized (widget, TRUE);
5147 attributes.x = allocation.x;
5148 attributes.y = allocation.y;
5149 attributes.width = allocation.width;
5150 attributes.height = allocation.height;
5151 attributes.window_type = GDK_WINDOW_CHILD;
5153 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
5155 attributes.visual = gtk_widget_get_visual (widget);
5156 attributes.wclass = GDK_INPUT_OUTPUT;
5158 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
5160 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
5161 &attributes, attributes_mask);
5162 gtk_widget_set_window (widget, gdk_window);
5163 gtk_widget_register_window (widget, gdk_window);
5165 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
5167 gdk_window_enable_synchronized_configure (gdk_window);
5171 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5173 /* ensure widget tree is properly size allocated */
5174 if (allocation.x == -1 &&
5175 allocation.y == -1 &&
5176 allocation.width == 1 &&
5177 allocation.height == 1)
5183 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5184 if (allocation.width == 0 || allocation.height == 0)
5186 /* non-empty window */
5187 allocation.width = 200;
5188 allocation.height = 200;
5190 gtk_widget_size_allocate (widget, &allocation);
5192 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5194 g_return_if_fail (!gtk_widget_get_realized (widget));
5197 gtk_widget_set_realized (widget, TRUE);
5201 case GTK_WINDOW_TOPLEVEL:
5202 attributes.window_type = GDK_WINDOW_TOPLEVEL;
5204 case GTK_WINDOW_POPUP:
5205 attributes.window_type = GDK_WINDOW_TEMP;
5208 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5212 attributes.title = priv->title;
5213 attributes.wmclass_name = priv->wmclass_name;
5214 attributes.wmclass_class = priv->wmclass_class;
5215 attributes.wclass = GDK_INPUT_OUTPUT;
5216 attributes.visual = gtk_widget_get_visual (widget);
5218 attributes_mask = 0;
5219 parent_window = gtk_widget_get_root_window (widget);
5221 gtk_widget_get_allocation (widget, &allocation);
5222 attributes.width = allocation.width;
5223 attributes.height = allocation.height;
5224 attributes.event_mask = gtk_widget_get_events (widget);
5225 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5226 GDK_KEY_PRESS_MASK |
5227 GDK_KEY_RELEASE_MASK |
5228 GDK_ENTER_NOTIFY_MASK |
5229 GDK_LEAVE_NOTIFY_MASK |
5230 GDK_FOCUS_CHANGE_MASK |
5231 GDK_STRUCTURE_MASK);
5232 attributes.type_hint = priv->type_hint;
5234 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5235 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5236 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5238 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5239 gtk_widget_set_window (widget, gdk_window);
5241 gdk_window_enable_synchronized_configure (gdk_window);
5243 gtk_widget_register_window (widget, gdk_window);
5245 context = gtk_widget_get_style_context (widget);
5246 gtk_style_context_set_background (context, gdk_window);
5249 if (priv->transient_parent &&
5250 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5251 gdk_window_set_transient_for (gdk_window,
5252 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5255 gdk_window_set_role (gdk_window, priv->wm_role);
5257 if (!priv->decorated)
5258 gdk_window_set_decorations (gdk_window, 0);
5260 if (!priv->deletable)
5261 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5263 if (gtk_window_get_skip_pager_hint (window))
5264 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5266 if (gtk_window_get_skip_taskbar_hint (window))
5267 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5269 if (gtk_window_get_accept_focus (window))
5270 gdk_window_set_accept_focus (gdk_window, TRUE);
5272 gdk_window_set_accept_focus (gdk_window, FALSE);
5274 if (gtk_window_get_focus_on_map (window))
5275 gdk_window_set_focus_on_map (gdk_window, TRUE);
5277 gdk_window_set_focus_on_map (gdk_window, FALSE);
5280 gdk_window_set_modal_hint (gdk_window, TRUE);
5282 gdk_window_set_modal_hint (gdk_window, FALSE);
5284 if (priv->startup_id)
5286 #ifdef GDK_WINDOWING_X11
5287 if (GDK_IS_X11_WINDOW (gdk_window))
5289 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5290 if (timestamp != GDK_CURRENT_TIME)
5291 gdk_x11_window_set_user_time (gdk_window, timestamp);
5294 if (!startup_id_is_fake (priv->startup_id))
5295 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5298 #ifdef GDK_WINDOWING_X11
5299 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5301 if (GDK_IS_X11_WINDOW (gdk_window))
5302 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5307 gtk_window_realize_icon (window);
5309 if (priv->has_resize_grip)
5310 resize_grip_create_window (window);
5314 gtk_window_unrealize (GtkWidget *widget)
5316 GtkWindow *window = GTK_WINDOW (widget);
5317 GtkWindowPrivate *priv = window->priv;
5318 GtkWindowGeometryInfo *info;
5320 /* On unrealize, we reset the size of the window such
5321 * that we will re-apply the default sizing stuff
5322 * next time we show the window.
5324 * Default positioning is reset on unmap, instead of unrealize.
5326 priv->need_default_size = TRUE;
5327 info = gtk_window_get_geometry_info (window, FALSE);
5330 info->resize_width = -1;
5331 info->resize_height = -1;
5332 info->last.configure_request.x = 0;
5333 info->last.configure_request.y = 0;
5334 info->last.configure_request.width = -1;
5335 info->last.configure_request.height = -1;
5336 /* be sure we reset geom hints on re-realize */
5337 info->last.flags = 0;
5341 gtk_window_unrealize_icon (window);
5343 if (priv->grip_window != NULL)
5344 resize_grip_destroy_window (window);
5346 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5349 static GtkJunctionSides
5350 get_grip_junction (GtkWidget *widget)
5352 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5353 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5355 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5359 get_drag_edge (GtkWidget *widget,
5360 GdkWindowEdge *edge)
5362 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5363 gboolean hresizable;
5364 gboolean vresizable;
5365 GtkTextDirection dir;
5366 GtkWindowGeometryInfo *info;
5371 info = priv->geometry_info;
5374 GdkWindowHints flags = info->last.flags;
5375 GdkGeometry *geometry = &info->last.geometry;
5377 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5379 hresizable = geometry->min_width < geometry->max_width;
5380 vresizable = geometry->min_height < geometry->max_height;
5384 dir = gtk_widget_get_direction (widget);
5386 if (hresizable && vresizable)
5387 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5388 else if (hresizable)
5389 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5390 else if (vresizable)
5391 *edge = GDK_WINDOW_EDGE_SOUTH;
5399 set_grip_cursor (GtkWindow *window)
5401 GtkWidget *widget = GTK_WIDGET (window);
5402 GtkWindowPrivate *priv = window->priv;
5404 if (priv->grip_window == NULL)
5407 if (gtk_widget_is_sensitive (widget))
5410 GdkDisplay *display;
5411 GdkCursorType cursor_type;
5414 cursor_type = GDK_LEFT_PTR;
5416 if (get_drag_edge (widget, &edge))
5420 case GDK_WINDOW_EDGE_EAST:
5421 cursor_type = GDK_RIGHT_SIDE;
5423 case GDK_WINDOW_EDGE_SOUTH_EAST:
5424 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5426 case GDK_WINDOW_EDGE_SOUTH:
5427 cursor_type = GDK_BOTTOM_SIDE;
5429 case GDK_WINDOW_EDGE_SOUTH_WEST:
5430 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5432 case GDK_WINDOW_EDGE_WEST:
5433 cursor_type = GDK_LEFT_SIDE;
5439 display = gtk_widget_get_display (widget);
5440 cursor = gdk_cursor_new_for_display (display, cursor_type);
5441 gdk_window_set_cursor (priv->grip_window, cursor);
5442 g_object_unref (cursor);
5445 gdk_window_set_cursor (priv->grip_window, NULL);
5449 set_grip_shape (GtkWindow *window)
5451 GtkWindowPrivate *priv = window->priv;
5452 cairo_region_t *region;
5453 cairo_surface_t *surface;
5455 double width, height;
5457 if (priv->grip_window == NULL)
5460 width = gdk_window_get_width (priv->grip_window);
5461 height = gdk_window_get_height (priv->grip_window);
5462 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
5464 cr = cairo_create (surface);
5465 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5467 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5468 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5470 cairo_move_to (cr, width, 0.0);
5471 cairo_line_to (cr, width, height);
5472 cairo_line_to (cr, 0.0, height);
5476 cairo_move_to (cr, 0.0, 0.0);
5477 cairo_line_to (cr, width, height);
5478 cairo_line_to (cr, 0.0, height);
5480 cairo_close_path (cr);
5483 region = gdk_cairo_region_create_from_surface (surface);
5484 cairo_surface_destroy (surface);
5486 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5487 cairo_region_destroy (region);
5491 set_grip_position (GtkWindow *window)
5493 GtkWindowPrivate *priv = window->priv;
5496 if (priv->grip_window == NULL)
5499 gtk_window_get_resize_grip_area (window, &rect);
5500 gdk_window_raise (priv->grip_window);
5501 gdk_window_move_resize (priv->grip_window,
5503 rect.width, rect.height);
5506 /* _gtk_window_set_allocation:
5507 * @window: a #GtkWindow
5508 * @allocation: the new allocation
5510 * This function is like gtk_widget_set_allocation()
5511 * but does the necessary extra work to update
5512 * the resize grip positioning, etc.
5514 * Call this instead of gtk_widget_set_allocation()
5515 * when overriding ::size_allocate in a GtkWindow
5516 * subclass without chaining up.
5519 _gtk_window_set_allocation (GtkWindow *window,
5520 GtkAllocation *allocation)
5522 GtkWidget *widget = (GtkWidget *)window;
5524 gtk_widget_set_allocation (widget, allocation);
5526 if (gtk_widget_get_realized (widget))
5528 /* If it's not a toplevel we're embedded, we need to resize
5529 * the window's window and skip the grip.
5531 if (!gtk_widget_is_toplevel (widget))
5533 gdk_window_move_resize (gtk_widget_get_window (widget),
5534 allocation->x, allocation->y,
5535 allocation->width, allocation->height);
5539 update_grip_visibility (window);
5540 set_grip_position (window);
5546 gtk_window_size_allocate (GtkWidget *widget,
5547 GtkAllocation *allocation)
5549 GtkWindow *window = GTK_WINDOW (widget);
5550 GtkAllocation child_allocation;
5554 _gtk_window_set_allocation (window, allocation);
5556 child = gtk_bin_get_child (&(window->bin));
5557 if (child && gtk_widget_get_visible (child))
5559 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5560 child_allocation.x = border_width;
5561 child_allocation.y = border_width;
5562 child_allocation.width = MAX (1, allocation->width - border_width * 2);
5563 child_allocation.height = MAX (1, allocation->height - border_width * 2);
5565 gtk_widget_size_allocate (child, &child_allocation);
5570 gtk_window_configure_event (GtkWidget *widget,
5571 GdkEventConfigure *event)
5573 GtkAllocation allocation;
5574 GtkWindow *window = GTK_WINDOW (widget);
5575 GtkWindowPrivate *priv = window->priv;
5576 gboolean expected_reply = priv->configure_request_count > 0;
5578 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5580 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5581 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5583 gdk_window_configure_finished (gtk_widget_get_window (widget));
5587 /* priv->configure_request_count incremented for each
5588 * configure request, and decremented to a min of 0 for
5589 * each configure notify.
5591 * All it means is that we know we will get at least
5592 * priv->configure_request_count more configure notifies.
5593 * We could get more configure notifies than that; some
5594 * of the configure notifies we get may be unrelated to
5595 * the configure requests. But we will get at least
5596 * priv->configure_request_count notifies.
5599 if (priv->configure_request_count > 0)
5601 priv->configure_request_count -= 1;
5602 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5605 /* As an optimization, we avoid a resize when possible.
5607 * The only times we can avoid a resize are:
5608 * - we know only the position changed, not the size
5609 * - we know we have made more requests and so will get more
5610 * notifies and can wait to resize when we get them
5612 gtk_widget_get_allocation (widget, &allocation);
5613 if (!expected_reply &&
5614 (allocation.width == event->width &&
5615 allocation.height == event->height))
5617 gdk_window_configure_finished (gtk_widget_get_window (widget));
5622 * If we do need to resize, we do that by:
5623 * - setting configure_notify_received to TRUE
5624 * for use in gtk_window_move_resize()
5625 * - queueing a resize, leading to invocation of
5626 * gtk_window_move_resize() in an idle handler
5630 priv->configure_notify_received = TRUE;
5632 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5634 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5640 gtk_window_state_event (GtkWidget *widget,
5641 GdkEventWindowState *event)
5643 update_grip_visibility (GTK_WINDOW (widget));
5645 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
5646 ensure_state_flag_backdrop (widget);
5652 gtk_window_direction_changed (GtkWidget *widget,
5653 GtkTextDirection prev_dir)
5655 GtkWindow *window = GTK_WINDOW (widget);
5657 set_grip_cursor (window);
5658 set_grip_position (window);
5659 set_grip_shape (window);
5663 gtk_window_state_changed (GtkWidget *widget,
5664 GtkStateType previous_state)
5666 GtkWindow *window = GTK_WINDOW (widget);
5668 update_grip_visibility (window);
5672 gtk_window_style_updated (GtkWidget *widget)
5674 GtkWindow *window = GTK_WINDOW (widget);
5675 GtkWindowPrivate *priv = window->priv;
5678 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5680 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5682 gdk_window_move_resize (priv->grip_window,
5684 rect.width, rect.height);
5686 set_grip_shape (window);
5691 resize_grip_create_window (GtkWindow *window)
5694 GtkWindowPrivate *priv;
5695 GdkWindowAttr attributes;
5696 gint attributes_mask;
5698 GdkRGBA transparent = {0, 0, 0, 0};
5700 priv = window->priv;
5701 widget = GTK_WIDGET (window);
5703 g_return_if_fail (gtk_widget_get_realized (widget));
5704 g_return_if_fail (priv->grip_window == NULL);
5706 gtk_window_get_resize_grip_area (window, &rect);
5708 attributes.x = rect.x;
5709 attributes.y = rect.y;
5710 attributes.width = rect.width;
5711 attributes.height = rect.height;
5712 attributes.window_type = GDK_WINDOW_CHILD;
5713 attributes.wclass = GDK_INPUT_OUTPUT;
5714 attributes.event_mask = gtk_widget_get_events (widget) |
5716 GDK_BUTTON_PRESS_MASK;
5718 attributes_mask = GDK_WA_X | GDK_WA_Y;
5720 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5723 gdk_window_set_background_rgba (priv->grip_window, &transparent);
5725 gtk_widget_register_window (widget, priv->grip_window);
5727 gdk_window_raise (priv->grip_window);
5729 set_grip_shape (window);
5730 update_grip_visibility (window);
5734 resize_grip_destroy_window (GtkWindow *window)
5736 GtkWindowPrivate *priv = window->priv;
5738 gtk_widget_unregister_window (GTK_WIDGET (window), priv->grip_window);
5739 gdk_window_destroy (priv->grip_window);
5740 priv->grip_window = NULL;
5741 update_grip_visibility (window);
5745 * gtk_window_set_has_resize_grip:
5746 * @window: a #GtkWindow
5747 * @value: %TRUE to allow a resize grip
5749 * Sets whether @window has a corner resize grip.
5751 * Note that the resize grip is only shown if the window
5752 * is actually resizable and not maximized. Use
5753 * gtk_window_resize_grip_is_visible() to find out if the
5754 * resize grip is currently shown.
5759 gtk_window_set_has_resize_grip (GtkWindow *window,
5762 GtkWidget *widget = GTK_WIDGET (window);
5763 GtkWindowPrivate *priv = window->priv;
5765 value = value != FALSE;
5767 if (value != priv->has_resize_grip)
5769 priv->has_resize_grip = value;
5770 gtk_widget_queue_draw (widget);
5772 if (gtk_widget_get_realized (widget) &&
5773 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5775 if (priv->has_resize_grip && priv->grip_window == NULL)
5776 resize_grip_create_window (window);
5777 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5778 resize_grip_destroy_window (window);
5781 g_object_notify (G_OBJECT (window), "has-resize-grip");
5786 update_grip_visibility (GtkWindow *window)
5788 GtkWindowPrivate *priv = window->priv;
5791 val = gtk_window_resize_grip_is_visible (window);
5793 if (priv->grip_window != NULL)
5797 gdk_window_show (priv->grip_window);
5798 set_grip_cursor (window);
5802 gdk_window_hide (priv->grip_window);
5806 if (priv->resize_grip_visible != val)
5808 priv->resize_grip_visible = val;
5810 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5815 * gtk_window_resize_grip_is_visible:
5816 * @window: a #GtkWindow
5818 * Determines whether a resize grip is visible for the specified window.
5820 * Returns: %TRUE if a resize grip exists and is visible
5825 gtk_window_resize_grip_is_visible (GtkWindow *window)
5828 GtkWindowPrivate *priv;
5831 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5833 priv = window->priv;
5834 widget = GTK_WIDGET (window);
5836 if (priv->type == GTK_WINDOW_POPUP)
5839 if (!priv->resizable)
5842 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5845 if (gtk_widget_get_realized (widget))
5847 GdkWindowState state;
5849 state = gdk_window_get_state (gtk_widget_get_window (widget));
5851 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5855 if (!get_drag_edge (widget, &edge))
5858 return window->priv->has_resize_grip;
5862 * gtk_window_get_has_resize_grip:
5863 * @window: a #GtkWindow
5865 * Determines whether the window may have a resize grip.
5867 * Returns: %TRUE if the window has a resize grip
5872 gtk_window_get_has_resize_grip (GtkWindow *window)
5874 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5876 return window->priv->has_resize_grip;
5880 * gtk_window_get_resize_grip_area:
5881 * @window: a #GtkWindow
5882 * @rect: (out): a pointer to a #GdkRectangle which we should store
5883 * the resize grip area
5885 * If a window has a resize grip, this will retrieve the grip
5886 * position, width and height into the specified #GdkRectangle.
5888 * Returns: %TRUE if the resize grip's area was retrieved
5893 gtk_window_get_resize_grip_area (GtkWindow *window,
5896 GtkWidget *widget = GTK_WIDGET (window);
5897 GtkAllocation allocation;
5901 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5903 if (!window->priv->has_resize_grip)
5906 gtk_widget_get_allocation (widget, &allocation);
5908 gtk_widget_style_get (widget,
5909 "resize-grip-width", &grip_width,
5910 "resize-grip-height", &grip_height,
5913 if (grip_width > allocation.width)
5914 grip_width = allocation.width;
5916 if (grip_height > allocation.height)
5917 grip_height = allocation.height;
5919 rect->width = grip_width;
5920 rect->height = grip_height;
5921 rect->y = allocation.y + allocation.height - grip_height;
5923 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5924 rect->x = allocation.x + allocation.width - grip_width;
5926 rect->x = allocation.x;
5931 /* the accel_key and accel_mods fields of the key have to be setup
5932 * upon calling this function. it'll then return whether that key
5933 * is at all used as accelerator, and if so will OR in the
5934 * accel_flags member of the key.
5937 _gtk_window_query_nonaccels (GtkWindow *window,
5939 GdkModifierType accel_mods)
5941 GtkWindowPrivate *priv;
5943 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5945 priv = window->priv;
5947 /* movement keys are considered locked accels */
5950 static const guint bindings[] = {
5951 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,
5952 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,
5956 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5957 if (bindings[i] == accel_key)
5961 /* mnemonics are considered locked accels */
5962 if (accel_mods == priv->mnemonic_modifier)
5964 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5965 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5973 * gtk_window_propagate_key_event:
5974 * @window: a #GtkWindow
5975 * @event: a #GdkEventKey
5977 * Propagate a key press or release event to the focus widget and
5978 * up the focus container chain until a widget handles @event.
5979 * This is normally called by the default ::key_press_event and
5980 * ::key_release_event handlers for toplevel windows,
5981 * however in some cases it may be useful to call this directly when
5982 * overriding the standard key handling for a toplevel window.
5984 * Return value: %TRUE if a widget in the focus chain handled the event.
5989 gtk_window_propagate_key_event (GtkWindow *window,
5992 GtkWindowPrivate *priv;
5993 gboolean handled = FALSE;
5994 GtkWidget *widget, *focus;
5996 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5998 priv = window->priv;
5999 widget = GTK_WIDGET (window);
6001 focus = priv->focus_widget;
6003 g_object_ref (focus);
6006 focus && focus != widget &&
6007 gtk_widget_get_toplevel (focus) == widget)
6011 if (gtk_widget_is_sensitive (focus))
6012 handled = gtk_widget_event (focus, (GdkEvent*) event);
6014 parent = gtk_widget_get_parent (focus);
6016 g_object_ref (parent);
6018 g_object_unref (focus);
6024 g_object_unref (focus);
6030 gtk_window_key_press_event (GtkWidget *widget,
6033 GtkWindow *window = GTK_WINDOW (widget);
6034 gboolean handled = FALSE;
6036 /* handle mnemonics and accelerators */
6038 handled = gtk_window_activate_key (window, event);
6040 /* handle focus widget key events */
6042 handled = gtk_window_propagate_key_event (window, event);
6044 /* Chain up, invokes binding set */
6046 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
6052 gtk_window_key_release_event (GtkWidget *widget,
6055 GtkWindow *window = GTK_WINDOW (widget);
6056 gboolean handled = FALSE;
6058 /* handle focus widget key events */
6060 handled = gtk_window_propagate_key_event (window, event);
6062 /* Chain up, invokes binding set */
6064 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
6070 gtk_window_button_press_event (GtkWidget *widget,
6071 GdkEventButton *event)
6073 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
6076 if (event->window == priv->grip_window)
6078 if (get_drag_edge (widget, &edge))
6079 gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
6081 gdk_event_get_device ((GdkEvent *) event),
6094 gtk_window_real_activate_default (GtkWindow *window)
6096 gtk_window_activate_default (window);
6100 gtk_window_real_activate_focus (GtkWindow *window)
6102 gtk_window_activate_focus (window);
6106 gtk_window_enter_notify_event (GtkWidget *widget,
6107 GdkEventCrossing *event)
6113 gtk_window_leave_notify_event (GtkWidget *widget,
6114 GdkEventCrossing *event)
6120 do_focus_change (GtkWidget *widget,
6124 GdkDeviceManager *device_manager;
6127 g_object_ref (widget);
6129 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
6130 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6131 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
6132 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
6134 for (d = devices; d; d = d->next)
6136 GdkDevice *dev = d->data;
6139 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
6142 /* Skip non-master keyboards that haven't
6143 * selected for events from this window
6145 window = gtk_widget_get_window (widget);
6146 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
6147 window && !gdk_window_get_device_events (window, dev))
6150 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
6152 fevent->focus_change.type = GDK_FOCUS_CHANGE;
6153 fevent->focus_change.window = window;
6155 g_object_ref (window);
6156 fevent->focus_change.in = in;
6157 gdk_event_set_device (fevent, dev);
6159 gtk_widget_send_focus_change (widget, fevent);
6161 gdk_event_free (fevent);
6164 g_list_free (devices);
6165 g_object_unref (widget);
6169 maybe_set_mnemonics_visible (GtkWindow *window)
6172 GdkDeviceManager *device_manager;
6174 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
6175 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6177 for (d = devices; d; d = d->next)
6179 GdkDevice *dev = d->data;
6181 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6183 GdkModifierType mask;
6185 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6187 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6189 _gtk_window_set_auto_mnemonics_visible (window);
6195 g_list_free (devices);
6199 gtk_window_focus_in_event (GtkWidget *widget,
6200 GdkEventFocus *event)
6202 GtkWindow *window = GTK_WINDOW (widget);
6203 gboolean auto_mnemonics;
6205 /* It appears spurious focus in events can occur when
6206 * the window is hidden. So we'll just check to see if
6207 * the window is visible before actually handling the
6210 if (gtk_widget_get_visible (widget))
6212 _gtk_window_set_has_toplevel_focus (window, TRUE);
6213 _gtk_window_set_is_active (window, TRUE);
6215 g_object_get (gtk_widget_get_settings (widget),
6216 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6218 maybe_set_mnemonics_visible (window);
6225 gtk_window_focus_out_event (GtkWidget *widget,
6226 GdkEventFocus *event)
6228 GtkWindow *window = GTK_WINDOW (widget);
6229 gboolean auto_mnemonics;
6231 _gtk_window_set_has_toplevel_focus (window, FALSE);
6232 _gtk_window_set_is_active (window, FALSE);
6234 /* set the mnemonic-visible property to false */
6235 g_object_get (gtk_widget_get_settings (widget),
6236 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6238 gtk_window_set_mnemonics_visible (window, FALSE);
6244 gtk_window_check_resize (GtkContainer *container)
6246 /* If the window is not toplevel anymore than it's embedded somewhere,
6247 * so handle it like a normal window */
6248 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6249 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6250 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6251 gtk_window_move_resize (GTK_WINDOW (container));
6255 gtk_window_focus (GtkWidget *widget,
6256 GtkDirectionType direction)
6258 GtkWindowPrivate *priv;
6261 GtkContainer *container;
6263 GtkWidget *old_focus_child;
6266 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6267 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6269 container = GTK_CONTAINER (widget);
6270 window = GTK_WINDOW (widget);
6271 priv = window->priv;
6272 bin = GTK_BIN (widget);
6274 old_focus_child = gtk_container_get_focus_child (container);
6276 /* We need a special implementation here to deal properly with wrapping
6277 * around in the tab chain without the danger of going into an
6280 if (old_focus_child)
6282 if (gtk_widget_child_focus (old_focus_child, direction))
6286 if (priv->focus_widget)
6288 if (direction == GTK_DIR_LEFT ||
6289 direction == GTK_DIR_RIGHT ||
6290 direction == GTK_DIR_UP ||
6291 direction == GTK_DIR_DOWN)
6296 /* Wrapped off the end, clear the focus setting for the toplpevel */
6297 parent = gtk_widget_get_parent (priv->focus_widget);
6300 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6301 parent = gtk_widget_get_parent (parent);
6304 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6307 /* Now try to focus the first widget in the window */
6308 child = gtk_bin_get_child (bin);
6311 if (gtk_widget_child_focus (child, direction))
6319 gtk_window_move_focus (GtkWidget *widget,
6320 GtkDirectionType dir)
6322 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6324 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6328 gtk_widget_child_focus (widget, dir);
6330 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6331 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6335 gtk_window_real_set_focus (GtkWindow *window,
6338 GtkWindowPrivate *priv = window->priv;
6339 GtkWidget *old_focus = priv->focus_widget;
6340 gboolean had_default = FALSE;
6341 gboolean focus_had_default = FALSE;
6342 gboolean old_focus_had_default = FALSE;
6346 g_object_ref (old_focus);
6347 g_object_freeze_notify (G_OBJECT (old_focus));
6348 old_focus_had_default = gtk_widget_has_default (old_focus);
6352 g_object_ref (focus);
6353 g_object_freeze_notify (G_OBJECT (focus));
6354 focus_had_default = gtk_widget_has_default (focus);
6357 if (priv->default_widget)
6358 had_default = gtk_widget_has_default (priv->default_widget);
6360 if (priv->focus_widget)
6362 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6363 (priv->focus_widget != priv->default_widget))
6365 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6366 gtk_widget_queue_draw (priv->focus_widget);
6368 if (priv->default_widget)
6369 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6372 priv->focus_widget = NULL;
6374 if (priv->has_focus)
6375 do_focus_change (old_focus, FALSE);
6377 g_object_notify (G_OBJECT (old_focus), "is-focus");
6380 /* The above notifications may have set a new focus widget,
6381 * if so, we don't want to override it.
6383 if (focus && !priv->focus_widget)
6385 priv->focus_widget = focus;
6387 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6388 (priv->focus_widget != priv->default_widget))
6390 if (gtk_widget_get_can_default (priv->focus_widget))
6391 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6393 if (priv->default_widget)
6394 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6397 if (priv->has_focus)
6398 do_focus_change (priv->focus_widget, TRUE);
6400 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6403 /* If the default widget changed, a redraw will have been queued
6404 * on the old and new default widgets by gtk_window_set_default(), so
6405 * we only have to worry about the case where it didn't change.
6406 * We'll sometimes queue a draw twice on the new widget but that
6409 if (priv->default_widget &&
6410 (had_default != gtk_widget_has_default (priv->default_widget)))
6411 gtk_widget_queue_draw (priv->default_widget);
6415 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6416 gtk_widget_queue_draw (old_focus);
6418 g_object_thaw_notify (G_OBJECT (old_focus));
6419 g_object_unref (old_focus);
6423 if (focus_had_default != gtk_widget_has_default (focus))
6424 gtk_widget_queue_draw (focus);
6426 g_object_thaw_notify (G_OBJECT (focus));
6427 g_object_unref (focus);
6432 * _gtk_window_unset_focus_and_default:
6433 * @window: a #GtkWindow
6434 * @widget: a widget inside of @window
6436 * Checks whether the focus and default widgets of @window are
6437 * @widget or a descendent of @widget, and if so, unset them.
6440 _gtk_window_unset_focus_and_default (GtkWindow *window,
6444 GtkWindowPrivate *priv = window->priv;
6448 g_object_ref (window);
6449 g_object_ref (widget);
6451 parent = gtk_widget_get_parent (widget);
6452 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6454 child = priv->focus_widget;
6456 while (child && child != widget)
6457 child = gtk_widget_get_parent (child);
6459 if (child == widget)
6460 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6463 child = priv->default_widget;
6465 while (child && child != widget)
6466 child = gtk_widget_get_parent (child);
6468 if (child == widget)
6469 gtk_window_set_default (window, NULL);
6471 g_object_unref (widget);
6472 g_object_unref (window);
6475 /*********************************
6476 * Functions related to resizing *
6477 *********************************/
6480 geometry_size_to_pixels (GdkGeometry *geometry,
6485 gint base_width = 0;
6486 gint base_height = 0;
6488 gint min_height = 0;
6490 gint height_inc = 1;
6492 if (flags & GDK_HINT_BASE_SIZE)
6494 base_width = geometry->base_width;
6495 base_height = geometry->base_height;
6497 if (flags & GDK_HINT_MIN_SIZE)
6499 min_width = geometry->min_width;
6500 min_height = geometry->min_height;
6502 if (flags & GDK_HINT_RESIZE_INC)
6504 width_inc = geometry->width_inc;
6505 height_inc = geometry->height_inc;
6509 *width = MAX (*width * width_inc + base_width, min_width);
6511 *height = MAX (*height * height_inc + base_height, min_height);
6514 /* This function doesn't constrain to geometry hints */
6516 gtk_window_compute_configure_request_size (GtkWindow *window,
6517 GdkGeometry *geometry,
6522 GtkWindowPrivate *priv = window->priv;
6523 GtkWindowGeometryInfo *info;
6526 * - we've done a size request
6529 info = gtk_window_get_geometry_info (window, FALSE);
6531 if (priv->need_default_size)
6533 gtk_window_guess_default_size (window, width, height);
6535 /* If window is empty so requests 0, default to random nonzero size */
6536 if (*width == 0 && *height == 0)
6542 /* Override with default size */
6546 if (info->default_width > 0)
6547 *width = info->default_width;
6548 if (info->default_height > 0)
6549 *height = info->default_height;
6551 if (info->default_is_geometry)
6552 geometry_size_to_pixels (geometry, flags,
6553 info->default_width > 0 ? width : NULL,
6554 info->default_height > 0 ? height : NULL);
6559 GtkAllocation allocation;
6561 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6563 /* Default to keeping current size */
6564 *width = allocation.width;
6565 *height = allocation.height;
6568 /* Override any size with gtk_window_resize() values */
6571 if (info->resize_width > 0)
6572 *width = info->resize_width;
6573 if (info->resize_height > 0)
6574 *height = info->resize_height;
6576 if (info->resize_is_geometry)
6577 geometry_size_to_pixels (geometry, flags,
6578 info->resize_width > 0 ? width : NULL,
6579 info->resize_height > 0 ? height : NULL);
6582 /* Don't ever request zero width or height, its not supported by
6583 gdk. The size allocation code will round it to 1 anyway but if
6584 we do it then the value returned from this function will is
6585 not comparable to the size allocation read from the GtkWindow. */
6586 *width = MAX (*width, 1);
6587 *height = MAX (*height, 1);
6590 static GtkWindowPosition
6591 get_effective_position (GtkWindow *window)
6593 GtkWindowPrivate *priv = window->priv;
6594 GtkWindowPosition pos = priv->position;
6596 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6597 (priv->transient_parent == NULL ||
6598 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6599 pos = GTK_WIN_POS_NONE;
6605 get_center_monitor_of_window (GtkWindow *window)
6607 /* We could try to sort out the relative positions of the monitors and
6608 * stuff, or we could just be losers and assume you have a row
6609 * or column of monitors.
6611 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6615 get_monitor_containing_pointer (GtkWindow *window)
6619 GdkScreen *window_screen;
6620 GdkScreen *pointer_screen;
6621 GdkDisplay *display;
6622 GdkDeviceManager *device_manager;
6625 window_screen = gtk_window_check_screen (window);
6626 display = gdk_screen_get_display (window_screen);
6627 device_manager = gdk_display_get_device_manager (display);
6628 pointer = gdk_device_manager_get_client_pointer (device_manager);
6630 gdk_device_get_position (pointer,
6634 if (pointer_screen == window_screen)
6635 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6643 center_window_on_monitor (GtkWindow *window,
6649 GdkRectangle monitor;
6652 monitor_num = get_monitor_containing_pointer (window);
6654 if (monitor_num == -1)
6655 monitor_num = get_center_monitor_of_window (window);
6657 gdk_screen_get_monitor_workarea (gtk_window_check_screen (window),
6658 monitor_num, &monitor);
6660 *x = (monitor.width - w) / 2 + monitor.x;
6661 *y = (monitor.height - h) / 2 + monitor.y;
6663 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6664 * and WM decorations.
6678 if (extent > clamp_extent)
6680 *base = clamp_base + clamp_extent/2 - extent/2;
6681 else if (*base < clamp_base)
6683 else if (*base + extent > clamp_base + clamp_extent)
6684 *base = clamp_base + clamp_extent - extent;
6688 clamp_window_to_rectangle (gint *x,
6692 const GdkRectangle *rect)
6694 #ifdef DEBUGGING_OUTPUT
6695 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);
6698 /* If it is too large, center it. If it fits on the monitor but is
6699 * partially outside, move it to the closest edge. Do this
6700 * separately in x and y directions.
6702 clamp (x, w, rect->x, rect->width);
6703 clamp (y, h, rect->y, rect->height);
6704 #ifdef DEBUGGING_OUTPUT
6705 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6711 gtk_window_compute_configure_request (GtkWindow *window,
6712 GdkRectangle *request,
6713 GdkGeometry *geometry,
6716 GtkWindowPrivate *priv = window->priv;
6717 GdkGeometry new_geometry;
6720 GtkWindowPosition pos;
6721 GtkWidget *parent_widget;
6722 GtkWindowGeometryInfo *info;
6726 screen = gtk_window_check_screen (window);
6728 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6729 gtk_window_compute_configure_request_size (window,
6730 &new_geometry, new_flags,
6733 gtk_window_constrain_size (window,
6734 &new_geometry, new_flags,
6738 parent_widget = (GtkWidget*) priv->transient_parent;
6740 pos = get_effective_position (window);
6741 info = gtk_window_get_geometry_info (window, FALSE);
6743 /* by default, don't change position requested */
6746 x = info->last.configure_request.x;
6747 y = info->last.configure_request.y;
6756 if (priv->need_default_position)
6759 /* FIXME this all interrelates with window gravity.
6760 * For most of them I think we want to set GRAVITY_CENTER.
6762 * Not sure how to go about that.
6766 /* here we are only handling CENTER_ALWAYS
6767 * as it relates to default positioning,
6768 * where it's equivalent to simply CENTER
6770 case GTK_WIN_POS_CENTER_ALWAYS:
6771 case GTK_WIN_POS_CENTER:
6772 center_window_on_monitor (window, w, h, &x, &y);
6775 case GTK_WIN_POS_CENTER_ON_PARENT:
6777 GtkAllocation allocation;
6778 GdkWindow *gdk_window;
6780 GdkRectangle monitor;
6783 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6785 gdk_window = gtk_widget_get_window (parent_widget);
6787 if (gdk_window != NULL)
6788 monitor_num = gdk_screen_get_monitor_at_window (screen,
6793 gdk_window_get_origin (gdk_window,
6796 gtk_widget_get_allocation (parent_widget, &allocation);
6797 x = ox + (allocation.width - w) / 2;
6798 y = oy + (allocation.height - h) / 2;
6800 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6801 * WM decorations. If parent wasn't on a monitor, just
6804 if (monitor_num >= 0)
6806 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6807 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6812 case GTK_WIN_POS_MOUSE:
6814 gint screen_width = gdk_screen_get_width (screen);
6815 gint screen_height = gdk_screen_get_height (screen);
6817 GdkRectangle monitor;
6818 GdkDisplay *display;
6819 GdkDeviceManager *device_manager;
6821 GdkScreen *pointer_screen;
6824 display = gdk_screen_get_display (screen);
6825 device_manager = gdk_display_get_device_manager (display);
6826 pointer = gdk_device_manager_get_client_pointer (device_manager);
6828 gdk_device_get_position (pointer,
6832 if (pointer_screen == screen)
6833 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6839 x = CLAMP (x, 0, screen_width - w);
6840 y = CLAMP (y, 0, screen_height - h);
6842 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6843 * WM decorations. Don't try to figure out what's going
6844 * on if the mouse wasn't inside a monitor.
6846 if (monitor_num >= 0)
6848 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6849 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6857 } /* if (priv->need_default_position) */
6859 if (priv->need_default_position && info &&
6860 info->initial_pos_set)
6862 x = info->initial_x;
6863 y = info->initial_y;
6864 gtk_window_constrain_position (window, w, h, &x, &y);
6870 request->height = h;
6873 *geometry = new_geometry;
6879 gtk_window_constrain_position (GtkWindow *window,
6885 GtkWindowPrivate *priv = window->priv;
6887 /* See long comments in gtk_window_move_resize()
6888 * on when it's safe to call this function.
6890 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6892 gint center_x, center_y;
6894 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6902 gtk_window_move_resize (GtkWindow *window)
6906 * First we determine whether any information has changed that would
6907 * cause us to revise our last configure request. If we would send
6908 * a different configure request from last time, then
6909 * configure_request_size_changed = TRUE or
6910 * configure_request_pos_changed = TRUE. configure_request_size_changed
6911 * may be true due to new hints, a gtk_window_resize(), or whatever.
6912 * configure_request_pos_changed may be true due to gtk_window_set_position()
6913 * or gtk_window_move().
6915 * If the configure request has changed, we send off a new one. To
6916 * ensure GTK+ invariants are maintained (resize queue does what it
6917 * should), we go ahead and size_allocate the requested size in this
6920 * If the configure request has not changed, we don't ever resend
6921 * it, because it could mean fighting the user or window manager.
6924 * To prepare the configure request, we come up with a base size/pos:
6925 * - the one from gtk_window_move()/gtk_window_resize()
6926 * - else default_width, default_height if we haven't ever
6928 * - else the size request if we haven't ever been mapped,
6929 * as a substitute default size
6930 * - else the current size of the window, as received from
6931 * configure notifies (i.e. the current allocation)
6933 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6934 * the position request to be centered.
6936 GtkWindowPrivate *priv = window->priv;
6937 GtkAllocation allocation;
6939 GtkContainer *container;
6940 GtkWindowGeometryInfo *info;
6941 GdkGeometry new_geometry;
6942 GdkWindow *gdk_window;
6944 GdkRectangle new_request;
6945 gboolean configure_request_size_changed;
6946 gboolean configure_request_pos_changed;
6947 gboolean hints_changed; /* do we need to send these again */
6948 GtkWindowLastGeometryInfo saved_last_info;
6950 widget = GTK_WIDGET (window);
6952 gdk_window = gtk_widget_get_window (widget);
6953 container = GTK_CONTAINER (widget);
6954 info = gtk_window_get_geometry_info (window, TRUE);
6956 configure_request_size_changed = FALSE;
6957 configure_request_pos_changed = FALSE;
6959 gtk_window_compute_configure_request (window, &new_request,
6960 &new_geometry, &new_flags);
6962 /* This check implies the invariant that we never set info->last
6963 * without setting the hints and sending off a configure request.
6965 * If we change info->last without sending the request, we may
6968 if (info->last.configure_request.x != new_request.x ||
6969 info->last.configure_request.y != new_request.y)
6970 configure_request_pos_changed = TRUE;
6972 if ((info->last.configure_request.width != new_request.width ||
6973 info->last.configure_request.height != new_request.height))
6974 configure_request_size_changed = TRUE;
6976 hints_changed = FALSE;
6978 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6979 &new_geometry, new_flags))
6981 hints_changed = TRUE;
6984 /* Position Constraints
6985 * ====================
6987 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6988 * a default. The other POS_ values are used only when the
6989 * window is shown, not after that.
6991 * However, we can't implement a position constraint as
6992 * "anytime the window size changes, center the window"
6993 * because this may well end up fighting the WM or user. In
6994 * fact it gets in an infinite loop with at least one WM.
6996 * Basically, applications are in no way in a position to
6997 * constrain the position of a window, with one exception:
6998 * override redirect windows. (Really the intended purpose
6999 * of CENTER_ALWAYS anyhow, I would think.)
7001 * So the way we implement this "constraint" is to say that when WE
7002 * cause a move or resize, i.e. we make a configure request changing
7003 * window size, we recompute the CENTER_ALWAYS position to reflect
7004 * the new window size, and include it in our request. Also, if we
7005 * just turned on CENTER_ALWAYS we snap to center with a new
7006 * request. Otherwise, if we are just NOTIFIED of a move or resize
7007 * done by someone else e.g. the window manager, we do NOT send a
7008 * new configure request.
7010 * For override redirect windows, this works fine; all window
7011 * sizes are from our configure requests. For managed windows,
7012 * it is at least semi-sane, though who knows what the
7013 * app author is thinking.
7016 /* This condition should be kept in sync with the condition later on
7017 * that determines whether we send a configure request. i.e. we
7018 * should do this position constraining anytime we were going to
7019 * send a configure request anyhow, plus when constraints have
7022 if (configure_request_pos_changed ||
7023 configure_request_size_changed ||
7025 info->position_constraints_changed)
7027 /* We request the constrained position if:
7028 * - we were changing position, and need to clamp
7029 * the change to the constraint
7030 * - we're changing the size anyway
7031 * - set_position() was called to toggle CENTER_ALWAYS on
7034 gtk_window_constrain_position (window,
7040 /* Update whether we need to request a move */
7041 if (info->last.configure_request.x != new_request.x ||
7042 info->last.configure_request.y != new_request.y)
7043 configure_request_pos_changed = TRUE;
7045 configure_request_pos_changed = FALSE;
7049 if (priv->type == GTK_WINDOW_TOPLEVEL)
7051 int notify_x, notify_y;
7053 /* this is the position from the last configure notify */
7054 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
7056 g_message ("--- %s ---\n"
7057 "last : %d,%d\t%d x %d\n"
7058 "this : %d,%d\t%d x %d\n"
7059 "alloc : %d,%d\t%d x %d\n"
7061 "resize: \t%d x %d\n"
7062 "size_changed: %d pos_changed: %d hints_changed: %d\n"
7063 "configure_notify_received: %d\n"
7064 "configure_request_count: %d\n"
7065 "position_constraints_changed: %d\n",
7066 priv->title ? priv->title : "(no title)",
7067 info->last.configure_request.x,
7068 info->last.configure_request.y,
7069 info->last.configure_request.width,
7070 info->last.configure_request.height,
7076 widget->allocation.width,
7077 widget->allocation.height,
7078 widget->requisition.width,
7079 widget->requisition.height,
7081 info->resize_height,
7082 configure_request_pos_changed,
7083 configure_request_size_changed,
7085 priv->configure_notify_received,
7086 priv->configure_request_count,
7087 info->position_constraints_changed);
7091 saved_last_info = info->last;
7092 info->last.geometry = new_geometry;
7093 info->last.flags = new_flags;
7094 info->last.configure_request = new_request;
7096 /* need to set PPosition so the WM will look at our position,
7097 * but we don't want to count PPosition coming and going as a hints
7098 * change for future iterations. So we saved info->last prior to
7102 /* Also, if the initial position was explicitly set, then we always
7103 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
7107 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
7108 * this is an initial map
7111 if ((configure_request_pos_changed ||
7112 info->initial_pos_set ||
7113 (priv->need_default_position &&
7114 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
7115 (new_flags & GDK_HINT_POS) == 0)
7117 new_flags |= GDK_HINT_POS;
7118 hints_changed = TRUE;
7121 /* Set hints if necessary
7124 gdk_window_set_geometry_hints (gdk_window,
7130 allocation.width = gdk_window_get_width (gdk_window);
7131 allocation.height = gdk_window_get_height (gdk_window);
7133 /* handle resizing/moving and widget tree allocation
7135 if (priv->configure_notify_received)
7137 /* If we have received a configure event since
7138 * the last time in this function, we need to
7139 * accept our new size and size_allocate child widgets.
7140 * (see gtk_window_configure_event() for more details).
7142 * 1 or more configure notifies may have been received.
7143 * Also, configure_notify_received will only be TRUE
7144 * if all expected configure notifies have been received
7145 * (one per configure request), as an optimization.
7148 priv->configure_notify_received = FALSE;
7150 /* gtk_window_configure_event() filled in widget->allocation */
7151 gtk_widget_size_allocate (widget, &allocation);
7153 set_grip_position (window);
7154 update_grip_visibility (window);
7156 gdk_window_process_updates (gdk_window, TRUE);
7158 gdk_window_configure_finished (gdk_window);
7160 /* If the configure request changed, it means that
7162 * 1) coincidentally changed hints or widget properties
7163 * impacting the configure request before getting
7164 * a configure notify, or
7165 * 2) some broken widget is changing its size request
7166 * during size allocation, resulting in
7167 * a false appearance of changed configure request.
7169 * For 1), we could just go ahead and ask for the
7170 * new size right now, but doing that for 2)
7171 * might well be fighting the user (and can even
7172 * trigger a loop). Since we really don't want to
7173 * do that, we requeue a resize in hopes that
7174 * by the time it gets handled, the child has seen
7175 * the light and is willing to go along with the
7176 * new size. (this happens for the zvt widget, since
7177 * the size_allocate() above will have stored the
7178 * requisition corresponding to the new size in the
7181 * This doesn't buy us anything for 1), but it shouldn't
7182 * hurt us too badly, since it is what would have
7183 * happened if we had gotten the configure event before
7184 * the new size had been set.
7187 if (configure_request_size_changed ||
7188 configure_request_pos_changed)
7190 /* Don't change the recorded last info after all, because we
7191 * haven't actually updated to the new info yet - we decided
7192 * to postpone our configure request until later.
7194 info->last = saved_last_info;
7196 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7199 return; /* Bail out, we didn't really process the move/resize */
7201 else if ((configure_request_size_changed || hints_changed) &&
7202 (allocation.width != new_request.width || allocation.height != new_request.height))
7205 /* We are in one of the following situations:
7206 * A. configure_request_size_changed
7207 * our requisition has changed and we need a different window size,
7208 * so we request it from the window manager.
7209 * B. !configure_request_size_changed && hints_changed
7210 * the window manager rejects our size, but we have just changed the
7211 * window manager hints, so there's a chance our request will
7212 * be honoured this time, so we try again.
7214 * However, if the new requisition is the same as the current allocation,
7215 * we don't request it again, since we won't get a ConfigureNotify back from
7216 * the window manager unless it decides to change our requisition. If
7217 * we don't get the ConfigureNotify back, the resize queue will never be run.
7220 /* Now send the configure request */
7221 if (configure_request_pos_changed)
7223 gdk_window_move_resize (gdk_window,
7224 new_request.x, new_request.y,
7225 new_request.width, new_request.height);
7227 else /* only size changed */
7229 gdk_window_resize (gdk_window,
7230 new_request.width, new_request.height);
7233 if (priv->type == GTK_WINDOW_POPUP)
7235 GtkAllocation allocation;
7237 /* Directly size allocate for override redirect (popup) windows. */
7240 allocation.width = new_request.width;
7241 allocation.height = new_request.height;
7243 gtk_widget_size_allocate (widget, &allocation);
7245 gdk_window_process_updates (gdk_window, TRUE);
7247 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7248 gtk_widget_queue_draw (widget);
7252 /* Increment the number of have-not-yet-received-notify requests */
7253 priv->configure_request_count += 1;
7254 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7256 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7257 * configure event in response to our resizing request.
7258 * the configure event will cause a new resize with
7259 * ->configure_notify_received=TRUE.
7260 * until then, we want to
7261 * - discard expose events
7262 * - coalesce resizes for our children
7263 * - defer any window resizes until the configure event arrived
7264 * to achieve this, we queue a resize for the window, but remove its
7265 * resizing handler, so resizing will not be handled from the next
7266 * idle handler but when the configure event arrives.
7268 * FIXME: we should also dequeue the pending redraws here, since
7269 * we handle those ourselves upon ->configure_notify_received==TRUE.
7271 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7273 gtk_widget_queue_resize_no_redraw (widget);
7274 _gtk_container_dequeue_resize_handler (container);
7280 /* Handle any position changes.
7282 if (configure_request_pos_changed)
7284 gdk_window_move (gdk_window,
7285 new_request.x, new_request.y);
7288 /* And run the resize queue.
7290 gtk_container_resize_children (container);
7293 /* We have now processed a move/resize since the last position
7294 * constraint change, setting of the initial position, or resize.
7295 * (Not resetting these flags here can lead to infinite loops for
7296 * GTK_RESIZE_IMMEDIATE containers)
7298 info->position_constraints_changed = FALSE;
7299 info->initial_pos_set = FALSE;
7300 info->resize_width = -1;
7301 info->resize_height = -1;
7304 /* Compare two sets of Geometry hints for equality.
7307 gtk_window_compare_hints (GdkGeometry *geometry_a,
7309 GdkGeometry *geometry_b,
7312 if (flags_a != flags_b)
7315 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7316 (geometry_a->min_width != geometry_b->min_width ||
7317 geometry_a->min_height != geometry_b->min_height))
7320 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7321 (geometry_a->max_width != geometry_b->max_width ||
7322 geometry_a->max_height != geometry_b->max_height))
7325 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7326 (geometry_a->base_width != geometry_b->base_width ||
7327 geometry_a->base_height != geometry_b->base_height))
7330 if ((flags_a & GDK_HINT_ASPECT) &&
7331 (geometry_a->min_aspect != geometry_b->min_aspect ||
7332 geometry_a->max_aspect != geometry_b->max_aspect))
7335 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7336 (geometry_a->width_inc != geometry_b->width_inc ||
7337 geometry_a->height_inc != geometry_b->height_inc))
7340 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7341 geometry_a->win_gravity != geometry_b->win_gravity)
7348 _gtk_window_constrain_size (GtkWindow *window,
7354 GtkWindowPrivate *priv;
7355 GtkWindowGeometryInfo *info;
7357 g_return_if_fail (GTK_IS_WINDOW (window));
7359 priv = window->priv;
7361 info = priv->geometry_info;
7364 GdkWindowHints flags = info->last.flags;
7365 GdkGeometry *geometry = &info->last.geometry;
7367 gtk_window_constrain_size (window,
7378 gtk_window_constrain_size (GtkWindow *window,
7379 GdkGeometry *geometry,
7386 gdk_window_constrain_size (geometry, flags, width, height,
7387 new_width, new_height);
7390 /* Compute the set of geometry hints and flags for a window
7391 * based on the application set geometry, and requisition
7392 * of the window. gtk_widget_get_preferred_size() must have been
7396 gtk_window_compute_hints (GtkWindow *window,
7397 GdkGeometry *new_geometry,
7400 GtkWindowPrivate *priv = window->priv;
7402 gint extra_width = 0;
7403 gint extra_height = 0;
7404 GtkWindowGeometryInfo *geometry_info;
7405 GtkRequisition requisition;
7407 widget = GTK_WIDGET (window);
7409 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7410 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7414 *new_flags = geometry_info->mask;
7415 *new_geometry = geometry_info->geometry;
7422 if (geometry_info && geometry_info->widget)
7424 /* If the geometry widget is set, then the hints really apply to that
7425 * widget. This is pretty much meaningless unless the window layout
7426 * is such that the rest of the window adds fixed size borders to
7427 * the geometry widget. Our job is to figure the size of the borders;
7428 * We do that by asking how big the toplevel would be if the
7429 * geometry widget was *really big*.
7432 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7433 * |GGGGG B| in the border can confuse things
7439 * |AAAAAAAAA | When the geometry widget is large, things are
7440 * |GGGGGGGGGGB| clearer.
7445 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7446 GtkRequisition requisition;
7447 int current_width, current_height;
7449 _gtk_widget_override_size_request (geometry_info->widget,
7450 TEMPORARY_SIZE, TEMPORARY_SIZE,
7451 ¤t_width, ¤t_height);
7452 gtk_widget_get_preferred_size (widget,
7453 &requisition, NULL);
7454 _gtk_widget_restore_size_request (geometry_info->widget,
7455 current_width, current_height);
7457 extra_width = requisition.width - TEMPORARY_SIZE;
7458 extra_height = requisition.height - TEMPORARY_SIZE;
7460 if (extra_width < 0 || extra_height < 0)
7462 g_warning("Toplevel size doesn't seem to directly depend on the "
7463 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7464 "The geometry widget might not be in the window, or it might not "
7465 "be packed into the window appropriately");
7466 extra_width = MAX(extra_width, 0);
7467 extra_height = MAX(extra_height, 0);
7469 #undef TEMPORARY_SIZE
7472 /* We don't want to set GDK_HINT_POS in here, we just set it
7473 * in gtk_window_move_resize() when we want the position
7477 if (*new_flags & GDK_HINT_BASE_SIZE)
7479 new_geometry->base_width += extra_width;
7480 new_geometry->base_height += extra_height;
7484 /* For simplicity, we always set the base hint, even when we
7485 * don't expect it to have any visible effect.
7486 * (Note: geometry_size_to_pixels() depends on this.)
7488 *new_flags |= GDK_HINT_BASE_SIZE;
7490 new_geometry->base_width = extra_width;
7491 new_geometry->base_height = extra_height;
7493 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7494 * base size is the minimum size */
7495 if (*new_flags & GDK_HINT_MIN_SIZE)
7497 if (new_geometry->min_width > 0)
7498 new_geometry->base_width += new_geometry->min_width;
7499 if (new_geometry->min_height > 0)
7500 new_geometry->base_height += new_geometry->min_height;
7504 /* Please use a good size for unresizable widgets, not the minimum one. */
7505 if (!priv->resizable)
7506 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7508 if (*new_flags & GDK_HINT_MIN_SIZE)
7510 if (new_geometry->min_width < 0)
7511 new_geometry->min_width = requisition.width;
7513 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7515 if (new_geometry->min_height < 0)
7516 new_geometry->min_height = requisition.height;
7518 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7522 *new_flags |= GDK_HINT_MIN_SIZE;
7524 new_geometry->min_width = requisition.width;
7525 new_geometry->min_height = requisition.height;
7528 if (*new_flags & GDK_HINT_MAX_SIZE)
7530 if (new_geometry->max_width < 0)
7531 new_geometry->max_width = requisition.width;
7533 new_geometry->max_width += extra_width;
7535 if (new_geometry->max_height < 0)
7536 new_geometry->max_height = requisition.height;
7538 new_geometry->max_height += extra_height;
7540 else if (!priv->resizable)
7542 *new_flags |= GDK_HINT_MAX_SIZE;
7544 new_geometry->max_width = requisition.width;
7545 new_geometry->max_height = requisition.height;
7548 *new_flags |= GDK_HINT_WIN_GRAVITY;
7549 new_geometry->win_gravity = priv->gravity;
7552 /***********************
7553 * Redrawing functions *
7554 ***********************/
7557 gtk_window_draw (GtkWidget *widget,
7560 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7561 GtkStyleContext *context;
7562 gboolean ret = FALSE;
7564 context = gtk_widget_get_style_context (widget);
7566 if (!gtk_widget_get_app_paintable (widget) &&
7567 gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
7569 gtk_render_background (context, cr, 0, 0,
7570 gtk_widget_get_allocated_width (widget),
7571 gtk_widget_get_allocated_height (widget));
7574 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7575 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7577 if (priv->grip_window &&
7578 gtk_cairo_should_draw_window (cr, priv->grip_window))
7582 gtk_style_context_save (context);
7585 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7586 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7588 gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND);
7589 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7590 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7591 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7594 gtk_style_context_restore (context);
7601 * gtk_window_present:
7602 * @window: a #GtkWindow
7604 * Presents a window to the user. This may mean raising the window
7605 * in the stacking order, deiconifying it, moving it to the current
7606 * desktop, and/or giving it the keyboard focus, possibly dependent
7607 * on the user's platform, window manager, and preferences.
7609 * If @window is hidden, this function calls gtk_widget_show()
7612 * This function should be used when the user tries to open a window
7613 * that's already open. Say for example the preferences dialog is
7614 * currently open, and the user chooses Preferences from the menu
7615 * a second time; use gtk_window_present() to move the already-open dialog
7616 * where the user can see it.
7618 * If you are calling this function in response to a user interaction,
7619 * it is preferable to use gtk_window_present_with_time().
7623 gtk_window_present (GtkWindow *window)
7625 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7629 * gtk_window_present_with_time:
7630 * @window: a #GtkWindow
7631 * @timestamp: the timestamp of the user interaction (typically a
7632 * button or key press event) which triggered this call
7634 * Presents a window to the user in response to a user interaction.
7635 * If you need to present a window without a timestamp, use
7636 * gtk_window_present(). See gtk_window_present() for details.
7641 gtk_window_present_with_time (GtkWindow *window,
7644 GtkWindowPrivate *priv;
7646 GdkWindow *gdk_window;
7648 g_return_if_fail (GTK_IS_WINDOW (window));
7650 priv = window->priv;
7651 widget = GTK_WIDGET (window);
7653 if (gtk_widget_get_visible (widget))
7655 gdk_window = gtk_widget_get_window (widget);
7657 g_assert (gdk_window != NULL);
7659 gdk_window_show (gdk_window);
7661 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7662 if (timestamp == GDK_CURRENT_TIME)
7664 #ifdef GDK_WINDOWING_X11
7665 if (GDK_IS_X11_WINDOW(gdk_window))
7667 GdkDisplay *display;
7669 display = gtk_widget_get_display (GTK_WIDGET (window));
7670 timestamp = gdk_x11_display_get_user_time (display);
7674 timestamp = gtk_get_current_event_time ();
7677 gdk_window_focus (gdk_window, timestamp);
7681 priv->initial_timestamp = timestamp;
7682 gtk_widget_show (widget);
7687 * gtk_window_iconify:
7688 * @window: a #GtkWindow
7690 * Asks to iconify (i.e. minimize) the specified @window. Note that
7691 * you shouldn't assume the window is definitely iconified afterward,
7692 * because other entities (e.g. the user or <link
7693 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7694 * again, or there may not be a window manager in which case
7695 * iconification isn't possible, etc. But normally the window will end
7696 * up iconified. Just don't write code that crashes if not.
7698 * It's permitted to call this function before showing a window,
7699 * in which case the window will be iconified before it ever appears
7702 * You can track iconification via the "window-state-event" signal
7707 gtk_window_iconify (GtkWindow *window)
7709 GtkWindowPrivate *priv;
7711 GdkWindow *toplevel;
7713 g_return_if_fail (GTK_IS_WINDOW (window));
7715 priv = window->priv;
7716 widget = GTK_WIDGET (window);
7718 priv->iconify_initially = TRUE;
7720 toplevel = gtk_widget_get_window (widget);
7722 if (toplevel != NULL)
7723 gdk_window_iconify (toplevel);
7727 * gtk_window_deiconify:
7728 * @window: a #GtkWindow
7730 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7731 * that you shouldn't assume the window is definitely deiconified
7732 * afterward, because other entities (e.g. the user or <link
7733 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7734 * again before your code which assumes deiconification gets to run.
7736 * You can track iconification via the "window-state-event" signal
7740 gtk_window_deiconify (GtkWindow *window)
7742 GtkWindowPrivate *priv;
7744 GdkWindow *toplevel;
7746 g_return_if_fail (GTK_IS_WINDOW (window));
7748 priv = window->priv;
7749 widget = GTK_WIDGET (window);
7751 priv->iconify_initially = FALSE;
7753 toplevel = gtk_widget_get_window (widget);
7755 if (toplevel != NULL)
7756 gdk_window_deiconify (toplevel);
7761 * @window: a #GtkWindow
7763 * Asks to stick @window, which means that it will appear on all user
7764 * desktops. Note that you shouldn't assume the window is definitely
7765 * stuck afterward, because other entities (e.g. the user or <link
7766 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7767 * again, and some window managers do not support sticking
7768 * windows. But normally the window will end up stuck. Just don't
7769 * write code that crashes if not.
7771 * It's permitted to call this function before showing a window.
7773 * You can track stickiness via the "window-state-event" signal
7778 gtk_window_stick (GtkWindow *window)
7780 GtkWindowPrivate *priv;
7782 GdkWindow *toplevel;
7784 g_return_if_fail (GTK_IS_WINDOW (window));
7786 priv = window->priv;
7787 widget = GTK_WIDGET (window);
7789 priv->stick_initially = TRUE;
7791 toplevel = gtk_widget_get_window (widget);
7793 if (toplevel != NULL)
7794 gdk_window_stick (toplevel);
7798 * gtk_window_unstick:
7799 * @window: a #GtkWindow
7801 * Asks to unstick @window, which means that it will appear on only
7802 * one of the user's desktops. Note that you shouldn't assume the
7803 * window is definitely unstuck afterward, because other entities
7804 * (e.g. the user or <link linkend="gtk-X11-arch">window
7805 * manager</link>) could stick it again. But normally the window will
7806 * end up stuck. Just don't write code that crashes if not.
7808 * You can track stickiness via the "window-state-event" signal
7813 gtk_window_unstick (GtkWindow *window)
7815 GtkWindowPrivate *priv;
7817 GdkWindow *toplevel;
7819 g_return_if_fail (GTK_IS_WINDOW (window));
7821 priv = window->priv;
7822 widget = GTK_WIDGET (window);
7824 priv->stick_initially = FALSE;
7826 toplevel = gtk_widget_get_window (widget);
7828 if (toplevel != NULL)
7829 gdk_window_unstick (toplevel);
7833 * gtk_window_maximize:
7834 * @window: a #GtkWindow
7836 * Asks to maximize @window, so that it becomes full-screen. Note that
7837 * you shouldn't assume the window is definitely maximized afterward,
7838 * because other entities (e.g. the user or <link
7839 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7840 * again, and not all window managers support maximization. But
7841 * normally the window will end up maximized. Just don't write code
7842 * that crashes if not.
7844 * It's permitted to call this function before showing a window,
7845 * in which case the window will be maximized when it appears onscreen
7848 * You can track maximization via the "window-state-event" signal
7853 gtk_window_maximize (GtkWindow *window)
7855 GtkWindowPrivate *priv;
7857 GdkWindow *toplevel;
7859 g_return_if_fail (GTK_IS_WINDOW (window));
7861 priv = window->priv;
7862 widget = GTK_WIDGET (window);
7864 priv->maximize_initially = TRUE;
7866 toplevel = gtk_widget_get_window (widget);
7868 if (toplevel != NULL)
7869 gdk_window_maximize (toplevel);
7873 * gtk_window_unmaximize:
7874 * @window: a #GtkWindow
7876 * Asks to unmaximize @window. Note that you shouldn't assume the
7877 * window is definitely unmaximized afterward, because other entities
7878 * (e.g. the user or <link linkend="gtk-X11-arch">window
7879 * manager</link>) could maximize it again, and not all window
7880 * managers honor requests to unmaximize. But normally the window will
7881 * end up unmaximized. Just don't write code that crashes if not.
7883 * You can track maximization via the "window-state-event" signal
7888 gtk_window_unmaximize (GtkWindow *window)
7890 GtkWindowPrivate *priv;
7892 GdkWindow *toplevel;
7894 g_return_if_fail (GTK_IS_WINDOW (window));
7896 priv = window->priv;
7897 widget = GTK_WIDGET (window);
7899 priv->maximize_initially = FALSE;
7901 toplevel = gtk_widget_get_window (widget);
7903 if (toplevel != NULL)
7904 gdk_window_unmaximize (toplevel);
7908 * gtk_window_fullscreen:
7909 * @window: a #GtkWindow
7911 * Asks to place @window in the fullscreen state. Note that you
7912 * shouldn't assume the window is definitely full screen afterward,
7913 * because other entities (e.g. the user or <link
7914 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7915 * again, and not all window managers honor requests to fullscreen
7916 * windows. But normally the window will end up fullscreen. Just
7917 * don't write code that crashes if not.
7919 * You can track the fullscreen state via the "window-state-event" signal
7925 gtk_window_fullscreen (GtkWindow *window)
7927 GtkWindowPrivate *priv;
7929 GdkWindow *toplevel;
7931 g_return_if_fail (GTK_IS_WINDOW (window));
7933 priv = window->priv;
7934 widget = GTK_WIDGET (window);
7936 priv->fullscreen_initially = TRUE;
7938 toplevel = gtk_widget_get_window (widget);
7940 if (toplevel != NULL)
7941 gdk_window_fullscreen (toplevel);
7945 * gtk_window_unfullscreen:
7946 * @window: a #GtkWindow
7948 * Asks to toggle off the fullscreen state for @window. Note that you
7949 * shouldn't assume the window is definitely not full screen
7950 * afterward, because other entities (e.g. the user or <link
7951 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7952 * again, and not all window managers honor requests to unfullscreen
7953 * windows. But normally the window will end up restored to its normal
7954 * state. Just don't write code that crashes if not.
7956 * You can track the fullscreen state via the "window-state-event" signal
7962 gtk_window_unfullscreen (GtkWindow *window)
7965 GdkWindow *toplevel;
7966 GtkWindowPrivate *priv;
7968 g_return_if_fail (GTK_IS_WINDOW (window));
7970 priv = window->priv;
7971 widget = GTK_WIDGET (window);
7973 priv->fullscreen_initially = FALSE;
7975 toplevel = gtk_widget_get_window (widget);
7977 if (toplevel != NULL)
7978 gdk_window_unfullscreen (toplevel);
7982 * gtk_window_set_keep_above:
7983 * @window: a #GtkWindow
7984 * @setting: whether to keep @window above other windows
7986 * Asks to keep @window above, so that it stays on top. Note that
7987 * you shouldn't assume the window is definitely above afterward,
7988 * because other entities (e.g. the user or <link
7989 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7990 * and not all window managers support keeping windows above. But
7991 * normally the window will end kept above. Just don't write code
7992 * that crashes if not.
7994 * It's permitted to call this function before showing a window,
7995 * in which case the window will be kept above when it appears onscreen
7998 * You can track the above state via the "window-state-event" signal
8001 * Note that, according to the <ulink
8002 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8003 * Manager Hints</ulink> specification, the above state is mainly meant
8004 * for user preferences and should not be used by applications e.g. for
8005 * drawing attention to their dialogs.
8010 gtk_window_set_keep_above (GtkWindow *window,
8014 GtkWindowPrivate *priv;
8015 GdkWindow *toplevel;
8017 g_return_if_fail (GTK_IS_WINDOW (window));
8019 priv = window->priv;
8020 widget = GTK_WIDGET (window);
8022 priv->above_initially = setting != FALSE;
8024 priv->below_initially = FALSE;
8026 toplevel = gtk_widget_get_window (widget);
8028 if (toplevel != NULL)
8029 gdk_window_set_keep_above (toplevel, setting);
8033 * gtk_window_set_keep_below:
8034 * @window: a #GtkWindow
8035 * @setting: whether to keep @window below other windows
8037 * Asks to keep @window below, so that it stays in bottom. Note that
8038 * you shouldn't assume the window is definitely below afterward,
8039 * because other entities (e.g. the user or <link
8040 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8041 * and not all window managers support putting windows below. But
8042 * normally the window will be kept below. Just don't write code
8043 * that crashes if not.
8045 * It's permitted to call this function before showing a window,
8046 * in which case the window will be kept below when it appears onscreen
8049 * You can track the below state via the "window-state-event" signal
8052 * Note that, according to the <ulink
8053 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8054 * Manager Hints</ulink> specification, the above state is mainly meant
8055 * for user preferences and should not be used by applications e.g. for
8056 * drawing attention to their dialogs.
8061 gtk_window_set_keep_below (GtkWindow *window,
8065 GtkWindowPrivate *priv;
8066 GdkWindow *toplevel;
8068 g_return_if_fail (GTK_IS_WINDOW (window));
8070 priv = window->priv;
8071 widget = GTK_WIDGET (window);
8073 priv->below_initially = setting != FALSE;
8075 priv->above_initially = FALSE;
8077 toplevel = gtk_widget_get_window (widget);
8079 if (toplevel != NULL)
8080 gdk_window_set_keep_below (toplevel, setting);
8084 * gtk_window_set_resizable:
8085 * @window: a #GtkWindow
8086 * @resizable: %TRUE if the user can resize this window
8088 * Sets whether the user can resize a window. Windows are user resizable
8092 gtk_window_set_resizable (GtkWindow *window,
8095 GtkWindowPrivate *priv;
8097 g_return_if_fail (GTK_IS_WINDOW (window));
8099 priv = window->priv;
8101 resizable = (resizable != FALSE);
8103 if (priv->resizable != resizable)
8105 priv->resizable = resizable;
8107 update_grip_visibility (window);
8109 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8111 g_object_notify (G_OBJECT (window), "resizable");
8116 * gtk_window_get_resizable:
8117 * @window: a #GtkWindow
8119 * Gets the value set by gtk_window_set_resizable().
8121 * Return value: %TRUE if the user can resize the window
8124 gtk_window_get_resizable (GtkWindow *window)
8126 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8128 return window->priv->resizable;
8132 * gtk_window_set_gravity:
8133 * @window: a #GtkWindow
8134 * @gravity: window gravity
8136 * Window gravity defines the meaning of coordinates passed to
8137 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8140 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8141 * typically "do what you mean."
8145 gtk_window_set_gravity (GtkWindow *window,
8148 GtkWindowPrivate *priv;
8150 g_return_if_fail (GTK_IS_WINDOW (window));
8152 priv = window->priv;
8154 if (gravity != priv->gravity)
8156 priv->gravity = gravity;
8158 /* gtk_window_move_resize() will adapt gravity
8160 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8162 g_object_notify (G_OBJECT (window), "gravity");
8167 * gtk_window_get_gravity:
8168 * @window: a #GtkWindow
8170 * Gets the value set by gtk_window_set_gravity().
8172 * Return value: (transfer none): window gravity
8175 gtk_window_get_gravity (GtkWindow *window)
8177 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8179 return window->priv->gravity;
8183 * gtk_window_begin_resize_drag:
8184 * @window: a #GtkWindow
8185 * @button: mouse button that initiated the drag
8186 * @edge: position of the resize control
8187 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8188 * @root_y: Y position where the user clicked to initiate the drag
8189 * @timestamp: timestamp from the click event that initiated the drag
8191 * Starts resizing a window. This function is used if an application
8192 * has window resizing controls. When GDK can support it, the resize
8193 * will be done using the standard mechanism for the <link
8194 * linkend="gtk-X11-arch">window manager</link> or windowing
8195 * system. Otherwise, GDK will try to emulate window resizing,
8196 * potentially not all that well, depending on the windowing system.
8200 gtk_window_begin_resize_drag (GtkWindow *window,
8208 GdkWindow *toplevel;
8210 g_return_if_fail (GTK_IS_WINDOW (window));
8211 widget = GTK_WIDGET (window);
8212 g_return_if_fail (gtk_widget_get_visible (widget));
8214 toplevel = gtk_widget_get_window (widget);
8216 gdk_window_begin_resize_drag (toplevel,
8223 * gtk_window_begin_move_drag:
8224 * @window: a #GtkWindow
8225 * @button: mouse button that initiated the drag
8226 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8227 * @root_y: Y position where the user clicked to initiate the drag
8228 * @timestamp: timestamp from the click event that initiated the drag
8230 * Starts moving a window. This function is used if an application has
8231 * window movement grips. When GDK can support it, the window movement
8232 * will be done using the standard mechanism for the <link
8233 * linkend="gtk-X11-arch">window manager</link> or windowing
8234 * system. Otherwise, GDK will try to emulate window movement,
8235 * potentially not all that well, depending on the windowing system.
8239 gtk_window_begin_move_drag (GtkWindow *window,
8246 GdkWindow *toplevel;
8248 g_return_if_fail (GTK_IS_WINDOW (window));
8249 widget = GTK_WIDGET (window);
8250 g_return_if_fail (gtk_widget_get_visible (widget));
8252 toplevel = gtk_widget_get_window (widget);
8254 gdk_window_begin_move_drag (toplevel,
8261 * gtk_window_set_screen:
8262 * @window: a #GtkWindow.
8263 * @screen: a #GdkScreen.
8265 * Sets the #GdkScreen where the @window is displayed; if
8266 * the window is already mapped, it will be unmapped, and
8267 * then remapped on the new screen.
8272 gtk_window_set_screen (GtkWindow *window,
8275 GtkWindowPrivate *priv;
8277 GdkScreen *previous_screen;
8278 gboolean was_mapped;
8280 g_return_if_fail (GTK_IS_WINDOW (window));
8281 g_return_if_fail (GDK_IS_SCREEN (screen));
8283 priv = window->priv;
8285 if (screen == priv->screen)
8288 widget = GTK_WIDGET (window);
8290 previous_screen = priv->screen;
8291 was_mapped = gtk_widget_get_mapped (widget);
8294 gtk_widget_unmap (widget);
8295 if (gtk_widget_get_realized (widget))
8296 gtk_widget_unrealize (widget);
8298 gtk_window_free_key_hash (window);
8299 priv->screen = screen;
8300 gtk_widget_reset_rc_styles (widget);
8301 if (screen != previous_screen)
8303 if (previous_screen)
8305 g_signal_handlers_disconnect_by_func (previous_screen,
8306 gtk_window_on_composited_changed, window);
8307 #ifdef GDK_WINDOWING_X11
8308 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8309 gtk_window_on_theme_variant_changed, window);
8312 g_signal_connect (screen, "composited-changed",
8313 G_CALLBACK (gtk_window_on_composited_changed), window);
8314 #ifdef GDK_WINDOWING_X11
8315 g_signal_connect (gtk_settings_get_for_screen (screen),
8316 "notify::gtk-application-prefer-dark-theme",
8317 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8320 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8321 _gtk_widget_propagate_composited_changed (widget);
8323 g_object_notify (G_OBJECT (window), "screen");
8326 gtk_widget_map (widget);
8330 gtk_window_set_theme_variant (GtkWindow *window)
8332 #ifdef GDK_WINDOWING_X11
8333 GdkWindow *gdk_window;
8334 gboolean dark_theme_requested;
8336 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8337 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8340 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8342 if (GDK_IS_X11_WINDOW (gdk_window))
8343 gdk_x11_window_set_theme_variant (gdk_window,
8344 dark_theme_requested ? "dark" : NULL);
8349 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8353 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8354 gtk_window_set_theme_variant (window);
8358 gtk_window_on_composited_changed (GdkScreen *screen,
8361 gtk_widget_queue_draw (GTK_WIDGET (window));
8363 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8367 gtk_window_check_screen (GtkWindow *window)
8369 GtkWindowPrivate *priv = window->priv;
8372 return priv->screen;
8375 g_warning ("Screen for GtkWindow not set; you must always set\n"
8376 "a screen for a GtkWindow before using the window");
8382 * gtk_window_get_screen:
8383 * @window: a #GtkWindow.
8385 * Returns the #GdkScreen associated with @window.
8387 * Return value: (transfer none): a #GdkScreen.
8392 gtk_window_get_screen (GtkWindow *window)
8394 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8396 return window->priv->screen;
8400 * gtk_window_is_active:
8401 * @window: a #GtkWindow
8403 * Returns whether the window is part of the current active toplevel.
8404 * (That is, the toplevel window receiving keystrokes.)
8405 * The return value is %TRUE if the window is active toplevel
8406 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8407 * You might use this function if you wanted to draw a widget
8408 * differently in an active window from a widget in an inactive window.
8409 * See gtk_window_has_toplevel_focus()
8411 * Return value: %TRUE if the window part of the current active window.
8416 gtk_window_is_active (GtkWindow *window)
8418 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8420 return window->priv->is_active;
8424 * gtk_window_has_toplevel_focus:
8425 * @window: a #GtkWindow
8427 * Returns whether the input focus is within this GtkWindow.
8428 * For real toplevel windows, this is identical to gtk_window_is_active(),
8429 * but for embedded windows, like #GtkPlug, the results will differ.
8431 * Return value: %TRUE if the input focus is within this GtkWindow
8436 gtk_window_has_toplevel_focus (GtkWindow *window)
8438 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8440 return window->priv->has_toplevel_focus;
8445 * SECTION:gtkwindowgroup
8446 * @Short_description: Limit the effect of grabs
8447 * @Title: GtkWindowGroup
8449 * #GtkWindowGroup objects are referenced by each window in the group,
8450 * so once you have added all windows to a #GtkWindowGroup, you can drop
8451 * the initial reference to the window group with g_object_unref(). If the
8452 * windows in the window group are subsequently destroyed, then they will
8453 * be removed from the window group and drop their references on the window
8454 * group; when all window have been removed, the window group will be
8458 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8461 gtk_window_group_init (GtkWindowGroup *group)
8463 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8464 GTK_TYPE_WINDOW_GROUP,
8465 GtkWindowGroupPrivate);
8469 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8471 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8475 * gtk_window_group_new:
8477 * Creates a new #GtkWindowGroup object. Grabs added with
8478 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8480 * Return value: a new #GtkWindowGroup.
8483 gtk_window_group_new (void)
8485 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8489 window_group_cleanup_grabs (GtkWindowGroup *group,
8492 GtkWindowGroupPrivate *priv;
8493 GtkDeviceGrabInfo *info;
8495 GSList *to_remove = NULL;
8499 tmp_list = priv->grabs;
8502 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8503 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8504 tmp_list = tmp_list->next;
8509 gtk_grab_remove (to_remove->data);
8510 g_object_unref (to_remove->data);
8511 to_remove = g_slist_delete_link (to_remove, to_remove);
8514 tmp_list = priv->device_grabs;
8518 info = tmp_list->data;
8520 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8521 to_remove = g_slist_prepend (to_remove, info);
8523 tmp_list = tmp_list->next;
8528 info = to_remove->data;
8530 gtk_device_grab_remove (info->widget, info->device);
8531 to_remove = g_slist_delete_link (to_remove, to_remove);
8536 * gtk_window_group_add_window:
8537 * @window_group: a #GtkWindowGroup
8538 * @window: the #GtkWindow to add
8540 * Adds a window to a #GtkWindowGroup.
8543 gtk_window_group_add_window (GtkWindowGroup *window_group,
8546 GtkWindowPrivate *priv;
8548 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8549 g_return_if_fail (GTK_IS_WINDOW (window));
8551 priv = window->priv;
8553 if (priv->group != window_group)
8555 g_object_ref (window);
8556 g_object_ref (window_group);
8559 gtk_window_group_remove_window (priv->group, window);
8561 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8563 priv->group = window_group;
8565 g_object_unref (window);
8570 * gtk_window_group_remove_window:
8571 * @window_group: a #GtkWindowGroup
8572 * @window: the #GtkWindow to remove
8574 * Removes a window from a #GtkWindowGroup.
8577 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8580 GtkWindowPrivate *priv;
8582 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8583 g_return_if_fail (GTK_IS_WINDOW (window));
8584 priv = window->priv;
8585 g_return_if_fail (priv->group == window_group);
8587 g_object_ref (window);
8589 window_group_cleanup_grabs (window_group, window);
8592 g_object_unref (window_group);
8593 g_object_unref (window);
8597 * gtk_window_group_list_windows:
8598 * @window_group: a #GtkWindowGroup
8600 * Returns a list of the #GtkWindows that belong to @window_group.
8602 * Returns: (element-type GtkWindow) (transfer container): A
8603 * newly-allocated list of windows inside the group.
8608 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8610 GList *toplevels, *toplevel, *group_windows;
8612 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8614 group_windows = NULL;
8615 toplevels = gtk_window_list_toplevels ();
8617 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8619 GtkWindow *window = toplevel->data;
8621 if (window_group == window->priv->group)
8622 group_windows = g_list_prepend (group_windows, window);
8625 g_list_free (toplevels);
8627 return g_list_reverse (group_windows);
8631 * gtk_window_get_group:
8632 * @window: (allow-none): a #GtkWindow, or %NULL
8634 * Returns the group for @window or the default group, if
8635 * @window is %NULL or if @window does not have an explicit
8638 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8643 gtk_window_get_group (GtkWindow *window)
8645 if (window && window->priv->group)
8646 return window->priv->group;
8649 static GtkWindowGroup *default_group = NULL;
8652 default_group = gtk_window_group_new ();
8654 return default_group;
8659 * gtk_window_has_group:
8660 * @window: a #GtkWindow
8662 * Returns whether @window has an explicit window group.
8664 * Return value: %TRUE if @window has an explicit window group.
8669 gtk_window_has_group (GtkWindow *window)
8671 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8673 return window->priv->group != NULL;
8677 * gtk_window_group_get_current_grab:
8678 * @window_group: a #GtkWindowGroup
8680 * Gets the current grab widget of the given group,
8681 * see gtk_grab_add().
8683 * Returns: (transfer none): the current grab widget of the group
8688 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8690 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8692 if (window_group->priv->grabs)
8693 return GTK_WIDGET (window_group->priv->grabs->data);
8698 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8701 GtkWindowGroupPrivate *priv;
8703 priv = window_group->priv;
8704 priv->grabs = g_slist_prepend (priv->grabs, widget);
8708 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8711 GtkWindowGroupPrivate *priv;
8713 priv = window_group->priv;
8714 priv->grabs = g_slist_remove (priv->grabs, widget);
8719 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8722 gboolean block_others)
8724 GtkWindowGroupPrivate *priv;
8725 GtkDeviceGrabInfo *info;
8727 priv = window_group->priv;
8729 info = g_slice_new0 (GtkDeviceGrabInfo);
8730 info->widget = widget;
8731 info->device = device;
8732 info->block_others = block_others;
8734 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8738 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8742 GtkWindowGroupPrivate *priv;
8743 GtkDeviceGrabInfo *info;
8744 GSList *list, *node = NULL;
8745 GdkDevice *other_device;
8747 priv = window_group->priv;
8748 other_device = gdk_device_get_associated_device (device);
8749 list = priv->device_grabs;
8755 if (info->widget == widget &&
8756 (info->device == device ||
8757 info->device == other_device))
8770 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8771 g_slice_free (GtkDeviceGrabInfo, info);
8776 * gtk_window_group_get_current_device_grab:
8777 * @window_group: a #GtkWindowGroup
8778 * @device: a #GdkDevice
8780 * Returns the current grab widget for @device, or %NULL if none.
8782 * Returns: (transfer none): The grab widget, or %NULL
8787 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8790 GtkWindowGroupPrivate *priv;
8791 GtkDeviceGrabInfo *info;
8792 GdkDevice *other_device;
8795 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8796 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8798 priv = window_group->priv;
8799 list = priv->device_grabs;
8800 other_device = gdk_device_get_associated_device (device);
8807 if (info->device == device ||
8808 info->device == other_device)
8809 return info->widget;
8816 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8820 GtkWindowGroupPrivate *priv;
8821 GtkDeviceGrabInfo *info;
8822 GdkDevice *other_device;
8825 priv = window_group->priv;
8826 other_device = gdk_device_get_associated_device (device);
8827 list = priv->device_grabs;
8834 /* Look for blocking grabs on other device pairs
8835 * that have the passed widget within the GTK+ grab.
8837 if (info->block_others &&
8838 info->device != device &&
8839 info->device != other_device &&
8840 (info->widget == widget ||
8841 gtk_widget_is_ancestor (widget, info->widget)))
8849 Derived from XParseGeometry() in XFree86
8851 Copyright 1985, 1986, 1987,1998 The Open Group
8853 All Rights Reserved.
8855 The above copyright notice and this permission notice shall be included
8856 in all copies or substantial portions of the Software.
8858 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8859 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8860 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8861 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8862 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8863 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8864 OTHER DEALINGS IN THE SOFTWARE.
8866 Except as contained in this notice, the name of The Open Group shall
8867 not be used in advertising or otherwise to promote the sale, use or
8868 other dealings in this Software without prior written authorization
8869 from The Open Group.
8874 * XParseGeometry parses strings of the form
8875 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8876 * width, height, xoffset, and yoffset are unsigned integers.
8877 * Example: "=80x24+300-49"
8878 * The equal sign is optional.
8879 * It returns a bitmask that indicates which of the four values
8880 * were actually found in the string. For each value found,
8881 * the corresponding argument is updated; for each value
8882 * not found, the corresponding argument is left unchanged.
8885 /* The following code is from Xlib, and is minimally modified, so we
8886 * can track any upstream changes if required. Don't change this
8887 * code. Or if you do, put in a huge comment marking which thing
8892 read_int (gchar *string,
8900 else if (*string == '-')
8906 for (; (*string >= '0') && (*string <= '9'); string++)
8908 result = (result * 10) + (*string - '0');
8920 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8921 * value (x, y, width, height) was found in the parsed string.
8923 #define NoValue 0x0000
8924 #define XValue 0x0001
8925 #define YValue 0x0002
8926 #define WidthValue 0x0004
8927 #define HeightValue 0x0008
8928 #define AllValues 0x000F
8929 #define XNegative 0x0010
8930 #define YNegative 0x0020
8932 /* Try not to reformat/modify, so we can compare/sync with X sources */
8934 gtk_XParseGeometry (const char *string,
8937 unsigned int *width,
8938 unsigned int *height)
8942 unsigned int tempWidth, tempHeight;
8944 char *nextCharacter;
8946 /* These initializations are just to silence gcc */
8952 if ( (string == NULL) || (*string == '\0')) return(mask);
8954 string++; /* ignore possible '=' at beg of geometry spec */
8956 strind = (char *)string;
8957 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8958 tempWidth = read_int(strind, &nextCharacter);
8959 if (strind == nextCharacter)
8961 strind = nextCharacter;
8965 if (*strind == 'x' || *strind == 'X') {
8967 tempHeight = read_int(strind, &nextCharacter);
8968 if (strind == nextCharacter)
8970 strind = nextCharacter;
8971 mask |= HeightValue;
8974 if ((*strind == '+') || (*strind == '-')) {
8975 if (*strind == '-') {
8977 tempX = -read_int(strind, &nextCharacter);
8978 if (strind == nextCharacter)
8980 strind = nextCharacter;
8986 tempX = read_int(strind, &nextCharacter);
8987 if (strind == nextCharacter)
8989 strind = nextCharacter;
8992 if ((*strind == '+') || (*strind == '-')) {
8993 if (*strind == '-') {
8995 tempY = -read_int(strind, &nextCharacter);
8996 if (strind == nextCharacter)
8998 strind = nextCharacter;
9005 tempY = read_int(strind, &nextCharacter);
9006 if (strind == nextCharacter)
9008 strind = nextCharacter;
9014 /* If strind isn't at the end of the string the it's an invalid
9015 geometry specification. */
9017 if (*strind != '\0') return (0);
9023 if (mask & WidthValue)
9025 if (mask & HeightValue)
9026 *height = tempHeight;
9031 * gtk_window_parse_geometry:
9032 * @window: a #GtkWindow
9033 * @geometry: geometry string
9035 * Parses a standard X Window System geometry string - see the
9036 * manual page for X (type 'man X') for details on this.
9037 * gtk_window_parse_geometry() does work on all GTK+ ports
9038 * including Win32 but is primarily intended for an X environment.
9040 * If either a size or a position can be extracted from the
9041 * geometry string, gtk_window_parse_geometry() returns %TRUE
9042 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9043 * to resize/move the window.
9045 * If gtk_window_parse_geometry() returns %TRUE, it will also
9046 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9047 * indicating to the window manager that the size/position of
9048 * the window was user-specified. This causes most window
9049 * managers to honor the geometry.
9051 * Note that for gtk_window_parse_geometry() to work as expected, it has
9052 * to be called when the window has its "final" size, i.e. after calling
9053 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9056 * #include <gtk/gtk.h>
9059 * fill_with_content (GtkWidget *vbox)
9061 * /* fill with content... */
9065 * main (int argc, char *argv[])
9067 * GtkWidget *window, *vbox;
9068 * GdkGeometry size_hints = {
9069 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9072 * gtk_init (&argc, &argv);
9074 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9075 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9077 * gtk_container_add (GTK_CONTAINER (window), vbox);
9078 * fill_with_content (vbox);
9079 * gtk_widget_show_all (vbox);
9081 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9084 * GDK_HINT_MIN_SIZE |
9085 * GDK_HINT_BASE_SIZE |
9086 * GDK_HINT_RESIZE_INC);
9090 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9091 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9094 * gtk_widget_show_all (window);
9101 * Return value: %TRUE if string was parsed successfully
9104 gtk_window_parse_geometry (GtkWindow *window,
9105 const gchar *geometry)
9107 gint result, x = 0, y = 0;
9111 gboolean size_set, pos_set;
9114 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9115 g_return_val_if_fail (geometry != NULL, FALSE);
9117 child = gtk_bin_get_child (GTK_BIN (window));
9118 if (!child || !gtk_widget_get_visible (child))
9119 g_warning ("gtk_window_parse_geometry() called on a window with no "
9120 "visible children; the window should be set up before "
9121 "gtk_window_parse_geometry() is called.");
9123 screen = gtk_window_check_screen (window);
9125 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9128 if ((result & WidthValue) || (result & HeightValue))
9130 gtk_window_set_default_size_internal (window,
9131 TRUE, result & WidthValue ? w : -1,
9132 TRUE, result & HeightValue ? h : -1,
9137 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9139 grav = GDK_GRAVITY_NORTH_WEST;
9141 if ((result & XNegative) && (result & YNegative))
9142 grav = GDK_GRAVITY_SOUTH_EAST;
9143 else if (result & XNegative)
9144 grav = GDK_GRAVITY_NORTH_EAST;
9145 else if (result & YNegative)
9146 grav = GDK_GRAVITY_SOUTH_WEST;
9148 if ((result & XValue) == 0)
9151 if ((result & YValue) == 0)
9154 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9155 grav == GDK_GRAVITY_SOUTH_EAST)
9156 y = gdk_screen_get_height (screen) - h + y;
9158 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9159 grav == GDK_GRAVITY_NORTH_EAST)
9160 x = gdk_screen_get_width (screen) - w + x;
9162 /* we don't let you put a window offscreen; maybe some people would
9163 * prefer to be able to, but it's kind of a bogus thing to do.
9172 if ((result & XValue) || (result & YValue))
9174 gtk_window_set_gravity (window, grav);
9175 gtk_window_move (window, x, y);
9179 if (size_set || pos_set)
9181 /* Set USSize, USPosition hints */
9182 GtkWindowGeometryInfo *info;
9184 info = gtk_window_get_geometry_info (window, TRUE);
9187 info->mask |= GDK_HINT_USER_POS;
9189 info->mask |= GDK_HINT_USER_SIZE;
9196 gtk_window_mnemonic_hash_foreach (guint keyval,
9202 GtkWindowKeysForeachFunc func;
9206 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9210 _gtk_window_keys_foreach (GtkWindow *window,
9211 GtkWindowKeysForeachFunc func,
9215 GtkMnemonicHash *mnemonic_hash;
9219 GtkWindowKeysForeachFunc func;
9223 info.window = window;
9225 info.func_data = func_data;
9227 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9229 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9230 gtk_window_mnemonic_hash_foreach, &info);
9232 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9235 GtkAccelGroup *group = groups->data;
9238 for (i = 0; i < group->priv->n_accels; i++)
9240 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9243 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9246 groups = groups->next;
9251 gtk_window_keys_changed (GtkWindow *window)
9253 gtk_window_free_key_hash (window);
9254 gtk_window_get_key_hash (window);
9257 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9259 struct _GtkWindowKeyEntry
9263 guint is_mnemonic : 1;
9267 window_key_entry_destroy (gpointer data)
9269 g_slice_free (GtkWindowKeyEntry, data);
9273 add_to_key_hash (GtkWindow *window,
9275 GdkModifierType modifiers,
9276 gboolean is_mnemonic,
9279 GtkKeyHash *key_hash = data;
9281 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9283 entry->keyval = keyval;
9284 entry->modifiers = modifiers;
9285 entry->is_mnemonic = is_mnemonic;
9287 /* GtkAccelGroup stores lowercased accelerators. To deal
9288 * with this, if <Shift> was specified, uppercase.
9290 if (modifiers & GDK_SHIFT_MASK)
9292 if (keyval == GDK_KEY_Tab)
9293 keyval = GDK_KEY_ISO_Left_Tab;
9295 keyval = gdk_keyval_to_upper (keyval);
9298 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9302 gtk_window_get_key_hash (GtkWindow *window)
9304 GdkScreen *screen = gtk_window_check_screen (window);
9305 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9310 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9311 (GDestroyNotify)window_key_entry_destroy);
9312 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9313 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9319 gtk_window_free_key_hash (GtkWindow *window)
9321 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9324 _gtk_key_hash_free (key_hash);
9325 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9330 * gtk_window_activate_key:
9331 * @window: a #GtkWindow
9332 * @event: a #GdkEventKey
9334 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9335 * called by the default ::key_press_event handler for toplevel windows,
9336 * however in some cases it may be useful to call this directly when
9337 * overriding the standard key handling for a toplevel window.
9339 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9344 gtk_window_activate_key (GtkWindow *window,
9347 GtkKeyHash *key_hash;
9348 GtkWindowKeyEntry *found_entry = NULL;
9349 gboolean enable_mnemonics;
9350 gboolean enable_accels;
9352 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9353 g_return_val_if_fail (event != NULL, FALSE);
9355 key_hash = gtk_window_get_key_hash (window);
9360 GSList *entries = _gtk_key_hash_lookup (key_hash,
9361 event->hardware_keycode,
9363 gtk_accelerator_get_default_mod_mask (),
9366 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9367 "gtk-enable-mnemonics", &enable_mnemonics,
9368 "gtk-enable-accels", &enable_accels,
9371 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9373 GtkWindowKeyEntry *entry = tmp_list->data;
9374 if (entry->is_mnemonic)
9376 if (enable_mnemonics)
9378 found_entry = entry;
9384 if (enable_accels && !found_entry)
9386 found_entry = entry;
9391 g_slist_free (entries);
9396 if (found_entry->is_mnemonic)
9398 if (enable_mnemonics)
9399 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9400 found_entry->modifiers);
9405 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9406 found_entry->modifiers);
9414 window_update_has_focus (GtkWindow *window)
9416 GtkWindowPrivate *priv = window->priv;
9417 GtkWidget *widget = GTK_WIDGET (window);
9418 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9420 if (has_focus != priv->has_focus)
9422 priv->has_focus = has_focus;
9426 if (priv->focus_widget &&
9427 priv->focus_widget != widget &&
9428 !gtk_widget_has_focus (priv->focus_widget))
9429 do_focus_change (priv->focus_widget, TRUE);
9433 if (priv->focus_widget &&
9434 priv->focus_widget != widget &&
9435 gtk_widget_has_focus (priv->focus_widget))
9436 do_focus_change (priv->focus_widget, FALSE);
9442 * _gtk_window_set_is_active:
9443 * @window: a #GtkWindow
9444 * @is_active: %TRUE if the window is in the currently active toplevel
9446 * Internal function that sets whether the #GtkWindow is part
9447 * of the currently active toplevel window (taking into account inter-process
9451 _gtk_window_set_is_active (GtkWindow *window,
9454 GtkWindowPrivate *priv;
9456 g_return_if_fail (GTK_IS_WINDOW (window));
9458 priv = window->priv;
9460 is_active = is_active != FALSE;
9462 if (is_active != priv->is_active)
9464 priv->is_active = is_active;
9465 window_update_has_focus (window);
9467 g_object_notify (G_OBJECT (window), "is-active");
9472 * _gtk_window_set_is_toplevel:
9473 * @window: a #GtkWindow
9474 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9475 * child of the root window); %FALSE if it is not (for example, for an
9476 * in-process, parented GtkPlug)
9478 * Internal function used by #GtkPlug when it gets parented/unparented by a
9479 * #GtkSocket. This keeps the @window's #GTK_WINDOW_TOPLEVEL flag in sync
9480 * with the global list of toplevel windows.
9483 _gtk_window_set_is_toplevel (GtkWindow *window,
9484 gboolean is_toplevel)
9487 GtkWidget *toplevel;
9489 widget = GTK_WIDGET (window);
9491 if (gtk_widget_is_toplevel (widget))
9492 g_assert (g_slist_find (toplevel_list, window) != NULL);
9494 g_assert (g_slist_find (toplevel_list, window) == NULL);
9496 if (is_toplevel == gtk_widget_is_toplevel (widget))
9501 /* Pass through regular pathways of an embedded toplevel
9502 * to go through unmapping and hiding the widget before
9503 * becomming a toplevel again.
9505 * We remain hidden after becomming toplevel in order to
9506 * avoid problems during an embedded toplevel's dispose cycle
9507 * (When a toplevel window is shown it tries to grab focus again,
9508 * this causes problems while disposing).
9510 gtk_widget_hide (widget);
9512 /* Save the toplevel this widget was previously anchored into before
9513 * propagating a hierarchy-changed.
9515 * Usually this happens by way of gtk_widget_unparent() and we are
9516 * already unanchored at this point, just adding this clause incase
9517 * things happen differently.
9519 toplevel = gtk_widget_get_toplevel (widget);
9520 if (!gtk_widget_is_toplevel (toplevel))
9523 _gtk_widget_set_is_toplevel (widget, TRUE);
9525 /* When a window becomes toplevel after being embedded and anchored
9526 * into another window we need to unset its anchored flag so that
9527 * the hierarchy changed signal kicks in properly.
9529 _gtk_widget_set_anchored (widget, FALSE);
9530 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9532 toplevel_list = g_slist_prepend (toplevel_list, window);
9536 _gtk_widget_set_is_toplevel (widget, FALSE);
9537 toplevel_list = g_slist_remove (toplevel_list, window);
9539 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9544 * _gtk_window_set_has_toplevel_focus:
9545 * @window: a #GtkWindow
9546 * @has_toplevel_focus: %TRUE if the in
9548 * Internal function that sets whether the keyboard focus for the
9549 * toplevel window (taking into account inter-process embedding.)
9552 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9553 gboolean has_toplevel_focus)
9555 GtkWindowPrivate *priv;
9557 g_return_if_fail (GTK_IS_WINDOW (window));
9559 priv = window->priv;
9561 has_toplevel_focus = has_toplevel_focus != FALSE;
9563 if (has_toplevel_focus != priv->has_toplevel_focus)
9565 priv->has_toplevel_focus = has_toplevel_focus;
9566 window_update_has_focus (window);
9568 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9573 * gtk_window_set_auto_startup_notification:
9574 * @setting: %TRUE to automatically do startup notification
9576 * By default, after showing the first #GtkWindow, GTK+ calls
9577 * gdk_notify_startup_complete(). Call this function to disable
9578 * the automatic startup notification. You might do this if your
9579 * first window is a splash screen, and you want to delay notification
9580 * until after your real main window has been shown, for example.
9582 * In that example, you would disable startup notification
9583 * temporarily, show your splash screen, then re-enable it so that
9584 * showing the main window would automatically result in notification.
9589 gtk_window_set_auto_startup_notification (gboolean setting)
9591 disable_startup_notification = !setting;
9595 * gtk_window_get_window_type:
9596 * @window: a #GtkWindow
9598 * Gets the type of the window. See #GtkWindowType.
9600 * Return value: the type of the window
9605 gtk_window_get_window_type (GtkWindow *window)
9607 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9609 return window->priv->type;
9613 * gtk_window_get_mnemonics_visible:
9614 * @window: a #GtkWindow
9616 * Gets the value of the #GtkWindow:mnemonics-visible property.
9618 * Returns: %TRUE if mnemonics are supposed to be visible
9624 gtk_window_get_mnemonics_visible (GtkWindow *window)
9626 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9628 return window->priv->mnemonics_visible;
9632 * gtk_window_set_mnemonics_visible:
9633 * @window: a #GtkWindow
9634 * @setting: the new value
9636 * Sets the #GtkWindow:mnemonics-visible property.
9641 gtk_window_set_mnemonics_visible (GtkWindow *window,
9644 GtkWindowPrivate *priv;
9646 g_return_if_fail (GTK_IS_WINDOW (window));
9648 priv = window->priv;
9650 setting = setting != FALSE;
9652 if (priv->mnemonics_visible != setting)
9654 priv->mnemonics_visible = setting;
9655 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9658 if (priv->auto_mnemonics_timeout_id)
9660 g_source_remove (priv->auto_mnemonics_timeout_id);
9661 priv->auto_mnemonics_timeout_id = 0;
9664 priv->mnemonics_visible_set = TRUE;
9668 set_auto_mnemonics_visible_cb (gpointer data)
9670 GtkWindow *window = data;
9672 gtk_window_set_mnemonics_visible (window, TRUE);
9674 window->priv->auto_mnemonics_timeout_id = 0;
9680 _gtk_window_set_auto_mnemonics_visible (GtkWindow *window)
9682 g_return_if_fail (GTK_IS_WINDOW (window));
9684 if (window->priv->auto_mnemonics_timeout_id)
9687 window->priv->auto_mnemonics_timeout_id =
9688 gdk_threads_add_timeout (AUTO_MNEMONICS_DELAY, set_auto_mnemonics_visible_cb, window);
9692 * gtk_window_get_focus_visible:
9693 * @window: a #GtkWindow
9695 * Gets the value of the #GtkWindow:focus-visible property.
9697 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9703 gtk_window_get_focus_visible (GtkWindow *window)
9705 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9707 return window->priv->focus_visible;
9711 * gtk_window_set_focus_visible:
9712 * @window: a #GtkWindow
9713 * @setting: the new value
9715 * Sets the #GtkWindow:focus-visible property.
9720 gtk_window_set_focus_visible (GtkWindow *window,
9723 GtkWindowPrivate *priv;
9725 g_return_if_fail (GTK_IS_WINDOW (window));
9727 priv = window->priv;
9729 setting = setting != FALSE;
9731 if (priv->focus_visible != setting)
9733 priv->focus_visible = setting;
9734 g_object_notify (G_OBJECT (window), "focus-visible");
9739 _gtk_window_get_wmclass (GtkWindow *window,
9740 gchar **wmclass_name,
9741 gchar **wmclass_class)
9743 GtkWindowPrivate *priv = window->priv;
9745 *wmclass_name = priv->wmclass_name;
9746 *wmclass_class = priv->wmclass_class;
9750 * gtk_window_set_has_user_ref_count:
9751 * @window: a #GtkWindow
9752 * @setting: the new value
9754 * Tells GTK+ whether to drop its extra reference to the window
9755 * when gtk_widget_destroy() is called.
9757 * This function is only exported for the benefit of language
9758 * bindings which may need to keep the window alive until their
9759 * wrapper object is garbage collected. There is no justification
9760 * for ever calling this function in an application.
9765 gtk_window_set_has_user_ref_count (GtkWindow *window,
9768 g_return_if_fail (GTK_IS_WINDOW (window));
9770 window->priv->has_user_ref_count = setting;
9774 ensure_state_flag_backdrop (GtkWidget *widget)
9777 gboolean window_focused = TRUE;
9779 window = gtk_widget_get_window (widget);
9781 window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9783 if (!window_focused)
9784 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
9786 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
9788 gtk_widget_queue_draw (widget);