1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gtkwindow.h"
36 #include "gtkprivate.h"
37 #include "gtkwindowprivate.h"
38 #include "gtkaccelgroupprivate.h"
39 #include "gtkbindings.h"
40 #include "gtkkeyhash.h"
42 #include "gtkmnemonichash.h"
43 #include "gtkmenubar.h"
44 #include "gtkiconfactory.h"
45 #include "gtkicontheme.h"
46 #include "gtkmarshalers.h"
48 #include "gtkbuildable.h"
49 #include "gtkwidgetprivate.h"
50 #include "gtkcontainerprivate.h"
52 #include "gtktypebuiltins.h"
53 #include "a11y/gtkwindowaccessible.h"
55 #ifdef GDK_WINDOWING_X11
62 * @short_description: Toplevel which can contain other widgets
64 * A GtkWindow is a toplevel window which can contain other widgets.
65 * Windows normally have decorations that are under the control
66 * of the windowing system and allow the user to manipulate the window
67 * (resize it, move it, close it,...).
69 * GTK+ also allows windows to have a resize grip (a small area in the lower
70 * right or left corner) which can be clicked to reszie the window. To
71 * control whether a window has a resize grip, use
72 * gtk_window_set_has_resize_grip().
74 * <refsect2 id="GtkWindow-BUILDER-UI">
75 * <title>GtkWindow as GtkBuildable</title>
77 * The GtkWindow implementation of the GtkBuildable interface supports a
78 * custom <tag class="starttag">accel-groups</tag> element, which supports
79 * any number of <tag class="starttag">group</tag> elements representing the
80 * #GtkAccelGroup objects you want to add to your window (synonymous with
81 * gtk_window_add_accel_group().
84 * <title>A UI definition fragment with accel groups</title>
85 * <programlisting><![CDATA[
86 * <object class="GtkWindow">
88 * <group name="accelgroup1"/>
94 * <object class="GtkAccelGroup" id="accelgroup1"/>
95 * ]]></programlisting>
100 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
102 struct _GtkWindowPrivate
104 GtkMnemonicHash *mnemonic_hash;
106 GtkWidget *default_widget;
107 GtkWidget *focus_widget;
108 GtkWindow *transient_parent;
109 GtkWindowGeometryInfo *geometry_info;
110 GtkWindowGroup *group;
112 GtkApplication *application;
114 GdkModifierType mnemonic_modifier;
115 GdkWindowTypeHint gdk_type_hint;
119 GdkWindow *grip_window;
123 gchar *wmclass_class;
127 guint keys_changed_handler;
129 guint32 initial_timestamp;
131 guint16 configure_request_count;
133 /* The following flags are initially TRUE (before a window is mapped).
134 * They cause us to compute a configure request that involves
135 * default-only parameters. Once mapped, we set them to FALSE.
136 * Then we set them to TRUE again on unmap (for position)
137 * and on unrealize (for size).
139 guint need_default_position : 1;
140 guint need_default_size : 1;
142 guint above_initially : 1;
143 guint accept_focus : 1;
144 guint below_initially : 1;
145 guint builder_visible : 1;
146 guint configure_notify_received : 1;
149 guint destroy_with_parent : 1;
150 guint focus_on_map : 1;
151 guint fullscreen_initially : 1;
153 guint has_user_ref_count : 1;
154 guint has_toplevel_focus : 1;
155 guint hide_titlebar_when_maximized : 1;
156 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
158 guint maximize_initially : 1;
159 guint mnemonics_visible : 1;
160 guint mnemonics_visible_set : 1;
161 guint focus_visible : 1;
163 guint opacity_set : 1;
165 guint reset_type_hint : 1;
167 guint skips_pager : 1;
168 guint skips_taskbar : 1;
169 guint stick_initially : 1;
170 guint transient_parent_group : 1;
171 guint type : 4; /* GtkWindowType */
172 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
173 * one of the original eight. If not,
175 * GDK_WINDOW_TYPE_HINT_NORMAL
178 guint has_resize_grip : 1;
179 guint resize_grip_visible : 1; /* don't use, just for "resize-
180 * grip-visible" notification
182 guint gravity : 5; /* GdkGravity */
209 PROP_DESTROY_WITH_PARENT,
210 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
215 PROP_SKIP_TASKBAR_HINT,
216 PROP_SKIP_PAGER_HINT,
225 PROP_HAS_RESIZE_GRIP,
226 PROP_RESIZE_GRIP_VISIBLE,
228 /* Readonly properties */
230 PROP_HAS_TOPLEVEL_FOCUS,
232 /* Writeonly properties */
235 PROP_MNEMONICS_VISIBLE,
246 guint using_default_icon : 1;
247 guint using_parent_icon : 1;
248 guint using_themed_icon : 1;
252 GdkGeometry geometry; /* Last set of geometry hints we set */
253 GdkWindowHints flags;
254 GdkRectangle configure_request;
255 } GtkWindowLastGeometryInfo;
257 struct _GtkWindowGeometryInfo
259 /* Properties that the app has set on the window
261 GdkGeometry geometry; /* Geometry hints */
263 GtkWidget *widget; /* subwidget to which hints apply */
264 /* from last gtk_window_resize () - if > 0, indicates that
265 * we should resize to this size.
270 /* From last gtk_window_move () prior to mapping -
271 * only used if initial_pos_set
276 /* Default size - used only the FIRST time we map a window,
281 /* whether to use initial_x, initial_y */
282 guint initial_pos_set : 1;
283 /* CENTER_ALWAYS or other position constraint changed since
284 * we sent the last configure request.
286 guint position_constraints_changed : 1;
288 /* if true, default_width, height should be multiplied by the
289 * increments and affect the geometry widget only
291 guint default_is_geometry : 1;
293 /* if true, resize_width, height should be multiplied by the
294 * increments and affect the geometry widget only
296 guint resize_is_geometry : 1;
298 GtkWindowLastGeometryInfo last;
302 struct _GtkDeviceGrabInfo
306 guint block_others : 1;
309 struct _GtkWindowGroupPrivate
312 GSList *device_grabs;
315 static void gtk_window_dispose (GObject *object);
316 static void gtk_window_finalize (GObject *object);
317 static void gtk_window_destroy (GtkWidget *widget);
318 static void gtk_window_show (GtkWidget *widget);
319 static void gtk_window_hide (GtkWidget *widget);
320 static void gtk_window_map (GtkWidget *widget);
321 static void gtk_window_unmap (GtkWidget *widget);
322 static void gtk_window_realize (GtkWidget *widget);
323 static void gtk_window_unrealize (GtkWidget *widget);
324 static void gtk_window_size_allocate (GtkWidget *widget,
325 GtkAllocation *allocation);
326 static gboolean gtk_window_map_event (GtkWidget *widget,
328 static gint gtk_window_configure_event (GtkWidget *widget,
329 GdkEventConfigure *event);
330 static gint gtk_window_key_press_event (GtkWidget *widget,
332 static gint gtk_window_key_release_event (GtkWidget *widget,
334 static gint gtk_window_button_press_event (GtkWidget *widget,
335 GdkEventButton *event);
336 static gint gtk_window_enter_notify_event (GtkWidget *widget,
337 GdkEventCrossing *event);
338 static gint gtk_window_leave_notify_event (GtkWidget *widget,
339 GdkEventCrossing *event);
340 static gint gtk_window_focus_in_event (GtkWidget *widget,
341 GdkEventFocus *event);
342 static gint gtk_window_focus_out_event (GtkWidget *widget,
343 GdkEventFocus *event);
344 static void gtk_window_style_updated (GtkWidget *widget);
345 static gboolean gtk_window_state_event (GtkWidget *widget,
346 GdkEventWindowState *event);
347 static void gtk_window_check_resize (GtkContainer *container);
348 static gint gtk_window_focus (GtkWidget *widget,
349 GtkDirectionType direction);
350 static void gtk_window_move_focus (GtkWidget *widget,
351 GtkDirectionType dir);
352 static void gtk_window_real_set_focus (GtkWindow *window,
354 static void gtk_window_direction_changed (GtkWidget *widget,
355 GtkTextDirection prev_dir);
356 static void gtk_window_state_changed (GtkWidget *widget,
357 GtkStateType previous_state);
359 static void gtk_window_real_activate_default (GtkWindow *window);
360 static void gtk_window_real_activate_focus (GtkWindow *window);
361 static void gtk_window_keys_changed (GtkWindow *window);
362 static gint gtk_window_draw (GtkWidget *widget,
364 static void gtk_window_unset_transient_for (GtkWindow *window);
365 static void gtk_window_transient_parent_realized (GtkWidget *parent,
367 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
370 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
372 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
375 static void gtk_window_move_resize (GtkWindow *window);
376 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
378 GdkGeometry *geometry_b,
380 static void gtk_window_constrain_size (GtkWindow *window,
381 GdkGeometry *geometry,
387 static void gtk_window_constrain_position (GtkWindow *window,
392 static void gtk_window_compute_hints (GtkWindow *window,
393 GdkGeometry *new_geometry,
395 static void gtk_window_compute_configure_request (GtkWindow *window,
396 GdkRectangle *request,
397 GdkGeometry *geometry,
400 static void gtk_window_set_default_size_internal (GtkWindow *window,
401 gboolean change_width,
403 gboolean change_height,
405 gboolean is_geometry);
407 static void update_themed_icon (GtkIconTheme *theme,
409 static GList *icon_list_from_theme (GtkWidget *widget,
411 static void gtk_window_realize_icon (GtkWindow *window);
412 static void gtk_window_unrealize_icon (GtkWindow *window);
413 static void resize_grip_create_window (GtkWindow *window);
414 static void resize_grip_destroy_window (GtkWindow *window);
415 static void update_grip_visibility (GtkWindow *window);
417 static void gtk_window_notify_keys_changed (GtkWindow *window);
418 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
419 static void gtk_window_free_key_hash (GtkWindow *window);
420 static void gtk_window_on_composited_changed (GdkScreen *screen,
422 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
425 static void gtk_window_set_theme_variant (GtkWindow *window);
427 static GSList *toplevel_list = NULL;
428 static guint window_signals[LAST_SIGNAL] = { 0 };
429 static GList *default_icon_list = NULL;
430 static gchar *default_icon_name = NULL;
431 static guint default_icon_serial = 0;
432 static gboolean disable_startup_notification = FALSE;
433 static gboolean sent_startup_notification = FALSE;
435 static GQuark quark_gtk_embedded = 0;
436 static GQuark quark_gtk_window_key_hash = 0;
437 static GQuark quark_gtk_window_icon_info = 0;
438 static GQuark quark_gtk_buildable_accels = 0;
440 static GtkBuildableIface *parent_buildable_iface;
442 static void gtk_window_set_property (GObject *object,
446 static void gtk_window_get_property (GObject *object,
452 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
453 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
456 const GValue *value);
457 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
458 GtkBuilder *builder);
459 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
462 const gchar *tagname,
463 GMarkupParser *parser,
465 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
468 const gchar *tagname,
472 static void gtk_window_get_preferred_width (GtkWidget *widget,
475 static void gtk_window_get_preferred_height (GtkWidget *widget,
479 static void ensure_state_flag_window_unfocused (GtkWidget *widget);
481 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
482 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
483 gtk_window_buildable_interface_init))
486 add_tab_bindings (GtkBindingSet *binding_set,
487 GdkModifierType modifiers,
488 GtkDirectionType direction)
490 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
492 GTK_TYPE_DIRECTION_TYPE, direction);
493 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
495 GTK_TYPE_DIRECTION_TYPE, direction);
499 add_arrow_bindings (GtkBindingSet *binding_set,
501 GtkDirectionType direction)
503 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
505 gtk_binding_entry_add_signal (binding_set, keysym, 0,
507 GTK_TYPE_DIRECTION_TYPE, direction);
508 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
510 GTK_TYPE_DIRECTION_TYPE, direction);
511 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
513 GTK_TYPE_DIRECTION_TYPE, direction);
514 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
516 GTK_TYPE_DIRECTION_TYPE, direction);
520 extract_time_from_startup_id (const gchar* startup_id)
522 gchar *timestr = g_strrstr (startup_id, "_TIME");
523 guint32 retval = GDK_CURRENT_TIME;
530 /* Skip past the "_TIME" part */
535 timestamp = g_ascii_strtoull (timestr, &end, 0);
536 if (errno == 0 && end != timestr)
544 startup_id_is_fake (const gchar* startup_id)
546 return strncmp (startup_id, "_TIME", 5) == 0;
550 gtk_window_class_init (GtkWindowClass *klass)
552 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
553 GtkWidgetClass *widget_class;
554 GtkContainerClass *container_class;
555 GtkBindingSet *binding_set;
557 widget_class = (GtkWidgetClass*) klass;
558 container_class = (GtkContainerClass*) klass;
560 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
561 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
562 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
563 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
565 gobject_class->dispose = gtk_window_dispose;
566 gobject_class->finalize = gtk_window_finalize;
568 gobject_class->set_property = gtk_window_set_property;
569 gobject_class->get_property = gtk_window_get_property;
571 widget_class->destroy = gtk_window_destroy;
572 widget_class->show = gtk_window_show;
573 widget_class->hide = gtk_window_hide;
574 widget_class->map = gtk_window_map;
575 widget_class->map_event = gtk_window_map_event;
576 widget_class->unmap = gtk_window_unmap;
577 widget_class->realize = gtk_window_realize;
578 widget_class->unrealize = gtk_window_unrealize;
579 widget_class->size_allocate = gtk_window_size_allocate;
580 widget_class->configure_event = gtk_window_configure_event;
581 widget_class->key_press_event = gtk_window_key_press_event;
582 widget_class->key_release_event = gtk_window_key_release_event;
583 widget_class->enter_notify_event = gtk_window_enter_notify_event;
584 widget_class->leave_notify_event = gtk_window_leave_notify_event;
585 widget_class->focus_in_event = gtk_window_focus_in_event;
586 widget_class->button_press_event = gtk_window_button_press_event;
587 widget_class->focus_out_event = gtk_window_focus_out_event;
588 widget_class->focus = gtk_window_focus;
589 widget_class->move_focus = gtk_window_move_focus;
590 widget_class->draw = gtk_window_draw;
591 widget_class->get_preferred_width = gtk_window_get_preferred_width;
592 widget_class->get_preferred_height = gtk_window_get_preferred_height;
593 widget_class->window_state_event = gtk_window_state_event;
594 widget_class->direction_changed = gtk_window_direction_changed;
595 widget_class->state_changed = gtk_window_state_changed;
596 widget_class->style_updated = gtk_window_style_updated;
598 container_class->check_resize = gtk_window_check_resize;
600 klass->set_focus = gtk_window_real_set_focus;
602 klass->activate_default = gtk_window_real_activate_default;
603 klass->activate_focus = gtk_window_real_activate_focus;
604 klass->keys_changed = gtk_window_keys_changed;
606 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
609 g_object_class_install_property (gobject_class,
611 g_param_spec_enum ("type",
613 P_("The type of the window"),
614 GTK_TYPE_WINDOW_TYPE,
616 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
618 g_object_class_install_property (gobject_class,
620 g_param_spec_string ("title",
622 P_("The title of the window"),
624 GTK_PARAM_READWRITE));
626 g_object_class_install_property (gobject_class,
628 g_param_spec_string ("role",
630 P_("Unique identifier for the window to be used when restoring a session"),
632 GTK_PARAM_READWRITE));
635 * GtkWindow:startup-id:
637 * The :startup-id is a write-only property for setting window's
638 * startup notification identifier. See gtk_window_set_startup_id()
643 g_object_class_install_property (gobject_class,
645 g_param_spec_string ("startup-id",
647 P_("Unique startup identifier for the window used by startup-notification"),
649 GTK_PARAM_WRITABLE));
651 g_object_class_install_property (gobject_class,
653 g_param_spec_boolean ("resizable",
655 P_("If TRUE, users can resize the window"),
657 GTK_PARAM_READWRITE));
659 g_object_class_install_property (gobject_class,
661 g_param_spec_boolean ("modal",
663 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
665 GTK_PARAM_READWRITE));
667 g_object_class_install_property (gobject_class,
669 g_param_spec_enum ("window-position",
670 P_("Window Position"),
671 P_("The initial position of the window"),
672 GTK_TYPE_WINDOW_POSITION,
674 GTK_PARAM_READWRITE));
676 g_object_class_install_property (gobject_class,
678 g_param_spec_int ("default-width",
680 P_("The default width of the window, used when initially showing the window"),
684 GTK_PARAM_READWRITE));
686 g_object_class_install_property (gobject_class,
688 g_param_spec_int ("default-height",
689 P_("Default Height"),
690 P_("The default height of the window, used when initially showing the window"),
694 GTK_PARAM_READWRITE));
696 g_object_class_install_property (gobject_class,
697 PROP_DESTROY_WITH_PARENT,
698 g_param_spec_boolean ("destroy-with-parent",
699 P_("Destroy with Parent"),
700 P_("If this window should be destroyed when the parent is destroyed"),
702 GTK_PARAM_READWRITE));
705 * GtkWindow:hide-titlebar-when-maximized:
707 * Whether the titlebar should be hidden during maximization.
711 g_object_class_install_property (gobject_class,
712 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
713 g_param_spec_boolean ("hide-titlebar-when-maximized",
714 P_("Hide the titlebar during maximization"),
715 P_("If this window's titlebar should be hidden when the window is maximized"),
717 GTK_PARAM_READWRITE));
719 g_object_class_install_property (gobject_class,
721 g_param_spec_object ("icon",
723 P_("Icon for this window"),
725 GTK_PARAM_READWRITE));
728 * GtkWindow:mnemonics-visible:
730 * Whether mnemonics are currently visible in this window.
732 * This property is maintained by GTK+ based on the
733 * #GtkSettings:gtk-auto-mnemonics setting and user input,
734 * and should not be set by applications.
738 g_object_class_install_property (gobject_class,
739 PROP_MNEMONICS_VISIBLE,
740 g_param_spec_boolean ("mnemonics-visible",
741 P_("Mnemonics Visible"),
742 P_("Whether mnemonics are currently visible in this window"),
744 GTK_PARAM_READWRITE));
747 * GtkWindow:focus-visible:
749 * Whether 'focus rectangles' are currently visible in this window.
751 * This property is maintained by GTK+ based on the
752 * #GtkSettings:gtk-visible-focus setting and user input
753 * and should not be set by applications.
757 g_object_class_install_property (gobject_class,
759 g_param_spec_boolean ("focus-visible",
761 P_("Whether focus rectangles are currently visible in this window"),
763 GTK_PARAM_READWRITE));
766 * GtkWindow:icon-name:
768 * The :icon-name property specifies the name of the themed icon to
769 * use as the window icon. See #GtkIconTheme for more details.
773 g_object_class_install_property (gobject_class,
775 g_param_spec_string ("icon-name",
777 P_("Name of the themed icon for this window"),
779 GTK_PARAM_READWRITE));
781 g_object_class_install_property (gobject_class,
783 g_param_spec_object ("screen",
785 P_("The screen where this window will be displayed"),
787 GTK_PARAM_READWRITE));
789 g_object_class_install_property (gobject_class,
791 g_param_spec_boolean ("is-active",
793 P_("Whether the toplevel is the current active window"),
795 GTK_PARAM_READABLE));
797 g_object_class_install_property (gobject_class,
798 PROP_HAS_TOPLEVEL_FOCUS,
799 g_param_spec_boolean ("has-toplevel-focus",
800 P_("Focus in Toplevel"),
801 P_("Whether the input focus is within this GtkWindow"),
803 GTK_PARAM_READABLE));
805 g_object_class_install_property (gobject_class,
807 g_param_spec_enum ("type-hint",
809 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
810 GDK_TYPE_WINDOW_TYPE_HINT,
811 GDK_WINDOW_TYPE_HINT_NORMAL,
812 GTK_PARAM_READWRITE));
814 g_object_class_install_property (gobject_class,
815 PROP_SKIP_TASKBAR_HINT,
816 g_param_spec_boolean ("skip-taskbar-hint",
818 P_("TRUE if the window should not be in the task bar."),
820 GTK_PARAM_READWRITE));
822 g_object_class_install_property (gobject_class,
823 PROP_SKIP_PAGER_HINT,
824 g_param_spec_boolean ("skip-pager-hint",
826 P_("TRUE if the window should not be in the pager."),
828 GTK_PARAM_READWRITE));
830 g_object_class_install_property (gobject_class,
832 g_param_spec_boolean ("urgency-hint",
834 P_("TRUE if the window should be brought to the user's attention."),
836 GTK_PARAM_READWRITE));
839 * GtkWindow:accept-focus:
841 * Whether the window should receive the input focus.
845 g_object_class_install_property (gobject_class,
847 g_param_spec_boolean ("accept-focus",
849 P_("TRUE if the window should receive the input focus."),
851 GTK_PARAM_READWRITE));
854 * GtkWindow:focus-on-map:
856 * Whether the window should receive the input focus when mapped.
860 g_object_class_install_property (gobject_class,
862 g_param_spec_boolean ("focus-on-map",
864 P_("TRUE if the window should receive the input focus when mapped."),
866 GTK_PARAM_READWRITE));
869 * GtkWindow:decorated:
871 * Whether the window should be decorated by the window manager.
875 g_object_class_install_property (gobject_class,
877 g_param_spec_boolean ("decorated",
879 P_("Whether the window should be decorated by the window manager"),
881 GTK_PARAM_READWRITE));
884 * GtkWindow:deletable:
886 * Whether the window frame should have a close button.
890 g_object_class_install_property (gobject_class,
892 g_param_spec_boolean ("deletable",
894 P_("Whether the window frame should have a close button"),
896 GTK_PARAM_READWRITE));
899 * GtkWindow:has-resize-grip
901 * Whether the window has a corner resize grip.
903 * Note that the resize grip is only shown if the window is
904 * actually resizable and not maximized. Use
905 * #GtkWindow:resize-grip-visible to find out if the resize
906 * grip is currently shown.
910 g_object_class_install_property (gobject_class,
911 PROP_HAS_RESIZE_GRIP,
912 g_param_spec_boolean ("has-resize-grip",
914 P_("Specifies whether the window should have a resize grip"),
916 GTK_PARAM_READWRITE));
919 * GtkWindow:resize-grip-visible:
921 * Whether a corner resize grip is currently shown.
925 g_object_class_install_property (gobject_class,
926 PROP_RESIZE_GRIP_VISIBLE,
927 g_param_spec_boolean ("resize-grip-visible",
928 P_("Resize grip is visible"),
929 P_("Specifies whether the window's resize grip is visible."),
931 GTK_PARAM_READABLE));
937 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
938 * more details about window gravity.
942 g_object_class_install_property (gobject_class,
944 g_param_spec_enum ("gravity",
946 P_("The window gravity of the window"),
948 GDK_GRAVITY_NORTH_WEST,
949 GTK_PARAM_READWRITE));
953 * GtkWindow:transient-for:
955 * The transient parent of the window. See gtk_window_set_transient_for() for
956 * more details about transient windows.
960 g_object_class_install_property (gobject_class,
962 g_param_spec_object ("transient-for",
963 P_("Transient for Window"),
964 P_("The transient parent of the dialog"),
966 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
971 * The requested opacity of the window. See gtk_window_set_opacity() for
972 * more details about window opacity.
976 g_object_class_install_property (gobject_class,
978 g_param_spec_double ("opacity",
979 P_("Opacity for Window"),
980 P_("The opacity of the window, from 0 to 1"),
984 GTK_PARAM_READWRITE));
988 gtk_widget_class_install_style_property (widget_class,
989 g_param_spec_int ("resize-grip-width",
990 P_("Width of resize grip"),
991 P_("Width of resize grip"),
992 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
994 gtk_widget_class_install_style_property (widget_class,
995 g_param_spec_int ("resize-grip-height",
996 P_("Height of resize grip"),
997 P_("Height of resize grip"),
998 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1002 * GtkWindow:application:
1004 * The #GtkApplication associated with the window.
1006 * The application will be kept alive for at least as long as it
1007 * has any windows associated with it (see g_application_hold()
1008 * for a way to keep it alive without windows).
1010 * Normally, the connection between the application and the window
1011 * will remain until the window is destroyed, but you can explicitly
1012 * remove it by setting the ::application property to %NULL.
1016 g_object_class_install_property (gobject_class,
1018 g_param_spec_object ("application",
1019 P_("GtkApplication"),
1020 P_("The GtkApplication for the window"),
1021 GTK_TYPE_APPLICATION,
1022 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1024 window_signals[SET_FOCUS] =
1025 g_signal_new (I_("set-focus"),
1026 G_TYPE_FROM_CLASS (gobject_class),
1028 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1030 _gtk_marshal_VOID__OBJECT,
1035 * GtkWindow::activate-focus:
1036 * @window: the window which received the signal
1038 * The ::activate-focus signal is a
1039 * <link linkend="keybinding-signals">keybinding signal</link>
1040 * which gets emitted when the user activates the currently
1041 * focused widget of @window.
1043 window_signals[ACTIVATE_FOCUS] =
1044 g_signal_new (I_("activate-focus"),
1045 G_TYPE_FROM_CLASS (gobject_class),
1046 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1047 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1049 _gtk_marshal_VOID__VOID,
1054 * GtkWindow::activate-default:
1055 * @window: the window which received the signal
1057 * The ::activate-default signal is a
1058 * <link linkend="keybinding-signals">keybinding signal</link>
1059 * which gets emitted when the user activates the default widget
1062 window_signals[ACTIVATE_DEFAULT] =
1063 g_signal_new (I_("activate-default"),
1064 G_TYPE_FROM_CLASS (gobject_class),
1065 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1066 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1068 _gtk_marshal_VOID__VOID,
1073 * GtkWindow::keys-changed:
1074 * @window: the window which received the signal
1076 * The ::keys-changed signal gets emitted when the set of accelerators
1077 * or mnemonics that are associated with @window changes.
1079 window_signals[KEYS_CHANGED] =
1080 g_signal_new (I_("keys-changed"),
1081 G_TYPE_FROM_CLASS (gobject_class),
1083 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1085 _gtk_marshal_VOID__VOID,
1093 binding_set = gtk_binding_set_by_class (klass);
1095 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1096 "activate-focus", 0);
1097 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1098 "activate-focus", 0);
1100 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1101 "activate-default", 0);
1102 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1103 "activate-default", 0);
1104 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1105 "activate-default", 0);
1107 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1108 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1109 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1110 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1112 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1113 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1114 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1115 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1117 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1121 gtk_window_init (GtkWindow *window)
1123 GtkWindowPrivate *priv;
1125 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1128 priv = window->priv;
1130 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1131 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1133 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1135 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1138 priv->wmclass_name = g_strdup (g_get_prgname ());
1139 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1140 priv->wm_role = NULL;
1141 priv->geometry_info = NULL;
1142 priv->type = GTK_WINDOW_TOPLEVEL;
1143 priv->focus_widget = NULL;
1144 priv->default_widget = NULL;
1145 priv->configure_request_count = 0;
1146 priv->resizable = TRUE;
1147 priv->configure_notify_received = FALSE;
1148 priv->position = GTK_WIN_POS_NONE;
1149 priv->need_default_size = TRUE;
1150 priv->need_default_position = TRUE;
1151 priv->modal = FALSE;
1152 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1153 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1154 priv->decorated = TRUE;
1155 priv->mnemonic_modifier = GDK_MOD1_MASK;
1156 priv->screen = gdk_screen_get_default ();
1158 priv->accept_focus = TRUE;
1159 priv->focus_on_map = TRUE;
1160 priv->deletable = TRUE;
1161 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1162 priv->opacity = 1.0;
1163 priv->startup_id = NULL;
1164 priv->initial_timestamp = GDK_CURRENT_TIME;
1165 priv->has_resize_grip = TRUE;
1166 priv->mnemonics_visible = TRUE;
1167 priv->focus_visible = TRUE;
1169 g_object_ref_sink (window);
1170 priv->has_user_ref_count = TRUE;
1171 toplevel_list = g_slist_prepend (toplevel_list, window);
1174 g_signal_connect (priv->screen, "composited-changed",
1175 G_CALLBACK (gtk_window_on_composited_changed), window);
1177 #ifdef GDK_WINDOWING_X11
1178 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1179 "notify::gtk-application-prefer-dark-theme",
1180 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1185 gtk_window_set_property (GObject *object,
1187 const GValue *value,
1190 GtkWindow *window = GTK_WINDOW (object);
1191 GtkWindowPrivate *priv = window->priv;
1196 priv->type = g_value_get_enum (value);
1199 gtk_window_set_title (window, g_value_get_string (value));
1202 gtk_window_set_role (window, g_value_get_string (value));
1204 case PROP_STARTUP_ID:
1205 gtk_window_set_startup_id (window, g_value_get_string (value));
1207 case PROP_RESIZABLE:
1208 gtk_window_set_resizable (window, g_value_get_boolean (value));
1211 gtk_window_set_modal (window, g_value_get_boolean (value));
1214 gtk_window_set_position (window, g_value_get_enum (value));
1216 case PROP_DEFAULT_WIDTH:
1217 gtk_window_set_default_size_internal (window,
1218 TRUE, g_value_get_int (value),
1221 case PROP_DEFAULT_HEIGHT:
1222 gtk_window_set_default_size_internal (window,
1224 TRUE, g_value_get_int (value), FALSE);
1226 case PROP_DESTROY_WITH_PARENT:
1227 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1229 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1230 gtk_window_set_hide_titlebar_when_maximized (window, g_value_get_boolean (value));
1233 gtk_window_set_icon (window,
1234 g_value_get_object (value));
1236 case PROP_ICON_NAME:
1237 gtk_window_set_icon_name (window, g_value_get_string (value));
1240 gtk_window_set_screen (window, g_value_get_object (value));
1242 case PROP_TYPE_HINT:
1243 gtk_window_set_type_hint (window,
1244 g_value_get_enum (value));
1246 case PROP_SKIP_TASKBAR_HINT:
1247 gtk_window_set_skip_taskbar_hint (window,
1248 g_value_get_boolean (value));
1250 case PROP_SKIP_PAGER_HINT:
1251 gtk_window_set_skip_pager_hint (window,
1252 g_value_get_boolean (value));
1254 case PROP_URGENCY_HINT:
1255 gtk_window_set_urgency_hint (window,
1256 g_value_get_boolean (value));
1258 case PROP_ACCEPT_FOCUS:
1259 gtk_window_set_accept_focus (window,
1260 g_value_get_boolean (value));
1262 case PROP_FOCUS_ON_MAP:
1263 gtk_window_set_focus_on_map (window,
1264 g_value_get_boolean (value));
1266 case PROP_DECORATED:
1267 gtk_window_set_decorated (window, g_value_get_boolean (value));
1269 case PROP_DELETABLE:
1270 gtk_window_set_deletable (window, g_value_get_boolean (value));
1273 gtk_window_set_gravity (window, g_value_get_enum (value));
1275 case PROP_TRANSIENT_FOR:
1276 gtk_window_set_transient_for (window, g_value_get_object (value));
1279 gtk_window_set_opacity (window, g_value_get_double (value));
1281 case PROP_HAS_RESIZE_GRIP:
1282 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1284 case PROP_APPLICATION:
1285 gtk_window_set_application (window, g_value_get_object (value));
1287 case PROP_MNEMONICS_VISIBLE:
1288 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1290 case PROP_FOCUS_VISIBLE:
1291 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1294 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1300 gtk_window_get_property (GObject *object,
1305 GtkWindow *window = GTK_WINDOW (object);
1306 GtkWindowPrivate *priv = window->priv;
1310 GtkWindowGeometryInfo *info;
1312 g_value_set_enum (value, priv->type);
1315 g_value_set_string (value, priv->wm_role);
1318 g_value_set_string (value, priv->title);
1320 case PROP_RESIZABLE:
1321 g_value_set_boolean (value, priv->resizable);
1324 g_value_set_boolean (value, priv->modal);
1327 g_value_set_enum (value, priv->position);
1329 case PROP_DEFAULT_WIDTH:
1330 info = gtk_window_get_geometry_info (window, FALSE);
1332 g_value_set_int (value, -1);
1334 g_value_set_int (value, info->default_width);
1336 case PROP_DEFAULT_HEIGHT:
1337 info = gtk_window_get_geometry_info (window, FALSE);
1339 g_value_set_int (value, -1);
1341 g_value_set_int (value, info->default_height);
1343 case PROP_DESTROY_WITH_PARENT:
1344 g_value_set_boolean (value, priv->destroy_with_parent);
1346 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1347 g_value_set_boolean (value, priv->hide_titlebar_when_maximized);
1350 g_value_set_object (value, gtk_window_get_icon (window));
1352 case PROP_ICON_NAME:
1353 g_value_set_string (value, gtk_window_get_icon_name (window));
1356 g_value_set_object (value, priv->screen);
1358 case PROP_IS_ACTIVE:
1359 g_value_set_boolean (value, priv->is_active);
1361 case PROP_HAS_TOPLEVEL_FOCUS:
1362 g_value_set_boolean (value, priv->has_toplevel_focus);
1364 case PROP_TYPE_HINT:
1365 g_value_set_enum (value, priv->type_hint);
1367 case PROP_SKIP_TASKBAR_HINT:
1368 g_value_set_boolean (value,
1369 gtk_window_get_skip_taskbar_hint (window));
1371 case PROP_SKIP_PAGER_HINT:
1372 g_value_set_boolean (value,
1373 gtk_window_get_skip_pager_hint (window));
1375 case PROP_URGENCY_HINT:
1376 g_value_set_boolean (value,
1377 gtk_window_get_urgency_hint (window));
1379 case PROP_ACCEPT_FOCUS:
1380 g_value_set_boolean (value,
1381 gtk_window_get_accept_focus (window));
1383 case PROP_FOCUS_ON_MAP:
1384 g_value_set_boolean (value,
1385 gtk_window_get_focus_on_map (window));
1387 case PROP_DECORATED:
1388 g_value_set_boolean (value, gtk_window_get_decorated (window));
1390 case PROP_DELETABLE:
1391 g_value_set_boolean (value, gtk_window_get_deletable (window));
1394 g_value_set_enum (value, gtk_window_get_gravity (window));
1396 case PROP_TRANSIENT_FOR:
1397 g_value_set_object (value, gtk_window_get_transient_for (window));
1400 g_value_set_double (value, gtk_window_get_opacity (window));
1402 case PROP_HAS_RESIZE_GRIP:
1403 g_value_set_boolean (value, priv->has_resize_grip);
1405 case PROP_RESIZE_GRIP_VISIBLE:
1406 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1408 case PROP_APPLICATION:
1409 g_value_set_object (value, gtk_window_get_application (window));
1411 case PROP_MNEMONICS_VISIBLE:
1412 g_value_set_boolean (value, priv->mnemonics_visible);
1414 case PROP_FOCUS_VISIBLE:
1415 g_value_set_boolean (value, priv->focus_visible);
1418 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1424 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1426 parent_buildable_iface = g_type_interface_peek_parent (iface);
1427 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1428 iface->parser_finished = gtk_window_buildable_parser_finished;
1429 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1430 iface->custom_finished = gtk_window_buildable_custom_finished;
1434 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1435 GtkBuilder *builder,
1437 const GValue *value)
1439 GtkWindow *window = GTK_WINDOW (buildable);
1440 GtkWindowPrivate *priv = window->priv;
1442 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1443 priv->builder_visible = TRUE;
1445 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1449 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1450 GtkBuilder *builder)
1452 GtkWindow *window = GTK_WINDOW (buildable);
1453 GtkWindowPrivate *priv = window->priv;
1457 if (priv->builder_visible)
1458 gtk_widget_show (GTK_WIDGET (buildable));
1460 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1461 for (l = accels; l; l = l->next)
1463 object = gtk_builder_get_object (builder, l->data);
1466 g_warning ("Unknown accel group %s specified in window %s",
1467 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1470 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1471 GTK_ACCEL_GROUP (object));
1475 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1477 parent_buildable_iface->parser_finished (buildable, builder);
1483 } GSListSubParserData;
1486 window_start_element (GMarkupParseContext *context,
1487 const gchar *element_name,
1488 const gchar **names,
1489 const gchar **values,
1494 GSListSubParserData *data = (GSListSubParserData*)user_data;
1496 if (strcmp (element_name, "group") == 0)
1498 for (i = 0; names[i]; i++)
1500 if (strcmp (names[i], "name") == 0)
1501 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1504 else if (strcmp (element_name, "accel-groups") == 0)
1507 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1512 static const GMarkupParser window_parser =
1514 window_start_element
1518 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1519 GtkBuilder *builder,
1521 const gchar *tagname,
1522 GMarkupParser *parser,
1525 GSListSubParserData *parser_data;
1527 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1528 tagname, parser, data))
1531 if (strcmp (tagname, "accel-groups") == 0)
1533 parser_data = g_slice_new0 (GSListSubParserData);
1534 parser_data->items = NULL;
1535 parser_data->object = G_OBJECT (buildable);
1537 *parser = window_parser;
1538 *data = parser_data;
1546 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1547 GtkBuilder *builder,
1549 const gchar *tagname,
1552 GSListSubParserData *data;
1554 parent_buildable_iface->custom_finished (buildable, builder, child,
1555 tagname, user_data);
1557 if (strcmp (tagname, "accel-groups") != 0)
1560 data = (GSListSubParserData*)user_data;
1562 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1563 data->items, (GDestroyNotify) g_slist_free);
1565 g_slice_free (GSListSubParserData, data);
1570 * @type: type of window
1572 * Creates a new #GtkWindow, which is a toplevel window that can
1573 * contain other widgets. Nearly always, the type of the window should
1574 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1575 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1576 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1577 * dialogs, though in some other toolkits dialogs are called "popups".
1578 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1579 * On X11, popup windows are not controlled by the <link
1580 * linkend="gtk-X11-arch">window manager</link>.
1582 * If you simply want an undecorated window (no window borders), use
1583 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1585 * Return value: a new #GtkWindow.
1588 gtk_window_new (GtkWindowType type)
1590 GtkWindowPrivate *priv;
1593 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1595 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1596 priv = window->priv;
1600 return GTK_WIDGET (window);
1604 * gtk_window_set_title:
1605 * @window: a #GtkWindow
1606 * @title: title of the window
1608 * Sets the title of the #GtkWindow. The title of a window will be
1609 * displayed in its title bar; on the X Window System, the title bar
1610 * is rendered by the <link linkend="gtk-X11-arch">window
1611 * manager</link>, so exactly how the title appears to users may vary
1612 * according to a user's exact configuration. The title should help a
1613 * user distinguish this window from other windows they may have
1614 * open. A good title might include the application name and current
1615 * document filename, for example.
1619 gtk_window_set_title (GtkWindow *window,
1622 GtkWindowPrivate *priv;
1626 g_return_if_fail (GTK_IS_WINDOW (window));
1628 priv = window->priv;
1629 widget = GTK_WIDGET (window);
1631 new_title = g_strdup (title);
1632 g_free (priv->title);
1633 priv->title = new_title;
1635 if (gtk_widget_get_realized (widget))
1637 gdk_window_set_title (gtk_widget_get_window (widget),
1641 g_object_notify (G_OBJECT (window), "title");
1645 * gtk_window_get_title:
1646 * @window: a #GtkWindow
1648 * Retrieves the title of the window. See gtk_window_set_title().
1650 * Return value: the title of the window, or %NULL if none has
1651 * been set explicitely. The returned string is owned by the widget
1652 * and must not be modified or freed.
1655 gtk_window_get_title (GtkWindow *window)
1657 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1659 return window->priv->title;
1663 * gtk_window_set_wmclass:
1664 * @window: a #GtkWindow
1665 * @wmclass_name: window name hint
1666 * @wmclass_class: window class hint
1668 * Don't use this function. It sets the X Window System "class" and
1669 * "name" hints for a window. According to the ICCCM, you should
1670 * always set these to the same value for all windows in an
1671 * application, and GTK+ sets them to that value by default, so calling
1672 * this function is sort of pointless. However, you may want to call
1673 * gtk_window_set_role() on each window in your application, for the
1674 * benefit of the session manager. Setting the role allows the window
1675 * manager to restore window positions when loading a saved session.
1679 gtk_window_set_wmclass (GtkWindow *window,
1680 const gchar *wmclass_name,
1681 const gchar *wmclass_class)
1683 GtkWindowPrivate *priv;
1685 g_return_if_fail (GTK_IS_WINDOW (window));
1687 priv = window->priv;
1689 g_free (priv->wmclass_name);
1690 priv->wmclass_name = g_strdup (wmclass_name);
1692 g_free (priv->wmclass_class);
1693 priv->wmclass_class = g_strdup (wmclass_class);
1695 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1696 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1700 * gtk_window_set_role:
1701 * @window: a #GtkWindow
1702 * @role: unique identifier for the window to be used when restoring a session
1704 * This function is only useful on X11, not with other GTK+ targets.
1706 * In combination with the window title, the window role allows a
1707 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1708 * same" window when an application is restarted. So for example you
1709 * might set the "toolbox" role on your app's toolbox window, so that
1710 * when the user restarts their session, the window manager can put
1711 * the toolbox back in the same place.
1713 * If a window already has a unique title, you don't need to set the
1714 * role, since the WM can use the title to identify the window when
1715 * restoring the session.
1719 gtk_window_set_role (GtkWindow *window,
1722 GtkWindowPrivate *priv;
1725 g_return_if_fail (GTK_IS_WINDOW (window));
1727 priv = window->priv;
1729 new_role = g_strdup (role);
1730 g_free (priv->wm_role);
1731 priv->wm_role = new_role;
1733 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1734 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1737 g_object_notify (G_OBJECT (window), "role");
1741 * gtk_window_set_startup_id:
1742 * @window: a #GtkWindow
1743 * @startup_id: a string with startup-notification identifier
1745 * Startup notification identifiers are used by desktop environment to
1746 * track application startup, to provide user feedback and other
1747 * features. This function changes the corresponding property on the
1748 * underlying GdkWindow. Normally, startup identifier is managed
1749 * automatically and you should only use this function in special cases
1750 * like transferring focus from other processes. You should use this
1751 * function before calling gtk_window_present() or any equivalent
1752 * function generating a window map event.
1754 * This function is only useful on X11, not with other GTK+ targets.
1759 gtk_window_set_startup_id (GtkWindow *window,
1760 const gchar *startup_id)
1762 GtkWindowPrivate *priv;
1765 g_return_if_fail (GTK_IS_WINDOW (window));
1767 priv = window->priv;
1768 widget = GTK_WIDGET (window);
1770 g_free (priv->startup_id);
1771 priv->startup_id = g_strdup (startup_id);
1773 if (gtk_widget_get_realized (widget))
1775 GdkWindow *gdk_window;
1776 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1778 gdk_window = gtk_widget_get_window (widget);
1780 #ifdef GDK_WINDOWING_X11
1781 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1782 gdk_x11_window_set_user_time (gdk_window, timestamp);
1785 /* Here we differentiate real and "fake" startup notification IDs,
1786 * constructed on purpose just to pass interaction timestamp
1788 if (startup_id_is_fake (priv->startup_id))
1789 gtk_window_present_with_time (window, timestamp);
1792 gdk_window_set_startup_id (gdk_window,
1795 /* If window is mapped, terminate the startup-notification too */
1796 if (gtk_widget_get_mapped (widget) &&
1797 !disable_startup_notification)
1798 gdk_notify_startup_complete_with_id (priv->startup_id);
1802 g_object_notify (G_OBJECT (window), "startup-id");
1806 * gtk_window_get_role:
1807 * @window: a #GtkWindow
1809 * Returns the role of the window. See gtk_window_set_role() for
1810 * further explanation.
1812 * Return value: the role of the window if set, or %NULL. The
1813 * returned is owned by the widget and must not be modified
1817 gtk_window_get_role (GtkWindow *window)
1819 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1821 return window->priv->wm_role;
1825 * gtk_window_set_focus:
1826 * @window: a #GtkWindow
1827 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1828 * any focus widget for the toplevel window.
1830 * If @focus is not the current focus widget, and is focusable, sets
1831 * it as the focus widget for the window. If @focus is %NULL, unsets
1832 * the focus widget for this window. To set the focus to a particular
1833 * widget in the toplevel, it is usually more convenient to use
1834 * gtk_widget_grab_focus() instead of this function.
1837 gtk_window_set_focus (GtkWindow *window,
1840 GtkWindowPrivate *priv;
1843 g_return_if_fail (GTK_IS_WINDOW (window));
1845 priv = window->priv;
1849 g_return_if_fail (GTK_IS_WIDGET (focus));
1850 g_return_if_fail (gtk_widget_get_can_focus (focus));
1854 gtk_widget_grab_focus (focus);
1857 /* Clear the existing focus chain, so that when we focus into
1858 * the window again, we start at the beginnning.
1860 GtkWidget *widget = priv->focus_widget;
1863 while ((parent = gtk_widget_get_parent (widget)))
1866 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1870 _gtk_window_internal_set_focus (window, NULL);
1875 _gtk_window_internal_set_focus (GtkWindow *window,
1878 GtkWindowPrivate *priv;
1880 g_return_if_fail (GTK_IS_WINDOW (window));
1882 priv = window->priv;
1884 if ((priv->focus_widget != focus) ||
1885 (focus && !gtk_widget_has_focus (focus)))
1886 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1890 * gtk_window_set_default:
1891 * @window: a #GtkWindow
1892 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1893 * default widget for the toplevel.
1895 * The default widget is the widget that's activated when the user
1896 * presses Enter in a dialog (for example). This function sets or
1897 * unsets the default widget for a #GtkWindow about. When setting
1898 * (rather than unsetting) the default widget it's generally easier to
1899 * call gtk_widget_grab_focus() on the widget. Before making a widget
1900 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1901 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1904 gtk_window_set_default (GtkWindow *window,
1905 GtkWidget *default_widget)
1907 GtkWindowPrivate *priv;
1909 g_return_if_fail (GTK_IS_WINDOW (window));
1911 priv = window->priv;
1914 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1916 if (priv->default_widget != default_widget)
1918 GtkWidget *old_default_widget = NULL;
1921 g_object_ref (default_widget);
1923 if (priv->default_widget)
1925 old_default_widget = priv->default_widget;
1927 if (priv->focus_widget != priv->default_widget ||
1928 !gtk_widget_get_receives_default (priv->default_widget))
1929 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1931 gtk_widget_queue_draw (priv->default_widget);
1934 priv->default_widget = default_widget;
1936 if (priv->default_widget)
1938 if (priv->focus_widget == NULL ||
1939 !gtk_widget_get_receives_default (priv->focus_widget))
1940 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1942 gtk_widget_queue_draw (priv->default_widget);
1945 if (old_default_widget)
1946 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1950 g_object_notify (G_OBJECT (default_widget), "has-default");
1951 g_object_unref (default_widget);
1957 * gtk_window_get_default_widget:
1958 * @window: a #GtkWindow
1960 * Returns the default widget for @window. See gtk_window_set_default()
1963 * Returns: (transfer none): the default widget, or %NULL if there is none.
1968 gtk_window_get_default_widget (GtkWindow *window)
1970 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1972 return window->priv->default_widget;
1976 handle_keys_changed (gpointer data)
1978 GtkWindow *window = GTK_WINDOW (data);
1979 GtkWindowPrivate *priv = window->priv;
1981 if (priv->keys_changed_handler)
1983 g_source_remove (priv->keys_changed_handler);
1984 priv->keys_changed_handler = 0;
1987 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1993 gtk_window_notify_keys_changed (GtkWindow *window)
1995 GtkWindowPrivate *priv = window->priv;
1997 if (!priv->keys_changed_handler)
1998 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
2002 * gtk_window_add_accel_group:
2003 * @window: window to attach accelerator group to
2004 * @accel_group: a #GtkAccelGroup
2006 * Associate @accel_group with @window, such that calling
2007 * gtk_accel_groups_activate() on @window will activate accelerators
2011 gtk_window_add_accel_group (GtkWindow *window,
2012 GtkAccelGroup *accel_group)
2014 g_return_if_fail (GTK_IS_WINDOW (window));
2015 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2017 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
2018 g_signal_connect_object (accel_group, "accel-changed",
2019 G_CALLBACK (gtk_window_notify_keys_changed),
2020 window, G_CONNECT_SWAPPED);
2021 gtk_window_notify_keys_changed (window);
2025 * gtk_window_remove_accel_group:
2026 * @window: a #GtkWindow
2027 * @accel_group: a #GtkAccelGroup
2029 * Reverses the effects of gtk_window_add_accel_group().
2032 gtk_window_remove_accel_group (GtkWindow *window,
2033 GtkAccelGroup *accel_group)
2035 g_return_if_fail (GTK_IS_WINDOW (window));
2036 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2038 g_signal_handlers_disconnect_by_func (accel_group,
2039 gtk_window_notify_keys_changed,
2041 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2042 gtk_window_notify_keys_changed (window);
2045 static GtkMnemonicHash *
2046 gtk_window_get_mnemonic_hash (GtkWindow *window,
2049 GtkWindowPrivate *private = window->priv;
2051 if (!private->mnemonic_hash && create)
2052 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2054 return private->mnemonic_hash;
2058 * gtk_window_add_mnemonic:
2059 * @window: a #GtkWindow
2060 * @keyval: the mnemonic
2061 * @target: the widget that gets activated by the mnemonic
2063 * Adds a mnemonic to this window.
2066 gtk_window_add_mnemonic (GtkWindow *window,
2070 g_return_if_fail (GTK_IS_WINDOW (window));
2071 g_return_if_fail (GTK_IS_WIDGET (target));
2073 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2075 gtk_window_notify_keys_changed (window);
2079 * gtk_window_remove_mnemonic:
2080 * @window: a #GtkWindow
2081 * @keyval: the mnemonic
2082 * @target: the widget that gets activated by the mnemonic
2084 * Removes a mnemonic from this window.
2087 gtk_window_remove_mnemonic (GtkWindow *window,
2091 g_return_if_fail (GTK_IS_WINDOW (window));
2092 g_return_if_fail (GTK_IS_WIDGET (target));
2094 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2096 gtk_window_notify_keys_changed (window);
2100 * gtk_window_mnemonic_activate:
2101 * @window: a #GtkWindow
2102 * @keyval: the mnemonic
2103 * @modifier: the modifiers
2105 * Activates the targets associated with the mnemonic.
2107 * Returns: %TRUE if the activation is done.
2110 gtk_window_mnemonic_activate (GtkWindow *window,
2112 GdkModifierType modifier)
2114 GtkWindowPrivate *priv;
2116 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2118 priv = window->priv;
2120 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2122 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2124 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2131 * gtk_window_set_mnemonic_modifier:
2132 * @window: a #GtkWindow
2133 * @modifier: the modifier mask used to activate
2134 * mnemonics on this window.
2136 * Sets the mnemonic modifier for this window.
2139 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2140 GdkModifierType modifier)
2142 GtkWindowPrivate *priv;
2144 g_return_if_fail (GTK_IS_WINDOW (window));
2145 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2147 priv = window->priv;
2149 priv->mnemonic_modifier = modifier;
2150 gtk_window_notify_keys_changed (window);
2154 * gtk_window_get_mnemonic_modifier:
2155 * @window: a #GtkWindow
2157 * Returns the mnemonic modifier for this window. See
2158 * gtk_window_set_mnemonic_modifier().
2160 * Return value: the modifier mask used to activate
2161 * mnemonics on this window.
2164 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2166 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2168 return window->priv->mnemonic_modifier;
2172 * gtk_window_set_position:
2173 * @window: a #GtkWindow.
2174 * @position: a position constraint.
2176 * Sets a position constraint for this window. If the old or new
2177 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2178 * the window to be repositioned to satisfy the new constraint.
2181 gtk_window_set_position (GtkWindow *window,
2182 GtkWindowPosition position)
2184 GtkWindowPrivate *priv;
2186 g_return_if_fail (GTK_IS_WINDOW (window));
2188 priv = window->priv;
2190 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2191 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2193 GtkWindowGeometryInfo *info;
2195 info = gtk_window_get_geometry_info (window, TRUE);
2197 /* this flag causes us to re-request the CENTER_ALWAYS
2198 * constraint in gtk_window_move_resize(), see
2199 * comment in that function.
2201 info->position_constraints_changed = TRUE;
2203 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2206 priv->position = position;
2208 g_object_notify (G_OBJECT (window), "window-position");
2212 * gtk_window_activate_focus:
2213 * @window: a #GtkWindow
2215 * Activates the current focused widget within the window.
2217 * Return value: %TRUE if a widget got activated.
2220 gtk_window_activate_focus (GtkWindow *window)
2222 GtkWindowPrivate *priv;
2224 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2226 priv = window->priv;
2228 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2229 return gtk_widget_activate (priv->focus_widget);
2235 * gtk_window_get_focus:
2236 * @window: a #GtkWindow
2238 * Retrieves the current focused widget within the window.
2239 * Note that this is the widget that would have the focus
2240 * if the toplevel window focused; if the toplevel window
2241 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2242 * not be %TRUE for the widget.
2244 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2247 gtk_window_get_focus (GtkWindow *window)
2249 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2251 return window->priv->focus_widget;
2255 * gtk_window_activate_default:
2256 * @window: a #GtkWindow
2258 * Activates the default widget for the window, unless the current
2259 * focused widget has been configured to receive the default action
2260 * (see gtk_widget_set_receives_default()), in which case the
2261 * focused widget is activated.
2263 * Return value: %TRUE if a widget got activated.
2266 gtk_window_activate_default (GtkWindow *window)
2268 GtkWindowPrivate *priv;
2270 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2272 priv = window->priv;
2274 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2275 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2276 return gtk_widget_activate (priv->default_widget);
2277 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2278 return gtk_widget_activate (priv->focus_widget);
2284 * gtk_window_set_modal:
2285 * @window: a #GtkWindow
2286 * @modal: whether the window is modal
2288 * Sets a window modal or non-modal. Modal windows prevent interaction
2289 * with other windows in the same application. To keep modal dialogs
2290 * on top of main application windows, use
2291 * gtk_window_set_transient_for() to make the dialog transient for the
2292 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2293 * will then disallow lowering the dialog below the parent.
2298 gtk_window_set_modal (GtkWindow *window,
2301 GtkWindowPrivate *priv;
2304 g_return_if_fail (GTK_IS_WINDOW (window));
2306 priv = window->priv;
2308 modal = modal != FALSE;
2309 if (priv->modal == modal)
2312 priv->modal = modal;
2313 widget = GTK_WIDGET (window);
2315 /* adjust desired modality state */
2316 if (gtk_widget_get_realized (widget))
2319 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2321 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2324 if (gtk_widget_get_visible (widget))
2327 gtk_grab_add (widget);
2329 gtk_grab_remove (widget);
2332 g_object_notify (G_OBJECT (window), "modal");
2336 * gtk_window_get_modal:
2337 * @window: a #GtkWindow
2339 * Returns whether the window is modal. See gtk_window_set_modal().
2341 * Return value: %TRUE if the window is set to be modal and
2342 * establishes a grab when shown
2345 gtk_window_get_modal (GtkWindow *window)
2347 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2349 return window->priv->modal;
2353 * gtk_window_list_toplevels:
2355 * Returns a list of all existing toplevel windows. The widgets
2356 * in the list are not individually referenced. If you want
2357 * to iterate through the list and perform actions involving
2358 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2359 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2360 * then unref all the widgets afterwards.
2362 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2365 gtk_window_list_toplevels (void)
2370 for (slist = toplevel_list; slist; slist = slist->next)
2371 list = g_list_prepend (list, slist->data);
2377 gtk_window_dispose (GObject *object)
2379 GtkWindow *window = GTK_WINDOW (object);
2381 gtk_window_set_focus (window, NULL);
2382 gtk_window_set_default (window, NULL);
2384 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2388 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2390 gtk_widget_destroy (GTK_WIDGET (child));
2394 connect_parent_destroyed (GtkWindow *window)
2396 GtkWindowPrivate *priv = window->priv;
2398 if (priv->transient_parent)
2400 g_signal_connect (priv->transient_parent,
2402 G_CALLBACK (parent_destroyed_callback),
2408 disconnect_parent_destroyed (GtkWindow *window)
2410 GtkWindowPrivate *priv = window->priv;
2412 if (priv->transient_parent)
2414 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2415 parent_destroyed_callback,
2421 gtk_window_transient_parent_realized (GtkWidget *parent,
2424 if (gtk_widget_get_realized (window))
2425 gdk_window_set_transient_for (gtk_widget_get_window (window),
2426 gtk_widget_get_window (parent));
2430 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2433 if (gtk_widget_get_realized (window))
2434 gdk_property_delete (gtk_widget_get_window (window),
2435 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2439 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2443 gtk_window_set_screen (window, parent->priv->screen);
2447 gtk_window_unset_transient_for (GtkWindow *window)
2449 GtkWindowPrivate *priv = window->priv;
2451 if (priv->transient_parent)
2453 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2454 gtk_window_transient_parent_realized,
2456 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2457 gtk_window_transient_parent_unrealized,
2459 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2460 gtk_window_transient_parent_screen_changed,
2462 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2463 gtk_widget_destroyed,
2464 &priv->transient_parent);
2466 if (priv->destroy_with_parent)
2467 disconnect_parent_destroyed (window);
2469 priv->transient_parent = NULL;
2471 if (priv->transient_parent_group)
2473 priv->transient_parent_group = FALSE;
2474 gtk_window_group_remove_window (priv->group,
2481 * gtk_window_set_transient_for:
2482 * @window: a #GtkWindow
2483 * @parent: (allow-none): parent window, or %NULL
2485 * Dialog windows should be set transient for the main application
2486 * window they were spawned from. This allows <link
2487 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2488 * dialog on top of the main window, or center the dialog over the
2489 * main window. gtk_dialog_new_with_buttons() and other convenience
2490 * functions in GTK+ will sometimes call
2491 * gtk_window_set_transient_for() on your behalf.
2493 * Passing %NULL for @parent unsets the current transient window.
2495 * On Windows, this function puts the child window on top of the parent,
2496 * much as the window manager would have done on X.
2499 gtk_window_set_transient_for (GtkWindow *window,
2502 GtkWindowPrivate *priv;
2504 g_return_if_fail (GTK_IS_WINDOW (window));
2505 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2506 g_return_if_fail (window != parent);
2508 priv = window->priv;
2510 if (priv->transient_parent)
2512 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2513 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2514 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2515 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2516 GTK_WIDGET (window));
2518 gtk_window_unset_transient_for (window);
2521 priv->transient_parent = parent;
2525 g_signal_connect (parent, "destroy",
2526 G_CALLBACK (gtk_widget_destroyed),
2527 &priv->transient_parent);
2528 g_signal_connect (parent, "realize",
2529 G_CALLBACK (gtk_window_transient_parent_realized),
2531 g_signal_connect (parent, "unrealize",
2532 G_CALLBACK (gtk_window_transient_parent_unrealized),
2534 g_signal_connect (parent, "notify::screen",
2535 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2538 gtk_window_set_screen (window, parent->priv->screen);
2540 if (priv->destroy_with_parent)
2541 connect_parent_destroyed (window);
2543 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2544 gtk_widget_get_realized (GTK_WIDGET (parent)))
2545 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2546 GTK_WIDGET (window));
2548 if (parent->priv->group)
2550 gtk_window_group_add_window (parent->priv->group, window);
2551 priv->transient_parent_group = TRUE;
2557 * gtk_window_get_transient_for:
2558 * @window: a #GtkWindow
2560 * Fetches the transient parent for this window. See
2561 * gtk_window_set_transient_for().
2563 * Return value: (transfer none): the transient parent for this window, or %NULL
2564 * if no transient parent has been set.
2567 gtk_window_get_transient_for (GtkWindow *window)
2569 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2571 return window->priv->transient_parent;
2575 * gtk_window_set_opacity:
2576 * @window: a #GtkWindow
2577 * @opacity: desired opacity, between 0 and 1
2579 * Request the windowing system to make @window partially transparent,
2580 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2581 * of the opacity parameter are clamped to the [0,1] range.) On X11
2582 * this has any effect only on X screens with a compositing manager
2583 * running. See gtk_widget_is_composited(). On Windows it should work
2586 * Note that setting a window's opacity after the window has been
2587 * shown causes it to flicker once on Windows.
2592 gtk_window_set_opacity (GtkWindow *window,
2595 GtkWindowPrivate *priv;
2597 g_return_if_fail (GTK_IS_WINDOW (window));
2599 priv = window->priv;
2603 else if (opacity > 1.0)
2606 priv->opacity_set = TRUE;
2607 priv->opacity = opacity;
2609 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2610 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2615 * gtk_window_get_opacity:
2616 * @window: a #GtkWindow
2618 * Fetches the requested opacity for this window. See
2619 * gtk_window_set_opacity().
2621 * Return value: the requested opacity for this window.
2626 gtk_window_get_opacity (GtkWindow *window)
2628 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2630 return window->priv->opacity;
2634 * gtk_window_get_application:
2635 * @window: a #GtkWindow
2637 * Gets the #GtkApplication associated with the window (if any).
2639 * Return value: (transfer none): a #GtkApplication, or %NULL
2644 gtk_window_get_application (GtkWindow *window)
2646 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2648 return window->priv->application;
2652 gtk_window_release_application (GtkWindow *window)
2654 if (window->priv->application)
2656 GtkApplication *application;
2658 /* steal reference into temp variable */
2659 application = window->priv->application;
2660 window->priv->application = NULL;
2662 gtk_application_remove_window (application, window);
2663 g_object_unref (application);
2668 * gtk_window_set_application:
2669 * @window: a #GtkWindow
2670 * @application: (allow-none): a #GtkApplication, or %NULL
2672 * Sets or unsets the #GtkApplication associated with the window.
2674 * The application will be kept alive for at least as long as the window
2680 gtk_window_set_application (GtkWindow *window,
2681 GtkApplication *application)
2683 GtkWindowPrivate *priv;
2685 g_return_if_fail (GTK_IS_WINDOW (window));
2687 priv = window->priv;
2688 if (priv->application != application)
2690 gtk_window_release_application (window);
2692 priv->application = application;
2694 if (priv->application != NULL)
2696 g_object_ref (priv->application);
2698 gtk_application_add_window (priv->application, window);
2701 g_object_notify (G_OBJECT (window), "application");
2706 * gtk_window_set_type_hint:
2707 * @window: a #GtkWindow
2708 * @hint: the window type
2710 * By setting the type hint for the window, you allow the window
2711 * manager to decorate and handle the window in a way which is
2712 * suitable to the function of the window in your application.
2714 * This function should be called before the window becomes visible.
2716 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2717 * will sometimes call gtk_window_set_type_hint() on your behalf.
2721 gtk_window_set_type_hint (GtkWindow *window,
2722 GdkWindowTypeHint hint)
2724 GtkWindowPrivate *priv;
2726 g_return_if_fail (GTK_IS_WINDOW (window));
2727 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2729 priv = window->priv;
2731 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2732 priv->type_hint = hint;
2734 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2736 priv->reset_type_hint = TRUE;
2737 priv->gdk_type_hint = hint;
2741 * gtk_window_get_type_hint:
2742 * @window: a #GtkWindow
2744 * Gets the type hint for this window. See gtk_window_set_type_hint().
2746 * Return value: the type hint for @window.
2749 gtk_window_get_type_hint (GtkWindow *window)
2751 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2753 return window->priv->gdk_type_hint;
2757 * gtk_window_set_skip_taskbar_hint:
2758 * @window: a #GtkWindow
2759 * @setting: %TRUE to keep this window from appearing in the task bar
2761 * Windows may set a hint asking the desktop environment not to display
2762 * the window in the task bar. This function sets this hint.
2767 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2770 GtkWindowPrivate *priv;
2772 g_return_if_fail (GTK_IS_WINDOW (window));
2774 priv = window->priv;
2776 setting = setting != FALSE;
2778 if (priv->skips_taskbar != setting)
2780 priv->skips_taskbar = setting;
2781 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2782 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2783 priv->skips_taskbar);
2784 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2789 * gtk_window_get_skip_taskbar_hint:
2790 * @window: a #GtkWindow
2792 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2794 * Return value: %TRUE if window shouldn't be in taskbar
2799 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2801 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2803 return window->priv->skips_taskbar;
2807 * gtk_window_set_skip_pager_hint:
2808 * @window: a #GtkWindow
2809 * @setting: %TRUE to keep this window from appearing in the pager
2811 * Windows may set a hint asking the desktop environment not to display
2812 * the window in the pager. This function sets this hint.
2813 * (A "pager" is any desktop navigation tool such as a workspace
2814 * switcher that displays a thumbnail representation of the windows
2820 gtk_window_set_skip_pager_hint (GtkWindow *window,
2823 GtkWindowPrivate *priv;
2825 g_return_if_fail (GTK_IS_WINDOW (window));
2827 priv = window->priv;
2829 setting = setting != FALSE;
2831 if (priv->skips_pager != setting)
2833 priv->skips_pager = setting;
2834 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2835 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2837 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2842 * gtk_window_get_skip_pager_hint:
2843 * @window: a #GtkWindow
2845 * Gets the value set by gtk_window_set_skip_pager_hint().
2847 * Return value: %TRUE if window shouldn't be in pager
2852 gtk_window_get_skip_pager_hint (GtkWindow *window)
2854 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2856 return window->priv->skips_pager;
2860 * gtk_window_set_urgency_hint:
2861 * @window: a #GtkWindow
2862 * @setting: %TRUE to mark this window as urgent
2864 * Windows may set a hint asking the desktop environment to draw
2865 * the users attention to the window. This function sets this hint.
2870 gtk_window_set_urgency_hint (GtkWindow *window,
2873 GtkWindowPrivate *priv;
2875 g_return_if_fail (GTK_IS_WINDOW (window));
2877 priv = window->priv;
2879 setting = setting != FALSE;
2881 if (priv->urgent != setting)
2883 priv->urgent = setting;
2884 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2885 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2887 g_object_notify (G_OBJECT (window), "urgency-hint");
2892 * gtk_window_get_urgency_hint:
2893 * @window: a #GtkWindow
2895 * Gets the value set by gtk_window_set_urgency_hint()
2897 * Return value: %TRUE if window is urgent
2902 gtk_window_get_urgency_hint (GtkWindow *window)
2904 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2906 return window->priv->urgent;
2910 * gtk_window_set_accept_focus:
2911 * @window: a #GtkWindow
2912 * @setting: %TRUE to let this window receive input focus
2914 * Windows may set a hint asking the desktop environment not to receive
2915 * the input focus. This function sets this hint.
2920 gtk_window_set_accept_focus (GtkWindow *window,
2923 GtkWindowPrivate *priv;
2925 g_return_if_fail (GTK_IS_WINDOW (window));
2927 priv = window->priv;
2929 setting = setting != FALSE;
2931 if (priv->accept_focus != setting)
2933 priv->accept_focus = setting;
2934 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2935 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2936 priv->accept_focus);
2937 g_object_notify (G_OBJECT (window), "accept-focus");
2942 * gtk_window_get_accept_focus:
2943 * @window: a #GtkWindow
2945 * Gets the value set by gtk_window_set_accept_focus().
2947 * Return value: %TRUE if window should receive the input focus
2952 gtk_window_get_accept_focus (GtkWindow *window)
2954 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2956 return window->priv->accept_focus;
2960 * gtk_window_set_focus_on_map:
2961 * @window: a #GtkWindow
2962 * @setting: %TRUE to let this window receive input focus on map
2964 * Windows may set a hint asking the desktop environment not to receive
2965 * the input focus when the window is mapped. This function sets this
2971 gtk_window_set_focus_on_map (GtkWindow *window,
2974 GtkWindowPrivate *priv;
2976 g_return_if_fail (GTK_IS_WINDOW (window));
2978 priv = window->priv;
2980 setting = setting != FALSE;
2982 if (priv->focus_on_map != setting)
2984 priv->focus_on_map = setting;
2985 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2986 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2987 priv->focus_on_map);
2988 g_object_notify (G_OBJECT (window), "focus-on-map");
2993 * gtk_window_get_focus_on_map:
2994 * @window: a #GtkWindow
2996 * Gets the value set by gtk_window_set_focus_on_map().
2998 * Return value: %TRUE if window should receive the input focus when
3004 gtk_window_get_focus_on_map (GtkWindow *window)
3006 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3008 return window->priv->focus_on_map;
3012 * gtk_window_set_destroy_with_parent:
3013 * @window: a #GtkWindow
3014 * @setting: whether to destroy @window with its transient parent
3016 * If @setting is %TRUE, then destroying the transient parent of @window
3017 * will also destroy @window itself. This is useful for dialogs that
3018 * shouldn't persist beyond the lifetime of the main window they're
3019 * associated with, for example.
3022 gtk_window_set_destroy_with_parent (GtkWindow *window,
3025 GtkWindowPrivate *priv;
3027 g_return_if_fail (GTK_IS_WINDOW (window));
3029 priv = window->priv;
3031 if (priv->destroy_with_parent == (setting != FALSE))
3034 if (priv->destroy_with_parent)
3036 disconnect_parent_destroyed (window);
3040 connect_parent_destroyed (window);
3043 priv->destroy_with_parent = setting;
3045 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3049 * gtk_window_get_destroy_with_parent:
3050 * @window: a #GtkWindow
3052 * Returns whether the window will be destroyed with its transient parent. See
3053 * gtk_window_set_destroy_with_parent ().
3055 * Return value: %TRUE if the window will be destroyed with its transient parent.
3058 gtk_window_get_destroy_with_parent (GtkWindow *window)
3060 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3062 return window->priv->destroy_with_parent;
3066 * gtk_window_set_hide_titlebar_when_maximized:
3067 * @window: a #GtkWindow
3068 * @setting: whether to hide the titlebar when @window is maximized
3070 * If @setting is %TRUE, then @window will request that it's titlebar
3071 * should be hidden when maximized.
3072 * This is useful for windows that don't convey any information other
3073 * than the application name in the titlebar, to put the available
3074 * screen space to better use. If the underlying window system does not
3075 * support the request, the setting will not have any effect.
3080 gtk_window_set_hide_titlebar_when_maximized (GtkWindow *window,
3083 g_return_if_fail (GTK_IS_WINDOW (window));
3085 #ifdef GDK_WINDOWING_X11
3087 GdkWindow *gdk_window;
3089 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3091 if (GDK_IS_X11_WINDOW (gdk_window))
3092 gdk_x11_window_set_hide_titlebar_when_maximized (gdk_window, setting);
3096 window->priv->hide_titlebar_when_maximized = setting;
3097 g_object_notify (G_OBJECT (window), "hide-titlebar-when-maximized");
3101 * gtk_window_get_hide_titlebar_when_maximized:
3102 * @window: a #GtkWindow
3104 * Returns whether the window has requested to have its titlebar hidden
3105 * when maximized. See gtk_window_set_hide_titlebar_when_maximized ().
3107 * Return value: %TRUE if the window has requested to have its titlebar
3108 * hidden when maximized
3113 gtk_window_get_hide_titlebar_when_maximized (GtkWindow *window)
3115 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3117 return window->priv->hide_titlebar_when_maximized;
3120 static GtkWindowGeometryInfo*
3121 gtk_window_get_geometry_info (GtkWindow *window,
3124 GtkWindowPrivate *priv = window->priv;
3125 GtkWindowGeometryInfo *info;
3127 info = priv->geometry_info;
3128 if (!info && create)
3130 info = g_new0 (GtkWindowGeometryInfo, 1);
3132 info->default_width = -1;
3133 info->default_height = -1;
3134 info->resize_width = -1;
3135 info->resize_height = -1;
3136 info->initial_x = 0;
3137 info->initial_y = 0;
3138 info->initial_pos_set = FALSE;
3139 info->default_is_geometry = FALSE;
3140 info->position_constraints_changed = FALSE;
3141 info->last.configure_request.x = 0;
3142 info->last.configure_request.y = 0;
3143 info->last.configure_request.width = -1;
3144 info->last.configure_request.height = -1;
3145 info->widget = NULL;
3147 priv->geometry_info = info;
3154 * gtk_window_set_geometry_hints:
3155 * @window: a #GtkWindow
3156 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3157 * @geometry: (allow-none): struct containing geometry information or %NULL
3158 * @geom_mask: mask indicating which struct fields should be paid attention to
3160 * This function sets up hints about how a window can be resized by
3161 * the user. You can set a minimum and maximum size; allowed resize
3162 * increments (e.g. for xterm, you can only resize by the size of a
3163 * character); aspect ratios; and more. See the #GdkGeometry struct.
3167 gtk_window_set_geometry_hints (GtkWindow *window,
3168 GtkWidget *geometry_widget,
3169 GdkGeometry *geometry,
3170 GdkWindowHints geom_mask)
3172 GtkWindowGeometryInfo *info;
3174 g_return_if_fail (GTK_IS_WINDOW (window));
3175 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3177 info = gtk_window_get_geometry_info (window, TRUE);
3180 g_signal_handlers_disconnect_by_func (info->widget,
3181 gtk_widget_destroyed,
3184 info->widget = geometry_widget;
3186 g_signal_connect (geometry_widget, "destroy",
3187 G_CALLBACK (gtk_widget_destroyed),
3191 info->geometry = *geometry;
3193 /* We store gravity in priv->gravity not in the hints. */
3194 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3196 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3198 gtk_window_set_gravity (window, geometry->win_gravity);
3201 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3205 * gtk_window_set_decorated:
3206 * @window: a #GtkWindow
3207 * @setting: %TRUE to decorate the window
3209 * By default, windows are decorated with a title bar, resize
3210 * controls, etc. Some <link linkend="gtk-X11-arch">window
3211 * managers</link> allow GTK+ to disable these decorations, creating a
3212 * borderless window. If you set the decorated property to %FALSE
3213 * using this function, GTK+ will do its best to convince the window
3214 * manager not to decorate the window. Depending on the system, this
3215 * function may not have any effect when called on a window that is
3216 * already visible, so you should call it before calling gtk_widget_show().
3218 * On Windows, this function always works, since there's no window manager
3223 gtk_window_set_decorated (GtkWindow *window,
3226 GtkWindowPrivate *priv;
3227 GdkWindow *gdk_window;
3229 g_return_if_fail (GTK_IS_WINDOW (window));
3231 priv = window->priv;
3233 setting = setting != FALSE;
3235 if (setting == priv->decorated)
3238 priv->decorated = setting;
3240 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3243 if (priv->decorated)
3244 gdk_window_set_decorations (gdk_window,
3247 gdk_window_set_decorations (gdk_window,
3251 g_object_notify (G_OBJECT (window), "decorated");
3255 * gtk_window_get_decorated:
3256 * @window: a #GtkWindow
3258 * Returns whether the window has been set to have decorations
3259 * such as a title bar via gtk_window_set_decorated().
3261 * Return value: %TRUE if the window has been set to have decorations
3264 gtk_window_get_decorated (GtkWindow *window)
3266 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3268 return window->priv->decorated;
3272 * gtk_window_set_deletable:
3273 * @window: a #GtkWindow
3274 * @setting: %TRUE to decorate the window as deletable
3276 * By default, windows have a close button in the window frame. Some
3277 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3278 * disable this button. If you set the deletable property to %FALSE
3279 * using this function, GTK+ will do its best to convince the window
3280 * manager not to show a close button. Depending on the system, this
3281 * function may not have any effect when called on a window that is
3282 * already visible, so you should call it before calling gtk_window_show().
3284 * On Windows, this function always works, since there's no window manager
3290 gtk_window_set_deletable (GtkWindow *window,
3293 GtkWindowPrivate *priv;
3294 GdkWindow *gdk_window;
3296 g_return_if_fail (GTK_IS_WINDOW (window));
3298 priv = window->priv;
3300 setting = setting != FALSE;
3302 if (setting == priv->deletable)
3305 priv->deletable = setting;
3307 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3310 if (priv->deletable)
3311 gdk_window_set_functions (gdk_window,
3314 gdk_window_set_functions (gdk_window,
3315 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3318 g_object_notify (G_OBJECT (window), "deletable");
3322 * gtk_window_get_deletable:
3323 * @window: a #GtkWindow
3325 * Returns whether the window has been set to have a close button
3326 * via gtk_window_set_deletable().
3328 * Return value: %TRUE if the window has been set to have a close button
3333 gtk_window_get_deletable (GtkWindow *window)
3335 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3337 return window->priv->deletable;
3340 static GtkWindowIconInfo*
3341 get_icon_info (GtkWindow *window)
3343 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3347 free_icon_info (GtkWindowIconInfo *info)
3349 g_free (info->icon_name);
3350 g_slice_free (GtkWindowIconInfo, info);
3354 static GtkWindowIconInfo*
3355 ensure_icon_info (GtkWindow *window)
3357 GtkWindowIconInfo *info;
3359 info = get_icon_info (window);
3363 info = g_slice_new0 (GtkWindowIconInfo);
3364 g_object_set_qdata_full (G_OBJECT (window),
3365 quark_gtk_window_icon_info,
3367 (GDestroyNotify)free_icon_info);
3374 icon_list_from_theme (GtkWidget *widget,
3379 GtkIconTheme *icon_theme;
3384 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3386 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3389 for (i = 0; sizes[i]; i++)
3392 * We need an EWMH extension to handle scalable icons
3393 * by passing their name to the WM. For now just use a
3397 icon = gtk_icon_theme_load_icon (icon_theme, name,
3400 icon = gtk_icon_theme_load_icon (icon_theme, name,
3403 list = g_list_append (list, icon);
3413 gtk_window_realize_icon (GtkWindow *window)
3415 GtkWindowPrivate *priv = window->priv;
3417 GtkWindowIconInfo *info;
3418 GdkWindow *gdk_window;
3421 widget = GTK_WIDGET (window);
3422 gdk_window = gtk_widget_get_window (widget);
3424 g_return_if_fail (gdk_window != NULL);
3426 /* no point setting an icon on override-redirect */
3427 if (priv->type == GTK_WINDOW_POPUP)
3432 info = ensure_icon_info (window);
3437 info->using_default_icon = FALSE;
3438 info->using_parent_icon = FALSE;
3439 info->using_themed_icon = FALSE;
3441 icon_list = info->icon_list;
3443 /* Look up themed icon */
3444 if (icon_list == NULL && info->icon_name)
3446 icon_list = icon_list_from_theme (widget, info->icon_name);
3448 info->using_themed_icon = TRUE;
3451 /* Inherit from transient parent */
3452 if (icon_list == NULL && priv->transient_parent)
3454 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3456 info->using_parent_icon = TRUE;
3459 /* Inherit from default */
3460 if (icon_list == NULL)
3462 icon_list = default_icon_list;
3464 info->using_default_icon = TRUE;
3467 /* Look up themed icon */
3468 if (icon_list == NULL && default_icon_name)
3470 icon_list = icon_list_from_theme (widget, default_icon_name);
3471 info->using_default_icon = TRUE;
3472 info->using_themed_icon = TRUE;
3475 info->realized = TRUE;
3477 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3479 if (info->using_themed_icon)
3481 GtkIconTheme *icon_theme;
3483 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3484 g_list_free (icon_list);
3486 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3487 g_signal_connect (icon_theme, "changed",
3488 G_CALLBACK (update_themed_icon), window);
3493 gtk_window_unrealize_icon (GtkWindow *window)
3495 GtkWindowIconInfo *info;
3497 info = get_icon_info (window);
3502 if (info->using_themed_icon)
3504 GtkIconTheme *icon_theme;
3506 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3508 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3511 /* We don't clear the properties on the window, just figure the
3512 * window is going away.
3515 info->realized = FALSE;
3520 * gtk_window_set_icon_list:
3521 * @window: a #GtkWindow
3522 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3524 * Sets up the icon representing a #GtkWindow. The icon is used when
3525 * the window is minimized (also known as iconified). Some window
3526 * managers or desktop environments may also place it in the window
3527 * frame, or display it in other contexts.
3529 * gtk_window_set_icon_list() allows you to pass in the same icon in
3530 * several hand-drawn sizes. The list should contain the natural sizes
3531 * your icon is available in; that is, don't scale the image before
3532 * passing it to GTK+. Scaling is postponed until the last minute,
3533 * when the desired final size is known, to allow best quality.
3535 * By passing several sizes, you may improve the final image quality
3536 * of the icon, by reducing or eliminating automatic image scaling.
3538 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3539 * larger images (64x64, 128x128) if you have them.
3541 * See also gtk_window_set_default_icon_list() to set the icon
3542 * for all windows in your application in one go.
3544 * Note that transient windows (those who have been set transient for another
3545 * window using gtk_window_set_transient_for()) will inherit their
3546 * icon from their transient parent. So there's no need to explicitly
3547 * set the icon on transient windows.
3550 gtk_window_set_icon_list (GtkWindow *window,
3553 GtkWindowIconInfo *info;
3555 g_return_if_fail (GTK_IS_WINDOW (window));
3557 info = ensure_icon_info (window);
3559 if (info->icon_list == list) /* check for NULL mostly */
3562 g_list_foreach (list,
3563 (GFunc) g_object_ref, NULL);
3565 g_list_foreach (info->icon_list,
3566 (GFunc) g_object_unref, NULL);
3568 g_list_free (info->icon_list);
3570 info->icon_list = g_list_copy (list);
3572 g_object_notify (G_OBJECT (window), "icon");
3574 gtk_window_unrealize_icon (window);
3576 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3577 gtk_window_realize_icon (window);
3579 /* We could try to update our transient children, but I don't think
3580 * it's really worth it. If we did it, the best way would probably
3581 * be to have children connect to notify::icon-list
3586 * gtk_window_get_icon_list:
3587 * @window: a #GtkWindow
3589 * Retrieves the list of icons set by gtk_window_set_icon_list().
3590 * The list is copied, but the reference count on each
3591 * member won't be incremented.
3593 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3596 gtk_window_get_icon_list (GtkWindow *window)
3598 GtkWindowIconInfo *info;
3600 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3602 info = get_icon_info (window);
3605 return g_list_copy (info->icon_list);
3611 * gtk_window_set_icon:
3612 * @window: a #GtkWindow
3613 * @icon: (allow-none): icon image, or %NULL
3615 * Sets up the icon representing a #GtkWindow. This icon is used when
3616 * the window is minimized (also known as iconified). Some window
3617 * managers or desktop environments may also place it in the window
3618 * frame, or display it in other contexts.
3620 * The icon should be provided in whatever size it was naturally
3621 * drawn; that is, don't scale the image before passing it to
3622 * GTK+. Scaling is postponed until the last minute, when the desired
3623 * final size is known, to allow best quality.
3625 * If you have your icon hand-drawn in multiple sizes, use
3626 * gtk_window_set_icon_list(). Then the best size will be used.
3628 * This function is equivalent to calling gtk_window_set_icon_list()
3629 * with a 1-element list.
3631 * See also gtk_window_set_default_icon_list() to set the icon
3632 * for all windows in your application in one go.
3635 gtk_window_set_icon (GtkWindow *window,
3640 g_return_if_fail (GTK_IS_WINDOW (window));
3641 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3646 list = g_list_append (list, icon);
3648 gtk_window_set_icon_list (window, list);
3654 update_themed_icon (GtkIconTheme *icon_theme,
3657 g_object_notify (G_OBJECT (window), "icon");
3659 gtk_window_unrealize_icon (window);
3661 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3662 gtk_window_realize_icon (window);
3666 * gtk_window_set_icon_name:
3667 * @window: a #GtkWindow
3668 * @name: (allow-none): the name of the themed icon
3670 * Sets the icon for the window from a named themed icon. See
3671 * the docs for #GtkIconTheme for more details.
3673 * Note that this has nothing to do with the WM_ICON_NAME
3674 * property which is mentioned in the ICCCM.
3679 gtk_window_set_icon_name (GtkWindow *window,
3682 GtkWindowIconInfo *info;
3685 g_return_if_fail (GTK_IS_WINDOW (window));
3687 info = ensure_icon_info (window);
3689 if (g_strcmp0 (info->icon_name, name) == 0)
3692 tmp = info->icon_name;
3693 info->icon_name = g_strdup (name);
3696 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3697 g_list_free (info->icon_list);
3698 info->icon_list = NULL;
3700 update_themed_icon (NULL, window);
3702 g_object_notify (G_OBJECT (window), "icon-name");
3706 * gtk_window_get_icon_name:
3707 * @window: a #GtkWindow
3709 * Returns the name of the themed icon for the window,
3710 * see gtk_window_set_icon_name().
3712 * Returns: the icon name or %NULL if the window has
3718 gtk_window_get_icon_name (GtkWindow *window)
3720 GtkWindowIconInfo *info;
3722 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3724 info = ensure_icon_info (window);
3726 return info->icon_name;
3730 * gtk_window_get_icon:
3731 * @window: a #GtkWindow
3733 * Gets the value set by gtk_window_set_icon() (or if you've
3734 * called gtk_window_set_icon_list(), gets the first icon in
3737 * Return value: (transfer none): icon for window
3740 gtk_window_get_icon (GtkWindow *window)
3742 GtkWindowIconInfo *info;
3744 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3746 info = get_icon_info (window);
3747 if (info && info->icon_list)
3748 return GDK_PIXBUF (info->icon_list->data);
3753 /* Load pixbuf, printing warning on failure if error == NULL
3756 load_pixbuf_verbosely (const char *filename,
3759 GError *local_err = NULL;
3762 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3770 g_warning ("Error loading icon from file '%s':\n\t%s",
3771 filename, local_err->message);
3772 g_error_free (local_err);
3780 * gtk_window_set_icon_from_file:
3781 * @window: a #GtkWindow
3782 * @filename: (type filename): location of icon file
3783 * @err: (allow-none): location to store error, or %NULL.
3785 * Sets the icon for @window.
3786 * Warns on failure if @err is %NULL.
3788 * This function is equivalent to calling gtk_window_set_icon()
3789 * with a pixbuf created by loading the image from @filename.
3791 * Returns: %TRUE if setting the icon succeeded.
3796 gtk_window_set_icon_from_file (GtkWindow *window,
3797 const gchar *filename,
3800 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3804 gtk_window_set_icon (window, pixbuf);
3805 g_object_unref (pixbuf);
3814 * gtk_window_set_default_icon_list:
3815 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3817 * Sets an icon list to be used as fallback for windows that haven't
3818 * had gtk_window_set_icon_list() called on them to set up a
3819 * window-specific icon list. This function allows you to set up the
3820 * icon for all windows in your app at once.
3822 * See gtk_window_set_icon_list() for more details.
3826 gtk_window_set_default_icon_list (GList *list)
3830 if (list == default_icon_list)
3833 /* Update serial so we don't used cached pixmaps/masks
3835 default_icon_serial++;
3837 g_list_foreach (list,
3838 (GFunc) g_object_ref, NULL);
3840 g_list_foreach (default_icon_list,
3841 (GFunc) g_object_unref, NULL);
3843 g_list_free (default_icon_list);
3845 default_icon_list = g_list_copy (list);
3847 /* Update all toplevels */
3848 toplevels = gtk_window_list_toplevels ();
3849 tmp_list = toplevels;
3850 while (tmp_list != NULL)
3852 GtkWindowIconInfo *info;
3853 GtkWindow *w = tmp_list->data;
3855 info = get_icon_info (w);
3856 if (info && info->using_default_icon)
3858 gtk_window_unrealize_icon (w);
3859 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3860 gtk_window_realize_icon (w);
3863 tmp_list = tmp_list->next;
3865 g_list_free (toplevels);
3869 * gtk_window_set_default_icon:
3872 * Sets an icon to be used as fallback for windows that haven't
3873 * had gtk_window_set_icon() called on them from a pixbuf.
3878 gtk_window_set_default_icon (GdkPixbuf *icon)
3882 g_return_if_fail (GDK_IS_PIXBUF (icon));
3884 list = g_list_prepend (NULL, icon);
3885 gtk_window_set_default_icon_list (list);
3890 * gtk_window_set_default_icon_name:
3891 * @name: the name of the themed icon
3893 * Sets an icon to be used as fallback for windows that haven't
3894 * had gtk_window_set_icon_list() called on them from a named
3895 * themed icon, see gtk_window_set_icon_name().
3900 gtk_window_set_default_icon_name (const gchar *name)
3905 /* Update serial so we don't used cached pixmaps/masks
3907 default_icon_serial++;
3909 g_free (default_icon_name);
3910 default_icon_name = g_strdup (name);
3912 g_list_foreach (default_icon_list,
3913 (GFunc) g_object_unref, NULL);
3915 g_list_free (default_icon_list);
3916 default_icon_list = NULL;
3918 /* Update all toplevels */
3919 toplevels = gtk_window_list_toplevels ();
3920 tmp_list = toplevels;
3921 while (tmp_list != NULL)
3923 GtkWindowIconInfo *info;
3924 GtkWindow *w = tmp_list->data;
3926 info = get_icon_info (w);
3927 if (info && info->using_default_icon && info->using_themed_icon)
3929 gtk_window_unrealize_icon (w);
3930 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3931 gtk_window_realize_icon (w);
3934 tmp_list = tmp_list->next;
3936 g_list_free (toplevels);
3940 * gtk_window_get_default_icon_name:
3942 * Returns the fallback icon name for windows that has been set
3943 * with gtk_window_set_default_icon_name(). The returned
3944 * string is owned by GTK+ and should not be modified. It
3945 * is only valid until the next call to
3946 * gtk_window_set_default_icon_name().
3948 * Returns: the fallback icon name for windows
3953 gtk_window_get_default_icon_name (void)
3955 return default_icon_name;
3959 * gtk_window_set_default_icon_from_file:
3960 * @filename: (type filename): location of icon file
3961 * @err: (allow-none): location to store error, or %NULL.
3963 * Sets an icon to be used as fallback for windows that haven't
3964 * had gtk_window_set_icon_list() called on them from a file
3965 * on disk. Warns on failure if @err is %NULL.
3967 * Returns: %TRUE if setting the icon succeeded.
3972 gtk_window_set_default_icon_from_file (const gchar *filename,
3975 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3979 gtk_window_set_default_icon (pixbuf);
3980 g_object_unref (pixbuf);
3989 * gtk_window_get_default_icon_list:
3991 * Gets the value set by gtk_window_set_default_icon_list().
3992 * The list is a copy and should be freed with g_list_free(),
3993 * but the pixbufs in the list have not had their reference count
3996 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3999 gtk_window_get_default_icon_list (void)
4001 return g_list_copy (default_icon_list);
4005 gtk_window_set_default_size_internal (GtkWindow *window,
4006 gboolean change_width,
4008 gboolean change_height,
4010 gboolean is_geometry)
4012 GtkWindowGeometryInfo *info;
4014 g_return_if_fail (change_width == FALSE || width >= -1);
4015 g_return_if_fail (change_height == FALSE || height >= -1);
4017 info = gtk_window_get_geometry_info (window, TRUE);
4019 g_object_freeze_notify (G_OBJECT (window));
4021 info->default_is_geometry = is_geometry != FALSE;
4031 info->default_width = width;
4033 g_object_notify (G_OBJECT (window), "default-width");
4044 info->default_height = height;
4046 g_object_notify (G_OBJECT (window), "default-height");
4049 g_object_thaw_notify (G_OBJECT (window));
4051 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4055 * gtk_window_set_default_size:
4056 * @window: a #GtkWindow
4057 * @width: width in pixels, or -1 to unset the default width
4058 * @height: height in pixels, or -1 to unset the default height
4060 * Sets the default size of a window. If the window's "natural" size
4061 * (its size request) is larger than the default, the default will be
4062 * ignored. More generally, if the default size does not obey the
4063 * geometry hints for the window (gtk_window_set_geometry_hints() can
4064 * be used to set these explicitly), the default size will be clamped
4065 * to the nearest permitted size.
4067 * Unlike gtk_widget_set_size_request(), which sets a size request for
4068 * a widget and thus would keep users from shrinking the window, this
4069 * function only sets the initial size, just as if the user had
4070 * resized the window themselves. Users can still shrink the window
4071 * again as they normally would. Setting a default size of -1 means to
4072 * use the "natural" default size (the size request of the window).
4074 * For more control over a window's initial size and how resizing works,
4075 * investigate gtk_window_set_geometry_hints().
4077 * For some uses, gtk_window_resize() is a more appropriate function.
4078 * gtk_window_resize() changes the current size of the window, rather
4079 * than the size to be used on initial display. gtk_window_resize() always
4080 * affects the window itself, not the geometry widget.
4082 * The default size of a window only affects the first time a window is
4083 * shown; if a window is hidden and re-shown, it will remember the size
4084 * it had prior to hiding, rather than using the default size.
4086 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4087 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4090 gtk_window_set_default_size (GtkWindow *window,
4094 g_return_if_fail (GTK_IS_WINDOW (window));
4095 g_return_if_fail (width >= -1);
4096 g_return_if_fail (height >= -1);
4098 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4102 * gtk_window_set_default_geometry:
4103 * @window: a #GtkWindow
4104 * @width: width in resize increments, or -1 to unset the default width
4105 * @height: height in resize increments, or -1 to unset the default height
4107 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4108 * in terms of the base size and increment set with
4109 * gtk_window_set_geometry_hints.
4114 gtk_window_set_default_geometry (GtkWindow *window,
4118 g_return_if_fail (GTK_IS_WINDOW (window));
4119 g_return_if_fail (width >= -1);
4120 g_return_if_fail (height >= -1);
4122 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4126 * gtk_window_get_default_size:
4127 * @window: a #GtkWindow
4128 * @width: (out) (allow-none): location to store the default width, or %NULL
4129 * @height: (out) (allow-none): location to store the default height, or %NULL
4131 * Gets the default size of the window. A value of -1 for the width or
4132 * height indicates that a default size has not been explicitly set
4133 * for that dimension, so the "natural" size of the window will be
4138 gtk_window_get_default_size (GtkWindow *window,
4142 GtkWindowGeometryInfo *info;
4144 g_return_if_fail (GTK_IS_WINDOW (window));
4146 info = gtk_window_get_geometry_info (window, FALSE);
4149 *width = info ? info->default_width : -1;
4152 *height = info ? info->default_height : -1;
4156 * gtk_window_resize:
4157 * @window: a #GtkWindow
4158 * @width: width in pixels to resize the window to
4159 * @height: height in pixels to resize the window to
4161 * Resizes the window as if the user had done so, obeying geometry
4162 * constraints. The default geometry constraint is that windows may
4163 * not be smaller than their size request; to override this
4164 * constraint, call gtk_widget_set_size_request() to set the window's
4165 * request to a smaller value.
4167 * If gtk_window_resize() is called before showing a window for the
4168 * first time, it overrides any default size set with
4169 * gtk_window_set_default_size().
4171 * Windows may not be resized smaller than 1 by 1 pixels.
4175 gtk_window_resize (GtkWindow *window,
4179 GtkWindowGeometryInfo *info;
4181 g_return_if_fail (GTK_IS_WINDOW (window));
4182 g_return_if_fail (width > 0);
4183 g_return_if_fail (height > 0);
4185 info = gtk_window_get_geometry_info (window, TRUE);
4187 info->resize_width = width;
4188 info->resize_height = height;
4189 info->resize_is_geometry = FALSE;
4191 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4195 * gtk_window_resize_to_geometry:
4196 * @window: a #GtkWindow
4197 * @width: width in resize increments to resize the window to
4198 * @height: height in resize increments to resize the window to
4200 * Like gtk_window_resize(), but @width and @height are interpreted
4201 * in terms of the base size and increment set with
4202 * gtk_window_set_geometry_hints.
4207 gtk_window_resize_to_geometry (GtkWindow *window,
4211 GtkWindowGeometryInfo *info;
4213 g_return_if_fail (GTK_IS_WINDOW (window));
4214 g_return_if_fail (width > 0);
4215 g_return_if_fail (height > 0);
4217 info = gtk_window_get_geometry_info (window, TRUE);
4219 info->resize_width = width;
4220 info->resize_height = height;
4221 info->resize_is_geometry = TRUE;
4223 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4227 * gtk_window_get_size:
4228 * @window: a #GtkWindow
4229 * @width: (out) (allow-none): return location for width, or %NULL
4230 * @height: (out) (allow-none): return location for height, or %NULL
4232 * Obtains the current size of @window. If @window is not onscreen,
4233 * it returns the size GTK+ will suggest to the <link
4234 * linkend="gtk-X11-arch">window manager</link> for the initial window
4235 * size (but this is not reliably the same as the size the window
4236 * manager will actually select). The size obtained by
4237 * gtk_window_get_size() is the last size received in a
4238 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4239 * rather than querying the X server for the size. As a result, if you
4240 * call gtk_window_resize() then immediately call
4241 * gtk_window_get_size(), the size won't have taken effect yet. After
4242 * the window manager processes the resize request, GTK+ receives
4243 * notification that the size has changed via a configure event, and
4244 * the size of the window gets updated.
4246 * Note 1: Nearly any use of this function creates a race condition,
4247 * because the size of the window may change between the time that you
4248 * get the size and the time that you perform some action assuming
4249 * that size is the current size. To avoid race conditions, connect to
4250 * "configure-event" on the window and adjust your size-dependent
4251 * state to match the size delivered in the #GdkEventConfigure.
4253 * Note 2: The returned size does <emphasis>not</emphasis> include the
4254 * size of the window manager decorations (aka the window frame or
4255 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4256 * method of determining their size.
4258 * Note 3: If you are getting a window size in order to position
4259 * the window onscreen, there may be a better way. The preferred
4260 * way is to simply set the window's semantic type with
4261 * gtk_window_set_type_hint(), which allows the window manager to
4262 * e.g. center dialogs. Also, if you set the transient parent of
4263 * dialogs with gtk_window_set_transient_for() window managers
4264 * will often center the dialog over its parent window. It's
4265 * much preferred to let the window manager handle these
4266 * things rather than doing it yourself, because all apps will
4267 * behave consistently and according to user prefs if the window
4268 * manager handles it. Also, the window manager can take the size
4269 * of the window decorations/border into account, while your
4270 * application cannot.
4272 * In any case, if you insist on application-specified window
4273 * positioning, there's <emphasis>still</emphasis> a better way than
4274 * doing it yourself - gtk_window_set_position() will frequently
4275 * handle the details for you.
4279 gtk_window_get_size (GtkWindow *window,
4285 g_return_if_fail (GTK_IS_WINDOW (window));
4287 if (width == NULL && height == NULL)
4290 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4292 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4293 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4297 GdkRectangle configure_request;
4299 gtk_window_compute_configure_request (window,
4303 w = configure_request.width;
4304 h = configure_request.height;
4315 * @window: a #GtkWindow
4316 * @x: X coordinate to move window to
4317 * @y: Y coordinate to move window to
4319 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4320 * @window to the given position. Window managers are free to ignore
4321 * this; most window managers ignore requests for initial window
4322 * positions (instead using a user-defined placement algorithm) and
4323 * honor requests after the window has already been shown.
4325 * Note: the position is the position of the gravity-determined
4326 * reference point for the window. The gravity determines two things:
4327 * first, the location of the reference point in root window
4328 * coordinates; and second, which point on the window is positioned at
4329 * the reference point.
4331 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4332 * point is simply the @x, @y supplied to gtk_window_move(). The
4333 * top-left corner of the window decorations (aka window frame or
4334 * border) will be placed at @x, @y. Therefore, to position a window
4335 * at the top left of the screen, you want to use the default gravity
4336 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4338 * To position a window at the bottom right corner of the screen, you
4339 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4340 * point is at @x + the window width and @y + the window height, and
4341 * the bottom-right corner of the window border will be placed at that
4342 * reference point. So, to place a window in the bottom right corner
4343 * you would first set gravity to south east, then write:
4344 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4345 * gdk_screen_height () - window_height)</literal> (note that this
4346 * example does not take multi-head scenarios into account).
4348 * The Extended Window Manager Hints specification at <ulink
4349 * url="http://www.freedesktop.org/Standards/wm-spec">
4350 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4351 * nice table of gravities in the "implementation notes" section.
4353 * The gtk_window_get_position() documentation may also be relevant.
4356 gtk_window_move (GtkWindow *window,
4360 GtkWindowGeometryInfo *info;
4363 g_return_if_fail (GTK_IS_WINDOW (window));
4365 widget = GTK_WIDGET (window);
4367 info = gtk_window_get_geometry_info (window, TRUE);
4369 if (gtk_widget_get_mapped (widget))
4371 GtkAllocation allocation;
4373 gtk_widget_get_allocation (widget, &allocation);
4375 /* we have now sent a request with this position
4376 * with currently-active constraints, so toggle flag.
4378 info->position_constraints_changed = FALSE;
4380 /* we only constrain if mapped - if not mapped,
4381 * then gtk_window_compute_configure_request()
4382 * will apply the constraints later, and we
4383 * don't want to lose information about
4384 * what position the user set before then.
4385 * i.e. if you do a move() then turn off POS_CENTER
4386 * then show the window, your move() will work.
4388 gtk_window_constrain_position (window,
4389 allocation.width, allocation.height,
4392 /* Note that this request doesn't go through our standard request
4393 * framework, e.g. doesn't increment configure_request_count,
4394 * doesn't set info->last, etc.; that's because
4395 * we don't save the info needed to arrive at this same request
4398 * To gtk_window_move_resize(), this will end up looking exactly
4399 * the same as the position being changed by the window
4402 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4406 /* Save this position to apply on mapping */
4407 info->initial_x = x;
4408 info->initial_y = y;
4409 info->initial_pos_set = TRUE;
4414 * gtk_window_get_position:
4415 * @window: a #GtkWindow
4416 * @root_x: (out) (allow-none): eturn location for X coordinate of
4417 * gravity-determined reference point, or %NULL
4418 * @root_y: (out) (allow-none): return location for Y coordinate of
4419 * gravity-determined reference point, or %NULL
4421 * This function returns the position you need to pass to
4422 * gtk_window_move() to keep @window in its current position.
4423 * This means that the meaning of the returned value varies with
4424 * window gravity. See gtk_window_move() for more details.
4426 * If you haven't changed the window gravity, its gravity will be
4427 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4428 * gets the position of the top-left corner of the window manager
4429 * frame for the window. gtk_window_move() sets the position of this
4430 * same top-left corner.
4432 * gtk_window_get_position() is not 100% reliable because the X Window System
4433 * does not specify a way to obtain the geometry of the
4434 * decorations placed on a window by the window manager.
4435 * Thus GTK+ is using a "best guess" that works with most
4438 * Moreover, nearly all window managers are historically broken with
4439 * respect to their handling of window gravity. So moving a window to
4440 * its current position as returned by gtk_window_get_position() tends
4441 * to result in moving the window slightly. Window managers are
4442 * slowly getting better over time.
4444 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4445 * frame is not relevant, and thus gtk_window_get_position() will
4446 * always produce accurate results. However you can't use static
4447 * gravity to do things like place a window in a corner of the screen,
4448 * because static gravity ignores the window manager decorations.
4450 * If you are saving and restoring your application's window
4451 * positions, you should know that it's impossible for applications to
4452 * do this without getting it somewhat wrong because applications do
4453 * not have sufficient knowledge of window manager state. The Correct
4454 * Mechanism is to support the session management protocol (see the
4455 * "GnomeClient" object in the GNOME libraries for example) and allow
4456 * the window manager to save your window sizes and positions.
4461 gtk_window_get_position (GtkWindow *window,
4465 GtkWindowPrivate *priv;
4467 GdkWindow *gdk_window;
4469 g_return_if_fail (GTK_IS_WINDOW (window));
4471 priv = window->priv;
4472 widget = GTK_WIDGET (window);
4473 gdk_window = gtk_widget_get_window (widget);
4475 if (priv->gravity == GDK_GRAVITY_STATIC)
4477 if (gtk_widget_get_mapped (widget))
4479 /* This does a server round-trip, which is sort of wrong;
4480 * but a server round-trip is inevitable for
4481 * gdk_window_get_frame_extents() in the usual
4482 * NorthWestGravity case below, so not sure what else to
4483 * do. We should likely be consistent about whether we get
4484 * the client-side info or the server-side info.
4486 gdk_window_get_origin (gdk_window, root_x, root_y);
4490 GdkRectangle configure_request;
4492 gtk_window_compute_configure_request (window,
4496 *root_x = configure_request.x;
4497 *root_y = configure_request.y;
4502 GdkRectangle frame_extents;
4507 if (gtk_widget_get_mapped (widget))
4509 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4510 x = frame_extents.x;
4511 y = frame_extents.y;
4512 gtk_window_get_size (window, &w, &h);
4516 /* We just say the frame has 0 size on all sides.
4517 * Not sure what else to do.
4519 gtk_window_compute_configure_request (window,
4522 x = frame_extents.x;
4523 y = frame_extents.y;
4524 w = frame_extents.width;
4525 h = frame_extents.height;
4528 switch (priv->gravity)
4530 case GDK_GRAVITY_NORTH:
4531 case GDK_GRAVITY_CENTER:
4532 case GDK_GRAVITY_SOUTH:
4533 /* Find center of frame. */
4534 x += frame_extents.width / 2;
4535 /* Center client window on that point. */
4539 case GDK_GRAVITY_SOUTH_EAST:
4540 case GDK_GRAVITY_EAST:
4541 case GDK_GRAVITY_NORTH_EAST:
4542 /* Find right edge of frame */
4543 x += frame_extents.width;
4544 /* Align left edge of client at that point. */
4551 switch (priv->gravity)
4553 case GDK_GRAVITY_WEST:
4554 case GDK_GRAVITY_CENTER:
4555 case GDK_GRAVITY_EAST:
4556 /* Find center of frame. */
4557 y += frame_extents.height / 2;
4558 /* Center client window there. */
4561 case GDK_GRAVITY_SOUTH_WEST:
4562 case GDK_GRAVITY_SOUTH:
4563 case GDK_GRAVITY_SOUTH_EAST:
4564 /* Find south edge of frame */
4565 y += frame_extents.height;
4566 /* Place bottom edge of client there */
4581 * gtk_window_reshow_with_initial_size:
4582 * @window: a #GtkWindow
4584 * Hides @window, then reshows it, resetting the
4585 * default size and position of the window. Used
4586 * by GUI builders only.
4589 gtk_window_reshow_with_initial_size (GtkWindow *window)
4593 g_return_if_fail (GTK_IS_WINDOW (window));
4595 widget = GTK_WIDGET (window);
4597 gtk_widget_hide (widget);
4598 gtk_widget_unrealize (widget);
4599 gtk_widget_show (widget);
4603 gtk_window_destroy (GtkWidget *widget)
4605 GtkWindow *window = GTK_WINDOW (widget);
4606 GtkWindowPrivate *priv = window->priv;
4608 gtk_window_release_application (window);
4610 toplevel_list = g_slist_remove (toplevel_list, window);
4612 if (priv->transient_parent)
4613 gtk_window_set_transient_for (window, NULL);
4615 /* frees the icons */
4616 gtk_window_set_icon_list (window, NULL);
4618 if (priv->has_user_ref_count)
4620 priv->has_user_ref_count = FALSE;
4621 g_object_unref (window);
4625 gtk_window_group_remove_window (priv->group, window);
4627 gtk_window_free_key_hash (window);
4629 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4633 gtk_window_finalize (GObject *object)
4635 GtkWindow *window = GTK_WINDOW (object);
4636 GtkWindowPrivate *priv = window->priv;
4637 GtkMnemonicHash *mnemonic_hash;
4639 g_free (priv->title);
4640 g_free (priv->wmclass_name);
4641 g_free (priv->wmclass_class);
4642 g_free (priv->wm_role);
4643 gtk_window_release_application (window);
4645 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4647 _gtk_mnemonic_hash_free (mnemonic_hash);
4649 if (priv->geometry_info)
4651 if (priv->geometry_info->widget)
4652 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4653 gtk_widget_destroyed,
4654 &priv->geometry_info->widget);
4655 g_free (priv->geometry_info);
4658 if (priv->keys_changed_handler)
4660 g_source_remove (priv->keys_changed_handler);
4661 priv->keys_changed_handler = 0;
4665 g_signal_handlers_disconnect_by_func (priv->screen,
4666 gtk_window_on_composited_changed, window);
4668 g_free (priv->startup_id);
4670 #ifdef GDK_WINDOWING_X11
4671 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4672 gtk_window_on_theme_variant_changed,
4676 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4680 gtk_window_show (GtkWidget *widget)
4682 GtkWindow *window = GTK_WINDOW (widget);
4683 GtkWindowPrivate *priv = window->priv;
4684 GtkContainer *container = GTK_CONTAINER (window);
4685 gboolean need_resize;
4688 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4690 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4694 _gtk_widget_set_visible_flag (widget, TRUE);
4696 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4697 _gtk_container_set_need_resize (container, FALSE);
4701 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4702 GtkAllocation allocation = { 0, 0 };
4703 GdkRectangle configure_request;
4704 GdkGeometry new_geometry;
4706 gboolean was_realized;
4708 /* We are going to go ahead and perform this configure request
4709 * and then emulate a configure notify by going ahead and
4710 * doing a size allocate. Sort of a synchronous
4711 * mini-copy of gtk_window_move_resize() here.
4713 gtk_window_compute_configure_request (window,
4718 /* We update this because we are going to go ahead
4719 * and gdk_window_resize() below, rather than
4722 info->last.configure_request.width = configure_request.width;
4723 info->last.configure_request.height = configure_request.height;
4725 /* and allocate the window - this is normally done
4726 * in move_resize in response to configure notify
4728 allocation.width = configure_request.width;
4729 allocation.height = configure_request.height;
4730 gtk_widget_size_allocate (widget, &allocation);
4732 /* Then we guarantee we have a realize */
4733 was_realized = FALSE;
4734 if (!gtk_widget_get_realized (widget))
4736 gtk_widget_realize (widget);
4737 was_realized = TRUE;
4740 /* We only send configure request if we didn't just finish
4741 * creating the window; if we just created the window
4742 * then we created it with widget->allocation anyhow.
4745 gdk_window_move_resize (gtk_widget_get_window (widget),
4746 configure_request.x,
4747 configure_request.y,
4748 configure_request.width,
4749 configure_request.height);
4752 gtk_container_check_resize (container);
4754 gtk_widget_map (widget);
4756 /* Try to make sure that we have some focused widget
4758 #ifdef GDK_WINDOWING_X11
4759 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4760 GTK_IS_PLUG (window);
4764 if (!priv->focus_widget && !is_plug)
4765 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4768 gtk_grab_add (widget);
4772 gtk_window_hide (GtkWidget *widget)
4774 GtkWindow *window = GTK_WINDOW (widget);
4775 GtkWindowPrivate *priv = window->priv;
4777 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4779 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4783 _gtk_widget_set_visible_flag (widget, FALSE);
4784 gtk_widget_unmap (widget);
4787 gtk_grab_remove (widget);
4791 gtk_window_map (GtkWidget *widget)
4794 GtkWindow *window = GTK_WINDOW (widget);
4795 GtkWindowPrivate *priv = window->priv;
4796 GdkWindow *gdk_window;
4797 gboolean auto_mnemonics;
4798 GtkPolicyType visible_focus;
4800 if (!gtk_widget_is_toplevel (widget))
4802 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4806 gtk_widget_set_mapped (widget, TRUE);
4808 child = gtk_bin_get_child (&(window->bin));
4810 gtk_widget_get_visible (child) &&
4811 !gtk_widget_get_mapped (child))
4812 gtk_widget_map (child);
4814 gdk_window = gtk_widget_get_window (widget);
4816 if (priv->maximize_initially)
4817 gdk_window_maximize (gdk_window);
4819 gdk_window_unmaximize (gdk_window);
4821 if (priv->stick_initially)
4822 gdk_window_stick (gdk_window);
4824 gdk_window_unstick (gdk_window);
4826 if (priv->iconify_initially)
4827 gdk_window_iconify (gdk_window);
4829 gdk_window_deiconify (gdk_window);
4831 if (priv->fullscreen_initially)
4832 gdk_window_fullscreen (gdk_window);
4834 gdk_window_unfullscreen (gdk_window);
4836 gdk_window_set_keep_above (gdk_window, priv->above_initially);
4838 gdk_window_set_keep_below (gdk_window, priv->below_initially);
4840 if (priv->type == GTK_WINDOW_TOPLEVEL)
4842 gtk_window_set_theme_variant (window);
4843 gtk_window_set_hide_titlebar_when_maximized (window,
4844 priv->hide_titlebar_when_maximized);
4847 /* No longer use the default settings */
4848 priv->need_default_size = FALSE;
4849 priv->need_default_position = FALSE;
4851 if (priv->reset_type_hint)
4853 /* We should only reset the type hint when the application
4854 * used gtk_window_set_type_hint() to change the hint.
4855 * Some applications use X directly to change the properties;
4856 * in that case, we shouldn't overwrite what they did.
4858 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4859 priv->reset_type_hint = FALSE;
4862 gdk_window_show (gdk_window);
4864 if (priv->grip_window)
4865 gdk_window_show (priv->grip_window);
4867 if (!disable_startup_notification)
4869 /* Do we have a custom startup-notification id? */
4870 if (priv->startup_id != NULL)
4872 /* Make sure we have a "real" id */
4873 if (!startup_id_is_fake (priv->startup_id))
4874 gdk_notify_startup_complete_with_id (priv->startup_id);
4876 g_free (priv->startup_id);
4877 priv->startup_id = NULL;
4879 else if (!sent_startup_notification)
4881 sent_startup_notification = TRUE;
4882 gdk_notify_startup_complete ();
4886 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4887 * (as in the case of popup menus), then hide mnemonics initially
4889 g_object_get (gtk_widget_get_settings (widget),
4890 "gtk-auto-mnemonics", &auto_mnemonics,
4891 "gtk-visible-focus", &visible_focus,
4894 if (auto_mnemonics && !priv->mnemonics_visible_set)
4895 gtk_window_set_mnemonics_visible (window, FALSE);
4897 /* inherit from transient parent, so that a dialog that is
4898 * opened via keynav shows focus initially
4900 if (priv->transient_parent)
4901 gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
4903 gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
4905 ensure_state_flag_window_unfocused (widget);
4909 gtk_window_map_event (GtkWidget *widget,
4912 if (!gtk_widget_get_mapped (widget))
4914 /* we should be be unmapped, but are getting a MapEvent, this may happen
4915 * to toplevel XWindows if mapping was intercepted by a window manager
4916 * and an unmap request occoured while the MapRequestEvent was still
4917 * being handled. we work around this situaiton here by re-requesting
4918 * the window being unmapped. more details can be found in:
4919 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4921 gdk_window_hide (gtk_widget_get_window (widget));
4927 gtk_window_unmap (GtkWidget *widget)
4929 GtkWindow *window = GTK_WINDOW (widget);
4930 GtkWindowPrivate *priv = window->priv;
4932 GtkWindowGeometryInfo *info;
4933 GdkWindow *gdk_window;
4934 GdkWindowState state;
4936 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4938 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
4942 gdk_window = gtk_widget_get_window (widget);
4944 gtk_widget_set_mapped (widget, FALSE);
4945 gdk_window_withdraw (gdk_window);
4947 priv->configure_request_count = 0;
4948 priv->configure_notify_received = FALSE;
4950 /* on unmap, we reset the default positioning of the window,
4951 * so it's placed again, but we don't reset the default
4952 * size of the window, so it's remembered.
4954 priv->need_default_position = TRUE;
4956 info = gtk_window_get_geometry_info (window, FALSE);
4959 info->initial_pos_set = FALSE;
4960 info->position_constraints_changed = FALSE;
4963 state = gdk_window_get_state (gdk_window);
4964 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4965 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4966 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4967 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4968 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4970 child = gtk_bin_get_child (&(window->bin));
4972 gtk_widget_unmap (child);
4975 /* (Note: Replace "size" with "width" or "height". Also, the request
4976 * mode is honoured.)
4977 * For selecting the default window size, the following conditions
4978 * should hold (in order of importance):
4979 * - the size is not below the minimum size
4980 * Windows cannot be resized below their minimum size, so we must
4981 * ensure we don't do that either.
4982 * - the size is not above the natural size
4983 * It seems weird to allocate more than this in an initial guess.
4984 * - the size does not exceed that of a maximized window
4985 * We want to see the whole window after all.
4986 * (Note that this may not be possible to achieve due to imperfect
4987 * information from the windowing system.)
4990 /* We use these for now to not make windows too big by accident. Note
4991 * that we still clamp these numbers by screen size. Also note that
4992 * minimum size still overrides this. So keep your windows small! :)
4994 #define MAX_DEFAULT_WINDOW_WIDTH 640
4995 #define MAX_DEFAULT_WINDOW_HEIGHT 480
4998 gtk_window_guess_default_size (GtkWindow *window,
5002 GtkWidget *widget = GTK_WIDGET (window);
5004 int minimum, natural;
5006 screen = gtk_widget_get_screen (widget);
5008 *width = gdk_screen_get_width (screen);
5009 *height = gdk_screen_get_height (screen);
5011 if (*width >= *height)
5014 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
5015 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
5020 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
5021 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
5024 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
5026 gtk_widget_get_preferred_height (widget, &minimum, &natural);
5027 *height = MAX (minimum, MIN (*height, natural));
5029 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
5030 *width = MAX (minimum, MIN (*width, natural));
5032 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
5034 gtk_widget_get_preferred_width (widget, &minimum, &natural);
5035 *width = MAX (minimum, MIN (*width, natural));
5037 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
5038 *height = MAX (minimum, MIN (*height, natural));
5043 gtk_window_realize (GtkWidget *widget)
5045 GtkAllocation allocation;
5047 GdkWindow *parent_window;
5048 GdkWindow *gdk_window;
5049 GdkWindowAttr attributes;
5050 gint attributes_mask;
5051 GtkWindowPrivate *priv;
5052 GtkStyleContext *context;
5054 window = GTK_WINDOW (widget);
5055 priv = window->priv;
5057 gtk_widget_get_allocation (widget, &allocation);
5059 if (gtk_widget_get_parent_window (widget))
5061 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
5063 gtk_widget_set_realized (widget, TRUE);
5065 attributes.x = allocation.x;
5066 attributes.y = allocation.y;
5067 attributes.width = allocation.width;
5068 attributes.height = allocation.height;
5069 attributes.window_type = GDK_WINDOW_CHILD;
5071 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
5073 attributes.visual = gtk_widget_get_visual (widget);
5074 attributes.wclass = GDK_INPUT_OUTPUT;
5076 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
5078 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
5079 &attributes, attributes_mask);
5080 gtk_widget_set_window (widget, gdk_window);
5081 gdk_window_set_user_data (gdk_window, widget);
5083 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
5085 gdk_window_enable_synchronized_configure (gdk_window);
5089 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5091 /* ensure widget tree is properly size allocated */
5092 if (allocation.x == -1 &&
5093 allocation.y == -1 &&
5094 allocation.width == 1 &&
5095 allocation.height == 1)
5101 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5102 if (allocation.width == 0 || allocation.height == 0)
5104 /* non-empty window */
5105 allocation.width = 200;
5106 allocation.height = 200;
5108 gtk_widget_size_allocate (widget, &allocation);
5110 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5112 g_return_if_fail (!gtk_widget_get_realized (widget));
5115 gtk_widget_set_realized (widget, TRUE);
5119 case GTK_WINDOW_TOPLEVEL:
5120 attributes.window_type = GDK_WINDOW_TOPLEVEL;
5122 case GTK_WINDOW_POPUP:
5123 attributes.window_type = GDK_WINDOW_TEMP;
5126 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5130 attributes.title = priv->title;
5131 attributes.wmclass_name = priv->wmclass_name;
5132 attributes.wmclass_class = priv->wmclass_class;
5133 attributes.wclass = GDK_INPUT_OUTPUT;
5134 attributes.visual = gtk_widget_get_visual (widget);
5136 attributes_mask = 0;
5137 parent_window = gtk_widget_get_root_window (widget);
5139 gtk_widget_get_allocation (widget, &allocation);
5140 attributes.width = allocation.width;
5141 attributes.height = allocation.height;
5142 attributes.event_mask = gtk_widget_get_events (widget);
5143 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5144 GDK_KEY_PRESS_MASK |
5145 GDK_KEY_RELEASE_MASK |
5146 GDK_ENTER_NOTIFY_MASK |
5147 GDK_LEAVE_NOTIFY_MASK |
5148 GDK_FOCUS_CHANGE_MASK |
5149 GDK_STRUCTURE_MASK);
5150 attributes.type_hint = priv->type_hint;
5152 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5153 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5154 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5156 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5157 gtk_widget_set_window (widget, gdk_window);
5159 if (priv->opacity_set)
5160 gdk_window_set_opacity (gdk_window, priv->opacity);
5162 gdk_window_enable_synchronized_configure (gdk_window);
5164 gdk_window_set_user_data (gdk_window, window);
5166 context = gtk_widget_get_style_context (widget);
5167 gtk_style_context_set_background (context, gdk_window);
5170 if (priv->transient_parent &&
5171 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5172 gdk_window_set_transient_for (gdk_window,
5173 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5176 gdk_window_set_role (gdk_window, priv->wm_role);
5178 if (!priv->decorated)
5179 gdk_window_set_decorations (gdk_window, 0);
5181 if (!priv->deletable)
5182 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5184 if (gtk_window_get_skip_pager_hint (window))
5185 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5187 if (gtk_window_get_skip_taskbar_hint (window))
5188 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5190 if (gtk_window_get_accept_focus (window))
5191 gdk_window_set_accept_focus (gdk_window, TRUE);
5193 gdk_window_set_accept_focus (gdk_window, FALSE);
5195 if (gtk_window_get_focus_on_map (window))
5196 gdk_window_set_focus_on_map (gdk_window, TRUE);
5198 gdk_window_set_focus_on_map (gdk_window, FALSE);
5201 gdk_window_set_modal_hint (gdk_window, TRUE);
5203 gdk_window_set_modal_hint (gdk_window, FALSE);
5205 if (priv->startup_id)
5207 #ifdef GDK_WINDOWING_X11
5208 if (GDK_IS_X11_WINDOW (gdk_window))
5210 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5211 if (timestamp != GDK_CURRENT_TIME)
5212 gdk_x11_window_set_user_time (gdk_window, timestamp);
5215 if (!startup_id_is_fake (priv->startup_id))
5216 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5219 #ifdef GDK_WINDOWING_X11
5220 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5222 if (GDK_IS_X11_WINDOW (gdk_window))
5223 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5228 gtk_window_realize_icon (window);
5230 if (priv->has_resize_grip)
5231 resize_grip_create_window (window);
5235 gtk_window_unrealize (GtkWidget *widget)
5237 GtkWindow *window = GTK_WINDOW (widget);
5238 GtkWindowPrivate *priv = window->priv;
5239 GtkWindowGeometryInfo *info;
5241 /* On unrealize, we reset the size of the window such
5242 * that we will re-apply the default sizing stuff
5243 * next time we show the window.
5245 * Default positioning is reset on unmap, instead of unrealize.
5247 priv->need_default_size = TRUE;
5248 info = gtk_window_get_geometry_info (window, FALSE);
5251 info->resize_width = -1;
5252 info->resize_height = -1;
5253 info->last.configure_request.x = 0;
5254 info->last.configure_request.y = 0;
5255 info->last.configure_request.width = -1;
5256 info->last.configure_request.height = -1;
5257 /* be sure we reset geom hints on re-realize */
5258 info->last.flags = 0;
5262 gtk_window_unrealize_icon (window);
5264 if (priv->grip_window != NULL)
5265 resize_grip_destroy_window (window);
5267 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5270 static GtkJunctionSides
5271 get_grip_junction (GtkWidget *widget)
5273 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5274 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5276 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5280 get_drag_edge (GtkWidget *widget,
5281 GdkWindowEdge *edge)
5283 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5284 gboolean hresizable;
5285 gboolean vresizable;
5286 GtkTextDirection dir;
5287 GtkWindowGeometryInfo *info;
5292 info = priv->geometry_info;
5295 GdkWindowHints flags = info->last.flags;
5296 GdkGeometry *geometry = &info->last.geometry;
5298 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5300 hresizable = geometry->min_width < geometry->max_width;
5301 vresizable = geometry->min_height < geometry->max_height;
5305 dir = gtk_widget_get_direction (widget);
5307 if (hresizable && vresizable)
5308 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5309 else if (hresizable)
5310 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5311 else if (vresizable)
5312 *edge = GDK_WINDOW_EDGE_SOUTH;
5320 set_grip_cursor (GtkWindow *window)
5322 GtkWidget *widget = GTK_WIDGET (window);
5323 GtkWindowPrivate *priv = window->priv;
5325 if (priv->grip_window == NULL)
5328 if (gtk_widget_is_sensitive (widget))
5331 GdkDisplay *display;
5332 GdkCursorType cursor_type;
5335 cursor_type = GDK_LEFT_PTR;
5337 if (get_drag_edge (widget, &edge))
5341 case GDK_WINDOW_EDGE_EAST:
5342 cursor_type = GDK_RIGHT_SIDE;
5344 case GDK_WINDOW_EDGE_SOUTH_EAST:
5345 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5347 case GDK_WINDOW_EDGE_SOUTH:
5348 cursor_type = GDK_BOTTOM_SIDE;
5350 case GDK_WINDOW_EDGE_SOUTH_WEST:
5351 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5353 case GDK_WINDOW_EDGE_WEST:
5354 cursor_type = GDK_LEFT_SIDE;
5360 display = gtk_widget_get_display (widget);
5361 cursor = gdk_cursor_new_for_display (display, cursor_type);
5362 gdk_window_set_cursor (priv->grip_window, cursor);
5363 g_object_unref (cursor);
5366 gdk_window_set_cursor (priv->grip_window, NULL);
5370 set_grip_shape (GtkWindow *window)
5372 GtkWindowPrivate *priv = window->priv;
5373 cairo_region_t *region;
5374 cairo_surface_t *surface;
5376 double width, height;
5378 if (priv->grip_window == NULL)
5381 width = gdk_window_get_width (priv->grip_window);
5382 height = gdk_window_get_height (priv->grip_window);
5383 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
5385 cr = cairo_create (surface);
5386 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5388 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5389 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5391 cairo_move_to (cr, width, 0.0);
5392 cairo_line_to (cr, width, height);
5393 cairo_line_to (cr, 0.0, height);
5397 cairo_move_to (cr, 0.0, 0.0);
5398 cairo_line_to (cr, width, height);
5399 cairo_line_to (cr, 0.0, height);
5401 cairo_close_path (cr);
5404 region = gdk_cairo_region_create_from_surface (surface);
5405 cairo_surface_destroy (surface);
5407 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5408 cairo_region_destroy (region);
5412 set_grip_position (GtkWindow *window)
5414 GtkWindowPrivate *priv = window->priv;
5417 if (priv->grip_window == NULL)
5420 gtk_window_get_resize_grip_area (window, &rect);
5421 gdk_window_raise (priv->grip_window);
5422 gdk_window_move_resize (priv->grip_window,
5424 rect.width, rect.height);
5428 gtk_window_size_allocate (GtkWidget *widget,
5429 GtkAllocation *allocation)
5431 GtkWindow *window = GTK_WINDOW (widget);
5432 GtkAllocation child_allocation;
5436 gtk_widget_set_allocation (widget, allocation);
5438 if (gtk_widget_get_realized (widget))
5440 /* If it's not a toplevel we're embedded, we need to resize the window's
5441 * window and skip the grip.
5443 if (!gtk_widget_is_toplevel (widget))
5445 gdk_window_move_resize (gtk_widget_get_window (widget),
5446 allocation->x, allocation->y,
5447 allocation->width, allocation->height);
5451 update_grip_visibility (window);
5452 set_grip_position (window);
5456 child = gtk_bin_get_child (&(window->bin));
5457 if (child && gtk_widget_get_visible (child))
5459 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5460 child_allocation.x = border_width;
5461 child_allocation.y = border_width;
5462 child_allocation.width =
5463 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5464 child_allocation.height =
5465 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5467 gtk_widget_size_allocate (child, &child_allocation);
5472 gtk_window_configure_event (GtkWidget *widget,
5473 GdkEventConfigure *event)
5475 GtkAllocation allocation;
5476 GtkWindow *window = GTK_WINDOW (widget);
5477 GtkWindowPrivate *priv = window->priv;
5478 gboolean expected_reply = priv->configure_request_count > 0;
5480 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5482 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5483 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5485 gdk_window_configure_finished (gtk_widget_get_window (widget));
5489 /* priv->configure_request_count incremented for each
5490 * configure request, and decremented to a min of 0 for
5491 * each configure notify.
5493 * All it means is that we know we will get at least
5494 * priv->configure_request_count more configure notifies.
5495 * We could get more configure notifies than that; some
5496 * of the configure notifies we get may be unrelated to
5497 * the configure requests. But we will get at least
5498 * priv->configure_request_count notifies.
5501 if (priv->configure_request_count > 0)
5503 priv->configure_request_count -= 1;
5504 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5507 /* As an optimization, we avoid a resize when possible.
5509 * The only times we can avoid a resize are:
5510 * - we know only the position changed, not the size
5511 * - we know we have made more requests and so will get more
5512 * notifies and can wait to resize when we get them
5514 gtk_widget_get_allocation (widget, &allocation);
5515 if (!expected_reply &&
5516 (allocation.width == event->width &&
5517 allocation.height == event->height))
5519 gdk_window_configure_finished (gtk_widget_get_window (widget));
5524 * If we do need to resize, we do that by:
5525 * - filling in widget->allocation with the new size
5526 * - setting configure_notify_received to TRUE
5527 * for use in gtk_window_move_resize()
5528 * - queueing a resize, leading to invocation of
5529 * gtk_window_move_resize() in an idle handler
5533 priv->configure_notify_received = TRUE;
5535 allocation.width = event->width;
5536 allocation.height = event->height;
5537 gtk_widget_set_allocation (widget, &allocation);
5539 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5541 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5547 gtk_window_state_event (GtkWidget *widget,
5548 GdkEventWindowState *event)
5550 update_grip_visibility (GTK_WINDOW (widget));
5552 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
5553 ensure_state_flag_window_unfocused (widget);
5559 gtk_window_direction_changed (GtkWidget *widget,
5560 GtkTextDirection prev_dir)
5562 GtkWindow *window = GTK_WINDOW (widget);
5564 set_grip_cursor (window);
5565 set_grip_position (window);
5566 set_grip_shape (window);
5570 gtk_window_state_changed (GtkWidget *widget,
5571 GtkStateType previous_state)
5573 GtkWindow *window = GTK_WINDOW (widget);
5575 update_grip_visibility (window);
5579 gtk_window_style_updated (GtkWidget *widget)
5581 GtkWindow *window = GTK_WINDOW (widget);
5582 GtkWindowPrivate *priv = window->priv;
5585 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5587 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5589 gdk_window_move_resize (priv->grip_window,
5591 rect.width, rect.height);
5593 set_grip_shape (window);
5594 gtk_widget_queue_resize (widget);
5599 resize_grip_create_window (GtkWindow *window)
5602 GtkWindowPrivate *priv;
5603 GdkWindowAttr attributes;
5604 gint attributes_mask;
5606 GdkRGBA transparent = {0, 0, 0, 0};
5608 priv = window->priv;
5609 widget = GTK_WIDGET (window);
5611 g_return_if_fail (gtk_widget_get_realized (widget));
5612 g_return_if_fail (priv->grip_window == NULL);
5614 gtk_window_get_resize_grip_area (window, &rect);
5616 attributes.x = rect.x;
5617 attributes.y = rect.y;
5618 attributes.width = rect.width;
5619 attributes.height = rect.height;
5620 attributes.window_type = GDK_WINDOW_CHILD;
5621 attributes.wclass = GDK_INPUT_OUTPUT;
5622 attributes.event_mask = gtk_widget_get_events (widget) |
5624 GDK_BUTTON_PRESS_MASK;
5626 attributes_mask = GDK_WA_X | GDK_WA_Y;
5628 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5631 gdk_window_set_background_rgba (priv->grip_window, &transparent);
5633 gdk_window_set_user_data (priv->grip_window, widget);
5635 gdk_window_raise (priv->grip_window);
5637 set_grip_shape (window);
5638 update_grip_visibility (window);
5642 resize_grip_destroy_window (GtkWindow *window)
5644 GtkWindowPrivate *priv = window->priv;
5646 gdk_window_set_user_data (priv->grip_window, NULL);
5647 gdk_window_destroy (priv->grip_window);
5648 priv->grip_window = NULL;
5649 update_grip_visibility (window);
5653 * gtk_window_set_has_resize_grip:
5654 * @window: a #GtkWindow
5655 * @value: %TRUE to allow a resize grip
5657 * Sets whether @window has a corner resize grip.
5659 * Note that the resize grip is only shown if the window
5660 * is actually resizable and not maximized. Use
5661 * gtk_window_resize_grip_is_visible() to find out if the
5662 * resize grip is currently shown.
5667 gtk_window_set_has_resize_grip (GtkWindow *window,
5670 GtkWidget *widget = GTK_WIDGET (window);
5671 GtkWindowPrivate *priv = window->priv;
5673 value = value != FALSE;
5675 if (value != priv->has_resize_grip)
5677 priv->has_resize_grip = value;
5678 gtk_widget_queue_draw (widget);
5680 if (gtk_widget_get_realized (widget) &&
5681 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5683 if (priv->has_resize_grip && priv->grip_window == NULL)
5684 resize_grip_create_window (window);
5685 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5686 resize_grip_destroy_window (window);
5689 g_object_notify (G_OBJECT (window), "has-resize-grip");
5694 update_grip_visibility (GtkWindow *window)
5696 GtkWindowPrivate *priv = window->priv;
5699 val = gtk_window_resize_grip_is_visible (window);
5701 if (priv->grip_window != NULL)
5705 gdk_window_show (priv->grip_window);
5706 set_grip_cursor (window);
5710 gdk_window_hide (priv->grip_window);
5714 if (priv->resize_grip_visible != val)
5716 priv->resize_grip_visible = val;
5718 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5723 * gtk_window_resize_grip_is_visible:
5724 * @window: a #GtkWindow
5726 * Determines whether a resize grip is visible for the specified window.
5728 * Returns: %TRUE if a resize grip exists and is visible
5733 gtk_window_resize_grip_is_visible (GtkWindow *window)
5736 GtkWindowPrivate *priv;
5739 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5741 priv = window->priv;
5742 widget = GTK_WIDGET (window);
5744 if (priv->type == GTK_WINDOW_POPUP)
5747 if (!priv->resizable)
5750 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5753 if (gtk_widget_get_realized (widget))
5755 GdkWindowState state;
5757 state = gdk_window_get_state (gtk_widget_get_window (widget));
5759 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5763 if (!get_drag_edge (widget, &edge))
5766 return window->priv->has_resize_grip;
5770 * gtk_window_get_has_resize_grip:
5771 * @window: a #GtkWindow
5773 * Determines whether the window may have a resize grip.
5775 * Returns: %TRUE if the window has a resize grip
5780 gtk_window_get_has_resize_grip (GtkWindow *window)
5782 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5784 return window->priv->has_resize_grip;
5788 * gtk_window_get_resize_grip_area:
5789 * @window: a #GtkWindow
5790 * @rect: (out): a pointer to a #GdkRectangle which we should store
5791 * the resize grip area
5793 * If a window has a resize grip, this will retrieve the grip
5794 * position, width and height into the specified #GdkRectangle.
5796 * Returns: %TRUE if the resize grip's area was retrieved
5801 gtk_window_get_resize_grip_area (GtkWindow *window,
5804 GtkWidget *widget = GTK_WIDGET (window);
5805 GtkAllocation allocation;
5809 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5811 if (!window->priv->has_resize_grip)
5814 gtk_widget_get_allocation (widget, &allocation);
5816 gtk_widget_style_get (widget,
5817 "resize-grip-width", &grip_width,
5818 "resize-grip-height", &grip_height,
5821 if (grip_width > allocation.width)
5822 grip_width = allocation.width;
5824 if (grip_height > allocation.height)
5825 grip_height = allocation.height;
5827 rect->width = grip_width;
5828 rect->height = grip_height;
5829 rect->y = allocation.y + allocation.height - grip_height;
5831 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5832 rect->x = allocation.x + allocation.width - grip_width;
5834 rect->x = allocation.x;
5839 /* the accel_key and accel_mods fields of the key have to be setup
5840 * upon calling this function. it'll then return whether that key
5841 * is at all used as accelerator, and if so will OR in the
5842 * accel_flags member of the key.
5845 _gtk_window_query_nonaccels (GtkWindow *window,
5847 GdkModifierType accel_mods)
5849 GtkWindowPrivate *priv;
5851 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5853 priv = window->priv;
5855 /* movement keys are considered locked accels */
5858 static const guint bindings[] = {
5859 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,
5860 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,
5864 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5865 if (bindings[i] == accel_key)
5869 /* mnemonics are considered locked accels */
5870 if (accel_mods == priv->mnemonic_modifier)
5872 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5873 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5881 * gtk_window_propagate_key_event:
5882 * @window: a #GtkWindow
5883 * @event: a #GdkEventKey
5885 * Propagate a key press or release event to the focus widget and
5886 * up the focus container chain until a widget handles @event.
5887 * This is normally called by the default ::key_press_event and
5888 * ::key_release_event handlers for toplevel windows,
5889 * however in some cases it may be useful to call this directly when
5890 * overriding the standard key handling for a toplevel window.
5892 * Return value: %TRUE if a widget in the focus chain handled the event.
5897 gtk_window_propagate_key_event (GtkWindow *window,
5900 GtkWindowPrivate *priv;
5901 gboolean handled = FALSE;
5902 GtkWidget *widget, *focus;
5904 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5906 priv = window->priv;
5907 widget = GTK_WIDGET (window);
5909 focus = priv->focus_widget;
5911 g_object_ref (focus);
5914 focus && focus != widget &&
5915 gtk_widget_get_toplevel (focus) == widget)
5919 if (gtk_widget_is_sensitive (focus))
5920 handled = gtk_widget_event (focus, (GdkEvent*) event);
5922 parent = gtk_widget_get_parent (focus);
5924 g_object_ref (parent);
5926 g_object_unref (focus);
5932 g_object_unref (focus);
5938 gtk_window_key_press_event (GtkWidget *widget,
5941 GtkWindow *window = GTK_WINDOW (widget);
5942 gboolean handled = FALSE;
5944 /* handle mnemonics and accelerators */
5946 handled = gtk_window_activate_key (window, event);
5948 /* handle focus widget key events */
5950 handled = gtk_window_propagate_key_event (window, event);
5952 /* Chain up, invokes binding set */
5954 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5960 gtk_window_key_release_event (GtkWidget *widget,
5963 GtkWindow *window = GTK_WINDOW (widget);
5964 gboolean handled = FALSE;
5966 /* handle focus widget key events */
5968 handled = gtk_window_propagate_key_event (window, event);
5970 /* Chain up, invokes binding set */
5972 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5978 gtk_window_button_press_event (GtkWidget *widget,
5979 GdkEventButton *event)
5981 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5984 if (event->window == priv->grip_window)
5986 if (get_drag_edge (widget, &edge))
5987 gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
5989 gdk_event_get_device ((GdkEvent *) event),
6002 gtk_window_real_activate_default (GtkWindow *window)
6004 gtk_window_activate_default (window);
6008 gtk_window_real_activate_focus (GtkWindow *window)
6010 gtk_window_activate_focus (window);
6014 gtk_window_enter_notify_event (GtkWidget *widget,
6015 GdkEventCrossing *event)
6021 gtk_window_leave_notify_event (GtkWidget *widget,
6022 GdkEventCrossing *event)
6028 do_focus_change (GtkWidget *widget,
6032 GdkDeviceManager *device_manager;
6035 g_object_ref (widget);
6037 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
6038 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6039 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
6040 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
6042 for (d = devices; d; d = d->next)
6044 GdkDevice *dev = d->data;
6047 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
6050 /* Skip non-master keyboards that haven't
6051 * selected for events from this window
6053 window = gtk_widget_get_window (widget);
6054 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
6055 window && !gdk_window_get_device_events (window, dev))
6058 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
6060 fevent->focus_change.type = GDK_FOCUS_CHANGE;
6061 fevent->focus_change.window = window;
6063 g_object_ref (window);
6064 fevent->focus_change.in = in;
6065 gdk_event_set_device (fevent, dev);
6067 gtk_widget_send_focus_change (widget, fevent);
6069 gdk_event_free (fevent);
6072 g_list_free (devices);
6073 g_object_unref (widget);
6077 maybe_set_mnemonics_visible (GtkWindow *window)
6080 GdkDeviceManager *device_manager;
6082 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
6083 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6085 for (d = devices; d; d = d->next)
6087 GdkDevice *dev = d->data;
6089 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6091 GdkModifierType mask;
6093 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6095 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6097 gtk_window_set_mnemonics_visible (window, TRUE);
6103 g_list_free (devices);
6107 gtk_window_focus_in_event (GtkWidget *widget,
6108 GdkEventFocus *event)
6110 GtkWindow *window = GTK_WINDOW (widget);
6111 gboolean auto_mnemonics;
6113 /* It appears spurious focus in events can occur when
6114 * the window is hidden. So we'll just check to see if
6115 * the window is visible before actually handling the
6118 if (gtk_widget_get_visible (widget))
6120 _gtk_window_set_has_toplevel_focus (window, TRUE);
6121 _gtk_window_set_is_active (window, TRUE);
6123 g_object_get (gtk_widget_get_settings (widget),
6124 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6126 maybe_set_mnemonics_visible (window);
6133 gtk_window_focus_out_event (GtkWidget *widget,
6134 GdkEventFocus *event)
6136 GtkWindow *window = GTK_WINDOW (widget);
6137 gboolean auto_mnemonics;
6139 _gtk_window_set_has_toplevel_focus (window, FALSE);
6140 _gtk_window_set_is_active (window, FALSE);
6142 /* set the mnemonic-visible property to false */
6143 g_object_get (gtk_widget_get_settings (widget),
6144 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6146 gtk_window_set_mnemonics_visible (window, FALSE);
6152 gtk_window_check_resize (GtkContainer *container)
6154 /* If the window is not toplevel anymore than it's embedded somewhere,
6155 * so handle it like a normal window */
6156 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6157 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6158 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6159 gtk_window_move_resize (GTK_WINDOW (container));
6163 gtk_window_focus (GtkWidget *widget,
6164 GtkDirectionType direction)
6166 GtkWindowPrivate *priv;
6169 GtkContainer *container;
6171 GtkWidget *old_focus_child;
6174 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6175 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6177 container = GTK_CONTAINER (widget);
6178 window = GTK_WINDOW (widget);
6179 priv = window->priv;
6180 bin = GTK_BIN (widget);
6182 old_focus_child = gtk_container_get_focus_child (container);
6184 /* We need a special implementation here to deal properly with wrapping
6185 * around in the tab chain without the danger of going into an
6188 if (old_focus_child)
6190 if (gtk_widget_child_focus (old_focus_child, direction))
6194 if (priv->focus_widget)
6196 if (direction == GTK_DIR_LEFT ||
6197 direction == GTK_DIR_RIGHT ||
6198 direction == GTK_DIR_UP ||
6199 direction == GTK_DIR_DOWN)
6204 /* Wrapped off the end, clear the focus setting for the toplpevel */
6205 parent = gtk_widget_get_parent (priv->focus_widget);
6208 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6209 parent = gtk_widget_get_parent (parent);
6212 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6215 /* Now try to focus the first widget in the window */
6216 child = gtk_bin_get_child (bin);
6219 if (gtk_widget_child_focus (child, direction))
6227 gtk_window_move_focus (GtkWidget *widget,
6228 GtkDirectionType dir)
6230 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6232 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6236 gtk_widget_child_focus (widget, dir);
6238 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6239 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6243 gtk_window_real_set_focus (GtkWindow *window,
6246 GtkWindowPrivate *priv = window->priv;
6247 GtkWidget *old_focus = priv->focus_widget;
6248 gboolean had_default = FALSE;
6249 gboolean focus_had_default = FALSE;
6250 gboolean old_focus_had_default = FALSE;
6254 g_object_ref (old_focus);
6255 g_object_freeze_notify (G_OBJECT (old_focus));
6256 old_focus_had_default = gtk_widget_has_default (old_focus);
6260 g_object_ref (focus);
6261 g_object_freeze_notify (G_OBJECT (focus));
6262 focus_had_default = gtk_widget_has_default (focus);
6265 if (priv->default_widget)
6266 had_default = gtk_widget_has_default (priv->default_widget);
6268 if (priv->focus_widget)
6270 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6271 (priv->focus_widget != priv->default_widget))
6273 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6274 gtk_widget_queue_draw (priv->focus_widget);
6276 if (priv->default_widget)
6277 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6280 priv->focus_widget = NULL;
6282 if (priv->has_focus)
6283 do_focus_change (old_focus, FALSE);
6285 g_object_notify (G_OBJECT (old_focus), "is-focus");
6288 /* The above notifications may have set a new focus widget,
6289 * if so, we don't want to override it.
6291 if (focus && !priv->focus_widget)
6293 priv->focus_widget = focus;
6295 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6296 (priv->focus_widget != priv->default_widget))
6298 if (gtk_widget_get_can_default (priv->focus_widget))
6299 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6301 if (priv->default_widget)
6302 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6305 if (priv->has_focus)
6306 do_focus_change (priv->focus_widget, TRUE);
6308 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6311 /* If the default widget changed, a redraw will have been queued
6312 * on the old and new default widgets by gtk_window_set_default(), so
6313 * we only have to worry about the case where it didn't change.
6314 * We'll sometimes queue a draw twice on the new widget but that
6317 if (priv->default_widget &&
6318 (had_default != gtk_widget_has_default (priv->default_widget)))
6319 gtk_widget_queue_draw (priv->default_widget);
6323 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6324 gtk_widget_queue_draw (old_focus);
6326 g_object_thaw_notify (G_OBJECT (old_focus));
6327 g_object_unref (old_focus);
6331 if (focus_had_default != gtk_widget_has_default (focus))
6332 gtk_widget_queue_draw (focus);
6334 g_object_thaw_notify (G_OBJECT (focus));
6335 g_object_unref (focus);
6341 gtk_window_get_preferred_width (GtkWidget *widget,
6349 window = GTK_WINDOW (widget);
6350 child = gtk_bin_get_child (GTK_BIN (window));
6352 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6353 *minimum_size = border_width * 2;
6354 *natural_size = border_width * 2;
6356 if (child && gtk_widget_get_visible (child))
6358 gint child_min, child_nat;
6359 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6361 *minimum_size += child_min;
6362 *natural_size += child_nat;
6367 gtk_window_get_preferred_height (GtkWidget *widget,
6375 window = GTK_WINDOW (widget);
6376 child = gtk_bin_get_child (GTK_BIN (window));
6378 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6379 *minimum_size = border_width * 2;
6380 *natural_size = border_width * 2;
6382 if (child && gtk_widget_get_visible (child))
6384 gint child_min, child_nat;
6385 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6387 *minimum_size += child_min;
6388 *natural_size += child_nat;
6394 * _gtk_window_unset_focus_and_default:
6395 * @window: a #GtkWindow
6396 * @widget: a widget inside of @window
6398 * Checks whether the focus and default widgets of @window are
6399 * @widget or a descendent of @widget, and if so, unset them.
6402 _gtk_window_unset_focus_and_default (GtkWindow *window,
6406 GtkWindowPrivate *priv = window->priv;
6410 g_object_ref (window);
6411 g_object_ref (widget);
6413 parent = gtk_widget_get_parent (widget);
6414 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6416 child = priv->focus_widget;
6418 while (child && child != widget)
6419 child = gtk_widget_get_parent (child);
6421 if (child == widget)
6422 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6425 child = priv->default_widget;
6427 while (child && child != widget)
6428 child = gtk_widget_get_parent (child);
6430 if (child == widget)
6431 gtk_window_set_default (window, NULL);
6433 g_object_unref (widget);
6434 g_object_unref (window);
6437 /*********************************
6438 * Functions related to resizing *
6439 *********************************/
6442 geometry_size_to_pixels (GdkGeometry *geometry,
6447 gint base_width = 0;
6448 gint base_height = 0;
6450 gint min_height = 0;
6452 gint height_inc = 1;
6454 if (flags & GDK_HINT_BASE_SIZE)
6456 base_width = geometry->base_width;
6457 base_height = geometry->base_height;
6459 if (flags & GDK_HINT_MIN_SIZE)
6461 min_width = geometry->min_width;
6462 min_height = geometry->min_height;
6464 if (flags & GDK_HINT_RESIZE_INC)
6466 width_inc = geometry->width_inc;
6467 height_inc = geometry->height_inc;
6471 *width = MAX (*width * width_inc + base_width, min_width);
6473 *height = MAX (*height * height_inc + base_height, min_height);
6476 /* This function doesn't constrain to geometry hints */
6478 gtk_window_compute_configure_request_size (GtkWindow *window,
6479 GdkGeometry *geometry,
6484 GtkWindowPrivate *priv = window->priv;
6485 GtkWindowGeometryInfo *info;
6488 * - we've done a size request
6491 info = gtk_window_get_geometry_info (window, FALSE);
6493 if (priv->need_default_size)
6495 gtk_window_guess_default_size (window, width, height);
6497 /* If window is empty so requests 0, default to random nonzero size */
6498 if (*width == 0 && *height == 0)
6504 /* Override with default size */
6508 if (info->default_width > 0)
6509 *width = info->default_width;
6510 if (info->default_height > 0)
6511 *height = info->default_height;
6513 if (info->default_is_geometry)
6514 geometry_size_to_pixels (geometry, flags,
6515 info->default_width > 0 ? width : NULL,
6516 info->default_height > 0 ? height : NULL);
6521 GtkAllocation allocation;
6523 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6525 /* Default to keeping current size */
6526 *width = allocation.width;
6527 *height = allocation.height;
6530 /* Override any size with gtk_window_resize() values */
6533 if (info->resize_width > 0)
6534 *width = info->resize_width;
6535 if (info->resize_height > 0)
6536 *height = info->resize_height;
6538 if (info->resize_is_geometry)
6539 geometry_size_to_pixels (geometry, flags,
6540 info->resize_width > 0 ? width : NULL,
6541 info->resize_height > 0 ? height : NULL);
6544 /* Don't ever request zero width or height, its not supported by
6545 gdk. The size allocation code will round it to 1 anyway but if
6546 we do it then the value returned from this function will is
6547 not comparable to the size allocation read from the GtkWindow. */
6548 *width = MAX (*width, 1);
6549 *height = MAX (*height, 1);
6552 static GtkWindowPosition
6553 get_effective_position (GtkWindow *window)
6555 GtkWindowPrivate *priv = window->priv;
6556 GtkWindowPosition pos = priv->position;
6558 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6559 (priv->transient_parent == NULL ||
6560 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6561 pos = GTK_WIN_POS_NONE;
6567 get_center_monitor_of_window (GtkWindow *window)
6569 /* We could try to sort out the relative positions of the monitors and
6570 * stuff, or we could just be losers and assume you have a row
6571 * or column of monitors.
6573 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6577 get_monitor_containing_pointer (GtkWindow *window)
6581 GdkScreen *window_screen;
6582 GdkScreen *pointer_screen;
6583 GdkDisplay *display;
6584 GdkDeviceManager *device_manager;
6587 window_screen = gtk_window_check_screen (window);
6588 display = gdk_screen_get_display (window_screen);
6589 device_manager = gdk_display_get_device_manager (display);
6590 pointer = gdk_device_manager_get_client_pointer (device_manager);
6592 gdk_device_get_position (pointer,
6596 if (pointer_screen == window_screen)
6597 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6605 center_window_on_monitor (GtkWindow *window,
6611 GdkRectangle monitor;
6614 monitor_num = get_monitor_containing_pointer (window);
6616 if (monitor_num == -1)
6617 monitor_num = get_center_monitor_of_window (window);
6619 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6620 monitor_num, &monitor);
6622 *x = (monitor.width - w) / 2 + monitor.x;
6623 *y = (monitor.height - h) / 2 + monitor.y;
6625 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6626 * and WM decorations.
6640 if (extent > clamp_extent)
6642 *base = clamp_base + clamp_extent/2 - extent/2;
6643 else if (*base < clamp_base)
6645 else if (*base + extent > clamp_base + clamp_extent)
6646 *base = clamp_base + clamp_extent - extent;
6650 clamp_window_to_rectangle (gint *x,
6654 const GdkRectangle *rect)
6656 #ifdef DEBUGGING_OUTPUT
6657 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);
6660 /* If it is too large, center it. If it fits on the monitor but is
6661 * partially outside, move it to the closest edge. Do this
6662 * separately in x and y directions.
6664 clamp (x, w, rect->x, rect->width);
6665 clamp (y, h, rect->y, rect->height);
6666 #ifdef DEBUGGING_OUTPUT
6667 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6673 gtk_window_compute_configure_request (GtkWindow *window,
6674 GdkRectangle *request,
6675 GdkGeometry *geometry,
6678 GtkWindowPrivate *priv = window->priv;
6679 GdkGeometry new_geometry;
6682 GtkWindowPosition pos;
6683 GtkWidget *parent_widget;
6684 GtkWindowGeometryInfo *info;
6688 screen = gtk_window_check_screen (window);
6690 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6691 gtk_window_compute_configure_request_size (window,
6692 &new_geometry, new_flags,
6695 gtk_window_constrain_size (window,
6696 &new_geometry, new_flags,
6700 parent_widget = (GtkWidget*) priv->transient_parent;
6702 pos = get_effective_position (window);
6703 info = gtk_window_get_geometry_info (window, FALSE);
6705 /* by default, don't change position requested */
6708 x = info->last.configure_request.x;
6709 y = info->last.configure_request.y;
6718 if (priv->need_default_position)
6721 /* FIXME this all interrelates with window gravity.
6722 * For most of them I think we want to set GRAVITY_CENTER.
6724 * Not sure how to go about that.
6728 /* here we are only handling CENTER_ALWAYS
6729 * as it relates to default positioning,
6730 * where it's equivalent to simply CENTER
6732 case GTK_WIN_POS_CENTER_ALWAYS:
6733 case GTK_WIN_POS_CENTER:
6734 center_window_on_monitor (window, w, h, &x, &y);
6737 case GTK_WIN_POS_CENTER_ON_PARENT:
6739 GtkAllocation allocation;
6740 GdkWindow *gdk_window;
6742 GdkRectangle monitor;
6745 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6747 gdk_window = gtk_widget_get_window (parent_widget);
6749 if (gdk_window != NULL)
6750 monitor_num = gdk_screen_get_monitor_at_window (screen,
6755 gdk_window_get_origin (gdk_window,
6758 gtk_widget_get_allocation (parent_widget, &allocation);
6759 x = ox + (allocation.width - w) / 2;
6760 y = oy + (allocation.height - h) / 2;
6762 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6763 * WM decorations. If parent wasn't on a monitor, just
6766 if (monitor_num >= 0)
6768 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6769 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6774 case GTK_WIN_POS_MOUSE:
6776 gint screen_width = gdk_screen_get_width (screen);
6777 gint screen_height = gdk_screen_get_height (screen);
6779 GdkRectangle monitor;
6780 GdkDisplay *display;
6781 GdkDeviceManager *device_manager;
6783 GdkScreen *pointer_screen;
6786 display = gdk_screen_get_display (screen);
6787 device_manager = gdk_display_get_device_manager (display);
6788 pointer = gdk_device_manager_get_client_pointer (device_manager);
6790 gdk_device_get_position (pointer,
6794 if (pointer_screen == screen)
6795 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6801 x = CLAMP (x, 0, screen_width - w);
6802 y = CLAMP (y, 0, screen_height - h);
6804 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6805 * WM decorations. Don't try to figure out what's going
6806 * on if the mouse wasn't inside a monitor.
6808 if (monitor_num >= 0)
6810 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6811 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6819 } /* if (priv->need_default_position) */
6821 if (priv->need_default_position && info &&
6822 info->initial_pos_set)
6824 x = info->initial_x;
6825 y = info->initial_y;
6826 gtk_window_constrain_position (window, w, h, &x, &y);
6832 request->height = h;
6835 *geometry = new_geometry;
6841 gtk_window_constrain_position (GtkWindow *window,
6847 GtkWindowPrivate *priv = window->priv;
6849 /* See long comments in gtk_window_move_resize()
6850 * on when it's safe to call this function.
6852 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6854 gint center_x, center_y;
6856 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6864 gtk_window_move_resize (GtkWindow *window)
6868 * First we determine whether any information has changed that would
6869 * cause us to revise our last configure request. If we would send
6870 * a different configure request from last time, then
6871 * configure_request_size_changed = TRUE or
6872 * configure_request_pos_changed = TRUE. configure_request_size_changed
6873 * may be true due to new hints, a gtk_window_resize(), or whatever.
6874 * configure_request_pos_changed may be true due to gtk_window_set_position()
6875 * or gtk_window_move().
6877 * If the configure request has changed, we send off a new one. To
6878 * ensure GTK+ invariants are maintained (resize queue does what it
6879 * should), we go ahead and size_allocate the requested size in this
6882 * If the configure request has not changed, we don't ever resend
6883 * it, because it could mean fighting the user or window manager.
6886 * To prepare the configure request, we come up with a base size/pos:
6887 * - the one from gtk_window_move()/gtk_window_resize()
6888 * - else default_width, default_height if we haven't ever
6890 * - else the size request if we haven't ever been mapped,
6891 * as a substitute default size
6892 * - else the current size of the window, as received from
6893 * configure notifies (i.e. the current allocation)
6895 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6896 * the position request to be centered.
6898 GtkWindowPrivate *priv = window->priv;
6899 GtkAllocation allocation;
6901 GtkContainer *container;
6902 GtkWindowGeometryInfo *info;
6903 GdkGeometry new_geometry;
6904 GdkWindow *gdk_window;
6906 GdkRectangle new_request;
6907 gboolean configure_request_size_changed;
6908 gboolean configure_request_pos_changed;
6909 gboolean hints_changed; /* do we need to send these again */
6910 GtkWindowLastGeometryInfo saved_last_info;
6912 widget = GTK_WIDGET (window);
6914 gdk_window = gtk_widget_get_window (widget);
6915 container = GTK_CONTAINER (widget);
6916 info = gtk_window_get_geometry_info (window, TRUE);
6918 configure_request_size_changed = FALSE;
6919 configure_request_pos_changed = FALSE;
6921 gtk_window_compute_configure_request (window, &new_request,
6922 &new_geometry, &new_flags);
6924 /* This check implies the invariant that we never set info->last
6925 * without setting the hints and sending off a configure request.
6927 * If we change info->last without sending the request, we may
6930 if (info->last.configure_request.x != new_request.x ||
6931 info->last.configure_request.y != new_request.y)
6932 configure_request_pos_changed = TRUE;
6934 if ((info->last.configure_request.width != new_request.width ||
6935 info->last.configure_request.height != new_request.height))
6936 configure_request_size_changed = TRUE;
6938 hints_changed = FALSE;
6940 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6941 &new_geometry, new_flags))
6943 hints_changed = TRUE;
6946 /* Position Constraints
6947 * ====================
6949 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6950 * a default. The other POS_ values are used only when the
6951 * window is shown, not after that.
6953 * However, we can't implement a position constraint as
6954 * "anytime the window size changes, center the window"
6955 * because this may well end up fighting the WM or user. In
6956 * fact it gets in an infinite loop with at least one WM.
6958 * Basically, applications are in no way in a position to
6959 * constrain the position of a window, with one exception:
6960 * override redirect windows. (Really the intended purpose
6961 * of CENTER_ALWAYS anyhow, I would think.)
6963 * So the way we implement this "constraint" is to say that when WE
6964 * cause a move or resize, i.e. we make a configure request changing
6965 * window size, we recompute the CENTER_ALWAYS position to reflect
6966 * the new window size, and include it in our request. Also, if we
6967 * just turned on CENTER_ALWAYS we snap to center with a new
6968 * request. Otherwise, if we are just NOTIFIED of a move or resize
6969 * done by someone else e.g. the window manager, we do NOT send a
6970 * new configure request.
6972 * For override redirect windows, this works fine; all window
6973 * sizes are from our configure requests. For managed windows,
6974 * it is at least semi-sane, though who knows what the
6975 * app author is thinking.
6978 /* This condition should be kept in sync with the condition later on
6979 * that determines whether we send a configure request. i.e. we
6980 * should do this position constraining anytime we were going to
6981 * send a configure request anyhow, plus when constraints have
6984 if (configure_request_pos_changed ||
6985 configure_request_size_changed ||
6987 info->position_constraints_changed)
6989 /* We request the constrained position if:
6990 * - we were changing position, and need to clamp
6991 * the change to the constraint
6992 * - we're changing the size anyway
6993 * - set_position() was called to toggle CENTER_ALWAYS on
6996 gtk_window_constrain_position (window,
7002 /* Update whether we need to request a move */
7003 if (info->last.configure_request.x != new_request.x ||
7004 info->last.configure_request.y != new_request.y)
7005 configure_request_pos_changed = TRUE;
7007 configure_request_pos_changed = FALSE;
7011 if (priv->type == GTK_WINDOW_TOPLEVEL)
7013 int notify_x, notify_y;
7015 /* this is the position from the last configure notify */
7016 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
7018 g_message ("--- %s ---\n"
7019 "last : %d,%d\t%d x %d\n"
7020 "this : %d,%d\t%d x %d\n"
7021 "alloc : %d,%d\t%d x %d\n"
7023 "resize: \t%d x %d\n"
7024 "size_changed: %d pos_changed: %d hints_changed: %d\n"
7025 "configure_notify_received: %d\n"
7026 "configure_request_count: %d\n"
7027 "position_constraints_changed: %d\n",
7028 priv->title ? priv->title : "(no title)",
7029 info->last.configure_request.x,
7030 info->last.configure_request.y,
7031 info->last.configure_request.width,
7032 info->last.configure_request.height,
7038 widget->allocation.width,
7039 widget->allocation.height,
7040 widget->requisition.width,
7041 widget->requisition.height,
7043 info->resize_height,
7044 configure_request_pos_changed,
7045 configure_request_size_changed,
7047 priv->configure_notify_received,
7048 priv->configure_request_count,
7049 info->position_constraints_changed);
7053 saved_last_info = info->last;
7054 info->last.geometry = new_geometry;
7055 info->last.flags = new_flags;
7056 info->last.configure_request = new_request;
7058 /* need to set PPosition so the WM will look at our position,
7059 * but we don't want to count PPosition coming and going as a hints
7060 * change for future iterations. So we saved info->last prior to
7064 /* Also, if the initial position was explicitly set, then we always
7065 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
7069 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
7070 * this is an initial map
7073 if ((configure_request_pos_changed ||
7074 info->initial_pos_set ||
7075 (priv->need_default_position &&
7076 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
7077 (new_flags & GDK_HINT_POS) == 0)
7079 new_flags |= GDK_HINT_POS;
7080 hints_changed = TRUE;
7083 /* Set hints if necessary
7086 gdk_window_set_geometry_hints (gdk_window,
7090 gtk_widget_get_allocation (widget, &allocation);
7092 /* handle resizing/moving and widget tree allocation
7094 if (priv->configure_notify_received)
7096 /* If we have received a configure event since
7097 * the last time in this function, we need to
7098 * accept our new size and size_allocate child widgets.
7099 * (see gtk_window_configure_event() for more details).
7101 * 1 or more configure notifies may have been received.
7102 * Also, configure_notify_received will only be TRUE
7103 * if all expected configure notifies have been received
7104 * (one per configure request), as an optimization.
7107 priv->configure_notify_received = FALSE;
7109 /* gtk_window_configure_event() filled in widget->allocation */
7110 gtk_widget_size_allocate (widget, &allocation);
7112 set_grip_position (window);
7113 update_grip_visibility (window);
7115 gdk_window_process_updates (gdk_window, TRUE);
7117 gdk_window_configure_finished (gdk_window);
7119 /* If the configure request changed, it means that
7121 * 1) coincidentally changed hints or widget properties
7122 * impacting the configure request before getting
7123 * a configure notify, or
7124 * 2) some broken widget is changing its size request
7125 * during size allocation, resulting in
7126 * a false appearance of changed configure request.
7128 * For 1), we could just go ahead and ask for the
7129 * new size right now, but doing that for 2)
7130 * might well be fighting the user (and can even
7131 * trigger a loop). Since we really don't want to
7132 * do that, we requeue a resize in hopes that
7133 * by the time it gets handled, the child has seen
7134 * the light and is willing to go along with the
7135 * new size. (this happens for the zvt widget, since
7136 * the size_allocate() above will have stored the
7137 * requisition corresponding to the new size in the
7140 * This doesn't buy us anything for 1), but it shouldn't
7141 * hurt us too badly, since it is what would have
7142 * happened if we had gotten the configure event before
7143 * the new size had been set.
7146 if (configure_request_size_changed ||
7147 configure_request_pos_changed)
7149 /* Don't change the recorded last info after all, because we
7150 * haven't actually updated to the new info yet - we decided
7151 * to postpone our configure request until later.
7153 info->last = saved_last_info;
7155 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7158 return; /* Bail out, we didn't really process the move/resize */
7160 else if ((configure_request_size_changed || hints_changed) &&
7161 (allocation.width != new_request.width || allocation.height != new_request.height))
7164 /* We are in one of the following situations:
7165 * A. configure_request_size_changed
7166 * our requisition has changed and we need a different window size,
7167 * so we request it from the window manager.
7168 * B. !configure_request_size_changed && hints_changed
7169 * the window manager rejects our size, but we have just changed the
7170 * window manager hints, so there's a chance our request will
7171 * be honoured this time, so we try again.
7173 * However, if the new requisition is the same as the current allocation,
7174 * we don't request it again, since we won't get a ConfigureNotify back from
7175 * the window manager unless it decides to change our requisition. If
7176 * we don't get the ConfigureNotify back, the resize queue will never be run.
7179 /* Now send the configure request */
7180 if (configure_request_pos_changed)
7182 gdk_window_move_resize (gdk_window,
7183 new_request.x, new_request.y,
7184 new_request.width, new_request.height);
7186 else /* only size changed */
7188 gdk_window_resize (gdk_window,
7189 new_request.width, new_request.height);
7192 if (priv->type == GTK_WINDOW_POPUP)
7194 GtkAllocation allocation;
7196 /* Directly size allocate for override redirect (popup) windows. */
7199 allocation.width = new_request.width;
7200 allocation.height = new_request.height;
7202 gtk_widget_size_allocate (widget, &allocation);
7204 gdk_window_process_updates (gdk_window, TRUE);
7206 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7207 gtk_widget_queue_draw (widget);
7211 /* Increment the number of have-not-yet-received-notify requests */
7212 priv->configure_request_count += 1;
7213 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7215 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7216 * configure event in response to our resizing request.
7217 * the configure event will cause a new resize with
7218 * ->configure_notify_received=TRUE.
7219 * until then, we want to
7220 * - discard expose events
7221 * - coalesce resizes for our children
7222 * - defer any window resizes until the configure event arrived
7223 * to achieve this, we queue a resize for the window, but remove its
7224 * resizing handler, so resizing will not be handled from the next
7225 * idle handler but when the configure event arrives.
7227 * FIXME: we should also dequeue the pending redraws here, since
7228 * we handle those ourselves upon ->configure_notify_received==TRUE.
7230 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7232 gtk_widget_queue_resize_no_redraw (widget);
7233 _gtk_container_dequeue_resize_handler (container);
7239 /* Handle any position changes.
7241 if (configure_request_pos_changed)
7243 gdk_window_move (gdk_window,
7244 new_request.x, new_request.y);
7247 /* And run the resize queue.
7249 gtk_container_resize_children (container);
7252 /* We have now processed a move/resize since the last position
7253 * constraint change, setting of the initial position, or resize.
7254 * (Not resetting these flags here can lead to infinite loops for
7255 * GTK_RESIZE_IMMEDIATE containers)
7257 info->position_constraints_changed = FALSE;
7258 info->initial_pos_set = FALSE;
7259 info->resize_width = -1;
7260 info->resize_height = -1;
7263 /* Compare two sets of Geometry hints for equality.
7266 gtk_window_compare_hints (GdkGeometry *geometry_a,
7268 GdkGeometry *geometry_b,
7271 if (flags_a != flags_b)
7274 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7275 (geometry_a->min_width != geometry_b->min_width ||
7276 geometry_a->min_height != geometry_b->min_height))
7279 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7280 (geometry_a->max_width != geometry_b->max_width ||
7281 geometry_a->max_height != geometry_b->max_height))
7284 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7285 (geometry_a->base_width != geometry_b->base_width ||
7286 geometry_a->base_height != geometry_b->base_height))
7289 if ((flags_a & GDK_HINT_ASPECT) &&
7290 (geometry_a->min_aspect != geometry_b->min_aspect ||
7291 geometry_a->max_aspect != geometry_b->max_aspect))
7294 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7295 (geometry_a->width_inc != geometry_b->width_inc ||
7296 geometry_a->height_inc != geometry_b->height_inc))
7299 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7300 geometry_a->win_gravity != geometry_b->win_gravity)
7307 _gtk_window_constrain_size (GtkWindow *window,
7313 GtkWindowPrivate *priv;
7314 GtkWindowGeometryInfo *info;
7316 g_return_if_fail (GTK_IS_WINDOW (window));
7318 priv = window->priv;
7320 info = priv->geometry_info;
7323 GdkWindowHints flags = info->last.flags;
7324 GdkGeometry *geometry = &info->last.geometry;
7326 gtk_window_constrain_size (window,
7337 gtk_window_constrain_size (GtkWindow *window,
7338 GdkGeometry *geometry,
7345 gdk_window_constrain_size (geometry, flags, width, height,
7346 new_width, new_height);
7349 /* Compute the set of geometry hints and flags for a window
7350 * based on the application set geometry, and requisition
7351 * of the window. gtk_widget_get_preferred_size() must have been
7355 gtk_window_compute_hints (GtkWindow *window,
7356 GdkGeometry *new_geometry,
7359 GtkWindowPrivate *priv = window->priv;
7361 gint extra_width = 0;
7362 gint extra_height = 0;
7363 GtkWindowGeometryInfo *geometry_info;
7364 GtkRequisition requisition;
7366 widget = GTK_WIDGET (window);
7368 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7369 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7373 *new_flags = geometry_info->mask;
7374 *new_geometry = geometry_info->geometry;
7381 if (geometry_info && geometry_info->widget)
7383 /* If the geometry widget is set, then the hints really apply to that
7384 * widget. This is pretty much meaningless unless the window layout
7385 * is such that the rest of the window adds fixed size borders to
7386 * the geometry widget. Our job is to figure the size of the borders;
7387 * We do that by asking how big the toplevel would be if the
7388 * geometry widget was *really big*.
7391 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7392 * |GGGGG B| in the border can confuse things
7398 * |AAAAAAAAA | When the geometry widget is large, things are
7399 * |GGGGGGGGGGB| clearer.
7404 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7405 GtkRequisition requisition;
7406 int current_width, current_height;
7408 _gtk_widget_override_size_request (geometry_info->widget,
7409 TEMPORARY_SIZE, TEMPORARY_SIZE,
7410 ¤t_width, ¤t_height);
7411 gtk_widget_get_preferred_size (widget,
7412 &requisition, NULL);
7413 _gtk_widget_restore_size_request (geometry_info->widget,
7414 current_width, current_height);
7416 extra_width = requisition.width - TEMPORARY_SIZE;
7417 extra_height = requisition.height - TEMPORARY_SIZE;
7419 if (extra_width < 0 || extra_height < 0)
7421 g_warning("Toplevel size doesn't seem to directly depend on the "
7422 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7423 "The geometry widget might not be in the window, or it might not "
7424 "be packed into the window appropriately");
7425 extra_width = MAX(extra_width, 0);
7426 extra_height = MAX(extra_height, 0);
7428 #undef TEMPORARY_SIZE
7431 /* We don't want to set GDK_HINT_POS in here, we just set it
7432 * in gtk_window_move_resize() when we want the position
7436 if (*new_flags & GDK_HINT_BASE_SIZE)
7438 new_geometry->base_width += extra_width;
7439 new_geometry->base_height += extra_height;
7443 /* For simplicity, we always set the base hint, even when we
7444 * don't expect it to have any visible effect.
7445 * (Note: geometry_size_to_pixels() depends on this.)
7447 *new_flags |= GDK_HINT_BASE_SIZE;
7449 new_geometry->base_width = extra_width;
7450 new_geometry->base_height = extra_height;
7452 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7453 * base size is the minimum size */
7454 if (*new_flags & GDK_HINT_MIN_SIZE)
7456 if (new_geometry->min_width > 0)
7457 new_geometry->base_width += new_geometry->min_width;
7458 if (new_geometry->min_height > 0)
7459 new_geometry->base_height += new_geometry->min_height;
7463 /* Please use a good size for unresizable widgets, not the minimum one. */
7464 if (!priv->resizable)
7465 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7467 if (*new_flags & GDK_HINT_MIN_SIZE)
7469 if (new_geometry->min_width < 0)
7470 new_geometry->min_width = requisition.width;
7472 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7474 if (new_geometry->min_height < 0)
7475 new_geometry->min_height = requisition.height;
7477 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7481 *new_flags |= GDK_HINT_MIN_SIZE;
7483 new_geometry->min_width = requisition.width;
7484 new_geometry->min_height = requisition.height;
7487 if (*new_flags & GDK_HINT_MAX_SIZE)
7489 if (new_geometry->max_width < 0)
7490 new_geometry->max_width = requisition.width;
7492 new_geometry->max_width += extra_width;
7494 if (new_geometry->max_height < 0)
7495 new_geometry->max_height = requisition.height;
7497 new_geometry->max_height += extra_height;
7499 else if (!priv->resizable)
7501 *new_flags |= GDK_HINT_MAX_SIZE;
7503 new_geometry->max_width = requisition.width;
7504 new_geometry->max_height = requisition.height;
7507 *new_flags |= GDK_HINT_WIN_GRAVITY;
7508 new_geometry->win_gravity = priv->gravity;
7511 /***********************
7512 * Redrawing functions *
7513 ***********************/
7516 gtk_window_draw (GtkWidget *widget,
7519 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7520 GtkStyleContext *context;
7521 gboolean ret = FALSE;
7523 context = gtk_widget_get_style_context (widget);
7525 gtk_style_context_save (context);
7527 if (!gtk_widget_get_app_paintable (widget) &&
7528 gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
7530 GtkStateFlags state;
7532 state = gtk_widget_get_state_flags (widget);
7534 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7535 state |= GTK_STATE_FLAG_FOCUSED;
7537 gtk_style_context_set_state (context, state);
7538 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7539 gtk_render_background (context, cr, 0, 0,
7540 gtk_widget_get_allocated_width (widget),
7541 gtk_widget_get_allocated_height (widget));
7544 gtk_style_context_restore (context);
7546 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7547 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7549 if (priv->grip_window &&
7550 gtk_cairo_should_draw_window (cr, priv->grip_window))
7554 gtk_style_context_save (context);
7557 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7558 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7560 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7561 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7562 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7565 gtk_style_context_restore (context);
7572 * gtk_window_present:
7573 * @window: a #GtkWindow
7575 * Presents a window to the user. This may mean raising the window
7576 * in the stacking order, deiconifying it, moving it to the current
7577 * desktop, and/or giving it the keyboard focus, possibly dependent
7578 * on the user's platform, window manager, and preferences.
7580 * If @window is hidden, this function calls gtk_widget_show()
7583 * This function should be used when the user tries to open a window
7584 * that's already open. Say for example the preferences dialog is
7585 * currently open, and the user chooses Preferences from the menu
7586 * a second time; use gtk_window_present() to move the already-open dialog
7587 * where the user can see it.
7589 * If you are calling this function in response to a user interaction,
7590 * it is preferable to use gtk_window_present_with_time().
7594 gtk_window_present (GtkWindow *window)
7596 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7600 * gtk_window_present_with_time:
7601 * @window: a #GtkWindow
7602 * @timestamp: the timestamp of the user interaction (typically a
7603 * button or key press event) which triggered this call
7605 * Presents a window to the user in response to a user interaction.
7606 * If you need to present a window without a timestamp, use
7607 * gtk_window_present(). See gtk_window_present() for details.
7612 gtk_window_present_with_time (GtkWindow *window,
7615 GtkWindowPrivate *priv;
7617 GdkWindow *gdk_window;
7619 g_return_if_fail (GTK_IS_WINDOW (window));
7621 priv = window->priv;
7622 widget = GTK_WIDGET (window);
7624 if (gtk_widget_get_visible (widget))
7626 gdk_window = gtk_widget_get_window (widget);
7628 g_assert (gdk_window != NULL);
7630 gdk_window_show (gdk_window);
7632 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7633 if (timestamp == GDK_CURRENT_TIME)
7635 #ifdef GDK_WINDOWING_X11
7636 if (GDK_IS_X11_WINDOW(gdk_window))
7638 GdkDisplay *display;
7640 display = gtk_widget_get_display (GTK_WIDGET (window));
7641 timestamp = gdk_x11_display_get_user_time (display);
7645 timestamp = gtk_get_current_event_time ();
7648 gdk_window_focus (gdk_window, timestamp);
7652 priv->initial_timestamp = timestamp;
7653 gtk_widget_show (widget);
7658 * gtk_window_iconify:
7659 * @window: a #GtkWindow
7661 * Asks to iconify (i.e. minimize) the specified @window. Note that
7662 * you shouldn't assume the window is definitely iconified afterward,
7663 * because other entities (e.g. the user or <link
7664 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7665 * again, or there may not be a window manager in which case
7666 * iconification isn't possible, etc. But normally the window will end
7667 * up iconified. Just don't write code that crashes if not.
7669 * It's permitted to call this function before showing a window,
7670 * in which case the window will be iconified before it ever appears
7673 * You can track iconification via the "window-state-event" signal
7678 gtk_window_iconify (GtkWindow *window)
7680 GtkWindowPrivate *priv;
7682 GdkWindow *toplevel;
7684 g_return_if_fail (GTK_IS_WINDOW (window));
7686 priv = window->priv;
7687 widget = GTK_WIDGET (window);
7689 priv->iconify_initially = TRUE;
7691 toplevel = gtk_widget_get_window (widget);
7693 if (toplevel != NULL)
7694 gdk_window_iconify (toplevel);
7698 * gtk_window_deiconify:
7699 * @window: a #GtkWindow
7701 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7702 * that you shouldn't assume the window is definitely deiconified
7703 * afterward, because other entities (e.g. the user or <link
7704 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7705 * again before your code which assumes deiconification gets to run.
7707 * You can track iconification via the "window-state-event" signal
7711 gtk_window_deiconify (GtkWindow *window)
7713 GtkWindowPrivate *priv;
7715 GdkWindow *toplevel;
7717 g_return_if_fail (GTK_IS_WINDOW (window));
7719 priv = window->priv;
7720 widget = GTK_WIDGET (window);
7722 priv->iconify_initially = FALSE;
7724 toplevel = gtk_widget_get_window (widget);
7726 if (toplevel != NULL)
7727 gdk_window_deiconify (toplevel);
7732 * @window: a #GtkWindow
7734 * Asks to stick @window, which means that it will appear on all user
7735 * desktops. Note that you shouldn't assume the window is definitely
7736 * stuck afterward, because other entities (e.g. the user or <link
7737 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7738 * again, and some window managers do not support sticking
7739 * windows. But normally the window will end up stuck. Just don't
7740 * write code that crashes if not.
7742 * It's permitted to call this function before showing a window.
7744 * You can track stickiness via the "window-state-event" signal
7749 gtk_window_stick (GtkWindow *window)
7751 GtkWindowPrivate *priv;
7753 GdkWindow *toplevel;
7755 g_return_if_fail (GTK_IS_WINDOW (window));
7757 priv = window->priv;
7758 widget = GTK_WIDGET (window);
7760 priv->stick_initially = TRUE;
7762 toplevel = gtk_widget_get_window (widget);
7764 if (toplevel != NULL)
7765 gdk_window_stick (toplevel);
7769 * gtk_window_unstick:
7770 * @window: a #GtkWindow
7772 * Asks to unstick @window, which means that it will appear on only
7773 * one of the user's desktops. Note that you shouldn't assume the
7774 * window is definitely unstuck afterward, because other entities
7775 * (e.g. the user or <link linkend="gtk-X11-arch">window
7776 * manager</link>) could stick it again. But normally the window will
7777 * end up stuck. Just don't write code that crashes if not.
7779 * You can track stickiness via the "window-state-event" signal
7784 gtk_window_unstick (GtkWindow *window)
7786 GtkWindowPrivate *priv;
7788 GdkWindow *toplevel;
7790 g_return_if_fail (GTK_IS_WINDOW (window));
7792 priv = window->priv;
7793 widget = GTK_WIDGET (window);
7795 priv->stick_initially = FALSE;
7797 toplevel = gtk_widget_get_window (widget);
7799 if (toplevel != NULL)
7800 gdk_window_unstick (toplevel);
7804 * gtk_window_maximize:
7805 * @window: a #GtkWindow
7807 * Asks to maximize @window, so that it becomes full-screen. Note that
7808 * you shouldn't assume the window is definitely maximized afterward,
7809 * because other entities (e.g. the user or <link
7810 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7811 * again, and not all window managers support maximization. But
7812 * normally the window will end up maximized. Just don't write code
7813 * that crashes if not.
7815 * It's permitted to call this function before showing a window,
7816 * in which case the window will be maximized when it appears onscreen
7819 * You can track maximization via the "window-state-event" signal
7824 gtk_window_maximize (GtkWindow *window)
7826 GtkWindowPrivate *priv;
7828 GdkWindow *toplevel;
7830 g_return_if_fail (GTK_IS_WINDOW (window));
7832 priv = window->priv;
7833 widget = GTK_WIDGET (window);
7835 priv->maximize_initially = TRUE;
7837 toplevel = gtk_widget_get_window (widget);
7839 if (toplevel != NULL)
7840 gdk_window_maximize (toplevel);
7844 * gtk_window_unmaximize:
7845 * @window: a #GtkWindow
7847 * Asks to unmaximize @window. Note that you shouldn't assume the
7848 * window is definitely unmaximized afterward, because other entities
7849 * (e.g. the user or <link linkend="gtk-X11-arch">window
7850 * manager</link>) could maximize it again, and not all window
7851 * managers honor requests to unmaximize. But normally the window will
7852 * end up unmaximized. Just don't write code that crashes if not.
7854 * You can track maximization via the "window-state-event" signal
7859 gtk_window_unmaximize (GtkWindow *window)
7861 GtkWindowPrivate *priv;
7863 GdkWindow *toplevel;
7865 g_return_if_fail (GTK_IS_WINDOW (window));
7867 priv = window->priv;
7868 widget = GTK_WIDGET (window);
7870 priv->maximize_initially = FALSE;
7872 toplevel = gtk_widget_get_window (widget);
7874 if (toplevel != NULL)
7875 gdk_window_unmaximize (toplevel);
7879 * gtk_window_fullscreen:
7880 * @window: a #GtkWindow
7882 * Asks to place @window in the fullscreen state. Note that you
7883 * shouldn't assume the window is definitely full screen afterward,
7884 * because other entities (e.g. the user or <link
7885 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7886 * again, and not all window managers honor requests to fullscreen
7887 * windows. But normally the window will end up fullscreen. Just
7888 * don't write code that crashes if not.
7890 * You can track the fullscreen state via the "window-state-event" signal
7896 gtk_window_fullscreen (GtkWindow *window)
7898 GtkWindowPrivate *priv;
7900 GdkWindow *toplevel;
7902 g_return_if_fail (GTK_IS_WINDOW (window));
7904 priv = window->priv;
7905 widget = GTK_WIDGET (window);
7907 priv->fullscreen_initially = TRUE;
7909 toplevel = gtk_widget_get_window (widget);
7911 if (toplevel != NULL)
7912 gdk_window_fullscreen (toplevel);
7916 * gtk_window_unfullscreen:
7917 * @window: a #GtkWindow
7919 * Asks to toggle off the fullscreen state for @window. Note that you
7920 * shouldn't assume the window is definitely not full screen
7921 * afterward, because other entities (e.g. the user or <link
7922 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7923 * again, and not all window managers honor requests to unfullscreen
7924 * windows. But normally the window will end up restored to its normal
7925 * state. Just don't write code that crashes if not.
7927 * You can track the fullscreen state via the "window-state-event" signal
7933 gtk_window_unfullscreen (GtkWindow *window)
7936 GdkWindow *toplevel;
7937 GtkWindowPrivate *priv;
7939 g_return_if_fail (GTK_IS_WINDOW (window));
7941 priv = window->priv;
7942 widget = GTK_WIDGET (window);
7944 priv->fullscreen_initially = FALSE;
7946 toplevel = gtk_widget_get_window (widget);
7948 if (toplevel != NULL)
7949 gdk_window_unfullscreen (toplevel);
7953 * gtk_window_set_keep_above:
7954 * @window: a #GtkWindow
7955 * @setting: whether to keep @window above other windows
7957 * Asks to keep @window above, so that it stays on top. Note that
7958 * you shouldn't assume the window is definitely above afterward,
7959 * because other entities (e.g. the user or <link
7960 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7961 * and not all window managers support keeping windows above. But
7962 * normally the window will end kept above. Just don't write code
7963 * that crashes if not.
7965 * It's permitted to call this function before showing a window,
7966 * in which case the window will be kept above when it appears onscreen
7969 * You can track the above state via the "window-state-event" signal
7972 * Note that, according to the <ulink
7973 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7974 * Manager Hints</ulink> specification, the above state is mainly meant
7975 * for user preferences and should not be used by applications e.g. for
7976 * drawing attention to their dialogs.
7981 gtk_window_set_keep_above (GtkWindow *window,
7985 GtkWindowPrivate *priv;
7986 GdkWindow *toplevel;
7988 g_return_if_fail (GTK_IS_WINDOW (window));
7990 priv = window->priv;
7991 widget = GTK_WIDGET (window);
7993 priv->above_initially = setting != FALSE;
7995 priv->below_initially = FALSE;
7997 toplevel = gtk_widget_get_window (widget);
7999 if (toplevel != NULL)
8000 gdk_window_set_keep_above (toplevel, setting);
8004 * gtk_window_set_keep_below:
8005 * @window: a #GtkWindow
8006 * @setting: whether to keep @window below other windows
8008 * Asks to keep @window below, so that it stays in bottom. Note that
8009 * you shouldn't assume the window is definitely below afterward,
8010 * because other entities (e.g. the user or <link
8011 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8012 * and not all window managers support putting windows below. But
8013 * normally the window will be kept below. Just don't write code
8014 * that crashes if not.
8016 * It's permitted to call this function before showing a window,
8017 * in which case the window will be kept below when it appears onscreen
8020 * You can track the below state via the "window-state-event" signal
8023 * Note that, according to the <ulink
8024 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8025 * Manager Hints</ulink> specification, the above state is mainly meant
8026 * for user preferences and should not be used by applications e.g. for
8027 * drawing attention to their dialogs.
8032 gtk_window_set_keep_below (GtkWindow *window,
8036 GtkWindowPrivate *priv;
8037 GdkWindow *toplevel;
8039 g_return_if_fail (GTK_IS_WINDOW (window));
8041 priv = window->priv;
8042 widget = GTK_WIDGET (window);
8044 priv->below_initially = setting != FALSE;
8046 priv->above_initially = FALSE;
8048 toplevel = gtk_widget_get_window (widget);
8050 if (toplevel != NULL)
8051 gdk_window_set_keep_below (toplevel, setting);
8055 * gtk_window_set_resizable:
8056 * @window: a #GtkWindow
8057 * @resizable: %TRUE if the user can resize this window
8059 * Sets whether the user can resize a window. Windows are user resizable
8063 gtk_window_set_resizable (GtkWindow *window,
8066 GtkWindowPrivate *priv;
8068 g_return_if_fail (GTK_IS_WINDOW (window));
8070 priv = window->priv;
8072 resizable = (resizable != FALSE);
8074 if (priv->resizable != resizable)
8076 priv->resizable = (resizable != FALSE);
8078 update_grip_visibility (window);
8080 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8082 g_object_notify (G_OBJECT (window), "resizable");
8087 * gtk_window_get_resizable:
8088 * @window: a #GtkWindow
8090 * Gets the value set by gtk_window_set_resizable().
8092 * Return value: %TRUE if the user can resize the window
8095 gtk_window_get_resizable (GtkWindow *window)
8097 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8099 return window->priv->resizable;
8103 * gtk_window_set_gravity:
8104 * @window: a #GtkWindow
8105 * @gravity: window gravity
8107 * Window gravity defines the meaning of coordinates passed to
8108 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8111 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8112 * typically "do what you mean."
8116 gtk_window_set_gravity (GtkWindow *window,
8119 GtkWindowPrivate *priv;
8121 g_return_if_fail (GTK_IS_WINDOW (window));
8123 priv = window->priv;
8125 if (gravity != priv->gravity)
8127 priv->gravity = gravity;
8129 /* gtk_window_move_resize() will adapt gravity
8131 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8133 g_object_notify (G_OBJECT (window), "gravity");
8138 * gtk_window_get_gravity:
8139 * @window: a #GtkWindow
8141 * Gets the value set by gtk_window_set_gravity().
8143 * Return value: (transfer none): window gravity
8146 gtk_window_get_gravity (GtkWindow *window)
8148 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8150 return window->priv->gravity;
8154 * gtk_window_begin_resize_drag:
8155 * @window: a #GtkWindow
8156 * @button: mouse button that initiated the drag
8157 * @edge: position of the resize control
8158 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8159 * @root_y: Y position where the user clicked to initiate the drag
8160 * @timestamp: timestamp from the click event that initiated the drag
8162 * Starts resizing a window. This function is used if an application
8163 * has window resizing controls. When GDK can support it, the resize
8164 * will be done using the standard mechanism for the <link
8165 * linkend="gtk-X11-arch">window manager</link> or windowing
8166 * system. Otherwise, GDK will try to emulate window resizing,
8167 * potentially not all that well, depending on the windowing system.
8171 gtk_window_begin_resize_drag (GtkWindow *window,
8179 GdkWindow *toplevel;
8181 g_return_if_fail (GTK_IS_WINDOW (window));
8182 widget = GTK_WIDGET (window);
8183 g_return_if_fail (gtk_widget_get_visible (widget));
8185 toplevel = gtk_widget_get_window (widget);
8187 gdk_window_begin_resize_drag (toplevel,
8194 * gtk_window_begin_move_drag:
8195 * @window: a #GtkWindow
8196 * @button: mouse button that initiated the drag
8197 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8198 * @root_y: Y position where the user clicked to initiate the drag
8199 * @timestamp: timestamp from the click event that initiated the drag
8201 * Starts moving a window. This function is used if an application has
8202 * window movement grips. When GDK can support it, the window movement
8203 * will be done using the standard mechanism for the <link
8204 * linkend="gtk-X11-arch">window manager</link> or windowing
8205 * system. Otherwise, GDK will try to emulate window movement,
8206 * potentially not all that well, depending on the windowing system.
8210 gtk_window_begin_move_drag (GtkWindow *window,
8217 GdkWindow *toplevel;
8219 g_return_if_fail (GTK_IS_WINDOW (window));
8220 widget = GTK_WIDGET (window);
8221 g_return_if_fail (gtk_widget_get_visible (widget));
8223 toplevel = gtk_widget_get_window (widget);
8225 gdk_window_begin_move_drag (toplevel,
8232 * gtk_window_set_screen:
8233 * @window: a #GtkWindow.
8234 * @screen: a #GdkScreen.
8236 * Sets the #GdkScreen where the @window is displayed; if
8237 * the window is already mapped, it will be unmapped, and
8238 * then remapped on the new screen.
8243 gtk_window_set_screen (GtkWindow *window,
8246 GtkWindowPrivate *priv;
8248 GdkScreen *previous_screen;
8249 gboolean was_mapped;
8251 g_return_if_fail (GTK_IS_WINDOW (window));
8252 g_return_if_fail (GDK_IS_SCREEN (screen));
8254 priv = window->priv;
8256 if (screen == priv->screen)
8259 widget = GTK_WIDGET (window);
8261 previous_screen = priv->screen;
8262 was_mapped = gtk_widget_get_mapped (widget);
8265 gtk_widget_unmap (widget);
8266 if (gtk_widget_get_realized (widget))
8267 gtk_widget_unrealize (widget);
8269 gtk_window_free_key_hash (window);
8270 priv->screen = screen;
8271 gtk_widget_reset_rc_styles (widget);
8272 if (screen != previous_screen)
8274 if (previous_screen)
8276 g_signal_handlers_disconnect_by_func (previous_screen,
8277 gtk_window_on_composited_changed, window);
8278 #ifdef GDK_WINDOWING_X11
8279 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8280 gtk_window_on_theme_variant_changed, window);
8283 g_signal_connect (screen, "composited-changed",
8284 G_CALLBACK (gtk_window_on_composited_changed), window);
8285 #ifdef GDK_WINDOWING_X11
8286 g_signal_connect (gtk_settings_get_for_screen (screen),
8287 "notify::gtk-application-prefer-dark-theme",
8288 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8291 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8292 _gtk_widget_propagate_composited_changed (widget);
8294 g_object_notify (G_OBJECT (window), "screen");
8297 gtk_widget_map (widget);
8301 gtk_window_set_theme_variant (GtkWindow *window)
8303 #ifdef GDK_WINDOWING_X11
8304 GdkWindow *gdk_window;
8305 gboolean dark_theme_requested;
8307 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8308 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8311 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8313 if (GDK_IS_X11_WINDOW (gdk_window))
8314 gdk_x11_window_set_theme_variant (gdk_window,
8315 dark_theme_requested ? "dark" : NULL);
8320 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8324 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8325 gtk_window_set_theme_variant (window);
8329 gtk_window_on_composited_changed (GdkScreen *screen,
8332 gtk_widget_queue_draw (GTK_WIDGET (window));
8334 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8338 gtk_window_check_screen (GtkWindow *window)
8340 GtkWindowPrivate *priv = window->priv;
8343 return priv->screen;
8346 g_warning ("Screen for GtkWindow not set; you must always set\n"
8347 "a screen for a GtkWindow before using the window");
8353 * gtk_window_get_screen:
8354 * @window: a #GtkWindow.
8356 * Returns the #GdkScreen associated with @window.
8358 * Return value: (transfer none): a #GdkScreen.
8363 gtk_window_get_screen (GtkWindow *window)
8365 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8367 return window->priv->screen;
8371 * gtk_window_is_active:
8372 * @window: a #GtkWindow
8374 * Returns whether the window is part of the current active toplevel.
8375 * (That is, the toplevel window receiving keystrokes.)
8376 * The return value is %TRUE if the window is active toplevel
8377 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8378 * You might use this function if you wanted to draw a widget
8379 * differently in an active window from a widget in an inactive window.
8380 * See gtk_window_has_toplevel_focus()
8382 * Return value: %TRUE if the window part of the current active window.
8387 gtk_window_is_active (GtkWindow *window)
8389 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8391 return window->priv->is_active;
8395 * gtk_window_has_toplevel_focus:
8396 * @window: a #GtkWindow
8398 * Returns whether the input focus is within this GtkWindow.
8399 * For real toplevel windows, this is identical to gtk_window_is_active(),
8400 * but for embedded windows, like #GtkPlug, the results will differ.
8402 * Return value: %TRUE if the input focus is within this GtkWindow
8407 gtk_window_has_toplevel_focus (GtkWindow *window)
8409 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8411 return window->priv->has_toplevel_focus;
8416 * SECTION:gtkwindowgroup
8417 * @Short_description: Limit the effect of grabs
8418 * @Title: GtkWindowGroup
8420 * #GtkWindowGroup objects are referenced by each window in the group,
8421 * so once you have added all windows to a #GtkWindowGroup, you can drop
8422 * the initial reference to the window group with g_object_unref(). If the
8423 * windows in the window group are subsequently destroyed, then they will
8424 * be removed from the window group and drop their references on the window
8425 * group; when all window have been removed, the window group will be
8429 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8432 gtk_window_group_init (GtkWindowGroup *group)
8434 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8435 GTK_TYPE_WINDOW_GROUP,
8436 GtkWindowGroupPrivate);
8440 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8442 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8446 * gtk_window_group_new:
8448 * Creates a new #GtkWindowGroup object. Grabs added with
8449 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8451 * Return value: a new #GtkWindowGroup.
8454 gtk_window_group_new (void)
8456 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8460 window_group_cleanup_grabs (GtkWindowGroup *group,
8463 GtkWindowGroupPrivate *priv;
8464 GtkDeviceGrabInfo *info;
8466 GSList *to_remove = NULL;
8470 tmp_list = priv->grabs;
8473 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8474 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8475 tmp_list = tmp_list->next;
8480 gtk_grab_remove (to_remove->data);
8481 g_object_unref (to_remove->data);
8482 to_remove = g_slist_delete_link (to_remove, to_remove);
8485 tmp_list = priv->device_grabs;
8489 info = tmp_list->data;
8491 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8492 to_remove = g_slist_prepend (to_remove, info);
8494 tmp_list = tmp_list->next;
8499 info = to_remove->data;
8501 gtk_device_grab_remove (info->widget, info->device);
8502 to_remove = g_slist_delete_link (to_remove, to_remove);
8507 * gtk_window_group_add_window:
8508 * @window_group: a #GtkWindowGroup
8509 * @window: the #GtkWindow to add
8511 * Adds a window to a #GtkWindowGroup.
8514 gtk_window_group_add_window (GtkWindowGroup *window_group,
8517 GtkWindowPrivate *priv;
8519 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8520 g_return_if_fail (GTK_IS_WINDOW (window));
8522 priv = window->priv;
8524 if (priv->group != window_group)
8526 g_object_ref (window);
8527 g_object_ref (window_group);
8530 gtk_window_group_remove_window (priv->group, window);
8532 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8534 priv->group = window_group;
8536 g_object_unref (window);
8541 * gtk_window_group_remove_window:
8542 * @window_group: a #GtkWindowGroup
8543 * @window: the #GtkWindow to remove
8545 * Removes a window from a #GtkWindowGroup.
8548 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8551 GtkWindowPrivate *priv;
8553 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8554 g_return_if_fail (GTK_IS_WINDOW (window));
8555 priv = window->priv;
8556 g_return_if_fail (priv->group == window_group);
8558 g_object_ref (window);
8560 window_group_cleanup_grabs (window_group, window);
8563 g_object_unref (window_group);
8564 g_object_unref (window);
8568 * gtk_window_group_list_windows:
8569 * @window_group: a #GtkWindowGroup
8571 * Returns a list of the #GtkWindows that belong to @window_group.
8573 * Returns: (element-type GtkWindow) (transfer container): A
8574 * newly-allocated list of windows inside the group.
8579 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8581 GList *toplevels, *toplevel, *group_windows;
8583 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8585 group_windows = NULL;
8586 toplevels = gtk_window_list_toplevels ();
8588 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8590 GtkWindow *window = toplevel->data;
8592 if (window_group == window->priv->group)
8593 group_windows = g_list_prepend (group_windows, window);
8596 g_list_free (toplevels);
8598 return g_list_reverse (group_windows);
8602 * gtk_window_get_group:
8603 * @window: (allow-none): a #GtkWindow, or %NULL
8605 * Returns the group for @window or the default group, if
8606 * @window is %NULL or if @window does not have an explicit
8609 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8614 gtk_window_get_group (GtkWindow *window)
8616 if (window && window->priv->group)
8617 return window->priv->group;
8620 static GtkWindowGroup *default_group = NULL;
8623 default_group = gtk_window_group_new ();
8625 return default_group;
8630 * gtk_window_has_group:
8631 * @window: a #GtkWindow
8633 * Returns whether @window has an explicit window group.
8635 * Return value: %TRUE if @window has an explicit window group.
8640 gtk_window_has_group (GtkWindow *window)
8642 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8644 return window->priv->group != NULL;
8648 * gtk_window_group_get_current_grab:
8649 * @window_group: a #GtkWindowGroup
8651 * Gets the current grab widget of the given group,
8652 * see gtk_grab_add().
8654 * Returns: (transfer none): the current grab widget of the group
8659 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8661 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8663 if (window_group->priv->grabs)
8664 return GTK_WIDGET (window_group->priv->grabs->data);
8669 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8672 GtkWindowGroupPrivate *priv;
8674 priv = window_group->priv;
8675 priv->grabs = g_slist_prepend (priv->grabs, widget);
8679 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8682 GtkWindowGroupPrivate *priv;
8684 priv = window_group->priv;
8685 priv->grabs = g_slist_remove (priv->grabs, widget);
8690 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8693 gboolean block_others)
8695 GtkWindowGroupPrivate *priv;
8696 GtkDeviceGrabInfo *info;
8698 priv = window_group->priv;
8700 info = g_slice_new0 (GtkDeviceGrabInfo);
8701 info->widget = widget;
8702 info->device = device;
8703 info->block_others = block_others;
8705 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8709 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8713 GtkWindowGroupPrivate *priv;
8714 GtkDeviceGrabInfo *info;
8715 GSList *list, *node = NULL;
8716 GdkDevice *other_device;
8718 priv = window_group->priv;
8719 other_device = gdk_device_get_associated_device (device);
8720 list = priv->device_grabs;
8726 if (info->widget == widget &&
8727 (info->device == device ||
8728 info->device == other_device))
8741 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8742 g_slice_free (GtkDeviceGrabInfo, info);
8747 * gtk_window_group_get_current_device_grab:
8748 * @window_group: a #GtkWindowGroup
8749 * @device: a #GdkDevice
8751 * Returns the current grab widget for @device, or %NULL if none.
8753 * Returns: (transfer none): The grab widget, or %NULL
8758 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8761 GtkWindowGroupPrivate *priv;
8762 GtkDeviceGrabInfo *info;
8763 GdkDevice *other_device;
8766 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8767 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8769 priv = window_group->priv;
8770 list = priv->device_grabs;
8771 other_device = gdk_device_get_associated_device (device);
8778 if (info->device == device ||
8779 info->device == other_device)
8780 return info->widget;
8787 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8791 GtkWindowGroupPrivate *priv;
8792 GtkDeviceGrabInfo *info;
8793 GdkDevice *other_device;
8796 priv = window_group->priv;
8797 other_device = gdk_device_get_associated_device (device);
8798 list = priv->device_grabs;
8805 /* Look for blocking grabs on other device pairs
8806 * that have the passed widget within the GTK+ grab.
8808 if (info->block_others &&
8809 info->device != device &&
8810 info->device != other_device &&
8811 (info->widget == widget ||
8812 gtk_widget_is_ancestor (widget, info->widget)))
8820 Derived from XParseGeometry() in XFree86
8822 Copyright 1985, 1986, 1987,1998 The Open Group
8824 All Rights Reserved.
8826 The above copyright notice and this permission notice shall be included
8827 in all copies or substantial portions of the Software.
8829 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8830 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8831 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8832 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8833 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8834 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8835 OTHER DEALINGS IN THE SOFTWARE.
8837 Except as contained in this notice, the name of The Open Group shall
8838 not be used in advertising or otherwise to promote the sale, use or
8839 other dealings in this Software without prior written authorization
8840 from The Open Group.
8845 * XParseGeometry parses strings of the form
8846 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8847 * width, height, xoffset, and yoffset are unsigned integers.
8848 * Example: "=80x24+300-49"
8849 * The equal sign is optional.
8850 * It returns a bitmask that indicates which of the four values
8851 * were actually found in the string. For each value found,
8852 * the corresponding argument is updated; for each value
8853 * not found, the corresponding argument is left unchanged.
8856 /* The following code is from Xlib, and is minimally modified, so we
8857 * can track any upstream changes if required. Don't change this
8858 * code. Or if you do, put in a huge comment marking which thing
8863 read_int (gchar *string,
8871 else if (*string == '-')
8877 for (; (*string >= '0') && (*string <= '9'); string++)
8879 result = (result * 10) + (*string - '0');
8891 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8892 * value (x, y, width, height) was found in the parsed string.
8894 #define NoValue 0x0000
8895 #define XValue 0x0001
8896 #define YValue 0x0002
8897 #define WidthValue 0x0004
8898 #define HeightValue 0x0008
8899 #define AllValues 0x000F
8900 #define XNegative 0x0010
8901 #define YNegative 0x0020
8903 /* Try not to reformat/modify, so we can compare/sync with X sources */
8905 gtk_XParseGeometry (const char *string,
8908 unsigned int *width,
8909 unsigned int *height)
8913 unsigned int tempWidth, tempHeight;
8915 char *nextCharacter;
8917 /* These initializations are just to silence gcc */
8923 if ( (string == NULL) || (*string == '\0')) return(mask);
8925 string++; /* ignore possible '=' at beg of geometry spec */
8927 strind = (char *)string;
8928 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8929 tempWidth = read_int(strind, &nextCharacter);
8930 if (strind == nextCharacter)
8932 strind = nextCharacter;
8936 if (*strind == 'x' || *strind == 'X') {
8938 tempHeight = read_int(strind, &nextCharacter);
8939 if (strind == nextCharacter)
8941 strind = nextCharacter;
8942 mask |= HeightValue;
8945 if ((*strind == '+') || (*strind == '-')) {
8946 if (*strind == '-') {
8948 tempX = -read_int(strind, &nextCharacter);
8949 if (strind == nextCharacter)
8951 strind = nextCharacter;
8957 tempX = read_int(strind, &nextCharacter);
8958 if (strind == nextCharacter)
8960 strind = nextCharacter;
8963 if ((*strind == '+') || (*strind == '-')) {
8964 if (*strind == '-') {
8966 tempY = -read_int(strind, &nextCharacter);
8967 if (strind == nextCharacter)
8969 strind = nextCharacter;
8976 tempY = read_int(strind, &nextCharacter);
8977 if (strind == nextCharacter)
8979 strind = nextCharacter;
8985 /* If strind isn't at the end of the string the it's an invalid
8986 geometry specification. */
8988 if (*strind != '\0') return (0);
8994 if (mask & WidthValue)
8996 if (mask & HeightValue)
8997 *height = tempHeight;
9002 * gtk_window_parse_geometry:
9003 * @window: a #GtkWindow
9004 * @geometry: geometry string
9006 * Parses a standard X Window System geometry string - see the
9007 * manual page for X (type 'man X') for details on this.
9008 * gtk_window_parse_geometry() does work on all GTK+ ports
9009 * including Win32 but is primarily intended for an X environment.
9011 * If either a size or a position can be extracted from the
9012 * geometry string, gtk_window_parse_geometry() returns %TRUE
9013 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9014 * to resize/move the window.
9016 * If gtk_window_parse_geometry() returns %TRUE, it will also
9017 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9018 * indicating to the window manager that the size/position of
9019 * the window was user-specified. This causes most window
9020 * managers to honor the geometry.
9022 * Note that for gtk_window_parse_geometry() to work as expected, it has
9023 * to be called when the window has its "final" size, i.e. after calling
9024 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9027 * #include <gtk/gtk.h>
9030 * fill_with_content (GtkWidget *vbox)
9032 * /* fill with content... */
9036 * main (int argc, char *argv[])
9038 * GtkWidget *window, *vbox;
9039 * GdkGeometry size_hints = {
9040 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9043 * gtk_init (&argc, &argv);
9045 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9046 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9048 * gtk_container_add (GTK_CONTAINER (window), vbox);
9049 * fill_with_content (vbox);
9050 * gtk_widget_show_all (vbox);
9052 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9055 * GDK_HINT_MIN_SIZE |
9056 * GDK_HINT_BASE_SIZE |
9057 * GDK_HINT_RESIZE_INC);
9061 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9062 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9065 * gtk_widget_show_all (window);
9072 * Return value: %TRUE if string was parsed successfully
9075 gtk_window_parse_geometry (GtkWindow *window,
9076 const gchar *geometry)
9078 gint result, x = 0, y = 0;
9082 gboolean size_set, pos_set;
9085 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9086 g_return_val_if_fail (geometry != NULL, FALSE);
9088 child = gtk_bin_get_child (GTK_BIN (window));
9089 if (!child || !gtk_widget_get_visible (child))
9090 g_warning ("gtk_window_parse_geometry() called on a window with no "
9091 "visible children; the window should be set up before "
9092 "gtk_window_parse_geometry() is called.");
9094 screen = gtk_window_check_screen (window);
9096 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9099 if ((result & WidthValue) || (result & HeightValue))
9101 gtk_window_set_default_size_internal (window,
9102 TRUE, result & WidthValue ? w : -1,
9103 TRUE, result & HeightValue ? h : -1,
9108 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9110 grav = GDK_GRAVITY_NORTH_WEST;
9112 if ((result & XNegative) && (result & YNegative))
9113 grav = GDK_GRAVITY_SOUTH_EAST;
9114 else if (result & XNegative)
9115 grav = GDK_GRAVITY_NORTH_EAST;
9116 else if (result & YNegative)
9117 grav = GDK_GRAVITY_SOUTH_WEST;
9119 if ((result & XValue) == 0)
9122 if ((result & YValue) == 0)
9125 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9126 grav == GDK_GRAVITY_SOUTH_EAST)
9127 y = gdk_screen_get_height (screen) - h + y;
9129 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9130 grav == GDK_GRAVITY_NORTH_EAST)
9131 x = gdk_screen_get_width (screen) - w + x;
9133 /* we don't let you put a window offscreen; maybe some people would
9134 * prefer to be able to, but it's kind of a bogus thing to do.
9143 if ((result & XValue) || (result & YValue))
9145 gtk_window_set_gravity (window, grav);
9146 gtk_window_move (window, x, y);
9150 if (size_set || pos_set)
9152 /* Set USSize, USPosition hints */
9153 GtkWindowGeometryInfo *info;
9155 info = gtk_window_get_geometry_info (window, TRUE);
9158 info->mask |= GDK_HINT_USER_POS;
9160 info->mask |= GDK_HINT_USER_SIZE;
9167 gtk_window_mnemonic_hash_foreach (guint keyval,
9173 GtkWindowKeysForeachFunc func;
9177 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9181 _gtk_window_keys_foreach (GtkWindow *window,
9182 GtkWindowKeysForeachFunc func,
9186 GtkMnemonicHash *mnemonic_hash;
9190 GtkWindowKeysForeachFunc func;
9194 info.window = window;
9196 info.func_data = func_data;
9198 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9200 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9201 gtk_window_mnemonic_hash_foreach, &info);
9203 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9206 GtkAccelGroup *group = groups->data;
9209 for (i = 0; i < group->priv->n_accels; i++)
9211 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9214 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9217 groups = groups->next;
9222 gtk_window_keys_changed (GtkWindow *window)
9224 gtk_window_free_key_hash (window);
9225 gtk_window_get_key_hash (window);
9228 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9230 struct _GtkWindowKeyEntry
9234 guint is_mnemonic : 1;
9238 window_key_entry_destroy (gpointer data)
9240 g_slice_free (GtkWindowKeyEntry, data);
9244 add_to_key_hash (GtkWindow *window,
9246 GdkModifierType modifiers,
9247 gboolean is_mnemonic,
9250 GtkKeyHash *key_hash = data;
9252 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9254 entry->keyval = keyval;
9255 entry->modifiers = modifiers;
9256 entry->is_mnemonic = is_mnemonic;
9258 /* GtkAccelGroup stores lowercased accelerators. To deal
9259 * with this, if <Shift> was specified, uppercase.
9261 if (modifiers & GDK_SHIFT_MASK)
9263 if (keyval == GDK_KEY_Tab)
9264 keyval = GDK_KEY_ISO_Left_Tab;
9266 keyval = gdk_keyval_to_upper (keyval);
9269 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9273 gtk_window_get_key_hash (GtkWindow *window)
9275 GdkScreen *screen = gtk_window_check_screen (window);
9276 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9281 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9282 (GDestroyNotify)window_key_entry_destroy);
9283 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9284 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9290 gtk_window_free_key_hash (GtkWindow *window)
9292 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9295 _gtk_key_hash_free (key_hash);
9296 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9301 * gtk_window_activate_key:
9302 * @window: a #GtkWindow
9303 * @event: a #GdkEventKey
9305 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9306 * called by the default ::key_press_event handler for toplevel windows,
9307 * however in some cases it may be useful to call this directly when
9308 * overriding the standard key handling for a toplevel window.
9310 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9315 gtk_window_activate_key (GtkWindow *window,
9318 GtkKeyHash *key_hash;
9319 GtkWindowKeyEntry *found_entry = NULL;
9320 gboolean enable_mnemonics;
9321 gboolean enable_accels;
9323 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9324 g_return_val_if_fail (event != NULL, FALSE);
9326 key_hash = gtk_window_get_key_hash (window);
9331 GSList *entries = _gtk_key_hash_lookup (key_hash,
9332 event->hardware_keycode,
9334 gtk_accelerator_get_default_mod_mask (),
9337 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9338 "gtk-enable-mnemonics", &enable_mnemonics,
9339 "gtk-enable-accels", &enable_accels,
9342 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9344 GtkWindowKeyEntry *entry = tmp_list->data;
9345 if (entry->is_mnemonic)
9347 if (enable_mnemonics)
9349 found_entry = entry;
9355 if (enable_accels && !found_entry)
9357 found_entry = entry;
9362 g_slist_free (entries);
9367 if (found_entry->is_mnemonic)
9369 if (enable_mnemonics)
9370 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9371 found_entry->modifiers);
9376 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9377 found_entry->modifiers);
9385 window_update_has_focus (GtkWindow *window)
9387 GtkWindowPrivate *priv = window->priv;
9388 GtkWidget *widget = GTK_WIDGET (window);
9389 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9391 if (has_focus != priv->has_focus)
9393 priv->has_focus = has_focus;
9397 if (priv->focus_widget &&
9398 priv->focus_widget != widget &&
9399 !gtk_widget_has_focus (priv->focus_widget))
9400 do_focus_change (priv->focus_widget, TRUE);
9404 if (priv->focus_widget &&
9405 priv->focus_widget != widget &&
9406 gtk_widget_has_focus (priv->focus_widget))
9407 do_focus_change (priv->focus_widget, FALSE);
9413 * _gtk_window_set_is_active:
9414 * @window: a #GtkWindow
9415 * @is_active: %TRUE if the window is in the currently active toplevel
9417 * Internal function that sets whether the #GtkWindow is part
9418 * of the currently active toplevel window (taking into account inter-process
9422 _gtk_window_set_is_active (GtkWindow *window,
9425 GtkWindowPrivate *priv;
9427 g_return_if_fail (GTK_IS_WINDOW (window));
9429 priv = window->priv;
9431 is_active = is_active != FALSE;
9433 if (is_active != priv->is_active)
9435 priv->is_active = is_active;
9436 window_update_has_focus (window);
9438 g_object_notify (G_OBJECT (window), "is-active");
9443 * _gtk_window_set_is_toplevel:
9444 * @window: a #GtkWindow
9445 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9446 * child of the root window); %FALSE if it is not (for example, for an
9447 * in-process, parented GtkPlug)
9449 * Internal function used by #GtkPlug when it gets parented/unparented by a
9450 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9451 * global list of toplevel windows.
9454 _gtk_window_set_is_toplevel (GtkWindow *window,
9455 gboolean is_toplevel)
9458 GtkWidget *toplevel;
9460 widget = GTK_WIDGET (window);
9462 if (gtk_widget_is_toplevel (widget))
9463 g_assert (g_slist_find (toplevel_list, window) != NULL);
9465 g_assert (g_slist_find (toplevel_list, window) == NULL);
9467 if (is_toplevel == gtk_widget_is_toplevel (widget))
9472 /* Pass through regular pathways of an embedded toplevel
9473 * to go through unmapping and hiding the widget before
9474 * becomming a toplevel again.
9476 * We remain hidden after becomming toplevel in order to
9477 * avoid problems during an embedded toplevel's dispose cycle
9478 * (When a toplevel window is shown it tries to grab focus again,
9479 * this causes problems while disposing).
9481 gtk_widget_hide (widget);
9483 /* Save the toplevel this widget was previously anchored into before
9484 * propagating a hierarchy-changed.
9486 * Usually this happens by way of gtk_widget_unparent() and we are
9487 * already unanchored at this point, just adding this clause incase
9488 * things happen differently.
9490 toplevel = gtk_widget_get_toplevel (widget);
9491 if (!gtk_widget_is_toplevel (toplevel))
9494 _gtk_widget_set_is_toplevel (widget, TRUE);
9496 /* When a window becomes toplevel after being embedded and anchored
9497 * into another window we need to unset its anchored flag so that
9498 * the hierarchy changed signal kicks in properly.
9500 _gtk_widget_set_anchored (widget, FALSE);
9501 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9503 toplevel_list = g_slist_prepend (toplevel_list, window);
9507 _gtk_widget_set_is_toplevel (widget, FALSE);
9508 toplevel_list = g_slist_remove (toplevel_list, window);
9510 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9515 * _gtk_window_set_has_toplevel_focus:
9516 * @window: a #GtkWindow
9517 * @has_toplevel_focus: %TRUE if the in
9519 * Internal function that sets whether the keyboard focus for the
9520 * toplevel window (taking into account inter-process embedding.)
9523 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9524 gboolean has_toplevel_focus)
9526 GtkWindowPrivate *priv;
9528 g_return_if_fail (GTK_IS_WINDOW (window));
9530 priv = window->priv;
9532 has_toplevel_focus = has_toplevel_focus != FALSE;
9534 if (has_toplevel_focus != priv->has_toplevel_focus)
9536 priv->has_toplevel_focus = has_toplevel_focus;
9537 window_update_has_focus (window);
9539 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9544 * gtk_window_set_auto_startup_notification:
9545 * @setting: %TRUE to automatically do startup notification
9547 * By default, after showing the first #GtkWindow, GTK+ calls
9548 * gdk_notify_startup_complete(). Call this function to disable
9549 * the automatic startup notification. You might do this if your
9550 * first window is a splash screen, and you want to delay notification
9551 * until after your real main window has been shown, for example.
9553 * In that example, you would disable startup notification
9554 * temporarily, show your splash screen, then re-enable it so that
9555 * showing the main window would automatically result in notification.
9560 gtk_window_set_auto_startup_notification (gboolean setting)
9562 disable_startup_notification = !setting;
9566 * gtk_window_get_window_type:
9567 * @window: a #GtkWindow
9569 * Gets the type of the window. See #GtkWindowType.
9571 * Return value: the type of the window
9576 gtk_window_get_window_type (GtkWindow *window)
9578 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9580 return window->priv->type;
9584 * gtk_window_get_mnemonics_visible:
9585 * @window: a #GtkWindow
9587 * Gets the value of the #GtkWindow:mnemonics-visible property.
9589 * Returns: %TRUE if mnemonics are supposed to be visible
9595 gtk_window_get_mnemonics_visible (GtkWindow *window)
9597 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9599 return window->priv->mnemonics_visible;
9603 * gtk_window_set_mnemonics_visible:
9604 * @window: a #GtkWindow
9605 * @setting: the new value
9607 * Sets the #GtkWindow:mnemonics-visible property.
9612 gtk_window_set_mnemonics_visible (GtkWindow *window,
9615 GtkWindowPrivate *priv;
9617 g_return_if_fail (GTK_IS_WINDOW (window));
9619 priv = window->priv;
9621 setting = setting != FALSE;
9623 if (priv->mnemonics_visible != setting)
9625 priv->mnemonics_visible = setting;
9626 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9629 priv->mnemonics_visible_set = TRUE;
9633 * gtk_window_get_focus_visible:
9634 * @window: a #GtkWindow
9636 * Gets the value of the #GtkWindow:focus-visible property.
9638 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9644 gtk_window_get_focus_visible (GtkWindow *window)
9646 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9648 return window->priv->focus_visible;
9652 * gtk_window_set_focus_visible:
9653 * @window: a #GtkWindow
9654 * @setting: the new value
9656 * Sets the #GtkWindow:focus-visible property.
9661 gtk_window_set_focus_visible (GtkWindow *window,
9664 GtkWindowPrivate *priv;
9666 g_return_if_fail (GTK_IS_WINDOW (window));
9668 priv = window->priv;
9670 setting = setting != FALSE;
9672 if (priv->focus_visible != setting)
9674 priv->focus_visible = setting;
9675 g_object_notify (G_OBJECT (window), "focus-visible");
9680 _gtk_window_get_wmclass (GtkWindow *window,
9681 gchar **wmclass_name,
9682 gchar **wmclass_class)
9684 GtkWindowPrivate *priv = window->priv;
9686 *wmclass_name = priv->wmclass_name;
9687 *wmclass_class = priv->wmclass_class;
9691 * gtk_window_set_has_user_ref_count:
9692 * @window: a #GtkWindow
9693 * @setting: the new value
9695 * Tells GTK+ whether to drop its extra reference to the window
9696 * when gtk_window_destroy() is called.
9698 * This function is only exported for the benefit of language
9699 * bindings which may need to keep the window alive until their
9700 * wrapper object is garbage collected. There is no justification
9701 * for ever calling this function in an application.
9706 gtk_window_set_has_user_ref_count (GtkWindow *window,
9709 g_return_if_fail (GTK_IS_WINDOW (window));
9711 window->priv->has_user_ref_count = setting;
9715 ensure_state_flag_window_unfocused (GtkWidget *widget)
9718 gboolean window_focused = TRUE;
9720 window = gtk_widget_get_window (widget);
9722 window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9724 if (!window_focused)
9725 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED, FALSE);
9727 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED);
9729 gtk_widget_queue_draw (widget);