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"
38 #include "gtkwindowprivate.h"
39 #include "gtkaccelgroupprivate.h"
40 #include "gtkbindings.h"
41 #include "gtkkeyhash.h"
43 #include "gtkmnemonichash.h"
44 #include "gtkmenubar.h"
45 #include "gtkiconfactory.h"
46 #include "gtkicontheme.h"
47 #include "gtkmarshalers.h"
49 #include "gtkbuildable.h"
50 #include "gtkwidgetprivate.h"
52 #include "gtktypebuiltins.h"
54 #ifdef GDK_WINDOWING_X11
61 * @short_description: Toplevel which can contain other widgets
63 * A GtkWindow is a toplevel window which can contain other widgets.
64 * Windows normally have decorations that are under the control
65 * of the windowing system and allow the user to manipulate the window
66 * (resize it, move it, close it,...).
68 * GTK+ also allows windows to have a resize grip (a small area in the lower
69 * right or left corner) which can be clicked to reszie the window. To
70 * control whether a window has a resize grip, use
71 * gtk_window_set_has_resize_grip().
73 * <refsect2 id="GtkWindow-BUILDER-UI">
74 * <title>GtkWindow as GtkBuildable</title>
76 * The GtkWindow implementation of the GtkBuildable interface supports a
77 * custom <tag class="starttag">accel-groups</tag> element, which supports
78 * any number of <tag class="starttag">group</tag> elements representing the
79 * #GtkAccelGroup objects you want to add to your window (synonymous with
80 * gtk_window_add_accel_group().
83 * <title>A UI definition fragment with accel groups</title>
84 * <programlisting><![CDATA[
85 * <object class="GtkWindow">
87 * <group name="accelgroup1"/>
93 * <object class="GtkAccelGroup" id="accelgroup1"/>
94 * ]]></programlisting>
99 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
101 struct _GtkWindowPrivate
103 GtkMnemonicHash *mnemonic_hash;
105 GtkWidget *default_widget;
106 GtkWidget *focus_widget;
107 GtkWindow *transient_parent;
108 GtkWindowGeometryInfo *geometry_info;
109 GtkWindowGroup *group;
111 GtkApplication *application;
113 GdkModifierType mnemonic_modifier;
114 GdkWindowTypeHint gdk_type_hint;
118 GdkWindow *grip_window;
122 gchar *wmclass_class;
126 guint keys_changed_handler;
128 guint16 configure_request_count;
130 /* The following flags are initially TRUE (before a window is mapped).
131 * They cause us to compute a configure request that involves
132 * default-only parameters. Once mapped, we set them to FALSE.
133 * Then we set them to TRUE again on unmap (for position)
134 * and on unrealize (for size).
136 guint need_default_position : 1;
137 guint need_default_size : 1;
139 guint above_initially : 1;
140 guint accept_focus : 1;
141 guint below_initially : 1;
142 guint builder_visible : 1;
143 guint configure_notify_received : 1;
146 guint destroy_with_parent : 1;
147 guint focus_on_map : 1;
148 guint fullscreen_initially : 1;
150 guint has_user_ref_count : 1;
151 guint has_toplevel_focus : 1;
152 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
154 guint maximize_initially : 1;
155 guint mnemonics_visible : 1;
156 guint mnemonics_visible_set : 1;
158 guint opacity_set : 1;
160 guint reset_type_hint : 1;
162 guint skips_pager : 1;
163 guint skips_taskbar : 1;
164 guint stick_initially : 1;
165 guint transient_parent_group : 1;
166 guint type : 4; /* GtkWindowType */
167 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
168 * one of the original eight. If not,
170 * GDK_WINDOW_TYPE_HINT_NORMAL
173 guint has_resize_grip : 1;
174 guint resize_grip_visible : 1; /* don't use, just for "resize-
175 * grip-visible" notification
177 guint gravity : 5; /* GdkGravity */
204 PROP_DESTROY_WITH_PARENT,
209 PROP_SKIP_TASKBAR_HINT,
210 PROP_SKIP_PAGER_HINT,
219 PROP_HAS_RESIZE_GRIP,
220 PROP_RESIZE_GRIP_VISIBLE,
222 /* Readonly properties */
224 PROP_HAS_TOPLEVEL_FOCUS,
226 /* Writeonly properties */
229 PROP_MNEMONICS_VISIBLE,
239 guint using_default_icon : 1;
240 guint using_parent_icon : 1;
241 guint using_themed_icon : 1;
245 GdkGeometry geometry; /* Last set of geometry hints we set */
246 GdkWindowHints flags;
247 GdkRectangle configure_request;
248 } GtkWindowLastGeometryInfo;
250 struct _GtkWindowGeometryInfo
252 /* Properties that the app has set on the window
254 GdkGeometry geometry; /* Geometry hints */
256 GtkWidget *widget; /* subwidget to which hints apply */
257 /* from last gtk_window_resize () - if > 0, indicates that
258 * we should resize to this size.
263 /* From last gtk_window_move () prior to mapping -
264 * only used if initial_pos_set
269 /* Default size - used only the FIRST time we map a window,
274 /* whether to use initial_x, initial_y */
275 guint initial_pos_set : 1;
276 /* CENTER_ALWAYS or other position constraint changed since
277 * we sent the last configure request.
279 guint position_constraints_changed : 1;
281 /* if true, default_width, height should be multiplied by the
282 * increments and affect the geometry widget only
284 guint default_is_geometry : 1;
286 /* if true, resize_width, height should be multiplied by the
287 * increments and affect the geometry widget only
289 guint resize_is_geometry : 1;
291 GtkWindowLastGeometryInfo last;
295 struct _GtkDeviceGrabInfo
299 guint block_others : 1;
302 struct _GtkWindowGroupPrivate
305 GSList *device_grabs;
308 static void gtk_window_dispose (GObject *object);
309 static void gtk_window_finalize (GObject *object);
310 static void gtk_window_destroy (GtkWidget *widget);
311 static void gtk_window_show (GtkWidget *widget);
312 static void gtk_window_hide (GtkWidget *widget);
313 static void gtk_window_map (GtkWidget *widget);
314 static void gtk_window_unmap (GtkWidget *widget);
315 static void gtk_window_realize (GtkWidget *widget);
316 static void gtk_window_unrealize (GtkWidget *widget);
317 static void gtk_window_size_allocate (GtkWidget *widget,
318 GtkAllocation *allocation);
319 static gboolean gtk_window_map_event (GtkWidget *widget,
321 static gint gtk_window_configure_event (GtkWidget *widget,
322 GdkEventConfigure *event);
323 static gint gtk_window_key_press_event (GtkWidget *widget,
325 static gint gtk_window_key_release_event (GtkWidget *widget,
327 static gint gtk_window_button_press_event (GtkWidget *widget,
328 GdkEventButton *event);
329 static gint gtk_window_enter_notify_event (GtkWidget *widget,
330 GdkEventCrossing *event);
331 static gint gtk_window_leave_notify_event (GtkWidget *widget,
332 GdkEventCrossing *event);
333 static gint gtk_window_focus_in_event (GtkWidget *widget,
334 GdkEventFocus *event);
335 static gint gtk_window_focus_out_event (GtkWidget *widget,
336 GdkEventFocus *event);
337 static void gtk_window_style_updated (GtkWidget *widget);
338 static gboolean gtk_window_state_event (GtkWidget *widget,
339 GdkEventWindowState *event);
340 static void gtk_window_check_resize (GtkContainer *container);
341 static gint gtk_window_focus (GtkWidget *widget,
342 GtkDirectionType direction);
343 static void gtk_window_move_focus (GtkWidget *widget,
344 GtkDirectionType dir);
345 static void gtk_window_real_set_focus (GtkWindow *window,
347 static void gtk_window_direction_changed (GtkWidget *widget,
348 GtkTextDirection prev_dir);
349 static void gtk_window_state_changed (GtkWidget *widget,
350 GtkStateType previous_state);
352 static void gtk_window_real_activate_default (GtkWindow *window);
353 static void gtk_window_real_activate_focus (GtkWindow *window);
354 static void gtk_window_keys_changed (GtkWindow *window);
355 static gint gtk_window_draw (GtkWidget *widget,
357 static void gtk_window_unset_transient_for (GtkWindow *window);
358 static void gtk_window_transient_parent_realized (GtkWidget *parent,
360 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
363 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
365 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
368 static void gtk_window_move_resize (GtkWindow *window);
369 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
371 GdkGeometry *geometry_b,
373 static void gtk_window_constrain_size (GtkWindow *window,
374 GdkGeometry *geometry,
380 static void gtk_window_constrain_position (GtkWindow *window,
385 static void gtk_window_compute_hints (GtkWindow *window,
386 GdkGeometry *new_geometry,
388 static void gtk_window_compute_configure_request (GtkWindow *window,
389 GdkRectangle *request,
390 GdkGeometry *geometry,
393 static void gtk_window_set_default_size_internal (GtkWindow *window,
394 gboolean change_width,
396 gboolean change_height,
398 gboolean is_geometry);
400 static void update_themed_icon (GtkIconTheme *theme,
402 static GList *icon_list_from_theme (GtkWidget *widget,
404 static void gtk_window_realize_icon (GtkWindow *window);
405 static void gtk_window_unrealize_icon (GtkWindow *window);
406 static void resize_grip_create_window (GtkWindow *window);
407 static void resize_grip_destroy_window (GtkWindow *window);
408 static void update_grip_visibility (GtkWindow *window);
410 static void gtk_window_notify_keys_changed (GtkWindow *window);
411 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
412 static void gtk_window_free_key_hash (GtkWindow *window);
413 static void gtk_window_on_composited_changed (GdkScreen *screen,
415 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
418 static void gtk_window_set_theme_variant (GtkWindow *window);
420 static GSList *toplevel_list = NULL;
421 static guint window_signals[LAST_SIGNAL] = { 0 };
422 static GList *default_icon_list = NULL;
423 static gchar *default_icon_name = NULL;
424 static guint default_icon_serial = 0;
425 static gboolean disable_startup_notification = FALSE;
426 static gboolean sent_startup_notification = FALSE;
428 static GQuark quark_gtk_embedded = 0;
429 static GQuark quark_gtk_window_key_hash = 0;
430 static GQuark quark_gtk_window_icon_info = 0;
431 static GQuark quark_gtk_buildable_accels = 0;
433 static GtkBuildableIface *parent_buildable_iface;
435 static void gtk_window_set_property (GObject *object,
439 static void gtk_window_get_property (GObject *object,
445 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
446 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
449 const GValue *value);
450 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
451 GtkBuilder *builder);
452 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
455 const gchar *tagname,
456 GMarkupParser *parser,
458 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
461 const gchar *tagname,
465 static void gtk_window_get_preferred_width (GtkWidget *widget,
468 static void gtk_window_get_preferred_height (GtkWidget *widget,
472 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
473 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
474 gtk_window_buildable_interface_init))
477 add_tab_bindings (GtkBindingSet *binding_set,
478 GdkModifierType modifiers,
479 GtkDirectionType direction)
481 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
483 GTK_TYPE_DIRECTION_TYPE, direction);
484 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
486 GTK_TYPE_DIRECTION_TYPE, direction);
490 add_arrow_bindings (GtkBindingSet *binding_set,
492 GtkDirectionType direction)
494 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
496 gtk_binding_entry_add_signal (binding_set, keysym, 0,
498 GTK_TYPE_DIRECTION_TYPE, direction);
499 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
501 GTK_TYPE_DIRECTION_TYPE, direction);
502 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
504 GTK_TYPE_DIRECTION_TYPE, direction);
505 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
507 GTK_TYPE_DIRECTION_TYPE, direction);
511 extract_time_from_startup_id (const gchar* startup_id)
513 gchar *timestr = g_strrstr (startup_id, "_TIME");
514 guint32 retval = GDK_CURRENT_TIME;
521 /* Skip past the "_TIME" part */
526 timestamp = g_ascii_strtoull (timestr, &end, 0);
527 if (errno == 0 && end != timestr)
535 startup_id_is_fake (const gchar* startup_id)
537 return strncmp (startup_id, "_TIME", 5) == 0;
541 gtk_window_class_init (GtkWindowClass *klass)
543 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
544 GtkWidgetClass *widget_class;
545 GtkContainerClass *container_class;
546 GtkBindingSet *binding_set;
548 widget_class = (GtkWidgetClass*) klass;
549 container_class = (GtkContainerClass*) klass;
551 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
552 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
553 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
554 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
556 gobject_class->dispose = gtk_window_dispose;
557 gobject_class->finalize = gtk_window_finalize;
559 gobject_class->set_property = gtk_window_set_property;
560 gobject_class->get_property = gtk_window_get_property;
562 widget_class->destroy = gtk_window_destroy;
563 widget_class->show = gtk_window_show;
564 widget_class->hide = gtk_window_hide;
565 widget_class->map = gtk_window_map;
566 widget_class->map_event = gtk_window_map_event;
567 widget_class->unmap = gtk_window_unmap;
568 widget_class->realize = gtk_window_realize;
569 widget_class->unrealize = gtk_window_unrealize;
570 widget_class->size_allocate = gtk_window_size_allocate;
571 widget_class->configure_event = gtk_window_configure_event;
572 widget_class->key_press_event = gtk_window_key_press_event;
573 widget_class->key_release_event = gtk_window_key_release_event;
574 widget_class->enter_notify_event = gtk_window_enter_notify_event;
575 widget_class->leave_notify_event = gtk_window_leave_notify_event;
576 widget_class->focus_in_event = gtk_window_focus_in_event;
577 widget_class->button_press_event = gtk_window_button_press_event;
578 widget_class->focus_out_event = gtk_window_focus_out_event;
579 widget_class->focus = gtk_window_focus;
580 widget_class->move_focus = gtk_window_move_focus;
581 widget_class->draw = gtk_window_draw;
582 widget_class->get_preferred_width = gtk_window_get_preferred_width;
583 widget_class->get_preferred_height = gtk_window_get_preferred_height;
584 widget_class->window_state_event = gtk_window_state_event;
585 widget_class->direction_changed = gtk_window_direction_changed;
586 widget_class->state_changed = gtk_window_state_changed;
587 widget_class->style_updated = gtk_window_style_updated;
589 container_class->check_resize = gtk_window_check_resize;
591 klass->set_focus = gtk_window_real_set_focus;
593 klass->activate_default = gtk_window_real_activate_default;
594 klass->activate_focus = gtk_window_real_activate_focus;
595 klass->keys_changed = gtk_window_keys_changed;
597 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
600 g_object_class_install_property (gobject_class,
602 g_param_spec_enum ("type",
604 P_("The type of the window"),
605 GTK_TYPE_WINDOW_TYPE,
607 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
609 g_object_class_install_property (gobject_class,
611 g_param_spec_string ("title",
613 P_("The title of the window"),
615 GTK_PARAM_READWRITE));
617 g_object_class_install_property (gobject_class,
619 g_param_spec_string ("role",
621 P_("Unique identifier for the window to be used when restoring a session"),
623 GTK_PARAM_READWRITE));
626 * GtkWindow:startup-id:
628 * The :startup-id is a write-only property for setting window's
629 * startup notification identifier. See gtk_window_set_startup_id()
634 g_object_class_install_property (gobject_class,
636 g_param_spec_string ("startup-id",
638 P_("Unique startup identifier for the window used by startup-notification"),
640 GTK_PARAM_WRITABLE));
642 g_object_class_install_property (gobject_class,
644 g_param_spec_boolean ("resizable",
646 P_("If TRUE, users can resize the window"),
648 GTK_PARAM_READWRITE));
650 g_object_class_install_property (gobject_class,
652 g_param_spec_boolean ("modal",
654 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
656 GTK_PARAM_READWRITE));
658 g_object_class_install_property (gobject_class,
660 g_param_spec_enum ("window-position",
661 P_("Window Position"),
662 P_("The initial position of the window"),
663 GTK_TYPE_WINDOW_POSITION,
665 GTK_PARAM_READWRITE));
667 g_object_class_install_property (gobject_class,
669 g_param_spec_int ("default-width",
671 P_("The default width of the window, used when initially showing the window"),
675 GTK_PARAM_READWRITE));
677 g_object_class_install_property (gobject_class,
679 g_param_spec_int ("default-height",
680 P_("Default Height"),
681 P_("The default height of the window, used when initially showing the window"),
685 GTK_PARAM_READWRITE));
687 g_object_class_install_property (gobject_class,
688 PROP_DESTROY_WITH_PARENT,
689 g_param_spec_boolean ("destroy-with-parent",
690 P_("Destroy with Parent"),
691 P_("If this window should be destroyed when the parent is destroyed"),
693 GTK_PARAM_READWRITE));
695 g_object_class_install_property (gobject_class,
697 g_param_spec_object ("icon",
699 P_("Icon for this window"),
701 GTK_PARAM_READWRITE));
702 g_object_class_install_property (gobject_class,
703 PROP_MNEMONICS_VISIBLE,
704 g_param_spec_boolean ("mnemonics-visible",
705 P_("Mnemonics Visible"),
706 P_("Whether mnemonics are currently visible in this window"),
708 GTK_PARAM_READWRITE));
711 * GtkWindow:icon-name:
713 * The :icon-name property specifies the name of the themed icon to
714 * use as the window icon. See #GtkIconTheme for more details.
718 g_object_class_install_property (gobject_class,
720 g_param_spec_string ("icon-name",
722 P_("Name of the themed icon for this window"),
724 GTK_PARAM_READWRITE));
726 g_object_class_install_property (gobject_class,
728 g_param_spec_object ("screen",
730 P_("The screen where this window will be displayed"),
732 GTK_PARAM_READWRITE));
734 g_object_class_install_property (gobject_class,
736 g_param_spec_boolean ("is-active",
738 P_("Whether the toplevel is the current active window"),
740 GTK_PARAM_READABLE));
742 g_object_class_install_property (gobject_class,
743 PROP_HAS_TOPLEVEL_FOCUS,
744 g_param_spec_boolean ("has-toplevel-focus",
745 P_("Focus in Toplevel"),
746 P_("Whether the input focus is within this GtkWindow"),
748 GTK_PARAM_READABLE));
750 g_object_class_install_property (gobject_class,
752 g_param_spec_enum ("type-hint",
754 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
755 GDK_TYPE_WINDOW_TYPE_HINT,
756 GDK_WINDOW_TYPE_HINT_NORMAL,
757 GTK_PARAM_READWRITE));
759 g_object_class_install_property (gobject_class,
760 PROP_SKIP_TASKBAR_HINT,
761 g_param_spec_boolean ("skip-taskbar-hint",
763 P_("TRUE if the window should not be in the task bar."),
765 GTK_PARAM_READWRITE));
767 g_object_class_install_property (gobject_class,
768 PROP_SKIP_PAGER_HINT,
769 g_param_spec_boolean ("skip-pager-hint",
771 P_("TRUE if the window should not be in the pager."),
773 GTK_PARAM_READWRITE));
775 g_object_class_install_property (gobject_class,
777 g_param_spec_boolean ("urgency-hint",
779 P_("TRUE if the window should be brought to the user's attention."),
781 GTK_PARAM_READWRITE));
784 * GtkWindow:accept-focus:
786 * Whether the window should receive the input focus.
790 g_object_class_install_property (gobject_class,
792 g_param_spec_boolean ("accept-focus",
794 P_("TRUE if the window should receive the input focus."),
796 GTK_PARAM_READWRITE));
799 * GtkWindow:focus-on-map:
801 * Whether the window should receive the input focus when mapped.
805 g_object_class_install_property (gobject_class,
807 g_param_spec_boolean ("focus-on-map",
809 P_("TRUE if the window should receive the input focus when mapped."),
811 GTK_PARAM_READWRITE));
814 * GtkWindow:decorated:
816 * Whether the window should be decorated by the window manager.
820 g_object_class_install_property (gobject_class,
822 g_param_spec_boolean ("decorated",
824 P_("Whether the window should be decorated by the window manager"),
826 GTK_PARAM_READWRITE));
829 * GtkWindow:deletable:
831 * Whether the window frame should have a close button.
835 g_object_class_install_property (gobject_class,
837 g_param_spec_boolean ("deletable",
839 P_("Whether the window frame should have a close button"),
841 GTK_PARAM_READWRITE));
844 * GtkWindow:has-resize-grip
846 * Whether the window has a corner resize grip.
848 * Note that the resize grip is only shown if the window is
849 * actually resizable and not maximized. Use
850 * #GtkWindow:resize-grip-visible to find out if the resize
851 * grip is currently shown.
855 g_object_class_install_property (gobject_class,
856 PROP_HAS_RESIZE_GRIP,
857 g_param_spec_boolean ("has-resize-grip",
859 P_("Specifies whether the window should have a resize grip"),
861 GTK_PARAM_READWRITE));
864 * GtkWindow:resize-grip-visible:
866 * Whether a corner resize grip is currently shown.
870 g_object_class_install_property (gobject_class,
871 PROP_RESIZE_GRIP_VISIBLE,
872 g_param_spec_boolean ("resize-grip-visible",
873 P_("Resize grip is visible"),
874 P_("Specifies whether the window's resize grip is visible."),
876 GTK_PARAM_READABLE));
882 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
883 * more details about window gravity.
887 g_object_class_install_property (gobject_class,
889 g_param_spec_enum ("gravity",
891 P_("The window gravity of the window"),
893 GDK_GRAVITY_NORTH_WEST,
894 GTK_PARAM_READWRITE));
898 * GtkWindow:transient-for:
900 * The transient parent of the window. See gtk_window_set_transient_for() for
901 * more details about transient windows.
905 g_object_class_install_property (gobject_class,
907 g_param_spec_object ("transient-for",
908 P_("Transient for Window"),
909 P_("The transient parent of the dialog"),
911 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
916 * The requested opacity of the window. See gtk_window_set_opacity() for
917 * more details about window opacity.
921 g_object_class_install_property (gobject_class,
923 g_param_spec_double ("opacity",
924 P_("Opacity for Window"),
925 P_("The opacity of the window, from 0 to 1"),
929 GTK_PARAM_READWRITE));
933 gtk_widget_class_install_style_property (widget_class,
934 g_param_spec_int ("resize-grip-width",
935 P_("Width of resize grip"),
936 P_("Width of resize grip"),
937 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
939 gtk_widget_class_install_style_property (widget_class,
940 g_param_spec_int ("resize-grip-height",
941 P_("Height of resize grip"),
942 P_("Height of resize grip"),
943 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
947 * GtkWindow:application:
949 * The #GtkApplication associated with the window.
951 * The application will be kept alive for at least as long as it
952 * has any windows associated with it (see g_application_hold()
953 * for a way to keep it alive without windows).
955 * Normally, the connection between the application and the window
956 * will remain until the window is destroyed, but you can explicitly
957 * remove it by setting the ::application property to %NULL.
961 g_object_class_install_property (gobject_class,
963 g_param_spec_object ("application",
964 P_("GtkApplication"),
965 P_("The GtkApplication for the window"),
966 GTK_TYPE_APPLICATION,
967 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
969 window_signals[SET_FOCUS] =
970 g_signal_new (I_("set-focus"),
971 G_TYPE_FROM_CLASS (gobject_class),
973 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
975 _gtk_marshal_VOID__OBJECT,
980 * GtkWindow::activate-focus:
981 * @window: the window which received the signal
983 * The ::activate-focus signal is a
984 * <link linkend="keybinding-signals">keybinding signal</link>
985 * which gets emitted when the user activates the currently
986 * focused widget of @window.
988 window_signals[ACTIVATE_FOCUS] =
989 g_signal_new (I_("activate-focus"),
990 G_TYPE_FROM_CLASS (gobject_class),
991 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
992 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
994 _gtk_marshal_VOID__VOID,
999 * GtkWindow::activate-default:
1000 * @window: the window which received the signal
1002 * The ::activate-default signal is a
1003 * <link linkend="keybinding-signals">keybinding signal</link>
1004 * which gets emitted when the user activates the default widget
1007 window_signals[ACTIVATE_DEFAULT] =
1008 g_signal_new (I_("activate-default"),
1009 G_TYPE_FROM_CLASS (gobject_class),
1010 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1011 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1013 _gtk_marshal_VOID__VOID,
1018 * GtkWindow::keys-changed:
1019 * @window: the window which received the signal
1021 * The ::keys-changed signal gets emitted when the set of accelerators
1022 * or mnemonics that are associated with @window changes.
1024 window_signals[KEYS_CHANGED] =
1025 g_signal_new (I_("keys-changed"),
1026 G_TYPE_FROM_CLASS (gobject_class),
1028 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1030 _gtk_marshal_VOID__VOID,
1038 binding_set = gtk_binding_set_by_class (klass);
1040 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1041 "activate-focus", 0);
1042 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1043 "activate-focus", 0);
1045 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1046 "activate-default", 0);
1047 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1048 "activate-default", 0);
1049 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1050 "activate-default", 0);
1052 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1053 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1054 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1055 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1057 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1058 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1059 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1060 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1064 gtk_window_init (GtkWindow *window)
1066 GtkWindowPrivate *priv;
1068 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1071 priv = window->priv;
1073 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1074 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1076 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1078 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1081 priv->wmclass_name = g_strdup (g_get_prgname ());
1082 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1083 priv->wm_role = NULL;
1084 priv->geometry_info = NULL;
1085 priv->type = GTK_WINDOW_TOPLEVEL;
1086 priv->focus_widget = NULL;
1087 priv->default_widget = NULL;
1088 priv->configure_request_count = 0;
1089 priv->resizable = TRUE;
1090 priv->configure_notify_received = FALSE;
1091 priv->position = GTK_WIN_POS_NONE;
1092 priv->need_default_size = TRUE;
1093 priv->need_default_position = TRUE;
1094 priv->modal = FALSE;
1095 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1096 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1097 priv->decorated = TRUE;
1098 priv->mnemonic_modifier = GDK_MOD1_MASK;
1099 priv->screen = gdk_screen_get_default ();
1101 priv->accept_focus = TRUE;
1102 priv->focus_on_map = TRUE;
1103 priv->deletable = TRUE;
1104 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1105 priv->opacity = 1.0;
1106 priv->startup_id = NULL;
1107 priv->has_resize_grip = TRUE;
1108 priv->mnemonics_visible = TRUE;
1110 g_object_ref_sink (window);
1111 priv->has_user_ref_count = TRUE;
1112 toplevel_list = g_slist_prepend (toplevel_list, window);
1115 g_signal_connect (priv->screen, "composited-changed",
1116 G_CALLBACK (gtk_window_on_composited_changed), window);
1118 #ifdef GDK_WINDOWING_X11
1119 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1120 "notify::gtk-application-prefer-dark-theme",
1121 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1126 gtk_window_set_property (GObject *object,
1128 const GValue *value,
1131 GtkWindow *window = GTK_WINDOW (object);
1132 GtkWindowPrivate *priv = window->priv;
1137 priv->type = g_value_get_enum (value);
1140 gtk_window_set_title (window, g_value_get_string (value));
1143 gtk_window_set_role (window, g_value_get_string (value));
1145 case PROP_STARTUP_ID:
1146 gtk_window_set_startup_id (window, g_value_get_string (value));
1148 case PROP_RESIZABLE:
1149 gtk_window_set_resizable (window, g_value_get_boolean (value));
1152 gtk_window_set_modal (window, g_value_get_boolean (value));
1155 gtk_window_set_position (window, g_value_get_enum (value));
1157 case PROP_DEFAULT_WIDTH:
1158 gtk_window_set_default_size_internal (window,
1159 TRUE, g_value_get_int (value),
1162 case PROP_DEFAULT_HEIGHT:
1163 gtk_window_set_default_size_internal (window,
1165 TRUE, g_value_get_int (value), FALSE);
1167 case PROP_DESTROY_WITH_PARENT:
1168 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1171 gtk_window_set_icon (window,
1172 g_value_get_object (value));
1174 case PROP_ICON_NAME:
1175 gtk_window_set_icon_name (window, g_value_get_string (value));
1178 gtk_window_set_screen (window, g_value_get_object (value));
1180 case PROP_TYPE_HINT:
1181 gtk_window_set_type_hint (window,
1182 g_value_get_enum (value));
1184 case PROP_SKIP_TASKBAR_HINT:
1185 gtk_window_set_skip_taskbar_hint (window,
1186 g_value_get_boolean (value));
1188 case PROP_SKIP_PAGER_HINT:
1189 gtk_window_set_skip_pager_hint (window,
1190 g_value_get_boolean (value));
1192 case PROP_URGENCY_HINT:
1193 gtk_window_set_urgency_hint (window,
1194 g_value_get_boolean (value));
1196 case PROP_ACCEPT_FOCUS:
1197 gtk_window_set_accept_focus (window,
1198 g_value_get_boolean (value));
1200 case PROP_FOCUS_ON_MAP:
1201 gtk_window_set_focus_on_map (window,
1202 g_value_get_boolean (value));
1204 case PROP_DECORATED:
1205 gtk_window_set_decorated (window, g_value_get_boolean (value));
1207 case PROP_DELETABLE:
1208 gtk_window_set_deletable (window, g_value_get_boolean (value));
1211 gtk_window_set_gravity (window, g_value_get_enum (value));
1213 case PROP_TRANSIENT_FOR:
1214 gtk_window_set_transient_for (window, g_value_get_object (value));
1217 gtk_window_set_opacity (window, g_value_get_double (value));
1219 case PROP_HAS_RESIZE_GRIP:
1220 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1222 case PROP_APPLICATION:
1223 gtk_window_set_application (window, g_value_get_object (value));
1225 case PROP_MNEMONICS_VISIBLE:
1226 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1229 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1235 gtk_window_get_property (GObject *object,
1240 GtkWindow *window = GTK_WINDOW (object);
1241 GtkWindowPrivate *priv = window->priv;
1245 GtkWindowGeometryInfo *info;
1247 g_value_set_enum (value, priv->type);
1250 g_value_set_string (value, priv->wm_role);
1253 g_value_set_string (value, priv->title);
1255 case PROP_RESIZABLE:
1256 g_value_set_boolean (value, priv->resizable);
1259 g_value_set_boolean (value, priv->modal);
1262 g_value_set_enum (value, priv->position);
1264 case PROP_DEFAULT_WIDTH:
1265 info = gtk_window_get_geometry_info (window, FALSE);
1267 g_value_set_int (value, -1);
1269 g_value_set_int (value, info->default_width);
1271 case PROP_DEFAULT_HEIGHT:
1272 info = gtk_window_get_geometry_info (window, FALSE);
1274 g_value_set_int (value, -1);
1276 g_value_set_int (value, info->default_height);
1278 case PROP_DESTROY_WITH_PARENT:
1279 g_value_set_boolean (value, priv->destroy_with_parent);
1282 g_value_set_object (value, gtk_window_get_icon (window));
1284 case PROP_ICON_NAME:
1285 g_value_set_string (value, gtk_window_get_icon_name (window));
1288 g_value_set_object (value, priv->screen);
1290 case PROP_IS_ACTIVE:
1291 g_value_set_boolean (value, priv->is_active);
1293 case PROP_HAS_TOPLEVEL_FOCUS:
1294 g_value_set_boolean (value, priv->has_toplevel_focus);
1296 case PROP_TYPE_HINT:
1297 g_value_set_enum (value, priv->type_hint);
1299 case PROP_SKIP_TASKBAR_HINT:
1300 g_value_set_boolean (value,
1301 gtk_window_get_skip_taskbar_hint (window));
1303 case PROP_SKIP_PAGER_HINT:
1304 g_value_set_boolean (value,
1305 gtk_window_get_skip_pager_hint (window));
1307 case PROP_URGENCY_HINT:
1308 g_value_set_boolean (value,
1309 gtk_window_get_urgency_hint (window));
1311 case PROP_ACCEPT_FOCUS:
1312 g_value_set_boolean (value,
1313 gtk_window_get_accept_focus (window));
1315 case PROP_FOCUS_ON_MAP:
1316 g_value_set_boolean (value,
1317 gtk_window_get_focus_on_map (window));
1319 case PROP_DECORATED:
1320 g_value_set_boolean (value, gtk_window_get_decorated (window));
1322 case PROP_DELETABLE:
1323 g_value_set_boolean (value, gtk_window_get_deletable (window));
1326 g_value_set_enum (value, gtk_window_get_gravity (window));
1328 case PROP_TRANSIENT_FOR:
1329 g_value_set_object (value, gtk_window_get_transient_for (window));
1332 g_value_set_double (value, gtk_window_get_opacity (window));
1334 case PROP_HAS_RESIZE_GRIP:
1335 g_value_set_boolean (value, priv->has_resize_grip);
1337 case PROP_RESIZE_GRIP_VISIBLE:
1338 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1340 case PROP_APPLICATION:
1341 g_value_set_object (value, gtk_window_get_application (window));
1343 case PROP_MNEMONICS_VISIBLE:
1344 g_value_set_boolean (value, priv->mnemonics_visible);
1347 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1353 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1355 parent_buildable_iface = g_type_interface_peek_parent (iface);
1356 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1357 iface->parser_finished = gtk_window_buildable_parser_finished;
1358 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1359 iface->custom_finished = gtk_window_buildable_custom_finished;
1363 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1364 GtkBuilder *builder,
1366 const GValue *value)
1368 GtkWindow *window = GTK_WINDOW (buildable);
1369 GtkWindowPrivate *priv = window->priv;
1371 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1372 priv->builder_visible = TRUE;
1374 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1378 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1379 GtkBuilder *builder)
1381 GtkWindow *window = GTK_WINDOW (buildable);
1382 GtkWindowPrivate *priv = window->priv;
1386 if (priv->builder_visible)
1387 gtk_widget_show (GTK_WIDGET (buildable));
1389 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1390 for (l = accels; l; l = l->next)
1392 object = gtk_builder_get_object (builder, l->data);
1395 g_warning ("Unknown accel group %s specified in window %s",
1396 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1399 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1400 GTK_ACCEL_GROUP (object));
1404 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1406 parent_buildable_iface->parser_finished (buildable, builder);
1412 } GSListSubParserData;
1415 window_start_element (GMarkupParseContext *context,
1416 const gchar *element_name,
1417 const gchar **names,
1418 const gchar **values,
1423 GSListSubParserData *data = (GSListSubParserData*)user_data;
1425 if (strcmp (element_name, "group") == 0)
1427 for (i = 0; names[i]; i++)
1429 if (strcmp (names[i], "name") == 0)
1430 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1433 else if (strcmp (element_name, "accel-groups") == 0)
1436 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1441 static const GMarkupParser window_parser =
1443 window_start_element
1447 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1448 GtkBuilder *builder,
1450 const gchar *tagname,
1451 GMarkupParser *parser,
1454 GSListSubParserData *parser_data;
1456 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1457 tagname, parser, data))
1460 if (strcmp (tagname, "accel-groups") == 0)
1462 parser_data = g_slice_new0 (GSListSubParserData);
1463 parser_data->items = NULL;
1464 parser_data->object = G_OBJECT (buildable);
1466 *parser = window_parser;
1467 *data = parser_data;
1475 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1476 GtkBuilder *builder,
1478 const gchar *tagname,
1481 GSListSubParserData *data;
1483 parent_buildable_iface->custom_finished (buildable, builder, child,
1484 tagname, user_data);
1486 if (strcmp (tagname, "accel-groups") != 0)
1489 data = (GSListSubParserData*)user_data;
1491 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1492 data->items, (GDestroyNotify) g_slist_free);
1494 g_slice_free (GSListSubParserData, data);
1499 * @type: type of window
1501 * Creates a new #GtkWindow, which is a toplevel window that can
1502 * contain other widgets. Nearly always, the type of the window should
1503 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1504 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1505 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1506 * dialogs, though in some other toolkits dialogs are called "popups".
1507 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1508 * On X11, popup windows are not controlled by the <link
1509 * linkend="gtk-X11-arch">window manager</link>.
1511 * If you simply want an undecorated window (no window borders), use
1512 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1514 * Return value: a new #GtkWindow.
1517 gtk_window_new (GtkWindowType type)
1519 GtkWindowPrivate *priv;
1522 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1524 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1525 priv = window->priv;
1529 return GTK_WIDGET (window);
1533 * gtk_window_set_title:
1534 * @window: a #GtkWindow
1535 * @title: title of the window
1537 * Sets the title of the #GtkWindow. The title of a window will be
1538 * displayed in its title bar; on the X Window System, the title bar
1539 * is rendered by the <link linkend="gtk-X11-arch">window
1540 * manager</link>, so exactly how the title appears to users may vary
1541 * according to a user's exact configuration. The title should help a
1542 * user distinguish this window from other windows they may have
1543 * open. A good title might include the application name and current
1544 * document filename, for example.
1548 gtk_window_set_title (GtkWindow *window,
1551 GtkWindowPrivate *priv;
1555 g_return_if_fail (GTK_IS_WINDOW (window));
1557 priv = window->priv;
1558 widget = GTK_WIDGET (window);
1560 new_title = g_strdup (title);
1561 g_free (priv->title);
1562 priv->title = new_title;
1564 if (gtk_widget_get_realized (widget))
1566 gdk_window_set_title (gtk_widget_get_window (widget),
1570 g_object_notify (G_OBJECT (window), "title");
1574 * gtk_window_get_title:
1575 * @window: a #GtkWindow
1577 * Retrieves the title of the window. See gtk_window_set_title().
1579 * Return value: the title of the window, or %NULL if none has
1580 * been set explicitely. The returned string is owned by the widget
1581 * and must not be modified or freed.
1583 G_CONST_RETURN gchar *
1584 gtk_window_get_title (GtkWindow *window)
1586 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1588 return window->priv->title;
1592 * gtk_window_set_wmclass:
1593 * @window: a #GtkWindow
1594 * @wmclass_name: window name hint
1595 * @wmclass_class: window class hint
1597 * Don't use this function. It sets the X Window System "class" and
1598 * "name" hints for a window. According to the ICCCM, you should
1599 * always set these to the same value for all windows in an
1600 * application, and GTK+ sets them to that value by default, so calling
1601 * this function is sort of pointless. However, you may want to call
1602 * gtk_window_set_role() on each window in your application, for the
1603 * benefit of the session manager. Setting the role allows the window
1604 * manager to restore window positions when loading a saved session.
1608 gtk_window_set_wmclass (GtkWindow *window,
1609 const gchar *wmclass_name,
1610 const gchar *wmclass_class)
1612 GtkWindowPrivate *priv;
1614 g_return_if_fail (GTK_IS_WINDOW (window));
1616 priv = window->priv;
1618 g_free (priv->wmclass_name);
1619 priv->wmclass_name = g_strdup (wmclass_name);
1621 g_free (priv->wmclass_class);
1622 priv->wmclass_class = g_strdup (wmclass_class);
1624 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1625 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1629 * gtk_window_set_role:
1630 * @window: a #GtkWindow
1631 * @role: unique identifier for the window to be used when restoring a session
1633 * This function is only useful on X11, not with other GTK+ targets.
1635 * In combination with the window title, the window role allows a
1636 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1637 * same" window when an application is restarted. So for example you
1638 * might set the "toolbox" role on your app's toolbox window, so that
1639 * when the user restarts their session, the window manager can put
1640 * the toolbox back in the same place.
1642 * If a window already has a unique title, you don't need to set the
1643 * role, since the WM can use the title to identify the window when
1644 * restoring the session.
1648 gtk_window_set_role (GtkWindow *window,
1651 GtkWindowPrivate *priv;
1654 g_return_if_fail (GTK_IS_WINDOW (window));
1656 priv = window->priv;
1658 new_role = g_strdup (role);
1659 g_free (priv->wm_role);
1660 priv->wm_role = new_role;
1662 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1663 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1666 g_object_notify (G_OBJECT (window), "role");
1670 * gtk_window_set_startup_id:
1671 * @window: a #GtkWindow
1672 * @startup_id: a string with startup-notification identifier
1674 * Startup notification identifiers are used by desktop environment to
1675 * track application startup, to provide user feedback and other
1676 * features. This function changes the corresponding property on the
1677 * underlying GdkWindow. Normally, startup identifier is managed
1678 * automatically and you should only use this function in special cases
1679 * like transferring focus from other processes. You should use this
1680 * function before calling gtk_window_present() or any equivalent
1681 * function generating a window map event.
1683 * This function is only useful on X11, not with other GTK+ targets.
1688 gtk_window_set_startup_id (GtkWindow *window,
1689 const gchar *startup_id)
1691 GtkWindowPrivate *priv;
1694 g_return_if_fail (GTK_IS_WINDOW (window));
1696 priv = window->priv;
1697 widget = GTK_WIDGET (window);
1699 g_free (priv->startup_id);
1700 priv->startup_id = g_strdup (startup_id);
1702 if (gtk_widget_get_realized (widget))
1704 GdkWindow *gdk_window;
1705 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1707 gdk_window = gtk_widget_get_window (widget);
1709 #ifdef GDK_WINDOWING_X11
1710 if (timestamp != GDK_CURRENT_TIME)
1711 gdk_x11_window_set_user_time (gdk_window, timestamp);
1714 /* Here we differentiate real and "fake" startup notification IDs,
1715 * constructed on purpose just to pass interaction timestamp
1717 if (startup_id_is_fake (priv->startup_id))
1718 gtk_window_present_with_time (window, timestamp);
1721 gdk_window_set_startup_id (gdk_window,
1724 /* If window is mapped, terminate the startup-notification too */
1725 if (gtk_widget_get_mapped (widget) &&
1726 !disable_startup_notification)
1727 gdk_notify_startup_complete_with_id (priv->startup_id);
1731 g_object_notify (G_OBJECT (window), "startup-id");
1735 * gtk_window_get_role:
1736 * @window: a #GtkWindow
1738 * Returns the role of the window. See gtk_window_set_role() for
1739 * further explanation.
1741 * Return value: the role of the window if set, or %NULL. The
1742 * returned is owned by the widget and must not be modified
1745 G_CONST_RETURN gchar *
1746 gtk_window_get_role (GtkWindow *window)
1748 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1750 return window->priv->wm_role;
1754 * gtk_window_set_focus:
1755 * @window: a #GtkWindow
1756 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1757 * any focus widget for the toplevel window.
1759 * If @focus is not the current focus widget, and is focusable, sets
1760 * it as the focus widget for the window. If @focus is %NULL, unsets
1761 * the focus widget for this window. To set the focus to a particular
1762 * widget in the toplevel, it is usually more convenient to use
1763 * gtk_widget_grab_focus() instead of this function.
1766 gtk_window_set_focus (GtkWindow *window,
1769 GtkWindowPrivate *priv;
1772 g_return_if_fail (GTK_IS_WINDOW (window));
1774 priv = window->priv;
1778 g_return_if_fail (GTK_IS_WIDGET (focus));
1779 g_return_if_fail (gtk_widget_get_can_focus (focus));
1783 gtk_widget_grab_focus (focus);
1786 /* Clear the existing focus chain, so that when we focus into
1787 * the window again, we start at the beginnning.
1789 GtkWidget *widget = priv->focus_widget;
1792 while ((parent = gtk_widget_get_parent (widget)))
1795 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1799 _gtk_window_internal_set_focus (window, NULL);
1804 _gtk_window_internal_set_focus (GtkWindow *window,
1807 GtkWindowPrivate *priv;
1809 g_return_if_fail (GTK_IS_WINDOW (window));
1811 priv = window->priv;
1813 if ((priv->focus_widget != focus) ||
1814 (focus && !gtk_widget_has_focus (focus)))
1815 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1819 * gtk_window_set_default:
1820 * @window: a #GtkWindow
1821 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1822 * default widget for the toplevel.
1824 * The default widget is the widget that's activated when the user
1825 * presses Enter in a dialog (for example). This function sets or
1826 * unsets the default widget for a #GtkWindow about. When setting
1827 * (rather than unsetting) the default widget it's generally easier to
1828 * call gtk_widget_grab_focus() on the widget. Before making a widget
1829 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1830 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1833 gtk_window_set_default (GtkWindow *window,
1834 GtkWidget *default_widget)
1836 GtkWindowPrivate *priv;
1838 g_return_if_fail (GTK_IS_WINDOW (window));
1840 priv = window->priv;
1843 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1845 if (priv->default_widget != default_widget)
1847 GtkWidget *old_default_widget = NULL;
1850 g_object_ref (default_widget);
1852 if (priv->default_widget)
1854 old_default_widget = priv->default_widget;
1856 if (priv->focus_widget != priv->default_widget ||
1857 !gtk_widget_get_receives_default (priv->default_widget))
1858 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1860 gtk_widget_queue_draw (priv->default_widget);
1863 priv->default_widget = default_widget;
1865 if (priv->default_widget)
1867 if (priv->focus_widget == NULL ||
1868 !gtk_widget_get_receives_default (priv->focus_widget))
1869 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1871 gtk_widget_queue_draw (priv->default_widget);
1874 if (old_default_widget)
1875 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1879 g_object_notify (G_OBJECT (default_widget), "has-default");
1880 g_object_unref (default_widget);
1886 * gtk_window_get_default_widget:
1887 * @window: a #GtkWindow
1889 * Returns the default widget for @window. See gtk_window_set_default()
1892 * Returns: (transfer none): the default widget, or %NULL if there is none.
1897 gtk_window_get_default_widget (GtkWindow *window)
1899 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1901 return window->priv->default_widget;
1905 handle_keys_changed (gpointer data)
1907 GtkWindow *window = GTK_WINDOW (data);
1908 GtkWindowPrivate *priv = window->priv;
1910 if (priv->keys_changed_handler)
1912 g_source_remove (priv->keys_changed_handler);
1913 priv->keys_changed_handler = 0;
1916 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1922 gtk_window_notify_keys_changed (GtkWindow *window)
1924 GtkWindowPrivate *priv = window->priv;
1926 if (!priv->keys_changed_handler)
1927 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1931 * gtk_window_add_accel_group:
1932 * @window: window to attach accelerator group to
1933 * @accel_group: a #GtkAccelGroup
1935 * Associate @accel_group with @window, such that calling
1936 * gtk_accel_groups_activate() on @window will activate accelerators
1940 gtk_window_add_accel_group (GtkWindow *window,
1941 GtkAccelGroup *accel_group)
1943 g_return_if_fail (GTK_IS_WINDOW (window));
1944 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1946 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1947 g_signal_connect_object (accel_group, "accel-changed",
1948 G_CALLBACK (gtk_window_notify_keys_changed),
1949 window, G_CONNECT_SWAPPED);
1950 gtk_window_notify_keys_changed (window);
1954 * gtk_window_remove_accel_group:
1955 * @window: a #GtkWindow
1956 * @accel_group: a #GtkAccelGroup
1958 * Reverses the effects of gtk_window_add_accel_group().
1961 gtk_window_remove_accel_group (GtkWindow *window,
1962 GtkAccelGroup *accel_group)
1964 g_return_if_fail (GTK_IS_WINDOW (window));
1965 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1967 g_signal_handlers_disconnect_by_func (accel_group,
1968 gtk_window_notify_keys_changed,
1970 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1971 gtk_window_notify_keys_changed (window);
1974 static GtkMnemonicHash *
1975 gtk_window_get_mnemonic_hash (GtkWindow *window,
1978 GtkWindowPrivate *private = window->priv;
1980 if (!private->mnemonic_hash && create)
1981 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1983 return private->mnemonic_hash;
1987 * gtk_window_add_mnemonic:
1988 * @window: a #GtkWindow
1989 * @keyval: the mnemonic
1990 * @target: the widget that gets activated by the mnemonic
1992 * Adds a mnemonic to this window.
1995 gtk_window_add_mnemonic (GtkWindow *window,
1999 g_return_if_fail (GTK_IS_WINDOW (window));
2000 g_return_if_fail (GTK_IS_WIDGET (target));
2002 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2004 gtk_window_notify_keys_changed (window);
2008 * gtk_window_remove_mnemonic:
2009 * @window: a #GtkWindow
2010 * @keyval: the mnemonic
2011 * @target: the widget that gets activated by the mnemonic
2013 * Removes a mnemonic from this window.
2016 gtk_window_remove_mnemonic (GtkWindow *window,
2020 g_return_if_fail (GTK_IS_WINDOW (window));
2021 g_return_if_fail (GTK_IS_WIDGET (target));
2023 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2025 gtk_window_notify_keys_changed (window);
2029 * gtk_window_mnemonic_activate:
2030 * @window: a #GtkWindow
2031 * @keyval: the mnemonic
2032 * @modifier: the modifiers
2033 * @returns: %TRUE if the activation is done.
2035 * Activates the targets associated with the mnemonic.
2038 gtk_window_mnemonic_activate (GtkWindow *window,
2040 GdkModifierType modifier)
2042 GtkWindowPrivate *priv;
2044 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2046 priv = window->priv;
2048 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2050 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2052 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2059 * gtk_window_set_mnemonic_modifier:
2060 * @window: a #GtkWindow
2061 * @modifier: the modifier mask used to activate
2062 * mnemonics on this window.
2064 * Sets the mnemonic modifier for this window.
2067 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2068 GdkModifierType modifier)
2070 GtkWindowPrivate *priv;
2072 g_return_if_fail (GTK_IS_WINDOW (window));
2073 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2075 priv = window->priv;
2077 priv->mnemonic_modifier = modifier;
2078 gtk_window_notify_keys_changed (window);
2082 * gtk_window_get_mnemonic_modifier:
2083 * @window: a #GtkWindow
2085 * Returns the mnemonic modifier for this window. See
2086 * gtk_window_set_mnemonic_modifier().
2088 * Return value: the modifier mask used to activate
2089 * mnemonics on this window.
2092 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2094 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2096 return window->priv->mnemonic_modifier;
2100 * gtk_window_set_position:
2101 * @window: a #GtkWindow.
2102 * @position: a position constraint.
2104 * Sets a position constraint for this window. If the old or new
2105 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2106 * the window to be repositioned to satisfy the new constraint.
2109 gtk_window_set_position (GtkWindow *window,
2110 GtkWindowPosition position)
2112 GtkWindowPrivate *priv;
2114 g_return_if_fail (GTK_IS_WINDOW (window));
2116 priv = window->priv;
2118 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2119 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2121 GtkWindowGeometryInfo *info;
2123 info = gtk_window_get_geometry_info (window, TRUE);
2125 /* this flag causes us to re-request the CENTER_ALWAYS
2126 * constraint in gtk_window_move_resize(), see
2127 * comment in that function.
2129 info->position_constraints_changed = TRUE;
2131 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2134 priv->position = position;
2136 g_object_notify (G_OBJECT (window), "window-position");
2140 * gtk_window_activate_focus:
2141 * @window: a #GtkWindow
2143 * Activates the current focused widget within the window.
2145 * Return value: %TRUE if a widget got activated.
2148 gtk_window_activate_focus (GtkWindow *window)
2150 GtkWindowPrivate *priv;
2152 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2154 priv = window->priv;
2156 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2157 return gtk_widget_activate (priv->focus_widget);
2163 * gtk_window_get_focus:
2164 * @window: a #GtkWindow
2166 * Retrieves the current focused widget within the window.
2167 * Note that this is the widget that would have the focus
2168 * if the toplevel window focused; if the toplevel window
2169 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2170 * not be %TRUE for the widget.
2172 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2175 gtk_window_get_focus (GtkWindow *window)
2177 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2179 return window->priv->focus_widget;
2183 * gtk_window_activate_default:
2184 * @window: a #GtkWindow
2186 * Activates the default widget for the window, unless the current
2187 * focused widget has been configured to receive the default action
2188 * (see gtk_widget_set_receives_default()), in which case the
2189 * focused widget is activated.
2191 * Return value: %TRUE if a widget got activated.
2194 gtk_window_activate_default (GtkWindow *window)
2196 GtkWindowPrivate *priv;
2198 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2200 priv = window->priv;
2202 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2203 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2204 return gtk_widget_activate (priv->default_widget);
2205 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2206 return gtk_widget_activate (priv->focus_widget);
2212 * gtk_window_set_modal:
2213 * @window: a #GtkWindow
2214 * @modal: whether the window is modal
2216 * Sets a window modal or non-modal. Modal windows prevent interaction
2217 * with other windows in the same application. To keep modal dialogs
2218 * on top of main application windows, use
2219 * gtk_window_set_transient_for() to make the dialog transient for the
2220 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2221 * will then disallow lowering the dialog below the parent.
2226 gtk_window_set_modal (GtkWindow *window,
2229 GtkWindowPrivate *priv;
2232 g_return_if_fail (GTK_IS_WINDOW (window));
2234 priv = window->priv;
2236 modal = modal != FALSE;
2237 if (priv->modal == modal)
2240 priv->modal = modal;
2241 widget = GTK_WIDGET (window);
2243 /* adjust desired modality state */
2244 if (gtk_widget_get_realized (widget))
2247 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2249 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2252 if (gtk_widget_get_visible (widget))
2255 gtk_grab_add (widget);
2257 gtk_grab_remove (widget);
2260 g_object_notify (G_OBJECT (window), "modal");
2264 * gtk_window_get_modal:
2265 * @window: a #GtkWindow
2267 * Returns whether the window is modal. See gtk_window_set_modal().
2269 * Return value: %TRUE if the window is set to be modal and
2270 * establishes a grab when shown
2273 gtk_window_get_modal (GtkWindow *window)
2275 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2277 return window->priv->modal;
2281 * gtk_window_list_toplevels:
2283 * Returns a list of all existing toplevel windows. The widgets
2284 * in the list are not individually referenced. If you want
2285 * to iterate through the list and perform actions involving
2286 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2287 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2288 * then unref all the widgets afterwards.
2290 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2293 gtk_window_list_toplevels (void)
2298 for (slist = toplevel_list; slist; slist = slist->next)
2299 list = g_list_prepend (list, slist->data);
2305 gtk_window_dispose (GObject *object)
2307 GtkWindow *window = GTK_WINDOW (object);
2309 gtk_window_set_focus (window, NULL);
2310 gtk_window_set_default (window, NULL);
2312 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2316 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2318 gtk_widget_destroy (GTK_WIDGET (child));
2322 connect_parent_destroyed (GtkWindow *window)
2324 GtkWindowPrivate *priv = window->priv;
2326 if (priv->transient_parent)
2328 g_signal_connect (priv->transient_parent,
2330 G_CALLBACK (parent_destroyed_callback),
2336 disconnect_parent_destroyed (GtkWindow *window)
2338 GtkWindowPrivate *priv = window->priv;
2340 if (priv->transient_parent)
2342 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2343 parent_destroyed_callback,
2349 gtk_window_transient_parent_realized (GtkWidget *parent,
2352 if (gtk_widget_get_realized (window))
2353 gdk_window_set_transient_for (gtk_widget_get_window (window),
2354 gtk_widget_get_window (parent));
2358 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2361 if (gtk_widget_get_realized (window))
2362 gdk_property_delete (gtk_widget_get_window (window),
2363 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2367 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2371 gtk_window_set_screen (window, parent->priv->screen);
2375 gtk_window_unset_transient_for (GtkWindow *window)
2377 GtkWindowPrivate *priv = window->priv;
2379 if (priv->transient_parent)
2381 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2382 gtk_window_transient_parent_realized,
2384 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2385 gtk_window_transient_parent_unrealized,
2387 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2388 gtk_window_transient_parent_screen_changed,
2390 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2391 gtk_widget_destroyed,
2392 &priv->transient_parent);
2394 if (priv->destroy_with_parent)
2395 disconnect_parent_destroyed (window);
2397 priv->transient_parent = NULL;
2399 if (priv->transient_parent_group)
2401 priv->transient_parent_group = FALSE;
2402 gtk_window_group_remove_window (priv->group,
2409 * gtk_window_set_transient_for:
2410 * @window: a #GtkWindow
2411 * @parent: (allow-none): parent window, or %NULL
2413 * Dialog windows should be set transient for the main application
2414 * window they were spawned from. This allows <link
2415 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2416 * dialog on top of the main window, or center the dialog over the
2417 * main window. gtk_dialog_new_with_buttons() and other convenience
2418 * functions in GTK+ will sometimes call
2419 * gtk_window_set_transient_for() on your behalf.
2421 * Passing %NULL for @parent unsets the current transient window.
2423 * On Windows, this function puts the child window on top of the parent,
2424 * much as the window manager would have done on X.
2427 gtk_window_set_transient_for (GtkWindow *window,
2430 GtkWindowPrivate *priv;
2432 g_return_if_fail (GTK_IS_WINDOW (window));
2433 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2434 g_return_if_fail (window != parent);
2436 priv = window->priv;
2438 if (priv->transient_parent)
2440 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2441 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2442 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2443 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2444 GTK_WIDGET (window));
2446 gtk_window_unset_transient_for (window);
2449 priv->transient_parent = parent;
2453 g_signal_connect (parent, "destroy",
2454 G_CALLBACK (gtk_widget_destroyed),
2455 &priv->transient_parent);
2456 g_signal_connect (parent, "realize",
2457 G_CALLBACK (gtk_window_transient_parent_realized),
2459 g_signal_connect (parent, "unrealize",
2460 G_CALLBACK (gtk_window_transient_parent_unrealized),
2462 g_signal_connect (parent, "notify::screen",
2463 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2466 gtk_window_set_screen (window, parent->priv->screen);
2468 if (priv->destroy_with_parent)
2469 connect_parent_destroyed (window);
2471 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2472 gtk_widget_get_realized (GTK_WIDGET (parent)))
2473 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2474 GTK_WIDGET (window));
2476 if (parent->priv->group)
2478 gtk_window_group_add_window (parent->priv->group, window);
2479 priv->transient_parent_group = TRUE;
2485 * gtk_window_get_transient_for:
2486 * @window: a #GtkWindow
2488 * Fetches the transient parent for this window. See
2489 * gtk_window_set_transient_for().
2491 * Return value: (transfer none): the transient parent for this window, or %NULL
2492 * if no transient parent has been set.
2495 gtk_window_get_transient_for (GtkWindow *window)
2497 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2499 return window->priv->transient_parent;
2503 * gtk_window_set_opacity:
2504 * @window: a #GtkWindow
2505 * @opacity: desired opacity, between 0 and 1
2507 * Request the windowing system to make @window partially transparent,
2508 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2509 * of the opacity parameter are clamped to the [0,1] range.) On X11
2510 * this has any effect only on X screens with a compositing manager
2511 * running. See gtk_widget_is_composited(). On Windows it should work
2514 * Note that setting a window's opacity after the window has been
2515 * shown causes it to flicker once on Windows.
2520 gtk_window_set_opacity (GtkWindow *window,
2523 GtkWindowPrivate *priv;
2525 g_return_if_fail (GTK_IS_WINDOW (window));
2527 priv = window->priv;
2531 else if (opacity > 1.0)
2534 priv->opacity_set = TRUE;
2535 priv->opacity = opacity;
2537 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2538 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2543 * gtk_window_get_opacity:
2544 * @window: a #GtkWindow
2546 * Fetches the requested opacity for this window. See
2547 * gtk_window_set_opacity().
2549 * Return value: the requested opacity for this window.
2554 gtk_window_get_opacity (GtkWindow *window)
2556 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2558 return window->priv->opacity;
2562 * gtk_window_get_application:
2563 * @window: a #GtkWindow
2565 * Gets the #GtkApplication associated with the window (if any).
2567 * Return value: (transfer none): a #GtkApplication, or %NULL
2572 gtk_window_get_application (GtkWindow *window)
2574 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2576 return window->priv->application;
2580 gtk_window_release_application (GtkWindow *window)
2582 if (window->priv->application)
2584 GtkApplication *application;
2586 /* steal reference into temp variable */
2587 application = window->priv->application;
2588 window->priv->application = NULL;
2590 gtk_application_remove_window (application, window);
2591 g_object_unref (application);
2596 * gtk_window_set_application:
2597 * @window: a #GtkWindow
2598 * @application: (allow-none): a #GtkApplication, or %NULL
2600 * Sets or unsets the #GtkApplication associated with the window.
2602 * The application will be kept alive for at least as long as the window
2608 gtk_window_set_application (GtkWindow *window,
2609 GtkApplication *application)
2611 GtkWindowPrivate *priv;
2613 g_return_if_fail (GTK_IS_WINDOW (window));
2615 priv = window->priv;
2616 if (priv->application != application)
2618 gtk_window_release_application (window);
2620 priv->application = application;
2622 if (priv->application != NULL)
2624 g_object_ref (priv->application);
2626 gtk_application_add_window (priv->application, window);
2629 g_object_notify (G_OBJECT (window), "application");
2634 * gtk_window_set_type_hint:
2635 * @window: a #GtkWindow
2636 * @hint: the window type
2638 * By setting the type hint for the window, you allow the window
2639 * manager to decorate and handle the window in a way which is
2640 * suitable to the function of the window in your application.
2642 * This function should be called before the window becomes visible.
2644 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2645 * will sometimes call gtk_window_set_type_hint() on your behalf.
2649 gtk_window_set_type_hint (GtkWindow *window,
2650 GdkWindowTypeHint hint)
2652 GtkWindowPrivate *priv;
2654 g_return_if_fail (GTK_IS_WINDOW (window));
2655 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2657 priv = window->priv;
2659 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2660 priv->type_hint = hint;
2662 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2664 priv->reset_type_hint = TRUE;
2665 priv->gdk_type_hint = hint;
2669 * gtk_window_get_type_hint:
2670 * @window: a #GtkWindow
2672 * Gets the type hint for this window. See gtk_window_set_type_hint().
2674 * Return value: the type hint for @window.
2677 gtk_window_get_type_hint (GtkWindow *window)
2679 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2681 return window->priv->gdk_type_hint;
2685 * gtk_window_set_skip_taskbar_hint:
2686 * @window: a #GtkWindow
2687 * @setting: %TRUE to keep this window from appearing in the task bar
2689 * Windows may set a hint asking the desktop environment not to display
2690 * the window in the task bar. This function sets this hint.
2695 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2698 GtkWindowPrivate *priv;
2700 g_return_if_fail (GTK_IS_WINDOW (window));
2702 priv = window->priv;
2704 setting = setting != FALSE;
2706 if (priv->skips_taskbar != setting)
2708 priv->skips_taskbar = setting;
2709 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2710 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2711 priv->skips_taskbar);
2712 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2717 * gtk_window_get_skip_taskbar_hint:
2718 * @window: a #GtkWindow
2720 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2722 * Return value: %TRUE if window shouldn't be in taskbar
2727 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2729 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2731 return window->priv->skips_taskbar;
2735 * gtk_window_set_skip_pager_hint:
2736 * @window: a #GtkWindow
2737 * @setting: %TRUE to keep this window from appearing in the pager
2739 * Windows may set a hint asking the desktop environment not to display
2740 * the window in the pager. This function sets this hint.
2741 * (A "pager" is any desktop navigation tool such as a workspace
2742 * switcher that displays a thumbnail representation of the windows
2748 gtk_window_set_skip_pager_hint (GtkWindow *window,
2751 GtkWindowPrivate *priv;
2753 g_return_if_fail (GTK_IS_WINDOW (window));
2755 priv = window->priv;
2757 setting = setting != FALSE;
2759 if (priv->skips_pager != setting)
2761 priv->skips_pager = setting;
2762 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2763 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2765 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2770 * gtk_window_get_skip_pager_hint:
2771 * @window: a #GtkWindow
2773 * Gets the value set by gtk_window_set_skip_pager_hint().
2775 * Return value: %TRUE if window shouldn't be in pager
2780 gtk_window_get_skip_pager_hint (GtkWindow *window)
2782 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2784 return window->priv->skips_pager;
2788 * gtk_window_set_urgency_hint:
2789 * @window: a #GtkWindow
2790 * @setting: %TRUE to mark this window as urgent
2792 * Windows may set a hint asking the desktop environment to draw
2793 * the users attention to the window. This function sets this hint.
2798 gtk_window_set_urgency_hint (GtkWindow *window,
2801 GtkWindowPrivate *priv;
2803 g_return_if_fail (GTK_IS_WINDOW (window));
2805 priv = window->priv;
2807 setting = setting != FALSE;
2809 if (priv->urgent != setting)
2811 priv->urgent = setting;
2812 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2813 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2815 g_object_notify (G_OBJECT (window), "urgency-hint");
2820 * gtk_window_get_urgency_hint:
2821 * @window: a #GtkWindow
2823 * Gets the value set by gtk_window_set_urgency_hint()
2825 * Return value: %TRUE if window is urgent
2830 gtk_window_get_urgency_hint (GtkWindow *window)
2832 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2834 return window->priv->urgent;
2838 * gtk_window_set_accept_focus:
2839 * @window: a #GtkWindow
2840 * @setting: %TRUE to let this window receive input focus
2842 * Windows may set a hint asking the desktop environment not to receive
2843 * the input focus. This function sets this hint.
2848 gtk_window_set_accept_focus (GtkWindow *window,
2851 GtkWindowPrivate *priv;
2853 g_return_if_fail (GTK_IS_WINDOW (window));
2855 priv = window->priv;
2857 setting = setting != FALSE;
2859 if (priv->accept_focus != setting)
2861 priv->accept_focus = setting;
2862 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2863 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2864 priv->accept_focus);
2865 g_object_notify (G_OBJECT (window), "accept-focus");
2870 * gtk_window_get_accept_focus:
2871 * @window: a #GtkWindow
2873 * Gets the value set by gtk_window_set_accept_focus().
2875 * Return value: %TRUE if window should receive the input focus
2880 gtk_window_get_accept_focus (GtkWindow *window)
2882 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2884 return window->priv->accept_focus;
2888 * gtk_window_set_focus_on_map:
2889 * @window: a #GtkWindow
2890 * @setting: %TRUE to let this window receive input focus on map
2892 * Windows may set a hint asking the desktop environment not to receive
2893 * the input focus when the window is mapped. This function sets this
2899 gtk_window_set_focus_on_map (GtkWindow *window,
2902 GtkWindowPrivate *priv;
2904 g_return_if_fail (GTK_IS_WINDOW (window));
2906 priv = window->priv;
2908 setting = setting != FALSE;
2910 if (priv->focus_on_map != setting)
2912 priv->focus_on_map = setting;
2913 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2914 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2915 priv->focus_on_map);
2916 g_object_notify (G_OBJECT (window), "focus-on-map");
2921 * gtk_window_get_focus_on_map:
2922 * @window: a #GtkWindow
2924 * Gets the value set by gtk_window_set_focus_on_map().
2926 * Return value: %TRUE if window should receive the input focus when
2932 gtk_window_get_focus_on_map (GtkWindow *window)
2934 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2936 return window->priv->focus_on_map;
2940 * gtk_window_set_destroy_with_parent:
2941 * @window: a #GtkWindow
2942 * @setting: whether to destroy @window with its transient parent
2944 * If @setting is %TRUE, then destroying the transient parent of @window
2945 * will also destroy @window itself. This is useful for dialogs that
2946 * shouldn't persist beyond the lifetime of the main window they're
2947 * associated with, for example.
2950 gtk_window_set_destroy_with_parent (GtkWindow *window,
2953 GtkWindowPrivate *priv;
2955 g_return_if_fail (GTK_IS_WINDOW (window));
2957 priv = window->priv;
2959 if (priv->destroy_with_parent == (setting != FALSE))
2962 if (priv->destroy_with_parent)
2964 disconnect_parent_destroyed (window);
2968 connect_parent_destroyed (window);
2971 priv->destroy_with_parent = setting;
2973 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2977 * gtk_window_get_destroy_with_parent:
2978 * @window: a #GtkWindow
2980 * Returns whether the window will be destroyed with its transient parent. See
2981 * gtk_window_set_destroy_with_parent ().
2983 * Return value: %TRUE if the window will be destroyed with its transient parent.
2986 gtk_window_get_destroy_with_parent (GtkWindow *window)
2988 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2990 return window->priv->destroy_with_parent;
2993 static GtkWindowGeometryInfo*
2994 gtk_window_get_geometry_info (GtkWindow *window,
2997 GtkWindowPrivate *priv = window->priv;
2998 GtkWindowGeometryInfo *info;
3000 info = priv->geometry_info;
3001 if (!info && create)
3003 info = g_new0 (GtkWindowGeometryInfo, 1);
3005 info->default_width = -1;
3006 info->default_height = -1;
3007 info->resize_width = -1;
3008 info->resize_height = -1;
3009 info->initial_x = 0;
3010 info->initial_y = 0;
3011 info->initial_pos_set = FALSE;
3012 info->default_is_geometry = FALSE;
3013 info->position_constraints_changed = FALSE;
3014 info->last.configure_request.x = 0;
3015 info->last.configure_request.y = 0;
3016 info->last.configure_request.width = -1;
3017 info->last.configure_request.height = -1;
3018 info->widget = NULL;
3020 priv->geometry_info = info;
3027 * gtk_window_set_geometry_hints:
3028 * @window: a #GtkWindow
3029 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3030 * @geometry: (allow-none): struct containing geometry information or %NULL
3031 * @geom_mask: mask indicating which struct fields should be paid attention to
3033 * This function sets up hints about how a window can be resized by
3034 * the user. You can set a minimum and maximum size; allowed resize
3035 * increments (e.g. for xterm, you can only resize by the size of a
3036 * character); aspect ratios; and more. See the #GdkGeometry struct.
3040 gtk_window_set_geometry_hints (GtkWindow *window,
3041 GtkWidget *geometry_widget,
3042 GdkGeometry *geometry,
3043 GdkWindowHints geom_mask)
3045 GtkWindowGeometryInfo *info;
3047 g_return_if_fail (GTK_IS_WINDOW (window));
3048 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3050 info = gtk_window_get_geometry_info (window, TRUE);
3053 g_signal_handlers_disconnect_by_func (info->widget,
3054 gtk_widget_destroyed,
3057 info->widget = geometry_widget;
3059 g_signal_connect (geometry_widget, "destroy",
3060 G_CALLBACK (gtk_widget_destroyed),
3064 info->geometry = *geometry;
3066 /* We store gravity in priv->gravity not in the hints. */
3067 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3069 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3071 gtk_window_set_gravity (window, geometry->win_gravity);
3074 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3078 * gtk_window_set_decorated:
3079 * @window: a #GtkWindow
3080 * @setting: %TRUE to decorate the window
3082 * By default, windows are decorated with a title bar, resize
3083 * controls, etc. Some <link linkend="gtk-X11-arch">window
3084 * managers</link> allow GTK+ to disable these decorations, creating a
3085 * borderless window. If you set the decorated property to %FALSE
3086 * using this function, GTK+ will do its best to convince the window
3087 * manager not to decorate the window. Depending on the system, this
3088 * function may not have any effect when called on a window that is
3089 * already visible, so you should call it before calling gtk_widget_show().
3091 * On Windows, this function always works, since there's no window manager
3096 gtk_window_set_decorated (GtkWindow *window,
3099 GtkWindowPrivate *priv;
3100 GdkWindow *gdk_window;
3102 g_return_if_fail (GTK_IS_WINDOW (window));
3104 priv = window->priv;
3106 setting = setting != FALSE;
3108 if (setting == priv->decorated)
3111 priv->decorated = setting;
3113 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3116 if (priv->decorated)
3117 gdk_window_set_decorations (gdk_window,
3120 gdk_window_set_decorations (gdk_window,
3124 g_object_notify (G_OBJECT (window), "decorated");
3128 * gtk_window_get_decorated:
3129 * @window: a #GtkWindow
3131 * Returns whether the window has been set to have decorations
3132 * such as a title bar via gtk_window_set_decorated().
3134 * Return value: %TRUE if the window has been set to have decorations
3137 gtk_window_get_decorated (GtkWindow *window)
3139 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3141 return window->priv->decorated;
3145 * gtk_window_set_deletable:
3146 * @window: a #GtkWindow
3147 * @setting: %TRUE to decorate the window as deletable
3149 * By default, windows have a close button in the window frame. Some
3150 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3151 * disable this button. If you set the deletable property to %FALSE
3152 * using this function, GTK+ will do its best to convince the window
3153 * manager not to show a close button. Depending on the system, this
3154 * function may not have any effect when called on a window that is
3155 * already visible, so you should call it before calling gtk_window_show().
3157 * On Windows, this function always works, since there's no window manager
3163 gtk_window_set_deletable (GtkWindow *window,
3166 GtkWindowPrivate *priv;
3167 GdkWindow *gdk_window;
3169 g_return_if_fail (GTK_IS_WINDOW (window));
3171 priv = window->priv;
3173 setting = setting != FALSE;
3175 if (setting == priv->deletable)
3178 priv->deletable = setting;
3180 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3183 if (priv->deletable)
3184 gdk_window_set_functions (gdk_window,
3187 gdk_window_set_functions (gdk_window,
3188 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3191 g_object_notify (G_OBJECT (window), "deletable");
3195 * gtk_window_get_deletable:
3196 * @window: a #GtkWindow
3198 * Returns whether the window has been set to have a close button
3199 * via gtk_window_set_deletable().
3201 * Return value: %TRUE if the window has been set to have a close button
3206 gtk_window_get_deletable (GtkWindow *window)
3208 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3210 return window->priv->deletable;
3213 static GtkWindowIconInfo*
3214 get_icon_info (GtkWindow *window)
3216 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3220 free_icon_info (GtkWindowIconInfo *info)
3222 g_free (info->icon_name);
3223 g_slice_free (GtkWindowIconInfo, info);
3227 static GtkWindowIconInfo*
3228 ensure_icon_info (GtkWindow *window)
3230 GtkWindowIconInfo *info;
3232 info = get_icon_info (window);
3236 info = g_slice_new0 (GtkWindowIconInfo);
3237 g_object_set_qdata_full (G_OBJECT (window),
3238 quark_gtk_window_icon_info,
3240 (GDestroyNotify)free_icon_info);
3247 icon_list_from_theme (GtkWidget *widget,
3252 GtkIconTheme *icon_theme;
3257 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3259 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3262 for (i = 0; sizes[i]; i++)
3265 * We need an EWMH extension to handle scalable icons
3266 * by passing their name to the WM. For now just use a
3270 icon = gtk_icon_theme_load_icon (icon_theme, name,
3273 icon = gtk_icon_theme_load_icon (icon_theme, name,
3276 list = g_list_append (list, icon);
3286 gtk_window_realize_icon (GtkWindow *window)
3288 GtkWindowPrivate *priv = window->priv;
3290 GtkWindowIconInfo *info;
3291 GdkWindow *gdk_window;
3294 widget = GTK_WIDGET (window);
3295 gdk_window = gtk_widget_get_window (widget);
3297 g_return_if_fail (gdk_window != NULL);
3299 /* no point setting an icon on override-redirect */
3300 if (priv->type == GTK_WINDOW_POPUP)
3305 info = ensure_icon_info (window);
3310 info->using_default_icon = FALSE;
3311 info->using_parent_icon = FALSE;
3312 info->using_themed_icon = FALSE;
3314 icon_list = info->icon_list;
3316 /* Look up themed icon */
3317 if (icon_list == NULL && info->icon_name)
3319 icon_list = icon_list_from_theme (widget, info->icon_name);
3321 info->using_themed_icon = TRUE;
3324 /* Inherit from transient parent */
3325 if (icon_list == NULL && priv->transient_parent)
3327 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3329 info->using_parent_icon = TRUE;
3332 /* Inherit from default */
3333 if (icon_list == NULL)
3335 icon_list = default_icon_list;
3337 info->using_default_icon = TRUE;
3340 /* Look up themed icon */
3341 if (icon_list == NULL && default_icon_name)
3343 icon_list = icon_list_from_theme (widget, default_icon_name);
3344 info->using_default_icon = TRUE;
3345 info->using_themed_icon = TRUE;
3348 info->realized = TRUE;
3350 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3352 if (info->using_themed_icon)
3354 GtkIconTheme *icon_theme;
3356 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3357 g_list_free (icon_list);
3359 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3360 g_signal_connect (icon_theme, "changed",
3361 G_CALLBACK (update_themed_icon), window);
3366 gtk_window_unrealize_icon (GtkWindow *window)
3368 GtkWindowIconInfo *info;
3370 info = get_icon_info (window);
3375 if (info->using_themed_icon)
3377 GtkIconTheme *icon_theme;
3379 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3381 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3384 /* We don't clear the properties on the window, just figure the
3385 * window is going away.
3388 info->realized = FALSE;
3393 * gtk_window_set_icon_list:
3394 * @window: a #GtkWindow
3395 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3397 * Sets up the icon representing a #GtkWindow. The icon is used when
3398 * the window is minimized (also known as iconified). Some window
3399 * managers or desktop environments may also place it in the window
3400 * frame, or display it in other contexts.
3402 * gtk_window_set_icon_list() allows you to pass in the same icon in
3403 * several hand-drawn sizes. The list should contain the natural sizes
3404 * your icon is available in; that is, don't scale the image before
3405 * passing it to GTK+. Scaling is postponed until the last minute,
3406 * when the desired final size is known, to allow best quality.
3408 * By passing several sizes, you may improve the final image quality
3409 * of the icon, by reducing or eliminating automatic image scaling.
3411 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3412 * larger images (64x64, 128x128) if you have them.
3414 * See also gtk_window_set_default_icon_list() to set the icon
3415 * for all windows in your application in one go.
3417 * Note that transient windows (those who have been set transient for another
3418 * window using gtk_window_set_transient_for()) will inherit their
3419 * icon from their transient parent. So there's no need to explicitly
3420 * set the icon on transient windows.
3423 gtk_window_set_icon_list (GtkWindow *window,
3426 GtkWindowIconInfo *info;
3428 g_return_if_fail (GTK_IS_WINDOW (window));
3430 info = ensure_icon_info (window);
3432 if (info->icon_list == list) /* check for NULL mostly */
3435 g_list_foreach (list,
3436 (GFunc) g_object_ref, NULL);
3438 g_list_foreach (info->icon_list,
3439 (GFunc) g_object_unref, NULL);
3441 g_list_free (info->icon_list);
3443 info->icon_list = g_list_copy (list);
3445 g_object_notify (G_OBJECT (window), "icon");
3447 gtk_window_unrealize_icon (window);
3449 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3450 gtk_window_realize_icon (window);
3452 /* We could try to update our transient children, but I don't think
3453 * it's really worth it. If we did it, the best way would probably
3454 * be to have children connect to notify::icon-list
3459 * gtk_window_get_icon_list:
3460 * @window: a #GtkWindow
3462 * Retrieves the list of icons set by gtk_window_set_icon_list().
3463 * The list is copied, but the reference count on each
3464 * member won't be incremented.
3466 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3469 gtk_window_get_icon_list (GtkWindow *window)
3471 GtkWindowIconInfo *info;
3473 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3475 info = get_icon_info (window);
3478 return g_list_copy (info->icon_list);
3484 * gtk_window_set_icon:
3485 * @window: a #GtkWindow
3486 * @icon: (allow-none): icon image, or %NULL
3488 * Sets up the icon representing a #GtkWindow. This icon is used when
3489 * the window is minimized (also known as iconified). Some window
3490 * managers or desktop environments may also place it in the window
3491 * frame, or display it in other contexts.
3493 * The icon should be provided in whatever size it was naturally
3494 * drawn; that is, don't scale the image before passing it to
3495 * GTK+. Scaling is postponed until the last minute, when the desired
3496 * final size is known, to allow best quality.
3498 * If you have your icon hand-drawn in multiple sizes, use
3499 * gtk_window_set_icon_list(). Then the best size will be used.
3501 * This function is equivalent to calling gtk_window_set_icon_list()
3502 * with a 1-element list.
3504 * See also gtk_window_set_default_icon_list() to set the icon
3505 * for all windows in your application in one go.
3508 gtk_window_set_icon (GtkWindow *window,
3513 g_return_if_fail (GTK_IS_WINDOW (window));
3514 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3519 list = g_list_append (list, icon);
3521 gtk_window_set_icon_list (window, list);
3527 update_themed_icon (GtkIconTheme *icon_theme,
3530 g_object_notify (G_OBJECT (window), "icon");
3532 gtk_window_unrealize_icon (window);
3534 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3535 gtk_window_realize_icon (window);
3539 * gtk_window_set_icon_name:
3540 * @window: a #GtkWindow
3541 * @name: (allow-none): the name of the themed icon
3543 * Sets the icon for the window from a named themed icon. See
3544 * the docs for #GtkIconTheme for more details.
3546 * Note that this has nothing to do with the WM_ICON_NAME
3547 * property which is mentioned in the ICCCM.
3552 gtk_window_set_icon_name (GtkWindow *window,
3555 GtkWindowIconInfo *info;
3558 g_return_if_fail (GTK_IS_WINDOW (window));
3560 info = ensure_icon_info (window);
3562 if (g_strcmp0 (info->icon_name, name) == 0)
3565 tmp = info->icon_name;
3566 info->icon_name = g_strdup (name);
3569 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3570 g_list_free (info->icon_list);
3571 info->icon_list = NULL;
3573 update_themed_icon (NULL, window);
3575 g_object_notify (G_OBJECT (window), "icon-name");
3579 * gtk_window_get_icon_name:
3580 * @window: a #GtkWindow
3582 * Returns the name of the themed icon for the window,
3583 * see gtk_window_set_icon_name().
3585 * Returns: the icon name or %NULL if the window has
3591 gtk_window_get_icon_name (GtkWindow *window)
3593 GtkWindowIconInfo *info;
3595 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3597 info = ensure_icon_info (window);
3599 return info->icon_name;
3603 * gtk_window_get_icon:
3604 * @window: a #GtkWindow
3606 * Gets the value set by gtk_window_set_icon() (or if you've
3607 * called gtk_window_set_icon_list(), gets the first icon in
3610 * Return value: (transfer none): icon for window
3613 gtk_window_get_icon (GtkWindow *window)
3615 GtkWindowIconInfo *info;
3617 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3619 info = get_icon_info (window);
3620 if (info && info->icon_list)
3621 return GDK_PIXBUF (info->icon_list->data);
3626 /* Load pixbuf, printing warning on failure if error == NULL
3629 load_pixbuf_verbosely (const char *filename,
3632 GError *local_err = NULL;
3635 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3643 g_warning ("Error loading icon from file '%s':\n\t%s",
3644 filename, local_err->message);
3645 g_error_free (local_err);
3653 * gtk_window_set_icon_from_file:
3654 * @window: a #GtkWindow
3655 * @filename: (type filename): location of icon file
3656 * @err: (allow-none): location to store error, or %NULL.
3658 * Sets the icon for @window.
3659 * Warns on failure if @err is %NULL.
3661 * This function is equivalent to calling gtk_window_set_icon()
3662 * with a pixbuf created by loading the image from @filename.
3664 * Returns: %TRUE if setting the icon succeeded.
3669 gtk_window_set_icon_from_file (GtkWindow *window,
3670 const gchar *filename,
3673 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3677 gtk_window_set_icon (window, pixbuf);
3678 g_object_unref (pixbuf);
3687 * gtk_window_set_default_icon_list:
3688 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3690 * Sets an icon list to be used as fallback for windows that haven't
3691 * had gtk_window_set_icon_list() called on them to set up a
3692 * window-specific icon list. This function allows you to set up the
3693 * icon for all windows in your app at once.
3695 * See gtk_window_set_icon_list() for more details.
3699 gtk_window_set_default_icon_list (GList *list)
3703 if (list == default_icon_list)
3706 /* Update serial so we don't used cached pixmaps/masks
3708 default_icon_serial++;
3710 g_list_foreach (list,
3711 (GFunc) g_object_ref, NULL);
3713 g_list_foreach (default_icon_list,
3714 (GFunc) g_object_unref, NULL);
3716 g_list_free (default_icon_list);
3718 default_icon_list = g_list_copy (list);
3720 /* Update all toplevels */
3721 toplevels = gtk_window_list_toplevels ();
3722 tmp_list = toplevels;
3723 while (tmp_list != NULL)
3725 GtkWindowIconInfo *info;
3726 GtkWindow *w = tmp_list->data;
3728 info = get_icon_info (w);
3729 if (info && info->using_default_icon)
3731 gtk_window_unrealize_icon (w);
3732 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3733 gtk_window_realize_icon (w);
3736 tmp_list = tmp_list->next;
3738 g_list_free (toplevels);
3742 * gtk_window_set_default_icon:
3745 * Sets an icon to be used as fallback for windows that haven't
3746 * had gtk_window_set_icon() called on them from a pixbuf.
3751 gtk_window_set_default_icon (GdkPixbuf *icon)
3755 g_return_if_fail (GDK_IS_PIXBUF (icon));
3757 list = g_list_prepend (NULL, icon);
3758 gtk_window_set_default_icon_list (list);
3763 * gtk_window_set_default_icon_name:
3764 * @name: the name of the themed icon
3766 * Sets an icon to be used as fallback for windows that haven't
3767 * had gtk_window_set_icon_list() called on them from a named
3768 * themed icon, see gtk_window_set_icon_name().
3773 gtk_window_set_default_icon_name (const gchar *name)
3778 /* Update serial so we don't used cached pixmaps/masks
3780 default_icon_serial++;
3782 g_free (default_icon_name);
3783 default_icon_name = g_strdup (name);
3785 g_list_foreach (default_icon_list,
3786 (GFunc) g_object_unref, NULL);
3788 g_list_free (default_icon_list);
3789 default_icon_list = NULL;
3791 /* Update all toplevels */
3792 toplevels = gtk_window_list_toplevels ();
3793 tmp_list = toplevels;
3794 while (tmp_list != NULL)
3796 GtkWindowIconInfo *info;
3797 GtkWindow *w = tmp_list->data;
3799 info = get_icon_info (w);
3800 if (info && info->using_default_icon && info->using_themed_icon)
3802 gtk_window_unrealize_icon (w);
3803 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3804 gtk_window_realize_icon (w);
3807 tmp_list = tmp_list->next;
3809 g_list_free (toplevels);
3813 * gtk_window_get_default_icon_name:
3815 * Returns the fallback icon name for windows that has been set
3816 * with gtk_window_set_default_icon_name(). The returned
3817 * string is owned by GTK+ and should not be modified. It
3818 * is only valid until the next call to
3819 * gtk_window_set_default_icon_name().
3821 * Returns: the fallback icon name for windows
3826 gtk_window_get_default_icon_name (void)
3828 return default_icon_name;
3832 * gtk_window_set_default_icon_from_file:
3833 * @filename: (type filename): location of icon file
3834 * @err: (allow-none): location to store error, or %NULL.
3836 * Sets an icon to be used as fallback for windows that haven't
3837 * had gtk_window_set_icon_list() called on them from a file
3838 * on disk. Warns on failure if @err is %NULL.
3840 * Returns: %TRUE if setting the icon succeeded.
3845 gtk_window_set_default_icon_from_file (const gchar *filename,
3848 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3852 gtk_window_set_default_icon (pixbuf);
3853 g_object_unref (pixbuf);
3862 * gtk_window_get_default_icon_list:
3864 * Gets the value set by gtk_window_set_default_icon_list().
3865 * The list is a copy and should be freed with g_list_free(),
3866 * but the pixbufs in the list have not had their reference count
3869 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3872 gtk_window_get_default_icon_list (void)
3874 return g_list_copy (default_icon_list);
3878 gtk_window_set_default_size_internal (GtkWindow *window,
3879 gboolean change_width,
3881 gboolean change_height,
3883 gboolean is_geometry)
3885 GtkWindowGeometryInfo *info;
3887 g_return_if_fail (change_width == FALSE || width >= -1);
3888 g_return_if_fail (change_height == FALSE || height >= -1);
3890 info = gtk_window_get_geometry_info (window, TRUE);
3892 g_object_freeze_notify (G_OBJECT (window));
3894 info->default_is_geometry = is_geometry != FALSE;
3904 info->default_width = width;
3906 g_object_notify (G_OBJECT (window), "default-width");
3917 info->default_height = height;
3919 g_object_notify (G_OBJECT (window), "default-height");
3922 g_object_thaw_notify (G_OBJECT (window));
3924 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3928 * gtk_window_set_default_size:
3929 * @window: a #GtkWindow
3930 * @width: width in pixels, or -1 to unset the default width
3931 * @height: height in pixels, or -1 to unset the default height
3933 * Sets the default size of a window. If the window's "natural" size
3934 * (its size request) is larger than the default, the default will be
3935 * ignored. More generally, if the default size does not obey the
3936 * geometry hints for the window (gtk_window_set_geometry_hints() can
3937 * be used to set these explicitly), the default size will be clamped
3938 * to the nearest permitted size.
3940 * Unlike gtk_widget_set_size_request(), which sets a size request for
3941 * a widget and thus would keep users from shrinking the window, this
3942 * function only sets the initial size, just as if the user had
3943 * resized the window themselves. Users can still shrink the window
3944 * again as they normally would. Setting a default size of -1 means to
3945 * use the "natural" default size (the size request of the window).
3947 * For more control over a window's initial size and how resizing works,
3948 * investigate gtk_window_set_geometry_hints().
3950 * For some uses, gtk_window_resize() is a more appropriate function.
3951 * gtk_window_resize() changes the current size of the window, rather
3952 * than the size to be used on initial display. gtk_window_resize() always
3953 * affects the window itself, not the geometry widget.
3955 * The default size of a window only affects the first time a window is
3956 * shown; if a window is hidden and re-shown, it will remember the size
3957 * it had prior to hiding, rather than using the default size.
3959 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3960 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3963 gtk_window_set_default_size (GtkWindow *window,
3967 g_return_if_fail (GTK_IS_WINDOW (window));
3968 g_return_if_fail (width >= -1);
3969 g_return_if_fail (height >= -1);
3971 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3975 * gtk_window_set_default_geometry:
3976 * @window: a #GtkWindow
3977 * @width: width in resize increments, or -1 to unset the default width
3978 * @height: height in resize increments, or -1 to unset the default height
3980 * Like gtk_window_set_default_size(), but @width and @height are interpreted
3981 * in terms of the base size and increment set with
3982 * gtk_window_set_geometry_hints.
3987 gtk_window_set_default_geometry (GtkWindow *window,
3991 g_return_if_fail (GTK_IS_WINDOW (window));
3992 g_return_if_fail (width >= -1);
3993 g_return_if_fail (height >= -1);
3995 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
3999 * gtk_window_get_default_size:
4000 * @window: a #GtkWindow
4001 * @width: (out) (allow-none): location to store the default width, or %NULL
4002 * @height: (out) (allow-none): location to store the default height, or %NULL
4004 * Gets the default size of the window. A value of -1 for the width or
4005 * height indicates that a default size has not been explicitly set
4006 * for that dimension, so the "natural" size of the window will be
4011 gtk_window_get_default_size (GtkWindow *window,
4015 GtkWindowGeometryInfo *info;
4017 g_return_if_fail (GTK_IS_WINDOW (window));
4019 info = gtk_window_get_geometry_info (window, FALSE);
4022 *width = info ? info->default_width : -1;
4025 *height = info ? info->default_height : -1;
4029 * gtk_window_resize:
4030 * @window: a #GtkWindow
4031 * @width: width in pixels to resize the window to
4032 * @height: height in pixels to resize the window to
4034 * Resizes the window as if the user had done so, obeying geometry
4035 * constraints. The default geometry constraint is that windows may
4036 * not be smaller than their size request; to override this
4037 * constraint, call gtk_widget_set_size_request() to set the window's
4038 * request to a smaller value.
4040 * If gtk_window_resize() is called before showing a window for the
4041 * first time, it overrides any default size set with
4042 * gtk_window_set_default_size().
4044 * Windows may not be resized smaller than 1 by 1 pixels.
4048 gtk_window_resize (GtkWindow *window,
4052 GtkWindowGeometryInfo *info;
4054 g_return_if_fail (GTK_IS_WINDOW (window));
4055 g_return_if_fail (width > 0);
4056 g_return_if_fail (height > 0);
4058 info = gtk_window_get_geometry_info (window, TRUE);
4060 info->resize_width = width;
4061 info->resize_height = height;
4062 info->resize_is_geometry = FALSE;
4064 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4068 * gtk_window_resize_to_geometry:
4069 * @window: a #GtkWindow
4070 * @width: width in resize increments to resize the window to
4071 * @height: height in resize increments to resize the window to
4073 * Like gtk_window_resize(), but @width and @height are interpreted
4074 * in terms of the base size and increment set with
4075 * gtk_window_set_geometry_hints.
4080 gtk_window_resize_to_geometry (GtkWindow *window,
4084 GtkWindowGeometryInfo *info;
4086 g_return_if_fail (GTK_IS_WINDOW (window));
4087 g_return_if_fail (width > 0);
4088 g_return_if_fail (height > 0);
4090 info = gtk_window_get_geometry_info (window, TRUE);
4092 info->resize_width = width;
4093 info->resize_height = height;
4094 info->resize_is_geometry = TRUE;
4096 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4100 * gtk_window_get_size:
4101 * @window: a #GtkWindow
4102 * @width: (out) (allow-none): return location for width, or %NULL
4103 * @height: (out) (allow-none): return location for height, or %NULL
4105 * Obtains the current size of @window. If @window is not onscreen,
4106 * it returns the size GTK+ will suggest to the <link
4107 * linkend="gtk-X11-arch">window manager</link> for the initial window
4108 * size (but this is not reliably the same as the size the window
4109 * manager will actually select). The size obtained by
4110 * gtk_window_get_size() is the last size received in a
4111 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4112 * rather than querying the X server for the size. As a result, if you
4113 * call gtk_window_resize() then immediately call
4114 * gtk_window_get_size(), the size won't have taken effect yet. After
4115 * the window manager processes the resize request, GTK+ receives
4116 * notification that the size has changed via a configure event, and
4117 * the size of the window gets updated.
4119 * Note 1: Nearly any use of this function creates a race condition,
4120 * because the size of the window may change between the time that you
4121 * get the size and the time that you perform some action assuming
4122 * that size is the current size. To avoid race conditions, connect to
4123 * "configure-event" on the window and adjust your size-dependent
4124 * state to match the size delivered in the #GdkEventConfigure.
4126 * Note 2: The returned size does <emphasis>not</emphasis> include the
4127 * size of the window manager decorations (aka the window frame or
4128 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4129 * method of determining their size.
4131 * Note 3: If you are getting a window size in order to position
4132 * the window onscreen, there may be a better way. The preferred
4133 * way is to simply set the window's semantic type with
4134 * gtk_window_set_type_hint(), which allows the window manager to
4135 * e.g. center dialogs. Also, if you set the transient parent of
4136 * dialogs with gtk_window_set_transient_for() window managers
4137 * will often center the dialog over its parent window. It's
4138 * much preferred to let the window manager handle these
4139 * things rather than doing it yourself, because all apps will
4140 * behave consistently and according to user prefs if the window
4141 * manager handles it. Also, the window manager can take the size
4142 * of the window decorations/border into account, while your
4143 * application cannot.
4145 * In any case, if you insist on application-specified window
4146 * positioning, there's <emphasis>still</emphasis> a better way than
4147 * doing it yourself - gtk_window_set_position() will frequently
4148 * handle the details for you.
4152 gtk_window_get_size (GtkWindow *window,
4158 g_return_if_fail (GTK_IS_WINDOW (window));
4160 if (width == NULL && height == NULL)
4163 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4165 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4166 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4170 GdkRectangle configure_request;
4172 gtk_window_compute_configure_request (window,
4176 w = configure_request.width;
4177 h = configure_request.height;
4188 * @window: a #GtkWindow
4189 * @x: X coordinate to move window to
4190 * @y: Y coordinate to move window to
4192 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4193 * @window to the given position. Window managers are free to ignore
4194 * this; most window managers ignore requests for initial window
4195 * positions (instead using a user-defined placement algorithm) and
4196 * honor requests after the window has already been shown.
4198 * Note: the position is the position of the gravity-determined
4199 * reference point for the window. The gravity determines two things:
4200 * first, the location of the reference point in root window
4201 * coordinates; and second, which point on the window is positioned at
4202 * the reference point.
4204 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4205 * point is simply the @x, @y supplied to gtk_window_move(). The
4206 * top-left corner of the window decorations (aka window frame or
4207 * border) will be placed at @x, @y. Therefore, to position a window
4208 * at the top left of the screen, you want to use the default gravity
4209 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4211 * To position a window at the bottom right corner of the screen, you
4212 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4213 * point is at @x + the window width and @y + the window height, and
4214 * the bottom-right corner of the window border will be placed at that
4215 * reference point. So, to place a window in the bottom right corner
4216 * you would first set gravity to south east, then write:
4217 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4218 * gdk_screen_height () - window_height)</literal> (note that this
4219 * example does not take multi-head scenarios into account).
4221 * The Extended Window Manager Hints specification at <ulink
4222 * url="http://www.freedesktop.org/Standards/wm-spec">
4223 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4224 * nice table of gravities in the "implementation notes" section.
4226 * The gtk_window_get_position() documentation may also be relevant.
4229 gtk_window_move (GtkWindow *window,
4233 GtkWindowGeometryInfo *info;
4236 g_return_if_fail (GTK_IS_WINDOW (window));
4238 widget = GTK_WIDGET (window);
4240 info = gtk_window_get_geometry_info (window, TRUE);
4242 if (gtk_widget_get_mapped (widget))
4244 GtkAllocation allocation;
4246 gtk_widget_get_allocation (widget, &allocation);
4248 /* we have now sent a request with this position
4249 * with currently-active constraints, so toggle flag.
4251 info->position_constraints_changed = FALSE;
4253 /* we only constrain if mapped - if not mapped,
4254 * then gtk_window_compute_configure_request()
4255 * will apply the constraints later, and we
4256 * don't want to lose information about
4257 * what position the user set before then.
4258 * i.e. if you do a move() then turn off POS_CENTER
4259 * then show the window, your move() will work.
4261 gtk_window_constrain_position (window,
4262 allocation.width, allocation.height,
4265 /* Note that this request doesn't go through our standard request
4266 * framework, e.g. doesn't increment configure_request_count,
4267 * doesn't set info->last, etc.; that's because
4268 * we don't save the info needed to arrive at this same request
4271 * To gtk_window_move_resize(), this will end up looking exactly
4272 * the same as the position being changed by the window
4275 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4279 /* Save this position to apply on mapping */
4280 info->initial_x = x;
4281 info->initial_y = y;
4282 info->initial_pos_set = TRUE;
4287 * gtk_window_get_position:
4288 * @window: a #GtkWindow
4289 * @root_x: (out) (allow-none): eturn location for X coordinate of
4290 * gravity-determined reference point, or %NULL
4291 * @root_y: (out) (allow-none): return location for Y coordinate of
4292 * gravity-determined reference point, or %NULL
4294 * This function returns the position you need to pass to
4295 * gtk_window_move() to keep @window in its current position.
4296 * This means that the meaning of the returned value varies with
4297 * window gravity. See gtk_window_move() for more details.
4299 * If you haven't changed the window gravity, its gravity will be
4300 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4301 * gets the position of the top-left corner of the window manager
4302 * frame for the window. gtk_window_move() sets the position of this
4303 * same top-left corner.
4305 * gtk_window_get_position() is not 100% reliable because the X Window System
4306 * does not specify a way to obtain the geometry of the
4307 * decorations placed on a window by the window manager.
4308 * Thus GTK+ is using a "best guess" that works with most
4311 * Moreover, nearly all window managers are historically broken with
4312 * respect to their handling of window gravity. So moving a window to
4313 * its current position as returned by gtk_window_get_position() tends
4314 * to result in moving the window slightly. Window managers are
4315 * slowly getting better over time.
4317 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4318 * frame is not relevant, and thus gtk_window_get_position() will
4319 * always produce accurate results. However you can't use static
4320 * gravity to do things like place a window in a corner of the screen,
4321 * because static gravity ignores the window manager decorations.
4323 * If you are saving and restoring your application's window
4324 * positions, you should know that it's impossible for applications to
4325 * do this without getting it somewhat wrong because applications do
4326 * not have sufficient knowledge of window manager state. The Correct
4327 * Mechanism is to support the session management protocol (see the
4328 * "GnomeClient" object in the GNOME libraries for example) and allow
4329 * the window manager to save your window sizes and positions.
4334 gtk_window_get_position (GtkWindow *window,
4338 GtkWindowPrivate *priv;
4340 GdkWindow *gdk_window;
4342 g_return_if_fail (GTK_IS_WINDOW (window));
4344 priv = window->priv;
4345 widget = GTK_WIDGET (window);
4346 gdk_window = gtk_widget_get_window (widget);
4348 if (priv->gravity == GDK_GRAVITY_STATIC)
4350 if (gtk_widget_get_mapped (widget))
4352 /* This does a server round-trip, which is sort of wrong;
4353 * but a server round-trip is inevitable for
4354 * gdk_window_get_frame_extents() in the usual
4355 * NorthWestGravity case below, so not sure what else to
4356 * do. We should likely be consistent about whether we get
4357 * the client-side info or the server-side info.
4359 gdk_window_get_origin (gdk_window, root_x, root_y);
4363 GdkRectangle configure_request;
4365 gtk_window_compute_configure_request (window,
4369 *root_x = configure_request.x;
4370 *root_y = configure_request.y;
4375 GdkRectangle frame_extents;
4380 if (gtk_widget_get_mapped (widget))
4382 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4383 x = frame_extents.x;
4384 y = frame_extents.y;
4385 gtk_window_get_size (window, &w, &h);
4389 /* We just say the frame has 0 size on all sides.
4390 * Not sure what else to do.
4392 gtk_window_compute_configure_request (window,
4395 x = frame_extents.x;
4396 y = frame_extents.y;
4397 w = frame_extents.width;
4398 h = frame_extents.height;
4401 switch (priv->gravity)
4403 case GDK_GRAVITY_NORTH:
4404 case GDK_GRAVITY_CENTER:
4405 case GDK_GRAVITY_SOUTH:
4406 /* Find center of frame. */
4407 x += frame_extents.width / 2;
4408 /* Center client window on that point. */
4412 case GDK_GRAVITY_SOUTH_EAST:
4413 case GDK_GRAVITY_EAST:
4414 case GDK_GRAVITY_NORTH_EAST:
4415 /* Find right edge of frame */
4416 x += frame_extents.width;
4417 /* Align left edge of client at that point. */
4424 switch (priv->gravity)
4426 case GDK_GRAVITY_WEST:
4427 case GDK_GRAVITY_CENTER:
4428 case GDK_GRAVITY_EAST:
4429 /* Find center of frame. */
4430 y += frame_extents.height / 2;
4431 /* Center client window there. */
4434 case GDK_GRAVITY_SOUTH_WEST:
4435 case GDK_GRAVITY_SOUTH:
4436 case GDK_GRAVITY_SOUTH_EAST:
4437 /* Find south edge of frame */
4438 y += frame_extents.height;
4439 /* Place bottom edge of client there */
4454 * gtk_window_reshow_with_initial_size:
4455 * @window: a #GtkWindow
4457 * Hides @window, then reshows it, resetting the
4458 * default size and position of the window. Used
4459 * by GUI builders only.
4462 gtk_window_reshow_with_initial_size (GtkWindow *window)
4466 g_return_if_fail (GTK_IS_WINDOW (window));
4468 widget = GTK_WIDGET (window);
4470 gtk_widget_hide (widget);
4471 gtk_widget_unrealize (widget);
4472 gtk_widget_show (widget);
4476 gtk_window_destroy (GtkWidget *widget)
4478 GtkWindow *window = GTK_WINDOW (widget);
4479 GtkWindowPrivate *priv = window->priv;
4481 gtk_window_release_application (window);
4483 toplevel_list = g_slist_remove (toplevel_list, window);
4485 if (priv->transient_parent)
4486 gtk_window_set_transient_for (window, NULL);
4488 /* frees the icons */
4489 gtk_window_set_icon_list (window, NULL);
4491 if (priv->has_user_ref_count)
4493 priv->has_user_ref_count = FALSE;
4494 g_object_unref (window);
4498 gtk_window_group_remove_window (priv->group, window);
4500 gtk_window_free_key_hash (window);
4502 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4506 gtk_window_finalize (GObject *object)
4508 GtkWindow *window = GTK_WINDOW (object);
4509 GtkWindowPrivate *priv = window->priv;
4510 GtkMnemonicHash *mnemonic_hash;
4512 g_free (priv->title);
4513 g_free (priv->wmclass_name);
4514 g_free (priv->wmclass_class);
4515 g_free (priv->wm_role);
4516 gtk_window_release_application (window);
4518 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4520 _gtk_mnemonic_hash_free (mnemonic_hash);
4522 if (priv->geometry_info)
4524 if (priv->geometry_info->widget)
4525 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4526 gtk_widget_destroyed,
4527 &priv->geometry_info->widget);
4528 g_free (priv->geometry_info);
4531 if (priv->keys_changed_handler)
4533 g_source_remove (priv->keys_changed_handler);
4534 priv->keys_changed_handler = 0;
4538 g_signal_handlers_disconnect_by_func (priv->screen,
4539 gtk_window_on_composited_changed, window);
4541 g_free (priv->startup_id);
4543 #ifdef GDK_WINDOWING_X11
4544 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4545 gtk_window_on_theme_variant_changed,
4549 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4553 gtk_window_show (GtkWidget *widget)
4555 GtkWindow *window = GTK_WINDOW (widget);
4556 GtkWindowPrivate *priv = window->priv;
4557 GtkContainer *container = GTK_CONTAINER (window);
4558 gboolean need_resize;
4561 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4563 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4567 _gtk_widget_set_visible_flag (widget, TRUE);
4569 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4570 _gtk_container_set_need_resize (container, FALSE);
4574 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4575 GtkAllocation allocation = { 0, 0 };
4576 GdkRectangle configure_request;
4577 GdkGeometry new_geometry;
4579 gboolean was_realized;
4581 /* We are going to go ahead and perform this configure request
4582 * and then emulate a configure notify by going ahead and
4583 * doing a size allocate. Sort of a synchronous
4584 * mini-copy of gtk_window_move_resize() here.
4586 gtk_window_compute_configure_request (window,
4591 /* We update this because we are going to go ahead
4592 * and gdk_window_resize() below, rather than
4595 info->last.configure_request.width = configure_request.width;
4596 info->last.configure_request.height = configure_request.height;
4598 /* and allocate the window - this is normally done
4599 * in move_resize in response to configure notify
4601 allocation.width = configure_request.width;
4602 allocation.height = configure_request.height;
4603 gtk_widget_size_allocate (widget, &allocation);
4605 /* Then we guarantee we have a realize */
4606 was_realized = FALSE;
4607 if (!gtk_widget_get_realized (widget))
4609 gtk_widget_realize (widget);
4610 was_realized = TRUE;
4613 /* We only send configure request if we didn't just finish
4614 * creating the window; if we just created the window
4615 * then we created it with widget->allocation anyhow.
4618 gdk_window_move_resize (gtk_widget_get_window (widget),
4619 configure_request.x,
4620 configure_request.y,
4621 configure_request.width,
4622 configure_request.height);
4625 gtk_container_check_resize (container);
4627 gtk_widget_map (widget);
4629 /* Try to make sure that we have some focused widget
4631 #ifdef GDK_WINDOWING_X11
4632 is_plug = GTK_IS_PLUG (window);
4636 if (!priv->focus_widget && !is_plug)
4637 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4640 gtk_grab_add (widget);
4644 gtk_window_hide (GtkWidget *widget)
4646 GtkWindow *window = GTK_WINDOW (widget);
4647 GtkWindowPrivate *priv = window->priv;
4649 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4651 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4655 _gtk_widget_set_visible_flag (widget, FALSE);
4656 gtk_widget_unmap (widget);
4659 gtk_grab_remove (widget);
4663 gtk_window_map (GtkWidget *widget)
4666 GtkWindow *window = GTK_WINDOW (widget);
4667 GtkWindowPrivate *priv = window->priv;
4668 GdkWindow *toplevel;
4669 GdkWindow *gdk_window;
4670 gboolean auto_mnemonics;
4672 gdk_window = gtk_widget_get_window (widget);
4674 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4676 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4680 gtk_widget_set_mapped (widget, TRUE);
4682 child = gtk_bin_get_child (&(window->bin));
4684 gtk_widget_get_visible (child) &&
4685 !gtk_widget_get_mapped (child))
4686 gtk_widget_map (child);
4688 toplevel = gdk_window;
4690 if (priv->maximize_initially)
4691 gdk_window_maximize (toplevel);
4693 gdk_window_unmaximize (toplevel);
4695 if (priv->stick_initially)
4696 gdk_window_stick (toplevel);
4698 gdk_window_unstick (toplevel);
4700 if (priv->iconify_initially)
4701 gdk_window_iconify (toplevel);
4703 gdk_window_deiconify (toplevel);
4705 if (priv->fullscreen_initially)
4706 gdk_window_fullscreen (toplevel);
4708 gdk_window_unfullscreen (toplevel);
4710 gdk_window_set_keep_above (toplevel, priv->above_initially);
4712 gdk_window_set_keep_below (toplevel, priv->below_initially);
4714 if (priv->type == GTK_WINDOW_TOPLEVEL)
4715 gtk_window_set_theme_variant (window);
4717 /* No longer use the default settings */
4718 priv->need_default_size = FALSE;
4719 priv->need_default_position = FALSE;
4721 if (priv->reset_type_hint)
4723 /* We should only reset the type hint when the application
4724 * used gtk_window_set_type_hint() to change the hint.
4725 * Some applications use X directly to change the properties;
4726 * in that case, we shouldn't overwrite what they did.
4728 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4729 priv->reset_type_hint = FALSE;
4732 gdk_window_show (gdk_window);
4734 if (priv->grip_window)
4735 gdk_window_show (priv->grip_window);
4737 if (!disable_startup_notification)
4739 /* Do we have a custom startup-notification id? */
4740 if (priv->startup_id != NULL)
4742 /* Make sure we have a "real" id */
4743 if (!startup_id_is_fake (priv->startup_id))
4744 gdk_notify_startup_complete_with_id (priv->startup_id);
4746 g_free (priv->startup_id);
4747 priv->startup_id = NULL;
4749 else if (!sent_startup_notification)
4751 sent_startup_notification = TRUE;
4752 gdk_notify_startup_complete ();
4756 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4757 * (as in the case of popup menus), then hide mnemonics initially
4759 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4760 &auto_mnemonics, NULL);
4761 if (auto_mnemonics && !priv->mnemonics_visible_set)
4762 gtk_window_set_mnemonics_visible (window, FALSE);
4766 gtk_window_map_event (GtkWidget *widget,
4769 if (!gtk_widget_get_mapped (widget))
4771 /* we should be be unmapped, but are getting a MapEvent, this may happen
4772 * to toplevel XWindows if mapping was intercepted by a window manager
4773 * and an unmap request occoured while the MapRequestEvent was still
4774 * being handled. we work around this situaiton here by re-requesting
4775 * the window being unmapped. more details can be found in:
4776 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4778 gdk_window_hide (gtk_widget_get_window (widget));
4784 gtk_window_unmap (GtkWidget *widget)
4786 GtkWindow *window = GTK_WINDOW (widget);
4787 GtkWindowPrivate *priv = window->priv;
4789 GtkWindowGeometryInfo *info;
4790 GdkWindow *gdk_window;
4791 GdkWindowState state;
4793 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4795 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
4799 gdk_window = gtk_widget_get_window (widget);
4801 gtk_widget_set_mapped (widget, FALSE);
4802 gdk_window_withdraw (gdk_window);
4804 priv->configure_request_count = 0;
4805 priv->configure_notify_received = FALSE;
4807 /* on unmap, we reset the default positioning of the window,
4808 * so it's placed again, but we don't reset the default
4809 * size of the window, so it's remembered.
4811 priv->need_default_position = TRUE;
4813 info = gtk_window_get_geometry_info (window, FALSE);
4816 info->initial_pos_set = FALSE;
4817 info->position_constraints_changed = FALSE;
4820 state = gdk_window_get_state (gdk_window);
4821 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4822 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4823 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4824 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4825 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4827 child = gtk_bin_get_child (&(window->bin));
4829 gtk_widget_unmap (child);
4833 gtk_window_realize (GtkWidget *widget)
4835 GtkAllocation allocation;
4837 GdkWindow *parent_window;
4838 GdkWindow *gdk_window;
4839 GdkWindowAttr attributes;
4840 gint attributes_mask;
4841 GtkWindowPrivate *priv;
4842 GtkStyleContext *context;
4844 window = GTK_WINDOW (widget);
4845 priv = window->priv;
4847 gtk_widget_get_allocation (widget, &allocation);
4849 if (gtk_widget_get_parent_window (widget))
4851 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
4853 gtk_widget_set_realized (widget, TRUE);
4855 attributes.x = allocation.x;
4856 attributes.y = allocation.y;
4857 attributes.width = allocation.width;
4858 attributes.height = allocation.height;
4859 attributes.window_type = GDK_WINDOW_CHILD;
4861 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
4863 attributes.visual = gtk_widget_get_visual (widget);
4864 attributes.wclass = GDK_INPUT_OUTPUT;
4866 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
4868 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
4869 &attributes, attributes_mask);
4870 gtk_widget_set_window (widget, gdk_window);
4871 gdk_window_set_user_data (gdk_window, widget);
4873 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
4875 gdk_window_enable_synchronized_configure (gdk_window);
4879 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
4881 /* ensure widget tree is properly size allocated */
4882 if (allocation.x == -1 &&
4883 allocation.y == -1 &&
4884 allocation.width == 1 &&
4885 allocation.height == 1)
4887 GtkRequisition requisition;
4891 allocation.width = 200;
4892 allocation.height = 200;
4894 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4895 if (requisition.width || requisition.height)
4897 /* non-empty window */
4898 allocation.width = requisition.width;
4899 allocation.height = requisition.height;
4901 gtk_widget_size_allocate (widget, &allocation);
4903 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4905 g_return_if_fail (!gtk_widget_get_realized (widget));
4908 gtk_widget_set_realized (widget, TRUE);
4912 case GTK_WINDOW_TOPLEVEL:
4913 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4915 case GTK_WINDOW_POPUP:
4916 attributes.window_type = GDK_WINDOW_TEMP;
4919 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4923 attributes.title = priv->title;
4924 attributes.wmclass_name = priv->wmclass_name;
4925 attributes.wmclass_class = priv->wmclass_class;
4926 attributes.wclass = GDK_INPUT_OUTPUT;
4927 attributes.visual = gtk_widget_get_visual (widget);
4929 attributes_mask = 0;
4930 parent_window = gtk_widget_get_root_window (widget);
4932 gtk_widget_get_allocation (widget, &allocation);
4933 attributes.width = allocation.width;
4934 attributes.height = allocation.height;
4935 attributes.event_mask = gtk_widget_get_events (widget);
4936 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4937 GDK_KEY_PRESS_MASK |
4938 GDK_KEY_RELEASE_MASK |
4939 GDK_ENTER_NOTIFY_MASK |
4940 GDK_LEAVE_NOTIFY_MASK |
4941 GDK_FOCUS_CHANGE_MASK |
4942 GDK_STRUCTURE_MASK);
4943 attributes.type_hint = priv->type_hint;
4945 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4946 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4947 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4949 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4950 gtk_widget_set_window (widget, gdk_window);
4952 if (priv->opacity_set)
4953 gdk_window_set_opacity (gdk_window, priv->opacity);
4955 gdk_window_enable_synchronized_configure (gdk_window);
4957 gdk_window_set_user_data (gdk_window, window);
4959 context = gtk_widget_get_style_context (widget);
4960 gtk_style_context_set_background (context, gdk_window);
4963 if (priv->transient_parent &&
4964 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4965 gdk_window_set_transient_for (gdk_window,
4966 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4969 gdk_window_set_role (gdk_window, priv->wm_role);
4971 if (!priv->decorated)
4972 gdk_window_set_decorations (gdk_window, 0);
4974 if (!priv->deletable)
4975 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4977 if (gtk_window_get_skip_pager_hint (window))
4978 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4980 if (gtk_window_get_skip_taskbar_hint (window))
4981 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4983 if (gtk_window_get_accept_focus (window))
4984 gdk_window_set_accept_focus (gdk_window, TRUE);
4986 gdk_window_set_accept_focus (gdk_window, FALSE);
4988 if (gtk_window_get_focus_on_map (window))
4989 gdk_window_set_focus_on_map (gdk_window, TRUE);
4991 gdk_window_set_focus_on_map (gdk_window, FALSE);
4994 gdk_window_set_modal_hint (gdk_window, TRUE);
4996 gdk_window_set_modal_hint (gdk_window, FALSE);
4998 if (priv->startup_id)
5000 #ifdef GDK_WINDOWING_X11
5001 if (GDK_IS_X11_WINDOW (gdk_window))
5003 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5004 if (timestamp != GDK_CURRENT_TIME)
5005 gdk_x11_window_set_user_time (gdk_window, timestamp);
5008 if (!startup_id_is_fake (priv->startup_id))
5009 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5013 gtk_window_realize_icon (window);
5015 if (priv->has_resize_grip)
5016 resize_grip_create_window (window);
5020 gtk_window_unrealize (GtkWidget *widget)
5022 GtkWindow *window = GTK_WINDOW (widget);
5023 GtkWindowPrivate *priv = window->priv;
5024 GtkWindowGeometryInfo *info;
5026 /* On unrealize, we reset the size of the window such
5027 * that we will re-apply the default sizing stuff
5028 * next time we show the window.
5030 * Default positioning is reset on unmap, instead of unrealize.
5032 priv->need_default_size = TRUE;
5033 info = gtk_window_get_geometry_info (window, FALSE);
5036 info->resize_width = -1;
5037 info->resize_height = -1;
5038 info->last.configure_request.x = 0;
5039 info->last.configure_request.y = 0;
5040 info->last.configure_request.width = -1;
5041 info->last.configure_request.height = -1;
5042 /* be sure we reset geom hints on re-realize */
5043 info->last.flags = 0;
5047 gtk_window_unrealize_icon (window);
5049 if (priv->grip_window != NULL)
5050 resize_grip_destroy_window (window);
5052 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5055 static GtkJunctionSides
5056 get_grip_junction (GtkWidget *widget)
5058 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5059 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5061 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5065 get_drag_edge (GtkWidget *widget,
5066 GdkWindowEdge *edge)
5068 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5069 gboolean hresizable;
5070 gboolean vresizable;
5071 GtkTextDirection dir;
5072 GtkWindowGeometryInfo *info;
5077 info = priv->geometry_info;
5080 GdkWindowHints flags = info->last.flags;
5081 GdkGeometry *geometry = &info->last.geometry;
5083 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5085 hresizable = geometry->min_width < geometry->max_width;
5086 vresizable = geometry->min_height < geometry->max_height;
5090 dir = gtk_widget_get_direction (widget);
5092 if (hresizable && vresizable)
5093 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5094 else if (hresizable)
5095 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5096 else if (vresizable)
5097 *edge = GDK_WINDOW_EDGE_SOUTH;
5105 set_grip_cursor (GtkWindow *window)
5107 GtkWidget *widget = GTK_WIDGET (window);
5108 GtkWindowPrivate *priv = window->priv;
5110 if (priv->grip_window == NULL)
5113 if (gtk_widget_is_sensitive (widget))
5116 GdkDisplay *display;
5117 GdkCursorType cursor_type;
5120 cursor_type = GDK_LEFT_PTR;
5122 if (get_drag_edge (widget, &edge))
5126 case GDK_WINDOW_EDGE_EAST:
5127 cursor_type = GDK_RIGHT_SIDE;
5129 case GDK_WINDOW_EDGE_SOUTH_EAST:
5130 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5132 case GDK_WINDOW_EDGE_SOUTH:
5133 cursor_type = GDK_BOTTOM_SIDE;
5135 case GDK_WINDOW_EDGE_SOUTH_WEST:
5136 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5138 case GDK_WINDOW_EDGE_WEST:
5139 cursor_type = GDK_LEFT_SIDE;
5145 display = gtk_widget_get_display (widget);
5146 cursor = gdk_cursor_new_for_display (display, cursor_type);
5147 gdk_window_set_cursor (priv->grip_window, cursor);
5148 g_object_unref (cursor);
5151 gdk_window_set_cursor (priv->grip_window, NULL);
5155 set_grip_shape (GtkWindow *window)
5157 GtkWindowPrivate *priv = window->priv;
5158 cairo_region_t *region;
5159 cairo_surface_t *surface;
5161 double width, height;
5163 if (priv->grip_window == NULL)
5166 width = gdk_window_get_width (priv->grip_window);
5167 height = gdk_window_get_height (priv->grip_window);
5168 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5170 cr = cairo_create (surface);
5171 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5173 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5174 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5176 cairo_move_to (cr, width, 0.0);
5177 cairo_line_to (cr, width, height);
5178 cairo_line_to (cr, 0.0, height);
5182 cairo_move_to (cr, 0.0, 0.0);
5183 cairo_line_to (cr, width, height);
5184 cairo_line_to (cr, 0.0, height);
5186 cairo_close_path (cr);
5189 region = gdk_cairo_region_create_from_surface (surface);
5190 cairo_surface_destroy (surface);
5192 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5193 cairo_region_destroy (region);
5197 set_grip_position (GtkWindow *window)
5199 GtkWindowPrivate *priv = window->priv;
5202 if (priv->grip_window == NULL)
5205 gtk_window_get_resize_grip_area (window, &rect);
5206 gdk_window_raise (priv->grip_window);
5207 gdk_window_move_resize (priv->grip_window,
5209 rect.width, rect.height);
5213 gtk_window_size_allocate (GtkWidget *widget,
5214 GtkAllocation *allocation)
5216 GtkWindow *window = GTK_WINDOW (widget);
5217 GtkAllocation child_allocation;
5221 gtk_widget_set_allocation (widget, allocation);
5223 if (gtk_widget_get_realized (widget))
5225 /* If it's not a toplevel we're embedded, we need to resize the window's
5226 * window and skip the grip.
5228 if (!gtk_widget_is_toplevel (widget))
5230 gdk_window_move_resize (gtk_widget_get_window (widget),
5231 allocation->x, allocation->y,
5232 allocation->width, allocation->height);
5236 update_grip_visibility (window);
5237 set_grip_position (window);
5241 child = gtk_bin_get_child (&(window->bin));
5242 if (child && gtk_widget_get_visible (child))
5244 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5245 child_allocation.x = border_width;
5246 child_allocation.y = border_width;
5247 child_allocation.width =
5248 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5249 child_allocation.height =
5250 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5252 gtk_widget_size_allocate (child, &child_allocation);
5257 gtk_window_configure_event (GtkWidget *widget,
5258 GdkEventConfigure *event)
5260 GtkAllocation allocation;
5261 GtkWindow *window = GTK_WINDOW (widget);
5262 GtkWindowPrivate *priv = window->priv;
5263 gboolean expected_reply = priv->configure_request_count > 0;
5265 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5267 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5268 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5270 gdk_window_configure_finished (gtk_widget_get_window (widget));
5274 /* priv->configure_request_count incremented for each
5275 * configure request, and decremented to a min of 0 for
5276 * each configure notify.
5278 * All it means is that we know we will get at least
5279 * priv->configure_request_count more configure notifies.
5280 * We could get more configure notifies than that; some
5281 * of the configure notifies we get may be unrelated to
5282 * the configure requests. But we will get at least
5283 * priv->configure_request_count notifies.
5286 if (priv->configure_request_count > 0)
5288 priv->configure_request_count -= 1;
5289 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5292 /* As an optimization, we avoid a resize when possible.
5294 * The only times we can avoid a resize are:
5295 * - we know only the position changed, not the size
5296 * - we know we have made more requests and so will get more
5297 * notifies and can wait to resize when we get them
5299 gtk_widget_get_allocation (widget, &allocation);
5300 if (!expected_reply &&
5301 (allocation.width == event->width &&
5302 allocation.height == event->height))
5304 gdk_window_configure_finished (gtk_widget_get_window (widget));
5309 * If we do need to resize, we do that by:
5310 * - filling in widget->allocation with the new size
5311 * - setting configure_notify_received to TRUE
5312 * for use in gtk_window_move_resize()
5313 * - queueing a resize, leading to invocation of
5314 * gtk_window_move_resize() in an idle handler
5318 priv->configure_notify_received = TRUE;
5320 allocation.width = event->width;
5321 allocation.height = event->height;
5322 gtk_widget_set_allocation (widget, &allocation);
5324 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5326 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5332 gtk_window_state_event (GtkWidget *widget,
5333 GdkEventWindowState *event)
5335 update_grip_visibility (GTK_WINDOW (widget));
5341 gtk_window_direction_changed (GtkWidget *widget,
5342 GtkTextDirection prev_dir)
5344 GtkWindow *window = GTK_WINDOW (widget);
5346 set_grip_cursor (window);
5347 set_grip_position (window);
5348 set_grip_shape (window);
5352 gtk_window_state_changed (GtkWidget *widget,
5353 GtkStateType previous_state)
5355 GtkWindow *window = GTK_WINDOW (widget);
5357 update_grip_visibility (window);
5361 gtk_window_style_updated (GtkWidget *widget)
5363 GtkWindow *window = GTK_WINDOW (widget);
5364 GtkWindowPrivate *priv = window->priv;
5367 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5369 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5371 gdk_window_move_resize (priv->grip_window,
5373 rect.width, rect.height);
5375 set_grip_shape (window);
5376 gtk_widget_queue_resize (widget);
5381 resize_grip_create_window (GtkWindow *window)
5384 GtkWindowPrivate *priv;
5385 GdkWindowAttr attributes;
5386 gint attributes_mask;
5389 priv = window->priv;
5390 widget = GTK_WIDGET (window);
5392 g_return_if_fail (gtk_widget_get_realized (widget));
5393 g_return_if_fail (priv->grip_window == NULL);
5395 gtk_window_get_resize_grip_area (window, &rect);
5397 attributes.x = rect.x;
5398 attributes.y = rect.y;
5399 attributes.width = rect.width;
5400 attributes.height = rect.height;
5401 attributes.window_type = GDK_WINDOW_CHILD;
5402 attributes.wclass = GDK_INPUT_OUTPUT;
5403 attributes.event_mask = gtk_widget_get_events (widget) |
5405 GDK_BUTTON_PRESS_MASK;
5407 attributes_mask = GDK_WA_X | GDK_WA_Y;
5409 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5413 gdk_window_set_user_data (priv->grip_window, widget);
5415 gdk_window_raise (priv->grip_window);
5417 set_grip_shape (window);
5418 update_grip_visibility (window);
5422 resize_grip_destroy_window (GtkWindow *window)
5424 GtkWindowPrivate *priv = window->priv;
5426 gdk_window_set_user_data (priv->grip_window, NULL);
5427 gdk_window_destroy (priv->grip_window);
5428 priv->grip_window = NULL;
5429 update_grip_visibility (window);
5433 * gtk_window_set_has_resize_grip:
5434 * @window: a #GtkWindow
5435 * @value: %TRUE to allow a resize grip
5437 * Sets whether @window has a corner resize grip.
5439 * Note that the resize grip is only shown if the window
5440 * is actually resizable and not maximized. Use
5441 * gtk_window_resize_grip_is_visible() to find out if the
5442 * resize grip is currently shown.
5447 gtk_window_set_has_resize_grip (GtkWindow *window,
5450 GtkWidget *widget = GTK_WIDGET (window);
5451 GtkWindowPrivate *priv = window->priv;
5453 value = value != FALSE;
5455 if (value != priv->has_resize_grip)
5457 priv->has_resize_grip = value;
5458 gtk_widget_queue_draw (widget);
5460 if (gtk_widget_get_realized (widget) &&
5461 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5463 if (priv->has_resize_grip && priv->grip_window == NULL)
5464 resize_grip_create_window (window);
5465 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5466 resize_grip_destroy_window (window);
5469 g_object_notify (G_OBJECT (window), "has-resize-grip");
5474 update_grip_visibility (GtkWindow *window)
5476 GtkWindowPrivate *priv = window->priv;
5479 val = gtk_window_resize_grip_is_visible (window);
5481 if (priv->grip_window != NULL)
5485 gdk_window_show (priv->grip_window);
5486 set_grip_cursor (window);
5490 gdk_window_hide (priv->grip_window);
5494 if (priv->resize_grip_visible != val)
5496 priv->resize_grip_visible = val;
5498 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5503 * gtk_window_resize_grip_is_visible:
5504 * @window: a #GtkWindow
5506 * Determines whether a resize grip is visible for the specified window.
5508 * Returns: %TRUE if a resize grip exists and is visible
5513 gtk_window_resize_grip_is_visible (GtkWindow *window)
5516 GtkWindowPrivate *priv;
5519 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5521 priv = window->priv;
5522 widget = GTK_WIDGET (window);
5524 if (priv->type == GTK_WINDOW_POPUP)
5527 if (!priv->resizable)
5530 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5533 if (gtk_widget_get_realized (widget))
5535 GdkWindowState state;
5537 state = gdk_window_get_state (gtk_widget_get_window (widget));
5539 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5543 if (!get_drag_edge (widget, &edge))
5546 return window->priv->has_resize_grip;
5550 * gtk_window_get_has_resize_grip:
5551 * @window: a #GtkWindow
5553 * Determines whether the window may have a resize grip.
5555 * Returns: %TRUE if the window has a resize grip
5560 gtk_window_get_has_resize_grip (GtkWindow *window)
5562 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5564 return window->priv->has_resize_grip;
5568 * gtk_window_get_resize_grip_area:
5569 * @window: a #GtkWindow
5570 * @rect: (out): a pointer to a #GdkRectangle which we should store
5571 * the resize grip area
5573 * If a window has a resize grip, this will retrieve the grip
5574 * position, width and height into the specified #GdkRectangle.
5576 * Returns: %TRUE if the resize grip's area was retrieved
5581 gtk_window_get_resize_grip_area (GtkWindow *window,
5584 GtkWidget *widget = GTK_WIDGET (window);
5585 GtkAllocation allocation;
5589 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5591 if (!window->priv->has_resize_grip)
5594 gtk_widget_get_allocation (widget, &allocation);
5596 gtk_widget_style_get (widget,
5597 "resize-grip-width", &grip_width,
5598 "resize-grip-height", &grip_height,
5601 if (grip_width > allocation.width)
5602 grip_width = allocation.width;
5604 if (grip_height > allocation.height)
5605 grip_height = allocation.height;
5607 rect->width = grip_width;
5608 rect->height = grip_height;
5609 rect->y = allocation.y + allocation.height - grip_height;
5611 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5612 rect->x = allocation.x + allocation.width - grip_width;
5614 rect->x = allocation.x;
5619 /* the accel_key and accel_mods fields of the key have to be setup
5620 * upon calling this function. it'll then return whether that key
5621 * is at all used as accelerator, and if so will OR in the
5622 * accel_flags member of the key.
5625 _gtk_window_query_nonaccels (GtkWindow *window,
5627 GdkModifierType accel_mods)
5629 GtkWindowPrivate *priv;
5631 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5633 priv = window->priv;
5635 /* movement keys are considered locked accels */
5638 static const guint bindings[] = {
5639 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,
5640 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,
5644 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5645 if (bindings[i] == accel_key)
5649 /* mnemonics are considered locked accels */
5650 if (accel_mods == priv->mnemonic_modifier)
5652 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5653 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5661 * gtk_window_propagate_key_event:
5662 * @window: a #GtkWindow
5663 * @event: a #GdkEventKey
5665 * Propagate a key press or release event to the focus widget and
5666 * up the focus container chain until a widget handles @event.
5667 * This is normally called by the default ::key_press_event and
5668 * ::key_release_event handlers for toplevel windows,
5669 * however in some cases it may be useful to call this directly when
5670 * overriding the standard key handling for a toplevel window.
5672 * Return value: %TRUE if a widget in the focus chain handled the event.
5677 gtk_window_propagate_key_event (GtkWindow *window,
5680 GtkWindowPrivate *priv;
5681 gboolean handled = FALSE;
5682 GtkWidget *widget, *focus;
5684 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5686 priv = window->priv;
5687 widget = GTK_WIDGET (window);
5689 focus = priv->focus_widget;
5691 g_object_ref (focus);
5694 focus && focus != widget &&
5695 gtk_widget_get_toplevel (focus) == widget)
5699 if (gtk_widget_is_sensitive (focus))
5700 handled = gtk_widget_event (focus, (GdkEvent*) event);
5702 parent = gtk_widget_get_parent (focus);
5704 g_object_ref (parent);
5706 g_object_unref (focus);
5712 g_object_unref (focus);
5718 gtk_window_key_press_event (GtkWidget *widget,
5721 GtkWindow *window = GTK_WINDOW (widget);
5722 gboolean handled = FALSE;
5724 /* handle mnemonics and accelerators */
5726 handled = gtk_window_activate_key (window, event);
5728 /* handle focus widget key events */
5730 handled = gtk_window_propagate_key_event (window, event);
5732 /* Chain up, invokes binding set */
5734 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5740 gtk_window_key_release_event (GtkWidget *widget,
5743 GtkWindow *window = GTK_WINDOW (widget);
5744 gboolean handled = FALSE;
5746 /* handle focus widget key events */
5748 handled = gtk_window_propagate_key_event (window, event);
5750 /* Chain up, invokes binding set */
5752 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5758 gtk_window_button_press_event (GtkWidget *widget,
5759 GdkEventButton *event)
5761 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5764 if (event->window == priv->grip_window)
5766 if (get_drag_edge (widget, &edge))
5767 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5781 gtk_window_real_activate_default (GtkWindow *window)
5783 gtk_window_activate_default (window);
5787 gtk_window_real_activate_focus (GtkWindow *window)
5789 gtk_window_activate_focus (window);
5793 gtk_window_enter_notify_event (GtkWidget *widget,
5794 GdkEventCrossing *event)
5800 gtk_window_leave_notify_event (GtkWidget *widget,
5801 GdkEventCrossing *event)
5807 do_focus_change (GtkWidget *widget,
5811 GdkDeviceManager *device_manager;
5814 g_object_ref (widget);
5816 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5817 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5818 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5819 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5821 for (d = devices; d; d = d->next)
5823 GdkDevice *dev = d->data;
5826 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5829 /* Skip non-master keyboards that haven't
5830 * selected for events from this window
5832 window = gtk_widget_get_window (widget);
5833 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5834 window && !gdk_window_get_device_events (window, dev))
5837 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5839 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5840 fevent->focus_change.window = window;
5842 g_object_ref (window);
5843 fevent->focus_change.in = in;
5844 gdk_event_set_device (fevent, dev);
5846 gtk_widget_send_focus_change (widget, fevent);
5848 gdk_event_free (fevent);
5851 g_list_free (devices);
5852 g_object_unref (widget);
5856 gtk_window_focus_in_event (GtkWidget *widget,
5857 GdkEventFocus *event)
5859 GtkWindow *window = GTK_WINDOW (widget);
5861 /* It appears spurious focus in events can occur when
5862 * the window is hidden. So we'll just check to see if
5863 * the window is visible before actually handling the
5866 if (gtk_widget_get_visible (widget))
5868 _gtk_window_set_has_toplevel_focus (window, TRUE);
5869 _gtk_window_set_is_active (window, TRUE);
5876 gtk_window_focus_out_event (GtkWidget *widget,
5877 GdkEventFocus *event)
5879 GtkWindow *window = GTK_WINDOW (widget);
5880 gboolean auto_mnemonics;
5882 _gtk_window_set_has_toplevel_focus (window, FALSE);
5883 _gtk_window_set_is_active (window, FALSE);
5885 /* set the mnemonic-visible property to false */
5886 g_object_get (gtk_widget_get_settings (widget),
5887 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5889 gtk_window_set_mnemonics_visible (window, FALSE);
5895 gtk_window_check_resize (GtkContainer *container)
5897 /* If the window is not toplevel anymore than it's embedded somewhere,
5898 * so handle it like a normal window */
5899 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
5900 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
5901 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
5902 gtk_window_move_resize (GTK_WINDOW (container));
5906 gtk_window_focus (GtkWidget *widget,
5907 GtkDirectionType direction)
5909 GtkWindowPrivate *priv;
5912 GtkContainer *container;
5914 GtkWidget *old_focus_child;
5917 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5918 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
5920 container = GTK_CONTAINER (widget);
5921 window = GTK_WINDOW (widget);
5922 priv = window->priv;
5923 bin = GTK_BIN (widget);
5925 old_focus_child = gtk_container_get_focus_child (container);
5927 /* We need a special implementation here to deal properly with wrapping
5928 * around in the tab chain without the danger of going into an
5931 if (old_focus_child)
5933 if (gtk_widget_child_focus (old_focus_child, direction))
5937 if (priv->focus_widget)
5939 if (direction == GTK_DIR_LEFT ||
5940 direction == GTK_DIR_RIGHT ||
5941 direction == GTK_DIR_UP ||
5942 direction == GTK_DIR_DOWN)
5947 /* Wrapped off the end, clear the focus setting for the toplpevel */
5948 parent = gtk_widget_get_parent (priv->focus_widget);
5951 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5952 parent = gtk_widget_get_parent (parent);
5955 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5958 /* Now try to focus the first widget in the window */
5959 child = gtk_bin_get_child (bin);
5962 if (gtk_widget_child_focus (child, direction))
5970 gtk_window_move_focus (GtkWidget *widget,
5971 GtkDirectionType dir)
5973 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5975 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
5979 gtk_widget_child_focus (widget, dir);
5981 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
5982 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
5986 gtk_window_real_set_focus (GtkWindow *window,
5989 GtkWindowPrivate *priv = window->priv;
5990 GtkWidget *old_focus = priv->focus_widget;
5991 gboolean had_default = FALSE;
5992 gboolean focus_had_default = FALSE;
5993 gboolean old_focus_had_default = FALSE;
5997 g_object_ref (old_focus);
5998 g_object_freeze_notify (G_OBJECT (old_focus));
5999 old_focus_had_default = gtk_widget_has_default (old_focus);
6003 g_object_ref (focus);
6004 g_object_freeze_notify (G_OBJECT (focus));
6005 focus_had_default = gtk_widget_has_default (focus);
6008 if (priv->default_widget)
6009 had_default = gtk_widget_has_default (priv->default_widget);
6011 if (priv->focus_widget)
6013 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6014 (priv->focus_widget != priv->default_widget))
6016 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6017 gtk_widget_queue_draw (priv->focus_widget);
6019 if (priv->default_widget)
6020 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6023 priv->focus_widget = NULL;
6025 if (priv->has_focus)
6026 do_focus_change (old_focus, FALSE);
6028 g_object_notify (G_OBJECT (old_focus), "is-focus");
6031 /* The above notifications may have set a new focus widget,
6032 * if so, we don't want to override it.
6034 if (focus && !priv->focus_widget)
6036 priv->focus_widget = focus;
6038 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6039 (priv->focus_widget != priv->default_widget))
6041 if (gtk_widget_get_can_default (priv->focus_widget))
6042 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6044 if (priv->default_widget)
6045 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6048 if (priv->has_focus)
6049 do_focus_change (priv->focus_widget, TRUE);
6051 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6054 /* If the default widget changed, a redraw will have been queued
6055 * on the old and new default widgets by gtk_window_set_default(), so
6056 * we only have to worry about the case where it didn't change.
6057 * We'll sometimes queue a draw twice on the new widget but that
6060 if (priv->default_widget &&
6061 (had_default != gtk_widget_has_default (priv->default_widget)))
6062 gtk_widget_queue_draw (priv->default_widget);
6066 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6067 gtk_widget_queue_draw (old_focus);
6069 g_object_thaw_notify (G_OBJECT (old_focus));
6070 g_object_unref (old_focus);
6074 if (focus_had_default != gtk_widget_has_default (focus))
6075 gtk_widget_queue_draw (focus);
6077 g_object_thaw_notify (G_OBJECT (focus));
6078 g_object_unref (focus);
6084 gtk_window_get_preferred_width (GtkWidget *widget,
6092 window = GTK_WINDOW (widget);
6093 child = gtk_bin_get_child (GTK_BIN (window));
6095 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6096 *minimum_size = border_width * 2;
6097 *natural_size = border_width * 2;
6099 if (child && gtk_widget_get_visible (child))
6101 gint child_min, child_nat;
6102 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6104 *minimum_size += child_min;
6105 *natural_size += child_nat;
6110 gtk_window_get_preferred_height (GtkWidget *widget,
6118 window = GTK_WINDOW (widget);
6119 child = gtk_bin_get_child (GTK_BIN (window));
6121 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6122 *minimum_size = border_width * 2;
6123 *natural_size = border_width * 2;
6125 if (child && gtk_widget_get_visible (child))
6127 gint child_min, child_nat;
6128 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6130 *minimum_size += child_min;
6131 *natural_size += child_nat;
6137 * _gtk_window_unset_focus_and_default:
6138 * @window: a #GtkWindow
6139 * @widget: a widget inside of @window
6141 * Checks whether the focus and default widgets of @window are
6142 * @widget or a descendent of @widget, and if so, unset them.
6145 _gtk_window_unset_focus_and_default (GtkWindow *window,
6149 GtkWindowPrivate *priv = window->priv;
6153 g_object_ref (window);
6154 g_object_ref (widget);
6156 parent = gtk_widget_get_parent (widget);
6157 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6159 child = priv->focus_widget;
6161 while (child && child != widget)
6162 child = gtk_widget_get_parent (child);
6164 if (child == widget)
6165 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6168 child = priv->default_widget;
6170 while (child && child != widget)
6171 child = gtk_widget_get_parent (child);
6173 if (child == widget)
6174 gtk_window_set_default (window, NULL);
6176 g_object_unref (widget);
6177 g_object_unref (window);
6180 /*********************************
6181 * Functions related to resizing *
6182 *********************************/
6185 geometry_size_to_pixels (GdkGeometry *geometry,
6190 gint base_width = 0;
6191 gint base_height = 0;
6193 gint min_height = 0;
6195 gint height_inc = 1;
6197 if (flags & GDK_HINT_BASE_SIZE)
6199 base_width = geometry->base_width;
6200 base_height = geometry->base_height;
6202 if (flags & GDK_HINT_MIN_SIZE)
6204 min_width = geometry->min_width;
6205 min_height = geometry->min_height;
6207 if (flags & GDK_HINT_RESIZE_INC)
6209 width_inc = geometry->width_inc;
6210 height_inc = geometry->height_inc;
6214 *width = MAX (*width * width_inc + base_width, min_width);
6216 *height = MAX (*height * height_inc + base_height, min_height);
6219 /* This function doesn't constrain to geometry hints */
6221 gtk_window_compute_configure_request_size (GtkWindow *window,
6222 GdkGeometry *geometry,
6227 GtkWindowPrivate *priv = window->priv;
6228 GtkRequisition requisition;
6229 GtkWindowGeometryInfo *info;
6233 * - we've done a size request
6236 widget = GTK_WIDGET (window);
6238 info = gtk_window_get_geometry_info (window, FALSE);
6240 if (priv->need_default_size)
6242 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6244 /* Default to requisition */
6245 *width = requisition.width;
6246 *height = requisition.height;
6248 /* If window is empty so requests 0, default to random nonzero size */
6249 if (*width == 0 && *height == 0)
6255 /* Override requisition with default size */
6259 if (info->default_width > 0)
6260 *width = info->default_width;
6261 if (info->default_height > 0)
6262 *height = info->default_height;
6264 if (info->default_is_geometry)
6265 geometry_size_to_pixels (geometry, flags,
6266 info->default_width > 0 ? width : NULL,
6267 info->default_height > 0 ? height : NULL);
6272 GtkAllocation allocation;
6274 gtk_widget_get_allocation (widget, &allocation);
6276 /* Default to keeping current size */
6277 *width = allocation.width;
6278 *height = allocation.height;
6281 /* Override any size with gtk_window_resize() values */
6284 if (info->resize_width > 0)
6285 *width = info->resize_width;
6286 if (info->resize_height > 0)
6287 *height = info->resize_height;
6289 if (info->resize_is_geometry)
6290 geometry_size_to_pixels (geometry, flags,
6291 info->resize_width > 0 ? width : NULL,
6292 info->resize_height > 0 ? height : NULL);
6295 /* Don't ever request zero width or height, its not supported by
6296 gdk. The size allocation code will round it to 1 anyway but if
6297 we do it then the value returned from this function will is
6298 not comparable to the size allocation read from the GtkWindow. */
6299 *width = MAX (*width, 1);
6300 *height = MAX (*height, 1);
6303 static GtkWindowPosition
6304 get_effective_position (GtkWindow *window)
6306 GtkWindowPrivate *priv = window->priv;
6307 GtkWindowPosition pos = priv->position;
6309 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6310 (priv->transient_parent == NULL ||
6311 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6312 pos = GTK_WIN_POS_NONE;
6318 get_center_monitor_of_window (GtkWindow *window)
6320 /* We could try to sort out the relative positions of the monitors and
6321 * stuff, or we could just be losers and assume you have a row
6322 * or column of monitors.
6324 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6328 get_monitor_containing_pointer (GtkWindow *window)
6332 GdkScreen *window_screen;
6333 GdkScreen *pointer_screen;
6334 GdkDisplay *display;
6335 GdkDeviceManager *device_manager;
6338 window_screen = gtk_window_check_screen (window);
6339 display = gdk_screen_get_display (window_screen);
6340 device_manager = gdk_display_get_device_manager (display);
6341 pointer = gdk_device_manager_get_client_pointer (device_manager);
6343 gdk_device_get_position (pointer,
6347 if (pointer_screen == window_screen)
6348 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6356 center_window_on_monitor (GtkWindow *window,
6362 GdkRectangle monitor;
6365 monitor_num = get_monitor_containing_pointer (window);
6367 if (monitor_num == -1)
6368 monitor_num = get_center_monitor_of_window (window);
6370 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6371 monitor_num, &monitor);
6373 *x = (monitor.width - w) / 2 + monitor.x;
6374 *y = (monitor.height - h) / 2 + monitor.y;
6376 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6377 * and WM decorations.
6391 if (extent > clamp_extent)
6393 *base = clamp_base + clamp_extent/2 - extent/2;
6394 else if (*base < clamp_base)
6396 else if (*base + extent > clamp_base + clamp_extent)
6397 *base = clamp_base + clamp_extent - extent;
6401 clamp_window_to_rectangle (gint *x,
6405 const GdkRectangle *rect)
6407 #ifdef DEBUGGING_OUTPUT
6408 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);
6411 /* If it is too large, center it. If it fits on the monitor but is
6412 * partially outside, move it to the closest edge. Do this
6413 * separately in x and y directions.
6415 clamp (x, w, rect->x, rect->width);
6416 clamp (y, h, rect->y, rect->height);
6417 #ifdef DEBUGGING_OUTPUT
6418 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6424 gtk_window_compute_configure_request (GtkWindow *window,
6425 GdkRectangle *request,
6426 GdkGeometry *geometry,
6429 GtkWindowPrivate *priv = window->priv;
6430 GdkGeometry new_geometry;
6433 GtkWindowPosition pos;
6434 GtkWidget *parent_widget;
6435 GtkWindowGeometryInfo *info;
6439 screen = gtk_window_check_screen (window);
6441 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6442 gtk_window_compute_configure_request_size (window,
6443 &new_geometry, new_flags,
6444 (guint *)&w, (guint *)&h);
6446 gtk_window_constrain_size (window,
6447 &new_geometry, new_flags,
6451 parent_widget = (GtkWidget*) priv->transient_parent;
6453 pos = get_effective_position (window);
6454 info = gtk_window_get_geometry_info (window, FALSE);
6456 /* by default, don't change position requested */
6459 x = info->last.configure_request.x;
6460 y = info->last.configure_request.y;
6469 if (priv->need_default_position)
6472 /* FIXME this all interrelates with window gravity.
6473 * For most of them I think we want to set GRAVITY_CENTER.
6475 * Not sure how to go about that.
6479 /* here we are only handling CENTER_ALWAYS
6480 * as it relates to default positioning,
6481 * where it's equivalent to simply CENTER
6483 case GTK_WIN_POS_CENTER_ALWAYS:
6484 case GTK_WIN_POS_CENTER:
6485 center_window_on_monitor (window, w, h, &x, &y);
6488 case GTK_WIN_POS_CENTER_ON_PARENT:
6490 GtkAllocation allocation;
6491 GdkWindow *gdk_window;
6493 GdkRectangle monitor;
6496 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6498 gdk_window = gtk_widget_get_window (parent_widget);
6500 if (gdk_window != NULL)
6501 monitor_num = gdk_screen_get_monitor_at_window (screen,
6506 gdk_window_get_origin (gdk_window,
6509 gtk_widget_get_allocation (parent_widget, &allocation);
6510 x = ox + (allocation.width - w) / 2;
6511 y = oy + (allocation.height - h) / 2;
6513 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6514 * WM decorations. If parent wasn't on a monitor, just
6517 if (monitor_num >= 0)
6519 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6520 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6525 case GTK_WIN_POS_MOUSE:
6527 gint screen_width = gdk_screen_get_width (screen);
6528 gint screen_height = gdk_screen_get_height (screen);
6530 GdkRectangle monitor;
6531 GdkDisplay *display;
6532 GdkDeviceManager *device_manager;
6534 GdkScreen *pointer_screen;
6537 display = gdk_screen_get_display (screen);
6538 device_manager = gdk_display_get_device_manager (display);
6539 pointer = gdk_device_manager_get_client_pointer (device_manager);
6541 gdk_device_get_position (pointer,
6545 if (pointer_screen == screen)
6546 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6552 x = CLAMP (x, 0, screen_width - w);
6553 y = CLAMP (y, 0, screen_height - h);
6555 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6556 * WM decorations. Don't try to figure out what's going
6557 * on if the mouse wasn't inside a monitor.
6559 if (monitor_num >= 0)
6561 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6562 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6570 } /* if (priv->need_default_position) */
6572 if (priv->need_default_position && info &&
6573 info->initial_pos_set)
6575 x = info->initial_x;
6576 y = info->initial_y;
6577 gtk_window_constrain_position (window, w, h, &x, &y);
6583 request->height = h;
6586 *geometry = new_geometry;
6592 gtk_window_constrain_position (GtkWindow *window,
6598 GtkWindowPrivate *priv = window->priv;
6600 /* See long comments in gtk_window_move_resize()
6601 * on when it's safe to call this function.
6603 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6605 gint center_x, center_y;
6607 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6615 gtk_window_move_resize (GtkWindow *window)
6619 * First we determine whether any information has changed that would
6620 * cause us to revise our last configure request. If we would send
6621 * a different configure request from last time, then
6622 * configure_request_size_changed = TRUE or
6623 * configure_request_pos_changed = TRUE. configure_request_size_changed
6624 * may be true due to new hints, a gtk_window_resize(), or whatever.
6625 * configure_request_pos_changed may be true due to gtk_window_set_position()
6626 * or gtk_window_move().
6628 * If the configure request has changed, we send off a new one. To
6629 * ensure GTK+ invariants are maintained (resize queue does what it
6630 * should), we go ahead and size_allocate the requested size in this
6633 * If the configure request has not changed, we don't ever resend
6634 * it, because it could mean fighting the user or window manager.
6637 * To prepare the configure request, we come up with a base size/pos:
6638 * - the one from gtk_window_move()/gtk_window_resize()
6639 * - else default_width, default_height if we haven't ever
6641 * - else the size request if we haven't ever been mapped,
6642 * as a substitute default size
6643 * - else the current size of the window, as received from
6644 * configure notifies (i.e. the current allocation)
6646 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6647 * the position request to be centered.
6649 GtkWindowPrivate *priv = window->priv;
6650 GtkAllocation allocation;
6652 GtkContainer *container;
6653 GtkWindowGeometryInfo *info;
6654 GdkGeometry new_geometry;
6655 GdkWindow *gdk_window;
6657 GdkRectangle new_request;
6658 gboolean configure_request_size_changed;
6659 gboolean configure_request_pos_changed;
6660 gboolean hints_changed; /* do we need to send these again */
6661 GtkWindowLastGeometryInfo saved_last_info;
6663 widget = GTK_WIDGET (window);
6665 gdk_window = gtk_widget_get_window (widget);
6666 container = GTK_CONTAINER (widget);
6667 info = gtk_window_get_geometry_info (window, TRUE);
6669 configure_request_size_changed = FALSE;
6670 configure_request_pos_changed = FALSE;
6672 gtk_window_compute_configure_request (window, &new_request,
6673 &new_geometry, &new_flags);
6675 /* This check implies the invariant that we never set info->last
6676 * without setting the hints and sending off a configure request.
6678 * If we change info->last without sending the request, we may
6681 if (info->last.configure_request.x != new_request.x ||
6682 info->last.configure_request.y != new_request.y)
6683 configure_request_pos_changed = TRUE;
6685 if ((info->last.configure_request.width != new_request.width ||
6686 info->last.configure_request.height != new_request.height))
6687 configure_request_size_changed = TRUE;
6689 hints_changed = FALSE;
6691 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6692 &new_geometry, new_flags))
6694 hints_changed = TRUE;
6697 /* Position Constraints
6698 * ====================
6700 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6701 * a default. The other POS_ values are used only when the
6702 * window is shown, not after that.
6704 * However, we can't implement a position constraint as
6705 * "anytime the window size changes, center the window"
6706 * because this may well end up fighting the WM or user. In
6707 * fact it gets in an infinite loop with at least one WM.
6709 * Basically, applications are in no way in a position to
6710 * constrain the position of a window, with one exception:
6711 * override redirect windows. (Really the intended purpose
6712 * of CENTER_ALWAYS anyhow, I would think.)
6714 * So the way we implement this "constraint" is to say that when WE
6715 * cause a move or resize, i.e. we make a configure request changing
6716 * window size, we recompute the CENTER_ALWAYS position to reflect
6717 * the new window size, and include it in our request. Also, if we
6718 * just turned on CENTER_ALWAYS we snap to center with a new
6719 * request. Otherwise, if we are just NOTIFIED of a move or resize
6720 * done by someone else e.g. the window manager, we do NOT send a
6721 * new configure request.
6723 * For override redirect windows, this works fine; all window
6724 * sizes are from our configure requests. For managed windows,
6725 * it is at least semi-sane, though who knows what the
6726 * app author is thinking.
6729 /* This condition should be kept in sync with the condition later on
6730 * that determines whether we send a configure request. i.e. we
6731 * should do this position constraining anytime we were going to
6732 * send a configure request anyhow, plus when constraints have
6735 if (configure_request_pos_changed ||
6736 configure_request_size_changed ||
6738 info->position_constraints_changed)
6740 /* We request the constrained position if:
6741 * - we were changing position, and need to clamp
6742 * the change to the constraint
6743 * - we're changing the size anyway
6744 * - set_position() was called to toggle CENTER_ALWAYS on
6747 gtk_window_constrain_position (window,
6753 /* Update whether we need to request a move */
6754 if (info->last.configure_request.x != new_request.x ||
6755 info->last.configure_request.y != new_request.y)
6756 configure_request_pos_changed = TRUE;
6758 configure_request_pos_changed = FALSE;
6762 if (priv->type == GTK_WINDOW_TOPLEVEL)
6764 int notify_x, notify_y;
6766 /* this is the position from the last configure notify */
6767 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6769 g_message ("--- %s ---\n"
6770 "last : %d,%d\t%d x %d\n"
6771 "this : %d,%d\t%d x %d\n"
6772 "alloc : %d,%d\t%d x %d\n"
6774 "resize: \t%d x %d\n"
6775 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6776 "configure_notify_received: %d\n"
6777 "configure_request_count: %d\n"
6778 "position_constraints_changed: %d\n",
6779 priv->title ? priv->title : "(no title)",
6780 info->last.configure_request.x,
6781 info->last.configure_request.y,
6782 info->last.configure_request.width,
6783 info->last.configure_request.height,
6789 widget->allocation.width,
6790 widget->allocation.height,
6791 widget->requisition.width,
6792 widget->requisition.height,
6794 info->resize_height,
6795 configure_request_pos_changed,
6796 configure_request_size_changed,
6798 priv->configure_notify_received,
6799 priv->configure_request_count,
6800 info->position_constraints_changed);
6804 saved_last_info = info->last;
6805 info->last.geometry = new_geometry;
6806 info->last.flags = new_flags;
6807 info->last.configure_request = new_request;
6809 /* need to set PPosition so the WM will look at our position,
6810 * but we don't want to count PPosition coming and going as a hints
6811 * change for future iterations. So we saved info->last prior to
6815 /* Also, if the initial position was explicitly set, then we always
6816 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6820 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6821 * this is an initial map
6824 if ((configure_request_pos_changed ||
6825 info->initial_pos_set ||
6826 (priv->need_default_position &&
6827 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6828 (new_flags & GDK_HINT_POS) == 0)
6830 new_flags |= GDK_HINT_POS;
6831 hints_changed = TRUE;
6834 /* Set hints if necessary
6837 gdk_window_set_geometry_hints (gdk_window,
6841 gtk_widget_get_allocation (widget, &allocation);
6843 /* handle resizing/moving and widget tree allocation
6845 if (priv->configure_notify_received)
6847 /* If we have received a configure event since
6848 * the last time in this function, we need to
6849 * accept our new size and size_allocate child widgets.
6850 * (see gtk_window_configure_event() for more details).
6852 * 1 or more configure notifies may have been received.
6853 * Also, configure_notify_received will only be TRUE
6854 * if all expected configure notifies have been received
6855 * (one per configure request), as an optimization.
6858 priv->configure_notify_received = FALSE;
6860 /* gtk_window_configure_event() filled in widget->allocation */
6861 gtk_widget_size_allocate (widget, &allocation);
6863 set_grip_position (window);
6864 update_grip_visibility (window);
6866 gdk_window_process_updates (gdk_window, TRUE);
6868 gdk_window_configure_finished (gdk_window);
6870 /* If the configure request changed, it means that
6872 * 1) coincidentally changed hints or widget properties
6873 * impacting the configure request before getting
6874 * a configure notify, or
6875 * 2) some broken widget is changing its size request
6876 * during size allocation, resulting in
6877 * a false appearance of changed configure request.
6879 * For 1), we could just go ahead and ask for the
6880 * new size right now, but doing that for 2)
6881 * might well be fighting the user (and can even
6882 * trigger a loop). Since we really don't want to
6883 * do that, we requeue a resize in hopes that
6884 * by the time it gets handled, the child has seen
6885 * the light and is willing to go along with the
6886 * new size. (this happens for the zvt widget, since
6887 * the size_allocate() above will have stored the
6888 * requisition corresponding to the new size in the
6891 * This doesn't buy us anything for 1), but it shouldn't
6892 * hurt us too badly, since it is what would have
6893 * happened if we had gotten the configure event before
6894 * the new size had been set.
6897 if (configure_request_size_changed ||
6898 configure_request_pos_changed)
6900 /* Don't change the recorded last info after all, because we
6901 * haven't actually updated to the new info yet - we decided
6902 * to postpone our configure request until later.
6904 info->last = saved_last_info;
6906 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6909 return; /* Bail out, we didn't really process the move/resize */
6911 else if ((configure_request_size_changed || hints_changed) &&
6912 (allocation.width != new_request.width || allocation.height != new_request.height))
6915 /* We are in one of the following situations:
6916 * A. configure_request_size_changed
6917 * our requisition has changed and we need a different window size,
6918 * so we request it from the window manager.
6919 * B. !configure_request_size_changed && hints_changed
6920 * the window manager rejects our size, but we have just changed the
6921 * window manager hints, so there's a chance our request will
6922 * be honoured this time, so we try again.
6924 * However, if the new requisition is the same as the current allocation,
6925 * we don't request it again, since we won't get a ConfigureNotify back from
6926 * the window manager unless it decides to change our requisition. If
6927 * we don't get the ConfigureNotify back, the resize queue will never be run.
6930 /* Now send the configure request */
6931 if (configure_request_pos_changed)
6933 gdk_window_move_resize (gdk_window,
6934 new_request.x, new_request.y,
6935 new_request.width, new_request.height);
6937 else /* only size changed */
6939 gdk_window_resize (gdk_window,
6940 new_request.width, new_request.height);
6943 if (priv->type == GTK_WINDOW_POPUP)
6945 GtkAllocation allocation;
6947 /* Directly size allocate for override redirect (popup) windows. */
6950 allocation.width = new_request.width;
6951 allocation.height = new_request.height;
6953 gtk_widget_size_allocate (widget, &allocation);
6955 gdk_window_process_updates (gdk_window, TRUE);
6957 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6958 gtk_widget_queue_draw (widget);
6962 /* Increment the number of have-not-yet-received-notify requests */
6963 priv->configure_request_count += 1;
6964 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
6966 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6967 * configure event in response to our resizing request.
6968 * the configure event will cause a new resize with
6969 * ->configure_notify_received=TRUE.
6970 * until then, we want to
6971 * - discard expose events
6972 * - coalesce resizes for our children
6973 * - defer any window resizes until the configure event arrived
6974 * to achieve this, we queue a resize for the window, but remove its
6975 * resizing handler, so resizing will not be handled from the next
6976 * idle handler but when the configure event arrives.
6978 * FIXME: we should also dequeue the pending redraws here, since
6979 * we handle those ourselves upon ->configure_notify_received==TRUE.
6981 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6983 gtk_widget_queue_resize_no_redraw (widget);
6984 _gtk_container_dequeue_resize_handler (container);
6990 /* Handle any position changes.
6992 if (configure_request_pos_changed)
6994 gdk_window_move (gdk_window,
6995 new_request.x, new_request.y);
6998 /* And run the resize queue.
7000 gtk_container_resize_children (container);
7003 /* We have now processed a move/resize since the last position
7004 * constraint change, setting of the initial position, or resize.
7005 * (Not resetting these flags here can lead to infinite loops for
7006 * GTK_RESIZE_IMMEDIATE containers)
7008 info->position_constraints_changed = FALSE;
7009 info->initial_pos_set = FALSE;
7010 info->resize_width = -1;
7011 info->resize_height = -1;
7014 /* Compare two sets of Geometry hints for equality.
7017 gtk_window_compare_hints (GdkGeometry *geometry_a,
7019 GdkGeometry *geometry_b,
7022 if (flags_a != flags_b)
7025 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7026 (geometry_a->min_width != geometry_b->min_width ||
7027 geometry_a->min_height != geometry_b->min_height))
7030 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7031 (geometry_a->max_width != geometry_b->max_width ||
7032 geometry_a->max_height != geometry_b->max_height))
7035 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7036 (geometry_a->base_width != geometry_b->base_width ||
7037 geometry_a->base_height != geometry_b->base_height))
7040 if ((flags_a & GDK_HINT_ASPECT) &&
7041 (geometry_a->min_aspect != geometry_b->min_aspect ||
7042 geometry_a->max_aspect != geometry_b->max_aspect))
7045 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7046 (geometry_a->width_inc != geometry_b->width_inc ||
7047 geometry_a->height_inc != geometry_b->height_inc))
7050 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7051 geometry_a->win_gravity != geometry_b->win_gravity)
7058 _gtk_window_constrain_size (GtkWindow *window,
7064 GtkWindowPrivate *priv;
7065 GtkWindowGeometryInfo *info;
7067 g_return_if_fail (GTK_IS_WINDOW (window));
7069 priv = window->priv;
7071 info = priv->geometry_info;
7074 GdkWindowHints flags = info->last.flags;
7075 GdkGeometry *geometry = &info->last.geometry;
7077 gtk_window_constrain_size (window,
7088 gtk_window_constrain_size (GtkWindow *window,
7089 GdkGeometry *geometry,
7096 gdk_window_constrain_size (geometry, flags, width, height,
7097 new_width, new_height);
7100 /* Compute the set of geometry hints and flags for a window
7101 * based on the application set geometry, and requisition
7102 * of the window. gtk_widget_get_preferred_size() must have been
7106 gtk_window_compute_hints (GtkWindow *window,
7107 GdkGeometry *new_geometry,
7110 GtkWindowPrivate *priv = window->priv;
7112 gint extra_width = 0;
7113 gint extra_height = 0;
7114 GtkWindowGeometryInfo *geometry_info;
7115 GtkRequisition requisition;
7117 widget = GTK_WIDGET (window);
7119 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7120 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7124 *new_flags = geometry_info->mask;
7125 *new_geometry = geometry_info->geometry;
7132 if (geometry_info && geometry_info->widget)
7134 /* If the geometry widget is set, then the hints really apply to that
7135 * widget. This is pretty much meaningless unless the window layout
7136 * is such that the rest of the window adds fixed size borders to
7137 * the geometry widget. Our job is to figure the size of the borders;
7138 * We do that by asking how big the toplevel would be if the
7139 * geometry widget was *really big*.
7142 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7143 * |GGGGG B| in the border can confuse things
7149 * |AAAAAAAAA | When the geometry widget is large, things are
7150 * |GGGGGGGGGGB| clearer.
7155 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7156 GtkRequisition requisition;
7157 int current_width, current_height;
7159 _gtk_widget_override_size_request (geometry_info->widget,
7160 TEMPORARY_SIZE, TEMPORARY_SIZE,
7161 ¤t_width, ¤t_height);
7162 gtk_widget_get_preferred_size (widget,
7163 &requisition, NULL);
7164 _gtk_widget_restore_size_request (geometry_info->widget,
7165 current_width, current_height);
7167 extra_width = requisition.width - TEMPORARY_SIZE;
7168 extra_height = requisition.height - TEMPORARY_SIZE;
7170 if (extra_width < 0 || extra_height < 0)
7172 g_warning("Toplevel size doesn't seem to directly depend on the "
7173 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7174 "The geometry widget might not be in the window, or it might not "
7175 "be packed into the window appropriately");
7176 extra_width = MAX(extra_width, 0);
7177 extra_height = MAX(extra_height, 0);
7179 #undef TEMPORARY_SIZE
7182 /* We don't want to set GDK_HINT_POS in here, we just set it
7183 * in gtk_window_move_resize() when we want the position
7187 if (*new_flags & GDK_HINT_BASE_SIZE)
7189 new_geometry->base_width += extra_width;
7190 new_geometry->base_height += extra_height;
7194 /* For simplicity, we always set the base hint, even when we
7195 * don't expect it to have any visible effect.
7196 * (Note: geometry_size_to_pixels() depends on this.)
7198 *new_flags |= GDK_HINT_BASE_SIZE;
7200 new_geometry->base_width = extra_width;
7201 new_geometry->base_height = extra_height;
7203 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7204 * base size is the minimum size */
7205 if (*new_flags & GDK_HINT_MIN_SIZE)
7207 if (new_geometry->min_width > 0)
7208 new_geometry->base_width += new_geometry->min_width;
7209 if (new_geometry->min_height > 0)
7210 new_geometry->base_height += new_geometry->min_height;
7214 if (*new_flags & GDK_HINT_MIN_SIZE)
7216 if (new_geometry->min_width < 0)
7217 new_geometry->min_width = requisition.width;
7219 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7221 if (new_geometry->min_height < 0)
7222 new_geometry->min_height = requisition.height;
7224 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7228 *new_flags |= GDK_HINT_MIN_SIZE;
7230 new_geometry->min_width = requisition.width;
7231 new_geometry->min_height = requisition.height;
7234 if (*new_flags & GDK_HINT_MAX_SIZE)
7236 if (new_geometry->max_width < 0)
7237 new_geometry->max_width = requisition.width;
7239 new_geometry->max_width += extra_width;
7241 if (new_geometry->max_height < 0)
7242 new_geometry->max_height = requisition.height;
7244 new_geometry->max_height += extra_height;
7246 else if (!priv->resizable)
7248 *new_flags |= GDK_HINT_MAX_SIZE;
7250 new_geometry->max_width = requisition.width;
7251 new_geometry->max_height = requisition.height;
7254 *new_flags |= GDK_HINT_WIN_GRAVITY;
7255 new_geometry->win_gravity = priv->gravity;
7258 /***********************
7259 * Redrawing functions *
7260 ***********************/
7263 gtk_window_draw (GtkWidget *widget,
7266 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7267 GtkStyleContext *context;
7268 gboolean ret = FALSE;
7270 context = gtk_widget_get_style_context (widget);
7272 gtk_style_context_save (context);
7274 if (!gtk_widget_get_app_paintable (widget))
7276 GtkStateFlags state;
7278 state = gtk_widget_get_state_flags (widget);
7280 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7281 state |= GTK_STATE_FLAG_FOCUSED;
7283 gtk_style_context_set_state (context, state);
7284 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7285 gtk_render_background (context, cr, 0, 0,
7286 gtk_widget_get_allocated_width (widget),
7287 gtk_widget_get_allocated_height (widget));
7290 gtk_style_context_restore (context);
7292 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7293 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7295 if (priv->grip_window != NULL &&
7296 gtk_cairo_should_draw_window (cr, priv->grip_window))
7300 gtk_style_context_save (context);
7303 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7304 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7306 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7307 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7308 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7311 gtk_style_context_restore (context);
7318 * gtk_window_present:
7319 * @window: a #GtkWindow
7321 * Presents a window to the user. This may mean raising the window
7322 * in the stacking order, deiconifying it, moving it to the current
7323 * desktop, and/or giving it the keyboard focus, possibly dependent
7324 * on the user's platform, window manager, and preferences.
7326 * If @window is hidden, this function calls gtk_widget_show()
7329 * This function should be used when the user tries to open a window
7330 * that's already open. Say for example the preferences dialog is
7331 * currently open, and the user chooses Preferences from the menu
7332 * a second time; use gtk_window_present() to move the already-open dialog
7333 * where the user can see it.
7335 * If you are calling this function in response to a user interaction,
7336 * it is preferable to use gtk_window_present_with_time().
7340 gtk_window_present (GtkWindow *window)
7342 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7346 * gtk_window_present_with_time:
7347 * @window: a #GtkWindow
7348 * @timestamp: the timestamp of the user interaction (typically a
7349 * button or key press event) which triggered this call
7351 * Presents a window to the user in response to a user interaction.
7352 * If you need to present a window without a timestamp, use
7353 * gtk_window_present(). See gtk_window_present() for details.
7358 gtk_window_present_with_time (GtkWindow *window,
7362 GdkWindow *gdk_window;
7364 g_return_if_fail (GTK_IS_WINDOW (window));
7366 widget = GTK_WIDGET (window);
7368 if (gtk_widget_get_visible (widget))
7370 gdk_window = gtk_widget_get_window (widget);
7372 g_assert (gdk_window != NULL);
7374 gdk_window_show (gdk_window);
7376 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7377 if (timestamp == GDK_CURRENT_TIME)
7379 #ifdef GDK_WINDOWING_X11
7380 GdkDisplay *display;
7382 display = gtk_widget_get_display (GTK_WIDGET (window));
7383 timestamp = gdk_x11_display_get_user_time (display);
7385 timestamp = gtk_get_current_event_time ();
7389 gdk_window_focus (gdk_window, timestamp);
7393 gtk_widget_show (widget);
7398 * gtk_window_iconify:
7399 * @window: a #GtkWindow
7401 * Asks to iconify (i.e. minimize) the specified @window. Note that
7402 * you shouldn't assume the window is definitely iconified afterward,
7403 * because other entities (e.g. the user or <link
7404 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7405 * again, or there may not be a window manager in which case
7406 * iconification isn't possible, etc. But normally the window will end
7407 * up iconified. Just don't write code that crashes if not.
7409 * It's permitted to call this function before showing a window,
7410 * in which case the window will be iconified before it ever appears
7413 * You can track iconification via the "window-state-event" signal
7418 gtk_window_iconify (GtkWindow *window)
7420 GtkWindowPrivate *priv;
7422 GdkWindow *toplevel;
7424 g_return_if_fail (GTK_IS_WINDOW (window));
7426 priv = window->priv;
7427 widget = GTK_WIDGET (window);
7429 priv->iconify_initially = TRUE;
7431 toplevel = gtk_widget_get_window (widget);
7433 if (toplevel != NULL)
7434 gdk_window_iconify (toplevel);
7438 * gtk_window_deiconify:
7439 * @window: a #GtkWindow
7441 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7442 * that you shouldn't assume the window is definitely deiconified
7443 * afterward, because other entities (e.g. the user or <link
7444 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7445 * again before your code which assumes deiconification gets to run.
7447 * You can track iconification via the "window-state-event" signal
7451 gtk_window_deiconify (GtkWindow *window)
7453 GtkWindowPrivate *priv;
7455 GdkWindow *toplevel;
7457 g_return_if_fail (GTK_IS_WINDOW (window));
7459 priv = window->priv;
7460 widget = GTK_WIDGET (window);
7462 priv->iconify_initially = FALSE;
7464 toplevel = gtk_widget_get_window (widget);
7466 if (toplevel != NULL)
7467 gdk_window_deiconify (toplevel);
7472 * @window: a #GtkWindow
7474 * Asks to stick @window, which means that it will appear on all user
7475 * desktops. Note that you shouldn't assume the window is definitely
7476 * stuck afterward, because other entities (e.g. the user or <link
7477 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7478 * again, and some window managers do not support sticking
7479 * windows. But normally the window will end up stuck. Just don't
7480 * write code that crashes if not.
7482 * It's permitted to call this function before showing a window.
7484 * You can track stickiness via the "window-state-event" signal
7489 gtk_window_stick (GtkWindow *window)
7491 GtkWindowPrivate *priv;
7493 GdkWindow *toplevel;
7495 g_return_if_fail (GTK_IS_WINDOW (window));
7497 priv = window->priv;
7498 widget = GTK_WIDGET (window);
7500 priv->stick_initially = TRUE;
7502 toplevel = gtk_widget_get_window (widget);
7504 if (toplevel != NULL)
7505 gdk_window_stick (toplevel);
7509 * gtk_window_unstick:
7510 * @window: a #GtkWindow
7512 * Asks to unstick @window, which means that it will appear on only
7513 * one of the user's desktops. Note that you shouldn't assume the
7514 * window is definitely unstuck afterward, because other entities
7515 * (e.g. the user or <link linkend="gtk-X11-arch">window
7516 * manager</link>) could stick it again. But normally the window will
7517 * end up stuck. Just don't write code that crashes if not.
7519 * You can track stickiness via the "window-state-event" signal
7524 gtk_window_unstick (GtkWindow *window)
7526 GtkWindowPrivate *priv;
7528 GdkWindow *toplevel;
7530 g_return_if_fail (GTK_IS_WINDOW (window));
7532 priv = window->priv;
7533 widget = GTK_WIDGET (window);
7535 priv->stick_initially = FALSE;
7537 toplevel = gtk_widget_get_window (widget);
7539 if (toplevel != NULL)
7540 gdk_window_unstick (toplevel);
7544 * gtk_window_maximize:
7545 * @window: a #GtkWindow
7547 * Asks to maximize @window, so that it becomes full-screen. Note that
7548 * you shouldn't assume the window is definitely maximized afterward,
7549 * because other entities (e.g. the user or <link
7550 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7551 * again, and not all window managers support maximization. But
7552 * normally the window will end up maximized. Just don't write code
7553 * that crashes if not.
7555 * It's permitted to call this function before showing a window,
7556 * in which case the window will be maximized when it appears onscreen
7559 * You can track maximization via the "window-state-event" signal
7564 gtk_window_maximize (GtkWindow *window)
7566 GtkWindowPrivate *priv;
7568 GdkWindow *toplevel;
7570 g_return_if_fail (GTK_IS_WINDOW (window));
7572 priv = window->priv;
7573 widget = GTK_WIDGET (window);
7575 priv->maximize_initially = TRUE;
7577 toplevel = gtk_widget_get_window (widget);
7579 if (toplevel != NULL)
7580 gdk_window_maximize (toplevel);
7584 * gtk_window_unmaximize:
7585 * @window: a #GtkWindow
7587 * Asks to unmaximize @window. Note that you shouldn't assume the
7588 * window is definitely unmaximized afterward, because other entities
7589 * (e.g. the user or <link linkend="gtk-X11-arch">window
7590 * manager</link>) could maximize it again, and not all window
7591 * managers honor requests to unmaximize. But normally the window will
7592 * end up unmaximized. Just don't write code that crashes if not.
7594 * You can track maximization via the "window-state-event" signal
7599 gtk_window_unmaximize (GtkWindow *window)
7601 GtkWindowPrivate *priv;
7603 GdkWindow *toplevel;
7605 g_return_if_fail (GTK_IS_WINDOW (window));
7607 priv = window->priv;
7608 widget = GTK_WIDGET (window);
7610 priv->maximize_initially = FALSE;
7612 toplevel = gtk_widget_get_window (widget);
7614 if (toplevel != NULL)
7615 gdk_window_unmaximize (toplevel);
7619 * gtk_window_fullscreen:
7620 * @window: a #GtkWindow
7622 * Asks to place @window in the fullscreen state. Note that you
7623 * shouldn't assume the window is definitely full screen afterward,
7624 * because other entities (e.g. the user or <link
7625 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7626 * again, and not all window managers honor requests to fullscreen
7627 * windows. But normally the window will end up fullscreen. Just
7628 * don't write code that crashes if not.
7630 * You can track the fullscreen state via the "window-state-event" signal
7636 gtk_window_fullscreen (GtkWindow *window)
7638 GtkWindowPrivate *priv;
7640 GdkWindow *toplevel;
7642 g_return_if_fail (GTK_IS_WINDOW (window));
7644 priv = window->priv;
7645 widget = GTK_WIDGET (window);
7647 priv->fullscreen_initially = TRUE;
7649 toplevel = gtk_widget_get_window (widget);
7651 if (toplevel != NULL)
7652 gdk_window_fullscreen (toplevel);
7656 * gtk_window_unfullscreen:
7657 * @window: a #GtkWindow
7659 * Asks to toggle off the fullscreen state for @window. Note that you
7660 * shouldn't assume the window is definitely not full screen
7661 * afterward, because other entities (e.g. the user or <link
7662 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7663 * again, and not all window managers honor requests to unfullscreen
7664 * windows. But normally the window will end up restored to its normal
7665 * state. Just don't write code that crashes if not.
7667 * You can track the fullscreen state via the "window-state-event" signal
7673 gtk_window_unfullscreen (GtkWindow *window)
7676 GdkWindow *toplevel;
7677 GtkWindowPrivate *priv;
7679 g_return_if_fail (GTK_IS_WINDOW (window));
7681 priv = window->priv;
7682 widget = GTK_WIDGET (window);
7684 priv->fullscreen_initially = FALSE;
7686 toplevel = gtk_widget_get_window (widget);
7688 if (toplevel != NULL)
7689 gdk_window_unfullscreen (toplevel);
7693 * gtk_window_set_keep_above:
7694 * @window: a #GtkWindow
7695 * @setting: whether to keep @window above other windows
7697 * Asks to keep @window above, so that it stays on top. Note that
7698 * you shouldn't assume the window is definitely above afterward,
7699 * because other entities (e.g. the user or <link
7700 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7701 * and not all window managers support keeping windows above. But
7702 * normally the window will end kept above. Just don't write code
7703 * that crashes if not.
7705 * It's permitted to call this function before showing a window,
7706 * in which case the window will be kept above when it appears onscreen
7709 * You can track the above state via the "window-state-event" signal
7712 * Note that, according to the <ulink
7713 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7714 * Manager Hints</ulink> specification, the above state is mainly meant
7715 * for user preferences and should not be used by applications e.g. for
7716 * drawing attention to their dialogs.
7721 gtk_window_set_keep_above (GtkWindow *window,
7725 GtkWindowPrivate *priv;
7726 GdkWindow *toplevel;
7728 g_return_if_fail (GTK_IS_WINDOW (window));
7730 priv = window->priv;
7731 widget = GTK_WIDGET (window);
7733 priv->above_initially = setting != FALSE;
7735 priv->below_initially = FALSE;
7737 toplevel = gtk_widget_get_window (widget);
7739 if (toplevel != NULL)
7740 gdk_window_set_keep_above (toplevel, setting);
7744 * gtk_window_set_keep_below:
7745 * @window: a #GtkWindow
7746 * @setting: whether to keep @window below other windows
7748 * Asks to keep @window below, so that it stays in bottom. Note that
7749 * you shouldn't assume the window is definitely below afterward,
7750 * because other entities (e.g. the user or <link
7751 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7752 * and not all window managers support putting windows below. But
7753 * normally the window will be kept below. Just don't write code
7754 * that crashes if not.
7756 * It's permitted to call this function before showing a window,
7757 * in which case the window will be kept below when it appears onscreen
7760 * You can track the below state via the "window-state-event" signal
7763 * Note that, according to the <ulink
7764 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7765 * Manager Hints</ulink> specification, the above state is mainly meant
7766 * for user preferences and should not be used by applications e.g. for
7767 * drawing attention to their dialogs.
7772 gtk_window_set_keep_below (GtkWindow *window,
7776 GtkWindowPrivate *priv;
7777 GdkWindow *toplevel;
7779 g_return_if_fail (GTK_IS_WINDOW (window));
7781 priv = window->priv;
7782 widget = GTK_WIDGET (window);
7784 priv->below_initially = setting != FALSE;
7786 priv->above_initially = FALSE;
7788 toplevel = gtk_widget_get_window (widget);
7790 if (toplevel != NULL)
7791 gdk_window_set_keep_below (toplevel, setting);
7795 * gtk_window_set_resizable:
7796 * @window: a #GtkWindow
7797 * @resizable: %TRUE if the user can resize this window
7799 * Sets whether the user can resize a window. Windows are user resizable
7803 gtk_window_set_resizable (GtkWindow *window,
7806 GtkWindowPrivate *priv;
7808 g_return_if_fail (GTK_IS_WINDOW (window));
7810 priv = window->priv;
7812 resizable = (resizable != FALSE);
7814 if (priv->resizable != resizable)
7816 priv->resizable = (resizable != FALSE);
7818 update_grip_visibility (window);
7820 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7822 g_object_notify (G_OBJECT (window), "resizable");
7827 * gtk_window_get_resizable:
7828 * @window: a #GtkWindow
7830 * Gets the value set by gtk_window_set_resizable().
7832 * Return value: %TRUE if the user can resize the window
7835 gtk_window_get_resizable (GtkWindow *window)
7837 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7839 return window->priv->resizable;
7843 * gtk_window_set_gravity:
7844 * @window: a #GtkWindow
7845 * @gravity: window gravity
7847 * Window gravity defines the meaning of coordinates passed to
7848 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7851 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7852 * typically "do what you mean."
7856 gtk_window_set_gravity (GtkWindow *window,
7859 GtkWindowPrivate *priv;
7861 g_return_if_fail (GTK_IS_WINDOW (window));
7863 priv = window->priv;
7865 if (gravity != priv->gravity)
7867 priv->gravity = gravity;
7869 /* gtk_window_move_resize() will adapt gravity
7871 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7873 g_object_notify (G_OBJECT (window), "gravity");
7878 * gtk_window_get_gravity:
7879 * @window: a #GtkWindow
7881 * Gets the value set by gtk_window_set_gravity().
7883 * Return value: (transfer none): window gravity
7886 gtk_window_get_gravity (GtkWindow *window)
7888 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7890 return window->priv->gravity;
7894 * gtk_window_begin_resize_drag:
7895 * @window: a #GtkWindow
7896 * @button: mouse button that initiated the drag
7897 * @edge: position of the resize control
7898 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7899 * @root_y: Y position where the user clicked to initiate the drag
7900 * @timestamp: timestamp from the click event that initiated the drag
7902 * Starts resizing a window. This function is used if an application
7903 * has window resizing controls. When GDK can support it, the resize
7904 * will be done using the standard mechanism for the <link
7905 * linkend="gtk-X11-arch">window manager</link> or windowing
7906 * system. Otherwise, GDK will try to emulate window resizing,
7907 * potentially not all that well, depending on the windowing system.
7911 gtk_window_begin_resize_drag (GtkWindow *window,
7919 GdkWindow *toplevel;
7921 g_return_if_fail (GTK_IS_WINDOW (window));
7922 widget = GTK_WIDGET (window);
7923 g_return_if_fail (gtk_widget_get_visible (widget));
7925 toplevel = gtk_widget_get_window (widget);
7927 gdk_window_begin_resize_drag (toplevel,
7934 * gtk_window_begin_move_drag:
7935 * @window: a #GtkWindow
7936 * @button: mouse button that initiated the drag
7937 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7938 * @root_y: Y position where the user clicked to initiate the drag
7939 * @timestamp: timestamp from the click event that initiated the drag
7941 * Starts moving a window. This function is used if an application has
7942 * window movement grips. When GDK can support it, the window movement
7943 * will be done using the standard mechanism for the <link
7944 * linkend="gtk-X11-arch">window manager</link> or windowing
7945 * system. Otherwise, GDK will try to emulate window movement,
7946 * potentially not all that well, depending on the windowing system.
7950 gtk_window_begin_move_drag (GtkWindow *window,
7957 GdkWindow *toplevel;
7959 g_return_if_fail (GTK_IS_WINDOW (window));
7960 widget = GTK_WIDGET (window);
7961 g_return_if_fail (gtk_widget_get_visible (widget));
7963 toplevel = gtk_widget_get_window (widget);
7965 gdk_window_begin_move_drag (toplevel,
7972 * gtk_window_set_screen:
7973 * @window: a #GtkWindow.
7974 * @screen: a #GdkScreen.
7976 * Sets the #GdkScreen where the @window is displayed; if
7977 * the window is already mapped, it will be unmapped, and
7978 * then remapped on the new screen.
7983 gtk_window_set_screen (GtkWindow *window,
7986 GtkWindowPrivate *priv;
7988 GdkScreen *previous_screen;
7989 gboolean was_mapped;
7991 g_return_if_fail (GTK_IS_WINDOW (window));
7992 g_return_if_fail (GDK_IS_SCREEN (screen));
7994 priv = window->priv;
7996 if (screen == priv->screen)
7999 widget = GTK_WIDGET (window);
8001 previous_screen = priv->screen;
8002 was_mapped = gtk_widget_get_mapped (widget);
8005 gtk_widget_unmap (widget);
8006 if (gtk_widget_get_realized (widget))
8007 gtk_widget_unrealize (widget);
8009 gtk_window_free_key_hash (window);
8010 priv->screen = screen;
8011 gtk_widget_reset_rc_styles (widget);
8012 if (screen != previous_screen)
8014 if (previous_screen)
8016 g_signal_handlers_disconnect_by_func (previous_screen,
8017 gtk_window_on_composited_changed, window);
8018 #ifdef GDK_WINDOWING_X11
8019 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8020 gtk_window_on_theme_variant_changed, window);
8023 g_signal_connect (screen, "composited-changed",
8024 G_CALLBACK (gtk_window_on_composited_changed), window);
8025 #ifdef GDK_WINDOWING_X11
8026 g_signal_connect (gtk_settings_get_for_screen (screen),
8027 "notify::gtk-application-prefer-dark-theme",
8028 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8031 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8032 _gtk_widget_propagate_composited_changed (widget);
8034 g_object_notify (G_OBJECT (window), "screen");
8037 gtk_widget_map (widget);
8041 gtk_window_set_theme_variant (GtkWindow *window)
8043 #ifdef GDK_WINDOWING_X11
8044 GdkWindow *gdk_window;
8045 gboolean dark_theme_requested;
8047 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8048 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8051 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8053 if (GDK_IS_X11_WINDOW (gdk_window))
8054 gdk_x11_window_set_theme_variant (gdk_window,
8055 dark_theme_requested ? "dark" : NULL);
8060 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8064 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8065 gtk_window_set_theme_variant (window);
8069 gtk_window_on_composited_changed (GdkScreen *screen,
8072 gtk_widget_queue_draw (GTK_WIDGET (window));
8074 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8078 gtk_window_check_screen (GtkWindow *window)
8080 GtkWindowPrivate *priv = window->priv;
8083 return priv->screen;
8086 g_warning ("Screen for GtkWindow not set; you must always set\n"
8087 "a screen for a GtkWindow before using the window");
8093 * gtk_window_get_screen:
8094 * @window: a #GtkWindow.
8096 * Returns the #GdkScreen associated with @window.
8098 * Return value: (transfer none): a #GdkScreen.
8103 gtk_window_get_screen (GtkWindow *window)
8105 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8107 return window->priv->screen;
8111 * gtk_window_is_active:
8112 * @window: a #GtkWindow
8114 * Returns whether the window is part of the current active toplevel.
8115 * (That is, the toplevel window receiving keystrokes.)
8116 * The return value is %TRUE if the window is active toplevel
8117 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8118 * You might use this function if you wanted to draw a widget
8119 * differently in an active window from a widget in an inactive window.
8120 * See gtk_window_has_toplevel_focus()
8122 * Return value: %TRUE if the window part of the current active window.
8127 gtk_window_is_active (GtkWindow *window)
8129 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8131 return window->priv->is_active;
8135 * gtk_window_has_toplevel_focus:
8136 * @window: a #GtkWindow
8138 * Returns whether the input focus is within this GtkWindow.
8139 * For real toplevel windows, this is identical to gtk_window_is_active(),
8140 * but for embedded windows, like #GtkPlug, the results will differ.
8142 * Return value: %TRUE if the input focus is within this GtkWindow
8147 gtk_window_has_toplevel_focus (GtkWindow *window)
8149 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8151 return window->priv->has_toplevel_focus;
8154 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8157 gtk_window_group_init (GtkWindowGroup *group)
8159 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8160 GTK_TYPE_WINDOW_GROUP,
8161 GtkWindowGroupPrivate);
8165 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8167 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8171 * gtk_window_group_new:
8173 * Creates a new #GtkWindowGroup object. Grabs added with
8174 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8176 * Return value: a new #GtkWindowGroup.
8179 gtk_window_group_new (void)
8181 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8185 window_group_cleanup_grabs (GtkWindowGroup *group,
8188 GtkWindowGroupPrivate *priv;
8189 GtkDeviceGrabInfo *info;
8191 GSList *to_remove = NULL;
8195 tmp_list = priv->grabs;
8198 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8199 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8200 tmp_list = tmp_list->next;
8205 gtk_grab_remove (to_remove->data);
8206 g_object_unref (to_remove->data);
8207 to_remove = g_slist_delete_link (to_remove, to_remove);
8210 tmp_list = priv->device_grabs;
8214 info = tmp_list->data;
8216 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8217 to_remove = g_slist_prepend (to_remove, info);
8219 tmp_list = tmp_list->next;
8224 info = to_remove->data;
8226 gtk_device_grab_remove (info->widget, info->device);
8227 to_remove = g_slist_delete_link (to_remove, to_remove);
8232 * gtk_window_group_add_window:
8233 * @window_group: a #GtkWindowGroup
8234 * @window: the #GtkWindow to add
8236 * Adds a window to a #GtkWindowGroup.
8239 gtk_window_group_add_window (GtkWindowGroup *window_group,
8242 GtkWindowPrivate *priv;
8244 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8245 g_return_if_fail (GTK_IS_WINDOW (window));
8247 priv = window->priv;
8249 if (priv->group != window_group)
8251 g_object_ref (window);
8252 g_object_ref (window_group);
8255 gtk_window_group_remove_window (priv->group, window);
8257 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8259 priv->group = window_group;
8261 g_object_unref (window);
8266 * gtk_window_group_remove_window:
8267 * @window_group: a #GtkWindowGroup
8268 * @window: the #GtkWindow to remove
8270 * Removes a window from a #GtkWindowGroup.
8273 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8276 GtkWindowPrivate *priv;
8278 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8279 g_return_if_fail (GTK_IS_WINDOW (window));
8280 priv = window->priv;
8281 g_return_if_fail (priv->group == window_group);
8283 g_object_ref (window);
8285 window_group_cleanup_grabs (window_group, window);
8288 g_object_unref (window_group);
8289 g_object_unref (window);
8293 * gtk_window_group_list_windows:
8294 * @window_group: a #GtkWindowGroup
8296 * Returns a list of the #GtkWindows that belong to @window_group.
8298 * Returns: (element-type GtkWindow) (transfer container): A
8299 * newly-allocated list of windows inside the group.
8304 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8306 GList *toplevels, *toplevel, *group_windows;
8308 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8310 group_windows = NULL;
8311 toplevels = gtk_window_list_toplevels ();
8313 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8315 GtkWindow *window = toplevel->data;
8317 if (window_group == window->priv->group)
8318 group_windows = g_list_prepend (group_windows, window);
8321 g_list_free (toplevels);
8323 return g_list_reverse (group_windows);
8327 * gtk_window_get_group:
8328 * @window: (allow-none): a #GtkWindow, or %NULL
8330 * Returns the group for @window or the default group, if
8331 * @window is %NULL or if @window does not have an explicit
8334 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8339 gtk_window_get_group (GtkWindow *window)
8341 if (window && window->priv->group)
8342 return window->priv->group;
8345 static GtkWindowGroup *default_group = NULL;
8348 default_group = gtk_window_group_new ();
8350 return default_group;
8355 * gtk_window_has_group:
8356 * @window: a #GtkWindow
8358 * Returns whether @window has an explicit window group.
8360 * Return value: %TRUE if @window has an explicit window group.
8365 gtk_window_has_group (GtkWindow *window)
8367 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8369 return window->priv->group != NULL;
8373 * gtk_window_group_get_current_grab:
8374 * @window_group: a #GtkWindowGroup
8376 * Gets the current grab widget of the given group,
8377 * see gtk_grab_add().
8379 * Returns: (transfer none): the current grab widget of the group
8384 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8386 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8388 if (window_group->priv->grabs)
8389 return GTK_WIDGET (window_group->priv->grabs->data);
8394 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8397 GtkWindowGroupPrivate *priv;
8399 priv = window_group->priv;
8400 priv->grabs = g_slist_prepend (priv->grabs, widget);
8404 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8407 GtkWindowGroupPrivate *priv;
8409 priv = window_group->priv;
8410 priv->grabs = g_slist_remove (priv->grabs, widget);
8415 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8418 gboolean block_others)
8420 GtkWindowGroupPrivate *priv;
8421 GtkDeviceGrabInfo *info;
8423 priv = window_group->priv;
8425 info = g_slice_new0 (GtkDeviceGrabInfo);
8426 info->widget = widget;
8427 info->device = device;
8428 info->block_others = block_others;
8430 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8434 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8438 GtkWindowGroupPrivate *priv;
8439 GtkDeviceGrabInfo *info;
8440 GSList *list, *node = NULL;
8441 GdkDevice *other_device;
8443 priv = window_group->priv;
8444 other_device = gdk_device_get_associated_device (device);
8445 list = priv->device_grabs;
8451 if (info->widget == widget &&
8452 (info->device == device ||
8453 info->device == other_device))
8466 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8467 g_slice_free (GtkDeviceGrabInfo, info);
8472 * gtk_window_group_get_current_device_grab:
8473 * @window_group: a #GtkWindowGroup
8474 * @device: a #GdkDevice
8476 * Returns the current grab widget for @device, or %NULL if none.
8478 * Returns: (transfer none): The grab widget, or %NULL
8483 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8486 GtkWindowGroupPrivate *priv;
8487 GtkDeviceGrabInfo *info;
8488 GdkDevice *other_device;
8491 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8492 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8494 priv = window_group->priv;
8495 list = priv->device_grabs;
8496 other_device = gdk_device_get_associated_device (device);
8503 if (info->device == device ||
8504 info->device == other_device)
8505 return info->widget;
8512 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8516 GtkWindowGroupPrivate *priv;
8517 GtkDeviceGrabInfo *info;
8518 GdkDevice *other_device;
8521 priv = window_group->priv;
8522 other_device = gdk_device_get_associated_device (device);
8523 list = priv->device_grabs;
8530 /* Look for blocking grabs on other device pairs
8531 * that have the passed widget within the GTK+ grab.
8533 if (info->block_others &&
8534 info->device != device &&
8535 info->device != other_device &&
8536 (info->widget == widget ||
8537 gtk_widget_is_ancestor (widget, info->widget)))
8545 Derived from XParseGeometry() in XFree86
8547 Copyright 1985, 1986, 1987,1998 The Open Group
8549 All Rights Reserved.
8551 The above copyright notice and this permission notice shall be included
8552 in all copies or substantial portions of the Software.
8554 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8555 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8556 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8557 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8558 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8559 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8560 OTHER DEALINGS IN THE SOFTWARE.
8562 Except as contained in this notice, the name of The Open Group shall
8563 not be used in advertising or otherwise to promote the sale, use or
8564 other dealings in this Software without prior written authorization
8565 from The Open Group.
8570 * XParseGeometry parses strings of the form
8571 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8572 * width, height, xoffset, and yoffset are unsigned integers.
8573 * Example: "=80x24+300-49"
8574 * The equal sign is optional.
8575 * It returns a bitmask that indicates which of the four values
8576 * were actually found in the string. For each value found,
8577 * the corresponding argument is updated; for each value
8578 * not found, the corresponding argument is left unchanged.
8581 /* The following code is from Xlib, and is minimally modified, so we
8582 * can track any upstream changes if required. Don't change this
8583 * code. Or if you do, put in a huge comment marking which thing
8588 read_int (gchar *string,
8596 else if (*string == '-')
8602 for (; (*string >= '0') && (*string <= '9'); string++)
8604 result = (result * 10) + (*string - '0');
8616 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8617 * value (x, y, width, height) was found in the parsed string.
8619 #define NoValue 0x0000
8620 #define XValue 0x0001
8621 #define YValue 0x0002
8622 #define WidthValue 0x0004
8623 #define HeightValue 0x0008
8624 #define AllValues 0x000F
8625 #define XNegative 0x0010
8626 #define YNegative 0x0020
8628 /* Try not to reformat/modify, so we can compare/sync with X sources */
8630 gtk_XParseGeometry (const char *string,
8633 unsigned int *width,
8634 unsigned int *height)
8638 unsigned int tempWidth, tempHeight;
8640 char *nextCharacter;
8642 /* These initializations are just to silence gcc */
8648 if ( (string == NULL) || (*string == '\0')) return(mask);
8650 string++; /* ignore possible '=' at beg of geometry spec */
8652 strind = (char *)string;
8653 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8654 tempWidth = read_int(strind, &nextCharacter);
8655 if (strind == nextCharacter)
8657 strind = nextCharacter;
8661 if (*strind == 'x' || *strind == 'X') {
8663 tempHeight = read_int(strind, &nextCharacter);
8664 if (strind == nextCharacter)
8666 strind = nextCharacter;
8667 mask |= HeightValue;
8670 if ((*strind == '+') || (*strind == '-')) {
8671 if (*strind == '-') {
8673 tempX = -read_int(strind, &nextCharacter);
8674 if (strind == nextCharacter)
8676 strind = nextCharacter;
8682 tempX = read_int(strind, &nextCharacter);
8683 if (strind == nextCharacter)
8685 strind = nextCharacter;
8688 if ((*strind == '+') || (*strind == '-')) {
8689 if (*strind == '-') {
8691 tempY = -read_int(strind, &nextCharacter);
8692 if (strind == nextCharacter)
8694 strind = nextCharacter;
8701 tempY = read_int(strind, &nextCharacter);
8702 if (strind == nextCharacter)
8704 strind = nextCharacter;
8710 /* If strind isn't at the end of the string the it's an invalid
8711 geometry specification. */
8713 if (*strind != '\0') return (0);
8719 if (mask & WidthValue)
8721 if (mask & HeightValue)
8722 *height = tempHeight;
8727 * gtk_window_parse_geometry:
8728 * @window: a #GtkWindow
8729 * @geometry: geometry string
8731 * Parses a standard X Window System geometry string - see the
8732 * manual page for X (type 'man X') for details on this.
8733 * gtk_window_parse_geometry() does work on all GTK+ ports
8734 * including Win32 but is primarily intended for an X environment.
8736 * If either a size or a position can be extracted from the
8737 * geometry string, gtk_window_parse_geometry() returns %TRUE
8738 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8739 * to resize/move the window.
8741 * If gtk_window_parse_geometry() returns %TRUE, it will also
8742 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8743 * indicating to the window manager that the size/position of
8744 * the window was user-specified. This causes most window
8745 * managers to honor the geometry.
8747 * Note that for gtk_window_parse_geometry() to work as expected, it has
8748 * to be called when the window has its "final" size, i.e. after calling
8749 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8752 * #include <gtk/gtk.h>
8755 * fill_with_content (GtkWidget *vbox)
8757 * /* fill with content... */
8761 * main (int argc, char *argv[])
8763 * GtkWidget *window, *vbox;
8764 * GdkGeometry size_hints = {
8765 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8768 * gtk_init (&argc, &argv);
8770 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8771 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8773 * gtk_container_add (GTK_CONTAINER (window), vbox);
8774 * fill_with_content (vbox);
8775 * gtk_widget_show_all (vbox);
8777 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8780 * GDK_HINT_MIN_SIZE |
8781 * GDK_HINT_BASE_SIZE |
8782 * GDK_HINT_RESIZE_INC);
8786 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8787 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8790 * gtk_widget_show_all (window);
8797 * Return value: %TRUE if string was parsed successfully
8800 gtk_window_parse_geometry (GtkWindow *window,
8801 const gchar *geometry)
8803 gint result, x = 0, y = 0;
8807 gboolean size_set, pos_set;
8810 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8811 g_return_val_if_fail (geometry != NULL, FALSE);
8813 child = gtk_bin_get_child (GTK_BIN (window));
8814 if (!child || !gtk_widget_get_visible (child))
8815 g_warning ("gtk_window_parse_geometry() called on a window with no "
8816 "visible children; the window should be set up before "
8817 "gtk_window_parse_geometry() is called.");
8819 screen = gtk_window_check_screen (window);
8821 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8824 if ((result & WidthValue) || (result & HeightValue))
8826 gtk_window_set_default_size_internal (window,
8827 TRUE, result & WidthValue ? w : -1,
8828 TRUE, result & HeightValue ? h : -1,
8833 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8835 grav = GDK_GRAVITY_NORTH_WEST;
8837 if ((result & XNegative) && (result & YNegative))
8838 grav = GDK_GRAVITY_SOUTH_EAST;
8839 else if (result & XNegative)
8840 grav = GDK_GRAVITY_NORTH_EAST;
8841 else if (result & YNegative)
8842 grav = GDK_GRAVITY_SOUTH_WEST;
8844 if ((result & XValue) == 0)
8847 if ((result & YValue) == 0)
8850 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8851 grav == GDK_GRAVITY_SOUTH_EAST)
8852 y = gdk_screen_get_height (screen) - h + y;
8854 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8855 grav == GDK_GRAVITY_NORTH_EAST)
8856 x = gdk_screen_get_width (screen) - w + x;
8858 /* we don't let you put a window offscreen; maybe some people would
8859 * prefer to be able to, but it's kind of a bogus thing to do.
8868 if ((result & XValue) || (result & YValue))
8870 gtk_window_set_gravity (window, grav);
8871 gtk_window_move (window, x, y);
8875 if (size_set || pos_set)
8877 /* Set USSize, USPosition hints */
8878 GtkWindowGeometryInfo *info;
8880 info = gtk_window_get_geometry_info (window, TRUE);
8883 info->mask |= GDK_HINT_USER_POS;
8885 info->mask |= GDK_HINT_USER_SIZE;
8892 gtk_window_mnemonic_hash_foreach (guint keyval,
8898 GtkWindowKeysForeachFunc func;
8902 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8906 _gtk_window_keys_foreach (GtkWindow *window,
8907 GtkWindowKeysForeachFunc func,
8911 GtkMnemonicHash *mnemonic_hash;
8915 GtkWindowKeysForeachFunc func;
8919 info.window = window;
8921 info.func_data = func_data;
8923 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8925 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8926 gtk_window_mnemonic_hash_foreach, &info);
8928 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8931 GtkAccelGroup *group = groups->data;
8934 for (i = 0; i < group->priv->n_accels; i++)
8936 GtkAccelKey *key = &group->priv->priv_accels[i].key;
8939 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8942 groups = groups->next;
8947 gtk_window_keys_changed (GtkWindow *window)
8949 gtk_window_free_key_hash (window);
8950 gtk_window_get_key_hash (window);
8953 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8955 struct _GtkWindowKeyEntry
8959 guint is_mnemonic : 1;
8963 window_key_entry_destroy (gpointer data)
8965 g_slice_free (GtkWindowKeyEntry, data);
8969 add_to_key_hash (GtkWindow *window,
8971 GdkModifierType modifiers,
8972 gboolean is_mnemonic,
8975 GtkKeyHash *key_hash = data;
8977 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8979 entry->keyval = keyval;
8980 entry->modifiers = modifiers;
8981 entry->is_mnemonic = is_mnemonic;
8983 /* GtkAccelGroup stores lowercased accelerators. To deal
8984 * with this, if <Shift> was specified, uppercase.
8986 if (modifiers & GDK_SHIFT_MASK)
8988 if (keyval == GDK_KEY_Tab)
8989 keyval = GDK_KEY_ISO_Left_Tab;
8991 keyval = gdk_keyval_to_upper (keyval);
8994 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8998 gtk_window_get_key_hash (GtkWindow *window)
9000 GdkScreen *screen = gtk_window_check_screen (window);
9001 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9006 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9007 (GDestroyNotify)window_key_entry_destroy);
9008 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9009 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9015 gtk_window_free_key_hash (GtkWindow *window)
9017 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9020 _gtk_key_hash_free (key_hash);
9021 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9026 * gtk_window_activate_key:
9027 * @window: a #GtkWindow
9028 * @event: a #GdkEventKey
9030 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9031 * called by the default ::key_press_event handler for toplevel windows,
9032 * however in some cases it may be useful to call this directly when
9033 * overriding the standard key handling for a toplevel window.
9035 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9040 gtk_window_activate_key (GtkWindow *window,
9043 GtkKeyHash *key_hash;
9044 GtkWindowKeyEntry *found_entry = NULL;
9045 gboolean enable_mnemonics;
9046 gboolean enable_accels;
9048 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9049 g_return_val_if_fail (event != NULL, FALSE);
9051 key_hash = gtk_window_get_key_hash (window);
9056 GSList *entries = _gtk_key_hash_lookup (key_hash,
9057 event->hardware_keycode,
9059 gtk_accelerator_get_default_mod_mask (),
9062 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9063 "gtk-enable-mnemonics", &enable_mnemonics,
9064 "gtk-enable-accels", &enable_accels,
9067 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9069 GtkWindowKeyEntry *entry = tmp_list->data;
9070 if (entry->is_mnemonic)
9072 if (enable_mnemonics)
9074 found_entry = entry;
9080 if (enable_accels && !found_entry)
9082 found_entry = entry;
9087 g_slist_free (entries);
9092 if (found_entry->is_mnemonic)
9094 if (enable_mnemonics)
9095 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9096 found_entry->modifiers);
9101 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9102 found_entry->modifiers);
9110 window_update_has_focus (GtkWindow *window)
9112 GtkWindowPrivate *priv = window->priv;
9113 GtkWidget *widget = GTK_WIDGET (window);
9114 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9116 if (has_focus != priv->has_focus)
9118 priv->has_focus = has_focus;
9122 if (priv->focus_widget &&
9123 priv->focus_widget != widget &&
9124 !gtk_widget_has_focus (priv->focus_widget))
9125 do_focus_change (priv->focus_widget, TRUE);
9129 if (priv->focus_widget &&
9130 priv->focus_widget != widget &&
9131 gtk_widget_has_focus (priv->focus_widget))
9132 do_focus_change (priv->focus_widget, FALSE);
9138 * _gtk_window_set_is_active:
9139 * @window: a #GtkWindow
9140 * @is_active: %TRUE if the window is in the currently active toplevel
9142 * Internal function that sets whether the #GtkWindow is part
9143 * of the currently active toplevel window (taking into account inter-process
9147 _gtk_window_set_is_active (GtkWindow *window,
9150 GtkWindowPrivate *priv;
9152 g_return_if_fail (GTK_IS_WINDOW (window));
9154 priv = window->priv;
9156 is_active = is_active != FALSE;
9158 if (is_active != priv->is_active)
9160 priv->is_active = is_active;
9161 window_update_has_focus (window);
9163 g_object_notify (G_OBJECT (window), "is-active");
9168 * _gtk_window_set_is_toplevel:
9169 * @window: a #GtkWindow
9170 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9171 * child of the root window); %FALSE if it is not (for example, for an
9172 * in-process, parented GtkPlug)
9174 * Internal function used by #GtkPlug when it gets parented/unparented by a
9175 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9176 * global list of toplevel windows.
9179 _gtk_window_set_is_toplevel (GtkWindow *window,
9180 gboolean is_toplevel)
9183 GtkWidget *toplevel;
9185 widget = GTK_WIDGET (window);
9187 if (gtk_widget_is_toplevel (widget))
9188 g_assert (g_slist_find (toplevel_list, window) != NULL);
9190 g_assert (g_slist_find (toplevel_list, window) == NULL);
9192 if (is_toplevel == gtk_widget_is_toplevel (widget))
9197 /* Pass through regular pathways of an embedded toplevel
9198 * to go through unmapping and hiding the widget before
9199 * becomming a toplevel again.
9201 * We remain hidden after becomming toplevel in order to
9202 * avoid problems during an embedded toplevel's dispose cycle
9203 * (When a toplevel window is shown it tries to grab focus again,
9204 * this causes problems while disposing).
9206 gtk_widget_hide (widget);
9208 /* Save the toplevel this widget was previously anchored into before
9209 * propagating a hierarchy-changed.
9211 * Usually this happens by way of gtk_widget_unparent() and we are
9212 * already unanchored at this point, just adding this clause incase
9213 * things happen differently.
9215 toplevel = gtk_widget_get_toplevel (widget);
9216 if (!gtk_widget_is_toplevel (toplevel))
9219 _gtk_widget_set_is_toplevel (widget, TRUE);
9221 /* When a window becomes toplevel after being embedded and anchored
9222 * into another window we need to unset its anchored flag so that
9223 * the hierarchy changed signal kicks in properly.
9225 _gtk_widget_set_anchored (widget, FALSE);
9226 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9228 toplevel_list = g_slist_prepend (toplevel_list, window);
9232 _gtk_widget_set_is_toplevel (widget, FALSE);
9233 toplevel_list = g_slist_remove (toplevel_list, window);
9235 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9240 * _gtk_window_set_has_toplevel_focus:
9241 * @window: a #GtkWindow
9242 * @has_toplevel_focus: %TRUE if the in
9244 * Internal function that sets whether the keyboard focus for the
9245 * toplevel window (taking into account inter-process embedding.)
9248 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9249 gboolean has_toplevel_focus)
9251 GtkWindowPrivate *priv;
9253 g_return_if_fail (GTK_IS_WINDOW (window));
9255 priv = window->priv;
9257 has_toplevel_focus = has_toplevel_focus != FALSE;
9259 if (has_toplevel_focus != priv->has_toplevel_focus)
9261 priv->has_toplevel_focus = has_toplevel_focus;
9262 window_update_has_focus (window);
9264 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9269 * gtk_window_set_auto_startup_notification:
9270 * @setting: %TRUE to automatically do startup notification
9272 * By default, after showing the first #GtkWindow, GTK+ calls
9273 * gdk_notify_startup_complete(). Call this function to disable
9274 * the automatic startup notification. You might do this if your
9275 * first window is a splash screen, and you want to delay notification
9276 * until after your real main window has been shown, for example.
9278 * In that example, you would disable startup notification
9279 * temporarily, show your splash screen, then re-enable it so that
9280 * showing the main window would automatically result in notification.
9285 gtk_window_set_auto_startup_notification (gboolean setting)
9287 disable_startup_notification = !setting;
9291 * gtk_window_get_window_type:
9292 * @window: a #GtkWindow
9294 * Gets the type of the window. See #GtkWindowType.
9296 * Return value: the type of the window
9301 gtk_window_get_window_type (GtkWindow *window)
9303 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9305 return window->priv->type;
9309 * gtk_window_get_mnemonics_visible:
9310 * @window: a #GtkWindow
9312 * Gets the value of the #GtkWindow:mnemonics-visible property.
9314 * Returns: %TRUE if mnemonics are supposed to be visible
9320 gtk_window_get_mnemonics_visible (GtkWindow *window)
9322 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9324 return window->priv->mnemonics_visible;
9328 * gtk_window_set_mnemonics_visible:
9329 * @window: a #GtkWindow
9330 * @setting: the new value
9332 * Sets the #GtkWindow:mnemonics-visible property.
9337 gtk_window_set_mnemonics_visible (GtkWindow *window,
9340 GtkWindowPrivate *priv;
9342 g_return_if_fail (GTK_IS_WINDOW (window));
9344 priv = window->priv;
9346 setting = setting != FALSE;
9348 if (priv->mnemonics_visible != setting)
9350 priv->mnemonics_visible = setting;
9351 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9354 priv->mnemonics_visible_set = TRUE;
9358 _gtk_window_get_wmclass (GtkWindow *window,
9359 gchar **wmclass_name,
9360 gchar **wmclass_class)
9362 GtkWindowPrivate *priv = window->priv;
9364 *wmclass_name = priv->wmclass_name;
9365 *wmclass_class = priv->wmclass_class;
9369 * gtk_window_set_has_user_ref_count:
9370 * @window: a #GtkWindow
9371 * @setting: the new value
9373 * Tells GTK+ whether to drop its extra reference to the window
9374 * when gtk_window_destroy() is called.
9376 * This function is only exported for the benefit of language
9377 * bindings which may need to keep the window alive until their
9378 * wrapper object is garbage collected. There is no justification
9379 * for ever calling this function in an application.
9384 gtk_window_set_has_user_ref_count (GtkWindow *window,
9387 g_return_if_fail (GTK_IS_WINDOW (window));
9389 window->priv->has_user_ref_count = setting;