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 #ifdef GDK_WINDOWING_X11
426 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
430 static void gtk_window_set_theme_variant (GtkWindow *window);
432 static GSList *toplevel_list = NULL;
433 static guint window_signals[LAST_SIGNAL] = { 0 };
434 static GList *default_icon_list = NULL;
435 static gchar *default_icon_name = NULL;
436 static guint default_icon_serial = 0;
437 static gboolean disable_startup_notification = FALSE;
438 static gboolean sent_startup_notification = FALSE;
440 static GQuark quark_gtk_embedded = 0;
441 static GQuark quark_gtk_window_key_hash = 0;
442 static GQuark quark_gtk_window_icon_info = 0;
443 static GQuark quark_gtk_buildable_accels = 0;
445 static GtkBuildableIface *parent_buildable_iface;
447 static void gtk_window_set_property (GObject *object,
451 static void gtk_window_get_property (GObject *object,
457 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
458 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
461 const GValue *value);
462 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
463 GtkBuilder *builder);
464 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
467 const gchar *tagname,
468 GMarkupParser *parser,
470 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
473 const gchar *tagname,
476 static void ensure_state_flag_backdrop (GtkWidget *widget);
478 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
479 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
480 gtk_window_buildable_interface_init))
483 add_tab_bindings (GtkBindingSet *binding_set,
484 GdkModifierType modifiers,
485 GtkDirectionType direction)
487 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
489 GTK_TYPE_DIRECTION_TYPE, direction);
490 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
492 GTK_TYPE_DIRECTION_TYPE, direction);
496 add_arrow_bindings (GtkBindingSet *binding_set,
498 GtkDirectionType direction)
500 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
502 gtk_binding_entry_add_signal (binding_set, keysym, 0,
504 GTK_TYPE_DIRECTION_TYPE, direction);
505 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
507 GTK_TYPE_DIRECTION_TYPE, direction);
508 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
510 GTK_TYPE_DIRECTION_TYPE, direction);
511 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
513 GTK_TYPE_DIRECTION_TYPE, direction);
517 extract_time_from_startup_id (const gchar* startup_id)
519 gchar *timestr = g_strrstr (startup_id, "_TIME");
520 guint32 retval = GDK_CURRENT_TIME;
527 /* Skip past the "_TIME" part */
532 timestamp = g_ascii_strtoull (timestr, &end, 0);
533 if (errno == 0 && end != timestr)
541 startup_id_is_fake (const gchar* startup_id)
543 return strncmp (startup_id, "_TIME", 5) == 0;
547 gtk_window_class_init (GtkWindowClass *klass)
549 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
550 GtkWidgetClass *widget_class;
551 GtkContainerClass *container_class;
552 GtkBindingSet *binding_set;
554 widget_class = (GtkWidgetClass*) klass;
555 container_class = (GtkContainerClass*) klass;
557 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
558 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
559 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
560 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
562 gobject_class->dispose = gtk_window_dispose;
563 gobject_class->finalize = gtk_window_finalize;
565 gobject_class->set_property = gtk_window_set_property;
566 gobject_class->get_property = gtk_window_get_property;
568 widget_class->destroy = gtk_window_destroy;
569 widget_class->show = gtk_window_show;
570 widget_class->hide = gtk_window_hide;
571 widget_class->map = gtk_window_map;
572 widget_class->map_event = gtk_window_map_event;
573 widget_class->unmap = gtk_window_unmap;
574 widget_class->realize = gtk_window_realize;
575 widget_class->unrealize = gtk_window_unrealize;
576 widget_class->size_allocate = gtk_window_size_allocate;
577 widget_class->configure_event = gtk_window_configure_event;
578 widget_class->key_press_event = gtk_window_key_press_event;
579 widget_class->key_release_event = gtk_window_key_release_event;
580 widget_class->enter_notify_event = gtk_window_enter_notify_event;
581 widget_class->leave_notify_event = gtk_window_leave_notify_event;
582 widget_class->focus_in_event = gtk_window_focus_in_event;
583 widget_class->button_press_event = gtk_window_button_press_event;
584 widget_class->focus_out_event = gtk_window_focus_out_event;
585 widget_class->focus = gtk_window_focus;
586 widget_class->move_focus = gtk_window_move_focus;
587 widget_class->draw = gtk_window_draw;
588 widget_class->window_state_event = gtk_window_state_event;
589 widget_class->direction_changed = gtk_window_direction_changed;
590 widget_class->state_changed = gtk_window_state_changed;
591 widget_class->style_updated = gtk_window_style_updated;
593 container_class->check_resize = gtk_window_check_resize;
595 klass->set_focus = gtk_window_real_set_focus;
597 klass->activate_default = gtk_window_real_activate_default;
598 klass->activate_focus = gtk_window_real_activate_focus;
599 klass->keys_changed = gtk_window_keys_changed;
601 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
604 g_object_class_install_property (gobject_class,
606 g_param_spec_enum ("type",
608 P_("The type of the window"),
609 GTK_TYPE_WINDOW_TYPE,
611 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
613 g_object_class_install_property (gobject_class,
615 g_param_spec_string ("title",
617 P_("The title of the window"),
619 GTK_PARAM_READWRITE));
621 g_object_class_install_property (gobject_class,
623 g_param_spec_string ("role",
625 P_("Unique identifier for the window to be used when restoring a session"),
627 GTK_PARAM_READWRITE));
630 * GtkWindow:startup-id:
632 * The :startup-id is a write-only property for setting window's
633 * startup notification identifier. See gtk_window_set_startup_id()
638 g_object_class_install_property (gobject_class,
640 g_param_spec_string ("startup-id",
642 P_("Unique startup identifier for the window used by startup-notification"),
644 GTK_PARAM_WRITABLE));
646 g_object_class_install_property (gobject_class,
648 g_param_spec_boolean ("resizable",
650 P_("If TRUE, users can resize the window"),
652 GTK_PARAM_READWRITE));
654 g_object_class_install_property (gobject_class,
656 g_param_spec_boolean ("modal",
658 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
660 GTK_PARAM_READWRITE));
662 g_object_class_install_property (gobject_class,
664 g_param_spec_enum ("window-position",
665 P_("Window Position"),
666 P_("The initial position of the window"),
667 GTK_TYPE_WINDOW_POSITION,
669 GTK_PARAM_READWRITE));
671 g_object_class_install_property (gobject_class,
673 g_param_spec_int ("default-width",
675 P_("The default width of the window, used when initially showing the window"),
679 GTK_PARAM_READWRITE));
681 g_object_class_install_property (gobject_class,
683 g_param_spec_int ("default-height",
684 P_("Default Height"),
685 P_("The default height of the window, used when initially showing the window"),
689 GTK_PARAM_READWRITE));
691 g_object_class_install_property (gobject_class,
692 PROP_DESTROY_WITH_PARENT,
693 g_param_spec_boolean ("destroy-with-parent",
694 P_("Destroy with Parent"),
695 P_("If this window should be destroyed when the parent is destroyed"),
697 GTK_PARAM_READWRITE));
700 * GtkWindow:hide-titlebar-when-maximized:
702 * Whether the titlebar should be hidden during maximization.
706 g_object_class_install_property (gobject_class,
707 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
708 g_param_spec_boolean ("hide-titlebar-when-maximized",
709 P_("Hide the titlebar during maximization"),
710 P_("If this window's titlebar should be hidden when the window is maximized"),
712 GTK_PARAM_READWRITE));
714 g_object_class_install_property (gobject_class,
716 g_param_spec_object ("icon",
718 P_("Icon for this window"),
720 GTK_PARAM_READWRITE));
723 * GtkWindow:mnemonics-visible:
725 * Whether mnemonics are currently visible in this window.
727 * This property is maintained by GTK+ based on the
728 * #GtkSettings:gtk-auto-mnemonics setting and user input,
729 * and should not be set by applications.
733 g_object_class_install_property (gobject_class,
734 PROP_MNEMONICS_VISIBLE,
735 g_param_spec_boolean ("mnemonics-visible",
736 P_("Mnemonics Visible"),
737 P_("Whether mnemonics are currently visible in this window"),
739 GTK_PARAM_READWRITE));
742 * GtkWindow:focus-visible:
744 * Whether 'focus rectangles' are currently visible in this window.
746 * This property is maintained by GTK+ based on the
747 * #GtkSettings:gtk-visible-focus setting and user input
748 * and should not be set by applications.
752 g_object_class_install_property (gobject_class,
754 g_param_spec_boolean ("focus-visible",
756 P_("Whether focus rectangles are currently visible in this window"),
758 GTK_PARAM_READWRITE));
761 * GtkWindow:icon-name:
763 * The :icon-name property specifies the name of the themed icon to
764 * use as the window icon. See #GtkIconTheme for more details.
768 g_object_class_install_property (gobject_class,
770 g_param_spec_string ("icon-name",
772 P_("Name of the themed icon for this window"),
774 GTK_PARAM_READWRITE));
776 g_object_class_install_property (gobject_class,
778 g_param_spec_object ("screen",
780 P_("The screen where this window will be displayed"),
782 GTK_PARAM_READWRITE));
784 g_object_class_install_property (gobject_class,
786 g_param_spec_boolean ("is-active",
788 P_("Whether the toplevel is the current active window"),
790 GTK_PARAM_READABLE));
792 g_object_class_install_property (gobject_class,
793 PROP_HAS_TOPLEVEL_FOCUS,
794 g_param_spec_boolean ("has-toplevel-focus",
795 P_("Focus in Toplevel"),
796 P_("Whether the input focus is within this GtkWindow"),
798 GTK_PARAM_READABLE));
800 g_object_class_install_property (gobject_class,
802 g_param_spec_enum ("type-hint",
804 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
805 GDK_TYPE_WINDOW_TYPE_HINT,
806 GDK_WINDOW_TYPE_HINT_NORMAL,
807 GTK_PARAM_READWRITE));
809 g_object_class_install_property (gobject_class,
810 PROP_SKIP_TASKBAR_HINT,
811 g_param_spec_boolean ("skip-taskbar-hint",
813 P_("TRUE if the window should not be in the task bar."),
815 GTK_PARAM_READWRITE));
817 g_object_class_install_property (gobject_class,
818 PROP_SKIP_PAGER_HINT,
819 g_param_spec_boolean ("skip-pager-hint",
821 P_("TRUE if the window should not be in the pager."),
823 GTK_PARAM_READWRITE));
825 g_object_class_install_property (gobject_class,
827 g_param_spec_boolean ("urgency-hint",
829 P_("TRUE if the window should be brought to the user's attention."),
831 GTK_PARAM_READWRITE));
834 * GtkWindow:accept-focus:
836 * Whether the window should receive the input focus.
840 g_object_class_install_property (gobject_class,
842 g_param_spec_boolean ("accept-focus",
844 P_("TRUE if the window should receive the input focus."),
846 GTK_PARAM_READWRITE));
849 * GtkWindow:focus-on-map:
851 * Whether the window should receive the input focus when mapped.
855 g_object_class_install_property (gobject_class,
857 g_param_spec_boolean ("focus-on-map",
859 P_("TRUE if the window should receive the input focus when mapped."),
861 GTK_PARAM_READWRITE));
864 * GtkWindow:decorated:
866 * Whether the window should be decorated by the window manager.
870 g_object_class_install_property (gobject_class,
872 g_param_spec_boolean ("decorated",
874 P_("Whether the window should be decorated by the window manager"),
876 GTK_PARAM_READWRITE));
879 * GtkWindow:deletable:
881 * Whether the window frame should have a close button.
885 g_object_class_install_property (gobject_class,
887 g_param_spec_boolean ("deletable",
889 P_("Whether the window frame should have a close button"),
891 GTK_PARAM_READWRITE));
894 * GtkWindow:has-resize-grip:
896 * Whether the window has a corner resize grip.
898 * Note that the resize grip is only shown if the window is
899 * actually resizable and not maximized. Use
900 * #GtkWindow:resize-grip-visible to find out if the resize
901 * grip is currently shown.
905 g_object_class_install_property (gobject_class,
906 PROP_HAS_RESIZE_GRIP,
907 g_param_spec_boolean ("has-resize-grip",
909 P_("Specifies whether the window should have a resize grip"),
911 GTK_PARAM_READWRITE));
914 * GtkWindow:resize-grip-visible:
916 * Whether a corner resize grip is currently shown.
920 g_object_class_install_property (gobject_class,
921 PROP_RESIZE_GRIP_VISIBLE,
922 g_param_spec_boolean ("resize-grip-visible",
923 P_("Resize grip is visible"),
924 P_("Specifies whether the window's resize grip is visible."),
926 GTK_PARAM_READABLE));
932 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
933 * more details about window gravity.
937 g_object_class_install_property (gobject_class,
939 g_param_spec_enum ("gravity",
941 P_("The window gravity of the window"),
943 GDK_GRAVITY_NORTH_WEST,
944 GTK_PARAM_READWRITE));
948 * GtkWindow:transient-for:
950 * The transient parent of the window. See gtk_window_set_transient_for() for
951 * more details about transient windows.
955 g_object_class_install_property (gobject_class,
957 g_param_spec_object ("transient-for",
958 P_("Transient for Window"),
959 P_("The transient parent of the dialog"),
961 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
964 * GtkWindow:attached-to:
966 * The widget to which this window is attached.
967 * See gtk_window_set_attached_to().
969 * Examples of places where specifying this relation is useful are
970 * for instance a #GtkMenu created by a #GtkComboBox, a completion
971 * popup window created by #GtkEntry or a typeahead search entry
972 * created by #GtkTreeView.
976 g_object_class_install_property (gobject_class,
978 g_param_spec_object ("attached-to",
979 P_("Attached to Widget"),
980 P_("The widget where the window is attached"),
982 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
986 gtk_widget_class_install_style_property (widget_class,
987 g_param_spec_int ("resize-grip-width",
988 P_("Width of resize grip"),
989 P_("Width of resize grip"),
990 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
992 gtk_widget_class_install_style_property (widget_class,
993 g_param_spec_int ("resize-grip-height",
994 P_("Height of resize grip"),
995 P_("Height of resize grip"),
996 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1000 * GtkWindow:application:
1002 * The #GtkApplication associated with the window.
1004 * The application will be kept alive for at least as long as it
1005 * has any windows associated with it (see g_application_hold()
1006 * for a way to keep it alive without windows).
1008 * Normally, the connection between the application and the window
1009 * will remain until the window is destroyed, but you can explicitly
1010 * remove it by setting the ::application property to %NULL.
1014 g_object_class_install_property (gobject_class,
1016 g_param_spec_object ("application",
1017 P_("GtkApplication"),
1018 P_("The GtkApplication for the window"),
1019 GTK_TYPE_APPLICATION,
1020 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1022 window_signals[SET_FOCUS] =
1023 g_signal_new (I_("set-focus"),
1024 G_TYPE_FROM_CLASS (gobject_class),
1026 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1028 _gtk_marshal_VOID__OBJECT,
1033 * GtkWindow::activate-focus:
1034 * @window: the window which received the signal
1036 * The ::activate-focus signal is a
1037 * <link linkend="keybinding-signals">keybinding signal</link>
1038 * which gets emitted when the user activates the currently
1039 * focused widget of @window.
1041 window_signals[ACTIVATE_FOCUS] =
1042 g_signal_new (I_("activate-focus"),
1043 G_TYPE_FROM_CLASS (gobject_class),
1044 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1045 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1047 _gtk_marshal_VOID__VOID,
1052 * GtkWindow::activate-default:
1053 * @window: the window which received the signal
1055 * The ::activate-default signal is a
1056 * <link linkend="keybinding-signals">keybinding signal</link>
1057 * which gets emitted when the user activates the default widget
1060 window_signals[ACTIVATE_DEFAULT] =
1061 g_signal_new (I_("activate-default"),
1062 G_TYPE_FROM_CLASS (gobject_class),
1063 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1064 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1066 _gtk_marshal_VOID__VOID,
1071 * GtkWindow::keys-changed:
1072 * @window: the window which received the signal
1074 * The ::keys-changed signal gets emitted when the set of accelerators
1075 * or mnemonics that are associated with @window changes.
1077 window_signals[KEYS_CHANGED] =
1078 g_signal_new (I_("keys-changed"),
1079 G_TYPE_FROM_CLASS (gobject_class),
1081 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1083 _gtk_marshal_VOID__VOID,
1091 binding_set = gtk_binding_set_by_class (klass);
1093 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1094 "activate-focus", 0);
1095 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1096 "activate-focus", 0);
1098 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1099 "activate-default", 0);
1100 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1101 "activate-default", 0);
1102 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1103 "activate-default", 0);
1105 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1106 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1107 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1108 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1110 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1111 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1112 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1113 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1115 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1119 gtk_window_init (GtkWindow *window)
1121 GtkStyleContext *context;
1122 GtkWindowPrivate *priv;
1124 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1127 priv = window->priv;
1129 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1130 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1132 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1134 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1137 priv->wmclass_name = g_strdup (g_get_prgname ());
1138 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1139 priv->wm_role = NULL;
1140 priv->geometry_info = NULL;
1141 priv->type = GTK_WINDOW_TOPLEVEL;
1142 priv->focus_widget = NULL;
1143 priv->default_widget = NULL;
1144 priv->configure_request_count = 0;
1145 priv->resizable = TRUE;
1146 priv->configure_notify_received = FALSE;
1147 priv->position = GTK_WIN_POS_NONE;
1148 priv->need_default_size = TRUE;
1149 priv->need_default_position = TRUE;
1150 priv->modal = FALSE;
1151 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1152 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1153 priv->decorated = TRUE;
1154 priv->mnemonic_modifier = GDK_MOD1_MASK;
1155 priv->screen = gdk_screen_get_default ();
1157 priv->accept_focus = TRUE;
1158 priv->focus_on_map = TRUE;
1159 priv->deletable = TRUE;
1160 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1161 priv->startup_id = NULL;
1162 priv->initial_timestamp = GDK_CURRENT_TIME;
1163 priv->has_resize_grip = TRUE;
1164 priv->mnemonics_visible = TRUE;
1165 priv->focus_visible = TRUE;
1167 g_object_ref_sink (window);
1168 priv->has_user_ref_count = TRUE;
1169 toplevel_list = g_slist_prepend (toplevel_list, window);
1172 g_signal_connect (priv->screen, "composited-changed",
1173 G_CALLBACK (gtk_window_on_composited_changed), window);
1175 #ifdef GDK_WINDOWING_X11
1176 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1177 "notify::gtk-application-prefer-dark-theme",
1178 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1181 context = gtk_widget_get_style_context (GTK_WIDGET (window));
1182 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
1186 gtk_window_set_property (GObject *object,
1188 const GValue *value,
1191 GtkWindow *window = GTK_WINDOW (object);
1192 GtkWindowPrivate *priv = window->priv;
1197 priv->type = g_value_get_enum (value);
1200 gtk_window_set_title (window, g_value_get_string (value));
1203 gtk_window_set_role (window, g_value_get_string (value));
1205 case PROP_STARTUP_ID:
1206 gtk_window_set_startup_id (window, g_value_get_string (value));
1208 case PROP_RESIZABLE:
1209 gtk_window_set_resizable (window, g_value_get_boolean (value));
1212 gtk_window_set_modal (window, g_value_get_boolean (value));
1215 gtk_window_set_position (window, g_value_get_enum (value));
1217 case PROP_DEFAULT_WIDTH:
1218 gtk_window_set_default_size_internal (window,
1219 TRUE, g_value_get_int (value),
1222 case PROP_DEFAULT_HEIGHT:
1223 gtk_window_set_default_size_internal (window,
1225 TRUE, g_value_get_int (value), FALSE);
1227 case PROP_DESTROY_WITH_PARENT:
1228 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1230 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1231 gtk_window_set_hide_titlebar_when_maximized (window, g_value_get_boolean (value));
1234 gtk_window_set_icon (window,
1235 g_value_get_object (value));
1237 case PROP_ICON_NAME:
1238 gtk_window_set_icon_name (window, g_value_get_string (value));
1241 gtk_window_set_screen (window, g_value_get_object (value));
1243 case PROP_TYPE_HINT:
1244 gtk_window_set_type_hint (window,
1245 g_value_get_enum (value));
1247 case PROP_SKIP_TASKBAR_HINT:
1248 gtk_window_set_skip_taskbar_hint (window,
1249 g_value_get_boolean (value));
1251 case PROP_SKIP_PAGER_HINT:
1252 gtk_window_set_skip_pager_hint (window,
1253 g_value_get_boolean (value));
1255 case PROP_URGENCY_HINT:
1256 gtk_window_set_urgency_hint (window,
1257 g_value_get_boolean (value));
1259 case PROP_ACCEPT_FOCUS:
1260 gtk_window_set_accept_focus (window,
1261 g_value_get_boolean (value));
1263 case PROP_FOCUS_ON_MAP:
1264 gtk_window_set_focus_on_map (window,
1265 g_value_get_boolean (value));
1267 case PROP_DECORATED:
1268 gtk_window_set_decorated (window, g_value_get_boolean (value));
1270 case PROP_DELETABLE:
1271 gtk_window_set_deletable (window, g_value_get_boolean (value));
1274 gtk_window_set_gravity (window, g_value_get_enum (value));
1276 case PROP_TRANSIENT_FOR:
1277 gtk_window_set_transient_for (window, g_value_get_object (value));
1279 case PROP_ATTACHED_TO:
1280 gtk_window_set_attached_to (window, g_value_get_object (value));
1282 case PROP_HAS_RESIZE_GRIP:
1283 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1285 case PROP_APPLICATION:
1286 gtk_window_set_application (window, g_value_get_object (value));
1288 case PROP_MNEMONICS_VISIBLE:
1289 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1291 case PROP_FOCUS_VISIBLE:
1292 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1295 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1301 gtk_window_get_property (GObject *object,
1306 GtkWindow *window = GTK_WINDOW (object);
1307 GtkWindowPrivate *priv = window->priv;
1311 GtkWindowGeometryInfo *info;
1313 g_value_set_enum (value, priv->type);
1316 g_value_set_string (value, priv->wm_role);
1319 g_value_set_string (value, priv->title);
1321 case PROP_RESIZABLE:
1322 g_value_set_boolean (value, priv->resizable);
1325 g_value_set_boolean (value, priv->modal);
1328 g_value_set_enum (value, priv->position);
1330 case PROP_DEFAULT_WIDTH:
1331 info = gtk_window_get_geometry_info (window, FALSE);
1333 g_value_set_int (value, -1);
1335 g_value_set_int (value, info->default_width);
1337 case PROP_DEFAULT_HEIGHT:
1338 info = gtk_window_get_geometry_info (window, FALSE);
1340 g_value_set_int (value, -1);
1342 g_value_set_int (value, info->default_height);
1344 case PROP_DESTROY_WITH_PARENT:
1345 g_value_set_boolean (value, priv->destroy_with_parent);
1347 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1348 g_value_set_boolean (value, priv->hide_titlebar_when_maximized);
1351 g_value_set_object (value, gtk_window_get_icon (window));
1353 case PROP_ICON_NAME:
1354 g_value_set_string (value, gtk_window_get_icon_name (window));
1357 g_value_set_object (value, priv->screen);
1359 case PROP_IS_ACTIVE:
1360 g_value_set_boolean (value, priv->is_active);
1362 case PROP_HAS_TOPLEVEL_FOCUS:
1363 g_value_set_boolean (value, priv->has_toplevel_focus);
1365 case PROP_TYPE_HINT:
1366 g_value_set_enum (value, priv->type_hint);
1368 case PROP_SKIP_TASKBAR_HINT:
1369 g_value_set_boolean (value,
1370 gtk_window_get_skip_taskbar_hint (window));
1372 case PROP_SKIP_PAGER_HINT:
1373 g_value_set_boolean (value,
1374 gtk_window_get_skip_pager_hint (window));
1376 case PROP_URGENCY_HINT:
1377 g_value_set_boolean (value,
1378 gtk_window_get_urgency_hint (window));
1380 case PROP_ACCEPT_FOCUS:
1381 g_value_set_boolean (value,
1382 gtk_window_get_accept_focus (window));
1384 case PROP_FOCUS_ON_MAP:
1385 g_value_set_boolean (value,
1386 gtk_window_get_focus_on_map (window));
1388 case PROP_DECORATED:
1389 g_value_set_boolean (value, gtk_window_get_decorated (window));
1391 case PROP_DELETABLE:
1392 g_value_set_boolean (value, gtk_window_get_deletable (window));
1395 g_value_set_enum (value, gtk_window_get_gravity (window));
1397 case PROP_TRANSIENT_FOR:
1398 g_value_set_object (value, gtk_window_get_transient_for (window));
1400 case PROP_ATTACHED_TO:
1401 g_value_set_object (value, gtk_window_get_attached_to (window));
1403 case PROP_HAS_RESIZE_GRIP:
1404 g_value_set_boolean (value, priv->has_resize_grip);
1406 case PROP_RESIZE_GRIP_VISIBLE:
1407 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1409 case PROP_APPLICATION:
1410 g_value_set_object (value, gtk_window_get_application (window));
1412 case PROP_MNEMONICS_VISIBLE:
1413 g_value_set_boolean (value, priv->mnemonics_visible);
1415 case PROP_FOCUS_VISIBLE:
1416 g_value_set_boolean (value, priv->focus_visible);
1419 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1425 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1427 parent_buildable_iface = g_type_interface_peek_parent (iface);
1428 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1429 iface->parser_finished = gtk_window_buildable_parser_finished;
1430 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1431 iface->custom_finished = gtk_window_buildable_custom_finished;
1435 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1436 GtkBuilder *builder,
1438 const GValue *value)
1440 GtkWindow *window = GTK_WINDOW (buildable);
1441 GtkWindowPrivate *priv = window->priv;
1443 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1444 priv->builder_visible = TRUE;
1446 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1450 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1451 GtkBuilder *builder)
1453 GtkWindow *window = GTK_WINDOW (buildable);
1454 GtkWindowPrivate *priv = window->priv;
1458 if (priv->builder_visible)
1459 gtk_widget_show (GTK_WIDGET (buildable));
1461 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1462 for (l = accels; l; l = l->next)
1464 object = gtk_builder_get_object (builder, l->data);
1467 g_warning ("Unknown accel group %s specified in window %s",
1468 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1471 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1472 GTK_ACCEL_GROUP (object));
1476 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1478 parent_buildable_iface->parser_finished (buildable, builder);
1484 } GSListSubParserData;
1487 window_start_element (GMarkupParseContext *context,
1488 const gchar *element_name,
1489 const gchar **names,
1490 const gchar **values,
1495 GSListSubParserData *data = (GSListSubParserData*)user_data;
1497 if (strcmp (element_name, "group") == 0)
1499 for (i = 0; names[i]; i++)
1501 if (strcmp (names[i], "name") == 0)
1502 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1505 else if (strcmp (element_name, "accel-groups") == 0)
1508 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1513 static const GMarkupParser window_parser =
1515 window_start_element
1519 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1520 GtkBuilder *builder,
1522 const gchar *tagname,
1523 GMarkupParser *parser,
1526 GSListSubParserData *parser_data;
1528 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1529 tagname, parser, data))
1532 if (strcmp (tagname, "accel-groups") == 0)
1534 parser_data = g_slice_new0 (GSListSubParserData);
1535 parser_data->items = NULL;
1536 parser_data->object = G_OBJECT (buildable);
1538 *parser = window_parser;
1539 *data = parser_data;
1547 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1548 GtkBuilder *builder,
1550 const gchar *tagname,
1553 GSListSubParserData *data;
1555 parent_buildable_iface->custom_finished (buildable, builder, child,
1556 tagname, user_data);
1558 if (strcmp (tagname, "accel-groups") != 0)
1561 data = (GSListSubParserData*)user_data;
1563 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1564 data->items, (GDestroyNotify) g_slist_free);
1566 g_slice_free (GSListSubParserData, data);
1571 * @type: type of window
1573 * Creates a new #GtkWindow, which is a toplevel window that can
1574 * contain other widgets. Nearly always, the type of the window should
1575 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1576 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1577 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1578 * dialogs, though in some other toolkits dialogs are called "popups".
1579 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1580 * On X11, popup windows are not controlled by the <link
1581 * linkend="gtk-X11-arch">window manager</link>.
1583 * If you simply want an undecorated window (no window borders), use
1584 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1586 * Return value: a new #GtkWindow.
1589 gtk_window_new (GtkWindowType type)
1591 GtkWindowPrivate *priv;
1594 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1596 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1597 priv = window->priv;
1601 return GTK_WIDGET (window);
1605 * gtk_window_set_title:
1606 * @window: a #GtkWindow
1607 * @title: title of the window
1609 * Sets the title of the #GtkWindow. The title of a window will be
1610 * displayed in its title bar; on the X Window System, the title bar
1611 * is rendered by the <link linkend="gtk-X11-arch">window
1612 * manager</link>, so exactly how the title appears to users may vary
1613 * according to a user's exact configuration. The title should help a
1614 * user distinguish this window from other windows they may have
1615 * open. A good title might include the application name and current
1616 * document filename, for example.
1620 gtk_window_set_title (GtkWindow *window,
1623 GtkWindowPrivate *priv;
1627 g_return_if_fail (GTK_IS_WINDOW (window));
1629 priv = window->priv;
1630 widget = GTK_WIDGET (window);
1632 new_title = g_strdup (title);
1633 g_free (priv->title);
1634 priv->title = new_title;
1636 if (gtk_widget_get_realized (widget))
1638 gdk_window_set_title (gtk_widget_get_window (widget),
1642 g_object_notify (G_OBJECT (window), "title");
1646 * gtk_window_get_title:
1647 * @window: a #GtkWindow
1649 * Retrieves the title of the window. See gtk_window_set_title().
1651 * Return value: the title of the window, or %NULL if none has
1652 * been set explicitely. The returned string is owned by the widget
1653 * and must not be modified or freed.
1656 gtk_window_get_title (GtkWindow *window)
1658 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1660 return window->priv->title;
1664 * gtk_window_set_wmclass:
1665 * @window: a #GtkWindow
1666 * @wmclass_name: window name hint
1667 * @wmclass_class: window class hint
1669 * Don't use this function. It sets the X Window System "class" and
1670 * "name" hints for a window. According to the ICCCM, you should
1671 * always set these to the same value for all windows in an
1672 * application, and GTK+ sets them to that value by default, so calling
1673 * this function is sort of pointless. However, you may want to call
1674 * gtk_window_set_role() on each window in your application, for the
1675 * benefit of the session manager. Setting the role allows the window
1676 * manager to restore window positions when loading a saved session.
1680 gtk_window_set_wmclass (GtkWindow *window,
1681 const gchar *wmclass_name,
1682 const gchar *wmclass_class)
1684 GtkWindowPrivate *priv;
1686 g_return_if_fail (GTK_IS_WINDOW (window));
1688 priv = window->priv;
1690 g_free (priv->wmclass_name);
1691 priv->wmclass_name = g_strdup (wmclass_name);
1693 g_free (priv->wmclass_class);
1694 priv->wmclass_class = g_strdup (wmclass_class);
1696 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1697 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1701 * gtk_window_set_role:
1702 * @window: a #GtkWindow
1703 * @role: unique identifier for the window to be used when restoring a session
1705 * This function is only useful on X11, not with other GTK+ targets.
1707 * In combination with the window title, the window role allows a
1708 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1709 * same" window when an application is restarted. So for example you
1710 * might set the "toolbox" role on your app's toolbox window, so that
1711 * when the user restarts their session, the window manager can put
1712 * the toolbox back in the same place.
1714 * If a window already has a unique title, you don't need to set the
1715 * role, since the WM can use the title to identify the window when
1716 * restoring the session.
1720 gtk_window_set_role (GtkWindow *window,
1723 GtkWindowPrivate *priv;
1726 g_return_if_fail (GTK_IS_WINDOW (window));
1728 priv = window->priv;
1730 new_role = g_strdup (role);
1731 g_free (priv->wm_role);
1732 priv->wm_role = new_role;
1734 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1735 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1738 g_object_notify (G_OBJECT (window), "role");
1742 * gtk_window_set_startup_id:
1743 * @window: a #GtkWindow
1744 * @startup_id: a string with startup-notification identifier
1746 * Startup notification identifiers are used by desktop environment to
1747 * track application startup, to provide user feedback and other
1748 * features. This function changes the corresponding property on the
1749 * underlying GdkWindow. Normally, startup identifier is managed
1750 * automatically and you should only use this function in special cases
1751 * like transferring focus from other processes. You should use this
1752 * function before calling gtk_window_present() or any equivalent
1753 * function generating a window map event.
1755 * This function is only useful on X11, not with other GTK+ targets.
1760 gtk_window_set_startup_id (GtkWindow *window,
1761 const gchar *startup_id)
1763 GtkWindowPrivate *priv;
1766 g_return_if_fail (GTK_IS_WINDOW (window));
1768 priv = window->priv;
1769 widget = GTK_WIDGET (window);
1771 g_free (priv->startup_id);
1772 priv->startup_id = g_strdup (startup_id);
1774 if (gtk_widget_get_realized (widget))
1776 GdkWindow *gdk_window;
1777 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1779 gdk_window = gtk_widget_get_window (widget);
1781 #ifdef GDK_WINDOWING_X11
1782 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1783 gdk_x11_window_set_user_time (gdk_window, timestamp);
1786 /* Here we differentiate real and "fake" startup notification IDs,
1787 * constructed on purpose just to pass interaction timestamp
1789 if (startup_id_is_fake (priv->startup_id))
1790 gtk_window_present_with_time (window, timestamp);
1793 gdk_window_set_startup_id (gdk_window,
1796 /* If window is mapped, terminate the startup-notification too */
1797 if (gtk_widget_get_mapped (widget) &&
1798 !disable_startup_notification)
1799 gdk_notify_startup_complete_with_id (priv->startup_id);
1803 g_object_notify (G_OBJECT (window), "startup-id");
1807 * gtk_window_get_role:
1808 * @window: a #GtkWindow
1810 * Returns the role of the window. See gtk_window_set_role() for
1811 * further explanation.
1813 * Return value: the role of the window if set, or %NULL. The
1814 * returned is owned by the widget and must not be modified
1818 gtk_window_get_role (GtkWindow *window)
1820 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1822 return window->priv->wm_role;
1826 * gtk_window_set_focus:
1827 * @window: a #GtkWindow
1828 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1829 * any focus widget for the toplevel window.
1831 * If @focus is not the current focus widget, and is focusable, sets
1832 * it as the focus widget for the window. If @focus is %NULL, unsets
1833 * the focus widget for this window. To set the focus to a particular
1834 * widget in the toplevel, it is usually more convenient to use
1835 * gtk_widget_grab_focus() instead of this function.
1838 gtk_window_set_focus (GtkWindow *window,
1841 GtkWindowPrivate *priv;
1844 g_return_if_fail (GTK_IS_WINDOW (window));
1846 priv = window->priv;
1850 g_return_if_fail (GTK_IS_WIDGET (focus));
1851 g_return_if_fail (gtk_widget_get_can_focus (focus));
1855 gtk_widget_grab_focus (focus);
1858 /* Clear the existing focus chain, so that when we focus into
1859 * the window again, we start at the beginnning.
1861 GtkWidget *widget = priv->focus_widget;
1864 while ((parent = gtk_widget_get_parent (widget)))
1867 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1871 _gtk_window_internal_set_focus (window, NULL);
1876 _gtk_window_internal_set_focus (GtkWindow *window,
1879 GtkWindowPrivate *priv;
1881 g_return_if_fail (GTK_IS_WINDOW (window));
1883 priv = window->priv;
1885 if ((priv->focus_widget != focus) ||
1886 (focus && !gtk_widget_has_focus (focus)))
1887 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1891 * gtk_window_set_default:
1892 * @window: a #GtkWindow
1893 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1894 * default widget for the toplevel.
1896 * The default widget is the widget that's activated when the user
1897 * presses Enter in a dialog (for example). This function sets or
1898 * unsets the default widget for a #GtkWindow about. When setting
1899 * (rather than unsetting) the default widget it's generally easier to
1900 * call gtk_widget_grab_focus() on the widget. Before making a widget
1901 * the default widget, you must call gtk_widget_set_can_default() on the
1902 * widget you'd like to make the default.
1905 gtk_window_set_default (GtkWindow *window,
1906 GtkWidget *default_widget)
1908 GtkWindowPrivate *priv;
1910 g_return_if_fail (GTK_IS_WINDOW (window));
1912 priv = window->priv;
1915 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1917 if (priv->default_widget != default_widget)
1919 GtkWidget *old_default_widget = NULL;
1922 g_object_ref (default_widget);
1924 if (priv->default_widget)
1926 old_default_widget = priv->default_widget;
1928 if (priv->focus_widget != priv->default_widget ||
1929 !gtk_widget_get_receives_default (priv->default_widget))
1930 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1932 gtk_widget_queue_draw (priv->default_widget);
1935 priv->default_widget = default_widget;
1937 if (priv->default_widget)
1939 if (priv->focus_widget == NULL ||
1940 !gtk_widget_get_receives_default (priv->focus_widget))
1941 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1943 gtk_widget_queue_draw (priv->default_widget);
1946 if (old_default_widget)
1947 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1951 g_object_notify (G_OBJECT (default_widget), "has-default");
1952 g_object_unref (default_widget);
1958 * gtk_window_get_default_widget:
1959 * @window: a #GtkWindow
1961 * Returns the default widget for @window. See gtk_window_set_default()
1964 * Returns: (transfer none): the default widget, or %NULL if there is none.
1969 gtk_window_get_default_widget (GtkWindow *window)
1971 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1973 return window->priv->default_widget;
1977 handle_keys_changed (gpointer data)
1979 GtkWindow *window = GTK_WINDOW (data);
1980 GtkWindowPrivate *priv = window->priv;
1982 if (priv->keys_changed_handler)
1984 g_source_remove (priv->keys_changed_handler);
1985 priv->keys_changed_handler = 0;
1988 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1994 gtk_window_notify_keys_changed (GtkWindow *window)
1996 GtkWindowPrivate *priv = window->priv;
1998 if (!priv->keys_changed_handler)
1999 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
2003 * gtk_window_add_accel_group:
2004 * @window: window to attach accelerator group to
2005 * @accel_group: a #GtkAccelGroup
2007 * Associate @accel_group with @window, such that calling
2008 * gtk_accel_groups_activate() on @window will activate accelerators
2012 gtk_window_add_accel_group (GtkWindow *window,
2013 GtkAccelGroup *accel_group)
2015 g_return_if_fail (GTK_IS_WINDOW (window));
2016 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2018 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
2019 g_signal_connect_object (accel_group, "accel-changed",
2020 G_CALLBACK (gtk_window_notify_keys_changed),
2021 window, G_CONNECT_SWAPPED);
2022 gtk_window_notify_keys_changed (window);
2026 * gtk_window_remove_accel_group:
2027 * @window: a #GtkWindow
2028 * @accel_group: a #GtkAccelGroup
2030 * Reverses the effects of gtk_window_add_accel_group().
2033 gtk_window_remove_accel_group (GtkWindow *window,
2034 GtkAccelGroup *accel_group)
2036 g_return_if_fail (GTK_IS_WINDOW (window));
2037 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2039 g_signal_handlers_disconnect_by_func (accel_group,
2040 gtk_window_notify_keys_changed,
2042 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2043 gtk_window_notify_keys_changed (window);
2046 static GtkMnemonicHash *
2047 gtk_window_get_mnemonic_hash (GtkWindow *window,
2050 GtkWindowPrivate *private = window->priv;
2052 if (!private->mnemonic_hash && create)
2053 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2055 return private->mnemonic_hash;
2059 * gtk_window_add_mnemonic:
2060 * @window: a #GtkWindow
2061 * @keyval: the mnemonic
2062 * @target: the widget that gets activated by the mnemonic
2064 * Adds a mnemonic to this window.
2067 gtk_window_add_mnemonic (GtkWindow *window,
2071 g_return_if_fail (GTK_IS_WINDOW (window));
2072 g_return_if_fail (GTK_IS_WIDGET (target));
2074 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2076 gtk_window_notify_keys_changed (window);
2080 * gtk_window_remove_mnemonic:
2081 * @window: a #GtkWindow
2082 * @keyval: the mnemonic
2083 * @target: the widget that gets activated by the mnemonic
2085 * Removes a mnemonic from this window.
2088 gtk_window_remove_mnemonic (GtkWindow *window,
2092 g_return_if_fail (GTK_IS_WINDOW (window));
2093 g_return_if_fail (GTK_IS_WIDGET (target));
2095 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2097 gtk_window_notify_keys_changed (window);
2101 * gtk_window_mnemonic_activate:
2102 * @window: a #GtkWindow
2103 * @keyval: the mnemonic
2104 * @modifier: the modifiers
2106 * Activates the targets associated with the mnemonic.
2108 * Returns: %TRUE if the activation is done.
2111 gtk_window_mnemonic_activate (GtkWindow *window,
2113 GdkModifierType modifier)
2115 GtkWindowPrivate *priv;
2117 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2119 priv = window->priv;
2121 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2123 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2125 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2132 * gtk_window_set_mnemonic_modifier:
2133 * @window: a #GtkWindow
2134 * @modifier: the modifier mask used to activate
2135 * mnemonics on this window.
2137 * Sets the mnemonic modifier for this window.
2140 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2141 GdkModifierType modifier)
2143 GtkWindowPrivate *priv;
2145 g_return_if_fail (GTK_IS_WINDOW (window));
2146 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2148 priv = window->priv;
2150 priv->mnemonic_modifier = modifier;
2151 gtk_window_notify_keys_changed (window);
2155 * gtk_window_get_mnemonic_modifier:
2156 * @window: a #GtkWindow
2158 * Returns the mnemonic modifier for this window. See
2159 * gtk_window_set_mnemonic_modifier().
2161 * Return value: the modifier mask used to activate
2162 * mnemonics on this window.
2165 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2167 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2169 return window->priv->mnemonic_modifier;
2173 * gtk_window_set_position:
2174 * @window: a #GtkWindow.
2175 * @position: a position constraint.
2177 * Sets a position constraint for this window. If the old or new
2178 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2179 * the window to be repositioned to satisfy the new constraint.
2182 gtk_window_set_position (GtkWindow *window,
2183 GtkWindowPosition position)
2185 GtkWindowPrivate *priv;
2187 g_return_if_fail (GTK_IS_WINDOW (window));
2189 priv = window->priv;
2191 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2192 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2194 GtkWindowGeometryInfo *info;
2196 info = gtk_window_get_geometry_info (window, TRUE);
2198 /* this flag causes us to re-request the CENTER_ALWAYS
2199 * constraint in gtk_window_move_resize(), see
2200 * comment in that function.
2202 info->position_constraints_changed = TRUE;
2204 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2207 priv->position = position;
2209 g_object_notify (G_OBJECT (window), "window-position");
2213 * gtk_window_activate_focus:
2214 * @window: a #GtkWindow
2216 * Activates the current focused widget within the window.
2218 * Return value: %TRUE if a widget got activated.
2221 gtk_window_activate_focus (GtkWindow *window)
2223 GtkWindowPrivate *priv;
2225 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2227 priv = window->priv;
2229 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2230 return gtk_widget_activate (priv->focus_widget);
2236 * gtk_window_get_focus:
2237 * @window: a #GtkWindow
2239 * Retrieves the current focused widget within the window.
2240 * Note that this is the widget that would have the focus
2241 * if the toplevel window focused; if the toplevel window
2242 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2243 * not be %TRUE for the widget.
2245 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2248 gtk_window_get_focus (GtkWindow *window)
2250 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2252 return window->priv->focus_widget;
2256 * gtk_window_activate_default:
2257 * @window: a #GtkWindow
2259 * Activates the default widget for the window, unless the current
2260 * focused widget has been configured to receive the default action
2261 * (see gtk_widget_set_receives_default()), in which case the
2262 * focused widget is activated.
2264 * Return value: %TRUE if a widget got activated.
2267 gtk_window_activate_default (GtkWindow *window)
2269 GtkWindowPrivate *priv;
2271 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2273 priv = window->priv;
2275 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2276 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2277 return gtk_widget_activate (priv->default_widget);
2278 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2279 return gtk_widget_activate (priv->focus_widget);
2285 * gtk_window_set_modal:
2286 * @window: a #GtkWindow
2287 * @modal: whether the window is modal
2289 * Sets a window modal or non-modal. Modal windows prevent interaction
2290 * with other windows in the same application. To keep modal dialogs
2291 * on top of main application windows, use
2292 * gtk_window_set_transient_for() to make the dialog transient for the
2293 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2294 * will then disallow lowering the dialog below the parent.
2299 gtk_window_set_modal (GtkWindow *window,
2302 GtkWindowPrivate *priv;
2305 g_return_if_fail (GTK_IS_WINDOW (window));
2307 priv = window->priv;
2309 modal = modal != FALSE;
2310 if (priv->modal == modal)
2313 priv->modal = modal;
2314 widget = GTK_WIDGET (window);
2316 /* adjust desired modality state */
2317 if (gtk_widget_get_realized (widget))
2320 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2322 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2325 if (gtk_widget_get_visible (widget))
2328 gtk_grab_add (widget);
2330 gtk_grab_remove (widget);
2333 g_object_notify (G_OBJECT (window), "modal");
2337 * gtk_window_get_modal:
2338 * @window: a #GtkWindow
2340 * Returns whether the window is modal. See gtk_window_set_modal().
2342 * Return value: %TRUE if the window is set to be modal and
2343 * establishes a grab when shown
2346 gtk_window_get_modal (GtkWindow *window)
2348 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2350 return window->priv->modal;
2354 * gtk_window_list_toplevels:
2356 * Returns a list of all existing toplevel windows. The widgets
2357 * in the list are not individually referenced. If you want
2358 * to iterate through the list and perform actions involving
2359 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2360 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2361 * then unref all the widgets afterwards.
2363 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2366 gtk_window_list_toplevels (void)
2371 for (slist = toplevel_list; slist; slist = slist->next)
2372 list = g_list_prepend (list, slist->data);
2378 remove_attach_widget (GtkWindow *window)
2380 GtkWindowPrivate *priv = window->priv;
2382 if (priv->attach_widget)
2384 _gtk_widget_remove_attached_window (priv->attach_widget, window);
2386 g_object_unref (priv->attach_widget);
2387 priv->attach_widget = NULL;
2392 gtk_window_dispose (GObject *object)
2394 GtkWindow *window = GTK_WINDOW (object);
2396 gtk_window_set_focus (window, NULL);
2397 gtk_window_set_default (window, NULL);
2399 remove_attach_widget (GTK_WINDOW (object));
2401 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2405 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2407 gtk_widget_destroy (GTK_WIDGET (child));
2411 connect_parent_destroyed (GtkWindow *window)
2413 GtkWindowPrivate *priv = window->priv;
2415 if (priv->transient_parent)
2417 g_signal_connect (priv->transient_parent,
2419 G_CALLBACK (parent_destroyed_callback),
2425 disconnect_parent_destroyed (GtkWindow *window)
2427 GtkWindowPrivate *priv = window->priv;
2429 if (priv->transient_parent)
2431 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2432 parent_destroyed_callback,
2438 gtk_window_transient_parent_realized (GtkWidget *parent,
2441 if (gtk_widget_get_realized (window))
2442 gdk_window_set_transient_for (gtk_widget_get_window (window),
2443 gtk_widget_get_window (parent));
2447 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2450 if (gtk_widget_get_realized (window))
2451 gdk_property_delete (gtk_widget_get_window (window),
2452 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2456 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2460 gtk_window_set_screen (window, parent->priv->screen);
2464 gtk_window_unset_transient_for (GtkWindow *window)
2466 GtkWindowPrivate *priv = window->priv;
2468 if (priv->transient_parent)
2470 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2471 gtk_window_transient_parent_realized,
2473 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2474 gtk_window_transient_parent_unrealized,
2476 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2477 gtk_window_transient_parent_screen_changed,
2479 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2480 gtk_widget_destroyed,
2481 &priv->transient_parent);
2483 if (priv->destroy_with_parent)
2484 disconnect_parent_destroyed (window);
2486 priv->transient_parent = NULL;
2488 if (priv->transient_parent_group)
2490 priv->transient_parent_group = FALSE;
2491 gtk_window_group_remove_window (priv->group,
2498 * gtk_window_set_transient_for:
2499 * @window: a #GtkWindow
2500 * @parent: (allow-none): parent window, or %NULL
2502 * Dialog windows should be set transient for the main application
2503 * window they were spawned from. This allows <link
2504 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2505 * dialog on top of the main window, or center the dialog over the
2506 * main window. gtk_dialog_new_with_buttons() and other convenience
2507 * functions in GTK+ will sometimes call
2508 * gtk_window_set_transient_for() on your behalf.
2510 * Passing %NULL for @parent unsets the current transient window.
2512 * On Windows, this function puts the child window on top of the parent,
2513 * much as the window manager would have done on X.
2516 gtk_window_set_transient_for (GtkWindow *window,
2519 GtkWindowPrivate *priv;
2521 g_return_if_fail (GTK_IS_WINDOW (window));
2522 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2523 g_return_if_fail (window != parent);
2525 priv = window->priv;
2527 if (priv->transient_parent)
2529 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2530 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2531 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2532 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2533 GTK_WIDGET (window));
2535 gtk_window_unset_transient_for (window);
2538 priv->transient_parent = parent;
2542 g_signal_connect (parent, "destroy",
2543 G_CALLBACK (gtk_widget_destroyed),
2544 &priv->transient_parent);
2545 g_signal_connect (parent, "realize",
2546 G_CALLBACK (gtk_window_transient_parent_realized),
2548 g_signal_connect (parent, "unrealize",
2549 G_CALLBACK (gtk_window_transient_parent_unrealized),
2551 g_signal_connect (parent, "notify::screen",
2552 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2555 gtk_window_set_screen (window, parent->priv->screen);
2557 if (priv->destroy_with_parent)
2558 connect_parent_destroyed (window);
2560 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2561 gtk_widget_get_realized (GTK_WIDGET (parent)))
2562 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2563 GTK_WIDGET (window));
2565 if (parent->priv->group)
2567 gtk_window_group_add_window (parent->priv->group, window);
2568 priv->transient_parent_group = TRUE;
2574 * gtk_window_get_transient_for:
2575 * @window: a #GtkWindow
2577 * Fetches the transient parent for this window. See
2578 * gtk_window_set_transient_for().
2580 * Return value: (transfer none): the transient parent for this window, or %NULL
2581 * if no transient parent has been set.
2584 gtk_window_get_transient_for (GtkWindow *window)
2586 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2588 return window->priv->transient_parent;
2592 * gtk_window_set_attached_to:
2593 * @window: a #GtkWindow
2594 * @attach_widget: (allow-none): a #GtkWidget, or %NULL
2596 * Marks @window as attached to @attach_widget. This creates a logical binding
2597 * between the window and the widget it belongs to, which is used by GTK+ to
2598 * propagate information such as styling or accessibility to @window as if it
2599 * was a children of @attach_widget.
2601 * Examples of places where specifying this relation is useful are for instance
2602 * a #GtkMenu created by a #GtkComboBox, a completion popup window
2603 * created by #GtkEntry or a typeahead search entry created by #GtkTreeView.
2605 * Note that this function should not be confused with
2606 * gtk_window_set_transient_for(), which specifies a window manager relation
2607 * between two toplevels instead.
2609 * Passing %NULL for @attach_widget detaches the window.
2614 gtk_window_set_attached_to (GtkWindow *window,
2615 GtkWidget *attach_widget)
2617 GtkStyleContext *context;
2618 GtkWindowPrivate *priv;
2620 g_return_if_fail (GTK_IS_WINDOW (window));
2621 g_return_if_fail (GTK_WIDGET (window) != attach_widget);
2623 priv = window->priv;
2625 if (priv->attach_widget == attach_widget)
2628 remove_attach_widget (window);
2630 priv->attach_widget = attach_widget;
2632 if (priv->attach_widget)
2634 _gtk_widget_add_attached_window (priv->attach_widget, window);
2636 g_object_ref (priv->attach_widget);
2639 /* Update the style, as the widget path might change. */
2640 context = gtk_widget_get_style_context (GTK_WIDGET (window));
2641 if (priv->attach_widget)
2642 gtk_style_context_set_parent (context, gtk_widget_get_style_context (priv->attach_widget));
2644 gtk_style_context_set_parent (context, NULL);
2648 * gtk_window_get_attached_to:
2649 * @window: a #GtkWindow
2651 * Fetches the attach widget for this window. See
2652 * gtk_window_set_attached_to().
2654 * Return value: (transfer none): the widget where the window is attached,
2655 * or %NULL if the window is not attached to any widget.
2660 gtk_window_get_attached_to (GtkWindow *window)
2662 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2664 return window->priv->attach_widget;
2668 * gtk_window_set_opacity:
2669 * @window: a #GtkWindow
2670 * @opacity: desired opacity, between 0 and 1
2672 * Request the windowing system to make @window partially transparent,
2673 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2674 * of the opacity parameter are clamped to the [0,1] range.) On X11
2675 * this has any effect only on X screens with a compositing manager
2676 * running. See gtk_widget_is_composited(). On Windows it should work
2679 * Note that setting a window's opacity after the window has been
2680 * shown causes it to flicker once on Windows.
2683 * Deprecated: 3.8: Use gtk_widget_set_opacity instead.
2686 gtk_window_set_opacity (GtkWindow *window,
2689 gtk_widget_set_opacity (GTK_WIDGET (window), opacity);
2693 * gtk_window_get_opacity:
2694 * @window: a #GtkWindow
2696 * Fetches the requested opacity for this window. See
2697 * gtk_window_set_opacity().
2699 * Return value: the requested opacity for this window.
2702 * Deprecated: 3.8: Use gtk_widget_get_opacity instead.
2705 gtk_window_get_opacity (GtkWindow *window)
2707 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2709 return gtk_widget_get_opacity (GTK_WIDGET (window));
2713 * gtk_window_get_application:
2714 * @window: a #GtkWindow
2716 * Gets the #GtkApplication associated with the window (if any).
2718 * Return value: (transfer none): a #GtkApplication, or %NULL
2723 gtk_window_get_application (GtkWindow *window)
2725 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2727 return window->priv->application;
2731 gtk_window_release_application (GtkWindow *window)
2733 if (window->priv->application)
2735 GtkApplication *application;
2737 /* steal reference into temp variable */
2738 application = window->priv->application;
2739 window->priv->application = NULL;
2741 gtk_application_remove_window (application, window);
2742 g_object_unref (application);
2747 * gtk_window_set_application:
2748 * @window: a #GtkWindow
2749 * @application: (allow-none): a #GtkApplication, or %NULL
2751 * Sets or unsets the #GtkApplication associated with the window.
2753 * The application will be kept alive for at least as long as the window
2759 gtk_window_set_application (GtkWindow *window,
2760 GtkApplication *application)
2762 GtkWindowPrivate *priv;
2764 g_return_if_fail (GTK_IS_WINDOW (window));
2766 priv = window->priv;
2767 if (priv->application != application)
2769 gtk_window_release_application (window);
2771 priv->application = application;
2773 if (priv->application != NULL)
2775 g_object_ref (priv->application);
2777 gtk_application_add_window (priv->application, window);
2780 /* don't use a normal cast: application may be NULL */
2781 gtk_widget_insert_action_group (GTK_WIDGET (window), "app", (GActionGroup *) application);
2783 g_object_notify (G_OBJECT (window), "application");
2788 * gtk_window_set_type_hint:
2789 * @window: a #GtkWindow
2790 * @hint: the window type
2792 * By setting the type hint for the window, you allow the window
2793 * manager to decorate and handle the window in a way which is
2794 * suitable to the function of the window in your application.
2796 * This function should be called before the window becomes visible.
2798 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2799 * will sometimes call gtk_window_set_type_hint() on your behalf.
2803 gtk_window_set_type_hint (GtkWindow *window,
2804 GdkWindowTypeHint hint)
2806 GtkWindowPrivate *priv;
2808 g_return_if_fail (GTK_IS_WINDOW (window));
2809 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2811 priv = window->priv;
2813 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2814 priv->type_hint = hint;
2816 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2818 priv->reset_type_hint = TRUE;
2819 priv->gdk_type_hint = hint;
2823 * gtk_window_get_type_hint:
2824 * @window: a #GtkWindow
2826 * Gets the type hint for this window. See gtk_window_set_type_hint().
2828 * Return value: the type hint for @window.
2831 gtk_window_get_type_hint (GtkWindow *window)
2833 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2835 return window->priv->gdk_type_hint;
2839 * gtk_window_set_skip_taskbar_hint:
2840 * @window: a #GtkWindow
2841 * @setting: %TRUE to keep this window from appearing in the task bar
2843 * Windows may set a hint asking the desktop environment not to display
2844 * the window in the task bar. This function sets this hint.
2849 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2852 GtkWindowPrivate *priv;
2854 g_return_if_fail (GTK_IS_WINDOW (window));
2856 priv = window->priv;
2858 setting = setting != FALSE;
2860 if (priv->skips_taskbar != setting)
2862 priv->skips_taskbar = setting;
2863 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2864 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2865 priv->skips_taskbar);
2866 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2871 * gtk_window_get_skip_taskbar_hint:
2872 * @window: a #GtkWindow
2874 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2876 * Return value: %TRUE if window shouldn't be in taskbar
2881 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2883 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2885 return window->priv->skips_taskbar;
2889 * gtk_window_set_skip_pager_hint:
2890 * @window: a #GtkWindow
2891 * @setting: %TRUE to keep this window from appearing in the pager
2893 * Windows may set a hint asking the desktop environment not to display
2894 * the window in the pager. This function sets this hint.
2895 * (A "pager" is any desktop navigation tool such as a workspace
2896 * switcher that displays a thumbnail representation of the windows
2902 gtk_window_set_skip_pager_hint (GtkWindow *window,
2905 GtkWindowPrivate *priv;
2907 g_return_if_fail (GTK_IS_WINDOW (window));
2909 priv = window->priv;
2911 setting = setting != FALSE;
2913 if (priv->skips_pager != setting)
2915 priv->skips_pager = setting;
2916 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2917 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2919 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2924 * gtk_window_get_skip_pager_hint:
2925 * @window: a #GtkWindow
2927 * Gets the value set by gtk_window_set_skip_pager_hint().
2929 * Return value: %TRUE if window shouldn't be in pager
2934 gtk_window_get_skip_pager_hint (GtkWindow *window)
2936 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2938 return window->priv->skips_pager;
2942 * gtk_window_set_urgency_hint:
2943 * @window: a #GtkWindow
2944 * @setting: %TRUE to mark this window as urgent
2946 * Windows may set a hint asking the desktop environment to draw
2947 * the users attention to the window. This function sets this hint.
2952 gtk_window_set_urgency_hint (GtkWindow *window,
2955 GtkWindowPrivate *priv;
2957 g_return_if_fail (GTK_IS_WINDOW (window));
2959 priv = window->priv;
2961 setting = setting != FALSE;
2963 if (priv->urgent != setting)
2965 priv->urgent = setting;
2966 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2967 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2969 g_object_notify (G_OBJECT (window), "urgency-hint");
2974 * gtk_window_get_urgency_hint:
2975 * @window: a #GtkWindow
2977 * Gets the value set by gtk_window_set_urgency_hint()
2979 * Return value: %TRUE if window is urgent
2984 gtk_window_get_urgency_hint (GtkWindow *window)
2986 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2988 return window->priv->urgent;
2992 * gtk_window_set_accept_focus:
2993 * @window: a #GtkWindow
2994 * @setting: %TRUE to let this window receive input focus
2996 * Windows may set a hint asking the desktop environment not to receive
2997 * the input focus. This function sets this hint.
3002 gtk_window_set_accept_focus (GtkWindow *window,
3005 GtkWindowPrivate *priv;
3007 g_return_if_fail (GTK_IS_WINDOW (window));
3009 priv = window->priv;
3011 setting = setting != FALSE;
3013 if (priv->accept_focus != setting)
3015 priv->accept_focus = setting;
3016 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3017 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
3018 priv->accept_focus);
3019 g_object_notify (G_OBJECT (window), "accept-focus");
3024 * gtk_window_get_accept_focus:
3025 * @window: a #GtkWindow
3027 * Gets the value set by gtk_window_set_accept_focus().
3029 * Return value: %TRUE if window should receive the input focus
3034 gtk_window_get_accept_focus (GtkWindow *window)
3036 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3038 return window->priv->accept_focus;
3042 * gtk_window_set_focus_on_map:
3043 * @window: a #GtkWindow
3044 * @setting: %TRUE to let this window receive input focus on map
3046 * Windows may set a hint asking the desktop environment not to receive
3047 * the input focus when the window is mapped. This function sets this
3053 gtk_window_set_focus_on_map (GtkWindow *window,
3056 GtkWindowPrivate *priv;
3058 g_return_if_fail (GTK_IS_WINDOW (window));
3060 priv = window->priv;
3062 setting = setting != FALSE;
3064 if (priv->focus_on_map != setting)
3066 priv->focus_on_map = setting;
3067 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3068 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
3069 priv->focus_on_map);
3070 g_object_notify (G_OBJECT (window), "focus-on-map");
3075 * gtk_window_get_focus_on_map:
3076 * @window: a #GtkWindow
3078 * Gets the value set by gtk_window_set_focus_on_map().
3080 * Return value: %TRUE if window should receive the input focus when
3086 gtk_window_get_focus_on_map (GtkWindow *window)
3088 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3090 return window->priv->focus_on_map;
3094 * gtk_window_set_destroy_with_parent:
3095 * @window: a #GtkWindow
3096 * @setting: whether to destroy @window with its transient parent
3098 * If @setting is %TRUE, then destroying the transient parent of @window
3099 * will also destroy @window itself. This is useful for dialogs that
3100 * shouldn't persist beyond the lifetime of the main window they're
3101 * associated with, for example.
3104 gtk_window_set_destroy_with_parent (GtkWindow *window,
3107 GtkWindowPrivate *priv;
3109 g_return_if_fail (GTK_IS_WINDOW (window));
3111 priv = window->priv;
3113 if (priv->destroy_with_parent == (setting != FALSE))
3116 if (priv->destroy_with_parent)
3118 disconnect_parent_destroyed (window);
3122 connect_parent_destroyed (window);
3125 priv->destroy_with_parent = setting;
3127 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3131 * gtk_window_get_destroy_with_parent:
3132 * @window: a #GtkWindow
3134 * Returns whether the window will be destroyed with its transient parent. See
3135 * gtk_window_set_destroy_with_parent ().
3137 * Return value: %TRUE if the window will be destroyed with its transient parent.
3140 gtk_window_get_destroy_with_parent (GtkWindow *window)
3142 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3144 return window->priv->destroy_with_parent;
3148 * gtk_window_set_hide_titlebar_when_maximized:
3149 * @window: a #GtkWindow
3150 * @setting: whether to hide the titlebar when @window is maximized
3152 * If @setting is %TRUE, then @window will request that it's titlebar
3153 * should be hidden when maximized.
3154 * This is useful for windows that don't convey any information other
3155 * than the application name in the titlebar, to put the available
3156 * screen space to better use. If the underlying window system does not
3157 * support the request, the setting will not have any effect.
3162 gtk_window_set_hide_titlebar_when_maximized (GtkWindow *window,
3165 g_return_if_fail (GTK_IS_WINDOW (window));
3167 #ifdef GDK_WINDOWING_X11
3169 GdkWindow *gdk_window;
3171 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3173 if (GDK_IS_X11_WINDOW (gdk_window))
3174 gdk_x11_window_set_hide_titlebar_when_maximized (gdk_window, setting);
3178 window->priv->hide_titlebar_when_maximized = setting;
3179 g_object_notify (G_OBJECT (window), "hide-titlebar-when-maximized");
3183 * gtk_window_get_hide_titlebar_when_maximized:
3184 * @window: a #GtkWindow
3186 * Returns whether the window has requested to have its titlebar hidden
3187 * when maximized. See gtk_window_set_hide_titlebar_when_maximized ().
3189 * Return value: %TRUE if the window has requested to have its titlebar
3190 * hidden when maximized
3195 gtk_window_get_hide_titlebar_when_maximized (GtkWindow *window)
3197 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3199 return window->priv->hide_titlebar_when_maximized;
3202 static GtkWindowGeometryInfo*
3203 gtk_window_get_geometry_info (GtkWindow *window,
3206 GtkWindowPrivate *priv = window->priv;
3207 GtkWindowGeometryInfo *info;
3209 info = priv->geometry_info;
3210 if (!info && create)
3212 info = g_new0 (GtkWindowGeometryInfo, 1);
3214 info->default_width = -1;
3215 info->default_height = -1;
3216 info->resize_width = -1;
3217 info->resize_height = -1;
3218 info->initial_x = 0;
3219 info->initial_y = 0;
3220 info->initial_pos_set = FALSE;
3221 info->default_is_geometry = FALSE;
3222 info->position_constraints_changed = FALSE;
3223 info->last.configure_request.x = 0;
3224 info->last.configure_request.y = 0;
3225 info->last.configure_request.width = -1;
3226 info->last.configure_request.height = -1;
3227 info->widget = NULL;
3229 priv->geometry_info = info;
3236 * gtk_window_set_geometry_hints:
3237 * @window: a #GtkWindow
3238 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3239 * @geometry: (allow-none): struct containing geometry information or %NULL
3240 * @geom_mask: mask indicating which struct fields should be paid attention to
3242 * This function sets up hints about how a window can be resized by
3243 * the user. You can set a minimum and maximum size; allowed resize
3244 * increments (e.g. for xterm, you can only resize by the size of a
3245 * character); aspect ratios; and more. See the #GdkGeometry struct.
3249 gtk_window_set_geometry_hints (GtkWindow *window,
3250 GtkWidget *geometry_widget,
3251 GdkGeometry *geometry,
3252 GdkWindowHints geom_mask)
3254 GtkWindowGeometryInfo *info;
3256 g_return_if_fail (GTK_IS_WINDOW (window));
3257 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3259 info = gtk_window_get_geometry_info (window, TRUE);
3262 g_signal_handlers_disconnect_by_func (info->widget,
3263 gtk_widget_destroyed,
3266 info->widget = geometry_widget;
3268 g_signal_connect (geometry_widget, "destroy",
3269 G_CALLBACK (gtk_widget_destroyed),
3273 info->geometry = *geometry;
3275 /* We store gravity in priv->gravity not in the hints. */
3276 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3278 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3280 gtk_window_set_gravity (window, geometry->win_gravity);
3283 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3287 * gtk_window_set_decorated:
3288 * @window: a #GtkWindow
3289 * @setting: %TRUE to decorate the window
3291 * By default, windows are decorated with a title bar, resize
3292 * controls, etc. Some <link linkend="gtk-X11-arch">window
3293 * managers</link> allow GTK+ to disable these decorations, creating a
3294 * borderless window. If you set the decorated property to %FALSE
3295 * using this function, GTK+ will do its best to convince the window
3296 * manager not to decorate the window. Depending on the system, this
3297 * function may not have any effect when called on a window that is
3298 * already visible, so you should call it before calling gtk_widget_show().
3300 * On Windows, this function always works, since there's no window manager
3305 gtk_window_set_decorated (GtkWindow *window,
3308 GtkWindowPrivate *priv;
3309 GdkWindow *gdk_window;
3311 g_return_if_fail (GTK_IS_WINDOW (window));
3313 priv = window->priv;
3315 setting = setting != FALSE;
3317 if (setting == priv->decorated)
3320 priv->decorated = setting;
3322 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3325 if (priv->decorated)
3326 gdk_window_set_decorations (gdk_window,
3329 gdk_window_set_decorations (gdk_window,
3333 g_object_notify (G_OBJECT (window), "decorated");
3337 * gtk_window_get_decorated:
3338 * @window: a #GtkWindow
3340 * Returns whether the window has been set to have decorations
3341 * such as a title bar via gtk_window_set_decorated().
3343 * Return value: %TRUE if the window has been set to have decorations
3346 gtk_window_get_decorated (GtkWindow *window)
3348 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3350 return window->priv->decorated;
3354 * gtk_window_set_deletable:
3355 * @window: a #GtkWindow
3356 * @setting: %TRUE to decorate the window as deletable
3358 * By default, windows have a close button in the window frame. Some
3359 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3360 * disable this button. If you set the deletable property to %FALSE
3361 * using this function, GTK+ will do its best to convince the window
3362 * manager not to show a close button. Depending on the system, this
3363 * function may not have any effect when called on a window that is
3364 * already visible, so you should call it before calling gtk_widget_show().
3366 * On Windows, this function always works, since there's no window manager
3372 gtk_window_set_deletable (GtkWindow *window,
3375 GtkWindowPrivate *priv;
3376 GdkWindow *gdk_window;
3378 g_return_if_fail (GTK_IS_WINDOW (window));
3380 priv = window->priv;
3382 setting = setting != FALSE;
3384 if (setting == priv->deletable)
3387 priv->deletable = setting;
3389 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3392 if (priv->deletable)
3393 gdk_window_set_functions (gdk_window,
3396 gdk_window_set_functions (gdk_window,
3397 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3400 g_object_notify (G_OBJECT (window), "deletable");
3404 * gtk_window_get_deletable:
3405 * @window: a #GtkWindow
3407 * Returns whether the window has been set to have a close button
3408 * via gtk_window_set_deletable().
3410 * Return value: %TRUE if the window has been set to have a close button
3415 gtk_window_get_deletable (GtkWindow *window)
3417 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3419 return window->priv->deletable;
3422 static GtkWindowIconInfo*
3423 get_icon_info (GtkWindow *window)
3425 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3429 free_icon_info (GtkWindowIconInfo *info)
3431 g_free (info->icon_name);
3432 g_slice_free (GtkWindowIconInfo, info);
3436 static GtkWindowIconInfo*
3437 ensure_icon_info (GtkWindow *window)
3439 GtkWindowIconInfo *info;
3441 info = get_icon_info (window);
3445 info = g_slice_new0 (GtkWindowIconInfo);
3446 g_object_set_qdata_full (G_OBJECT (window),
3447 quark_gtk_window_icon_info,
3449 (GDestroyNotify)free_icon_info);
3456 icon_list_from_theme (GtkWidget *widget,
3461 GtkIconTheme *icon_theme;
3466 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3468 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3471 for (i = 0; sizes[i]; i++)
3474 * We need an EWMH extension to handle scalable icons
3475 * by passing their name to the WM. For now just use a
3479 icon = gtk_icon_theme_load_icon (icon_theme, name,
3482 icon = gtk_icon_theme_load_icon (icon_theme, name,
3485 list = g_list_append (list, icon);
3495 gtk_window_realize_icon (GtkWindow *window)
3497 GtkWindowPrivate *priv = window->priv;
3499 GtkWindowIconInfo *info;
3500 GdkWindow *gdk_window;
3503 widget = GTK_WIDGET (window);
3504 gdk_window = gtk_widget_get_window (widget);
3506 g_return_if_fail (gdk_window != NULL);
3508 /* no point setting an icon on override-redirect */
3509 if (priv->type == GTK_WINDOW_POPUP)
3514 info = ensure_icon_info (window);
3519 info->using_default_icon = FALSE;
3520 info->using_parent_icon = FALSE;
3521 info->using_themed_icon = FALSE;
3523 icon_list = info->icon_list;
3525 /* Look up themed icon */
3526 if (icon_list == NULL && info->icon_name)
3528 icon_list = icon_list_from_theme (widget, info->icon_name);
3530 info->using_themed_icon = TRUE;
3533 /* Inherit from transient parent */
3534 if (icon_list == NULL && priv->transient_parent)
3536 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3538 info->using_parent_icon = TRUE;
3541 /* Inherit from default */
3542 if (icon_list == NULL)
3544 icon_list = default_icon_list;
3546 info->using_default_icon = TRUE;
3549 /* Look up themed icon */
3550 if (icon_list == NULL && default_icon_name)
3552 icon_list = icon_list_from_theme (widget, default_icon_name);
3553 info->using_default_icon = TRUE;
3554 info->using_themed_icon = TRUE;
3557 info->realized = TRUE;
3559 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3561 if (info->using_themed_icon)
3563 GtkIconTheme *icon_theme;
3565 g_list_free_full (icon_list, g_object_unref);
3567 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3568 g_signal_connect (icon_theme, "changed",
3569 G_CALLBACK (update_themed_icon), window);
3574 gtk_window_unrealize_icon (GtkWindow *window)
3576 GtkWindowIconInfo *info;
3578 info = get_icon_info (window);
3583 if (info->using_themed_icon)
3585 GtkIconTheme *icon_theme;
3587 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3589 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3592 /* We don't clear the properties on the window, just figure the
3593 * window is going away.
3596 info->realized = FALSE;
3601 * gtk_window_set_icon_list:
3602 * @window: a #GtkWindow
3603 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3605 * Sets up the icon representing a #GtkWindow. The icon is used when
3606 * the window is minimized (also known as iconified). Some window
3607 * managers or desktop environments may also place it in the window
3608 * frame, or display it in other contexts.
3610 * gtk_window_set_icon_list() allows you to pass in the same icon in
3611 * several hand-drawn sizes. The list should contain the natural sizes
3612 * your icon is available in; that is, don't scale the image before
3613 * passing it to GTK+. Scaling is postponed until the last minute,
3614 * when the desired final size is known, to allow best quality.
3616 * By passing several sizes, you may improve the final image quality
3617 * of the icon, by reducing or eliminating automatic image scaling.
3619 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3620 * larger images (64x64, 128x128) if you have them.
3622 * See also gtk_window_set_default_icon_list() to set the icon
3623 * for all windows in your application in one go.
3625 * Note that transient windows (those who have been set transient for another
3626 * window using gtk_window_set_transient_for()) will inherit their
3627 * icon from their transient parent. So there's no need to explicitly
3628 * set the icon on transient windows.
3631 gtk_window_set_icon_list (GtkWindow *window,
3634 GtkWindowIconInfo *info;
3636 g_return_if_fail (GTK_IS_WINDOW (window));
3638 info = ensure_icon_info (window);
3640 if (info->icon_list == list) /* check for NULL mostly */
3643 g_list_foreach (list,
3644 (GFunc) g_object_ref, NULL);
3646 g_list_free_full (info->icon_list, g_object_unref);
3648 info->icon_list = g_list_copy (list);
3650 g_object_notify (G_OBJECT (window), "icon");
3652 gtk_window_unrealize_icon (window);
3654 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3655 gtk_window_realize_icon (window);
3657 /* We could try to update our transient children, but I don't think
3658 * it's really worth it. If we did it, the best way would probably
3659 * be to have children connect to notify::icon-list
3664 * gtk_window_get_icon_list:
3665 * @window: a #GtkWindow
3667 * Retrieves the list of icons set by gtk_window_set_icon_list().
3668 * The list is copied, but the reference count on each
3669 * member won't be incremented.
3671 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3674 gtk_window_get_icon_list (GtkWindow *window)
3676 GtkWindowIconInfo *info;
3678 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3680 info = get_icon_info (window);
3683 return g_list_copy (info->icon_list);
3689 * gtk_window_set_icon:
3690 * @window: a #GtkWindow
3691 * @icon: (allow-none): icon image, or %NULL
3693 * Sets up the icon representing a #GtkWindow. This icon is used when
3694 * the window is minimized (also known as iconified). Some window
3695 * managers or desktop environments may also place it in the window
3696 * frame, or display it in other contexts.
3698 * The icon should be provided in whatever size it was naturally
3699 * drawn; that is, don't scale the image before passing it to
3700 * GTK+. Scaling is postponed until the last minute, when the desired
3701 * final size is known, to allow best quality.
3703 * If you have your icon hand-drawn in multiple sizes, use
3704 * gtk_window_set_icon_list(). Then the best size will be used.
3706 * This function is equivalent to calling gtk_window_set_icon_list()
3707 * with a 1-element list.
3709 * See also gtk_window_set_default_icon_list() to set the icon
3710 * for all windows in your application in one go.
3713 gtk_window_set_icon (GtkWindow *window,
3718 g_return_if_fail (GTK_IS_WINDOW (window));
3719 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3724 list = g_list_append (list, icon);
3726 gtk_window_set_icon_list (window, list);
3732 update_themed_icon (GtkIconTheme *icon_theme,
3735 g_object_notify (G_OBJECT (window), "icon");
3737 gtk_window_unrealize_icon (window);
3739 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3740 gtk_window_realize_icon (window);
3744 * gtk_window_set_icon_name:
3745 * @window: a #GtkWindow
3746 * @name: (allow-none): the name of the themed icon
3748 * Sets the icon for the window from a named themed icon. See
3749 * the docs for #GtkIconTheme for more details.
3751 * Note that this has nothing to do with the WM_ICON_NAME
3752 * property which is mentioned in the ICCCM.
3757 gtk_window_set_icon_name (GtkWindow *window,
3760 GtkWindowIconInfo *info;
3763 g_return_if_fail (GTK_IS_WINDOW (window));
3765 info = ensure_icon_info (window);
3767 if (g_strcmp0 (info->icon_name, name) == 0)
3770 tmp = info->icon_name;
3771 info->icon_name = g_strdup (name);
3774 g_list_free_full (info->icon_list, g_object_unref);
3775 info->icon_list = NULL;
3777 update_themed_icon (NULL, window);
3779 g_object_notify (G_OBJECT (window), "icon-name");
3783 * gtk_window_get_icon_name:
3784 * @window: a #GtkWindow
3786 * Returns the name of the themed icon for the window,
3787 * see gtk_window_set_icon_name().
3789 * Returns: the icon name or %NULL if the window has
3795 gtk_window_get_icon_name (GtkWindow *window)
3797 GtkWindowIconInfo *info;
3799 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3801 info = ensure_icon_info (window);
3803 return info->icon_name;
3807 * gtk_window_get_icon:
3808 * @window: a #GtkWindow
3810 * Gets the value set by gtk_window_set_icon() (or if you've
3811 * called gtk_window_set_icon_list(), gets the first icon in
3814 * Return value: (transfer none): icon for window
3817 gtk_window_get_icon (GtkWindow *window)
3819 GtkWindowIconInfo *info;
3821 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3823 info = get_icon_info (window);
3824 if (info && info->icon_list)
3825 return GDK_PIXBUF (info->icon_list->data);
3830 /* Load pixbuf, printing warning on failure if error == NULL
3833 load_pixbuf_verbosely (const char *filename,
3836 GError *local_err = NULL;
3839 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3847 g_warning ("Error loading icon from file '%s':\n\t%s",
3848 filename, local_err->message);
3849 g_error_free (local_err);
3857 * gtk_window_set_icon_from_file:
3858 * @window: a #GtkWindow
3859 * @filename: (type filename): location of icon file
3860 * @err: (allow-none): location to store error, or %NULL.
3862 * Sets the icon for @window.
3863 * Warns on failure if @err is %NULL.
3865 * This function is equivalent to calling gtk_window_set_icon()
3866 * with a pixbuf created by loading the image from @filename.
3868 * Returns: %TRUE if setting the icon succeeded.
3873 gtk_window_set_icon_from_file (GtkWindow *window,
3874 const gchar *filename,
3877 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3881 gtk_window_set_icon (window, pixbuf);
3882 g_object_unref (pixbuf);
3891 * gtk_window_set_default_icon_list:
3892 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3894 * Sets an icon list to be used as fallback for windows that haven't
3895 * had gtk_window_set_icon_list() called on them to set up a
3896 * window-specific icon list. This function allows you to set up the
3897 * icon for all windows in your app at once.
3899 * See gtk_window_set_icon_list() for more details.
3903 gtk_window_set_default_icon_list (GList *list)
3907 if (list == default_icon_list)
3910 /* Update serial so we don't used cached pixmaps/masks
3912 default_icon_serial++;
3914 g_list_foreach (list,
3915 (GFunc) g_object_ref, NULL);
3917 g_list_free_full (default_icon_list, g_object_unref);
3919 default_icon_list = g_list_copy (list);
3921 /* Update all toplevels */
3922 toplevels = gtk_window_list_toplevels ();
3923 tmp_list = toplevels;
3924 while (tmp_list != NULL)
3926 GtkWindowIconInfo *info;
3927 GtkWindow *w = tmp_list->data;
3929 info = get_icon_info (w);
3930 if (info && info->using_default_icon)
3932 gtk_window_unrealize_icon (w);
3933 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3934 gtk_window_realize_icon (w);
3937 tmp_list = tmp_list->next;
3939 g_list_free (toplevels);
3943 * gtk_window_set_default_icon:
3946 * Sets an icon to be used as fallback for windows that haven't
3947 * had gtk_window_set_icon() called on them from a pixbuf.
3952 gtk_window_set_default_icon (GdkPixbuf *icon)
3956 g_return_if_fail (GDK_IS_PIXBUF (icon));
3958 list = g_list_prepend (NULL, icon);
3959 gtk_window_set_default_icon_list (list);
3964 * gtk_window_set_default_icon_name:
3965 * @name: the name of the themed icon
3967 * Sets an icon to be used as fallback for windows that haven't
3968 * had gtk_window_set_icon_list() called on them from a named
3969 * themed icon, see gtk_window_set_icon_name().
3974 gtk_window_set_default_icon_name (const gchar *name)
3979 /* Update serial so we don't used cached pixmaps/masks
3981 default_icon_serial++;
3983 g_free (default_icon_name);
3984 default_icon_name = g_strdup (name);
3986 g_list_free_full (default_icon_list, g_object_unref);
3987 default_icon_list = NULL;
3989 /* Update all toplevels */
3990 toplevels = gtk_window_list_toplevels ();
3991 tmp_list = toplevels;
3992 while (tmp_list != NULL)
3994 GtkWindowIconInfo *info;
3995 GtkWindow *w = tmp_list->data;
3997 info = get_icon_info (w);
3998 if (info && info->using_default_icon && info->using_themed_icon)
4000 gtk_window_unrealize_icon (w);
4001 if (gtk_widget_get_realized (GTK_WIDGET (w)))
4002 gtk_window_realize_icon (w);
4005 tmp_list = tmp_list->next;
4007 g_list_free (toplevels);
4011 * gtk_window_get_default_icon_name:
4013 * Returns the fallback icon name for windows that has been set
4014 * with gtk_window_set_default_icon_name(). The returned
4015 * string is owned by GTK+ and should not be modified. It
4016 * is only valid until the next call to
4017 * gtk_window_set_default_icon_name().
4019 * Returns: the fallback icon name for windows
4024 gtk_window_get_default_icon_name (void)
4026 return default_icon_name;
4030 * gtk_window_set_default_icon_from_file:
4031 * @filename: (type filename): location of icon file
4032 * @err: (allow-none): location to store error, or %NULL.
4034 * Sets an icon to be used as fallback for windows that haven't
4035 * had gtk_window_set_icon_list() called on them from a file
4036 * on disk. Warns on failure if @err is %NULL.
4038 * Returns: %TRUE if setting the icon succeeded.
4043 gtk_window_set_default_icon_from_file (const gchar *filename,
4046 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
4050 gtk_window_set_default_icon (pixbuf);
4051 g_object_unref (pixbuf);
4060 * gtk_window_get_default_icon_list:
4062 * Gets the value set by gtk_window_set_default_icon_list().
4063 * The list is a copy and should be freed with g_list_free(),
4064 * but the pixbufs in the list have not had their reference count
4067 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
4070 gtk_window_get_default_icon_list (void)
4072 return g_list_copy (default_icon_list);
4076 gtk_window_set_default_size_internal (GtkWindow *window,
4077 gboolean change_width,
4079 gboolean change_height,
4081 gboolean is_geometry)
4083 GtkWindowGeometryInfo *info;
4085 g_return_if_fail (change_width == FALSE || width >= -1);
4086 g_return_if_fail (change_height == FALSE || height >= -1);
4088 info = gtk_window_get_geometry_info (window, TRUE);
4090 g_object_freeze_notify (G_OBJECT (window));
4092 info->default_is_geometry = is_geometry != FALSE;
4102 info->default_width = width;
4104 g_object_notify (G_OBJECT (window), "default-width");
4115 info->default_height = height;
4117 g_object_notify (G_OBJECT (window), "default-height");
4120 g_object_thaw_notify (G_OBJECT (window));
4122 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4126 * gtk_window_set_default_size:
4127 * @window: a #GtkWindow
4128 * @width: width in pixels, or -1 to unset the default width
4129 * @height: height in pixels, or -1 to unset the default height
4131 * Sets the default size of a window. If the window's "natural" size
4132 * (its size request) is larger than the default, the default will be
4133 * ignored. More generally, if the default size does not obey the
4134 * geometry hints for the window (gtk_window_set_geometry_hints() can
4135 * be used to set these explicitly), the default size will be clamped
4136 * to the nearest permitted size.
4138 * Unlike gtk_widget_set_size_request(), which sets a size request for
4139 * a widget and thus would keep users from shrinking the window, this
4140 * function only sets the initial size, just as if the user had
4141 * resized the window themselves. Users can still shrink the window
4142 * again as they normally would. Setting a default size of -1 means to
4143 * use the "natural" default size (the size request of the window).
4145 * For more control over a window's initial size and how resizing works,
4146 * investigate gtk_window_set_geometry_hints().
4148 * For some uses, gtk_window_resize() is a more appropriate function.
4149 * gtk_window_resize() changes the current size of the window, rather
4150 * than the size to be used on initial display. gtk_window_resize() always
4151 * affects the window itself, not the geometry widget.
4153 * The default size of a window only affects the first time a window is
4154 * shown; if a window is hidden and re-shown, it will remember the size
4155 * it had prior to hiding, rather than using the default size.
4157 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4158 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4161 gtk_window_set_default_size (GtkWindow *window,
4165 g_return_if_fail (GTK_IS_WINDOW (window));
4166 g_return_if_fail (width >= -1);
4167 g_return_if_fail (height >= -1);
4169 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4173 * gtk_window_set_default_geometry:
4174 * @window: a #GtkWindow
4175 * @width: width in resize increments, or -1 to unset the default width
4176 * @height: height in resize increments, or -1 to unset the default height
4178 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4179 * in terms of the base size and increment set with
4180 * gtk_window_set_geometry_hints.
4185 gtk_window_set_default_geometry (GtkWindow *window,
4189 g_return_if_fail (GTK_IS_WINDOW (window));
4190 g_return_if_fail (width >= -1);
4191 g_return_if_fail (height >= -1);
4193 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4197 * gtk_window_get_default_size:
4198 * @window: a #GtkWindow
4199 * @width: (out) (allow-none): location to store the default width, or %NULL
4200 * @height: (out) (allow-none): location to store the default height, or %NULL
4202 * Gets the default size of the window. A value of -1 for the width or
4203 * height indicates that a default size has not been explicitly set
4204 * for that dimension, so the "natural" size of the window will be
4209 gtk_window_get_default_size (GtkWindow *window,
4213 GtkWindowGeometryInfo *info;
4215 g_return_if_fail (GTK_IS_WINDOW (window));
4217 info = gtk_window_get_geometry_info (window, FALSE);
4220 *width = info ? info->default_width : -1;
4223 *height = info ? info->default_height : -1;
4227 * gtk_window_resize:
4228 * @window: a #GtkWindow
4229 * @width: width in pixels to resize the window to
4230 * @height: height in pixels to resize the window to
4232 * Resizes the window as if the user had done so, obeying geometry
4233 * constraints. The default geometry constraint is that windows may
4234 * not be smaller than their size request; to override this
4235 * constraint, call gtk_widget_set_size_request() to set the window's
4236 * request to a smaller value.
4238 * If gtk_window_resize() is called before showing a window for the
4239 * first time, it overrides any default size set with
4240 * gtk_window_set_default_size().
4242 * Windows may not be resized smaller than 1 by 1 pixels.
4246 gtk_window_resize (GtkWindow *window,
4250 GtkWindowGeometryInfo *info;
4252 g_return_if_fail (GTK_IS_WINDOW (window));
4253 g_return_if_fail (width > 0);
4254 g_return_if_fail (height > 0);
4256 info = gtk_window_get_geometry_info (window, TRUE);
4258 info->resize_width = width;
4259 info->resize_height = height;
4260 info->resize_is_geometry = FALSE;
4262 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4266 * gtk_window_resize_to_geometry:
4267 * @window: a #GtkWindow
4268 * @width: width in resize increments to resize the window to
4269 * @height: height in resize increments to resize the window to
4271 * Like gtk_window_resize(), but @width and @height are interpreted
4272 * in terms of the base size and increment set with
4273 * gtk_window_set_geometry_hints.
4278 gtk_window_resize_to_geometry (GtkWindow *window,
4282 GtkWindowGeometryInfo *info;
4284 g_return_if_fail (GTK_IS_WINDOW (window));
4285 g_return_if_fail (width > 0);
4286 g_return_if_fail (height > 0);
4288 info = gtk_window_get_geometry_info (window, TRUE);
4290 info->resize_width = width;
4291 info->resize_height = height;
4292 info->resize_is_geometry = TRUE;
4294 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4298 * gtk_window_get_size:
4299 * @window: a #GtkWindow
4300 * @width: (out) (allow-none): return location for width, or %NULL
4301 * @height: (out) (allow-none): return location for height, or %NULL
4303 * Obtains the current size of @window. If @window is not onscreen,
4304 * it returns the size GTK+ will suggest to the <link
4305 * linkend="gtk-X11-arch">window manager</link> for the initial window
4306 * size (but this is not reliably the same as the size the window
4307 * manager will actually select). The size obtained by
4308 * gtk_window_get_size() is the last size received in a
4309 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4310 * rather than querying the X server for the size. As a result, if you
4311 * call gtk_window_resize() then immediately call
4312 * gtk_window_get_size(), the size won't have taken effect yet. After
4313 * the window manager processes the resize request, GTK+ receives
4314 * notification that the size has changed via a configure event, and
4315 * the size of the window gets updated.
4317 * Note 1: Nearly any use of this function creates a race condition,
4318 * because the size of the window may change between the time that you
4319 * get the size and the time that you perform some action assuming
4320 * that size is the current size. To avoid race conditions, connect to
4321 * "configure-event" on the window and adjust your size-dependent
4322 * state to match the size delivered in the #GdkEventConfigure.
4324 * Note 2: The returned size does <emphasis>not</emphasis> include the
4325 * size of the window manager decorations (aka the window frame or
4326 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4327 * method of determining their size.
4329 * Note 3: If you are getting a window size in order to position
4330 * the window onscreen, there may be a better way. The preferred
4331 * way is to simply set the window's semantic type with
4332 * gtk_window_set_type_hint(), which allows the window manager to
4333 * e.g. center dialogs. Also, if you set the transient parent of
4334 * dialogs with gtk_window_set_transient_for() window managers
4335 * will often center the dialog over its parent window. It's
4336 * much preferred to let the window manager handle these
4337 * things rather than doing it yourself, because all apps will
4338 * behave consistently and according to user prefs if the window
4339 * manager handles it. Also, the window manager can take the size
4340 * of the window decorations/border into account, while your
4341 * application cannot.
4343 * In any case, if you insist on application-specified window
4344 * positioning, there's <emphasis>still</emphasis> a better way than
4345 * doing it yourself - gtk_window_set_position() will frequently
4346 * handle the details for you.
4350 gtk_window_get_size (GtkWindow *window,
4356 g_return_if_fail (GTK_IS_WINDOW (window));
4358 if (width == NULL && height == NULL)
4361 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4363 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4364 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4368 GdkRectangle configure_request;
4370 gtk_window_compute_configure_request (window,
4374 w = configure_request.width;
4375 h = configure_request.height;
4386 * @window: a #GtkWindow
4387 * @x: X coordinate to move window to
4388 * @y: Y coordinate to move window to
4390 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4391 * @window to the given position. Window managers are free to ignore
4392 * this; most window managers ignore requests for initial window
4393 * positions (instead using a user-defined placement algorithm) and
4394 * honor requests after the window has already been shown.
4396 * Note: the position is the position of the gravity-determined
4397 * reference point for the window. The gravity determines two things:
4398 * first, the location of the reference point in root window
4399 * coordinates; and second, which point on the window is positioned at
4400 * the reference point.
4402 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4403 * point is simply the @x, @y supplied to gtk_window_move(). The
4404 * top-left corner of the window decorations (aka window frame or
4405 * border) will be placed at @x, @y. Therefore, to position a window
4406 * at the top left of the screen, you want to use the default gravity
4407 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4409 * To position a window at the bottom right corner of the screen, you
4410 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4411 * point is at @x + the window width and @y + the window height, and
4412 * the bottom-right corner of the window border will be placed at that
4413 * reference point. So, to place a window in the bottom right corner
4414 * you would first set gravity to south east, then write:
4415 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4416 * gdk_screen_height () - window_height)</literal> (note that this
4417 * example does not take multi-head scenarios into account).
4419 * The Extended Window Manager Hints specification at <ulink
4420 * url="http://www.freedesktop.org/Standards/wm-spec">
4421 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4422 * nice table of gravities in the "implementation notes" section.
4424 * The gtk_window_get_position() documentation may also be relevant.
4427 gtk_window_move (GtkWindow *window,
4431 GtkWindowGeometryInfo *info;
4434 g_return_if_fail (GTK_IS_WINDOW (window));
4436 widget = GTK_WIDGET (window);
4438 info = gtk_window_get_geometry_info (window, TRUE);
4440 if (gtk_widget_get_mapped (widget))
4442 GtkAllocation allocation;
4444 gtk_widget_get_allocation (widget, &allocation);
4446 /* we have now sent a request with this position
4447 * with currently-active constraints, so toggle flag.
4449 info->position_constraints_changed = FALSE;
4451 /* we only constrain if mapped - if not mapped,
4452 * then gtk_window_compute_configure_request()
4453 * will apply the constraints later, and we
4454 * don't want to lose information about
4455 * what position the user set before then.
4456 * i.e. if you do a move() then turn off POS_CENTER
4457 * then show the window, your move() will work.
4459 gtk_window_constrain_position (window,
4460 allocation.width, allocation.height,
4463 /* Note that this request doesn't go through our standard request
4464 * framework, e.g. doesn't increment configure_request_count,
4465 * doesn't set info->last, etc.; that's because
4466 * we don't save the info needed to arrive at this same request
4469 * To gtk_window_move_resize(), this will end up looking exactly
4470 * the same as the position being changed by the window
4473 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4477 /* Save this position to apply on mapping */
4478 info->initial_x = x;
4479 info->initial_y = y;
4480 info->initial_pos_set = TRUE;
4485 * gtk_window_get_position:
4486 * @window: a #GtkWindow
4487 * @root_x: (out) (allow-none): return location for X coordinate of
4488 * gravity-determined reference point, or %NULL
4489 * @root_y: (out) (allow-none): return location for Y coordinate of
4490 * gravity-determined reference point, or %NULL
4492 * This function returns the position you need to pass to
4493 * gtk_window_move() to keep @window in its current position.
4494 * This means that the meaning of the returned value varies with
4495 * window gravity. See gtk_window_move() for more details.
4497 * If you haven't changed the window gravity, its gravity will be
4498 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4499 * gets the position of the top-left corner of the window manager
4500 * frame for the window. gtk_window_move() sets the position of this
4501 * same top-left corner.
4503 * gtk_window_get_position() is not 100% reliable because the X Window System
4504 * does not specify a way to obtain the geometry of the
4505 * decorations placed on a window by the window manager.
4506 * Thus GTK+ is using a "best guess" that works with most
4509 * Moreover, nearly all window managers are historically broken with
4510 * respect to their handling of window gravity. So moving a window to
4511 * its current position as returned by gtk_window_get_position() tends
4512 * to result in moving the window slightly. Window managers are
4513 * slowly getting better over time.
4515 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4516 * frame is not relevant, and thus gtk_window_get_position() will
4517 * always produce accurate results. However you can't use static
4518 * gravity to do things like place a window in a corner of the screen,
4519 * because static gravity ignores the window manager decorations.
4521 * If you are saving and restoring your application's window
4522 * positions, you should know that it's impossible for applications to
4523 * do this without getting it somewhat wrong because applications do
4524 * not have sufficient knowledge of window manager state. The Correct
4525 * Mechanism is to support the session management protocol (see the
4526 * "GnomeClient" object in the GNOME libraries for example) and allow
4527 * the window manager to save your window sizes and positions.
4532 gtk_window_get_position (GtkWindow *window,
4536 GtkWindowPrivate *priv;
4538 GdkWindow *gdk_window;
4540 g_return_if_fail (GTK_IS_WINDOW (window));
4542 priv = window->priv;
4543 widget = GTK_WIDGET (window);
4544 gdk_window = gtk_widget_get_window (widget);
4546 if (priv->gravity == GDK_GRAVITY_STATIC)
4548 if (gtk_widget_get_mapped (widget))
4550 /* This does a server round-trip, which is sort of wrong;
4551 * but a server round-trip is inevitable for
4552 * gdk_window_get_frame_extents() in the usual
4553 * NorthWestGravity case below, so not sure what else to
4554 * do. We should likely be consistent about whether we get
4555 * the client-side info or the server-side info.
4557 gdk_window_get_origin (gdk_window, root_x, root_y);
4561 GdkRectangle configure_request;
4563 gtk_window_compute_configure_request (window,
4567 *root_x = configure_request.x;
4568 *root_y = configure_request.y;
4573 GdkRectangle frame_extents;
4578 if (gtk_widget_get_mapped (widget))
4580 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4581 x = frame_extents.x;
4582 y = frame_extents.y;
4583 gtk_window_get_size (window, &w, &h);
4587 /* We just say the frame has 0 size on all sides.
4588 * Not sure what else to do.
4590 gtk_window_compute_configure_request (window,
4593 x = frame_extents.x;
4594 y = frame_extents.y;
4595 w = frame_extents.width;
4596 h = frame_extents.height;
4599 switch (priv->gravity)
4601 case GDK_GRAVITY_NORTH:
4602 case GDK_GRAVITY_CENTER:
4603 case GDK_GRAVITY_SOUTH:
4604 /* Find center of frame. */
4605 x += frame_extents.width / 2;
4606 /* Center client window on that point. */
4610 case GDK_GRAVITY_SOUTH_EAST:
4611 case GDK_GRAVITY_EAST:
4612 case GDK_GRAVITY_NORTH_EAST:
4613 /* Find right edge of frame */
4614 x += frame_extents.width;
4615 /* Align left edge of client at that point. */
4622 switch (priv->gravity)
4624 case GDK_GRAVITY_WEST:
4625 case GDK_GRAVITY_CENTER:
4626 case GDK_GRAVITY_EAST:
4627 /* Find center of frame. */
4628 y += frame_extents.height / 2;
4629 /* Center client window there. */
4632 case GDK_GRAVITY_SOUTH_WEST:
4633 case GDK_GRAVITY_SOUTH:
4634 case GDK_GRAVITY_SOUTH_EAST:
4635 /* Find south edge of frame */
4636 y += frame_extents.height;
4637 /* Place bottom edge of client there */
4652 * gtk_window_reshow_with_initial_size:
4653 * @window: a #GtkWindow
4655 * Hides @window, then reshows it, resetting the
4656 * default size and position of the window. Used
4657 * by GUI builders only.
4660 gtk_window_reshow_with_initial_size (GtkWindow *window)
4664 g_return_if_fail (GTK_IS_WINDOW (window));
4666 widget = GTK_WIDGET (window);
4668 gtk_widget_hide (widget);
4669 gtk_widget_unrealize (widget);
4670 gtk_widget_show (widget);
4674 gtk_window_destroy (GtkWidget *widget)
4676 GtkWindow *window = GTK_WINDOW (widget);
4677 GtkWindowPrivate *priv = window->priv;
4679 gtk_window_release_application (window);
4681 toplevel_list = g_slist_remove (toplevel_list, window);
4683 if (priv->transient_parent)
4684 gtk_window_set_transient_for (window, NULL);
4686 remove_attach_widget (GTK_WINDOW (widget));
4688 /* frees the icons */
4689 gtk_window_set_icon_list (window, NULL);
4691 if (priv->has_user_ref_count)
4693 priv->has_user_ref_count = FALSE;
4694 g_object_unref (window);
4698 gtk_window_group_remove_window (priv->group, window);
4700 gtk_window_free_key_hash (window);
4702 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4706 gtk_window_finalize (GObject *object)
4708 GtkWindow *window = GTK_WINDOW (object);
4709 GtkWindowPrivate *priv = window->priv;
4710 GtkMnemonicHash *mnemonic_hash;
4712 g_free (priv->title);
4713 g_free (priv->wmclass_name);
4714 g_free (priv->wmclass_class);
4715 g_free (priv->wm_role);
4716 gtk_window_release_application (window);
4718 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4720 _gtk_mnemonic_hash_free (mnemonic_hash);
4722 if (priv->geometry_info)
4724 if (priv->geometry_info->widget)
4725 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4726 gtk_widget_destroyed,
4727 &priv->geometry_info->widget);
4728 g_free (priv->geometry_info);
4731 if (priv->keys_changed_handler)
4733 g_source_remove (priv->keys_changed_handler);
4734 priv->keys_changed_handler = 0;
4738 g_signal_handlers_disconnect_by_func (priv->screen,
4739 gtk_window_on_composited_changed, window);
4741 g_free (priv->startup_id);
4743 if (priv->auto_mnemonics_timeout_id)
4745 g_source_remove (priv->auto_mnemonics_timeout_id);
4746 priv->auto_mnemonics_timeout_id = 0;
4749 #ifdef GDK_WINDOWING_X11
4750 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4751 gtk_window_on_theme_variant_changed,
4755 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4759 gtk_window_show (GtkWidget *widget)
4761 GtkWindow *window = GTK_WINDOW (widget);
4762 GtkWindowPrivate *priv = window->priv;
4763 GtkContainer *container = GTK_CONTAINER (window);
4765 gboolean need_resize;
4768 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4770 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4774 _gtk_widget_set_visible_flag (widget, TRUE);
4776 need_resize = _gtk_widget_get_alloc_needed (widget) || !gtk_widget_get_realized (widget);
4778 empty = _gtk_bitmask_new ();
4779 _gtk_style_context_validate (gtk_widget_get_style_context (widget),
4780 g_get_monotonic_time (),
4783 _gtk_bitmask_free (empty);
4787 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4788 GtkAllocation allocation = { 0, 0 };
4789 GdkRectangle configure_request;
4790 GdkGeometry new_geometry;
4792 gboolean was_realized;
4794 /* We are going to go ahead and perform this configure request
4795 * and then emulate a configure notify by going ahead and
4796 * doing a size allocate. Sort of a synchronous
4797 * mini-copy of gtk_window_move_resize() here.
4799 gtk_window_compute_configure_request (window,
4804 /* We update this because we are going to go ahead
4805 * and gdk_window_resize() below, rather than
4808 info->last.configure_request.width = configure_request.width;
4809 info->last.configure_request.height = configure_request.height;
4811 /* and allocate the window - this is normally done
4812 * in move_resize in response to configure notify
4814 allocation.width = configure_request.width;
4815 allocation.height = configure_request.height;
4816 gtk_widget_size_allocate (widget, &allocation);
4818 /* Then we guarantee we have a realize */
4819 was_realized = FALSE;
4820 if (!gtk_widget_get_realized (widget))
4822 gtk_widget_realize (widget);
4823 was_realized = TRUE;
4826 /* We only send configure request if we didn't just finish
4827 * creating the window; if we just created the window
4828 * then we created it with widget->allocation anyhow.
4831 gdk_window_move_resize (gtk_widget_get_window (widget),
4832 configure_request.x,
4833 configure_request.y,
4834 configure_request.width,
4835 configure_request.height);
4838 gtk_container_check_resize (container);
4840 gtk_widget_map (widget);
4842 /* Try to make sure that we have some focused widget
4844 #ifdef GDK_WINDOWING_X11
4845 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4846 GTK_IS_PLUG (window);
4850 if (!priv->focus_widget && !is_plug)
4851 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4854 gtk_grab_add (widget);
4858 gtk_window_hide (GtkWidget *widget)
4860 GtkWindow *window = GTK_WINDOW (widget);
4861 GtkWindowPrivate *priv = window->priv;
4863 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4865 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4869 _gtk_widget_set_visible_flag (widget, FALSE);
4870 gtk_widget_unmap (widget);
4873 gtk_grab_remove (widget);
4877 gtk_window_map (GtkWidget *widget)
4880 GtkWindow *window = GTK_WINDOW (widget);
4881 GtkWindowPrivate *priv = window->priv;
4882 GdkWindow *gdk_window;
4883 gboolean auto_mnemonics;
4884 GtkPolicyType visible_focus;
4886 if (!gtk_widget_is_toplevel (widget))
4888 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4892 gtk_widget_set_mapped (widget, TRUE);
4894 child = gtk_bin_get_child (&(window->bin));
4896 gtk_widget_get_visible (child) &&
4897 !gtk_widget_get_mapped (child))
4898 gtk_widget_map (child);
4900 gdk_window = gtk_widget_get_window (widget);
4902 if (priv->maximize_initially)
4903 gdk_window_maximize (gdk_window);
4905 gdk_window_unmaximize (gdk_window);
4907 if (priv->stick_initially)
4908 gdk_window_stick (gdk_window);
4910 gdk_window_unstick (gdk_window);
4912 if (priv->iconify_initially)
4913 gdk_window_iconify (gdk_window);
4915 gdk_window_deiconify (gdk_window);
4917 if (priv->fullscreen_initially)
4918 gdk_window_fullscreen (gdk_window);
4920 gdk_window_unfullscreen (gdk_window);
4922 gdk_window_set_keep_above (gdk_window, priv->above_initially);
4924 gdk_window_set_keep_below (gdk_window, priv->below_initially);
4926 if (priv->type == GTK_WINDOW_TOPLEVEL)
4928 gtk_window_set_theme_variant (window);
4929 gtk_window_set_hide_titlebar_when_maximized (window,
4930 priv->hide_titlebar_when_maximized);
4933 /* No longer use the default settings */
4934 priv->need_default_size = FALSE;
4935 priv->need_default_position = FALSE;
4937 if (priv->reset_type_hint)
4939 /* We should only reset the type hint when the application
4940 * used gtk_window_set_type_hint() to change the hint.
4941 * Some applications use X directly to change the properties;
4942 * in that case, we shouldn't overwrite what they did.
4944 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4945 priv->reset_type_hint = FALSE;
4948 gdk_window_show (gdk_window);
4950 if (priv->grip_window)
4951 gdk_window_show (priv->grip_window);
4953 if (!disable_startup_notification)
4955 /* Do we have a custom startup-notification id? */
4956 if (priv->startup_id != NULL)
4958 /* Make sure we have a "real" id */
4959 if (!startup_id_is_fake (priv->startup_id))
4960 gdk_notify_startup_complete_with_id (priv->startup_id);
4962 g_free (priv->startup_id);
4963 priv->startup_id = NULL;
4965 else if (!sent_startup_notification)
4967 sent_startup_notification = TRUE;
4968 gdk_notify_startup_complete ();
4972 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4973 * (as in the case of popup menus), then hide mnemonics initially
4975 g_object_get (gtk_widget_get_settings (widget),
4976 "gtk-auto-mnemonics", &auto_mnemonics,
4977 "gtk-visible-focus", &visible_focus,
4980 if (auto_mnemonics && !priv->mnemonics_visible_set)
4981 gtk_window_set_mnemonics_visible (window, FALSE);
4983 /* inherit from transient parent, so that a dialog that is
4984 * opened via keynav shows focus initially
4986 if (priv->transient_parent)
4987 gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
4989 gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
4993 gtk_window_map_event (GtkWidget *widget,
4996 if (!gtk_widget_get_mapped (widget))
4998 /* we should be be unmapped, but are getting a MapEvent, this may happen
4999 * to toplevel XWindows if mapping was intercepted by a window manager
5000 * and an unmap request occoured while the MapRequestEvent was still
5001 * being handled. we work around this situaiton here by re-requesting
5002 * the window being unmapped. more details can be found in:
5003 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
5005 gdk_window_hide (gtk_widget_get_window (widget));
5011 gtk_window_unmap (GtkWidget *widget)
5013 GtkWindow *window = GTK_WINDOW (widget);
5014 GtkWindowPrivate *priv = window->priv;
5016 GtkWindowGeometryInfo *info;
5017 GdkWindow *gdk_window;
5018 GdkWindowState state;
5020 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5022 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
5026 gdk_window = gtk_widget_get_window (widget);
5028 gtk_widget_set_mapped (widget, FALSE);
5029 gdk_window_withdraw (gdk_window);
5031 priv->configure_request_count = 0;
5032 priv->configure_notify_received = FALSE;
5034 /* on unmap, we reset the default positioning of the window,
5035 * so it's placed again, but we don't reset the default
5036 * size of the window, so it's remembered.
5038 priv->need_default_position = TRUE;
5040 info = gtk_window_get_geometry_info (window, FALSE);
5043 info->initial_pos_set = FALSE;
5044 info->position_constraints_changed = FALSE;
5047 state = gdk_window_get_state (gdk_window);
5048 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
5049 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
5050 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
5051 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
5052 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
5054 child = gtk_bin_get_child (&(window->bin));
5056 gtk_widget_unmap (child);
5059 /* (Note: Replace "size" with "width" or "height". Also, the request
5060 * mode is honoured.)
5061 * For selecting the default window size, the following conditions
5062 * should hold (in order of importance):
5063 * - the size is not below the minimum size
5064 * Windows cannot be resized below their minimum size, so we must
5065 * ensure we don't do that either.
5066 * - the size is not above the natural size
5067 * It seems weird to allocate more than this in an initial guess.
5068 * - the size does not exceed that of a maximized window
5069 * We want to see the whole window after all.
5070 * (Note that this may not be possible to achieve due to imperfect
5071 * information from the windowing system.)
5074 /* We use these for now to not make windows too big by accident. Note
5075 * that we still clamp these numbers by screen size. Also note that
5076 * minimum size still overrides this. So keep your windows small! :)
5078 #define MAX_DEFAULT_WINDOW_WIDTH 640
5079 #define MAX_DEFAULT_WINDOW_HEIGHT 480
5082 gtk_window_guess_default_size (GtkWindow *window,
5086 GtkWidget *widget = GTK_WIDGET (window);
5088 int minimum, natural;
5090 screen = gtk_widget_get_screen (widget);
5092 *width = gdk_screen_get_width (screen);
5093 *height = gdk_screen_get_height (screen);
5095 if (*width >= *height)
5098 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
5099 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
5104 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
5105 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
5108 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
5110 gtk_widget_get_preferred_height (widget, &minimum, &natural);
5111 *height = MAX (minimum, MIN (*height, natural));
5113 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
5114 *width = MAX (minimum, MIN (*width, natural));
5116 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
5118 gtk_widget_get_preferred_width (widget, &minimum, &natural);
5119 *width = MAX (minimum, MIN (*width, natural));
5121 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
5122 *height = MAX (minimum, MIN (*height, natural));
5127 gtk_window_realize (GtkWidget *widget)
5129 GtkAllocation allocation;
5131 GdkWindow *parent_window;
5132 GdkWindow *gdk_window;
5133 GdkWindowAttr attributes;
5134 gint attributes_mask;
5135 GtkWindowPrivate *priv;
5136 GtkStyleContext *context;
5138 window = GTK_WINDOW (widget);
5139 priv = window->priv;
5141 gtk_widget_get_allocation (widget, &allocation);
5143 if (gtk_widget_get_parent_window (widget))
5145 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
5147 gtk_widget_set_realized (widget, TRUE);
5149 attributes.x = allocation.x;
5150 attributes.y = allocation.y;
5151 attributes.width = allocation.width;
5152 attributes.height = allocation.height;
5153 attributes.window_type = GDK_WINDOW_CHILD;
5155 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
5157 attributes.visual = gtk_widget_get_visual (widget);
5158 attributes.wclass = GDK_INPUT_OUTPUT;
5160 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
5162 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
5163 &attributes, attributes_mask);
5164 gtk_widget_set_window (widget, gdk_window);
5165 gtk_widget_register_window (widget, gdk_window);
5167 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
5172 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5174 /* ensure widget tree is properly size allocated */
5175 if (allocation.x == -1 &&
5176 allocation.y == -1 &&
5177 allocation.width == 1 &&
5178 allocation.height == 1)
5184 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5185 if (allocation.width == 0 || allocation.height == 0)
5187 /* non-empty window */
5188 allocation.width = 200;
5189 allocation.height = 200;
5191 gtk_widget_size_allocate (widget, &allocation);
5193 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5195 g_return_if_fail (!gtk_widget_get_realized (widget));
5198 gtk_widget_set_realized (widget, TRUE);
5202 case GTK_WINDOW_TOPLEVEL:
5203 attributes.window_type = GDK_WINDOW_TOPLEVEL;
5205 case GTK_WINDOW_POPUP:
5206 attributes.window_type = GDK_WINDOW_TEMP;
5209 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5213 attributes.title = priv->title;
5214 attributes.wmclass_name = priv->wmclass_name;
5215 attributes.wmclass_class = priv->wmclass_class;
5216 attributes.wclass = GDK_INPUT_OUTPUT;
5217 attributes.visual = gtk_widget_get_visual (widget);
5219 attributes_mask = 0;
5220 parent_window = gtk_widget_get_root_window (widget);
5222 gtk_widget_get_allocation (widget, &allocation);
5223 attributes.width = allocation.width;
5224 attributes.height = allocation.height;
5225 attributes.event_mask = gtk_widget_get_events (widget);
5226 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5227 GDK_KEY_PRESS_MASK |
5228 GDK_KEY_RELEASE_MASK |
5229 GDK_ENTER_NOTIFY_MASK |
5230 GDK_LEAVE_NOTIFY_MASK |
5231 GDK_FOCUS_CHANGE_MASK |
5232 GDK_STRUCTURE_MASK);
5233 attributes.type_hint = priv->type_hint;
5235 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5236 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5237 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5239 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5240 gtk_widget_set_window (widget, gdk_window);
5242 gtk_widget_register_window (widget, gdk_window);
5244 context = gtk_widget_get_style_context (widget);
5245 gtk_style_context_set_background (context, gdk_window);
5248 if (priv->transient_parent &&
5249 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5250 gdk_window_set_transient_for (gdk_window,
5251 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5254 gdk_window_set_role (gdk_window, priv->wm_role);
5256 if (!priv->decorated)
5257 gdk_window_set_decorations (gdk_window, 0);
5259 if (!priv->deletable)
5260 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5262 if (gtk_window_get_skip_pager_hint (window))
5263 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5265 if (gtk_window_get_skip_taskbar_hint (window))
5266 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5268 if (gtk_window_get_accept_focus (window))
5269 gdk_window_set_accept_focus (gdk_window, TRUE);
5271 gdk_window_set_accept_focus (gdk_window, FALSE);
5273 if (gtk_window_get_focus_on_map (window))
5274 gdk_window_set_focus_on_map (gdk_window, TRUE);
5276 gdk_window_set_focus_on_map (gdk_window, FALSE);
5279 gdk_window_set_modal_hint (gdk_window, TRUE);
5281 gdk_window_set_modal_hint (gdk_window, FALSE);
5283 if (priv->startup_id)
5285 #ifdef GDK_WINDOWING_X11
5286 if (GDK_IS_X11_WINDOW (gdk_window))
5288 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5289 if (timestamp != GDK_CURRENT_TIME)
5290 gdk_x11_window_set_user_time (gdk_window, timestamp);
5293 if (!startup_id_is_fake (priv->startup_id))
5294 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5297 #ifdef GDK_WINDOWING_X11
5298 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5300 if (GDK_IS_X11_WINDOW (gdk_window))
5301 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5306 gtk_window_realize_icon (window);
5308 if (priv->has_resize_grip)
5309 resize_grip_create_window (window);
5313 gtk_window_unrealize (GtkWidget *widget)
5315 GtkWindow *window = GTK_WINDOW (widget);
5316 GtkWindowPrivate *priv = window->priv;
5317 GtkWindowGeometryInfo *info;
5319 /* On unrealize, we reset the size of the window such
5320 * that we will re-apply the default sizing stuff
5321 * next time we show the window.
5323 * Default positioning is reset on unmap, instead of unrealize.
5325 priv->need_default_size = TRUE;
5326 info = gtk_window_get_geometry_info (window, FALSE);
5329 info->resize_width = -1;
5330 info->resize_height = -1;
5331 info->last.configure_request.x = 0;
5332 info->last.configure_request.y = 0;
5333 info->last.configure_request.width = -1;
5334 info->last.configure_request.height = -1;
5335 /* be sure we reset geom hints on re-realize */
5336 info->last.flags = 0;
5340 gtk_window_unrealize_icon (window);
5342 if (priv->grip_window != NULL)
5343 resize_grip_destroy_window (window);
5345 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5348 static GtkJunctionSides
5349 get_grip_junction (GtkWidget *widget)
5351 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5352 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5354 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5358 get_drag_edge (GtkWidget *widget,
5359 GdkWindowEdge *edge)
5361 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5362 gboolean hresizable;
5363 gboolean vresizable;
5364 GtkTextDirection dir;
5365 GtkWindowGeometryInfo *info;
5370 info = priv->geometry_info;
5373 GdkWindowHints flags = info->last.flags;
5374 GdkGeometry *geometry = &info->last.geometry;
5376 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5378 hresizable = geometry->min_width < geometry->max_width;
5379 vresizable = geometry->min_height < geometry->max_height;
5383 dir = gtk_widget_get_direction (widget);
5385 if (hresizable && vresizable)
5386 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5387 else if (hresizable)
5388 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5389 else if (vresizable)
5390 *edge = GDK_WINDOW_EDGE_SOUTH;
5398 set_grip_cursor (GtkWindow *window)
5400 GtkWidget *widget = GTK_WIDGET (window);
5401 GtkWindowPrivate *priv = window->priv;
5403 if (priv->grip_window == NULL)
5406 if (gtk_widget_is_sensitive (widget))
5409 GdkDisplay *display;
5410 GdkCursorType cursor_type;
5413 cursor_type = GDK_LEFT_PTR;
5415 if (get_drag_edge (widget, &edge))
5419 case GDK_WINDOW_EDGE_EAST:
5420 cursor_type = GDK_RIGHT_SIDE;
5422 case GDK_WINDOW_EDGE_SOUTH_EAST:
5423 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5425 case GDK_WINDOW_EDGE_SOUTH:
5426 cursor_type = GDK_BOTTOM_SIDE;
5428 case GDK_WINDOW_EDGE_SOUTH_WEST:
5429 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5431 case GDK_WINDOW_EDGE_WEST:
5432 cursor_type = GDK_LEFT_SIDE;
5438 display = gtk_widget_get_display (widget);
5439 cursor = gdk_cursor_new_for_display (display, cursor_type);
5440 gdk_window_set_cursor (priv->grip_window, cursor);
5441 g_object_unref (cursor);
5444 gdk_window_set_cursor (priv->grip_window, NULL);
5448 set_grip_shape (GtkWindow *window)
5450 GtkWindowPrivate *priv = window->priv;
5451 cairo_region_t *region;
5452 cairo_surface_t *surface;
5454 double width, height;
5456 if (priv->grip_window == NULL)
5459 width = gdk_window_get_width (priv->grip_window);
5460 height = gdk_window_get_height (priv->grip_window);
5461 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
5463 cr = cairo_create (surface);
5464 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5466 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5467 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5469 cairo_move_to (cr, width, 0.0);
5470 cairo_line_to (cr, width, height);
5471 cairo_line_to (cr, 0.0, height);
5475 cairo_move_to (cr, 0.0, 0.0);
5476 cairo_line_to (cr, width, height);
5477 cairo_line_to (cr, 0.0, height);
5479 cairo_close_path (cr);
5482 region = gdk_cairo_region_create_from_surface (surface);
5483 cairo_surface_destroy (surface);
5485 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5486 cairo_region_destroy (region);
5490 set_grip_position (GtkWindow *window)
5492 GtkWindowPrivate *priv = window->priv;
5495 if (priv->grip_window == NULL)
5498 gtk_window_get_resize_grip_area (window, &rect);
5499 gdk_window_raise (priv->grip_window);
5500 gdk_window_move_resize (priv->grip_window,
5502 rect.width, rect.height);
5505 /* _gtk_window_set_allocation:
5506 * @window: a #GtkWindow
5507 * @allocation: the new allocation
5509 * This function is like gtk_widget_set_allocation()
5510 * but does the necessary extra work to update
5511 * the resize grip positioning, etc.
5513 * Call this instead of gtk_widget_set_allocation()
5514 * when overriding ::size_allocate in a GtkWindow
5515 * subclass without chaining up.
5518 _gtk_window_set_allocation (GtkWindow *window,
5519 GtkAllocation *allocation)
5521 GtkWidget *widget = (GtkWidget *)window;
5523 gtk_widget_set_allocation (widget, allocation);
5525 if (gtk_widget_get_realized (widget))
5527 /* If it's not a toplevel we're embedded, we need to resize
5528 * the window's window and skip the grip.
5530 if (!gtk_widget_is_toplevel (widget))
5532 gdk_window_move_resize (gtk_widget_get_window (widget),
5533 allocation->x, allocation->y,
5534 allocation->width, allocation->height);
5538 update_grip_visibility (window);
5539 set_grip_position (window);
5545 gtk_window_size_allocate (GtkWidget *widget,
5546 GtkAllocation *allocation)
5548 GtkWindow *window = GTK_WINDOW (widget);
5549 GtkAllocation child_allocation;
5553 _gtk_window_set_allocation (window, allocation);
5555 child = gtk_bin_get_child (&(window->bin));
5556 if (child && gtk_widget_get_visible (child))
5558 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5559 child_allocation.x = border_width;
5560 child_allocation.y = border_width;
5561 child_allocation.width = MAX (1, allocation->width - border_width * 2);
5562 child_allocation.height = MAX (1, allocation->height - border_width * 2);
5564 gtk_widget_size_allocate (child, &child_allocation);
5569 gtk_window_configure_event (GtkWidget *widget,
5570 GdkEventConfigure *event)
5572 GtkAllocation allocation;
5573 GtkWindow *window = GTK_WINDOW (widget);
5574 GtkWindowPrivate *priv = window->priv;
5575 gboolean expected_reply = priv->configure_request_count > 0;
5577 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5579 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5580 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5585 /* priv->configure_request_count incremented for each
5586 * configure request, and decremented to a min of 0 for
5587 * each configure notify.
5589 * All it means is that we know we will get at least
5590 * priv->configure_request_count more configure notifies.
5591 * We could get more configure notifies than that; some
5592 * of the configure notifies we get may be unrelated to
5593 * the configure requests. But we will get at least
5594 * priv->configure_request_count notifies.
5597 if (priv->configure_request_count > 0)
5599 priv->configure_request_count -= 1;
5600 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5603 /* As an optimization, we avoid a resize when possible.
5605 * The only times we can avoid a resize are:
5606 * - we know only the position changed, not the size
5607 * - we know we have made more requests and so will get more
5608 * notifies and can wait to resize when we get them
5610 gtk_widget_get_allocation (widget, &allocation);
5611 if (!expected_reply &&
5612 (allocation.width == event->width &&
5613 allocation.height == event->height))
5619 * If we do need to resize, we do that by:
5620 * - setting configure_notify_received to TRUE
5621 * for use in gtk_window_move_resize()
5622 * - queueing a resize, leading to invocation of
5623 * gtk_window_move_resize() in an idle handler
5627 priv->configure_notify_received = TRUE;
5629 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5631 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5637 gtk_window_state_event (GtkWidget *widget,
5638 GdkEventWindowState *event)
5640 update_grip_visibility (GTK_WINDOW (widget));
5642 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
5643 ensure_state_flag_backdrop (widget);
5649 gtk_window_direction_changed (GtkWidget *widget,
5650 GtkTextDirection prev_dir)
5652 GtkWindow *window = GTK_WINDOW (widget);
5654 set_grip_cursor (window);
5655 set_grip_position (window);
5656 set_grip_shape (window);
5660 gtk_window_state_changed (GtkWidget *widget,
5661 GtkStateType previous_state)
5663 GtkWindow *window = GTK_WINDOW (widget);
5665 update_grip_visibility (window);
5669 gtk_window_style_updated (GtkWidget *widget)
5671 GtkWindow *window = GTK_WINDOW (widget);
5672 GtkWindowPrivate *priv = window->priv;
5675 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5677 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5679 gdk_window_move_resize (priv->grip_window,
5681 rect.width, rect.height);
5683 set_grip_shape (window);
5688 resize_grip_create_window (GtkWindow *window)
5691 GtkWindowPrivate *priv;
5692 GdkWindowAttr attributes;
5693 gint attributes_mask;
5695 GdkRGBA transparent = {0, 0, 0, 0};
5697 priv = window->priv;
5698 widget = GTK_WIDGET (window);
5700 g_return_if_fail (gtk_widget_get_realized (widget));
5701 g_return_if_fail (priv->grip_window == NULL);
5703 gtk_window_get_resize_grip_area (window, &rect);
5705 attributes.x = rect.x;
5706 attributes.y = rect.y;
5707 attributes.width = rect.width;
5708 attributes.height = rect.height;
5709 attributes.window_type = GDK_WINDOW_CHILD;
5710 attributes.wclass = GDK_INPUT_OUTPUT;
5711 attributes.event_mask = gtk_widget_get_events (widget) |
5713 GDK_BUTTON_PRESS_MASK;
5715 attributes_mask = GDK_WA_X | GDK_WA_Y;
5717 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5720 gdk_window_set_background_rgba (priv->grip_window, &transparent);
5722 gtk_widget_register_window (widget, priv->grip_window);
5724 gdk_window_raise (priv->grip_window);
5726 set_grip_shape (window);
5727 update_grip_visibility (window);
5731 resize_grip_destroy_window (GtkWindow *window)
5733 GtkWindowPrivate *priv = window->priv;
5735 gtk_widget_unregister_window (GTK_WIDGET (window), priv->grip_window);
5736 gdk_window_destroy (priv->grip_window);
5737 priv->grip_window = NULL;
5738 update_grip_visibility (window);
5742 * gtk_window_set_has_resize_grip:
5743 * @window: a #GtkWindow
5744 * @value: %TRUE to allow a resize grip
5746 * Sets whether @window has a corner resize grip.
5748 * Note that the resize grip is only shown if the window
5749 * is actually resizable and not maximized. Use
5750 * gtk_window_resize_grip_is_visible() to find out if the
5751 * resize grip is currently shown.
5756 gtk_window_set_has_resize_grip (GtkWindow *window,
5759 GtkWidget *widget = GTK_WIDGET (window);
5760 GtkWindowPrivate *priv = window->priv;
5762 value = value != FALSE;
5764 if (value != priv->has_resize_grip)
5766 priv->has_resize_grip = value;
5767 gtk_widget_queue_draw (widget);
5769 if (gtk_widget_get_realized (widget) &&
5770 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5772 if (priv->has_resize_grip && priv->grip_window == NULL)
5773 resize_grip_create_window (window);
5774 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5775 resize_grip_destroy_window (window);
5778 g_object_notify (G_OBJECT (window), "has-resize-grip");
5783 update_grip_visibility (GtkWindow *window)
5785 GtkWindowPrivate *priv = window->priv;
5788 val = gtk_window_resize_grip_is_visible (window);
5790 if (priv->grip_window != NULL)
5794 gdk_window_show (priv->grip_window);
5795 set_grip_cursor (window);
5799 gdk_window_hide (priv->grip_window);
5803 if (priv->resize_grip_visible != val)
5805 priv->resize_grip_visible = val;
5807 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5812 * gtk_window_resize_grip_is_visible:
5813 * @window: a #GtkWindow
5815 * Determines whether a resize grip is visible for the specified window.
5817 * Returns: %TRUE if a resize grip exists and is visible
5822 gtk_window_resize_grip_is_visible (GtkWindow *window)
5825 GtkWindowPrivate *priv;
5828 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5830 priv = window->priv;
5831 widget = GTK_WIDGET (window);
5833 if (priv->type == GTK_WINDOW_POPUP)
5836 if (!priv->resizable)
5839 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5842 if (gtk_widget_get_realized (widget))
5844 GdkWindowState state;
5846 state = gdk_window_get_state (gtk_widget_get_window (widget));
5848 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5852 if (!get_drag_edge (widget, &edge))
5855 return window->priv->has_resize_grip;
5859 * gtk_window_get_has_resize_grip:
5860 * @window: a #GtkWindow
5862 * Determines whether the window may have a resize grip.
5864 * Returns: %TRUE if the window has a resize grip
5869 gtk_window_get_has_resize_grip (GtkWindow *window)
5871 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5873 return window->priv->has_resize_grip;
5877 * gtk_window_get_resize_grip_area:
5878 * @window: a #GtkWindow
5879 * @rect: (out): a pointer to a #GdkRectangle which we should store
5880 * the resize grip area
5882 * If a window has a resize grip, this will retrieve the grip
5883 * position, width and height into the specified #GdkRectangle.
5885 * Returns: %TRUE if the resize grip's area was retrieved
5890 gtk_window_get_resize_grip_area (GtkWindow *window,
5893 GtkWidget *widget = GTK_WIDGET (window);
5894 GtkAllocation allocation;
5898 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5900 if (!window->priv->has_resize_grip)
5903 gtk_widget_get_allocation (widget, &allocation);
5905 gtk_widget_style_get (widget,
5906 "resize-grip-width", &grip_width,
5907 "resize-grip-height", &grip_height,
5910 if (grip_width > allocation.width)
5911 grip_width = allocation.width;
5913 if (grip_height > allocation.height)
5914 grip_height = allocation.height;
5916 rect->width = grip_width;
5917 rect->height = grip_height;
5918 rect->y = allocation.y + allocation.height - grip_height;
5920 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5921 rect->x = allocation.x + allocation.width - grip_width;
5923 rect->x = allocation.x;
5928 /* the accel_key and accel_mods fields of the key have to be setup
5929 * upon calling this function. it'll then return whether that key
5930 * is at all used as accelerator, and if so will OR in the
5931 * accel_flags member of the key.
5934 _gtk_window_query_nonaccels (GtkWindow *window,
5936 GdkModifierType accel_mods)
5938 GtkWindowPrivate *priv;
5940 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5942 priv = window->priv;
5944 /* movement keys are considered locked accels */
5947 static const guint bindings[] = {
5948 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,
5949 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,
5953 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5954 if (bindings[i] == accel_key)
5958 /* mnemonics are considered locked accels */
5959 if (accel_mods == priv->mnemonic_modifier)
5961 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5962 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5970 * gtk_window_propagate_key_event:
5971 * @window: a #GtkWindow
5972 * @event: a #GdkEventKey
5974 * Propagate a key press or release event to the focus widget and
5975 * up the focus container chain until a widget handles @event.
5976 * This is normally called by the default ::key_press_event and
5977 * ::key_release_event handlers for toplevel windows,
5978 * however in some cases it may be useful to call this directly when
5979 * overriding the standard key handling for a toplevel window.
5981 * Return value: %TRUE if a widget in the focus chain handled the event.
5986 gtk_window_propagate_key_event (GtkWindow *window,
5989 GtkWindowPrivate *priv;
5990 gboolean handled = FALSE;
5991 GtkWidget *widget, *focus;
5993 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5995 priv = window->priv;
5996 widget = GTK_WIDGET (window);
5998 focus = priv->focus_widget;
6000 g_object_ref (focus);
6003 focus && focus != widget &&
6004 gtk_widget_get_toplevel (focus) == widget)
6008 if (gtk_widget_is_sensitive (focus))
6009 handled = gtk_widget_event (focus, (GdkEvent*) event);
6011 parent = gtk_widget_get_parent (focus);
6013 g_object_ref (parent);
6015 g_object_unref (focus);
6021 g_object_unref (focus);
6027 gtk_window_key_press_event (GtkWidget *widget,
6030 GtkWindow *window = GTK_WINDOW (widget);
6031 gboolean handled = FALSE;
6033 /* handle mnemonics and accelerators */
6035 handled = gtk_window_activate_key (window, event);
6037 /* handle focus widget key events */
6039 handled = gtk_window_propagate_key_event (window, event);
6041 /* Chain up, invokes binding set */
6043 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
6049 gtk_window_key_release_event (GtkWidget *widget,
6052 GtkWindow *window = GTK_WINDOW (widget);
6053 gboolean handled = FALSE;
6055 /* handle focus widget key events */
6057 handled = gtk_window_propagate_key_event (window, event);
6059 /* Chain up, invokes binding set */
6061 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
6067 gtk_window_button_press_event (GtkWidget *widget,
6068 GdkEventButton *event)
6070 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
6073 if (event->window == priv->grip_window)
6075 if (get_drag_edge (widget, &edge))
6076 gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
6078 gdk_event_get_device ((GdkEvent *) event),
6091 gtk_window_real_activate_default (GtkWindow *window)
6093 gtk_window_activate_default (window);
6097 gtk_window_real_activate_focus (GtkWindow *window)
6099 gtk_window_activate_focus (window);
6103 gtk_window_enter_notify_event (GtkWidget *widget,
6104 GdkEventCrossing *event)
6110 gtk_window_leave_notify_event (GtkWidget *widget,
6111 GdkEventCrossing *event)
6117 do_focus_change (GtkWidget *widget,
6121 GdkDeviceManager *device_manager;
6124 g_object_ref (widget);
6126 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
6127 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6128 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
6129 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
6131 for (d = devices; d; d = d->next)
6133 GdkDevice *dev = d->data;
6136 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
6139 /* Skip non-master keyboards that haven't
6140 * selected for events from this window
6142 window = gtk_widget_get_window (widget);
6143 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
6144 window && !gdk_window_get_device_events (window, dev))
6147 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
6149 fevent->focus_change.type = GDK_FOCUS_CHANGE;
6150 fevent->focus_change.window = window;
6152 g_object_ref (window);
6153 fevent->focus_change.in = in;
6154 gdk_event_set_device (fevent, dev);
6156 gtk_widget_send_focus_change (widget, fevent);
6158 gdk_event_free (fevent);
6161 g_list_free (devices);
6162 g_object_unref (widget);
6166 maybe_set_mnemonics_visible (GtkWindow *window)
6169 GdkDeviceManager *device_manager;
6171 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
6172 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6174 for (d = devices; d; d = d->next)
6176 GdkDevice *dev = d->data;
6178 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6180 GdkModifierType mask;
6182 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6184 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6186 _gtk_window_set_auto_mnemonics_visible (window);
6192 g_list_free (devices);
6196 gtk_window_focus_in_event (GtkWidget *widget,
6197 GdkEventFocus *event)
6199 GtkWindow *window = GTK_WINDOW (widget);
6200 gboolean auto_mnemonics;
6202 /* It appears spurious focus in events can occur when
6203 * the window is hidden. So we'll just check to see if
6204 * the window is visible before actually handling the
6207 if (gtk_widget_get_visible (widget))
6209 _gtk_window_set_has_toplevel_focus (window, TRUE);
6210 _gtk_window_set_is_active (window, TRUE);
6212 g_object_get (gtk_widget_get_settings (widget),
6213 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6215 maybe_set_mnemonics_visible (window);
6222 gtk_window_focus_out_event (GtkWidget *widget,
6223 GdkEventFocus *event)
6225 GtkWindow *window = GTK_WINDOW (widget);
6226 gboolean auto_mnemonics;
6228 _gtk_window_set_has_toplevel_focus (window, FALSE);
6229 _gtk_window_set_is_active (window, FALSE);
6231 /* set the mnemonic-visible property to false */
6232 g_object_get (gtk_widget_get_settings (widget),
6233 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6235 gtk_window_set_mnemonics_visible (window, FALSE);
6241 gtk_window_check_resize (GtkContainer *container)
6243 /* If the window is not toplevel anymore than it's embedded somewhere,
6244 * so handle it like a normal window */
6245 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6246 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6247 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6248 gtk_window_move_resize (GTK_WINDOW (container));
6252 gtk_window_focus (GtkWidget *widget,
6253 GtkDirectionType direction)
6255 GtkWindowPrivate *priv;
6258 GtkContainer *container;
6260 GtkWidget *old_focus_child;
6263 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6264 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6266 container = GTK_CONTAINER (widget);
6267 window = GTK_WINDOW (widget);
6268 priv = window->priv;
6269 bin = GTK_BIN (widget);
6271 old_focus_child = gtk_container_get_focus_child (container);
6273 /* We need a special implementation here to deal properly with wrapping
6274 * around in the tab chain without the danger of going into an
6277 if (old_focus_child)
6279 if (gtk_widget_child_focus (old_focus_child, direction))
6283 if (priv->focus_widget)
6285 if (direction == GTK_DIR_LEFT ||
6286 direction == GTK_DIR_RIGHT ||
6287 direction == GTK_DIR_UP ||
6288 direction == GTK_DIR_DOWN)
6293 /* Wrapped off the end, clear the focus setting for the toplpevel */
6294 parent = gtk_widget_get_parent (priv->focus_widget);
6297 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6298 parent = gtk_widget_get_parent (parent);
6301 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6304 /* Now try to focus the first widget in the window */
6305 child = gtk_bin_get_child (bin);
6308 if (gtk_widget_child_focus (child, direction))
6316 gtk_window_move_focus (GtkWidget *widget,
6317 GtkDirectionType dir)
6319 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6321 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6325 gtk_widget_child_focus (widget, dir);
6327 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6328 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6332 gtk_window_real_set_focus (GtkWindow *window,
6335 GtkWindowPrivate *priv = window->priv;
6336 GtkWidget *old_focus = priv->focus_widget;
6337 gboolean had_default = FALSE;
6338 gboolean focus_had_default = FALSE;
6339 gboolean old_focus_had_default = FALSE;
6343 g_object_ref (old_focus);
6344 g_object_freeze_notify (G_OBJECT (old_focus));
6345 old_focus_had_default = gtk_widget_has_default (old_focus);
6349 g_object_ref (focus);
6350 g_object_freeze_notify (G_OBJECT (focus));
6351 focus_had_default = gtk_widget_has_default (focus);
6354 if (priv->default_widget)
6355 had_default = gtk_widget_has_default (priv->default_widget);
6357 if (priv->focus_widget)
6359 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6360 (priv->focus_widget != priv->default_widget))
6362 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6363 gtk_widget_queue_draw (priv->focus_widget);
6365 if (priv->default_widget)
6366 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6369 priv->focus_widget = NULL;
6371 if (priv->has_focus)
6372 do_focus_change (old_focus, FALSE);
6374 g_object_notify (G_OBJECT (old_focus), "is-focus");
6377 /* The above notifications may have set a new focus widget,
6378 * if so, we don't want to override it.
6380 if (focus && !priv->focus_widget)
6382 priv->focus_widget = focus;
6384 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6385 (priv->focus_widget != priv->default_widget))
6387 if (gtk_widget_get_can_default (priv->focus_widget))
6388 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6390 if (priv->default_widget)
6391 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6394 if (priv->has_focus)
6395 do_focus_change (priv->focus_widget, TRUE);
6397 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6400 /* If the default widget changed, a redraw will have been queued
6401 * on the old and new default widgets by gtk_window_set_default(), so
6402 * we only have to worry about the case where it didn't change.
6403 * We'll sometimes queue a draw twice on the new widget but that
6406 if (priv->default_widget &&
6407 (had_default != gtk_widget_has_default (priv->default_widget)))
6408 gtk_widget_queue_draw (priv->default_widget);
6412 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6413 gtk_widget_queue_draw (old_focus);
6415 g_object_thaw_notify (G_OBJECT (old_focus));
6416 g_object_unref (old_focus);
6420 if (focus_had_default != gtk_widget_has_default (focus))
6421 gtk_widget_queue_draw (focus);
6423 g_object_thaw_notify (G_OBJECT (focus));
6424 g_object_unref (focus);
6429 * _gtk_window_unset_focus_and_default:
6430 * @window: a #GtkWindow
6431 * @widget: a widget inside of @window
6433 * Checks whether the focus and default widgets of @window are
6434 * @widget or a descendent of @widget, and if so, unset them.
6437 _gtk_window_unset_focus_and_default (GtkWindow *window,
6441 GtkWindowPrivate *priv = window->priv;
6445 g_object_ref (window);
6446 g_object_ref (widget);
6448 parent = gtk_widget_get_parent (widget);
6449 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6451 child = priv->focus_widget;
6453 while (child && child != widget)
6454 child = gtk_widget_get_parent (child);
6456 if (child == widget)
6457 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6460 child = priv->default_widget;
6462 while (child && child != widget)
6463 child = gtk_widget_get_parent (child);
6465 if (child == widget)
6466 gtk_window_set_default (window, NULL);
6468 g_object_unref (widget);
6469 g_object_unref (window);
6472 /*********************************
6473 * Functions related to resizing *
6474 *********************************/
6477 geometry_size_to_pixels (GdkGeometry *geometry,
6482 gint base_width = 0;
6483 gint base_height = 0;
6485 gint min_height = 0;
6487 gint height_inc = 1;
6489 if (flags & GDK_HINT_BASE_SIZE)
6491 base_width = geometry->base_width;
6492 base_height = geometry->base_height;
6494 if (flags & GDK_HINT_MIN_SIZE)
6496 min_width = geometry->min_width;
6497 min_height = geometry->min_height;
6499 if (flags & GDK_HINT_RESIZE_INC)
6501 width_inc = geometry->width_inc;
6502 height_inc = geometry->height_inc;
6506 *width = MAX (*width * width_inc + base_width, min_width);
6508 *height = MAX (*height * height_inc + base_height, min_height);
6511 /* This function doesn't constrain to geometry hints */
6513 gtk_window_compute_configure_request_size (GtkWindow *window,
6514 GdkGeometry *geometry,
6519 GtkWindowPrivate *priv = window->priv;
6520 GtkWindowGeometryInfo *info;
6523 * - we've done a size request
6526 info = gtk_window_get_geometry_info (window, FALSE);
6528 if (priv->need_default_size)
6530 gtk_window_guess_default_size (window, width, height);
6532 /* If window is empty so requests 0, default to random nonzero size */
6533 if (*width == 0 && *height == 0)
6539 /* Override with default size */
6543 if (info->default_width > 0)
6544 *width = info->default_width;
6545 if (info->default_height > 0)
6546 *height = info->default_height;
6548 if (info->default_is_geometry)
6549 geometry_size_to_pixels (geometry, flags,
6550 info->default_width > 0 ? width : NULL,
6551 info->default_height > 0 ? height : NULL);
6556 GtkAllocation allocation;
6558 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6560 /* Default to keeping current size */
6561 *width = allocation.width;
6562 *height = allocation.height;
6565 /* Override any size with gtk_window_resize() values */
6568 if (info->resize_width > 0)
6569 *width = info->resize_width;
6570 if (info->resize_height > 0)
6571 *height = info->resize_height;
6573 if (info->resize_is_geometry)
6574 geometry_size_to_pixels (geometry, flags,
6575 info->resize_width > 0 ? width : NULL,
6576 info->resize_height > 0 ? height : NULL);
6579 /* Don't ever request zero width or height, it's not supported by
6580 gdk. The size allocation code will round it to 1 anyway but if
6581 we do it then the value returned from this function will is
6582 not comparable to the size allocation read from the GtkWindow. */
6583 *width = MAX (*width, 1);
6584 *height = MAX (*height, 1);
6587 static GtkWindowPosition
6588 get_effective_position (GtkWindow *window)
6590 GtkWindowPrivate *priv = window->priv;
6591 GtkWindowPosition pos = priv->position;
6593 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6594 (priv->transient_parent == NULL ||
6595 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6596 pos = GTK_WIN_POS_NONE;
6602 get_center_monitor_of_window (GtkWindow *window)
6604 /* We could try to sort out the relative positions of the monitors and
6605 * stuff, or we could just be losers and assume you have a row
6606 * or column of monitors.
6608 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6612 get_monitor_containing_pointer (GtkWindow *window)
6616 GdkScreen *window_screen;
6617 GdkScreen *pointer_screen;
6618 GdkDisplay *display;
6619 GdkDeviceManager *device_manager;
6622 window_screen = gtk_window_check_screen (window);
6623 display = gdk_screen_get_display (window_screen);
6624 device_manager = gdk_display_get_device_manager (display);
6625 pointer = gdk_device_manager_get_client_pointer (device_manager);
6627 gdk_device_get_position (pointer,
6631 if (pointer_screen == window_screen)
6632 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6640 center_window_on_monitor (GtkWindow *window,
6646 GdkRectangle monitor;
6649 monitor_num = get_monitor_containing_pointer (window);
6651 if (monitor_num == -1)
6652 monitor_num = get_center_monitor_of_window (window);
6654 gdk_screen_get_monitor_workarea (gtk_window_check_screen (window),
6655 monitor_num, &monitor);
6657 *x = (monitor.width - w) / 2 + monitor.x;
6658 *y = (monitor.height - h) / 2 + monitor.y;
6660 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6661 * and WM decorations.
6675 if (extent > clamp_extent)
6677 *base = clamp_base + clamp_extent/2 - extent/2;
6678 else if (*base < clamp_base)
6680 else if (*base + extent > clamp_base + clamp_extent)
6681 *base = clamp_base + clamp_extent - extent;
6685 clamp_window_to_rectangle (gint *x,
6689 const GdkRectangle *rect)
6691 #ifdef DEBUGGING_OUTPUT
6692 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);
6695 /* If it is too large, center it. If it fits on the monitor but is
6696 * partially outside, move it to the closest edge. Do this
6697 * separately in x and y directions.
6699 clamp (x, w, rect->x, rect->width);
6700 clamp (y, h, rect->y, rect->height);
6701 #ifdef DEBUGGING_OUTPUT
6702 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6708 gtk_window_compute_configure_request (GtkWindow *window,
6709 GdkRectangle *request,
6710 GdkGeometry *geometry,
6713 GtkWindowPrivate *priv = window->priv;
6714 GdkGeometry new_geometry;
6717 GtkWindowPosition pos;
6718 GtkWidget *parent_widget;
6719 GtkWindowGeometryInfo *info;
6723 screen = gtk_window_check_screen (window);
6725 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6726 gtk_window_compute_configure_request_size (window,
6727 &new_geometry, new_flags,
6730 gtk_window_constrain_size (window,
6731 &new_geometry, new_flags,
6735 parent_widget = (GtkWidget*) priv->transient_parent;
6737 pos = get_effective_position (window);
6738 info = gtk_window_get_geometry_info (window, FALSE);
6740 /* by default, don't change position requested */
6743 x = info->last.configure_request.x;
6744 y = info->last.configure_request.y;
6753 if (priv->need_default_position)
6756 /* FIXME this all interrelates with window gravity.
6757 * For most of them I think we want to set GRAVITY_CENTER.
6759 * Not sure how to go about that.
6763 /* here we are only handling CENTER_ALWAYS
6764 * as it relates to default positioning,
6765 * where it's equivalent to simply CENTER
6767 case GTK_WIN_POS_CENTER_ALWAYS:
6768 case GTK_WIN_POS_CENTER:
6769 center_window_on_monitor (window, w, h, &x, &y);
6772 case GTK_WIN_POS_CENTER_ON_PARENT:
6774 GtkAllocation allocation;
6775 GdkWindow *gdk_window;
6777 GdkRectangle monitor;
6780 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6782 gdk_window = gtk_widget_get_window (parent_widget);
6784 if (gdk_window != NULL)
6785 monitor_num = gdk_screen_get_monitor_at_window (screen,
6790 gdk_window_get_origin (gdk_window,
6793 gtk_widget_get_allocation (parent_widget, &allocation);
6794 x = ox + (allocation.width - w) / 2;
6795 y = oy + (allocation.height - h) / 2;
6797 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6798 * WM decorations. If parent wasn't on a monitor, just
6801 if (monitor_num >= 0)
6803 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6804 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6809 case GTK_WIN_POS_MOUSE:
6811 gint screen_width = gdk_screen_get_width (screen);
6812 gint screen_height = gdk_screen_get_height (screen);
6814 GdkRectangle monitor;
6815 GdkDisplay *display;
6816 GdkDeviceManager *device_manager;
6818 GdkScreen *pointer_screen;
6821 display = gdk_screen_get_display (screen);
6822 device_manager = gdk_display_get_device_manager (display);
6823 pointer = gdk_device_manager_get_client_pointer (device_manager);
6825 gdk_device_get_position (pointer,
6829 if (pointer_screen == screen)
6830 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6836 x = CLAMP (x, 0, screen_width - w);
6837 y = CLAMP (y, 0, screen_height - h);
6839 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6840 * WM decorations. Don't try to figure out what's going
6841 * on if the mouse wasn't inside a monitor.
6843 if (monitor_num >= 0)
6845 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6846 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6854 } /* if (priv->need_default_position) */
6856 if (priv->need_default_position && info &&
6857 info->initial_pos_set)
6859 x = info->initial_x;
6860 y = info->initial_y;
6861 gtk_window_constrain_position (window, w, h, &x, &y);
6867 request->height = h;
6870 *geometry = new_geometry;
6876 gtk_window_constrain_position (GtkWindow *window,
6882 GtkWindowPrivate *priv = window->priv;
6884 /* See long comments in gtk_window_move_resize()
6885 * on when it's safe to call this function.
6887 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6889 gint center_x, center_y;
6891 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6899 gtk_window_move_resize (GtkWindow *window)
6903 * First we determine whether any information has changed that would
6904 * cause us to revise our last configure request. If we would send
6905 * a different configure request from last time, then
6906 * configure_request_size_changed = TRUE or
6907 * configure_request_pos_changed = TRUE. configure_request_size_changed
6908 * may be true due to new hints, a gtk_window_resize(), or whatever.
6909 * configure_request_pos_changed may be true due to gtk_window_set_position()
6910 * or gtk_window_move().
6912 * If the configure request has changed, we send off a new one. To
6913 * ensure GTK+ invariants are maintained (resize queue does what it
6914 * should), we go ahead and size_allocate the requested size in this
6917 * If the configure request has not changed, we don't ever resend
6918 * it, because it could mean fighting the user or window manager.
6921 * To prepare the configure request, we come up with a base size/pos:
6922 * - the one from gtk_window_move()/gtk_window_resize()
6923 * - else default_width, default_height if we haven't ever
6925 * - else the size request if we haven't ever been mapped,
6926 * as a substitute default size
6927 * - else the current size of the window, as received from
6928 * configure notifies (i.e. the current allocation)
6930 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6931 * the position request to be centered.
6933 GtkWindowPrivate *priv = window->priv;
6934 GtkAllocation allocation;
6936 GtkContainer *container;
6937 GtkWindowGeometryInfo *info;
6938 GdkGeometry new_geometry;
6939 GdkWindow *gdk_window;
6941 GdkRectangle new_request;
6942 gboolean configure_request_size_changed;
6943 gboolean configure_request_pos_changed;
6944 gboolean hints_changed; /* do we need to send these again */
6945 GtkWindowLastGeometryInfo saved_last_info;
6947 widget = GTK_WIDGET (window);
6949 gdk_window = gtk_widget_get_window (widget);
6950 container = GTK_CONTAINER (widget);
6951 info = gtk_window_get_geometry_info (window, TRUE);
6953 configure_request_size_changed = FALSE;
6954 configure_request_pos_changed = FALSE;
6956 gtk_window_compute_configure_request (window, &new_request,
6957 &new_geometry, &new_flags);
6959 /* This check implies the invariant that we never set info->last
6960 * without setting the hints and sending off a configure request.
6962 * If we change info->last without sending the request, we may
6965 if (info->last.configure_request.x != new_request.x ||
6966 info->last.configure_request.y != new_request.y)
6967 configure_request_pos_changed = TRUE;
6969 if ((info->last.configure_request.width != new_request.width ||
6970 info->last.configure_request.height != new_request.height))
6971 configure_request_size_changed = TRUE;
6973 hints_changed = FALSE;
6975 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6976 &new_geometry, new_flags))
6978 hints_changed = TRUE;
6981 /* Position Constraints
6982 * ====================
6984 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6985 * a default. The other POS_ values are used only when the
6986 * window is shown, not after that.
6988 * However, we can't implement a position constraint as
6989 * "anytime the window size changes, center the window"
6990 * because this may well end up fighting the WM or user. In
6991 * fact it gets in an infinite loop with at least one WM.
6993 * Basically, applications are in no way in a position to
6994 * constrain the position of a window, with one exception:
6995 * override redirect windows. (Really the intended purpose
6996 * of CENTER_ALWAYS anyhow, I would think.)
6998 * So the way we implement this "constraint" is to say that when WE
6999 * cause a move or resize, i.e. we make a configure request changing
7000 * window size, we recompute the CENTER_ALWAYS position to reflect
7001 * the new window size, and include it in our request. Also, if we
7002 * just turned on CENTER_ALWAYS we snap to center with a new
7003 * request. Otherwise, if we are just NOTIFIED of a move or resize
7004 * done by someone else e.g. the window manager, we do NOT send a
7005 * new configure request.
7007 * For override redirect windows, this works fine; all window
7008 * sizes are from our configure requests. For managed windows,
7009 * it is at least semi-sane, though who knows what the
7010 * app author is thinking.
7013 /* This condition should be kept in sync with the condition later on
7014 * that determines whether we send a configure request. i.e. we
7015 * should do this position constraining anytime we were going to
7016 * send a configure request anyhow, plus when constraints have
7019 if (configure_request_pos_changed ||
7020 configure_request_size_changed ||
7022 info->position_constraints_changed)
7024 /* We request the constrained position if:
7025 * - we were changing position, and need to clamp
7026 * the change to the constraint
7027 * - we're changing the size anyway
7028 * - set_position() was called to toggle CENTER_ALWAYS on
7031 gtk_window_constrain_position (window,
7037 /* Update whether we need to request a move */
7038 if (info->last.configure_request.x != new_request.x ||
7039 info->last.configure_request.y != new_request.y)
7040 configure_request_pos_changed = TRUE;
7042 configure_request_pos_changed = FALSE;
7046 if (priv->type == GTK_WINDOW_TOPLEVEL)
7048 int notify_x, notify_y;
7050 /* this is the position from the last configure notify */
7051 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
7053 g_message ("--- %s ---\n"
7054 "last : %d,%d\t%d x %d\n"
7055 "this : %d,%d\t%d x %d\n"
7056 "alloc : %d,%d\t%d x %d\n"
7058 "resize: \t%d x %d\n"
7059 "size_changed: %d pos_changed: %d hints_changed: %d\n"
7060 "configure_notify_received: %d\n"
7061 "configure_request_count: %d\n"
7062 "position_constraints_changed: %d\n",
7063 priv->title ? priv->title : "(no title)",
7064 info->last.configure_request.x,
7065 info->last.configure_request.y,
7066 info->last.configure_request.width,
7067 info->last.configure_request.height,
7073 widget->allocation.width,
7074 widget->allocation.height,
7075 widget->requisition.width,
7076 widget->requisition.height,
7078 info->resize_height,
7079 configure_request_pos_changed,
7080 configure_request_size_changed,
7082 priv->configure_notify_received,
7083 priv->configure_request_count,
7084 info->position_constraints_changed);
7088 saved_last_info = info->last;
7089 info->last.geometry = new_geometry;
7090 info->last.flags = new_flags;
7091 info->last.configure_request = new_request;
7093 /* need to set PPosition so the WM will look at our position,
7094 * but we don't want to count PPosition coming and going as a hints
7095 * change for future iterations. So we saved info->last prior to
7099 /* Also, if the initial position was explicitly set, then we always
7100 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
7104 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
7105 * this is an initial map
7108 if ((configure_request_pos_changed ||
7109 info->initial_pos_set ||
7110 (priv->need_default_position &&
7111 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
7112 (new_flags & GDK_HINT_POS) == 0)
7114 new_flags |= GDK_HINT_POS;
7115 hints_changed = TRUE;
7118 /* Set hints if necessary
7121 gdk_window_set_geometry_hints (gdk_window,
7127 allocation.width = gdk_window_get_width (gdk_window);
7128 allocation.height = gdk_window_get_height (gdk_window);
7130 /* handle resizing/moving and widget tree allocation
7132 if (priv->configure_notify_received)
7134 /* If we have received a configure event since
7135 * the last time in this function, we need to
7136 * accept our new size and size_allocate child widgets.
7137 * (see gtk_window_configure_event() for more details).
7139 * 1 or more configure notifies may have been received.
7140 * Also, configure_notify_received will only be TRUE
7141 * if all expected configure notifies have been received
7142 * (one per configure request), as an optimization.
7145 priv->configure_notify_received = FALSE;
7147 /* gtk_window_configure_event() filled in widget->allocation */
7148 gtk_widget_size_allocate (widget, &allocation);
7150 set_grip_position (window);
7151 update_grip_visibility (window);
7153 /* If the configure request changed, it means that
7155 * 1) coincidentally changed hints or widget properties
7156 * impacting the configure request before getting
7157 * a configure notify, or
7158 * 2) some broken widget is changing its size request
7159 * during size allocation, resulting in
7160 * a false appearance of changed configure request.
7162 * For 1), we could just go ahead and ask for the
7163 * new size right now, but doing that for 2)
7164 * might well be fighting the user (and can even
7165 * trigger a loop). Since we really don't want to
7166 * do that, we requeue a resize in hopes that
7167 * by the time it gets handled, the child has seen
7168 * the light and is willing to go along with the
7169 * new size. (this happens for the zvt widget, since
7170 * the size_allocate() above will have stored the
7171 * requisition corresponding to the new size in the
7174 * This doesn't buy us anything for 1), but it shouldn't
7175 * hurt us too badly, since it is what would have
7176 * happened if we had gotten the configure event before
7177 * the new size had been set.
7180 if (configure_request_size_changed ||
7181 configure_request_pos_changed)
7183 /* Don't change the recorded last info after all, because we
7184 * haven't actually updated to the new info yet - we decided
7185 * to postpone our configure request until later.
7187 info->last = saved_last_info;
7189 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7192 return; /* Bail out, we didn't really process the move/resize */
7194 else if ((configure_request_size_changed || hints_changed) &&
7195 (allocation.width != new_request.width || allocation.height != new_request.height))
7198 /* We are in one of the following situations:
7199 * A. configure_request_size_changed
7200 * our requisition has changed and we need a different window size,
7201 * so we request it from the window manager.
7202 * B. !configure_request_size_changed && hints_changed
7203 * the window manager rejects our size, but we have just changed the
7204 * window manager hints, so there's a chance our request will
7205 * be honoured this time, so we try again.
7207 * However, if the new requisition is the same as the current allocation,
7208 * we don't request it again, since we won't get a ConfigureNotify back from
7209 * the window manager unless it decides to change our requisition. If
7210 * we don't get the ConfigureNotify back, the resize queue will never be run.
7213 /* Now send the configure request */
7214 if (configure_request_pos_changed)
7216 gdk_window_move_resize (gdk_window,
7217 new_request.x, new_request.y,
7218 new_request.width, new_request.height);
7220 else /* only size changed */
7222 gdk_window_resize (gdk_window,
7223 new_request.width, new_request.height);
7226 if (priv->type == GTK_WINDOW_POPUP)
7228 GtkAllocation allocation;
7230 /* Directly size allocate for override redirect (popup) windows. */
7233 allocation.width = new_request.width;
7234 allocation.height = new_request.height;
7236 gtk_widget_size_allocate (widget, &allocation);
7238 gdk_window_process_updates (gdk_window, TRUE);
7240 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7241 gtk_widget_queue_draw (widget);
7245 /* Increment the number of have-not-yet-received-notify requests */
7246 priv->configure_request_count += 1;
7247 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7249 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7250 * configure event in response to our resizing request.
7251 * the configure event will cause a new resize with
7252 * ->configure_notify_received=TRUE.
7253 * until then, we want to
7254 * - discard expose events
7255 * - coalesce resizes for our children
7256 * - defer any window resizes until the configure event arrived
7257 * to achieve this, we queue a resize for the window, but remove its
7258 * resizing handler, so resizing will not be handled from the next
7259 * idle handler but when the configure event arrives.
7261 * FIXME: we should also dequeue the pending redraws here, since
7262 * we handle those ourselves upon ->configure_notify_received==TRUE.
7264 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7266 gtk_widget_queue_resize_no_redraw (widget);
7267 _gtk_container_dequeue_resize_handler (container);
7273 /* Handle any position changes.
7275 if (configure_request_pos_changed)
7277 gdk_window_move (gdk_window,
7278 new_request.x, new_request.y);
7281 /* And run the resize queue.
7283 gtk_container_resize_children (container);
7286 /* We have now processed a move/resize since the last position
7287 * constraint change, setting of the initial position, or resize.
7288 * (Not resetting these flags here can lead to infinite loops for
7289 * GTK_RESIZE_IMMEDIATE containers)
7291 info->position_constraints_changed = FALSE;
7292 info->initial_pos_set = FALSE;
7293 info->resize_width = -1;
7294 info->resize_height = -1;
7297 /* Compare two sets of Geometry hints for equality.
7300 gtk_window_compare_hints (GdkGeometry *geometry_a,
7302 GdkGeometry *geometry_b,
7305 if (flags_a != flags_b)
7308 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7309 (geometry_a->min_width != geometry_b->min_width ||
7310 geometry_a->min_height != geometry_b->min_height))
7313 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7314 (geometry_a->max_width != geometry_b->max_width ||
7315 geometry_a->max_height != geometry_b->max_height))
7318 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7319 (geometry_a->base_width != geometry_b->base_width ||
7320 geometry_a->base_height != geometry_b->base_height))
7323 if ((flags_a & GDK_HINT_ASPECT) &&
7324 (geometry_a->min_aspect != geometry_b->min_aspect ||
7325 geometry_a->max_aspect != geometry_b->max_aspect))
7328 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7329 (geometry_a->width_inc != geometry_b->width_inc ||
7330 geometry_a->height_inc != geometry_b->height_inc))
7333 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7334 geometry_a->win_gravity != geometry_b->win_gravity)
7341 _gtk_window_constrain_size (GtkWindow *window,
7347 GtkWindowPrivate *priv;
7348 GtkWindowGeometryInfo *info;
7350 g_return_if_fail (GTK_IS_WINDOW (window));
7352 priv = window->priv;
7354 info = priv->geometry_info;
7357 GdkWindowHints flags = info->last.flags;
7358 GdkGeometry *geometry = &info->last.geometry;
7360 gtk_window_constrain_size (window,
7371 gtk_window_constrain_size (GtkWindow *window,
7372 GdkGeometry *geometry,
7379 gdk_window_constrain_size (geometry, flags, width, height,
7380 new_width, new_height);
7383 /* Compute the set of geometry hints and flags for a window
7384 * based on the application set geometry, and requisition
7385 * of the window. gtk_widget_get_preferred_size() must have been
7389 gtk_window_compute_hints (GtkWindow *window,
7390 GdkGeometry *new_geometry,
7393 GtkWindowPrivate *priv = window->priv;
7395 gint extra_width = 0;
7396 gint extra_height = 0;
7397 GtkWindowGeometryInfo *geometry_info;
7398 GtkRequisition requisition;
7400 widget = GTK_WIDGET (window);
7402 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7403 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7407 *new_flags = geometry_info->mask;
7408 *new_geometry = geometry_info->geometry;
7415 if (geometry_info && geometry_info->widget)
7417 /* If the geometry widget is set, then the hints really apply to that
7418 * widget. This is pretty much meaningless unless the window layout
7419 * is such that the rest of the window adds fixed size borders to
7420 * the geometry widget. Our job is to figure the size of the borders;
7421 * We do that by asking how big the toplevel would be if the
7422 * geometry widget was *really big*.
7425 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7426 * |GGGGG B| in the border can confuse things
7432 * |AAAAAAAAA | When the geometry widget is large, things are
7433 * |GGGGGGGGGGB| clearer.
7438 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7439 GtkRequisition requisition;
7440 int current_width, current_height;
7442 _gtk_widget_override_size_request (geometry_info->widget,
7443 TEMPORARY_SIZE, TEMPORARY_SIZE,
7444 ¤t_width, ¤t_height);
7445 gtk_widget_get_preferred_size (widget,
7446 &requisition, NULL);
7447 _gtk_widget_restore_size_request (geometry_info->widget,
7448 current_width, current_height);
7450 extra_width = requisition.width - TEMPORARY_SIZE;
7451 extra_height = requisition.height - TEMPORARY_SIZE;
7453 if (extra_width < 0 || extra_height < 0)
7455 g_warning("Toplevel size doesn't seem to directly depend on the "
7456 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7457 "The geometry widget might not be in the window, or it might not "
7458 "be packed into the window appropriately");
7459 extra_width = MAX(extra_width, 0);
7460 extra_height = MAX(extra_height, 0);
7462 #undef TEMPORARY_SIZE
7465 /* We don't want to set GDK_HINT_POS in here, we just set it
7466 * in gtk_window_move_resize() when we want the position
7470 if (*new_flags & GDK_HINT_BASE_SIZE)
7472 new_geometry->base_width += extra_width;
7473 new_geometry->base_height += extra_height;
7477 /* For simplicity, we always set the base hint, even when we
7478 * don't expect it to have any visible effect.
7479 * (Note: geometry_size_to_pixels() depends on this.)
7481 *new_flags |= GDK_HINT_BASE_SIZE;
7483 new_geometry->base_width = extra_width;
7484 new_geometry->base_height = extra_height;
7486 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7487 * base size is the minimum size */
7488 if (*new_flags & GDK_HINT_MIN_SIZE)
7490 if (new_geometry->min_width > 0)
7491 new_geometry->base_width += new_geometry->min_width;
7492 if (new_geometry->min_height > 0)
7493 new_geometry->base_height += new_geometry->min_height;
7497 /* Please use a good size for unresizable widgets, not the minimum one. */
7498 if (!priv->resizable)
7499 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7501 if (*new_flags & GDK_HINT_MIN_SIZE)
7503 if (new_geometry->min_width < 0)
7504 new_geometry->min_width = requisition.width;
7506 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7508 if (new_geometry->min_height < 0)
7509 new_geometry->min_height = requisition.height;
7511 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7515 *new_flags |= GDK_HINT_MIN_SIZE;
7517 new_geometry->min_width = requisition.width;
7518 new_geometry->min_height = requisition.height;
7521 if (*new_flags & GDK_HINT_MAX_SIZE)
7523 if (new_geometry->max_width < 0)
7524 new_geometry->max_width = requisition.width;
7526 new_geometry->max_width += extra_width;
7528 if (new_geometry->max_height < 0)
7529 new_geometry->max_height = requisition.height;
7531 new_geometry->max_height += extra_height;
7533 else if (!priv->resizable)
7535 *new_flags |= GDK_HINT_MAX_SIZE;
7537 new_geometry->max_width = requisition.width;
7538 new_geometry->max_height = requisition.height;
7541 *new_flags |= GDK_HINT_WIN_GRAVITY;
7542 new_geometry->win_gravity = priv->gravity;
7545 /***********************
7546 * Redrawing functions *
7547 ***********************/
7550 gtk_window_draw (GtkWidget *widget,
7553 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7554 GtkStyleContext *context;
7555 gboolean ret = FALSE;
7557 context = gtk_widget_get_style_context (widget);
7559 if (!gtk_widget_get_app_paintable (widget) &&
7560 gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
7562 gtk_render_background (context, cr, 0, 0,
7563 gtk_widget_get_allocated_width (widget),
7564 gtk_widget_get_allocated_height (widget));
7567 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7568 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7570 if (priv->grip_window &&
7571 gtk_cairo_should_draw_window (cr, priv->grip_window))
7575 gtk_style_context_save (context);
7578 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7579 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7581 gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND);
7582 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7583 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7584 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7587 gtk_style_context_restore (context);
7594 * gtk_window_present:
7595 * @window: a #GtkWindow
7597 * Presents a window to the user. This may mean raising the window
7598 * in the stacking order, deiconifying it, moving it to the current
7599 * desktop, and/or giving it the keyboard focus, possibly dependent
7600 * on the user's platform, window manager, and preferences.
7602 * If @window is hidden, this function calls gtk_widget_show()
7605 * This function should be used when the user tries to open a window
7606 * that's already open. Say for example the preferences dialog is
7607 * currently open, and the user chooses Preferences from the menu
7608 * a second time; use gtk_window_present() to move the already-open dialog
7609 * where the user can see it.
7611 * If you are calling this function in response to a user interaction,
7612 * it is preferable to use gtk_window_present_with_time().
7616 gtk_window_present (GtkWindow *window)
7618 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7622 * gtk_window_present_with_time:
7623 * @window: a #GtkWindow
7624 * @timestamp: the timestamp of the user interaction (typically a
7625 * button or key press event) which triggered this call
7627 * Presents a window to the user in response to a user interaction.
7628 * If you need to present a window without a timestamp, use
7629 * gtk_window_present(). See gtk_window_present() for details.
7634 gtk_window_present_with_time (GtkWindow *window,
7637 GtkWindowPrivate *priv;
7639 GdkWindow *gdk_window;
7641 g_return_if_fail (GTK_IS_WINDOW (window));
7643 priv = window->priv;
7644 widget = GTK_WIDGET (window);
7646 if (gtk_widget_get_visible (widget))
7648 gdk_window = gtk_widget_get_window (widget);
7650 g_assert (gdk_window != NULL);
7652 gdk_window_show (gdk_window);
7654 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7655 if (timestamp == GDK_CURRENT_TIME)
7657 #ifdef GDK_WINDOWING_X11
7658 if (GDK_IS_X11_WINDOW(gdk_window))
7660 GdkDisplay *display;
7662 display = gtk_widget_get_display (GTK_WIDGET (window));
7663 timestamp = gdk_x11_display_get_user_time (display);
7667 timestamp = gtk_get_current_event_time ();
7670 gdk_window_focus (gdk_window, timestamp);
7674 priv->initial_timestamp = timestamp;
7675 gtk_widget_show (widget);
7680 * gtk_window_iconify:
7681 * @window: a #GtkWindow
7683 * Asks to iconify (i.e. minimize) the specified @window. Note that
7684 * you shouldn't assume the window is definitely iconified afterward,
7685 * because other entities (e.g. the user or <link
7686 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7687 * again, or there may not be a window manager in which case
7688 * iconification isn't possible, etc. But normally the window will end
7689 * up iconified. Just don't write code that crashes if not.
7691 * It's permitted to call this function before showing a window,
7692 * in which case the window will be iconified before it ever appears
7695 * You can track iconification via the "window-state-event" signal
7700 gtk_window_iconify (GtkWindow *window)
7702 GtkWindowPrivate *priv;
7704 GdkWindow *toplevel;
7706 g_return_if_fail (GTK_IS_WINDOW (window));
7708 priv = window->priv;
7709 widget = GTK_WIDGET (window);
7711 priv->iconify_initially = TRUE;
7713 toplevel = gtk_widget_get_window (widget);
7715 if (toplevel != NULL)
7716 gdk_window_iconify (toplevel);
7720 * gtk_window_deiconify:
7721 * @window: a #GtkWindow
7723 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7724 * that you shouldn't assume the window is definitely deiconified
7725 * afterward, because other entities (e.g. the user or <link
7726 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7727 * again before your code which assumes deiconification gets to run.
7729 * You can track iconification via the "window-state-event" signal
7733 gtk_window_deiconify (GtkWindow *window)
7735 GtkWindowPrivate *priv;
7737 GdkWindow *toplevel;
7739 g_return_if_fail (GTK_IS_WINDOW (window));
7741 priv = window->priv;
7742 widget = GTK_WIDGET (window);
7744 priv->iconify_initially = FALSE;
7746 toplevel = gtk_widget_get_window (widget);
7748 if (toplevel != NULL)
7749 gdk_window_deiconify (toplevel);
7754 * @window: a #GtkWindow
7756 * Asks to stick @window, which means that it will appear on all user
7757 * desktops. Note that you shouldn't assume the window is definitely
7758 * stuck afterward, because other entities (e.g. the user or <link
7759 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7760 * again, and some window managers do not support sticking
7761 * windows. But normally the window will end up stuck. Just don't
7762 * write code that crashes if not.
7764 * It's permitted to call this function before showing a window.
7766 * You can track stickiness via the "window-state-event" signal
7771 gtk_window_stick (GtkWindow *window)
7773 GtkWindowPrivate *priv;
7775 GdkWindow *toplevel;
7777 g_return_if_fail (GTK_IS_WINDOW (window));
7779 priv = window->priv;
7780 widget = GTK_WIDGET (window);
7782 priv->stick_initially = TRUE;
7784 toplevel = gtk_widget_get_window (widget);
7786 if (toplevel != NULL)
7787 gdk_window_stick (toplevel);
7791 * gtk_window_unstick:
7792 * @window: a #GtkWindow
7794 * Asks to unstick @window, which means that it will appear on only
7795 * one of the user's desktops. Note that you shouldn't assume the
7796 * window is definitely unstuck afterward, because other entities
7797 * (e.g. the user or <link linkend="gtk-X11-arch">window
7798 * manager</link>) could stick it again. But normally the window will
7799 * end up stuck. Just don't write code that crashes if not.
7801 * You can track stickiness via the "window-state-event" signal
7806 gtk_window_unstick (GtkWindow *window)
7808 GtkWindowPrivate *priv;
7810 GdkWindow *toplevel;
7812 g_return_if_fail (GTK_IS_WINDOW (window));
7814 priv = window->priv;
7815 widget = GTK_WIDGET (window);
7817 priv->stick_initially = FALSE;
7819 toplevel = gtk_widget_get_window (widget);
7821 if (toplevel != NULL)
7822 gdk_window_unstick (toplevel);
7826 * gtk_window_maximize:
7827 * @window: a #GtkWindow
7829 * Asks to maximize @window, so that it becomes full-screen. Note that
7830 * you shouldn't assume the window is definitely maximized afterward,
7831 * because other entities (e.g. the user or <link
7832 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7833 * again, and not all window managers support maximization. But
7834 * normally the window will end up maximized. Just don't write code
7835 * that crashes if not.
7837 * It's permitted to call this function before showing a window,
7838 * in which case the window will be maximized when it appears onscreen
7841 * You can track maximization via the "window-state-event" signal
7846 gtk_window_maximize (GtkWindow *window)
7848 GtkWindowPrivate *priv;
7850 GdkWindow *toplevel;
7852 g_return_if_fail (GTK_IS_WINDOW (window));
7854 priv = window->priv;
7855 widget = GTK_WIDGET (window);
7857 priv->maximize_initially = TRUE;
7859 toplevel = gtk_widget_get_window (widget);
7861 if (toplevel != NULL)
7862 gdk_window_maximize (toplevel);
7866 * gtk_window_unmaximize:
7867 * @window: a #GtkWindow
7869 * Asks to unmaximize @window. Note that you shouldn't assume the
7870 * window is definitely unmaximized afterward, because other entities
7871 * (e.g. the user or <link linkend="gtk-X11-arch">window
7872 * manager</link>) could maximize it again, and not all window
7873 * managers honor requests to unmaximize. But normally the window will
7874 * end up unmaximized. Just don't write code that crashes if not.
7876 * You can track maximization via the "window-state-event" signal
7881 gtk_window_unmaximize (GtkWindow *window)
7883 GtkWindowPrivate *priv;
7885 GdkWindow *toplevel;
7887 g_return_if_fail (GTK_IS_WINDOW (window));
7889 priv = window->priv;
7890 widget = GTK_WIDGET (window);
7892 priv->maximize_initially = FALSE;
7894 toplevel = gtk_widget_get_window (widget);
7896 if (toplevel != NULL)
7897 gdk_window_unmaximize (toplevel);
7901 * gtk_window_fullscreen:
7902 * @window: a #GtkWindow
7904 * Asks to place @window in the fullscreen state. Note that you
7905 * shouldn't assume the window is definitely full screen afterward,
7906 * because other entities (e.g. the user or <link
7907 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7908 * again, and not all window managers honor requests to fullscreen
7909 * windows. But normally the window will end up fullscreen. Just
7910 * don't write code that crashes if not.
7912 * You can track the fullscreen state via the "window-state-event" signal
7918 gtk_window_fullscreen (GtkWindow *window)
7920 GtkWindowPrivate *priv;
7922 GdkWindow *toplevel;
7924 g_return_if_fail (GTK_IS_WINDOW (window));
7926 priv = window->priv;
7927 widget = GTK_WIDGET (window);
7929 priv->fullscreen_initially = TRUE;
7931 toplevel = gtk_widget_get_window (widget);
7933 if (toplevel != NULL)
7934 gdk_window_fullscreen (toplevel);
7938 * gtk_window_unfullscreen:
7939 * @window: a #GtkWindow
7941 * Asks to toggle off the fullscreen state for @window. Note that you
7942 * shouldn't assume the window is definitely not full screen
7943 * afterward, because other entities (e.g. the user or <link
7944 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7945 * again, and not all window managers honor requests to unfullscreen
7946 * windows. But normally the window will end up restored to its normal
7947 * state. Just don't write code that crashes if not.
7949 * You can track the fullscreen state via the "window-state-event" signal
7955 gtk_window_unfullscreen (GtkWindow *window)
7958 GdkWindow *toplevel;
7959 GtkWindowPrivate *priv;
7961 g_return_if_fail (GTK_IS_WINDOW (window));
7963 priv = window->priv;
7964 widget = GTK_WIDGET (window);
7966 priv->fullscreen_initially = FALSE;
7968 toplevel = gtk_widget_get_window (widget);
7970 if (toplevel != NULL)
7971 gdk_window_unfullscreen (toplevel);
7975 * gtk_window_set_keep_above:
7976 * @window: a #GtkWindow
7977 * @setting: whether to keep @window above other windows
7979 * Asks to keep @window above, so that it stays on top. Note that
7980 * you shouldn't assume the window is definitely above afterward,
7981 * because other entities (e.g. the user or <link
7982 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7983 * and not all window managers support keeping windows above. But
7984 * normally the window will end kept above. Just don't write code
7985 * that crashes if not.
7987 * It's permitted to call this function before showing a window,
7988 * in which case the window will be kept above when it appears onscreen
7991 * You can track the above state via the "window-state-event" signal
7994 * Note that, according to the <ulink
7995 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7996 * Manager Hints</ulink> specification, the above state is mainly meant
7997 * for user preferences and should not be used by applications e.g. for
7998 * drawing attention to their dialogs.
8003 gtk_window_set_keep_above (GtkWindow *window,
8007 GtkWindowPrivate *priv;
8008 GdkWindow *toplevel;
8010 g_return_if_fail (GTK_IS_WINDOW (window));
8012 priv = window->priv;
8013 widget = GTK_WIDGET (window);
8015 priv->above_initially = setting != FALSE;
8017 priv->below_initially = FALSE;
8019 toplevel = gtk_widget_get_window (widget);
8021 if (toplevel != NULL)
8022 gdk_window_set_keep_above (toplevel, setting);
8026 * gtk_window_set_keep_below:
8027 * @window: a #GtkWindow
8028 * @setting: whether to keep @window below other windows
8030 * Asks to keep @window below, so that it stays in bottom. Note that
8031 * you shouldn't assume the window is definitely below afterward,
8032 * because other entities (e.g. the user or <link
8033 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8034 * and not all window managers support putting windows below. But
8035 * normally the window will be kept below. Just don't write code
8036 * that crashes if not.
8038 * It's permitted to call this function before showing a window,
8039 * in which case the window will be kept below when it appears onscreen
8042 * You can track the below state via the "window-state-event" signal
8045 * Note that, according to the <ulink
8046 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8047 * Manager Hints</ulink> specification, the above state is mainly meant
8048 * for user preferences and should not be used by applications e.g. for
8049 * drawing attention to their dialogs.
8054 gtk_window_set_keep_below (GtkWindow *window,
8058 GtkWindowPrivate *priv;
8059 GdkWindow *toplevel;
8061 g_return_if_fail (GTK_IS_WINDOW (window));
8063 priv = window->priv;
8064 widget = GTK_WIDGET (window);
8066 priv->below_initially = setting != FALSE;
8068 priv->above_initially = FALSE;
8070 toplevel = gtk_widget_get_window (widget);
8072 if (toplevel != NULL)
8073 gdk_window_set_keep_below (toplevel, setting);
8077 * gtk_window_set_resizable:
8078 * @window: a #GtkWindow
8079 * @resizable: %TRUE if the user can resize this window
8081 * Sets whether the user can resize a window. Windows are user resizable
8085 gtk_window_set_resizable (GtkWindow *window,
8088 GtkWindowPrivate *priv;
8090 g_return_if_fail (GTK_IS_WINDOW (window));
8092 priv = window->priv;
8094 resizable = (resizable != FALSE);
8096 if (priv->resizable != resizable)
8098 priv->resizable = resizable;
8100 update_grip_visibility (window);
8102 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8104 g_object_notify (G_OBJECT (window), "resizable");
8109 * gtk_window_get_resizable:
8110 * @window: a #GtkWindow
8112 * Gets the value set by gtk_window_set_resizable().
8114 * Return value: %TRUE if the user can resize the window
8117 gtk_window_get_resizable (GtkWindow *window)
8119 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8121 return window->priv->resizable;
8125 * gtk_window_set_gravity:
8126 * @window: a #GtkWindow
8127 * @gravity: window gravity
8129 * Window gravity defines the meaning of coordinates passed to
8130 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8133 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8134 * typically "do what you mean."
8138 gtk_window_set_gravity (GtkWindow *window,
8141 GtkWindowPrivate *priv;
8143 g_return_if_fail (GTK_IS_WINDOW (window));
8145 priv = window->priv;
8147 if (gravity != priv->gravity)
8149 priv->gravity = gravity;
8151 /* gtk_window_move_resize() will adapt gravity
8153 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8155 g_object_notify (G_OBJECT (window), "gravity");
8160 * gtk_window_get_gravity:
8161 * @window: a #GtkWindow
8163 * Gets the value set by gtk_window_set_gravity().
8165 * Return value: (transfer none): window gravity
8168 gtk_window_get_gravity (GtkWindow *window)
8170 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8172 return window->priv->gravity;
8176 * gtk_window_begin_resize_drag:
8177 * @window: a #GtkWindow
8178 * @button: mouse button that initiated the drag
8179 * @edge: position of the resize control
8180 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8181 * @root_y: Y position where the user clicked to initiate the drag
8182 * @timestamp: timestamp from the click event that initiated the drag
8184 * Starts resizing a window. This function is used if an application
8185 * has window resizing controls. When GDK can support it, the resize
8186 * will be done using the standard mechanism for the <link
8187 * linkend="gtk-X11-arch">window manager</link> or windowing
8188 * system. Otherwise, GDK will try to emulate window resizing,
8189 * potentially not all that well, depending on the windowing system.
8193 gtk_window_begin_resize_drag (GtkWindow *window,
8201 GdkWindow *toplevel;
8203 g_return_if_fail (GTK_IS_WINDOW (window));
8204 widget = GTK_WIDGET (window);
8205 g_return_if_fail (gtk_widget_get_visible (widget));
8207 toplevel = gtk_widget_get_window (widget);
8209 gdk_window_begin_resize_drag (toplevel,
8216 * gtk_window_begin_move_drag:
8217 * @window: a #GtkWindow
8218 * @button: mouse button that initiated the drag
8219 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8220 * @root_y: Y position where the user clicked to initiate the drag
8221 * @timestamp: timestamp from the click event that initiated the drag
8223 * Starts moving a window. This function is used if an application has
8224 * window movement grips. When GDK can support it, the window movement
8225 * will be done using the standard mechanism for the <link
8226 * linkend="gtk-X11-arch">window manager</link> or windowing
8227 * system. Otherwise, GDK will try to emulate window movement,
8228 * potentially not all that well, depending on the windowing system.
8232 gtk_window_begin_move_drag (GtkWindow *window,
8239 GdkWindow *toplevel;
8241 g_return_if_fail (GTK_IS_WINDOW (window));
8242 widget = GTK_WIDGET (window);
8243 g_return_if_fail (gtk_widget_get_visible (widget));
8245 toplevel = gtk_widget_get_window (widget);
8247 gdk_window_begin_move_drag (toplevel,
8254 * gtk_window_set_screen:
8255 * @window: a #GtkWindow.
8256 * @screen: a #GdkScreen.
8258 * Sets the #GdkScreen where the @window is displayed; if
8259 * the window is already mapped, it will be unmapped, and
8260 * then remapped on the new screen.
8265 gtk_window_set_screen (GtkWindow *window,
8268 GtkWindowPrivate *priv;
8270 GdkScreen *previous_screen;
8271 gboolean was_mapped;
8273 g_return_if_fail (GTK_IS_WINDOW (window));
8274 g_return_if_fail (GDK_IS_SCREEN (screen));
8276 priv = window->priv;
8278 if (screen == priv->screen)
8281 widget = GTK_WIDGET (window);
8283 previous_screen = priv->screen;
8284 was_mapped = gtk_widget_get_mapped (widget);
8287 gtk_widget_unmap (widget);
8288 if (gtk_widget_get_realized (widget))
8289 gtk_widget_unrealize (widget);
8291 gtk_window_free_key_hash (window);
8292 priv->screen = screen;
8293 gtk_widget_reset_rc_styles (widget);
8294 if (screen != previous_screen)
8296 if (previous_screen)
8298 g_signal_handlers_disconnect_by_func (previous_screen,
8299 gtk_window_on_composited_changed, window);
8300 #ifdef GDK_WINDOWING_X11
8301 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8302 gtk_window_on_theme_variant_changed, window);
8305 g_signal_connect (screen, "composited-changed",
8306 G_CALLBACK (gtk_window_on_composited_changed), window);
8307 #ifdef GDK_WINDOWING_X11
8308 g_signal_connect (gtk_settings_get_for_screen (screen),
8309 "notify::gtk-application-prefer-dark-theme",
8310 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8313 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8314 _gtk_widget_propagate_composited_changed (widget);
8316 g_object_notify (G_OBJECT (window), "screen");
8319 gtk_widget_map (widget);
8323 gtk_window_set_theme_variant (GtkWindow *window)
8325 #ifdef GDK_WINDOWING_X11
8326 GdkWindow *gdk_window;
8327 gboolean dark_theme_requested;
8329 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8330 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8333 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8335 if (GDK_IS_X11_WINDOW (gdk_window))
8336 gdk_x11_window_set_theme_variant (gdk_window,
8337 dark_theme_requested ? "dark" : NULL);
8341 #ifdef GDK_WINDOWING_X11
8343 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8347 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8348 gtk_window_set_theme_variant (window);
8353 gtk_window_on_composited_changed (GdkScreen *screen,
8356 gtk_widget_queue_draw (GTK_WIDGET (window));
8358 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8362 gtk_window_check_screen (GtkWindow *window)
8364 GtkWindowPrivate *priv = window->priv;
8367 return priv->screen;
8370 g_warning ("Screen for GtkWindow not set; you must always set\n"
8371 "a screen for a GtkWindow before using the window");
8377 * gtk_window_get_screen:
8378 * @window: a #GtkWindow.
8380 * Returns the #GdkScreen associated with @window.
8382 * Return value: (transfer none): a #GdkScreen.
8387 gtk_window_get_screen (GtkWindow *window)
8389 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8391 return window->priv->screen;
8395 * gtk_window_is_active:
8396 * @window: a #GtkWindow
8398 * Returns whether the window is part of the current active toplevel.
8399 * (That is, the toplevel window receiving keystrokes.)
8400 * The return value is %TRUE if the window is active toplevel
8401 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8402 * You might use this function if you wanted to draw a widget
8403 * differently in an active window from a widget in an inactive window.
8404 * See gtk_window_has_toplevel_focus()
8406 * Return value: %TRUE if the window part of the current active window.
8411 gtk_window_is_active (GtkWindow *window)
8413 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8415 return window->priv->is_active;
8419 * gtk_window_has_toplevel_focus:
8420 * @window: a #GtkWindow
8422 * Returns whether the input focus is within this GtkWindow.
8423 * For real toplevel windows, this is identical to gtk_window_is_active(),
8424 * but for embedded windows, like #GtkPlug, the results will differ.
8426 * Return value: %TRUE if the input focus is within this GtkWindow
8431 gtk_window_has_toplevel_focus (GtkWindow *window)
8433 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8435 return window->priv->has_toplevel_focus;
8440 * SECTION:gtkwindowgroup
8441 * @Short_description: Limit the effect of grabs
8442 * @Title: GtkWindowGroup
8444 * #GtkWindowGroup objects are referenced by each window in the group,
8445 * so once you have added all windows to a #GtkWindowGroup, you can drop
8446 * the initial reference to the window group with g_object_unref(). If the
8447 * windows in the window group are subsequently destroyed, then they will
8448 * be removed from the window group and drop their references on the window
8449 * group; when all window have been removed, the window group will be
8453 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8456 gtk_window_group_init (GtkWindowGroup *group)
8458 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8459 GTK_TYPE_WINDOW_GROUP,
8460 GtkWindowGroupPrivate);
8464 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8466 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8470 * gtk_window_group_new:
8472 * Creates a new #GtkWindowGroup object. Grabs added with
8473 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8475 * Return value: a new #GtkWindowGroup.
8478 gtk_window_group_new (void)
8480 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8484 window_group_cleanup_grabs (GtkWindowGroup *group,
8487 GtkWindowGroupPrivate *priv;
8488 GtkDeviceGrabInfo *info;
8490 GSList *to_remove = NULL;
8494 tmp_list = priv->grabs;
8497 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8498 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8499 tmp_list = tmp_list->next;
8504 gtk_grab_remove (to_remove->data);
8505 g_object_unref (to_remove->data);
8506 to_remove = g_slist_delete_link (to_remove, to_remove);
8509 tmp_list = priv->device_grabs;
8513 info = tmp_list->data;
8515 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8516 to_remove = g_slist_prepend (to_remove, info);
8518 tmp_list = tmp_list->next;
8523 info = to_remove->data;
8525 gtk_device_grab_remove (info->widget, info->device);
8526 to_remove = g_slist_delete_link (to_remove, to_remove);
8531 * gtk_window_group_add_window:
8532 * @window_group: a #GtkWindowGroup
8533 * @window: the #GtkWindow to add
8535 * Adds a window to a #GtkWindowGroup.
8538 gtk_window_group_add_window (GtkWindowGroup *window_group,
8541 GtkWindowPrivate *priv;
8543 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8544 g_return_if_fail (GTK_IS_WINDOW (window));
8546 priv = window->priv;
8548 if (priv->group != window_group)
8550 g_object_ref (window);
8551 g_object_ref (window_group);
8554 gtk_window_group_remove_window (priv->group, window);
8556 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8558 priv->group = window_group;
8560 g_object_unref (window);
8565 * gtk_window_group_remove_window:
8566 * @window_group: a #GtkWindowGroup
8567 * @window: the #GtkWindow to remove
8569 * Removes a window from a #GtkWindowGroup.
8572 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8575 GtkWindowPrivate *priv;
8577 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8578 g_return_if_fail (GTK_IS_WINDOW (window));
8579 priv = window->priv;
8580 g_return_if_fail (priv->group == window_group);
8582 g_object_ref (window);
8584 window_group_cleanup_grabs (window_group, window);
8587 g_object_unref (window_group);
8588 g_object_unref (window);
8592 * gtk_window_group_list_windows:
8593 * @window_group: a #GtkWindowGroup
8595 * Returns a list of the #GtkWindows that belong to @window_group.
8597 * Returns: (element-type GtkWindow) (transfer container): A
8598 * newly-allocated list of windows inside the group.
8603 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8605 GList *toplevels, *toplevel, *group_windows;
8607 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8609 group_windows = NULL;
8610 toplevels = gtk_window_list_toplevels ();
8612 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8614 GtkWindow *window = toplevel->data;
8616 if (window_group == window->priv->group)
8617 group_windows = g_list_prepend (group_windows, window);
8620 g_list_free (toplevels);
8622 return g_list_reverse (group_windows);
8626 * gtk_window_get_group:
8627 * @window: (allow-none): a #GtkWindow, or %NULL
8629 * Returns the group for @window or the default group, if
8630 * @window is %NULL or if @window does not have an explicit
8633 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8638 gtk_window_get_group (GtkWindow *window)
8640 if (window && window->priv->group)
8641 return window->priv->group;
8644 static GtkWindowGroup *default_group = NULL;
8647 default_group = gtk_window_group_new ();
8649 return default_group;
8654 * gtk_window_has_group:
8655 * @window: a #GtkWindow
8657 * Returns whether @window has an explicit window group.
8659 * Return value: %TRUE if @window has an explicit window group.
8664 gtk_window_has_group (GtkWindow *window)
8666 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8668 return window->priv->group != NULL;
8672 * gtk_window_group_get_current_grab:
8673 * @window_group: a #GtkWindowGroup
8675 * Gets the current grab widget of the given group,
8676 * see gtk_grab_add().
8678 * Returns: (transfer none): the current grab widget of the group
8683 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8685 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8687 if (window_group->priv->grabs)
8688 return GTK_WIDGET (window_group->priv->grabs->data);
8693 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8696 GtkWindowGroupPrivate *priv;
8698 priv = window_group->priv;
8699 priv->grabs = g_slist_prepend (priv->grabs, widget);
8703 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8706 GtkWindowGroupPrivate *priv;
8708 priv = window_group->priv;
8709 priv->grabs = g_slist_remove (priv->grabs, widget);
8714 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8717 gboolean block_others)
8719 GtkWindowGroupPrivate *priv;
8720 GtkDeviceGrabInfo *info;
8722 priv = window_group->priv;
8724 info = g_slice_new0 (GtkDeviceGrabInfo);
8725 info->widget = widget;
8726 info->device = device;
8727 info->block_others = block_others;
8729 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8733 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8737 GtkWindowGroupPrivate *priv;
8738 GtkDeviceGrabInfo *info;
8739 GSList *list, *node = NULL;
8740 GdkDevice *other_device;
8742 priv = window_group->priv;
8743 other_device = gdk_device_get_associated_device (device);
8744 list = priv->device_grabs;
8750 if (info->widget == widget &&
8751 (info->device == device ||
8752 info->device == other_device))
8765 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8766 g_slice_free (GtkDeviceGrabInfo, info);
8771 * gtk_window_group_get_current_device_grab:
8772 * @window_group: a #GtkWindowGroup
8773 * @device: a #GdkDevice
8775 * Returns the current grab widget for @device, or %NULL if none.
8777 * Returns: (transfer none): The grab widget, or %NULL
8782 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8785 GtkWindowGroupPrivate *priv;
8786 GtkDeviceGrabInfo *info;
8787 GdkDevice *other_device;
8790 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8791 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8793 priv = window_group->priv;
8794 list = priv->device_grabs;
8795 other_device = gdk_device_get_associated_device (device);
8802 if (info->device == device ||
8803 info->device == other_device)
8804 return info->widget;
8811 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8815 GtkWindowGroupPrivate *priv;
8816 GtkDeviceGrabInfo *info;
8817 GdkDevice *other_device;
8820 priv = window_group->priv;
8821 other_device = gdk_device_get_associated_device (device);
8822 list = priv->device_grabs;
8829 /* Look for blocking grabs on other device pairs
8830 * that have the passed widget within the GTK+ grab.
8832 if (info->block_others &&
8833 info->device != device &&
8834 info->device != other_device &&
8835 (info->widget == widget ||
8836 gtk_widget_is_ancestor (widget, info->widget)))
8844 Derived from XParseGeometry() in XFree86
8846 Copyright 1985, 1986, 1987,1998 The Open Group
8848 All Rights Reserved.
8850 The above copyright notice and this permission notice shall be included
8851 in all copies or substantial portions of the Software.
8853 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8854 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8855 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8856 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8857 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8858 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8859 OTHER DEALINGS IN THE SOFTWARE.
8861 Except as contained in this notice, the name of The Open Group shall
8862 not be used in advertising or otherwise to promote the sale, use or
8863 other dealings in this Software without prior written authorization
8864 from The Open Group.
8869 * XParseGeometry parses strings of the form
8870 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8871 * width, height, xoffset, and yoffset are unsigned integers.
8872 * Example: "=80x24+300-49"
8873 * The equal sign is optional.
8874 * It returns a bitmask that indicates which of the four values
8875 * were actually found in the string. For each value found,
8876 * the corresponding argument is updated; for each value
8877 * not found, the corresponding argument is left unchanged.
8880 /* The following code is from Xlib, and is minimally modified, so we
8881 * can track any upstream changes if required. Don't change this
8882 * code. Or if you do, put in a huge comment marking which thing
8887 read_int (gchar *string,
8895 else if (*string == '-')
8901 for (; (*string >= '0') && (*string <= '9'); string++)
8903 result = (result * 10) + (*string - '0');
8915 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8916 * value (x, y, width, height) was found in the parsed string.
8918 #define NoValue 0x0000
8919 #define XValue 0x0001
8920 #define YValue 0x0002
8921 #define WidthValue 0x0004
8922 #define HeightValue 0x0008
8923 #define AllValues 0x000F
8924 #define XNegative 0x0010
8925 #define YNegative 0x0020
8927 /* Try not to reformat/modify, so we can compare/sync with X sources */
8929 gtk_XParseGeometry (const char *string,
8932 unsigned int *width,
8933 unsigned int *height)
8937 unsigned int tempWidth, tempHeight;
8939 char *nextCharacter;
8941 /* These initializations are just to silence gcc */
8947 if ( (string == NULL) || (*string == '\0')) return(mask);
8949 string++; /* ignore possible '=' at beg of geometry spec */
8951 strind = (char *)string;
8952 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8953 tempWidth = read_int(strind, &nextCharacter);
8954 if (strind == nextCharacter)
8956 strind = nextCharacter;
8960 if (*strind == 'x' || *strind == 'X') {
8962 tempHeight = read_int(strind, &nextCharacter);
8963 if (strind == nextCharacter)
8965 strind = nextCharacter;
8966 mask |= HeightValue;
8969 if ((*strind == '+') || (*strind == '-')) {
8970 if (*strind == '-') {
8972 tempX = -read_int(strind, &nextCharacter);
8973 if (strind == nextCharacter)
8975 strind = nextCharacter;
8981 tempX = read_int(strind, &nextCharacter);
8982 if (strind == nextCharacter)
8984 strind = nextCharacter;
8987 if ((*strind == '+') || (*strind == '-')) {
8988 if (*strind == '-') {
8990 tempY = -read_int(strind, &nextCharacter);
8991 if (strind == nextCharacter)
8993 strind = nextCharacter;
9000 tempY = read_int(strind, &nextCharacter);
9001 if (strind == nextCharacter)
9003 strind = nextCharacter;
9009 /* If strind isn't at the end of the string the it's an invalid
9010 geometry specification. */
9012 if (*strind != '\0') return (0);
9018 if (mask & WidthValue)
9020 if (mask & HeightValue)
9021 *height = tempHeight;
9026 * gtk_window_parse_geometry:
9027 * @window: a #GtkWindow
9028 * @geometry: geometry string
9030 * Parses a standard X Window System geometry string - see the
9031 * manual page for X (type 'man X') for details on this.
9032 * gtk_window_parse_geometry() does work on all GTK+ ports
9033 * including Win32 but is primarily intended for an X environment.
9035 * If either a size or a position can be extracted from the
9036 * geometry string, gtk_window_parse_geometry() returns %TRUE
9037 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9038 * to resize/move the window.
9040 * If gtk_window_parse_geometry() returns %TRUE, it will also
9041 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9042 * indicating to the window manager that the size/position of
9043 * the window was user-specified. This causes most window
9044 * managers to honor the geometry.
9046 * Note that for gtk_window_parse_geometry() to work as expected, it has
9047 * to be called when the window has its "final" size, i.e. after calling
9048 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9051 * #include <gtk/gtk.h>
9054 * fill_with_content (GtkWidget *vbox)
9056 * /* fill with content... */
9060 * main (int argc, char *argv[])
9062 * GtkWidget *window, *vbox;
9063 * GdkGeometry size_hints = {
9064 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9067 * gtk_init (&argc, &argv);
9069 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9070 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9072 * gtk_container_add (GTK_CONTAINER (window), vbox);
9073 * fill_with_content (vbox);
9074 * gtk_widget_show_all (vbox);
9076 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9079 * GDK_HINT_MIN_SIZE |
9080 * GDK_HINT_BASE_SIZE |
9081 * GDK_HINT_RESIZE_INC);
9085 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9086 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9089 * gtk_widget_show_all (window);
9096 * Return value: %TRUE if string was parsed successfully
9099 gtk_window_parse_geometry (GtkWindow *window,
9100 const gchar *geometry)
9102 gint result, x = 0, y = 0;
9106 gboolean size_set, pos_set;
9109 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9110 g_return_val_if_fail (geometry != NULL, FALSE);
9112 child = gtk_bin_get_child (GTK_BIN (window));
9113 if (!child || !gtk_widget_get_visible (child))
9114 g_warning ("gtk_window_parse_geometry() called on a window with no "
9115 "visible children; the window should be set up before "
9116 "gtk_window_parse_geometry() is called.");
9118 screen = gtk_window_check_screen (window);
9120 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9123 if ((result & WidthValue) || (result & HeightValue))
9125 gtk_window_set_default_size_internal (window,
9126 TRUE, result & WidthValue ? w : -1,
9127 TRUE, result & HeightValue ? h : -1,
9132 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9134 grav = GDK_GRAVITY_NORTH_WEST;
9136 if ((result & XNegative) && (result & YNegative))
9137 grav = GDK_GRAVITY_SOUTH_EAST;
9138 else if (result & XNegative)
9139 grav = GDK_GRAVITY_NORTH_EAST;
9140 else if (result & YNegative)
9141 grav = GDK_GRAVITY_SOUTH_WEST;
9143 if ((result & XValue) == 0)
9146 if ((result & YValue) == 0)
9149 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9150 grav == GDK_GRAVITY_SOUTH_EAST)
9151 y = gdk_screen_get_height (screen) - h + y;
9153 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9154 grav == GDK_GRAVITY_NORTH_EAST)
9155 x = gdk_screen_get_width (screen) - w + x;
9157 /* we don't let you put a window offscreen; maybe some people would
9158 * prefer to be able to, but it's kind of a bogus thing to do.
9167 if ((result & XValue) || (result & YValue))
9169 gtk_window_set_gravity (window, grav);
9170 gtk_window_move (window, x, y);
9174 if (size_set || pos_set)
9176 /* Set USSize, USPosition hints */
9177 GtkWindowGeometryInfo *info;
9179 info = gtk_window_get_geometry_info (window, TRUE);
9182 info->mask |= GDK_HINT_USER_POS;
9184 info->mask |= GDK_HINT_USER_SIZE;
9191 gtk_window_mnemonic_hash_foreach (guint keyval,
9197 GtkWindowKeysForeachFunc func;
9201 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9205 _gtk_window_keys_foreach (GtkWindow *window,
9206 GtkWindowKeysForeachFunc func,
9210 GtkMnemonicHash *mnemonic_hash;
9214 GtkWindowKeysForeachFunc func;
9218 info.window = window;
9220 info.func_data = func_data;
9222 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9224 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9225 gtk_window_mnemonic_hash_foreach, &info);
9227 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9230 GtkAccelGroup *group = groups->data;
9233 for (i = 0; i < group->priv->n_accels; i++)
9235 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9238 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9241 groups = groups->next;
9246 gtk_window_keys_changed (GtkWindow *window)
9248 gtk_window_free_key_hash (window);
9249 gtk_window_get_key_hash (window);
9252 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9254 struct _GtkWindowKeyEntry
9258 guint is_mnemonic : 1;
9262 window_key_entry_destroy (gpointer data)
9264 g_slice_free (GtkWindowKeyEntry, data);
9268 add_to_key_hash (GtkWindow *window,
9270 GdkModifierType modifiers,
9271 gboolean is_mnemonic,
9274 GtkKeyHash *key_hash = data;
9276 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9278 entry->keyval = keyval;
9279 entry->modifiers = modifiers;
9280 entry->is_mnemonic = is_mnemonic;
9282 /* GtkAccelGroup stores lowercased accelerators. To deal
9283 * with this, if <Shift> was specified, uppercase.
9285 if (modifiers & GDK_SHIFT_MASK)
9287 if (keyval == GDK_KEY_Tab)
9288 keyval = GDK_KEY_ISO_Left_Tab;
9290 keyval = gdk_keyval_to_upper (keyval);
9293 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9297 gtk_window_get_key_hash (GtkWindow *window)
9299 GdkScreen *screen = gtk_window_check_screen (window);
9300 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9305 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9306 (GDestroyNotify)window_key_entry_destroy);
9307 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9308 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9314 gtk_window_free_key_hash (GtkWindow *window)
9316 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9319 _gtk_key_hash_free (key_hash);
9320 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9325 * gtk_window_activate_key:
9326 * @window: a #GtkWindow
9327 * @event: a #GdkEventKey
9329 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9330 * called by the default ::key_press_event handler for toplevel windows,
9331 * however in some cases it may be useful to call this directly when
9332 * overriding the standard key handling for a toplevel window.
9334 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9339 gtk_window_activate_key (GtkWindow *window,
9342 GtkKeyHash *key_hash;
9343 GtkWindowKeyEntry *found_entry = NULL;
9344 gboolean enable_mnemonics;
9345 gboolean enable_accels;
9347 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9348 g_return_val_if_fail (event != NULL, FALSE);
9350 key_hash = gtk_window_get_key_hash (window);
9355 GSList *entries = _gtk_key_hash_lookup (key_hash,
9356 event->hardware_keycode,
9358 gtk_accelerator_get_default_mod_mask (),
9361 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9362 "gtk-enable-mnemonics", &enable_mnemonics,
9363 "gtk-enable-accels", &enable_accels,
9366 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9368 GtkWindowKeyEntry *entry = tmp_list->data;
9369 if (entry->is_mnemonic)
9371 if (enable_mnemonics)
9373 found_entry = entry;
9379 if (enable_accels && !found_entry)
9381 found_entry = entry;
9386 g_slist_free (entries);
9391 if (found_entry->is_mnemonic)
9393 if (enable_mnemonics)
9394 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9395 found_entry->modifiers);
9400 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9401 found_entry->modifiers);
9409 window_update_has_focus (GtkWindow *window)
9411 GtkWindowPrivate *priv = window->priv;
9412 GtkWidget *widget = GTK_WIDGET (window);
9413 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9415 if (has_focus != priv->has_focus)
9417 priv->has_focus = has_focus;
9421 if (priv->focus_widget &&
9422 priv->focus_widget != widget &&
9423 !gtk_widget_has_focus (priv->focus_widget))
9424 do_focus_change (priv->focus_widget, TRUE);
9428 if (priv->focus_widget &&
9429 priv->focus_widget != widget &&
9430 gtk_widget_has_focus (priv->focus_widget))
9431 do_focus_change (priv->focus_widget, FALSE);
9437 * _gtk_window_set_is_active:
9438 * @window: a #GtkWindow
9439 * @is_active: %TRUE if the window is in the currently active toplevel
9441 * Internal function that sets whether the #GtkWindow is part
9442 * of the currently active toplevel window (taking into account inter-process
9446 _gtk_window_set_is_active (GtkWindow *window,
9449 GtkWindowPrivate *priv;
9451 g_return_if_fail (GTK_IS_WINDOW (window));
9453 priv = window->priv;
9455 is_active = is_active != FALSE;
9457 if (is_active != priv->is_active)
9459 priv->is_active = is_active;
9460 window_update_has_focus (window);
9462 g_object_notify (G_OBJECT (window), "is-active");
9467 * _gtk_window_set_is_toplevel:
9468 * @window: a #GtkWindow
9469 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9470 * child of the root window); %FALSE if it is not (for example, for an
9471 * in-process, parented GtkPlug)
9473 * Internal function used by #GtkPlug when it gets parented/unparented by a
9474 * #GtkSocket. This keeps the @window's #GTK_WINDOW_TOPLEVEL flag in sync
9475 * with the global list of toplevel windows.
9478 _gtk_window_set_is_toplevel (GtkWindow *window,
9479 gboolean is_toplevel)
9482 GtkWidget *toplevel;
9484 widget = GTK_WIDGET (window);
9486 if (gtk_widget_is_toplevel (widget))
9487 g_assert (g_slist_find (toplevel_list, window) != NULL);
9489 g_assert (g_slist_find (toplevel_list, window) == NULL);
9491 if (is_toplevel == gtk_widget_is_toplevel (widget))
9496 /* Pass through regular pathways of an embedded toplevel
9497 * to go through unmapping and hiding the widget before
9498 * becomming a toplevel again.
9500 * We remain hidden after becomming toplevel in order to
9501 * avoid problems during an embedded toplevel's dispose cycle
9502 * (When a toplevel window is shown it tries to grab focus again,
9503 * this causes problems while disposing).
9505 gtk_widget_hide (widget);
9507 /* Save the toplevel this widget was previously anchored into before
9508 * propagating a hierarchy-changed.
9510 * Usually this happens by way of gtk_widget_unparent() and we are
9511 * already unanchored at this point, just adding this clause incase
9512 * things happen differently.
9514 toplevel = gtk_widget_get_toplevel (widget);
9515 if (!gtk_widget_is_toplevel (toplevel))
9518 _gtk_widget_set_is_toplevel (widget, TRUE);
9520 /* When a window becomes toplevel after being embedded and anchored
9521 * into another window we need to unset its anchored flag so that
9522 * the hierarchy changed signal kicks in properly.
9524 _gtk_widget_set_anchored (widget, FALSE);
9525 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9527 toplevel_list = g_slist_prepend (toplevel_list, window);
9531 _gtk_widget_set_is_toplevel (widget, FALSE);
9532 toplevel_list = g_slist_remove (toplevel_list, window);
9534 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9539 * _gtk_window_set_has_toplevel_focus:
9540 * @window: a #GtkWindow
9541 * @has_toplevel_focus: %TRUE if the in
9543 * Internal function that sets whether the keyboard focus for the
9544 * toplevel window (taking into account inter-process embedding.)
9547 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9548 gboolean has_toplevel_focus)
9550 GtkWindowPrivate *priv;
9552 g_return_if_fail (GTK_IS_WINDOW (window));
9554 priv = window->priv;
9556 has_toplevel_focus = has_toplevel_focus != FALSE;
9558 if (has_toplevel_focus != priv->has_toplevel_focus)
9560 priv->has_toplevel_focus = has_toplevel_focus;
9561 window_update_has_focus (window);
9563 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9568 * gtk_window_set_auto_startup_notification:
9569 * @setting: %TRUE to automatically do startup notification
9571 * By default, after showing the first #GtkWindow, GTK+ calls
9572 * gdk_notify_startup_complete(). Call this function to disable
9573 * the automatic startup notification. You might do this if your
9574 * first window is a splash screen, and you want to delay notification
9575 * until after your real main window has been shown, for example.
9577 * In that example, you would disable startup notification
9578 * temporarily, show your splash screen, then re-enable it so that
9579 * showing the main window would automatically result in notification.
9584 gtk_window_set_auto_startup_notification (gboolean setting)
9586 disable_startup_notification = !setting;
9590 * gtk_window_get_window_type:
9591 * @window: a #GtkWindow
9593 * Gets the type of the window. See #GtkWindowType.
9595 * Return value: the type of the window
9600 gtk_window_get_window_type (GtkWindow *window)
9602 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9604 return window->priv->type;
9608 * gtk_window_get_mnemonics_visible:
9609 * @window: a #GtkWindow
9611 * Gets the value of the #GtkWindow:mnemonics-visible property.
9613 * Returns: %TRUE if mnemonics are supposed to be visible
9619 gtk_window_get_mnemonics_visible (GtkWindow *window)
9621 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9623 return window->priv->mnemonics_visible;
9627 * gtk_window_set_mnemonics_visible:
9628 * @window: a #GtkWindow
9629 * @setting: the new value
9631 * Sets the #GtkWindow:mnemonics-visible property.
9636 gtk_window_set_mnemonics_visible (GtkWindow *window,
9639 GtkWindowPrivate *priv;
9641 g_return_if_fail (GTK_IS_WINDOW (window));
9643 priv = window->priv;
9645 setting = setting != FALSE;
9647 if (priv->mnemonics_visible != setting)
9649 priv->mnemonics_visible = setting;
9650 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9653 if (priv->auto_mnemonics_timeout_id)
9655 g_source_remove (priv->auto_mnemonics_timeout_id);
9656 priv->auto_mnemonics_timeout_id = 0;
9659 priv->mnemonics_visible_set = TRUE;
9663 set_auto_mnemonics_visible_cb (gpointer data)
9665 GtkWindow *window = data;
9667 gtk_window_set_mnemonics_visible (window, TRUE);
9669 window->priv->auto_mnemonics_timeout_id = 0;
9675 _gtk_window_set_auto_mnemonics_visible (GtkWindow *window)
9677 g_return_if_fail (GTK_IS_WINDOW (window));
9679 if (window->priv->auto_mnemonics_timeout_id)
9682 window->priv->auto_mnemonics_timeout_id =
9683 gdk_threads_add_timeout (AUTO_MNEMONICS_DELAY, set_auto_mnemonics_visible_cb, window);
9687 * gtk_window_get_focus_visible:
9688 * @window: a #GtkWindow
9690 * Gets the value of the #GtkWindow:focus-visible property.
9692 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9698 gtk_window_get_focus_visible (GtkWindow *window)
9700 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9702 return window->priv->focus_visible;
9706 * gtk_window_set_focus_visible:
9707 * @window: a #GtkWindow
9708 * @setting: the new value
9710 * Sets the #GtkWindow:focus-visible property.
9715 gtk_window_set_focus_visible (GtkWindow *window,
9718 GtkWindowPrivate *priv;
9720 g_return_if_fail (GTK_IS_WINDOW (window));
9722 priv = window->priv;
9724 setting = setting != FALSE;
9726 if (priv->focus_visible != setting)
9728 priv->focus_visible = setting;
9729 g_object_notify (G_OBJECT (window), "focus-visible");
9734 _gtk_window_get_wmclass (GtkWindow *window,
9735 gchar **wmclass_name,
9736 gchar **wmclass_class)
9738 GtkWindowPrivate *priv = window->priv;
9740 *wmclass_name = priv->wmclass_name;
9741 *wmclass_class = priv->wmclass_class;
9745 * gtk_window_set_has_user_ref_count:
9746 * @window: a #GtkWindow
9747 * @setting: the new value
9749 * Tells GTK+ whether to drop its extra reference to the window
9750 * when gtk_widget_destroy() is called.
9752 * This function is only exported for the benefit of language
9753 * bindings which may need to keep the window alive until their
9754 * wrapper object is garbage collected. There is no justification
9755 * for ever calling this function in an application.
9760 gtk_window_set_has_user_ref_count (GtkWindow *window,
9763 g_return_if_fail (GTK_IS_WINDOW (window));
9765 window->priv->has_user_ref_count = setting;
9769 ensure_state_flag_backdrop (GtkWidget *widget)
9772 gboolean window_focused = TRUE;
9774 window = gtk_widget_get_window (widget);
9776 window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9778 if (!window_focused)
9779 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
9781 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
9783 gtk_widget_queue_draw (widget);