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/.
33 #include "gdk/gdkkeysyms.h"
37 #include "gtkprivate.h"
39 #include "gtkwindow.h"
40 #include "gtkwindow-decorate.h"
41 #include "gtkbindings.h"
42 #include "gtkkeyhash.h"
44 #include "gtkmnemonichash.h"
45 #include "gtkmenubar.h"
46 #include "gtkiconfactory.h"
47 #include "gtkicontheme.h"
48 #include "gtkmarshalers.h"
50 #include "gtkbuildable.h"
51 #include "gtksizerequest.h"
53 #ifdef GDK_WINDOWING_X11
60 * @short_description: Toplevel which can contain other widgets
62 * <refsect2 id="GtkWindow-BUILDER-UI">
63 * <title>GtkWindow as GtkBuildable</title>
65 * The GtkWindow implementation of the GtkBuildable interface supports a
66 * custom <tag class="starttag">accel-groups</tag> element, which supports
67 * any number of <tag class="starttag">group</tag> elements representing the
68 * #GtkAccelGroup objects you want to add to your window (synonymous with
69 * gtk_window_add_accel_group().
72 * <title>A UI definition fragment with accel groups</title>
73 * <programlisting><![CDATA[
74 * <object class="GtkWindow">
76 * <group name="accelgroup1"/>
82 * <object class="GtkAccelGroup" id="accelgroup1"/>
83 * ]]></programlisting>
88 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
89 typedef struct _GtkWindowGroupPrivate GtkWindowGroupPrivate;
91 struct _GtkWindowPrivate
93 GtkMnemonicHash *mnemonic_hash;
95 GtkWidget *default_widget;
96 GtkWidget *focus_widget;
97 GtkWindow *transient_parent;
98 GtkWindowGeometryInfo *geometry_info;
99 GtkWindowGroup *group;
101 GdkModifierType mnemonic_modifier;
104 GdkWindowTypeHint gdk_type_hint;
110 gchar *wmclass_class;
118 guint keys_changed_handler;
120 guint16 configure_request_count;
122 /* The following flags are initially TRUE (before a window is mapped).
123 * They cause us to compute a configure request that involves
124 * default-only parameters. Once mapped, we set them to FALSE.
125 * Then we set them to TRUE again on unmap (for position)
126 * and on unrealize (for size).
128 guint need_default_position : 1;
129 guint need_default_size : 1;
131 guint above_initially : 1;
132 guint accept_focus : 1;
133 guint below_initially : 1;
134 guint builder_visible : 1;
135 guint configure_notify_received : 1;
138 guint destroy_with_parent : 1;
139 guint focus_on_map : 1;
140 guint fullscreen_initially : 1;
141 guint gravity : 5; /* GdkGravity */
143 guint has_user_ref_count : 1;
145 guint has_toplevel_focus : 1;
146 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
148 guint maximize_initially : 1;
149 guint mnemonics_visible : 1;
150 guint mnemonics_visible_set : 1;
152 guint opacity_set : 1;
154 guint reset_type_hint : 1;
156 guint skips_pager : 1;
157 guint skips_taskbar : 1;
158 guint stick_initially : 1;
159 guint transient_parent_group : 1;
160 guint type : 4; /* GtkWindowType */
161 guint type_hint : 3; /* GdkWindowTypeHint if the hint is one of the original eight. If not, then
162 * it contains GDK_WINDOW_TYPE_HINT_NORMAL */
189 PROP_DESTROY_WITH_PARENT,
194 PROP_SKIP_TASKBAR_HINT,
195 PROP_SKIP_PAGER_HINT,
205 /* Readonly properties */
207 PROP_HAS_TOPLEVEL_FOCUS,
209 /* Writeonly properties */
212 PROP_MNEMONICS_VISIBLE,
220 GdkPixmap *icon_pixmap;
221 GdkPixmap *icon_mask;
224 guint using_default_icon : 1;
225 guint using_parent_icon : 1;
226 guint using_themed_icon : 1;
230 GdkGeometry geometry; /* Last set of geometry hints we set */
231 GdkWindowHints flags;
232 GdkRectangle configure_request;
233 } GtkWindowLastGeometryInfo;
235 struct _GtkWindowGeometryInfo
237 /* Properties that the app has set on the window
239 GdkGeometry geometry; /* Geometry hints */
241 GtkWidget *widget; /* subwidget to which hints apply */
242 /* from last gtk_window_resize () - if > 0, indicates that
243 * we should resize to this size.
248 /* From last gtk_window_move () prior to mapping -
249 * only used if initial_pos_set
254 /* Default size - used only the FIRST time we map a window,
259 /* whether to use initial_x, initial_y */
260 guint initial_pos_set : 1;
261 /* CENTER_ALWAYS or other position constraint changed since
262 * we sent the last configure request.
264 guint position_constraints_changed : 1;
266 /* if true, default_width, height come from gtk_window_parse_geometry,
267 * and thus should be multiplied by the increments and affect the
268 * geometry widget only
270 guint default_is_geometry : 1;
272 GtkWindowLastGeometryInfo last;
275 #define GTK_WINDOW_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW_GROUP, GtkWindowGroupPrivate))
277 struct _GtkDeviceGrabInfo
281 guint block_others : 1;
284 struct _GtkWindowGroupPrivate
286 GSList *device_grabs;
289 static void gtk_window_dispose (GObject *object);
290 static void gtk_window_destroy (GtkObject *object);
291 static void gtk_window_finalize (GObject *object);
292 static void gtk_window_show (GtkWidget *widget);
293 static void gtk_window_hide (GtkWidget *widget);
294 static void gtk_window_map (GtkWidget *widget);
295 static void gtk_window_unmap (GtkWidget *widget);
296 static void gtk_window_realize (GtkWidget *widget);
297 static void gtk_window_unrealize (GtkWidget *widget);
298 static void gtk_window_size_allocate (GtkWidget *widget,
299 GtkAllocation *allocation);
300 static gint gtk_window_event (GtkWidget *widget,
302 static gboolean gtk_window_map_event (GtkWidget *widget,
304 static gboolean gtk_window_frame_event (GtkWindow *window,
306 static gint gtk_window_configure_event (GtkWidget *widget,
307 GdkEventConfigure *event);
308 static gint gtk_window_key_press_event (GtkWidget *widget,
310 static gint gtk_window_key_release_event (GtkWidget *widget,
312 static gint gtk_window_enter_notify_event (GtkWidget *widget,
313 GdkEventCrossing *event);
314 static gint gtk_window_leave_notify_event (GtkWidget *widget,
315 GdkEventCrossing *event);
316 static gint gtk_window_focus_in_event (GtkWidget *widget,
317 GdkEventFocus *event);
318 static gint gtk_window_focus_out_event (GtkWidget *widget,
319 GdkEventFocus *event);
320 static gint gtk_window_client_event (GtkWidget *widget,
321 GdkEventClient *event);
322 static void gtk_window_check_resize (GtkContainer *container);
323 static gint gtk_window_focus (GtkWidget *widget,
324 GtkDirectionType direction);
325 static void gtk_window_real_set_focus (GtkWindow *window,
328 static void gtk_window_real_activate_default (GtkWindow *window);
329 static void gtk_window_real_activate_focus (GtkWindow *window);
330 static void gtk_window_move_focus (GtkWindow *window,
331 GtkDirectionType dir);
332 static void gtk_window_keys_changed (GtkWindow *window);
333 static void gtk_window_paint (GtkWidget *widget,
335 static gint gtk_window_expose (GtkWidget *widget,
336 GdkEventExpose *event);
337 static void gtk_window_unset_transient_for (GtkWindow *window);
338 static void gtk_window_transient_parent_realized (GtkWidget *parent,
340 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
343 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
345 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
348 static void gtk_window_move_resize (GtkWindow *window);
349 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
351 GdkGeometry *geometry_b,
353 static void gtk_window_constrain_size (GtkWindow *window,
354 GdkGeometry *geometry,
360 static void gtk_window_constrain_position (GtkWindow *window,
365 static void gtk_window_compute_hints (GtkWindow *window,
366 GdkGeometry *new_geometry,
368 static void gtk_window_compute_configure_request (GtkWindow *window,
369 GdkRectangle *request,
370 GdkGeometry *geometry,
373 static void gtk_window_set_default_size_internal (GtkWindow *window,
374 gboolean change_width,
376 gboolean change_height,
378 gboolean is_geometry);
380 static void update_themed_icon (GtkIconTheme *theme,
382 static GList *icon_list_from_theme (GtkWidget *widget,
384 static void gtk_window_realize_icon (GtkWindow *window);
385 static void gtk_window_unrealize_icon (GtkWindow *window);
387 static void gtk_window_notify_keys_changed (GtkWindow *window);
388 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
389 static void gtk_window_free_key_hash (GtkWindow *window);
390 static void gtk_window_on_composited_changed (GdkScreen *screen,
393 static GSList *toplevel_list = NULL;
394 static guint window_signals[LAST_SIGNAL] = { 0 };
395 static GList *default_icon_list = NULL;
396 static gchar *default_icon_name = NULL;
397 static guint default_icon_serial = 0;
398 static gboolean disable_startup_notification = FALSE;
399 static gboolean sent_startup_notification = FALSE;
401 static GQuark quark_gtk_embedded = 0;
402 static GQuark quark_gtk_window_key_hash = 0;
403 static GQuark quark_gtk_window_default_icon_pixmap = 0;
404 static GQuark quark_gtk_window_icon_info = 0;
405 static GQuark quark_gtk_buildable_accels = 0;
407 static GtkBuildableIface *parent_buildable_iface;
409 static void gtk_window_set_property (GObject *object,
413 static void gtk_window_get_property (GObject *object,
419 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
420 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
423 const GValue *value);
424 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
425 GtkBuilder *builder);
426 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
429 const gchar *tagname,
430 GMarkupParser *parser,
432 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
435 const gchar *tagname,
439 static void gtk_window_size_request_init (GtkSizeRequestIface *iface);
440 static void gtk_window_get_width (GtkSizeRequest *widget,
443 static void gtk_window_get_height (GtkSizeRequest *widget,
447 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
448 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
449 gtk_window_buildable_interface_init)
450 G_IMPLEMENT_INTERFACE (GTK_TYPE_SIZE_REQUEST,
451 gtk_window_size_request_init))
454 add_tab_bindings (GtkBindingSet *binding_set,
455 GdkModifierType modifiers,
456 GtkDirectionType direction)
458 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
460 GTK_TYPE_DIRECTION_TYPE, direction);
461 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
463 GTK_TYPE_DIRECTION_TYPE, direction);
467 add_arrow_bindings (GtkBindingSet *binding_set,
469 GtkDirectionType direction)
471 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
473 gtk_binding_entry_add_signal (binding_set, keysym, 0,
475 GTK_TYPE_DIRECTION_TYPE, direction);
476 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
478 GTK_TYPE_DIRECTION_TYPE, direction);
479 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
481 GTK_TYPE_DIRECTION_TYPE, direction);
482 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
484 GTK_TYPE_DIRECTION_TYPE, direction);
488 extract_time_from_startup_id (const gchar* startup_id)
490 gchar *timestr = g_strrstr (startup_id, "_TIME");
491 guint32 retval = GDK_CURRENT_TIME;
498 /* Skip past the "_TIME" part */
502 timestamp = strtoul (timestr, &end, 0);
503 if (end != timestr && errno == 0)
511 startup_id_is_fake (const gchar* startup_id)
513 return strncmp (startup_id, "_TIME", 5) == 0;
517 gtk_window_class_init (GtkWindowClass *klass)
519 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
520 GtkObjectClass *object_class;
521 GtkWidgetClass *widget_class;
522 GtkContainerClass *container_class;
523 GtkBindingSet *binding_set;
525 object_class = (GtkObjectClass*) klass;
526 widget_class = (GtkWidgetClass*) klass;
527 container_class = (GtkContainerClass*) klass;
529 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
530 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
531 quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap");
532 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
533 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
535 gobject_class->dispose = gtk_window_dispose;
536 gobject_class->finalize = gtk_window_finalize;
538 gobject_class->set_property = gtk_window_set_property;
539 gobject_class->get_property = gtk_window_get_property;
541 object_class->destroy = gtk_window_destroy;
543 widget_class->show = gtk_window_show;
544 widget_class->hide = gtk_window_hide;
545 widget_class->map = gtk_window_map;
546 widget_class->map_event = gtk_window_map_event;
547 widget_class->unmap = gtk_window_unmap;
548 widget_class->realize = gtk_window_realize;
549 widget_class->unrealize = gtk_window_unrealize;
550 widget_class->size_allocate = gtk_window_size_allocate;
551 widget_class->configure_event = gtk_window_configure_event;
552 widget_class->key_press_event = gtk_window_key_press_event;
553 widget_class->key_release_event = gtk_window_key_release_event;
554 widget_class->enter_notify_event = gtk_window_enter_notify_event;
555 widget_class->leave_notify_event = gtk_window_leave_notify_event;
556 widget_class->focus_in_event = gtk_window_focus_in_event;
557 widget_class->focus_out_event = gtk_window_focus_out_event;
558 widget_class->client_event = gtk_window_client_event;
559 widget_class->focus = gtk_window_focus;
560 widget_class->expose_event = gtk_window_expose;
562 container_class->check_resize = gtk_window_check_resize;
564 klass->set_focus = gtk_window_real_set_focus;
565 klass->frame_event = gtk_window_frame_event;
567 klass->activate_default = gtk_window_real_activate_default;
568 klass->activate_focus = gtk_window_real_activate_focus;
569 klass->move_focus = gtk_window_move_focus;
570 klass->keys_changed = gtk_window_keys_changed;
572 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
575 g_object_class_install_property (gobject_class,
577 g_param_spec_enum ("type",
579 P_("The type of the window"),
580 GTK_TYPE_WINDOW_TYPE,
582 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
584 g_object_class_install_property (gobject_class,
586 g_param_spec_string ("title",
588 P_("The title of the window"),
590 GTK_PARAM_READWRITE));
592 g_object_class_install_property (gobject_class,
594 g_param_spec_string ("role",
596 P_("Unique identifier for the window to be used when restoring a session"),
598 GTK_PARAM_READWRITE));
601 * GtkWindow:startup-id:
603 * The :startup-id is a write-only property for setting window's
604 * startup notification identifier. See gtk_window_set_startup_id()
609 g_object_class_install_property (gobject_class,
611 g_param_spec_string ("startup-id",
613 P_("Unique startup identifier for the window used by startup-notification"),
615 GTK_PARAM_WRITABLE));
617 g_object_class_install_property (gobject_class,
619 g_param_spec_boolean ("resizable",
621 P_("If TRUE, users can resize the window"),
623 GTK_PARAM_READWRITE));
625 g_object_class_install_property (gobject_class,
627 g_param_spec_boolean ("modal",
629 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
631 GTK_PARAM_READWRITE));
633 g_object_class_install_property (gobject_class,
635 g_param_spec_enum ("window-position",
636 P_("Window Position"),
637 P_("The initial position of the window"),
638 GTK_TYPE_WINDOW_POSITION,
640 GTK_PARAM_READWRITE));
642 g_object_class_install_property (gobject_class,
644 g_param_spec_int ("default-width",
646 P_("The default width of the window, used when initially showing the window"),
650 GTK_PARAM_READWRITE));
652 g_object_class_install_property (gobject_class,
654 g_param_spec_int ("default-height",
655 P_("Default Height"),
656 P_("The default height of the window, used when initially showing the window"),
660 GTK_PARAM_READWRITE));
662 g_object_class_install_property (gobject_class,
663 PROP_DESTROY_WITH_PARENT,
664 g_param_spec_boolean ("destroy-with-parent",
665 P_("Destroy with Parent"),
666 P_("If this window should be destroyed when the parent is destroyed"),
668 GTK_PARAM_READWRITE));
670 g_object_class_install_property (gobject_class,
672 g_param_spec_object ("icon",
674 P_("Icon for this window"),
676 GTK_PARAM_READWRITE));
677 g_object_class_install_property (gobject_class,
678 PROP_MNEMONICS_VISIBLE,
679 g_param_spec_boolean ("mnemonics-visible",
680 P_("Mnemonics Visible"),
681 P_("Whether mnemonics are currently visible in this window"),
683 GTK_PARAM_READWRITE));
686 * GtkWindow:icon-name:
688 * The :icon-name property specifies the name of the themed icon to
689 * use as the window icon. See #GtkIconTheme for more details.
693 g_object_class_install_property (gobject_class,
695 g_param_spec_string ("icon-name",
697 P_("Name of the themed icon for this window"),
699 GTK_PARAM_READWRITE));
701 g_object_class_install_property (gobject_class,
703 g_param_spec_object ("screen",
705 P_("The screen where this window will be displayed"),
707 GTK_PARAM_READWRITE));
709 g_object_class_install_property (gobject_class,
711 g_param_spec_boolean ("is-active",
713 P_("Whether the toplevel is the current active window"),
715 GTK_PARAM_READABLE));
717 g_object_class_install_property (gobject_class,
718 PROP_HAS_TOPLEVEL_FOCUS,
719 g_param_spec_boolean ("has-toplevel-focus",
720 P_("Focus in Toplevel"),
721 P_("Whether the input focus is within this GtkWindow"),
723 GTK_PARAM_READABLE));
725 g_object_class_install_property (gobject_class,
727 g_param_spec_enum ("type-hint",
729 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
730 GDK_TYPE_WINDOW_TYPE_HINT,
731 GDK_WINDOW_TYPE_HINT_NORMAL,
732 GTK_PARAM_READWRITE));
734 g_object_class_install_property (gobject_class,
735 PROP_SKIP_TASKBAR_HINT,
736 g_param_spec_boolean ("skip-taskbar-hint",
738 P_("TRUE if the window should not be in the task bar."),
740 GTK_PARAM_READWRITE));
742 g_object_class_install_property (gobject_class,
743 PROP_SKIP_PAGER_HINT,
744 g_param_spec_boolean ("skip-pager-hint",
746 P_("TRUE if the window should not be in the pager."),
748 GTK_PARAM_READWRITE));
750 g_object_class_install_property (gobject_class,
752 g_param_spec_boolean ("urgency-hint",
754 P_("TRUE if the window should be brought to the user's attention."),
756 GTK_PARAM_READWRITE));
759 * GtkWindow:accept-focus:
761 * Whether the window should receive the input focus.
765 g_object_class_install_property (gobject_class,
767 g_param_spec_boolean ("accept-focus",
769 P_("TRUE if the window should receive the input focus."),
771 GTK_PARAM_READWRITE));
774 * GtkWindow:focus-on-map:
776 * Whether the window should receive the input focus when mapped.
780 g_object_class_install_property (gobject_class,
782 g_param_spec_boolean ("focus-on-map",
784 P_("TRUE if the window should receive the input focus when mapped."),
786 GTK_PARAM_READWRITE));
789 * GtkWindow:decorated:
791 * Whether the window should be decorated by the window manager.
795 g_object_class_install_property (gobject_class,
797 g_param_spec_boolean ("decorated",
799 P_("Whether the window should be decorated by the window manager"),
801 GTK_PARAM_READWRITE));
804 * GtkWindow:deletable:
806 * Whether the window frame should have a close button.
810 g_object_class_install_property (gobject_class,
812 g_param_spec_boolean ("deletable",
814 P_("Whether the window frame should have a close button"),
816 GTK_PARAM_READWRITE));
822 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
823 * more details about window gravity.
827 g_object_class_install_property (gobject_class,
829 g_param_spec_enum ("gravity",
831 P_("The window gravity of the window"),
833 GDK_GRAVITY_NORTH_WEST,
834 GTK_PARAM_READWRITE));
838 * GtkWindow:transient-for:
840 * The transient parent of the window. See gtk_window_set_transient_for() for
841 * more details about transient windows.
845 g_object_class_install_property (gobject_class,
847 g_param_spec_object ("transient-for",
848 P_("Transient for Window"),
849 P_("The transient parent of the dialog"),
851 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
856 * The requested opacity of the window. See gtk_window_set_opacity() for
857 * more details about window opacity.
861 g_object_class_install_property (gobject_class,
863 g_param_spec_double ("opacity",
864 P_("Opacity for Window"),
865 P_("The opacity of the window, from 0 to 1"),
869 GTK_PARAM_READWRITE));
871 window_signals[SET_FOCUS] =
872 g_signal_new (I_("set-focus"),
873 G_TYPE_FROM_CLASS (gobject_class),
875 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
877 _gtk_marshal_VOID__OBJECT,
881 window_signals[FRAME_EVENT] =
882 g_signal_new (I_("frame-event"),
883 G_TYPE_FROM_CLASS (gobject_class),
885 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
886 _gtk_boolean_handled_accumulator, NULL,
887 _gtk_marshal_BOOLEAN__BOXED,
892 * GtkWindow::activate-focus:
893 * @window: the window which received the signal
895 * The ::activate-focus signal is a
896 * <link linkend="keybinding-signals">keybinding signal</link>
897 * which gets emitted when the user activates the currently
898 * focused widget of @window.
900 window_signals[ACTIVATE_FOCUS] =
901 g_signal_new (I_("activate-focus"),
902 G_TYPE_FROM_CLASS (gobject_class),
903 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
904 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
906 _gtk_marshal_VOID__VOID,
911 * GtkWindow::activate-default:
912 * @window: the window which received the signal
914 * The ::activate-default signal is a
915 * <link linkend="keybinding-signals">keybinding signal</link>
916 * which gets emitted when the user activates the default widget
919 window_signals[ACTIVATE_DEFAULT] =
920 g_signal_new (I_("activate-default"),
921 G_TYPE_FROM_CLASS (gobject_class),
922 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
923 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
925 _gtk_marshal_VOID__VOID,
930 * GtkWindow::keys-changed:
931 * @window: the window which received the signal
933 * The ::keys-changed signal gets emitted when the set of accelerators
934 * or mnemonics that are associated with @window changes.
936 window_signals[KEYS_CHANGED] =
937 g_signal_new (I_("keys-changed"),
938 G_TYPE_FROM_CLASS (gobject_class),
940 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
942 _gtk_marshal_VOID__VOID,
950 binding_set = gtk_binding_set_by_class (klass);
952 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
953 "activate-focus", 0);
954 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
955 "activate-focus", 0);
957 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
958 "activate-default", 0);
959 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
960 "activate-default", 0);
961 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
962 "activate-default", 0);
964 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
965 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
966 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
967 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
969 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
970 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
971 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
972 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
976 gtk_window_init (GtkWindow *window)
978 GtkWindowPrivate *priv;
979 GdkColormap *colormap;
981 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
986 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
987 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
989 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
991 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
994 priv->wmclass_name = g_strdup (g_get_prgname ());
995 priv->wmclass_class = g_strdup (gdk_get_program_class ());
996 priv->wm_role = NULL;
997 priv->geometry_info = NULL;
998 priv->type = GTK_WINDOW_TOPLEVEL;
999 priv->focus_widget = NULL;
1000 priv->default_widget = NULL;
1001 priv->configure_request_count = 0;
1002 priv->resizable = TRUE;
1003 priv->configure_notify_received = FALSE;
1004 priv->position = GTK_WIN_POS_NONE;
1005 priv->need_default_size = TRUE;
1006 priv->need_default_position = TRUE;
1007 priv->modal = FALSE;
1009 priv->has_frame = FALSE;
1010 priv->frame_left = 0;
1011 priv->frame_right = 0;
1012 priv->frame_top = 0;
1013 priv->frame_bottom = 0;
1014 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1015 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1016 priv->decorated = TRUE;
1017 priv->mnemonic_modifier = GDK_MOD1_MASK;
1018 priv->screen = gdk_screen_get_default ();
1020 priv->accept_focus = TRUE;
1021 priv->focus_on_map = TRUE;
1022 priv->deletable = TRUE;
1023 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1024 priv->opacity = 1.0;
1025 priv->startup_id = NULL;
1026 priv->mnemonics_visible = TRUE;
1028 colormap = _gtk_widget_peek_colormap ();
1030 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
1032 g_object_ref_sink (window);
1033 priv->has_user_ref_count = TRUE;
1034 toplevel_list = g_slist_prepend (toplevel_list, window);
1036 gtk_decorated_window_init (window);
1038 g_signal_connect (priv->screen, "composited-changed",
1039 G_CALLBACK (gtk_window_on_composited_changed), window);
1043 gtk_window_set_property (GObject *object,
1045 const GValue *value,
1048 GtkWindow *window = GTK_WINDOW (object);
1049 GtkWindowPrivate *priv = window->priv;
1054 priv->type = g_value_get_enum (value);
1057 gtk_window_set_title (window, g_value_get_string (value));
1060 gtk_window_set_role (window, g_value_get_string (value));
1062 case PROP_STARTUP_ID:
1063 gtk_window_set_startup_id (window, g_value_get_string (value));
1065 case PROP_RESIZABLE:
1066 priv->resizable = g_value_get_boolean (value);
1067 gtk_widget_queue_resize (GTK_WIDGET (window));
1070 gtk_window_set_modal (window, g_value_get_boolean (value));
1073 gtk_window_set_position (window, g_value_get_enum (value));
1075 case PROP_DEFAULT_WIDTH:
1076 gtk_window_set_default_size_internal (window,
1077 TRUE, g_value_get_int (value),
1080 case PROP_DEFAULT_HEIGHT:
1081 gtk_window_set_default_size_internal (window,
1083 TRUE, g_value_get_int (value), FALSE);
1085 case PROP_DESTROY_WITH_PARENT:
1086 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1089 gtk_window_set_icon (window,
1090 g_value_get_object (value));
1092 case PROP_ICON_NAME:
1093 gtk_window_set_icon_name (window, g_value_get_string (value));
1096 gtk_window_set_screen (window, g_value_get_object (value));
1098 case PROP_TYPE_HINT:
1099 gtk_window_set_type_hint (window,
1100 g_value_get_enum (value));
1102 case PROP_SKIP_TASKBAR_HINT:
1103 gtk_window_set_skip_taskbar_hint (window,
1104 g_value_get_boolean (value));
1106 case PROP_SKIP_PAGER_HINT:
1107 gtk_window_set_skip_pager_hint (window,
1108 g_value_get_boolean (value));
1110 case PROP_URGENCY_HINT:
1111 gtk_window_set_urgency_hint (window,
1112 g_value_get_boolean (value));
1114 case PROP_ACCEPT_FOCUS:
1115 gtk_window_set_accept_focus (window,
1116 g_value_get_boolean (value));
1118 case PROP_FOCUS_ON_MAP:
1119 gtk_window_set_focus_on_map (window,
1120 g_value_get_boolean (value));
1122 case PROP_DECORATED:
1123 gtk_window_set_decorated (window, g_value_get_boolean (value));
1125 case PROP_DELETABLE:
1126 gtk_window_set_deletable (window, g_value_get_boolean (value));
1129 gtk_window_set_gravity (window, g_value_get_enum (value));
1131 case PROP_TRANSIENT_FOR:
1132 gtk_window_set_transient_for (window, g_value_get_object (value));
1135 gtk_window_set_opacity (window, g_value_get_double (value));
1137 case PROP_MNEMONICS_VISIBLE:
1138 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1141 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1147 gtk_window_get_property (GObject *object,
1152 GtkWindow *window = GTK_WINDOW (object);
1153 GtkWindowPrivate *priv = window->priv;
1157 GtkWindowGeometryInfo *info;
1159 g_value_set_enum (value, priv->type);
1162 g_value_set_string (value, priv->wm_role);
1165 g_value_set_string (value, priv->title);
1167 case PROP_RESIZABLE:
1168 g_value_set_boolean (value, priv->resizable);
1171 g_value_set_boolean (value, priv->modal);
1174 g_value_set_enum (value, priv->position);
1176 case PROP_DEFAULT_WIDTH:
1177 info = gtk_window_get_geometry_info (window, FALSE);
1179 g_value_set_int (value, -1);
1181 g_value_set_int (value, info->default_width);
1183 case PROP_DEFAULT_HEIGHT:
1184 info = gtk_window_get_geometry_info (window, FALSE);
1186 g_value_set_int (value, -1);
1188 g_value_set_int (value, info->default_height);
1190 case PROP_DESTROY_WITH_PARENT:
1191 g_value_set_boolean (value, priv->destroy_with_parent);
1194 g_value_set_object (value, gtk_window_get_icon (window));
1196 case PROP_ICON_NAME:
1197 g_value_set_string (value, gtk_window_get_icon_name (window));
1200 g_value_set_object (value, priv->screen);
1202 case PROP_IS_ACTIVE:
1203 g_value_set_boolean (value, priv->is_active);
1205 case PROP_HAS_TOPLEVEL_FOCUS:
1206 g_value_set_boolean (value, priv->has_toplevel_focus);
1208 case PROP_TYPE_HINT:
1209 g_value_set_enum (value, priv->type_hint);
1211 case PROP_SKIP_TASKBAR_HINT:
1212 g_value_set_boolean (value,
1213 gtk_window_get_skip_taskbar_hint (window));
1215 case PROP_SKIP_PAGER_HINT:
1216 g_value_set_boolean (value,
1217 gtk_window_get_skip_pager_hint (window));
1219 case PROP_URGENCY_HINT:
1220 g_value_set_boolean (value,
1221 gtk_window_get_urgency_hint (window));
1223 case PROP_ACCEPT_FOCUS:
1224 g_value_set_boolean (value,
1225 gtk_window_get_accept_focus (window));
1227 case PROP_FOCUS_ON_MAP:
1228 g_value_set_boolean (value,
1229 gtk_window_get_focus_on_map (window));
1231 case PROP_DECORATED:
1232 g_value_set_boolean (value, gtk_window_get_decorated (window));
1234 case PROP_DELETABLE:
1235 g_value_set_boolean (value, gtk_window_get_deletable (window));
1238 g_value_set_enum (value, gtk_window_get_gravity (window));
1240 case PROP_TRANSIENT_FOR:
1241 g_value_set_object (value, gtk_window_get_transient_for (window));
1244 g_value_set_double (value, gtk_window_get_opacity (window));
1246 case PROP_MNEMONICS_VISIBLE:
1247 g_value_set_boolean (value, priv->mnemonics_visible);
1250 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1256 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1258 parent_buildable_iface = g_type_interface_peek_parent (iface);
1259 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1260 iface->parser_finished = gtk_window_buildable_parser_finished;
1261 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1262 iface->custom_finished = gtk_window_buildable_custom_finished;
1266 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1267 GtkBuilder *builder,
1269 const GValue *value)
1271 GtkWindow *window = GTK_WINDOW (buildable);
1272 GtkWindowPrivate *priv = window->priv;
1274 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1275 priv->builder_visible = TRUE;
1277 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1281 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1282 GtkBuilder *builder)
1284 GtkWindow *window = GTK_WINDOW (buildable);
1285 GtkWindowPrivate *priv = window->priv;
1289 if (priv->builder_visible)
1290 gtk_widget_show (GTK_WIDGET (buildable));
1292 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1293 for (l = accels; l; l = l->next)
1295 object = gtk_builder_get_object (builder, l->data);
1298 g_warning ("Unknown accel group %s specified in window %s",
1299 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1302 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1303 GTK_ACCEL_GROUP (object));
1307 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1309 parent_buildable_iface->parser_finished (buildable, builder);
1315 } GSListSubParserData;
1318 window_start_element (GMarkupParseContext *context,
1319 const gchar *element_name,
1320 const gchar **names,
1321 const gchar **values,
1326 GSListSubParserData *data = (GSListSubParserData*)user_data;
1328 if (strcmp (element_name, "group") == 0)
1330 for (i = 0; names[i]; i++)
1332 if (strcmp (names[i], "name") == 0)
1333 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1336 else if (strcmp (element_name, "accel-groups") == 0)
1339 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1344 static const GMarkupParser window_parser =
1346 window_start_element
1350 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1351 GtkBuilder *builder,
1353 const gchar *tagname,
1354 GMarkupParser *parser,
1357 GSListSubParserData *parser_data;
1359 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1360 tagname, parser, data))
1363 if (strcmp (tagname, "accel-groups") == 0)
1365 parser_data = g_slice_new0 (GSListSubParserData);
1366 parser_data->items = NULL;
1367 parser_data->object = G_OBJECT (buildable);
1369 *parser = window_parser;
1370 *data = parser_data;
1378 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1379 GtkBuilder *builder,
1381 const gchar *tagname,
1384 GSListSubParserData *data;
1386 parent_buildable_iface->custom_finished (buildable, builder, child,
1387 tagname, user_data);
1389 if (strcmp (tagname, "accel-groups") != 0)
1392 data = (GSListSubParserData*)user_data;
1394 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1395 data->items, (GDestroyNotify) g_slist_free);
1397 g_slice_free (GSListSubParserData, data);
1402 * @type: type of window
1404 * Creates a new #GtkWindow, which is a toplevel window that can
1405 * contain other widgets. Nearly always, the type of the window should
1406 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1407 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1408 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1409 * dialogs, though in some other toolkits dialogs are called "popups".
1410 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1411 * On X11, popup windows are not controlled by the <link
1412 * linkend="gtk-X11-arch">window manager</link>.
1414 * If you simply want an undecorated window (no window borders), use
1415 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1417 * Return value: a new #GtkWindow.
1420 gtk_window_new (GtkWindowType type)
1422 GtkWindowPrivate *priv;
1425 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1427 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1428 priv = window->priv;
1432 return GTK_WIDGET (window);
1436 * gtk_window_set_title:
1437 * @window: a #GtkWindow
1438 * @title: title of the window
1440 * Sets the title of the #GtkWindow. The title of a window will be
1441 * displayed in its title bar; on the X Window System, the title bar
1442 * is rendered by the <link linkend="gtk-X11-arch">window
1443 * manager</link>, so exactly how the title appears to users may vary
1444 * according to a user's exact configuration. The title should help a
1445 * user distinguish this window from other windows they may have
1446 * open. A good title might include the application name and current
1447 * document filename, for example.
1451 gtk_window_set_title (GtkWindow *window,
1454 GtkWindowPrivate *priv;
1458 g_return_if_fail (GTK_IS_WINDOW (window));
1460 priv = window->priv;
1461 widget = GTK_WIDGET (window);
1463 new_title = g_strdup (title);
1464 g_free (priv->title);
1465 priv->title = new_title;
1467 if (gtk_widget_get_realized (widget))
1469 gdk_window_set_title (gtk_widget_get_window (widget),
1472 gtk_decorated_window_set_title (window, title);
1475 g_object_notify (G_OBJECT (window), "title");
1479 * gtk_window_get_title:
1480 * @window: a #GtkWindow
1482 * Retrieves the title of the window. See gtk_window_set_title().
1484 * Return value: the title of the window, or %NULL if none has
1485 * been set explicitely. The returned string is owned by the widget
1486 * and must not be modified or freed.
1488 G_CONST_RETURN gchar *
1489 gtk_window_get_title (GtkWindow *window)
1491 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1493 return window->priv->title;
1497 * gtk_window_set_wmclass:
1498 * @window: a #GtkWindow
1499 * @wmclass_name: window name hint
1500 * @wmclass_class: window class hint
1502 * Don't use this function. It sets the X Window System "class" and
1503 * "name" hints for a window. According to the ICCCM, you should
1504 * always set these to the same value for all windows in an
1505 * application, and GTK+ sets them to that value by default, so calling
1506 * this function is sort of pointless. However, you may want to call
1507 * gtk_window_set_role() on each window in your application, for the
1508 * benefit of the session manager. Setting the role allows the window
1509 * manager to restore window positions when loading a saved session.
1513 gtk_window_set_wmclass (GtkWindow *window,
1514 const gchar *wmclass_name,
1515 const gchar *wmclass_class)
1517 GtkWindowPrivate *priv;
1519 g_return_if_fail (GTK_IS_WINDOW (window));
1521 priv = window->priv;
1523 g_free (priv->wmclass_name);
1524 priv->wmclass_name = g_strdup (wmclass_name);
1526 g_free (priv->wmclass_class);
1527 priv->wmclass_class = g_strdup (wmclass_class);
1529 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1530 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1534 * gtk_window_set_role:
1535 * @window: a #GtkWindow
1536 * @role: unique identifier for the window to be used when restoring a session
1538 * This function is only useful on X11, not with other GTK+ targets.
1540 * In combination with the window title, the window role allows a
1541 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1542 * same" window when an application is restarted. So for example you
1543 * might set the "toolbox" role on your app's toolbox window, so that
1544 * when the user restarts their session, the window manager can put
1545 * the toolbox back in the same place.
1547 * If a window already has a unique title, you don't need to set the
1548 * role, since the WM can use the title to identify the window when
1549 * restoring the session.
1553 gtk_window_set_role (GtkWindow *window,
1556 GtkWindowPrivate *priv;
1559 g_return_if_fail (GTK_IS_WINDOW (window));
1561 priv = window->priv;
1563 new_role = g_strdup (role);
1564 g_free (priv->wm_role);
1565 priv->wm_role = new_role;
1567 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1568 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1571 g_object_notify (G_OBJECT (window), "role");
1575 * gtk_window_set_startup_id:
1576 * @window: a #GtkWindow
1577 * @startup_id: a string with startup-notification identifier
1579 * Startup notification identifiers are used by desktop environment to
1580 * track application startup, to provide user feedback and other
1581 * features. This function changes the corresponding property on the
1582 * underlying GdkWindow. Normally, startup identifier is managed
1583 * automatically and you should only use this function in special cases
1584 * like transferring focus from other processes. You should use this
1585 * function before calling gtk_window_present() or any equivalent
1586 * function generating a window map event.
1588 * This function is only useful on X11, not with other GTK+ targets.
1593 gtk_window_set_startup_id (GtkWindow *window,
1594 const gchar *startup_id)
1596 GtkWindowPrivate *priv;
1599 g_return_if_fail (GTK_IS_WINDOW (window));
1601 priv = window->priv;
1602 widget = GTK_WIDGET (window);
1604 g_free (priv->startup_id);
1605 priv->startup_id = g_strdup (startup_id);
1607 if (gtk_widget_get_realized (widget))
1609 GdkWindow *gdk_window;
1610 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1612 gdk_window = gtk_widget_get_window (widget);
1614 #ifdef GDK_WINDOWING_X11
1615 if (timestamp != GDK_CURRENT_TIME)
1616 gdk_x11_window_set_user_time (gdk_window, timestamp);
1619 /* Here we differentiate real and "fake" startup notification IDs,
1620 * constructed on purpose just to pass interaction timestamp
1622 if (startup_id_is_fake (priv->startup_id))
1623 gtk_window_present_with_time (window, timestamp);
1626 gdk_window_set_startup_id (gdk_window,
1629 /* If window is mapped, terminate the startup-notification too */
1630 if (gtk_widget_get_mapped (widget) &&
1631 !disable_startup_notification)
1632 gdk_notify_startup_complete_with_id (priv->startup_id);
1636 g_object_notify (G_OBJECT (window), "startup-id");
1640 * gtk_window_get_role:
1641 * @window: a #GtkWindow
1643 * Returns the role of the window. See gtk_window_set_role() for
1644 * further explanation.
1646 * Return value: the role of the window if set, or %NULL. The
1647 * returned is owned by the widget and must not be modified
1650 G_CONST_RETURN gchar *
1651 gtk_window_get_role (GtkWindow *window)
1653 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1655 return window->priv->wm_role;
1659 * gtk_window_set_focus:
1660 * @window: a #GtkWindow
1661 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1662 * any focus widget for the toplevel window.
1664 * If @focus is not the current focus widget, and is focusable, sets
1665 * it as the focus widget for the window. If @focus is %NULL, unsets
1666 * the focus widget for this window. To set the focus to a particular
1667 * widget in the toplevel, it is usually more convenient to use
1668 * gtk_widget_grab_focus() instead of this function.
1671 gtk_window_set_focus (GtkWindow *window,
1674 GtkWindowPrivate *priv;
1677 g_return_if_fail (GTK_IS_WINDOW (window));
1679 priv = window->priv;
1683 g_return_if_fail (GTK_IS_WIDGET (focus));
1684 g_return_if_fail (gtk_widget_get_can_focus (focus));
1688 gtk_widget_grab_focus (focus);
1691 /* Clear the existing focus chain, so that when we focus into
1692 * the window again, we start at the beginnning.
1694 GtkWidget *widget = priv->focus_widget;
1697 while ((parent = gtk_widget_get_parent (widget)))
1700 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1704 _gtk_window_internal_set_focus (window, NULL);
1709 _gtk_window_internal_set_focus (GtkWindow *window,
1712 GtkWindowPrivate *priv;
1714 g_return_if_fail (GTK_IS_WINDOW (window));
1716 priv = window->priv;
1718 if ((priv->focus_widget != focus) ||
1719 (focus && !gtk_widget_has_focus (focus)))
1720 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1724 * gtk_window_set_default:
1725 * @window: a #GtkWindow
1726 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1727 * default widget for the toplevel.
1729 * The default widget is the widget that's activated when the user
1730 * presses Enter in a dialog (for example). This function sets or
1731 * unsets the default widget for a #GtkWindow about. When setting
1732 * (rather than unsetting) the default widget it's generally easier to
1733 * call gtk_widget_grab_focus() on the widget. Before making a widget
1734 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1735 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1738 gtk_window_set_default (GtkWindow *window,
1739 GtkWidget *default_widget)
1741 GtkWindowPrivate *priv;
1743 g_return_if_fail (GTK_IS_WINDOW (window));
1745 priv = window->priv;
1748 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1750 if (priv->default_widget != default_widget)
1752 GtkWidget *old_default_widget = NULL;
1755 g_object_ref (default_widget);
1757 if (priv->default_widget)
1759 old_default_widget = priv->default_widget;
1761 if (priv->focus_widget != priv->default_widget ||
1762 !gtk_widget_get_receives_default (priv->default_widget))
1763 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1765 gtk_widget_queue_draw (priv->default_widget);
1768 priv->default_widget = default_widget;
1770 if (priv->default_widget)
1772 if (priv->focus_widget == NULL ||
1773 !gtk_widget_get_receives_default (priv->focus_widget))
1774 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1776 gtk_widget_queue_draw (priv->default_widget);
1779 if (old_default_widget)
1780 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1784 g_object_notify (G_OBJECT (default_widget), "has-default");
1785 g_object_unref (default_widget);
1791 * gtk_window_get_default_widget:
1792 * @window: a #GtkWindow
1794 * Returns the default widget for @window. See gtk_window_set_default()
1797 * Returns: the default widget, or %NULL if there is none.
1802 gtk_window_get_default_widget (GtkWindow *window)
1804 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1806 return window->priv->default_widget;
1810 handle_keys_changed (gpointer data)
1812 GtkWindow *window = GTK_WINDOW (data);
1813 GtkWindowPrivate *priv = window->priv;
1815 if (priv->keys_changed_handler)
1817 g_source_remove (priv->keys_changed_handler);
1818 priv->keys_changed_handler = 0;
1821 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1827 gtk_window_notify_keys_changed (GtkWindow *window)
1829 GtkWindowPrivate *priv = window->priv;
1831 if (!priv->keys_changed_handler)
1832 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1836 * gtk_window_add_accel_group:
1837 * @window: window to attach accelerator group to
1838 * @accel_group: a #GtkAccelGroup
1840 * Associate @accel_group with @window, such that calling
1841 * gtk_accel_groups_activate() on @window will activate accelerators
1845 gtk_window_add_accel_group (GtkWindow *window,
1846 GtkAccelGroup *accel_group)
1848 g_return_if_fail (GTK_IS_WINDOW (window));
1849 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1851 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1852 g_signal_connect_object (accel_group, "accel-changed",
1853 G_CALLBACK (gtk_window_notify_keys_changed),
1854 window, G_CONNECT_SWAPPED);
1855 gtk_window_notify_keys_changed (window);
1859 * gtk_window_remove_accel_group:
1860 * @window: a #GtkWindow
1861 * @accel_group: a #GtkAccelGroup
1863 * Reverses the effects of gtk_window_add_accel_group().
1866 gtk_window_remove_accel_group (GtkWindow *window,
1867 GtkAccelGroup *accel_group)
1869 g_return_if_fail (GTK_IS_WINDOW (window));
1870 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1872 g_signal_handlers_disconnect_by_func (accel_group,
1873 gtk_window_notify_keys_changed,
1875 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1876 gtk_window_notify_keys_changed (window);
1879 static GtkMnemonicHash *
1880 gtk_window_get_mnemonic_hash (GtkWindow *window,
1883 GtkWindowPrivate *private = window->priv;
1885 if (!private->mnemonic_hash && create)
1886 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1888 return private->mnemonic_hash;
1892 * gtk_window_add_mnemonic:
1893 * @window: a #GtkWindow
1894 * @keyval: the mnemonic
1895 * @target: the widget that gets activated by the mnemonic
1897 * Adds a mnemonic to this window.
1900 gtk_window_add_mnemonic (GtkWindow *window,
1904 g_return_if_fail (GTK_IS_WINDOW (window));
1905 g_return_if_fail (GTK_IS_WIDGET (target));
1907 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1909 gtk_window_notify_keys_changed (window);
1913 * gtk_window_remove_mnemonic:
1914 * @window: a #GtkWindow
1915 * @keyval: the mnemonic
1916 * @target: the widget that gets activated by the mnemonic
1918 * Removes a mnemonic from this window.
1921 gtk_window_remove_mnemonic (GtkWindow *window,
1925 g_return_if_fail (GTK_IS_WINDOW (window));
1926 g_return_if_fail (GTK_IS_WIDGET (target));
1928 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1930 gtk_window_notify_keys_changed (window);
1934 * gtk_window_mnemonic_activate:
1935 * @window: a #GtkWindow
1936 * @keyval: the mnemonic
1937 * @modifier: the modifiers
1938 * @returns: %TRUE if the activation is done.
1940 * Activates the targets associated with the mnemonic.
1943 gtk_window_mnemonic_activate (GtkWindow *window,
1945 GdkModifierType modifier)
1947 GtkWindowPrivate *priv;
1949 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1951 priv = window->priv;
1953 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1955 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1957 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1964 * gtk_window_set_mnemonic_modifier:
1965 * @window: a #GtkWindow
1966 * @modifier: the modifier mask used to activate
1967 * mnemonics on this window.
1969 * Sets the mnemonic modifier for this window.
1972 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1973 GdkModifierType modifier)
1975 GtkWindowPrivate *priv;
1977 g_return_if_fail (GTK_IS_WINDOW (window));
1978 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1980 priv = window->priv;
1982 priv->mnemonic_modifier = modifier;
1983 gtk_window_notify_keys_changed (window);
1987 * gtk_window_get_mnemonic_modifier:
1988 * @window: a #GtkWindow
1990 * Returns the mnemonic modifier for this window. See
1991 * gtk_window_set_mnemonic_modifier().
1993 * Return value: the modifier mask used to activate
1994 * mnemonics on this window.
1997 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1999 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2001 return window->priv->mnemonic_modifier;
2005 * gtk_window_set_position:
2006 * @window: a #GtkWindow.
2007 * @position: a position constraint.
2009 * Sets a position constraint for this window. If the old or new
2010 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2011 * the window to be repositioned to satisfy the new constraint.
2014 gtk_window_set_position (GtkWindow *window,
2015 GtkWindowPosition position)
2017 GtkWindowPrivate *priv;
2019 g_return_if_fail (GTK_IS_WINDOW (window));
2021 priv = window->priv;
2023 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2024 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2026 GtkWindowGeometryInfo *info;
2028 info = gtk_window_get_geometry_info (window, TRUE);
2030 /* this flag causes us to re-request the CENTER_ALWAYS
2031 * constraint in gtk_window_move_resize(), see
2032 * comment in that function.
2034 info->position_constraints_changed = TRUE;
2036 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2039 priv->position = position;
2041 g_object_notify (G_OBJECT (window), "window-position");
2045 * gtk_window_activate_focus:
2046 * @window: a #GtkWindow
2048 * Activates the current focused widget within the window.
2050 * Return value: %TRUE if a widget got activated.
2053 gtk_window_activate_focus (GtkWindow *window)
2055 GtkWindowPrivate *priv;
2057 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2059 priv = window->priv;
2061 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2062 return gtk_widget_activate (priv->focus_widget);
2068 * gtk_window_get_focus:
2069 * @window: a #GtkWindow
2071 * Retrieves the current focused widget within the window.
2072 * Note that this is the widget that would have the focus
2073 * if the toplevel window focused; if the toplevel window
2074 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2075 * not be %TRUE for the widget.
2077 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2080 gtk_window_get_focus (GtkWindow *window)
2082 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2084 return window->priv->focus_widget;
2088 * gtk_window_activate_default:
2089 * @window: a #GtkWindow
2091 * Activates the default widget for the window, unless the current
2092 * focused widget has been configured to receive the default action
2093 * (see gtk_widget_set_receives_default()), in which case the
2094 * focused widget is activated.
2096 * Return value: %TRUE if a widget got activated.
2099 gtk_window_activate_default (GtkWindow *window)
2101 GtkWindowPrivate *priv;
2103 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2105 priv = window->priv;
2107 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2108 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2109 return gtk_widget_activate (priv->default_widget);
2110 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2111 return gtk_widget_activate (priv->focus_widget);
2117 * gtk_window_set_modal:
2118 * @window: a #GtkWindow
2119 * @modal: whether the window is modal
2121 * Sets a window modal or non-modal. Modal windows prevent interaction
2122 * with other windows in the same application. To keep modal dialogs
2123 * on top of main application windows, use
2124 * gtk_window_set_transient_for() to make the dialog transient for the
2125 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2126 * will then disallow lowering the dialog below the parent.
2131 gtk_window_set_modal (GtkWindow *window,
2134 GtkWindowPrivate *priv;
2137 g_return_if_fail (GTK_IS_WINDOW (window));
2139 priv = window->priv;
2141 modal = modal != FALSE;
2142 if (priv->modal == modal)
2145 priv->modal = modal;
2146 widget = GTK_WIDGET (window);
2148 /* adjust desired modality state */
2149 if (gtk_widget_get_realized (widget))
2152 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2154 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2157 if (gtk_widget_get_visible (widget))
2160 gtk_grab_add (widget);
2162 gtk_grab_remove (widget);
2165 g_object_notify (G_OBJECT (window), "modal");
2169 * gtk_window_get_modal:
2170 * @window: a #GtkWindow
2172 * Returns whether the window is modal. See gtk_window_set_modal().
2174 * Return value: %TRUE if the window is set to be modal and
2175 * establishes a grab when shown
2178 gtk_window_get_modal (GtkWindow *window)
2180 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2182 return window->priv->modal;
2186 * gtk_window_list_toplevels:
2188 * Returns a list of all existing toplevel windows. The widgets
2189 * in the list are not individually referenced. If you want
2190 * to iterate through the list and perform actions involving
2191 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2192 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2193 * then unref all the widgets afterwards.
2195 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2198 gtk_window_list_toplevels (void)
2203 for (slist = toplevel_list; slist; slist = slist->next)
2204 list = g_list_prepend (list, slist->data);
2210 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2212 GList *embedded_windows;
2214 g_return_if_fail (GTK_IS_WINDOW (window));
2216 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2217 if (embedded_windows)
2218 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2219 embedded_windows = g_list_prepend (embedded_windows,
2220 GUINT_TO_POINTER (xid));
2222 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2225 (GDestroyNotify) g_list_free : NULL);
2229 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2231 GList *embedded_windows;
2234 g_return_if_fail (GTK_IS_WINDOW (window));
2236 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2237 if (embedded_windows)
2238 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2240 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2243 embedded_windows = g_list_remove_link (embedded_windows, node);
2244 g_list_free_1 (node);
2247 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2250 (GDestroyNotify) g_list_free : NULL);
2254 gtk_window_dispose (GObject *object)
2256 GtkWindow *window = GTK_WINDOW (object);
2258 gtk_window_set_focus (window, NULL);
2259 gtk_window_set_default (window, NULL);
2261 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2265 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2267 gtk_widget_destroy (GTK_WIDGET (child));
2271 connect_parent_destroyed (GtkWindow *window)
2273 GtkWindowPrivate *priv = window->priv;
2275 if (priv->transient_parent)
2277 g_signal_connect (priv->transient_parent,
2279 G_CALLBACK (parent_destroyed_callback),
2285 disconnect_parent_destroyed (GtkWindow *window)
2287 GtkWindowPrivate *priv = window->priv;
2289 if (priv->transient_parent)
2291 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2292 parent_destroyed_callback,
2298 gtk_window_transient_parent_realized (GtkWidget *parent,
2301 if (gtk_widget_get_realized (window))
2302 gdk_window_set_transient_for (gtk_widget_get_window (window),
2303 gtk_widget_get_window (parent));
2307 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2310 if (gtk_widget_get_realized (window))
2311 gdk_property_delete (gtk_widget_get_window (window),
2312 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2316 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2320 gtk_window_set_screen (window, parent->priv->screen);
2324 gtk_window_unset_transient_for (GtkWindow *window)
2326 GtkWindowPrivate *priv = window->priv;
2328 if (priv->transient_parent)
2330 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2331 gtk_window_transient_parent_realized,
2333 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2334 gtk_window_transient_parent_unrealized,
2336 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2337 gtk_window_transient_parent_screen_changed,
2339 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2340 gtk_widget_destroyed,
2341 &priv->transient_parent);
2343 if (priv->destroy_with_parent)
2344 disconnect_parent_destroyed (window);
2346 priv->transient_parent = NULL;
2348 if (priv->transient_parent_group)
2350 priv->transient_parent_group = FALSE;
2351 gtk_window_group_remove_window (priv->group,
2358 * gtk_window_set_transient_for:
2359 * @window: a #GtkWindow
2360 * @parent: (allow-none): parent window, or %NULL
2362 * Dialog windows should be set transient for the main application
2363 * window they were spawned from. This allows <link
2364 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2365 * dialog on top of the main window, or center the dialog over the
2366 * main window. gtk_dialog_new_with_buttons() and other convenience
2367 * functions in GTK+ will sometimes call
2368 * gtk_window_set_transient_for() on your behalf.
2370 * Passing %NULL for @parent unsets the current transient window.
2372 * On Windows, this function puts the child window on top of the parent,
2373 * much as the window manager would have done on X.
2376 gtk_window_set_transient_for (GtkWindow *window,
2379 GtkWindowPrivate *priv;
2381 g_return_if_fail (GTK_IS_WINDOW (window));
2382 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2383 g_return_if_fail (window != parent);
2385 priv = window->priv;
2387 if (priv->transient_parent)
2389 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2390 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2391 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2392 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2393 GTK_WIDGET (window));
2395 gtk_window_unset_transient_for (window);
2398 priv->transient_parent = parent;
2402 g_signal_connect (parent, "destroy",
2403 G_CALLBACK (gtk_widget_destroyed),
2404 &priv->transient_parent);
2405 g_signal_connect (parent, "realize",
2406 G_CALLBACK (gtk_window_transient_parent_realized),
2408 g_signal_connect (parent, "unrealize",
2409 G_CALLBACK (gtk_window_transient_parent_unrealized),
2411 g_signal_connect (parent, "notify::screen",
2412 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2415 gtk_window_set_screen (window, parent->priv->screen);
2417 if (priv->destroy_with_parent)
2418 connect_parent_destroyed (window);
2420 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2421 gtk_widget_get_realized (GTK_WIDGET (parent)))
2422 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2423 GTK_WIDGET (window));
2425 if (parent->priv->group)
2427 gtk_window_group_add_window (parent->priv->group, window);
2428 priv->transient_parent_group = TRUE;
2434 * gtk_window_get_transient_for:
2435 * @window: a #GtkWindow
2437 * Fetches the transient parent for this window. See
2438 * gtk_window_set_transient_for().
2440 * Return value: (transfer none): the transient parent for this window, or %NULL
2441 * if no transient parent has been set.
2444 gtk_window_get_transient_for (GtkWindow *window)
2446 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2448 return window->priv->transient_parent;
2452 * gtk_window_set_opacity:
2453 * @window: a #GtkWindow
2454 * @opacity: desired opacity, between 0 and 1
2456 * Request the windowing system to make @window partially transparent,
2457 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2458 * of the opacity parameter are clamped to the [0,1] range.) On X11
2459 * this has any effect only on X screens with a compositing manager
2460 * running. See gtk_widget_is_composited(). On Windows it should work
2463 * Note that setting a window's opacity after the window has been
2464 * shown causes it to flicker once on Windows.
2469 gtk_window_set_opacity (GtkWindow *window,
2472 GtkWindowPrivate *priv;
2474 g_return_if_fail (GTK_IS_WINDOW (window));
2476 priv = window->priv;
2480 else if (opacity > 1.0)
2483 priv->opacity_set = TRUE;
2484 priv->opacity = opacity;
2486 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2487 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2492 * gtk_window_get_opacity:
2493 * @window: a #GtkWindow
2495 * Fetches the requested opacity for this window. See
2496 * gtk_window_set_opacity().
2498 * Return value: the requested opacity for this window.
2503 gtk_window_get_opacity (GtkWindow *window)
2505 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2507 return window->priv->opacity;
2511 * gtk_window_set_type_hint:
2512 * @window: a #GtkWindow
2513 * @hint: the window type
2515 * By setting the type hint for the window, you allow the window
2516 * manager to decorate and handle the window in a way which is
2517 * suitable to the function of the window in your application.
2519 * This function should be called before the window becomes visible.
2521 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2522 * will sometimes call gtk_window_set_type_hint() on your behalf.
2526 gtk_window_set_type_hint (GtkWindow *window,
2527 GdkWindowTypeHint hint)
2529 GtkWindowPrivate *priv;
2531 g_return_if_fail (GTK_IS_WINDOW (window));
2532 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2534 priv = window->priv;
2536 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2537 priv->gdk_type_hint = hint;
2539 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2541 priv->reset_type_hint = TRUE;
2542 priv->type_hint = hint;
2546 * gtk_window_get_type_hint:
2547 * @window: a #GtkWindow
2549 * Gets the type hint for this window. See gtk_window_set_type_hint().
2551 * Return value: the type hint for @window.
2554 gtk_window_get_type_hint (GtkWindow *window)
2556 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2558 return window->priv->type_hint;
2562 * gtk_window_set_skip_taskbar_hint:
2563 * @window: a #GtkWindow
2564 * @setting: %TRUE to keep this window from appearing in the task bar
2566 * Windows may set a hint asking the desktop environment not to display
2567 * the window in the task bar. This function sets this hint.
2572 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2575 GtkWindowPrivate *priv;
2577 g_return_if_fail (GTK_IS_WINDOW (window));
2579 priv = window->priv;
2581 setting = setting != FALSE;
2583 if (priv->skips_taskbar != setting)
2585 priv->skips_taskbar = setting;
2586 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2587 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2588 priv->skips_taskbar);
2589 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2594 * gtk_window_get_skip_taskbar_hint:
2595 * @window: a #GtkWindow
2597 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2599 * Return value: %TRUE if window shouldn't be in taskbar
2604 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2606 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2608 return window->priv->skips_taskbar;
2612 * gtk_window_set_skip_pager_hint:
2613 * @window: a #GtkWindow
2614 * @setting: %TRUE to keep this window from appearing in the pager
2616 * Windows may set a hint asking the desktop environment not to display
2617 * the window in the pager. This function sets this hint.
2618 * (A "pager" is any desktop navigation tool such as a workspace
2619 * switcher that displays a thumbnail representation of the windows
2625 gtk_window_set_skip_pager_hint (GtkWindow *window,
2628 GtkWindowPrivate *priv;
2630 g_return_if_fail (GTK_IS_WINDOW (window));
2632 priv = window->priv;
2634 setting = setting != FALSE;
2636 if (priv->skips_pager != setting)
2638 priv->skips_pager = setting;
2639 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2640 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2642 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2647 * gtk_window_get_skip_pager_hint:
2648 * @window: a #GtkWindow
2650 * Gets the value set by gtk_window_set_skip_pager_hint().
2652 * Return value: %TRUE if window shouldn't be in pager
2657 gtk_window_get_skip_pager_hint (GtkWindow *window)
2659 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2661 return window->priv->skips_pager;
2665 * gtk_window_set_urgency_hint:
2666 * @window: a #GtkWindow
2667 * @setting: %TRUE to mark this window as urgent
2669 * Windows may set a hint asking the desktop environment to draw
2670 * the users attention to the window. This function sets this hint.
2675 gtk_window_set_urgency_hint (GtkWindow *window,
2678 GtkWindowPrivate *priv;
2680 g_return_if_fail (GTK_IS_WINDOW (window));
2682 priv = window->priv;
2684 setting = setting != FALSE;
2686 if (priv->urgent != setting)
2688 priv->urgent = setting;
2689 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2690 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2692 g_object_notify (G_OBJECT (window), "urgency-hint");
2697 * gtk_window_get_urgency_hint:
2698 * @window: a #GtkWindow
2700 * Gets the value set by gtk_window_set_urgency_hint()
2702 * Return value: %TRUE if window is urgent
2707 gtk_window_get_urgency_hint (GtkWindow *window)
2709 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2711 return window->priv->urgent;
2715 * gtk_window_set_accept_focus:
2716 * @window: a #GtkWindow
2717 * @setting: %TRUE to let this window receive input focus
2719 * Windows may set a hint asking the desktop environment not to receive
2720 * the input focus. This function sets this hint.
2725 gtk_window_set_accept_focus (GtkWindow *window,
2728 GtkWindowPrivate *priv;
2730 g_return_if_fail (GTK_IS_WINDOW (window));
2732 priv = window->priv;
2734 setting = setting != FALSE;
2736 if (priv->accept_focus != setting)
2738 priv->accept_focus = setting;
2739 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2740 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2741 priv->accept_focus);
2742 g_object_notify (G_OBJECT (window), "accept-focus");
2747 * gtk_window_get_accept_focus:
2748 * @window: a #GtkWindow
2750 * Gets the value set by gtk_window_set_accept_focus().
2752 * Return value: %TRUE if window should receive the input focus
2757 gtk_window_get_accept_focus (GtkWindow *window)
2759 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2761 return window->priv->accept_focus;
2765 * gtk_window_set_focus_on_map:
2766 * @window: a #GtkWindow
2767 * @setting: %TRUE to let this window receive input focus on map
2769 * Windows may set a hint asking the desktop environment not to receive
2770 * the input focus when the window is mapped. This function sets this
2776 gtk_window_set_focus_on_map (GtkWindow *window,
2779 GtkWindowPrivate *priv;
2781 g_return_if_fail (GTK_IS_WINDOW (window));
2783 priv = window->priv;
2785 setting = setting != FALSE;
2787 if (priv->focus_on_map != setting)
2789 priv->focus_on_map = setting;
2790 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2791 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2792 priv->focus_on_map);
2793 g_object_notify (G_OBJECT (window), "focus-on-map");
2798 * gtk_window_get_focus_on_map:
2799 * @window: a #GtkWindow
2801 * Gets the value set by gtk_window_set_focus_on_map().
2803 * Return value: %TRUE if window should receive the input focus when
2809 gtk_window_get_focus_on_map (GtkWindow *window)
2811 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2813 return window->priv->focus_on_map;
2817 * gtk_window_set_destroy_with_parent:
2818 * @window: a #GtkWindow
2819 * @setting: whether to destroy @window with its transient parent
2821 * If @setting is %TRUE, then destroying the transient parent of @window
2822 * will also destroy @window itself. This is useful for dialogs that
2823 * shouldn't persist beyond the lifetime of the main window they're
2824 * associated with, for example.
2827 gtk_window_set_destroy_with_parent (GtkWindow *window,
2830 GtkWindowPrivate *priv;
2832 g_return_if_fail (GTK_IS_WINDOW (window));
2834 priv = window->priv;
2836 if (priv->destroy_with_parent == (setting != FALSE))
2839 if (priv->destroy_with_parent)
2841 disconnect_parent_destroyed (window);
2845 connect_parent_destroyed (window);
2848 priv->destroy_with_parent = setting;
2850 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2854 * gtk_window_get_destroy_with_parent:
2855 * @window: a #GtkWindow
2857 * Returns whether the window will be destroyed with its transient parent. See
2858 * gtk_window_set_destroy_with_parent ().
2860 * Return value: %TRUE if the window will be destroyed with its transient parent.
2863 gtk_window_get_destroy_with_parent (GtkWindow *window)
2865 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2867 return window->priv->destroy_with_parent;
2870 static GtkWindowGeometryInfo*
2871 gtk_window_get_geometry_info (GtkWindow *window,
2874 GtkWindowPrivate *priv = window->priv;
2875 GtkWindowGeometryInfo *info;
2877 info = priv->geometry_info;
2878 if (!info && create)
2880 info = g_new0 (GtkWindowGeometryInfo, 1);
2882 info->default_width = -1;
2883 info->default_height = -1;
2884 info->resize_width = -1;
2885 info->resize_height = -1;
2886 info->initial_x = 0;
2887 info->initial_y = 0;
2888 info->initial_pos_set = FALSE;
2889 info->default_is_geometry = FALSE;
2890 info->position_constraints_changed = FALSE;
2891 info->last.configure_request.x = 0;
2892 info->last.configure_request.y = 0;
2893 info->last.configure_request.width = -1;
2894 info->last.configure_request.height = -1;
2895 info->widget = NULL;
2897 priv->geometry_info = info;
2904 * gtk_window_set_geometry_hints:
2905 * @window: a #GtkWindow
2906 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
2907 * @geometry: (allow-none): struct containing geometry information or %NULL
2908 * @geom_mask: mask indicating which struct fields should be paid attention to
2910 * This function sets up hints about how a window can be resized by
2911 * the user. You can set a minimum and maximum size; allowed resize
2912 * increments (e.g. for xterm, you can only resize by the size of a
2913 * character); aspect ratios; and more. See the #GdkGeometry struct.
2917 gtk_window_set_geometry_hints (GtkWindow *window,
2918 GtkWidget *geometry_widget,
2919 GdkGeometry *geometry,
2920 GdkWindowHints geom_mask)
2922 GtkWindowGeometryInfo *info;
2924 g_return_if_fail (GTK_IS_WINDOW (window));
2925 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2927 info = gtk_window_get_geometry_info (window, TRUE);
2930 g_signal_handlers_disconnect_by_func (info->widget,
2931 gtk_widget_destroyed,
2934 info->widget = geometry_widget;
2936 g_signal_connect (geometry_widget, "destroy",
2937 G_CALLBACK (gtk_widget_destroyed),
2941 info->geometry = *geometry;
2943 /* We store gravity in priv->gravity not in the hints. */
2944 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2946 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2948 gtk_window_set_gravity (window, geometry->win_gravity);
2951 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2955 * gtk_window_set_decorated:
2956 * @window: a #GtkWindow
2957 * @setting: %TRUE to decorate the window
2959 * By default, windows are decorated with a title bar, resize
2960 * controls, etc. Some <link linkend="gtk-X11-arch">window
2961 * managers</link> allow GTK+ to disable these decorations, creating a
2962 * borderless window. If you set the decorated property to %FALSE
2963 * using this function, GTK+ will do its best to convince the window
2964 * manager not to decorate the window. Depending on the system, this
2965 * function may not have any effect when called on a window that is
2966 * already visible, so you should call it before calling gtk_window_show().
2968 * On Windows, this function always works, since there's no window manager
2973 gtk_window_set_decorated (GtkWindow *window,
2976 GtkWindowPrivate *priv;
2977 GdkWindow *gdk_window;
2979 g_return_if_fail (GTK_IS_WINDOW (window));
2981 priv = window->priv;
2983 setting = setting != FALSE;
2985 if (setting == priv->decorated)
2988 priv->decorated = setting;
2990 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
2993 if (priv->decorated)
2994 gdk_window_set_decorations (gdk_window,
2997 gdk_window_set_decorations (gdk_window,
3001 g_object_notify (G_OBJECT (window), "decorated");
3005 * gtk_window_get_decorated:
3006 * @window: a #GtkWindow
3008 * Returns whether the window has been set to have decorations
3009 * such as a title bar via gtk_window_set_decorated().
3011 * Return value: %TRUE if the window has been set to have decorations
3014 gtk_window_get_decorated (GtkWindow *window)
3016 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3018 return window->priv->decorated;
3022 * gtk_window_set_deletable:
3023 * @window: a #GtkWindow
3024 * @setting: %TRUE to decorate the window as deletable
3026 * By default, windows have a close button in the window frame. Some
3027 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3028 * disable this button. If you set the deletable property to %FALSE
3029 * using this function, GTK+ will do its best to convince the window
3030 * manager not to show a close button. Depending on the system, this
3031 * function may not have any effect when called on a window that is
3032 * already visible, so you should call it before calling gtk_window_show().
3034 * On Windows, this function always works, since there's no window manager
3040 gtk_window_set_deletable (GtkWindow *window,
3043 GtkWindowPrivate *priv;
3044 GdkWindow *gdk_window;
3046 g_return_if_fail (GTK_IS_WINDOW (window));
3048 priv = window->priv;
3050 setting = setting != FALSE;
3052 if (setting == priv->deletable)
3055 priv->deletable = setting;
3057 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3060 if (priv->deletable)
3061 gdk_window_set_functions (gdk_window,
3064 gdk_window_set_functions (gdk_window,
3065 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3068 g_object_notify (G_OBJECT (window), "deletable");
3072 * gtk_window_get_deletable:
3073 * @window: a #GtkWindow
3075 * Returns whether the window has been set to have a close button
3076 * via gtk_window_set_deletable().
3078 * Return value: %TRUE if the window has been set to have a close button
3083 gtk_window_get_deletable (GtkWindow *window)
3085 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3087 return window->priv->deletable;
3090 static GtkWindowIconInfo*
3091 get_icon_info (GtkWindow *window)
3093 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3097 free_icon_info (GtkWindowIconInfo *info)
3099 g_free (info->icon_name);
3100 g_slice_free (GtkWindowIconInfo, info);
3104 static GtkWindowIconInfo*
3105 ensure_icon_info (GtkWindow *window)
3107 GtkWindowIconInfo *info;
3109 info = get_icon_info (window);
3113 info = g_slice_new0 (GtkWindowIconInfo);
3114 g_object_set_qdata_full (G_OBJECT (window),
3115 quark_gtk_window_icon_info,
3117 (GDestroyNotify)free_icon_info);
3129 static ScreenIconInfo *
3130 get_screen_icon_info (GdkScreen *screen)
3132 ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen),
3133 quark_gtk_window_default_icon_pixmap);
3136 info = g_slice_new0 (ScreenIconInfo);
3137 g_object_set_qdata (G_OBJECT (screen),
3138 quark_gtk_window_default_icon_pixmap, info);
3141 if (info->serial != default_icon_serial)
3145 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
3146 info->pixmap = NULL;
3151 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
3155 info->serial = default_icon_serial;
3162 get_pixmap_and_mask (GdkWindow *window,
3163 GtkWindowIconInfo *parent_info,
3164 gboolean is_default_list,
3166 GdkPixmap **pmap_return,
3167 GdkBitmap **mask_return)
3169 GdkScreen *screen = gdk_drawable_get_screen (window);
3170 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
3171 GdkPixbuf *best_icon;
3175 *pmap_return = NULL;
3176 *mask_return = NULL;
3178 if (is_default_list &&
3179 default_icon_info->pixmap != NULL)
3181 /* Use shared icon pixmap for all windows on this screen.
3183 if (default_icon_info->pixmap)
3184 g_object_ref (default_icon_info->pixmap);
3185 if (default_icon_info->mask)
3186 g_object_ref (default_icon_info->mask);
3188 *pmap_return = default_icon_info->pixmap;
3189 *mask_return = default_icon_info->mask;
3191 else if (parent_info && parent_info->icon_pixmap)
3193 if (parent_info->icon_pixmap)
3194 g_object_ref (parent_info->icon_pixmap);
3195 if (parent_info->icon_mask)
3196 g_object_ref (parent_info->icon_mask);
3198 *pmap_return = parent_info->icon_pixmap;
3199 *mask_return = parent_info->icon_mask;
3203 #define IDEAL_SIZE 48
3205 best_size = G_MAXINT;
3207 tmp_list = icon_list;
3208 while (tmp_list != NULL)
3210 GdkPixbuf *pixbuf = tmp_list->data;
3213 /* average width and height - if someone passes in a rectangular
3214 * icon they deserve what they get.
3216 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3219 if (best_icon == NULL)
3226 /* icon is better if it's 32 pixels or larger, and closer to
3227 * the ideal size than the current best.
3230 (ABS (best_size - IDEAL_SIZE) <
3231 ABS (this - IDEAL_SIZE)))
3238 tmp_list = tmp_list->next;
3242 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
3243 gdk_screen_get_system_colormap (screen),
3248 /* Save pmap/mask for others to use if appropriate */
3251 parent_info->icon_pixmap = *pmap_return;
3252 parent_info->icon_mask = *mask_return;
3254 if (parent_info->icon_pixmap)
3255 g_object_ref (parent_info->icon_pixmap);
3256 if (parent_info->icon_mask)
3257 g_object_ref (parent_info->icon_mask);
3259 else if (is_default_list)
3261 default_icon_info->pixmap = *pmap_return;
3262 default_icon_info->mask = *mask_return;
3264 if (default_icon_info->pixmap)
3265 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
3266 (gpointer*)&default_icon_info->pixmap);
3267 if (default_icon_info->mask)
3268 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
3269 (gpointer*)&default_icon_info->mask);
3275 icon_list_from_theme (GtkWidget *widget,
3280 GtkIconTheme *icon_theme;
3285 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3287 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3290 for (i = 0; sizes[i]; i++)
3293 * We need an EWMH extension to handle scalable icons
3294 * by passing their name to the WM. For now just use a
3298 icon = gtk_icon_theme_load_icon (icon_theme, name,
3301 icon = gtk_icon_theme_load_icon (icon_theme, name,
3304 list = g_list_append (list, icon);
3314 gtk_window_realize_icon (GtkWindow *window)
3316 GtkWindowPrivate *priv = window->priv;
3318 GtkWindowIconInfo *info;
3319 GdkWindow *gdk_window;
3322 widget = GTK_WIDGET (window);
3323 gdk_window = gtk_widget_get_window (widget);
3325 g_return_if_fail (gdk_window != NULL);
3327 /* no point setting an icon on override-redirect */
3328 if (priv->type == GTK_WINDOW_POPUP)
3333 info = ensure_icon_info (window);
3338 g_return_if_fail (info->icon_pixmap == NULL);
3339 g_return_if_fail (info->icon_mask == NULL);
3341 info->using_default_icon = FALSE;
3342 info->using_parent_icon = FALSE;
3343 info->using_themed_icon = FALSE;
3345 icon_list = info->icon_list;
3347 /* Look up themed icon */
3348 if (icon_list == NULL && info->icon_name)
3350 icon_list = icon_list_from_theme (widget, info->icon_name);
3352 info->using_themed_icon = TRUE;
3355 /* Inherit from transient parent */
3356 if (icon_list == NULL && priv->transient_parent)
3358 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3360 info->using_parent_icon = TRUE;
3363 /* Inherit from default */
3364 if (icon_list == NULL)
3366 icon_list = default_icon_list;
3368 info->using_default_icon = TRUE;
3371 /* Look up themed icon */
3372 if (icon_list == NULL && default_icon_name)
3374 icon_list = icon_list_from_theme (widget, default_icon_name);
3375 info->using_default_icon = TRUE;
3376 info->using_themed_icon = TRUE;
3379 gdk_window_set_icon_list (gdk_window, icon_list);
3381 get_pixmap_and_mask (gdk_window,
3382 info->using_parent_icon ? ensure_icon_info (priv->transient_parent) : NULL,
3383 info->using_default_icon,
3388 /* This is a slight ICCCM violation since it's a color pixmap not
3389 * a bitmap, but everyone does it.
3391 gdk_window_set_icon (gdk_window,
3396 info->realized = TRUE;
3398 if (info->using_themed_icon)
3400 GtkIconTheme *icon_theme;
3402 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3403 g_list_free (icon_list);
3405 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3406 g_signal_connect (icon_theme, "changed",
3407 G_CALLBACK (update_themed_icon), window);
3412 gtk_window_unrealize_icon (GtkWindow *window)
3414 GtkWindowIconInfo *info;
3416 info = get_icon_info (window);
3421 if (info->icon_pixmap)
3422 g_object_unref (info->icon_pixmap);
3424 if (info->icon_mask)
3425 g_object_unref (info->icon_mask);
3427 info->icon_pixmap = NULL;
3428 info->icon_mask = NULL;
3430 if (info->using_themed_icon)
3432 GtkIconTheme *icon_theme;
3434 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3436 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3439 /* We don't clear the properties on the window, just figure the
3440 * window is going away.
3443 info->realized = FALSE;
3448 * gtk_window_set_icon_list:
3449 * @window: a #GtkWindow
3450 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3452 * Sets up the icon representing a #GtkWindow. The icon is used when
3453 * the window is minimized (also known as iconified). Some window
3454 * managers or desktop environments may also place it in the window
3455 * frame, or display it in other contexts.
3457 * gtk_window_set_icon_list() allows you to pass in the same icon in
3458 * several hand-drawn sizes. The list should contain the natural sizes
3459 * your icon is available in; that is, don't scale the image before
3460 * passing it to GTK+. Scaling is postponed until the last minute,
3461 * when the desired final size is known, to allow best quality.
3463 * By passing several sizes, you may improve the final image quality
3464 * of the icon, by reducing or eliminating automatic image scaling.
3466 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3467 * larger images (64x64, 128x128) if you have them.
3469 * See also gtk_window_set_default_icon_list() to set the icon
3470 * for all windows in your application in one go.
3472 * Note that transient windows (those who have been set transient for another
3473 * window using gtk_window_set_transient_for()) will inherit their
3474 * icon from their transient parent. So there's no need to explicitly
3475 * set the icon on transient windows.
3478 gtk_window_set_icon_list (GtkWindow *window,
3481 GtkWindowIconInfo *info;
3483 g_return_if_fail (GTK_IS_WINDOW (window));
3485 info = ensure_icon_info (window);
3487 if (info->icon_list == list) /* check for NULL mostly */
3490 g_list_foreach (list,
3491 (GFunc) g_object_ref, NULL);
3493 g_list_foreach (info->icon_list,
3494 (GFunc) g_object_unref, NULL);
3496 g_list_free (info->icon_list);
3498 info->icon_list = g_list_copy (list);
3500 g_object_notify (G_OBJECT (window), "icon");
3502 gtk_window_unrealize_icon (window);
3504 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3505 gtk_window_realize_icon (window);
3507 /* We could try to update our transient children, but I don't think
3508 * it's really worth it. If we did it, the best way would probably
3509 * be to have children connect to notify::icon-list
3514 * gtk_window_get_icon_list:
3515 * @window: a #GtkWindow
3517 * Retrieves the list of icons set by gtk_window_set_icon_list().
3518 * The list is copied, but the reference count on each
3519 * member won't be incremented.
3521 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3524 gtk_window_get_icon_list (GtkWindow *window)
3526 GtkWindowIconInfo *info;
3528 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3530 info = get_icon_info (window);
3533 return g_list_copy (info->icon_list);
3539 * gtk_window_set_icon:
3540 * @window: a #GtkWindow
3541 * @icon: (allow-none): icon image, or %NULL
3543 * Sets up the icon representing a #GtkWindow. This icon is used when
3544 * the window is minimized (also known as iconified). Some window
3545 * managers or desktop environments may also place it in the window
3546 * frame, or display it in other contexts.
3548 * The icon should be provided in whatever size it was naturally
3549 * drawn; that is, don't scale the image before passing it to
3550 * GTK+. Scaling is postponed until the last minute, when the desired
3551 * final size is known, to allow best quality.
3553 * If you have your icon hand-drawn in multiple sizes, use
3554 * gtk_window_set_icon_list(). Then the best size will be used.
3556 * This function is equivalent to calling gtk_window_set_icon_list()
3557 * with a 1-element list.
3559 * See also gtk_window_set_default_icon_list() to set the icon
3560 * for all windows in your application in one go.
3563 gtk_window_set_icon (GtkWindow *window,
3568 g_return_if_fail (GTK_IS_WINDOW (window));
3569 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3574 list = g_list_append (list, icon);
3576 gtk_window_set_icon_list (window, list);
3582 update_themed_icon (GtkIconTheme *icon_theme,
3585 g_object_notify (G_OBJECT (window), "icon");
3587 gtk_window_unrealize_icon (window);
3589 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3590 gtk_window_realize_icon (window);
3594 * gtk_window_set_icon_name:
3595 * @window: a #GtkWindow
3596 * @name: (allow-none): the name of the themed icon
3598 * Sets the icon for the window from a named themed icon. See
3599 * the docs for #GtkIconTheme for more details.
3601 * Note that this has nothing to do with the WM_ICON_NAME
3602 * property which is mentioned in the ICCCM.
3607 gtk_window_set_icon_name (GtkWindow *window,
3610 GtkWindowIconInfo *info;
3613 g_return_if_fail (GTK_IS_WINDOW (window));
3615 info = ensure_icon_info (window);
3617 if (g_strcmp0 (info->icon_name, name) == 0)
3620 tmp = info->icon_name;
3621 info->icon_name = g_strdup (name);
3624 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3625 g_list_free (info->icon_list);
3626 info->icon_list = NULL;
3628 update_themed_icon (NULL, window);
3630 g_object_notify (G_OBJECT (window), "icon-name");
3634 * gtk_window_get_icon_name:
3635 * @window: a #GtkWindow
3637 * Returns the name of the themed icon for the window,
3638 * see gtk_window_set_icon_name().
3640 * Returns: the icon name or %NULL if the window has
3646 gtk_window_get_icon_name (GtkWindow *window)
3648 GtkWindowIconInfo *info;
3650 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3652 info = ensure_icon_info (window);
3654 return info->icon_name;
3658 * gtk_window_get_icon:
3659 * @window: a #GtkWindow
3661 * Gets the value set by gtk_window_set_icon() (or if you've
3662 * called gtk_window_set_icon_list(), gets the first icon in
3665 * Return value: (transfer none): icon for window
3668 gtk_window_get_icon (GtkWindow *window)
3670 GtkWindowIconInfo *info;
3672 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3674 info = get_icon_info (window);
3675 if (info && info->icon_list)
3676 return GDK_PIXBUF (info->icon_list->data);
3681 /* Load pixbuf, printing warning on failure if error == NULL
3684 load_pixbuf_verbosely (const char *filename,
3687 GError *local_err = NULL;
3690 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3698 g_warning ("Error loading icon from file '%s':\n\t%s",
3699 filename, local_err->message);
3700 g_error_free (local_err);
3708 * gtk_window_set_icon_from_file:
3709 * @window: a #GtkWindow
3710 * @filename: location of icon file
3711 * @err: (allow-none): location to store error, or %NULL.
3713 * Sets the icon for @window.
3714 * Warns on failure if @err is %NULL.
3716 * This function is equivalent to calling gtk_window_set_icon()
3717 * with a pixbuf created by loading the image from @filename.
3719 * Returns: %TRUE if setting the icon succeeded.
3724 gtk_window_set_icon_from_file (GtkWindow *window,
3725 const gchar *filename,
3728 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3732 gtk_window_set_icon (window, pixbuf);
3733 g_object_unref (pixbuf);
3742 * gtk_window_set_default_icon_list:
3743 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3745 * Sets an icon list to be used as fallback for windows that haven't
3746 * had gtk_window_set_icon_list() called on them to set up a
3747 * window-specific icon list. This function allows you to set up the
3748 * icon for all windows in your app at once.
3750 * See gtk_window_set_icon_list() for more details.
3754 gtk_window_set_default_icon_list (GList *list)
3758 if (list == default_icon_list)
3761 /* Update serial so we don't used cached pixmaps/masks
3763 default_icon_serial++;
3765 g_list_foreach (list,
3766 (GFunc) g_object_ref, NULL);
3768 g_list_foreach (default_icon_list,
3769 (GFunc) g_object_unref, NULL);
3771 g_list_free (default_icon_list);
3773 default_icon_list = g_list_copy (list);
3775 /* Update all toplevels */
3776 toplevels = gtk_window_list_toplevels ();
3777 tmp_list = toplevels;
3778 while (tmp_list != NULL)
3780 GtkWindowIconInfo *info;
3781 GtkWindow *w = tmp_list->data;
3783 info = get_icon_info (w);
3784 if (info && info->using_default_icon)
3786 gtk_window_unrealize_icon (w);
3787 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3788 gtk_window_realize_icon (w);
3791 tmp_list = tmp_list->next;
3793 g_list_free (toplevels);
3797 * gtk_window_set_default_icon:
3800 * Sets an icon to be used as fallback for windows that haven't
3801 * had gtk_window_set_icon() called on them from a pixbuf.
3806 gtk_window_set_default_icon (GdkPixbuf *icon)
3810 g_return_if_fail (GDK_IS_PIXBUF (icon));
3812 list = g_list_prepend (NULL, icon);
3813 gtk_window_set_default_icon_list (list);
3818 * gtk_window_set_default_icon_name:
3819 * @name: the name of the themed icon
3821 * Sets an icon to be used as fallback for windows that haven't
3822 * had gtk_window_set_icon_list() called on them from a named
3823 * themed icon, see gtk_window_set_icon_name().
3828 gtk_window_set_default_icon_name (const gchar *name)
3833 /* Update serial so we don't used cached pixmaps/masks
3835 default_icon_serial++;
3837 g_free (default_icon_name);
3838 default_icon_name = g_strdup (name);
3840 g_list_foreach (default_icon_list,
3841 (GFunc) g_object_unref, NULL);
3843 g_list_free (default_icon_list);
3844 default_icon_list = NULL;
3846 /* Update all toplevels */
3847 toplevels = gtk_window_list_toplevels ();
3848 tmp_list = toplevels;
3849 while (tmp_list != NULL)
3851 GtkWindowIconInfo *info;
3852 GtkWindow *w = tmp_list->data;
3854 info = get_icon_info (w);
3855 if (info && info->using_default_icon && info->using_themed_icon)
3857 gtk_window_unrealize_icon (w);
3858 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3859 gtk_window_realize_icon (w);
3862 tmp_list = tmp_list->next;
3864 g_list_free (toplevels);
3868 * gtk_window_get_default_icon_name:
3870 * Returns the fallback icon name for windows that has been set
3871 * with gtk_window_set_default_icon_name(). The returned
3872 * string is owned by GTK+ and should not be modified. It
3873 * is only valid until the next call to
3874 * gtk_window_set_default_icon_name().
3876 * Returns: the fallback icon name for windows
3881 gtk_window_get_default_icon_name (void)
3883 return default_icon_name;
3887 * gtk_window_set_default_icon_from_file:
3888 * @filename: location of icon file
3889 * @err: (allow-none): location to store error, or %NULL.
3891 * Sets an icon to be used as fallback for windows that haven't
3892 * had gtk_window_set_icon_list() called on them from a file
3893 * on disk. Warns on failure if @err is %NULL.
3895 * Returns: %TRUE if setting the icon succeeded.
3900 gtk_window_set_default_icon_from_file (const gchar *filename,
3903 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3907 gtk_window_set_default_icon (pixbuf);
3908 g_object_unref (pixbuf);
3917 * gtk_window_get_default_icon_list:
3919 * Gets the value set by gtk_window_set_default_icon_list().
3920 * The list is a copy and should be freed with g_list_free(),
3921 * but the pixbufs in the list have not had their reference count
3924 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3927 gtk_window_get_default_icon_list (void)
3929 return g_list_copy (default_icon_list);
3933 gtk_window_set_default_size_internal (GtkWindow *window,
3934 gboolean change_width,
3936 gboolean change_height,
3938 gboolean is_geometry)
3940 GtkWindowGeometryInfo *info;
3942 g_return_if_fail (change_width == FALSE || width >= -1);
3943 g_return_if_fail (change_height == FALSE || height >= -1);
3945 info = gtk_window_get_geometry_info (window, TRUE);
3947 g_object_freeze_notify (G_OBJECT (window));
3949 info->default_is_geometry = is_geometry != FALSE;
3959 info->default_width = width;
3961 g_object_notify (G_OBJECT (window), "default-width");
3972 info->default_height = height;
3974 g_object_notify (G_OBJECT (window), "default-height");
3977 g_object_thaw_notify (G_OBJECT (window));
3979 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3983 * gtk_window_set_default_size:
3984 * @window: a #GtkWindow
3985 * @width: width in pixels, or -1 to unset the default width
3986 * @height: height in pixels, or -1 to unset the default height
3988 * Sets the default size of a window. If the window's "natural" size
3989 * (its size request) is larger than the default, the default will be
3990 * ignored. More generally, if the default size does not obey the
3991 * geometry hints for the window (gtk_window_set_geometry_hints() can
3992 * be used to set these explicitly), the default size will be clamped
3993 * to the nearest permitted size.
3995 * Unlike gtk_widget_set_size_request(), which sets a size request for
3996 * a widget and thus would keep users from shrinking the window, this
3997 * function only sets the initial size, just as if the user had
3998 * resized the window themselves. Users can still shrink the window
3999 * again as they normally would. Setting a default size of -1 means to
4000 * use the "natural" default size (the size request of the window).
4002 * For more control over a window's initial size and how resizing works,
4003 * investigate gtk_window_set_geometry_hints().
4005 * For some uses, gtk_window_resize() is a more appropriate function.
4006 * gtk_window_resize() changes the current size of the window, rather
4007 * than the size to be used on initial display. gtk_window_resize() always
4008 * affects the window itself, not the geometry widget.
4010 * The default size of a window only affects the first time a window is
4011 * shown; if a window is hidden and re-shown, it will remember the size
4012 * it had prior to hiding, rather than using the default size.
4014 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4015 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4018 gtk_window_set_default_size (GtkWindow *window,
4022 g_return_if_fail (GTK_IS_WINDOW (window));
4023 g_return_if_fail (width >= -1);
4024 g_return_if_fail (height >= -1);
4026 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4030 * gtk_window_get_default_size:
4031 * @window: a #GtkWindow
4032 * @width: (out) (allow-none): location to store the default width, or %NULL
4033 * @height: (out) (allow-none): location to store the default height, or %NULL
4035 * Gets the default size of the window. A value of -1 for the width or
4036 * height indicates that a default size has not been explicitly set
4037 * for that dimension, so the "natural" size of the window will be
4042 gtk_window_get_default_size (GtkWindow *window,
4046 GtkWindowGeometryInfo *info;
4048 g_return_if_fail (GTK_IS_WINDOW (window));
4050 info = gtk_window_get_geometry_info (window, FALSE);
4053 *width = info ? info->default_width : -1;
4056 *height = info ? info->default_height : -1;
4060 * gtk_window_resize:
4061 * @window: a #GtkWindow
4062 * @width: width in pixels to resize the window to
4063 * @height: height in pixels to resize the window to
4065 * Resizes the window as if the user had done so, obeying geometry
4066 * constraints. The default geometry constraint is that windows may
4067 * not be smaller than their size request; to override this
4068 * constraint, call gtk_widget_set_size_request() to set the window's
4069 * request to a smaller value.
4071 * If gtk_window_resize() is called before showing a window for the
4072 * first time, it overrides any default size set with
4073 * gtk_window_set_default_size().
4075 * Windows may not be resized smaller than 1 by 1 pixels.
4079 gtk_window_resize (GtkWindow *window,
4083 GtkWindowGeometryInfo *info;
4085 g_return_if_fail (GTK_IS_WINDOW (window));
4086 g_return_if_fail (width > 0);
4087 g_return_if_fail (height > 0);
4089 info = gtk_window_get_geometry_info (window, TRUE);
4091 info->resize_width = width;
4092 info->resize_height = height;
4094 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4098 * gtk_window_get_size:
4099 * @window: a #GtkWindow
4100 * @width: (out) (allow-none): return location for width, or %NULL
4101 * @height: (out) (allow-none): return location for height, or %NULL
4103 * Obtains the current size of @window. If @window is not onscreen,
4104 * it returns the size GTK+ will suggest to the <link
4105 * linkend="gtk-X11-arch">window manager</link> for the initial window
4106 * size (but this is not reliably the same as the size the window
4107 * manager will actually select). The size obtained by
4108 * gtk_window_get_size() is the last size received in a
4109 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4110 * rather than querying the X server for the size. As a result, if you
4111 * call gtk_window_resize() then immediately call
4112 * gtk_window_get_size(), the size won't have taken effect yet. After
4113 * the window manager processes the resize request, GTK+ receives
4114 * notification that the size has changed via a configure event, and
4115 * the size of the window gets updated.
4117 * Note 1: Nearly any use of this function creates a race condition,
4118 * because the size of the window may change between the time that you
4119 * get the size and the time that you perform some action assuming
4120 * that size is the current size. To avoid race conditions, connect to
4121 * "configure-event" on the window and adjust your size-dependent
4122 * state to match the size delivered in the #GdkEventConfigure.
4124 * Note 2: The returned size does <emphasis>not</emphasis> include the
4125 * size of the window manager decorations (aka the window frame or
4126 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4127 * method of determining their size.
4129 * Note 3: If you are getting a window size in order to position
4130 * the window onscreen, there may be a better way. The preferred
4131 * way is to simply set the window's semantic type with
4132 * gtk_window_set_type_hint(), which allows the window manager to
4133 * e.g. center dialogs. Also, if you set the transient parent of
4134 * dialogs with gtk_window_set_transient_for() window managers
4135 * will often center the dialog over its parent window. It's
4136 * much preferred to let the window manager handle these
4137 * things rather than doing it yourself, because all apps will
4138 * behave consistently and according to user prefs if the window
4139 * manager handles it. Also, the window manager can take the size
4140 * of the window decorations/border into account, while your
4141 * application cannot.
4143 * In any case, if you insist on application-specified window
4144 * positioning, there's <emphasis>still</emphasis> a better way than
4145 * doing it yourself - gtk_window_set_position() will frequently
4146 * handle the details for you.
4150 gtk_window_get_size (GtkWindow *window,
4156 g_return_if_fail (GTK_IS_WINDOW (window));
4158 if (width == NULL && height == NULL)
4161 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4163 gdk_drawable_get_size (gtk_widget_get_window (GTK_WIDGET (window)),
4168 GdkRectangle configure_request;
4170 gtk_window_compute_configure_request (window,
4174 w = configure_request.width;
4175 h = configure_request.height;
4186 * @window: a #GtkWindow
4187 * @x: X coordinate to move window to
4188 * @y: Y coordinate to move window to
4190 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4191 * @window to the given position. Window managers are free to ignore
4192 * this; most window managers ignore requests for initial window
4193 * positions (instead using a user-defined placement algorithm) and
4194 * honor requests after the window has already been shown.
4196 * Note: the position is the position of the gravity-determined
4197 * reference point for the window. The gravity determines two things:
4198 * first, the location of the reference point in root window
4199 * coordinates; and second, which point on the window is positioned at
4200 * the reference point.
4202 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4203 * point is simply the @x, @y supplied to gtk_window_move(). The
4204 * top-left corner of the window decorations (aka window frame or
4205 * border) will be placed at @x, @y. Therefore, to position a window
4206 * at the top left of the screen, you want to use the default gravity
4207 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4209 * To position a window at the bottom right corner of the screen, you
4210 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4211 * point is at @x + the window width and @y + the window height, and
4212 * the bottom-right corner of the window border will be placed at that
4213 * reference point. So, to place a window in the bottom right corner
4214 * you would first set gravity to south east, then write:
4215 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4216 * gdk_screen_height () - window_height)</literal> (note that this
4217 * example does not take multi-head scenarios into account).
4219 * The Extended Window Manager Hints specification at <ulink
4220 * url="http://www.freedesktop.org/Standards/wm-spec">
4221 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4222 * nice table of gravities in the "implementation notes" section.
4224 * The gtk_window_get_position() documentation may also be relevant.
4227 gtk_window_move (GtkWindow *window,
4231 GtkWindowPrivate *priv;
4232 GtkWindowGeometryInfo *info;
4235 g_return_if_fail (GTK_IS_WINDOW (window));
4237 priv = window->priv;
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
4276 /* FIXME are we handling gravity properly for framed windows? */
4278 gdk_window_move (priv->frame,
4279 x - priv->frame_left,
4280 y - priv->frame_top);
4282 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)),
4287 /* Save this position to apply on mapping */
4288 info->initial_x = x;
4289 info->initial_y = y;
4290 info->initial_pos_set = TRUE;
4295 * gtk_window_get_position:
4296 * @window: a #GtkWindow
4297 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4298 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4300 * This function returns the position you need to pass to
4301 * gtk_window_move() to keep @window in its current position. This
4302 * means that the meaning of the returned value varies with window
4303 * gravity. See gtk_window_move() for more details.
4305 * If you haven't changed the window gravity, its gravity will be
4306 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4307 * gets the position of the top-left corner of the window manager
4308 * frame for the window. gtk_window_move() sets the position of this
4309 * same top-left corner.
4311 * gtk_window_get_position() is not 100% reliable because the X Window System
4312 * does not specify a way to obtain the geometry of the
4313 * decorations placed on a window by the window manager.
4314 * Thus GTK+ is using a "best guess" that works with most
4317 * Moreover, nearly all window managers are historically broken with
4318 * respect to their handling of window gravity. So moving a window to
4319 * its current position as returned by gtk_window_get_position() tends
4320 * to result in moving the window slightly. Window managers are
4321 * slowly getting better over time.
4323 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4324 * frame is not relevant, and thus gtk_window_get_position() will
4325 * always produce accurate results. However you can't use static
4326 * gravity to do things like place a window in a corner of the screen,
4327 * because static gravity ignores the window manager decorations.
4329 * If you are saving and restoring your application's window
4330 * positions, you should know that it's impossible for applications to
4331 * do this without getting it somewhat wrong because applications do
4332 * not have sufficient knowledge of window manager state. The Correct
4333 * Mechanism is to support the session management protocol (see the
4334 * "GnomeClient" object in the GNOME libraries for example) and allow
4335 * the window manager to save your window sizes and positions.
4340 gtk_window_get_position (GtkWindow *window,
4344 GtkWindowPrivate *priv;
4346 GdkWindow *gdk_window;
4348 g_return_if_fail (GTK_IS_WINDOW (window));
4350 priv = window->priv;
4351 widget = GTK_WIDGET (window);
4352 gdk_window = gtk_widget_get_window (widget);
4354 if (priv->gravity == GDK_GRAVITY_STATIC)
4356 if (gtk_widget_get_mapped (widget))
4358 /* This does a server round-trip, which is sort of wrong;
4359 * but a server round-trip is inevitable for
4360 * gdk_window_get_frame_extents() in the usual
4361 * NorthWestGravity case below, so not sure what else to
4362 * do. We should likely be consistent about whether we get
4363 * the client-side info or the server-side info.
4365 gdk_window_get_origin (gdk_window, root_x, root_y);
4369 GdkRectangle configure_request;
4371 gtk_window_compute_configure_request (window,
4375 *root_x = configure_request.x;
4376 *root_y = configure_request.y;
4381 GdkRectangle frame_extents;
4386 if (gtk_widget_get_mapped (widget))
4389 gdk_window_get_frame_extents (priv->frame, &frame_extents);
4391 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4392 x = frame_extents.x;
4393 y = frame_extents.y;
4394 gtk_window_get_size (window, &w, &h);
4398 /* We just say the frame has 0 size on all sides.
4399 * Not sure what else to do.
4401 gtk_window_compute_configure_request (window,
4404 x = frame_extents.x;
4405 y = frame_extents.y;
4406 w = frame_extents.width;
4407 h = frame_extents.height;
4410 switch (priv->gravity)
4412 case GDK_GRAVITY_NORTH:
4413 case GDK_GRAVITY_CENTER:
4414 case GDK_GRAVITY_SOUTH:
4415 /* Find center of frame. */
4416 x += frame_extents.width / 2;
4417 /* Center client window on that point. */
4421 case GDK_GRAVITY_SOUTH_EAST:
4422 case GDK_GRAVITY_EAST:
4423 case GDK_GRAVITY_NORTH_EAST:
4424 /* Find right edge of frame */
4425 x += frame_extents.width;
4426 /* Align left edge of client at that point. */
4433 switch (priv->gravity)
4435 case GDK_GRAVITY_WEST:
4436 case GDK_GRAVITY_CENTER:
4437 case GDK_GRAVITY_EAST:
4438 /* Find center of frame. */
4439 y += frame_extents.height / 2;
4440 /* Center client window there. */
4443 case GDK_GRAVITY_SOUTH_WEST:
4444 case GDK_GRAVITY_SOUTH:
4445 case GDK_GRAVITY_SOUTH_EAST:
4446 /* Find south edge of frame */
4447 y += frame_extents.height;
4448 /* Place bottom edge of client there */
4463 * gtk_window_reshow_with_initial_size:
4464 * @window: a #GtkWindow
4466 * Hides @window, then reshows it, resetting the
4467 * default size and position of the window. Used
4468 * by GUI builders only.
4471 gtk_window_reshow_with_initial_size (GtkWindow *window)
4475 g_return_if_fail (GTK_IS_WINDOW (window));
4477 widget = GTK_WIDGET (window);
4479 gtk_widget_hide (widget);
4480 gtk_widget_unrealize (widget);
4481 gtk_widget_show (widget);
4485 gtk_window_destroy (GtkObject *object)
4487 GtkWindow *window = GTK_WINDOW (object);
4488 GtkWindowPrivate *priv = window->priv;
4490 toplevel_list = g_slist_remove (toplevel_list, window);
4492 if (priv->transient_parent)
4493 gtk_window_set_transient_for (window, NULL);
4495 /* frees the icons */
4496 gtk_window_set_icon_list (window, NULL);
4498 if (priv->has_user_ref_count)
4500 priv->has_user_ref_count = FALSE;
4501 g_object_unref (window);
4505 gtk_window_group_remove_window (priv->group, window);
4507 gtk_window_free_key_hash (window);
4509 GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
4513 gtk_window_finalize (GObject *object)
4515 GtkWindow *window = GTK_WINDOW (object);
4516 GtkWindowPrivate *priv = window->priv;
4517 GtkMnemonicHash *mnemonic_hash;
4519 g_free (priv->title);
4520 g_free (priv->wmclass_name);
4521 g_free (priv->wmclass_class);
4522 g_free (priv->wm_role);
4524 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4526 _gtk_mnemonic_hash_free (mnemonic_hash);
4528 if (priv->geometry_info)
4530 if (priv->geometry_info->widget)
4531 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4532 gtk_widget_destroyed,
4533 &priv->geometry_info->widget);
4534 g_free (priv->geometry_info);
4537 if (priv->keys_changed_handler)
4539 g_source_remove (priv->keys_changed_handler);
4540 priv->keys_changed_handler = 0;
4544 g_signal_handlers_disconnect_by_func (priv->screen,
4545 gtk_window_on_composited_changed, window);
4547 g_free (priv->startup_id);
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;
4560 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4562 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4563 _gtk_container_set_need_resize (container, FALSE);
4567 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4568 GtkAllocation allocation = { 0, 0 };
4569 GdkRectangle configure_request;
4570 GdkGeometry new_geometry;
4572 gboolean was_realized;
4574 /* We are going to go ahead and perform this configure request
4575 * and then emulate a configure notify by going ahead and
4576 * doing a size allocate. Sort of a synchronous
4577 * mini-copy of gtk_window_move_resize() here.
4579 gtk_window_compute_configure_request (window,
4584 /* We update this because we are going to go ahead
4585 * and gdk_window_resize() below, rather than
4588 info->last.configure_request.width = configure_request.width;
4589 info->last.configure_request.height = configure_request.height;
4591 /* and allocate the window - this is normally done
4592 * in move_resize in response to configure notify
4594 allocation.width = configure_request.width;
4595 allocation.height = configure_request.height;
4596 gtk_widget_size_allocate (widget, &allocation);
4598 /* Then we guarantee we have a realize */
4599 was_realized = FALSE;
4600 if (!gtk_widget_get_realized (widget))
4602 gtk_widget_realize (widget);
4603 was_realized = TRUE;
4606 /* Must be done after the windows are realized,
4607 * so that the decorations can be read
4609 gtk_decorated_window_calculate_frame_size (window);
4611 /* We only send configure request if we didn't just finish
4612 * creating the window; if we just created the window
4613 * then we created it with widget->allocation anyhow.
4616 gdk_window_move_resize (gtk_widget_get_window (widget),
4617 configure_request.x,
4618 configure_request.y,
4619 configure_request.width,
4620 configure_request.height);
4623 gtk_container_check_resize (container);
4625 gtk_widget_map (widget);
4627 /* Try to make sure that we have some focused widget
4629 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4630 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4633 gtk_grab_add (widget);
4637 gtk_window_hide (GtkWidget *widget)
4639 GtkWindow *window = GTK_WINDOW (widget);
4640 GtkWindowPrivate *priv = window->priv;
4642 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4643 gtk_widget_unmap (widget);
4646 gtk_grab_remove (widget);
4650 gtk_window_map (GtkWidget *widget)
4653 GtkWindow *window = GTK_WINDOW (widget);
4654 GtkWindowPrivate *priv = window->priv;
4655 GdkWindow *toplevel;
4656 GdkWindow *gdk_window;
4657 gboolean auto_mnemonics;
4659 gdk_window = gtk_widget_get_window (widget);
4661 gtk_widget_set_mapped (widget, TRUE);
4663 child = gtk_bin_get_child (&(window->bin));
4665 gtk_widget_get_visible (child) &&
4666 !gtk_widget_get_mapped (child))
4667 gtk_widget_map (child);
4670 toplevel = priv->frame;
4672 toplevel = gdk_window;
4674 if (priv->maximize_initially)
4675 gdk_window_maximize (toplevel);
4677 gdk_window_unmaximize (toplevel);
4679 if (priv->stick_initially)
4680 gdk_window_stick (toplevel);
4682 gdk_window_unstick (toplevel);
4684 if (priv->iconify_initially)
4685 gdk_window_iconify (toplevel);
4687 gdk_window_deiconify (toplevel);
4689 if (priv->fullscreen_initially)
4690 gdk_window_fullscreen (toplevel);
4692 gdk_window_unfullscreen (toplevel);
4694 gdk_window_set_keep_above (toplevel, priv->above_initially);
4696 gdk_window_set_keep_below (toplevel, priv->below_initially);
4698 /* No longer use the default settings */
4699 priv->need_default_size = FALSE;
4700 priv->need_default_position = FALSE;
4702 if (priv->reset_type_hint)
4704 /* We should only reset the type hint when the application
4705 * used gtk_window_set_type_hint() to change the hint.
4706 * Some applications use X directly to change the properties;
4707 * in that case, we shouldn't overwrite what they did.
4709 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4710 priv->reset_type_hint = FALSE;
4713 gdk_window_show (gdk_window);
4716 gdk_window_show (priv->frame);
4718 if (!disable_startup_notification)
4720 /* Do we have a custom startup-notification id? */
4721 if (priv->startup_id != NULL)
4723 /* Make sure we have a "real" id */
4724 if (!startup_id_is_fake (priv->startup_id))
4725 gdk_notify_startup_complete_with_id (priv->startup_id);
4727 g_free (priv->startup_id);
4728 priv->startup_id = NULL;
4730 else if (!sent_startup_notification)
4732 sent_startup_notification = TRUE;
4733 gdk_notify_startup_complete ();
4737 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4738 * (as in the case of popup menus), then hide mnemonics initially
4740 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4741 &auto_mnemonics, NULL);
4742 if (auto_mnemonics && !priv->mnemonics_visible_set)
4743 gtk_window_set_mnemonics_visible (window, FALSE);
4747 gtk_window_map_event (GtkWidget *widget,
4750 if (!gtk_widget_get_mapped (widget))
4752 /* we should be be unmapped, but are getting a MapEvent, this may happen
4753 * to toplevel XWindows if mapping was intercepted by a window manager
4754 * and an unmap request occoured while the MapRequestEvent was still
4755 * being handled. we work around this situaiton here by re-requesting
4756 * the window being unmapped. more details can be found in:
4757 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4759 gdk_window_hide (gtk_widget_get_window (widget));
4765 gtk_window_unmap (GtkWidget *widget)
4767 GtkWindow *window = GTK_WINDOW (widget);
4768 GtkWindowPrivate *priv = window->priv;
4769 GtkWindowGeometryInfo *info;
4770 GdkWindow *gdk_window;
4771 GdkWindowState state;
4773 gdk_window = gtk_widget_get_window (widget);
4775 gtk_widget_set_mapped (widget, FALSE);
4777 gdk_window_withdraw (priv->frame);
4779 gdk_window_withdraw (gdk_window);
4781 priv->configure_request_count = 0;
4782 priv->configure_notify_received = FALSE;
4784 /* on unmap, we reset the default positioning of the window,
4785 * so it's placed again, but we don't reset the default
4786 * size of the window, so it's remembered.
4788 priv->need_default_position = TRUE;
4790 info = gtk_window_get_geometry_info (window, FALSE);
4793 info->initial_pos_set = FALSE;
4794 info->position_constraints_changed = FALSE;
4797 state = gdk_window_get_state (gdk_window);
4798 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4799 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4800 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4801 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4802 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4806 gtk_window_realize (GtkWidget *widget)
4808 GtkAllocation allocation;
4811 GdkWindow *parent_window;
4812 GdkWindow *gdk_window;
4813 GdkWindowAttr attributes;
4814 gint attributes_mask;
4815 GtkWindowPrivate *priv;
4817 window = GTK_WINDOW (widget);
4818 priv = window->priv;
4820 gtk_widget_get_allocation (widget, &allocation);
4822 /* ensure widget tree is properly size allocated */
4823 if (allocation.x == -1 &&
4824 allocation.y == -1 &&
4825 allocation.width == 1 &&
4826 allocation.height == 1)
4828 GtkRequisition requisition;
4829 GtkAllocation allocation = { 0, 0, 200, 200 };
4831 gtk_widget_size_request (widget, &requisition);
4832 if (requisition.width || requisition.height)
4834 /* non-empty window */
4835 allocation.width = requisition.width;
4836 allocation.height = requisition.height;
4838 gtk_widget_size_allocate (widget, &allocation);
4840 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4842 g_return_if_fail (!gtk_widget_get_realized (widget));
4845 gtk_widget_set_realized (widget, TRUE);
4849 case GTK_WINDOW_TOPLEVEL:
4850 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4852 case GTK_WINDOW_POPUP:
4853 attributes.window_type = GDK_WINDOW_TEMP;
4856 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4860 attributes.title = priv->title;
4861 attributes.wmclass_name = priv->wmclass_name;
4862 attributes.wmclass_class = priv->wmclass_class;
4863 attributes.wclass = GDK_INPUT_OUTPUT;
4864 attributes.visual = gtk_widget_get_visual (widget);
4865 attributes.colormap = gtk_widget_get_colormap (widget);
4867 if (priv->has_frame)
4869 gtk_widget_get_allocation (widget, &allocation);
4870 attributes.width = allocation.width + priv->frame_left + priv->frame_right;
4871 attributes.height = allocation.height + priv->frame_top + priv->frame_bottom;
4872 attributes.event_mask = (GDK_EXPOSURE_MASK |
4873 GDK_KEY_PRESS_MASK |
4874 GDK_ENTER_NOTIFY_MASK |
4875 GDK_LEAVE_NOTIFY_MASK |
4876 GDK_FOCUS_CHANGE_MASK |
4877 GDK_STRUCTURE_MASK |
4878 GDK_BUTTON_MOTION_MASK |
4879 GDK_POINTER_MOTION_HINT_MASK |
4880 GDK_BUTTON_PRESS_MASK |
4881 GDK_BUTTON_RELEASE_MASK);
4883 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4885 priv->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4886 &attributes, attributes_mask);
4888 if (priv->opacity_set)
4889 gdk_window_set_opacity (priv->frame, priv->opacity);
4891 gdk_window_set_user_data (priv->frame, widget);
4893 attributes.window_type = GDK_WINDOW_CHILD;
4894 attributes.x = priv->frame_left;
4895 attributes.y = priv->frame_top;
4897 attributes_mask = GDK_WA_X | GDK_WA_Y;
4899 parent_window = priv->frame;
4901 g_signal_connect (window,
4903 G_CALLBACK (gtk_window_event),
4908 attributes_mask = 0;
4909 parent_window = gtk_widget_get_root_window (widget);
4912 gtk_widget_get_allocation (widget, &allocation);
4913 attributes.width = allocation.width;
4914 attributes.height = allocation.height;
4915 attributes.event_mask = gtk_widget_get_events (widget);
4916 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4917 GDK_KEY_PRESS_MASK |
4918 GDK_KEY_RELEASE_MASK |
4919 GDK_ENTER_NOTIFY_MASK |
4920 GDK_LEAVE_NOTIFY_MASK |
4921 GDK_FOCUS_CHANGE_MASK |
4922 GDK_STRUCTURE_MASK);
4923 attributes.type_hint = priv->type_hint;
4925 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_TYPE_HINT;
4926 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4927 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4929 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4930 gtk_widget_set_window (widget, gdk_window);
4932 if (!priv->has_frame && priv->opacity_set)
4933 gdk_window_set_opacity (gdk_window, priv->opacity);
4935 gdk_window_enable_synchronized_configure (gdk_window);
4937 gdk_window_set_user_data (gdk_window, window);
4939 gtk_widget_style_attach (widget);
4940 style = gtk_widget_get_style (widget);
4941 gtk_style_set_background (style, gdk_window, GTK_STATE_NORMAL);
4943 gtk_style_set_background (style, priv->frame, GTK_STATE_NORMAL);
4945 /* This is a bad hack to set the window background. */
4946 gtk_window_paint (widget, NULL);
4948 if (priv->transient_parent &&
4949 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4950 gdk_window_set_transient_for (gdk_window,
4951 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4954 gdk_window_set_role (gdk_window, priv->wm_role);
4956 if (!priv->decorated)
4957 gdk_window_set_decorations (gdk_window, 0);
4959 if (!priv->deletable)
4960 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4962 if (gtk_window_get_skip_pager_hint (window))
4963 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4965 if (gtk_window_get_skip_taskbar_hint (window))
4966 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4968 if (gtk_window_get_accept_focus (window))
4969 gdk_window_set_accept_focus (gdk_window, TRUE);
4971 gdk_window_set_accept_focus (gdk_window, FALSE);
4973 if (gtk_window_get_focus_on_map (window))
4974 gdk_window_set_focus_on_map (gdk_window, TRUE);
4976 gdk_window_set_focus_on_map (gdk_window, FALSE);
4979 gdk_window_set_modal_hint (gdk_window, TRUE);
4981 gdk_window_set_modal_hint (gdk_window, FALSE);
4983 if (priv->startup_id)
4985 #ifdef GDK_WINDOWING_X11
4986 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4987 if (timestamp != GDK_CURRENT_TIME)
4988 gdk_x11_window_set_user_time (gdk_window, timestamp);
4990 if (!startup_id_is_fake (priv->startup_id))
4991 gdk_window_set_startup_id (gdk_window, priv->startup_id);
4995 gtk_window_realize_icon (window);
4999 gtk_window_unrealize (GtkWidget *widget)
5001 GtkWindow *window = GTK_WINDOW (widget);
5002 GtkWindowPrivate *priv = window->priv;
5003 GtkWindowGeometryInfo *info;
5005 /* On unrealize, we reset the size of the window such
5006 * that we will re-apply the default sizing stuff
5007 * next time we show the window.
5009 * Default positioning is reset on unmap, instead of unrealize.
5011 priv->need_default_size = TRUE;
5012 info = gtk_window_get_geometry_info (window, FALSE);
5015 info->resize_width = -1;
5016 info->resize_height = -1;
5017 info->last.configure_request.x = 0;
5018 info->last.configure_request.y = 0;
5019 info->last.configure_request.width = -1;
5020 info->last.configure_request.height = -1;
5021 /* be sure we reset geom hints on re-realize */
5022 info->last.flags = 0;
5027 gdk_window_set_user_data (priv->frame, NULL);
5028 gdk_window_destroy (priv->frame);
5033 gtk_window_unrealize_icon (window);
5035 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5039 gtk_window_size_allocate (GtkWidget *widget,
5040 GtkAllocation *allocation)
5042 GtkWindow *window = GTK_WINDOW (widget);
5043 GtkWindowPrivate *priv = window->priv;
5044 GtkAllocation child_allocation;
5048 gtk_widget_set_allocation (widget, allocation);
5050 child = gtk_bin_get_child (&(window->bin));
5051 if (child && gtk_widget_get_visible (child))
5053 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5054 child_allocation.x = border_width;
5055 child_allocation.y = border_width;
5056 child_allocation.width =
5057 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5058 child_allocation.height =
5059 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5061 gtk_widget_size_allocate (child, &child_allocation);
5064 if (gtk_widget_get_realized (widget) && priv->frame)
5066 gdk_window_resize (priv->frame,
5067 allocation->width + priv->frame_left + priv->frame_right,
5068 allocation->height + priv->frame_top + priv->frame_bottom);
5073 gtk_window_event (GtkWidget *widget, GdkEvent *event)
5075 GtkWindow *window = GTK_WINDOW (widget);
5076 GtkWindowPrivate *priv = window->priv;
5077 gboolean return_val;
5079 if (priv->frame && (event->any.window == priv->frame))
5081 if ((event->type != GDK_KEY_PRESS) &&
5082 (event->type != GDK_KEY_RELEASE) &&
5083 (event->type != GDK_FOCUS_CHANGE))
5085 g_signal_stop_emission_by_name (widget, "event");
5087 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
5092 g_object_unref (event->any.window);
5093 event->any.window = g_object_ref (gtk_widget_get_window (widget));
5101 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
5103 GtkWindowPrivate *priv = window->priv;
5104 GdkEventConfigure *configure_event;
5107 switch (event->type)
5110 configure_event = (GdkEventConfigure *)event;
5112 /* Invalidate the decorations */
5115 rect.width = configure_event->width;
5116 rect.height = configure_event->height;
5118 gdk_window_invalidate_rect (priv->frame, &rect, FALSE);
5120 /* Pass on the (modified) configure event */
5121 configure_event->width -= priv->frame_left + priv->frame_right;
5122 configure_event->height -= priv->frame_top + priv->frame_bottom;
5123 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5132 gtk_window_configure_event (GtkWidget *widget,
5133 GdkEventConfigure *event)
5135 GtkAllocation allocation;
5136 GtkWindow *window = GTK_WINDOW (widget);
5137 GtkWindowPrivate *priv = window->priv;
5138 gboolean expected_reply = priv->configure_request_count > 0;
5140 /* priv->configure_request_count incremented for each
5141 * configure request, and decremented to a min of 0 for
5142 * each configure notify.
5144 * All it means is that we know we will get at least
5145 * priv->configure_request_count more configure notifies.
5146 * We could get more configure notifies than that; some
5147 * of the configure notifies we get may be unrelated to
5148 * the configure requests. But we will get at least
5149 * priv->configure_request_count notifies.
5152 if (priv->configure_request_count > 0)
5154 priv->configure_request_count -= 1;
5155 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5158 /* As an optimization, we avoid a resize when possible.
5160 * The only times we can avoid a resize are:
5161 * - we know only the position changed, not the size
5162 * - we know we have made more requests and so will get more
5163 * notifies and can wait to resize when we get them
5165 gtk_widget_get_allocation (widget, &allocation);
5166 if (!expected_reply &&
5167 (allocation.width == event->width &&
5168 allocation.height == event->height))
5170 gdk_window_configure_finished (gtk_widget_get_window (widget));
5175 * If we do need to resize, we do that by:
5176 * - filling in widget->allocation with the new size
5177 * - setting configure_notify_received to TRUE
5178 * for use in gtk_window_move_resize()
5179 * - queueing a resize, leading to invocation of
5180 * gtk_window_move_resize() in an idle handler
5184 priv->configure_notify_received = TRUE;
5186 allocation.width = event->width;
5187 allocation.height = event->height;
5188 gtk_widget_set_allocation (widget, &allocation);
5190 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5195 /* the accel_key and accel_mods fields of the key have to be setup
5196 * upon calling this function. it'll then return whether that key
5197 * is at all used as accelerator, and if so will OR in the
5198 * accel_flags member of the key.
5201 _gtk_window_query_nonaccels (GtkWindow *window,
5203 GdkModifierType accel_mods)
5205 GtkWindowPrivate *priv;
5207 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5209 priv = window->priv;
5211 /* movement keys are considered locked accels */
5214 static const guint bindings[] = {
5215 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,
5216 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,
5220 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5221 if (bindings[i] == accel_key)
5225 /* mnemonics are considered locked accels */
5226 if (accel_mods == priv->mnemonic_modifier)
5228 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5229 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5237 * gtk_window_propagate_key_event:
5238 * @window: a #GtkWindow
5239 * @event: a #GdkEventKey
5241 * Propagate a key press or release event to the focus widget and
5242 * up the focus container chain until a widget handles @event.
5243 * This is normally called by the default ::key_press_event and
5244 * ::key_release_event handlers for toplevel windows,
5245 * however in some cases it may be useful to call this directly when
5246 * overriding the standard key handling for a toplevel window.
5248 * Return value: %TRUE if a widget in the focus chain handled the event.
5253 gtk_window_propagate_key_event (GtkWindow *window,
5256 GtkWindowPrivate *priv;
5257 gboolean handled = FALSE;
5258 GtkWidget *widget, *focus;
5260 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5262 priv = window->priv;
5263 widget = GTK_WIDGET (window);
5265 focus = priv->focus_widget;
5267 g_object_ref (focus);
5270 focus && focus != widget &&
5271 gtk_widget_get_toplevel (focus) == widget)
5275 if (gtk_widget_is_sensitive (focus))
5276 handled = gtk_widget_event (focus, (GdkEvent*) event);
5278 parent = gtk_widget_get_parent (focus);
5280 g_object_ref (parent);
5282 g_object_unref (focus);
5288 g_object_unref (focus);
5294 gtk_window_key_press_event (GtkWidget *widget,
5297 GtkWindow *window = GTK_WINDOW (widget);
5298 gboolean handled = FALSE;
5300 /* handle mnemonics and accelerators */
5302 handled = gtk_window_activate_key (window, event);
5304 /* handle focus widget key events */
5306 handled = gtk_window_propagate_key_event (window, event);
5308 /* Chain up, invokes binding set */
5310 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5316 gtk_window_key_release_event (GtkWidget *widget,
5319 GtkWindow *window = GTK_WINDOW (widget);
5320 gboolean handled = FALSE;
5322 /* handle focus widget key events */
5324 handled = gtk_window_propagate_key_event (window, event);
5326 /* Chain up, invokes binding set */
5328 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5334 gtk_window_real_activate_default (GtkWindow *window)
5336 gtk_window_activate_default (window);
5340 gtk_window_real_activate_focus (GtkWindow *window)
5342 gtk_window_activate_focus (window);
5346 gtk_window_move_focus (GtkWindow *window,
5347 GtkDirectionType dir)
5349 gtk_widget_child_focus (GTK_WIDGET (window), dir);
5351 if (!gtk_container_get_focus_child (GTK_CONTAINER (window)))
5352 gtk_window_set_focus (window, NULL);
5356 gtk_window_enter_notify_event (GtkWidget *widget,
5357 GdkEventCrossing *event)
5363 gtk_window_leave_notify_event (GtkWidget *widget,
5364 GdkEventCrossing *event)
5370 do_focus_change (GtkWidget *widget,
5374 GdkDeviceManager *device_manager;
5377 g_object_ref (widget);
5379 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5380 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5381 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5382 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5384 for (d = devices; d; d = d->next)
5386 GdkDevice *dev = d->data;
5389 if (dev->source != GDK_SOURCE_KEYBOARD)
5392 /* Skip non-master keyboards that haven't
5393 * selected for events from this window
5395 window = gtk_widget_get_window (widget);
5396 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5397 window && !gdk_window_get_device_events (window, dev))
5400 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5402 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5403 fevent->focus_change.window = window;
5405 g_object_ref (window);
5406 fevent->focus_change.in = in;
5407 gdk_event_set_device (fevent, dev);
5409 gtk_widget_send_focus_change (widget, fevent);
5411 gdk_event_free (fevent);
5414 g_list_free (devices);
5415 g_object_unref (widget);
5419 gtk_window_focus_in_event (GtkWidget *widget,
5420 GdkEventFocus *event)
5422 GtkWindow *window = GTK_WINDOW (widget);
5424 /* It appears spurious focus in events can occur when
5425 * the window is hidden. So we'll just check to see if
5426 * the window is visible before actually handling the
5429 if (gtk_widget_get_visible (widget))
5431 _gtk_window_set_has_toplevel_focus (window, TRUE);
5432 _gtk_window_set_is_active (window, TRUE);
5439 gtk_window_focus_out_event (GtkWidget *widget,
5440 GdkEventFocus *event)
5442 GtkWindow *window = GTK_WINDOW (widget);
5443 gboolean auto_mnemonics;
5445 _gtk_window_set_has_toplevel_focus (window, FALSE);
5446 _gtk_window_set_is_active (window, FALSE);
5448 /* set the mnemonic-visible property to false */
5449 g_object_get (gtk_widget_get_settings (widget),
5450 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5452 gtk_window_set_mnemonics_visible (window, FALSE);
5457 static GdkAtom atom_rcfiles = GDK_NONE;
5458 static GdkAtom atom_iconthemes = GDK_NONE;
5461 send_client_message_to_embedded_windows (GtkWidget *widget,
5462 GdkAtom message_type)
5464 GList *embedded_windows;
5466 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5467 if (embedded_windows)
5469 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5472 for (i = 0; i < 5; i++)
5473 send_event->client.data.l[i] = 0;
5474 send_event->client.data_format = 32;
5475 send_event->client.message_type = message_type;
5477 while (embedded_windows)
5479 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5480 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5481 embedded_windows = embedded_windows->next;
5484 gdk_event_free (send_event);
5489 gtk_window_client_event (GtkWidget *widget,
5490 GdkEventClient *event)
5494 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5495 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5498 if (event->message_type == atom_rcfiles)
5500 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5501 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5504 if (event->message_type == atom_iconthemes)
5506 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5507 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5514 gtk_window_check_resize (GtkContainer *container)
5516 if (gtk_widget_get_visible (GTK_WIDGET (container)))
5517 gtk_window_move_resize (GTK_WINDOW (container));
5521 gtk_window_focus (GtkWidget *widget,
5522 GtkDirectionType direction)
5524 GtkWindowPrivate *priv;
5527 GtkContainer *container;
5529 GtkWidget *old_focus_child;
5532 container = GTK_CONTAINER (widget);
5533 window = GTK_WINDOW (widget);
5534 priv = window->priv;
5535 bin = GTK_BIN (widget);
5537 old_focus_child = gtk_container_get_focus_child (container);
5539 /* We need a special implementation here to deal properly with wrapping
5540 * around in the tab chain without the danger of going into an
5543 if (old_focus_child)
5545 if (gtk_widget_child_focus (old_focus_child, direction))
5549 if (priv->focus_widget)
5551 if (direction == GTK_DIR_LEFT ||
5552 direction == GTK_DIR_RIGHT ||
5553 direction == GTK_DIR_UP ||
5554 direction == GTK_DIR_DOWN)
5559 /* Wrapped off the end, clear the focus setting for the toplpevel */
5560 parent = gtk_widget_get_parent (priv->focus_widget);
5563 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5564 parent = gtk_widget_get_parent (parent);
5567 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5570 /* Now try to focus the first widget in the window */
5571 child = gtk_bin_get_child (bin);
5574 if (gtk_widget_child_focus (child, direction))
5582 gtk_window_real_set_focus (GtkWindow *window,
5585 GtkWindowPrivate *priv = window->priv;
5586 GtkWidget *old_focus = priv->focus_widget;
5587 gboolean had_default = FALSE;
5588 gboolean focus_had_default = FALSE;
5589 gboolean old_focus_had_default = FALSE;
5593 g_object_ref (old_focus);
5594 g_object_freeze_notify (G_OBJECT (old_focus));
5595 old_focus_had_default = gtk_widget_has_default (old_focus);
5599 g_object_ref (focus);
5600 g_object_freeze_notify (G_OBJECT (focus));
5601 focus_had_default = gtk_widget_has_default (focus);
5604 if (priv->default_widget)
5605 had_default = gtk_widget_has_default (priv->default_widget);
5607 if (priv->focus_widget)
5609 if (gtk_widget_get_receives_default (priv->focus_widget) &&
5610 (priv->focus_widget != priv->default_widget))
5612 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
5613 gtk_widget_queue_draw (priv->focus_widget);
5615 if (priv->default_widget)
5616 _gtk_widget_set_has_default (priv->default_widget, TRUE);
5619 priv->focus_widget = NULL;
5621 if (priv->has_focus)
5622 do_focus_change (old_focus, FALSE);
5624 g_object_notify (G_OBJECT (old_focus), "is-focus");
5627 /* The above notifications may have set a new focus widget,
5628 * if so, we don't want to override it.
5630 if (focus && !priv->focus_widget)
5632 priv->focus_widget = focus;
5634 if (gtk_widget_get_receives_default (priv->focus_widget) &&
5635 (priv->focus_widget != priv->default_widget))
5637 if (gtk_widget_get_can_default (priv->focus_widget))
5638 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
5640 if (priv->default_widget)
5641 _gtk_widget_set_has_default (priv->default_widget, FALSE);
5644 if (priv->has_focus)
5645 do_focus_change (priv->focus_widget, TRUE);
5647 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
5650 /* If the default widget changed, a redraw will have been queued
5651 * on the old and new default widgets by gtk_window_set_default(), so
5652 * we only have to worry about the case where it didn't change.
5653 * We'll sometimes queue a draw twice on the new widget but that
5656 if (priv->default_widget &&
5657 (had_default != gtk_widget_has_default (priv->default_widget)))
5658 gtk_widget_queue_draw (priv->default_widget);
5662 if (old_focus_had_default != gtk_widget_has_default (old_focus))
5663 gtk_widget_queue_draw (old_focus);
5665 g_object_thaw_notify (G_OBJECT (old_focus));
5666 g_object_unref (old_focus);
5670 if (focus_had_default != gtk_widget_has_default (focus))
5671 gtk_widget_queue_draw (focus);
5673 g_object_thaw_notify (G_OBJECT (focus));
5674 g_object_unref (focus);
5680 gtk_window_size_request_init (GtkSizeRequestIface *iface)
5682 iface->get_width = gtk_window_get_width;
5683 iface->get_height = gtk_window_get_height;
5688 gtk_window_get_width (GtkSizeRequest *widget,
5696 window = GTK_WINDOW (widget);
5697 child = gtk_bin_get_child (GTK_BIN (window));
5699 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5700 *minimum_size = border_width * 2;
5701 *natural_size = border_width * 2;
5703 if (child && gtk_widget_get_visible (child))
5705 gint child_min, child_nat;
5706 gtk_size_request_get_width (GTK_SIZE_REQUEST (child), &child_min, &child_nat);
5708 *minimum_size += child_min;
5709 *natural_size += child_nat;
5714 gtk_window_get_height (GtkSizeRequest *widget,
5722 window = GTK_WINDOW (widget);
5723 child = gtk_bin_get_child (GTK_BIN (window));
5725 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5726 *minimum_size = border_width * 2;
5727 *natural_size = border_width * 2;
5729 if (child && gtk_widget_get_visible (child))
5731 gint child_min, child_nat;
5732 gtk_size_request_get_height (GTK_SIZE_REQUEST (child), &child_min, &child_nat);
5734 *minimum_size += child_min;
5735 *natural_size += child_nat;
5741 * _gtk_window_unset_focus_and_default:
5742 * @window: a #GtkWindow
5743 * @widget: a widget inside of @window
5745 * Checks whether the focus and default widgets of @window are
5746 * @widget or a descendent of @widget, and if so, unset them.
5749 _gtk_window_unset_focus_and_default (GtkWindow *window,
5753 GtkWindowPrivate *priv = window->priv;
5757 g_object_ref (window);
5758 g_object_ref (widget);
5760 parent = gtk_widget_get_parent (widget);
5761 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
5763 child = priv->focus_widget;
5765 while (child && child != widget)
5766 child = gtk_widget_get_parent (child);
5768 if (child == widget)
5769 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5772 child = priv->default_widget;
5774 while (child && child != widget)
5775 child = gtk_widget_get_parent (child);
5777 if (child == widget)
5778 gtk_window_set_default (window, NULL);
5780 g_object_unref (widget);
5781 g_object_unref (window);
5784 /*********************************
5785 * Functions related to resizing *
5786 *********************************/
5788 /* This function doesn't constrain to geometry hints */
5790 gtk_window_compute_configure_request_size (GtkWindow *window,
5794 GtkWindowPrivate *priv = window->priv;
5795 GtkRequisition requisition;
5796 GtkWindowGeometryInfo *info;
5800 * - we've done a size request
5803 widget = GTK_WIDGET (window);
5805 info = gtk_window_get_geometry_info (window, FALSE);
5807 if (priv->need_default_size)
5809 gtk_widget_get_child_requisition (widget, &requisition);
5811 /* Default to requisition */
5812 *width = requisition.width;
5813 *height = requisition.height;
5815 /* If window is empty so requests 0, default to random nonzero size */
5816 if (*width == 0 && *height == 0)
5822 /* Override requisition with default size */
5826 gint base_width = 0;
5827 gint base_height = 0;
5829 gint min_height = 0;
5831 gint height_inc = 1;
5833 if (info->default_is_geometry &&
5834 (info->default_width > 0 || info->default_height > 0))
5836 GdkGeometry geometry;
5839 gtk_window_compute_hints (window, &geometry, &flags);
5841 if (flags & GDK_HINT_BASE_SIZE)
5843 base_width = geometry.base_width;
5844 base_height = geometry.base_height;
5846 if (flags & GDK_HINT_MIN_SIZE)
5848 min_width = geometry.min_width;
5849 min_height = geometry.min_height;
5851 if (flags & GDK_HINT_RESIZE_INC)
5853 width_inc = geometry.width_inc;
5854 height_inc = geometry.height_inc;
5858 if (info->default_width > 0)
5859 *width = MAX (info->default_width * width_inc + base_width, min_width);
5861 if (info->default_height > 0)
5862 *height = MAX (info->default_height * height_inc + base_height, min_height);
5867 GtkAllocation allocation;
5869 gtk_widget_get_allocation (widget, &allocation);
5871 /* Default to keeping current size */
5872 *width = allocation.width;
5873 *height = allocation.height;
5876 /* Override any size with gtk_window_resize() values */
5879 if (info->resize_width > 0)
5880 *width = info->resize_width;
5882 if (info->resize_height > 0)
5883 *height = info->resize_height;
5886 /* Don't ever request zero width or height, its not supported by
5887 gdk. The size allocation code will round it to 1 anyway but if
5888 we do it then the value returned from this function will is
5889 not comparable to the size allocation read from the GtkWindow. */
5890 *width = MAX (*width, 1);
5891 *height = MAX (*height, 1);
5894 static GtkWindowPosition
5895 get_effective_position (GtkWindow *window)
5897 GtkWindowPrivate *priv = window->priv;
5898 GtkWindowPosition pos = priv->position;
5900 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5901 (priv->transient_parent == NULL ||
5902 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
5903 pos = GTK_WIN_POS_NONE;
5909 get_center_monitor_of_window (GtkWindow *window)
5911 /* We could try to sort out the relative positions of the monitors and
5912 * stuff, or we could just be losers and assume you have a row
5913 * or column of monitors.
5915 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5919 get_monitor_containing_pointer (GtkWindow *window)
5923 GdkScreen *window_screen;
5924 GdkScreen *pointer_screen;
5925 GdkDisplay *display;
5926 GdkDeviceManager *device_manager;
5929 window_screen = gtk_window_check_screen (window);
5930 display = gdk_screen_get_display (window_screen);
5931 device_manager = gdk_display_get_device_manager (display);
5932 pointer = gdk_device_manager_get_client_pointer (device_manager);
5934 gdk_display_get_device_state (display, pointer,
5938 if (pointer_screen == window_screen)
5939 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5947 center_window_on_monitor (GtkWindow *window,
5953 GdkRectangle monitor;
5956 monitor_num = get_monitor_containing_pointer (window);
5958 if (monitor_num == -1)
5959 monitor_num = get_center_monitor_of_window (window);
5961 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5962 monitor_num, &monitor);
5964 *x = (monitor.width - w) / 2 + monitor.x;
5965 *y = (monitor.height - h) / 2 + monitor.y;
5967 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5968 * and WM decorations.
5982 if (extent > clamp_extent)
5984 *base = clamp_base + clamp_extent/2 - extent/2;
5985 else if (*base < clamp_base)
5987 else if (*base + extent > clamp_base + clamp_extent)
5988 *base = clamp_base + clamp_extent - extent;
5992 clamp_window_to_rectangle (gint *x,
5996 const GdkRectangle *rect)
5998 #ifdef DEBUGGING_OUTPUT
5999 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);
6002 /* If it is too large, center it. If it fits on the monitor but is
6003 * partially outside, move it to the closest edge. Do this
6004 * separately in x and y directions.
6006 clamp (x, w, rect->x, rect->width);
6007 clamp (y, h, rect->y, rect->height);
6008 #ifdef DEBUGGING_OUTPUT
6009 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6015 gtk_window_compute_configure_request (GtkWindow *window,
6016 GdkRectangle *request,
6017 GdkGeometry *geometry,
6020 GtkWindowPrivate *priv = window->priv;
6021 GdkGeometry new_geometry;
6025 GtkWindowPosition pos;
6026 GtkWidget *parent_widget;
6027 GtkWindowGeometryInfo *info;
6031 widget = GTK_WIDGET (window);
6033 screen = gtk_window_check_screen (window);
6035 gtk_widget_size_request (widget, NULL);
6036 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
6038 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6039 gtk_window_constrain_size (window,
6040 &new_geometry, new_flags,
6044 parent_widget = (GtkWidget*) priv->transient_parent;
6046 pos = get_effective_position (window);
6047 info = gtk_window_get_geometry_info (window, FALSE);
6049 /* by default, don't change position requested */
6052 x = info->last.configure_request.x;
6053 y = info->last.configure_request.y;
6062 if (priv->need_default_position)
6065 /* FIXME this all interrelates with window gravity.
6066 * For most of them I think we want to set GRAVITY_CENTER.
6068 * Not sure how to go about that.
6073 /* here we are only handling CENTER_ALWAYS
6074 * as it relates to default positioning,
6075 * where it's equivalent to simply CENTER
6077 case GTK_WIN_POS_CENTER_ALWAYS:
6078 case GTK_WIN_POS_CENTER:
6079 center_window_on_monitor (window, w, h, &x, &y);
6082 case GTK_WIN_POS_CENTER_ON_PARENT:
6084 GtkAllocation allocation;
6085 GdkWindow *gdk_window;
6087 GdkRectangle monitor;
6090 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6092 gdk_window = gtk_widget_get_window (parent_widget);
6094 if (gdk_window != NULL)
6095 monitor_num = gdk_screen_get_monitor_at_window (screen,
6100 gdk_window_get_origin (gdk_window,
6103 gtk_widget_get_allocation (parent_widget, &allocation);
6104 x = ox + (allocation.width - w) / 2;
6105 y = oy + (allocation.height - h) / 2;
6107 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6108 * WM decorations. If parent wasn't on a monitor, just
6111 if (monitor_num >= 0)
6113 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6114 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6119 case GTK_WIN_POS_MOUSE:
6121 gint screen_width = gdk_screen_get_width (screen);
6122 gint screen_height = gdk_screen_get_height (screen);
6124 GdkRectangle monitor;
6125 GdkDisplay *display;
6126 GdkDeviceManager *device_manager;
6128 GdkScreen *pointer_screen;
6131 display = gdk_screen_get_display (screen);
6132 device_manager = gdk_display_get_device_manager (display);
6133 pointer = gdk_device_manager_get_client_pointer (device_manager);
6135 gdk_display_get_device_state (display, pointer,
6139 if (pointer_screen == screen)
6140 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6146 x = CLAMP (x, 0, screen_width - w);
6147 y = CLAMP (y, 0, screen_height - h);
6149 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6150 * WM decorations. Don't try to figure out what's going
6151 * on if the mouse wasn't inside a monitor.
6153 if (monitor_num >= 0)
6155 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6156 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6164 } /* if (priv->need_default_position) */
6166 if (priv->need_default_position && info &&
6167 info->initial_pos_set)
6169 x = info->initial_x;
6170 y = info->initial_y;
6171 gtk_window_constrain_position (window, w, h, &x, &y);
6177 request->height = h;
6180 *geometry = new_geometry;
6186 gtk_window_constrain_position (GtkWindow *window,
6192 GtkWindowPrivate *priv = window->priv;
6194 /* See long comments in gtk_window_move_resize()
6195 * on when it's safe to call this function.
6197 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6199 gint center_x, center_y;
6201 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6209 gtk_window_move_resize (GtkWindow *window)
6213 * First we determine whether any information has changed that would
6214 * cause us to revise our last configure request. If we would send
6215 * a different configure request from last time, then
6216 * configure_request_size_changed = TRUE or
6217 * configure_request_pos_changed = TRUE. configure_request_size_changed
6218 * may be true due to new hints, a gtk_window_resize(), or whatever.
6219 * configure_request_pos_changed may be true due to gtk_window_set_position()
6220 * or gtk_window_move().
6222 * If the configure request has changed, we send off a new one. To
6223 * ensure GTK+ invariants are maintained (resize queue does what it
6224 * should), we go ahead and size_allocate the requested size in this
6227 * If the configure request has not changed, we don't ever resend
6228 * it, because it could mean fighting the user or window manager.
6231 * To prepare the configure request, we come up with a base size/pos:
6232 * - the one from gtk_window_move()/gtk_window_resize()
6233 * - else default_width, default_height if we haven't ever
6235 * - else the size request if we haven't ever been mapped,
6236 * as a substitute default size
6237 * - else the current size of the window, as received from
6238 * configure notifies (i.e. the current allocation)
6240 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6241 * the position request to be centered.
6243 GtkWindowPrivate *priv = window->priv;
6244 GtkAllocation allocation;
6246 GtkContainer *container;
6247 GtkWindowGeometryInfo *info;
6248 GdkGeometry new_geometry;
6249 GdkWindow *gdk_window;
6251 GdkRectangle new_request;
6252 gboolean configure_request_size_changed;
6253 gboolean configure_request_pos_changed;
6254 gboolean hints_changed; /* do we need to send these again */
6255 GtkWindowLastGeometryInfo saved_last_info;
6257 widget = GTK_WIDGET (window);
6258 gdk_window = gtk_widget_get_window (widget);
6259 container = GTK_CONTAINER (widget);
6260 info = gtk_window_get_geometry_info (window, TRUE);
6262 configure_request_size_changed = FALSE;
6263 configure_request_pos_changed = FALSE;
6265 gtk_window_compute_configure_request (window, &new_request,
6266 &new_geometry, &new_flags);
6268 /* This check implies the invariant that we never set info->last
6269 * without setting the hints and sending off a configure request.
6271 * If we change info->last without sending the request, we may
6274 if (info->last.configure_request.x != new_request.x ||
6275 info->last.configure_request.y != new_request.y)
6276 configure_request_pos_changed = TRUE;
6278 if ((info->last.configure_request.width != new_request.width ||
6279 info->last.configure_request.height != new_request.height))
6280 configure_request_size_changed = TRUE;
6282 hints_changed = FALSE;
6284 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6285 &new_geometry, new_flags))
6287 hints_changed = TRUE;
6290 /* Position Constraints
6291 * ====================
6293 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6294 * a default. The other POS_ values are used only when the
6295 * window is shown, not after that.
6297 * However, we can't implement a position constraint as
6298 * "anytime the window size changes, center the window"
6299 * because this may well end up fighting the WM or user. In
6300 * fact it gets in an infinite loop with at least one WM.
6302 * Basically, applications are in no way in a position to
6303 * constrain the position of a window, with one exception:
6304 * override redirect windows. (Really the intended purpose
6305 * of CENTER_ALWAYS anyhow, I would think.)
6307 * So the way we implement this "constraint" is to say that when WE
6308 * cause a move or resize, i.e. we make a configure request changing
6309 * window size, we recompute the CENTER_ALWAYS position to reflect
6310 * the new window size, and include it in our request. Also, if we
6311 * just turned on CENTER_ALWAYS we snap to center with a new
6312 * request. Otherwise, if we are just NOTIFIED of a move or resize
6313 * done by someone else e.g. the window manager, we do NOT send a
6314 * new configure request.
6316 * For override redirect windows, this works fine; all window
6317 * sizes are from our configure requests. For managed windows,
6318 * it is at least semi-sane, though who knows what the
6319 * app author is thinking.
6322 /* This condition should be kept in sync with the condition later on
6323 * that determines whether we send a configure request. i.e. we
6324 * should do this position constraining anytime we were going to
6325 * send a configure request anyhow, plus when constraints have
6328 if (configure_request_pos_changed ||
6329 configure_request_size_changed ||
6331 info->position_constraints_changed)
6333 /* We request the constrained position if:
6334 * - we were changing position, and need to clamp
6335 * the change to the constraint
6336 * - we're changing the size anyway
6337 * - set_position() was called to toggle CENTER_ALWAYS on
6340 gtk_window_constrain_position (window,
6346 /* Update whether we need to request a move */
6347 if (info->last.configure_request.x != new_request.x ||
6348 info->last.configure_request.y != new_request.y)
6349 configure_request_pos_changed = TRUE;
6351 configure_request_pos_changed = FALSE;
6355 if (priv->type == GTK_WINDOW_TOPLEVEL)
6357 int notify_x, notify_y;
6359 /* this is the position from the last configure notify */
6360 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6362 g_message ("--- %s ---\n"
6363 "last : %d,%d\t%d x %d\n"
6364 "this : %d,%d\t%d x %d\n"
6365 "alloc : %d,%d\t%d x %d\n"
6367 "resize: \t%d x %d\n"
6368 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6369 "configure_notify_received: %d\n"
6370 "configure_request_count: %d\n"
6371 "position_constraints_changed: %d\n",
6372 priv->title ? priv->title : "(no title)",
6373 info->last.configure_request.x,
6374 info->last.configure_request.y,
6375 info->last.configure_request.width,
6376 info->last.configure_request.height,
6382 widget->allocation.width,
6383 widget->allocation.height,
6384 widget->requisition.width,
6385 widget->requisition.height,
6387 info->resize_height,
6388 configure_request_pos_changed,
6389 configure_request_size_changed,
6391 priv->configure_notify_received,
6392 priv->configure_request_count,
6393 info->position_constraints_changed);
6397 saved_last_info = info->last;
6398 info->last.geometry = new_geometry;
6399 info->last.flags = new_flags;
6400 info->last.configure_request = new_request;
6402 /* need to set PPosition so the WM will look at our position,
6403 * but we don't want to count PPosition coming and going as a hints
6404 * change for future iterations. So we saved info->last prior to
6408 /* Also, if the initial position was explicitly set, then we always
6409 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6413 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6414 * this is an initial map
6417 if ((configure_request_pos_changed ||
6418 info->initial_pos_set ||
6419 (priv->need_default_position &&
6420 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6421 (new_flags & GDK_HINT_POS) == 0)
6423 new_flags |= GDK_HINT_POS;
6424 hints_changed = TRUE;
6427 /* Set hints if necessary
6430 gdk_window_set_geometry_hints (gdk_window,
6434 gtk_widget_get_allocation (widget, &allocation);
6436 /* handle resizing/moving and widget tree allocation
6438 if (priv->configure_notify_received)
6440 /* If we have received a configure event since
6441 * the last time in this function, we need to
6442 * accept our new size and size_allocate child widgets.
6443 * (see gtk_window_configure_event() for more details).
6445 * 1 or more configure notifies may have been received.
6446 * Also, configure_notify_received will only be TRUE
6447 * if all expected configure notifies have been received
6448 * (one per configure request), as an optimization.
6451 priv->configure_notify_received = FALSE;
6453 /* gtk_window_configure_event() filled in widget->allocation */
6454 gtk_widget_size_allocate (widget, &allocation);
6456 gdk_window_process_updates (gdk_window, TRUE);
6458 gdk_window_configure_finished (gdk_window);
6460 /* If the configure request changed, it means that
6462 * 1) coincidentally changed hints or widget properties
6463 * impacting the configure request before getting
6464 * a configure notify, or
6465 * 2) some broken widget is changing its size request
6466 * during size allocation, resulting in
6467 * a false appearance of changed configure request.
6469 * For 1), we could just go ahead and ask for the
6470 * new size right now, but doing that for 2)
6471 * might well be fighting the user (and can even
6472 * trigger a loop). Since we really don't want to
6473 * do that, we requeue a resize in hopes that
6474 * by the time it gets handled, the child has seen
6475 * the light and is willing to go along with the
6476 * new size. (this happens for the zvt widget, since
6477 * the size_allocate() above will have stored the
6478 * requisition corresponding to the new size in the
6481 * This doesn't buy us anything for 1), but it shouldn't
6482 * hurt us too badly, since it is what would have
6483 * happened if we had gotten the configure event before
6484 * the new size had been set.
6487 if (configure_request_size_changed ||
6488 configure_request_pos_changed)
6490 /* Don't change the recorded last info after all, because we
6491 * haven't actually updated to the new info yet - we decided
6492 * to postpone our configure request until later.
6494 info->last = saved_last_info;
6496 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6499 return; /* Bail out, we didn't really process the move/resize */
6501 else if ((configure_request_size_changed || hints_changed) &&
6502 (allocation.width != new_request.width || allocation.height != new_request.height))
6505 /* We are in one of the following situations:
6506 * A. configure_request_size_changed
6507 * our requisition has changed and we need a different window size,
6508 * so we request it from the window manager.
6509 * B. !configure_request_size_changed && hints_changed
6510 * the window manager rejects our size, but we have just changed the
6511 * window manager hints, so there's a chance our request will
6512 * be honoured this time, so we try again.
6514 * However, if the new requisition is the same as the current allocation,
6515 * we don't request it again, since we won't get a ConfigureNotify back from
6516 * the window manager unless it decides to change our requisition. If
6517 * we don't get the ConfigureNotify back, the resize queue will never be run.
6520 /* Now send the configure request */
6521 if (configure_request_pos_changed)
6525 gdk_window_move_resize (priv->frame,
6526 new_request.x - priv->frame_left,
6527 new_request.y - priv->frame_top,
6528 new_request.width + priv->frame_left + priv->frame_right,
6529 new_request.height + priv->frame_top + priv->frame_bottom);
6530 gdk_window_resize (gdk_window,
6531 new_request.width, new_request.height);
6534 gdk_window_move_resize (gdk_window,
6535 new_request.x, new_request.y,
6536 new_request.width, new_request.height);
6538 else /* only size changed */
6541 gdk_window_resize (priv->frame,
6542 new_request.width + priv->frame_left + priv->frame_right,
6543 new_request.height + priv->frame_top + priv->frame_bottom);
6544 gdk_window_resize (gdk_window,
6545 new_request.width, new_request.height);
6548 if (priv->type == GTK_WINDOW_POPUP)
6550 GtkAllocation allocation;
6552 /* Directly size allocate for override redirect (popup) windows. */
6555 allocation.width = new_request.width;
6556 allocation.height = new_request.height;
6558 gtk_widget_size_allocate (widget, &allocation);
6560 gdk_window_process_updates (gdk_window, TRUE);
6562 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6563 gtk_widget_queue_draw (widget);
6567 /* Increment the number of have-not-yet-received-notify requests */
6568 priv->configure_request_count += 1;
6569 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
6571 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6572 * configure event in response to our resizing request.
6573 * the configure event will cause a new resize with
6574 * ->configure_notify_received=TRUE.
6575 * until then, we want to
6576 * - discard expose events
6577 * - coalesce resizes for our children
6578 * - defer any window resizes until the configure event arrived
6579 * to achieve this, we queue a resize for the window, but remove its
6580 * resizing handler, so resizing will not be handled from the next
6581 * idle handler but when the configure event arrives.
6583 * FIXME: we should also dequeue the pending redraws here, since
6584 * we handle those ourselves upon ->configure_notify_received==TRUE.
6586 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6588 gtk_widget_queue_resize_no_redraw (widget);
6589 _gtk_container_dequeue_resize_handler (container);
6595 /* Handle any position changes.
6597 if (configure_request_pos_changed)
6601 gdk_window_move (priv->frame,
6602 new_request.x - priv->frame_left,
6603 new_request.y - priv->frame_top);
6606 gdk_window_move (gdk_window,
6607 new_request.x, new_request.y);
6610 /* And run the resize queue.
6612 gtk_container_resize_children (container);
6615 /* We have now processed a move/resize since the last position
6616 * constraint change, setting of the initial position, or resize.
6617 * (Not resetting these flags here can lead to infinite loops for
6618 * GTK_RESIZE_IMMEDIATE containers)
6620 info->position_constraints_changed = FALSE;
6621 info->initial_pos_set = FALSE;
6622 info->resize_width = -1;
6623 info->resize_height = -1;
6626 /* Compare two sets of Geometry hints for equality.
6629 gtk_window_compare_hints (GdkGeometry *geometry_a,
6631 GdkGeometry *geometry_b,
6634 if (flags_a != flags_b)
6637 if ((flags_a & GDK_HINT_MIN_SIZE) &&
6638 (geometry_a->min_width != geometry_b->min_width ||
6639 geometry_a->min_height != geometry_b->min_height))
6642 if ((flags_a & GDK_HINT_MAX_SIZE) &&
6643 (geometry_a->max_width != geometry_b->max_width ||
6644 geometry_a->max_height != geometry_b->max_height))
6647 if ((flags_a & GDK_HINT_BASE_SIZE) &&
6648 (geometry_a->base_width != geometry_b->base_width ||
6649 geometry_a->base_height != geometry_b->base_height))
6652 if ((flags_a & GDK_HINT_ASPECT) &&
6653 (geometry_a->min_aspect != geometry_b->min_aspect ||
6654 geometry_a->max_aspect != geometry_b->max_aspect))
6657 if ((flags_a & GDK_HINT_RESIZE_INC) &&
6658 (geometry_a->width_inc != geometry_b->width_inc ||
6659 geometry_a->height_inc != geometry_b->height_inc))
6662 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
6663 geometry_a->win_gravity != geometry_b->win_gravity)
6670 _gtk_window_constrain_size (GtkWindow *window,
6676 GtkWindowPrivate *priv;
6677 GtkWindowGeometryInfo *info;
6679 g_return_if_fail (GTK_IS_WINDOW (window));
6681 priv = window->priv;
6683 info = priv->geometry_info;
6686 GdkWindowHints flags = info->last.flags;
6687 GdkGeometry *geometry = &info->last.geometry;
6689 gtk_window_constrain_size (window,
6700 gtk_window_constrain_size (GtkWindow *window,
6701 GdkGeometry *geometry,
6708 gdk_window_constrain_size (geometry, flags, width, height,
6709 new_width, new_height);
6712 /* Compute the set of geometry hints and flags for a window
6713 * based on the application set geometry, and requisiition
6714 * of the window. gtk_widget_size_request() must have been
6718 gtk_window_compute_hints (GtkWindow *window,
6719 GdkGeometry *new_geometry,
6722 GtkWindowPrivate *priv = window->priv;
6724 gint extra_width = 0;
6725 gint extra_height = 0;
6726 GtkWindowGeometryInfo *geometry_info;
6727 GtkRequisition requisition;
6729 widget = GTK_WIDGET (window);
6731 gtk_widget_get_child_requisition (widget, &requisition);
6732 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
6736 *new_flags = geometry_info->mask;
6737 *new_geometry = geometry_info->geometry;
6744 if (geometry_info && geometry_info->widget)
6746 GtkRequisition requisition;
6747 GtkRequisition child_requisition;
6749 /* FIXME: This really isn't right. It gets the min size wrong and forces
6750 * callers to do horrible hacks like set a huge usize on the child requisition
6751 * to get the base size right. We really want to find the answers to:
6753 * - If the geometry widget was infinitely big, how much extra space
6754 * would be needed for the stuff around it.
6756 * - If the geometry widget was infinitely small, how big would the
6757 * window still have to be.
6759 * Finding these answers would be a bit of a mess here. (Bug #68668)
6761 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
6763 gtk_size_request_get_size (GTK_SIZE_REQUEST (widget), &requisition, NULL);
6764 extra_width = requisition.width - child_requisition.width;
6765 extra_height = requisition.height - child_requisition.height;
6768 /* We don't want to set GDK_HINT_POS in here, we just set it
6769 * in gtk_window_move_resize() when we want the position
6773 if (*new_flags & GDK_HINT_BASE_SIZE)
6775 new_geometry->base_width += extra_width;
6776 new_geometry->base_height += extra_height;
6778 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
6779 (*new_flags & GDK_HINT_RESIZE_INC) &&
6780 ((extra_width != 0) || (extra_height != 0)))
6782 *new_flags |= GDK_HINT_BASE_SIZE;
6784 new_geometry->base_width = extra_width;
6785 new_geometry->base_height = extra_height;
6788 if (*new_flags & GDK_HINT_MIN_SIZE)
6790 if (new_geometry->min_width < 0)
6791 new_geometry->min_width = requisition.width;
6793 new_geometry->min_width += extra_width;
6795 if (new_geometry->min_height < 0)
6796 new_geometry->min_height = requisition.height;
6798 new_geometry->min_height += extra_height;
6802 *new_flags |= GDK_HINT_MIN_SIZE;
6804 new_geometry->min_width = requisition.width;
6805 new_geometry->min_height = requisition.height;
6808 if (*new_flags & GDK_HINT_MAX_SIZE)
6810 if (new_geometry->max_width < 0)
6811 new_geometry->max_width = requisition.width;
6813 new_geometry->max_width += extra_width;
6815 if (new_geometry->max_height < 0)
6816 new_geometry->max_height = requisition.height;
6818 new_geometry->max_height += extra_height;
6820 else if (!priv->resizable)
6822 *new_flags |= GDK_HINT_MAX_SIZE;
6824 new_geometry->max_width = requisition.width;
6825 new_geometry->max_height = requisition.height;
6828 *new_flags |= GDK_HINT_WIN_GRAVITY;
6829 new_geometry->win_gravity = priv->gravity;
6832 /***********************
6833 * Redrawing functions *
6834 ***********************/
6837 gtk_window_paint (GtkWidget *widget,
6840 gtk_paint_flat_box (gtk_widget_get_style (widget),
6841 gtk_widget_get_window (widget),
6843 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6847 gtk_window_expose (GtkWidget *widget,
6848 GdkEventExpose *event)
6850 if (!gtk_widget_get_app_paintable (widget))
6851 gtk_window_paint (widget, &event->area);
6853 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
6854 return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
6860 * gtk_window_set_has_frame:
6861 * @window: a #GtkWindow
6862 * @setting: a boolean
6864 * (Note: this is a special-purpose function for the framebuffer port,
6865 * that causes GTK+ to draw its own window border. For most applications,
6866 * you want gtk_window_set_decorated() instead, which tells the window
6867 * manager whether to draw the window border.)
6869 * If this function is called on a window with setting of %TRUE, before
6870 * it is realized or showed, it will have a "frame" window around
6871 * @window->window, accessible in @window->frame. Using the signal
6872 * frame_event you can receive all events targeted at the frame.
6874 * This function is used by the linux-fb port to implement managed
6875 * windows, but it could conceivably be used by X-programs that
6876 * want to do their own window decorations.
6880 gtk_window_set_has_frame (GtkWindow *window,
6883 GtkWindowPrivate *priv;
6885 g_return_if_fail (GTK_IS_WINDOW (window));
6886 g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
6888 priv = window->priv;
6890 priv->has_frame = setting != FALSE;
6894 * gtk_window_get_has_frame:
6895 * @window: a #GtkWindow
6897 * Accessor for whether the window has a frame window exterior to
6898 * @window->window. Gets the value set by gtk_window_set_has_frame ().
6900 * Return value: %TRUE if a frame has been added to the window
6901 * via gtk_window_set_has_frame().
6904 gtk_window_get_has_frame (GtkWindow *window)
6906 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6908 return window->priv->has_frame;
6912 * gtk_window_set_frame_dimensions:
6913 * @window: a #GtkWindow that has a frame
6914 * @left: The width of the left border
6915 * @top: The height of the top border
6916 * @right: The width of the right border
6917 * @bottom: The height of the bottom border
6919 * (Note: this is a special-purpose function intended for the framebuffer
6920 * port; see gtk_window_set_has_frame(). It will have no effect on the
6921 * window border drawn by the window manager, which is the normal
6922 * case when using the X Window system.)
6924 * For windows with frames (see gtk_window_set_has_frame()) this function
6925 * can be used to change the size of the frame border.
6928 gtk_window_set_frame_dimensions (GtkWindow *window,
6934 GtkWindowPrivate *priv;
6935 GtkAllocation allocation;
6938 g_return_if_fail (GTK_IS_WINDOW (window));
6940 priv = window->priv;
6941 widget = GTK_WIDGET (window);
6943 if (priv->frame_left == left &&
6944 priv->frame_top == top &&
6945 priv->frame_right == right &&
6946 priv->frame_bottom == bottom)
6949 priv->frame_left = left;
6950 priv->frame_top = top;
6951 priv->frame_right = right;
6952 priv->frame_bottom = bottom;
6954 if (gtk_widget_get_realized (widget) && priv->frame)
6956 gtk_widget_get_allocation (widget, &allocation);
6958 gint width = allocation.width + left + right;
6959 gint height = allocation.height + top + bottom;
6960 gdk_window_resize (priv->frame, width, height);
6961 gtk_decorated_window_move_resize_window (window,
6969 * gtk_window_present:
6970 * @window: a #GtkWindow
6972 * Presents a window to the user. This may mean raising the window
6973 * in the stacking order, deiconifying it, moving it to the current
6974 * desktop, and/or giving it the keyboard focus, possibly dependent
6975 * on the user's platform, window manager, and preferences.
6977 * If @window is hidden, this function calls gtk_widget_show()
6980 * This function should be used when the user tries to open a window
6981 * that's already open. Say for example the preferences dialog is
6982 * currently open, and the user chooses Preferences from the menu
6983 * a second time; use gtk_window_present() to move the already-open dialog
6984 * where the user can see it.
6986 * If you are calling this function in response to a user interaction,
6987 * it is preferable to use gtk_window_present_with_time().
6991 gtk_window_present (GtkWindow *window)
6993 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6997 * gtk_window_present_with_time:
6998 * @window: a #GtkWindow
6999 * @timestamp: the timestamp of the user interaction (typically a
7000 * button or key press event) which triggered this call
7002 * Presents a window to the user in response to a user interaction.
7003 * If you need to present a window without a timestamp, use
7004 * gtk_window_present(). See gtk_window_present() for details.
7009 gtk_window_present_with_time (GtkWindow *window,
7013 GdkWindow *gdk_window;
7015 g_return_if_fail (GTK_IS_WINDOW (window));
7017 widget = GTK_WIDGET (window);
7019 if (gtk_widget_get_visible (widget))
7021 gdk_window = gtk_widget_get_window (widget);
7023 g_assert (gdk_window != NULL);
7025 gdk_window_show (gdk_window);
7027 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7028 if (timestamp == GDK_CURRENT_TIME)
7030 #ifdef GDK_WINDOWING_X11
7031 GdkDisplay *display;
7033 display = gtk_widget_get_display (GTK_WIDGET (window));
7034 timestamp = gdk_x11_display_get_user_time (display);
7036 timestamp = gtk_get_current_event_time ();
7040 gdk_window_focus (gdk_window, timestamp);
7044 gtk_widget_show (widget);
7049 * gtk_window_iconify:
7050 * @window: a #GtkWindow
7052 * Asks to iconify (i.e. minimize) the specified @window. Note that
7053 * you shouldn't assume the window is definitely iconified afterward,
7054 * because other entities (e.g. the user or <link
7055 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7056 * again, or there may not be a window manager in which case
7057 * iconification isn't possible, etc. But normally the window will end
7058 * up iconified. Just don't write code that crashes if not.
7060 * It's permitted to call this function before showing a window,
7061 * in which case the window will be iconified before it ever appears
7064 * You can track iconification via the "window-state-event" signal
7069 gtk_window_iconify (GtkWindow *window)
7071 GtkWindowPrivate *priv;
7073 GdkWindow *toplevel;
7075 g_return_if_fail (GTK_IS_WINDOW (window));
7077 priv = window->priv;
7078 widget = GTK_WIDGET (window);
7080 priv->iconify_initially = TRUE;
7083 toplevel = priv->frame;
7085 toplevel = gtk_widget_get_window (widget);
7087 if (toplevel != NULL)
7088 gdk_window_iconify (toplevel);
7092 * gtk_window_deiconify:
7093 * @window: a #GtkWindow
7095 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7096 * that you shouldn't assume the window is definitely deiconified
7097 * afterward, because other entities (e.g. the user or <link
7098 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7099 * again before your code which assumes deiconification gets to run.
7101 * You can track iconification via the "window-state-event" signal
7105 gtk_window_deiconify (GtkWindow *window)
7107 GtkWindowPrivate *priv;
7109 GdkWindow *toplevel;
7111 g_return_if_fail (GTK_IS_WINDOW (window));
7113 priv = window->priv;
7114 widget = GTK_WIDGET (window);
7116 priv->iconify_initially = FALSE;
7119 toplevel = priv->frame;
7121 toplevel = gtk_widget_get_window (widget);
7123 if (toplevel != NULL)
7124 gdk_window_deiconify (toplevel);
7129 * @window: a #GtkWindow
7131 * Asks to stick @window, which means that it will appear on all user
7132 * desktops. Note that you shouldn't assume the window is definitely
7133 * stuck afterward, because other entities (e.g. the user or <link
7134 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7135 * again, and some window managers do not support sticking
7136 * windows. But normally the window will end up stuck. Just don't
7137 * write code that crashes if not.
7139 * It's permitted to call this function before showing a window.
7141 * You can track stickiness via the "window-state-event" signal
7146 gtk_window_stick (GtkWindow *window)
7148 GtkWindowPrivate *priv;
7150 GdkWindow *toplevel;
7152 g_return_if_fail (GTK_IS_WINDOW (window));
7154 priv = window->priv;
7155 widget = GTK_WIDGET (window);
7157 priv->stick_initially = TRUE;
7160 toplevel = priv->frame;
7162 toplevel = gtk_widget_get_window (widget);
7164 if (toplevel != NULL)
7165 gdk_window_stick (toplevel);
7169 * gtk_window_unstick:
7170 * @window: a #GtkWindow
7172 * Asks to unstick @window, which means that it will appear on only
7173 * one of the user's desktops. Note that you shouldn't assume the
7174 * window is definitely unstuck afterward, because other entities
7175 * (e.g. the user or <link linkend="gtk-X11-arch">window
7176 * manager</link>) could stick it again. But normally the window will
7177 * end up stuck. Just don't write code that crashes if not.
7179 * You can track stickiness via the "window-state-event" signal
7184 gtk_window_unstick (GtkWindow *window)
7186 GtkWindowPrivate *priv;
7188 GdkWindow *toplevel;
7190 g_return_if_fail (GTK_IS_WINDOW (window));
7192 priv = window->priv;
7193 widget = GTK_WIDGET (window);
7195 priv->stick_initially = FALSE;
7198 toplevel = priv->frame;
7200 toplevel = gtk_widget_get_window (widget);
7202 if (toplevel != NULL)
7203 gdk_window_unstick (toplevel);
7207 * gtk_window_maximize:
7208 * @window: a #GtkWindow
7210 * Asks to maximize @window, so that it becomes full-screen. Note that
7211 * you shouldn't assume the window is definitely maximized afterward,
7212 * because other entities (e.g. the user or <link
7213 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7214 * again, and not all window managers support maximization. But
7215 * normally the window will end up maximized. Just don't write code
7216 * that crashes if not.
7218 * It's permitted to call this function before showing a window,
7219 * in which case the window will be maximized when it appears onscreen
7222 * You can track maximization via the "window-state-event" signal
7227 gtk_window_maximize (GtkWindow *window)
7229 GtkWindowPrivate *priv;
7231 GdkWindow *toplevel;
7233 g_return_if_fail (GTK_IS_WINDOW (window));
7235 priv = window->priv;
7236 widget = GTK_WIDGET (window);
7238 priv->maximize_initially = TRUE;
7241 toplevel = priv->frame;
7243 toplevel = gtk_widget_get_window (widget);
7245 if (toplevel != NULL)
7246 gdk_window_maximize (toplevel);
7250 * gtk_window_unmaximize:
7251 * @window: a #GtkWindow
7253 * Asks to unmaximize @window. Note that you shouldn't assume the
7254 * window is definitely unmaximized afterward, because other entities
7255 * (e.g. the user or <link linkend="gtk-X11-arch">window
7256 * manager</link>) could maximize it again, and not all window
7257 * managers honor requests to unmaximize. But normally the window will
7258 * end up unmaximized. Just don't write code that crashes if not.
7260 * You can track maximization via the "window-state-event" signal
7265 gtk_window_unmaximize (GtkWindow *window)
7267 GtkWindowPrivate *priv;
7269 GdkWindow *toplevel;
7271 g_return_if_fail (GTK_IS_WINDOW (window));
7273 priv = window->priv;
7274 widget = GTK_WIDGET (window);
7276 priv->maximize_initially = FALSE;
7279 toplevel = priv->frame;
7281 toplevel = gtk_widget_get_window (widget);
7283 if (toplevel != NULL)
7284 gdk_window_unmaximize (toplevel);
7288 * gtk_window_fullscreen:
7289 * @window: a #GtkWindow
7291 * Asks to place @window in the fullscreen state. Note that you
7292 * shouldn't assume the window is definitely full screen afterward,
7293 * because other entities (e.g. the user or <link
7294 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7295 * again, and not all window managers honor requests to fullscreen
7296 * windows. But normally the window will end up fullscreen. Just
7297 * don't write code that crashes if not.
7299 * You can track the fullscreen state via the "window-state-event" signal
7305 gtk_window_fullscreen (GtkWindow *window)
7307 GtkWindowPrivate *priv;
7309 GdkWindow *toplevel;
7311 g_return_if_fail (GTK_IS_WINDOW (window));
7313 priv = window->priv;
7314 widget = GTK_WIDGET (window);
7316 priv->fullscreen_initially = TRUE;
7319 toplevel = priv->frame;
7321 toplevel = gtk_widget_get_window (widget);
7323 if (toplevel != NULL)
7324 gdk_window_fullscreen (toplevel);
7328 * gtk_window_unfullscreen:
7329 * @window: a #GtkWindow
7331 * Asks to toggle off the fullscreen state for @window. Note that you
7332 * shouldn't assume the window is definitely not full screen
7333 * afterward, because other entities (e.g. the user or <link
7334 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7335 * again, and not all window managers honor requests to unfullscreen
7336 * windows. But normally the window will end up restored to its normal
7337 * state. Just don't write code that crashes if not.
7339 * You can track the fullscreen state via the "window-state-event" signal
7345 gtk_window_unfullscreen (GtkWindow *window)
7348 GdkWindow *toplevel;
7349 GtkWindowPrivate *priv;
7351 g_return_if_fail (GTK_IS_WINDOW (window));
7353 priv = window->priv;
7354 widget = GTK_WIDGET (window);
7356 priv->fullscreen_initially = FALSE;
7359 toplevel = priv->frame;
7361 toplevel = gtk_widget_get_window (widget);
7363 if (toplevel != NULL)
7364 gdk_window_unfullscreen (toplevel);
7368 * gtk_window_set_keep_above:
7369 * @window: a #GtkWindow
7370 * @setting: whether to keep @window above other windows
7372 * Asks to keep @window above, so that it stays on top. Note that
7373 * you shouldn't assume the window is definitely above afterward,
7374 * because other entities (e.g. the user or <link
7375 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7376 * and not all window managers support keeping windows above. But
7377 * normally the window will end kept above. Just don't write code
7378 * that crashes if not.
7380 * It's permitted to call this function before showing a window,
7381 * in which case the window will be kept above when it appears onscreen
7384 * You can track the above state via the "window-state-event" signal
7387 * Note that, according to the <ulink
7388 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7389 * Manager Hints</ulink> specification, the above state is mainly meant
7390 * for user preferences and should not be used by applications e.g. for
7391 * drawing attention to their dialogs.
7396 gtk_window_set_keep_above (GtkWindow *window,
7400 GtkWindowPrivate *priv;
7401 GdkWindow *toplevel;
7403 g_return_if_fail (GTK_IS_WINDOW (window));
7405 priv = window->priv;
7406 widget = GTK_WIDGET (window);
7408 priv->above_initially = setting != FALSE;
7410 priv->below_initially = FALSE;
7413 toplevel = priv->frame;
7415 toplevel = gtk_widget_get_window (widget);
7417 if (toplevel != NULL)
7418 gdk_window_set_keep_above (toplevel, setting);
7422 * gtk_window_set_keep_below:
7423 * @window: a #GtkWindow
7424 * @setting: whether to keep @window below other windows
7426 * Asks to keep @window below, so that it stays in bottom. Note that
7427 * you shouldn't assume the window is definitely below afterward,
7428 * because other entities (e.g. the user or <link
7429 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7430 * and not all window managers support putting windows below. But
7431 * normally the window will be kept below. Just don't write code
7432 * that crashes if not.
7434 * It's permitted to call this function before showing a window,
7435 * in which case the window will be kept below when it appears onscreen
7438 * You can track the below state via the "window-state-event" signal
7441 * Note that, according to the <ulink
7442 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7443 * Manager Hints</ulink> specification, the above state is mainly meant
7444 * for user preferences and should not be used by applications e.g. for
7445 * drawing attention to their dialogs.
7450 gtk_window_set_keep_below (GtkWindow *window,
7454 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->below_initially = setting != FALSE;
7464 priv->above_initially = FALSE;
7467 toplevel = priv->frame;
7469 toplevel = gtk_widget_get_window (widget);
7471 if (toplevel != NULL)
7472 gdk_window_set_keep_below (toplevel, setting);
7476 * gtk_window_set_resizable:
7477 * @window: a #GtkWindow
7478 * @resizable: %TRUE if the user can resize this window
7480 * Sets whether the user can resize a window. Windows are user resizable
7484 gtk_window_set_resizable (GtkWindow *window,
7487 GtkWindowPrivate *priv;
7489 g_return_if_fail (GTK_IS_WINDOW (window));
7491 priv = window->priv;
7493 priv->resizable = (resizable != FALSE);
7495 g_object_notify (G_OBJECT (window), "resizable");
7497 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7501 * gtk_window_get_resizable:
7502 * @window: a #GtkWindow
7504 * Gets the value set by gtk_window_set_resizable().
7506 * Return value: %TRUE if the user can resize the window
7509 gtk_window_get_resizable (GtkWindow *window)
7511 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7513 return window->priv->resizable;
7517 * gtk_window_set_gravity:
7518 * @window: a #GtkWindow
7519 * @gravity: window gravity
7521 * Window gravity defines the meaning of coordinates passed to
7522 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7525 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7526 * typically "do what you mean."
7530 gtk_window_set_gravity (GtkWindow *window,
7533 GtkWindowPrivate *priv;
7535 g_return_if_fail (GTK_IS_WINDOW (window));
7537 priv = window->priv;
7539 if (gravity != priv->gravity)
7541 priv->gravity = gravity;
7543 /* gtk_window_move_resize() will adapt gravity
7545 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7547 g_object_notify (G_OBJECT (window), "gravity");
7552 * gtk_window_get_gravity:
7553 * @window: a #GtkWindow
7555 * Gets the value set by gtk_window_set_gravity().
7557 * Return value: (transfer none): window gravity
7560 gtk_window_get_gravity (GtkWindow *window)
7562 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7564 return window->priv->gravity;
7568 * gtk_window_begin_resize_drag:
7569 * @window: a #GtkWindow
7570 * @button: mouse button that initiated the drag
7571 * @edge: position of the resize control
7572 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7573 * @root_y: Y position where the user clicked to initiate the drag
7574 * @timestamp: timestamp from the click event that initiated the drag
7576 * Starts resizing a window. This function is used if an application
7577 * has window resizing controls. When GDK can support it, the resize
7578 * will be done using the standard mechanism for the <link
7579 * linkend="gtk-X11-arch">window manager</link> or windowing
7580 * system. Otherwise, GDK will try to emulate window resizing,
7581 * potentially not all that well, depending on the windowing system.
7585 gtk_window_begin_resize_drag (GtkWindow *window,
7592 GtkWindowPrivate *priv;
7594 GdkWindow *toplevel;
7596 g_return_if_fail (GTK_IS_WINDOW (window));
7597 widget = GTK_WIDGET (window);
7598 g_return_if_fail (gtk_widget_get_visible (widget));
7600 priv = window->priv;
7603 toplevel = priv->frame;
7605 toplevel = gtk_widget_get_window (widget);
7607 gdk_window_begin_resize_drag (toplevel,
7614 * gtk_window_get_frame_dimensions:
7615 * @window: a #GtkWindow
7616 * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
7617 * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
7618 * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
7619 * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
7621 * (Note: this is a special-purpose function intended for the
7622 * framebuffer port; see gtk_window_set_has_frame(). It will not
7623 * return the size of the window border drawn by the <link
7624 * linkend="gtk-X11-arch">window manager</link>, which is the normal
7625 * case when using a windowing system. See
7626 * gdk_window_get_frame_extents() to get the standard window border
7629 * Retrieves the dimensions of the frame window for this toplevel.
7630 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
7633 gtk_window_get_frame_dimensions (GtkWindow *window,
7639 GtkWindowPrivate *priv;
7641 g_return_if_fail (GTK_IS_WINDOW (window));
7643 priv = window->priv;
7646 *left = priv->frame_left;
7648 *top = priv->frame_top;
7650 *right = priv->frame_right;
7652 *bottom = priv->frame_bottom;
7656 * gtk_window_begin_move_drag:
7657 * @window: a #GtkWindow
7658 * @button: mouse button that initiated the drag
7659 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7660 * @root_y: Y position where the user clicked to initiate the drag
7661 * @timestamp: timestamp from the click event that initiated the drag
7663 * Starts moving a window. This function is used if an application has
7664 * window movement grips. When GDK can support it, the window movement
7665 * will be done using the standard mechanism for the <link
7666 * linkend="gtk-X11-arch">window manager</link> or windowing
7667 * system. Otherwise, GDK will try to emulate window movement,
7668 * potentially not all that well, depending on the windowing system.
7672 gtk_window_begin_move_drag (GtkWindow *window,
7678 GtkWindowPrivate *priv;
7680 GdkWindow *toplevel;
7682 g_return_if_fail (GTK_IS_WINDOW (window));
7683 widget = GTK_WIDGET (window);
7684 g_return_if_fail (gtk_widget_get_visible (widget));
7686 priv = window->priv;
7689 toplevel = priv->frame;
7691 toplevel = gtk_widget_get_window (widget);
7693 gdk_window_begin_move_drag (toplevel,
7700 * gtk_window_set_screen:
7701 * @window: a #GtkWindow.
7702 * @screen: a #GdkScreen.
7704 * Sets the #GdkScreen where the @window is displayed; if
7705 * the window is already mapped, it will be unmapped, and
7706 * then remapped on the new screen.
7711 gtk_window_set_screen (GtkWindow *window,
7714 GtkWindowPrivate *priv;
7716 GdkScreen *previous_screen;
7717 gboolean was_mapped;
7719 g_return_if_fail (GTK_IS_WINDOW (window));
7720 g_return_if_fail (GDK_IS_SCREEN (screen));
7722 priv = window->priv;
7724 if (screen == priv->screen)
7727 widget = GTK_WIDGET (window);
7729 previous_screen = priv->screen;
7730 was_mapped = gtk_widget_get_mapped (widget);
7733 gtk_widget_unmap (widget);
7734 if (gtk_widget_get_realized (widget))
7735 gtk_widget_unrealize (widget);
7737 gtk_window_free_key_hash (window);
7738 priv->screen = screen;
7739 gtk_widget_reset_rc_styles (widget);
7740 if (screen != previous_screen)
7742 g_signal_handlers_disconnect_by_func (previous_screen,
7743 gtk_window_on_composited_changed, window);
7744 g_signal_connect (screen, "composited-changed",
7745 G_CALLBACK (gtk_window_on_composited_changed), window);
7747 _gtk_widget_propagate_screen_changed (widget, previous_screen);
7748 _gtk_widget_propagate_composited_changed (widget);
7750 g_object_notify (G_OBJECT (window), "screen");
7753 gtk_widget_map (widget);
7757 gtk_window_on_composited_changed (GdkScreen *screen,
7760 gtk_widget_queue_draw (GTK_WIDGET (window));
7762 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
7766 gtk_window_check_screen (GtkWindow *window)
7768 GtkWindowPrivate *priv = window->priv;
7771 return priv->screen;
7774 g_warning ("Screen for GtkWindow not set; you must always set\n"
7775 "a screen for a GtkWindow before using the window");
7781 * gtk_window_get_screen:
7782 * @window: a #GtkWindow.
7784 * Returns the #GdkScreen associated with @window.
7786 * Return value: (transfer none): a #GdkScreen.
7791 gtk_window_get_screen (GtkWindow *window)
7793 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
7795 return window->priv->screen;
7799 * gtk_window_is_active:
7800 * @window: a #GtkWindow
7802 * Returns whether the window is part of the current active toplevel.
7803 * (That is, the toplevel window receiving keystrokes.)
7804 * The return value is %TRUE if the window is active toplevel
7805 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
7806 * You might use this function if you wanted to draw a widget
7807 * differently in an active window from a widget in an inactive window.
7808 * See gtk_window_has_toplevel_focus()
7810 * Return value: %TRUE if the window part of the current active window.
7815 gtk_window_is_active (GtkWindow *window)
7817 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7819 return window->priv->is_active;
7823 * gtk_window_has_toplevel_focus:
7824 * @window: a #GtkWindow
7826 * Returns whether the input focus is within this GtkWindow.
7827 * For real toplevel windows, this is identical to gtk_window_is_active(),
7828 * but for embedded windows, like #GtkPlug, the results will differ.
7830 * Return value: %TRUE if the input focus is within this GtkWindow
7835 gtk_window_has_toplevel_focus (GtkWindow *window)
7837 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7839 return window->priv->has_toplevel_focus;
7843 gtk_window_group_class_init (GtkWindowGroupClass *klass)
7845 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
7849 gtk_window_group_get_type (void)
7851 static GType window_group_type = 0;
7853 if (!window_group_type)
7855 const GTypeInfo window_group_info =
7857 sizeof (GtkWindowGroupClass),
7858 NULL, /* base_init */
7859 NULL, /* base_finalize */
7860 (GClassInitFunc) gtk_window_group_class_init,
7861 NULL, /* class_finalize */
7862 NULL, /* class_data */
7863 sizeof (GtkWindowGroup),
7864 0, /* n_preallocs */
7865 (GInstanceInitFunc) NULL,
7868 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
7869 &window_group_info, 0);
7872 return window_group_type;
7876 * gtk_window_group_new:
7878 * Creates a new #GtkWindowGroup object. Grabs added with
7879 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7881 * Return value: a new #GtkWindowGroup.
7884 gtk_window_group_new (void)
7886 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7890 window_group_cleanup_grabs (GtkWindowGroup *group,
7893 GtkWindowGroupPrivate *priv;
7894 GtkDeviceGrabInfo *info;
7896 GSList *to_remove = NULL;
7898 tmp_list = group->grabs;
7901 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7902 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7903 tmp_list = tmp_list->next;
7908 gtk_grab_remove (to_remove->data);
7909 g_object_unref (to_remove->data);
7910 to_remove = g_slist_delete_link (to_remove, to_remove);
7913 priv = GTK_WINDOW_GROUP_GET_PRIVATE (group);
7914 tmp_list = priv->device_grabs;
7918 info = tmp_list->data;
7920 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
7921 to_remove = g_slist_prepend (to_remove, info);
7923 tmp_list = tmp_list->next;
7928 info = to_remove->data;
7930 gtk_device_grab_remove (info->widget, info->device);
7931 to_remove = g_slist_delete_link (to_remove, to_remove);
7936 * gtk_window_group_add_window:
7937 * @window_group: a #GtkWindowGroup
7938 * @window: the #GtkWindow to add
7940 * Adds a window to a #GtkWindowGroup.
7943 gtk_window_group_add_window (GtkWindowGroup *window_group,
7946 GtkWindowPrivate *priv;
7948 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7949 g_return_if_fail (GTK_IS_WINDOW (window));
7951 priv = window->priv;
7953 if (priv->group != window_group)
7955 g_object_ref (window);
7956 g_object_ref (window_group);
7959 gtk_window_group_remove_window (priv->group, window);
7961 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7963 priv->group = window_group;
7965 g_object_unref (window);
7970 * gtk_window_group_remove_window:
7971 * @window_group: a #GtkWindowGroup
7972 * @window: the #GtkWindow to remove
7974 * Removes a window from a #GtkWindowGroup.
7977 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7980 GtkWindowPrivate *priv;
7982 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7983 g_return_if_fail (GTK_IS_WINDOW (window));
7984 priv = window->priv;
7985 g_return_if_fail (priv->group == window_group);
7987 g_object_ref (window);
7989 window_group_cleanup_grabs (window_group, window);
7992 g_object_unref (window_group);
7993 g_object_unref (window);
7997 * gtk_window_group_list_windows:
7998 * @window_group: a #GtkWindowGroup
8000 * Returns a list of the #GtkWindows that belong to @window_group.
8002 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8003 * windows inside the group.
8008 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8010 GList *toplevels, *toplevel, *group_windows;
8012 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8014 group_windows = NULL;
8015 toplevels = gtk_window_list_toplevels ();
8017 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8019 GtkWindow *window = toplevel->data;
8021 if (window_group == window->priv->group)
8022 group_windows = g_list_prepend (group_windows, window);
8025 return g_list_reverse (group_windows);
8029 * gtk_window_get_group:
8030 * @window: (allow-none): a #GtkWindow, or %NULL
8032 * Returns the group for @window or the default group, if
8033 * @window is %NULL or if @window does not have an explicit
8036 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8041 gtk_window_get_group (GtkWindow *window)
8043 if (window && window->priv->group)
8044 return window->priv->group;
8047 static GtkWindowGroup *default_group = NULL;
8050 default_group = gtk_window_group_new ();
8052 return default_group;
8057 * gtk_window_has_group:
8058 * @window: a #GtkWindow
8060 * Returns whether @window has an explicit window group.
8062 * Return value: %TRUE if @window has an explicit window group.
8067 gtk_window_has_group (GtkWindow *window)
8069 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8071 return window->priv->group != NULL;
8075 * gtk_window_group_get_current_grab:
8076 * @window_group: a #GtkWindowGroup
8078 * Gets the current grab widget of the given group,
8079 * see gtk_grab_add().
8081 * Returns: the current grab widget of the group
8086 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8088 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8090 if (window_group->grabs)
8091 return GTK_WIDGET (window_group->grabs->data);
8096 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8099 gboolean block_others)
8101 GtkWindowGroupPrivate *priv;
8102 GtkDeviceGrabInfo *info;
8104 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8106 info = g_slice_new0 (GtkDeviceGrabInfo);
8107 info->widget = widget;
8108 info->device = device;
8109 info->block_others = block_others;
8111 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8115 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8119 GtkWindowGroupPrivate *priv;
8120 GtkDeviceGrabInfo *info;
8121 GSList *list, *node = NULL;
8122 GdkDevice *other_device;
8124 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8125 other_device = gdk_device_get_associated_device (device);
8126 list = priv->device_grabs;
8132 if (info->widget == widget &&
8133 (info->device == device ||
8134 info->device == other_device))
8147 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8148 g_slice_free (GtkDeviceGrabInfo, info);
8153 * gtk_window_group_get_current_device_grab:
8154 * @window_group: a #GtkWindowGroup
8155 * @device: a #GdkDevice
8157 * Returns the current grab widget for @device, or %NULL if none.
8159 * Returns: The grab widget, or %NULL
8164 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8167 GtkWindowGroupPrivate *priv;
8168 GtkDeviceGrabInfo *info;
8169 GdkDevice *other_device;
8172 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8173 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8175 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8176 list = priv->device_grabs;
8177 other_device = gdk_device_get_associated_device (device);
8184 if (info->device == device ||
8185 info->device == other_device)
8186 return info->widget;
8193 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8197 GtkWindowGroupPrivate *priv;
8198 GtkDeviceGrabInfo *info;
8199 GdkDevice *other_device;
8202 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8203 other_device = gdk_device_get_associated_device (device);
8204 list = priv->device_grabs;
8211 /* Look for blocking grabs on other device pairs
8212 * that have the passed widget within the GTK+ grab.
8214 if (info->block_others &&
8215 info->device != device &&
8216 info->device != other_device &&
8217 (info->widget == widget ||
8218 gtk_widget_is_ancestor (widget, info->widget)))
8226 Derived from XParseGeometry() in XFree86
8228 Copyright 1985, 1986, 1987,1998 The Open Group
8230 All Rights Reserved.
8232 The above copyright notice and this permission notice shall be included
8233 in all copies or substantial portions of the Software.
8235 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8236 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8237 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8238 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8239 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8240 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8241 OTHER DEALINGS IN THE SOFTWARE.
8243 Except as contained in this notice, the name of The Open Group shall
8244 not be used in advertising or otherwise to promote the sale, use or
8245 other dealings in this Software without prior written authorization
8246 from The Open Group.
8251 * XParseGeometry parses strings of the form
8252 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8253 * width, height, xoffset, and yoffset are unsigned integers.
8254 * Example: "=80x24+300-49"
8255 * The equal sign is optional.
8256 * It returns a bitmask that indicates which of the four values
8257 * were actually found in the string. For each value found,
8258 * the corresponding argument is updated; for each value
8259 * not found, the corresponding argument is left unchanged.
8262 /* The following code is from Xlib, and is minimally modified, so we
8263 * can track any upstream changes if required. Don't change this
8264 * code. Or if you do, put in a huge comment marking which thing
8269 read_int (gchar *string,
8277 else if (*string == '-')
8283 for (; (*string >= '0') && (*string <= '9'); string++)
8285 result = (result * 10) + (*string - '0');
8297 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8298 * value (x, y, width, height) was found in the parsed string.
8300 #define NoValue 0x0000
8301 #define XValue 0x0001
8302 #define YValue 0x0002
8303 #define WidthValue 0x0004
8304 #define HeightValue 0x0008
8305 #define AllValues 0x000F
8306 #define XNegative 0x0010
8307 #define YNegative 0x0020
8309 /* Try not to reformat/modify, so we can compare/sync with X sources */
8311 gtk_XParseGeometry (const char *string,
8314 unsigned int *width,
8315 unsigned int *height)
8319 unsigned int tempWidth, tempHeight;
8321 char *nextCharacter;
8323 /* These initializations are just to silence gcc */
8329 if ( (string == NULL) || (*string == '\0')) return(mask);
8331 string++; /* ignore possible '=' at beg of geometry spec */
8333 strind = (char *)string;
8334 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8335 tempWidth = read_int(strind, &nextCharacter);
8336 if (strind == nextCharacter)
8338 strind = nextCharacter;
8342 if (*strind == 'x' || *strind == 'X') {
8344 tempHeight = read_int(strind, &nextCharacter);
8345 if (strind == nextCharacter)
8347 strind = nextCharacter;
8348 mask |= HeightValue;
8351 if ((*strind == '+') || (*strind == '-')) {
8352 if (*strind == '-') {
8354 tempX = -read_int(strind, &nextCharacter);
8355 if (strind == nextCharacter)
8357 strind = nextCharacter;
8363 tempX = read_int(strind, &nextCharacter);
8364 if (strind == nextCharacter)
8366 strind = nextCharacter;
8369 if ((*strind == '+') || (*strind == '-')) {
8370 if (*strind == '-') {
8372 tempY = -read_int(strind, &nextCharacter);
8373 if (strind == nextCharacter)
8375 strind = nextCharacter;
8382 tempY = read_int(strind, &nextCharacter);
8383 if (strind == nextCharacter)
8385 strind = nextCharacter;
8391 /* If strind isn't at the end of the string the it's an invalid
8392 geometry specification. */
8394 if (*strind != '\0') return (0);
8400 if (mask & WidthValue)
8402 if (mask & HeightValue)
8403 *height = tempHeight;
8408 * gtk_window_parse_geometry:
8409 * @window: a #GtkWindow
8410 * @geometry: geometry string
8412 * Parses a standard X Window System geometry string - see the
8413 * manual page for X (type 'man X') for details on this.
8414 * gtk_window_parse_geometry() does work on all GTK+ ports
8415 * including Win32 but is primarily intended for an X environment.
8417 * If either a size or a position can be extracted from the
8418 * geometry string, gtk_window_parse_geometry() returns %TRUE
8419 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8420 * to resize/move the window.
8422 * If gtk_window_parse_geometry() returns %TRUE, it will also
8423 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8424 * indicating to the window manager that the size/position of
8425 * the window was user-specified. This causes most window
8426 * managers to honor the geometry.
8428 * Note that for gtk_window_parse_geometry() to work as expected, it has
8429 * to be called when the window has its "final" size, i.e. after calling
8430 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8433 * #include <gtk/gtk.h>
8436 * fill_with_content (GtkWidget *vbox)
8438 * /* fill with content... */
8442 * main (int argc, char *argv[])
8444 * GtkWidget *window, *vbox;
8445 * GdkGeometry size_hints = {
8446 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8449 * gtk_init (&argc, &argv);
8451 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8452 * vbox = gtk_vbox_new (FALSE, 0);
8454 * gtk_container_add (GTK_CONTAINER (window), vbox);
8455 * fill_with_content (vbox);
8456 * gtk_widget_show_all (vbox);
8458 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8461 * GDK_HINT_MIN_SIZE |
8462 * GDK_HINT_BASE_SIZE |
8463 * GDK_HINT_RESIZE_INC);
8467 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8468 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8471 * gtk_widget_show_all (window);
8478 * Return value: %TRUE if string was parsed successfully
8481 gtk_window_parse_geometry (GtkWindow *window,
8482 const gchar *geometry)
8484 gint result, x = 0, y = 0;
8487 gboolean size_set, pos_set;
8490 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8491 g_return_val_if_fail (geometry != NULL, FALSE);
8493 screen = gtk_window_check_screen (window);
8495 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8498 if ((result & WidthValue) || (result & HeightValue))
8500 gtk_window_set_default_size_internal (window,
8501 TRUE, result & WidthValue ? w : -1,
8502 TRUE, result & HeightValue ? h : -1,
8507 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8509 grav = GDK_GRAVITY_NORTH_WEST;
8511 if ((result & XNegative) && (result & YNegative))
8512 grav = GDK_GRAVITY_SOUTH_EAST;
8513 else if (result & XNegative)
8514 grav = GDK_GRAVITY_NORTH_EAST;
8515 else if (result & YNegative)
8516 grav = GDK_GRAVITY_SOUTH_WEST;
8518 if ((result & XValue) == 0)
8521 if ((result & YValue) == 0)
8524 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8525 grav == GDK_GRAVITY_SOUTH_EAST)
8526 y = gdk_screen_get_height (screen) - h + y;
8528 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8529 grav == GDK_GRAVITY_NORTH_EAST)
8530 x = gdk_screen_get_width (screen) - w + x;
8532 /* we don't let you put a window offscreen; maybe some people would
8533 * prefer to be able to, but it's kind of a bogus thing to do.
8542 if ((result & XValue) || (result & YValue))
8544 gtk_window_set_gravity (window, grav);
8545 gtk_window_move (window, x, y);
8549 if (size_set || pos_set)
8551 /* Set USSize, USPosition hints */
8552 GtkWindowGeometryInfo *info;
8554 info = gtk_window_get_geometry_info (window, TRUE);
8557 info->mask |= GDK_HINT_USER_POS;
8559 info->mask |= GDK_HINT_USER_SIZE;
8566 gtk_window_mnemonic_hash_foreach (guint keyval,
8572 GtkWindowKeysForeachFunc func;
8576 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8580 _gtk_window_keys_foreach (GtkWindow *window,
8581 GtkWindowKeysForeachFunc func,
8585 GtkMnemonicHash *mnemonic_hash;
8589 GtkWindowKeysForeachFunc func;
8593 info.window = window;
8595 info.func_data = func_data;
8597 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8599 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8600 gtk_window_mnemonic_hash_foreach, &info);
8602 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8605 GtkAccelGroup *group = groups->data;
8608 for (i = 0; i < group->priv->n_accels; i++)
8610 GtkAccelKey *key = &group->priv->priv_accels[i].key;
8613 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8616 groups = groups->next;
8621 gtk_window_keys_changed (GtkWindow *window)
8623 gtk_window_free_key_hash (window);
8624 gtk_window_get_key_hash (window);
8627 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8629 struct _GtkWindowKeyEntry
8633 guint is_mnemonic : 1;
8637 window_key_entry_destroy (gpointer data)
8639 g_slice_free (GtkWindowKeyEntry, data);
8643 add_to_key_hash (GtkWindow *window,
8645 GdkModifierType modifiers,
8646 gboolean is_mnemonic,
8649 GtkKeyHash *key_hash = data;
8651 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8653 entry->keyval = keyval;
8654 entry->modifiers = modifiers;
8655 entry->is_mnemonic = is_mnemonic;
8657 /* GtkAccelGroup stores lowercased accelerators. To deal
8658 * with this, if <Shift> was specified, uppercase.
8660 if (modifiers & GDK_SHIFT_MASK)
8662 if (keyval == GDK_KEY_Tab)
8663 keyval = GDK_KEY_ISO_Left_Tab;
8665 keyval = gdk_keyval_to_upper (keyval);
8668 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8672 gtk_window_get_key_hash (GtkWindow *window)
8674 GdkScreen *screen = gtk_window_check_screen (window);
8675 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8680 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8681 (GDestroyNotify)window_key_entry_destroy);
8682 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8683 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8689 gtk_window_free_key_hash (GtkWindow *window)
8691 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8694 _gtk_key_hash_free (key_hash);
8695 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8700 * gtk_window_activate_key:
8701 * @window: a #GtkWindow
8702 * @event: a #GdkEventKey
8704 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8705 * called by the default ::key_press_event handler for toplevel windows,
8706 * however in some cases it may be useful to call this directly when
8707 * overriding the standard key handling for a toplevel window.
8709 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8714 gtk_window_activate_key (GtkWindow *window,
8717 GtkKeyHash *key_hash;
8718 GtkWindowKeyEntry *found_entry = NULL;
8719 gboolean enable_mnemonics;
8720 gboolean enable_accels;
8722 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8723 g_return_val_if_fail (event != NULL, FALSE);
8725 key_hash = gtk_window_get_key_hash (window);
8730 GSList *entries = _gtk_key_hash_lookup (key_hash,
8731 event->hardware_keycode,
8733 gtk_accelerator_get_default_mod_mask (),
8736 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
8737 "gtk-enable-mnemonics", &enable_mnemonics,
8738 "gtk-enable-accels", &enable_accels,
8741 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
8743 GtkWindowKeyEntry *entry = tmp_list->data;
8744 if (entry->is_mnemonic)
8746 if (enable_mnemonics)
8748 found_entry = entry;
8754 if (enable_accels && !found_entry)
8756 found_entry = entry;
8761 g_slist_free (entries);
8766 if (found_entry->is_mnemonic)
8768 if (enable_mnemonics)
8769 return gtk_window_mnemonic_activate (window, found_entry->keyval,
8770 found_entry->modifiers);
8775 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
8776 found_entry->modifiers);
8784 window_update_has_focus (GtkWindow *window)
8786 GtkWindowPrivate *priv = window->priv;
8787 GtkWidget *widget = GTK_WIDGET (window);
8788 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
8790 if (has_focus != priv->has_focus)
8792 priv->has_focus = has_focus;
8796 if (priv->focus_widget &&
8797 priv->focus_widget != widget &&
8798 !gtk_widget_has_focus (priv->focus_widget))
8799 do_focus_change (priv->focus_widget, TRUE);
8803 if (priv->focus_widget &&
8804 priv->focus_widget != widget &&
8805 gtk_widget_has_focus (priv->focus_widget))
8806 do_focus_change (priv->focus_widget, FALSE);
8812 * _gtk_window_set_is_active:
8813 * @window: a #GtkWindow
8814 * @is_active: %TRUE if the window is in the currently active toplevel
8816 * Internal function that sets whether the #GtkWindow is part
8817 * of the currently active toplevel window (taking into account inter-process
8821 _gtk_window_set_is_active (GtkWindow *window,
8824 GtkWindowPrivate *priv;
8826 g_return_if_fail (GTK_IS_WINDOW (window));
8828 priv = window->priv;
8830 is_active = is_active != FALSE;
8832 if (is_active != priv->is_active)
8834 priv->is_active = is_active;
8835 window_update_has_focus (window);
8837 g_object_notify (G_OBJECT (window), "is-active");
8842 * _gtk_window_set_is_toplevel:
8843 * @window: a #GtkWindow
8844 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
8845 * parent of the root window); %FALSE if it is not (for example, for an
8846 * in-process, parented GtkPlug)
8848 * Internal function used by #GtkPlug when it gets parented/unparented by a
8849 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
8850 * global list of toplevel windows.
8853 _gtk_window_set_is_toplevel (GtkWindow *window,
8854 gboolean is_toplevel)
8858 widget = GTK_WIDGET (window);
8860 if (gtk_widget_is_toplevel (widget))
8861 g_assert (g_slist_find (toplevel_list, window) != NULL);
8863 g_assert (g_slist_find (toplevel_list, window) == NULL);
8865 if (is_toplevel == gtk_widget_is_toplevel (widget))
8870 _gtk_widget_set_is_toplevel (widget, TRUE);
8871 toplevel_list = g_slist_prepend (toplevel_list, window);
8875 _gtk_widget_set_is_toplevel (widget, FALSE);
8876 toplevel_list = g_slist_remove (toplevel_list, window);
8881 * _gtk_window_set_has_toplevel_focus:
8882 * @window: a #GtkWindow
8883 * @has_toplevel_focus: %TRUE if the in
8885 * Internal function that sets whether the keyboard focus for the
8886 * toplevel window (taking into account inter-process embedding.)
8889 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
8890 gboolean has_toplevel_focus)
8892 GtkWindowPrivate *priv;
8894 g_return_if_fail (GTK_IS_WINDOW (window));
8896 priv = window->priv;
8898 has_toplevel_focus = has_toplevel_focus != FALSE;
8900 if (has_toplevel_focus != priv->has_toplevel_focus)
8902 priv->has_toplevel_focus = has_toplevel_focus;
8903 window_update_has_focus (window);
8905 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
8910 * gtk_window_set_auto_startup_notification:
8911 * @setting: %TRUE to automatically do startup notification
8913 * By default, after showing the first #GtkWindow, GTK+ calls
8914 * gdk_notify_startup_complete(). Call this function to disable
8915 * the automatic startup notification. You might do this if your
8916 * first window is a splash screen, and you want to delay notification
8917 * until after your real main window has been shown, for example.
8919 * In that example, you would disable startup notification
8920 * temporarily, show your splash screen, then re-enable it so that
8921 * showing the main window would automatically result in notification.
8926 gtk_window_set_auto_startup_notification (gboolean setting)
8928 disable_startup_notification = !setting;
8932 * gtk_window_get_window_type:
8933 * @window: a #GtkWindow
8935 * Gets the type of the window. See #GtkWindowType.
8937 * Return value: the type of the window
8942 gtk_window_get_window_type (GtkWindow *window)
8944 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
8946 return window->priv->type;
8950 * gtk_window_get_mnemonics_visible:
8951 * @window: a #GtkWindow
8953 * Gets the value of the #GtkWindow:mnemonics-visible property.
8955 * Returns: %TRUE if mnemonics are supposed to be visible
8961 gtk_window_get_mnemonics_visible (GtkWindow *window)
8963 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8965 return window->priv->mnemonics_visible;
8969 * gtk_window_set_mnemonics_visible:
8970 * @window: a #GtkWindow
8971 * @setting: the new value
8973 * Sets the #GtkWindow:mnemonics-visible property.
8978 gtk_window_set_mnemonics_visible (GtkWindow *window,
8981 GtkWindowPrivate *priv;
8983 g_return_if_fail (GTK_IS_WINDOW (window));
8985 priv = window->priv;
8987 setting = setting != FALSE;
8989 if (priv->mnemonics_visible != setting)
8991 priv->mnemonics_visible = setting;
8992 g_object_notify (G_OBJECT (window), "mnemonics-visible");
8995 priv->mnemonics_visible_set = TRUE;
8999 _gtk_window_get_wmclass (GtkWindow *window,
9000 gchar **wmclass_name,
9001 gchar **wmclass_class)
9003 GtkWindowPrivate *priv = window->priv;
9005 *wmclass_name = priv->wmclass_name;
9006 *wmclass_class = priv->wmclass_class;