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 iconify_initially : 1; /* gtk_window_iconify() called before realization */
157 guint maximize_initially : 1;
158 guint mnemonics_visible : 1;
159 guint mnemonics_visible_set : 1;
160 guint focus_visible : 1;
162 guint opacity_set : 1;
164 guint reset_type_hint : 1;
166 guint skips_pager : 1;
167 guint skips_taskbar : 1;
168 guint stick_initially : 1;
169 guint transient_parent_group : 1;
170 guint type : 4; /* GtkWindowType */
171 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
172 * one of the original eight. If not,
174 * GDK_WINDOW_TYPE_HINT_NORMAL
177 guint has_resize_grip : 1;
178 guint resize_grip_visible : 1; /* don't use, just for "resize-
179 * grip-visible" notification
181 guint gravity : 5; /* GdkGravity */
208 PROP_DESTROY_WITH_PARENT,
213 PROP_SKIP_TASKBAR_HINT,
214 PROP_SKIP_PAGER_HINT,
223 PROP_HAS_RESIZE_GRIP,
224 PROP_RESIZE_GRIP_VISIBLE,
226 /* Readonly properties */
228 PROP_HAS_TOPLEVEL_FOCUS,
230 /* Writeonly properties */
233 PROP_MNEMONICS_VISIBLE,
244 guint using_default_icon : 1;
245 guint using_parent_icon : 1;
246 guint using_themed_icon : 1;
250 GdkGeometry geometry; /* Last set of geometry hints we set */
251 GdkWindowHints flags;
252 GdkRectangle configure_request;
253 } GtkWindowLastGeometryInfo;
255 struct _GtkWindowGeometryInfo
257 /* Properties that the app has set on the window
259 GdkGeometry geometry; /* Geometry hints */
261 GtkWidget *widget; /* subwidget to which hints apply */
262 /* from last gtk_window_resize () - if > 0, indicates that
263 * we should resize to this size.
268 /* From last gtk_window_move () prior to mapping -
269 * only used if initial_pos_set
274 /* Default size - used only the FIRST time we map a window,
279 /* whether to use initial_x, initial_y */
280 guint initial_pos_set : 1;
281 /* CENTER_ALWAYS or other position constraint changed since
282 * we sent the last configure request.
284 guint position_constraints_changed : 1;
286 /* if true, default_width, height should be multiplied by the
287 * increments and affect the geometry widget only
289 guint default_is_geometry : 1;
291 /* if true, resize_width, height should be multiplied by the
292 * increments and affect the geometry widget only
294 guint resize_is_geometry : 1;
296 GtkWindowLastGeometryInfo last;
300 struct _GtkDeviceGrabInfo
304 guint block_others : 1;
307 struct _GtkWindowGroupPrivate
310 GSList *device_grabs;
313 static void gtk_window_dispose (GObject *object);
314 static void gtk_window_finalize (GObject *object);
315 static void gtk_window_destroy (GtkWidget *widget);
316 static void gtk_window_show (GtkWidget *widget);
317 static void gtk_window_hide (GtkWidget *widget);
318 static void gtk_window_map (GtkWidget *widget);
319 static void gtk_window_unmap (GtkWidget *widget);
320 static void gtk_window_realize (GtkWidget *widget);
321 static void gtk_window_unrealize (GtkWidget *widget);
322 static void gtk_window_size_allocate (GtkWidget *widget,
323 GtkAllocation *allocation);
324 static gboolean gtk_window_map_event (GtkWidget *widget,
326 static gint gtk_window_configure_event (GtkWidget *widget,
327 GdkEventConfigure *event);
328 static gint gtk_window_key_press_event (GtkWidget *widget,
330 static gint gtk_window_key_release_event (GtkWidget *widget,
332 static gint gtk_window_button_press_event (GtkWidget *widget,
333 GdkEventButton *event);
334 static gint gtk_window_enter_notify_event (GtkWidget *widget,
335 GdkEventCrossing *event);
336 static gint gtk_window_leave_notify_event (GtkWidget *widget,
337 GdkEventCrossing *event);
338 static gint gtk_window_focus_in_event (GtkWidget *widget,
339 GdkEventFocus *event);
340 static gint gtk_window_focus_out_event (GtkWidget *widget,
341 GdkEventFocus *event);
342 static void gtk_window_style_updated (GtkWidget *widget);
343 static gboolean gtk_window_state_event (GtkWidget *widget,
344 GdkEventWindowState *event);
345 static void gtk_window_check_resize (GtkContainer *container);
346 static gint gtk_window_focus (GtkWidget *widget,
347 GtkDirectionType direction);
348 static void gtk_window_move_focus (GtkWidget *widget,
349 GtkDirectionType dir);
350 static void gtk_window_real_set_focus (GtkWindow *window,
352 static void gtk_window_direction_changed (GtkWidget *widget,
353 GtkTextDirection prev_dir);
354 static void gtk_window_state_changed (GtkWidget *widget,
355 GtkStateType previous_state);
357 static void gtk_window_real_activate_default (GtkWindow *window);
358 static void gtk_window_real_activate_focus (GtkWindow *window);
359 static void gtk_window_keys_changed (GtkWindow *window);
360 static gint gtk_window_draw (GtkWidget *widget,
362 static void gtk_window_unset_transient_for (GtkWindow *window);
363 static void gtk_window_transient_parent_realized (GtkWidget *parent,
365 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
368 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
370 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
373 static void gtk_window_move_resize (GtkWindow *window);
374 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
376 GdkGeometry *geometry_b,
378 static void gtk_window_constrain_size (GtkWindow *window,
379 GdkGeometry *geometry,
385 static void gtk_window_constrain_position (GtkWindow *window,
390 static void gtk_window_compute_hints (GtkWindow *window,
391 GdkGeometry *new_geometry,
393 static void gtk_window_compute_configure_request (GtkWindow *window,
394 GdkRectangle *request,
395 GdkGeometry *geometry,
398 static void gtk_window_set_default_size_internal (GtkWindow *window,
399 gboolean change_width,
401 gboolean change_height,
403 gboolean is_geometry);
405 static void update_themed_icon (GtkIconTheme *theme,
407 static GList *icon_list_from_theme (GtkWidget *widget,
409 static void gtk_window_realize_icon (GtkWindow *window);
410 static void gtk_window_unrealize_icon (GtkWindow *window);
411 static void resize_grip_create_window (GtkWindow *window);
412 static void resize_grip_destroy_window (GtkWindow *window);
413 static void update_grip_visibility (GtkWindow *window);
415 static void gtk_window_notify_keys_changed (GtkWindow *window);
416 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
417 static void gtk_window_free_key_hash (GtkWindow *window);
418 static void gtk_window_on_composited_changed (GdkScreen *screen,
420 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
423 static void gtk_window_set_theme_variant (GtkWindow *window);
425 static GSList *toplevel_list = NULL;
426 static guint window_signals[LAST_SIGNAL] = { 0 };
427 static GList *default_icon_list = NULL;
428 static gchar *default_icon_name = NULL;
429 static guint default_icon_serial = 0;
430 static gboolean disable_startup_notification = FALSE;
431 static gboolean sent_startup_notification = FALSE;
433 static GQuark quark_gtk_embedded = 0;
434 static GQuark quark_gtk_window_key_hash = 0;
435 static GQuark quark_gtk_window_icon_info = 0;
436 static GQuark quark_gtk_buildable_accels = 0;
438 static GtkBuildableIface *parent_buildable_iface;
440 static void gtk_window_set_property (GObject *object,
444 static void gtk_window_get_property (GObject *object,
450 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
451 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
454 const GValue *value);
455 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
456 GtkBuilder *builder);
457 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
460 const gchar *tagname,
461 GMarkupParser *parser,
463 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
466 const gchar *tagname,
470 static void gtk_window_get_preferred_width (GtkWidget *widget,
473 static void gtk_window_get_preferred_height (GtkWidget *widget,
477 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
478 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
479 gtk_window_buildable_interface_init))
482 add_tab_bindings (GtkBindingSet *binding_set,
483 GdkModifierType modifiers,
484 GtkDirectionType direction)
486 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
488 GTK_TYPE_DIRECTION_TYPE, direction);
489 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
491 GTK_TYPE_DIRECTION_TYPE, direction);
495 add_arrow_bindings (GtkBindingSet *binding_set,
497 GtkDirectionType direction)
499 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
501 gtk_binding_entry_add_signal (binding_set, keysym, 0,
503 GTK_TYPE_DIRECTION_TYPE, direction);
504 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
506 GTK_TYPE_DIRECTION_TYPE, direction);
507 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
509 GTK_TYPE_DIRECTION_TYPE, direction);
510 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
512 GTK_TYPE_DIRECTION_TYPE, direction);
516 extract_time_from_startup_id (const gchar* startup_id)
518 gchar *timestr = g_strrstr (startup_id, "_TIME");
519 guint32 retval = GDK_CURRENT_TIME;
526 /* Skip past the "_TIME" part */
531 timestamp = g_ascii_strtoull (timestr, &end, 0);
532 if (errno == 0 && end != timestr)
540 startup_id_is_fake (const gchar* startup_id)
542 return strncmp (startup_id, "_TIME", 5) == 0;
546 gtk_window_class_init (GtkWindowClass *klass)
548 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
549 GtkWidgetClass *widget_class;
550 GtkContainerClass *container_class;
551 GtkBindingSet *binding_set;
553 widget_class = (GtkWidgetClass*) klass;
554 container_class = (GtkContainerClass*) klass;
556 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
557 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
558 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
559 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
561 gobject_class->dispose = gtk_window_dispose;
562 gobject_class->finalize = gtk_window_finalize;
564 gobject_class->set_property = gtk_window_set_property;
565 gobject_class->get_property = gtk_window_get_property;
567 widget_class->destroy = gtk_window_destroy;
568 widget_class->show = gtk_window_show;
569 widget_class->hide = gtk_window_hide;
570 widget_class->map = gtk_window_map;
571 widget_class->map_event = gtk_window_map_event;
572 widget_class->unmap = gtk_window_unmap;
573 widget_class->realize = gtk_window_realize;
574 widget_class->unrealize = gtk_window_unrealize;
575 widget_class->size_allocate = gtk_window_size_allocate;
576 widget_class->configure_event = gtk_window_configure_event;
577 widget_class->key_press_event = gtk_window_key_press_event;
578 widget_class->key_release_event = gtk_window_key_release_event;
579 widget_class->enter_notify_event = gtk_window_enter_notify_event;
580 widget_class->leave_notify_event = gtk_window_leave_notify_event;
581 widget_class->focus_in_event = gtk_window_focus_in_event;
582 widget_class->button_press_event = gtk_window_button_press_event;
583 widget_class->focus_out_event = gtk_window_focus_out_event;
584 widget_class->focus = gtk_window_focus;
585 widget_class->move_focus = gtk_window_move_focus;
586 widget_class->draw = gtk_window_draw;
587 widget_class->get_preferred_width = gtk_window_get_preferred_width;
588 widget_class->get_preferred_height = gtk_window_get_preferred_height;
589 widget_class->window_state_event = gtk_window_state_event;
590 widget_class->direction_changed = gtk_window_direction_changed;
591 widget_class->state_changed = gtk_window_state_changed;
592 widget_class->style_updated = gtk_window_style_updated;
594 container_class->check_resize = gtk_window_check_resize;
596 klass->set_focus = gtk_window_real_set_focus;
598 klass->activate_default = gtk_window_real_activate_default;
599 klass->activate_focus = gtk_window_real_activate_focus;
600 klass->keys_changed = gtk_window_keys_changed;
602 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
605 g_object_class_install_property (gobject_class,
607 g_param_spec_enum ("type",
609 P_("The type of the window"),
610 GTK_TYPE_WINDOW_TYPE,
612 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
614 g_object_class_install_property (gobject_class,
616 g_param_spec_string ("title",
618 P_("The title of the window"),
620 GTK_PARAM_READWRITE));
622 g_object_class_install_property (gobject_class,
624 g_param_spec_string ("role",
626 P_("Unique identifier for the window to be used when restoring a session"),
628 GTK_PARAM_READWRITE));
631 * GtkWindow:startup-id:
633 * The :startup-id is a write-only property for setting window's
634 * startup notification identifier. See gtk_window_set_startup_id()
639 g_object_class_install_property (gobject_class,
641 g_param_spec_string ("startup-id",
643 P_("Unique startup identifier for the window used by startup-notification"),
645 GTK_PARAM_WRITABLE));
647 g_object_class_install_property (gobject_class,
649 g_param_spec_boolean ("resizable",
651 P_("If TRUE, users can resize the window"),
653 GTK_PARAM_READWRITE));
655 g_object_class_install_property (gobject_class,
657 g_param_spec_boolean ("modal",
659 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
661 GTK_PARAM_READWRITE));
663 g_object_class_install_property (gobject_class,
665 g_param_spec_enum ("window-position",
666 P_("Window Position"),
667 P_("The initial position of the window"),
668 GTK_TYPE_WINDOW_POSITION,
670 GTK_PARAM_READWRITE));
672 g_object_class_install_property (gobject_class,
674 g_param_spec_int ("default-width",
676 P_("The default width of the window, used when initially showing the window"),
680 GTK_PARAM_READWRITE));
682 g_object_class_install_property (gobject_class,
684 g_param_spec_int ("default-height",
685 P_("Default Height"),
686 P_("The default height of the window, used when initially showing the window"),
690 GTK_PARAM_READWRITE));
692 g_object_class_install_property (gobject_class,
693 PROP_DESTROY_WITH_PARENT,
694 g_param_spec_boolean ("destroy-with-parent",
695 P_("Destroy with Parent"),
696 P_("If this window should be destroyed when the parent is destroyed"),
698 GTK_PARAM_READWRITE));
700 g_object_class_install_property (gobject_class,
702 g_param_spec_object ("icon",
704 P_("Icon for this window"),
706 GTK_PARAM_READWRITE));
709 * GtkWindow:mnemonics-visible:
711 * Whether mnemonics are currently visible in this window.
713 * This property is maintained by GTK+ based on the
714 * #GtkSettings:gtk-auto-mnemonics setting and user input,
715 * and should not be set by applications.
719 g_object_class_install_property (gobject_class,
720 PROP_MNEMONICS_VISIBLE,
721 g_param_spec_boolean ("mnemonics-visible",
722 P_("Mnemonics Visible"),
723 P_("Whether mnemonics are currently visible in this window"),
725 GTK_PARAM_READWRITE));
728 * GtkWindow:focus-visible:
730 * Whether 'focus rectangles' are currently visible in this window.
732 * This property is maintained by GTK+ based on the
733 * #GtkSettings:gtk-visible-focus setting and user input
734 * and should not be set by applications.
738 g_object_class_install_property (gobject_class,
740 g_param_spec_boolean ("focus-visible",
742 P_("Whether focus rectangles are currently visible in this window"),
744 GTK_PARAM_READWRITE));
747 * GtkWindow:icon-name:
749 * The :icon-name property specifies the name of the themed icon to
750 * use as the window icon. See #GtkIconTheme for more details.
754 g_object_class_install_property (gobject_class,
756 g_param_spec_string ("icon-name",
758 P_("Name of the themed icon for this window"),
760 GTK_PARAM_READWRITE));
762 g_object_class_install_property (gobject_class,
764 g_param_spec_object ("screen",
766 P_("The screen where this window will be displayed"),
768 GTK_PARAM_READWRITE));
770 g_object_class_install_property (gobject_class,
772 g_param_spec_boolean ("is-active",
774 P_("Whether the toplevel is the current active window"),
776 GTK_PARAM_READABLE));
778 g_object_class_install_property (gobject_class,
779 PROP_HAS_TOPLEVEL_FOCUS,
780 g_param_spec_boolean ("has-toplevel-focus",
781 P_("Focus in Toplevel"),
782 P_("Whether the input focus is within this GtkWindow"),
784 GTK_PARAM_READABLE));
786 g_object_class_install_property (gobject_class,
788 g_param_spec_enum ("type-hint",
790 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
791 GDK_TYPE_WINDOW_TYPE_HINT,
792 GDK_WINDOW_TYPE_HINT_NORMAL,
793 GTK_PARAM_READWRITE));
795 g_object_class_install_property (gobject_class,
796 PROP_SKIP_TASKBAR_HINT,
797 g_param_spec_boolean ("skip-taskbar-hint",
799 P_("TRUE if the window should not be in the task bar."),
801 GTK_PARAM_READWRITE));
803 g_object_class_install_property (gobject_class,
804 PROP_SKIP_PAGER_HINT,
805 g_param_spec_boolean ("skip-pager-hint",
807 P_("TRUE if the window should not be in the pager."),
809 GTK_PARAM_READWRITE));
811 g_object_class_install_property (gobject_class,
813 g_param_spec_boolean ("urgency-hint",
815 P_("TRUE if the window should be brought to the user's attention."),
817 GTK_PARAM_READWRITE));
820 * GtkWindow:accept-focus:
822 * Whether the window should receive the input focus.
826 g_object_class_install_property (gobject_class,
828 g_param_spec_boolean ("accept-focus",
830 P_("TRUE if the window should receive the input focus."),
832 GTK_PARAM_READWRITE));
835 * GtkWindow:focus-on-map:
837 * Whether the window should receive the input focus when mapped.
841 g_object_class_install_property (gobject_class,
843 g_param_spec_boolean ("focus-on-map",
845 P_("TRUE if the window should receive the input focus when mapped."),
847 GTK_PARAM_READWRITE));
850 * GtkWindow:decorated:
852 * Whether the window should be decorated by the window manager.
856 g_object_class_install_property (gobject_class,
858 g_param_spec_boolean ("decorated",
860 P_("Whether the window should be decorated by the window manager"),
862 GTK_PARAM_READWRITE));
865 * GtkWindow:deletable:
867 * Whether the window frame should have a close button.
871 g_object_class_install_property (gobject_class,
873 g_param_spec_boolean ("deletable",
875 P_("Whether the window frame should have a close button"),
877 GTK_PARAM_READWRITE));
880 * GtkWindow:has-resize-grip
882 * Whether the window has a corner resize grip.
884 * Note that the resize grip is only shown if the window is
885 * actually resizable and not maximized. Use
886 * #GtkWindow:resize-grip-visible to find out if the resize
887 * grip is currently shown.
891 g_object_class_install_property (gobject_class,
892 PROP_HAS_RESIZE_GRIP,
893 g_param_spec_boolean ("has-resize-grip",
895 P_("Specifies whether the window should have a resize grip"),
897 GTK_PARAM_READWRITE));
900 * GtkWindow:resize-grip-visible:
902 * Whether a corner resize grip is currently shown.
906 g_object_class_install_property (gobject_class,
907 PROP_RESIZE_GRIP_VISIBLE,
908 g_param_spec_boolean ("resize-grip-visible",
909 P_("Resize grip is visible"),
910 P_("Specifies whether the window's resize grip is visible."),
912 GTK_PARAM_READABLE));
918 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
919 * more details about window gravity.
923 g_object_class_install_property (gobject_class,
925 g_param_spec_enum ("gravity",
927 P_("The window gravity of the window"),
929 GDK_GRAVITY_NORTH_WEST,
930 GTK_PARAM_READWRITE));
934 * GtkWindow:transient-for:
936 * The transient parent of the window. See gtk_window_set_transient_for() for
937 * more details about transient windows.
941 g_object_class_install_property (gobject_class,
943 g_param_spec_object ("transient-for",
944 P_("Transient for Window"),
945 P_("The transient parent of the dialog"),
947 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
952 * The requested opacity of the window. See gtk_window_set_opacity() for
953 * more details about window opacity.
957 g_object_class_install_property (gobject_class,
959 g_param_spec_double ("opacity",
960 P_("Opacity for Window"),
961 P_("The opacity of the window, from 0 to 1"),
965 GTK_PARAM_READWRITE));
969 gtk_widget_class_install_style_property (widget_class,
970 g_param_spec_int ("resize-grip-width",
971 P_("Width of resize grip"),
972 P_("Width of resize grip"),
973 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
975 gtk_widget_class_install_style_property (widget_class,
976 g_param_spec_int ("resize-grip-height",
977 P_("Height of resize grip"),
978 P_("Height of resize grip"),
979 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
983 * GtkWindow:application:
985 * The #GtkApplication associated with the window.
987 * The application will be kept alive for at least as long as it
988 * has any windows associated with it (see g_application_hold()
989 * for a way to keep it alive without windows).
991 * Normally, the connection between the application and the window
992 * will remain until the window is destroyed, but you can explicitly
993 * remove it by setting the ::application property to %NULL.
997 g_object_class_install_property (gobject_class,
999 g_param_spec_object ("application",
1000 P_("GtkApplication"),
1001 P_("The GtkApplication for the window"),
1002 GTK_TYPE_APPLICATION,
1003 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1005 window_signals[SET_FOCUS] =
1006 g_signal_new (I_("set-focus"),
1007 G_TYPE_FROM_CLASS (gobject_class),
1009 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1011 _gtk_marshal_VOID__OBJECT,
1016 * GtkWindow::activate-focus:
1017 * @window: the window which received the signal
1019 * The ::activate-focus signal is a
1020 * <link linkend="keybinding-signals">keybinding signal</link>
1021 * which gets emitted when the user activates the currently
1022 * focused widget of @window.
1024 window_signals[ACTIVATE_FOCUS] =
1025 g_signal_new (I_("activate-focus"),
1026 G_TYPE_FROM_CLASS (gobject_class),
1027 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1028 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1030 _gtk_marshal_VOID__VOID,
1035 * GtkWindow::activate-default:
1036 * @window: the window which received the signal
1038 * The ::activate-default signal is a
1039 * <link linkend="keybinding-signals">keybinding signal</link>
1040 * which gets emitted when the user activates the default widget
1043 window_signals[ACTIVATE_DEFAULT] =
1044 g_signal_new (I_("activate-default"),
1045 G_TYPE_FROM_CLASS (gobject_class),
1046 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1047 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1049 _gtk_marshal_VOID__VOID,
1054 * GtkWindow::keys-changed:
1055 * @window: the window which received the signal
1057 * The ::keys-changed signal gets emitted when the set of accelerators
1058 * or mnemonics that are associated with @window changes.
1060 window_signals[KEYS_CHANGED] =
1061 g_signal_new (I_("keys-changed"),
1062 G_TYPE_FROM_CLASS (gobject_class),
1064 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1066 _gtk_marshal_VOID__VOID,
1074 binding_set = gtk_binding_set_by_class (klass);
1076 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1077 "activate-focus", 0);
1078 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1079 "activate-focus", 0);
1081 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1082 "activate-default", 0);
1083 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1084 "activate-default", 0);
1085 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1086 "activate-default", 0);
1088 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1089 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1090 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1091 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1093 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1094 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1095 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1096 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1098 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1102 gtk_window_init (GtkWindow *window)
1104 GtkWindowPrivate *priv;
1106 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1109 priv = window->priv;
1111 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1112 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1114 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1116 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1119 priv->wmclass_name = g_strdup (g_get_prgname ());
1120 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1121 priv->wm_role = NULL;
1122 priv->geometry_info = NULL;
1123 priv->type = GTK_WINDOW_TOPLEVEL;
1124 priv->focus_widget = NULL;
1125 priv->default_widget = NULL;
1126 priv->configure_request_count = 0;
1127 priv->resizable = TRUE;
1128 priv->configure_notify_received = FALSE;
1129 priv->position = GTK_WIN_POS_NONE;
1130 priv->need_default_size = TRUE;
1131 priv->need_default_position = TRUE;
1132 priv->modal = FALSE;
1133 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1134 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1135 priv->decorated = TRUE;
1136 priv->mnemonic_modifier = GDK_MOD1_MASK;
1137 priv->screen = gdk_screen_get_default ();
1139 priv->accept_focus = TRUE;
1140 priv->focus_on_map = TRUE;
1141 priv->deletable = TRUE;
1142 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1143 priv->opacity = 1.0;
1144 priv->startup_id = NULL;
1145 priv->initial_timestamp = GDK_CURRENT_TIME;
1146 priv->has_resize_grip = TRUE;
1147 priv->mnemonics_visible = TRUE;
1148 priv->focus_visible = TRUE;
1150 g_object_ref_sink (window);
1151 priv->has_user_ref_count = TRUE;
1152 toplevel_list = g_slist_prepend (toplevel_list, window);
1155 g_signal_connect (priv->screen, "composited-changed",
1156 G_CALLBACK (gtk_window_on_composited_changed), window);
1158 #ifdef GDK_WINDOWING_X11
1159 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1160 "notify::gtk-application-prefer-dark-theme",
1161 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1166 gtk_window_set_property (GObject *object,
1168 const GValue *value,
1171 GtkWindow *window = GTK_WINDOW (object);
1172 GtkWindowPrivate *priv = window->priv;
1177 priv->type = g_value_get_enum (value);
1180 gtk_window_set_title (window, g_value_get_string (value));
1183 gtk_window_set_role (window, g_value_get_string (value));
1185 case PROP_STARTUP_ID:
1186 gtk_window_set_startup_id (window, g_value_get_string (value));
1188 case PROP_RESIZABLE:
1189 gtk_window_set_resizable (window, g_value_get_boolean (value));
1192 gtk_window_set_modal (window, g_value_get_boolean (value));
1195 gtk_window_set_position (window, g_value_get_enum (value));
1197 case PROP_DEFAULT_WIDTH:
1198 gtk_window_set_default_size_internal (window,
1199 TRUE, g_value_get_int (value),
1202 case PROP_DEFAULT_HEIGHT:
1203 gtk_window_set_default_size_internal (window,
1205 TRUE, g_value_get_int (value), FALSE);
1207 case PROP_DESTROY_WITH_PARENT:
1208 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1211 gtk_window_set_icon (window,
1212 g_value_get_object (value));
1214 case PROP_ICON_NAME:
1215 gtk_window_set_icon_name (window, g_value_get_string (value));
1218 gtk_window_set_screen (window, g_value_get_object (value));
1220 case PROP_TYPE_HINT:
1221 gtk_window_set_type_hint (window,
1222 g_value_get_enum (value));
1224 case PROP_SKIP_TASKBAR_HINT:
1225 gtk_window_set_skip_taskbar_hint (window,
1226 g_value_get_boolean (value));
1228 case PROP_SKIP_PAGER_HINT:
1229 gtk_window_set_skip_pager_hint (window,
1230 g_value_get_boolean (value));
1232 case PROP_URGENCY_HINT:
1233 gtk_window_set_urgency_hint (window,
1234 g_value_get_boolean (value));
1236 case PROP_ACCEPT_FOCUS:
1237 gtk_window_set_accept_focus (window,
1238 g_value_get_boolean (value));
1240 case PROP_FOCUS_ON_MAP:
1241 gtk_window_set_focus_on_map (window,
1242 g_value_get_boolean (value));
1244 case PROP_DECORATED:
1245 gtk_window_set_decorated (window, g_value_get_boolean (value));
1247 case PROP_DELETABLE:
1248 gtk_window_set_deletable (window, g_value_get_boolean (value));
1251 gtk_window_set_gravity (window, g_value_get_enum (value));
1253 case PROP_TRANSIENT_FOR:
1254 gtk_window_set_transient_for (window, g_value_get_object (value));
1257 gtk_window_set_opacity (window, g_value_get_double (value));
1259 case PROP_HAS_RESIZE_GRIP:
1260 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1262 case PROP_APPLICATION:
1263 gtk_window_set_application (window, g_value_get_object (value));
1265 case PROP_MNEMONICS_VISIBLE:
1266 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1268 case PROP_FOCUS_VISIBLE:
1269 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1272 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1278 gtk_window_get_property (GObject *object,
1283 GtkWindow *window = GTK_WINDOW (object);
1284 GtkWindowPrivate *priv = window->priv;
1288 GtkWindowGeometryInfo *info;
1290 g_value_set_enum (value, priv->type);
1293 g_value_set_string (value, priv->wm_role);
1296 g_value_set_string (value, priv->title);
1298 case PROP_RESIZABLE:
1299 g_value_set_boolean (value, priv->resizable);
1302 g_value_set_boolean (value, priv->modal);
1305 g_value_set_enum (value, priv->position);
1307 case PROP_DEFAULT_WIDTH:
1308 info = gtk_window_get_geometry_info (window, FALSE);
1310 g_value_set_int (value, -1);
1312 g_value_set_int (value, info->default_width);
1314 case PROP_DEFAULT_HEIGHT:
1315 info = gtk_window_get_geometry_info (window, FALSE);
1317 g_value_set_int (value, -1);
1319 g_value_set_int (value, info->default_height);
1321 case PROP_DESTROY_WITH_PARENT:
1322 g_value_set_boolean (value, priv->destroy_with_parent);
1325 g_value_set_object (value, gtk_window_get_icon (window));
1327 case PROP_ICON_NAME:
1328 g_value_set_string (value, gtk_window_get_icon_name (window));
1331 g_value_set_object (value, priv->screen);
1333 case PROP_IS_ACTIVE:
1334 g_value_set_boolean (value, priv->is_active);
1336 case PROP_HAS_TOPLEVEL_FOCUS:
1337 g_value_set_boolean (value, priv->has_toplevel_focus);
1339 case PROP_TYPE_HINT:
1340 g_value_set_enum (value, priv->type_hint);
1342 case PROP_SKIP_TASKBAR_HINT:
1343 g_value_set_boolean (value,
1344 gtk_window_get_skip_taskbar_hint (window));
1346 case PROP_SKIP_PAGER_HINT:
1347 g_value_set_boolean (value,
1348 gtk_window_get_skip_pager_hint (window));
1350 case PROP_URGENCY_HINT:
1351 g_value_set_boolean (value,
1352 gtk_window_get_urgency_hint (window));
1354 case PROP_ACCEPT_FOCUS:
1355 g_value_set_boolean (value,
1356 gtk_window_get_accept_focus (window));
1358 case PROP_FOCUS_ON_MAP:
1359 g_value_set_boolean (value,
1360 gtk_window_get_focus_on_map (window));
1362 case PROP_DECORATED:
1363 g_value_set_boolean (value, gtk_window_get_decorated (window));
1365 case PROP_DELETABLE:
1366 g_value_set_boolean (value, gtk_window_get_deletable (window));
1369 g_value_set_enum (value, gtk_window_get_gravity (window));
1371 case PROP_TRANSIENT_FOR:
1372 g_value_set_object (value, gtk_window_get_transient_for (window));
1375 g_value_set_double (value, gtk_window_get_opacity (window));
1377 case PROP_HAS_RESIZE_GRIP:
1378 g_value_set_boolean (value, priv->has_resize_grip);
1380 case PROP_RESIZE_GRIP_VISIBLE:
1381 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1383 case PROP_APPLICATION:
1384 g_value_set_object (value, gtk_window_get_application (window));
1386 case PROP_MNEMONICS_VISIBLE:
1387 g_value_set_boolean (value, priv->mnemonics_visible);
1389 case PROP_FOCUS_VISIBLE:
1390 g_value_set_boolean (value, priv->focus_visible);
1393 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1399 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1401 parent_buildable_iface = g_type_interface_peek_parent (iface);
1402 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1403 iface->parser_finished = gtk_window_buildable_parser_finished;
1404 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1405 iface->custom_finished = gtk_window_buildable_custom_finished;
1409 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1410 GtkBuilder *builder,
1412 const GValue *value)
1414 GtkWindow *window = GTK_WINDOW (buildable);
1415 GtkWindowPrivate *priv = window->priv;
1417 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1418 priv->builder_visible = TRUE;
1420 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1424 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1425 GtkBuilder *builder)
1427 GtkWindow *window = GTK_WINDOW (buildable);
1428 GtkWindowPrivate *priv = window->priv;
1432 if (priv->builder_visible)
1433 gtk_widget_show (GTK_WIDGET (buildable));
1435 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1436 for (l = accels; l; l = l->next)
1438 object = gtk_builder_get_object (builder, l->data);
1441 g_warning ("Unknown accel group %s specified in window %s",
1442 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1445 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1446 GTK_ACCEL_GROUP (object));
1450 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1452 parent_buildable_iface->parser_finished (buildable, builder);
1458 } GSListSubParserData;
1461 window_start_element (GMarkupParseContext *context,
1462 const gchar *element_name,
1463 const gchar **names,
1464 const gchar **values,
1469 GSListSubParserData *data = (GSListSubParserData*)user_data;
1471 if (strcmp (element_name, "group") == 0)
1473 for (i = 0; names[i]; i++)
1475 if (strcmp (names[i], "name") == 0)
1476 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1479 else if (strcmp (element_name, "accel-groups") == 0)
1482 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1487 static const GMarkupParser window_parser =
1489 window_start_element
1493 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1494 GtkBuilder *builder,
1496 const gchar *tagname,
1497 GMarkupParser *parser,
1500 GSListSubParserData *parser_data;
1502 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1503 tagname, parser, data))
1506 if (strcmp (tagname, "accel-groups") == 0)
1508 parser_data = g_slice_new0 (GSListSubParserData);
1509 parser_data->items = NULL;
1510 parser_data->object = G_OBJECT (buildable);
1512 *parser = window_parser;
1513 *data = parser_data;
1521 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1522 GtkBuilder *builder,
1524 const gchar *tagname,
1527 GSListSubParserData *data;
1529 parent_buildable_iface->custom_finished (buildable, builder, child,
1530 tagname, user_data);
1532 if (strcmp (tagname, "accel-groups") != 0)
1535 data = (GSListSubParserData*)user_data;
1537 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1538 data->items, (GDestroyNotify) g_slist_free);
1540 g_slice_free (GSListSubParserData, data);
1545 * @type: type of window
1547 * Creates a new #GtkWindow, which is a toplevel window that can
1548 * contain other widgets. Nearly always, the type of the window should
1549 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1550 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1551 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1552 * dialogs, though in some other toolkits dialogs are called "popups".
1553 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1554 * On X11, popup windows are not controlled by the <link
1555 * linkend="gtk-X11-arch">window manager</link>.
1557 * If you simply want an undecorated window (no window borders), use
1558 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1560 * Return value: a new #GtkWindow.
1563 gtk_window_new (GtkWindowType type)
1565 GtkWindowPrivate *priv;
1568 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1570 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1571 priv = window->priv;
1575 return GTK_WIDGET (window);
1579 * gtk_window_set_title:
1580 * @window: a #GtkWindow
1581 * @title: title of the window
1583 * Sets the title of the #GtkWindow. The title of a window will be
1584 * displayed in its title bar; on the X Window System, the title bar
1585 * is rendered by the <link linkend="gtk-X11-arch">window
1586 * manager</link>, so exactly how the title appears to users may vary
1587 * according to a user's exact configuration. The title should help a
1588 * user distinguish this window from other windows they may have
1589 * open. A good title might include the application name and current
1590 * document filename, for example.
1594 gtk_window_set_title (GtkWindow *window,
1597 GtkWindowPrivate *priv;
1601 g_return_if_fail (GTK_IS_WINDOW (window));
1603 priv = window->priv;
1604 widget = GTK_WIDGET (window);
1606 new_title = g_strdup (title);
1607 g_free (priv->title);
1608 priv->title = new_title;
1610 if (gtk_widget_get_realized (widget))
1612 gdk_window_set_title (gtk_widget_get_window (widget),
1616 g_object_notify (G_OBJECT (window), "title");
1620 * gtk_window_get_title:
1621 * @window: a #GtkWindow
1623 * Retrieves the title of the window. See gtk_window_set_title().
1625 * Return value: the title of the window, or %NULL if none has
1626 * been set explicitely. The returned string is owned by the widget
1627 * and must not be modified or freed.
1630 gtk_window_get_title (GtkWindow *window)
1632 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1634 return window->priv->title;
1638 * gtk_window_set_wmclass:
1639 * @window: a #GtkWindow
1640 * @wmclass_name: window name hint
1641 * @wmclass_class: window class hint
1643 * Don't use this function. It sets the X Window System "class" and
1644 * "name" hints for a window. According to the ICCCM, you should
1645 * always set these to the same value for all windows in an
1646 * application, and GTK+ sets them to that value by default, so calling
1647 * this function is sort of pointless. However, you may want to call
1648 * gtk_window_set_role() on each window in your application, for the
1649 * benefit of the session manager. Setting the role allows the window
1650 * manager to restore window positions when loading a saved session.
1654 gtk_window_set_wmclass (GtkWindow *window,
1655 const gchar *wmclass_name,
1656 const gchar *wmclass_class)
1658 GtkWindowPrivate *priv;
1660 g_return_if_fail (GTK_IS_WINDOW (window));
1662 priv = window->priv;
1664 g_free (priv->wmclass_name);
1665 priv->wmclass_name = g_strdup (wmclass_name);
1667 g_free (priv->wmclass_class);
1668 priv->wmclass_class = g_strdup (wmclass_class);
1670 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1671 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1675 * gtk_window_set_role:
1676 * @window: a #GtkWindow
1677 * @role: unique identifier for the window to be used when restoring a session
1679 * This function is only useful on X11, not with other GTK+ targets.
1681 * In combination with the window title, the window role allows a
1682 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1683 * same" window when an application is restarted. So for example you
1684 * might set the "toolbox" role on your app's toolbox window, so that
1685 * when the user restarts their session, the window manager can put
1686 * the toolbox back in the same place.
1688 * If a window already has a unique title, you don't need to set the
1689 * role, since the WM can use the title to identify the window when
1690 * restoring the session.
1694 gtk_window_set_role (GtkWindow *window,
1697 GtkWindowPrivate *priv;
1700 g_return_if_fail (GTK_IS_WINDOW (window));
1702 priv = window->priv;
1704 new_role = g_strdup (role);
1705 g_free (priv->wm_role);
1706 priv->wm_role = new_role;
1708 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1709 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1712 g_object_notify (G_OBJECT (window), "role");
1716 * gtk_window_set_startup_id:
1717 * @window: a #GtkWindow
1718 * @startup_id: a string with startup-notification identifier
1720 * Startup notification identifiers are used by desktop environment to
1721 * track application startup, to provide user feedback and other
1722 * features. This function changes the corresponding property on the
1723 * underlying GdkWindow. Normally, startup identifier is managed
1724 * automatically and you should only use this function in special cases
1725 * like transferring focus from other processes. You should use this
1726 * function before calling gtk_window_present() or any equivalent
1727 * function generating a window map event.
1729 * This function is only useful on X11, not with other GTK+ targets.
1734 gtk_window_set_startup_id (GtkWindow *window,
1735 const gchar *startup_id)
1737 GtkWindowPrivate *priv;
1740 g_return_if_fail (GTK_IS_WINDOW (window));
1742 priv = window->priv;
1743 widget = GTK_WIDGET (window);
1745 g_free (priv->startup_id);
1746 priv->startup_id = g_strdup (startup_id);
1748 if (gtk_widget_get_realized (widget))
1750 GdkWindow *gdk_window;
1751 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1753 gdk_window = gtk_widget_get_window (widget);
1755 #ifdef GDK_WINDOWING_X11
1756 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1757 gdk_x11_window_set_user_time (gdk_window, timestamp);
1760 /* Here we differentiate real and "fake" startup notification IDs,
1761 * constructed on purpose just to pass interaction timestamp
1763 if (startup_id_is_fake (priv->startup_id))
1764 gtk_window_present_with_time (window, timestamp);
1767 gdk_window_set_startup_id (gdk_window,
1770 /* If window is mapped, terminate the startup-notification too */
1771 if (gtk_widget_get_mapped (widget) &&
1772 !disable_startup_notification)
1773 gdk_notify_startup_complete_with_id (priv->startup_id);
1777 g_object_notify (G_OBJECT (window), "startup-id");
1781 * gtk_window_get_role:
1782 * @window: a #GtkWindow
1784 * Returns the role of the window. See gtk_window_set_role() for
1785 * further explanation.
1787 * Return value: the role of the window if set, or %NULL. The
1788 * returned is owned by the widget and must not be modified
1792 gtk_window_get_role (GtkWindow *window)
1794 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1796 return window->priv->wm_role;
1800 * gtk_window_set_focus:
1801 * @window: a #GtkWindow
1802 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1803 * any focus widget for the toplevel window.
1805 * If @focus is not the current focus widget, and is focusable, sets
1806 * it as the focus widget for the window. If @focus is %NULL, unsets
1807 * the focus widget for this window. To set the focus to a particular
1808 * widget in the toplevel, it is usually more convenient to use
1809 * gtk_widget_grab_focus() instead of this function.
1812 gtk_window_set_focus (GtkWindow *window,
1815 GtkWindowPrivate *priv;
1818 g_return_if_fail (GTK_IS_WINDOW (window));
1820 priv = window->priv;
1824 g_return_if_fail (GTK_IS_WIDGET (focus));
1825 g_return_if_fail (gtk_widget_get_can_focus (focus));
1829 gtk_widget_grab_focus (focus);
1832 /* Clear the existing focus chain, so that when we focus into
1833 * the window again, we start at the beginnning.
1835 GtkWidget *widget = priv->focus_widget;
1838 while ((parent = gtk_widget_get_parent (widget)))
1841 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1845 _gtk_window_internal_set_focus (window, NULL);
1850 _gtk_window_internal_set_focus (GtkWindow *window,
1853 GtkWindowPrivate *priv;
1855 g_return_if_fail (GTK_IS_WINDOW (window));
1857 priv = window->priv;
1859 if ((priv->focus_widget != focus) ||
1860 (focus && !gtk_widget_has_focus (focus)))
1861 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1865 * gtk_window_set_default:
1866 * @window: a #GtkWindow
1867 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1868 * default widget for the toplevel.
1870 * The default widget is the widget that's activated when the user
1871 * presses Enter in a dialog (for example). This function sets or
1872 * unsets the default widget for a #GtkWindow about. When setting
1873 * (rather than unsetting) the default widget it's generally easier to
1874 * call gtk_widget_grab_focus() on the widget. Before making a widget
1875 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1876 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1879 gtk_window_set_default (GtkWindow *window,
1880 GtkWidget *default_widget)
1882 GtkWindowPrivate *priv;
1884 g_return_if_fail (GTK_IS_WINDOW (window));
1886 priv = window->priv;
1889 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1891 if (priv->default_widget != default_widget)
1893 GtkWidget *old_default_widget = NULL;
1896 g_object_ref (default_widget);
1898 if (priv->default_widget)
1900 old_default_widget = priv->default_widget;
1902 if (priv->focus_widget != priv->default_widget ||
1903 !gtk_widget_get_receives_default (priv->default_widget))
1904 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1906 gtk_widget_queue_draw (priv->default_widget);
1909 priv->default_widget = default_widget;
1911 if (priv->default_widget)
1913 if (priv->focus_widget == NULL ||
1914 !gtk_widget_get_receives_default (priv->focus_widget))
1915 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1917 gtk_widget_queue_draw (priv->default_widget);
1920 if (old_default_widget)
1921 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1925 g_object_notify (G_OBJECT (default_widget), "has-default");
1926 g_object_unref (default_widget);
1932 * gtk_window_get_default_widget:
1933 * @window: a #GtkWindow
1935 * Returns the default widget for @window. See gtk_window_set_default()
1938 * Returns: (transfer none): the default widget, or %NULL if there is none.
1943 gtk_window_get_default_widget (GtkWindow *window)
1945 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1947 return window->priv->default_widget;
1951 handle_keys_changed (gpointer data)
1953 GtkWindow *window = GTK_WINDOW (data);
1954 GtkWindowPrivate *priv = window->priv;
1956 if (priv->keys_changed_handler)
1958 g_source_remove (priv->keys_changed_handler);
1959 priv->keys_changed_handler = 0;
1962 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1968 gtk_window_notify_keys_changed (GtkWindow *window)
1970 GtkWindowPrivate *priv = window->priv;
1972 if (!priv->keys_changed_handler)
1973 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1977 * gtk_window_add_accel_group:
1978 * @window: window to attach accelerator group to
1979 * @accel_group: a #GtkAccelGroup
1981 * Associate @accel_group with @window, such that calling
1982 * gtk_accel_groups_activate() on @window will activate accelerators
1986 gtk_window_add_accel_group (GtkWindow *window,
1987 GtkAccelGroup *accel_group)
1989 g_return_if_fail (GTK_IS_WINDOW (window));
1990 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1992 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1993 g_signal_connect_object (accel_group, "accel-changed",
1994 G_CALLBACK (gtk_window_notify_keys_changed),
1995 window, G_CONNECT_SWAPPED);
1996 gtk_window_notify_keys_changed (window);
2000 * gtk_window_remove_accel_group:
2001 * @window: a #GtkWindow
2002 * @accel_group: a #GtkAccelGroup
2004 * Reverses the effects of gtk_window_add_accel_group().
2007 gtk_window_remove_accel_group (GtkWindow *window,
2008 GtkAccelGroup *accel_group)
2010 g_return_if_fail (GTK_IS_WINDOW (window));
2011 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2013 g_signal_handlers_disconnect_by_func (accel_group,
2014 gtk_window_notify_keys_changed,
2016 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2017 gtk_window_notify_keys_changed (window);
2020 static GtkMnemonicHash *
2021 gtk_window_get_mnemonic_hash (GtkWindow *window,
2024 GtkWindowPrivate *private = window->priv;
2026 if (!private->mnemonic_hash && create)
2027 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2029 return private->mnemonic_hash;
2033 * gtk_window_add_mnemonic:
2034 * @window: a #GtkWindow
2035 * @keyval: the mnemonic
2036 * @target: the widget that gets activated by the mnemonic
2038 * Adds a mnemonic to this window.
2041 gtk_window_add_mnemonic (GtkWindow *window,
2045 g_return_if_fail (GTK_IS_WINDOW (window));
2046 g_return_if_fail (GTK_IS_WIDGET (target));
2048 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2050 gtk_window_notify_keys_changed (window);
2054 * gtk_window_remove_mnemonic:
2055 * @window: a #GtkWindow
2056 * @keyval: the mnemonic
2057 * @target: the widget that gets activated by the mnemonic
2059 * Removes a mnemonic from this window.
2062 gtk_window_remove_mnemonic (GtkWindow *window,
2066 g_return_if_fail (GTK_IS_WINDOW (window));
2067 g_return_if_fail (GTK_IS_WIDGET (target));
2069 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2071 gtk_window_notify_keys_changed (window);
2075 * gtk_window_mnemonic_activate:
2076 * @window: a #GtkWindow
2077 * @keyval: the mnemonic
2078 * @modifier: the modifiers
2079 * @returns: %TRUE if the activation is done.
2081 * Activates the targets associated with the mnemonic.
2084 gtk_window_mnemonic_activate (GtkWindow *window,
2086 GdkModifierType modifier)
2088 GtkWindowPrivate *priv;
2090 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2092 priv = window->priv;
2094 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2096 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2098 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2105 * gtk_window_set_mnemonic_modifier:
2106 * @window: a #GtkWindow
2107 * @modifier: the modifier mask used to activate
2108 * mnemonics on this window.
2110 * Sets the mnemonic modifier for this window.
2113 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2114 GdkModifierType modifier)
2116 GtkWindowPrivate *priv;
2118 g_return_if_fail (GTK_IS_WINDOW (window));
2119 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2121 priv = window->priv;
2123 priv->mnemonic_modifier = modifier;
2124 gtk_window_notify_keys_changed (window);
2128 * gtk_window_get_mnemonic_modifier:
2129 * @window: a #GtkWindow
2131 * Returns the mnemonic modifier for this window. See
2132 * gtk_window_set_mnemonic_modifier().
2134 * Return value: the modifier mask used to activate
2135 * mnemonics on this window.
2138 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2140 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2142 return window->priv->mnemonic_modifier;
2146 * gtk_window_set_position:
2147 * @window: a #GtkWindow.
2148 * @position: a position constraint.
2150 * Sets a position constraint for this window. If the old or new
2151 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2152 * the window to be repositioned to satisfy the new constraint.
2155 gtk_window_set_position (GtkWindow *window,
2156 GtkWindowPosition position)
2158 GtkWindowPrivate *priv;
2160 g_return_if_fail (GTK_IS_WINDOW (window));
2162 priv = window->priv;
2164 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2165 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2167 GtkWindowGeometryInfo *info;
2169 info = gtk_window_get_geometry_info (window, TRUE);
2171 /* this flag causes us to re-request the CENTER_ALWAYS
2172 * constraint in gtk_window_move_resize(), see
2173 * comment in that function.
2175 info->position_constraints_changed = TRUE;
2177 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2180 priv->position = position;
2182 g_object_notify (G_OBJECT (window), "window-position");
2186 * gtk_window_activate_focus:
2187 * @window: a #GtkWindow
2189 * Activates the current focused widget within the window.
2191 * Return value: %TRUE if a widget got activated.
2194 gtk_window_activate_focus (GtkWindow *window)
2196 GtkWindowPrivate *priv;
2198 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2200 priv = window->priv;
2202 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2203 return gtk_widget_activate (priv->focus_widget);
2209 * gtk_window_get_focus:
2210 * @window: a #GtkWindow
2212 * Retrieves the current focused widget within the window.
2213 * Note that this is the widget that would have the focus
2214 * if the toplevel window focused; if the toplevel window
2215 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2216 * not be %TRUE for the widget.
2218 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2221 gtk_window_get_focus (GtkWindow *window)
2223 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2225 return window->priv->focus_widget;
2229 * gtk_window_activate_default:
2230 * @window: a #GtkWindow
2232 * Activates the default widget for the window, unless the current
2233 * focused widget has been configured to receive the default action
2234 * (see gtk_widget_set_receives_default()), in which case the
2235 * focused widget is activated.
2237 * Return value: %TRUE if a widget got activated.
2240 gtk_window_activate_default (GtkWindow *window)
2242 GtkWindowPrivate *priv;
2244 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2246 priv = window->priv;
2248 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2249 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2250 return gtk_widget_activate (priv->default_widget);
2251 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2252 return gtk_widget_activate (priv->focus_widget);
2258 * gtk_window_set_modal:
2259 * @window: a #GtkWindow
2260 * @modal: whether the window is modal
2262 * Sets a window modal or non-modal. Modal windows prevent interaction
2263 * with other windows in the same application. To keep modal dialogs
2264 * on top of main application windows, use
2265 * gtk_window_set_transient_for() to make the dialog transient for the
2266 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2267 * will then disallow lowering the dialog below the parent.
2272 gtk_window_set_modal (GtkWindow *window,
2275 GtkWindowPrivate *priv;
2278 g_return_if_fail (GTK_IS_WINDOW (window));
2280 priv = window->priv;
2282 modal = modal != FALSE;
2283 if (priv->modal == modal)
2286 priv->modal = modal;
2287 widget = GTK_WIDGET (window);
2289 /* adjust desired modality state */
2290 if (gtk_widget_get_realized (widget))
2293 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2295 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2298 if (gtk_widget_get_visible (widget))
2301 gtk_grab_add (widget);
2303 gtk_grab_remove (widget);
2306 g_object_notify (G_OBJECT (window), "modal");
2310 * gtk_window_get_modal:
2311 * @window: a #GtkWindow
2313 * Returns whether the window is modal. See gtk_window_set_modal().
2315 * Return value: %TRUE if the window is set to be modal and
2316 * establishes a grab when shown
2319 gtk_window_get_modal (GtkWindow *window)
2321 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2323 return window->priv->modal;
2327 * gtk_window_list_toplevels:
2329 * Returns a list of all existing toplevel windows. The widgets
2330 * in the list are not individually referenced. If you want
2331 * to iterate through the list and perform actions involving
2332 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2333 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2334 * then unref all the widgets afterwards.
2336 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2339 gtk_window_list_toplevels (void)
2344 for (slist = toplevel_list; slist; slist = slist->next)
2345 list = g_list_prepend (list, slist->data);
2351 gtk_window_dispose (GObject *object)
2353 GtkWindow *window = GTK_WINDOW (object);
2355 gtk_window_set_focus (window, NULL);
2356 gtk_window_set_default (window, NULL);
2358 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2362 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2364 gtk_widget_destroy (GTK_WIDGET (child));
2368 connect_parent_destroyed (GtkWindow *window)
2370 GtkWindowPrivate *priv = window->priv;
2372 if (priv->transient_parent)
2374 g_signal_connect (priv->transient_parent,
2376 G_CALLBACK (parent_destroyed_callback),
2382 disconnect_parent_destroyed (GtkWindow *window)
2384 GtkWindowPrivate *priv = window->priv;
2386 if (priv->transient_parent)
2388 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2389 parent_destroyed_callback,
2395 gtk_window_transient_parent_realized (GtkWidget *parent,
2398 if (gtk_widget_get_realized (window))
2399 gdk_window_set_transient_for (gtk_widget_get_window (window),
2400 gtk_widget_get_window (parent));
2404 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2407 if (gtk_widget_get_realized (window))
2408 gdk_property_delete (gtk_widget_get_window (window),
2409 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2413 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2417 gtk_window_set_screen (window, parent->priv->screen);
2421 gtk_window_unset_transient_for (GtkWindow *window)
2423 GtkWindowPrivate *priv = window->priv;
2425 if (priv->transient_parent)
2427 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2428 gtk_window_transient_parent_realized,
2430 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2431 gtk_window_transient_parent_unrealized,
2433 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2434 gtk_window_transient_parent_screen_changed,
2436 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2437 gtk_widget_destroyed,
2438 &priv->transient_parent);
2440 if (priv->destroy_with_parent)
2441 disconnect_parent_destroyed (window);
2443 priv->transient_parent = NULL;
2445 if (priv->transient_parent_group)
2447 priv->transient_parent_group = FALSE;
2448 gtk_window_group_remove_window (priv->group,
2455 * gtk_window_set_transient_for:
2456 * @window: a #GtkWindow
2457 * @parent: (allow-none): parent window, or %NULL
2459 * Dialog windows should be set transient for the main application
2460 * window they were spawned from. This allows <link
2461 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2462 * dialog on top of the main window, or center the dialog over the
2463 * main window. gtk_dialog_new_with_buttons() and other convenience
2464 * functions in GTK+ will sometimes call
2465 * gtk_window_set_transient_for() on your behalf.
2467 * Passing %NULL for @parent unsets the current transient window.
2469 * On Windows, this function puts the child window on top of the parent,
2470 * much as the window manager would have done on X.
2473 gtk_window_set_transient_for (GtkWindow *window,
2476 GtkWindowPrivate *priv;
2478 g_return_if_fail (GTK_IS_WINDOW (window));
2479 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2480 g_return_if_fail (window != parent);
2482 priv = window->priv;
2484 if (priv->transient_parent)
2486 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2487 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2488 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2489 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2490 GTK_WIDGET (window));
2492 gtk_window_unset_transient_for (window);
2495 priv->transient_parent = parent;
2499 g_signal_connect (parent, "destroy",
2500 G_CALLBACK (gtk_widget_destroyed),
2501 &priv->transient_parent);
2502 g_signal_connect (parent, "realize",
2503 G_CALLBACK (gtk_window_transient_parent_realized),
2505 g_signal_connect (parent, "unrealize",
2506 G_CALLBACK (gtk_window_transient_parent_unrealized),
2508 g_signal_connect (parent, "notify::screen",
2509 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2512 gtk_window_set_screen (window, parent->priv->screen);
2514 if (priv->destroy_with_parent)
2515 connect_parent_destroyed (window);
2517 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2518 gtk_widget_get_realized (GTK_WIDGET (parent)))
2519 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2520 GTK_WIDGET (window));
2522 if (parent->priv->group)
2524 gtk_window_group_add_window (parent->priv->group, window);
2525 priv->transient_parent_group = TRUE;
2531 * gtk_window_get_transient_for:
2532 * @window: a #GtkWindow
2534 * Fetches the transient parent for this window. See
2535 * gtk_window_set_transient_for().
2537 * Return value: (transfer none): the transient parent for this window, or %NULL
2538 * if no transient parent has been set.
2541 gtk_window_get_transient_for (GtkWindow *window)
2543 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2545 return window->priv->transient_parent;
2549 * gtk_window_set_opacity:
2550 * @window: a #GtkWindow
2551 * @opacity: desired opacity, between 0 and 1
2553 * Request the windowing system to make @window partially transparent,
2554 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2555 * of the opacity parameter are clamped to the [0,1] range.) On X11
2556 * this has any effect only on X screens with a compositing manager
2557 * running. See gtk_widget_is_composited(). On Windows it should work
2560 * Note that setting a window's opacity after the window has been
2561 * shown causes it to flicker once on Windows.
2566 gtk_window_set_opacity (GtkWindow *window,
2569 GtkWindowPrivate *priv;
2571 g_return_if_fail (GTK_IS_WINDOW (window));
2573 priv = window->priv;
2577 else if (opacity > 1.0)
2580 priv->opacity_set = TRUE;
2581 priv->opacity = opacity;
2583 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2584 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2589 * gtk_window_get_opacity:
2590 * @window: a #GtkWindow
2592 * Fetches the requested opacity for this window. See
2593 * gtk_window_set_opacity().
2595 * Return value: the requested opacity for this window.
2600 gtk_window_get_opacity (GtkWindow *window)
2602 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2604 return window->priv->opacity;
2608 * gtk_window_get_application:
2609 * @window: a #GtkWindow
2611 * Gets the #GtkApplication associated with the window (if any).
2613 * Return value: (transfer none): a #GtkApplication, or %NULL
2618 gtk_window_get_application (GtkWindow *window)
2620 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2622 return window->priv->application;
2626 gtk_window_release_application (GtkWindow *window)
2628 if (window->priv->application)
2630 GtkApplication *application;
2632 /* steal reference into temp variable */
2633 application = window->priv->application;
2634 window->priv->application = NULL;
2636 gtk_application_remove_window (application, window);
2637 g_object_unref (application);
2642 * gtk_window_set_application:
2643 * @window: a #GtkWindow
2644 * @application: (allow-none): a #GtkApplication, or %NULL
2646 * Sets or unsets the #GtkApplication associated with the window.
2648 * The application will be kept alive for at least as long as the window
2654 gtk_window_set_application (GtkWindow *window,
2655 GtkApplication *application)
2657 GtkWindowPrivate *priv;
2659 g_return_if_fail (GTK_IS_WINDOW (window));
2661 priv = window->priv;
2662 if (priv->application != application)
2664 gtk_window_release_application (window);
2666 priv->application = application;
2668 if (priv->application != NULL)
2670 g_object_ref (priv->application);
2672 gtk_application_add_window (priv->application, window);
2675 g_object_notify (G_OBJECT (window), "application");
2680 * gtk_window_set_type_hint:
2681 * @window: a #GtkWindow
2682 * @hint: the window type
2684 * By setting the type hint for the window, you allow the window
2685 * manager to decorate and handle the window in a way which is
2686 * suitable to the function of the window in your application.
2688 * This function should be called before the window becomes visible.
2690 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2691 * will sometimes call gtk_window_set_type_hint() on your behalf.
2695 gtk_window_set_type_hint (GtkWindow *window,
2696 GdkWindowTypeHint hint)
2698 GtkWindowPrivate *priv;
2700 g_return_if_fail (GTK_IS_WINDOW (window));
2701 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2703 priv = window->priv;
2705 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2706 priv->type_hint = hint;
2708 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2710 priv->reset_type_hint = TRUE;
2711 priv->gdk_type_hint = hint;
2715 * gtk_window_get_type_hint:
2716 * @window: a #GtkWindow
2718 * Gets the type hint for this window. See gtk_window_set_type_hint().
2720 * Return value: the type hint for @window.
2723 gtk_window_get_type_hint (GtkWindow *window)
2725 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2727 return window->priv->gdk_type_hint;
2731 * gtk_window_set_skip_taskbar_hint:
2732 * @window: a #GtkWindow
2733 * @setting: %TRUE to keep this window from appearing in the task bar
2735 * Windows may set a hint asking the desktop environment not to display
2736 * the window in the task bar. This function sets this hint.
2741 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2744 GtkWindowPrivate *priv;
2746 g_return_if_fail (GTK_IS_WINDOW (window));
2748 priv = window->priv;
2750 setting = setting != FALSE;
2752 if (priv->skips_taskbar != setting)
2754 priv->skips_taskbar = setting;
2755 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2756 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2757 priv->skips_taskbar);
2758 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2763 * gtk_window_get_skip_taskbar_hint:
2764 * @window: a #GtkWindow
2766 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2768 * Return value: %TRUE if window shouldn't be in taskbar
2773 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2775 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2777 return window->priv->skips_taskbar;
2781 * gtk_window_set_skip_pager_hint:
2782 * @window: a #GtkWindow
2783 * @setting: %TRUE to keep this window from appearing in the pager
2785 * Windows may set a hint asking the desktop environment not to display
2786 * the window in the pager. This function sets this hint.
2787 * (A "pager" is any desktop navigation tool such as a workspace
2788 * switcher that displays a thumbnail representation of the windows
2794 gtk_window_set_skip_pager_hint (GtkWindow *window,
2797 GtkWindowPrivate *priv;
2799 g_return_if_fail (GTK_IS_WINDOW (window));
2801 priv = window->priv;
2803 setting = setting != FALSE;
2805 if (priv->skips_pager != setting)
2807 priv->skips_pager = setting;
2808 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2809 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2811 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2816 * gtk_window_get_skip_pager_hint:
2817 * @window: a #GtkWindow
2819 * Gets the value set by gtk_window_set_skip_pager_hint().
2821 * Return value: %TRUE if window shouldn't be in pager
2826 gtk_window_get_skip_pager_hint (GtkWindow *window)
2828 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2830 return window->priv->skips_pager;
2834 * gtk_window_set_urgency_hint:
2835 * @window: a #GtkWindow
2836 * @setting: %TRUE to mark this window as urgent
2838 * Windows may set a hint asking the desktop environment to draw
2839 * the users attention to the window. This function sets this hint.
2844 gtk_window_set_urgency_hint (GtkWindow *window,
2847 GtkWindowPrivate *priv;
2849 g_return_if_fail (GTK_IS_WINDOW (window));
2851 priv = window->priv;
2853 setting = setting != FALSE;
2855 if (priv->urgent != setting)
2857 priv->urgent = setting;
2858 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2859 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2861 g_object_notify (G_OBJECT (window), "urgency-hint");
2866 * gtk_window_get_urgency_hint:
2867 * @window: a #GtkWindow
2869 * Gets the value set by gtk_window_set_urgency_hint()
2871 * Return value: %TRUE if window is urgent
2876 gtk_window_get_urgency_hint (GtkWindow *window)
2878 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2880 return window->priv->urgent;
2884 * gtk_window_set_accept_focus:
2885 * @window: a #GtkWindow
2886 * @setting: %TRUE to let this window receive input focus
2888 * Windows may set a hint asking the desktop environment not to receive
2889 * the input focus. This function sets this hint.
2894 gtk_window_set_accept_focus (GtkWindow *window,
2897 GtkWindowPrivate *priv;
2899 g_return_if_fail (GTK_IS_WINDOW (window));
2901 priv = window->priv;
2903 setting = setting != FALSE;
2905 if (priv->accept_focus != setting)
2907 priv->accept_focus = setting;
2908 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2909 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2910 priv->accept_focus);
2911 g_object_notify (G_OBJECT (window), "accept-focus");
2916 * gtk_window_get_accept_focus:
2917 * @window: a #GtkWindow
2919 * Gets the value set by gtk_window_set_accept_focus().
2921 * Return value: %TRUE if window should receive the input focus
2926 gtk_window_get_accept_focus (GtkWindow *window)
2928 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2930 return window->priv->accept_focus;
2934 * gtk_window_set_focus_on_map:
2935 * @window: a #GtkWindow
2936 * @setting: %TRUE to let this window receive input focus on map
2938 * Windows may set a hint asking the desktop environment not to receive
2939 * the input focus when the window is mapped. This function sets this
2945 gtk_window_set_focus_on_map (GtkWindow *window,
2948 GtkWindowPrivate *priv;
2950 g_return_if_fail (GTK_IS_WINDOW (window));
2952 priv = window->priv;
2954 setting = setting != FALSE;
2956 if (priv->focus_on_map != setting)
2958 priv->focus_on_map = setting;
2959 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2960 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2961 priv->focus_on_map);
2962 g_object_notify (G_OBJECT (window), "focus-on-map");
2967 * gtk_window_get_focus_on_map:
2968 * @window: a #GtkWindow
2970 * Gets the value set by gtk_window_set_focus_on_map().
2972 * Return value: %TRUE if window should receive the input focus when
2978 gtk_window_get_focus_on_map (GtkWindow *window)
2980 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2982 return window->priv->focus_on_map;
2986 * gtk_window_set_destroy_with_parent:
2987 * @window: a #GtkWindow
2988 * @setting: whether to destroy @window with its transient parent
2990 * If @setting is %TRUE, then destroying the transient parent of @window
2991 * will also destroy @window itself. This is useful for dialogs that
2992 * shouldn't persist beyond the lifetime of the main window they're
2993 * associated with, for example.
2996 gtk_window_set_destroy_with_parent (GtkWindow *window,
2999 GtkWindowPrivate *priv;
3001 g_return_if_fail (GTK_IS_WINDOW (window));
3003 priv = window->priv;
3005 if (priv->destroy_with_parent == (setting != FALSE))
3008 if (priv->destroy_with_parent)
3010 disconnect_parent_destroyed (window);
3014 connect_parent_destroyed (window);
3017 priv->destroy_with_parent = setting;
3019 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3023 * gtk_window_get_destroy_with_parent:
3024 * @window: a #GtkWindow
3026 * Returns whether the window will be destroyed with its transient parent. See
3027 * gtk_window_set_destroy_with_parent ().
3029 * Return value: %TRUE if the window will be destroyed with its transient parent.
3032 gtk_window_get_destroy_with_parent (GtkWindow *window)
3034 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3036 return window->priv->destroy_with_parent;
3039 static GtkWindowGeometryInfo*
3040 gtk_window_get_geometry_info (GtkWindow *window,
3043 GtkWindowPrivate *priv = window->priv;
3044 GtkWindowGeometryInfo *info;
3046 info = priv->geometry_info;
3047 if (!info && create)
3049 info = g_new0 (GtkWindowGeometryInfo, 1);
3051 info->default_width = -1;
3052 info->default_height = -1;
3053 info->resize_width = -1;
3054 info->resize_height = -1;
3055 info->initial_x = 0;
3056 info->initial_y = 0;
3057 info->initial_pos_set = FALSE;
3058 info->default_is_geometry = FALSE;
3059 info->position_constraints_changed = FALSE;
3060 info->last.configure_request.x = 0;
3061 info->last.configure_request.y = 0;
3062 info->last.configure_request.width = -1;
3063 info->last.configure_request.height = -1;
3064 info->widget = NULL;
3066 priv->geometry_info = info;
3073 * gtk_window_set_geometry_hints:
3074 * @window: a #GtkWindow
3075 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3076 * @geometry: (allow-none): struct containing geometry information or %NULL
3077 * @geom_mask: mask indicating which struct fields should be paid attention to
3079 * This function sets up hints about how a window can be resized by
3080 * the user. You can set a minimum and maximum size; allowed resize
3081 * increments (e.g. for xterm, you can only resize by the size of a
3082 * character); aspect ratios; and more. See the #GdkGeometry struct.
3086 gtk_window_set_geometry_hints (GtkWindow *window,
3087 GtkWidget *geometry_widget,
3088 GdkGeometry *geometry,
3089 GdkWindowHints geom_mask)
3091 GtkWindowGeometryInfo *info;
3093 g_return_if_fail (GTK_IS_WINDOW (window));
3094 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3096 info = gtk_window_get_geometry_info (window, TRUE);
3099 g_signal_handlers_disconnect_by_func (info->widget,
3100 gtk_widget_destroyed,
3103 info->widget = geometry_widget;
3105 g_signal_connect (geometry_widget, "destroy",
3106 G_CALLBACK (gtk_widget_destroyed),
3110 info->geometry = *geometry;
3112 /* We store gravity in priv->gravity not in the hints. */
3113 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3115 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3117 gtk_window_set_gravity (window, geometry->win_gravity);
3120 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3124 * gtk_window_set_decorated:
3125 * @window: a #GtkWindow
3126 * @setting: %TRUE to decorate the window
3128 * By default, windows are decorated with a title bar, resize
3129 * controls, etc. Some <link linkend="gtk-X11-arch">window
3130 * managers</link> allow GTK+ to disable these decorations, creating a
3131 * borderless window. If you set the decorated property to %FALSE
3132 * using this function, GTK+ will do its best to convince the window
3133 * manager not to decorate the window. Depending on the system, this
3134 * function may not have any effect when called on a window that is
3135 * already visible, so you should call it before calling gtk_widget_show().
3137 * On Windows, this function always works, since there's no window manager
3142 gtk_window_set_decorated (GtkWindow *window,
3145 GtkWindowPrivate *priv;
3146 GdkWindow *gdk_window;
3148 g_return_if_fail (GTK_IS_WINDOW (window));
3150 priv = window->priv;
3152 setting = setting != FALSE;
3154 if (setting == priv->decorated)
3157 priv->decorated = setting;
3159 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3162 if (priv->decorated)
3163 gdk_window_set_decorations (gdk_window,
3166 gdk_window_set_decorations (gdk_window,
3170 g_object_notify (G_OBJECT (window), "decorated");
3174 * gtk_window_get_decorated:
3175 * @window: a #GtkWindow
3177 * Returns whether the window has been set to have decorations
3178 * such as a title bar via gtk_window_set_decorated().
3180 * Return value: %TRUE if the window has been set to have decorations
3183 gtk_window_get_decorated (GtkWindow *window)
3185 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3187 return window->priv->decorated;
3191 * gtk_window_set_deletable:
3192 * @window: a #GtkWindow
3193 * @setting: %TRUE to decorate the window as deletable
3195 * By default, windows have a close button in the window frame. Some
3196 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3197 * disable this button. If you set the deletable property to %FALSE
3198 * using this function, GTK+ will do its best to convince the window
3199 * manager not to show a close button. Depending on the system, this
3200 * function may not have any effect when called on a window that is
3201 * already visible, so you should call it before calling gtk_window_show().
3203 * On Windows, this function always works, since there's no window manager
3209 gtk_window_set_deletable (GtkWindow *window,
3212 GtkWindowPrivate *priv;
3213 GdkWindow *gdk_window;
3215 g_return_if_fail (GTK_IS_WINDOW (window));
3217 priv = window->priv;
3219 setting = setting != FALSE;
3221 if (setting == priv->deletable)
3224 priv->deletable = setting;
3226 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3229 if (priv->deletable)
3230 gdk_window_set_functions (gdk_window,
3233 gdk_window_set_functions (gdk_window,
3234 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3237 g_object_notify (G_OBJECT (window), "deletable");
3241 * gtk_window_get_deletable:
3242 * @window: a #GtkWindow
3244 * Returns whether the window has been set to have a close button
3245 * via gtk_window_set_deletable().
3247 * Return value: %TRUE if the window has been set to have a close button
3252 gtk_window_get_deletable (GtkWindow *window)
3254 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3256 return window->priv->deletable;
3259 static GtkWindowIconInfo*
3260 get_icon_info (GtkWindow *window)
3262 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3266 free_icon_info (GtkWindowIconInfo *info)
3268 g_free (info->icon_name);
3269 g_slice_free (GtkWindowIconInfo, info);
3273 static GtkWindowIconInfo*
3274 ensure_icon_info (GtkWindow *window)
3276 GtkWindowIconInfo *info;
3278 info = get_icon_info (window);
3282 info = g_slice_new0 (GtkWindowIconInfo);
3283 g_object_set_qdata_full (G_OBJECT (window),
3284 quark_gtk_window_icon_info,
3286 (GDestroyNotify)free_icon_info);
3293 icon_list_from_theme (GtkWidget *widget,
3298 GtkIconTheme *icon_theme;
3303 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3305 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3308 for (i = 0; sizes[i]; i++)
3311 * We need an EWMH extension to handle scalable icons
3312 * by passing their name to the WM. For now just use a
3316 icon = gtk_icon_theme_load_icon (icon_theme, name,
3319 icon = gtk_icon_theme_load_icon (icon_theme, name,
3322 list = g_list_append (list, icon);
3332 gtk_window_realize_icon (GtkWindow *window)
3334 GtkWindowPrivate *priv = window->priv;
3336 GtkWindowIconInfo *info;
3337 GdkWindow *gdk_window;
3340 widget = GTK_WIDGET (window);
3341 gdk_window = gtk_widget_get_window (widget);
3343 g_return_if_fail (gdk_window != NULL);
3345 /* no point setting an icon on override-redirect */
3346 if (priv->type == GTK_WINDOW_POPUP)
3351 info = ensure_icon_info (window);
3356 info->using_default_icon = FALSE;
3357 info->using_parent_icon = FALSE;
3358 info->using_themed_icon = FALSE;
3360 icon_list = info->icon_list;
3362 /* Look up themed icon */
3363 if (icon_list == NULL && info->icon_name)
3365 icon_list = icon_list_from_theme (widget, info->icon_name);
3367 info->using_themed_icon = TRUE;
3370 /* Inherit from transient parent */
3371 if (icon_list == NULL && priv->transient_parent)
3373 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3375 info->using_parent_icon = TRUE;
3378 /* Inherit from default */
3379 if (icon_list == NULL)
3381 icon_list = default_icon_list;
3383 info->using_default_icon = TRUE;
3386 /* Look up themed icon */
3387 if (icon_list == NULL && default_icon_name)
3389 icon_list = icon_list_from_theme (widget, default_icon_name);
3390 info->using_default_icon = TRUE;
3391 info->using_themed_icon = TRUE;
3394 info->realized = TRUE;
3396 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3398 if (info->using_themed_icon)
3400 GtkIconTheme *icon_theme;
3402 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3403 g_list_free (icon_list);
3405 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3406 g_signal_connect (icon_theme, "changed",
3407 G_CALLBACK (update_themed_icon), window);
3412 gtk_window_unrealize_icon (GtkWindow *window)
3414 GtkWindowIconInfo *info;
3416 info = get_icon_info (window);
3421 if (info->using_themed_icon)
3423 GtkIconTheme *icon_theme;
3425 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3427 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3430 /* We don't clear the properties on the window, just figure the
3431 * window is going away.
3434 info->realized = FALSE;
3439 * gtk_window_set_icon_list:
3440 * @window: a #GtkWindow
3441 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3443 * Sets up the icon representing a #GtkWindow. The icon is used when
3444 * the window is minimized (also known as iconified). Some window
3445 * managers or desktop environments may also place it in the window
3446 * frame, or display it in other contexts.
3448 * gtk_window_set_icon_list() allows you to pass in the same icon in
3449 * several hand-drawn sizes. The list should contain the natural sizes
3450 * your icon is available in; that is, don't scale the image before
3451 * passing it to GTK+. Scaling is postponed until the last minute,
3452 * when the desired final size is known, to allow best quality.
3454 * By passing several sizes, you may improve the final image quality
3455 * of the icon, by reducing or eliminating automatic image scaling.
3457 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3458 * larger images (64x64, 128x128) if you have them.
3460 * See also gtk_window_set_default_icon_list() to set the icon
3461 * for all windows in your application in one go.
3463 * Note that transient windows (those who have been set transient for another
3464 * window using gtk_window_set_transient_for()) will inherit their
3465 * icon from their transient parent. So there's no need to explicitly
3466 * set the icon on transient windows.
3469 gtk_window_set_icon_list (GtkWindow *window,
3472 GtkWindowIconInfo *info;
3474 g_return_if_fail (GTK_IS_WINDOW (window));
3476 info = ensure_icon_info (window);
3478 if (info->icon_list == list) /* check for NULL mostly */
3481 g_list_foreach (list,
3482 (GFunc) g_object_ref, NULL);
3484 g_list_foreach (info->icon_list,
3485 (GFunc) g_object_unref, NULL);
3487 g_list_free (info->icon_list);
3489 info->icon_list = g_list_copy (list);
3491 g_object_notify (G_OBJECT (window), "icon");
3493 gtk_window_unrealize_icon (window);
3495 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3496 gtk_window_realize_icon (window);
3498 /* We could try to update our transient children, but I don't think
3499 * it's really worth it. If we did it, the best way would probably
3500 * be to have children connect to notify::icon-list
3505 * gtk_window_get_icon_list:
3506 * @window: a #GtkWindow
3508 * Retrieves the list of icons set by gtk_window_set_icon_list().
3509 * The list is copied, but the reference count on each
3510 * member won't be incremented.
3512 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3515 gtk_window_get_icon_list (GtkWindow *window)
3517 GtkWindowIconInfo *info;
3519 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3521 info = get_icon_info (window);
3524 return g_list_copy (info->icon_list);
3530 * gtk_window_set_icon:
3531 * @window: a #GtkWindow
3532 * @icon: (allow-none): icon image, or %NULL
3534 * Sets up the icon representing a #GtkWindow. This icon is used when
3535 * the window is minimized (also known as iconified). Some window
3536 * managers or desktop environments may also place it in the window
3537 * frame, or display it in other contexts.
3539 * The icon should be provided in whatever size it was naturally
3540 * drawn; that is, don't scale the image before passing it to
3541 * GTK+. Scaling is postponed until the last minute, when the desired
3542 * final size is known, to allow best quality.
3544 * If you have your icon hand-drawn in multiple sizes, use
3545 * gtk_window_set_icon_list(). Then the best size will be used.
3547 * This function is equivalent to calling gtk_window_set_icon_list()
3548 * with a 1-element list.
3550 * See also gtk_window_set_default_icon_list() to set the icon
3551 * for all windows in your application in one go.
3554 gtk_window_set_icon (GtkWindow *window,
3559 g_return_if_fail (GTK_IS_WINDOW (window));
3560 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3565 list = g_list_append (list, icon);
3567 gtk_window_set_icon_list (window, list);
3573 update_themed_icon (GtkIconTheme *icon_theme,
3576 g_object_notify (G_OBJECT (window), "icon");
3578 gtk_window_unrealize_icon (window);
3580 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3581 gtk_window_realize_icon (window);
3585 * gtk_window_set_icon_name:
3586 * @window: a #GtkWindow
3587 * @name: (allow-none): the name of the themed icon
3589 * Sets the icon for the window from a named themed icon. See
3590 * the docs for #GtkIconTheme for more details.
3592 * Note that this has nothing to do with the WM_ICON_NAME
3593 * property which is mentioned in the ICCCM.
3598 gtk_window_set_icon_name (GtkWindow *window,
3601 GtkWindowIconInfo *info;
3604 g_return_if_fail (GTK_IS_WINDOW (window));
3606 info = ensure_icon_info (window);
3608 if (g_strcmp0 (info->icon_name, name) == 0)
3611 tmp = info->icon_name;
3612 info->icon_name = g_strdup (name);
3615 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3616 g_list_free (info->icon_list);
3617 info->icon_list = NULL;
3619 update_themed_icon (NULL, window);
3621 g_object_notify (G_OBJECT (window), "icon-name");
3625 * gtk_window_get_icon_name:
3626 * @window: a #GtkWindow
3628 * Returns the name of the themed icon for the window,
3629 * see gtk_window_set_icon_name().
3631 * Returns: the icon name or %NULL if the window has
3637 gtk_window_get_icon_name (GtkWindow *window)
3639 GtkWindowIconInfo *info;
3641 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3643 info = ensure_icon_info (window);
3645 return info->icon_name;
3649 * gtk_window_get_icon:
3650 * @window: a #GtkWindow
3652 * Gets the value set by gtk_window_set_icon() (or if you've
3653 * called gtk_window_set_icon_list(), gets the first icon in
3656 * Return value: (transfer none): icon for window
3659 gtk_window_get_icon (GtkWindow *window)
3661 GtkWindowIconInfo *info;
3663 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3665 info = get_icon_info (window);
3666 if (info && info->icon_list)
3667 return GDK_PIXBUF (info->icon_list->data);
3672 /* Load pixbuf, printing warning on failure if error == NULL
3675 load_pixbuf_verbosely (const char *filename,
3678 GError *local_err = NULL;
3681 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3689 g_warning ("Error loading icon from file '%s':\n\t%s",
3690 filename, local_err->message);
3691 g_error_free (local_err);
3699 * gtk_window_set_icon_from_file:
3700 * @window: a #GtkWindow
3701 * @filename: (type filename): location of icon file
3702 * @err: (allow-none): location to store error, or %NULL.
3704 * Sets the icon for @window.
3705 * Warns on failure if @err is %NULL.
3707 * This function is equivalent to calling gtk_window_set_icon()
3708 * with a pixbuf created by loading the image from @filename.
3710 * Returns: %TRUE if setting the icon succeeded.
3715 gtk_window_set_icon_from_file (GtkWindow *window,
3716 const gchar *filename,
3719 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3723 gtk_window_set_icon (window, pixbuf);
3724 g_object_unref (pixbuf);
3733 * gtk_window_set_default_icon_list:
3734 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3736 * Sets an icon list to be used as fallback for windows that haven't
3737 * had gtk_window_set_icon_list() called on them to set up a
3738 * window-specific icon list. This function allows you to set up the
3739 * icon for all windows in your app at once.
3741 * See gtk_window_set_icon_list() for more details.
3745 gtk_window_set_default_icon_list (GList *list)
3749 if (list == default_icon_list)
3752 /* Update serial so we don't used cached pixmaps/masks
3754 default_icon_serial++;
3756 g_list_foreach (list,
3757 (GFunc) g_object_ref, NULL);
3759 g_list_foreach (default_icon_list,
3760 (GFunc) g_object_unref, NULL);
3762 g_list_free (default_icon_list);
3764 default_icon_list = g_list_copy (list);
3766 /* Update all toplevels */
3767 toplevels = gtk_window_list_toplevels ();
3768 tmp_list = toplevels;
3769 while (tmp_list != NULL)
3771 GtkWindowIconInfo *info;
3772 GtkWindow *w = tmp_list->data;
3774 info = get_icon_info (w);
3775 if (info && info->using_default_icon)
3777 gtk_window_unrealize_icon (w);
3778 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3779 gtk_window_realize_icon (w);
3782 tmp_list = tmp_list->next;
3784 g_list_free (toplevels);
3788 * gtk_window_set_default_icon:
3791 * Sets an icon to be used as fallback for windows that haven't
3792 * had gtk_window_set_icon() called on them from a pixbuf.
3797 gtk_window_set_default_icon (GdkPixbuf *icon)
3801 g_return_if_fail (GDK_IS_PIXBUF (icon));
3803 list = g_list_prepend (NULL, icon);
3804 gtk_window_set_default_icon_list (list);
3809 * gtk_window_set_default_icon_name:
3810 * @name: the name of the themed icon
3812 * Sets an icon to be used as fallback for windows that haven't
3813 * had gtk_window_set_icon_list() called on them from a named
3814 * themed icon, see gtk_window_set_icon_name().
3819 gtk_window_set_default_icon_name (const gchar *name)
3824 /* Update serial so we don't used cached pixmaps/masks
3826 default_icon_serial++;
3828 g_free (default_icon_name);
3829 default_icon_name = g_strdup (name);
3831 g_list_foreach (default_icon_list,
3832 (GFunc) g_object_unref, NULL);
3834 g_list_free (default_icon_list);
3835 default_icon_list = NULL;
3837 /* Update all toplevels */
3838 toplevels = gtk_window_list_toplevels ();
3839 tmp_list = toplevels;
3840 while (tmp_list != NULL)
3842 GtkWindowIconInfo *info;
3843 GtkWindow *w = tmp_list->data;
3845 info = get_icon_info (w);
3846 if (info && info->using_default_icon && info->using_themed_icon)
3848 gtk_window_unrealize_icon (w);
3849 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3850 gtk_window_realize_icon (w);
3853 tmp_list = tmp_list->next;
3855 g_list_free (toplevels);
3859 * gtk_window_get_default_icon_name:
3861 * Returns the fallback icon name for windows that has been set
3862 * with gtk_window_set_default_icon_name(). The returned
3863 * string is owned by GTK+ and should not be modified. It
3864 * is only valid until the next call to
3865 * gtk_window_set_default_icon_name().
3867 * Returns: the fallback icon name for windows
3872 gtk_window_get_default_icon_name (void)
3874 return default_icon_name;
3878 * gtk_window_set_default_icon_from_file:
3879 * @filename: (type filename): location of icon file
3880 * @err: (allow-none): location to store error, or %NULL.
3882 * Sets an icon to be used as fallback for windows that haven't
3883 * had gtk_window_set_icon_list() called on them from a file
3884 * on disk. Warns on failure if @err is %NULL.
3886 * Returns: %TRUE if setting the icon succeeded.
3891 gtk_window_set_default_icon_from_file (const gchar *filename,
3894 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3898 gtk_window_set_default_icon (pixbuf);
3899 g_object_unref (pixbuf);
3908 * gtk_window_get_default_icon_list:
3910 * Gets the value set by gtk_window_set_default_icon_list().
3911 * The list is a copy and should be freed with g_list_free(),
3912 * but the pixbufs in the list have not had their reference count
3915 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3918 gtk_window_get_default_icon_list (void)
3920 return g_list_copy (default_icon_list);
3924 gtk_window_set_default_size_internal (GtkWindow *window,
3925 gboolean change_width,
3927 gboolean change_height,
3929 gboolean is_geometry)
3931 GtkWindowGeometryInfo *info;
3933 g_return_if_fail (change_width == FALSE || width >= -1);
3934 g_return_if_fail (change_height == FALSE || height >= -1);
3936 info = gtk_window_get_geometry_info (window, TRUE);
3938 g_object_freeze_notify (G_OBJECT (window));
3940 info->default_is_geometry = is_geometry != FALSE;
3950 info->default_width = width;
3952 g_object_notify (G_OBJECT (window), "default-width");
3963 info->default_height = height;
3965 g_object_notify (G_OBJECT (window), "default-height");
3968 g_object_thaw_notify (G_OBJECT (window));
3970 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3974 * gtk_window_set_default_size:
3975 * @window: a #GtkWindow
3976 * @width: width in pixels, or -1 to unset the default width
3977 * @height: height in pixels, or -1 to unset the default height
3979 * Sets the default size of a window. If the window's "natural" size
3980 * (its size request) is larger than the default, the default will be
3981 * ignored. More generally, if the default size does not obey the
3982 * geometry hints for the window (gtk_window_set_geometry_hints() can
3983 * be used to set these explicitly), the default size will be clamped
3984 * to the nearest permitted size.
3986 * Unlike gtk_widget_set_size_request(), which sets a size request for
3987 * a widget and thus would keep users from shrinking the window, this
3988 * function only sets the initial size, just as if the user had
3989 * resized the window themselves. Users can still shrink the window
3990 * again as they normally would. Setting a default size of -1 means to
3991 * use the "natural" default size (the size request of the window).
3993 * For more control over a window's initial size and how resizing works,
3994 * investigate gtk_window_set_geometry_hints().
3996 * For some uses, gtk_window_resize() is a more appropriate function.
3997 * gtk_window_resize() changes the current size of the window, rather
3998 * than the size to be used on initial display. gtk_window_resize() always
3999 * affects the window itself, not the geometry widget.
4001 * The default size of a window only affects the first time a window is
4002 * shown; if a window is hidden and re-shown, it will remember the size
4003 * it had prior to hiding, rather than using the default size.
4005 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4006 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4009 gtk_window_set_default_size (GtkWindow *window,
4013 g_return_if_fail (GTK_IS_WINDOW (window));
4014 g_return_if_fail (width >= -1);
4015 g_return_if_fail (height >= -1);
4017 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4021 * gtk_window_set_default_geometry:
4022 * @window: a #GtkWindow
4023 * @width: width in resize increments, or -1 to unset the default width
4024 * @height: height in resize increments, or -1 to unset the default height
4026 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4027 * in terms of the base size and increment set with
4028 * gtk_window_set_geometry_hints.
4033 gtk_window_set_default_geometry (GtkWindow *window,
4037 g_return_if_fail (GTK_IS_WINDOW (window));
4038 g_return_if_fail (width >= -1);
4039 g_return_if_fail (height >= -1);
4041 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4045 * gtk_window_get_default_size:
4046 * @window: a #GtkWindow
4047 * @width: (out) (allow-none): location to store the default width, or %NULL
4048 * @height: (out) (allow-none): location to store the default height, or %NULL
4050 * Gets the default size of the window. A value of -1 for the width or
4051 * height indicates that a default size has not been explicitly set
4052 * for that dimension, so the "natural" size of the window will be
4057 gtk_window_get_default_size (GtkWindow *window,
4061 GtkWindowGeometryInfo *info;
4063 g_return_if_fail (GTK_IS_WINDOW (window));
4065 info = gtk_window_get_geometry_info (window, FALSE);
4068 *width = info ? info->default_width : -1;
4071 *height = info ? info->default_height : -1;
4075 * gtk_window_resize:
4076 * @window: a #GtkWindow
4077 * @width: width in pixels to resize the window to
4078 * @height: height in pixels to resize the window to
4080 * Resizes the window as if the user had done so, obeying geometry
4081 * constraints. The default geometry constraint is that windows may
4082 * not be smaller than their size request; to override this
4083 * constraint, call gtk_widget_set_size_request() to set the window's
4084 * request to a smaller value.
4086 * If gtk_window_resize() is called before showing a window for the
4087 * first time, it overrides any default size set with
4088 * gtk_window_set_default_size().
4090 * Windows may not be resized smaller than 1 by 1 pixels.
4094 gtk_window_resize (GtkWindow *window,
4098 GtkWindowGeometryInfo *info;
4100 g_return_if_fail (GTK_IS_WINDOW (window));
4101 g_return_if_fail (width > 0);
4102 g_return_if_fail (height > 0);
4104 info = gtk_window_get_geometry_info (window, TRUE);
4106 info->resize_width = width;
4107 info->resize_height = height;
4108 info->resize_is_geometry = FALSE;
4110 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4114 * gtk_window_resize_to_geometry:
4115 * @window: a #GtkWindow
4116 * @width: width in resize increments to resize the window to
4117 * @height: height in resize increments to resize the window to
4119 * Like gtk_window_resize(), but @width and @height are interpreted
4120 * in terms of the base size and increment set with
4121 * gtk_window_set_geometry_hints.
4126 gtk_window_resize_to_geometry (GtkWindow *window,
4130 GtkWindowGeometryInfo *info;
4132 g_return_if_fail (GTK_IS_WINDOW (window));
4133 g_return_if_fail (width > 0);
4134 g_return_if_fail (height > 0);
4136 info = gtk_window_get_geometry_info (window, TRUE);
4138 info->resize_width = width;
4139 info->resize_height = height;
4140 info->resize_is_geometry = TRUE;
4142 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4146 * gtk_window_get_size:
4147 * @window: a #GtkWindow
4148 * @width: (out) (allow-none): return location for width, or %NULL
4149 * @height: (out) (allow-none): return location for height, or %NULL
4151 * Obtains the current size of @window. If @window is not onscreen,
4152 * it returns the size GTK+ will suggest to the <link
4153 * linkend="gtk-X11-arch">window manager</link> for the initial window
4154 * size (but this is not reliably the same as the size the window
4155 * manager will actually select). The size obtained by
4156 * gtk_window_get_size() is the last size received in a
4157 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4158 * rather than querying the X server for the size. As a result, if you
4159 * call gtk_window_resize() then immediately call
4160 * gtk_window_get_size(), the size won't have taken effect yet. After
4161 * the window manager processes the resize request, GTK+ receives
4162 * notification that the size has changed via a configure event, and
4163 * the size of the window gets updated.
4165 * Note 1: Nearly any use of this function creates a race condition,
4166 * because the size of the window may change between the time that you
4167 * get the size and the time that you perform some action assuming
4168 * that size is the current size. To avoid race conditions, connect to
4169 * "configure-event" on the window and adjust your size-dependent
4170 * state to match the size delivered in the #GdkEventConfigure.
4172 * Note 2: The returned size does <emphasis>not</emphasis> include the
4173 * size of the window manager decorations (aka the window frame or
4174 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4175 * method of determining their size.
4177 * Note 3: If you are getting a window size in order to position
4178 * the window onscreen, there may be a better way. The preferred
4179 * way is to simply set the window's semantic type with
4180 * gtk_window_set_type_hint(), which allows the window manager to
4181 * e.g. center dialogs. Also, if you set the transient parent of
4182 * dialogs with gtk_window_set_transient_for() window managers
4183 * will often center the dialog over its parent window. It's
4184 * much preferred to let the window manager handle these
4185 * things rather than doing it yourself, because all apps will
4186 * behave consistently and according to user prefs if the window
4187 * manager handles it. Also, the window manager can take the size
4188 * of the window decorations/border into account, while your
4189 * application cannot.
4191 * In any case, if you insist on application-specified window
4192 * positioning, there's <emphasis>still</emphasis> a better way than
4193 * doing it yourself - gtk_window_set_position() will frequently
4194 * handle the details for you.
4198 gtk_window_get_size (GtkWindow *window,
4204 g_return_if_fail (GTK_IS_WINDOW (window));
4206 if (width == NULL && height == NULL)
4209 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4211 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4212 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4216 GdkRectangle configure_request;
4218 gtk_window_compute_configure_request (window,
4222 w = configure_request.width;
4223 h = configure_request.height;
4234 * @window: a #GtkWindow
4235 * @x: X coordinate to move window to
4236 * @y: Y coordinate to move window to
4238 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4239 * @window to the given position. Window managers are free to ignore
4240 * this; most window managers ignore requests for initial window
4241 * positions (instead using a user-defined placement algorithm) and
4242 * honor requests after the window has already been shown.
4244 * Note: the position is the position of the gravity-determined
4245 * reference point for the window. The gravity determines two things:
4246 * first, the location of the reference point in root window
4247 * coordinates; and second, which point on the window is positioned at
4248 * the reference point.
4250 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4251 * point is simply the @x, @y supplied to gtk_window_move(). The
4252 * top-left corner of the window decorations (aka window frame or
4253 * border) will be placed at @x, @y. Therefore, to position a window
4254 * at the top left of the screen, you want to use the default gravity
4255 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4257 * To position a window at the bottom right corner of the screen, you
4258 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4259 * point is at @x + the window width and @y + the window height, and
4260 * the bottom-right corner of the window border will be placed at that
4261 * reference point. So, to place a window in the bottom right corner
4262 * you would first set gravity to south east, then write:
4263 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4264 * gdk_screen_height () - window_height)</literal> (note that this
4265 * example does not take multi-head scenarios into account).
4267 * The Extended Window Manager Hints specification at <ulink
4268 * url="http://www.freedesktop.org/Standards/wm-spec">
4269 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4270 * nice table of gravities in the "implementation notes" section.
4272 * The gtk_window_get_position() documentation may also be relevant.
4275 gtk_window_move (GtkWindow *window,
4279 GtkWindowGeometryInfo *info;
4282 g_return_if_fail (GTK_IS_WINDOW (window));
4284 widget = GTK_WIDGET (window);
4286 info = gtk_window_get_geometry_info (window, TRUE);
4288 if (gtk_widget_get_mapped (widget))
4290 GtkAllocation allocation;
4292 gtk_widget_get_allocation (widget, &allocation);
4294 /* we have now sent a request with this position
4295 * with currently-active constraints, so toggle flag.
4297 info->position_constraints_changed = FALSE;
4299 /* we only constrain if mapped - if not mapped,
4300 * then gtk_window_compute_configure_request()
4301 * will apply the constraints later, and we
4302 * don't want to lose information about
4303 * what position the user set before then.
4304 * i.e. if you do a move() then turn off POS_CENTER
4305 * then show the window, your move() will work.
4307 gtk_window_constrain_position (window,
4308 allocation.width, allocation.height,
4311 /* Note that this request doesn't go through our standard request
4312 * framework, e.g. doesn't increment configure_request_count,
4313 * doesn't set info->last, etc.; that's because
4314 * we don't save the info needed to arrive at this same request
4317 * To gtk_window_move_resize(), this will end up looking exactly
4318 * the same as the position being changed by the window
4321 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4325 /* Save this position to apply on mapping */
4326 info->initial_x = x;
4327 info->initial_y = y;
4328 info->initial_pos_set = TRUE;
4333 * gtk_window_get_position:
4334 * @window: a #GtkWindow
4335 * @root_x: (out) (allow-none): eturn location for X coordinate of
4336 * gravity-determined reference point, or %NULL
4337 * @root_y: (out) (allow-none): return location for Y coordinate of
4338 * gravity-determined reference point, or %NULL
4340 * This function returns the position you need to pass to
4341 * gtk_window_move() to keep @window in its current position.
4342 * This means that the meaning of the returned value varies with
4343 * window gravity. See gtk_window_move() for more details.
4345 * If you haven't changed the window gravity, its gravity will be
4346 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4347 * gets the position of the top-left corner of the window manager
4348 * frame for the window. gtk_window_move() sets the position of this
4349 * same top-left corner.
4351 * gtk_window_get_position() is not 100% reliable because the X Window System
4352 * does not specify a way to obtain the geometry of the
4353 * decorations placed on a window by the window manager.
4354 * Thus GTK+ is using a "best guess" that works with most
4357 * Moreover, nearly all window managers are historically broken with
4358 * respect to their handling of window gravity. So moving a window to
4359 * its current position as returned by gtk_window_get_position() tends
4360 * to result in moving the window slightly. Window managers are
4361 * slowly getting better over time.
4363 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4364 * frame is not relevant, and thus gtk_window_get_position() will
4365 * always produce accurate results. However you can't use static
4366 * gravity to do things like place a window in a corner of the screen,
4367 * because static gravity ignores the window manager decorations.
4369 * If you are saving and restoring your application's window
4370 * positions, you should know that it's impossible for applications to
4371 * do this without getting it somewhat wrong because applications do
4372 * not have sufficient knowledge of window manager state. The Correct
4373 * Mechanism is to support the session management protocol (see the
4374 * "GnomeClient" object in the GNOME libraries for example) and allow
4375 * the window manager to save your window sizes and positions.
4380 gtk_window_get_position (GtkWindow *window,
4384 GtkWindowPrivate *priv;
4386 GdkWindow *gdk_window;
4388 g_return_if_fail (GTK_IS_WINDOW (window));
4390 priv = window->priv;
4391 widget = GTK_WIDGET (window);
4392 gdk_window = gtk_widget_get_window (widget);
4394 if (priv->gravity == GDK_GRAVITY_STATIC)
4396 if (gtk_widget_get_mapped (widget))
4398 /* This does a server round-trip, which is sort of wrong;
4399 * but a server round-trip is inevitable for
4400 * gdk_window_get_frame_extents() in the usual
4401 * NorthWestGravity case below, so not sure what else to
4402 * do. We should likely be consistent about whether we get
4403 * the client-side info or the server-side info.
4405 gdk_window_get_origin (gdk_window, root_x, root_y);
4409 GdkRectangle configure_request;
4411 gtk_window_compute_configure_request (window,
4415 *root_x = configure_request.x;
4416 *root_y = configure_request.y;
4421 GdkRectangle frame_extents;
4426 if (gtk_widget_get_mapped (widget))
4428 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4429 x = frame_extents.x;
4430 y = frame_extents.y;
4431 gtk_window_get_size (window, &w, &h);
4435 /* We just say the frame has 0 size on all sides.
4436 * Not sure what else to do.
4438 gtk_window_compute_configure_request (window,
4441 x = frame_extents.x;
4442 y = frame_extents.y;
4443 w = frame_extents.width;
4444 h = frame_extents.height;
4447 switch (priv->gravity)
4449 case GDK_GRAVITY_NORTH:
4450 case GDK_GRAVITY_CENTER:
4451 case GDK_GRAVITY_SOUTH:
4452 /* Find center of frame. */
4453 x += frame_extents.width / 2;
4454 /* Center client window on that point. */
4458 case GDK_GRAVITY_SOUTH_EAST:
4459 case GDK_GRAVITY_EAST:
4460 case GDK_GRAVITY_NORTH_EAST:
4461 /* Find right edge of frame */
4462 x += frame_extents.width;
4463 /* Align left edge of client at that point. */
4470 switch (priv->gravity)
4472 case GDK_GRAVITY_WEST:
4473 case GDK_GRAVITY_CENTER:
4474 case GDK_GRAVITY_EAST:
4475 /* Find center of frame. */
4476 y += frame_extents.height / 2;
4477 /* Center client window there. */
4480 case GDK_GRAVITY_SOUTH_WEST:
4481 case GDK_GRAVITY_SOUTH:
4482 case GDK_GRAVITY_SOUTH_EAST:
4483 /* Find south edge of frame */
4484 y += frame_extents.height;
4485 /* Place bottom edge of client there */
4500 * gtk_window_reshow_with_initial_size:
4501 * @window: a #GtkWindow
4503 * Hides @window, then reshows it, resetting the
4504 * default size and position of the window. Used
4505 * by GUI builders only.
4508 gtk_window_reshow_with_initial_size (GtkWindow *window)
4512 g_return_if_fail (GTK_IS_WINDOW (window));
4514 widget = GTK_WIDGET (window);
4516 gtk_widget_hide (widget);
4517 gtk_widget_unrealize (widget);
4518 gtk_widget_show (widget);
4522 gtk_window_destroy (GtkWidget *widget)
4524 GtkWindow *window = GTK_WINDOW (widget);
4525 GtkWindowPrivate *priv = window->priv;
4527 gtk_window_release_application (window);
4529 toplevel_list = g_slist_remove (toplevel_list, window);
4531 if (priv->transient_parent)
4532 gtk_window_set_transient_for (window, NULL);
4534 /* frees the icons */
4535 gtk_window_set_icon_list (window, NULL);
4537 if (priv->has_user_ref_count)
4539 priv->has_user_ref_count = FALSE;
4540 g_object_unref (window);
4544 gtk_window_group_remove_window (priv->group, window);
4546 gtk_window_free_key_hash (window);
4548 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4552 gtk_window_finalize (GObject *object)
4554 GtkWindow *window = GTK_WINDOW (object);
4555 GtkWindowPrivate *priv = window->priv;
4556 GtkMnemonicHash *mnemonic_hash;
4558 g_free (priv->title);
4559 g_free (priv->wmclass_name);
4560 g_free (priv->wmclass_class);
4561 g_free (priv->wm_role);
4562 gtk_window_release_application (window);
4564 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4566 _gtk_mnemonic_hash_free (mnemonic_hash);
4568 if (priv->geometry_info)
4570 if (priv->geometry_info->widget)
4571 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4572 gtk_widget_destroyed,
4573 &priv->geometry_info->widget);
4574 g_free (priv->geometry_info);
4577 if (priv->keys_changed_handler)
4579 g_source_remove (priv->keys_changed_handler);
4580 priv->keys_changed_handler = 0;
4584 g_signal_handlers_disconnect_by_func (priv->screen,
4585 gtk_window_on_composited_changed, window);
4587 g_free (priv->startup_id);
4589 #ifdef GDK_WINDOWING_X11
4590 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4591 gtk_window_on_theme_variant_changed,
4595 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4599 gtk_window_show (GtkWidget *widget)
4601 GtkWindow *window = GTK_WINDOW (widget);
4602 GtkWindowPrivate *priv = window->priv;
4603 GtkContainer *container = GTK_CONTAINER (window);
4604 gboolean need_resize;
4607 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4609 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4613 _gtk_widget_set_visible_flag (widget, TRUE);
4615 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4616 _gtk_container_set_need_resize (container, FALSE);
4620 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4621 GtkAllocation allocation = { 0, 0 };
4622 GdkRectangle configure_request;
4623 GdkGeometry new_geometry;
4625 gboolean was_realized;
4627 /* We are going to go ahead and perform this configure request
4628 * and then emulate a configure notify by going ahead and
4629 * doing a size allocate. Sort of a synchronous
4630 * mini-copy of gtk_window_move_resize() here.
4632 gtk_window_compute_configure_request (window,
4637 /* We update this because we are going to go ahead
4638 * and gdk_window_resize() below, rather than
4641 info->last.configure_request.width = configure_request.width;
4642 info->last.configure_request.height = configure_request.height;
4644 /* and allocate the window - this is normally done
4645 * in move_resize in response to configure notify
4647 allocation.width = configure_request.width;
4648 allocation.height = configure_request.height;
4649 gtk_widget_size_allocate (widget, &allocation);
4651 /* Then we guarantee we have a realize */
4652 was_realized = FALSE;
4653 if (!gtk_widget_get_realized (widget))
4655 gtk_widget_realize (widget);
4656 was_realized = TRUE;
4659 /* We only send configure request if we didn't just finish
4660 * creating the window; if we just created the window
4661 * then we created it with widget->allocation anyhow.
4664 gdk_window_move_resize (gtk_widget_get_window (widget),
4665 configure_request.x,
4666 configure_request.y,
4667 configure_request.width,
4668 configure_request.height);
4671 gtk_container_check_resize (container);
4673 gtk_widget_map (widget);
4675 /* Try to make sure that we have some focused widget
4677 #ifdef GDK_WINDOWING_X11
4678 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4679 GTK_IS_PLUG (window);
4683 if (!priv->focus_widget && !is_plug)
4684 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4687 gtk_grab_add (widget);
4691 gtk_window_hide (GtkWidget *widget)
4693 GtkWindow *window = GTK_WINDOW (widget);
4694 GtkWindowPrivate *priv = window->priv;
4696 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4698 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4702 _gtk_widget_set_visible_flag (widget, FALSE);
4703 gtk_widget_unmap (widget);
4706 gtk_grab_remove (widget);
4710 gtk_window_map (GtkWidget *widget)
4713 GtkWindow *window = GTK_WINDOW (widget);
4714 GtkWindowPrivate *priv = window->priv;
4715 GdkWindow *toplevel;
4716 GdkWindow *gdk_window;
4717 gboolean auto_mnemonics;
4718 GtkPolicyType visible_focus;
4720 gdk_window = gtk_widget_get_window (widget);
4722 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4724 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4728 gtk_widget_set_mapped (widget, TRUE);
4730 child = gtk_bin_get_child (&(window->bin));
4732 gtk_widget_get_visible (child) &&
4733 !gtk_widget_get_mapped (child))
4734 gtk_widget_map (child);
4736 toplevel = gdk_window;
4738 if (priv->maximize_initially)
4739 gdk_window_maximize (toplevel);
4741 gdk_window_unmaximize (toplevel);
4743 if (priv->stick_initially)
4744 gdk_window_stick (toplevel);
4746 gdk_window_unstick (toplevel);
4748 if (priv->iconify_initially)
4749 gdk_window_iconify (toplevel);
4751 gdk_window_deiconify (toplevel);
4753 if (priv->fullscreen_initially)
4754 gdk_window_fullscreen (toplevel);
4756 gdk_window_unfullscreen (toplevel);
4758 gdk_window_set_keep_above (toplevel, priv->above_initially);
4760 gdk_window_set_keep_below (toplevel, priv->below_initially);
4762 if (priv->type == GTK_WINDOW_TOPLEVEL)
4763 gtk_window_set_theme_variant (window);
4765 /* No longer use the default settings */
4766 priv->need_default_size = FALSE;
4767 priv->need_default_position = FALSE;
4769 if (priv->reset_type_hint)
4771 /* We should only reset the type hint when the application
4772 * used gtk_window_set_type_hint() to change the hint.
4773 * Some applications use X directly to change the properties;
4774 * in that case, we shouldn't overwrite what they did.
4776 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4777 priv->reset_type_hint = FALSE;
4780 gdk_window_show (gdk_window);
4782 if (priv->grip_window)
4783 gdk_window_show (priv->grip_window);
4785 if (!disable_startup_notification)
4787 /* Do we have a custom startup-notification id? */
4788 if (priv->startup_id != NULL)
4790 /* Make sure we have a "real" id */
4791 if (!startup_id_is_fake (priv->startup_id))
4792 gdk_notify_startup_complete_with_id (priv->startup_id);
4794 g_free (priv->startup_id);
4795 priv->startup_id = NULL;
4797 else if (!sent_startup_notification)
4799 sent_startup_notification = TRUE;
4800 gdk_notify_startup_complete ();
4804 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4805 * (as in the case of popup menus), then hide mnemonics initially
4807 g_object_get (gtk_widget_get_settings (widget),
4808 "gtk-auto-mnemonics", &auto_mnemonics,
4809 "gtk-visible-focus", &visible_focus,
4812 if (auto_mnemonics && !priv->mnemonics_visible_set)
4813 gtk_window_set_mnemonics_visible (window, FALSE);
4815 /* inherit from transient parent, so that a dialog that is
4816 * opened via keynav shows focus initially
4818 if (priv->transient_parent)
4819 gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
4821 gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
4825 gtk_window_map_event (GtkWidget *widget,
4828 if (!gtk_widget_get_mapped (widget))
4830 /* we should be be unmapped, but are getting a MapEvent, this may happen
4831 * to toplevel XWindows if mapping was intercepted by a window manager
4832 * and an unmap request occoured while the MapRequestEvent was still
4833 * being handled. we work around this situaiton here by re-requesting
4834 * the window being unmapped. more details can be found in:
4835 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4837 gdk_window_hide (gtk_widget_get_window (widget));
4843 gtk_window_unmap (GtkWidget *widget)
4845 GtkWindow *window = GTK_WINDOW (widget);
4846 GtkWindowPrivate *priv = window->priv;
4848 GtkWindowGeometryInfo *info;
4849 GdkWindow *gdk_window;
4850 GdkWindowState state;
4852 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4854 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
4858 gdk_window = gtk_widget_get_window (widget);
4860 gtk_widget_set_mapped (widget, FALSE);
4861 gdk_window_withdraw (gdk_window);
4863 priv->configure_request_count = 0;
4864 priv->configure_notify_received = FALSE;
4866 /* on unmap, we reset the default positioning of the window,
4867 * so it's placed again, but we don't reset the default
4868 * size of the window, so it's remembered.
4870 priv->need_default_position = TRUE;
4872 info = gtk_window_get_geometry_info (window, FALSE);
4875 info->initial_pos_set = FALSE;
4876 info->position_constraints_changed = FALSE;
4879 state = gdk_window_get_state (gdk_window);
4880 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4881 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4882 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4883 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4884 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4886 child = gtk_bin_get_child (&(window->bin));
4888 gtk_widget_unmap (child);
4891 /* (Note: Replace "size" with "width" or "height". Also, the request
4892 * mode is honoured.)
4893 * For selecting the default window size, the following conditions
4894 * should hold (in order of importance):
4895 * - the size is not below the minimum size
4896 * Windows cannot be resized below their minimum size, so we must
4897 * ensure we don't do that either.
4898 * - the size is not above the natural size
4899 * It seems weird to allocate more than this in an initial guess.
4900 * - the size does not exceed that of a maximized window
4901 * We want to see the whole window after all.
4902 * (Note that this may not be possible to achieve due to imperfect
4903 * information from the windowing system.)
4906 /* We use these for now to not make windows too big by accident. Note
4907 * that we still clamp these numbers by screen size. Also note that
4908 * minimum size still overrides this. So keep your windows small! :)
4910 #define MAX_DEFAULT_WINDOW_WIDTH 640
4911 #define MAX_DEFAULT_WINDOW_HEIGHT 480
4914 gtk_window_guess_default_size (GtkWindow *window,
4918 GtkWidget *widget = GTK_WIDGET (window);
4920 int minimum, natural;
4922 screen = gtk_widget_get_screen (widget);
4924 *width = gdk_screen_get_width (screen);
4925 *height = gdk_screen_get_height (screen);
4927 if (*width >= *height)
4930 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
4931 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
4936 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
4937 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
4940 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
4942 gtk_widget_get_preferred_height (widget, &minimum, &natural);
4943 *height = MAX (minimum, MIN (*height, natural));
4945 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
4946 *width = MAX (minimum, MIN (*width, natural));
4948 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
4950 gtk_widget_get_preferred_width (widget, &minimum, &natural);
4951 *width = MAX (minimum, MIN (*width, natural));
4953 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
4954 *height = MAX (minimum, MIN (*height, natural));
4959 gtk_window_realize (GtkWidget *widget)
4961 GtkAllocation allocation;
4963 GdkWindow *parent_window;
4964 GdkWindow *gdk_window;
4965 GdkWindowAttr attributes;
4966 gint attributes_mask;
4967 GtkWindowPrivate *priv;
4968 GtkStyleContext *context;
4970 window = GTK_WINDOW (widget);
4971 priv = window->priv;
4973 gtk_widget_get_allocation (widget, &allocation);
4975 if (gtk_widget_get_parent_window (widget))
4977 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
4979 gtk_widget_set_realized (widget, TRUE);
4981 attributes.x = allocation.x;
4982 attributes.y = allocation.y;
4983 attributes.width = allocation.width;
4984 attributes.height = allocation.height;
4985 attributes.window_type = GDK_WINDOW_CHILD;
4987 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
4989 attributes.visual = gtk_widget_get_visual (widget);
4990 attributes.wclass = GDK_INPUT_OUTPUT;
4992 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
4994 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
4995 &attributes, attributes_mask);
4996 gtk_widget_set_window (widget, gdk_window);
4997 gdk_window_set_user_data (gdk_window, widget);
4999 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
5001 gdk_window_enable_synchronized_configure (gdk_window);
5005 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5007 /* ensure widget tree is properly size allocated */
5008 if (allocation.x == -1 &&
5009 allocation.y == -1 &&
5010 allocation.width == 1 &&
5011 allocation.height == 1)
5017 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5018 if (allocation.width == 0 || allocation.height == 0)
5020 /* non-empty window */
5021 allocation.width = 200;
5022 allocation.height = 200;
5024 gtk_widget_size_allocate (widget, &allocation);
5026 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5028 g_return_if_fail (!gtk_widget_get_realized (widget));
5031 gtk_widget_set_realized (widget, TRUE);
5035 case GTK_WINDOW_TOPLEVEL:
5036 attributes.window_type = GDK_WINDOW_TOPLEVEL;
5038 case GTK_WINDOW_POPUP:
5039 attributes.window_type = GDK_WINDOW_TEMP;
5042 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5046 attributes.title = priv->title;
5047 attributes.wmclass_name = priv->wmclass_name;
5048 attributes.wmclass_class = priv->wmclass_class;
5049 attributes.wclass = GDK_INPUT_OUTPUT;
5050 attributes.visual = gtk_widget_get_visual (widget);
5052 attributes_mask = 0;
5053 parent_window = gtk_widget_get_root_window (widget);
5055 gtk_widget_get_allocation (widget, &allocation);
5056 attributes.width = allocation.width;
5057 attributes.height = allocation.height;
5058 attributes.event_mask = gtk_widget_get_events (widget);
5059 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5060 GDK_KEY_PRESS_MASK |
5061 GDK_KEY_RELEASE_MASK |
5062 GDK_ENTER_NOTIFY_MASK |
5063 GDK_LEAVE_NOTIFY_MASK |
5064 GDK_FOCUS_CHANGE_MASK |
5065 GDK_STRUCTURE_MASK);
5066 attributes.type_hint = priv->type_hint;
5068 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5069 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5070 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5072 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5073 gtk_widget_set_window (widget, gdk_window);
5075 if (priv->opacity_set)
5076 gdk_window_set_opacity (gdk_window, priv->opacity);
5078 gdk_window_enable_synchronized_configure (gdk_window);
5080 gdk_window_set_user_data (gdk_window, window);
5082 context = gtk_widget_get_style_context (widget);
5083 gtk_style_context_set_background (context, gdk_window);
5086 if (priv->transient_parent &&
5087 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5088 gdk_window_set_transient_for (gdk_window,
5089 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5092 gdk_window_set_role (gdk_window, priv->wm_role);
5094 if (!priv->decorated)
5095 gdk_window_set_decorations (gdk_window, 0);
5097 if (!priv->deletable)
5098 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5100 if (gtk_window_get_skip_pager_hint (window))
5101 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5103 if (gtk_window_get_skip_taskbar_hint (window))
5104 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5106 if (gtk_window_get_accept_focus (window))
5107 gdk_window_set_accept_focus (gdk_window, TRUE);
5109 gdk_window_set_accept_focus (gdk_window, FALSE);
5111 if (gtk_window_get_focus_on_map (window))
5112 gdk_window_set_focus_on_map (gdk_window, TRUE);
5114 gdk_window_set_focus_on_map (gdk_window, FALSE);
5117 gdk_window_set_modal_hint (gdk_window, TRUE);
5119 gdk_window_set_modal_hint (gdk_window, FALSE);
5121 if (priv->startup_id)
5123 #ifdef GDK_WINDOWING_X11
5124 if (GDK_IS_X11_WINDOW (gdk_window))
5126 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5127 if (timestamp != GDK_CURRENT_TIME)
5128 gdk_x11_window_set_user_time (gdk_window, timestamp);
5131 if (!startup_id_is_fake (priv->startup_id))
5132 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5135 #ifdef GDK_WINDOWING_X11
5136 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5138 if (GDK_IS_X11_WINDOW (gdk_window))
5139 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5144 gtk_window_realize_icon (window);
5146 if (priv->has_resize_grip)
5147 resize_grip_create_window (window);
5151 gtk_window_unrealize (GtkWidget *widget)
5153 GtkWindow *window = GTK_WINDOW (widget);
5154 GtkWindowPrivate *priv = window->priv;
5155 GtkWindowGeometryInfo *info;
5157 /* On unrealize, we reset the size of the window such
5158 * that we will re-apply the default sizing stuff
5159 * next time we show the window.
5161 * Default positioning is reset on unmap, instead of unrealize.
5163 priv->need_default_size = TRUE;
5164 info = gtk_window_get_geometry_info (window, FALSE);
5167 info->resize_width = -1;
5168 info->resize_height = -1;
5169 info->last.configure_request.x = 0;
5170 info->last.configure_request.y = 0;
5171 info->last.configure_request.width = -1;
5172 info->last.configure_request.height = -1;
5173 /* be sure we reset geom hints on re-realize */
5174 info->last.flags = 0;
5178 gtk_window_unrealize_icon (window);
5180 if (priv->grip_window != NULL)
5181 resize_grip_destroy_window (window);
5183 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5186 static GtkJunctionSides
5187 get_grip_junction (GtkWidget *widget)
5189 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5190 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5192 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5196 get_drag_edge (GtkWidget *widget,
5197 GdkWindowEdge *edge)
5199 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5200 gboolean hresizable;
5201 gboolean vresizable;
5202 GtkTextDirection dir;
5203 GtkWindowGeometryInfo *info;
5208 info = priv->geometry_info;
5211 GdkWindowHints flags = info->last.flags;
5212 GdkGeometry *geometry = &info->last.geometry;
5214 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5216 hresizable = geometry->min_width < geometry->max_width;
5217 vresizable = geometry->min_height < geometry->max_height;
5221 dir = gtk_widget_get_direction (widget);
5223 if (hresizable && vresizable)
5224 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5225 else if (hresizable)
5226 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5227 else if (vresizable)
5228 *edge = GDK_WINDOW_EDGE_SOUTH;
5236 set_grip_cursor (GtkWindow *window)
5238 GtkWidget *widget = GTK_WIDGET (window);
5239 GtkWindowPrivate *priv = window->priv;
5241 if (priv->grip_window == NULL)
5244 if (gtk_widget_is_sensitive (widget))
5247 GdkDisplay *display;
5248 GdkCursorType cursor_type;
5251 cursor_type = GDK_LEFT_PTR;
5253 if (get_drag_edge (widget, &edge))
5257 case GDK_WINDOW_EDGE_EAST:
5258 cursor_type = GDK_RIGHT_SIDE;
5260 case GDK_WINDOW_EDGE_SOUTH_EAST:
5261 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5263 case GDK_WINDOW_EDGE_SOUTH:
5264 cursor_type = GDK_BOTTOM_SIDE;
5266 case GDK_WINDOW_EDGE_SOUTH_WEST:
5267 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5269 case GDK_WINDOW_EDGE_WEST:
5270 cursor_type = GDK_LEFT_SIDE;
5276 display = gtk_widget_get_display (widget);
5277 cursor = gdk_cursor_new_for_display (display, cursor_type);
5278 gdk_window_set_cursor (priv->grip_window, cursor);
5279 g_object_unref (cursor);
5282 gdk_window_set_cursor (priv->grip_window, NULL);
5286 set_grip_shape (GtkWindow *window)
5288 GtkWindowPrivate *priv = window->priv;
5289 cairo_region_t *region;
5290 cairo_surface_t *surface;
5292 double width, height;
5294 if (priv->grip_window == NULL)
5297 width = gdk_window_get_width (priv->grip_window);
5298 height = gdk_window_get_height (priv->grip_window);
5299 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5301 cr = cairo_create (surface);
5302 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5304 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5305 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5307 cairo_move_to (cr, width, 0.0);
5308 cairo_line_to (cr, width, height);
5309 cairo_line_to (cr, 0.0, height);
5313 cairo_move_to (cr, 0.0, 0.0);
5314 cairo_line_to (cr, width, height);
5315 cairo_line_to (cr, 0.0, height);
5317 cairo_close_path (cr);
5320 region = gdk_cairo_region_create_from_surface (surface);
5321 cairo_surface_destroy (surface);
5323 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5324 cairo_region_destroy (region);
5328 set_grip_position (GtkWindow *window)
5330 GtkWindowPrivate *priv = window->priv;
5333 if (priv->grip_window == NULL)
5336 gtk_window_get_resize_grip_area (window, &rect);
5337 gdk_window_raise (priv->grip_window);
5338 gdk_window_move_resize (priv->grip_window,
5340 rect.width, rect.height);
5344 gtk_window_size_allocate (GtkWidget *widget,
5345 GtkAllocation *allocation)
5347 GtkWindow *window = GTK_WINDOW (widget);
5348 GtkAllocation child_allocation;
5352 gtk_widget_set_allocation (widget, allocation);
5354 if (gtk_widget_get_realized (widget))
5356 /* If it's not a toplevel we're embedded, we need to resize the window's
5357 * window and skip the grip.
5359 if (!gtk_widget_is_toplevel (widget))
5361 gdk_window_move_resize (gtk_widget_get_window (widget),
5362 allocation->x, allocation->y,
5363 allocation->width, allocation->height);
5367 update_grip_visibility (window);
5368 set_grip_position (window);
5372 child = gtk_bin_get_child (&(window->bin));
5373 if (child && gtk_widget_get_visible (child))
5375 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5376 child_allocation.x = border_width;
5377 child_allocation.y = border_width;
5378 child_allocation.width =
5379 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5380 child_allocation.height =
5381 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5383 gtk_widget_size_allocate (child, &child_allocation);
5388 gtk_window_configure_event (GtkWidget *widget,
5389 GdkEventConfigure *event)
5391 GtkAllocation allocation;
5392 GtkWindow *window = GTK_WINDOW (widget);
5393 GtkWindowPrivate *priv = window->priv;
5394 gboolean expected_reply = priv->configure_request_count > 0;
5396 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5398 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5399 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5401 gdk_window_configure_finished (gtk_widget_get_window (widget));
5405 /* priv->configure_request_count incremented for each
5406 * configure request, and decremented to a min of 0 for
5407 * each configure notify.
5409 * All it means is that we know we will get at least
5410 * priv->configure_request_count more configure notifies.
5411 * We could get more configure notifies than that; some
5412 * of the configure notifies we get may be unrelated to
5413 * the configure requests. But we will get at least
5414 * priv->configure_request_count notifies.
5417 if (priv->configure_request_count > 0)
5419 priv->configure_request_count -= 1;
5420 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5423 /* As an optimization, we avoid a resize when possible.
5425 * The only times we can avoid a resize are:
5426 * - we know only the position changed, not the size
5427 * - we know we have made more requests and so will get more
5428 * notifies and can wait to resize when we get them
5430 gtk_widget_get_allocation (widget, &allocation);
5431 if (!expected_reply &&
5432 (allocation.width == event->width &&
5433 allocation.height == event->height))
5435 gdk_window_configure_finished (gtk_widget_get_window (widget));
5440 * If we do need to resize, we do that by:
5441 * - filling in widget->allocation with the new size
5442 * - setting configure_notify_received to TRUE
5443 * for use in gtk_window_move_resize()
5444 * - queueing a resize, leading to invocation of
5445 * gtk_window_move_resize() in an idle handler
5449 priv->configure_notify_received = TRUE;
5451 allocation.width = event->width;
5452 allocation.height = event->height;
5453 gtk_widget_set_allocation (widget, &allocation);
5455 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5457 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5463 gtk_window_state_event (GtkWidget *widget,
5464 GdkEventWindowState *event)
5466 update_grip_visibility (GTK_WINDOW (widget));
5472 gtk_window_direction_changed (GtkWidget *widget,
5473 GtkTextDirection prev_dir)
5475 GtkWindow *window = GTK_WINDOW (widget);
5477 set_grip_cursor (window);
5478 set_grip_position (window);
5479 set_grip_shape (window);
5483 gtk_window_state_changed (GtkWidget *widget,
5484 GtkStateType previous_state)
5486 GtkWindow *window = GTK_WINDOW (widget);
5488 update_grip_visibility (window);
5492 gtk_window_style_updated (GtkWidget *widget)
5494 GtkWindow *window = GTK_WINDOW (widget);
5495 GtkWindowPrivate *priv = window->priv;
5498 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5500 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5502 gdk_window_move_resize (priv->grip_window,
5504 rect.width, rect.height);
5506 set_grip_shape (window);
5507 gtk_widget_queue_resize (widget);
5512 resize_grip_create_window (GtkWindow *window)
5515 GtkWindowPrivate *priv;
5516 GdkWindowAttr attributes;
5517 gint attributes_mask;
5520 priv = window->priv;
5521 widget = GTK_WIDGET (window);
5523 g_return_if_fail (gtk_widget_get_realized (widget));
5524 g_return_if_fail (priv->grip_window == NULL);
5526 gtk_window_get_resize_grip_area (window, &rect);
5528 attributes.x = rect.x;
5529 attributes.y = rect.y;
5530 attributes.width = rect.width;
5531 attributes.height = rect.height;
5532 attributes.window_type = GDK_WINDOW_CHILD;
5533 attributes.wclass = GDK_INPUT_OUTPUT;
5534 attributes.event_mask = gtk_widget_get_events (widget) |
5536 GDK_BUTTON_PRESS_MASK;
5538 attributes_mask = GDK_WA_X | GDK_WA_Y;
5540 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5544 gdk_window_set_user_data (priv->grip_window, widget);
5546 gdk_window_raise (priv->grip_window);
5548 set_grip_shape (window);
5549 update_grip_visibility (window);
5553 resize_grip_destroy_window (GtkWindow *window)
5555 GtkWindowPrivate *priv = window->priv;
5557 gdk_window_set_user_data (priv->grip_window, NULL);
5558 gdk_window_destroy (priv->grip_window);
5559 priv->grip_window = NULL;
5560 update_grip_visibility (window);
5564 * gtk_window_set_has_resize_grip:
5565 * @window: a #GtkWindow
5566 * @value: %TRUE to allow a resize grip
5568 * Sets whether @window has a corner resize grip.
5570 * Note that the resize grip is only shown if the window
5571 * is actually resizable and not maximized. Use
5572 * gtk_window_resize_grip_is_visible() to find out if the
5573 * resize grip is currently shown.
5578 gtk_window_set_has_resize_grip (GtkWindow *window,
5581 GtkWidget *widget = GTK_WIDGET (window);
5582 GtkWindowPrivate *priv = window->priv;
5584 value = value != FALSE;
5586 if (value != priv->has_resize_grip)
5588 priv->has_resize_grip = value;
5589 gtk_widget_queue_draw (widget);
5591 if (gtk_widget_get_realized (widget) &&
5592 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5594 if (priv->has_resize_grip && priv->grip_window == NULL)
5595 resize_grip_create_window (window);
5596 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5597 resize_grip_destroy_window (window);
5600 g_object_notify (G_OBJECT (window), "has-resize-grip");
5605 update_grip_visibility (GtkWindow *window)
5607 GtkWindowPrivate *priv = window->priv;
5610 val = gtk_window_resize_grip_is_visible (window);
5612 if (priv->grip_window != NULL)
5616 gdk_window_show (priv->grip_window);
5617 set_grip_cursor (window);
5621 gdk_window_hide (priv->grip_window);
5625 if (priv->resize_grip_visible != val)
5627 priv->resize_grip_visible = val;
5629 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5634 * gtk_window_resize_grip_is_visible:
5635 * @window: a #GtkWindow
5637 * Determines whether a resize grip is visible for the specified window.
5639 * Returns: %TRUE if a resize grip exists and is visible
5644 gtk_window_resize_grip_is_visible (GtkWindow *window)
5647 GtkWindowPrivate *priv;
5650 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5652 priv = window->priv;
5653 widget = GTK_WIDGET (window);
5655 if (priv->type == GTK_WINDOW_POPUP)
5658 if (!priv->resizable)
5661 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5664 if (gtk_widget_get_realized (widget))
5666 GdkWindowState state;
5668 state = gdk_window_get_state (gtk_widget_get_window (widget));
5670 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5674 if (!get_drag_edge (widget, &edge))
5677 return window->priv->has_resize_grip;
5681 * gtk_window_get_has_resize_grip:
5682 * @window: a #GtkWindow
5684 * Determines whether the window may have a resize grip.
5686 * Returns: %TRUE if the window has a resize grip
5691 gtk_window_get_has_resize_grip (GtkWindow *window)
5693 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5695 return window->priv->has_resize_grip;
5699 * gtk_window_get_resize_grip_area:
5700 * @window: a #GtkWindow
5701 * @rect: (out): a pointer to a #GdkRectangle which we should store
5702 * the resize grip area
5704 * If a window has a resize grip, this will retrieve the grip
5705 * position, width and height into the specified #GdkRectangle.
5707 * Returns: %TRUE if the resize grip's area was retrieved
5712 gtk_window_get_resize_grip_area (GtkWindow *window,
5715 GtkWidget *widget = GTK_WIDGET (window);
5716 GtkAllocation allocation;
5720 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5722 if (!window->priv->has_resize_grip)
5725 gtk_widget_get_allocation (widget, &allocation);
5727 gtk_widget_style_get (widget,
5728 "resize-grip-width", &grip_width,
5729 "resize-grip-height", &grip_height,
5732 if (grip_width > allocation.width)
5733 grip_width = allocation.width;
5735 if (grip_height > allocation.height)
5736 grip_height = allocation.height;
5738 rect->width = grip_width;
5739 rect->height = grip_height;
5740 rect->y = allocation.y + allocation.height - grip_height;
5742 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5743 rect->x = allocation.x + allocation.width - grip_width;
5745 rect->x = allocation.x;
5750 /* the accel_key and accel_mods fields of the key have to be setup
5751 * upon calling this function. it'll then return whether that key
5752 * is at all used as accelerator, and if so will OR in the
5753 * accel_flags member of the key.
5756 _gtk_window_query_nonaccels (GtkWindow *window,
5758 GdkModifierType accel_mods)
5760 GtkWindowPrivate *priv;
5762 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5764 priv = window->priv;
5766 /* movement keys are considered locked accels */
5769 static const guint bindings[] = {
5770 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,
5771 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,
5775 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5776 if (bindings[i] == accel_key)
5780 /* mnemonics are considered locked accels */
5781 if (accel_mods == priv->mnemonic_modifier)
5783 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5784 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5792 * gtk_window_propagate_key_event:
5793 * @window: a #GtkWindow
5794 * @event: a #GdkEventKey
5796 * Propagate a key press or release event to the focus widget and
5797 * up the focus container chain until a widget handles @event.
5798 * This is normally called by the default ::key_press_event and
5799 * ::key_release_event handlers for toplevel windows,
5800 * however in some cases it may be useful to call this directly when
5801 * overriding the standard key handling for a toplevel window.
5803 * Return value: %TRUE if a widget in the focus chain handled the event.
5808 gtk_window_propagate_key_event (GtkWindow *window,
5811 GtkWindowPrivate *priv;
5812 gboolean handled = FALSE;
5813 GtkWidget *widget, *focus;
5815 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5817 priv = window->priv;
5818 widget = GTK_WIDGET (window);
5820 focus = priv->focus_widget;
5822 g_object_ref (focus);
5825 focus && focus != widget &&
5826 gtk_widget_get_toplevel (focus) == widget)
5830 if (gtk_widget_is_sensitive (focus))
5831 handled = gtk_widget_event (focus, (GdkEvent*) event);
5833 parent = gtk_widget_get_parent (focus);
5835 g_object_ref (parent);
5837 g_object_unref (focus);
5843 g_object_unref (focus);
5849 gtk_window_key_press_event (GtkWidget *widget,
5852 GtkWindow *window = GTK_WINDOW (widget);
5853 gboolean handled = FALSE;
5855 /* handle mnemonics and accelerators */
5857 handled = gtk_window_activate_key (window, event);
5859 /* handle focus widget key events */
5861 handled = gtk_window_propagate_key_event (window, event);
5863 /* Chain up, invokes binding set */
5865 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5871 gtk_window_key_release_event (GtkWidget *widget,
5874 GtkWindow *window = GTK_WINDOW (widget);
5875 gboolean handled = FALSE;
5877 /* handle focus widget key events */
5879 handled = gtk_window_propagate_key_event (window, event);
5881 /* Chain up, invokes binding set */
5883 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5889 gtk_window_button_press_event (GtkWidget *widget,
5890 GdkEventButton *event)
5892 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5895 if (event->window == priv->grip_window)
5897 if (get_drag_edge (widget, &edge))
5898 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5912 gtk_window_real_activate_default (GtkWindow *window)
5914 gtk_window_activate_default (window);
5918 gtk_window_real_activate_focus (GtkWindow *window)
5920 gtk_window_activate_focus (window);
5924 gtk_window_enter_notify_event (GtkWidget *widget,
5925 GdkEventCrossing *event)
5931 gtk_window_leave_notify_event (GtkWidget *widget,
5932 GdkEventCrossing *event)
5938 do_focus_change (GtkWidget *widget,
5942 GdkDeviceManager *device_manager;
5945 g_object_ref (widget);
5947 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5948 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5949 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5950 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5952 for (d = devices; d; d = d->next)
5954 GdkDevice *dev = d->data;
5957 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5960 /* Skip non-master keyboards that haven't
5961 * selected for events from this window
5963 window = gtk_widget_get_window (widget);
5964 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5965 window && !gdk_window_get_device_events (window, dev))
5968 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5970 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5971 fevent->focus_change.window = window;
5973 g_object_ref (window);
5974 fevent->focus_change.in = in;
5975 gdk_event_set_device (fevent, dev);
5977 gtk_widget_send_focus_change (widget, fevent);
5979 gdk_event_free (fevent);
5982 g_list_free (devices);
5983 g_object_unref (widget);
5987 maybe_set_mnemonics_visible (GtkWindow *window)
5990 GdkDeviceManager *device_manager;
5992 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
5993 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5995 for (d = devices; d; d = d->next)
5997 GdkDevice *dev = d->data;
5999 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6001 GdkModifierType mask;
6003 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6005 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6007 gtk_window_set_mnemonics_visible (window, TRUE);
6013 g_list_free (devices);
6017 gtk_window_focus_in_event (GtkWidget *widget,
6018 GdkEventFocus *event)
6020 GtkWindow *window = GTK_WINDOW (widget);
6021 gboolean auto_mnemonics;
6023 /* It appears spurious focus in events can occur when
6024 * the window is hidden. So we'll just check to see if
6025 * the window is visible before actually handling the
6028 if (gtk_widget_get_visible (widget))
6030 _gtk_window_set_has_toplevel_focus (window, TRUE);
6031 _gtk_window_set_is_active (window, TRUE);
6033 g_object_get (gtk_widget_get_settings (widget),
6034 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6036 maybe_set_mnemonics_visible (window);
6043 gtk_window_focus_out_event (GtkWidget *widget,
6044 GdkEventFocus *event)
6046 GtkWindow *window = GTK_WINDOW (widget);
6047 gboolean auto_mnemonics;
6049 _gtk_window_set_has_toplevel_focus (window, FALSE);
6050 _gtk_window_set_is_active (window, FALSE);
6052 /* set the mnemonic-visible property to false */
6053 g_object_get (gtk_widget_get_settings (widget),
6054 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6056 gtk_window_set_mnemonics_visible (window, FALSE);
6062 gtk_window_check_resize (GtkContainer *container)
6064 /* If the window is not toplevel anymore than it's embedded somewhere,
6065 * so handle it like a normal window */
6066 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6067 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6068 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6069 gtk_window_move_resize (GTK_WINDOW (container));
6073 gtk_window_focus (GtkWidget *widget,
6074 GtkDirectionType direction)
6076 GtkWindowPrivate *priv;
6079 GtkContainer *container;
6081 GtkWidget *old_focus_child;
6084 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6085 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6087 container = GTK_CONTAINER (widget);
6088 window = GTK_WINDOW (widget);
6089 priv = window->priv;
6090 bin = GTK_BIN (widget);
6092 old_focus_child = gtk_container_get_focus_child (container);
6094 /* We need a special implementation here to deal properly with wrapping
6095 * around in the tab chain without the danger of going into an
6098 if (old_focus_child)
6100 if (gtk_widget_child_focus (old_focus_child, direction))
6104 if (priv->focus_widget)
6106 if (direction == GTK_DIR_LEFT ||
6107 direction == GTK_DIR_RIGHT ||
6108 direction == GTK_DIR_UP ||
6109 direction == GTK_DIR_DOWN)
6114 /* Wrapped off the end, clear the focus setting for the toplpevel */
6115 parent = gtk_widget_get_parent (priv->focus_widget);
6118 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6119 parent = gtk_widget_get_parent (parent);
6122 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6125 /* Now try to focus the first widget in the window */
6126 child = gtk_bin_get_child (bin);
6129 if (gtk_widget_child_focus (child, direction))
6137 gtk_window_move_focus (GtkWidget *widget,
6138 GtkDirectionType dir)
6140 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6142 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6146 gtk_widget_child_focus (widget, dir);
6148 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6149 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6153 gtk_window_real_set_focus (GtkWindow *window,
6156 GtkWindowPrivate *priv = window->priv;
6157 GtkWidget *old_focus = priv->focus_widget;
6158 gboolean had_default = FALSE;
6159 gboolean focus_had_default = FALSE;
6160 gboolean old_focus_had_default = FALSE;
6164 g_object_ref (old_focus);
6165 g_object_freeze_notify (G_OBJECT (old_focus));
6166 old_focus_had_default = gtk_widget_has_default (old_focus);
6170 g_object_ref (focus);
6171 g_object_freeze_notify (G_OBJECT (focus));
6172 focus_had_default = gtk_widget_has_default (focus);
6175 if (priv->default_widget)
6176 had_default = gtk_widget_has_default (priv->default_widget);
6178 if (priv->focus_widget)
6180 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6181 (priv->focus_widget != priv->default_widget))
6183 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6184 gtk_widget_queue_draw (priv->focus_widget);
6186 if (priv->default_widget)
6187 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6190 priv->focus_widget = NULL;
6192 if (priv->has_focus)
6193 do_focus_change (old_focus, FALSE);
6195 g_object_notify (G_OBJECT (old_focus), "is-focus");
6198 /* The above notifications may have set a new focus widget,
6199 * if so, we don't want to override it.
6201 if (focus && !priv->focus_widget)
6203 priv->focus_widget = focus;
6205 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6206 (priv->focus_widget != priv->default_widget))
6208 if (gtk_widget_get_can_default (priv->focus_widget))
6209 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6211 if (priv->default_widget)
6212 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6215 if (priv->has_focus)
6216 do_focus_change (priv->focus_widget, TRUE);
6218 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6221 /* If the default widget changed, a redraw will have been queued
6222 * on the old and new default widgets by gtk_window_set_default(), so
6223 * we only have to worry about the case where it didn't change.
6224 * We'll sometimes queue a draw twice on the new widget but that
6227 if (priv->default_widget &&
6228 (had_default != gtk_widget_has_default (priv->default_widget)))
6229 gtk_widget_queue_draw (priv->default_widget);
6233 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6234 gtk_widget_queue_draw (old_focus);
6236 g_object_thaw_notify (G_OBJECT (old_focus));
6237 g_object_unref (old_focus);
6241 if (focus_had_default != gtk_widget_has_default (focus))
6242 gtk_widget_queue_draw (focus);
6244 g_object_thaw_notify (G_OBJECT (focus));
6245 g_object_unref (focus);
6251 gtk_window_get_preferred_width (GtkWidget *widget,
6259 window = GTK_WINDOW (widget);
6260 child = gtk_bin_get_child (GTK_BIN (window));
6262 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6263 *minimum_size = border_width * 2;
6264 *natural_size = border_width * 2;
6266 if (child && gtk_widget_get_visible (child))
6268 gint child_min, child_nat;
6269 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6271 *minimum_size += child_min;
6272 *natural_size += child_nat;
6277 gtk_window_get_preferred_height (GtkWidget *widget,
6285 window = GTK_WINDOW (widget);
6286 child = gtk_bin_get_child (GTK_BIN (window));
6288 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6289 *minimum_size = border_width * 2;
6290 *natural_size = border_width * 2;
6292 if (child && gtk_widget_get_visible (child))
6294 gint child_min, child_nat;
6295 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6297 *minimum_size += child_min;
6298 *natural_size += child_nat;
6304 * _gtk_window_unset_focus_and_default:
6305 * @window: a #GtkWindow
6306 * @widget: a widget inside of @window
6308 * Checks whether the focus and default widgets of @window are
6309 * @widget or a descendent of @widget, and if so, unset them.
6312 _gtk_window_unset_focus_and_default (GtkWindow *window,
6316 GtkWindowPrivate *priv = window->priv;
6320 g_object_ref (window);
6321 g_object_ref (widget);
6323 parent = gtk_widget_get_parent (widget);
6324 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6326 child = priv->focus_widget;
6328 while (child && child != widget)
6329 child = gtk_widget_get_parent (child);
6331 if (child == widget)
6332 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6335 child = priv->default_widget;
6337 while (child && child != widget)
6338 child = gtk_widget_get_parent (child);
6340 if (child == widget)
6341 gtk_window_set_default (window, NULL);
6343 g_object_unref (widget);
6344 g_object_unref (window);
6347 /*********************************
6348 * Functions related to resizing *
6349 *********************************/
6352 geometry_size_to_pixels (GdkGeometry *geometry,
6357 gint base_width = 0;
6358 gint base_height = 0;
6360 gint min_height = 0;
6362 gint height_inc = 1;
6364 if (flags & GDK_HINT_BASE_SIZE)
6366 base_width = geometry->base_width;
6367 base_height = geometry->base_height;
6369 if (flags & GDK_HINT_MIN_SIZE)
6371 min_width = geometry->min_width;
6372 min_height = geometry->min_height;
6374 if (flags & GDK_HINT_RESIZE_INC)
6376 width_inc = geometry->width_inc;
6377 height_inc = geometry->height_inc;
6381 *width = MAX (*width * width_inc + base_width, min_width);
6383 *height = MAX (*height * height_inc + base_height, min_height);
6386 /* This function doesn't constrain to geometry hints */
6388 gtk_window_compute_configure_request_size (GtkWindow *window,
6389 GdkGeometry *geometry,
6394 GtkWindowPrivate *priv = window->priv;
6395 GtkWindowGeometryInfo *info;
6398 * - we've done a size request
6401 info = gtk_window_get_geometry_info (window, FALSE);
6403 if (priv->need_default_size)
6405 gtk_window_guess_default_size (window, width, height);
6407 /* If window is empty so requests 0, default to random nonzero size */
6408 if (*width == 0 && *height == 0)
6414 /* Override with default size */
6418 if (info->default_width > 0)
6419 *width = info->default_width;
6420 if (info->default_height > 0)
6421 *height = info->default_height;
6423 if (info->default_is_geometry)
6424 geometry_size_to_pixels (geometry, flags,
6425 info->default_width > 0 ? width : NULL,
6426 info->default_height > 0 ? height : NULL);
6431 GtkAllocation allocation;
6433 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6435 /* Default to keeping current size */
6436 *width = allocation.width;
6437 *height = allocation.height;
6440 /* Override any size with gtk_window_resize() values */
6443 if (info->resize_width > 0)
6444 *width = info->resize_width;
6445 if (info->resize_height > 0)
6446 *height = info->resize_height;
6448 if (info->resize_is_geometry)
6449 geometry_size_to_pixels (geometry, flags,
6450 info->resize_width > 0 ? width : NULL,
6451 info->resize_height > 0 ? height : NULL);
6454 /* Don't ever request zero width or height, its not supported by
6455 gdk. The size allocation code will round it to 1 anyway but if
6456 we do it then the value returned from this function will is
6457 not comparable to the size allocation read from the GtkWindow. */
6458 *width = MAX (*width, 1);
6459 *height = MAX (*height, 1);
6462 static GtkWindowPosition
6463 get_effective_position (GtkWindow *window)
6465 GtkWindowPrivate *priv = window->priv;
6466 GtkWindowPosition pos = priv->position;
6468 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6469 (priv->transient_parent == NULL ||
6470 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6471 pos = GTK_WIN_POS_NONE;
6477 get_center_monitor_of_window (GtkWindow *window)
6479 /* We could try to sort out the relative positions of the monitors and
6480 * stuff, or we could just be losers and assume you have a row
6481 * or column of monitors.
6483 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6487 get_monitor_containing_pointer (GtkWindow *window)
6491 GdkScreen *window_screen;
6492 GdkScreen *pointer_screen;
6493 GdkDisplay *display;
6494 GdkDeviceManager *device_manager;
6497 window_screen = gtk_window_check_screen (window);
6498 display = gdk_screen_get_display (window_screen);
6499 device_manager = gdk_display_get_device_manager (display);
6500 pointer = gdk_device_manager_get_client_pointer (device_manager);
6502 gdk_device_get_position (pointer,
6506 if (pointer_screen == window_screen)
6507 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6515 center_window_on_monitor (GtkWindow *window,
6521 GdkRectangle monitor;
6524 monitor_num = get_monitor_containing_pointer (window);
6526 if (monitor_num == -1)
6527 monitor_num = get_center_monitor_of_window (window);
6529 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6530 monitor_num, &monitor);
6532 *x = (monitor.width - w) / 2 + monitor.x;
6533 *y = (monitor.height - h) / 2 + monitor.y;
6535 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6536 * and WM decorations.
6550 if (extent > clamp_extent)
6552 *base = clamp_base + clamp_extent/2 - extent/2;
6553 else if (*base < clamp_base)
6555 else if (*base + extent > clamp_base + clamp_extent)
6556 *base = clamp_base + clamp_extent - extent;
6560 clamp_window_to_rectangle (gint *x,
6564 const GdkRectangle *rect)
6566 #ifdef DEBUGGING_OUTPUT
6567 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);
6570 /* If it is too large, center it. If it fits on the monitor but is
6571 * partially outside, move it to the closest edge. Do this
6572 * separately in x and y directions.
6574 clamp (x, w, rect->x, rect->width);
6575 clamp (y, h, rect->y, rect->height);
6576 #ifdef DEBUGGING_OUTPUT
6577 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6583 gtk_window_compute_configure_request (GtkWindow *window,
6584 GdkRectangle *request,
6585 GdkGeometry *geometry,
6588 GtkWindowPrivate *priv = window->priv;
6589 GdkGeometry new_geometry;
6592 GtkWindowPosition pos;
6593 GtkWidget *parent_widget;
6594 GtkWindowGeometryInfo *info;
6598 screen = gtk_window_check_screen (window);
6600 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6601 gtk_window_compute_configure_request_size (window,
6602 &new_geometry, new_flags,
6605 gtk_window_constrain_size (window,
6606 &new_geometry, new_flags,
6610 parent_widget = (GtkWidget*) priv->transient_parent;
6612 pos = get_effective_position (window);
6613 info = gtk_window_get_geometry_info (window, FALSE);
6615 /* by default, don't change position requested */
6618 x = info->last.configure_request.x;
6619 y = info->last.configure_request.y;
6628 if (priv->need_default_position)
6631 /* FIXME this all interrelates with window gravity.
6632 * For most of them I think we want to set GRAVITY_CENTER.
6634 * Not sure how to go about that.
6638 /* here we are only handling CENTER_ALWAYS
6639 * as it relates to default positioning,
6640 * where it's equivalent to simply CENTER
6642 case GTK_WIN_POS_CENTER_ALWAYS:
6643 case GTK_WIN_POS_CENTER:
6644 center_window_on_monitor (window, w, h, &x, &y);
6647 case GTK_WIN_POS_CENTER_ON_PARENT:
6649 GtkAllocation allocation;
6650 GdkWindow *gdk_window;
6652 GdkRectangle monitor;
6655 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6657 gdk_window = gtk_widget_get_window (parent_widget);
6659 if (gdk_window != NULL)
6660 monitor_num = gdk_screen_get_monitor_at_window (screen,
6665 gdk_window_get_origin (gdk_window,
6668 gtk_widget_get_allocation (parent_widget, &allocation);
6669 x = ox + (allocation.width - w) / 2;
6670 y = oy + (allocation.height - h) / 2;
6672 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6673 * WM decorations. If parent wasn't on a monitor, just
6676 if (monitor_num >= 0)
6678 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6679 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6684 case GTK_WIN_POS_MOUSE:
6686 gint screen_width = gdk_screen_get_width (screen);
6687 gint screen_height = gdk_screen_get_height (screen);
6689 GdkRectangle monitor;
6690 GdkDisplay *display;
6691 GdkDeviceManager *device_manager;
6693 GdkScreen *pointer_screen;
6696 display = gdk_screen_get_display (screen);
6697 device_manager = gdk_display_get_device_manager (display);
6698 pointer = gdk_device_manager_get_client_pointer (device_manager);
6700 gdk_device_get_position (pointer,
6704 if (pointer_screen == screen)
6705 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6711 x = CLAMP (x, 0, screen_width - w);
6712 y = CLAMP (y, 0, screen_height - h);
6714 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6715 * WM decorations. Don't try to figure out what's going
6716 * on if the mouse wasn't inside a monitor.
6718 if (monitor_num >= 0)
6720 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6721 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6729 } /* if (priv->need_default_position) */
6731 if (priv->need_default_position && info &&
6732 info->initial_pos_set)
6734 x = info->initial_x;
6735 y = info->initial_y;
6736 gtk_window_constrain_position (window, w, h, &x, &y);
6742 request->height = h;
6745 *geometry = new_geometry;
6751 gtk_window_constrain_position (GtkWindow *window,
6757 GtkWindowPrivate *priv = window->priv;
6759 /* See long comments in gtk_window_move_resize()
6760 * on when it's safe to call this function.
6762 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6764 gint center_x, center_y;
6766 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6774 gtk_window_move_resize (GtkWindow *window)
6778 * First we determine whether any information has changed that would
6779 * cause us to revise our last configure request. If we would send
6780 * a different configure request from last time, then
6781 * configure_request_size_changed = TRUE or
6782 * configure_request_pos_changed = TRUE. configure_request_size_changed
6783 * may be true due to new hints, a gtk_window_resize(), or whatever.
6784 * configure_request_pos_changed may be true due to gtk_window_set_position()
6785 * or gtk_window_move().
6787 * If the configure request has changed, we send off a new one. To
6788 * ensure GTK+ invariants are maintained (resize queue does what it
6789 * should), we go ahead and size_allocate the requested size in this
6792 * If the configure request has not changed, we don't ever resend
6793 * it, because it could mean fighting the user or window manager.
6796 * To prepare the configure request, we come up with a base size/pos:
6797 * - the one from gtk_window_move()/gtk_window_resize()
6798 * - else default_width, default_height if we haven't ever
6800 * - else the size request if we haven't ever been mapped,
6801 * as a substitute default size
6802 * - else the current size of the window, as received from
6803 * configure notifies (i.e. the current allocation)
6805 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6806 * the position request to be centered.
6808 GtkWindowPrivate *priv = window->priv;
6809 GtkAllocation allocation;
6811 GtkContainer *container;
6812 GtkWindowGeometryInfo *info;
6813 GdkGeometry new_geometry;
6814 GdkWindow *gdk_window;
6816 GdkRectangle new_request;
6817 gboolean configure_request_size_changed;
6818 gboolean configure_request_pos_changed;
6819 gboolean hints_changed; /* do we need to send these again */
6820 GtkWindowLastGeometryInfo saved_last_info;
6822 widget = GTK_WIDGET (window);
6824 gdk_window = gtk_widget_get_window (widget);
6825 container = GTK_CONTAINER (widget);
6826 info = gtk_window_get_geometry_info (window, TRUE);
6828 configure_request_size_changed = FALSE;
6829 configure_request_pos_changed = FALSE;
6831 gtk_window_compute_configure_request (window, &new_request,
6832 &new_geometry, &new_flags);
6834 /* This check implies the invariant that we never set info->last
6835 * without setting the hints and sending off a configure request.
6837 * If we change info->last without sending the request, we may
6840 if (info->last.configure_request.x != new_request.x ||
6841 info->last.configure_request.y != new_request.y)
6842 configure_request_pos_changed = TRUE;
6844 if ((info->last.configure_request.width != new_request.width ||
6845 info->last.configure_request.height != new_request.height))
6846 configure_request_size_changed = TRUE;
6848 hints_changed = FALSE;
6850 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6851 &new_geometry, new_flags))
6853 hints_changed = TRUE;
6856 /* Position Constraints
6857 * ====================
6859 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6860 * a default. The other POS_ values are used only when the
6861 * window is shown, not after that.
6863 * However, we can't implement a position constraint as
6864 * "anytime the window size changes, center the window"
6865 * because this may well end up fighting the WM or user. In
6866 * fact it gets in an infinite loop with at least one WM.
6868 * Basically, applications are in no way in a position to
6869 * constrain the position of a window, with one exception:
6870 * override redirect windows. (Really the intended purpose
6871 * of CENTER_ALWAYS anyhow, I would think.)
6873 * So the way we implement this "constraint" is to say that when WE
6874 * cause a move or resize, i.e. we make a configure request changing
6875 * window size, we recompute the CENTER_ALWAYS position to reflect
6876 * the new window size, and include it in our request. Also, if we
6877 * just turned on CENTER_ALWAYS we snap to center with a new
6878 * request. Otherwise, if we are just NOTIFIED of a move or resize
6879 * done by someone else e.g. the window manager, we do NOT send a
6880 * new configure request.
6882 * For override redirect windows, this works fine; all window
6883 * sizes are from our configure requests. For managed windows,
6884 * it is at least semi-sane, though who knows what the
6885 * app author is thinking.
6888 /* This condition should be kept in sync with the condition later on
6889 * that determines whether we send a configure request. i.e. we
6890 * should do this position constraining anytime we were going to
6891 * send a configure request anyhow, plus when constraints have
6894 if (configure_request_pos_changed ||
6895 configure_request_size_changed ||
6897 info->position_constraints_changed)
6899 /* We request the constrained position if:
6900 * - we were changing position, and need to clamp
6901 * the change to the constraint
6902 * - we're changing the size anyway
6903 * - set_position() was called to toggle CENTER_ALWAYS on
6906 gtk_window_constrain_position (window,
6912 /* Update whether we need to request a move */
6913 if (info->last.configure_request.x != new_request.x ||
6914 info->last.configure_request.y != new_request.y)
6915 configure_request_pos_changed = TRUE;
6917 configure_request_pos_changed = FALSE;
6921 if (priv->type == GTK_WINDOW_TOPLEVEL)
6923 int notify_x, notify_y;
6925 /* this is the position from the last configure notify */
6926 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6928 g_message ("--- %s ---\n"
6929 "last : %d,%d\t%d x %d\n"
6930 "this : %d,%d\t%d x %d\n"
6931 "alloc : %d,%d\t%d x %d\n"
6933 "resize: \t%d x %d\n"
6934 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6935 "configure_notify_received: %d\n"
6936 "configure_request_count: %d\n"
6937 "position_constraints_changed: %d\n",
6938 priv->title ? priv->title : "(no title)",
6939 info->last.configure_request.x,
6940 info->last.configure_request.y,
6941 info->last.configure_request.width,
6942 info->last.configure_request.height,
6948 widget->allocation.width,
6949 widget->allocation.height,
6950 widget->requisition.width,
6951 widget->requisition.height,
6953 info->resize_height,
6954 configure_request_pos_changed,
6955 configure_request_size_changed,
6957 priv->configure_notify_received,
6958 priv->configure_request_count,
6959 info->position_constraints_changed);
6963 saved_last_info = info->last;
6964 info->last.geometry = new_geometry;
6965 info->last.flags = new_flags;
6966 info->last.configure_request = new_request;
6968 /* need to set PPosition so the WM will look at our position,
6969 * but we don't want to count PPosition coming and going as a hints
6970 * change for future iterations. So we saved info->last prior to
6974 /* Also, if the initial position was explicitly set, then we always
6975 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6979 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6980 * this is an initial map
6983 if ((configure_request_pos_changed ||
6984 info->initial_pos_set ||
6985 (priv->need_default_position &&
6986 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6987 (new_flags & GDK_HINT_POS) == 0)
6989 new_flags |= GDK_HINT_POS;
6990 hints_changed = TRUE;
6993 /* Set hints if necessary
6996 gdk_window_set_geometry_hints (gdk_window,
7000 gtk_widget_get_allocation (widget, &allocation);
7002 /* handle resizing/moving and widget tree allocation
7004 if (priv->configure_notify_received)
7006 /* If we have received a configure event since
7007 * the last time in this function, we need to
7008 * accept our new size and size_allocate child widgets.
7009 * (see gtk_window_configure_event() for more details).
7011 * 1 or more configure notifies may have been received.
7012 * Also, configure_notify_received will only be TRUE
7013 * if all expected configure notifies have been received
7014 * (one per configure request), as an optimization.
7017 priv->configure_notify_received = FALSE;
7019 /* gtk_window_configure_event() filled in widget->allocation */
7020 gtk_widget_size_allocate (widget, &allocation);
7022 set_grip_position (window);
7023 update_grip_visibility (window);
7025 gdk_window_process_updates (gdk_window, TRUE);
7027 gdk_window_configure_finished (gdk_window);
7029 /* If the configure request changed, it means that
7031 * 1) coincidentally changed hints or widget properties
7032 * impacting the configure request before getting
7033 * a configure notify, or
7034 * 2) some broken widget is changing its size request
7035 * during size allocation, resulting in
7036 * a false appearance of changed configure request.
7038 * For 1), we could just go ahead and ask for the
7039 * new size right now, but doing that for 2)
7040 * might well be fighting the user (and can even
7041 * trigger a loop). Since we really don't want to
7042 * do that, we requeue a resize in hopes that
7043 * by the time it gets handled, the child has seen
7044 * the light and is willing to go along with the
7045 * new size. (this happens for the zvt widget, since
7046 * the size_allocate() above will have stored the
7047 * requisition corresponding to the new size in the
7050 * This doesn't buy us anything for 1), but it shouldn't
7051 * hurt us too badly, since it is what would have
7052 * happened if we had gotten the configure event before
7053 * the new size had been set.
7056 if (configure_request_size_changed ||
7057 configure_request_pos_changed)
7059 /* Don't change the recorded last info after all, because we
7060 * haven't actually updated to the new info yet - we decided
7061 * to postpone our configure request until later.
7063 info->last = saved_last_info;
7065 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7068 return; /* Bail out, we didn't really process the move/resize */
7070 else if ((configure_request_size_changed || hints_changed) &&
7071 (allocation.width != new_request.width || allocation.height != new_request.height))
7074 /* We are in one of the following situations:
7075 * A. configure_request_size_changed
7076 * our requisition has changed and we need a different window size,
7077 * so we request it from the window manager.
7078 * B. !configure_request_size_changed && hints_changed
7079 * the window manager rejects our size, but we have just changed the
7080 * window manager hints, so there's a chance our request will
7081 * be honoured this time, so we try again.
7083 * However, if the new requisition is the same as the current allocation,
7084 * we don't request it again, since we won't get a ConfigureNotify back from
7085 * the window manager unless it decides to change our requisition. If
7086 * we don't get the ConfigureNotify back, the resize queue will never be run.
7089 /* Now send the configure request */
7090 if (configure_request_pos_changed)
7092 gdk_window_move_resize (gdk_window,
7093 new_request.x, new_request.y,
7094 new_request.width, new_request.height);
7096 else /* only size changed */
7098 gdk_window_resize (gdk_window,
7099 new_request.width, new_request.height);
7102 if (priv->type == GTK_WINDOW_POPUP)
7104 GtkAllocation allocation;
7106 /* Directly size allocate for override redirect (popup) windows. */
7109 allocation.width = new_request.width;
7110 allocation.height = new_request.height;
7112 gtk_widget_size_allocate (widget, &allocation);
7114 gdk_window_process_updates (gdk_window, TRUE);
7116 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7117 gtk_widget_queue_draw (widget);
7121 /* Increment the number of have-not-yet-received-notify requests */
7122 priv->configure_request_count += 1;
7123 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7125 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7126 * configure event in response to our resizing request.
7127 * the configure event will cause a new resize with
7128 * ->configure_notify_received=TRUE.
7129 * until then, we want to
7130 * - discard expose events
7131 * - coalesce resizes for our children
7132 * - defer any window resizes until the configure event arrived
7133 * to achieve this, we queue a resize for the window, but remove its
7134 * resizing handler, so resizing will not be handled from the next
7135 * idle handler but when the configure event arrives.
7137 * FIXME: we should also dequeue the pending redraws here, since
7138 * we handle those ourselves upon ->configure_notify_received==TRUE.
7140 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7142 gtk_widget_queue_resize_no_redraw (widget);
7143 _gtk_container_dequeue_resize_handler (container);
7149 /* Handle any position changes.
7151 if (configure_request_pos_changed)
7153 gdk_window_move (gdk_window,
7154 new_request.x, new_request.y);
7157 /* And run the resize queue.
7159 gtk_container_resize_children (container);
7162 /* We have now processed a move/resize since the last position
7163 * constraint change, setting of the initial position, or resize.
7164 * (Not resetting these flags here can lead to infinite loops for
7165 * GTK_RESIZE_IMMEDIATE containers)
7167 info->position_constraints_changed = FALSE;
7168 info->initial_pos_set = FALSE;
7169 info->resize_width = -1;
7170 info->resize_height = -1;
7173 /* Compare two sets of Geometry hints for equality.
7176 gtk_window_compare_hints (GdkGeometry *geometry_a,
7178 GdkGeometry *geometry_b,
7181 if (flags_a != flags_b)
7184 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7185 (geometry_a->min_width != geometry_b->min_width ||
7186 geometry_a->min_height != geometry_b->min_height))
7189 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7190 (geometry_a->max_width != geometry_b->max_width ||
7191 geometry_a->max_height != geometry_b->max_height))
7194 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7195 (geometry_a->base_width != geometry_b->base_width ||
7196 geometry_a->base_height != geometry_b->base_height))
7199 if ((flags_a & GDK_HINT_ASPECT) &&
7200 (geometry_a->min_aspect != geometry_b->min_aspect ||
7201 geometry_a->max_aspect != geometry_b->max_aspect))
7204 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7205 (geometry_a->width_inc != geometry_b->width_inc ||
7206 geometry_a->height_inc != geometry_b->height_inc))
7209 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7210 geometry_a->win_gravity != geometry_b->win_gravity)
7217 _gtk_window_constrain_size (GtkWindow *window,
7223 GtkWindowPrivate *priv;
7224 GtkWindowGeometryInfo *info;
7226 g_return_if_fail (GTK_IS_WINDOW (window));
7228 priv = window->priv;
7230 info = priv->geometry_info;
7233 GdkWindowHints flags = info->last.flags;
7234 GdkGeometry *geometry = &info->last.geometry;
7236 gtk_window_constrain_size (window,
7247 gtk_window_constrain_size (GtkWindow *window,
7248 GdkGeometry *geometry,
7255 gdk_window_constrain_size (geometry, flags, width, height,
7256 new_width, new_height);
7259 /* Compute the set of geometry hints and flags for a window
7260 * based on the application set geometry, and requisition
7261 * of the window. gtk_widget_get_preferred_size() must have been
7265 gtk_window_compute_hints (GtkWindow *window,
7266 GdkGeometry *new_geometry,
7269 GtkWindowPrivate *priv = window->priv;
7271 gint extra_width = 0;
7272 gint extra_height = 0;
7273 GtkWindowGeometryInfo *geometry_info;
7274 GtkRequisition requisition;
7276 widget = GTK_WIDGET (window);
7278 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7279 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7283 *new_flags = geometry_info->mask;
7284 *new_geometry = geometry_info->geometry;
7291 if (geometry_info && geometry_info->widget)
7293 /* If the geometry widget is set, then the hints really apply to that
7294 * widget. This is pretty much meaningless unless the window layout
7295 * is such that the rest of the window adds fixed size borders to
7296 * the geometry widget. Our job is to figure the size of the borders;
7297 * We do that by asking how big the toplevel would be if the
7298 * geometry widget was *really big*.
7301 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7302 * |GGGGG B| in the border can confuse things
7308 * |AAAAAAAAA | When the geometry widget is large, things are
7309 * |GGGGGGGGGGB| clearer.
7314 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7315 GtkRequisition requisition;
7316 int current_width, current_height;
7318 _gtk_widget_override_size_request (geometry_info->widget,
7319 TEMPORARY_SIZE, TEMPORARY_SIZE,
7320 ¤t_width, ¤t_height);
7321 gtk_widget_get_preferred_size (widget,
7322 &requisition, NULL);
7323 _gtk_widget_restore_size_request (geometry_info->widget,
7324 current_width, current_height);
7326 extra_width = requisition.width - TEMPORARY_SIZE;
7327 extra_height = requisition.height - TEMPORARY_SIZE;
7329 if (extra_width < 0 || extra_height < 0)
7331 g_warning("Toplevel size doesn't seem to directly depend on the "
7332 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7333 "The geometry widget might not be in the window, or it might not "
7334 "be packed into the window appropriately");
7335 extra_width = MAX(extra_width, 0);
7336 extra_height = MAX(extra_height, 0);
7338 #undef TEMPORARY_SIZE
7341 /* We don't want to set GDK_HINT_POS in here, we just set it
7342 * in gtk_window_move_resize() when we want the position
7346 if (*new_flags & GDK_HINT_BASE_SIZE)
7348 new_geometry->base_width += extra_width;
7349 new_geometry->base_height += extra_height;
7353 /* For simplicity, we always set the base hint, even when we
7354 * don't expect it to have any visible effect.
7355 * (Note: geometry_size_to_pixels() depends on this.)
7357 *new_flags |= GDK_HINT_BASE_SIZE;
7359 new_geometry->base_width = extra_width;
7360 new_geometry->base_height = extra_height;
7362 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7363 * base size is the minimum size */
7364 if (*new_flags & GDK_HINT_MIN_SIZE)
7366 if (new_geometry->min_width > 0)
7367 new_geometry->base_width += new_geometry->min_width;
7368 if (new_geometry->min_height > 0)
7369 new_geometry->base_height += new_geometry->min_height;
7373 /* Please use a good size for unresizable widgets, not the minimum one. */
7374 if (!priv->resizable)
7375 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7377 if (*new_flags & GDK_HINT_MIN_SIZE)
7379 if (new_geometry->min_width < 0)
7380 new_geometry->min_width = requisition.width;
7382 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7384 if (new_geometry->min_height < 0)
7385 new_geometry->min_height = requisition.height;
7387 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7391 *new_flags |= GDK_HINT_MIN_SIZE;
7393 new_geometry->min_width = requisition.width;
7394 new_geometry->min_height = requisition.height;
7397 if (*new_flags & GDK_HINT_MAX_SIZE)
7399 if (new_geometry->max_width < 0)
7400 new_geometry->max_width = requisition.width;
7402 new_geometry->max_width += extra_width;
7404 if (new_geometry->max_height < 0)
7405 new_geometry->max_height = requisition.height;
7407 new_geometry->max_height += extra_height;
7409 else if (!priv->resizable)
7411 *new_flags |= GDK_HINT_MAX_SIZE;
7413 new_geometry->max_width = requisition.width;
7414 new_geometry->max_height = requisition.height;
7417 *new_flags |= GDK_HINT_WIN_GRAVITY;
7418 new_geometry->win_gravity = priv->gravity;
7421 /***********************
7422 * Redrawing functions *
7423 ***********************/
7426 gtk_window_draw (GtkWidget *widget,
7429 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7430 GtkStyleContext *context;
7431 gboolean ret = FALSE;
7433 context = gtk_widget_get_style_context (widget);
7435 gtk_style_context_save (context);
7437 if (!gtk_widget_get_app_paintable (widget))
7439 GtkStateFlags state;
7441 state = gtk_widget_get_state_flags (widget);
7443 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7444 state |= GTK_STATE_FLAG_FOCUSED;
7446 gtk_style_context_set_state (context, state);
7447 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7448 gtk_render_background (context, cr, 0, 0,
7449 gtk_widget_get_allocated_width (widget),
7450 gtk_widget_get_allocated_height (widget));
7453 gtk_style_context_restore (context);
7455 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7456 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7458 if (priv->grip_window &&
7459 gtk_cairo_should_draw_window (cr, priv->grip_window))
7463 gtk_style_context_save (context);
7466 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7467 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7469 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7470 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7471 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7474 gtk_style_context_restore (context);
7481 * gtk_window_present:
7482 * @window: a #GtkWindow
7484 * Presents a window to the user. This may mean raising the window
7485 * in the stacking order, deiconifying it, moving it to the current
7486 * desktop, and/or giving it the keyboard focus, possibly dependent
7487 * on the user's platform, window manager, and preferences.
7489 * If @window is hidden, this function calls gtk_widget_show()
7492 * This function should be used when the user tries to open a window
7493 * that's already open. Say for example the preferences dialog is
7494 * currently open, and the user chooses Preferences from the menu
7495 * a second time; use gtk_window_present() to move the already-open dialog
7496 * where the user can see it.
7498 * If you are calling this function in response to a user interaction,
7499 * it is preferable to use gtk_window_present_with_time().
7503 gtk_window_present (GtkWindow *window)
7505 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7509 * gtk_window_present_with_time:
7510 * @window: a #GtkWindow
7511 * @timestamp: the timestamp of the user interaction (typically a
7512 * button or key press event) which triggered this call
7514 * Presents a window to the user in response to a user interaction.
7515 * If you need to present a window without a timestamp, use
7516 * gtk_window_present(). See gtk_window_present() for details.
7521 gtk_window_present_with_time (GtkWindow *window,
7524 GtkWindowPrivate *priv;
7526 GdkWindow *gdk_window;
7528 g_return_if_fail (GTK_IS_WINDOW (window));
7530 priv = window->priv;
7531 widget = GTK_WIDGET (window);
7533 if (gtk_widget_get_visible (widget))
7535 gdk_window = gtk_widget_get_window (widget);
7537 g_assert (gdk_window != NULL);
7539 gdk_window_show (gdk_window);
7541 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7542 if (timestamp == GDK_CURRENT_TIME)
7544 #ifdef GDK_WINDOWING_X11
7545 if (GDK_IS_X11_WINDOW(gdk_window))
7547 GdkDisplay *display;
7549 display = gtk_widget_get_display (GTK_WIDGET (window));
7550 timestamp = gdk_x11_display_get_user_time (display);
7554 timestamp = gtk_get_current_event_time ();
7557 gdk_window_focus (gdk_window, timestamp);
7561 priv->initial_timestamp = timestamp;
7562 gtk_widget_show (widget);
7567 * gtk_window_iconify:
7568 * @window: a #GtkWindow
7570 * Asks to iconify (i.e. minimize) the specified @window. Note that
7571 * you shouldn't assume the window is definitely iconified afterward,
7572 * because other entities (e.g. the user or <link
7573 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7574 * again, or there may not be a window manager in which case
7575 * iconification isn't possible, etc. But normally the window will end
7576 * up iconified. Just don't write code that crashes if not.
7578 * It's permitted to call this function before showing a window,
7579 * in which case the window will be iconified before it ever appears
7582 * You can track iconification via the "window-state-event" signal
7587 gtk_window_iconify (GtkWindow *window)
7589 GtkWindowPrivate *priv;
7591 GdkWindow *toplevel;
7593 g_return_if_fail (GTK_IS_WINDOW (window));
7595 priv = window->priv;
7596 widget = GTK_WIDGET (window);
7598 priv->iconify_initially = TRUE;
7600 toplevel = gtk_widget_get_window (widget);
7602 if (toplevel != NULL)
7603 gdk_window_iconify (toplevel);
7607 * gtk_window_deiconify:
7608 * @window: a #GtkWindow
7610 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7611 * that you shouldn't assume the window is definitely deiconified
7612 * afterward, because other entities (e.g. the user or <link
7613 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7614 * again before your code which assumes deiconification gets to run.
7616 * You can track iconification via the "window-state-event" signal
7620 gtk_window_deiconify (GtkWindow *window)
7622 GtkWindowPrivate *priv;
7624 GdkWindow *toplevel;
7626 g_return_if_fail (GTK_IS_WINDOW (window));
7628 priv = window->priv;
7629 widget = GTK_WIDGET (window);
7631 priv->iconify_initially = FALSE;
7633 toplevel = gtk_widget_get_window (widget);
7635 if (toplevel != NULL)
7636 gdk_window_deiconify (toplevel);
7641 * @window: a #GtkWindow
7643 * Asks to stick @window, which means that it will appear on all user
7644 * desktops. Note that you shouldn't assume the window is definitely
7645 * stuck afterward, because other entities (e.g. the user or <link
7646 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7647 * again, and some window managers do not support sticking
7648 * windows. But normally the window will end up stuck. Just don't
7649 * write code that crashes if not.
7651 * It's permitted to call this function before showing a window.
7653 * You can track stickiness via the "window-state-event" signal
7658 gtk_window_stick (GtkWindow *window)
7660 GtkWindowPrivate *priv;
7662 GdkWindow *toplevel;
7664 g_return_if_fail (GTK_IS_WINDOW (window));
7666 priv = window->priv;
7667 widget = GTK_WIDGET (window);
7669 priv->stick_initially = TRUE;
7671 toplevel = gtk_widget_get_window (widget);
7673 if (toplevel != NULL)
7674 gdk_window_stick (toplevel);
7678 * gtk_window_unstick:
7679 * @window: a #GtkWindow
7681 * Asks to unstick @window, which means that it will appear on only
7682 * one of the user's desktops. Note that you shouldn't assume the
7683 * window is definitely unstuck afterward, because other entities
7684 * (e.g. the user or <link linkend="gtk-X11-arch">window
7685 * manager</link>) could stick it again. But normally the window will
7686 * end up stuck. Just don't write code that crashes if not.
7688 * You can track stickiness via the "window-state-event" signal
7693 gtk_window_unstick (GtkWindow *window)
7695 GtkWindowPrivate *priv;
7697 GdkWindow *toplevel;
7699 g_return_if_fail (GTK_IS_WINDOW (window));
7701 priv = window->priv;
7702 widget = GTK_WIDGET (window);
7704 priv->stick_initially = FALSE;
7706 toplevel = gtk_widget_get_window (widget);
7708 if (toplevel != NULL)
7709 gdk_window_unstick (toplevel);
7713 * gtk_window_maximize:
7714 * @window: a #GtkWindow
7716 * Asks to maximize @window, so that it becomes full-screen. Note that
7717 * you shouldn't assume the window is definitely maximized afterward,
7718 * because other entities (e.g. the user or <link
7719 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7720 * again, and not all window managers support maximization. But
7721 * normally the window will end up maximized. Just don't write code
7722 * that crashes if not.
7724 * It's permitted to call this function before showing a window,
7725 * in which case the window will be maximized when it appears onscreen
7728 * You can track maximization via the "window-state-event" signal
7733 gtk_window_maximize (GtkWindow *window)
7735 GtkWindowPrivate *priv;
7737 GdkWindow *toplevel;
7739 g_return_if_fail (GTK_IS_WINDOW (window));
7741 priv = window->priv;
7742 widget = GTK_WIDGET (window);
7744 priv->maximize_initially = TRUE;
7746 toplevel = gtk_widget_get_window (widget);
7748 if (toplevel != NULL)
7749 gdk_window_maximize (toplevel);
7753 * gtk_window_unmaximize:
7754 * @window: a #GtkWindow
7756 * Asks to unmaximize @window. Note that you shouldn't assume the
7757 * window is definitely unmaximized afterward, because other entities
7758 * (e.g. the user or <link linkend="gtk-X11-arch">window
7759 * manager</link>) could maximize it again, and not all window
7760 * managers honor requests to unmaximize. But normally the window will
7761 * end up unmaximized. Just don't write code that crashes if not.
7763 * You can track maximization via the "window-state-event" signal
7768 gtk_window_unmaximize (GtkWindow *window)
7770 GtkWindowPrivate *priv;
7772 GdkWindow *toplevel;
7774 g_return_if_fail (GTK_IS_WINDOW (window));
7776 priv = window->priv;
7777 widget = GTK_WIDGET (window);
7779 priv->maximize_initially = FALSE;
7781 toplevel = gtk_widget_get_window (widget);
7783 if (toplevel != NULL)
7784 gdk_window_unmaximize (toplevel);
7788 * gtk_window_fullscreen:
7789 * @window: a #GtkWindow
7791 * Asks to place @window in the fullscreen state. Note that you
7792 * shouldn't assume the window is definitely full screen afterward,
7793 * because other entities (e.g. the user or <link
7794 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7795 * again, and not all window managers honor requests to fullscreen
7796 * windows. But normally the window will end up fullscreen. Just
7797 * don't write code that crashes if not.
7799 * You can track the fullscreen state via the "window-state-event" signal
7805 gtk_window_fullscreen (GtkWindow *window)
7807 GtkWindowPrivate *priv;
7809 GdkWindow *toplevel;
7811 g_return_if_fail (GTK_IS_WINDOW (window));
7813 priv = window->priv;
7814 widget = GTK_WIDGET (window);
7816 priv->fullscreen_initially = TRUE;
7818 toplevel = gtk_widget_get_window (widget);
7820 if (toplevel != NULL)
7821 gdk_window_fullscreen (toplevel);
7825 * gtk_window_unfullscreen:
7826 * @window: a #GtkWindow
7828 * Asks to toggle off the fullscreen state for @window. Note that you
7829 * shouldn't assume the window is definitely not full screen
7830 * afterward, because other entities (e.g. the user or <link
7831 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7832 * again, and not all window managers honor requests to unfullscreen
7833 * windows. But normally the window will end up restored to its normal
7834 * state. Just don't write code that crashes if not.
7836 * You can track the fullscreen state via the "window-state-event" signal
7842 gtk_window_unfullscreen (GtkWindow *window)
7845 GdkWindow *toplevel;
7846 GtkWindowPrivate *priv;
7848 g_return_if_fail (GTK_IS_WINDOW (window));
7850 priv = window->priv;
7851 widget = GTK_WIDGET (window);
7853 priv->fullscreen_initially = FALSE;
7855 toplevel = gtk_widget_get_window (widget);
7857 if (toplevel != NULL)
7858 gdk_window_unfullscreen (toplevel);
7862 * gtk_window_set_keep_above:
7863 * @window: a #GtkWindow
7864 * @setting: whether to keep @window above other windows
7866 * Asks to keep @window above, so that it stays on top. Note that
7867 * you shouldn't assume the window is definitely above afterward,
7868 * because other entities (e.g. the user or <link
7869 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7870 * and not all window managers support keeping windows above. But
7871 * normally the window will end kept above. Just don't write code
7872 * that crashes if not.
7874 * It's permitted to call this function before showing a window,
7875 * in which case the window will be kept above when it appears onscreen
7878 * You can track the above state via the "window-state-event" signal
7881 * Note that, according to the <ulink
7882 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7883 * Manager Hints</ulink> specification, the above state is mainly meant
7884 * for user preferences and should not be used by applications e.g. for
7885 * drawing attention to their dialogs.
7890 gtk_window_set_keep_above (GtkWindow *window,
7894 GtkWindowPrivate *priv;
7895 GdkWindow *toplevel;
7897 g_return_if_fail (GTK_IS_WINDOW (window));
7899 priv = window->priv;
7900 widget = GTK_WIDGET (window);
7902 priv->above_initially = setting != FALSE;
7904 priv->below_initially = FALSE;
7906 toplevel = gtk_widget_get_window (widget);
7908 if (toplevel != NULL)
7909 gdk_window_set_keep_above (toplevel, setting);
7913 * gtk_window_set_keep_below:
7914 * @window: a #GtkWindow
7915 * @setting: whether to keep @window below other windows
7917 * Asks to keep @window below, so that it stays in bottom. Note that
7918 * you shouldn't assume the window is definitely below afterward,
7919 * because other entities (e.g. the user or <link
7920 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7921 * and not all window managers support putting windows below. But
7922 * normally the window will be kept below. Just don't write code
7923 * that crashes if not.
7925 * It's permitted to call this function before showing a window,
7926 * in which case the window will be kept below when it appears onscreen
7929 * You can track the below state via the "window-state-event" signal
7932 * Note that, according to the <ulink
7933 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7934 * Manager Hints</ulink> specification, the above state is mainly meant
7935 * for user preferences and should not be used by applications e.g. for
7936 * drawing attention to their dialogs.
7941 gtk_window_set_keep_below (GtkWindow *window,
7945 GtkWindowPrivate *priv;
7946 GdkWindow *toplevel;
7948 g_return_if_fail (GTK_IS_WINDOW (window));
7950 priv = window->priv;
7951 widget = GTK_WIDGET (window);
7953 priv->below_initially = setting != FALSE;
7955 priv->above_initially = FALSE;
7957 toplevel = gtk_widget_get_window (widget);
7959 if (toplevel != NULL)
7960 gdk_window_set_keep_below (toplevel, setting);
7964 * gtk_window_set_resizable:
7965 * @window: a #GtkWindow
7966 * @resizable: %TRUE if the user can resize this window
7968 * Sets whether the user can resize a window. Windows are user resizable
7972 gtk_window_set_resizable (GtkWindow *window,
7975 GtkWindowPrivate *priv;
7977 g_return_if_fail (GTK_IS_WINDOW (window));
7979 priv = window->priv;
7981 resizable = (resizable != FALSE);
7983 if (priv->resizable != resizable)
7985 priv->resizable = (resizable != FALSE);
7987 update_grip_visibility (window);
7989 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7991 g_object_notify (G_OBJECT (window), "resizable");
7996 * gtk_window_get_resizable:
7997 * @window: a #GtkWindow
7999 * Gets the value set by gtk_window_set_resizable().
8001 * Return value: %TRUE if the user can resize the window
8004 gtk_window_get_resizable (GtkWindow *window)
8006 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8008 return window->priv->resizable;
8012 * gtk_window_set_gravity:
8013 * @window: a #GtkWindow
8014 * @gravity: window gravity
8016 * Window gravity defines the meaning of coordinates passed to
8017 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8020 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8021 * typically "do what you mean."
8025 gtk_window_set_gravity (GtkWindow *window,
8028 GtkWindowPrivate *priv;
8030 g_return_if_fail (GTK_IS_WINDOW (window));
8032 priv = window->priv;
8034 if (gravity != priv->gravity)
8036 priv->gravity = gravity;
8038 /* gtk_window_move_resize() will adapt gravity
8040 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8042 g_object_notify (G_OBJECT (window), "gravity");
8047 * gtk_window_get_gravity:
8048 * @window: a #GtkWindow
8050 * Gets the value set by gtk_window_set_gravity().
8052 * Return value: (transfer none): window gravity
8055 gtk_window_get_gravity (GtkWindow *window)
8057 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8059 return window->priv->gravity;
8063 * gtk_window_begin_resize_drag:
8064 * @window: a #GtkWindow
8065 * @button: mouse button that initiated the drag
8066 * @edge: position of the resize control
8067 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8068 * @root_y: Y position where the user clicked to initiate the drag
8069 * @timestamp: timestamp from the click event that initiated the drag
8071 * Starts resizing a window. This function is used if an application
8072 * has window resizing controls. When GDK can support it, the resize
8073 * will be done using the standard mechanism for the <link
8074 * linkend="gtk-X11-arch">window manager</link> or windowing
8075 * system. Otherwise, GDK will try to emulate window resizing,
8076 * potentially not all that well, depending on the windowing system.
8080 gtk_window_begin_resize_drag (GtkWindow *window,
8088 GdkWindow *toplevel;
8090 g_return_if_fail (GTK_IS_WINDOW (window));
8091 widget = GTK_WIDGET (window);
8092 g_return_if_fail (gtk_widget_get_visible (widget));
8094 toplevel = gtk_widget_get_window (widget);
8096 gdk_window_begin_resize_drag (toplevel,
8103 * gtk_window_begin_move_drag:
8104 * @window: a #GtkWindow
8105 * @button: mouse button that initiated the drag
8106 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8107 * @root_y: Y position where the user clicked to initiate the drag
8108 * @timestamp: timestamp from the click event that initiated the drag
8110 * Starts moving a window. This function is used if an application has
8111 * window movement grips. When GDK can support it, the window movement
8112 * will be done using the standard mechanism for the <link
8113 * linkend="gtk-X11-arch">window manager</link> or windowing
8114 * system. Otherwise, GDK will try to emulate window movement,
8115 * potentially not all that well, depending on the windowing system.
8119 gtk_window_begin_move_drag (GtkWindow *window,
8126 GdkWindow *toplevel;
8128 g_return_if_fail (GTK_IS_WINDOW (window));
8129 widget = GTK_WIDGET (window);
8130 g_return_if_fail (gtk_widget_get_visible (widget));
8132 toplevel = gtk_widget_get_window (widget);
8134 gdk_window_begin_move_drag (toplevel,
8141 * gtk_window_set_screen:
8142 * @window: a #GtkWindow.
8143 * @screen: a #GdkScreen.
8145 * Sets the #GdkScreen where the @window is displayed; if
8146 * the window is already mapped, it will be unmapped, and
8147 * then remapped on the new screen.
8152 gtk_window_set_screen (GtkWindow *window,
8155 GtkWindowPrivate *priv;
8157 GdkScreen *previous_screen;
8158 gboolean was_mapped;
8160 g_return_if_fail (GTK_IS_WINDOW (window));
8161 g_return_if_fail (GDK_IS_SCREEN (screen));
8163 priv = window->priv;
8165 if (screen == priv->screen)
8168 widget = GTK_WIDGET (window);
8170 previous_screen = priv->screen;
8171 was_mapped = gtk_widget_get_mapped (widget);
8174 gtk_widget_unmap (widget);
8175 if (gtk_widget_get_realized (widget))
8176 gtk_widget_unrealize (widget);
8178 gtk_window_free_key_hash (window);
8179 priv->screen = screen;
8180 gtk_widget_reset_rc_styles (widget);
8181 if (screen != previous_screen)
8183 if (previous_screen)
8185 g_signal_handlers_disconnect_by_func (previous_screen,
8186 gtk_window_on_composited_changed, window);
8187 #ifdef GDK_WINDOWING_X11
8188 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8189 gtk_window_on_theme_variant_changed, window);
8192 g_signal_connect (screen, "composited-changed",
8193 G_CALLBACK (gtk_window_on_composited_changed), window);
8194 #ifdef GDK_WINDOWING_X11
8195 g_signal_connect (gtk_settings_get_for_screen (screen),
8196 "notify::gtk-application-prefer-dark-theme",
8197 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8200 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8201 _gtk_widget_propagate_composited_changed (widget);
8203 g_object_notify (G_OBJECT (window), "screen");
8206 gtk_widget_map (widget);
8210 gtk_window_set_theme_variant (GtkWindow *window)
8212 #ifdef GDK_WINDOWING_X11
8213 GdkWindow *gdk_window;
8214 gboolean dark_theme_requested;
8216 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8217 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8220 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8222 if (GDK_IS_X11_WINDOW (gdk_window))
8223 gdk_x11_window_set_theme_variant (gdk_window,
8224 dark_theme_requested ? "dark" : NULL);
8229 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8233 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8234 gtk_window_set_theme_variant (window);
8238 gtk_window_on_composited_changed (GdkScreen *screen,
8241 gtk_widget_queue_draw (GTK_WIDGET (window));
8243 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8247 gtk_window_check_screen (GtkWindow *window)
8249 GtkWindowPrivate *priv = window->priv;
8252 return priv->screen;
8255 g_warning ("Screen for GtkWindow not set; you must always set\n"
8256 "a screen for a GtkWindow before using the window");
8262 * gtk_window_get_screen:
8263 * @window: a #GtkWindow.
8265 * Returns the #GdkScreen associated with @window.
8267 * Return value: (transfer none): a #GdkScreen.
8272 gtk_window_get_screen (GtkWindow *window)
8274 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8276 return window->priv->screen;
8280 * gtk_window_is_active:
8281 * @window: a #GtkWindow
8283 * Returns whether the window is part of the current active toplevel.
8284 * (That is, the toplevel window receiving keystrokes.)
8285 * The return value is %TRUE if the window is active toplevel
8286 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8287 * You might use this function if you wanted to draw a widget
8288 * differently in an active window from a widget in an inactive window.
8289 * See gtk_window_has_toplevel_focus()
8291 * Return value: %TRUE if the window part of the current active window.
8296 gtk_window_is_active (GtkWindow *window)
8298 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8300 return window->priv->is_active;
8304 * gtk_window_has_toplevel_focus:
8305 * @window: a #GtkWindow
8307 * Returns whether the input focus is within this GtkWindow.
8308 * For real toplevel windows, this is identical to gtk_window_is_active(),
8309 * but for embedded windows, like #GtkPlug, the results will differ.
8311 * Return value: %TRUE if the input focus is within this GtkWindow
8316 gtk_window_has_toplevel_focus (GtkWindow *window)
8318 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8320 return window->priv->has_toplevel_focus;
8325 * SECTION:gtkwindowgroup
8326 * @Short_description: Limit the effect of grabs
8327 * @Title: GtkWindowGroup
8329 * #GtkWindowGroup objects are referenced by each window in the group,
8330 * so once you have added all windows to a #GtkWindowGroup, you can drop
8331 * the initial reference to the window group with g_object_unref(). If the
8332 * windows in the window group are subsequently destroyed, then they will
8333 * be removed from the window group and drop their references on the window
8334 * group; when all window have been removed, the window group will be
8338 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8341 gtk_window_group_init (GtkWindowGroup *group)
8343 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8344 GTK_TYPE_WINDOW_GROUP,
8345 GtkWindowGroupPrivate);
8349 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8351 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8355 * gtk_window_group_new:
8357 * Creates a new #GtkWindowGroup object. Grabs added with
8358 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8360 * Return value: a new #GtkWindowGroup.
8363 gtk_window_group_new (void)
8365 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8369 window_group_cleanup_grabs (GtkWindowGroup *group,
8372 GtkWindowGroupPrivate *priv;
8373 GtkDeviceGrabInfo *info;
8375 GSList *to_remove = NULL;
8379 tmp_list = priv->grabs;
8382 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8383 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8384 tmp_list = tmp_list->next;
8389 gtk_grab_remove (to_remove->data);
8390 g_object_unref (to_remove->data);
8391 to_remove = g_slist_delete_link (to_remove, to_remove);
8394 tmp_list = priv->device_grabs;
8398 info = tmp_list->data;
8400 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8401 to_remove = g_slist_prepend (to_remove, info);
8403 tmp_list = tmp_list->next;
8408 info = to_remove->data;
8410 gtk_device_grab_remove (info->widget, info->device);
8411 to_remove = g_slist_delete_link (to_remove, to_remove);
8416 * gtk_window_group_add_window:
8417 * @window_group: a #GtkWindowGroup
8418 * @window: the #GtkWindow to add
8420 * Adds a window to a #GtkWindowGroup.
8423 gtk_window_group_add_window (GtkWindowGroup *window_group,
8426 GtkWindowPrivate *priv;
8428 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8429 g_return_if_fail (GTK_IS_WINDOW (window));
8431 priv = window->priv;
8433 if (priv->group != window_group)
8435 g_object_ref (window);
8436 g_object_ref (window_group);
8439 gtk_window_group_remove_window (priv->group, window);
8441 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8443 priv->group = window_group;
8445 g_object_unref (window);
8450 * gtk_window_group_remove_window:
8451 * @window_group: a #GtkWindowGroup
8452 * @window: the #GtkWindow to remove
8454 * Removes a window from a #GtkWindowGroup.
8457 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8460 GtkWindowPrivate *priv;
8462 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8463 g_return_if_fail (GTK_IS_WINDOW (window));
8464 priv = window->priv;
8465 g_return_if_fail (priv->group == window_group);
8467 g_object_ref (window);
8469 window_group_cleanup_grabs (window_group, window);
8472 g_object_unref (window_group);
8473 g_object_unref (window);
8477 * gtk_window_group_list_windows:
8478 * @window_group: a #GtkWindowGroup
8480 * Returns a list of the #GtkWindows that belong to @window_group.
8482 * Returns: (element-type GtkWindow) (transfer container): A
8483 * newly-allocated list of windows inside the group.
8488 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8490 GList *toplevels, *toplevel, *group_windows;
8492 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8494 group_windows = NULL;
8495 toplevels = gtk_window_list_toplevels ();
8497 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8499 GtkWindow *window = toplevel->data;
8501 if (window_group == window->priv->group)
8502 group_windows = g_list_prepend (group_windows, window);
8505 g_list_free (toplevels);
8507 return g_list_reverse (group_windows);
8511 * gtk_window_get_group:
8512 * @window: (allow-none): a #GtkWindow, or %NULL
8514 * Returns the group for @window or the default group, if
8515 * @window is %NULL or if @window does not have an explicit
8518 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8523 gtk_window_get_group (GtkWindow *window)
8525 if (window && window->priv->group)
8526 return window->priv->group;
8529 static GtkWindowGroup *default_group = NULL;
8532 default_group = gtk_window_group_new ();
8534 return default_group;
8539 * gtk_window_has_group:
8540 * @window: a #GtkWindow
8542 * Returns whether @window has an explicit window group.
8544 * Return value: %TRUE if @window has an explicit window group.
8549 gtk_window_has_group (GtkWindow *window)
8551 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8553 return window->priv->group != NULL;
8557 * gtk_window_group_get_current_grab:
8558 * @window_group: a #GtkWindowGroup
8560 * Gets the current grab widget of the given group,
8561 * see gtk_grab_add().
8563 * Returns: (transfer none): the current grab widget of the group
8568 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8570 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8572 if (window_group->priv->grabs)
8573 return GTK_WIDGET (window_group->priv->grabs->data);
8578 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8581 GtkWindowGroupPrivate *priv;
8583 priv = window_group->priv;
8584 priv->grabs = g_slist_prepend (priv->grabs, widget);
8588 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8591 GtkWindowGroupPrivate *priv;
8593 priv = window_group->priv;
8594 priv->grabs = g_slist_remove (priv->grabs, widget);
8599 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8602 gboolean block_others)
8604 GtkWindowGroupPrivate *priv;
8605 GtkDeviceGrabInfo *info;
8607 priv = window_group->priv;
8609 info = g_slice_new0 (GtkDeviceGrabInfo);
8610 info->widget = widget;
8611 info->device = device;
8612 info->block_others = block_others;
8614 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8618 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8622 GtkWindowGroupPrivate *priv;
8623 GtkDeviceGrabInfo *info;
8624 GSList *list, *node = NULL;
8625 GdkDevice *other_device;
8627 priv = window_group->priv;
8628 other_device = gdk_device_get_associated_device (device);
8629 list = priv->device_grabs;
8635 if (info->widget == widget &&
8636 (info->device == device ||
8637 info->device == other_device))
8650 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8651 g_slice_free (GtkDeviceGrabInfo, info);
8656 * gtk_window_group_get_current_device_grab:
8657 * @window_group: a #GtkWindowGroup
8658 * @device: a #GdkDevice
8660 * Returns the current grab widget for @device, or %NULL if none.
8662 * Returns: (transfer none): The grab widget, or %NULL
8667 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8670 GtkWindowGroupPrivate *priv;
8671 GtkDeviceGrabInfo *info;
8672 GdkDevice *other_device;
8675 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8676 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8678 priv = window_group->priv;
8679 list = priv->device_grabs;
8680 other_device = gdk_device_get_associated_device (device);
8687 if (info->device == device ||
8688 info->device == other_device)
8689 return info->widget;
8696 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8700 GtkWindowGroupPrivate *priv;
8701 GtkDeviceGrabInfo *info;
8702 GdkDevice *other_device;
8705 priv = window_group->priv;
8706 other_device = gdk_device_get_associated_device (device);
8707 list = priv->device_grabs;
8714 /* Look for blocking grabs on other device pairs
8715 * that have the passed widget within the GTK+ grab.
8717 if (info->block_others &&
8718 info->device != device &&
8719 info->device != other_device &&
8720 (info->widget == widget ||
8721 gtk_widget_is_ancestor (widget, info->widget)))
8729 Derived from XParseGeometry() in XFree86
8731 Copyright 1985, 1986, 1987,1998 The Open Group
8733 All Rights Reserved.
8735 The above copyright notice and this permission notice shall be included
8736 in all copies or substantial portions of the Software.
8738 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8739 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8740 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8741 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8742 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8743 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8744 OTHER DEALINGS IN THE SOFTWARE.
8746 Except as contained in this notice, the name of The Open Group shall
8747 not be used in advertising or otherwise to promote the sale, use or
8748 other dealings in this Software without prior written authorization
8749 from The Open Group.
8754 * XParseGeometry parses strings of the form
8755 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8756 * width, height, xoffset, and yoffset are unsigned integers.
8757 * Example: "=80x24+300-49"
8758 * The equal sign is optional.
8759 * It returns a bitmask that indicates which of the four values
8760 * were actually found in the string. For each value found,
8761 * the corresponding argument is updated; for each value
8762 * not found, the corresponding argument is left unchanged.
8765 /* The following code is from Xlib, and is minimally modified, so we
8766 * can track any upstream changes if required. Don't change this
8767 * code. Or if you do, put in a huge comment marking which thing
8772 read_int (gchar *string,
8780 else if (*string == '-')
8786 for (; (*string >= '0') && (*string <= '9'); string++)
8788 result = (result * 10) + (*string - '0');
8800 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8801 * value (x, y, width, height) was found in the parsed string.
8803 #define NoValue 0x0000
8804 #define XValue 0x0001
8805 #define YValue 0x0002
8806 #define WidthValue 0x0004
8807 #define HeightValue 0x0008
8808 #define AllValues 0x000F
8809 #define XNegative 0x0010
8810 #define YNegative 0x0020
8812 /* Try not to reformat/modify, so we can compare/sync with X sources */
8814 gtk_XParseGeometry (const char *string,
8817 unsigned int *width,
8818 unsigned int *height)
8822 unsigned int tempWidth, tempHeight;
8824 char *nextCharacter;
8826 /* These initializations are just to silence gcc */
8832 if ( (string == NULL) || (*string == '\0')) return(mask);
8834 string++; /* ignore possible '=' at beg of geometry spec */
8836 strind = (char *)string;
8837 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8838 tempWidth = read_int(strind, &nextCharacter);
8839 if (strind == nextCharacter)
8841 strind = nextCharacter;
8845 if (*strind == 'x' || *strind == 'X') {
8847 tempHeight = read_int(strind, &nextCharacter);
8848 if (strind == nextCharacter)
8850 strind = nextCharacter;
8851 mask |= HeightValue;
8854 if ((*strind == '+') || (*strind == '-')) {
8855 if (*strind == '-') {
8857 tempX = -read_int(strind, &nextCharacter);
8858 if (strind == nextCharacter)
8860 strind = nextCharacter;
8866 tempX = read_int(strind, &nextCharacter);
8867 if (strind == nextCharacter)
8869 strind = nextCharacter;
8872 if ((*strind == '+') || (*strind == '-')) {
8873 if (*strind == '-') {
8875 tempY = -read_int(strind, &nextCharacter);
8876 if (strind == nextCharacter)
8878 strind = nextCharacter;
8885 tempY = read_int(strind, &nextCharacter);
8886 if (strind == nextCharacter)
8888 strind = nextCharacter;
8894 /* If strind isn't at the end of the string the it's an invalid
8895 geometry specification. */
8897 if (*strind != '\0') return (0);
8903 if (mask & WidthValue)
8905 if (mask & HeightValue)
8906 *height = tempHeight;
8911 * gtk_window_parse_geometry:
8912 * @window: a #GtkWindow
8913 * @geometry: geometry string
8915 * Parses a standard X Window System geometry string - see the
8916 * manual page for X (type 'man X') for details on this.
8917 * gtk_window_parse_geometry() does work on all GTK+ ports
8918 * including Win32 but is primarily intended for an X environment.
8920 * If either a size or a position can be extracted from the
8921 * geometry string, gtk_window_parse_geometry() returns %TRUE
8922 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8923 * to resize/move the window.
8925 * If gtk_window_parse_geometry() returns %TRUE, it will also
8926 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8927 * indicating to the window manager that the size/position of
8928 * the window was user-specified. This causes most window
8929 * managers to honor the geometry.
8931 * Note that for gtk_window_parse_geometry() to work as expected, it has
8932 * to be called when the window has its "final" size, i.e. after calling
8933 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8936 * #include <gtk/gtk.h>
8939 * fill_with_content (GtkWidget *vbox)
8941 * /* fill with content... */
8945 * main (int argc, char *argv[])
8947 * GtkWidget *window, *vbox;
8948 * GdkGeometry size_hints = {
8949 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8952 * gtk_init (&argc, &argv);
8954 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8955 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8957 * gtk_container_add (GTK_CONTAINER (window), vbox);
8958 * fill_with_content (vbox);
8959 * gtk_widget_show_all (vbox);
8961 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8964 * GDK_HINT_MIN_SIZE |
8965 * GDK_HINT_BASE_SIZE |
8966 * GDK_HINT_RESIZE_INC);
8970 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8971 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8974 * gtk_widget_show_all (window);
8981 * Return value: %TRUE if string was parsed successfully
8984 gtk_window_parse_geometry (GtkWindow *window,
8985 const gchar *geometry)
8987 gint result, x = 0, y = 0;
8991 gboolean size_set, pos_set;
8994 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8995 g_return_val_if_fail (geometry != NULL, FALSE);
8997 child = gtk_bin_get_child (GTK_BIN (window));
8998 if (!child || !gtk_widget_get_visible (child))
8999 g_warning ("gtk_window_parse_geometry() called on a window with no "
9000 "visible children; the window should be set up before "
9001 "gtk_window_parse_geometry() is called.");
9003 screen = gtk_window_check_screen (window);
9005 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9008 if ((result & WidthValue) || (result & HeightValue))
9010 gtk_window_set_default_size_internal (window,
9011 TRUE, result & WidthValue ? w : -1,
9012 TRUE, result & HeightValue ? h : -1,
9017 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9019 grav = GDK_GRAVITY_NORTH_WEST;
9021 if ((result & XNegative) && (result & YNegative))
9022 grav = GDK_GRAVITY_SOUTH_EAST;
9023 else if (result & XNegative)
9024 grav = GDK_GRAVITY_NORTH_EAST;
9025 else if (result & YNegative)
9026 grav = GDK_GRAVITY_SOUTH_WEST;
9028 if ((result & XValue) == 0)
9031 if ((result & YValue) == 0)
9034 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9035 grav == GDK_GRAVITY_SOUTH_EAST)
9036 y = gdk_screen_get_height (screen) - h + y;
9038 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9039 grav == GDK_GRAVITY_NORTH_EAST)
9040 x = gdk_screen_get_width (screen) - w + x;
9042 /* we don't let you put a window offscreen; maybe some people would
9043 * prefer to be able to, but it's kind of a bogus thing to do.
9052 if ((result & XValue) || (result & YValue))
9054 gtk_window_set_gravity (window, grav);
9055 gtk_window_move (window, x, y);
9059 if (size_set || pos_set)
9061 /* Set USSize, USPosition hints */
9062 GtkWindowGeometryInfo *info;
9064 info = gtk_window_get_geometry_info (window, TRUE);
9067 info->mask |= GDK_HINT_USER_POS;
9069 info->mask |= GDK_HINT_USER_SIZE;
9076 gtk_window_mnemonic_hash_foreach (guint keyval,
9082 GtkWindowKeysForeachFunc func;
9086 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9090 _gtk_window_keys_foreach (GtkWindow *window,
9091 GtkWindowKeysForeachFunc func,
9095 GtkMnemonicHash *mnemonic_hash;
9099 GtkWindowKeysForeachFunc func;
9103 info.window = window;
9105 info.func_data = func_data;
9107 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9109 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9110 gtk_window_mnemonic_hash_foreach, &info);
9112 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9115 GtkAccelGroup *group = groups->data;
9118 for (i = 0; i < group->priv->n_accels; i++)
9120 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9123 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9126 groups = groups->next;
9131 gtk_window_keys_changed (GtkWindow *window)
9133 gtk_window_free_key_hash (window);
9134 gtk_window_get_key_hash (window);
9137 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9139 struct _GtkWindowKeyEntry
9143 guint is_mnemonic : 1;
9147 window_key_entry_destroy (gpointer data)
9149 g_slice_free (GtkWindowKeyEntry, data);
9153 add_to_key_hash (GtkWindow *window,
9155 GdkModifierType modifiers,
9156 gboolean is_mnemonic,
9159 GtkKeyHash *key_hash = data;
9161 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9163 entry->keyval = keyval;
9164 entry->modifiers = modifiers;
9165 entry->is_mnemonic = is_mnemonic;
9167 /* GtkAccelGroup stores lowercased accelerators. To deal
9168 * with this, if <Shift> was specified, uppercase.
9170 if (modifiers & GDK_SHIFT_MASK)
9172 if (keyval == GDK_KEY_Tab)
9173 keyval = GDK_KEY_ISO_Left_Tab;
9175 keyval = gdk_keyval_to_upper (keyval);
9178 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9182 gtk_window_get_key_hash (GtkWindow *window)
9184 GdkScreen *screen = gtk_window_check_screen (window);
9185 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9190 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9191 (GDestroyNotify)window_key_entry_destroy);
9192 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9193 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9199 gtk_window_free_key_hash (GtkWindow *window)
9201 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9204 _gtk_key_hash_free (key_hash);
9205 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9210 * gtk_window_activate_key:
9211 * @window: a #GtkWindow
9212 * @event: a #GdkEventKey
9214 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9215 * called by the default ::key_press_event handler for toplevel windows,
9216 * however in some cases it may be useful to call this directly when
9217 * overriding the standard key handling for a toplevel window.
9219 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9224 gtk_window_activate_key (GtkWindow *window,
9227 GtkKeyHash *key_hash;
9228 GtkWindowKeyEntry *found_entry = NULL;
9229 gboolean enable_mnemonics;
9230 gboolean enable_accels;
9232 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9233 g_return_val_if_fail (event != NULL, FALSE);
9235 key_hash = gtk_window_get_key_hash (window);
9240 GSList *entries = _gtk_key_hash_lookup (key_hash,
9241 event->hardware_keycode,
9243 gtk_accelerator_get_default_mod_mask (),
9246 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9247 "gtk-enable-mnemonics", &enable_mnemonics,
9248 "gtk-enable-accels", &enable_accels,
9251 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9253 GtkWindowKeyEntry *entry = tmp_list->data;
9254 if (entry->is_mnemonic)
9256 if (enable_mnemonics)
9258 found_entry = entry;
9264 if (enable_accels && !found_entry)
9266 found_entry = entry;
9271 g_slist_free (entries);
9276 if (found_entry->is_mnemonic)
9278 if (enable_mnemonics)
9279 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9280 found_entry->modifiers);
9285 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9286 found_entry->modifiers);
9294 window_update_has_focus (GtkWindow *window)
9296 GtkWindowPrivate *priv = window->priv;
9297 GtkWidget *widget = GTK_WIDGET (window);
9298 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9300 if (has_focus != priv->has_focus)
9302 priv->has_focus = has_focus;
9306 if (priv->focus_widget &&
9307 priv->focus_widget != widget &&
9308 !gtk_widget_has_focus (priv->focus_widget))
9309 do_focus_change (priv->focus_widget, TRUE);
9313 if (priv->focus_widget &&
9314 priv->focus_widget != widget &&
9315 gtk_widget_has_focus (priv->focus_widget))
9316 do_focus_change (priv->focus_widget, FALSE);
9322 * _gtk_window_set_is_active:
9323 * @window: a #GtkWindow
9324 * @is_active: %TRUE if the window is in the currently active toplevel
9326 * Internal function that sets whether the #GtkWindow is part
9327 * of the currently active toplevel window (taking into account inter-process
9331 _gtk_window_set_is_active (GtkWindow *window,
9334 GtkWindowPrivate *priv;
9336 g_return_if_fail (GTK_IS_WINDOW (window));
9338 priv = window->priv;
9340 is_active = is_active != FALSE;
9342 if (is_active != priv->is_active)
9344 priv->is_active = is_active;
9345 window_update_has_focus (window);
9347 g_object_notify (G_OBJECT (window), "is-active");
9352 * _gtk_window_set_is_toplevel:
9353 * @window: a #GtkWindow
9354 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9355 * child of the root window); %FALSE if it is not (for example, for an
9356 * in-process, parented GtkPlug)
9358 * Internal function used by #GtkPlug when it gets parented/unparented by a
9359 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9360 * global list of toplevel windows.
9363 _gtk_window_set_is_toplevel (GtkWindow *window,
9364 gboolean is_toplevel)
9367 GtkWidget *toplevel;
9369 widget = GTK_WIDGET (window);
9371 if (gtk_widget_is_toplevel (widget))
9372 g_assert (g_slist_find (toplevel_list, window) != NULL);
9374 g_assert (g_slist_find (toplevel_list, window) == NULL);
9376 if (is_toplevel == gtk_widget_is_toplevel (widget))
9381 /* Pass through regular pathways of an embedded toplevel
9382 * to go through unmapping and hiding the widget before
9383 * becomming a toplevel again.
9385 * We remain hidden after becomming toplevel in order to
9386 * avoid problems during an embedded toplevel's dispose cycle
9387 * (When a toplevel window is shown it tries to grab focus again,
9388 * this causes problems while disposing).
9390 gtk_widget_hide (widget);
9392 /* Save the toplevel this widget was previously anchored into before
9393 * propagating a hierarchy-changed.
9395 * Usually this happens by way of gtk_widget_unparent() and we are
9396 * already unanchored at this point, just adding this clause incase
9397 * things happen differently.
9399 toplevel = gtk_widget_get_toplevel (widget);
9400 if (!gtk_widget_is_toplevel (toplevel))
9403 _gtk_widget_set_is_toplevel (widget, TRUE);
9405 /* When a window becomes toplevel after being embedded and anchored
9406 * into another window we need to unset its anchored flag so that
9407 * the hierarchy changed signal kicks in properly.
9409 _gtk_widget_set_anchored (widget, FALSE);
9410 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9412 toplevel_list = g_slist_prepend (toplevel_list, window);
9416 _gtk_widget_set_is_toplevel (widget, FALSE);
9417 toplevel_list = g_slist_remove (toplevel_list, window);
9419 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9424 * _gtk_window_set_has_toplevel_focus:
9425 * @window: a #GtkWindow
9426 * @has_toplevel_focus: %TRUE if the in
9428 * Internal function that sets whether the keyboard focus for the
9429 * toplevel window (taking into account inter-process embedding.)
9432 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9433 gboolean has_toplevel_focus)
9435 GtkWindowPrivate *priv;
9437 g_return_if_fail (GTK_IS_WINDOW (window));
9439 priv = window->priv;
9441 has_toplevel_focus = has_toplevel_focus != FALSE;
9443 if (has_toplevel_focus != priv->has_toplevel_focus)
9445 priv->has_toplevel_focus = has_toplevel_focus;
9446 window_update_has_focus (window);
9448 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9453 * gtk_window_set_auto_startup_notification:
9454 * @setting: %TRUE to automatically do startup notification
9456 * By default, after showing the first #GtkWindow, GTK+ calls
9457 * gdk_notify_startup_complete(). Call this function to disable
9458 * the automatic startup notification. You might do this if your
9459 * first window is a splash screen, and you want to delay notification
9460 * until after your real main window has been shown, for example.
9462 * In that example, you would disable startup notification
9463 * temporarily, show your splash screen, then re-enable it so that
9464 * showing the main window would automatically result in notification.
9469 gtk_window_set_auto_startup_notification (gboolean setting)
9471 disable_startup_notification = !setting;
9475 * gtk_window_get_window_type:
9476 * @window: a #GtkWindow
9478 * Gets the type of the window. See #GtkWindowType.
9480 * Return value: the type of the window
9485 gtk_window_get_window_type (GtkWindow *window)
9487 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9489 return window->priv->type;
9493 * gtk_window_get_mnemonics_visible:
9494 * @window: a #GtkWindow
9496 * Gets the value of the #GtkWindow:mnemonics-visible property.
9498 * Returns: %TRUE if mnemonics are supposed to be visible
9504 gtk_window_get_mnemonics_visible (GtkWindow *window)
9506 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9508 return window->priv->mnemonics_visible;
9512 * gtk_window_set_mnemonics_visible:
9513 * @window: a #GtkWindow
9514 * @setting: the new value
9516 * Sets the #GtkWindow:mnemonics-visible property.
9521 gtk_window_set_mnemonics_visible (GtkWindow *window,
9524 GtkWindowPrivate *priv;
9526 g_return_if_fail (GTK_IS_WINDOW (window));
9528 priv = window->priv;
9530 setting = setting != FALSE;
9532 if (priv->mnemonics_visible != setting)
9534 priv->mnemonics_visible = setting;
9535 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9538 priv->mnemonics_visible_set = TRUE;
9542 * gtk_window_get_focus_visible:
9543 * @window: a #GtkWindow
9545 * Gets the value of the #GtkWindow:focus-visible property.
9547 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9553 gtk_window_get_focus_visible (GtkWindow *window)
9555 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9557 return window->priv->focus_visible;
9561 * gtk_window_set_focus_visible:
9562 * @window: a #GtkWindow
9563 * @setting: the new value
9565 * Sets the #GtkWindow:focus-visible property.
9570 gtk_window_set_focus_visible (GtkWindow *window,
9573 GtkWindowPrivate *priv;
9575 g_return_if_fail (GTK_IS_WINDOW (window));
9577 priv = window->priv;
9579 setting = setting != FALSE;
9581 if (priv->focus_visible != setting)
9583 priv->focus_visible = setting;
9584 g_object_notify (G_OBJECT (window), "focus-visible");
9589 _gtk_window_get_wmclass (GtkWindow *window,
9590 gchar **wmclass_name,
9591 gchar **wmclass_class)
9593 GtkWindowPrivate *priv = window->priv;
9595 *wmclass_name = priv->wmclass_name;
9596 *wmclass_class = priv->wmclass_class;
9600 * gtk_window_set_has_user_ref_count:
9601 * @window: a #GtkWindow
9602 * @setting: the new value
9604 * Tells GTK+ whether to drop its extra reference to the window
9605 * when gtk_window_destroy() is called.
9607 * This function is only exported for the benefit of language
9608 * bindings which may need to keep the window alive until their
9609 * wrapper object is garbage collected. There is no justification
9610 * for ever calling this function in an application.
9615 gtk_window_set_has_user_ref_count (GtkWindow *window,
9618 g_return_if_fail (GTK_IS_WINDOW (window));
9620 window->priv->has_user_ref_count = setting;