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 static void ensure_state_flag_window_unfocused (GtkWidget *widget);
479 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
480 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
481 gtk_window_buildable_interface_init))
484 add_tab_bindings (GtkBindingSet *binding_set,
485 GdkModifierType modifiers,
486 GtkDirectionType direction)
488 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
490 GTK_TYPE_DIRECTION_TYPE, direction);
491 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
493 GTK_TYPE_DIRECTION_TYPE, direction);
497 add_arrow_bindings (GtkBindingSet *binding_set,
499 GtkDirectionType direction)
501 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
503 gtk_binding_entry_add_signal (binding_set, keysym, 0,
505 GTK_TYPE_DIRECTION_TYPE, direction);
506 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
508 GTK_TYPE_DIRECTION_TYPE, direction);
509 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
511 GTK_TYPE_DIRECTION_TYPE, direction);
512 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
514 GTK_TYPE_DIRECTION_TYPE, direction);
518 extract_time_from_startup_id (const gchar* startup_id)
520 gchar *timestr = g_strrstr (startup_id, "_TIME");
521 guint32 retval = GDK_CURRENT_TIME;
528 /* Skip past the "_TIME" part */
533 timestamp = g_ascii_strtoull (timestr, &end, 0);
534 if (errno == 0 && end != timestr)
542 startup_id_is_fake (const gchar* startup_id)
544 return strncmp (startup_id, "_TIME", 5) == 0;
548 gtk_window_class_init (GtkWindowClass *klass)
550 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
551 GtkWidgetClass *widget_class;
552 GtkContainerClass *container_class;
553 GtkBindingSet *binding_set;
555 widget_class = (GtkWidgetClass*) klass;
556 container_class = (GtkContainerClass*) klass;
558 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
559 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
560 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
561 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
563 gobject_class->dispose = gtk_window_dispose;
564 gobject_class->finalize = gtk_window_finalize;
566 gobject_class->set_property = gtk_window_set_property;
567 gobject_class->get_property = gtk_window_get_property;
569 widget_class->destroy = gtk_window_destroy;
570 widget_class->show = gtk_window_show;
571 widget_class->hide = gtk_window_hide;
572 widget_class->map = gtk_window_map;
573 widget_class->map_event = gtk_window_map_event;
574 widget_class->unmap = gtk_window_unmap;
575 widget_class->realize = gtk_window_realize;
576 widget_class->unrealize = gtk_window_unrealize;
577 widget_class->size_allocate = gtk_window_size_allocate;
578 widget_class->configure_event = gtk_window_configure_event;
579 widget_class->key_press_event = gtk_window_key_press_event;
580 widget_class->key_release_event = gtk_window_key_release_event;
581 widget_class->enter_notify_event = gtk_window_enter_notify_event;
582 widget_class->leave_notify_event = gtk_window_leave_notify_event;
583 widget_class->focus_in_event = gtk_window_focus_in_event;
584 widget_class->button_press_event = gtk_window_button_press_event;
585 widget_class->focus_out_event = gtk_window_focus_out_event;
586 widget_class->focus = gtk_window_focus;
587 widget_class->move_focus = gtk_window_move_focus;
588 widget_class->draw = gtk_window_draw;
589 widget_class->get_preferred_width = gtk_window_get_preferred_width;
590 widget_class->get_preferred_height = gtk_window_get_preferred_height;
591 widget_class->window_state_event = gtk_window_state_event;
592 widget_class->direction_changed = gtk_window_direction_changed;
593 widget_class->state_changed = gtk_window_state_changed;
594 widget_class->style_updated = gtk_window_style_updated;
596 container_class->check_resize = gtk_window_check_resize;
598 klass->set_focus = gtk_window_real_set_focus;
600 klass->activate_default = gtk_window_real_activate_default;
601 klass->activate_focus = gtk_window_real_activate_focus;
602 klass->keys_changed = gtk_window_keys_changed;
604 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
607 g_object_class_install_property (gobject_class,
609 g_param_spec_enum ("type",
611 P_("The type of the window"),
612 GTK_TYPE_WINDOW_TYPE,
614 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
616 g_object_class_install_property (gobject_class,
618 g_param_spec_string ("title",
620 P_("The title of the window"),
622 GTK_PARAM_READWRITE));
624 g_object_class_install_property (gobject_class,
626 g_param_spec_string ("role",
628 P_("Unique identifier for the window to be used when restoring a session"),
630 GTK_PARAM_READWRITE));
633 * GtkWindow:startup-id:
635 * The :startup-id is a write-only property for setting window's
636 * startup notification identifier. See gtk_window_set_startup_id()
641 g_object_class_install_property (gobject_class,
643 g_param_spec_string ("startup-id",
645 P_("Unique startup identifier for the window used by startup-notification"),
647 GTK_PARAM_WRITABLE));
649 g_object_class_install_property (gobject_class,
651 g_param_spec_boolean ("resizable",
653 P_("If TRUE, users can resize the window"),
655 GTK_PARAM_READWRITE));
657 g_object_class_install_property (gobject_class,
659 g_param_spec_boolean ("modal",
661 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
663 GTK_PARAM_READWRITE));
665 g_object_class_install_property (gobject_class,
667 g_param_spec_enum ("window-position",
668 P_("Window Position"),
669 P_("The initial position of the window"),
670 GTK_TYPE_WINDOW_POSITION,
672 GTK_PARAM_READWRITE));
674 g_object_class_install_property (gobject_class,
676 g_param_spec_int ("default-width",
678 P_("The default width of the window, used when initially showing the window"),
682 GTK_PARAM_READWRITE));
684 g_object_class_install_property (gobject_class,
686 g_param_spec_int ("default-height",
687 P_("Default Height"),
688 P_("The default height of the window, used when initially showing the window"),
692 GTK_PARAM_READWRITE));
694 g_object_class_install_property (gobject_class,
695 PROP_DESTROY_WITH_PARENT,
696 g_param_spec_boolean ("destroy-with-parent",
697 P_("Destroy with Parent"),
698 P_("If this window should be destroyed when the parent is destroyed"),
700 GTK_PARAM_READWRITE));
702 g_object_class_install_property (gobject_class,
704 g_param_spec_object ("icon",
706 P_("Icon for this window"),
708 GTK_PARAM_READWRITE));
711 * GtkWindow:mnemonics-visible:
713 * Whether mnemonics are currently visible in this window.
715 * This property is maintained by GTK+ based on the
716 * #GtkSettings:gtk-auto-mnemonics setting and user input,
717 * and should not be set by applications.
721 g_object_class_install_property (gobject_class,
722 PROP_MNEMONICS_VISIBLE,
723 g_param_spec_boolean ("mnemonics-visible",
724 P_("Mnemonics Visible"),
725 P_("Whether mnemonics are currently visible in this window"),
727 GTK_PARAM_READWRITE));
730 * GtkWindow:focus-visible:
732 * Whether 'focus rectangles' are currently visible in this window.
734 * This property is maintained by GTK+ based on the
735 * #GtkSettings:gtk-visible-focus setting and user input
736 * and should not be set by applications.
740 g_object_class_install_property (gobject_class,
742 g_param_spec_boolean ("focus-visible",
744 P_("Whether focus rectangles are currently visible in this window"),
746 GTK_PARAM_READWRITE));
749 * GtkWindow:icon-name:
751 * The :icon-name property specifies the name of the themed icon to
752 * use as the window icon. See #GtkIconTheme for more details.
756 g_object_class_install_property (gobject_class,
758 g_param_spec_string ("icon-name",
760 P_("Name of the themed icon for this window"),
762 GTK_PARAM_READWRITE));
764 g_object_class_install_property (gobject_class,
766 g_param_spec_object ("screen",
768 P_("The screen where this window will be displayed"),
770 GTK_PARAM_READWRITE));
772 g_object_class_install_property (gobject_class,
774 g_param_spec_boolean ("is-active",
776 P_("Whether the toplevel is the current active window"),
778 GTK_PARAM_READABLE));
780 g_object_class_install_property (gobject_class,
781 PROP_HAS_TOPLEVEL_FOCUS,
782 g_param_spec_boolean ("has-toplevel-focus",
783 P_("Focus in Toplevel"),
784 P_("Whether the input focus is within this GtkWindow"),
786 GTK_PARAM_READABLE));
788 g_object_class_install_property (gobject_class,
790 g_param_spec_enum ("type-hint",
792 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
793 GDK_TYPE_WINDOW_TYPE_HINT,
794 GDK_WINDOW_TYPE_HINT_NORMAL,
795 GTK_PARAM_READWRITE));
797 g_object_class_install_property (gobject_class,
798 PROP_SKIP_TASKBAR_HINT,
799 g_param_spec_boolean ("skip-taskbar-hint",
801 P_("TRUE if the window should not be in the task bar."),
803 GTK_PARAM_READWRITE));
805 g_object_class_install_property (gobject_class,
806 PROP_SKIP_PAGER_HINT,
807 g_param_spec_boolean ("skip-pager-hint",
809 P_("TRUE if the window should not be in the pager."),
811 GTK_PARAM_READWRITE));
813 g_object_class_install_property (gobject_class,
815 g_param_spec_boolean ("urgency-hint",
817 P_("TRUE if the window should be brought to the user's attention."),
819 GTK_PARAM_READWRITE));
822 * GtkWindow:accept-focus:
824 * Whether the window should receive the input focus.
828 g_object_class_install_property (gobject_class,
830 g_param_spec_boolean ("accept-focus",
832 P_("TRUE if the window should receive the input focus."),
834 GTK_PARAM_READWRITE));
837 * GtkWindow:focus-on-map:
839 * Whether the window should receive the input focus when mapped.
843 g_object_class_install_property (gobject_class,
845 g_param_spec_boolean ("focus-on-map",
847 P_("TRUE if the window should receive the input focus when mapped."),
849 GTK_PARAM_READWRITE));
852 * GtkWindow:decorated:
854 * Whether the window should be decorated by the window manager.
858 g_object_class_install_property (gobject_class,
860 g_param_spec_boolean ("decorated",
862 P_("Whether the window should be decorated by the window manager"),
864 GTK_PARAM_READWRITE));
867 * GtkWindow:deletable:
869 * Whether the window frame should have a close button.
873 g_object_class_install_property (gobject_class,
875 g_param_spec_boolean ("deletable",
877 P_("Whether the window frame should have a close button"),
879 GTK_PARAM_READWRITE));
882 * GtkWindow:has-resize-grip
884 * Whether the window has a corner resize grip.
886 * Note that the resize grip is only shown if the window is
887 * actually resizable and not maximized. Use
888 * #GtkWindow:resize-grip-visible to find out if the resize
889 * grip is currently shown.
893 g_object_class_install_property (gobject_class,
894 PROP_HAS_RESIZE_GRIP,
895 g_param_spec_boolean ("has-resize-grip",
897 P_("Specifies whether the window should have a resize grip"),
899 GTK_PARAM_READWRITE));
902 * GtkWindow:resize-grip-visible:
904 * Whether a corner resize grip is currently shown.
908 g_object_class_install_property (gobject_class,
909 PROP_RESIZE_GRIP_VISIBLE,
910 g_param_spec_boolean ("resize-grip-visible",
911 P_("Resize grip is visible"),
912 P_("Specifies whether the window's resize grip is visible."),
914 GTK_PARAM_READABLE));
920 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
921 * more details about window gravity.
925 g_object_class_install_property (gobject_class,
927 g_param_spec_enum ("gravity",
929 P_("The window gravity of the window"),
931 GDK_GRAVITY_NORTH_WEST,
932 GTK_PARAM_READWRITE));
936 * GtkWindow:transient-for:
938 * The transient parent of the window. See gtk_window_set_transient_for() for
939 * more details about transient windows.
943 g_object_class_install_property (gobject_class,
945 g_param_spec_object ("transient-for",
946 P_("Transient for Window"),
947 P_("The transient parent of the dialog"),
949 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
954 * The requested opacity of the window. See gtk_window_set_opacity() for
955 * more details about window opacity.
959 g_object_class_install_property (gobject_class,
961 g_param_spec_double ("opacity",
962 P_("Opacity for Window"),
963 P_("The opacity of the window, from 0 to 1"),
967 GTK_PARAM_READWRITE));
971 gtk_widget_class_install_style_property (widget_class,
972 g_param_spec_int ("resize-grip-width",
973 P_("Width of resize grip"),
974 P_("Width of resize grip"),
975 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
977 gtk_widget_class_install_style_property (widget_class,
978 g_param_spec_int ("resize-grip-height",
979 P_("Height of resize grip"),
980 P_("Height of resize grip"),
981 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
985 * GtkWindow:application:
987 * The #GtkApplication associated with the window.
989 * The application will be kept alive for at least as long as it
990 * has any windows associated with it (see g_application_hold()
991 * for a way to keep it alive without windows).
993 * Normally, the connection between the application and the window
994 * will remain until the window is destroyed, but you can explicitly
995 * remove it by setting the ::application property to %NULL.
999 g_object_class_install_property (gobject_class,
1001 g_param_spec_object ("application",
1002 P_("GtkApplication"),
1003 P_("The GtkApplication for the window"),
1004 GTK_TYPE_APPLICATION,
1005 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1007 window_signals[SET_FOCUS] =
1008 g_signal_new (I_("set-focus"),
1009 G_TYPE_FROM_CLASS (gobject_class),
1011 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1013 _gtk_marshal_VOID__OBJECT,
1018 * GtkWindow::activate-focus:
1019 * @window: the window which received the signal
1021 * The ::activate-focus signal is a
1022 * <link linkend="keybinding-signals">keybinding signal</link>
1023 * which gets emitted when the user activates the currently
1024 * focused widget of @window.
1026 window_signals[ACTIVATE_FOCUS] =
1027 g_signal_new (I_("activate-focus"),
1028 G_TYPE_FROM_CLASS (gobject_class),
1029 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1030 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1032 _gtk_marshal_VOID__VOID,
1037 * GtkWindow::activate-default:
1038 * @window: the window which received the signal
1040 * The ::activate-default signal is a
1041 * <link linkend="keybinding-signals">keybinding signal</link>
1042 * which gets emitted when the user activates the default widget
1045 window_signals[ACTIVATE_DEFAULT] =
1046 g_signal_new (I_("activate-default"),
1047 G_TYPE_FROM_CLASS (gobject_class),
1048 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1049 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1051 _gtk_marshal_VOID__VOID,
1056 * GtkWindow::keys-changed:
1057 * @window: the window which received the signal
1059 * The ::keys-changed signal gets emitted when the set of accelerators
1060 * or mnemonics that are associated with @window changes.
1062 window_signals[KEYS_CHANGED] =
1063 g_signal_new (I_("keys-changed"),
1064 G_TYPE_FROM_CLASS (gobject_class),
1066 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1068 _gtk_marshal_VOID__VOID,
1076 binding_set = gtk_binding_set_by_class (klass);
1078 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1079 "activate-focus", 0);
1080 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1081 "activate-focus", 0);
1083 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1084 "activate-default", 0);
1085 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1086 "activate-default", 0);
1087 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1088 "activate-default", 0);
1090 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1091 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1092 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1093 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1095 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1096 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1097 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1098 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1100 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1104 gtk_window_init (GtkWindow *window)
1106 GtkWindowPrivate *priv;
1108 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1111 priv = window->priv;
1113 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1114 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1116 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1118 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1121 priv->wmclass_name = g_strdup (g_get_prgname ());
1122 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1123 priv->wm_role = NULL;
1124 priv->geometry_info = NULL;
1125 priv->type = GTK_WINDOW_TOPLEVEL;
1126 priv->focus_widget = NULL;
1127 priv->default_widget = NULL;
1128 priv->configure_request_count = 0;
1129 priv->resizable = TRUE;
1130 priv->configure_notify_received = FALSE;
1131 priv->position = GTK_WIN_POS_NONE;
1132 priv->need_default_size = TRUE;
1133 priv->need_default_position = TRUE;
1134 priv->modal = FALSE;
1135 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1136 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1137 priv->decorated = TRUE;
1138 priv->mnemonic_modifier = GDK_MOD1_MASK;
1139 priv->screen = gdk_screen_get_default ();
1141 priv->accept_focus = TRUE;
1142 priv->focus_on_map = TRUE;
1143 priv->deletable = TRUE;
1144 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1145 priv->opacity = 1.0;
1146 priv->startup_id = NULL;
1147 priv->initial_timestamp = GDK_CURRENT_TIME;
1148 priv->has_resize_grip = TRUE;
1149 priv->mnemonics_visible = TRUE;
1150 priv->focus_visible = TRUE;
1152 g_object_ref_sink (window);
1153 priv->has_user_ref_count = TRUE;
1154 toplevel_list = g_slist_prepend (toplevel_list, window);
1157 g_signal_connect (priv->screen, "composited-changed",
1158 G_CALLBACK (gtk_window_on_composited_changed), window);
1160 #ifdef GDK_WINDOWING_X11
1161 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1162 "notify::gtk-application-prefer-dark-theme",
1163 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1168 gtk_window_set_property (GObject *object,
1170 const GValue *value,
1173 GtkWindow *window = GTK_WINDOW (object);
1174 GtkWindowPrivate *priv = window->priv;
1179 priv->type = g_value_get_enum (value);
1182 gtk_window_set_title (window, g_value_get_string (value));
1185 gtk_window_set_role (window, g_value_get_string (value));
1187 case PROP_STARTUP_ID:
1188 gtk_window_set_startup_id (window, g_value_get_string (value));
1190 case PROP_RESIZABLE:
1191 gtk_window_set_resizable (window, g_value_get_boolean (value));
1194 gtk_window_set_modal (window, g_value_get_boolean (value));
1197 gtk_window_set_position (window, g_value_get_enum (value));
1199 case PROP_DEFAULT_WIDTH:
1200 gtk_window_set_default_size_internal (window,
1201 TRUE, g_value_get_int (value),
1204 case PROP_DEFAULT_HEIGHT:
1205 gtk_window_set_default_size_internal (window,
1207 TRUE, g_value_get_int (value), FALSE);
1209 case PROP_DESTROY_WITH_PARENT:
1210 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1213 gtk_window_set_icon (window,
1214 g_value_get_object (value));
1216 case PROP_ICON_NAME:
1217 gtk_window_set_icon_name (window, g_value_get_string (value));
1220 gtk_window_set_screen (window, g_value_get_object (value));
1222 case PROP_TYPE_HINT:
1223 gtk_window_set_type_hint (window,
1224 g_value_get_enum (value));
1226 case PROP_SKIP_TASKBAR_HINT:
1227 gtk_window_set_skip_taskbar_hint (window,
1228 g_value_get_boolean (value));
1230 case PROP_SKIP_PAGER_HINT:
1231 gtk_window_set_skip_pager_hint (window,
1232 g_value_get_boolean (value));
1234 case PROP_URGENCY_HINT:
1235 gtk_window_set_urgency_hint (window,
1236 g_value_get_boolean (value));
1238 case PROP_ACCEPT_FOCUS:
1239 gtk_window_set_accept_focus (window,
1240 g_value_get_boolean (value));
1242 case PROP_FOCUS_ON_MAP:
1243 gtk_window_set_focus_on_map (window,
1244 g_value_get_boolean (value));
1246 case PROP_DECORATED:
1247 gtk_window_set_decorated (window, g_value_get_boolean (value));
1249 case PROP_DELETABLE:
1250 gtk_window_set_deletable (window, g_value_get_boolean (value));
1253 gtk_window_set_gravity (window, g_value_get_enum (value));
1255 case PROP_TRANSIENT_FOR:
1256 gtk_window_set_transient_for (window, g_value_get_object (value));
1259 gtk_window_set_opacity (window, g_value_get_double (value));
1261 case PROP_HAS_RESIZE_GRIP:
1262 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1264 case PROP_APPLICATION:
1265 gtk_window_set_application (window, g_value_get_object (value));
1267 case PROP_MNEMONICS_VISIBLE:
1268 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1270 case PROP_FOCUS_VISIBLE:
1271 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1274 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1280 gtk_window_get_property (GObject *object,
1285 GtkWindow *window = GTK_WINDOW (object);
1286 GtkWindowPrivate *priv = window->priv;
1290 GtkWindowGeometryInfo *info;
1292 g_value_set_enum (value, priv->type);
1295 g_value_set_string (value, priv->wm_role);
1298 g_value_set_string (value, priv->title);
1300 case PROP_RESIZABLE:
1301 g_value_set_boolean (value, priv->resizable);
1304 g_value_set_boolean (value, priv->modal);
1307 g_value_set_enum (value, priv->position);
1309 case PROP_DEFAULT_WIDTH:
1310 info = gtk_window_get_geometry_info (window, FALSE);
1312 g_value_set_int (value, -1);
1314 g_value_set_int (value, info->default_width);
1316 case PROP_DEFAULT_HEIGHT:
1317 info = gtk_window_get_geometry_info (window, FALSE);
1319 g_value_set_int (value, -1);
1321 g_value_set_int (value, info->default_height);
1323 case PROP_DESTROY_WITH_PARENT:
1324 g_value_set_boolean (value, priv->destroy_with_parent);
1327 g_value_set_object (value, gtk_window_get_icon (window));
1329 case PROP_ICON_NAME:
1330 g_value_set_string (value, gtk_window_get_icon_name (window));
1333 g_value_set_object (value, priv->screen);
1335 case PROP_IS_ACTIVE:
1336 g_value_set_boolean (value, priv->is_active);
1338 case PROP_HAS_TOPLEVEL_FOCUS:
1339 g_value_set_boolean (value, priv->has_toplevel_focus);
1341 case PROP_TYPE_HINT:
1342 g_value_set_enum (value, priv->type_hint);
1344 case PROP_SKIP_TASKBAR_HINT:
1345 g_value_set_boolean (value,
1346 gtk_window_get_skip_taskbar_hint (window));
1348 case PROP_SKIP_PAGER_HINT:
1349 g_value_set_boolean (value,
1350 gtk_window_get_skip_pager_hint (window));
1352 case PROP_URGENCY_HINT:
1353 g_value_set_boolean (value,
1354 gtk_window_get_urgency_hint (window));
1356 case PROP_ACCEPT_FOCUS:
1357 g_value_set_boolean (value,
1358 gtk_window_get_accept_focus (window));
1360 case PROP_FOCUS_ON_MAP:
1361 g_value_set_boolean (value,
1362 gtk_window_get_focus_on_map (window));
1364 case PROP_DECORATED:
1365 g_value_set_boolean (value, gtk_window_get_decorated (window));
1367 case PROP_DELETABLE:
1368 g_value_set_boolean (value, gtk_window_get_deletable (window));
1371 g_value_set_enum (value, gtk_window_get_gravity (window));
1373 case PROP_TRANSIENT_FOR:
1374 g_value_set_object (value, gtk_window_get_transient_for (window));
1377 g_value_set_double (value, gtk_window_get_opacity (window));
1379 case PROP_HAS_RESIZE_GRIP:
1380 g_value_set_boolean (value, priv->has_resize_grip);
1382 case PROP_RESIZE_GRIP_VISIBLE:
1383 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1385 case PROP_APPLICATION:
1386 g_value_set_object (value, gtk_window_get_application (window));
1388 case PROP_MNEMONICS_VISIBLE:
1389 g_value_set_boolean (value, priv->mnemonics_visible);
1391 case PROP_FOCUS_VISIBLE:
1392 g_value_set_boolean (value, priv->focus_visible);
1395 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1401 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1403 parent_buildable_iface = g_type_interface_peek_parent (iface);
1404 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1405 iface->parser_finished = gtk_window_buildable_parser_finished;
1406 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1407 iface->custom_finished = gtk_window_buildable_custom_finished;
1411 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1412 GtkBuilder *builder,
1414 const GValue *value)
1416 GtkWindow *window = GTK_WINDOW (buildable);
1417 GtkWindowPrivate *priv = window->priv;
1419 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1420 priv->builder_visible = TRUE;
1422 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1426 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1427 GtkBuilder *builder)
1429 GtkWindow *window = GTK_WINDOW (buildable);
1430 GtkWindowPrivate *priv = window->priv;
1434 if (priv->builder_visible)
1435 gtk_widget_show (GTK_WIDGET (buildable));
1437 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1438 for (l = accels; l; l = l->next)
1440 object = gtk_builder_get_object (builder, l->data);
1443 g_warning ("Unknown accel group %s specified in window %s",
1444 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1447 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1448 GTK_ACCEL_GROUP (object));
1452 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1454 parent_buildable_iface->parser_finished (buildable, builder);
1460 } GSListSubParserData;
1463 window_start_element (GMarkupParseContext *context,
1464 const gchar *element_name,
1465 const gchar **names,
1466 const gchar **values,
1471 GSListSubParserData *data = (GSListSubParserData*)user_data;
1473 if (strcmp (element_name, "group") == 0)
1475 for (i = 0; names[i]; i++)
1477 if (strcmp (names[i], "name") == 0)
1478 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1481 else if (strcmp (element_name, "accel-groups") == 0)
1484 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1489 static const GMarkupParser window_parser =
1491 window_start_element
1495 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1496 GtkBuilder *builder,
1498 const gchar *tagname,
1499 GMarkupParser *parser,
1502 GSListSubParserData *parser_data;
1504 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1505 tagname, parser, data))
1508 if (strcmp (tagname, "accel-groups") == 0)
1510 parser_data = g_slice_new0 (GSListSubParserData);
1511 parser_data->items = NULL;
1512 parser_data->object = G_OBJECT (buildable);
1514 *parser = window_parser;
1515 *data = parser_data;
1523 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1524 GtkBuilder *builder,
1526 const gchar *tagname,
1529 GSListSubParserData *data;
1531 parent_buildable_iface->custom_finished (buildable, builder, child,
1532 tagname, user_data);
1534 if (strcmp (tagname, "accel-groups") != 0)
1537 data = (GSListSubParserData*)user_data;
1539 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1540 data->items, (GDestroyNotify) g_slist_free);
1542 g_slice_free (GSListSubParserData, data);
1547 * @type: type of window
1549 * Creates a new #GtkWindow, which is a toplevel window that can
1550 * contain other widgets. Nearly always, the type of the window should
1551 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1552 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1553 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1554 * dialogs, though in some other toolkits dialogs are called "popups".
1555 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1556 * On X11, popup windows are not controlled by the <link
1557 * linkend="gtk-X11-arch">window manager</link>.
1559 * If you simply want an undecorated window (no window borders), use
1560 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1562 * Return value: a new #GtkWindow.
1565 gtk_window_new (GtkWindowType type)
1567 GtkWindowPrivate *priv;
1570 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1572 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1573 priv = window->priv;
1577 return GTK_WIDGET (window);
1581 * gtk_window_set_title:
1582 * @window: a #GtkWindow
1583 * @title: title of the window
1585 * Sets the title of the #GtkWindow. The title of a window will be
1586 * displayed in its title bar; on the X Window System, the title bar
1587 * is rendered by the <link linkend="gtk-X11-arch">window
1588 * manager</link>, so exactly how the title appears to users may vary
1589 * according to a user's exact configuration. The title should help a
1590 * user distinguish this window from other windows they may have
1591 * open. A good title might include the application name and current
1592 * document filename, for example.
1596 gtk_window_set_title (GtkWindow *window,
1599 GtkWindowPrivate *priv;
1603 g_return_if_fail (GTK_IS_WINDOW (window));
1605 priv = window->priv;
1606 widget = GTK_WIDGET (window);
1608 new_title = g_strdup (title);
1609 g_free (priv->title);
1610 priv->title = new_title;
1612 if (gtk_widget_get_realized (widget))
1614 gdk_window_set_title (gtk_widget_get_window (widget),
1618 g_object_notify (G_OBJECT (window), "title");
1622 * gtk_window_get_title:
1623 * @window: a #GtkWindow
1625 * Retrieves the title of the window. See gtk_window_set_title().
1627 * Return value: the title of the window, or %NULL if none has
1628 * been set explicitely. The returned string is owned by the widget
1629 * and must not be modified or freed.
1632 gtk_window_get_title (GtkWindow *window)
1634 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1636 return window->priv->title;
1640 * gtk_window_set_wmclass:
1641 * @window: a #GtkWindow
1642 * @wmclass_name: window name hint
1643 * @wmclass_class: window class hint
1645 * Don't use this function. It sets the X Window System "class" and
1646 * "name" hints for a window. According to the ICCCM, you should
1647 * always set these to the same value for all windows in an
1648 * application, and GTK+ sets them to that value by default, so calling
1649 * this function is sort of pointless. However, you may want to call
1650 * gtk_window_set_role() on each window in your application, for the
1651 * benefit of the session manager. Setting the role allows the window
1652 * manager to restore window positions when loading a saved session.
1656 gtk_window_set_wmclass (GtkWindow *window,
1657 const gchar *wmclass_name,
1658 const gchar *wmclass_class)
1660 GtkWindowPrivate *priv;
1662 g_return_if_fail (GTK_IS_WINDOW (window));
1664 priv = window->priv;
1666 g_free (priv->wmclass_name);
1667 priv->wmclass_name = g_strdup (wmclass_name);
1669 g_free (priv->wmclass_class);
1670 priv->wmclass_class = g_strdup (wmclass_class);
1672 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1673 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1677 * gtk_window_set_role:
1678 * @window: a #GtkWindow
1679 * @role: unique identifier for the window to be used when restoring a session
1681 * This function is only useful on X11, not with other GTK+ targets.
1683 * In combination with the window title, the window role allows a
1684 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1685 * same" window when an application is restarted. So for example you
1686 * might set the "toolbox" role on your app's toolbox window, so that
1687 * when the user restarts their session, the window manager can put
1688 * the toolbox back in the same place.
1690 * If a window already has a unique title, you don't need to set the
1691 * role, since the WM can use the title to identify the window when
1692 * restoring the session.
1696 gtk_window_set_role (GtkWindow *window,
1699 GtkWindowPrivate *priv;
1702 g_return_if_fail (GTK_IS_WINDOW (window));
1704 priv = window->priv;
1706 new_role = g_strdup (role);
1707 g_free (priv->wm_role);
1708 priv->wm_role = new_role;
1710 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1711 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1714 g_object_notify (G_OBJECT (window), "role");
1718 * gtk_window_set_startup_id:
1719 * @window: a #GtkWindow
1720 * @startup_id: a string with startup-notification identifier
1722 * Startup notification identifiers are used by desktop environment to
1723 * track application startup, to provide user feedback and other
1724 * features. This function changes the corresponding property on the
1725 * underlying GdkWindow. Normally, startup identifier is managed
1726 * automatically and you should only use this function in special cases
1727 * like transferring focus from other processes. You should use this
1728 * function before calling gtk_window_present() or any equivalent
1729 * function generating a window map event.
1731 * This function is only useful on X11, not with other GTK+ targets.
1736 gtk_window_set_startup_id (GtkWindow *window,
1737 const gchar *startup_id)
1739 GtkWindowPrivate *priv;
1742 g_return_if_fail (GTK_IS_WINDOW (window));
1744 priv = window->priv;
1745 widget = GTK_WIDGET (window);
1747 g_free (priv->startup_id);
1748 priv->startup_id = g_strdup (startup_id);
1750 if (gtk_widget_get_realized (widget))
1752 GdkWindow *gdk_window;
1753 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1755 gdk_window = gtk_widget_get_window (widget);
1757 #ifdef GDK_WINDOWING_X11
1758 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1759 gdk_x11_window_set_user_time (gdk_window, timestamp);
1762 /* Here we differentiate real and "fake" startup notification IDs,
1763 * constructed on purpose just to pass interaction timestamp
1765 if (startup_id_is_fake (priv->startup_id))
1766 gtk_window_present_with_time (window, timestamp);
1769 gdk_window_set_startup_id (gdk_window,
1772 /* If window is mapped, terminate the startup-notification too */
1773 if (gtk_widget_get_mapped (widget) &&
1774 !disable_startup_notification)
1775 gdk_notify_startup_complete_with_id (priv->startup_id);
1779 g_object_notify (G_OBJECT (window), "startup-id");
1783 * gtk_window_get_role:
1784 * @window: a #GtkWindow
1786 * Returns the role of the window. See gtk_window_set_role() for
1787 * further explanation.
1789 * Return value: the role of the window if set, or %NULL. The
1790 * returned is owned by the widget and must not be modified
1794 gtk_window_get_role (GtkWindow *window)
1796 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1798 return window->priv->wm_role;
1802 * gtk_window_set_focus:
1803 * @window: a #GtkWindow
1804 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1805 * any focus widget for the toplevel window.
1807 * If @focus is not the current focus widget, and is focusable, sets
1808 * it as the focus widget for the window. If @focus is %NULL, unsets
1809 * the focus widget for this window. To set the focus to a particular
1810 * widget in the toplevel, it is usually more convenient to use
1811 * gtk_widget_grab_focus() instead of this function.
1814 gtk_window_set_focus (GtkWindow *window,
1817 GtkWindowPrivate *priv;
1820 g_return_if_fail (GTK_IS_WINDOW (window));
1822 priv = window->priv;
1826 g_return_if_fail (GTK_IS_WIDGET (focus));
1827 g_return_if_fail (gtk_widget_get_can_focus (focus));
1831 gtk_widget_grab_focus (focus);
1834 /* Clear the existing focus chain, so that when we focus into
1835 * the window again, we start at the beginnning.
1837 GtkWidget *widget = priv->focus_widget;
1840 while ((parent = gtk_widget_get_parent (widget)))
1843 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1847 _gtk_window_internal_set_focus (window, NULL);
1852 _gtk_window_internal_set_focus (GtkWindow *window,
1855 GtkWindowPrivate *priv;
1857 g_return_if_fail (GTK_IS_WINDOW (window));
1859 priv = window->priv;
1861 if ((priv->focus_widget != focus) ||
1862 (focus && !gtk_widget_has_focus (focus)))
1863 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1867 * gtk_window_set_default:
1868 * @window: a #GtkWindow
1869 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1870 * default widget for the toplevel.
1872 * The default widget is the widget that's activated when the user
1873 * presses Enter in a dialog (for example). This function sets or
1874 * unsets the default widget for a #GtkWindow about. When setting
1875 * (rather than unsetting) the default widget it's generally easier to
1876 * call gtk_widget_grab_focus() on the widget. Before making a widget
1877 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1878 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1881 gtk_window_set_default (GtkWindow *window,
1882 GtkWidget *default_widget)
1884 GtkWindowPrivate *priv;
1886 g_return_if_fail (GTK_IS_WINDOW (window));
1888 priv = window->priv;
1891 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1893 if (priv->default_widget != default_widget)
1895 GtkWidget *old_default_widget = NULL;
1898 g_object_ref (default_widget);
1900 if (priv->default_widget)
1902 old_default_widget = priv->default_widget;
1904 if (priv->focus_widget != priv->default_widget ||
1905 !gtk_widget_get_receives_default (priv->default_widget))
1906 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1908 gtk_widget_queue_draw (priv->default_widget);
1911 priv->default_widget = default_widget;
1913 if (priv->default_widget)
1915 if (priv->focus_widget == NULL ||
1916 !gtk_widget_get_receives_default (priv->focus_widget))
1917 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1919 gtk_widget_queue_draw (priv->default_widget);
1922 if (old_default_widget)
1923 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1927 g_object_notify (G_OBJECT (default_widget), "has-default");
1928 g_object_unref (default_widget);
1934 * gtk_window_get_default_widget:
1935 * @window: a #GtkWindow
1937 * Returns the default widget for @window. See gtk_window_set_default()
1940 * Returns: (transfer none): the default widget, or %NULL if there is none.
1945 gtk_window_get_default_widget (GtkWindow *window)
1947 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1949 return window->priv->default_widget;
1953 handle_keys_changed (gpointer data)
1955 GtkWindow *window = GTK_WINDOW (data);
1956 GtkWindowPrivate *priv = window->priv;
1958 if (priv->keys_changed_handler)
1960 g_source_remove (priv->keys_changed_handler);
1961 priv->keys_changed_handler = 0;
1964 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1970 gtk_window_notify_keys_changed (GtkWindow *window)
1972 GtkWindowPrivate *priv = window->priv;
1974 if (!priv->keys_changed_handler)
1975 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1979 * gtk_window_add_accel_group:
1980 * @window: window to attach accelerator group to
1981 * @accel_group: a #GtkAccelGroup
1983 * Associate @accel_group with @window, such that calling
1984 * gtk_accel_groups_activate() on @window will activate accelerators
1988 gtk_window_add_accel_group (GtkWindow *window,
1989 GtkAccelGroup *accel_group)
1991 g_return_if_fail (GTK_IS_WINDOW (window));
1992 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1994 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1995 g_signal_connect_object (accel_group, "accel-changed",
1996 G_CALLBACK (gtk_window_notify_keys_changed),
1997 window, G_CONNECT_SWAPPED);
1998 gtk_window_notify_keys_changed (window);
2002 * gtk_window_remove_accel_group:
2003 * @window: a #GtkWindow
2004 * @accel_group: a #GtkAccelGroup
2006 * Reverses the effects of gtk_window_add_accel_group().
2009 gtk_window_remove_accel_group (GtkWindow *window,
2010 GtkAccelGroup *accel_group)
2012 g_return_if_fail (GTK_IS_WINDOW (window));
2013 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2015 g_signal_handlers_disconnect_by_func (accel_group,
2016 gtk_window_notify_keys_changed,
2018 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2019 gtk_window_notify_keys_changed (window);
2022 static GtkMnemonicHash *
2023 gtk_window_get_mnemonic_hash (GtkWindow *window,
2026 GtkWindowPrivate *private = window->priv;
2028 if (!private->mnemonic_hash && create)
2029 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2031 return private->mnemonic_hash;
2035 * gtk_window_add_mnemonic:
2036 * @window: a #GtkWindow
2037 * @keyval: the mnemonic
2038 * @target: the widget that gets activated by the mnemonic
2040 * Adds a mnemonic to this window.
2043 gtk_window_add_mnemonic (GtkWindow *window,
2047 g_return_if_fail (GTK_IS_WINDOW (window));
2048 g_return_if_fail (GTK_IS_WIDGET (target));
2050 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2052 gtk_window_notify_keys_changed (window);
2056 * gtk_window_remove_mnemonic:
2057 * @window: a #GtkWindow
2058 * @keyval: the mnemonic
2059 * @target: the widget that gets activated by the mnemonic
2061 * Removes a mnemonic from this window.
2064 gtk_window_remove_mnemonic (GtkWindow *window,
2068 g_return_if_fail (GTK_IS_WINDOW (window));
2069 g_return_if_fail (GTK_IS_WIDGET (target));
2071 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2073 gtk_window_notify_keys_changed (window);
2077 * gtk_window_mnemonic_activate:
2078 * @window: a #GtkWindow
2079 * @keyval: the mnemonic
2080 * @modifier: the modifiers
2082 * Activates the targets associated with the mnemonic.
2084 * Returns: %TRUE if the activation is done.
2087 gtk_window_mnemonic_activate (GtkWindow *window,
2089 GdkModifierType modifier)
2091 GtkWindowPrivate *priv;
2093 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2095 priv = window->priv;
2097 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2099 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2101 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2108 * gtk_window_set_mnemonic_modifier:
2109 * @window: a #GtkWindow
2110 * @modifier: the modifier mask used to activate
2111 * mnemonics on this window.
2113 * Sets the mnemonic modifier for this window.
2116 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2117 GdkModifierType modifier)
2119 GtkWindowPrivate *priv;
2121 g_return_if_fail (GTK_IS_WINDOW (window));
2122 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2124 priv = window->priv;
2126 priv->mnemonic_modifier = modifier;
2127 gtk_window_notify_keys_changed (window);
2131 * gtk_window_get_mnemonic_modifier:
2132 * @window: a #GtkWindow
2134 * Returns the mnemonic modifier for this window. See
2135 * gtk_window_set_mnemonic_modifier().
2137 * Return value: the modifier mask used to activate
2138 * mnemonics on this window.
2141 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2143 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2145 return window->priv->mnemonic_modifier;
2149 * gtk_window_set_position:
2150 * @window: a #GtkWindow.
2151 * @position: a position constraint.
2153 * Sets a position constraint for this window. If the old or new
2154 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2155 * the window to be repositioned to satisfy the new constraint.
2158 gtk_window_set_position (GtkWindow *window,
2159 GtkWindowPosition position)
2161 GtkWindowPrivate *priv;
2163 g_return_if_fail (GTK_IS_WINDOW (window));
2165 priv = window->priv;
2167 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2168 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2170 GtkWindowGeometryInfo *info;
2172 info = gtk_window_get_geometry_info (window, TRUE);
2174 /* this flag causes us to re-request the CENTER_ALWAYS
2175 * constraint in gtk_window_move_resize(), see
2176 * comment in that function.
2178 info->position_constraints_changed = TRUE;
2180 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2183 priv->position = position;
2185 g_object_notify (G_OBJECT (window), "window-position");
2189 * gtk_window_activate_focus:
2190 * @window: a #GtkWindow
2192 * Activates the current focused widget within the window.
2194 * Return value: %TRUE if a widget got activated.
2197 gtk_window_activate_focus (GtkWindow *window)
2199 GtkWindowPrivate *priv;
2201 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2203 priv = window->priv;
2205 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2206 return gtk_widget_activate (priv->focus_widget);
2212 * gtk_window_get_focus:
2213 * @window: a #GtkWindow
2215 * Retrieves the current focused widget within the window.
2216 * Note that this is the widget that would have the focus
2217 * if the toplevel window focused; if the toplevel window
2218 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2219 * not be %TRUE for the widget.
2221 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2224 gtk_window_get_focus (GtkWindow *window)
2226 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2228 return window->priv->focus_widget;
2232 * gtk_window_activate_default:
2233 * @window: a #GtkWindow
2235 * Activates the default widget for the window, unless the current
2236 * focused widget has been configured to receive the default action
2237 * (see gtk_widget_set_receives_default()), in which case the
2238 * focused widget is activated.
2240 * Return value: %TRUE if a widget got activated.
2243 gtk_window_activate_default (GtkWindow *window)
2245 GtkWindowPrivate *priv;
2247 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2249 priv = window->priv;
2251 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2252 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2253 return gtk_widget_activate (priv->default_widget);
2254 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2255 return gtk_widget_activate (priv->focus_widget);
2261 * gtk_window_set_modal:
2262 * @window: a #GtkWindow
2263 * @modal: whether the window is modal
2265 * Sets a window modal or non-modal. Modal windows prevent interaction
2266 * with other windows in the same application. To keep modal dialogs
2267 * on top of main application windows, use
2268 * gtk_window_set_transient_for() to make the dialog transient for the
2269 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2270 * will then disallow lowering the dialog below the parent.
2275 gtk_window_set_modal (GtkWindow *window,
2278 GtkWindowPrivate *priv;
2281 g_return_if_fail (GTK_IS_WINDOW (window));
2283 priv = window->priv;
2285 modal = modal != FALSE;
2286 if (priv->modal == modal)
2289 priv->modal = modal;
2290 widget = GTK_WIDGET (window);
2292 /* adjust desired modality state */
2293 if (gtk_widget_get_realized (widget))
2296 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2298 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2301 if (gtk_widget_get_visible (widget))
2304 gtk_grab_add (widget);
2306 gtk_grab_remove (widget);
2309 g_object_notify (G_OBJECT (window), "modal");
2313 * gtk_window_get_modal:
2314 * @window: a #GtkWindow
2316 * Returns whether the window is modal. See gtk_window_set_modal().
2318 * Return value: %TRUE if the window is set to be modal and
2319 * establishes a grab when shown
2322 gtk_window_get_modal (GtkWindow *window)
2324 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2326 return window->priv->modal;
2330 * gtk_window_list_toplevels:
2332 * Returns a list of all existing toplevel windows. The widgets
2333 * in the list are not individually referenced. If you want
2334 * to iterate through the list and perform actions involving
2335 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2336 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2337 * then unref all the widgets afterwards.
2339 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2342 gtk_window_list_toplevels (void)
2347 for (slist = toplevel_list; slist; slist = slist->next)
2348 list = g_list_prepend (list, slist->data);
2354 gtk_window_dispose (GObject *object)
2356 GtkWindow *window = GTK_WINDOW (object);
2358 gtk_window_set_focus (window, NULL);
2359 gtk_window_set_default (window, NULL);
2361 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2365 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2367 gtk_widget_destroy (GTK_WIDGET (child));
2371 connect_parent_destroyed (GtkWindow *window)
2373 GtkWindowPrivate *priv = window->priv;
2375 if (priv->transient_parent)
2377 g_signal_connect (priv->transient_parent,
2379 G_CALLBACK (parent_destroyed_callback),
2385 disconnect_parent_destroyed (GtkWindow *window)
2387 GtkWindowPrivate *priv = window->priv;
2389 if (priv->transient_parent)
2391 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2392 parent_destroyed_callback,
2398 gtk_window_transient_parent_realized (GtkWidget *parent,
2401 if (gtk_widget_get_realized (window))
2402 gdk_window_set_transient_for (gtk_widget_get_window (window),
2403 gtk_widget_get_window (parent));
2407 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2410 if (gtk_widget_get_realized (window))
2411 gdk_property_delete (gtk_widget_get_window (window),
2412 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2416 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2420 gtk_window_set_screen (window, parent->priv->screen);
2424 gtk_window_unset_transient_for (GtkWindow *window)
2426 GtkWindowPrivate *priv = window->priv;
2428 if (priv->transient_parent)
2430 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2431 gtk_window_transient_parent_realized,
2433 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2434 gtk_window_transient_parent_unrealized,
2436 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2437 gtk_window_transient_parent_screen_changed,
2439 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2440 gtk_widget_destroyed,
2441 &priv->transient_parent);
2443 if (priv->destroy_with_parent)
2444 disconnect_parent_destroyed (window);
2446 priv->transient_parent = NULL;
2448 if (priv->transient_parent_group)
2450 priv->transient_parent_group = FALSE;
2451 gtk_window_group_remove_window (priv->group,
2458 * gtk_window_set_transient_for:
2459 * @window: a #GtkWindow
2460 * @parent: (allow-none): parent window, or %NULL
2462 * Dialog windows should be set transient for the main application
2463 * window they were spawned from. This allows <link
2464 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2465 * dialog on top of the main window, or center the dialog over the
2466 * main window. gtk_dialog_new_with_buttons() and other convenience
2467 * functions in GTK+ will sometimes call
2468 * gtk_window_set_transient_for() on your behalf.
2470 * Passing %NULL for @parent unsets the current transient window.
2472 * On Windows, this function puts the child window on top of the parent,
2473 * much as the window manager would have done on X.
2476 gtk_window_set_transient_for (GtkWindow *window,
2479 GtkWindowPrivate *priv;
2481 g_return_if_fail (GTK_IS_WINDOW (window));
2482 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2483 g_return_if_fail (window != parent);
2485 priv = window->priv;
2487 if (priv->transient_parent)
2489 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2490 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2491 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2492 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2493 GTK_WIDGET (window));
2495 gtk_window_unset_transient_for (window);
2498 priv->transient_parent = parent;
2502 g_signal_connect (parent, "destroy",
2503 G_CALLBACK (gtk_widget_destroyed),
2504 &priv->transient_parent);
2505 g_signal_connect (parent, "realize",
2506 G_CALLBACK (gtk_window_transient_parent_realized),
2508 g_signal_connect (parent, "unrealize",
2509 G_CALLBACK (gtk_window_transient_parent_unrealized),
2511 g_signal_connect (parent, "notify::screen",
2512 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2515 gtk_window_set_screen (window, parent->priv->screen);
2517 if (priv->destroy_with_parent)
2518 connect_parent_destroyed (window);
2520 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2521 gtk_widget_get_realized (GTK_WIDGET (parent)))
2522 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2523 GTK_WIDGET (window));
2525 if (parent->priv->group)
2527 gtk_window_group_add_window (parent->priv->group, window);
2528 priv->transient_parent_group = TRUE;
2534 * gtk_window_get_transient_for:
2535 * @window: a #GtkWindow
2537 * Fetches the transient parent for this window. See
2538 * gtk_window_set_transient_for().
2540 * Return value: (transfer none): the transient parent for this window, or %NULL
2541 * if no transient parent has been set.
2544 gtk_window_get_transient_for (GtkWindow *window)
2546 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2548 return window->priv->transient_parent;
2552 * gtk_window_set_opacity:
2553 * @window: a #GtkWindow
2554 * @opacity: desired opacity, between 0 and 1
2556 * Request the windowing system to make @window partially transparent,
2557 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2558 * of the opacity parameter are clamped to the [0,1] range.) On X11
2559 * this has any effect only on X screens with a compositing manager
2560 * running. See gtk_widget_is_composited(). On Windows it should work
2563 * Note that setting a window's opacity after the window has been
2564 * shown causes it to flicker once on Windows.
2569 gtk_window_set_opacity (GtkWindow *window,
2572 GtkWindowPrivate *priv;
2574 g_return_if_fail (GTK_IS_WINDOW (window));
2576 priv = window->priv;
2580 else if (opacity > 1.0)
2583 priv->opacity_set = TRUE;
2584 priv->opacity = opacity;
2586 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2587 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2592 * gtk_window_get_opacity:
2593 * @window: a #GtkWindow
2595 * Fetches the requested opacity for this window. See
2596 * gtk_window_set_opacity().
2598 * Return value: the requested opacity for this window.
2603 gtk_window_get_opacity (GtkWindow *window)
2605 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2607 return window->priv->opacity;
2611 * gtk_window_get_application:
2612 * @window: a #GtkWindow
2614 * Gets the #GtkApplication associated with the window (if any).
2616 * Return value: (transfer none): a #GtkApplication, or %NULL
2621 gtk_window_get_application (GtkWindow *window)
2623 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2625 return window->priv->application;
2629 gtk_window_release_application (GtkWindow *window)
2631 if (window->priv->application)
2633 GtkApplication *application;
2635 /* steal reference into temp variable */
2636 application = window->priv->application;
2637 window->priv->application = NULL;
2639 gtk_application_remove_window (application, window);
2640 g_object_unref (application);
2645 * gtk_window_set_application:
2646 * @window: a #GtkWindow
2647 * @application: (allow-none): a #GtkApplication, or %NULL
2649 * Sets or unsets the #GtkApplication associated with the window.
2651 * The application will be kept alive for at least as long as the window
2657 gtk_window_set_application (GtkWindow *window,
2658 GtkApplication *application)
2660 GtkWindowPrivate *priv;
2662 g_return_if_fail (GTK_IS_WINDOW (window));
2664 priv = window->priv;
2665 if (priv->application != application)
2667 gtk_window_release_application (window);
2669 priv->application = application;
2671 if (priv->application != NULL)
2673 g_object_ref (priv->application);
2675 gtk_application_add_window (priv->application, window);
2678 g_object_notify (G_OBJECT (window), "application");
2683 * gtk_window_set_type_hint:
2684 * @window: a #GtkWindow
2685 * @hint: the window type
2687 * By setting the type hint for the window, you allow the window
2688 * manager to decorate and handle the window in a way which is
2689 * suitable to the function of the window in your application.
2691 * This function should be called before the window becomes visible.
2693 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2694 * will sometimes call gtk_window_set_type_hint() on your behalf.
2698 gtk_window_set_type_hint (GtkWindow *window,
2699 GdkWindowTypeHint hint)
2701 GtkWindowPrivate *priv;
2703 g_return_if_fail (GTK_IS_WINDOW (window));
2704 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2706 priv = window->priv;
2708 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2709 priv->type_hint = hint;
2711 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2713 priv->reset_type_hint = TRUE;
2714 priv->gdk_type_hint = hint;
2718 * gtk_window_get_type_hint:
2719 * @window: a #GtkWindow
2721 * Gets the type hint for this window. See gtk_window_set_type_hint().
2723 * Return value: the type hint for @window.
2726 gtk_window_get_type_hint (GtkWindow *window)
2728 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2730 return window->priv->gdk_type_hint;
2734 * gtk_window_set_skip_taskbar_hint:
2735 * @window: a #GtkWindow
2736 * @setting: %TRUE to keep this window from appearing in the task bar
2738 * Windows may set a hint asking the desktop environment not to display
2739 * the window in the task bar. This function sets this hint.
2744 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2747 GtkWindowPrivate *priv;
2749 g_return_if_fail (GTK_IS_WINDOW (window));
2751 priv = window->priv;
2753 setting = setting != FALSE;
2755 if (priv->skips_taskbar != setting)
2757 priv->skips_taskbar = setting;
2758 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2759 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2760 priv->skips_taskbar);
2761 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2766 * gtk_window_get_skip_taskbar_hint:
2767 * @window: a #GtkWindow
2769 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2771 * Return value: %TRUE if window shouldn't be in taskbar
2776 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2778 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2780 return window->priv->skips_taskbar;
2784 * gtk_window_set_skip_pager_hint:
2785 * @window: a #GtkWindow
2786 * @setting: %TRUE to keep this window from appearing in the pager
2788 * Windows may set a hint asking the desktop environment not to display
2789 * the window in the pager. This function sets this hint.
2790 * (A "pager" is any desktop navigation tool such as a workspace
2791 * switcher that displays a thumbnail representation of the windows
2797 gtk_window_set_skip_pager_hint (GtkWindow *window,
2800 GtkWindowPrivate *priv;
2802 g_return_if_fail (GTK_IS_WINDOW (window));
2804 priv = window->priv;
2806 setting = setting != FALSE;
2808 if (priv->skips_pager != setting)
2810 priv->skips_pager = setting;
2811 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2812 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2814 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2819 * gtk_window_get_skip_pager_hint:
2820 * @window: a #GtkWindow
2822 * Gets the value set by gtk_window_set_skip_pager_hint().
2824 * Return value: %TRUE if window shouldn't be in pager
2829 gtk_window_get_skip_pager_hint (GtkWindow *window)
2831 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2833 return window->priv->skips_pager;
2837 * gtk_window_set_urgency_hint:
2838 * @window: a #GtkWindow
2839 * @setting: %TRUE to mark this window as urgent
2841 * Windows may set a hint asking the desktop environment to draw
2842 * the users attention to the window. This function sets this hint.
2847 gtk_window_set_urgency_hint (GtkWindow *window,
2850 GtkWindowPrivate *priv;
2852 g_return_if_fail (GTK_IS_WINDOW (window));
2854 priv = window->priv;
2856 setting = setting != FALSE;
2858 if (priv->urgent != setting)
2860 priv->urgent = setting;
2861 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2862 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2864 g_object_notify (G_OBJECT (window), "urgency-hint");
2869 * gtk_window_get_urgency_hint:
2870 * @window: a #GtkWindow
2872 * Gets the value set by gtk_window_set_urgency_hint()
2874 * Return value: %TRUE if window is urgent
2879 gtk_window_get_urgency_hint (GtkWindow *window)
2881 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2883 return window->priv->urgent;
2887 * gtk_window_set_accept_focus:
2888 * @window: a #GtkWindow
2889 * @setting: %TRUE to let this window receive input focus
2891 * Windows may set a hint asking the desktop environment not to receive
2892 * the input focus. This function sets this hint.
2897 gtk_window_set_accept_focus (GtkWindow *window,
2900 GtkWindowPrivate *priv;
2902 g_return_if_fail (GTK_IS_WINDOW (window));
2904 priv = window->priv;
2906 setting = setting != FALSE;
2908 if (priv->accept_focus != setting)
2910 priv->accept_focus = setting;
2911 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2912 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2913 priv->accept_focus);
2914 g_object_notify (G_OBJECT (window), "accept-focus");
2919 * gtk_window_get_accept_focus:
2920 * @window: a #GtkWindow
2922 * Gets the value set by gtk_window_set_accept_focus().
2924 * Return value: %TRUE if window should receive the input focus
2929 gtk_window_get_accept_focus (GtkWindow *window)
2931 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2933 return window->priv->accept_focus;
2937 * gtk_window_set_focus_on_map:
2938 * @window: a #GtkWindow
2939 * @setting: %TRUE to let this window receive input focus on map
2941 * Windows may set a hint asking the desktop environment not to receive
2942 * the input focus when the window is mapped. This function sets this
2948 gtk_window_set_focus_on_map (GtkWindow *window,
2951 GtkWindowPrivate *priv;
2953 g_return_if_fail (GTK_IS_WINDOW (window));
2955 priv = window->priv;
2957 setting = setting != FALSE;
2959 if (priv->focus_on_map != setting)
2961 priv->focus_on_map = setting;
2962 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2963 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2964 priv->focus_on_map);
2965 g_object_notify (G_OBJECT (window), "focus-on-map");
2970 * gtk_window_get_focus_on_map:
2971 * @window: a #GtkWindow
2973 * Gets the value set by gtk_window_set_focus_on_map().
2975 * Return value: %TRUE if window should receive the input focus when
2981 gtk_window_get_focus_on_map (GtkWindow *window)
2983 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2985 return window->priv->focus_on_map;
2989 * gtk_window_set_destroy_with_parent:
2990 * @window: a #GtkWindow
2991 * @setting: whether to destroy @window with its transient parent
2993 * If @setting is %TRUE, then destroying the transient parent of @window
2994 * will also destroy @window itself. This is useful for dialogs that
2995 * shouldn't persist beyond the lifetime of the main window they're
2996 * associated with, for example.
2999 gtk_window_set_destroy_with_parent (GtkWindow *window,
3002 GtkWindowPrivate *priv;
3004 g_return_if_fail (GTK_IS_WINDOW (window));
3006 priv = window->priv;
3008 if (priv->destroy_with_parent == (setting != FALSE))
3011 if (priv->destroy_with_parent)
3013 disconnect_parent_destroyed (window);
3017 connect_parent_destroyed (window);
3020 priv->destroy_with_parent = setting;
3022 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3026 * gtk_window_get_destroy_with_parent:
3027 * @window: a #GtkWindow
3029 * Returns whether the window will be destroyed with its transient parent. See
3030 * gtk_window_set_destroy_with_parent ().
3032 * Return value: %TRUE if the window will be destroyed with its transient parent.
3035 gtk_window_get_destroy_with_parent (GtkWindow *window)
3037 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3039 return window->priv->destroy_with_parent;
3042 static GtkWindowGeometryInfo*
3043 gtk_window_get_geometry_info (GtkWindow *window,
3046 GtkWindowPrivate *priv = window->priv;
3047 GtkWindowGeometryInfo *info;
3049 info = priv->geometry_info;
3050 if (!info && create)
3052 info = g_new0 (GtkWindowGeometryInfo, 1);
3054 info->default_width = -1;
3055 info->default_height = -1;
3056 info->resize_width = -1;
3057 info->resize_height = -1;
3058 info->initial_x = 0;
3059 info->initial_y = 0;
3060 info->initial_pos_set = FALSE;
3061 info->default_is_geometry = FALSE;
3062 info->position_constraints_changed = FALSE;
3063 info->last.configure_request.x = 0;
3064 info->last.configure_request.y = 0;
3065 info->last.configure_request.width = -1;
3066 info->last.configure_request.height = -1;
3067 info->widget = NULL;
3069 priv->geometry_info = info;
3076 * gtk_window_set_geometry_hints:
3077 * @window: a #GtkWindow
3078 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3079 * @geometry: (allow-none): struct containing geometry information or %NULL
3080 * @geom_mask: mask indicating which struct fields should be paid attention to
3082 * This function sets up hints about how a window can be resized by
3083 * the user. You can set a minimum and maximum size; allowed resize
3084 * increments (e.g. for xterm, you can only resize by the size of a
3085 * character); aspect ratios; and more. See the #GdkGeometry struct.
3089 gtk_window_set_geometry_hints (GtkWindow *window,
3090 GtkWidget *geometry_widget,
3091 GdkGeometry *geometry,
3092 GdkWindowHints geom_mask)
3094 GtkWindowGeometryInfo *info;
3096 g_return_if_fail (GTK_IS_WINDOW (window));
3097 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3099 info = gtk_window_get_geometry_info (window, TRUE);
3102 g_signal_handlers_disconnect_by_func (info->widget,
3103 gtk_widget_destroyed,
3106 info->widget = geometry_widget;
3108 g_signal_connect (geometry_widget, "destroy",
3109 G_CALLBACK (gtk_widget_destroyed),
3113 info->geometry = *geometry;
3115 /* We store gravity in priv->gravity not in the hints. */
3116 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3118 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3120 gtk_window_set_gravity (window, geometry->win_gravity);
3123 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3127 * gtk_window_set_decorated:
3128 * @window: a #GtkWindow
3129 * @setting: %TRUE to decorate the window
3131 * By default, windows are decorated with a title bar, resize
3132 * controls, etc. Some <link linkend="gtk-X11-arch">window
3133 * managers</link> allow GTK+ to disable these decorations, creating a
3134 * borderless window. If you set the decorated property to %FALSE
3135 * using this function, GTK+ will do its best to convince the window
3136 * manager not to decorate the window. Depending on the system, this
3137 * function may not have any effect when called on a window that is
3138 * already visible, so you should call it before calling gtk_widget_show().
3140 * On Windows, this function always works, since there's no window manager
3145 gtk_window_set_decorated (GtkWindow *window,
3148 GtkWindowPrivate *priv;
3149 GdkWindow *gdk_window;
3151 g_return_if_fail (GTK_IS_WINDOW (window));
3153 priv = window->priv;
3155 setting = setting != FALSE;
3157 if (setting == priv->decorated)
3160 priv->decorated = setting;
3162 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3165 if (priv->decorated)
3166 gdk_window_set_decorations (gdk_window,
3169 gdk_window_set_decorations (gdk_window,
3173 g_object_notify (G_OBJECT (window), "decorated");
3177 * gtk_window_get_decorated:
3178 * @window: a #GtkWindow
3180 * Returns whether the window has been set to have decorations
3181 * such as a title bar via gtk_window_set_decorated().
3183 * Return value: %TRUE if the window has been set to have decorations
3186 gtk_window_get_decorated (GtkWindow *window)
3188 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3190 return window->priv->decorated;
3194 * gtk_window_set_deletable:
3195 * @window: a #GtkWindow
3196 * @setting: %TRUE to decorate the window as deletable
3198 * By default, windows have a close button in the window frame. Some
3199 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3200 * disable this button. If you set the deletable property to %FALSE
3201 * using this function, GTK+ will do its best to convince the window
3202 * manager not to show a close button. Depending on the system, this
3203 * function may not have any effect when called on a window that is
3204 * already visible, so you should call it before calling gtk_window_show().
3206 * On Windows, this function always works, since there's no window manager
3212 gtk_window_set_deletable (GtkWindow *window,
3215 GtkWindowPrivate *priv;
3216 GdkWindow *gdk_window;
3218 g_return_if_fail (GTK_IS_WINDOW (window));
3220 priv = window->priv;
3222 setting = setting != FALSE;
3224 if (setting == priv->deletable)
3227 priv->deletable = setting;
3229 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3232 if (priv->deletable)
3233 gdk_window_set_functions (gdk_window,
3236 gdk_window_set_functions (gdk_window,
3237 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3240 g_object_notify (G_OBJECT (window), "deletable");
3244 * gtk_window_get_deletable:
3245 * @window: a #GtkWindow
3247 * Returns whether the window has been set to have a close button
3248 * via gtk_window_set_deletable().
3250 * Return value: %TRUE if the window has been set to have a close button
3255 gtk_window_get_deletable (GtkWindow *window)
3257 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3259 return window->priv->deletable;
3262 static GtkWindowIconInfo*
3263 get_icon_info (GtkWindow *window)
3265 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3269 free_icon_info (GtkWindowIconInfo *info)
3271 g_free (info->icon_name);
3272 g_slice_free (GtkWindowIconInfo, info);
3276 static GtkWindowIconInfo*
3277 ensure_icon_info (GtkWindow *window)
3279 GtkWindowIconInfo *info;
3281 info = get_icon_info (window);
3285 info = g_slice_new0 (GtkWindowIconInfo);
3286 g_object_set_qdata_full (G_OBJECT (window),
3287 quark_gtk_window_icon_info,
3289 (GDestroyNotify)free_icon_info);
3296 icon_list_from_theme (GtkWidget *widget,
3301 GtkIconTheme *icon_theme;
3306 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3308 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3311 for (i = 0; sizes[i]; i++)
3314 * We need an EWMH extension to handle scalable icons
3315 * by passing their name to the WM. For now just use a
3319 icon = gtk_icon_theme_load_icon (icon_theme, name,
3322 icon = gtk_icon_theme_load_icon (icon_theme, name,
3325 list = g_list_append (list, icon);
3335 gtk_window_realize_icon (GtkWindow *window)
3337 GtkWindowPrivate *priv = window->priv;
3339 GtkWindowIconInfo *info;
3340 GdkWindow *gdk_window;
3343 widget = GTK_WIDGET (window);
3344 gdk_window = gtk_widget_get_window (widget);
3346 g_return_if_fail (gdk_window != NULL);
3348 /* no point setting an icon on override-redirect */
3349 if (priv->type == GTK_WINDOW_POPUP)
3354 info = ensure_icon_info (window);
3359 info->using_default_icon = FALSE;
3360 info->using_parent_icon = FALSE;
3361 info->using_themed_icon = FALSE;
3363 icon_list = info->icon_list;
3365 /* Look up themed icon */
3366 if (icon_list == NULL && info->icon_name)
3368 icon_list = icon_list_from_theme (widget, info->icon_name);
3370 info->using_themed_icon = TRUE;
3373 /* Inherit from transient parent */
3374 if (icon_list == NULL && priv->transient_parent)
3376 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3378 info->using_parent_icon = TRUE;
3381 /* Inherit from default */
3382 if (icon_list == NULL)
3384 icon_list = default_icon_list;
3386 info->using_default_icon = TRUE;
3389 /* Look up themed icon */
3390 if (icon_list == NULL && default_icon_name)
3392 icon_list = icon_list_from_theme (widget, default_icon_name);
3393 info->using_default_icon = TRUE;
3394 info->using_themed_icon = TRUE;
3397 info->realized = TRUE;
3399 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3401 if (info->using_themed_icon)
3403 GtkIconTheme *icon_theme;
3405 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3406 g_list_free (icon_list);
3408 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3409 g_signal_connect (icon_theme, "changed",
3410 G_CALLBACK (update_themed_icon), window);
3415 gtk_window_unrealize_icon (GtkWindow *window)
3417 GtkWindowIconInfo *info;
3419 info = get_icon_info (window);
3424 if (info->using_themed_icon)
3426 GtkIconTheme *icon_theme;
3428 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3430 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3433 /* We don't clear the properties on the window, just figure the
3434 * window is going away.
3437 info->realized = FALSE;
3442 * gtk_window_set_icon_list:
3443 * @window: a #GtkWindow
3444 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3446 * Sets up the icon representing a #GtkWindow. The icon is used when
3447 * the window is minimized (also known as iconified). Some window
3448 * managers or desktop environments may also place it in the window
3449 * frame, or display it in other contexts.
3451 * gtk_window_set_icon_list() allows you to pass in the same icon in
3452 * several hand-drawn sizes. The list should contain the natural sizes
3453 * your icon is available in; that is, don't scale the image before
3454 * passing it to GTK+. Scaling is postponed until the last minute,
3455 * when the desired final size is known, to allow best quality.
3457 * By passing several sizes, you may improve the final image quality
3458 * of the icon, by reducing or eliminating automatic image scaling.
3460 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3461 * larger images (64x64, 128x128) if you have them.
3463 * See also gtk_window_set_default_icon_list() to set the icon
3464 * for all windows in your application in one go.
3466 * Note that transient windows (those who have been set transient for another
3467 * window using gtk_window_set_transient_for()) will inherit their
3468 * icon from their transient parent. So there's no need to explicitly
3469 * set the icon on transient windows.
3472 gtk_window_set_icon_list (GtkWindow *window,
3475 GtkWindowIconInfo *info;
3477 g_return_if_fail (GTK_IS_WINDOW (window));
3479 info = ensure_icon_info (window);
3481 if (info->icon_list == list) /* check for NULL mostly */
3484 g_list_foreach (list,
3485 (GFunc) g_object_ref, NULL);
3487 g_list_foreach (info->icon_list,
3488 (GFunc) g_object_unref, NULL);
3490 g_list_free (info->icon_list);
3492 info->icon_list = g_list_copy (list);
3494 g_object_notify (G_OBJECT (window), "icon");
3496 gtk_window_unrealize_icon (window);
3498 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3499 gtk_window_realize_icon (window);
3501 /* We could try to update our transient children, but I don't think
3502 * it's really worth it. If we did it, the best way would probably
3503 * be to have children connect to notify::icon-list
3508 * gtk_window_get_icon_list:
3509 * @window: a #GtkWindow
3511 * Retrieves the list of icons set by gtk_window_set_icon_list().
3512 * The list is copied, but the reference count on each
3513 * member won't be incremented.
3515 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3518 gtk_window_get_icon_list (GtkWindow *window)
3520 GtkWindowIconInfo *info;
3522 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3524 info = get_icon_info (window);
3527 return g_list_copy (info->icon_list);
3533 * gtk_window_set_icon:
3534 * @window: a #GtkWindow
3535 * @icon: (allow-none): icon image, or %NULL
3537 * Sets up the icon representing a #GtkWindow. This icon is used when
3538 * the window is minimized (also known as iconified). Some window
3539 * managers or desktop environments may also place it in the window
3540 * frame, or display it in other contexts.
3542 * The icon should be provided in whatever size it was naturally
3543 * drawn; that is, don't scale the image before passing it to
3544 * GTK+. Scaling is postponed until the last minute, when the desired
3545 * final size is known, to allow best quality.
3547 * If you have your icon hand-drawn in multiple sizes, use
3548 * gtk_window_set_icon_list(). Then the best size will be used.
3550 * This function is equivalent to calling gtk_window_set_icon_list()
3551 * with a 1-element list.
3553 * See also gtk_window_set_default_icon_list() to set the icon
3554 * for all windows in your application in one go.
3557 gtk_window_set_icon (GtkWindow *window,
3562 g_return_if_fail (GTK_IS_WINDOW (window));
3563 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3568 list = g_list_append (list, icon);
3570 gtk_window_set_icon_list (window, list);
3576 update_themed_icon (GtkIconTheme *icon_theme,
3579 g_object_notify (G_OBJECT (window), "icon");
3581 gtk_window_unrealize_icon (window);
3583 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3584 gtk_window_realize_icon (window);
3588 * gtk_window_set_icon_name:
3589 * @window: a #GtkWindow
3590 * @name: (allow-none): the name of the themed icon
3592 * Sets the icon for the window from a named themed icon. See
3593 * the docs for #GtkIconTheme for more details.
3595 * Note that this has nothing to do with the WM_ICON_NAME
3596 * property which is mentioned in the ICCCM.
3601 gtk_window_set_icon_name (GtkWindow *window,
3604 GtkWindowIconInfo *info;
3607 g_return_if_fail (GTK_IS_WINDOW (window));
3609 info = ensure_icon_info (window);
3611 if (g_strcmp0 (info->icon_name, name) == 0)
3614 tmp = info->icon_name;
3615 info->icon_name = g_strdup (name);
3618 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3619 g_list_free (info->icon_list);
3620 info->icon_list = NULL;
3622 update_themed_icon (NULL, window);
3624 g_object_notify (G_OBJECT (window), "icon-name");
3628 * gtk_window_get_icon_name:
3629 * @window: a #GtkWindow
3631 * Returns the name of the themed icon for the window,
3632 * see gtk_window_set_icon_name().
3634 * Returns: the icon name or %NULL if the window has
3640 gtk_window_get_icon_name (GtkWindow *window)
3642 GtkWindowIconInfo *info;
3644 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3646 info = ensure_icon_info (window);
3648 return info->icon_name;
3652 * gtk_window_get_icon:
3653 * @window: a #GtkWindow
3655 * Gets the value set by gtk_window_set_icon() (or if you've
3656 * called gtk_window_set_icon_list(), gets the first icon in
3659 * Return value: (transfer none): icon for window
3662 gtk_window_get_icon (GtkWindow *window)
3664 GtkWindowIconInfo *info;
3666 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3668 info = get_icon_info (window);
3669 if (info && info->icon_list)
3670 return GDK_PIXBUF (info->icon_list->data);
3675 /* Load pixbuf, printing warning on failure if error == NULL
3678 load_pixbuf_verbosely (const char *filename,
3681 GError *local_err = NULL;
3684 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3692 g_warning ("Error loading icon from file '%s':\n\t%s",
3693 filename, local_err->message);
3694 g_error_free (local_err);
3702 * gtk_window_set_icon_from_file:
3703 * @window: a #GtkWindow
3704 * @filename: (type filename): location of icon file
3705 * @err: (allow-none): location to store error, or %NULL.
3707 * Sets the icon for @window.
3708 * Warns on failure if @err is %NULL.
3710 * This function is equivalent to calling gtk_window_set_icon()
3711 * with a pixbuf created by loading the image from @filename.
3713 * Returns: %TRUE if setting the icon succeeded.
3718 gtk_window_set_icon_from_file (GtkWindow *window,
3719 const gchar *filename,
3722 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3726 gtk_window_set_icon (window, pixbuf);
3727 g_object_unref (pixbuf);
3736 * gtk_window_set_default_icon_list:
3737 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3739 * Sets an icon list to be used as fallback for windows that haven't
3740 * had gtk_window_set_icon_list() called on them to set up a
3741 * window-specific icon list. This function allows you to set up the
3742 * icon for all windows in your app at once.
3744 * See gtk_window_set_icon_list() for more details.
3748 gtk_window_set_default_icon_list (GList *list)
3752 if (list == default_icon_list)
3755 /* Update serial so we don't used cached pixmaps/masks
3757 default_icon_serial++;
3759 g_list_foreach (list,
3760 (GFunc) g_object_ref, NULL);
3762 g_list_foreach (default_icon_list,
3763 (GFunc) g_object_unref, NULL);
3765 g_list_free (default_icon_list);
3767 default_icon_list = g_list_copy (list);
3769 /* Update all toplevels */
3770 toplevels = gtk_window_list_toplevels ();
3771 tmp_list = toplevels;
3772 while (tmp_list != NULL)
3774 GtkWindowIconInfo *info;
3775 GtkWindow *w = tmp_list->data;
3777 info = get_icon_info (w);
3778 if (info && info->using_default_icon)
3780 gtk_window_unrealize_icon (w);
3781 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3782 gtk_window_realize_icon (w);
3785 tmp_list = tmp_list->next;
3787 g_list_free (toplevels);
3791 * gtk_window_set_default_icon:
3794 * Sets an icon to be used as fallback for windows that haven't
3795 * had gtk_window_set_icon() called on them from a pixbuf.
3800 gtk_window_set_default_icon (GdkPixbuf *icon)
3804 g_return_if_fail (GDK_IS_PIXBUF (icon));
3806 list = g_list_prepend (NULL, icon);
3807 gtk_window_set_default_icon_list (list);
3812 * gtk_window_set_default_icon_name:
3813 * @name: the name of the themed icon
3815 * Sets an icon to be used as fallback for windows that haven't
3816 * had gtk_window_set_icon_list() called on them from a named
3817 * themed icon, see gtk_window_set_icon_name().
3822 gtk_window_set_default_icon_name (const gchar *name)
3827 /* Update serial so we don't used cached pixmaps/masks
3829 default_icon_serial++;
3831 g_free (default_icon_name);
3832 default_icon_name = g_strdup (name);
3834 g_list_foreach (default_icon_list,
3835 (GFunc) g_object_unref, NULL);
3837 g_list_free (default_icon_list);
3838 default_icon_list = NULL;
3840 /* Update all toplevels */
3841 toplevels = gtk_window_list_toplevels ();
3842 tmp_list = toplevels;
3843 while (tmp_list != NULL)
3845 GtkWindowIconInfo *info;
3846 GtkWindow *w = tmp_list->data;
3848 info = get_icon_info (w);
3849 if (info && info->using_default_icon && info->using_themed_icon)
3851 gtk_window_unrealize_icon (w);
3852 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3853 gtk_window_realize_icon (w);
3856 tmp_list = tmp_list->next;
3858 g_list_free (toplevels);
3862 * gtk_window_get_default_icon_name:
3864 * Returns the fallback icon name for windows that has been set
3865 * with gtk_window_set_default_icon_name(). The returned
3866 * string is owned by GTK+ and should not be modified. It
3867 * is only valid until the next call to
3868 * gtk_window_set_default_icon_name().
3870 * Returns: the fallback icon name for windows
3875 gtk_window_get_default_icon_name (void)
3877 return default_icon_name;
3881 * gtk_window_set_default_icon_from_file:
3882 * @filename: (type filename): location of icon file
3883 * @err: (allow-none): location to store error, or %NULL.
3885 * Sets an icon to be used as fallback for windows that haven't
3886 * had gtk_window_set_icon_list() called on them from a file
3887 * on disk. Warns on failure if @err is %NULL.
3889 * Returns: %TRUE if setting the icon succeeded.
3894 gtk_window_set_default_icon_from_file (const gchar *filename,
3897 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3901 gtk_window_set_default_icon (pixbuf);
3902 g_object_unref (pixbuf);
3911 * gtk_window_get_default_icon_list:
3913 * Gets the value set by gtk_window_set_default_icon_list().
3914 * The list is a copy and should be freed with g_list_free(),
3915 * but the pixbufs in the list have not had their reference count
3918 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3921 gtk_window_get_default_icon_list (void)
3923 return g_list_copy (default_icon_list);
3927 gtk_window_set_default_size_internal (GtkWindow *window,
3928 gboolean change_width,
3930 gboolean change_height,
3932 gboolean is_geometry)
3934 GtkWindowGeometryInfo *info;
3936 g_return_if_fail (change_width == FALSE || width >= -1);
3937 g_return_if_fail (change_height == FALSE || height >= -1);
3939 info = gtk_window_get_geometry_info (window, TRUE);
3941 g_object_freeze_notify (G_OBJECT (window));
3943 info->default_is_geometry = is_geometry != FALSE;
3953 info->default_width = width;
3955 g_object_notify (G_OBJECT (window), "default-width");
3966 info->default_height = height;
3968 g_object_notify (G_OBJECT (window), "default-height");
3971 g_object_thaw_notify (G_OBJECT (window));
3973 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3977 * gtk_window_set_default_size:
3978 * @window: a #GtkWindow
3979 * @width: width in pixels, or -1 to unset the default width
3980 * @height: height in pixels, or -1 to unset the default height
3982 * Sets the default size of a window. If the window's "natural" size
3983 * (its size request) is larger than the default, the default will be
3984 * ignored. More generally, if the default size does not obey the
3985 * geometry hints for the window (gtk_window_set_geometry_hints() can
3986 * be used to set these explicitly), the default size will be clamped
3987 * to the nearest permitted size.
3989 * Unlike gtk_widget_set_size_request(), which sets a size request for
3990 * a widget and thus would keep users from shrinking the window, this
3991 * function only sets the initial size, just as if the user had
3992 * resized the window themselves. Users can still shrink the window
3993 * again as they normally would. Setting a default size of -1 means to
3994 * use the "natural" default size (the size request of the window).
3996 * For more control over a window's initial size and how resizing works,
3997 * investigate gtk_window_set_geometry_hints().
3999 * For some uses, gtk_window_resize() is a more appropriate function.
4000 * gtk_window_resize() changes the current size of the window, rather
4001 * than the size to be used on initial display. gtk_window_resize() always
4002 * affects the window itself, not the geometry widget.
4004 * The default size of a window only affects the first time a window is
4005 * shown; if a window is hidden and re-shown, it will remember the size
4006 * it had prior to hiding, rather than using the default size.
4008 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4009 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4012 gtk_window_set_default_size (GtkWindow *window,
4016 g_return_if_fail (GTK_IS_WINDOW (window));
4017 g_return_if_fail (width >= -1);
4018 g_return_if_fail (height >= -1);
4020 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4024 * gtk_window_set_default_geometry:
4025 * @window: a #GtkWindow
4026 * @width: width in resize increments, or -1 to unset the default width
4027 * @height: height in resize increments, or -1 to unset the default height
4029 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4030 * in terms of the base size and increment set with
4031 * gtk_window_set_geometry_hints.
4036 gtk_window_set_default_geometry (GtkWindow *window,
4040 g_return_if_fail (GTK_IS_WINDOW (window));
4041 g_return_if_fail (width >= -1);
4042 g_return_if_fail (height >= -1);
4044 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4048 * gtk_window_get_default_size:
4049 * @window: a #GtkWindow
4050 * @width: (out) (allow-none): location to store the default width, or %NULL
4051 * @height: (out) (allow-none): location to store the default height, or %NULL
4053 * Gets the default size of the window. A value of -1 for the width or
4054 * height indicates that a default size has not been explicitly set
4055 * for that dimension, so the "natural" size of the window will be
4060 gtk_window_get_default_size (GtkWindow *window,
4064 GtkWindowGeometryInfo *info;
4066 g_return_if_fail (GTK_IS_WINDOW (window));
4068 info = gtk_window_get_geometry_info (window, FALSE);
4071 *width = info ? info->default_width : -1;
4074 *height = info ? info->default_height : -1;
4078 * gtk_window_resize:
4079 * @window: a #GtkWindow
4080 * @width: width in pixels to resize the window to
4081 * @height: height in pixels to resize the window to
4083 * Resizes the window as if the user had done so, obeying geometry
4084 * constraints. The default geometry constraint is that windows may
4085 * not be smaller than their size request; to override this
4086 * constraint, call gtk_widget_set_size_request() to set the window's
4087 * request to a smaller value.
4089 * If gtk_window_resize() is called before showing a window for the
4090 * first time, it overrides any default size set with
4091 * gtk_window_set_default_size().
4093 * Windows may not be resized smaller than 1 by 1 pixels.
4097 gtk_window_resize (GtkWindow *window,
4101 GtkWindowGeometryInfo *info;
4103 g_return_if_fail (GTK_IS_WINDOW (window));
4104 g_return_if_fail (width > 0);
4105 g_return_if_fail (height > 0);
4107 info = gtk_window_get_geometry_info (window, TRUE);
4109 info->resize_width = width;
4110 info->resize_height = height;
4111 info->resize_is_geometry = FALSE;
4113 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4117 * gtk_window_resize_to_geometry:
4118 * @window: a #GtkWindow
4119 * @width: width in resize increments to resize the window to
4120 * @height: height in resize increments to resize the window to
4122 * Like gtk_window_resize(), but @width and @height are interpreted
4123 * in terms of the base size and increment set with
4124 * gtk_window_set_geometry_hints.
4129 gtk_window_resize_to_geometry (GtkWindow *window,
4133 GtkWindowGeometryInfo *info;
4135 g_return_if_fail (GTK_IS_WINDOW (window));
4136 g_return_if_fail (width > 0);
4137 g_return_if_fail (height > 0);
4139 info = gtk_window_get_geometry_info (window, TRUE);
4141 info->resize_width = width;
4142 info->resize_height = height;
4143 info->resize_is_geometry = TRUE;
4145 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4149 * gtk_window_get_size:
4150 * @window: a #GtkWindow
4151 * @width: (out) (allow-none): return location for width, or %NULL
4152 * @height: (out) (allow-none): return location for height, or %NULL
4154 * Obtains the current size of @window. If @window is not onscreen,
4155 * it returns the size GTK+ will suggest to the <link
4156 * linkend="gtk-X11-arch">window manager</link> for the initial window
4157 * size (but this is not reliably the same as the size the window
4158 * manager will actually select). The size obtained by
4159 * gtk_window_get_size() is the last size received in a
4160 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4161 * rather than querying the X server for the size. As a result, if you
4162 * call gtk_window_resize() then immediately call
4163 * gtk_window_get_size(), the size won't have taken effect yet. After
4164 * the window manager processes the resize request, GTK+ receives
4165 * notification that the size has changed via a configure event, and
4166 * the size of the window gets updated.
4168 * Note 1: Nearly any use of this function creates a race condition,
4169 * because the size of the window may change between the time that you
4170 * get the size and the time that you perform some action assuming
4171 * that size is the current size. To avoid race conditions, connect to
4172 * "configure-event" on the window and adjust your size-dependent
4173 * state to match the size delivered in the #GdkEventConfigure.
4175 * Note 2: The returned size does <emphasis>not</emphasis> include the
4176 * size of the window manager decorations (aka the window frame or
4177 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4178 * method of determining their size.
4180 * Note 3: If you are getting a window size in order to position
4181 * the window onscreen, there may be a better way. The preferred
4182 * way is to simply set the window's semantic type with
4183 * gtk_window_set_type_hint(), which allows the window manager to
4184 * e.g. center dialogs. Also, if you set the transient parent of
4185 * dialogs with gtk_window_set_transient_for() window managers
4186 * will often center the dialog over its parent window. It's
4187 * much preferred to let the window manager handle these
4188 * things rather than doing it yourself, because all apps will
4189 * behave consistently and according to user prefs if the window
4190 * manager handles it. Also, the window manager can take the size
4191 * of the window decorations/border into account, while your
4192 * application cannot.
4194 * In any case, if you insist on application-specified window
4195 * positioning, there's <emphasis>still</emphasis> a better way than
4196 * doing it yourself - gtk_window_set_position() will frequently
4197 * handle the details for you.
4201 gtk_window_get_size (GtkWindow *window,
4207 g_return_if_fail (GTK_IS_WINDOW (window));
4209 if (width == NULL && height == NULL)
4212 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4214 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4215 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4219 GdkRectangle configure_request;
4221 gtk_window_compute_configure_request (window,
4225 w = configure_request.width;
4226 h = configure_request.height;
4237 * @window: a #GtkWindow
4238 * @x: X coordinate to move window to
4239 * @y: Y coordinate to move window to
4241 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4242 * @window to the given position. Window managers are free to ignore
4243 * this; most window managers ignore requests for initial window
4244 * positions (instead using a user-defined placement algorithm) and
4245 * honor requests after the window has already been shown.
4247 * Note: the position is the position of the gravity-determined
4248 * reference point for the window. The gravity determines two things:
4249 * first, the location of the reference point in root window
4250 * coordinates; and second, which point on the window is positioned at
4251 * the reference point.
4253 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4254 * point is simply the @x, @y supplied to gtk_window_move(). The
4255 * top-left corner of the window decorations (aka window frame or
4256 * border) will be placed at @x, @y. Therefore, to position a window
4257 * at the top left of the screen, you want to use the default gravity
4258 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4260 * To position a window at the bottom right corner of the screen, you
4261 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4262 * point is at @x + the window width and @y + the window height, and
4263 * the bottom-right corner of the window border will be placed at that
4264 * reference point. So, to place a window in the bottom right corner
4265 * you would first set gravity to south east, then write:
4266 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4267 * gdk_screen_height () - window_height)</literal> (note that this
4268 * example does not take multi-head scenarios into account).
4270 * The Extended Window Manager Hints specification at <ulink
4271 * url="http://www.freedesktop.org/Standards/wm-spec">
4272 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4273 * nice table of gravities in the "implementation notes" section.
4275 * The gtk_window_get_position() documentation may also be relevant.
4278 gtk_window_move (GtkWindow *window,
4282 GtkWindowGeometryInfo *info;
4285 g_return_if_fail (GTK_IS_WINDOW (window));
4287 widget = GTK_WIDGET (window);
4289 info = gtk_window_get_geometry_info (window, TRUE);
4291 if (gtk_widget_get_mapped (widget))
4293 GtkAllocation allocation;
4295 gtk_widget_get_allocation (widget, &allocation);
4297 /* we have now sent a request with this position
4298 * with currently-active constraints, so toggle flag.
4300 info->position_constraints_changed = FALSE;
4302 /* we only constrain if mapped - if not mapped,
4303 * then gtk_window_compute_configure_request()
4304 * will apply the constraints later, and we
4305 * don't want to lose information about
4306 * what position the user set before then.
4307 * i.e. if you do a move() then turn off POS_CENTER
4308 * then show the window, your move() will work.
4310 gtk_window_constrain_position (window,
4311 allocation.width, allocation.height,
4314 /* Note that this request doesn't go through our standard request
4315 * framework, e.g. doesn't increment configure_request_count,
4316 * doesn't set info->last, etc.; that's because
4317 * we don't save the info needed to arrive at this same request
4320 * To gtk_window_move_resize(), this will end up looking exactly
4321 * the same as the position being changed by the window
4324 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4328 /* Save this position to apply on mapping */
4329 info->initial_x = x;
4330 info->initial_y = y;
4331 info->initial_pos_set = TRUE;
4336 * gtk_window_get_position:
4337 * @window: a #GtkWindow
4338 * @root_x: (out) (allow-none): eturn location for X coordinate of
4339 * gravity-determined reference point, or %NULL
4340 * @root_y: (out) (allow-none): return location for Y coordinate of
4341 * gravity-determined reference point, or %NULL
4343 * This function returns the position you need to pass to
4344 * gtk_window_move() to keep @window in its current position.
4345 * This means that the meaning of the returned value varies with
4346 * window gravity. See gtk_window_move() for more details.
4348 * If you haven't changed the window gravity, its gravity will be
4349 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4350 * gets the position of the top-left corner of the window manager
4351 * frame for the window. gtk_window_move() sets the position of this
4352 * same top-left corner.
4354 * gtk_window_get_position() is not 100% reliable because the X Window System
4355 * does not specify a way to obtain the geometry of the
4356 * decorations placed on a window by the window manager.
4357 * Thus GTK+ is using a "best guess" that works with most
4360 * Moreover, nearly all window managers are historically broken with
4361 * respect to their handling of window gravity. So moving a window to
4362 * its current position as returned by gtk_window_get_position() tends
4363 * to result in moving the window slightly. Window managers are
4364 * slowly getting better over time.
4366 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4367 * frame is not relevant, and thus gtk_window_get_position() will
4368 * always produce accurate results. However you can't use static
4369 * gravity to do things like place a window in a corner of the screen,
4370 * because static gravity ignores the window manager decorations.
4372 * If you are saving and restoring your application's window
4373 * positions, you should know that it's impossible for applications to
4374 * do this without getting it somewhat wrong because applications do
4375 * not have sufficient knowledge of window manager state. The Correct
4376 * Mechanism is to support the session management protocol (see the
4377 * "GnomeClient" object in the GNOME libraries for example) and allow
4378 * the window manager to save your window sizes and positions.
4383 gtk_window_get_position (GtkWindow *window,
4387 GtkWindowPrivate *priv;
4389 GdkWindow *gdk_window;
4391 g_return_if_fail (GTK_IS_WINDOW (window));
4393 priv = window->priv;
4394 widget = GTK_WIDGET (window);
4395 gdk_window = gtk_widget_get_window (widget);
4397 if (priv->gravity == GDK_GRAVITY_STATIC)
4399 if (gtk_widget_get_mapped (widget))
4401 /* This does a server round-trip, which is sort of wrong;
4402 * but a server round-trip is inevitable for
4403 * gdk_window_get_frame_extents() in the usual
4404 * NorthWestGravity case below, so not sure what else to
4405 * do. We should likely be consistent about whether we get
4406 * the client-side info or the server-side info.
4408 gdk_window_get_origin (gdk_window, root_x, root_y);
4412 GdkRectangle configure_request;
4414 gtk_window_compute_configure_request (window,
4418 *root_x = configure_request.x;
4419 *root_y = configure_request.y;
4424 GdkRectangle frame_extents;
4429 if (gtk_widget_get_mapped (widget))
4431 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4432 x = frame_extents.x;
4433 y = frame_extents.y;
4434 gtk_window_get_size (window, &w, &h);
4438 /* We just say the frame has 0 size on all sides.
4439 * Not sure what else to do.
4441 gtk_window_compute_configure_request (window,
4444 x = frame_extents.x;
4445 y = frame_extents.y;
4446 w = frame_extents.width;
4447 h = frame_extents.height;
4450 switch (priv->gravity)
4452 case GDK_GRAVITY_NORTH:
4453 case GDK_GRAVITY_CENTER:
4454 case GDK_GRAVITY_SOUTH:
4455 /* Find center of frame. */
4456 x += frame_extents.width / 2;
4457 /* Center client window on that point. */
4461 case GDK_GRAVITY_SOUTH_EAST:
4462 case GDK_GRAVITY_EAST:
4463 case GDK_GRAVITY_NORTH_EAST:
4464 /* Find right edge of frame */
4465 x += frame_extents.width;
4466 /* Align left edge of client at that point. */
4473 switch (priv->gravity)
4475 case GDK_GRAVITY_WEST:
4476 case GDK_GRAVITY_CENTER:
4477 case GDK_GRAVITY_EAST:
4478 /* Find center of frame. */
4479 y += frame_extents.height / 2;
4480 /* Center client window there. */
4483 case GDK_GRAVITY_SOUTH_WEST:
4484 case GDK_GRAVITY_SOUTH:
4485 case GDK_GRAVITY_SOUTH_EAST:
4486 /* Find south edge of frame */
4487 y += frame_extents.height;
4488 /* Place bottom edge of client there */
4503 * gtk_window_reshow_with_initial_size:
4504 * @window: a #GtkWindow
4506 * Hides @window, then reshows it, resetting the
4507 * default size and position of the window. Used
4508 * by GUI builders only.
4511 gtk_window_reshow_with_initial_size (GtkWindow *window)
4515 g_return_if_fail (GTK_IS_WINDOW (window));
4517 widget = GTK_WIDGET (window);
4519 gtk_widget_hide (widget);
4520 gtk_widget_unrealize (widget);
4521 gtk_widget_show (widget);
4525 gtk_window_destroy (GtkWidget *widget)
4527 GtkWindow *window = GTK_WINDOW (widget);
4528 GtkWindowPrivate *priv = window->priv;
4530 gtk_window_release_application (window);
4532 toplevel_list = g_slist_remove (toplevel_list, window);
4534 if (priv->transient_parent)
4535 gtk_window_set_transient_for (window, NULL);
4537 /* frees the icons */
4538 gtk_window_set_icon_list (window, NULL);
4540 if (priv->has_user_ref_count)
4542 priv->has_user_ref_count = FALSE;
4543 g_object_unref (window);
4547 gtk_window_group_remove_window (priv->group, window);
4549 gtk_window_free_key_hash (window);
4551 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4555 gtk_window_finalize (GObject *object)
4557 GtkWindow *window = GTK_WINDOW (object);
4558 GtkWindowPrivate *priv = window->priv;
4559 GtkMnemonicHash *mnemonic_hash;
4561 g_free (priv->title);
4562 g_free (priv->wmclass_name);
4563 g_free (priv->wmclass_class);
4564 g_free (priv->wm_role);
4565 gtk_window_release_application (window);
4567 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4569 _gtk_mnemonic_hash_free (mnemonic_hash);
4571 if (priv->geometry_info)
4573 if (priv->geometry_info->widget)
4574 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4575 gtk_widget_destroyed,
4576 &priv->geometry_info->widget);
4577 g_free (priv->geometry_info);
4580 if (priv->keys_changed_handler)
4582 g_source_remove (priv->keys_changed_handler);
4583 priv->keys_changed_handler = 0;
4587 g_signal_handlers_disconnect_by_func (priv->screen,
4588 gtk_window_on_composited_changed, window);
4590 g_free (priv->startup_id);
4592 #ifdef GDK_WINDOWING_X11
4593 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4594 gtk_window_on_theme_variant_changed,
4598 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4602 gtk_window_show (GtkWidget *widget)
4604 GtkWindow *window = GTK_WINDOW (widget);
4605 GtkWindowPrivate *priv = window->priv;
4606 GtkContainer *container = GTK_CONTAINER (window);
4607 gboolean need_resize;
4610 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4612 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4616 _gtk_widget_set_visible_flag (widget, TRUE);
4618 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4619 _gtk_container_set_need_resize (container, FALSE);
4623 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4624 GtkAllocation allocation = { 0, 0 };
4625 GdkRectangle configure_request;
4626 GdkGeometry new_geometry;
4628 gboolean was_realized;
4630 /* We are going to go ahead and perform this configure request
4631 * and then emulate a configure notify by going ahead and
4632 * doing a size allocate. Sort of a synchronous
4633 * mini-copy of gtk_window_move_resize() here.
4635 gtk_window_compute_configure_request (window,
4640 /* We update this because we are going to go ahead
4641 * and gdk_window_resize() below, rather than
4644 info->last.configure_request.width = configure_request.width;
4645 info->last.configure_request.height = configure_request.height;
4647 /* and allocate the window - this is normally done
4648 * in move_resize in response to configure notify
4650 allocation.width = configure_request.width;
4651 allocation.height = configure_request.height;
4652 gtk_widget_size_allocate (widget, &allocation);
4654 /* Then we guarantee we have a realize */
4655 was_realized = FALSE;
4656 if (!gtk_widget_get_realized (widget))
4658 gtk_widget_realize (widget);
4659 was_realized = TRUE;
4662 /* We only send configure request if we didn't just finish
4663 * creating the window; if we just created the window
4664 * then we created it with widget->allocation anyhow.
4667 gdk_window_move_resize (gtk_widget_get_window (widget),
4668 configure_request.x,
4669 configure_request.y,
4670 configure_request.width,
4671 configure_request.height);
4674 gtk_container_check_resize (container);
4676 gtk_widget_map (widget);
4678 /* Try to make sure that we have some focused widget
4680 #ifdef GDK_WINDOWING_X11
4681 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4682 GTK_IS_PLUG (window);
4686 if (!priv->focus_widget && !is_plug)
4687 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4690 gtk_grab_add (widget);
4694 gtk_window_hide (GtkWidget *widget)
4696 GtkWindow *window = GTK_WINDOW (widget);
4697 GtkWindowPrivate *priv = window->priv;
4699 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4701 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4705 _gtk_widget_set_visible_flag (widget, FALSE);
4706 gtk_widget_unmap (widget);
4709 gtk_grab_remove (widget);
4713 gtk_window_map (GtkWidget *widget)
4716 GtkWindow *window = GTK_WINDOW (widget);
4717 GtkWindowPrivate *priv = window->priv;
4718 GdkWindow *gdk_window;
4719 gboolean auto_mnemonics;
4720 GtkPolicyType visible_focus;
4722 if (!gtk_widget_is_toplevel (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 gdk_window = gtk_widget_get_window (widget);
4738 if (priv->maximize_initially)
4739 gdk_window_maximize (gdk_window);
4741 gdk_window_unmaximize (gdk_window);
4743 if (priv->stick_initially)
4744 gdk_window_stick (gdk_window);
4746 gdk_window_unstick (gdk_window);
4748 if (priv->iconify_initially)
4749 gdk_window_iconify (gdk_window);
4751 gdk_window_deiconify (gdk_window);
4753 if (priv->fullscreen_initially)
4754 gdk_window_fullscreen (gdk_window);
4756 gdk_window_unfullscreen (gdk_window);
4758 gdk_window_set_keep_above (gdk_window, priv->above_initially);
4760 gdk_window_set_keep_below (gdk_window, 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);
4823 ensure_state_flag_window_unfocused (widget);
4827 gtk_window_map_event (GtkWidget *widget,
4830 if (!gtk_widget_get_mapped (widget))
4832 /* we should be be unmapped, but are getting a MapEvent, this may happen
4833 * to toplevel XWindows if mapping was intercepted by a window manager
4834 * and an unmap request occoured while the MapRequestEvent was still
4835 * being handled. we work around this situaiton here by re-requesting
4836 * the window being unmapped. more details can be found in:
4837 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4839 gdk_window_hide (gtk_widget_get_window (widget));
4845 gtk_window_unmap (GtkWidget *widget)
4847 GtkWindow *window = GTK_WINDOW (widget);
4848 GtkWindowPrivate *priv = window->priv;
4850 GtkWindowGeometryInfo *info;
4851 GdkWindow *gdk_window;
4852 GdkWindowState state;
4854 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4856 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
4860 gdk_window = gtk_widget_get_window (widget);
4862 gtk_widget_set_mapped (widget, FALSE);
4863 gdk_window_withdraw (gdk_window);
4865 priv->configure_request_count = 0;
4866 priv->configure_notify_received = FALSE;
4868 /* on unmap, we reset the default positioning of the window,
4869 * so it's placed again, but we don't reset the default
4870 * size of the window, so it's remembered.
4872 priv->need_default_position = TRUE;
4874 info = gtk_window_get_geometry_info (window, FALSE);
4877 info->initial_pos_set = FALSE;
4878 info->position_constraints_changed = FALSE;
4881 state = gdk_window_get_state (gdk_window);
4882 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4883 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4884 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4885 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4886 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4888 child = gtk_bin_get_child (&(window->bin));
4890 gtk_widget_unmap (child);
4893 /* (Note: Replace "size" with "width" or "height". Also, the request
4894 * mode is honoured.)
4895 * For selecting the default window size, the following conditions
4896 * should hold (in order of importance):
4897 * - the size is not below the minimum size
4898 * Windows cannot be resized below their minimum size, so we must
4899 * ensure we don't do that either.
4900 * - the size is not above the natural size
4901 * It seems weird to allocate more than this in an initial guess.
4902 * - the size does not exceed that of a maximized window
4903 * We want to see the whole window after all.
4904 * (Note that this may not be possible to achieve due to imperfect
4905 * information from the windowing system.)
4908 /* We use these for now to not make windows too big by accident. Note
4909 * that we still clamp these numbers by screen size. Also note that
4910 * minimum size still overrides this. So keep your windows small! :)
4912 #define MAX_DEFAULT_WINDOW_WIDTH 640
4913 #define MAX_DEFAULT_WINDOW_HEIGHT 480
4916 gtk_window_guess_default_size (GtkWindow *window,
4920 GtkWidget *widget = GTK_WIDGET (window);
4922 int minimum, natural;
4924 screen = gtk_widget_get_screen (widget);
4926 *width = gdk_screen_get_width (screen);
4927 *height = gdk_screen_get_height (screen);
4929 if (*width >= *height)
4932 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
4933 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
4938 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
4939 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
4942 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
4944 gtk_widget_get_preferred_height (widget, &minimum, &natural);
4945 *height = MAX (minimum, MIN (*height, natural));
4947 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
4948 *width = MAX (minimum, MIN (*width, natural));
4950 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
4952 gtk_widget_get_preferred_width (widget, &minimum, &natural);
4953 *width = MAX (minimum, MIN (*width, natural));
4955 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
4956 *height = MAX (minimum, MIN (*height, natural));
4961 gtk_window_realize (GtkWidget *widget)
4963 GtkAllocation allocation;
4965 GdkWindow *parent_window;
4966 GdkWindow *gdk_window;
4967 GdkWindowAttr attributes;
4968 gint attributes_mask;
4969 GtkWindowPrivate *priv;
4970 GtkStyleContext *context;
4972 window = GTK_WINDOW (widget);
4973 priv = window->priv;
4975 gtk_widget_get_allocation (widget, &allocation);
4977 if (gtk_widget_get_parent_window (widget))
4979 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
4981 gtk_widget_set_realized (widget, TRUE);
4983 attributes.x = allocation.x;
4984 attributes.y = allocation.y;
4985 attributes.width = allocation.width;
4986 attributes.height = allocation.height;
4987 attributes.window_type = GDK_WINDOW_CHILD;
4989 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
4991 attributes.visual = gtk_widget_get_visual (widget);
4992 attributes.wclass = GDK_INPUT_OUTPUT;
4994 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
4996 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
4997 &attributes, attributes_mask);
4998 gtk_widget_set_window (widget, gdk_window);
4999 gdk_window_set_user_data (gdk_window, widget);
5001 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
5003 gdk_window_enable_synchronized_configure (gdk_window);
5007 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5009 /* ensure widget tree is properly size allocated */
5010 if (allocation.x == -1 &&
5011 allocation.y == -1 &&
5012 allocation.width == 1 &&
5013 allocation.height == 1)
5019 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5020 if (allocation.width == 0 || allocation.height == 0)
5022 /* non-empty window */
5023 allocation.width = 200;
5024 allocation.height = 200;
5026 gtk_widget_size_allocate (widget, &allocation);
5028 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5030 g_return_if_fail (!gtk_widget_get_realized (widget));
5033 gtk_widget_set_realized (widget, TRUE);
5037 case GTK_WINDOW_TOPLEVEL:
5038 attributes.window_type = GDK_WINDOW_TOPLEVEL;
5040 case GTK_WINDOW_POPUP:
5041 attributes.window_type = GDK_WINDOW_TEMP;
5044 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5048 attributes.title = priv->title;
5049 attributes.wmclass_name = priv->wmclass_name;
5050 attributes.wmclass_class = priv->wmclass_class;
5051 attributes.wclass = GDK_INPUT_OUTPUT;
5052 attributes.visual = gtk_widget_get_visual (widget);
5054 attributes_mask = 0;
5055 parent_window = gtk_widget_get_root_window (widget);
5057 gtk_widget_get_allocation (widget, &allocation);
5058 attributes.width = allocation.width;
5059 attributes.height = allocation.height;
5060 attributes.event_mask = gtk_widget_get_events (widget);
5061 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5062 GDK_KEY_PRESS_MASK |
5063 GDK_KEY_RELEASE_MASK |
5064 GDK_ENTER_NOTIFY_MASK |
5065 GDK_LEAVE_NOTIFY_MASK |
5066 GDK_FOCUS_CHANGE_MASK |
5067 GDK_STRUCTURE_MASK);
5068 attributes.type_hint = priv->type_hint;
5070 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5071 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5072 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5074 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5075 gtk_widget_set_window (widget, gdk_window);
5077 if (priv->opacity_set)
5078 gdk_window_set_opacity (gdk_window, priv->opacity);
5080 gdk_window_enable_synchronized_configure (gdk_window);
5082 gdk_window_set_user_data (gdk_window, window);
5084 context = gtk_widget_get_style_context (widget);
5085 gtk_style_context_set_background (context, gdk_window);
5088 if (priv->transient_parent &&
5089 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5090 gdk_window_set_transient_for (gdk_window,
5091 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5094 gdk_window_set_role (gdk_window, priv->wm_role);
5096 if (!priv->decorated)
5097 gdk_window_set_decorations (gdk_window, 0);
5099 if (!priv->deletable)
5100 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5102 if (gtk_window_get_skip_pager_hint (window))
5103 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5105 if (gtk_window_get_skip_taskbar_hint (window))
5106 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5108 if (gtk_window_get_accept_focus (window))
5109 gdk_window_set_accept_focus (gdk_window, TRUE);
5111 gdk_window_set_accept_focus (gdk_window, FALSE);
5113 if (gtk_window_get_focus_on_map (window))
5114 gdk_window_set_focus_on_map (gdk_window, TRUE);
5116 gdk_window_set_focus_on_map (gdk_window, FALSE);
5119 gdk_window_set_modal_hint (gdk_window, TRUE);
5121 gdk_window_set_modal_hint (gdk_window, FALSE);
5123 if (priv->startup_id)
5125 #ifdef GDK_WINDOWING_X11
5126 if (GDK_IS_X11_WINDOW (gdk_window))
5128 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5129 if (timestamp != GDK_CURRENT_TIME)
5130 gdk_x11_window_set_user_time (gdk_window, timestamp);
5133 if (!startup_id_is_fake (priv->startup_id))
5134 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5137 #ifdef GDK_WINDOWING_X11
5138 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5140 if (GDK_IS_X11_WINDOW (gdk_window))
5141 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5146 gtk_window_realize_icon (window);
5148 if (priv->has_resize_grip)
5149 resize_grip_create_window (window);
5153 gtk_window_unrealize (GtkWidget *widget)
5155 GtkWindow *window = GTK_WINDOW (widget);
5156 GtkWindowPrivate *priv = window->priv;
5157 GtkWindowGeometryInfo *info;
5159 /* On unrealize, we reset the size of the window such
5160 * that we will re-apply the default sizing stuff
5161 * next time we show the window.
5163 * Default positioning is reset on unmap, instead of unrealize.
5165 priv->need_default_size = TRUE;
5166 info = gtk_window_get_geometry_info (window, FALSE);
5169 info->resize_width = -1;
5170 info->resize_height = -1;
5171 info->last.configure_request.x = 0;
5172 info->last.configure_request.y = 0;
5173 info->last.configure_request.width = -1;
5174 info->last.configure_request.height = -1;
5175 /* be sure we reset geom hints on re-realize */
5176 info->last.flags = 0;
5180 gtk_window_unrealize_icon (window);
5182 if (priv->grip_window != NULL)
5183 resize_grip_destroy_window (window);
5185 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5188 static GtkJunctionSides
5189 get_grip_junction (GtkWidget *widget)
5191 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5192 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5194 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5198 get_drag_edge (GtkWidget *widget,
5199 GdkWindowEdge *edge)
5201 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5202 gboolean hresizable;
5203 gboolean vresizable;
5204 GtkTextDirection dir;
5205 GtkWindowGeometryInfo *info;
5210 info = priv->geometry_info;
5213 GdkWindowHints flags = info->last.flags;
5214 GdkGeometry *geometry = &info->last.geometry;
5216 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5218 hresizable = geometry->min_width < geometry->max_width;
5219 vresizable = geometry->min_height < geometry->max_height;
5223 dir = gtk_widget_get_direction (widget);
5225 if (hresizable && vresizable)
5226 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5227 else if (hresizable)
5228 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5229 else if (vresizable)
5230 *edge = GDK_WINDOW_EDGE_SOUTH;
5238 set_grip_cursor (GtkWindow *window)
5240 GtkWidget *widget = GTK_WIDGET (window);
5241 GtkWindowPrivate *priv = window->priv;
5243 if (priv->grip_window == NULL)
5246 if (gtk_widget_is_sensitive (widget))
5249 GdkDisplay *display;
5250 GdkCursorType cursor_type;
5253 cursor_type = GDK_LEFT_PTR;
5255 if (get_drag_edge (widget, &edge))
5259 case GDK_WINDOW_EDGE_EAST:
5260 cursor_type = GDK_RIGHT_SIDE;
5262 case GDK_WINDOW_EDGE_SOUTH_EAST:
5263 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5265 case GDK_WINDOW_EDGE_SOUTH:
5266 cursor_type = GDK_BOTTOM_SIDE;
5268 case GDK_WINDOW_EDGE_SOUTH_WEST:
5269 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5271 case GDK_WINDOW_EDGE_WEST:
5272 cursor_type = GDK_LEFT_SIDE;
5278 display = gtk_widget_get_display (widget);
5279 cursor = gdk_cursor_new_for_display (display, cursor_type);
5280 gdk_window_set_cursor (priv->grip_window, cursor);
5281 g_object_unref (cursor);
5284 gdk_window_set_cursor (priv->grip_window, NULL);
5288 set_grip_shape (GtkWindow *window)
5290 GtkWindowPrivate *priv = window->priv;
5291 cairo_region_t *region;
5292 cairo_surface_t *surface;
5294 double width, height;
5296 if (priv->grip_window == NULL)
5299 width = gdk_window_get_width (priv->grip_window);
5300 height = gdk_window_get_height (priv->grip_window);
5301 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5303 cr = cairo_create (surface);
5304 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5306 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5307 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5309 cairo_move_to (cr, width, 0.0);
5310 cairo_line_to (cr, width, height);
5311 cairo_line_to (cr, 0.0, height);
5315 cairo_move_to (cr, 0.0, 0.0);
5316 cairo_line_to (cr, width, height);
5317 cairo_line_to (cr, 0.0, height);
5319 cairo_close_path (cr);
5322 region = gdk_cairo_region_create_from_surface (surface);
5323 cairo_surface_destroy (surface);
5325 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5326 cairo_region_destroy (region);
5330 set_grip_position (GtkWindow *window)
5332 GtkWindowPrivate *priv = window->priv;
5335 if (priv->grip_window == NULL)
5338 gtk_window_get_resize_grip_area (window, &rect);
5339 gdk_window_raise (priv->grip_window);
5340 gdk_window_move_resize (priv->grip_window,
5342 rect.width, rect.height);
5346 gtk_window_size_allocate (GtkWidget *widget,
5347 GtkAllocation *allocation)
5349 GtkWindow *window = GTK_WINDOW (widget);
5350 GtkAllocation child_allocation;
5354 gtk_widget_set_allocation (widget, allocation);
5356 if (gtk_widget_get_realized (widget))
5358 /* If it's not a toplevel we're embedded, we need to resize the window's
5359 * window and skip the grip.
5361 if (!gtk_widget_is_toplevel (widget))
5363 gdk_window_move_resize (gtk_widget_get_window (widget),
5364 allocation->x, allocation->y,
5365 allocation->width, allocation->height);
5369 update_grip_visibility (window);
5370 set_grip_position (window);
5374 child = gtk_bin_get_child (&(window->bin));
5375 if (child && gtk_widget_get_visible (child))
5377 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5378 child_allocation.x = border_width;
5379 child_allocation.y = border_width;
5380 child_allocation.width =
5381 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5382 child_allocation.height =
5383 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5385 gtk_widget_size_allocate (child, &child_allocation);
5390 gtk_window_configure_event (GtkWidget *widget,
5391 GdkEventConfigure *event)
5393 GtkAllocation allocation;
5394 GtkWindow *window = GTK_WINDOW (widget);
5395 GtkWindowPrivate *priv = window->priv;
5396 gboolean expected_reply = priv->configure_request_count > 0;
5398 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5400 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5401 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5403 gdk_window_configure_finished (gtk_widget_get_window (widget));
5407 /* priv->configure_request_count incremented for each
5408 * configure request, and decremented to a min of 0 for
5409 * each configure notify.
5411 * All it means is that we know we will get at least
5412 * priv->configure_request_count more configure notifies.
5413 * We could get more configure notifies than that; some
5414 * of the configure notifies we get may be unrelated to
5415 * the configure requests. But we will get at least
5416 * priv->configure_request_count notifies.
5419 if (priv->configure_request_count > 0)
5421 priv->configure_request_count -= 1;
5422 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5425 /* As an optimization, we avoid a resize when possible.
5427 * The only times we can avoid a resize are:
5428 * - we know only the position changed, not the size
5429 * - we know we have made more requests and so will get more
5430 * notifies and can wait to resize when we get them
5432 gtk_widget_get_allocation (widget, &allocation);
5433 if (!expected_reply &&
5434 (allocation.width == event->width &&
5435 allocation.height == event->height))
5437 gdk_window_configure_finished (gtk_widget_get_window (widget));
5442 * If we do need to resize, we do that by:
5443 * - filling in widget->allocation with the new size
5444 * - setting configure_notify_received to TRUE
5445 * for use in gtk_window_move_resize()
5446 * - queueing a resize, leading to invocation of
5447 * gtk_window_move_resize() in an idle handler
5451 priv->configure_notify_received = TRUE;
5453 allocation.width = event->width;
5454 allocation.height = event->height;
5455 gtk_widget_set_allocation (widget, &allocation);
5457 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5459 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5465 gtk_window_state_event (GtkWidget *widget,
5466 GdkEventWindowState *event)
5468 update_grip_visibility (GTK_WINDOW (widget));
5470 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
5471 ensure_state_flag_window_unfocused (widget);
5477 gtk_window_direction_changed (GtkWidget *widget,
5478 GtkTextDirection prev_dir)
5480 GtkWindow *window = GTK_WINDOW (widget);
5482 set_grip_cursor (window);
5483 set_grip_position (window);
5484 set_grip_shape (window);
5488 gtk_window_state_changed (GtkWidget *widget,
5489 GtkStateType previous_state)
5491 GtkWindow *window = GTK_WINDOW (widget);
5493 update_grip_visibility (window);
5497 gtk_window_style_updated (GtkWidget *widget)
5499 GtkWindow *window = GTK_WINDOW (widget);
5500 GtkWindowPrivate *priv = window->priv;
5503 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5505 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5507 gdk_window_move_resize (priv->grip_window,
5509 rect.width, rect.height);
5511 set_grip_shape (window);
5512 gtk_widget_queue_resize (widget);
5517 resize_grip_create_window (GtkWindow *window)
5520 GtkWindowPrivate *priv;
5521 GdkWindowAttr attributes;
5522 gint attributes_mask;
5525 priv = window->priv;
5526 widget = GTK_WIDGET (window);
5528 g_return_if_fail (gtk_widget_get_realized (widget));
5529 g_return_if_fail (priv->grip_window == NULL);
5531 gtk_window_get_resize_grip_area (window, &rect);
5533 attributes.x = rect.x;
5534 attributes.y = rect.y;
5535 attributes.width = rect.width;
5536 attributes.height = rect.height;
5537 attributes.window_type = GDK_WINDOW_CHILD;
5538 attributes.wclass = GDK_INPUT_OUTPUT;
5539 attributes.event_mask = gtk_widget_get_events (widget) |
5541 GDK_BUTTON_PRESS_MASK;
5543 attributes_mask = GDK_WA_X | GDK_WA_Y;
5545 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5549 gdk_window_set_user_data (priv->grip_window, widget);
5551 gdk_window_raise (priv->grip_window);
5553 set_grip_shape (window);
5554 update_grip_visibility (window);
5558 resize_grip_destroy_window (GtkWindow *window)
5560 GtkWindowPrivate *priv = window->priv;
5562 gdk_window_set_user_data (priv->grip_window, NULL);
5563 gdk_window_destroy (priv->grip_window);
5564 priv->grip_window = NULL;
5565 update_grip_visibility (window);
5569 * gtk_window_set_has_resize_grip:
5570 * @window: a #GtkWindow
5571 * @value: %TRUE to allow a resize grip
5573 * Sets whether @window has a corner resize grip.
5575 * Note that the resize grip is only shown if the window
5576 * is actually resizable and not maximized. Use
5577 * gtk_window_resize_grip_is_visible() to find out if the
5578 * resize grip is currently shown.
5583 gtk_window_set_has_resize_grip (GtkWindow *window,
5586 GtkWidget *widget = GTK_WIDGET (window);
5587 GtkWindowPrivate *priv = window->priv;
5589 value = value != FALSE;
5591 if (value != priv->has_resize_grip)
5593 priv->has_resize_grip = value;
5594 gtk_widget_queue_draw (widget);
5596 if (gtk_widget_get_realized (widget) &&
5597 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5599 if (priv->has_resize_grip && priv->grip_window == NULL)
5600 resize_grip_create_window (window);
5601 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5602 resize_grip_destroy_window (window);
5605 g_object_notify (G_OBJECT (window), "has-resize-grip");
5610 update_grip_visibility (GtkWindow *window)
5612 GtkWindowPrivate *priv = window->priv;
5615 val = gtk_window_resize_grip_is_visible (window);
5617 if (priv->grip_window != NULL)
5621 gdk_window_show (priv->grip_window);
5622 set_grip_cursor (window);
5626 gdk_window_hide (priv->grip_window);
5630 if (priv->resize_grip_visible != val)
5632 priv->resize_grip_visible = val;
5634 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5639 * gtk_window_resize_grip_is_visible:
5640 * @window: a #GtkWindow
5642 * Determines whether a resize grip is visible for the specified window.
5644 * Returns: %TRUE if a resize grip exists and is visible
5649 gtk_window_resize_grip_is_visible (GtkWindow *window)
5652 GtkWindowPrivate *priv;
5655 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5657 priv = window->priv;
5658 widget = GTK_WIDGET (window);
5660 if (priv->type == GTK_WINDOW_POPUP)
5663 if (!priv->resizable)
5666 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5669 if (gtk_widget_get_realized (widget))
5671 GdkWindowState state;
5673 state = gdk_window_get_state (gtk_widget_get_window (widget));
5675 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5679 if (!get_drag_edge (widget, &edge))
5682 return window->priv->has_resize_grip;
5686 * gtk_window_get_has_resize_grip:
5687 * @window: a #GtkWindow
5689 * Determines whether the window may have a resize grip.
5691 * Returns: %TRUE if the window has a resize grip
5696 gtk_window_get_has_resize_grip (GtkWindow *window)
5698 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5700 return window->priv->has_resize_grip;
5704 * gtk_window_get_resize_grip_area:
5705 * @window: a #GtkWindow
5706 * @rect: (out): a pointer to a #GdkRectangle which we should store
5707 * the resize grip area
5709 * If a window has a resize grip, this will retrieve the grip
5710 * position, width and height into the specified #GdkRectangle.
5712 * Returns: %TRUE if the resize grip's area was retrieved
5717 gtk_window_get_resize_grip_area (GtkWindow *window,
5720 GtkWidget *widget = GTK_WIDGET (window);
5721 GtkAllocation allocation;
5725 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5727 if (!window->priv->has_resize_grip)
5730 gtk_widget_get_allocation (widget, &allocation);
5732 gtk_widget_style_get (widget,
5733 "resize-grip-width", &grip_width,
5734 "resize-grip-height", &grip_height,
5737 if (grip_width > allocation.width)
5738 grip_width = allocation.width;
5740 if (grip_height > allocation.height)
5741 grip_height = allocation.height;
5743 rect->width = grip_width;
5744 rect->height = grip_height;
5745 rect->y = allocation.y + allocation.height - grip_height;
5747 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5748 rect->x = allocation.x + allocation.width - grip_width;
5750 rect->x = allocation.x;
5755 /* the accel_key and accel_mods fields of the key have to be setup
5756 * upon calling this function. it'll then return whether that key
5757 * is at all used as accelerator, and if so will OR in the
5758 * accel_flags member of the key.
5761 _gtk_window_query_nonaccels (GtkWindow *window,
5763 GdkModifierType accel_mods)
5765 GtkWindowPrivate *priv;
5767 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5769 priv = window->priv;
5771 /* movement keys are considered locked accels */
5774 static const guint bindings[] = {
5775 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,
5776 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,
5780 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5781 if (bindings[i] == accel_key)
5785 /* mnemonics are considered locked accels */
5786 if (accel_mods == priv->mnemonic_modifier)
5788 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5789 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5797 * gtk_window_propagate_key_event:
5798 * @window: a #GtkWindow
5799 * @event: a #GdkEventKey
5801 * Propagate a key press or release event to the focus widget and
5802 * up the focus container chain until a widget handles @event.
5803 * This is normally called by the default ::key_press_event and
5804 * ::key_release_event handlers for toplevel windows,
5805 * however in some cases it may be useful to call this directly when
5806 * overriding the standard key handling for a toplevel window.
5808 * Return value: %TRUE if a widget in the focus chain handled the event.
5813 gtk_window_propagate_key_event (GtkWindow *window,
5816 GtkWindowPrivate *priv;
5817 gboolean handled = FALSE;
5818 GtkWidget *widget, *focus;
5820 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5822 priv = window->priv;
5823 widget = GTK_WIDGET (window);
5825 focus = priv->focus_widget;
5827 g_object_ref (focus);
5830 focus && focus != widget &&
5831 gtk_widget_get_toplevel (focus) == widget)
5835 if (gtk_widget_is_sensitive (focus))
5836 handled = gtk_widget_event (focus, (GdkEvent*) event);
5838 parent = gtk_widget_get_parent (focus);
5840 g_object_ref (parent);
5842 g_object_unref (focus);
5848 g_object_unref (focus);
5854 gtk_window_key_press_event (GtkWidget *widget,
5857 GtkWindow *window = GTK_WINDOW (widget);
5858 gboolean handled = FALSE;
5860 /* handle mnemonics and accelerators */
5862 handled = gtk_window_activate_key (window, event);
5864 /* handle focus widget key events */
5866 handled = gtk_window_propagate_key_event (window, event);
5868 /* Chain up, invokes binding set */
5870 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5876 gtk_window_key_release_event (GtkWidget *widget,
5879 GtkWindow *window = GTK_WINDOW (widget);
5880 gboolean handled = FALSE;
5882 /* handle focus widget key events */
5884 handled = gtk_window_propagate_key_event (window, event);
5886 /* Chain up, invokes binding set */
5888 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5894 gtk_window_button_press_event (GtkWidget *widget,
5895 GdkEventButton *event)
5897 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5900 if (event->window == priv->grip_window)
5902 if (get_drag_edge (widget, &edge))
5903 gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
5905 gdk_event_get_device ((GdkEvent *) event),
5918 gtk_window_real_activate_default (GtkWindow *window)
5920 gtk_window_activate_default (window);
5924 gtk_window_real_activate_focus (GtkWindow *window)
5926 gtk_window_activate_focus (window);
5930 gtk_window_enter_notify_event (GtkWidget *widget,
5931 GdkEventCrossing *event)
5937 gtk_window_leave_notify_event (GtkWidget *widget,
5938 GdkEventCrossing *event)
5944 do_focus_change (GtkWidget *widget,
5948 GdkDeviceManager *device_manager;
5951 g_object_ref (widget);
5953 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5954 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5955 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5956 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5958 for (d = devices; d; d = d->next)
5960 GdkDevice *dev = d->data;
5963 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5966 /* Skip non-master keyboards that haven't
5967 * selected for events from this window
5969 window = gtk_widget_get_window (widget);
5970 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5971 window && !gdk_window_get_device_events (window, dev))
5974 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5976 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5977 fevent->focus_change.window = window;
5979 g_object_ref (window);
5980 fevent->focus_change.in = in;
5981 gdk_event_set_device (fevent, dev);
5983 gtk_widget_send_focus_change (widget, fevent);
5985 gdk_event_free (fevent);
5988 g_list_free (devices);
5989 g_object_unref (widget);
5993 maybe_set_mnemonics_visible (GtkWindow *window)
5996 GdkDeviceManager *device_manager;
5998 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
5999 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6001 for (d = devices; d; d = d->next)
6003 GdkDevice *dev = d->data;
6005 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6007 GdkModifierType mask;
6009 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6011 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6013 gtk_window_set_mnemonics_visible (window, TRUE);
6019 g_list_free (devices);
6023 gtk_window_focus_in_event (GtkWidget *widget,
6024 GdkEventFocus *event)
6026 GtkWindow *window = GTK_WINDOW (widget);
6027 gboolean auto_mnemonics;
6029 /* It appears spurious focus in events can occur when
6030 * the window is hidden. So we'll just check to see if
6031 * the window is visible before actually handling the
6034 if (gtk_widget_get_visible (widget))
6036 _gtk_window_set_has_toplevel_focus (window, TRUE);
6037 _gtk_window_set_is_active (window, TRUE);
6039 g_object_get (gtk_widget_get_settings (widget),
6040 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6042 maybe_set_mnemonics_visible (window);
6049 gtk_window_focus_out_event (GtkWidget *widget,
6050 GdkEventFocus *event)
6052 GtkWindow *window = GTK_WINDOW (widget);
6053 gboolean auto_mnemonics;
6055 _gtk_window_set_has_toplevel_focus (window, FALSE);
6056 _gtk_window_set_is_active (window, FALSE);
6058 /* set the mnemonic-visible property to false */
6059 g_object_get (gtk_widget_get_settings (widget),
6060 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6062 gtk_window_set_mnemonics_visible (window, FALSE);
6068 gtk_window_check_resize (GtkContainer *container)
6070 /* If the window is not toplevel anymore than it's embedded somewhere,
6071 * so handle it like a normal window */
6072 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6073 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6074 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6075 gtk_window_move_resize (GTK_WINDOW (container));
6079 gtk_window_focus (GtkWidget *widget,
6080 GtkDirectionType direction)
6082 GtkWindowPrivate *priv;
6085 GtkContainer *container;
6087 GtkWidget *old_focus_child;
6090 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6091 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6093 container = GTK_CONTAINER (widget);
6094 window = GTK_WINDOW (widget);
6095 priv = window->priv;
6096 bin = GTK_BIN (widget);
6098 old_focus_child = gtk_container_get_focus_child (container);
6100 /* We need a special implementation here to deal properly with wrapping
6101 * around in the tab chain without the danger of going into an
6104 if (old_focus_child)
6106 if (gtk_widget_child_focus (old_focus_child, direction))
6110 if (priv->focus_widget)
6112 if (direction == GTK_DIR_LEFT ||
6113 direction == GTK_DIR_RIGHT ||
6114 direction == GTK_DIR_UP ||
6115 direction == GTK_DIR_DOWN)
6120 /* Wrapped off the end, clear the focus setting for the toplpevel */
6121 parent = gtk_widget_get_parent (priv->focus_widget);
6124 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6125 parent = gtk_widget_get_parent (parent);
6128 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6131 /* Now try to focus the first widget in the window */
6132 child = gtk_bin_get_child (bin);
6135 if (gtk_widget_child_focus (child, direction))
6143 gtk_window_move_focus (GtkWidget *widget,
6144 GtkDirectionType dir)
6146 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6148 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6152 gtk_widget_child_focus (widget, dir);
6154 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6155 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6159 gtk_window_real_set_focus (GtkWindow *window,
6162 GtkWindowPrivate *priv = window->priv;
6163 GtkWidget *old_focus = priv->focus_widget;
6164 gboolean had_default = FALSE;
6165 gboolean focus_had_default = FALSE;
6166 gboolean old_focus_had_default = FALSE;
6170 g_object_ref (old_focus);
6171 g_object_freeze_notify (G_OBJECT (old_focus));
6172 old_focus_had_default = gtk_widget_has_default (old_focus);
6176 g_object_ref (focus);
6177 g_object_freeze_notify (G_OBJECT (focus));
6178 focus_had_default = gtk_widget_has_default (focus);
6181 if (priv->default_widget)
6182 had_default = gtk_widget_has_default (priv->default_widget);
6184 if (priv->focus_widget)
6186 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6187 (priv->focus_widget != priv->default_widget))
6189 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6190 gtk_widget_queue_draw (priv->focus_widget);
6192 if (priv->default_widget)
6193 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6196 priv->focus_widget = NULL;
6198 if (priv->has_focus)
6199 do_focus_change (old_focus, FALSE);
6201 g_object_notify (G_OBJECT (old_focus), "is-focus");
6204 /* The above notifications may have set a new focus widget,
6205 * if so, we don't want to override it.
6207 if (focus && !priv->focus_widget)
6209 priv->focus_widget = focus;
6211 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6212 (priv->focus_widget != priv->default_widget))
6214 if (gtk_widget_get_can_default (priv->focus_widget))
6215 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6217 if (priv->default_widget)
6218 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6221 if (priv->has_focus)
6222 do_focus_change (priv->focus_widget, TRUE);
6224 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6227 /* If the default widget changed, a redraw will have been queued
6228 * on the old and new default widgets by gtk_window_set_default(), so
6229 * we only have to worry about the case where it didn't change.
6230 * We'll sometimes queue a draw twice on the new widget but that
6233 if (priv->default_widget &&
6234 (had_default != gtk_widget_has_default (priv->default_widget)))
6235 gtk_widget_queue_draw (priv->default_widget);
6239 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6240 gtk_widget_queue_draw (old_focus);
6242 g_object_thaw_notify (G_OBJECT (old_focus));
6243 g_object_unref (old_focus);
6247 if (focus_had_default != gtk_widget_has_default (focus))
6248 gtk_widget_queue_draw (focus);
6250 g_object_thaw_notify (G_OBJECT (focus));
6251 g_object_unref (focus);
6257 gtk_window_get_preferred_width (GtkWidget *widget,
6265 window = GTK_WINDOW (widget);
6266 child = gtk_bin_get_child (GTK_BIN (window));
6268 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6269 *minimum_size = border_width * 2;
6270 *natural_size = border_width * 2;
6272 if (child && gtk_widget_get_visible (child))
6274 gint child_min, child_nat;
6275 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6277 *minimum_size += child_min;
6278 *natural_size += child_nat;
6283 gtk_window_get_preferred_height (GtkWidget *widget,
6291 window = GTK_WINDOW (widget);
6292 child = gtk_bin_get_child (GTK_BIN (window));
6294 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6295 *minimum_size = border_width * 2;
6296 *natural_size = border_width * 2;
6298 if (child && gtk_widget_get_visible (child))
6300 gint child_min, child_nat;
6301 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6303 *minimum_size += child_min;
6304 *natural_size += child_nat;
6310 * _gtk_window_unset_focus_and_default:
6311 * @window: a #GtkWindow
6312 * @widget: a widget inside of @window
6314 * Checks whether the focus and default widgets of @window are
6315 * @widget or a descendent of @widget, and if so, unset them.
6318 _gtk_window_unset_focus_and_default (GtkWindow *window,
6322 GtkWindowPrivate *priv = window->priv;
6326 g_object_ref (window);
6327 g_object_ref (widget);
6329 parent = gtk_widget_get_parent (widget);
6330 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6332 child = priv->focus_widget;
6334 while (child && child != widget)
6335 child = gtk_widget_get_parent (child);
6337 if (child == widget)
6338 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6341 child = priv->default_widget;
6343 while (child && child != widget)
6344 child = gtk_widget_get_parent (child);
6346 if (child == widget)
6347 gtk_window_set_default (window, NULL);
6349 g_object_unref (widget);
6350 g_object_unref (window);
6353 /*********************************
6354 * Functions related to resizing *
6355 *********************************/
6358 geometry_size_to_pixels (GdkGeometry *geometry,
6363 gint base_width = 0;
6364 gint base_height = 0;
6366 gint min_height = 0;
6368 gint height_inc = 1;
6370 if (flags & GDK_HINT_BASE_SIZE)
6372 base_width = geometry->base_width;
6373 base_height = geometry->base_height;
6375 if (flags & GDK_HINT_MIN_SIZE)
6377 min_width = geometry->min_width;
6378 min_height = geometry->min_height;
6380 if (flags & GDK_HINT_RESIZE_INC)
6382 width_inc = geometry->width_inc;
6383 height_inc = geometry->height_inc;
6387 *width = MAX (*width * width_inc + base_width, min_width);
6389 *height = MAX (*height * height_inc + base_height, min_height);
6392 /* This function doesn't constrain to geometry hints */
6394 gtk_window_compute_configure_request_size (GtkWindow *window,
6395 GdkGeometry *geometry,
6400 GtkWindowPrivate *priv = window->priv;
6401 GtkWindowGeometryInfo *info;
6404 * - we've done a size request
6407 info = gtk_window_get_geometry_info (window, FALSE);
6409 if (priv->need_default_size)
6411 gtk_window_guess_default_size (window, width, height);
6413 /* If window is empty so requests 0, default to random nonzero size */
6414 if (*width == 0 && *height == 0)
6420 /* Override with default size */
6424 if (info->default_width > 0)
6425 *width = info->default_width;
6426 if (info->default_height > 0)
6427 *height = info->default_height;
6429 if (info->default_is_geometry)
6430 geometry_size_to_pixels (geometry, flags,
6431 info->default_width > 0 ? width : NULL,
6432 info->default_height > 0 ? height : NULL);
6437 GtkAllocation allocation;
6439 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6441 /* Default to keeping current size */
6442 *width = allocation.width;
6443 *height = allocation.height;
6446 /* Override any size with gtk_window_resize() values */
6449 if (info->resize_width > 0)
6450 *width = info->resize_width;
6451 if (info->resize_height > 0)
6452 *height = info->resize_height;
6454 if (info->resize_is_geometry)
6455 geometry_size_to_pixels (geometry, flags,
6456 info->resize_width > 0 ? width : NULL,
6457 info->resize_height > 0 ? height : NULL);
6460 /* Don't ever request zero width or height, its not supported by
6461 gdk. The size allocation code will round it to 1 anyway but if
6462 we do it then the value returned from this function will is
6463 not comparable to the size allocation read from the GtkWindow. */
6464 *width = MAX (*width, 1);
6465 *height = MAX (*height, 1);
6468 static GtkWindowPosition
6469 get_effective_position (GtkWindow *window)
6471 GtkWindowPrivate *priv = window->priv;
6472 GtkWindowPosition pos = priv->position;
6474 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6475 (priv->transient_parent == NULL ||
6476 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6477 pos = GTK_WIN_POS_NONE;
6483 get_center_monitor_of_window (GtkWindow *window)
6485 /* We could try to sort out the relative positions of the monitors and
6486 * stuff, or we could just be losers and assume you have a row
6487 * or column of monitors.
6489 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6493 get_monitor_containing_pointer (GtkWindow *window)
6497 GdkScreen *window_screen;
6498 GdkScreen *pointer_screen;
6499 GdkDisplay *display;
6500 GdkDeviceManager *device_manager;
6503 window_screen = gtk_window_check_screen (window);
6504 display = gdk_screen_get_display (window_screen);
6505 device_manager = gdk_display_get_device_manager (display);
6506 pointer = gdk_device_manager_get_client_pointer (device_manager);
6508 gdk_device_get_position (pointer,
6512 if (pointer_screen == window_screen)
6513 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6521 center_window_on_monitor (GtkWindow *window,
6527 GdkRectangle monitor;
6530 monitor_num = get_monitor_containing_pointer (window);
6532 if (monitor_num == -1)
6533 monitor_num = get_center_monitor_of_window (window);
6535 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6536 monitor_num, &monitor);
6538 *x = (monitor.width - w) / 2 + monitor.x;
6539 *y = (monitor.height - h) / 2 + monitor.y;
6541 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6542 * and WM decorations.
6556 if (extent > clamp_extent)
6558 *base = clamp_base + clamp_extent/2 - extent/2;
6559 else if (*base < clamp_base)
6561 else if (*base + extent > clamp_base + clamp_extent)
6562 *base = clamp_base + clamp_extent - extent;
6566 clamp_window_to_rectangle (gint *x,
6570 const GdkRectangle *rect)
6572 #ifdef DEBUGGING_OUTPUT
6573 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);
6576 /* If it is too large, center it. If it fits on the monitor but is
6577 * partially outside, move it to the closest edge. Do this
6578 * separately in x and y directions.
6580 clamp (x, w, rect->x, rect->width);
6581 clamp (y, h, rect->y, rect->height);
6582 #ifdef DEBUGGING_OUTPUT
6583 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6589 gtk_window_compute_configure_request (GtkWindow *window,
6590 GdkRectangle *request,
6591 GdkGeometry *geometry,
6594 GtkWindowPrivate *priv = window->priv;
6595 GdkGeometry new_geometry;
6598 GtkWindowPosition pos;
6599 GtkWidget *parent_widget;
6600 GtkWindowGeometryInfo *info;
6604 screen = gtk_window_check_screen (window);
6606 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6607 gtk_window_compute_configure_request_size (window,
6608 &new_geometry, new_flags,
6611 gtk_window_constrain_size (window,
6612 &new_geometry, new_flags,
6616 parent_widget = (GtkWidget*) priv->transient_parent;
6618 pos = get_effective_position (window);
6619 info = gtk_window_get_geometry_info (window, FALSE);
6621 /* by default, don't change position requested */
6624 x = info->last.configure_request.x;
6625 y = info->last.configure_request.y;
6634 if (priv->need_default_position)
6637 /* FIXME this all interrelates with window gravity.
6638 * For most of them I think we want to set GRAVITY_CENTER.
6640 * Not sure how to go about that.
6644 /* here we are only handling CENTER_ALWAYS
6645 * as it relates to default positioning,
6646 * where it's equivalent to simply CENTER
6648 case GTK_WIN_POS_CENTER_ALWAYS:
6649 case GTK_WIN_POS_CENTER:
6650 center_window_on_monitor (window, w, h, &x, &y);
6653 case GTK_WIN_POS_CENTER_ON_PARENT:
6655 GtkAllocation allocation;
6656 GdkWindow *gdk_window;
6658 GdkRectangle monitor;
6661 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6663 gdk_window = gtk_widget_get_window (parent_widget);
6665 if (gdk_window != NULL)
6666 monitor_num = gdk_screen_get_monitor_at_window (screen,
6671 gdk_window_get_origin (gdk_window,
6674 gtk_widget_get_allocation (parent_widget, &allocation);
6675 x = ox + (allocation.width - w) / 2;
6676 y = oy + (allocation.height - h) / 2;
6678 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6679 * WM decorations. If parent wasn't on a monitor, just
6682 if (monitor_num >= 0)
6684 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6685 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6690 case GTK_WIN_POS_MOUSE:
6692 gint screen_width = gdk_screen_get_width (screen);
6693 gint screen_height = gdk_screen_get_height (screen);
6695 GdkRectangle monitor;
6696 GdkDisplay *display;
6697 GdkDeviceManager *device_manager;
6699 GdkScreen *pointer_screen;
6702 display = gdk_screen_get_display (screen);
6703 device_manager = gdk_display_get_device_manager (display);
6704 pointer = gdk_device_manager_get_client_pointer (device_manager);
6706 gdk_device_get_position (pointer,
6710 if (pointer_screen == screen)
6711 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6717 x = CLAMP (x, 0, screen_width - w);
6718 y = CLAMP (y, 0, screen_height - h);
6720 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6721 * WM decorations. Don't try to figure out what's going
6722 * on if the mouse wasn't inside a monitor.
6724 if (monitor_num >= 0)
6726 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6727 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6735 } /* if (priv->need_default_position) */
6737 if (priv->need_default_position && info &&
6738 info->initial_pos_set)
6740 x = info->initial_x;
6741 y = info->initial_y;
6742 gtk_window_constrain_position (window, w, h, &x, &y);
6748 request->height = h;
6751 *geometry = new_geometry;
6757 gtk_window_constrain_position (GtkWindow *window,
6763 GtkWindowPrivate *priv = window->priv;
6765 /* See long comments in gtk_window_move_resize()
6766 * on when it's safe to call this function.
6768 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6770 gint center_x, center_y;
6772 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6780 gtk_window_move_resize (GtkWindow *window)
6784 * First we determine whether any information has changed that would
6785 * cause us to revise our last configure request. If we would send
6786 * a different configure request from last time, then
6787 * configure_request_size_changed = TRUE or
6788 * configure_request_pos_changed = TRUE. configure_request_size_changed
6789 * may be true due to new hints, a gtk_window_resize(), or whatever.
6790 * configure_request_pos_changed may be true due to gtk_window_set_position()
6791 * or gtk_window_move().
6793 * If the configure request has changed, we send off a new one. To
6794 * ensure GTK+ invariants are maintained (resize queue does what it
6795 * should), we go ahead and size_allocate the requested size in this
6798 * If the configure request has not changed, we don't ever resend
6799 * it, because it could mean fighting the user or window manager.
6802 * To prepare the configure request, we come up with a base size/pos:
6803 * - the one from gtk_window_move()/gtk_window_resize()
6804 * - else default_width, default_height if we haven't ever
6806 * - else the size request if we haven't ever been mapped,
6807 * as a substitute default size
6808 * - else the current size of the window, as received from
6809 * configure notifies (i.e. the current allocation)
6811 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6812 * the position request to be centered.
6814 GtkWindowPrivate *priv = window->priv;
6815 GtkAllocation allocation;
6817 GtkContainer *container;
6818 GtkWindowGeometryInfo *info;
6819 GdkGeometry new_geometry;
6820 GdkWindow *gdk_window;
6822 GdkRectangle new_request;
6823 gboolean configure_request_size_changed;
6824 gboolean configure_request_pos_changed;
6825 gboolean hints_changed; /* do we need to send these again */
6826 GtkWindowLastGeometryInfo saved_last_info;
6828 widget = GTK_WIDGET (window);
6830 gdk_window = gtk_widget_get_window (widget);
6831 container = GTK_CONTAINER (widget);
6832 info = gtk_window_get_geometry_info (window, TRUE);
6834 configure_request_size_changed = FALSE;
6835 configure_request_pos_changed = FALSE;
6837 gtk_window_compute_configure_request (window, &new_request,
6838 &new_geometry, &new_flags);
6840 /* This check implies the invariant that we never set info->last
6841 * without setting the hints and sending off a configure request.
6843 * If we change info->last without sending the request, we may
6846 if (info->last.configure_request.x != new_request.x ||
6847 info->last.configure_request.y != new_request.y)
6848 configure_request_pos_changed = TRUE;
6850 if ((info->last.configure_request.width != new_request.width ||
6851 info->last.configure_request.height != new_request.height))
6852 configure_request_size_changed = TRUE;
6854 hints_changed = FALSE;
6856 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6857 &new_geometry, new_flags))
6859 hints_changed = TRUE;
6862 /* Position Constraints
6863 * ====================
6865 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6866 * a default. The other POS_ values are used only when the
6867 * window is shown, not after that.
6869 * However, we can't implement a position constraint as
6870 * "anytime the window size changes, center the window"
6871 * because this may well end up fighting the WM or user. In
6872 * fact it gets in an infinite loop with at least one WM.
6874 * Basically, applications are in no way in a position to
6875 * constrain the position of a window, with one exception:
6876 * override redirect windows. (Really the intended purpose
6877 * of CENTER_ALWAYS anyhow, I would think.)
6879 * So the way we implement this "constraint" is to say that when WE
6880 * cause a move or resize, i.e. we make a configure request changing
6881 * window size, we recompute the CENTER_ALWAYS position to reflect
6882 * the new window size, and include it in our request. Also, if we
6883 * just turned on CENTER_ALWAYS we snap to center with a new
6884 * request. Otherwise, if we are just NOTIFIED of a move or resize
6885 * done by someone else e.g. the window manager, we do NOT send a
6886 * new configure request.
6888 * For override redirect windows, this works fine; all window
6889 * sizes are from our configure requests. For managed windows,
6890 * it is at least semi-sane, though who knows what the
6891 * app author is thinking.
6894 /* This condition should be kept in sync with the condition later on
6895 * that determines whether we send a configure request. i.e. we
6896 * should do this position constraining anytime we were going to
6897 * send a configure request anyhow, plus when constraints have
6900 if (configure_request_pos_changed ||
6901 configure_request_size_changed ||
6903 info->position_constraints_changed)
6905 /* We request the constrained position if:
6906 * - we were changing position, and need to clamp
6907 * the change to the constraint
6908 * - we're changing the size anyway
6909 * - set_position() was called to toggle CENTER_ALWAYS on
6912 gtk_window_constrain_position (window,
6918 /* Update whether we need to request a move */
6919 if (info->last.configure_request.x != new_request.x ||
6920 info->last.configure_request.y != new_request.y)
6921 configure_request_pos_changed = TRUE;
6923 configure_request_pos_changed = FALSE;
6927 if (priv->type == GTK_WINDOW_TOPLEVEL)
6929 int notify_x, notify_y;
6931 /* this is the position from the last configure notify */
6932 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6934 g_message ("--- %s ---\n"
6935 "last : %d,%d\t%d x %d\n"
6936 "this : %d,%d\t%d x %d\n"
6937 "alloc : %d,%d\t%d x %d\n"
6939 "resize: \t%d x %d\n"
6940 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6941 "configure_notify_received: %d\n"
6942 "configure_request_count: %d\n"
6943 "position_constraints_changed: %d\n",
6944 priv->title ? priv->title : "(no title)",
6945 info->last.configure_request.x,
6946 info->last.configure_request.y,
6947 info->last.configure_request.width,
6948 info->last.configure_request.height,
6954 widget->allocation.width,
6955 widget->allocation.height,
6956 widget->requisition.width,
6957 widget->requisition.height,
6959 info->resize_height,
6960 configure_request_pos_changed,
6961 configure_request_size_changed,
6963 priv->configure_notify_received,
6964 priv->configure_request_count,
6965 info->position_constraints_changed);
6969 saved_last_info = info->last;
6970 info->last.geometry = new_geometry;
6971 info->last.flags = new_flags;
6972 info->last.configure_request = new_request;
6974 /* need to set PPosition so the WM will look at our position,
6975 * but we don't want to count PPosition coming and going as a hints
6976 * change for future iterations. So we saved info->last prior to
6980 /* Also, if the initial position was explicitly set, then we always
6981 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6985 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6986 * this is an initial map
6989 if ((configure_request_pos_changed ||
6990 info->initial_pos_set ||
6991 (priv->need_default_position &&
6992 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6993 (new_flags & GDK_HINT_POS) == 0)
6995 new_flags |= GDK_HINT_POS;
6996 hints_changed = TRUE;
6999 /* Set hints if necessary
7002 gdk_window_set_geometry_hints (gdk_window,
7006 gtk_widget_get_allocation (widget, &allocation);
7008 /* handle resizing/moving and widget tree allocation
7010 if (priv->configure_notify_received)
7012 /* If we have received a configure event since
7013 * the last time in this function, we need to
7014 * accept our new size and size_allocate child widgets.
7015 * (see gtk_window_configure_event() for more details).
7017 * 1 or more configure notifies may have been received.
7018 * Also, configure_notify_received will only be TRUE
7019 * if all expected configure notifies have been received
7020 * (one per configure request), as an optimization.
7023 priv->configure_notify_received = FALSE;
7025 /* gtk_window_configure_event() filled in widget->allocation */
7026 gtk_widget_size_allocate (widget, &allocation);
7028 set_grip_position (window);
7029 update_grip_visibility (window);
7031 gdk_window_process_updates (gdk_window, TRUE);
7033 gdk_window_configure_finished (gdk_window);
7035 /* If the configure request changed, it means that
7037 * 1) coincidentally changed hints or widget properties
7038 * impacting the configure request before getting
7039 * a configure notify, or
7040 * 2) some broken widget is changing its size request
7041 * during size allocation, resulting in
7042 * a false appearance of changed configure request.
7044 * For 1), we could just go ahead and ask for the
7045 * new size right now, but doing that for 2)
7046 * might well be fighting the user (and can even
7047 * trigger a loop). Since we really don't want to
7048 * do that, we requeue a resize in hopes that
7049 * by the time it gets handled, the child has seen
7050 * the light and is willing to go along with the
7051 * new size. (this happens for the zvt widget, since
7052 * the size_allocate() above will have stored the
7053 * requisition corresponding to the new size in the
7056 * This doesn't buy us anything for 1), but it shouldn't
7057 * hurt us too badly, since it is what would have
7058 * happened if we had gotten the configure event before
7059 * the new size had been set.
7062 if (configure_request_size_changed ||
7063 configure_request_pos_changed)
7065 /* Don't change the recorded last info after all, because we
7066 * haven't actually updated to the new info yet - we decided
7067 * to postpone our configure request until later.
7069 info->last = saved_last_info;
7071 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7074 return; /* Bail out, we didn't really process the move/resize */
7076 else if ((configure_request_size_changed || hints_changed) &&
7077 (allocation.width != new_request.width || allocation.height != new_request.height))
7080 /* We are in one of the following situations:
7081 * A. configure_request_size_changed
7082 * our requisition has changed and we need a different window size,
7083 * so we request it from the window manager.
7084 * B. !configure_request_size_changed && hints_changed
7085 * the window manager rejects our size, but we have just changed the
7086 * window manager hints, so there's a chance our request will
7087 * be honoured this time, so we try again.
7089 * However, if the new requisition is the same as the current allocation,
7090 * we don't request it again, since we won't get a ConfigureNotify back from
7091 * the window manager unless it decides to change our requisition. If
7092 * we don't get the ConfigureNotify back, the resize queue will never be run.
7095 /* Now send the configure request */
7096 if (configure_request_pos_changed)
7098 gdk_window_move_resize (gdk_window,
7099 new_request.x, new_request.y,
7100 new_request.width, new_request.height);
7102 else /* only size changed */
7104 gdk_window_resize (gdk_window,
7105 new_request.width, new_request.height);
7108 if (priv->type == GTK_WINDOW_POPUP)
7110 GtkAllocation allocation;
7112 /* Directly size allocate for override redirect (popup) windows. */
7115 allocation.width = new_request.width;
7116 allocation.height = new_request.height;
7118 gtk_widget_size_allocate (widget, &allocation);
7120 gdk_window_process_updates (gdk_window, TRUE);
7122 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7123 gtk_widget_queue_draw (widget);
7127 /* Increment the number of have-not-yet-received-notify requests */
7128 priv->configure_request_count += 1;
7129 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7131 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7132 * configure event in response to our resizing request.
7133 * the configure event will cause a new resize with
7134 * ->configure_notify_received=TRUE.
7135 * until then, we want to
7136 * - discard expose events
7137 * - coalesce resizes for our children
7138 * - defer any window resizes until the configure event arrived
7139 * to achieve this, we queue a resize for the window, but remove its
7140 * resizing handler, so resizing will not be handled from the next
7141 * idle handler but when the configure event arrives.
7143 * FIXME: we should also dequeue the pending redraws here, since
7144 * we handle those ourselves upon ->configure_notify_received==TRUE.
7146 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7148 gtk_widget_queue_resize_no_redraw (widget);
7149 _gtk_container_dequeue_resize_handler (container);
7155 /* Handle any position changes.
7157 if (configure_request_pos_changed)
7159 gdk_window_move (gdk_window,
7160 new_request.x, new_request.y);
7163 /* And run the resize queue.
7165 gtk_container_resize_children (container);
7168 /* We have now processed a move/resize since the last position
7169 * constraint change, setting of the initial position, or resize.
7170 * (Not resetting these flags here can lead to infinite loops for
7171 * GTK_RESIZE_IMMEDIATE containers)
7173 info->position_constraints_changed = FALSE;
7174 info->initial_pos_set = FALSE;
7175 info->resize_width = -1;
7176 info->resize_height = -1;
7179 /* Compare two sets of Geometry hints for equality.
7182 gtk_window_compare_hints (GdkGeometry *geometry_a,
7184 GdkGeometry *geometry_b,
7187 if (flags_a != flags_b)
7190 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7191 (geometry_a->min_width != geometry_b->min_width ||
7192 geometry_a->min_height != geometry_b->min_height))
7195 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7196 (geometry_a->max_width != geometry_b->max_width ||
7197 geometry_a->max_height != geometry_b->max_height))
7200 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7201 (geometry_a->base_width != geometry_b->base_width ||
7202 geometry_a->base_height != geometry_b->base_height))
7205 if ((flags_a & GDK_HINT_ASPECT) &&
7206 (geometry_a->min_aspect != geometry_b->min_aspect ||
7207 geometry_a->max_aspect != geometry_b->max_aspect))
7210 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7211 (geometry_a->width_inc != geometry_b->width_inc ||
7212 geometry_a->height_inc != geometry_b->height_inc))
7215 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7216 geometry_a->win_gravity != geometry_b->win_gravity)
7223 _gtk_window_constrain_size (GtkWindow *window,
7229 GtkWindowPrivate *priv;
7230 GtkWindowGeometryInfo *info;
7232 g_return_if_fail (GTK_IS_WINDOW (window));
7234 priv = window->priv;
7236 info = priv->geometry_info;
7239 GdkWindowHints flags = info->last.flags;
7240 GdkGeometry *geometry = &info->last.geometry;
7242 gtk_window_constrain_size (window,
7253 gtk_window_constrain_size (GtkWindow *window,
7254 GdkGeometry *geometry,
7261 gdk_window_constrain_size (geometry, flags, width, height,
7262 new_width, new_height);
7265 /* Compute the set of geometry hints and flags for a window
7266 * based on the application set geometry, and requisition
7267 * of the window. gtk_widget_get_preferred_size() must have been
7271 gtk_window_compute_hints (GtkWindow *window,
7272 GdkGeometry *new_geometry,
7275 GtkWindowPrivate *priv = window->priv;
7277 gint extra_width = 0;
7278 gint extra_height = 0;
7279 GtkWindowGeometryInfo *geometry_info;
7280 GtkRequisition requisition;
7282 widget = GTK_WIDGET (window);
7284 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7285 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7289 *new_flags = geometry_info->mask;
7290 *new_geometry = geometry_info->geometry;
7297 if (geometry_info && geometry_info->widget)
7299 /* If the geometry widget is set, then the hints really apply to that
7300 * widget. This is pretty much meaningless unless the window layout
7301 * is such that the rest of the window adds fixed size borders to
7302 * the geometry widget. Our job is to figure the size of the borders;
7303 * We do that by asking how big the toplevel would be if the
7304 * geometry widget was *really big*.
7307 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7308 * |GGGGG B| in the border can confuse things
7314 * |AAAAAAAAA | When the geometry widget is large, things are
7315 * |GGGGGGGGGGB| clearer.
7320 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7321 GtkRequisition requisition;
7322 int current_width, current_height;
7324 _gtk_widget_override_size_request (geometry_info->widget,
7325 TEMPORARY_SIZE, TEMPORARY_SIZE,
7326 ¤t_width, ¤t_height);
7327 gtk_widget_get_preferred_size (widget,
7328 &requisition, NULL);
7329 _gtk_widget_restore_size_request (geometry_info->widget,
7330 current_width, current_height);
7332 extra_width = requisition.width - TEMPORARY_SIZE;
7333 extra_height = requisition.height - TEMPORARY_SIZE;
7335 if (extra_width < 0 || extra_height < 0)
7337 g_warning("Toplevel size doesn't seem to directly depend on the "
7338 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7339 "The geometry widget might not be in the window, or it might not "
7340 "be packed into the window appropriately");
7341 extra_width = MAX(extra_width, 0);
7342 extra_height = MAX(extra_height, 0);
7344 #undef TEMPORARY_SIZE
7347 /* We don't want to set GDK_HINT_POS in here, we just set it
7348 * in gtk_window_move_resize() when we want the position
7352 if (*new_flags & GDK_HINT_BASE_SIZE)
7354 new_geometry->base_width += extra_width;
7355 new_geometry->base_height += extra_height;
7359 /* For simplicity, we always set the base hint, even when we
7360 * don't expect it to have any visible effect.
7361 * (Note: geometry_size_to_pixels() depends on this.)
7363 *new_flags |= GDK_HINT_BASE_SIZE;
7365 new_geometry->base_width = extra_width;
7366 new_geometry->base_height = extra_height;
7368 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7369 * base size is the minimum size */
7370 if (*new_flags & GDK_HINT_MIN_SIZE)
7372 if (new_geometry->min_width > 0)
7373 new_geometry->base_width += new_geometry->min_width;
7374 if (new_geometry->min_height > 0)
7375 new_geometry->base_height += new_geometry->min_height;
7379 /* Please use a good size for unresizable widgets, not the minimum one. */
7380 if (!priv->resizable)
7381 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7383 if (*new_flags & GDK_HINT_MIN_SIZE)
7385 if (new_geometry->min_width < 0)
7386 new_geometry->min_width = requisition.width;
7388 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7390 if (new_geometry->min_height < 0)
7391 new_geometry->min_height = requisition.height;
7393 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7397 *new_flags |= GDK_HINT_MIN_SIZE;
7399 new_geometry->min_width = requisition.width;
7400 new_geometry->min_height = requisition.height;
7403 if (*new_flags & GDK_HINT_MAX_SIZE)
7405 if (new_geometry->max_width < 0)
7406 new_geometry->max_width = requisition.width;
7408 new_geometry->max_width += extra_width;
7410 if (new_geometry->max_height < 0)
7411 new_geometry->max_height = requisition.height;
7413 new_geometry->max_height += extra_height;
7415 else if (!priv->resizable)
7417 *new_flags |= GDK_HINT_MAX_SIZE;
7419 new_geometry->max_width = requisition.width;
7420 new_geometry->max_height = requisition.height;
7423 *new_flags |= GDK_HINT_WIN_GRAVITY;
7424 new_geometry->win_gravity = priv->gravity;
7427 /***********************
7428 * Redrawing functions *
7429 ***********************/
7432 gtk_window_draw (GtkWidget *widget,
7435 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7436 GtkStyleContext *context;
7437 gboolean ret = FALSE;
7439 context = gtk_widget_get_style_context (widget);
7441 gtk_style_context_save (context);
7443 if (!gtk_widget_get_app_paintable (widget))
7445 GtkStateFlags state;
7447 state = gtk_widget_get_state_flags (widget);
7449 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7450 state |= GTK_STATE_FLAG_FOCUSED;
7452 gtk_style_context_set_state (context, state);
7453 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7454 gtk_render_background (context, cr, 0, 0,
7455 gtk_widget_get_allocated_width (widget),
7456 gtk_widget_get_allocated_height (widget));
7459 gtk_style_context_restore (context);
7461 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7462 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7464 if (priv->grip_window &&
7465 gtk_cairo_should_draw_window (cr, priv->grip_window))
7469 gtk_style_context_save (context);
7472 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7473 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7475 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7476 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7477 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7480 gtk_style_context_restore (context);
7487 * gtk_window_present:
7488 * @window: a #GtkWindow
7490 * Presents a window to the user. This may mean raising the window
7491 * in the stacking order, deiconifying it, moving it to the current
7492 * desktop, and/or giving it the keyboard focus, possibly dependent
7493 * on the user's platform, window manager, and preferences.
7495 * If @window is hidden, this function calls gtk_widget_show()
7498 * This function should be used when the user tries to open a window
7499 * that's already open. Say for example the preferences dialog is
7500 * currently open, and the user chooses Preferences from the menu
7501 * a second time; use gtk_window_present() to move the already-open dialog
7502 * where the user can see it.
7504 * If you are calling this function in response to a user interaction,
7505 * it is preferable to use gtk_window_present_with_time().
7509 gtk_window_present (GtkWindow *window)
7511 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7515 * gtk_window_present_with_time:
7516 * @window: a #GtkWindow
7517 * @timestamp: the timestamp of the user interaction (typically a
7518 * button or key press event) which triggered this call
7520 * Presents a window to the user in response to a user interaction.
7521 * If you need to present a window without a timestamp, use
7522 * gtk_window_present(). See gtk_window_present() for details.
7527 gtk_window_present_with_time (GtkWindow *window,
7530 GtkWindowPrivate *priv;
7532 GdkWindow *gdk_window;
7534 g_return_if_fail (GTK_IS_WINDOW (window));
7536 priv = window->priv;
7537 widget = GTK_WIDGET (window);
7539 if (gtk_widget_get_visible (widget))
7541 gdk_window = gtk_widget_get_window (widget);
7543 g_assert (gdk_window != NULL);
7545 gdk_window_show (gdk_window);
7547 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7548 if (timestamp == GDK_CURRENT_TIME)
7550 #ifdef GDK_WINDOWING_X11
7551 if (GDK_IS_X11_WINDOW(gdk_window))
7553 GdkDisplay *display;
7555 display = gtk_widget_get_display (GTK_WIDGET (window));
7556 timestamp = gdk_x11_display_get_user_time (display);
7560 timestamp = gtk_get_current_event_time ();
7563 gdk_window_focus (gdk_window, timestamp);
7567 priv->initial_timestamp = timestamp;
7568 gtk_widget_show (widget);
7573 * gtk_window_iconify:
7574 * @window: a #GtkWindow
7576 * Asks to iconify (i.e. minimize) the specified @window. Note that
7577 * you shouldn't assume the window is definitely iconified afterward,
7578 * because other entities (e.g. the user or <link
7579 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7580 * again, or there may not be a window manager in which case
7581 * iconification isn't possible, etc. But normally the window will end
7582 * up iconified. Just don't write code that crashes if not.
7584 * It's permitted to call this function before showing a window,
7585 * in which case the window will be iconified before it ever appears
7588 * You can track iconification via the "window-state-event" signal
7593 gtk_window_iconify (GtkWindow *window)
7595 GtkWindowPrivate *priv;
7597 GdkWindow *toplevel;
7599 g_return_if_fail (GTK_IS_WINDOW (window));
7601 priv = window->priv;
7602 widget = GTK_WIDGET (window);
7604 priv->iconify_initially = TRUE;
7606 toplevel = gtk_widget_get_window (widget);
7608 if (toplevel != NULL)
7609 gdk_window_iconify (toplevel);
7613 * gtk_window_deiconify:
7614 * @window: a #GtkWindow
7616 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7617 * that you shouldn't assume the window is definitely deiconified
7618 * afterward, because other entities (e.g. the user or <link
7619 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7620 * again before your code which assumes deiconification gets to run.
7622 * You can track iconification via the "window-state-event" signal
7626 gtk_window_deiconify (GtkWindow *window)
7628 GtkWindowPrivate *priv;
7630 GdkWindow *toplevel;
7632 g_return_if_fail (GTK_IS_WINDOW (window));
7634 priv = window->priv;
7635 widget = GTK_WIDGET (window);
7637 priv->iconify_initially = FALSE;
7639 toplevel = gtk_widget_get_window (widget);
7641 if (toplevel != NULL)
7642 gdk_window_deiconify (toplevel);
7647 * @window: a #GtkWindow
7649 * Asks to stick @window, which means that it will appear on all user
7650 * desktops. Note that you shouldn't assume the window is definitely
7651 * stuck afterward, because other entities (e.g. the user or <link
7652 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7653 * again, and some window managers do not support sticking
7654 * windows. But normally the window will end up stuck. Just don't
7655 * write code that crashes if not.
7657 * It's permitted to call this function before showing a window.
7659 * You can track stickiness via the "window-state-event" signal
7664 gtk_window_stick (GtkWindow *window)
7666 GtkWindowPrivate *priv;
7668 GdkWindow *toplevel;
7670 g_return_if_fail (GTK_IS_WINDOW (window));
7672 priv = window->priv;
7673 widget = GTK_WIDGET (window);
7675 priv->stick_initially = TRUE;
7677 toplevel = gtk_widget_get_window (widget);
7679 if (toplevel != NULL)
7680 gdk_window_stick (toplevel);
7684 * gtk_window_unstick:
7685 * @window: a #GtkWindow
7687 * Asks to unstick @window, which means that it will appear on only
7688 * one of the user's desktops. Note that you shouldn't assume the
7689 * window is definitely unstuck afterward, because other entities
7690 * (e.g. the user or <link linkend="gtk-X11-arch">window
7691 * manager</link>) could stick it again. But normally the window will
7692 * end up stuck. Just don't write code that crashes if not.
7694 * You can track stickiness via the "window-state-event" signal
7699 gtk_window_unstick (GtkWindow *window)
7701 GtkWindowPrivate *priv;
7703 GdkWindow *toplevel;
7705 g_return_if_fail (GTK_IS_WINDOW (window));
7707 priv = window->priv;
7708 widget = GTK_WIDGET (window);
7710 priv->stick_initially = FALSE;
7712 toplevel = gtk_widget_get_window (widget);
7714 if (toplevel != NULL)
7715 gdk_window_unstick (toplevel);
7719 * gtk_window_maximize:
7720 * @window: a #GtkWindow
7722 * Asks to maximize @window, so that it becomes full-screen. Note that
7723 * you shouldn't assume the window is definitely maximized afterward,
7724 * because other entities (e.g. the user or <link
7725 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7726 * again, and not all window managers support maximization. But
7727 * normally the window will end up maximized. Just don't write code
7728 * that crashes if not.
7730 * It's permitted to call this function before showing a window,
7731 * in which case the window will be maximized when it appears onscreen
7734 * You can track maximization via the "window-state-event" signal
7739 gtk_window_maximize (GtkWindow *window)
7741 GtkWindowPrivate *priv;
7743 GdkWindow *toplevel;
7745 g_return_if_fail (GTK_IS_WINDOW (window));
7747 priv = window->priv;
7748 widget = GTK_WIDGET (window);
7750 priv->maximize_initially = TRUE;
7752 toplevel = gtk_widget_get_window (widget);
7754 if (toplevel != NULL)
7755 gdk_window_maximize (toplevel);
7759 * gtk_window_unmaximize:
7760 * @window: a #GtkWindow
7762 * Asks to unmaximize @window. Note that you shouldn't assume the
7763 * window is definitely unmaximized afterward, because other entities
7764 * (e.g. the user or <link linkend="gtk-X11-arch">window
7765 * manager</link>) could maximize it again, and not all window
7766 * managers honor requests to unmaximize. But normally the window will
7767 * end up unmaximized. Just don't write code that crashes if not.
7769 * You can track maximization via the "window-state-event" signal
7774 gtk_window_unmaximize (GtkWindow *window)
7776 GtkWindowPrivate *priv;
7778 GdkWindow *toplevel;
7780 g_return_if_fail (GTK_IS_WINDOW (window));
7782 priv = window->priv;
7783 widget = GTK_WIDGET (window);
7785 priv->maximize_initially = FALSE;
7787 toplevel = gtk_widget_get_window (widget);
7789 if (toplevel != NULL)
7790 gdk_window_unmaximize (toplevel);
7794 * gtk_window_fullscreen:
7795 * @window: a #GtkWindow
7797 * Asks to place @window in the fullscreen state. Note that you
7798 * shouldn't assume the window is definitely full screen afterward,
7799 * because other entities (e.g. the user or <link
7800 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7801 * again, and not all window managers honor requests to fullscreen
7802 * windows. But normally the window will end up fullscreen. Just
7803 * don't write code that crashes if not.
7805 * You can track the fullscreen state via the "window-state-event" signal
7811 gtk_window_fullscreen (GtkWindow *window)
7813 GtkWindowPrivate *priv;
7815 GdkWindow *toplevel;
7817 g_return_if_fail (GTK_IS_WINDOW (window));
7819 priv = window->priv;
7820 widget = GTK_WIDGET (window);
7822 priv->fullscreen_initially = TRUE;
7824 toplevel = gtk_widget_get_window (widget);
7826 if (toplevel != NULL)
7827 gdk_window_fullscreen (toplevel);
7831 * gtk_window_unfullscreen:
7832 * @window: a #GtkWindow
7834 * Asks to toggle off the fullscreen state for @window. Note that you
7835 * shouldn't assume the window is definitely not full screen
7836 * afterward, because other entities (e.g. the user or <link
7837 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7838 * again, and not all window managers honor requests to unfullscreen
7839 * windows. But normally the window will end up restored to its normal
7840 * state. Just don't write code that crashes if not.
7842 * You can track the fullscreen state via the "window-state-event" signal
7848 gtk_window_unfullscreen (GtkWindow *window)
7851 GdkWindow *toplevel;
7852 GtkWindowPrivate *priv;
7854 g_return_if_fail (GTK_IS_WINDOW (window));
7856 priv = window->priv;
7857 widget = GTK_WIDGET (window);
7859 priv->fullscreen_initially = FALSE;
7861 toplevel = gtk_widget_get_window (widget);
7863 if (toplevel != NULL)
7864 gdk_window_unfullscreen (toplevel);
7868 * gtk_window_set_keep_above:
7869 * @window: a #GtkWindow
7870 * @setting: whether to keep @window above other windows
7872 * Asks to keep @window above, so that it stays on top. Note that
7873 * you shouldn't assume the window is definitely above afterward,
7874 * because other entities (e.g. the user or <link
7875 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7876 * and not all window managers support keeping windows above. But
7877 * normally the window will end kept above. Just don't write code
7878 * that crashes if not.
7880 * It's permitted to call this function before showing a window,
7881 * in which case the window will be kept above when it appears onscreen
7884 * You can track the above state via the "window-state-event" signal
7887 * Note that, according to the <ulink
7888 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7889 * Manager Hints</ulink> specification, the above state is mainly meant
7890 * for user preferences and should not be used by applications e.g. for
7891 * drawing attention to their dialogs.
7896 gtk_window_set_keep_above (GtkWindow *window,
7900 GtkWindowPrivate *priv;
7901 GdkWindow *toplevel;
7903 g_return_if_fail (GTK_IS_WINDOW (window));
7905 priv = window->priv;
7906 widget = GTK_WIDGET (window);
7908 priv->above_initially = setting != FALSE;
7910 priv->below_initially = FALSE;
7912 toplevel = gtk_widget_get_window (widget);
7914 if (toplevel != NULL)
7915 gdk_window_set_keep_above (toplevel, setting);
7919 * gtk_window_set_keep_below:
7920 * @window: a #GtkWindow
7921 * @setting: whether to keep @window below other windows
7923 * Asks to keep @window below, so that it stays in bottom. Note that
7924 * you shouldn't assume the window is definitely below afterward,
7925 * because other entities (e.g. the user or <link
7926 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7927 * and not all window managers support putting windows below. But
7928 * normally the window will be kept below. Just don't write code
7929 * that crashes if not.
7931 * It's permitted to call this function before showing a window,
7932 * in which case the window will be kept below when it appears onscreen
7935 * You can track the below state via the "window-state-event" signal
7938 * Note that, according to the <ulink
7939 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7940 * Manager Hints</ulink> specification, the above state is mainly meant
7941 * for user preferences and should not be used by applications e.g. for
7942 * drawing attention to their dialogs.
7947 gtk_window_set_keep_below (GtkWindow *window,
7951 GtkWindowPrivate *priv;
7952 GdkWindow *toplevel;
7954 g_return_if_fail (GTK_IS_WINDOW (window));
7956 priv = window->priv;
7957 widget = GTK_WIDGET (window);
7959 priv->below_initially = setting != FALSE;
7961 priv->above_initially = FALSE;
7963 toplevel = gtk_widget_get_window (widget);
7965 if (toplevel != NULL)
7966 gdk_window_set_keep_below (toplevel, setting);
7970 * gtk_window_set_resizable:
7971 * @window: a #GtkWindow
7972 * @resizable: %TRUE if the user can resize this window
7974 * Sets whether the user can resize a window. Windows are user resizable
7978 gtk_window_set_resizable (GtkWindow *window,
7981 GtkWindowPrivate *priv;
7983 g_return_if_fail (GTK_IS_WINDOW (window));
7985 priv = window->priv;
7987 resizable = (resizable != FALSE);
7989 if (priv->resizable != resizable)
7991 priv->resizable = (resizable != FALSE);
7993 update_grip_visibility (window);
7995 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7997 g_object_notify (G_OBJECT (window), "resizable");
8002 * gtk_window_get_resizable:
8003 * @window: a #GtkWindow
8005 * Gets the value set by gtk_window_set_resizable().
8007 * Return value: %TRUE if the user can resize the window
8010 gtk_window_get_resizable (GtkWindow *window)
8012 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8014 return window->priv->resizable;
8018 * gtk_window_set_gravity:
8019 * @window: a #GtkWindow
8020 * @gravity: window gravity
8022 * Window gravity defines the meaning of coordinates passed to
8023 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8026 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8027 * typically "do what you mean."
8031 gtk_window_set_gravity (GtkWindow *window,
8034 GtkWindowPrivate *priv;
8036 g_return_if_fail (GTK_IS_WINDOW (window));
8038 priv = window->priv;
8040 if (gravity != priv->gravity)
8042 priv->gravity = gravity;
8044 /* gtk_window_move_resize() will adapt gravity
8046 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8048 g_object_notify (G_OBJECT (window), "gravity");
8053 * gtk_window_get_gravity:
8054 * @window: a #GtkWindow
8056 * Gets the value set by gtk_window_set_gravity().
8058 * Return value: (transfer none): window gravity
8061 gtk_window_get_gravity (GtkWindow *window)
8063 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8065 return window->priv->gravity;
8069 * gtk_window_begin_resize_drag:
8070 * @window: a #GtkWindow
8071 * @button: mouse button that initiated the drag
8072 * @edge: position of the resize control
8073 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8074 * @root_y: Y position where the user clicked to initiate the drag
8075 * @timestamp: timestamp from the click event that initiated the drag
8077 * Starts resizing a window. This function is used if an application
8078 * has window resizing controls. When GDK can support it, the resize
8079 * will be done using the standard mechanism for the <link
8080 * linkend="gtk-X11-arch">window manager</link> or windowing
8081 * system. Otherwise, GDK will try to emulate window resizing,
8082 * potentially not all that well, depending on the windowing system.
8086 gtk_window_begin_resize_drag (GtkWindow *window,
8094 GdkWindow *toplevel;
8096 g_return_if_fail (GTK_IS_WINDOW (window));
8097 widget = GTK_WIDGET (window);
8098 g_return_if_fail (gtk_widget_get_visible (widget));
8100 toplevel = gtk_widget_get_window (widget);
8102 gdk_window_begin_resize_drag (toplevel,
8109 * gtk_window_begin_move_drag:
8110 * @window: a #GtkWindow
8111 * @button: mouse button that initiated the drag
8112 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8113 * @root_y: Y position where the user clicked to initiate the drag
8114 * @timestamp: timestamp from the click event that initiated the drag
8116 * Starts moving a window. This function is used if an application has
8117 * window movement grips. When GDK can support it, the window movement
8118 * will be done using the standard mechanism for the <link
8119 * linkend="gtk-X11-arch">window manager</link> or windowing
8120 * system. Otherwise, GDK will try to emulate window movement,
8121 * potentially not all that well, depending on the windowing system.
8125 gtk_window_begin_move_drag (GtkWindow *window,
8132 GdkWindow *toplevel;
8134 g_return_if_fail (GTK_IS_WINDOW (window));
8135 widget = GTK_WIDGET (window);
8136 g_return_if_fail (gtk_widget_get_visible (widget));
8138 toplevel = gtk_widget_get_window (widget);
8140 gdk_window_begin_move_drag (toplevel,
8147 * gtk_window_set_screen:
8148 * @window: a #GtkWindow.
8149 * @screen: a #GdkScreen.
8151 * Sets the #GdkScreen where the @window is displayed; if
8152 * the window is already mapped, it will be unmapped, and
8153 * then remapped on the new screen.
8158 gtk_window_set_screen (GtkWindow *window,
8161 GtkWindowPrivate *priv;
8163 GdkScreen *previous_screen;
8164 gboolean was_mapped;
8166 g_return_if_fail (GTK_IS_WINDOW (window));
8167 g_return_if_fail (GDK_IS_SCREEN (screen));
8169 priv = window->priv;
8171 if (screen == priv->screen)
8174 widget = GTK_WIDGET (window);
8176 previous_screen = priv->screen;
8177 was_mapped = gtk_widget_get_mapped (widget);
8180 gtk_widget_unmap (widget);
8181 if (gtk_widget_get_realized (widget))
8182 gtk_widget_unrealize (widget);
8184 gtk_window_free_key_hash (window);
8185 priv->screen = screen;
8186 gtk_widget_reset_rc_styles (widget);
8187 if (screen != previous_screen)
8189 if (previous_screen)
8191 g_signal_handlers_disconnect_by_func (previous_screen,
8192 gtk_window_on_composited_changed, window);
8193 #ifdef GDK_WINDOWING_X11
8194 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8195 gtk_window_on_theme_variant_changed, window);
8198 g_signal_connect (screen, "composited-changed",
8199 G_CALLBACK (gtk_window_on_composited_changed), window);
8200 #ifdef GDK_WINDOWING_X11
8201 g_signal_connect (gtk_settings_get_for_screen (screen),
8202 "notify::gtk-application-prefer-dark-theme",
8203 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8206 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8207 _gtk_widget_propagate_composited_changed (widget);
8209 g_object_notify (G_OBJECT (window), "screen");
8212 gtk_widget_map (widget);
8216 gtk_window_set_theme_variant (GtkWindow *window)
8218 #ifdef GDK_WINDOWING_X11
8219 GdkWindow *gdk_window;
8220 gboolean dark_theme_requested;
8222 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8223 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8226 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8228 if (GDK_IS_X11_WINDOW (gdk_window))
8229 gdk_x11_window_set_theme_variant (gdk_window,
8230 dark_theme_requested ? "dark" : NULL);
8235 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8239 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8240 gtk_window_set_theme_variant (window);
8244 gtk_window_on_composited_changed (GdkScreen *screen,
8247 gtk_widget_queue_draw (GTK_WIDGET (window));
8249 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8253 gtk_window_check_screen (GtkWindow *window)
8255 GtkWindowPrivate *priv = window->priv;
8258 return priv->screen;
8261 g_warning ("Screen for GtkWindow not set; you must always set\n"
8262 "a screen for a GtkWindow before using the window");
8268 * gtk_window_get_screen:
8269 * @window: a #GtkWindow.
8271 * Returns the #GdkScreen associated with @window.
8273 * Return value: (transfer none): a #GdkScreen.
8278 gtk_window_get_screen (GtkWindow *window)
8280 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8282 return window->priv->screen;
8286 * gtk_window_is_active:
8287 * @window: a #GtkWindow
8289 * Returns whether the window is part of the current active toplevel.
8290 * (That is, the toplevel window receiving keystrokes.)
8291 * The return value is %TRUE if the window is active toplevel
8292 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8293 * You might use this function if you wanted to draw a widget
8294 * differently in an active window from a widget in an inactive window.
8295 * See gtk_window_has_toplevel_focus()
8297 * Return value: %TRUE if the window part of the current active window.
8302 gtk_window_is_active (GtkWindow *window)
8304 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8306 return window->priv->is_active;
8310 * gtk_window_has_toplevel_focus:
8311 * @window: a #GtkWindow
8313 * Returns whether the input focus is within this GtkWindow.
8314 * For real toplevel windows, this is identical to gtk_window_is_active(),
8315 * but for embedded windows, like #GtkPlug, the results will differ.
8317 * Return value: %TRUE if the input focus is within this GtkWindow
8322 gtk_window_has_toplevel_focus (GtkWindow *window)
8324 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8326 return window->priv->has_toplevel_focus;
8331 * SECTION:gtkwindowgroup
8332 * @Short_description: Limit the effect of grabs
8333 * @Title: GtkWindowGroup
8335 * #GtkWindowGroup objects are referenced by each window in the group,
8336 * so once you have added all windows to a #GtkWindowGroup, you can drop
8337 * the initial reference to the window group with g_object_unref(). If the
8338 * windows in the window group are subsequently destroyed, then they will
8339 * be removed from the window group and drop their references on the window
8340 * group; when all window have been removed, the window group will be
8344 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8347 gtk_window_group_init (GtkWindowGroup *group)
8349 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8350 GTK_TYPE_WINDOW_GROUP,
8351 GtkWindowGroupPrivate);
8355 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8357 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8361 * gtk_window_group_new:
8363 * Creates a new #GtkWindowGroup object. Grabs added with
8364 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8366 * Return value: a new #GtkWindowGroup.
8369 gtk_window_group_new (void)
8371 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8375 window_group_cleanup_grabs (GtkWindowGroup *group,
8378 GtkWindowGroupPrivate *priv;
8379 GtkDeviceGrabInfo *info;
8381 GSList *to_remove = NULL;
8385 tmp_list = priv->grabs;
8388 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8389 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8390 tmp_list = tmp_list->next;
8395 gtk_grab_remove (to_remove->data);
8396 g_object_unref (to_remove->data);
8397 to_remove = g_slist_delete_link (to_remove, to_remove);
8400 tmp_list = priv->device_grabs;
8404 info = tmp_list->data;
8406 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8407 to_remove = g_slist_prepend (to_remove, info);
8409 tmp_list = tmp_list->next;
8414 info = to_remove->data;
8416 gtk_device_grab_remove (info->widget, info->device);
8417 to_remove = g_slist_delete_link (to_remove, to_remove);
8422 * gtk_window_group_add_window:
8423 * @window_group: a #GtkWindowGroup
8424 * @window: the #GtkWindow to add
8426 * Adds a window to a #GtkWindowGroup.
8429 gtk_window_group_add_window (GtkWindowGroup *window_group,
8432 GtkWindowPrivate *priv;
8434 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8435 g_return_if_fail (GTK_IS_WINDOW (window));
8437 priv = window->priv;
8439 if (priv->group != window_group)
8441 g_object_ref (window);
8442 g_object_ref (window_group);
8445 gtk_window_group_remove_window (priv->group, window);
8447 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8449 priv->group = window_group;
8451 g_object_unref (window);
8456 * gtk_window_group_remove_window:
8457 * @window_group: a #GtkWindowGroup
8458 * @window: the #GtkWindow to remove
8460 * Removes a window from a #GtkWindowGroup.
8463 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8466 GtkWindowPrivate *priv;
8468 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8469 g_return_if_fail (GTK_IS_WINDOW (window));
8470 priv = window->priv;
8471 g_return_if_fail (priv->group == window_group);
8473 g_object_ref (window);
8475 window_group_cleanup_grabs (window_group, window);
8478 g_object_unref (window_group);
8479 g_object_unref (window);
8483 * gtk_window_group_list_windows:
8484 * @window_group: a #GtkWindowGroup
8486 * Returns a list of the #GtkWindows that belong to @window_group.
8488 * Returns: (element-type GtkWindow) (transfer container): A
8489 * newly-allocated list of windows inside the group.
8494 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8496 GList *toplevels, *toplevel, *group_windows;
8498 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8500 group_windows = NULL;
8501 toplevels = gtk_window_list_toplevels ();
8503 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8505 GtkWindow *window = toplevel->data;
8507 if (window_group == window->priv->group)
8508 group_windows = g_list_prepend (group_windows, window);
8511 g_list_free (toplevels);
8513 return g_list_reverse (group_windows);
8517 * gtk_window_get_group:
8518 * @window: (allow-none): a #GtkWindow, or %NULL
8520 * Returns the group for @window or the default group, if
8521 * @window is %NULL or if @window does not have an explicit
8524 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8529 gtk_window_get_group (GtkWindow *window)
8531 if (window && window->priv->group)
8532 return window->priv->group;
8535 static GtkWindowGroup *default_group = NULL;
8538 default_group = gtk_window_group_new ();
8540 return default_group;
8545 * gtk_window_has_group:
8546 * @window: a #GtkWindow
8548 * Returns whether @window has an explicit window group.
8550 * Return value: %TRUE if @window has an explicit window group.
8555 gtk_window_has_group (GtkWindow *window)
8557 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8559 return window->priv->group != NULL;
8563 * gtk_window_group_get_current_grab:
8564 * @window_group: a #GtkWindowGroup
8566 * Gets the current grab widget of the given group,
8567 * see gtk_grab_add().
8569 * Returns: (transfer none): the current grab widget of the group
8574 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8576 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8578 if (window_group->priv->grabs)
8579 return GTK_WIDGET (window_group->priv->grabs->data);
8584 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8587 GtkWindowGroupPrivate *priv;
8589 priv = window_group->priv;
8590 priv->grabs = g_slist_prepend (priv->grabs, widget);
8594 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8597 GtkWindowGroupPrivate *priv;
8599 priv = window_group->priv;
8600 priv->grabs = g_slist_remove (priv->grabs, widget);
8605 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8608 gboolean block_others)
8610 GtkWindowGroupPrivate *priv;
8611 GtkDeviceGrabInfo *info;
8613 priv = window_group->priv;
8615 info = g_slice_new0 (GtkDeviceGrabInfo);
8616 info->widget = widget;
8617 info->device = device;
8618 info->block_others = block_others;
8620 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8624 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8628 GtkWindowGroupPrivate *priv;
8629 GtkDeviceGrabInfo *info;
8630 GSList *list, *node = NULL;
8631 GdkDevice *other_device;
8633 priv = window_group->priv;
8634 other_device = gdk_device_get_associated_device (device);
8635 list = priv->device_grabs;
8641 if (info->widget == widget &&
8642 (info->device == device ||
8643 info->device == other_device))
8656 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8657 g_slice_free (GtkDeviceGrabInfo, info);
8662 * gtk_window_group_get_current_device_grab:
8663 * @window_group: a #GtkWindowGroup
8664 * @device: a #GdkDevice
8666 * Returns the current grab widget for @device, or %NULL if none.
8668 * Returns: (transfer none): The grab widget, or %NULL
8673 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8676 GtkWindowGroupPrivate *priv;
8677 GtkDeviceGrabInfo *info;
8678 GdkDevice *other_device;
8681 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8682 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8684 priv = window_group->priv;
8685 list = priv->device_grabs;
8686 other_device = gdk_device_get_associated_device (device);
8693 if (info->device == device ||
8694 info->device == other_device)
8695 return info->widget;
8702 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8706 GtkWindowGroupPrivate *priv;
8707 GtkDeviceGrabInfo *info;
8708 GdkDevice *other_device;
8711 priv = window_group->priv;
8712 other_device = gdk_device_get_associated_device (device);
8713 list = priv->device_grabs;
8720 /* Look for blocking grabs on other device pairs
8721 * that have the passed widget within the GTK+ grab.
8723 if (info->block_others &&
8724 info->device != device &&
8725 info->device != other_device &&
8726 (info->widget == widget ||
8727 gtk_widget_is_ancestor (widget, info->widget)))
8735 Derived from XParseGeometry() in XFree86
8737 Copyright 1985, 1986, 1987,1998 The Open Group
8739 All Rights Reserved.
8741 The above copyright notice and this permission notice shall be included
8742 in all copies or substantial portions of the Software.
8744 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8745 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8746 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8747 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8748 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8749 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8750 OTHER DEALINGS IN THE SOFTWARE.
8752 Except as contained in this notice, the name of The Open Group shall
8753 not be used in advertising or otherwise to promote the sale, use or
8754 other dealings in this Software without prior written authorization
8755 from The Open Group.
8760 * XParseGeometry parses strings of the form
8761 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8762 * width, height, xoffset, and yoffset are unsigned integers.
8763 * Example: "=80x24+300-49"
8764 * The equal sign is optional.
8765 * It returns a bitmask that indicates which of the four values
8766 * were actually found in the string. For each value found,
8767 * the corresponding argument is updated; for each value
8768 * not found, the corresponding argument is left unchanged.
8771 /* The following code is from Xlib, and is minimally modified, so we
8772 * can track any upstream changes if required. Don't change this
8773 * code. Or if you do, put in a huge comment marking which thing
8778 read_int (gchar *string,
8786 else if (*string == '-')
8792 for (; (*string >= '0') && (*string <= '9'); string++)
8794 result = (result * 10) + (*string - '0');
8806 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8807 * value (x, y, width, height) was found in the parsed string.
8809 #define NoValue 0x0000
8810 #define XValue 0x0001
8811 #define YValue 0x0002
8812 #define WidthValue 0x0004
8813 #define HeightValue 0x0008
8814 #define AllValues 0x000F
8815 #define XNegative 0x0010
8816 #define YNegative 0x0020
8818 /* Try not to reformat/modify, so we can compare/sync with X sources */
8820 gtk_XParseGeometry (const char *string,
8823 unsigned int *width,
8824 unsigned int *height)
8828 unsigned int tempWidth, tempHeight;
8830 char *nextCharacter;
8832 /* These initializations are just to silence gcc */
8838 if ( (string == NULL) || (*string == '\0')) return(mask);
8840 string++; /* ignore possible '=' at beg of geometry spec */
8842 strind = (char *)string;
8843 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8844 tempWidth = read_int(strind, &nextCharacter);
8845 if (strind == nextCharacter)
8847 strind = nextCharacter;
8851 if (*strind == 'x' || *strind == 'X') {
8853 tempHeight = read_int(strind, &nextCharacter);
8854 if (strind == nextCharacter)
8856 strind = nextCharacter;
8857 mask |= HeightValue;
8860 if ((*strind == '+') || (*strind == '-')) {
8861 if (*strind == '-') {
8863 tempX = -read_int(strind, &nextCharacter);
8864 if (strind == nextCharacter)
8866 strind = nextCharacter;
8872 tempX = read_int(strind, &nextCharacter);
8873 if (strind == nextCharacter)
8875 strind = nextCharacter;
8878 if ((*strind == '+') || (*strind == '-')) {
8879 if (*strind == '-') {
8881 tempY = -read_int(strind, &nextCharacter);
8882 if (strind == nextCharacter)
8884 strind = nextCharacter;
8891 tempY = read_int(strind, &nextCharacter);
8892 if (strind == nextCharacter)
8894 strind = nextCharacter;
8900 /* If strind isn't at the end of the string the it's an invalid
8901 geometry specification. */
8903 if (*strind != '\0') return (0);
8909 if (mask & WidthValue)
8911 if (mask & HeightValue)
8912 *height = tempHeight;
8917 * gtk_window_parse_geometry:
8918 * @window: a #GtkWindow
8919 * @geometry: geometry string
8921 * Parses a standard X Window System geometry string - see the
8922 * manual page for X (type 'man X') for details on this.
8923 * gtk_window_parse_geometry() does work on all GTK+ ports
8924 * including Win32 but is primarily intended for an X environment.
8926 * If either a size or a position can be extracted from the
8927 * geometry string, gtk_window_parse_geometry() returns %TRUE
8928 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8929 * to resize/move the window.
8931 * If gtk_window_parse_geometry() returns %TRUE, it will also
8932 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8933 * indicating to the window manager that the size/position of
8934 * the window was user-specified. This causes most window
8935 * managers to honor the geometry.
8937 * Note that for gtk_window_parse_geometry() to work as expected, it has
8938 * to be called when the window has its "final" size, i.e. after calling
8939 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8942 * #include <gtk/gtk.h>
8945 * fill_with_content (GtkWidget *vbox)
8947 * /* fill with content... */
8951 * main (int argc, char *argv[])
8953 * GtkWidget *window, *vbox;
8954 * GdkGeometry size_hints = {
8955 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8958 * gtk_init (&argc, &argv);
8960 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8961 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8963 * gtk_container_add (GTK_CONTAINER (window), vbox);
8964 * fill_with_content (vbox);
8965 * gtk_widget_show_all (vbox);
8967 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8970 * GDK_HINT_MIN_SIZE |
8971 * GDK_HINT_BASE_SIZE |
8972 * GDK_HINT_RESIZE_INC);
8976 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8977 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8980 * gtk_widget_show_all (window);
8987 * Return value: %TRUE if string was parsed successfully
8990 gtk_window_parse_geometry (GtkWindow *window,
8991 const gchar *geometry)
8993 gint result, x = 0, y = 0;
8997 gboolean size_set, pos_set;
9000 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9001 g_return_val_if_fail (geometry != NULL, FALSE);
9003 child = gtk_bin_get_child (GTK_BIN (window));
9004 if (!child || !gtk_widget_get_visible (child))
9005 g_warning ("gtk_window_parse_geometry() called on a window with no "
9006 "visible children; the window should be set up before "
9007 "gtk_window_parse_geometry() is called.");
9009 screen = gtk_window_check_screen (window);
9011 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9014 if ((result & WidthValue) || (result & HeightValue))
9016 gtk_window_set_default_size_internal (window,
9017 TRUE, result & WidthValue ? w : -1,
9018 TRUE, result & HeightValue ? h : -1,
9023 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9025 grav = GDK_GRAVITY_NORTH_WEST;
9027 if ((result & XNegative) && (result & YNegative))
9028 grav = GDK_GRAVITY_SOUTH_EAST;
9029 else if (result & XNegative)
9030 grav = GDK_GRAVITY_NORTH_EAST;
9031 else if (result & YNegative)
9032 grav = GDK_GRAVITY_SOUTH_WEST;
9034 if ((result & XValue) == 0)
9037 if ((result & YValue) == 0)
9040 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9041 grav == GDK_GRAVITY_SOUTH_EAST)
9042 y = gdk_screen_get_height (screen) - h + y;
9044 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9045 grav == GDK_GRAVITY_NORTH_EAST)
9046 x = gdk_screen_get_width (screen) - w + x;
9048 /* we don't let you put a window offscreen; maybe some people would
9049 * prefer to be able to, but it's kind of a bogus thing to do.
9058 if ((result & XValue) || (result & YValue))
9060 gtk_window_set_gravity (window, grav);
9061 gtk_window_move (window, x, y);
9065 if (size_set || pos_set)
9067 /* Set USSize, USPosition hints */
9068 GtkWindowGeometryInfo *info;
9070 info = gtk_window_get_geometry_info (window, TRUE);
9073 info->mask |= GDK_HINT_USER_POS;
9075 info->mask |= GDK_HINT_USER_SIZE;
9082 gtk_window_mnemonic_hash_foreach (guint keyval,
9088 GtkWindowKeysForeachFunc func;
9092 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9096 _gtk_window_keys_foreach (GtkWindow *window,
9097 GtkWindowKeysForeachFunc func,
9101 GtkMnemonicHash *mnemonic_hash;
9105 GtkWindowKeysForeachFunc func;
9109 info.window = window;
9111 info.func_data = func_data;
9113 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9115 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9116 gtk_window_mnemonic_hash_foreach, &info);
9118 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9121 GtkAccelGroup *group = groups->data;
9124 for (i = 0; i < group->priv->n_accels; i++)
9126 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9129 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9132 groups = groups->next;
9137 gtk_window_keys_changed (GtkWindow *window)
9139 gtk_window_free_key_hash (window);
9140 gtk_window_get_key_hash (window);
9143 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9145 struct _GtkWindowKeyEntry
9149 guint is_mnemonic : 1;
9153 window_key_entry_destroy (gpointer data)
9155 g_slice_free (GtkWindowKeyEntry, data);
9159 add_to_key_hash (GtkWindow *window,
9161 GdkModifierType modifiers,
9162 gboolean is_mnemonic,
9165 GtkKeyHash *key_hash = data;
9167 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9169 entry->keyval = keyval;
9170 entry->modifiers = modifiers;
9171 entry->is_mnemonic = is_mnemonic;
9173 /* GtkAccelGroup stores lowercased accelerators. To deal
9174 * with this, if <Shift> was specified, uppercase.
9176 if (modifiers & GDK_SHIFT_MASK)
9178 if (keyval == GDK_KEY_Tab)
9179 keyval = GDK_KEY_ISO_Left_Tab;
9181 keyval = gdk_keyval_to_upper (keyval);
9184 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9188 gtk_window_get_key_hash (GtkWindow *window)
9190 GdkScreen *screen = gtk_window_check_screen (window);
9191 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9196 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9197 (GDestroyNotify)window_key_entry_destroy);
9198 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9199 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9205 gtk_window_free_key_hash (GtkWindow *window)
9207 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9210 _gtk_key_hash_free (key_hash);
9211 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9216 * gtk_window_activate_key:
9217 * @window: a #GtkWindow
9218 * @event: a #GdkEventKey
9220 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9221 * called by the default ::key_press_event handler for toplevel windows,
9222 * however in some cases it may be useful to call this directly when
9223 * overriding the standard key handling for a toplevel window.
9225 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9230 gtk_window_activate_key (GtkWindow *window,
9233 GtkKeyHash *key_hash;
9234 GtkWindowKeyEntry *found_entry = NULL;
9235 gboolean enable_mnemonics;
9236 gboolean enable_accels;
9238 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9239 g_return_val_if_fail (event != NULL, FALSE);
9241 key_hash = gtk_window_get_key_hash (window);
9246 GSList *entries = _gtk_key_hash_lookup (key_hash,
9247 event->hardware_keycode,
9249 gtk_accelerator_get_default_mod_mask (),
9252 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9253 "gtk-enable-mnemonics", &enable_mnemonics,
9254 "gtk-enable-accels", &enable_accels,
9257 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9259 GtkWindowKeyEntry *entry = tmp_list->data;
9260 if (entry->is_mnemonic)
9262 if (enable_mnemonics)
9264 found_entry = entry;
9270 if (enable_accels && !found_entry)
9272 found_entry = entry;
9277 g_slist_free (entries);
9282 if (found_entry->is_mnemonic)
9284 if (enable_mnemonics)
9285 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9286 found_entry->modifiers);
9291 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9292 found_entry->modifiers);
9300 window_update_has_focus (GtkWindow *window)
9302 GtkWindowPrivate *priv = window->priv;
9303 GtkWidget *widget = GTK_WIDGET (window);
9304 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9306 if (has_focus != priv->has_focus)
9308 priv->has_focus = has_focus;
9312 if (priv->focus_widget &&
9313 priv->focus_widget != widget &&
9314 !gtk_widget_has_focus (priv->focus_widget))
9315 do_focus_change (priv->focus_widget, TRUE);
9319 if (priv->focus_widget &&
9320 priv->focus_widget != widget &&
9321 gtk_widget_has_focus (priv->focus_widget))
9322 do_focus_change (priv->focus_widget, FALSE);
9328 * _gtk_window_set_is_active:
9329 * @window: a #GtkWindow
9330 * @is_active: %TRUE if the window is in the currently active toplevel
9332 * Internal function that sets whether the #GtkWindow is part
9333 * of the currently active toplevel window (taking into account inter-process
9337 _gtk_window_set_is_active (GtkWindow *window,
9340 GtkWindowPrivate *priv;
9342 g_return_if_fail (GTK_IS_WINDOW (window));
9344 priv = window->priv;
9346 is_active = is_active != FALSE;
9348 if (is_active != priv->is_active)
9350 priv->is_active = is_active;
9351 window_update_has_focus (window);
9353 g_object_notify (G_OBJECT (window), "is-active");
9358 * _gtk_window_set_is_toplevel:
9359 * @window: a #GtkWindow
9360 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9361 * child of the root window); %FALSE if it is not (for example, for an
9362 * in-process, parented GtkPlug)
9364 * Internal function used by #GtkPlug when it gets parented/unparented by a
9365 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9366 * global list of toplevel windows.
9369 _gtk_window_set_is_toplevel (GtkWindow *window,
9370 gboolean is_toplevel)
9373 GtkWidget *toplevel;
9375 widget = GTK_WIDGET (window);
9377 if (gtk_widget_is_toplevel (widget))
9378 g_assert (g_slist_find (toplevel_list, window) != NULL);
9380 g_assert (g_slist_find (toplevel_list, window) == NULL);
9382 if (is_toplevel == gtk_widget_is_toplevel (widget))
9387 /* Pass through regular pathways of an embedded toplevel
9388 * to go through unmapping and hiding the widget before
9389 * becomming a toplevel again.
9391 * We remain hidden after becomming toplevel in order to
9392 * avoid problems during an embedded toplevel's dispose cycle
9393 * (When a toplevel window is shown it tries to grab focus again,
9394 * this causes problems while disposing).
9396 gtk_widget_hide (widget);
9398 /* Save the toplevel this widget was previously anchored into before
9399 * propagating a hierarchy-changed.
9401 * Usually this happens by way of gtk_widget_unparent() and we are
9402 * already unanchored at this point, just adding this clause incase
9403 * things happen differently.
9405 toplevel = gtk_widget_get_toplevel (widget);
9406 if (!gtk_widget_is_toplevel (toplevel))
9409 _gtk_widget_set_is_toplevel (widget, TRUE);
9411 /* When a window becomes toplevel after being embedded and anchored
9412 * into another window we need to unset its anchored flag so that
9413 * the hierarchy changed signal kicks in properly.
9415 _gtk_widget_set_anchored (widget, FALSE);
9416 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9418 toplevel_list = g_slist_prepend (toplevel_list, window);
9422 _gtk_widget_set_is_toplevel (widget, FALSE);
9423 toplevel_list = g_slist_remove (toplevel_list, window);
9425 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9430 * _gtk_window_set_has_toplevel_focus:
9431 * @window: a #GtkWindow
9432 * @has_toplevel_focus: %TRUE if the in
9434 * Internal function that sets whether the keyboard focus for the
9435 * toplevel window (taking into account inter-process embedding.)
9438 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9439 gboolean has_toplevel_focus)
9441 GtkWindowPrivate *priv;
9443 g_return_if_fail (GTK_IS_WINDOW (window));
9445 priv = window->priv;
9447 has_toplevel_focus = has_toplevel_focus != FALSE;
9449 if (has_toplevel_focus != priv->has_toplevel_focus)
9451 priv->has_toplevel_focus = has_toplevel_focus;
9452 window_update_has_focus (window);
9454 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9459 * gtk_window_set_auto_startup_notification:
9460 * @setting: %TRUE to automatically do startup notification
9462 * By default, after showing the first #GtkWindow, GTK+ calls
9463 * gdk_notify_startup_complete(). Call this function to disable
9464 * the automatic startup notification. You might do this if your
9465 * first window is a splash screen, and you want to delay notification
9466 * until after your real main window has been shown, for example.
9468 * In that example, you would disable startup notification
9469 * temporarily, show your splash screen, then re-enable it so that
9470 * showing the main window would automatically result in notification.
9475 gtk_window_set_auto_startup_notification (gboolean setting)
9477 disable_startup_notification = !setting;
9481 * gtk_window_get_window_type:
9482 * @window: a #GtkWindow
9484 * Gets the type of the window. See #GtkWindowType.
9486 * Return value: the type of the window
9491 gtk_window_get_window_type (GtkWindow *window)
9493 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9495 return window->priv->type;
9499 * gtk_window_get_mnemonics_visible:
9500 * @window: a #GtkWindow
9502 * Gets the value of the #GtkWindow:mnemonics-visible property.
9504 * Returns: %TRUE if mnemonics are supposed to be visible
9510 gtk_window_get_mnemonics_visible (GtkWindow *window)
9512 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9514 return window->priv->mnemonics_visible;
9518 * gtk_window_set_mnemonics_visible:
9519 * @window: a #GtkWindow
9520 * @setting: the new value
9522 * Sets the #GtkWindow:mnemonics-visible property.
9527 gtk_window_set_mnemonics_visible (GtkWindow *window,
9530 GtkWindowPrivate *priv;
9532 g_return_if_fail (GTK_IS_WINDOW (window));
9534 priv = window->priv;
9536 setting = setting != FALSE;
9538 if (priv->mnemonics_visible != setting)
9540 priv->mnemonics_visible = setting;
9541 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9544 priv->mnemonics_visible_set = TRUE;
9548 * gtk_window_get_focus_visible:
9549 * @window: a #GtkWindow
9551 * Gets the value of the #GtkWindow:focus-visible property.
9553 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9559 gtk_window_get_focus_visible (GtkWindow *window)
9561 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9563 return window->priv->focus_visible;
9567 * gtk_window_set_focus_visible:
9568 * @window: a #GtkWindow
9569 * @setting: the new value
9571 * Sets the #GtkWindow:focus-visible property.
9576 gtk_window_set_focus_visible (GtkWindow *window,
9579 GtkWindowPrivate *priv;
9581 g_return_if_fail (GTK_IS_WINDOW (window));
9583 priv = window->priv;
9585 setting = setting != FALSE;
9587 if (priv->focus_visible != setting)
9589 priv->focus_visible = setting;
9590 g_object_notify (G_OBJECT (window), "focus-visible");
9595 _gtk_window_get_wmclass (GtkWindow *window,
9596 gchar **wmclass_name,
9597 gchar **wmclass_class)
9599 GtkWindowPrivate *priv = window->priv;
9601 *wmclass_name = priv->wmclass_name;
9602 *wmclass_class = priv->wmclass_class;
9606 * gtk_window_set_has_user_ref_count:
9607 * @window: a #GtkWindow
9608 * @setting: the new value
9610 * Tells GTK+ whether to drop its extra reference to the window
9611 * when gtk_window_destroy() is called.
9613 * This function is only exported for the benefit of language
9614 * bindings which may need to keep the window alive until their
9615 * wrapper object is garbage collected. There is no justification
9616 * for ever calling this function in an application.
9621 gtk_window_set_has_user_ref_count (GtkWindow *window,
9624 g_return_if_fail (GTK_IS_WINDOW (window));
9626 window->priv->has_user_ref_count = setting;
9630 ensure_state_flag_window_unfocused (GtkWidget *widget)
9633 gboolean window_focused = TRUE;
9635 window = gtk_widget_get_window (widget);
9637 window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9639 if (!window_focused)
9640 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED, FALSE);
9642 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED);
9644 gtk_widget_queue_draw (widget);