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/.
36 #include "gtkprivate.h"
38 #include "gtkwindow.h"
39 #include "gtkwindowprivate.h"
40 #include "gtkaccelgroupprivate.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 "gtkwidgetprivate.h"
53 #ifdef GDK_WINDOWING_X11
60 * @short_description: Toplevel which can contain other widgets
62 * A GtkWindow is a toplevel window which can contain other widgets.
63 * Windows normally have decorations that are under the control
64 * of the windowing system and allow the user to manipulate the window
65 * (resize it, move it, close it,...).
67 * GTK+ also allows windows to have a resize grip (a small area in the lower
68 * right or left corner) which can be clicked to reszie the window. To
69 * control whether a window has a resize grip, use
70 * gtk_window_set_has_resize_grip().
72 * <refsect2 id="GtkWindow-BUILDER-UI">
73 * <title>GtkWindow as GtkBuildable</title>
75 * The GtkWindow implementation of the GtkBuildable interface supports a
76 * custom <tag class="starttag">accel-groups</tag> element, which supports
77 * any number of <tag class="starttag">group</tag> elements representing the
78 * #GtkAccelGroup objects you want to add to your window (synonymous with
79 * gtk_window_add_accel_group().
82 * <title>A UI definition fragment with accel groups</title>
83 * <programlisting><![CDATA[
84 * <object class="GtkWindow">
86 * <group name="accelgroup1"/>
92 * <object class="GtkAccelGroup" id="accelgroup1"/>
93 * ]]></programlisting>
98 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
100 struct _GtkWindowPrivate
102 GtkMnemonicHash *mnemonic_hash;
104 GtkWidget *default_widget;
105 GtkWidget *focus_widget;
106 GtkWindow *transient_parent;
107 GtkWindowGeometryInfo *geometry_info;
108 GtkWindowGroup *group;
110 GdkModifierType mnemonic_modifier;
112 GdkWindowTypeHint gdk_type_hint;
114 GtkApplication *application;
118 GdkWindow *grip_window;
122 gchar *wmclass_class;
126 guint keys_changed_handler;
128 guint16 configure_request_count;
130 /* The following flags are initially TRUE (before a window is mapped).
131 * They cause us to compute a configure request that involves
132 * default-only parameters. Once mapped, we set them to FALSE.
133 * Then we set them to TRUE again on unmap (for position)
134 * and on unrealize (for size).
136 guint need_default_position : 1;
137 guint need_default_size : 1;
139 guint above_initially : 1;
140 guint accept_focus : 1;
141 guint below_initially : 1;
142 guint builder_visible : 1;
143 guint configure_notify_received : 1;
146 guint destroy_with_parent : 1;
147 guint focus_on_map : 1;
148 guint fullscreen_initially : 1;
149 guint gravity : 5; /* GdkGravity */
151 guint has_user_ref_count : 1;
152 guint has_toplevel_focus : 1;
153 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
155 guint maximize_initially : 1;
156 guint mnemonics_visible : 1;
157 guint mnemonics_visible_set : 1;
159 guint opacity_set : 1;
161 guint reset_type_hint : 1;
163 guint skips_pager : 1;
164 guint skips_taskbar : 1;
165 guint stick_initially : 1;
166 guint transient_parent_group : 1;
167 guint type : 4; /* GtkWindowType */
168 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
169 * one of the original eight. If not,
171 * GDK_WINDOW_TYPE_HINT_NORMAL
174 guint has_resize_grip : 1;
175 guint resize_grip_visible : 1; /* don't use, just for "resize-
176 * grip-visible" notification
204 PROP_DESTROY_WITH_PARENT,
209 PROP_SKIP_TASKBAR_HINT,
210 PROP_SKIP_PAGER_HINT,
219 PROP_HAS_RESIZE_GRIP,
220 PROP_RESIZE_GRIP_VISIBLE,
222 /* Readonly properties */
224 PROP_HAS_TOPLEVEL_FOCUS,
226 /* Writeonly properties */
229 PROP_MNEMONICS_VISIBLE,
239 guint using_default_icon : 1;
240 guint using_parent_icon : 1;
241 guint using_themed_icon : 1;
245 GdkGeometry geometry; /* Last set of geometry hints we set */
246 GdkWindowHints flags;
247 GdkRectangle configure_request;
248 } GtkWindowLastGeometryInfo;
250 struct _GtkWindowGeometryInfo
252 /* Properties that the app has set on the window
254 GdkGeometry geometry; /* Geometry hints */
256 GtkWidget *widget; /* subwidget to which hints apply */
257 /* from last gtk_window_resize () - if > 0, indicates that
258 * we should resize to this size.
263 /* From last gtk_window_move () prior to mapping -
264 * only used if initial_pos_set
269 /* Default size - used only the FIRST time we map a window,
274 /* whether to use initial_x, initial_y */
275 guint initial_pos_set : 1;
276 /* CENTER_ALWAYS or other position constraint changed since
277 * we sent the last configure request.
279 guint position_constraints_changed : 1;
281 /* if true, default_width, height should be multiplied by the
282 * increments and affect the geometry widget only
284 guint default_is_geometry : 1;
286 /* if true, resize_width, height should be multiplied by the
287 * increments and affect the geometry widget only
289 guint resize_is_geometry : 1;
291 GtkWindowLastGeometryInfo last;
295 struct _GtkDeviceGrabInfo
299 guint block_others : 1;
302 struct _GtkWindowGroupPrivate
305 GSList *device_grabs;
308 static void gtk_window_dispose (GObject *object);
309 static void gtk_window_finalize (GObject *object);
310 static void gtk_window_destroy (GtkWidget *widget);
311 static void gtk_window_show (GtkWidget *widget);
312 static void gtk_window_hide (GtkWidget *widget);
313 static void gtk_window_map (GtkWidget *widget);
314 static void gtk_window_unmap (GtkWidget *widget);
315 static void gtk_window_realize (GtkWidget *widget);
316 static void gtk_window_unrealize (GtkWidget *widget);
317 static void gtk_window_size_allocate (GtkWidget *widget,
318 GtkAllocation *allocation);
319 static gboolean gtk_window_map_event (GtkWidget *widget,
321 static gint gtk_window_configure_event (GtkWidget *widget,
322 GdkEventConfigure *event);
323 static gint gtk_window_key_press_event (GtkWidget *widget,
325 static gint gtk_window_key_release_event (GtkWidget *widget,
327 static gint gtk_window_button_press_event (GtkWidget *widget,
328 GdkEventButton *event);
329 static gint gtk_window_enter_notify_event (GtkWidget *widget,
330 GdkEventCrossing *event);
331 static gint gtk_window_leave_notify_event (GtkWidget *widget,
332 GdkEventCrossing *event);
333 static gint gtk_window_focus_in_event (GtkWidget *widget,
334 GdkEventFocus *event);
335 static gint gtk_window_focus_out_event (GtkWidget *widget,
336 GdkEventFocus *event);
337 static void gtk_window_style_updated (GtkWidget *widget);
338 static gint gtk_window_client_event (GtkWidget *widget,
339 GdkEventClient *event);
340 static gboolean gtk_window_state_event (GtkWidget *widget,
341 GdkEventWindowState *event);
342 static void gtk_window_check_resize (GtkContainer *container);
343 static gint gtk_window_focus (GtkWidget *widget,
344 GtkDirectionType direction);
345 static void gtk_window_move_focus (GtkWidget *widget,
346 GtkDirectionType dir);
347 static void gtk_window_real_set_focus (GtkWindow *window,
349 static void gtk_window_direction_changed (GtkWidget *widget,
350 GtkTextDirection prev_dir);
351 static void gtk_window_state_changed (GtkWidget *widget,
352 GtkStateType previous_state);
354 static void gtk_window_real_activate_default (GtkWindow *window);
355 static void gtk_window_real_activate_focus (GtkWindow *window);
356 static void gtk_window_keys_changed (GtkWindow *window);
357 static gint gtk_window_draw (GtkWidget *widget,
359 static void gtk_window_unset_transient_for (GtkWindow *window);
360 static void gtk_window_transient_parent_realized (GtkWidget *parent,
362 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
365 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
367 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
370 static void gtk_window_move_resize (GtkWindow *window);
371 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
373 GdkGeometry *geometry_b,
375 static void gtk_window_constrain_size (GtkWindow *window,
376 GdkGeometry *geometry,
382 static void gtk_window_constrain_position (GtkWindow *window,
387 static void gtk_window_compute_hints (GtkWindow *window,
388 GdkGeometry *new_geometry,
390 static void gtk_window_compute_configure_request (GtkWindow *window,
391 GdkRectangle *request,
392 GdkGeometry *geometry,
395 static void gtk_window_set_default_size_internal (GtkWindow *window,
396 gboolean change_width,
398 gboolean change_height,
400 gboolean is_geometry);
402 static void update_themed_icon (GtkIconTheme *theme,
404 static GList *icon_list_from_theme (GtkWidget *widget,
406 static void gtk_window_realize_icon (GtkWindow *window);
407 static void gtk_window_unrealize_icon (GtkWindow *window);
408 static void resize_grip_create_window (GtkWindow *window);
409 static void resize_grip_destroy_window (GtkWindow *window);
410 static void update_grip_visibility (GtkWindow *window);
412 static void gtk_window_notify_keys_changed (GtkWindow *window);
413 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
414 static void gtk_window_free_key_hash (GtkWindow *window);
415 static void gtk_window_on_composited_changed (GdkScreen *screen,
418 static GSList *toplevel_list = NULL;
419 static guint window_signals[LAST_SIGNAL] = { 0 };
420 static GList *default_icon_list = NULL;
421 static gchar *default_icon_name = NULL;
422 static guint default_icon_serial = 0;
423 static gboolean disable_startup_notification = FALSE;
424 static gboolean sent_startup_notification = FALSE;
426 static GQuark quark_gtk_embedded = 0;
427 static GQuark quark_gtk_window_key_hash = 0;
428 static GQuark quark_gtk_window_icon_info = 0;
429 static GQuark quark_gtk_buildable_accels = 0;
431 static GtkBuildableIface *parent_buildable_iface;
433 static void gtk_window_set_property (GObject *object,
437 static void gtk_window_get_property (GObject *object,
443 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
444 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
447 const GValue *value);
448 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
449 GtkBuilder *builder);
450 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
453 const gchar *tagname,
454 GMarkupParser *parser,
456 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
459 const gchar *tagname,
463 static void gtk_window_get_preferred_width (GtkWidget *widget,
466 static void gtk_window_get_preferred_height (GtkWidget *widget,
470 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
471 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
472 gtk_window_buildable_interface_init))
475 add_tab_bindings (GtkBindingSet *binding_set,
476 GdkModifierType modifiers,
477 GtkDirectionType direction)
479 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
481 GTK_TYPE_DIRECTION_TYPE, direction);
482 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
484 GTK_TYPE_DIRECTION_TYPE, direction);
488 add_arrow_bindings (GtkBindingSet *binding_set,
490 GtkDirectionType direction)
492 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
494 gtk_binding_entry_add_signal (binding_set, keysym, 0,
496 GTK_TYPE_DIRECTION_TYPE, direction);
497 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
499 GTK_TYPE_DIRECTION_TYPE, direction);
500 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
502 GTK_TYPE_DIRECTION_TYPE, direction);
503 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
505 GTK_TYPE_DIRECTION_TYPE, direction);
509 extract_time_from_startup_id (const gchar* startup_id)
511 gchar *timestr = g_strrstr (startup_id, "_TIME");
512 guint32 retval = GDK_CURRENT_TIME;
519 /* Skip past the "_TIME" part */
524 timestamp = g_ascii_strtoull (timestr, &end, 0);
525 if (errno == 0 && end != timestr)
533 startup_id_is_fake (const gchar* startup_id)
535 return strncmp (startup_id, "_TIME", 5) == 0;
539 gtk_window_class_init (GtkWindowClass *klass)
541 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
542 GtkWidgetClass *widget_class;
543 GtkContainerClass *container_class;
544 GtkBindingSet *binding_set;
546 widget_class = (GtkWidgetClass*) klass;
547 container_class = (GtkContainerClass*) klass;
549 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
550 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
551 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
552 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
554 gobject_class->dispose = gtk_window_dispose;
555 gobject_class->finalize = gtk_window_finalize;
557 gobject_class->set_property = gtk_window_set_property;
558 gobject_class->get_property = gtk_window_get_property;
560 widget_class->destroy = gtk_window_destroy;
561 widget_class->show = gtk_window_show;
562 widget_class->hide = gtk_window_hide;
563 widget_class->map = gtk_window_map;
564 widget_class->map_event = gtk_window_map_event;
565 widget_class->unmap = gtk_window_unmap;
566 widget_class->realize = gtk_window_realize;
567 widget_class->unrealize = gtk_window_unrealize;
568 widget_class->size_allocate = gtk_window_size_allocate;
569 widget_class->configure_event = gtk_window_configure_event;
570 widget_class->key_press_event = gtk_window_key_press_event;
571 widget_class->key_release_event = gtk_window_key_release_event;
572 widget_class->enter_notify_event = gtk_window_enter_notify_event;
573 widget_class->leave_notify_event = gtk_window_leave_notify_event;
574 widget_class->focus_in_event = gtk_window_focus_in_event;
575 widget_class->button_press_event = gtk_window_button_press_event;
576 widget_class->focus_out_event = gtk_window_focus_out_event;
577 widget_class->client_event = gtk_window_client_event;
578 widget_class->focus = gtk_window_focus;
579 widget_class->move_focus = gtk_window_move_focus;
580 widget_class->draw = gtk_window_draw;
581 widget_class->get_preferred_width = gtk_window_get_preferred_width;
582 widget_class->get_preferred_height = gtk_window_get_preferred_height;
583 widget_class->window_state_event = gtk_window_state_event;
584 widget_class->direction_changed = gtk_window_direction_changed;
585 widget_class->state_changed = gtk_window_state_changed;
586 widget_class->style_updated = gtk_window_style_updated;
588 container_class->check_resize = gtk_window_check_resize;
590 klass->set_focus = gtk_window_real_set_focus;
592 klass->activate_default = gtk_window_real_activate_default;
593 klass->activate_focus = gtk_window_real_activate_focus;
594 klass->keys_changed = gtk_window_keys_changed;
596 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
599 g_object_class_install_property (gobject_class,
601 g_param_spec_enum ("type",
603 P_("The type of the window"),
604 GTK_TYPE_WINDOW_TYPE,
606 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
608 g_object_class_install_property (gobject_class,
610 g_param_spec_string ("title",
612 P_("The title of the window"),
614 GTK_PARAM_READWRITE));
616 g_object_class_install_property (gobject_class,
618 g_param_spec_string ("role",
620 P_("Unique identifier for the window to be used when restoring a session"),
622 GTK_PARAM_READWRITE));
625 * GtkWindow:startup-id:
627 * The :startup-id is a write-only property for setting window's
628 * startup notification identifier. See gtk_window_set_startup_id()
633 g_object_class_install_property (gobject_class,
635 g_param_spec_string ("startup-id",
637 P_("Unique startup identifier for the window used by startup-notification"),
639 GTK_PARAM_WRITABLE));
641 g_object_class_install_property (gobject_class,
643 g_param_spec_boolean ("resizable",
645 P_("If TRUE, users can resize the window"),
647 GTK_PARAM_READWRITE));
649 g_object_class_install_property (gobject_class,
651 g_param_spec_boolean ("modal",
653 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
655 GTK_PARAM_READWRITE));
657 g_object_class_install_property (gobject_class,
659 g_param_spec_enum ("window-position",
660 P_("Window Position"),
661 P_("The initial position of the window"),
662 GTK_TYPE_WINDOW_POSITION,
664 GTK_PARAM_READWRITE));
666 g_object_class_install_property (gobject_class,
668 g_param_spec_int ("default-width",
670 P_("The default width of the window, used when initially showing the window"),
674 GTK_PARAM_READWRITE));
676 g_object_class_install_property (gobject_class,
678 g_param_spec_int ("default-height",
679 P_("Default Height"),
680 P_("The default height of the window, used when initially showing the window"),
684 GTK_PARAM_READWRITE));
686 g_object_class_install_property (gobject_class,
687 PROP_DESTROY_WITH_PARENT,
688 g_param_spec_boolean ("destroy-with-parent",
689 P_("Destroy with Parent"),
690 P_("If this window should be destroyed when the parent is destroyed"),
692 GTK_PARAM_READWRITE));
694 g_object_class_install_property (gobject_class,
696 g_param_spec_object ("icon",
698 P_("Icon for this window"),
700 GTK_PARAM_READWRITE));
701 g_object_class_install_property (gobject_class,
702 PROP_MNEMONICS_VISIBLE,
703 g_param_spec_boolean ("mnemonics-visible",
704 P_("Mnemonics Visible"),
705 P_("Whether mnemonics are currently visible in this window"),
707 GTK_PARAM_READWRITE));
710 * GtkWindow:icon-name:
712 * The :icon-name property specifies the name of the themed icon to
713 * use as the window icon. See #GtkIconTheme for more details.
717 g_object_class_install_property (gobject_class,
719 g_param_spec_string ("icon-name",
721 P_("Name of the themed icon for this window"),
723 GTK_PARAM_READWRITE));
725 g_object_class_install_property (gobject_class,
727 g_param_spec_object ("screen",
729 P_("The screen where this window will be displayed"),
731 GTK_PARAM_READWRITE));
733 g_object_class_install_property (gobject_class,
735 g_param_spec_boolean ("is-active",
737 P_("Whether the toplevel is the current active window"),
739 GTK_PARAM_READABLE));
741 g_object_class_install_property (gobject_class,
742 PROP_HAS_TOPLEVEL_FOCUS,
743 g_param_spec_boolean ("has-toplevel-focus",
744 P_("Focus in Toplevel"),
745 P_("Whether the input focus is within this GtkWindow"),
747 GTK_PARAM_READABLE));
749 g_object_class_install_property (gobject_class,
751 g_param_spec_enum ("type-hint",
753 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
754 GDK_TYPE_WINDOW_TYPE_HINT,
755 GDK_WINDOW_TYPE_HINT_NORMAL,
756 GTK_PARAM_READWRITE));
758 g_object_class_install_property (gobject_class,
759 PROP_SKIP_TASKBAR_HINT,
760 g_param_spec_boolean ("skip-taskbar-hint",
762 P_("TRUE if the window should not be in the task bar."),
764 GTK_PARAM_READWRITE));
766 g_object_class_install_property (gobject_class,
767 PROP_SKIP_PAGER_HINT,
768 g_param_spec_boolean ("skip-pager-hint",
770 P_("TRUE if the window should not be in the pager."),
772 GTK_PARAM_READWRITE));
774 g_object_class_install_property (gobject_class,
776 g_param_spec_boolean ("urgency-hint",
778 P_("TRUE if the window should be brought to the user's attention."),
780 GTK_PARAM_READWRITE));
783 * GtkWindow:accept-focus:
785 * Whether the window should receive the input focus.
789 g_object_class_install_property (gobject_class,
791 g_param_spec_boolean ("accept-focus",
793 P_("TRUE if the window should receive the input focus."),
795 GTK_PARAM_READWRITE));
798 * GtkWindow:focus-on-map:
800 * Whether the window should receive the input focus when mapped.
804 g_object_class_install_property (gobject_class,
806 g_param_spec_boolean ("focus-on-map",
808 P_("TRUE if the window should receive the input focus when mapped."),
810 GTK_PARAM_READWRITE));
813 * GtkWindow:decorated:
815 * Whether the window should be decorated by the window manager.
819 g_object_class_install_property (gobject_class,
821 g_param_spec_boolean ("decorated",
823 P_("Whether the window should be decorated by the window manager"),
825 GTK_PARAM_READWRITE));
828 * GtkWindow:deletable:
830 * Whether the window frame should have a close button.
834 g_object_class_install_property (gobject_class,
836 g_param_spec_boolean ("deletable",
838 P_("Whether the window frame should have a close button"),
840 GTK_PARAM_READWRITE));
843 * GtkWindow:has-resize-grip
845 * Whether the window has a corner resize grip.
847 * Note that the resize grip is only shown if the window is
848 * actually resizable and not maximized. Use
849 * #GtkWindow:resize-grip-visible to find out if the resize
850 * grip is currently shown.
854 g_object_class_install_property (gobject_class,
855 PROP_HAS_RESIZE_GRIP,
856 g_param_spec_boolean ("has-resize-grip",
858 P_("Specifies whether the window should have a resize grip"),
860 GTK_PARAM_READWRITE));
863 * GtkWindow: resize-grip-visible:
865 * Whether a corner resize grip is currently shown.
869 g_object_class_install_property (gobject_class,
870 PROP_RESIZE_GRIP_VISIBLE,
871 g_param_spec_boolean ("resize-grip-visible",
872 P_("Resize grip is visible"),
873 P_("Specifies whether the window's resize grip is visible."),
875 GTK_PARAM_READABLE));
881 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
882 * more details about window gravity.
886 g_object_class_install_property (gobject_class,
888 g_param_spec_enum ("gravity",
890 P_("The window gravity of the window"),
892 GDK_GRAVITY_NORTH_WEST,
893 GTK_PARAM_READWRITE));
897 * GtkWindow:transient-for:
899 * The transient parent of the window. See gtk_window_set_transient_for() for
900 * more details about transient windows.
904 g_object_class_install_property (gobject_class,
906 g_param_spec_object ("transient-for",
907 P_("Transient for Window"),
908 P_("The transient parent of the dialog"),
910 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
915 * The requested opacity of the window. See gtk_window_set_opacity() for
916 * more details about window opacity.
920 g_object_class_install_property (gobject_class,
922 g_param_spec_double ("opacity",
923 P_("Opacity for Window"),
924 P_("The opacity of the window, from 0 to 1"),
928 GTK_PARAM_READWRITE));
932 gtk_widget_class_install_style_property (widget_class,
933 g_param_spec_int ("resize-grip-width",
934 P_("Width of resize grip"),
935 P_("Width of resize grip"),
936 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
938 gtk_widget_class_install_style_property (widget_class,
939 g_param_spec_int ("resize-grip-height",
940 P_("Height of resize grip"),
941 P_("Height of resize grip"),
942 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
948 * GtkWindow:application:
950 * The #GtkApplication associated with the window.
952 * The application will be kept alive for at least as long as the
957 g_object_class_install_property (gobject_class,
959 g_param_spec_object ("application",
960 P_("GtkApplication"),
961 P_("The GtkApplication for the window"),
962 GTK_TYPE_APPLICATION,
963 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
965 window_signals[SET_FOCUS] =
966 g_signal_new (I_("set-focus"),
967 G_TYPE_FROM_CLASS (gobject_class),
969 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
971 _gtk_marshal_VOID__OBJECT,
976 * GtkWindow::activate-focus:
977 * @window: the window which received the signal
979 * The ::activate-focus signal is a
980 * <link linkend="keybinding-signals">keybinding signal</link>
981 * which gets emitted when the user activates the currently
982 * focused widget of @window.
984 window_signals[ACTIVATE_FOCUS] =
985 g_signal_new (I_("activate-focus"),
986 G_TYPE_FROM_CLASS (gobject_class),
987 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
988 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
990 _gtk_marshal_VOID__VOID,
995 * GtkWindow::activate-default:
996 * @window: the window which received the signal
998 * The ::activate-default signal is a
999 * <link linkend="keybinding-signals">keybinding signal</link>
1000 * which gets emitted when the user activates the default widget
1003 window_signals[ACTIVATE_DEFAULT] =
1004 g_signal_new (I_("activate-default"),
1005 G_TYPE_FROM_CLASS (gobject_class),
1006 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1007 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1009 _gtk_marshal_VOID__VOID,
1014 * GtkWindow::keys-changed:
1015 * @window: the window which received the signal
1017 * The ::keys-changed signal gets emitted when the set of accelerators
1018 * or mnemonics that are associated with @window changes.
1020 window_signals[KEYS_CHANGED] =
1021 g_signal_new (I_("keys-changed"),
1022 G_TYPE_FROM_CLASS (gobject_class),
1024 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1026 _gtk_marshal_VOID__VOID,
1034 binding_set = gtk_binding_set_by_class (klass);
1036 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1037 "activate-focus", 0);
1038 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1039 "activate-focus", 0);
1041 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1042 "activate-default", 0);
1043 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1044 "activate-default", 0);
1045 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1046 "activate-default", 0);
1048 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1049 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1050 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1051 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1053 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1054 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1055 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1056 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1060 gtk_window_init (GtkWindow *window)
1062 GtkWindowPrivate *priv;
1064 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1067 priv = window->priv;
1069 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1070 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1072 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1074 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1077 priv->wmclass_name = g_strdup (g_get_prgname ());
1078 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1079 priv->wm_role = NULL;
1080 priv->geometry_info = NULL;
1081 priv->type = GTK_WINDOW_TOPLEVEL;
1082 priv->focus_widget = NULL;
1083 priv->default_widget = NULL;
1084 priv->configure_request_count = 0;
1085 priv->resizable = TRUE;
1086 priv->configure_notify_received = FALSE;
1087 priv->position = GTK_WIN_POS_NONE;
1088 priv->need_default_size = TRUE;
1089 priv->need_default_position = TRUE;
1090 priv->modal = FALSE;
1091 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1092 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1093 priv->decorated = TRUE;
1094 priv->mnemonic_modifier = GDK_MOD1_MASK;
1095 priv->screen = gdk_screen_get_default ();
1097 priv->accept_focus = TRUE;
1098 priv->focus_on_map = TRUE;
1099 priv->deletable = TRUE;
1100 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1101 priv->opacity = 1.0;
1102 priv->startup_id = NULL;
1103 priv->has_resize_grip = TRUE;
1104 priv->mnemonics_visible = TRUE;
1106 g_object_ref_sink (window);
1107 priv->has_user_ref_count = TRUE;
1108 toplevel_list = g_slist_prepend (toplevel_list, window);
1110 g_signal_connect (priv->screen, "composited-changed",
1111 G_CALLBACK (gtk_window_on_composited_changed), window);
1115 gtk_window_set_property (GObject *object,
1117 const GValue *value,
1120 GtkWindow *window = GTK_WINDOW (object);
1121 GtkWindowPrivate *priv = window->priv;
1126 priv->type = g_value_get_enum (value);
1129 gtk_window_set_title (window, g_value_get_string (value));
1132 gtk_window_set_role (window, g_value_get_string (value));
1134 case PROP_STARTUP_ID:
1135 gtk_window_set_startup_id (window, g_value_get_string (value));
1137 case PROP_RESIZABLE:
1138 gtk_window_set_resizable (window, g_value_get_boolean (value));
1141 gtk_window_set_modal (window, g_value_get_boolean (value));
1144 gtk_window_set_position (window, g_value_get_enum (value));
1146 case PROP_DEFAULT_WIDTH:
1147 gtk_window_set_default_size_internal (window,
1148 TRUE, g_value_get_int (value),
1151 case PROP_DEFAULT_HEIGHT:
1152 gtk_window_set_default_size_internal (window,
1154 TRUE, g_value_get_int (value), FALSE);
1156 case PROP_DESTROY_WITH_PARENT:
1157 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1160 gtk_window_set_icon (window,
1161 g_value_get_object (value));
1163 case PROP_ICON_NAME:
1164 gtk_window_set_icon_name (window, g_value_get_string (value));
1167 gtk_window_set_screen (window, g_value_get_object (value));
1169 case PROP_TYPE_HINT:
1170 gtk_window_set_type_hint (window,
1171 g_value_get_enum (value));
1173 case PROP_SKIP_TASKBAR_HINT:
1174 gtk_window_set_skip_taskbar_hint (window,
1175 g_value_get_boolean (value));
1177 case PROP_SKIP_PAGER_HINT:
1178 gtk_window_set_skip_pager_hint (window,
1179 g_value_get_boolean (value));
1181 case PROP_URGENCY_HINT:
1182 gtk_window_set_urgency_hint (window,
1183 g_value_get_boolean (value));
1185 case PROP_ACCEPT_FOCUS:
1186 gtk_window_set_accept_focus (window,
1187 g_value_get_boolean (value));
1189 case PROP_FOCUS_ON_MAP:
1190 gtk_window_set_focus_on_map (window,
1191 g_value_get_boolean (value));
1193 case PROP_DECORATED:
1194 gtk_window_set_decorated (window, g_value_get_boolean (value));
1196 case PROP_DELETABLE:
1197 gtk_window_set_deletable (window, g_value_get_boolean (value));
1200 gtk_window_set_gravity (window, g_value_get_enum (value));
1202 case PROP_TRANSIENT_FOR:
1203 gtk_window_set_transient_for (window, g_value_get_object (value));
1206 gtk_window_set_opacity (window, g_value_get_double (value));
1208 case PROP_HAS_RESIZE_GRIP:
1209 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1211 case PROP_APPLICATION:
1212 gtk_window_set_application (window, g_value_get_object (value));
1214 case PROP_MNEMONICS_VISIBLE:
1215 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1218 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1224 gtk_window_get_property (GObject *object,
1229 GtkWindow *window = GTK_WINDOW (object);
1230 GtkWindowPrivate *priv = window->priv;
1234 GtkWindowGeometryInfo *info;
1236 g_value_set_enum (value, priv->type);
1239 g_value_set_string (value, priv->wm_role);
1242 g_value_set_string (value, priv->title);
1244 case PROP_RESIZABLE:
1245 g_value_set_boolean (value, priv->resizable);
1248 g_value_set_boolean (value, priv->modal);
1251 g_value_set_enum (value, priv->position);
1253 case PROP_DEFAULT_WIDTH:
1254 info = gtk_window_get_geometry_info (window, FALSE);
1256 g_value_set_int (value, -1);
1258 g_value_set_int (value, info->default_width);
1260 case PROP_DEFAULT_HEIGHT:
1261 info = gtk_window_get_geometry_info (window, FALSE);
1263 g_value_set_int (value, -1);
1265 g_value_set_int (value, info->default_height);
1267 case PROP_DESTROY_WITH_PARENT:
1268 g_value_set_boolean (value, priv->destroy_with_parent);
1271 g_value_set_object (value, gtk_window_get_icon (window));
1273 case PROP_ICON_NAME:
1274 g_value_set_string (value, gtk_window_get_icon_name (window));
1277 g_value_set_object (value, priv->screen);
1279 case PROP_IS_ACTIVE:
1280 g_value_set_boolean (value, priv->is_active);
1282 case PROP_HAS_TOPLEVEL_FOCUS:
1283 g_value_set_boolean (value, priv->has_toplevel_focus);
1285 case PROP_TYPE_HINT:
1286 g_value_set_enum (value, priv->type_hint);
1288 case PROP_SKIP_TASKBAR_HINT:
1289 g_value_set_boolean (value,
1290 gtk_window_get_skip_taskbar_hint (window));
1292 case PROP_SKIP_PAGER_HINT:
1293 g_value_set_boolean (value,
1294 gtk_window_get_skip_pager_hint (window));
1296 case PROP_URGENCY_HINT:
1297 g_value_set_boolean (value,
1298 gtk_window_get_urgency_hint (window));
1300 case PROP_ACCEPT_FOCUS:
1301 g_value_set_boolean (value,
1302 gtk_window_get_accept_focus (window));
1304 case PROP_FOCUS_ON_MAP:
1305 g_value_set_boolean (value,
1306 gtk_window_get_focus_on_map (window));
1308 case PROP_DECORATED:
1309 g_value_set_boolean (value, gtk_window_get_decorated (window));
1311 case PROP_DELETABLE:
1312 g_value_set_boolean (value, gtk_window_get_deletable (window));
1315 g_value_set_enum (value, gtk_window_get_gravity (window));
1317 case PROP_TRANSIENT_FOR:
1318 g_value_set_object (value, gtk_window_get_transient_for (window));
1321 g_value_set_double (value, gtk_window_get_opacity (window));
1323 case PROP_HAS_RESIZE_GRIP:
1324 g_value_set_boolean (value, priv->has_resize_grip);
1326 case PROP_RESIZE_GRIP_VISIBLE:
1327 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1329 case PROP_APPLICATION:
1330 g_value_set_object (value, gtk_window_get_application (window));
1332 case PROP_MNEMONICS_VISIBLE:
1333 g_value_set_boolean (value, priv->mnemonics_visible);
1336 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1342 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1344 parent_buildable_iface = g_type_interface_peek_parent (iface);
1345 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1346 iface->parser_finished = gtk_window_buildable_parser_finished;
1347 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1348 iface->custom_finished = gtk_window_buildable_custom_finished;
1352 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1353 GtkBuilder *builder,
1355 const GValue *value)
1357 GtkWindow *window = GTK_WINDOW (buildable);
1358 GtkWindowPrivate *priv = window->priv;
1360 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1361 priv->builder_visible = TRUE;
1363 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1367 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1368 GtkBuilder *builder)
1370 GtkWindow *window = GTK_WINDOW (buildable);
1371 GtkWindowPrivate *priv = window->priv;
1375 if (priv->builder_visible)
1376 gtk_widget_show (GTK_WIDGET (buildable));
1378 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1379 for (l = accels; l; l = l->next)
1381 object = gtk_builder_get_object (builder, l->data);
1384 g_warning ("Unknown accel group %s specified in window %s",
1385 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1388 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1389 GTK_ACCEL_GROUP (object));
1393 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1395 parent_buildable_iface->parser_finished (buildable, builder);
1401 } GSListSubParserData;
1404 window_start_element (GMarkupParseContext *context,
1405 const gchar *element_name,
1406 const gchar **names,
1407 const gchar **values,
1412 GSListSubParserData *data = (GSListSubParserData*)user_data;
1414 if (strcmp (element_name, "group") == 0)
1416 for (i = 0; names[i]; i++)
1418 if (strcmp (names[i], "name") == 0)
1419 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1422 else if (strcmp (element_name, "accel-groups") == 0)
1425 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1430 static const GMarkupParser window_parser =
1432 window_start_element
1436 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1437 GtkBuilder *builder,
1439 const gchar *tagname,
1440 GMarkupParser *parser,
1443 GSListSubParserData *parser_data;
1445 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1446 tagname, parser, data))
1449 if (strcmp (tagname, "accel-groups") == 0)
1451 parser_data = g_slice_new0 (GSListSubParserData);
1452 parser_data->items = NULL;
1453 parser_data->object = G_OBJECT (buildable);
1455 *parser = window_parser;
1456 *data = parser_data;
1464 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1465 GtkBuilder *builder,
1467 const gchar *tagname,
1470 GSListSubParserData *data;
1472 parent_buildable_iface->custom_finished (buildable, builder, child,
1473 tagname, user_data);
1475 if (strcmp (tagname, "accel-groups") != 0)
1478 data = (GSListSubParserData*)user_data;
1480 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1481 data->items, (GDestroyNotify) g_slist_free);
1483 g_slice_free (GSListSubParserData, data);
1488 * @type: type of window
1490 * Creates a new #GtkWindow, which is a toplevel window that can
1491 * contain other widgets. Nearly always, the type of the window should
1492 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1493 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1494 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1495 * dialogs, though in some other toolkits dialogs are called "popups".
1496 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1497 * On X11, popup windows are not controlled by the <link
1498 * linkend="gtk-X11-arch">window manager</link>.
1500 * If you simply want an undecorated window (no window borders), use
1501 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1503 * Return value: a new #GtkWindow.
1506 gtk_window_new (GtkWindowType type)
1508 GtkWindowPrivate *priv;
1511 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1513 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1514 priv = window->priv;
1518 return GTK_WIDGET (window);
1522 * gtk_window_set_title:
1523 * @window: a #GtkWindow
1524 * @title: title of the window
1526 * Sets the title of the #GtkWindow. The title of a window will be
1527 * displayed in its title bar; on the X Window System, the title bar
1528 * is rendered by the <link linkend="gtk-X11-arch">window
1529 * manager</link>, so exactly how the title appears to users may vary
1530 * according to a user's exact configuration. The title should help a
1531 * user distinguish this window from other windows they may have
1532 * open. A good title might include the application name and current
1533 * document filename, for example.
1537 gtk_window_set_title (GtkWindow *window,
1540 GtkWindowPrivate *priv;
1544 g_return_if_fail (GTK_IS_WINDOW (window));
1546 priv = window->priv;
1547 widget = GTK_WIDGET (window);
1549 new_title = g_strdup (title);
1550 g_free (priv->title);
1551 priv->title = new_title;
1553 if (gtk_widget_get_realized (widget))
1555 gdk_window_set_title (gtk_widget_get_window (widget),
1559 g_object_notify (G_OBJECT (window), "title");
1563 * gtk_window_get_title:
1564 * @window: a #GtkWindow
1566 * Retrieves the title of the window. See gtk_window_set_title().
1568 * Return value: the title of the window, or %NULL if none has
1569 * been set explicitely. The returned string is owned by the widget
1570 * and must not be modified or freed.
1572 G_CONST_RETURN gchar *
1573 gtk_window_get_title (GtkWindow *window)
1575 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1577 return window->priv->title;
1581 * gtk_window_set_wmclass:
1582 * @window: a #GtkWindow
1583 * @wmclass_name: window name hint
1584 * @wmclass_class: window class hint
1586 * Don't use this function. It sets the X Window System "class" and
1587 * "name" hints for a window. According to the ICCCM, you should
1588 * always set these to the same value for all windows in an
1589 * application, and GTK+ sets them to that value by default, so calling
1590 * this function is sort of pointless. However, you may want to call
1591 * gtk_window_set_role() on each window in your application, for the
1592 * benefit of the session manager. Setting the role allows the window
1593 * manager to restore window positions when loading a saved session.
1597 gtk_window_set_wmclass (GtkWindow *window,
1598 const gchar *wmclass_name,
1599 const gchar *wmclass_class)
1601 GtkWindowPrivate *priv;
1603 g_return_if_fail (GTK_IS_WINDOW (window));
1605 priv = window->priv;
1607 g_free (priv->wmclass_name);
1608 priv->wmclass_name = g_strdup (wmclass_name);
1610 g_free (priv->wmclass_class);
1611 priv->wmclass_class = g_strdup (wmclass_class);
1613 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1614 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1618 * gtk_window_set_role:
1619 * @window: a #GtkWindow
1620 * @role: unique identifier for the window to be used when restoring a session
1622 * This function is only useful on X11, not with other GTK+ targets.
1624 * In combination with the window title, the window role allows a
1625 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1626 * same" window when an application is restarted. So for example you
1627 * might set the "toolbox" role on your app's toolbox window, so that
1628 * when the user restarts their session, the window manager can put
1629 * the toolbox back in the same place.
1631 * If a window already has a unique title, you don't need to set the
1632 * role, since the WM can use the title to identify the window when
1633 * restoring the session.
1637 gtk_window_set_role (GtkWindow *window,
1640 GtkWindowPrivate *priv;
1643 g_return_if_fail (GTK_IS_WINDOW (window));
1645 priv = window->priv;
1647 new_role = g_strdup (role);
1648 g_free (priv->wm_role);
1649 priv->wm_role = new_role;
1651 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1652 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1655 g_object_notify (G_OBJECT (window), "role");
1659 * gtk_window_set_startup_id:
1660 * @window: a #GtkWindow
1661 * @startup_id: a string with startup-notification identifier
1663 * Startup notification identifiers are used by desktop environment to
1664 * track application startup, to provide user feedback and other
1665 * features. This function changes the corresponding property on the
1666 * underlying GdkWindow. Normally, startup identifier is managed
1667 * automatically and you should only use this function in special cases
1668 * like transferring focus from other processes. You should use this
1669 * function before calling gtk_window_present() or any equivalent
1670 * function generating a window map event.
1672 * This function is only useful on X11, not with other GTK+ targets.
1677 gtk_window_set_startup_id (GtkWindow *window,
1678 const gchar *startup_id)
1680 GtkWindowPrivate *priv;
1683 g_return_if_fail (GTK_IS_WINDOW (window));
1685 priv = window->priv;
1686 widget = GTK_WIDGET (window);
1688 g_free (priv->startup_id);
1689 priv->startup_id = g_strdup (startup_id);
1691 if (gtk_widget_get_realized (widget))
1693 GdkWindow *gdk_window;
1694 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1696 gdk_window = gtk_widget_get_window (widget);
1698 #ifdef GDK_WINDOWING_X11
1699 if (timestamp != GDK_CURRENT_TIME)
1700 gdk_x11_window_set_user_time (gdk_window, timestamp);
1703 /* Here we differentiate real and "fake" startup notification IDs,
1704 * constructed on purpose just to pass interaction timestamp
1706 if (startup_id_is_fake (priv->startup_id))
1707 gtk_window_present_with_time (window, timestamp);
1710 gdk_window_set_startup_id (gdk_window,
1713 /* If window is mapped, terminate the startup-notification too */
1714 if (gtk_widget_get_mapped (widget) &&
1715 !disable_startup_notification)
1716 gdk_notify_startup_complete_with_id (priv->startup_id);
1720 g_object_notify (G_OBJECT (window), "startup-id");
1724 * gtk_window_get_role:
1725 * @window: a #GtkWindow
1727 * Returns the role of the window. See gtk_window_set_role() for
1728 * further explanation.
1730 * Return value: the role of the window if set, or %NULL. The
1731 * returned is owned by the widget and must not be modified
1734 G_CONST_RETURN gchar *
1735 gtk_window_get_role (GtkWindow *window)
1737 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1739 return window->priv->wm_role;
1743 * gtk_window_set_focus:
1744 * @window: a #GtkWindow
1745 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1746 * any focus widget for the toplevel window.
1748 * If @focus is not the current focus widget, and is focusable, sets
1749 * it as the focus widget for the window. If @focus is %NULL, unsets
1750 * the focus widget for this window. To set the focus to a particular
1751 * widget in the toplevel, it is usually more convenient to use
1752 * gtk_widget_grab_focus() instead of this function.
1755 gtk_window_set_focus (GtkWindow *window,
1758 GtkWindowPrivate *priv;
1761 g_return_if_fail (GTK_IS_WINDOW (window));
1763 priv = window->priv;
1767 g_return_if_fail (GTK_IS_WIDGET (focus));
1768 g_return_if_fail (gtk_widget_get_can_focus (focus));
1772 gtk_widget_grab_focus (focus);
1775 /* Clear the existing focus chain, so that when we focus into
1776 * the window again, we start at the beginnning.
1778 GtkWidget *widget = priv->focus_widget;
1781 while ((parent = gtk_widget_get_parent (widget)))
1784 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1788 _gtk_window_internal_set_focus (window, NULL);
1793 _gtk_window_internal_set_focus (GtkWindow *window,
1796 GtkWindowPrivate *priv;
1798 g_return_if_fail (GTK_IS_WINDOW (window));
1800 priv = window->priv;
1802 if ((priv->focus_widget != focus) ||
1803 (focus && !gtk_widget_has_focus (focus)))
1804 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1808 * gtk_window_set_default:
1809 * @window: a #GtkWindow
1810 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1811 * default widget for the toplevel.
1813 * The default widget is the widget that's activated when the user
1814 * presses Enter in a dialog (for example). This function sets or
1815 * unsets the default widget for a #GtkWindow about. When setting
1816 * (rather than unsetting) the default widget it's generally easier to
1817 * call gtk_widget_grab_focus() on the widget. Before making a widget
1818 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1819 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1822 gtk_window_set_default (GtkWindow *window,
1823 GtkWidget *default_widget)
1825 GtkWindowPrivate *priv;
1827 g_return_if_fail (GTK_IS_WINDOW (window));
1829 priv = window->priv;
1832 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1834 if (priv->default_widget != default_widget)
1836 GtkWidget *old_default_widget = NULL;
1839 g_object_ref (default_widget);
1841 if (priv->default_widget)
1843 old_default_widget = priv->default_widget;
1845 if (priv->focus_widget != priv->default_widget ||
1846 !gtk_widget_get_receives_default (priv->default_widget))
1847 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1849 gtk_widget_queue_draw (priv->default_widget);
1852 priv->default_widget = default_widget;
1854 if (priv->default_widget)
1856 if (priv->focus_widget == NULL ||
1857 !gtk_widget_get_receives_default (priv->focus_widget))
1858 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1860 gtk_widget_queue_draw (priv->default_widget);
1863 if (old_default_widget)
1864 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1868 g_object_notify (G_OBJECT (default_widget), "has-default");
1869 g_object_unref (default_widget);
1875 * gtk_window_get_default_widget:
1876 * @window: a #GtkWindow
1878 * Returns the default widget for @window. See gtk_window_set_default()
1881 * Returns: (transfer none): the default widget, or %NULL if there is none.
1886 gtk_window_get_default_widget (GtkWindow *window)
1888 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1890 return window->priv->default_widget;
1894 handle_keys_changed (gpointer data)
1896 GtkWindow *window = GTK_WINDOW (data);
1897 GtkWindowPrivate *priv = window->priv;
1899 if (priv->keys_changed_handler)
1901 g_source_remove (priv->keys_changed_handler);
1902 priv->keys_changed_handler = 0;
1905 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1911 gtk_window_notify_keys_changed (GtkWindow *window)
1913 GtkWindowPrivate *priv = window->priv;
1915 if (!priv->keys_changed_handler)
1916 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1920 * gtk_window_add_accel_group:
1921 * @window: window to attach accelerator group to
1922 * @accel_group: a #GtkAccelGroup
1924 * Associate @accel_group with @window, such that calling
1925 * gtk_accel_groups_activate() on @window will activate accelerators
1929 gtk_window_add_accel_group (GtkWindow *window,
1930 GtkAccelGroup *accel_group)
1932 g_return_if_fail (GTK_IS_WINDOW (window));
1933 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1935 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1936 g_signal_connect_object (accel_group, "accel-changed",
1937 G_CALLBACK (gtk_window_notify_keys_changed),
1938 window, G_CONNECT_SWAPPED);
1939 gtk_window_notify_keys_changed (window);
1943 * gtk_window_remove_accel_group:
1944 * @window: a #GtkWindow
1945 * @accel_group: a #GtkAccelGroup
1947 * Reverses the effects of gtk_window_add_accel_group().
1950 gtk_window_remove_accel_group (GtkWindow *window,
1951 GtkAccelGroup *accel_group)
1953 g_return_if_fail (GTK_IS_WINDOW (window));
1954 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1956 g_signal_handlers_disconnect_by_func (accel_group,
1957 gtk_window_notify_keys_changed,
1959 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1960 gtk_window_notify_keys_changed (window);
1963 static GtkMnemonicHash *
1964 gtk_window_get_mnemonic_hash (GtkWindow *window,
1967 GtkWindowPrivate *private = window->priv;
1969 if (!private->mnemonic_hash && create)
1970 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1972 return private->mnemonic_hash;
1976 * gtk_window_add_mnemonic:
1977 * @window: a #GtkWindow
1978 * @keyval: the mnemonic
1979 * @target: the widget that gets activated by the mnemonic
1981 * Adds a mnemonic to this window.
1984 gtk_window_add_mnemonic (GtkWindow *window,
1988 g_return_if_fail (GTK_IS_WINDOW (window));
1989 g_return_if_fail (GTK_IS_WIDGET (target));
1991 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1993 gtk_window_notify_keys_changed (window);
1997 * gtk_window_remove_mnemonic:
1998 * @window: a #GtkWindow
1999 * @keyval: the mnemonic
2000 * @target: the widget that gets activated by the mnemonic
2002 * Removes a mnemonic from this window.
2005 gtk_window_remove_mnemonic (GtkWindow *window,
2009 g_return_if_fail (GTK_IS_WINDOW (window));
2010 g_return_if_fail (GTK_IS_WIDGET (target));
2012 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2014 gtk_window_notify_keys_changed (window);
2018 * gtk_window_mnemonic_activate:
2019 * @window: a #GtkWindow
2020 * @keyval: the mnemonic
2021 * @modifier: the modifiers
2022 * @returns: %TRUE if the activation is done.
2024 * Activates the targets associated with the mnemonic.
2027 gtk_window_mnemonic_activate (GtkWindow *window,
2029 GdkModifierType modifier)
2031 GtkWindowPrivate *priv;
2033 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2035 priv = window->priv;
2037 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2039 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2041 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2048 * gtk_window_set_mnemonic_modifier:
2049 * @window: a #GtkWindow
2050 * @modifier: the modifier mask used to activate
2051 * mnemonics on this window.
2053 * Sets the mnemonic modifier for this window.
2056 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2057 GdkModifierType modifier)
2059 GtkWindowPrivate *priv;
2061 g_return_if_fail (GTK_IS_WINDOW (window));
2062 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2064 priv = window->priv;
2066 priv->mnemonic_modifier = modifier;
2067 gtk_window_notify_keys_changed (window);
2071 * gtk_window_get_mnemonic_modifier:
2072 * @window: a #GtkWindow
2074 * Returns the mnemonic modifier for this window. See
2075 * gtk_window_set_mnemonic_modifier().
2077 * Return value: the modifier mask used to activate
2078 * mnemonics on this window.
2081 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2083 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2085 return window->priv->mnemonic_modifier;
2089 * gtk_window_set_position:
2090 * @window: a #GtkWindow.
2091 * @position: a position constraint.
2093 * Sets a position constraint for this window. If the old or new
2094 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2095 * the window to be repositioned to satisfy the new constraint.
2098 gtk_window_set_position (GtkWindow *window,
2099 GtkWindowPosition position)
2101 GtkWindowPrivate *priv;
2103 g_return_if_fail (GTK_IS_WINDOW (window));
2105 priv = window->priv;
2107 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2108 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2110 GtkWindowGeometryInfo *info;
2112 info = gtk_window_get_geometry_info (window, TRUE);
2114 /* this flag causes us to re-request the CENTER_ALWAYS
2115 * constraint in gtk_window_move_resize(), see
2116 * comment in that function.
2118 info->position_constraints_changed = TRUE;
2120 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2123 priv->position = position;
2125 g_object_notify (G_OBJECT (window), "window-position");
2129 * gtk_window_activate_focus:
2130 * @window: a #GtkWindow
2132 * Activates the current focused widget within the window.
2134 * Return value: %TRUE if a widget got activated.
2137 gtk_window_activate_focus (GtkWindow *window)
2139 GtkWindowPrivate *priv;
2141 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2143 priv = window->priv;
2145 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2146 return gtk_widget_activate (priv->focus_widget);
2152 * gtk_window_get_focus:
2153 * @window: a #GtkWindow
2155 * Retrieves the current focused widget within the window.
2156 * Note that this is the widget that would have the focus
2157 * if the toplevel window focused; if the toplevel window
2158 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2159 * not be %TRUE for the widget.
2161 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2164 gtk_window_get_focus (GtkWindow *window)
2166 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2168 return window->priv->focus_widget;
2172 * gtk_window_activate_default:
2173 * @window: a #GtkWindow
2175 * Activates the default widget for the window, unless the current
2176 * focused widget has been configured to receive the default action
2177 * (see gtk_widget_set_receives_default()), in which case the
2178 * focused widget is activated.
2180 * Return value: %TRUE if a widget got activated.
2183 gtk_window_activate_default (GtkWindow *window)
2185 GtkWindowPrivate *priv;
2187 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2189 priv = window->priv;
2191 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2192 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2193 return gtk_widget_activate (priv->default_widget);
2194 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2195 return gtk_widget_activate (priv->focus_widget);
2201 * gtk_window_set_modal:
2202 * @window: a #GtkWindow
2203 * @modal: whether the window is modal
2205 * Sets a window modal or non-modal. Modal windows prevent interaction
2206 * with other windows in the same application. To keep modal dialogs
2207 * on top of main application windows, use
2208 * gtk_window_set_transient_for() to make the dialog transient for the
2209 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2210 * will then disallow lowering the dialog below the parent.
2215 gtk_window_set_modal (GtkWindow *window,
2218 GtkWindowPrivate *priv;
2221 g_return_if_fail (GTK_IS_WINDOW (window));
2223 priv = window->priv;
2225 modal = modal != FALSE;
2226 if (priv->modal == modal)
2229 priv->modal = modal;
2230 widget = GTK_WIDGET (window);
2232 /* adjust desired modality state */
2233 if (gtk_widget_get_realized (widget))
2236 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2238 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2241 if (gtk_widget_get_visible (widget))
2244 gtk_grab_add (widget);
2246 gtk_grab_remove (widget);
2249 g_object_notify (G_OBJECT (window), "modal");
2253 * gtk_window_get_modal:
2254 * @window: a #GtkWindow
2256 * Returns whether the window is modal. See gtk_window_set_modal().
2258 * Return value: %TRUE if the window is set to be modal and
2259 * establishes a grab when shown
2262 gtk_window_get_modal (GtkWindow *window)
2264 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2266 return window->priv->modal;
2270 * gtk_window_list_toplevels:
2272 * Returns a list of all existing toplevel windows. The widgets
2273 * in the list are not individually referenced. If you want
2274 * to iterate through the list and perform actions involving
2275 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2276 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2277 * then unref all the widgets afterwards.
2279 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2282 gtk_window_list_toplevels (void)
2287 for (slist = toplevel_list; slist; slist = slist->next)
2288 list = g_list_prepend (list, slist->data);
2294 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2296 GList *embedded_windows;
2298 g_return_if_fail (GTK_IS_WINDOW (window));
2300 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2301 if (embedded_windows)
2302 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2303 embedded_windows = g_list_prepend (embedded_windows,
2304 GUINT_TO_POINTER (xid));
2306 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2309 (GDestroyNotify) g_list_free : NULL);
2313 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2315 GList *embedded_windows;
2318 g_return_if_fail (GTK_IS_WINDOW (window));
2320 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2321 if (embedded_windows)
2322 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2324 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2327 embedded_windows = g_list_remove_link (embedded_windows, node);
2328 g_list_free_1 (node);
2331 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2334 (GDestroyNotify) g_list_free : NULL);
2338 gtk_window_dispose (GObject *object)
2340 GtkWindow *window = GTK_WINDOW (object);
2342 gtk_window_set_focus (window, NULL);
2343 gtk_window_set_default (window, NULL);
2345 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2349 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2351 gtk_widget_destroy (GTK_WIDGET (child));
2355 connect_parent_destroyed (GtkWindow *window)
2357 GtkWindowPrivate *priv = window->priv;
2359 if (priv->transient_parent)
2361 g_signal_connect (priv->transient_parent,
2363 G_CALLBACK (parent_destroyed_callback),
2369 disconnect_parent_destroyed (GtkWindow *window)
2371 GtkWindowPrivate *priv = window->priv;
2373 if (priv->transient_parent)
2375 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2376 parent_destroyed_callback,
2382 gtk_window_transient_parent_realized (GtkWidget *parent,
2385 if (gtk_widget_get_realized (window))
2386 gdk_window_set_transient_for (gtk_widget_get_window (window),
2387 gtk_widget_get_window (parent));
2391 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2394 if (gtk_widget_get_realized (window))
2395 gdk_property_delete (gtk_widget_get_window (window),
2396 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2400 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2404 gtk_window_set_screen (window, parent->priv->screen);
2408 gtk_window_unset_transient_for (GtkWindow *window)
2410 GtkWindowPrivate *priv = window->priv;
2412 if (priv->transient_parent)
2414 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2415 gtk_window_transient_parent_realized,
2417 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2418 gtk_window_transient_parent_unrealized,
2420 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2421 gtk_window_transient_parent_screen_changed,
2423 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2424 gtk_widget_destroyed,
2425 &priv->transient_parent);
2427 if (priv->destroy_with_parent)
2428 disconnect_parent_destroyed (window);
2430 priv->transient_parent = NULL;
2432 if (priv->transient_parent_group)
2434 priv->transient_parent_group = FALSE;
2435 gtk_window_group_remove_window (priv->group,
2442 * gtk_window_set_transient_for:
2443 * @window: a #GtkWindow
2444 * @parent: (allow-none): parent window, or %NULL
2446 * Dialog windows should be set transient for the main application
2447 * window they were spawned from. This allows <link
2448 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2449 * dialog on top of the main window, or center the dialog over the
2450 * main window. gtk_dialog_new_with_buttons() and other convenience
2451 * functions in GTK+ will sometimes call
2452 * gtk_window_set_transient_for() on your behalf.
2454 * Passing %NULL for @parent unsets the current transient window.
2456 * On Windows, this function puts the child window on top of the parent,
2457 * much as the window manager would have done on X.
2460 gtk_window_set_transient_for (GtkWindow *window,
2463 GtkWindowPrivate *priv;
2465 g_return_if_fail (GTK_IS_WINDOW (window));
2466 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2467 g_return_if_fail (window != parent);
2469 priv = window->priv;
2471 if (priv->transient_parent)
2473 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2474 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2475 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2476 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2477 GTK_WIDGET (window));
2479 gtk_window_unset_transient_for (window);
2482 priv->transient_parent = parent;
2486 g_signal_connect (parent, "destroy",
2487 G_CALLBACK (gtk_widget_destroyed),
2488 &priv->transient_parent);
2489 g_signal_connect (parent, "realize",
2490 G_CALLBACK (gtk_window_transient_parent_realized),
2492 g_signal_connect (parent, "unrealize",
2493 G_CALLBACK (gtk_window_transient_parent_unrealized),
2495 g_signal_connect (parent, "notify::screen",
2496 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2499 gtk_window_set_screen (window, parent->priv->screen);
2501 if (priv->destroy_with_parent)
2502 connect_parent_destroyed (window);
2504 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2505 gtk_widget_get_realized (GTK_WIDGET (parent)))
2506 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2507 GTK_WIDGET (window));
2509 if (parent->priv->group)
2511 gtk_window_group_add_window (parent->priv->group, window);
2512 priv->transient_parent_group = TRUE;
2518 * gtk_window_get_transient_for:
2519 * @window: a #GtkWindow
2521 * Fetches the transient parent for this window. See
2522 * gtk_window_set_transient_for().
2524 * Return value: (transfer none): the transient parent for this window, or %NULL
2525 * if no transient parent has been set.
2528 gtk_window_get_transient_for (GtkWindow *window)
2530 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2532 return window->priv->transient_parent;
2536 * gtk_window_set_opacity:
2537 * @window: a #GtkWindow
2538 * @opacity: desired opacity, between 0 and 1
2540 * Request the windowing system to make @window partially transparent,
2541 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2542 * of the opacity parameter are clamped to the [0,1] range.) On X11
2543 * this has any effect only on X screens with a compositing manager
2544 * running. See gtk_widget_is_composited(). On Windows it should work
2547 * Note that setting a window's opacity after the window has been
2548 * shown causes it to flicker once on Windows.
2553 gtk_window_set_opacity (GtkWindow *window,
2556 GtkWindowPrivate *priv;
2558 g_return_if_fail (GTK_IS_WINDOW (window));
2560 priv = window->priv;
2564 else if (opacity > 1.0)
2567 priv->opacity_set = TRUE;
2568 priv->opacity = opacity;
2570 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2571 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2576 * gtk_window_get_opacity:
2577 * @window: a #GtkWindow
2579 * Fetches the requested opacity for this window. See
2580 * gtk_window_set_opacity().
2582 * Return value: the requested opacity for this window.
2587 gtk_window_get_opacity (GtkWindow *window)
2589 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2591 return window->priv->opacity;
2595 * gtk_window_get_application:
2596 * @window: a #GtkWindow
2598 * Gets the #GtkApplication associated with the window (if any).
2600 * Return value: a #GtkApplication, or %NULL
2605 gtk_window_get_application (GtkWindow *window)
2607 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2609 return window->priv->application;
2613 gtk_window_release_application (GtkWindow *window)
2615 if (window->priv->application)
2617 GtkApplication *application;
2619 /* steal reference into temp variable */
2620 application = window->priv->application;
2621 window->priv->application = NULL;
2623 gtk_application_remove_window (application, window);
2624 g_object_unref (application);
2629 * gtk_window_set_application:
2630 * @window: a #GtkWindow
2631 * @application: a #GtkApplication, or %NULL
2633 * Sets or unsets the #GtkApplication associated with the window.
2635 * The application will be kept alive for at least as long as the window
2641 gtk_window_set_application (GtkWindow *window,
2642 GtkApplication *application)
2644 GtkWindowPrivate *priv;
2646 g_return_if_fail (GTK_IS_WINDOW (window));
2648 priv = window->priv;
2649 if (priv->application != application)
2651 gtk_window_release_application (window);
2653 priv->application = application;
2655 if (priv->application != NULL)
2657 g_object_ref (priv->application);
2659 gtk_application_add_window (priv->application, window);
2662 g_object_notify (G_OBJECT (window), "application");
2667 * gtk_window_set_type_hint:
2668 * @window: a #GtkWindow
2669 * @hint: the window type
2671 * By setting the type hint for the window, you allow the window
2672 * manager to decorate and handle the window in a way which is
2673 * suitable to the function of the window in your application.
2675 * This function should be called before the window becomes visible.
2677 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2678 * will sometimes call gtk_window_set_type_hint() on your behalf.
2682 gtk_window_set_type_hint (GtkWindow *window,
2683 GdkWindowTypeHint hint)
2685 GtkWindowPrivate *priv;
2687 g_return_if_fail (GTK_IS_WINDOW (window));
2688 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2690 priv = window->priv;
2692 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2693 priv->gdk_type_hint = hint;
2695 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2697 priv->reset_type_hint = TRUE;
2698 priv->type_hint = hint;
2702 * gtk_window_get_type_hint:
2703 * @window: a #GtkWindow
2705 * Gets the type hint for this window. See gtk_window_set_type_hint().
2707 * Return value: the type hint for @window.
2710 gtk_window_get_type_hint (GtkWindow *window)
2712 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2714 return window->priv->type_hint;
2718 * gtk_window_set_skip_taskbar_hint:
2719 * @window: a #GtkWindow
2720 * @setting: %TRUE to keep this window from appearing in the task bar
2722 * Windows may set a hint asking the desktop environment not to display
2723 * the window in the task bar. This function sets this hint.
2728 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2731 GtkWindowPrivate *priv;
2733 g_return_if_fail (GTK_IS_WINDOW (window));
2735 priv = window->priv;
2737 setting = setting != FALSE;
2739 if (priv->skips_taskbar != setting)
2741 priv->skips_taskbar = setting;
2742 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2743 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2744 priv->skips_taskbar);
2745 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2750 * gtk_window_get_skip_taskbar_hint:
2751 * @window: a #GtkWindow
2753 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2755 * Return value: %TRUE if window shouldn't be in taskbar
2760 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2762 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2764 return window->priv->skips_taskbar;
2768 * gtk_window_set_skip_pager_hint:
2769 * @window: a #GtkWindow
2770 * @setting: %TRUE to keep this window from appearing in the pager
2772 * Windows may set a hint asking the desktop environment not to display
2773 * the window in the pager. This function sets this hint.
2774 * (A "pager" is any desktop navigation tool such as a workspace
2775 * switcher that displays a thumbnail representation of the windows
2781 gtk_window_set_skip_pager_hint (GtkWindow *window,
2784 GtkWindowPrivate *priv;
2786 g_return_if_fail (GTK_IS_WINDOW (window));
2788 priv = window->priv;
2790 setting = setting != FALSE;
2792 if (priv->skips_pager != setting)
2794 priv->skips_pager = setting;
2795 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2796 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2798 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2803 * gtk_window_get_skip_pager_hint:
2804 * @window: a #GtkWindow
2806 * Gets the value set by gtk_window_set_skip_pager_hint().
2808 * Return value: %TRUE if window shouldn't be in pager
2813 gtk_window_get_skip_pager_hint (GtkWindow *window)
2815 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2817 return window->priv->skips_pager;
2821 * gtk_window_set_urgency_hint:
2822 * @window: a #GtkWindow
2823 * @setting: %TRUE to mark this window as urgent
2825 * Windows may set a hint asking the desktop environment to draw
2826 * the users attention to the window. This function sets this hint.
2831 gtk_window_set_urgency_hint (GtkWindow *window,
2834 GtkWindowPrivate *priv;
2836 g_return_if_fail (GTK_IS_WINDOW (window));
2838 priv = window->priv;
2840 setting = setting != FALSE;
2842 if (priv->urgent != setting)
2844 priv->urgent = setting;
2845 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2846 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2848 g_object_notify (G_OBJECT (window), "urgency-hint");
2853 * gtk_window_get_urgency_hint:
2854 * @window: a #GtkWindow
2856 * Gets the value set by gtk_window_set_urgency_hint()
2858 * Return value: %TRUE if window is urgent
2863 gtk_window_get_urgency_hint (GtkWindow *window)
2865 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2867 return window->priv->urgent;
2871 * gtk_window_set_accept_focus:
2872 * @window: a #GtkWindow
2873 * @setting: %TRUE to let this window receive input focus
2875 * Windows may set a hint asking the desktop environment not to receive
2876 * the input focus. This function sets this hint.
2881 gtk_window_set_accept_focus (GtkWindow *window,
2884 GtkWindowPrivate *priv;
2886 g_return_if_fail (GTK_IS_WINDOW (window));
2888 priv = window->priv;
2890 setting = setting != FALSE;
2892 if (priv->accept_focus != setting)
2894 priv->accept_focus = setting;
2895 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2896 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2897 priv->accept_focus);
2898 g_object_notify (G_OBJECT (window), "accept-focus");
2903 * gtk_window_get_accept_focus:
2904 * @window: a #GtkWindow
2906 * Gets the value set by gtk_window_set_accept_focus().
2908 * Return value: %TRUE if window should receive the input focus
2913 gtk_window_get_accept_focus (GtkWindow *window)
2915 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2917 return window->priv->accept_focus;
2921 * gtk_window_set_focus_on_map:
2922 * @window: a #GtkWindow
2923 * @setting: %TRUE to let this window receive input focus on map
2925 * Windows may set a hint asking the desktop environment not to receive
2926 * the input focus when the window is mapped. This function sets this
2932 gtk_window_set_focus_on_map (GtkWindow *window,
2935 GtkWindowPrivate *priv;
2937 g_return_if_fail (GTK_IS_WINDOW (window));
2939 priv = window->priv;
2941 setting = setting != FALSE;
2943 if (priv->focus_on_map != setting)
2945 priv->focus_on_map = setting;
2946 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2947 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2948 priv->focus_on_map);
2949 g_object_notify (G_OBJECT (window), "focus-on-map");
2954 * gtk_window_get_focus_on_map:
2955 * @window: a #GtkWindow
2957 * Gets the value set by gtk_window_set_focus_on_map().
2959 * Return value: %TRUE if window should receive the input focus when
2965 gtk_window_get_focus_on_map (GtkWindow *window)
2967 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2969 return window->priv->focus_on_map;
2973 * gtk_window_set_destroy_with_parent:
2974 * @window: a #GtkWindow
2975 * @setting: whether to destroy @window with its transient parent
2977 * If @setting is %TRUE, then destroying the transient parent of @window
2978 * will also destroy @window itself. This is useful for dialogs that
2979 * shouldn't persist beyond the lifetime of the main window they're
2980 * associated with, for example.
2983 gtk_window_set_destroy_with_parent (GtkWindow *window,
2986 GtkWindowPrivate *priv;
2988 g_return_if_fail (GTK_IS_WINDOW (window));
2990 priv = window->priv;
2992 if (priv->destroy_with_parent == (setting != FALSE))
2995 if (priv->destroy_with_parent)
2997 disconnect_parent_destroyed (window);
3001 connect_parent_destroyed (window);
3004 priv->destroy_with_parent = setting;
3006 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3010 * gtk_window_get_destroy_with_parent:
3011 * @window: a #GtkWindow
3013 * Returns whether the window will be destroyed with its transient parent. See
3014 * gtk_window_set_destroy_with_parent ().
3016 * Return value: %TRUE if the window will be destroyed with its transient parent.
3019 gtk_window_get_destroy_with_parent (GtkWindow *window)
3021 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3023 return window->priv->destroy_with_parent;
3026 static GtkWindowGeometryInfo*
3027 gtk_window_get_geometry_info (GtkWindow *window,
3030 GtkWindowPrivate *priv = window->priv;
3031 GtkWindowGeometryInfo *info;
3033 info = priv->geometry_info;
3034 if (!info && create)
3036 info = g_new0 (GtkWindowGeometryInfo, 1);
3038 info->default_width = -1;
3039 info->default_height = -1;
3040 info->resize_width = -1;
3041 info->resize_height = -1;
3042 info->initial_x = 0;
3043 info->initial_y = 0;
3044 info->initial_pos_set = FALSE;
3045 info->default_is_geometry = FALSE;
3046 info->position_constraints_changed = FALSE;
3047 info->last.configure_request.x = 0;
3048 info->last.configure_request.y = 0;
3049 info->last.configure_request.width = -1;
3050 info->last.configure_request.height = -1;
3051 info->widget = NULL;
3053 priv->geometry_info = info;
3060 * gtk_window_set_geometry_hints:
3061 * @window: a #GtkWindow
3062 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3063 * @geometry: (allow-none): struct containing geometry information or %NULL
3064 * @geom_mask: mask indicating which struct fields should be paid attention to
3066 * This function sets up hints about how a window can be resized by
3067 * the user. You can set a minimum and maximum size; allowed resize
3068 * increments (e.g. for xterm, you can only resize by the size of a
3069 * character); aspect ratios; and more. See the #GdkGeometry struct.
3073 gtk_window_set_geometry_hints (GtkWindow *window,
3074 GtkWidget *geometry_widget,
3075 GdkGeometry *geometry,
3076 GdkWindowHints geom_mask)
3078 GtkWindowGeometryInfo *info;
3080 g_return_if_fail (GTK_IS_WINDOW (window));
3081 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3083 info = gtk_window_get_geometry_info (window, TRUE);
3086 g_signal_handlers_disconnect_by_func (info->widget,
3087 gtk_widget_destroyed,
3090 info->widget = geometry_widget;
3092 g_signal_connect (geometry_widget, "destroy",
3093 G_CALLBACK (gtk_widget_destroyed),
3097 info->geometry = *geometry;
3099 /* We store gravity in priv->gravity not in the hints. */
3100 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3102 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3104 gtk_window_set_gravity (window, geometry->win_gravity);
3107 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3111 * gtk_window_set_decorated:
3112 * @window: a #GtkWindow
3113 * @setting: %TRUE to decorate the window
3115 * By default, windows are decorated with a title bar, resize
3116 * controls, etc. Some <link linkend="gtk-X11-arch">window
3117 * managers</link> allow GTK+ to disable these decorations, creating a
3118 * borderless window. If you set the decorated property to %FALSE
3119 * using this function, GTK+ will do its best to convince the window
3120 * manager not to decorate the window. Depending on the system, this
3121 * function may not have any effect when called on a window that is
3122 * already visible, so you should call it before calling gtk_widget_show().
3124 * On Windows, this function always works, since there's no window manager
3129 gtk_window_set_decorated (GtkWindow *window,
3132 GtkWindowPrivate *priv;
3133 GdkWindow *gdk_window;
3135 g_return_if_fail (GTK_IS_WINDOW (window));
3137 priv = window->priv;
3139 setting = setting != FALSE;
3141 if (setting == priv->decorated)
3144 priv->decorated = setting;
3146 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3149 if (priv->decorated)
3150 gdk_window_set_decorations (gdk_window,
3153 gdk_window_set_decorations (gdk_window,
3157 g_object_notify (G_OBJECT (window), "decorated");
3161 * gtk_window_get_decorated:
3162 * @window: a #GtkWindow
3164 * Returns whether the window has been set to have decorations
3165 * such as a title bar via gtk_window_set_decorated().
3167 * Return value: %TRUE if the window has been set to have decorations
3170 gtk_window_get_decorated (GtkWindow *window)
3172 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3174 return window->priv->decorated;
3178 * gtk_window_set_deletable:
3179 * @window: a #GtkWindow
3180 * @setting: %TRUE to decorate the window as deletable
3182 * By default, windows have a close button in the window frame. Some
3183 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3184 * disable this button. If you set the deletable property to %FALSE
3185 * using this function, GTK+ will do its best to convince the window
3186 * manager not to show a close button. Depending on the system, this
3187 * function may not have any effect when called on a window that is
3188 * already visible, so you should call it before calling gtk_window_show().
3190 * On Windows, this function always works, since there's no window manager
3196 gtk_window_set_deletable (GtkWindow *window,
3199 GtkWindowPrivate *priv;
3200 GdkWindow *gdk_window;
3202 g_return_if_fail (GTK_IS_WINDOW (window));
3204 priv = window->priv;
3206 setting = setting != FALSE;
3208 if (setting == priv->deletable)
3211 priv->deletable = setting;
3213 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3216 if (priv->deletable)
3217 gdk_window_set_functions (gdk_window,
3220 gdk_window_set_functions (gdk_window,
3221 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3224 g_object_notify (G_OBJECT (window), "deletable");
3228 * gtk_window_get_deletable:
3229 * @window: a #GtkWindow
3231 * Returns whether the window has been set to have a close button
3232 * via gtk_window_set_deletable().
3234 * Return value: %TRUE if the window has been set to have a close button
3239 gtk_window_get_deletable (GtkWindow *window)
3241 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3243 return window->priv->deletable;
3246 static GtkWindowIconInfo*
3247 get_icon_info (GtkWindow *window)
3249 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3253 free_icon_info (GtkWindowIconInfo *info)
3255 g_free (info->icon_name);
3256 g_slice_free (GtkWindowIconInfo, info);
3260 static GtkWindowIconInfo*
3261 ensure_icon_info (GtkWindow *window)
3263 GtkWindowIconInfo *info;
3265 info = get_icon_info (window);
3269 info = g_slice_new0 (GtkWindowIconInfo);
3270 g_object_set_qdata_full (G_OBJECT (window),
3271 quark_gtk_window_icon_info,
3273 (GDestroyNotify)free_icon_info);
3280 icon_list_from_theme (GtkWidget *widget,
3285 GtkIconTheme *icon_theme;
3290 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3292 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3295 for (i = 0; sizes[i]; i++)
3298 * We need an EWMH extension to handle scalable icons
3299 * by passing their name to the WM. For now just use a
3303 icon = gtk_icon_theme_load_icon (icon_theme, name,
3306 icon = gtk_icon_theme_load_icon (icon_theme, name,
3309 list = g_list_append (list, icon);
3319 gtk_window_realize_icon (GtkWindow *window)
3321 GtkWindowPrivate *priv = window->priv;
3323 GtkWindowIconInfo *info;
3324 GdkWindow *gdk_window;
3327 widget = GTK_WIDGET (window);
3328 gdk_window = gtk_widget_get_window (widget);
3330 g_return_if_fail (gdk_window != NULL);
3332 /* no point setting an icon on override-redirect */
3333 if (priv->type == GTK_WINDOW_POPUP)
3338 info = ensure_icon_info (window);
3343 info->using_default_icon = FALSE;
3344 info->using_parent_icon = FALSE;
3345 info->using_themed_icon = FALSE;
3347 icon_list = info->icon_list;
3349 /* Look up themed icon */
3350 if (icon_list == NULL && info->icon_name)
3352 icon_list = icon_list_from_theme (widget, info->icon_name);
3354 info->using_themed_icon = TRUE;
3357 /* Inherit from transient parent */
3358 if (icon_list == NULL && priv->transient_parent)
3360 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3362 info->using_parent_icon = TRUE;
3365 /* Inherit from default */
3366 if (icon_list == NULL)
3368 icon_list = default_icon_list;
3370 info->using_default_icon = TRUE;
3373 /* Look up themed icon */
3374 if (icon_list == NULL && default_icon_name)
3376 icon_list = icon_list_from_theme (widget, default_icon_name);
3377 info->using_default_icon = TRUE;
3378 info->using_themed_icon = TRUE;
3381 info->realized = TRUE;
3383 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3385 if (info->using_themed_icon)
3387 GtkIconTheme *icon_theme;
3389 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3390 g_list_free (icon_list);
3392 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3393 g_signal_connect (icon_theme, "changed",
3394 G_CALLBACK (update_themed_icon), window);
3399 gtk_window_unrealize_icon (GtkWindow *window)
3401 GtkWindowIconInfo *info;
3403 info = get_icon_info (window);
3408 if (info->using_themed_icon)
3410 GtkIconTheme *icon_theme;
3412 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3414 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3417 /* We don't clear the properties on the window, just figure the
3418 * window is going away.
3421 info->realized = FALSE;
3426 * gtk_window_set_icon_list:
3427 * @window: a #GtkWindow
3428 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3430 * Sets up the icon representing a #GtkWindow. The icon is used when
3431 * the window is minimized (also known as iconified). Some window
3432 * managers or desktop environments may also place it in the window
3433 * frame, or display it in other contexts.
3435 * gtk_window_set_icon_list() allows you to pass in the same icon in
3436 * several hand-drawn sizes. The list should contain the natural sizes
3437 * your icon is available in; that is, don't scale the image before
3438 * passing it to GTK+. Scaling is postponed until the last minute,
3439 * when the desired final size is known, to allow best quality.
3441 * By passing several sizes, you may improve the final image quality
3442 * of the icon, by reducing or eliminating automatic image scaling.
3444 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3445 * larger images (64x64, 128x128) if you have them.
3447 * See also gtk_window_set_default_icon_list() to set the icon
3448 * for all windows in your application in one go.
3450 * Note that transient windows (those who have been set transient for another
3451 * window using gtk_window_set_transient_for()) will inherit their
3452 * icon from their transient parent. So there's no need to explicitly
3453 * set the icon on transient windows.
3456 gtk_window_set_icon_list (GtkWindow *window,
3459 GtkWindowIconInfo *info;
3461 g_return_if_fail (GTK_IS_WINDOW (window));
3463 info = ensure_icon_info (window);
3465 if (info->icon_list == list) /* check for NULL mostly */
3468 g_list_foreach (list,
3469 (GFunc) g_object_ref, NULL);
3471 g_list_foreach (info->icon_list,
3472 (GFunc) g_object_unref, NULL);
3474 g_list_free (info->icon_list);
3476 info->icon_list = g_list_copy (list);
3478 g_object_notify (G_OBJECT (window), "icon");
3480 gtk_window_unrealize_icon (window);
3482 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3483 gtk_window_realize_icon (window);
3485 /* We could try to update our transient children, but I don't think
3486 * it's really worth it. If we did it, the best way would probably
3487 * be to have children connect to notify::icon-list
3492 * gtk_window_get_icon_list:
3493 * @window: a #GtkWindow
3495 * Retrieves the list of icons set by gtk_window_set_icon_list().
3496 * The list is copied, but the reference count on each
3497 * member won't be incremented.
3499 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3502 gtk_window_get_icon_list (GtkWindow *window)
3504 GtkWindowIconInfo *info;
3506 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3508 info = get_icon_info (window);
3511 return g_list_copy (info->icon_list);
3517 * gtk_window_set_icon:
3518 * @window: a #GtkWindow
3519 * @icon: (allow-none): icon image, or %NULL
3521 * Sets up the icon representing a #GtkWindow. This icon is used when
3522 * the window is minimized (also known as iconified). Some window
3523 * managers or desktop environments may also place it in the window
3524 * frame, or display it in other contexts.
3526 * The icon should be provided in whatever size it was naturally
3527 * drawn; that is, don't scale the image before passing it to
3528 * GTK+. Scaling is postponed until the last minute, when the desired
3529 * final size is known, to allow best quality.
3531 * If you have your icon hand-drawn in multiple sizes, use
3532 * gtk_window_set_icon_list(). Then the best size will be used.
3534 * This function is equivalent to calling gtk_window_set_icon_list()
3535 * with a 1-element list.
3537 * See also gtk_window_set_default_icon_list() to set the icon
3538 * for all windows in your application in one go.
3541 gtk_window_set_icon (GtkWindow *window,
3546 g_return_if_fail (GTK_IS_WINDOW (window));
3547 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3552 list = g_list_append (list, icon);
3554 gtk_window_set_icon_list (window, list);
3560 update_themed_icon (GtkIconTheme *icon_theme,
3563 g_object_notify (G_OBJECT (window), "icon");
3565 gtk_window_unrealize_icon (window);
3567 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3568 gtk_window_realize_icon (window);
3572 * gtk_window_set_icon_name:
3573 * @window: a #GtkWindow
3574 * @name: (allow-none): the name of the themed icon
3576 * Sets the icon for the window from a named themed icon. See
3577 * the docs for #GtkIconTheme for more details.
3579 * Note that this has nothing to do with the WM_ICON_NAME
3580 * property which is mentioned in the ICCCM.
3585 gtk_window_set_icon_name (GtkWindow *window,
3588 GtkWindowIconInfo *info;
3591 g_return_if_fail (GTK_IS_WINDOW (window));
3593 info = ensure_icon_info (window);
3595 if (g_strcmp0 (info->icon_name, name) == 0)
3598 tmp = info->icon_name;
3599 info->icon_name = g_strdup (name);
3602 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3603 g_list_free (info->icon_list);
3604 info->icon_list = NULL;
3606 update_themed_icon (NULL, window);
3608 g_object_notify (G_OBJECT (window), "icon-name");
3612 * gtk_window_get_icon_name:
3613 * @window: a #GtkWindow
3615 * Returns the name of the themed icon for the window,
3616 * see gtk_window_set_icon_name().
3618 * Returns: the icon name or %NULL if the window has
3624 gtk_window_get_icon_name (GtkWindow *window)
3626 GtkWindowIconInfo *info;
3628 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3630 info = ensure_icon_info (window);
3632 return info->icon_name;
3636 * gtk_window_get_icon:
3637 * @window: a #GtkWindow
3639 * Gets the value set by gtk_window_set_icon() (or if you've
3640 * called gtk_window_set_icon_list(), gets the first icon in
3643 * Return value: (transfer none): icon for window
3646 gtk_window_get_icon (GtkWindow *window)
3648 GtkWindowIconInfo *info;
3650 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3652 info = get_icon_info (window);
3653 if (info && info->icon_list)
3654 return GDK_PIXBUF (info->icon_list->data);
3659 /* Load pixbuf, printing warning on failure if error == NULL
3662 load_pixbuf_verbosely (const char *filename,
3665 GError *local_err = NULL;
3668 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3676 g_warning ("Error loading icon from file '%s':\n\t%s",
3677 filename, local_err->message);
3678 g_error_free (local_err);
3686 * gtk_window_set_icon_from_file:
3687 * @window: a #GtkWindow
3688 * @filename: location of icon file
3689 * @err: (allow-none): location to store error, or %NULL.
3691 * Sets the icon for @window.
3692 * Warns on failure if @err is %NULL.
3694 * This function is equivalent to calling gtk_window_set_icon()
3695 * with a pixbuf created by loading the image from @filename.
3697 * Returns: %TRUE if setting the icon succeeded.
3702 gtk_window_set_icon_from_file (GtkWindow *window,
3703 const gchar *filename,
3706 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3710 gtk_window_set_icon (window, pixbuf);
3711 g_object_unref (pixbuf);
3720 * gtk_window_set_default_icon_list:
3721 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3723 * Sets an icon list to be used as fallback for windows that haven't
3724 * had gtk_window_set_icon_list() called on them to set up a
3725 * window-specific icon list. This function allows you to set up the
3726 * icon for all windows in your app at once.
3728 * See gtk_window_set_icon_list() for more details.
3732 gtk_window_set_default_icon_list (GList *list)
3736 if (list == default_icon_list)
3739 /* Update serial so we don't used cached pixmaps/masks
3741 default_icon_serial++;
3743 g_list_foreach (list,
3744 (GFunc) g_object_ref, NULL);
3746 g_list_foreach (default_icon_list,
3747 (GFunc) g_object_unref, NULL);
3749 g_list_free (default_icon_list);
3751 default_icon_list = g_list_copy (list);
3753 /* Update all toplevels */
3754 toplevels = gtk_window_list_toplevels ();
3755 tmp_list = toplevels;
3756 while (tmp_list != NULL)
3758 GtkWindowIconInfo *info;
3759 GtkWindow *w = tmp_list->data;
3761 info = get_icon_info (w);
3762 if (info && info->using_default_icon)
3764 gtk_window_unrealize_icon (w);
3765 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3766 gtk_window_realize_icon (w);
3769 tmp_list = tmp_list->next;
3771 g_list_free (toplevels);
3775 * gtk_window_set_default_icon:
3778 * Sets an icon to be used as fallback for windows that haven't
3779 * had gtk_window_set_icon() called on them from a pixbuf.
3784 gtk_window_set_default_icon (GdkPixbuf *icon)
3788 g_return_if_fail (GDK_IS_PIXBUF (icon));
3790 list = g_list_prepend (NULL, icon);
3791 gtk_window_set_default_icon_list (list);
3796 * gtk_window_set_default_icon_name:
3797 * @name: the name of the themed icon
3799 * Sets an icon to be used as fallback for windows that haven't
3800 * had gtk_window_set_icon_list() called on them from a named
3801 * themed icon, see gtk_window_set_icon_name().
3806 gtk_window_set_default_icon_name (const gchar *name)
3811 /* Update serial so we don't used cached pixmaps/masks
3813 default_icon_serial++;
3815 g_free (default_icon_name);
3816 default_icon_name = g_strdup (name);
3818 g_list_foreach (default_icon_list,
3819 (GFunc) g_object_unref, NULL);
3821 g_list_free (default_icon_list);
3822 default_icon_list = NULL;
3824 /* Update all toplevels */
3825 toplevels = gtk_window_list_toplevels ();
3826 tmp_list = toplevels;
3827 while (tmp_list != NULL)
3829 GtkWindowIconInfo *info;
3830 GtkWindow *w = tmp_list->data;
3832 info = get_icon_info (w);
3833 if (info && info->using_default_icon && info->using_themed_icon)
3835 gtk_window_unrealize_icon (w);
3836 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3837 gtk_window_realize_icon (w);
3840 tmp_list = tmp_list->next;
3842 g_list_free (toplevels);
3846 * gtk_window_get_default_icon_name:
3848 * Returns the fallback icon name for windows that has been set
3849 * with gtk_window_set_default_icon_name(). The returned
3850 * string is owned by GTK+ and should not be modified. It
3851 * is only valid until the next call to
3852 * gtk_window_set_default_icon_name().
3854 * Returns: the fallback icon name for windows
3859 gtk_window_get_default_icon_name (void)
3861 return default_icon_name;
3865 * gtk_window_set_default_icon_from_file:
3866 * @filename: location of icon file
3867 * @err: (allow-none): location to store error, or %NULL.
3869 * Sets an icon to be used as fallback for windows that haven't
3870 * had gtk_window_set_icon_list() called on them from a file
3871 * on disk. Warns on failure if @err is %NULL.
3873 * Returns: %TRUE if setting the icon succeeded.
3878 gtk_window_set_default_icon_from_file (const gchar *filename,
3881 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3885 gtk_window_set_default_icon (pixbuf);
3886 g_object_unref (pixbuf);
3895 * gtk_window_get_default_icon_list:
3897 * Gets the value set by gtk_window_set_default_icon_list().
3898 * The list is a copy and should be freed with g_list_free(),
3899 * but the pixbufs in the list have not had their reference count
3902 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3905 gtk_window_get_default_icon_list (void)
3907 return g_list_copy (default_icon_list);
3911 gtk_window_set_default_size_internal (GtkWindow *window,
3912 gboolean change_width,
3914 gboolean change_height,
3916 gboolean is_geometry)
3918 GtkWindowGeometryInfo *info;
3920 g_return_if_fail (change_width == FALSE || width >= -1);
3921 g_return_if_fail (change_height == FALSE || height >= -1);
3923 info = gtk_window_get_geometry_info (window, TRUE);
3925 g_object_freeze_notify (G_OBJECT (window));
3927 info->default_is_geometry = is_geometry != FALSE;
3937 info->default_width = width;
3939 g_object_notify (G_OBJECT (window), "default-width");
3950 info->default_height = height;
3952 g_object_notify (G_OBJECT (window), "default-height");
3955 g_object_thaw_notify (G_OBJECT (window));
3957 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3961 * gtk_window_set_default_size:
3962 * @window: a #GtkWindow
3963 * @width: width in pixels, or -1 to unset the default width
3964 * @height: height in pixels, or -1 to unset the default height
3966 * Sets the default size of a window. If the window's "natural" size
3967 * (its size request) is larger than the default, the default will be
3968 * ignored. More generally, if the default size does not obey the
3969 * geometry hints for the window (gtk_window_set_geometry_hints() can
3970 * be used to set these explicitly), the default size will be clamped
3971 * to the nearest permitted size.
3973 * Unlike gtk_widget_set_size_request(), which sets a size request for
3974 * a widget and thus would keep users from shrinking the window, this
3975 * function only sets the initial size, just as if the user had
3976 * resized the window themselves. Users can still shrink the window
3977 * again as they normally would. Setting a default size of -1 means to
3978 * use the "natural" default size (the size request of the window).
3980 * For more control over a window's initial size and how resizing works,
3981 * investigate gtk_window_set_geometry_hints().
3983 * For some uses, gtk_window_resize() is a more appropriate function.
3984 * gtk_window_resize() changes the current size of the window, rather
3985 * than the size to be used on initial display. gtk_window_resize() always
3986 * affects the window itself, not the geometry widget.
3988 * The default size of a window only affects the first time a window is
3989 * shown; if a window is hidden and re-shown, it will remember the size
3990 * it had prior to hiding, rather than using the default size.
3992 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3993 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3996 gtk_window_set_default_size (GtkWindow *window,
4000 g_return_if_fail (GTK_IS_WINDOW (window));
4001 g_return_if_fail (width >= -1);
4002 g_return_if_fail (height >= -1);
4004 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4008 * gtk_window_set_default_geometry:
4009 * @window: a #GtkWindow
4010 * @width: width in resize increments, or -1 to unset the default width
4011 * @height: height in resize increments, or -1 to unset the default height
4013 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4014 * in terms of the base size and increment set with
4015 * gtk_window_set_geometry_hints.
4020 gtk_window_set_default_geometry (GtkWindow *window,
4024 g_return_if_fail (GTK_IS_WINDOW (window));
4025 g_return_if_fail (width >= -1);
4026 g_return_if_fail (height >= -1);
4028 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4032 * gtk_window_get_default_size:
4033 * @window: a #GtkWindow
4034 * @width: (out) (allow-none): location to store the default width, or %NULL
4035 * @height: (out) (allow-none): location to store the default height, or %NULL
4037 * Gets the default size of the window. A value of -1 for the width or
4038 * height indicates that a default size has not been explicitly set
4039 * for that dimension, so the "natural" size of the window will be
4044 gtk_window_get_default_size (GtkWindow *window,
4048 GtkWindowGeometryInfo *info;
4050 g_return_if_fail (GTK_IS_WINDOW (window));
4052 info = gtk_window_get_geometry_info (window, FALSE);
4055 *width = info ? info->default_width : -1;
4058 *height = info ? info->default_height : -1;
4062 * gtk_window_resize:
4063 * @window: a #GtkWindow
4064 * @width: width in pixels to resize the window to
4065 * @height: height in pixels to resize the window to
4067 * Resizes the window as if the user had done so, obeying geometry
4068 * constraints. The default geometry constraint is that windows may
4069 * not be smaller than their size request; to override this
4070 * constraint, call gtk_widget_set_size_request() to set the window's
4071 * request to a smaller value.
4073 * If gtk_window_resize() is called before showing a window for the
4074 * first time, it overrides any default size set with
4075 * gtk_window_set_default_size().
4077 * Windows may not be resized smaller than 1 by 1 pixels.
4081 gtk_window_resize (GtkWindow *window,
4085 GtkWindowGeometryInfo *info;
4087 g_return_if_fail (GTK_IS_WINDOW (window));
4088 g_return_if_fail (width > 0);
4089 g_return_if_fail (height > 0);
4091 info = gtk_window_get_geometry_info (window, TRUE);
4093 info->resize_width = width;
4094 info->resize_height = height;
4095 info->resize_is_geometry = FALSE;
4097 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4101 * gtk_window_resize_to_geometry:
4102 * @window: a #GtkWindow
4103 * @width: width in resize increments to resize the window to
4104 * @height: height in resize increments to resize the window to
4106 * Like gtk_window_resize(), but @width and @height are interpreted
4107 * in terms of the base size and increment set with
4108 * gtk_window_set_geometry_hints.
4113 gtk_window_resize_to_geometry (GtkWindow *window,
4117 GtkWindowGeometryInfo *info;
4119 g_return_if_fail (GTK_IS_WINDOW (window));
4120 g_return_if_fail (width > 0);
4121 g_return_if_fail (height > 0);
4123 info = gtk_window_get_geometry_info (window, TRUE);
4125 info->resize_width = width;
4126 info->resize_height = height;
4127 info->resize_is_geometry = TRUE;
4129 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4133 * gtk_window_get_size:
4134 * @window: a #GtkWindow
4135 * @width: (out) (allow-none): return location for width, or %NULL
4136 * @height: (out) (allow-none): return location for height, or %NULL
4138 * Obtains the current size of @window. If @window is not onscreen,
4139 * it returns the size GTK+ will suggest to the <link
4140 * linkend="gtk-X11-arch">window manager</link> for the initial window
4141 * size (but this is not reliably the same as the size the window
4142 * manager will actually select). The size obtained by
4143 * gtk_window_get_size() is the last size received in a
4144 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4145 * rather than querying the X server for the size. As a result, if you
4146 * call gtk_window_resize() then immediately call
4147 * gtk_window_get_size(), the size won't have taken effect yet. After
4148 * the window manager processes the resize request, GTK+ receives
4149 * notification that the size has changed via a configure event, and
4150 * the size of the window gets updated.
4152 * Note 1: Nearly any use of this function creates a race condition,
4153 * because the size of the window may change between the time that you
4154 * get the size and the time that you perform some action assuming
4155 * that size is the current size. To avoid race conditions, connect to
4156 * "configure-event" on the window and adjust your size-dependent
4157 * state to match the size delivered in the #GdkEventConfigure.
4159 * Note 2: The returned size does <emphasis>not</emphasis> include the
4160 * size of the window manager decorations (aka the window frame or
4161 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4162 * method of determining their size.
4164 * Note 3: If you are getting a window size in order to position
4165 * the window onscreen, there may be a better way. The preferred
4166 * way is to simply set the window's semantic type with
4167 * gtk_window_set_type_hint(), which allows the window manager to
4168 * e.g. center dialogs. Also, if you set the transient parent of
4169 * dialogs with gtk_window_set_transient_for() window managers
4170 * will often center the dialog over its parent window. It's
4171 * much preferred to let the window manager handle these
4172 * things rather than doing it yourself, because all apps will
4173 * behave consistently and according to user prefs if the window
4174 * manager handles it. Also, the window manager can take the size
4175 * of the window decorations/border into account, while your
4176 * application cannot.
4178 * In any case, if you insist on application-specified window
4179 * positioning, there's <emphasis>still</emphasis> a better way than
4180 * doing it yourself - gtk_window_set_position() will frequently
4181 * handle the details for you.
4185 gtk_window_get_size (GtkWindow *window,
4191 g_return_if_fail (GTK_IS_WINDOW (window));
4193 if (width == NULL && height == NULL)
4196 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4198 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4199 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4203 GdkRectangle configure_request;
4205 gtk_window_compute_configure_request (window,
4209 w = configure_request.width;
4210 h = configure_request.height;
4221 * @window: a #GtkWindow
4222 * @x: X coordinate to move window to
4223 * @y: Y coordinate to move window to
4225 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4226 * @window to the given position. Window managers are free to ignore
4227 * this; most window managers ignore requests for initial window
4228 * positions (instead using a user-defined placement algorithm) and
4229 * honor requests after the window has already been shown.
4231 * Note: the position is the position of the gravity-determined
4232 * reference point for the window. The gravity determines two things:
4233 * first, the location of the reference point in root window
4234 * coordinates; and second, which point on the window is positioned at
4235 * the reference point.
4237 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4238 * point is simply the @x, @y supplied to gtk_window_move(). The
4239 * top-left corner of the window decorations (aka window frame or
4240 * border) will be placed at @x, @y. Therefore, to position a window
4241 * at the top left of the screen, you want to use the default gravity
4242 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4244 * To position a window at the bottom right corner of the screen, you
4245 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4246 * point is at @x + the window width and @y + the window height, and
4247 * the bottom-right corner of the window border will be placed at that
4248 * reference point. So, to place a window in the bottom right corner
4249 * you would first set gravity to south east, then write:
4250 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4251 * gdk_screen_height () - window_height)</literal> (note that this
4252 * example does not take multi-head scenarios into account).
4254 * The Extended Window Manager Hints specification at <ulink
4255 * url="http://www.freedesktop.org/Standards/wm-spec">
4256 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4257 * nice table of gravities in the "implementation notes" section.
4259 * The gtk_window_get_position() documentation may also be relevant.
4262 gtk_window_move (GtkWindow *window,
4266 GtkWindowPrivate *priv;
4267 GtkWindowGeometryInfo *info;
4270 g_return_if_fail (GTK_IS_WINDOW (window));
4272 priv = window->priv;
4273 widget = GTK_WIDGET (window);
4275 info = gtk_window_get_geometry_info (window, TRUE);
4277 if (gtk_widget_get_mapped (widget))
4279 GtkAllocation allocation;
4281 gtk_widget_get_allocation (widget, &allocation);
4283 /* we have now sent a request with this position
4284 * with currently-active constraints, so toggle flag.
4286 info->position_constraints_changed = FALSE;
4288 /* we only constrain if mapped - if not mapped,
4289 * then gtk_window_compute_configure_request()
4290 * will apply the constraints later, and we
4291 * don't want to lose information about
4292 * what position the user set before then.
4293 * i.e. if you do a move() then turn off POS_CENTER
4294 * then show the window, your move() will work.
4296 gtk_window_constrain_position (window,
4297 allocation.width, allocation.height,
4300 /* Note that this request doesn't go through our standard request
4301 * framework, e.g. doesn't increment configure_request_count,
4302 * doesn't set info->last, etc.; that's because
4303 * we don't save the info needed to arrive at this same request
4306 * To gtk_window_move_resize(), this will end up looking exactly
4307 * the same as the position being changed by the window
4310 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4314 /* Save this position to apply on mapping */
4315 info->initial_x = x;
4316 info->initial_y = y;
4317 info->initial_pos_set = TRUE;
4322 * gtk_window_get_position:
4323 * @window: a #GtkWindow
4324 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4325 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4327 * This function returns the position you need to pass to
4328 * gtk_window_move() to keep @window in its current position. This
4329 * means that the meaning of the returned value varies with window
4330 * gravity. See gtk_window_move() for more details.
4332 * If you haven't changed the window gravity, its gravity will be
4333 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4334 * gets the position of the top-left corner of the window manager
4335 * frame for the window. gtk_window_move() sets the position of this
4336 * same top-left corner.
4338 * gtk_window_get_position() is not 100% reliable because the X Window System
4339 * does not specify a way to obtain the geometry of the
4340 * decorations placed on a window by the window manager.
4341 * Thus GTK+ is using a "best guess" that works with most
4344 * Moreover, nearly all window managers are historically broken with
4345 * respect to their handling of window gravity. So moving a window to
4346 * its current position as returned by gtk_window_get_position() tends
4347 * to result in moving the window slightly. Window managers are
4348 * slowly getting better over time.
4350 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4351 * frame is not relevant, and thus gtk_window_get_position() will
4352 * always produce accurate results. However you can't use static
4353 * gravity to do things like place a window in a corner of the screen,
4354 * because static gravity ignores the window manager decorations.
4356 * If you are saving and restoring your application's window
4357 * positions, you should know that it's impossible for applications to
4358 * do this without getting it somewhat wrong because applications do
4359 * not have sufficient knowledge of window manager state. The Correct
4360 * Mechanism is to support the session management protocol (see the
4361 * "GnomeClient" object in the GNOME libraries for example) and allow
4362 * the window manager to save your window sizes and positions.
4367 gtk_window_get_position (GtkWindow *window,
4371 GtkWindowPrivate *priv;
4373 GdkWindow *gdk_window;
4375 g_return_if_fail (GTK_IS_WINDOW (window));
4377 priv = window->priv;
4378 widget = GTK_WIDGET (window);
4379 gdk_window = gtk_widget_get_window (widget);
4381 if (priv->gravity == GDK_GRAVITY_STATIC)
4383 if (gtk_widget_get_mapped (widget))
4385 /* This does a server round-trip, which is sort of wrong;
4386 * but a server round-trip is inevitable for
4387 * gdk_window_get_frame_extents() in the usual
4388 * NorthWestGravity case below, so not sure what else to
4389 * do. We should likely be consistent about whether we get
4390 * the client-side info or the server-side info.
4392 gdk_window_get_origin (gdk_window, root_x, root_y);
4396 GdkRectangle configure_request;
4398 gtk_window_compute_configure_request (window,
4402 *root_x = configure_request.x;
4403 *root_y = configure_request.y;
4408 GdkRectangle frame_extents;
4413 if (gtk_widget_get_mapped (widget))
4415 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4416 x = frame_extents.x;
4417 y = frame_extents.y;
4418 gtk_window_get_size (window, &w, &h);
4422 /* We just say the frame has 0 size on all sides.
4423 * Not sure what else to do.
4425 gtk_window_compute_configure_request (window,
4428 x = frame_extents.x;
4429 y = frame_extents.y;
4430 w = frame_extents.width;
4431 h = frame_extents.height;
4434 switch (priv->gravity)
4436 case GDK_GRAVITY_NORTH:
4437 case GDK_GRAVITY_CENTER:
4438 case GDK_GRAVITY_SOUTH:
4439 /* Find center of frame. */
4440 x += frame_extents.width / 2;
4441 /* Center client window on that point. */
4445 case GDK_GRAVITY_SOUTH_EAST:
4446 case GDK_GRAVITY_EAST:
4447 case GDK_GRAVITY_NORTH_EAST:
4448 /* Find right edge of frame */
4449 x += frame_extents.width;
4450 /* Align left edge of client at that point. */
4457 switch (priv->gravity)
4459 case GDK_GRAVITY_WEST:
4460 case GDK_GRAVITY_CENTER:
4461 case GDK_GRAVITY_EAST:
4462 /* Find center of frame. */
4463 y += frame_extents.height / 2;
4464 /* Center client window there. */
4467 case GDK_GRAVITY_SOUTH_WEST:
4468 case GDK_GRAVITY_SOUTH:
4469 case GDK_GRAVITY_SOUTH_EAST:
4470 /* Find south edge of frame */
4471 y += frame_extents.height;
4472 /* Place bottom edge of client there */
4487 * gtk_window_reshow_with_initial_size:
4488 * @window: a #GtkWindow
4490 * Hides @window, then reshows it, resetting the
4491 * default size and position of the window. Used
4492 * by GUI builders only.
4495 gtk_window_reshow_with_initial_size (GtkWindow *window)
4499 g_return_if_fail (GTK_IS_WINDOW (window));
4501 widget = GTK_WIDGET (window);
4503 gtk_widget_hide (widget);
4504 gtk_widget_unrealize (widget);
4505 gtk_widget_show (widget);
4509 gtk_window_destroy (GtkWidget *widget)
4511 GtkWindow *window = GTK_WINDOW (widget);
4512 GtkWindowPrivate *priv = window->priv;
4514 gtk_window_release_application (window);
4516 toplevel_list = g_slist_remove (toplevel_list, window);
4518 if (priv->transient_parent)
4519 gtk_window_set_transient_for (window, NULL);
4521 /* frees the icons */
4522 gtk_window_set_icon_list (window, NULL);
4524 if (priv->has_user_ref_count)
4526 priv->has_user_ref_count = FALSE;
4527 g_object_unref (window);
4531 gtk_window_group_remove_window (priv->group, window);
4533 gtk_window_free_key_hash (window);
4535 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4539 gtk_window_finalize (GObject *object)
4541 GtkWindow *window = GTK_WINDOW (object);
4542 GtkWindowPrivate *priv = window->priv;
4543 GtkMnemonicHash *mnemonic_hash;
4545 g_free (priv->title);
4546 g_free (priv->wmclass_name);
4547 g_free (priv->wmclass_class);
4548 g_free (priv->wm_role);
4549 gtk_window_release_application (window);
4551 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4553 _gtk_mnemonic_hash_free (mnemonic_hash);
4555 if (priv->geometry_info)
4557 if (priv->geometry_info->widget)
4558 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4559 gtk_widget_destroyed,
4560 &priv->geometry_info->widget);
4561 g_free (priv->geometry_info);
4564 if (priv->keys_changed_handler)
4566 g_source_remove (priv->keys_changed_handler);
4567 priv->keys_changed_handler = 0;
4571 g_signal_handlers_disconnect_by_func (priv->screen,
4572 gtk_window_on_composited_changed, window);
4574 g_free (priv->startup_id);
4576 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4580 gtk_window_show (GtkWidget *widget)
4582 GtkWindow *window = GTK_WINDOW (widget);
4583 GtkWindowPrivate *priv = window->priv;
4584 GtkContainer *container = GTK_CONTAINER (window);
4585 gboolean need_resize;
4587 _gtk_widget_set_visible_flag (widget, TRUE);
4589 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4590 _gtk_container_set_need_resize (container, FALSE);
4594 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4595 GtkAllocation allocation = { 0, 0 };
4596 GdkRectangle configure_request;
4597 GdkGeometry new_geometry;
4599 gboolean was_realized;
4601 /* We are going to go ahead and perform this configure request
4602 * and then emulate a configure notify by going ahead and
4603 * doing a size allocate. Sort of a synchronous
4604 * mini-copy of gtk_window_move_resize() here.
4606 gtk_window_compute_configure_request (window,
4611 /* We update this because we are going to go ahead
4612 * and gdk_window_resize() below, rather than
4615 info->last.configure_request.width = configure_request.width;
4616 info->last.configure_request.height = configure_request.height;
4618 /* and allocate the window - this is normally done
4619 * in move_resize in response to configure notify
4621 allocation.width = configure_request.width;
4622 allocation.height = configure_request.height;
4623 gtk_widget_size_allocate (widget, &allocation);
4625 /* Then we guarantee we have a realize */
4626 was_realized = FALSE;
4627 if (!gtk_widget_get_realized (widget))
4629 gtk_widget_realize (widget);
4630 was_realized = TRUE;
4633 /* We only send configure request if we didn't just finish
4634 * creating the window; if we just created the window
4635 * then we created it with widget->allocation anyhow.
4638 gdk_window_move_resize (gtk_widget_get_window (widget),
4639 configure_request.x,
4640 configure_request.y,
4641 configure_request.width,
4642 configure_request.height);
4645 gtk_container_check_resize (container);
4647 gtk_widget_map (widget);
4649 /* Try to make sure that we have some focused widget
4651 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4652 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4655 gtk_grab_add (widget);
4659 gtk_window_hide (GtkWidget *widget)
4661 GtkWindow *window = GTK_WINDOW (widget);
4662 GtkWindowPrivate *priv = window->priv;
4664 _gtk_widget_set_visible_flag (widget, FALSE);
4665 gtk_widget_unmap (widget);
4668 gtk_grab_remove (widget);
4672 gtk_window_map (GtkWidget *widget)
4675 GtkWindow *window = GTK_WINDOW (widget);
4676 GtkWindowPrivate *priv = window->priv;
4677 GdkWindow *toplevel;
4678 GdkWindow *gdk_window;
4679 gboolean auto_mnemonics;
4681 gdk_window = gtk_widget_get_window (widget);
4683 gtk_widget_set_mapped (widget, TRUE);
4685 child = gtk_bin_get_child (&(window->bin));
4687 gtk_widget_get_visible (child) &&
4688 !gtk_widget_get_mapped (child))
4689 gtk_widget_map (child);
4691 toplevel = gdk_window;
4693 if (priv->maximize_initially)
4694 gdk_window_maximize (toplevel);
4696 gdk_window_unmaximize (toplevel);
4698 if (priv->stick_initially)
4699 gdk_window_stick (toplevel);
4701 gdk_window_unstick (toplevel);
4703 if (priv->iconify_initially)
4704 gdk_window_iconify (toplevel);
4706 gdk_window_deiconify (toplevel);
4708 if (priv->fullscreen_initially)
4709 gdk_window_fullscreen (toplevel);
4711 gdk_window_unfullscreen (toplevel);
4713 gdk_window_set_keep_above (toplevel, priv->above_initially);
4715 gdk_window_set_keep_below (toplevel, priv->below_initially);
4717 /* No longer use the default settings */
4718 priv->need_default_size = FALSE;
4719 priv->need_default_position = FALSE;
4721 if (priv->reset_type_hint)
4723 /* We should only reset the type hint when the application
4724 * used gtk_window_set_type_hint() to change the hint.
4725 * Some applications use X directly to change the properties;
4726 * in that case, we shouldn't overwrite what they did.
4728 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4729 priv->reset_type_hint = FALSE;
4732 gdk_window_show (gdk_window);
4734 if (priv->grip_window)
4735 gdk_window_show (priv->grip_window);
4737 if (!disable_startup_notification)
4739 /* Do we have a custom startup-notification id? */
4740 if (priv->startup_id != NULL)
4742 /* Make sure we have a "real" id */
4743 if (!startup_id_is_fake (priv->startup_id))
4744 gdk_notify_startup_complete_with_id (priv->startup_id);
4746 g_free (priv->startup_id);
4747 priv->startup_id = NULL;
4749 else if (!sent_startup_notification)
4751 sent_startup_notification = TRUE;
4752 gdk_notify_startup_complete ();
4756 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4757 * (as in the case of popup menus), then hide mnemonics initially
4759 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4760 &auto_mnemonics, NULL);
4761 if (auto_mnemonics && !priv->mnemonics_visible_set)
4762 gtk_window_set_mnemonics_visible (window, FALSE);
4766 gtk_window_map_event (GtkWidget *widget,
4769 if (!gtk_widget_get_mapped (widget))
4771 /* we should be be unmapped, but are getting a MapEvent, this may happen
4772 * to toplevel XWindows if mapping was intercepted by a window manager
4773 * and an unmap request occoured while the MapRequestEvent was still
4774 * being handled. we work around this situaiton here by re-requesting
4775 * the window being unmapped. more details can be found in:
4776 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4778 gdk_window_hide (gtk_widget_get_window (widget));
4784 gtk_window_unmap (GtkWidget *widget)
4786 GtkWindow *window = GTK_WINDOW (widget);
4787 GtkWindowPrivate *priv = window->priv;
4789 GtkWindowGeometryInfo *info;
4790 GdkWindow *gdk_window;
4791 GdkWindowState state;
4793 gdk_window = gtk_widget_get_window (widget);
4795 gtk_widget_set_mapped (widget, FALSE);
4796 gdk_window_withdraw (gdk_window);
4798 priv->configure_request_count = 0;
4799 priv->configure_notify_received = FALSE;
4801 /* on unmap, we reset the default positioning of the window,
4802 * so it's placed again, but we don't reset the default
4803 * size of the window, so it's remembered.
4805 priv->need_default_position = TRUE;
4807 info = gtk_window_get_geometry_info (window, FALSE);
4810 info->initial_pos_set = FALSE;
4811 info->position_constraints_changed = FALSE;
4814 state = gdk_window_get_state (gdk_window);
4815 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4816 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4817 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4818 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4819 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4821 child = gtk_bin_get_child (&(window->bin));
4823 gtk_widget_unmap (child);
4827 gtk_window_realize (GtkWidget *widget)
4829 GtkAllocation allocation;
4831 GdkWindow *parent_window;
4832 GdkWindow *gdk_window;
4833 GdkWindowAttr attributes;
4834 gint attributes_mask;
4835 GtkWindowPrivate *priv;
4836 GtkStyleContext *context;
4838 window = GTK_WINDOW (widget);
4839 priv = window->priv;
4841 gtk_widget_get_allocation (widget, &allocation);
4843 /* ensure widget tree is properly size allocated */
4844 if (allocation.x == -1 &&
4845 allocation.y == -1 &&
4846 allocation.width == 1 &&
4847 allocation.height == 1)
4849 GtkRequisition requisition;
4853 allocation.width = 200;
4854 allocation.height = 200;
4856 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4857 if (requisition.width || requisition.height)
4859 /* non-empty window */
4860 allocation.width = requisition.width;
4861 allocation.height = requisition.height;
4863 gtk_widget_size_allocate (widget, &allocation);
4865 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4867 g_return_if_fail (!gtk_widget_get_realized (widget));
4870 gtk_widget_set_realized (widget, TRUE);
4874 case GTK_WINDOW_TOPLEVEL:
4875 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4877 case GTK_WINDOW_POPUP:
4878 attributes.window_type = GDK_WINDOW_TEMP;
4881 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4885 attributes.title = priv->title;
4886 attributes.wmclass_name = priv->wmclass_name;
4887 attributes.wmclass_class = priv->wmclass_class;
4888 attributes.wclass = GDK_INPUT_OUTPUT;
4889 attributes.visual = gtk_widget_get_visual (widget);
4891 attributes_mask = 0;
4892 parent_window = gtk_widget_get_root_window (widget);
4894 gtk_widget_get_allocation (widget, &allocation);
4895 attributes.width = allocation.width;
4896 attributes.height = allocation.height;
4897 attributes.event_mask = gtk_widget_get_events (widget);
4898 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4899 GDK_KEY_PRESS_MASK |
4900 GDK_KEY_RELEASE_MASK |
4901 GDK_ENTER_NOTIFY_MASK |
4902 GDK_LEAVE_NOTIFY_MASK |
4903 GDK_FOCUS_CHANGE_MASK |
4904 GDK_STRUCTURE_MASK);
4905 attributes.type_hint = priv->type_hint;
4907 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4908 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4909 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4911 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4912 gtk_widget_set_window (widget, gdk_window);
4914 if (priv->opacity_set)
4915 gdk_window_set_opacity (gdk_window, priv->opacity);
4917 gdk_window_enable_synchronized_configure (gdk_window);
4919 gdk_window_set_user_data (gdk_window, window);
4921 context = gtk_widget_get_style_context (widget);
4922 gtk_style_context_set_background (context, gdk_window);
4924 if (priv->transient_parent &&
4925 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4926 gdk_window_set_transient_for (gdk_window,
4927 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4930 gdk_window_set_role (gdk_window, priv->wm_role);
4932 if (!priv->decorated)
4933 gdk_window_set_decorations (gdk_window, 0);
4935 if (!priv->deletable)
4936 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4938 if (gtk_window_get_skip_pager_hint (window))
4939 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4941 if (gtk_window_get_skip_taskbar_hint (window))
4942 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4944 if (gtk_window_get_accept_focus (window))
4945 gdk_window_set_accept_focus (gdk_window, TRUE);
4947 gdk_window_set_accept_focus (gdk_window, FALSE);
4949 if (gtk_window_get_focus_on_map (window))
4950 gdk_window_set_focus_on_map (gdk_window, TRUE);
4952 gdk_window_set_focus_on_map (gdk_window, FALSE);
4955 gdk_window_set_modal_hint (gdk_window, TRUE);
4957 gdk_window_set_modal_hint (gdk_window, FALSE);
4959 if (priv->startup_id)
4961 #ifdef GDK_WINDOWING_X11
4962 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4963 if (timestamp != GDK_CURRENT_TIME)
4964 gdk_x11_window_set_user_time (gdk_window, timestamp);
4966 if (!startup_id_is_fake (priv->startup_id))
4967 gdk_window_set_startup_id (gdk_window, priv->startup_id);
4971 gtk_window_realize_icon (window);
4973 if (priv->has_resize_grip)
4974 resize_grip_create_window (window);
4978 gtk_window_unrealize (GtkWidget *widget)
4980 GtkWindow *window = GTK_WINDOW (widget);
4981 GtkWindowPrivate *priv = window->priv;
4982 GtkWindowGeometryInfo *info;
4984 /* On unrealize, we reset the size of the window such
4985 * that we will re-apply the default sizing stuff
4986 * next time we show the window.
4988 * Default positioning is reset on unmap, instead of unrealize.
4990 priv->need_default_size = TRUE;
4991 info = gtk_window_get_geometry_info (window, FALSE);
4994 info->resize_width = -1;
4995 info->resize_height = -1;
4996 info->last.configure_request.x = 0;
4997 info->last.configure_request.y = 0;
4998 info->last.configure_request.width = -1;
4999 info->last.configure_request.height = -1;
5000 /* be sure we reset geom hints on re-realize */
5001 info->last.flags = 0;
5005 gtk_window_unrealize_icon (window);
5007 if (priv->grip_window != NULL)
5008 resize_grip_destroy_window (window);
5010 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5013 static GtkJunctionSides
5014 get_grip_junction (GtkWidget *widget)
5016 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5017 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5019 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5023 get_drag_edge (GtkWidget *widget,
5024 GdkWindowEdge *edge)
5026 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5027 gboolean hresizable;
5028 gboolean vresizable;
5029 GtkTextDirection dir;
5030 GtkWindowGeometryInfo *info;
5035 info = priv->geometry_info;
5038 GdkWindowHints flags = info->last.flags;
5039 GdkGeometry *geometry = &info->last.geometry;
5041 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5043 hresizable = geometry->min_width < geometry->max_width;
5044 vresizable = geometry->min_height < geometry->max_height;
5048 dir = gtk_widget_get_direction (widget);
5050 if (hresizable && vresizable)
5051 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5052 else if (hresizable)
5053 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5054 else if (vresizable)
5055 *edge = GDK_WINDOW_EDGE_SOUTH;
5063 set_grip_cursor (GtkWindow *window)
5065 GtkWidget *widget = GTK_WIDGET (window);
5066 GtkWindowPrivate *priv = window->priv;
5068 if (priv->grip_window == NULL)
5071 if (gtk_widget_is_sensitive (widget))
5074 GdkDisplay *display;
5075 GdkCursorType cursor_type;
5078 cursor_type = GDK_LEFT_PTR;
5080 if (get_drag_edge (widget, &edge))
5084 case GDK_WINDOW_EDGE_EAST:
5085 cursor_type = GDK_RIGHT_SIDE;
5087 case GDK_WINDOW_EDGE_SOUTH_EAST:
5088 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5090 case GDK_WINDOW_EDGE_SOUTH:
5091 cursor_type = GDK_BOTTOM_SIDE;
5093 case GDK_WINDOW_EDGE_SOUTH_WEST:
5094 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5096 case GDK_WINDOW_EDGE_WEST:
5097 cursor_type = GDK_LEFT_SIDE;
5103 display = gtk_widget_get_display (widget);
5104 cursor = gdk_cursor_new_for_display (display, cursor_type);
5105 gdk_window_set_cursor (priv->grip_window, cursor);
5106 g_object_unref (cursor);
5109 gdk_window_set_cursor (priv->grip_window, NULL);
5113 set_grip_shape (GtkWindow *window)
5115 GtkWindowPrivate *priv = window->priv;
5116 cairo_region_t *region;
5117 cairo_surface_t *surface;
5119 double width, height;
5121 if (priv->grip_window == NULL)
5124 width = gdk_window_get_width (priv->grip_window);
5125 height = gdk_window_get_height (priv->grip_window);
5126 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5128 cr = cairo_create (surface);
5129 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5131 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5132 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5134 cairo_move_to (cr, width, 0.0);
5135 cairo_line_to (cr, width, height);
5136 cairo_line_to (cr, 0.0, height);
5140 cairo_move_to (cr, 0.0, 0.0);
5141 cairo_line_to (cr, width, height);
5142 cairo_line_to (cr, 0.0, height);
5144 cairo_close_path (cr);
5147 region = gdk_cairo_region_create_from_surface (surface);
5148 cairo_surface_destroy (surface);
5150 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5151 cairo_region_destroy (region);
5155 set_grip_position (GtkWindow *window)
5157 GtkWindowPrivate *priv = window->priv;
5160 if (priv->grip_window == NULL)
5163 gtk_window_get_resize_grip_area (window, &rect);
5164 gdk_window_raise (priv->grip_window);
5165 gdk_window_move_resize (priv->grip_window,
5167 rect.width, rect.height);
5171 gtk_window_size_allocate (GtkWidget *widget,
5172 GtkAllocation *allocation)
5174 GtkWindow *window = GTK_WINDOW (widget);
5175 GtkAllocation child_allocation;
5179 gtk_widget_set_allocation (widget, allocation);
5181 child = gtk_bin_get_child (&(window->bin));
5182 if (child && gtk_widget_get_visible (child))
5184 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5185 child_allocation.x = border_width;
5186 child_allocation.y = border_width;
5187 child_allocation.width =
5188 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5189 child_allocation.height =
5190 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5192 gtk_widget_size_allocate (child, &child_allocation);
5195 if (gtk_widget_get_realized (widget))
5197 update_grip_visibility (window);
5198 set_grip_position (window);
5203 gtk_window_configure_event (GtkWidget *widget,
5204 GdkEventConfigure *event)
5206 GtkAllocation allocation;
5207 GtkWindow *window = GTK_WINDOW (widget);
5208 GtkWindowPrivate *priv = window->priv;
5209 gboolean expected_reply = priv->configure_request_count > 0;
5211 /* priv->configure_request_count incremented for each
5212 * configure request, and decremented to a min of 0 for
5213 * each configure notify.
5215 * All it means is that we know we will get at least
5216 * priv->configure_request_count more configure notifies.
5217 * We could get more configure notifies than that; some
5218 * of the configure notifies we get may be unrelated to
5219 * the configure requests. But we will get at least
5220 * priv->configure_request_count notifies.
5223 if (priv->configure_request_count > 0)
5225 priv->configure_request_count -= 1;
5226 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5229 /* As an optimization, we avoid a resize when possible.
5231 * The only times we can avoid a resize are:
5232 * - we know only the position changed, not the size
5233 * - we know we have made more requests and so will get more
5234 * notifies and can wait to resize when we get them
5236 gtk_widget_get_allocation (widget, &allocation);
5237 if (!expected_reply &&
5238 (allocation.width == event->width &&
5239 allocation.height == event->height))
5241 gdk_window_configure_finished (gtk_widget_get_window (widget));
5246 * If we do need to resize, we do that by:
5247 * - filling in widget->allocation with the new size
5248 * - setting configure_notify_received to TRUE
5249 * for use in gtk_window_move_resize()
5250 * - queueing a resize, leading to invocation of
5251 * gtk_window_move_resize() in an idle handler
5255 priv->configure_notify_received = TRUE;
5257 allocation.width = event->width;
5258 allocation.height = event->height;
5259 gtk_widget_set_allocation (widget, &allocation);
5261 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5263 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5269 gtk_window_state_event (GtkWidget *widget,
5270 GdkEventWindowState *event)
5272 update_grip_visibility (GTK_WINDOW (widget));
5278 gtk_window_direction_changed (GtkWidget *widget,
5279 GtkTextDirection prev_dir)
5281 GtkWindow *window = GTK_WINDOW (widget);
5283 set_grip_cursor (window);
5284 set_grip_position (window);
5285 set_grip_shape (window);
5289 gtk_window_state_changed (GtkWidget *widget,
5290 GtkStateType previous_state)
5292 GtkWindow *window = GTK_WINDOW (widget);
5294 update_grip_visibility (window);
5298 gtk_window_style_updated (GtkWidget *widget)
5300 GtkWindow *window = GTK_WINDOW (widget);
5301 GtkWindowPrivate *priv = window->priv;
5304 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5306 gdk_window_move_resize (priv->grip_window,
5308 rect.width, rect.height);
5310 set_grip_shape (window);
5311 gtk_widget_queue_resize (widget);
5316 resize_grip_create_window (GtkWindow *window)
5319 GtkWindowPrivate *priv;
5320 GdkWindowAttr attributes;
5321 gint attributes_mask;
5324 priv = window->priv;
5325 widget = GTK_WIDGET (window);
5327 g_return_if_fail (gtk_widget_get_realized (widget));
5328 g_return_if_fail (priv->grip_window == NULL);
5330 gtk_window_get_resize_grip_area (window, &rect);
5332 attributes.x = rect.x;
5333 attributes.y = rect.y;
5334 attributes.width = rect.width;
5335 attributes.height = rect.height;
5336 attributes.window_type = GDK_WINDOW_CHILD;
5337 attributes.wclass = GDK_INPUT_OUTPUT;
5338 attributes.event_mask = gtk_widget_get_events (widget) |
5340 GDK_BUTTON_PRESS_MASK;
5342 attributes_mask = GDK_WA_X | GDK_WA_Y;
5344 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5348 gdk_window_set_user_data (priv->grip_window, widget);
5350 gdk_window_raise (priv->grip_window);
5352 set_grip_shape (window);
5353 update_grip_visibility (window);
5357 resize_grip_destroy_window (GtkWindow *window)
5359 GtkWindowPrivate *priv = window->priv;
5361 gdk_window_set_user_data (priv->grip_window, NULL);
5362 gdk_window_destroy (priv->grip_window);
5363 priv->grip_window = NULL;
5364 update_grip_visibility (window);
5368 * gtk_window_set_has_resize_grip:
5369 * @window: a #GtkWindow
5370 * @value: %TRUE to allow a resize grip
5372 * Sets whether @window has a corner resize grip.
5374 * Note that the resize grip is only shown if the window
5375 * is actually resizable and not maximized. Use
5376 * gtk_window_resize_grip_is_visible() to find out if the
5377 * resize grip is currently shown.
5382 gtk_window_set_has_resize_grip (GtkWindow *window,
5385 GtkWidget *widget = GTK_WIDGET (window);
5386 GtkWindowPrivate *priv = window->priv;
5388 value = value != FALSE;
5390 if (value != priv->has_resize_grip)
5392 priv->has_resize_grip = value;
5393 gtk_widget_queue_draw (widget);
5395 if (gtk_widget_get_realized (widget))
5397 if (priv->has_resize_grip && priv->grip_window == NULL)
5398 resize_grip_create_window (window);
5399 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5400 resize_grip_destroy_window (window);
5403 g_object_notify (G_OBJECT (window), "has-resize-grip");
5408 update_grip_visibility (GtkWindow *window)
5410 GtkWindowPrivate *priv = window->priv;
5413 val = gtk_window_resize_grip_is_visible (window);
5415 if (priv->grip_window != NULL)
5419 gdk_window_show (priv->grip_window);
5420 set_grip_cursor (window);
5424 gdk_window_hide (priv->grip_window);
5428 if (priv->resize_grip_visible != val)
5430 priv->resize_grip_visible = val;
5432 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5437 * gtk_window_resize_grip_is_visible:
5438 * @window: a #GtkWindow
5440 * Determines whether a resize grip is visible for the specified window.
5442 * Returns %TRUE if a resize grip exists and is visible.
5447 gtk_window_resize_grip_is_visible (GtkWindow *window)
5450 GtkWindowPrivate *priv;
5453 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5455 priv = window->priv;
5456 widget = GTK_WIDGET (window);
5458 if (priv->type == GTK_WINDOW_POPUP)
5461 if (!priv->resizable)
5464 if (gtk_widget_get_realized (widget))
5466 GdkWindowState state;
5468 state = gdk_window_get_state (gtk_widget_get_window (widget));
5470 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5474 if (!get_drag_edge (widget, &edge))
5477 return window->priv->has_resize_grip;
5481 * gtk_window_get_has_resize_grip:
5482 * @window: a #GtkWindow
5484 * Determines whether the window may have a resize grip.
5486 * Returns: %TRUE if the window has a resize grip.
5491 gtk_window_get_has_resize_grip (GtkWindow *window)
5493 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5495 return window->priv->has_resize_grip;
5499 * gtk_window_get_resize_grip_area:
5500 * @window: a #GtkWindow
5501 * @rect: a pointer to a #GdkRectangle which we should store the
5504 * If a window has a resize grip, this will retrieve the grip
5505 * position, width and height into the specified #GdkRectangle.
5507 * Returns: %TRUE if the resize grip's area was retrieved.
5512 gtk_window_get_resize_grip_area (GtkWindow *window,
5515 GtkWidget *widget = GTK_WIDGET (window);
5516 GtkAllocation allocation;
5520 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5522 if (!window->priv->has_resize_grip)
5525 gtk_widget_get_allocation (widget, &allocation);
5527 gtk_widget_style_get (widget,
5528 "resize-grip-width", &grip_width,
5529 "resize-grip-height", &grip_height,
5532 if (grip_width > allocation.width)
5533 grip_width = allocation.width;
5535 if (grip_height > allocation.height)
5536 grip_height = allocation.height;
5538 rect->width = grip_width;
5539 rect->height = grip_height;
5540 rect->y = allocation.y + allocation.height - grip_height;
5542 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5543 rect->x = allocation.x + allocation.width - grip_width;
5545 rect->x = allocation.x;
5550 /* the accel_key and accel_mods fields of the key have to be setup
5551 * upon calling this function. it'll then return whether that key
5552 * is at all used as accelerator, and if so will OR in the
5553 * accel_flags member of the key.
5556 _gtk_window_query_nonaccels (GtkWindow *window,
5558 GdkModifierType accel_mods)
5560 GtkWindowPrivate *priv;
5562 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5564 priv = window->priv;
5566 /* movement keys are considered locked accels */
5569 static const guint bindings[] = {
5570 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,
5571 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,
5575 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5576 if (bindings[i] == accel_key)
5580 /* mnemonics are considered locked accels */
5581 if (accel_mods == priv->mnemonic_modifier)
5583 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5584 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5592 * gtk_window_propagate_key_event:
5593 * @window: a #GtkWindow
5594 * @event: a #GdkEventKey
5596 * Propagate a key press or release event to the focus widget and
5597 * up the focus container chain until a widget handles @event.
5598 * This is normally called by the default ::key_press_event and
5599 * ::key_release_event handlers for toplevel windows,
5600 * however in some cases it may be useful to call this directly when
5601 * overriding the standard key handling for a toplevel window.
5603 * Return value: %TRUE if a widget in the focus chain handled the event.
5608 gtk_window_propagate_key_event (GtkWindow *window,
5611 GtkWindowPrivate *priv;
5612 gboolean handled = FALSE;
5613 GtkWidget *widget, *focus;
5615 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5617 priv = window->priv;
5618 widget = GTK_WIDGET (window);
5620 focus = priv->focus_widget;
5622 g_object_ref (focus);
5625 focus && focus != widget &&
5626 gtk_widget_get_toplevel (focus) == widget)
5630 if (gtk_widget_is_sensitive (focus))
5631 handled = gtk_widget_event (focus, (GdkEvent*) event);
5633 parent = gtk_widget_get_parent (focus);
5635 g_object_ref (parent);
5637 g_object_unref (focus);
5643 g_object_unref (focus);
5649 gtk_window_key_press_event (GtkWidget *widget,
5652 GtkWindow *window = GTK_WINDOW (widget);
5653 gboolean handled = FALSE;
5655 /* handle mnemonics and accelerators */
5657 handled = gtk_window_activate_key (window, event);
5659 /* handle focus widget key events */
5661 handled = gtk_window_propagate_key_event (window, event);
5663 /* Chain up, invokes binding set */
5665 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5671 gtk_window_key_release_event (GtkWidget *widget,
5674 GtkWindow *window = GTK_WINDOW (widget);
5675 gboolean handled = FALSE;
5677 /* handle focus widget key events */
5679 handled = gtk_window_propagate_key_event (window, event);
5681 /* Chain up, invokes binding set */
5683 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5689 gtk_window_button_press_event (GtkWidget *widget,
5690 GdkEventButton *event)
5692 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5695 if (event->window == priv->grip_window)
5697 if (get_drag_edge (widget, &edge))
5698 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5712 gtk_window_real_activate_default (GtkWindow *window)
5714 gtk_window_activate_default (window);
5718 gtk_window_real_activate_focus (GtkWindow *window)
5720 gtk_window_activate_focus (window);
5724 gtk_window_enter_notify_event (GtkWidget *widget,
5725 GdkEventCrossing *event)
5731 gtk_window_leave_notify_event (GtkWidget *widget,
5732 GdkEventCrossing *event)
5738 do_focus_change (GtkWidget *widget,
5742 GdkDeviceManager *device_manager;
5745 g_object_ref (widget);
5747 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5748 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5749 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5750 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5752 for (d = devices; d; d = d->next)
5754 GdkDevice *dev = d->data;
5757 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5760 /* Skip non-master keyboards that haven't
5761 * selected for events from this window
5763 window = gtk_widget_get_window (widget);
5764 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5765 window && !gdk_window_get_device_events (window, dev))
5768 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5770 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5771 fevent->focus_change.window = window;
5773 g_object_ref (window);
5774 fevent->focus_change.in = in;
5775 gdk_event_set_device (fevent, dev);
5777 gtk_widget_send_focus_change (widget, fevent);
5779 gdk_event_free (fevent);
5782 g_list_free (devices);
5783 g_object_unref (widget);
5787 gtk_window_focus_in_event (GtkWidget *widget,
5788 GdkEventFocus *event)
5790 GtkWindow *window = GTK_WINDOW (widget);
5792 /* It appears spurious focus in events can occur when
5793 * the window is hidden. So we'll just check to see if
5794 * the window is visible before actually handling the
5797 if (gtk_widget_get_visible (widget))
5799 _gtk_window_set_has_toplevel_focus (window, TRUE);
5800 _gtk_window_set_is_active (window, TRUE);
5807 gtk_window_focus_out_event (GtkWidget *widget,
5808 GdkEventFocus *event)
5810 GtkWindow *window = GTK_WINDOW (widget);
5811 gboolean auto_mnemonics;
5813 _gtk_window_set_has_toplevel_focus (window, FALSE);
5814 _gtk_window_set_is_active (window, FALSE);
5816 /* set the mnemonic-visible property to false */
5817 g_object_get (gtk_widget_get_settings (widget),
5818 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5820 gtk_window_set_mnemonics_visible (window, FALSE);
5825 static GdkAtom atom_rcfiles = GDK_NONE;
5826 static GdkAtom atom_iconthemes = GDK_NONE;
5829 send_client_message_to_embedded_windows (GtkWidget *widget,
5830 GdkAtom message_type)
5832 GList *embedded_windows;
5834 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5835 if (embedded_windows)
5837 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5840 for (i = 0; i < 5; i++)
5841 send_event->client.data.l[i] = 0;
5842 send_event->client.data_format = 32;
5843 send_event->client.message_type = message_type;
5845 while (embedded_windows)
5847 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5848 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5849 embedded_windows = embedded_windows->next;
5852 gdk_event_free (send_event);
5857 gtk_window_client_event (GtkWidget *widget,
5858 GdkEventClient *event)
5862 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5863 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5866 if (event->message_type == atom_rcfiles)
5868 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5869 gtk_style_context_reset_widgets (gtk_widget_get_screen (widget));
5872 if (event->message_type == atom_iconthemes)
5874 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5875 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5882 gtk_window_check_resize (GtkContainer *container)
5884 if (gtk_widget_get_visible (GTK_WIDGET (container)))
5885 gtk_window_move_resize (GTK_WINDOW (container));
5889 gtk_window_focus (GtkWidget *widget,
5890 GtkDirectionType direction)
5892 GtkWindowPrivate *priv;
5895 GtkContainer *container;
5897 GtkWidget *old_focus_child;
5900 container = GTK_CONTAINER (widget);
5901 window = GTK_WINDOW (widget);
5902 priv = window->priv;
5903 bin = GTK_BIN (widget);
5905 old_focus_child = gtk_container_get_focus_child (container);
5907 /* We need a special implementation here to deal properly with wrapping
5908 * around in the tab chain without the danger of going into an
5911 if (old_focus_child)
5913 if (gtk_widget_child_focus (old_focus_child, direction))
5917 if (priv->focus_widget)
5919 if (direction == GTK_DIR_LEFT ||
5920 direction == GTK_DIR_RIGHT ||
5921 direction == GTK_DIR_UP ||
5922 direction == GTK_DIR_DOWN)
5927 /* Wrapped off the end, clear the focus setting for the toplpevel */
5928 parent = gtk_widget_get_parent (priv->focus_widget);
5931 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5932 parent = gtk_widget_get_parent (parent);
5935 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5938 /* Now try to focus the first widget in the window */
5939 child = gtk_bin_get_child (bin);
5942 if (gtk_widget_child_focus (child, direction))
5950 gtk_window_move_focus (GtkWidget *widget,
5951 GtkDirectionType dir)
5953 gtk_widget_child_focus (widget, dir);
5955 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
5956 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
5960 gtk_window_real_set_focus (GtkWindow *window,
5963 GtkWindowPrivate *priv = window->priv;
5964 GtkWidget *old_focus = priv->focus_widget;
5965 gboolean had_default = FALSE;
5966 gboolean focus_had_default = FALSE;
5967 gboolean old_focus_had_default = FALSE;
5971 g_object_ref (old_focus);
5972 g_object_freeze_notify (G_OBJECT (old_focus));
5973 old_focus_had_default = gtk_widget_has_default (old_focus);
5977 g_object_ref (focus);
5978 g_object_freeze_notify (G_OBJECT (focus));
5979 focus_had_default = gtk_widget_has_default (focus);
5982 if (priv->default_widget)
5983 had_default = gtk_widget_has_default (priv->default_widget);
5985 if (priv->focus_widget)
5987 if (gtk_widget_get_receives_default (priv->focus_widget) &&
5988 (priv->focus_widget != priv->default_widget))
5990 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
5991 gtk_widget_queue_draw (priv->focus_widget);
5993 if (priv->default_widget)
5994 _gtk_widget_set_has_default (priv->default_widget, TRUE);
5997 priv->focus_widget = NULL;
5999 if (priv->has_focus)
6000 do_focus_change (old_focus, FALSE);
6002 g_object_notify (G_OBJECT (old_focus), "is-focus");
6005 /* The above notifications may have set a new focus widget,
6006 * if so, we don't want to override it.
6008 if (focus && !priv->focus_widget)
6010 priv->focus_widget = focus;
6012 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6013 (priv->focus_widget != priv->default_widget))
6015 if (gtk_widget_get_can_default (priv->focus_widget))
6016 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6018 if (priv->default_widget)
6019 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6022 if (priv->has_focus)
6023 do_focus_change (priv->focus_widget, TRUE);
6025 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6028 /* If the default widget changed, a redraw will have been queued
6029 * on the old and new default widgets by gtk_window_set_default(), so
6030 * we only have to worry about the case where it didn't change.
6031 * We'll sometimes queue a draw twice on the new widget but that
6034 if (priv->default_widget &&
6035 (had_default != gtk_widget_has_default (priv->default_widget)))
6036 gtk_widget_queue_draw (priv->default_widget);
6040 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6041 gtk_widget_queue_draw (old_focus);
6043 g_object_thaw_notify (G_OBJECT (old_focus));
6044 g_object_unref (old_focus);
6048 if (focus_had_default != gtk_widget_has_default (focus))
6049 gtk_widget_queue_draw (focus);
6051 g_object_thaw_notify (G_OBJECT (focus));
6052 g_object_unref (focus);
6058 gtk_window_get_preferred_width (GtkWidget *widget,
6066 window = GTK_WINDOW (widget);
6067 child = gtk_bin_get_child (GTK_BIN (window));
6069 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6070 *minimum_size = border_width * 2;
6071 *natural_size = border_width * 2;
6073 if (child && gtk_widget_get_visible (child))
6075 gint child_min, child_nat;
6076 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6078 *minimum_size += child_min;
6079 *natural_size += child_nat;
6084 gtk_window_get_preferred_height (GtkWidget *widget,
6092 window = GTK_WINDOW (widget);
6093 child = gtk_bin_get_child (GTK_BIN (window));
6095 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6096 *minimum_size = border_width * 2;
6097 *natural_size = border_width * 2;
6099 if (child && gtk_widget_get_visible (child))
6101 gint child_min, child_nat;
6102 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6104 *minimum_size += child_min;
6105 *natural_size += child_nat;
6111 * _gtk_window_unset_focus_and_default:
6112 * @window: a #GtkWindow
6113 * @widget: a widget inside of @window
6115 * Checks whether the focus and default widgets of @window are
6116 * @widget or a descendent of @widget, and if so, unset them.
6119 _gtk_window_unset_focus_and_default (GtkWindow *window,
6123 GtkWindowPrivate *priv = window->priv;
6127 g_object_ref (window);
6128 g_object_ref (widget);
6130 parent = gtk_widget_get_parent (widget);
6131 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6133 child = priv->focus_widget;
6135 while (child && child != widget)
6136 child = gtk_widget_get_parent (child);
6138 if (child == widget)
6139 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6142 child = priv->default_widget;
6144 while (child && child != widget)
6145 child = gtk_widget_get_parent (child);
6147 if (child == widget)
6148 gtk_window_set_default (window, NULL);
6150 g_object_unref (widget);
6151 g_object_unref (window);
6154 /*********************************
6155 * Functions related to resizing *
6156 *********************************/
6159 geometry_size_to_pixels (GdkGeometry *geometry,
6164 gint base_width = 0;
6165 gint base_height = 0;
6167 gint min_height = 0;
6169 gint height_inc = 1;
6171 if (flags & GDK_HINT_BASE_SIZE)
6173 base_width = geometry->base_width;
6174 base_height = geometry->base_height;
6176 if (flags & GDK_HINT_MIN_SIZE)
6178 min_width = geometry->min_width;
6179 min_height = geometry->min_height;
6181 if (flags & GDK_HINT_RESIZE_INC)
6183 width_inc = geometry->width_inc;
6184 height_inc = geometry->height_inc;
6188 *width = MAX (*width * width_inc + base_width, min_width);
6190 *height = MAX (*height * height_inc + base_height, min_height);
6193 /* This function doesn't constrain to geometry hints */
6195 gtk_window_compute_configure_request_size (GtkWindow *window,
6196 GdkGeometry *geometry,
6201 GtkWindowPrivate *priv = window->priv;
6202 GtkRequisition requisition;
6203 GtkWindowGeometryInfo *info;
6207 * - we've done a size request
6210 widget = GTK_WIDGET (window);
6212 info = gtk_window_get_geometry_info (window, FALSE);
6214 if (priv->need_default_size)
6216 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6218 /* Default to requisition */
6219 *width = requisition.width;
6220 *height = requisition.height;
6222 /* If window is empty so requests 0, default to random nonzero size */
6223 if (*width == 0 && *height == 0)
6229 /* Override requisition with default size */
6233 if (info->default_width > 0)
6234 *width = info->default_width;
6235 if (info->default_height > 0)
6236 *height = info->default_height;
6238 if (info->default_is_geometry)
6239 geometry_size_to_pixels (geometry, flags,
6240 info->default_width > 0 ? width : NULL,
6241 info->default_height > 0 ? height : NULL);
6246 GtkAllocation allocation;
6248 gtk_widget_get_allocation (widget, &allocation);
6250 /* Default to keeping current size */
6251 *width = allocation.width;
6252 *height = allocation.height;
6255 /* Override any size with gtk_window_resize() values */
6258 if (info->resize_width > 0)
6259 *width = info->resize_width;
6260 if (info->resize_height > 0)
6261 *height = info->resize_height;
6263 if (info->resize_is_geometry)
6264 geometry_size_to_pixels (geometry, flags,
6265 info->resize_width > 0 ? width : NULL,
6266 info->resize_height > 0 ? height : NULL);
6269 /* Don't ever request zero width or height, its not supported by
6270 gdk. The size allocation code will round it to 1 anyway but if
6271 we do it then the value returned from this function will is
6272 not comparable to the size allocation read from the GtkWindow. */
6273 *width = MAX (*width, 1);
6274 *height = MAX (*height, 1);
6277 static GtkWindowPosition
6278 get_effective_position (GtkWindow *window)
6280 GtkWindowPrivate *priv = window->priv;
6281 GtkWindowPosition pos = priv->position;
6283 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6284 (priv->transient_parent == NULL ||
6285 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6286 pos = GTK_WIN_POS_NONE;
6292 get_center_monitor_of_window (GtkWindow *window)
6294 /* We could try to sort out the relative positions of the monitors and
6295 * stuff, or we could just be losers and assume you have a row
6296 * or column of monitors.
6298 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6302 get_monitor_containing_pointer (GtkWindow *window)
6306 GdkScreen *window_screen;
6307 GdkScreen *pointer_screen;
6308 GdkDisplay *display;
6309 GdkDeviceManager *device_manager;
6312 window_screen = gtk_window_check_screen (window);
6313 display = gdk_screen_get_display (window_screen);
6314 device_manager = gdk_display_get_device_manager (display);
6315 pointer = gdk_device_manager_get_client_pointer (device_manager);
6317 gdk_device_get_position (pointer,
6321 if (pointer_screen == window_screen)
6322 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6330 center_window_on_monitor (GtkWindow *window,
6336 GdkRectangle monitor;
6339 monitor_num = get_monitor_containing_pointer (window);
6341 if (monitor_num == -1)
6342 monitor_num = get_center_monitor_of_window (window);
6344 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6345 monitor_num, &monitor);
6347 *x = (monitor.width - w) / 2 + monitor.x;
6348 *y = (monitor.height - h) / 2 + monitor.y;
6350 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6351 * and WM decorations.
6365 if (extent > clamp_extent)
6367 *base = clamp_base + clamp_extent/2 - extent/2;
6368 else if (*base < clamp_base)
6370 else if (*base + extent > clamp_base + clamp_extent)
6371 *base = clamp_base + clamp_extent - extent;
6375 clamp_window_to_rectangle (gint *x,
6379 const GdkRectangle *rect)
6381 #ifdef DEBUGGING_OUTPUT
6382 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);
6385 /* If it is too large, center it. If it fits on the monitor but is
6386 * partially outside, move it to the closest edge. Do this
6387 * separately in x and y directions.
6389 clamp (x, w, rect->x, rect->width);
6390 clamp (y, h, rect->y, rect->height);
6391 #ifdef DEBUGGING_OUTPUT
6392 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6398 gtk_window_compute_configure_request (GtkWindow *window,
6399 GdkRectangle *request,
6400 GdkGeometry *geometry,
6403 GtkWindowPrivate *priv = window->priv;
6404 GdkGeometry new_geometry;
6408 GtkWindowPosition pos;
6409 GtkWidget *parent_widget;
6410 GtkWindowGeometryInfo *info;
6414 widget = GTK_WIDGET (window);
6416 screen = gtk_window_check_screen (window);
6418 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6419 gtk_window_compute_configure_request_size (window,
6420 &new_geometry, new_flags,
6421 (guint *)&w, (guint *)&h);
6423 gtk_window_constrain_size (window,
6424 &new_geometry, new_flags,
6428 parent_widget = (GtkWidget*) priv->transient_parent;
6430 pos = get_effective_position (window);
6431 info = gtk_window_get_geometry_info (window, FALSE);
6433 /* by default, don't change position requested */
6436 x = info->last.configure_request.x;
6437 y = info->last.configure_request.y;
6446 if (priv->need_default_position)
6449 /* FIXME this all interrelates with window gravity.
6450 * For most of them I think we want to set GRAVITY_CENTER.
6452 * Not sure how to go about that.
6457 /* here we are only handling CENTER_ALWAYS
6458 * as it relates to default positioning,
6459 * where it's equivalent to simply CENTER
6461 case GTK_WIN_POS_CENTER_ALWAYS:
6462 case GTK_WIN_POS_CENTER:
6463 center_window_on_monitor (window, w, h, &x, &y);
6466 case GTK_WIN_POS_CENTER_ON_PARENT:
6468 GtkAllocation allocation;
6469 GdkWindow *gdk_window;
6471 GdkRectangle monitor;
6474 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6476 gdk_window = gtk_widget_get_window (parent_widget);
6478 if (gdk_window != NULL)
6479 monitor_num = gdk_screen_get_monitor_at_window (screen,
6484 gdk_window_get_origin (gdk_window,
6487 gtk_widget_get_allocation (parent_widget, &allocation);
6488 x = ox + (allocation.width - w) / 2;
6489 y = oy + (allocation.height - h) / 2;
6491 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6492 * WM decorations. If parent wasn't on a monitor, just
6495 if (monitor_num >= 0)
6497 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6498 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6503 case GTK_WIN_POS_MOUSE:
6505 gint screen_width = gdk_screen_get_width (screen);
6506 gint screen_height = gdk_screen_get_height (screen);
6508 GdkRectangle monitor;
6509 GdkDisplay *display;
6510 GdkDeviceManager *device_manager;
6512 GdkScreen *pointer_screen;
6515 display = gdk_screen_get_display (screen);
6516 device_manager = gdk_display_get_device_manager (display);
6517 pointer = gdk_device_manager_get_client_pointer (device_manager);
6519 gdk_device_get_position (pointer,
6523 if (pointer_screen == screen)
6524 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6530 x = CLAMP (x, 0, screen_width - w);
6531 y = CLAMP (y, 0, screen_height - h);
6533 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6534 * WM decorations. Don't try to figure out what's going
6535 * on if the mouse wasn't inside a monitor.
6537 if (monitor_num >= 0)
6539 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6540 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6548 } /* if (priv->need_default_position) */
6550 if (priv->need_default_position && info &&
6551 info->initial_pos_set)
6553 x = info->initial_x;
6554 y = info->initial_y;
6555 gtk_window_constrain_position (window, w, h, &x, &y);
6561 request->height = h;
6564 *geometry = new_geometry;
6570 gtk_window_constrain_position (GtkWindow *window,
6576 GtkWindowPrivate *priv = window->priv;
6578 /* See long comments in gtk_window_move_resize()
6579 * on when it's safe to call this function.
6581 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6583 gint center_x, center_y;
6585 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6593 gtk_window_move_resize (GtkWindow *window)
6597 * First we determine whether any information has changed that would
6598 * cause us to revise our last configure request. If we would send
6599 * a different configure request from last time, then
6600 * configure_request_size_changed = TRUE or
6601 * configure_request_pos_changed = TRUE. configure_request_size_changed
6602 * may be true due to new hints, a gtk_window_resize(), or whatever.
6603 * configure_request_pos_changed may be true due to gtk_window_set_position()
6604 * or gtk_window_move().
6606 * If the configure request has changed, we send off a new one. To
6607 * ensure GTK+ invariants are maintained (resize queue does what it
6608 * should), we go ahead and size_allocate the requested size in this
6611 * If the configure request has not changed, we don't ever resend
6612 * it, because it could mean fighting the user or window manager.
6615 * To prepare the configure request, we come up with a base size/pos:
6616 * - the one from gtk_window_move()/gtk_window_resize()
6617 * - else default_width, default_height if we haven't ever
6619 * - else the size request if we haven't ever been mapped,
6620 * as a substitute default size
6621 * - else the current size of the window, as received from
6622 * configure notifies (i.e. the current allocation)
6624 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6625 * the position request to be centered.
6627 GtkWindowPrivate *priv = window->priv;
6628 GtkAllocation allocation;
6630 GtkContainer *container;
6631 GtkWindowGeometryInfo *info;
6632 GdkGeometry new_geometry;
6633 GdkWindow *gdk_window;
6635 GdkRectangle new_request;
6636 gboolean configure_request_size_changed;
6637 gboolean configure_request_pos_changed;
6638 gboolean hints_changed; /* do we need to send these again */
6639 GtkWindowLastGeometryInfo saved_last_info;
6641 widget = GTK_WIDGET (window);
6642 gdk_window = gtk_widget_get_window (widget);
6643 container = GTK_CONTAINER (widget);
6644 info = gtk_window_get_geometry_info (window, TRUE);
6646 configure_request_size_changed = FALSE;
6647 configure_request_pos_changed = FALSE;
6649 gtk_window_compute_configure_request (window, &new_request,
6650 &new_geometry, &new_flags);
6652 /* This check implies the invariant that we never set info->last
6653 * without setting the hints and sending off a configure request.
6655 * If we change info->last without sending the request, we may
6658 if (info->last.configure_request.x != new_request.x ||
6659 info->last.configure_request.y != new_request.y)
6660 configure_request_pos_changed = TRUE;
6662 if ((info->last.configure_request.width != new_request.width ||
6663 info->last.configure_request.height != new_request.height))
6664 configure_request_size_changed = TRUE;
6666 hints_changed = FALSE;
6668 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6669 &new_geometry, new_flags))
6671 hints_changed = TRUE;
6674 /* Position Constraints
6675 * ====================
6677 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6678 * a default. The other POS_ values are used only when the
6679 * window is shown, not after that.
6681 * However, we can't implement a position constraint as
6682 * "anytime the window size changes, center the window"
6683 * because this may well end up fighting the WM or user. In
6684 * fact it gets in an infinite loop with at least one WM.
6686 * Basically, applications are in no way in a position to
6687 * constrain the position of a window, with one exception:
6688 * override redirect windows. (Really the intended purpose
6689 * of CENTER_ALWAYS anyhow, I would think.)
6691 * So the way we implement this "constraint" is to say that when WE
6692 * cause a move or resize, i.e. we make a configure request changing
6693 * window size, we recompute the CENTER_ALWAYS position to reflect
6694 * the new window size, and include it in our request. Also, if we
6695 * just turned on CENTER_ALWAYS we snap to center with a new
6696 * request. Otherwise, if we are just NOTIFIED of a move or resize
6697 * done by someone else e.g. the window manager, we do NOT send a
6698 * new configure request.
6700 * For override redirect windows, this works fine; all window
6701 * sizes are from our configure requests. For managed windows,
6702 * it is at least semi-sane, though who knows what the
6703 * app author is thinking.
6706 /* This condition should be kept in sync with the condition later on
6707 * that determines whether we send a configure request. i.e. we
6708 * should do this position constraining anytime we were going to
6709 * send a configure request anyhow, plus when constraints have
6712 if (configure_request_pos_changed ||
6713 configure_request_size_changed ||
6715 info->position_constraints_changed)
6717 /* We request the constrained position if:
6718 * - we were changing position, and need to clamp
6719 * the change to the constraint
6720 * - we're changing the size anyway
6721 * - set_position() was called to toggle CENTER_ALWAYS on
6724 gtk_window_constrain_position (window,
6730 /* Update whether we need to request a move */
6731 if (info->last.configure_request.x != new_request.x ||
6732 info->last.configure_request.y != new_request.y)
6733 configure_request_pos_changed = TRUE;
6735 configure_request_pos_changed = FALSE;
6739 if (priv->type == GTK_WINDOW_TOPLEVEL)
6741 int notify_x, notify_y;
6743 /* this is the position from the last configure notify */
6744 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6746 g_message ("--- %s ---\n"
6747 "last : %d,%d\t%d x %d\n"
6748 "this : %d,%d\t%d x %d\n"
6749 "alloc : %d,%d\t%d x %d\n"
6751 "resize: \t%d x %d\n"
6752 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6753 "configure_notify_received: %d\n"
6754 "configure_request_count: %d\n"
6755 "position_constraints_changed: %d\n",
6756 priv->title ? priv->title : "(no title)",
6757 info->last.configure_request.x,
6758 info->last.configure_request.y,
6759 info->last.configure_request.width,
6760 info->last.configure_request.height,
6766 widget->allocation.width,
6767 widget->allocation.height,
6768 widget->requisition.width,
6769 widget->requisition.height,
6771 info->resize_height,
6772 configure_request_pos_changed,
6773 configure_request_size_changed,
6775 priv->configure_notify_received,
6776 priv->configure_request_count,
6777 info->position_constraints_changed);
6781 saved_last_info = info->last;
6782 info->last.geometry = new_geometry;
6783 info->last.flags = new_flags;
6784 info->last.configure_request = new_request;
6786 /* need to set PPosition so the WM will look at our position,
6787 * but we don't want to count PPosition coming and going as a hints
6788 * change for future iterations. So we saved info->last prior to
6792 /* Also, if the initial position was explicitly set, then we always
6793 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6797 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6798 * this is an initial map
6801 if ((configure_request_pos_changed ||
6802 info->initial_pos_set ||
6803 (priv->need_default_position &&
6804 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6805 (new_flags & GDK_HINT_POS) == 0)
6807 new_flags |= GDK_HINT_POS;
6808 hints_changed = TRUE;
6811 /* Set hints if necessary
6814 gdk_window_set_geometry_hints (gdk_window,
6818 gtk_widget_get_allocation (widget, &allocation);
6820 /* handle resizing/moving and widget tree allocation
6822 if (priv->configure_notify_received)
6824 /* If we have received a configure event since
6825 * the last time in this function, we need to
6826 * accept our new size and size_allocate child widgets.
6827 * (see gtk_window_configure_event() for more details).
6829 * 1 or more configure notifies may have been received.
6830 * Also, configure_notify_received will only be TRUE
6831 * if all expected configure notifies have been received
6832 * (one per configure request), as an optimization.
6835 priv->configure_notify_received = FALSE;
6837 /* gtk_window_configure_event() filled in widget->allocation */
6838 gtk_widget_size_allocate (widget, &allocation);
6840 set_grip_position (window);
6841 update_grip_visibility (window);
6843 gdk_window_process_updates (gdk_window, TRUE);
6845 gdk_window_configure_finished (gdk_window);
6847 /* If the configure request changed, it means that
6849 * 1) coincidentally changed hints or widget properties
6850 * impacting the configure request before getting
6851 * a configure notify, or
6852 * 2) some broken widget is changing its size request
6853 * during size allocation, resulting in
6854 * a false appearance of changed configure request.
6856 * For 1), we could just go ahead and ask for the
6857 * new size right now, but doing that for 2)
6858 * might well be fighting the user (and can even
6859 * trigger a loop). Since we really don't want to
6860 * do that, we requeue a resize in hopes that
6861 * by the time it gets handled, the child has seen
6862 * the light and is willing to go along with the
6863 * new size. (this happens for the zvt widget, since
6864 * the size_allocate() above will have stored the
6865 * requisition corresponding to the new size in the
6868 * This doesn't buy us anything for 1), but it shouldn't
6869 * hurt us too badly, since it is what would have
6870 * happened if we had gotten the configure event before
6871 * the new size had been set.
6874 if (configure_request_size_changed ||
6875 configure_request_pos_changed)
6877 /* Don't change the recorded last info after all, because we
6878 * haven't actually updated to the new info yet - we decided
6879 * to postpone our configure request until later.
6881 info->last = saved_last_info;
6883 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6886 return; /* Bail out, we didn't really process the move/resize */
6888 else if ((configure_request_size_changed || hints_changed) &&
6889 (allocation.width != new_request.width || allocation.height != new_request.height))
6892 /* We are in one of the following situations:
6893 * A. configure_request_size_changed
6894 * our requisition has changed and we need a different window size,
6895 * so we request it from the window manager.
6896 * B. !configure_request_size_changed && hints_changed
6897 * the window manager rejects our size, but we have just changed the
6898 * window manager hints, so there's a chance our request will
6899 * be honoured this time, so we try again.
6901 * However, if the new requisition is the same as the current allocation,
6902 * we don't request it again, since we won't get a ConfigureNotify back from
6903 * the window manager unless it decides to change our requisition. If
6904 * we don't get the ConfigureNotify back, the resize queue will never be run.
6907 /* Now send the configure request */
6908 if (configure_request_pos_changed)
6910 gdk_window_move_resize (gdk_window,
6911 new_request.x, new_request.y,
6912 new_request.width, new_request.height);
6914 else /* only size changed */
6916 gdk_window_resize (gdk_window,
6917 new_request.width, new_request.height);
6920 if (priv->type == GTK_WINDOW_POPUP)
6922 GtkAllocation allocation;
6924 /* Directly size allocate for override redirect (popup) windows. */
6927 allocation.width = new_request.width;
6928 allocation.height = new_request.height;
6930 gtk_widget_size_allocate (widget, &allocation);
6932 gdk_window_process_updates (gdk_window, TRUE);
6934 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6935 gtk_widget_queue_draw (widget);
6939 /* Increment the number of have-not-yet-received-notify requests */
6940 priv->configure_request_count += 1;
6941 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
6943 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6944 * configure event in response to our resizing request.
6945 * the configure event will cause a new resize with
6946 * ->configure_notify_received=TRUE.
6947 * until then, we want to
6948 * - discard expose events
6949 * - coalesce resizes for our children
6950 * - defer any window resizes until the configure event arrived
6951 * to achieve this, we queue a resize for the window, but remove its
6952 * resizing handler, so resizing will not be handled from the next
6953 * idle handler but when the configure event arrives.
6955 * FIXME: we should also dequeue the pending redraws here, since
6956 * we handle those ourselves upon ->configure_notify_received==TRUE.
6958 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6960 gtk_widget_queue_resize_no_redraw (widget);
6961 _gtk_container_dequeue_resize_handler (container);
6967 /* Handle any position changes.
6969 if (configure_request_pos_changed)
6971 gdk_window_move (gdk_window,
6972 new_request.x, new_request.y);
6975 /* And run the resize queue.
6977 gtk_container_resize_children (container);
6980 /* We have now processed a move/resize since the last position
6981 * constraint change, setting of the initial position, or resize.
6982 * (Not resetting these flags here can lead to infinite loops for
6983 * GTK_RESIZE_IMMEDIATE containers)
6985 info->position_constraints_changed = FALSE;
6986 info->initial_pos_set = FALSE;
6987 info->resize_width = -1;
6988 info->resize_height = -1;
6991 /* Compare two sets of Geometry hints for equality.
6994 gtk_window_compare_hints (GdkGeometry *geometry_a,
6996 GdkGeometry *geometry_b,
6999 if (flags_a != flags_b)
7002 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7003 (geometry_a->min_width != geometry_b->min_width ||
7004 geometry_a->min_height != geometry_b->min_height))
7007 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7008 (geometry_a->max_width != geometry_b->max_width ||
7009 geometry_a->max_height != geometry_b->max_height))
7012 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7013 (geometry_a->base_width != geometry_b->base_width ||
7014 geometry_a->base_height != geometry_b->base_height))
7017 if ((flags_a & GDK_HINT_ASPECT) &&
7018 (geometry_a->min_aspect != geometry_b->min_aspect ||
7019 geometry_a->max_aspect != geometry_b->max_aspect))
7022 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7023 (geometry_a->width_inc != geometry_b->width_inc ||
7024 geometry_a->height_inc != geometry_b->height_inc))
7027 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7028 geometry_a->win_gravity != geometry_b->win_gravity)
7035 _gtk_window_constrain_size (GtkWindow *window,
7041 GtkWindowPrivate *priv;
7042 GtkWindowGeometryInfo *info;
7044 g_return_if_fail (GTK_IS_WINDOW (window));
7046 priv = window->priv;
7048 info = priv->geometry_info;
7051 GdkWindowHints flags = info->last.flags;
7052 GdkGeometry *geometry = &info->last.geometry;
7054 gtk_window_constrain_size (window,
7065 gtk_window_constrain_size (GtkWindow *window,
7066 GdkGeometry *geometry,
7073 gdk_window_constrain_size (geometry, flags, width, height,
7074 new_width, new_height);
7077 /* Compute the set of geometry hints and flags for a window
7078 * based on the application set geometry, and requisition
7079 * of the window. gtk_widget_get_preferred_size() must have been
7083 gtk_window_compute_hints (GtkWindow *window,
7084 GdkGeometry *new_geometry,
7087 GtkWindowPrivate *priv = window->priv;
7089 gint extra_width = 0;
7090 gint extra_height = 0;
7091 GtkWindowGeometryInfo *geometry_info;
7092 GtkRequisition requisition;
7094 widget = GTK_WIDGET (window);
7096 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7097 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7101 *new_flags = geometry_info->mask;
7102 *new_geometry = geometry_info->geometry;
7109 if (geometry_info && geometry_info->widget)
7111 /* If the geometry widget is set, then the hints really apply to that
7112 * widget. This is pretty much meaningless unless the window layout
7113 * is such that the rest of the window adds fixed size borders to
7114 * the geometry widget. Our job is to figure the size of the borders;
7115 * We do that by asking how big the toplevel would be if the
7116 * geometry widget was *really big*.
7119 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7120 * |GGGGG B| in the border can confuse things
7126 * |AAAAAAAAA | When the geometry widget is large, things are
7127 * |GGGGGGGGGGB| clearer.
7132 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7133 GtkRequisition requisition;
7134 int current_width, current_height;
7136 _gtk_widget_override_size_request (geometry_info->widget,
7137 TEMPORARY_SIZE, TEMPORARY_SIZE,
7138 ¤t_width, ¤t_height);
7139 gtk_widget_get_preferred_size (widget,
7140 &requisition, NULL);
7141 _gtk_widget_restore_size_request (geometry_info->widget,
7142 current_width, current_height);
7144 extra_width = requisition.width - TEMPORARY_SIZE;
7145 extra_height = requisition.height - TEMPORARY_SIZE;
7147 if (extra_width < 0 || extra_width < 0)
7149 g_warning("Toplevel size doesn't seem to directly depend on the "
7150 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7151 "The geometry widget might not be in the window, or it might not "
7152 "be packed into the window appropriately");
7153 extra_width = MAX(extra_width, 0);
7154 extra_height = MAX(extra_height, 0);
7156 #undef TEMPORARY_SIZE
7159 /* We don't want to set GDK_HINT_POS in here, we just set it
7160 * in gtk_window_move_resize() when we want the position
7164 if (*new_flags & GDK_HINT_BASE_SIZE)
7166 new_geometry->base_width += extra_width;
7167 new_geometry->base_height += extra_height;
7171 /* For simplicity, we always set the base hint, even when we
7172 * don't expect it to have any visible effect.
7173 * (Note: geometry_size_to_pixels() depends on this.)
7175 *new_flags |= GDK_HINT_BASE_SIZE;
7177 new_geometry->base_width = extra_width;
7178 new_geometry->base_height = extra_height;
7180 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7181 * base size is the minimum size */
7182 if (*new_flags & GDK_HINT_MIN_SIZE)
7184 if (new_geometry->min_width > 0)
7185 new_geometry->base_width += new_geometry->min_width;
7186 if (new_geometry->min_height > 0)
7187 new_geometry->base_height += new_geometry->min_height;
7191 if (*new_flags & GDK_HINT_MIN_SIZE)
7193 if (new_geometry->min_width < 0)
7194 new_geometry->min_width = requisition.width;
7196 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7198 if (new_geometry->min_height < 0)
7199 new_geometry->min_height = requisition.height;
7201 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7205 *new_flags |= GDK_HINT_MIN_SIZE;
7207 new_geometry->min_width = requisition.width;
7208 new_geometry->min_height = requisition.height;
7211 if (*new_flags & GDK_HINT_MAX_SIZE)
7213 if (new_geometry->max_width < 0)
7214 new_geometry->max_width = requisition.width;
7216 new_geometry->max_width += extra_width;
7218 if (new_geometry->max_height < 0)
7219 new_geometry->max_height = requisition.height;
7221 new_geometry->max_height += extra_height;
7223 else if (!priv->resizable)
7225 *new_flags |= GDK_HINT_MAX_SIZE;
7227 new_geometry->max_width = requisition.width;
7228 new_geometry->max_height = requisition.height;
7231 *new_flags |= GDK_HINT_WIN_GRAVITY;
7232 new_geometry->win_gravity = priv->gravity;
7235 /***********************
7236 * Redrawing functions *
7237 ***********************/
7240 gtk_window_draw (GtkWidget *widget,
7243 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7244 GtkStyleContext *context;
7245 gboolean ret = FALSE;
7247 context = gtk_widget_get_style_context (widget);
7249 gtk_style_context_save (context);
7251 if (!gtk_widget_get_app_paintable (widget))
7253 GtkStateFlags state;
7255 state = gtk_widget_get_state_flags (widget);
7257 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7258 state |= GTK_STATE_FLAG_FOCUSED;
7260 gtk_style_context_set_state (context, state);
7261 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7262 gtk_render_background (context, cr, 0, 0,
7263 gtk_widget_get_allocated_width (widget),
7264 gtk_widget_get_allocated_height (widget));
7267 gtk_style_context_restore (context);
7269 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7270 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7272 if (priv->grip_window != NULL &&
7273 gtk_cairo_should_draw_window (cr, priv->grip_window))
7277 gtk_style_context_save (context);
7280 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7281 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7283 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7284 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7285 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7288 gtk_style_context_restore (context);
7295 * gtk_window_present:
7296 * @window: a #GtkWindow
7298 * Presents a window to the user. This may mean raising the window
7299 * in the stacking order, deiconifying it, moving it to the current
7300 * desktop, and/or giving it the keyboard focus, possibly dependent
7301 * on the user's platform, window manager, and preferences.
7303 * If @window is hidden, this function calls gtk_widget_show()
7306 * This function should be used when the user tries to open a window
7307 * that's already open. Say for example the preferences dialog is
7308 * currently open, and the user chooses Preferences from the menu
7309 * a second time; use gtk_window_present() to move the already-open dialog
7310 * where the user can see it.
7312 * If you are calling this function in response to a user interaction,
7313 * it is preferable to use gtk_window_present_with_time().
7317 gtk_window_present (GtkWindow *window)
7319 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7323 * gtk_window_present_with_time:
7324 * @window: a #GtkWindow
7325 * @timestamp: the timestamp of the user interaction (typically a
7326 * button or key press event) which triggered this call
7328 * Presents a window to the user in response to a user interaction.
7329 * If you need to present a window without a timestamp, use
7330 * gtk_window_present(). See gtk_window_present() for details.
7335 gtk_window_present_with_time (GtkWindow *window,
7339 GdkWindow *gdk_window;
7341 g_return_if_fail (GTK_IS_WINDOW (window));
7343 widget = GTK_WIDGET (window);
7345 if (gtk_widget_get_visible (widget))
7347 gdk_window = gtk_widget_get_window (widget);
7349 g_assert (gdk_window != NULL);
7351 gdk_window_show (gdk_window);
7353 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7354 if (timestamp == GDK_CURRENT_TIME)
7356 #ifdef GDK_WINDOWING_X11
7357 GdkDisplay *display;
7359 display = gtk_widget_get_display (GTK_WIDGET (window));
7360 timestamp = gdk_x11_display_get_user_time (display);
7362 timestamp = gtk_get_current_event_time ();
7366 gdk_window_focus (gdk_window, timestamp);
7370 gtk_widget_show (widget);
7375 * gtk_window_iconify:
7376 * @window: a #GtkWindow
7378 * Asks to iconify (i.e. minimize) the specified @window. Note that
7379 * you shouldn't assume the window is definitely iconified afterward,
7380 * because other entities (e.g. the user or <link
7381 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7382 * again, or there may not be a window manager in which case
7383 * iconification isn't possible, etc. But normally the window will end
7384 * up iconified. Just don't write code that crashes if not.
7386 * It's permitted to call this function before showing a window,
7387 * in which case the window will be iconified before it ever appears
7390 * You can track iconification via the "window-state-event" signal
7395 gtk_window_iconify (GtkWindow *window)
7397 GtkWindowPrivate *priv;
7399 GdkWindow *toplevel;
7401 g_return_if_fail (GTK_IS_WINDOW (window));
7403 priv = window->priv;
7404 widget = GTK_WIDGET (window);
7406 priv->iconify_initially = TRUE;
7408 toplevel = gtk_widget_get_window (widget);
7410 if (toplevel != NULL)
7411 gdk_window_iconify (toplevel);
7415 * gtk_window_deiconify:
7416 * @window: a #GtkWindow
7418 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7419 * that you shouldn't assume the window is definitely deiconified
7420 * afterward, because other entities (e.g. the user or <link
7421 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7422 * again before your code which assumes deiconification gets to run.
7424 * You can track iconification via the "window-state-event" signal
7428 gtk_window_deiconify (GtkWindow *window)
7430 GtkWindowPrivate *priv;
7432 GdkWindow *toplevel;
7434 g_return_if_fail (GTK_IS_WINDOW (window));
7436 priv = window->priv;
7437 widget = GTK_WIDGET (window);
7439 priv->iconify_initially = FALSE;
7441 toplevel = gtk_widget_get_window (widget);
7443 if (toplevel != NULL)
7444 gdk_window_deiconify (toplevel);
7449 * @window: a #GtkWindow
7451 * Asks to stick @window, which means that it will appear on all user
7452 * desktops. Note that you shouldn't assume the window is definitely
7453 * stuck afterward, because other entities (e.g. the user or <link
7454 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7455 * again, and some window managers do not support sticking
7456 * windows. But normally the window will end up stuck. Just don't
7457 * write code that crashes if not.
7459 * It's permitted to call this function before showing a window.
7461 * You can track stickiness via the "window-state-event" signal
7466 gtk_window_stick (GtkWindow *window)
7468 GtkWindowPrivate *priv;
7470 GdkWindow *toplevel;
7472 g_return_if_fail (GTK_IS_WINDOW (window));
7474 priv = window->priv;
7475 widget = GTK_WIDGET (window);
7477 priv->stick_initially = TRUE;
7479 toplevel = gtk_widget_get_window (widget);
7481 if (toplevel != NULL)
7482 gdk_window_stick (toplevel);
7486 * gtk_window_unstick:
7487 * @window: a #GtkWindow
7489 * Asks to unstick @window, which means that it will appear on only
7490 * one of the user's desktops. Note that you shouldn't assume the
7491 * window is definitely unstuck afterward, because other entities
7492 * (e.g. the user or <link linkend="gtk-X11-arch">window
7493 * manager</link>) could stick it again. But normally the window will
7494 * end up stuck. Just don't write code that crashes if not.
7496 * You can track stickiness via the "window-state-event" signal
7501 gtk_window_unstick (GtkWindow *window)
7503 GtkWindowPrivate *priv;
7505 GdkWindow *toplevel;
7507 g_return_if_fail (GTK_IS_WINDOW (window));
7509 priv = window->priv;
7510 widget = GTK_WIDGET (window);
7512 priv->stick_initially = FALSE;
7514 toplevel = gtk_widget_get_window (widget);
7516 if (toplevel != NULL)
7517 gdk_window_unstick (toplevel);
7521 * gtk_window_maximize:
7522 * @window: a #GtkWindow
7524 * Asks to maximize @window, so that it becomes full-screen. Note that
7525 * you shouldn't assume the window is definitely maximized afterward,
7526 * because other entities (e.g. the user or <link
7527 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7528 * again, and not all window managers support maximization. But
7529 * normally the window will end up maximized. Just don't write code
7530 * that crashes if not.
7532 * It's permitted to call this function before showing a window,
7533 * in which case the window will be maximized when it appears onscreen
7536 * You can track maximization via the "window-state-event" signal
7541 gtk_window_maximize (GtkWindow *window)
7543 GtkWindowPrivate *priv;
7545 GdkWindow *toplevel;
7547 g_return_if_fail (GTK_IS_WINDOW (window));
7549 priv = window->priv;
7550 widget = GTK_WIDGET (window);
7552 priv->maximize_initially = TRUE;
7554 toplevel = gtk_widget_get_window (widget);
7556 if (toplevel != NULL)
7557 gdk_window_maximize (toplevel);
7561 * gtk_window_unmaximize:
7562 * @window: a #GtkWindow
7564 * Asks to unmaximize @window. Note that you shouldn't assume the
7565 * window is definitely unmaximized afterward, because other entities
7566 * (e.g. the user or <link linkend="gtk-X11-arch">window
7567 * manager</link>) could maximize it again, and not all window
7568 * managers honor requests to unmaximize. But normally the window will
7569 * end up unmaximized. Just don't write code that crashes if not.
7571 * You can track maximization via the "window-state-event" signal
7576 gtk_window_unmaximize (GtkWindow *window)
7578 GtkWindowPrivate *priv;
7580 GdkWindow *toplevel;
7582 g_return_if_fail (GTK_IS_WINDOW (window));
7584 priv = window->priv;
7585 widget = GTK_WIDGET (window);
7587 priv->maximize_initially = FALSE;
7589 toplevel = gtk_widget_get_window (widget);
7591 if (toplevel != NULL)
7592 gdk_window_unmaximize (toplevel);
7596 * gtk_window_fullscreen:
7597 * @window: a #GtkWindow
7599 * Asks to place @window in the fullscreen state. Note that you
7600 * shouldn't assume the window is definitely full screen afterward,
7601 * because other entities (e.g. the user or <link
7602 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7603 * again, and not all window managers honor requests to fullscreen
7604 * windows. But normally the window will end up fullscreen. Just
7605 * don't write code that crashes if not.
7607 * You can track the fullscreen state via the "window-state-event" signal
7613 gtk_window_fullscreen (GtkWindow *window)
7615 GtkWindowPrivate *priv;
7617 GdkWindow *toplevel;
7619 g_return_if_fail (GTK_IS_WINDOW (window));
7621 priv = window->priv;
7622 widget = GTK_WIDGET (window);
7624 priv->fullscreen_initially = TRUE;
7626 toplevel = gtk_widget_get_window (widget);
7628 if (toplevel != NULL)
7629 gdk_window_fullscreen (toplevel);
7633 * gtk_window_unfullscreen:
7634 * @window: a #GtkWindow
7636 * Asks to toggle off the fullscreen state for @window. Note that you
7637 * shouldn't assume the window is definitely not full screen
7638 * afterward, because other entities (e.g. the user or <link
7639 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7640 * again, and not all window managers honor requests to unfullscreen
7641 * windows. But normally the window will end up restored to its normal
7642 * state. Just don't write code that crashes if not.
7644 * You can track the fullscreen state via the "window-state-event" signal
7650 gtk_window_unfullscreen (GtkWindow *window)
7653 GdkWindow *toplevel;
7654 GtkWindowPrivate *priv;
7656 g_return_if_fail (GTK_IS_WINDOW (window));
7658 priv = window->priv;
7659 widget = GTK_WIDGET (window);
7661 priv->fullscreen_initially = FALSE;
7663 toplevel = gtk_widget_get_window (widget);
7665 if (toplevel != NULL)
7666 gdk_window_unfullscreen (toplevel);
7670 * gtk_window_set_keep_above:
7671 * @window: a #GtkWindow
7672 * @setting: whether to keep @window above other windows
7674 * Asks to keep @window above, so that it stays on top. Note that
7675 * you shouldn't assume the window is definitely above afterward,
7676 * because other entities (e.g. the user or <link
7677 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7678 * and not all window managers support keeping windows above. But
7679 * normally the window will end kept above. Just don't write code
7680 * that crashes if not.
7682 * It's permitted to call this function before showing a window,
7683 * in which case the window will be kept above when it appears onscreen
7686 * You can track the above state via the "window-state-event" signal
7689 * Note that, according to the <ulink
7690 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7691 * Manager Hints</ulink> specification, the above state is mainly meant
7692 * for user preferences and should not be used by applications e.g. for
7693 * drawing attention to their dialogs.
7698 gtk_window_set_keep_above (GtkWindow *window,
7702 GtkWindowPrivate *priv;
7703 GdkWindow *toplevel;
7705 g_return_if_fail (GTK_IS_WINDOW (window));
7707 priv = window->priv;
7708 widget = GTK_WIDGET (window);
7710 priv->above_initially = setting != FALSE;
7712 priv->below_initially = FALSE;
7714 toplevel = gtk_widget_get_window (widget);
7716 if (toplevel != NULL)
7717 gdk_window_set_keep_above (toplevel, setting);
7721 * gtk_window_set_keep_below:
7722 * @window: a #GtkWindow
7723 * @setting: whether to keep @window below other windows
7725 * Asks to keep @window below, so that it stays in bottom. Note that
7726 * you shouldn't assume the window is definitely below afterward,
7727 * because other entities (e.g. the user or <link
7728 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7729 * and not all window managers support putting windows below. But
7730 * normally the window will be kept below. Just don't write code
7731 * that crashes if not.
7733 * It's permitted to call this function before showing a window,
7734 * in which case the window will be kept below when it appears onscreen
7737 * You can track the below state via the "window-state-event" signal
7740 * Note that, according to the <ulink
7741 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7742 * Manager Hints</ulink> specification, the above state is mainly meant
7743 * for user preferences and should not be used by applications e.g. for
7744 * drawing attention to their dialogs.
7749 gtk_window_set_keep_below (GtkWindow *window,
7753 GtkWindowPrivate *priv;
7754 GdkWindow *toplevel;
7756 g_return_if_fail (GTK_IS_WINDOW (window));
7758 priv = window->priv;
7759 widget = GTK_WIDGET (window);
7761 priv->below_initially = setting != FALSE;
7763 priv->above_initially = FALSE;
7765 toplevel = gtk_widget_get_window (widget);
7767 if (toplevel != NULL)
7768 gdk_window_set_keep_below (toplevel, setting);
7772 * gtk_window_set_resizable:
7773 * @window: a #GtkWindow
7774 * @resizable: %TRUE if the user can resize this window
7776 * Sets whether the user can resize a window. Windows are user resizable
7780 gtk_window_set_resizable (GtkWindow *window,
7783 GtkWindowPrivate *priv;
7785 g_return_if_fail (GTK_IS_WINDOW (window));
7787 priv = window->priv;
7789 resizable = (resizable != FALSE);
7791 if (priv->resizable != resizable)
7793 priv->resizable = (resizable != FALSE);
7795 update_grip_visibility (window);
7797 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7799 g_object_notify (G_OBJECT (window), "resizable");
7804 * gtk_window_get_resizable:
7805 * @window: a #GtkWindow
7807 * Gets the value set by gtk_window_set_resizable().
7809 * Return value: %TRUE if the user can resize the window
7812 gtk_window_get_resizable (GtkWindow *window)
7814 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7816 return window->priv->resizable;
7820 * gtk_window_set_gravity:
7821 * @window: a #GtkWindow
7822 * @gravity: window gravity
7824 * Window gravity defines the meaning of coordinates passed to
7825 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7828 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7829 * typically "do what you mean."
7833 gtk_window_set_gravity (GtkWindow *window,
7836 GtkWindowPrivate *priv;
7838 g_return_if_fail (GTK_IS_WINDOW (window));
7840 priv = window->priv;
7842 if (gravity != priv->gravity)
7844 priv->gravity = gravity;
7846 /* gtk_window_move_resize() will adapt gravity
7848 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7850 g_object_notify (G_OBJECT (window), "gravity");
7855 * gtk_window_get_gravity:
7856 * @window: a #GtkWindow
7858 * Gets the value set by gtk_window_set_gravity().
7860 * Return value: (transfer none): window gravity
7863 gtk_window_get_gravity (GtkWindow *window)
7865 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7867 return window->priv->gravity;
7871 * gtk_window_begin_resize_drag:
7872 * @window: a #GtkWindow
7873 * @button: mouse button that initiated the drag
7874 * @edge: position of the resize control
7875 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7876 * @root_y: Y position where the user clicked to initiate the drag
7877 * @timestamp: timestamp from the click event that initiated the drag
7879 * Starts resizing a window. This function is used if an application
7880 * has window resizing controls. When GDK can support it, the resize
7881 * will be done using the standard mechanism for the <link
7882 * linkend="gtk-X11-arch">window manager</link> or windowing
7883 * system. Otherwise, GDK will try to emulate window resizing,
7884 * potentially not all that well, depending on the windowing system.
7888 gtk_window_begin_resize_drag (GtkWindow *window,
7895 GtkWindowPrivate *priv;
7897 GdkWindow *toplevel;
7899 g_return_if_fail (GTK_IS_WINDOW (window));
7900 widget = GTK_WIDGET (window);
7901 g_return_if_fail (gtk_widget_get_visible (widget));
7903 priv = window->priv;
7905 toplevel = gtk_widget_get_window (widget);
7907 gdk_window_begin_resize_drag (toplevel,
7914 * gtk_window_begin_move_drag:
7915 * @window: a #GtkWindow
7916 * @button: mouse button that initiated the drag
7917 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7918 * @root_y: Y position where the user clicked to initiate the drag
7919 * @timestamp: timestamp from the click event that initiated the drag
7921 * Starts moving a window. This function is used if an application has
7922 * window movement grips. When GDK can support it, the window movement
7923 * will be done using the standard mechanism for the <link
7924 * linkend="gtk-X11-arch">window manager</link> or windowing
7925 * system. Otherwise, GDK will try to emulate window movement,
7926 * potentially not all that well, depending on the windowing system.
7930 gtk_window_begin_move_drag (GtkWindow *window,
7936 GtkWindowPrivate *priv;
7938 GdkWindow *toplevel;
7940 g_return_if_fail (GTK_IS_WINDOW (window));
7941 widget = GTK_WIDGET (window);
7942 g_return_if_fail (gtk_widget_get_visible (widget));
7944 priv = window->priv;
7946 toplevel = gtk_widget_get_window (widget);
7948 gdk_window_begin_move_drag (toplevel,
7955 * gtk_window_set_screen:
7956 * @window: a #GtkWindow.
7957 * @screen: a #GdkScreen.
7959 * Sets the #GdkScreen where the @window is displayed; if
7960 * the window is already mapped, it will be unmapped, and
7961 * then remapped on the new screen.
7966 gtk_window_set_screen (GtkWindow *window,
7969 GtkWindowPrivate *priv;
7971 GdkScreen *previous_screen;
7972 gboolean was_mapped;
7974 g_return_if_fail (GTK_IS_WINDOW (window));
7975 g_return_if_fail (GDK_IS_SCREEN (screen));
7977 priv = window->priv;
7979 if (screen == priv->screen)
7982 widget = GTK_WIDGET (window);
7984 previous_screen = priv->screen;
7985 was_mapped = gtk_widget_get_mapped (widget);
7988 gtk_widget_unmap (widget);
7989 if (gtk_widget_get_realized (widget))
7990 gtk_widget_unrealize (widget);
7992 gtk_window_free_key_hash (window);
7993 priv->screen = screen;
7994 gtk_widget_reset_rc_styles (widget);
7995 if (screen != previous_screen)
7997 g_signal_handlers_disconnect_by_func (previous_screen,
7998 gtk_window_on_composited_changed, window);
7999 g_signal_connect (screen, "composited-changed",
8000 G_CALLBACK (gtk_window_on_composited_changed), window);
8002 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8003 _gtk_widget_propagate_composited_changed (widget);
8005 g_object_notify (G_OBJECT (window), "screen");
8008 gtk_widget_map (widget);
8012 gtk_window_on_composited_changed (GdkScreen *screen,
8015 gtk_widget_queue_draw (GTK_WIDGET (window));
8017 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8021 gtk_window_check_screen (GtkWindow *window)
8023 GtkWindowPrivate *priv = window->priv;
8026 return priv->screen;
8029 g_warning ("Screen for GtkWindow not set; you must always set\n"
8030 "a screen for a GtkWindow before using the window");
8036 * gtk_window_get_screen:
8037 * @window: a #GtkWindow.
8039 * Returns the #GdkScreen associated with @window.
8041 * Return value: (transfer none): a #GdkScreen.
8046 gtk_window_get_screen (GtkWindow *window)
8048 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8050 return window->priv->screen;
8054 * gtk_window_is_active:
8055 * @window: a #GtkWindow
8057 * Returns whether the window is part of the current active toplevel.
8058 * (That is, the toplevel window receiving keystrokes.)
8059 * The return value is %TRUE if the window is active toplevel
8060 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8061 * You might use this function if you wanted to draw a widget
8062 * differently in an active window from a widget in an inactive window.
8063 * See gtk_window_has_toplevel_focus()
8065 * Return value: %TRUE if the window part of the current active window.
8070 gtk_window_is_active (GtkWindow *window)
8072 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8074 return window->priv->is_active;
8078 * gtk_window_has_toplevel_focus:
8079 * @window: a #GtkWindow
8081 * Returns whether the input focus is within this GtkWindow.
8082 * For real toplevel windows, this is identical to gtk_window_is_active(),
8083 * but for embedded windows, like #GtkPlug, the results will differ.
8085 * Return value: %TRUE if the input focus is within this GtkWindow
8090 gtk_window_has_toplevel_focus (GtkWindow *window)
8092 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8094 return window->priv->has_toplevel_focus;
8097 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8100 gtk_window_group_init (GtkWindowGroup *group)
8102 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8103 GTK_TYPE_WINDOW_GROUP,
8104 GtkWindowGroupPrivate);
8108 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8110 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8114 * gtk_window_group_new:
8116 * Creates a new #GtkWindowGroup object. Grabs added with
8117 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8119 * Return value: a new #GtkWindowGroup.
8122 gtk_window_group_new (void)
8124 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8128 window_group_cleanup_grabs (GtkWindowGroup *group,
8131 GtkWindowGroupPrivate *priv;
8132 GtkDeviceGrabInfo *info;
8134 GSList *to_remove = NULL;
8138 tmp_list = priv->grabs;
8141 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8142 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8143 tmp_list = tmp_list->next;
8148 gtk_grab_remove (to_remove->data);
8149 g_object_unref (to_remove->data);
8150 to_remove = g_slist_delete_link (to_remove, to_remove);
8153 tmp_list = priv->device_grabs;
8157 info = tmp_list->data;
8159 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8160 to_remove = g_slist_prepend (to_remove, info);
8162 tmp_list = tmp_list->next;
8167 info = to_remove->data;
8169 gtk_device_grab_remove (info->widget, info->device);
8170 to_remove = g_slist_delete_link (to_remove, to_remove);
8175 * gtk_window_group_add_window:
8176 * @window_group: a #GtkWindowGroup
8177 * @window: the #GtkWindow to add
8179 * Adds a window to a #GtkWindowGroup.
8182 gtk_window_group_add_window (GtkWindowGroup *window_group,
8185 GtkWindowPrivate *priv;
8187 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8188 g_return_if_fail (GTK_IS_WINDOW (window));
8190 priv = window->priv;
8192 if (priv->group != window_group)
8194 g_object_ref (window);
8195 g_object_ref (window_group);
8198 gtk_window_group_remove_window (priv->group, window);
8200 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8202 priv->group = window_group;
8204 g_object_unref (window);
8209 * gtk_window_group_remove_window:
8210 * @window_group: a #GtkWindowGroup
8211 * @window: the #GtkWindow to remove
8213 * Removes a window from a #GtkWindowGroup.
8216 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8219 GtkWindowPrivate *priv;
8221 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8222 g_return_if_fail (GTK_IS_WINDOW (window));
8223 priv = window->priv;
8224 g_return_if_fail (priv->group == window_group);
8226 g_object_ref (window);
8228 window_group_cleanup_grabs (window_group, window);
8231 g_object_unref (window_group);
8232 g_object_unref (window);
8236 * gtk_window_group_list_windows:
8237 * @window_group: a #GtkWindowGroup
8239 * Returns a list of the #GtkWindows that belong to @window_group.
8241 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8242 * windows inside the group.
8247 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8249 GList *toplevels, *toplevel, *group_windows;
8251 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8253 group_windows = NULL;
8254 toplevels = gtk_window_list_toplevels ();
8256 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8258 GtkWindow *window = toplevel->data;
8260 if (window_group == window->priv->group)
8261 group_windows = g_list_prepend (group_windows, window);
8264 return g_list_reverse (group_windows);
8268 * gtk_window_get_group:
8269 * @window: (allow-none): a #GtkWindow, or %NULL
8271 * Returns the group for @window or the default group, if
8272 * @window is %NULL or if @window does not have an explicit
8275 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8280 gtk_window_get_group (GtkWindow *window)
8282 if (window && window->priv->group)
8283 return window->priv->group;
8286 static GtkWindowGroup *default_group = NULL;
8289 default_group = gtk_window_group_new ();
8291 return default_group;
8296 * gtk_window_has_group:
8297 * @window: a #GtkWindow
8299 * Returns whether @window has an explicit window group.
8301 * Return value: %TRUE if @window has an explicit window group.
8306 gtk_window_has_group (GtkWindow *window)
8308 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8310 return window->priv->group != NULL;
8314 * gtk_window_group_get_current_grab:
8315 * @window_group: a #GtkWindowGroup
8317 * Gets the current grab widget of the given group,
8318 * see gtk_grab_add().
8320 * Returns: the current grab widget of the group
8325 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8327 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8329 if (window_group->priv->grabs)
8330 return GTK_WIDGET (window_group->priv->grabs->data);
8335 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8338 GtkWindowGroupPrivate *priv;
8340 priv = window_group->priv;
8341 priv->grabs = g_slist_prepend (priv->grabs, widget);
8345 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8348 GtkWindowGroupPrivate *priv;
8350 priv = window_group->priv;
8351 priv->grabs = g_slist_remove (priv->grabs, widget);
8356 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8359 gboolean block_others)
8361 GtkWindowGroupPrivate *priv;
8362 GtkDeviceGrabInfo *info;
8364 priv = window_group->priv;
8366 info = g_slice_new0 (GtkDeviceGrabInfo);
8367 info->widget = widget;
8368 info->device = device;
8369 info->block_others = block_others;
8371 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8375 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8379 GtkWindowGroupPrivate *priv;
8380 GtkDeviceGrabInfo *info;
8381 GSList *list, *node = NULL;
8382 GdkDevice *other_device;
8384 priv = window_group->priv;
8385 other_device = gdk_device_get_associated_device (device);
8386 list = priv->device_grabs;
8392 if (info->widget == widget &&
8393 (info->device == device ||
8394 info->device == other_device))
8407 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8408 g_slice_free (GtkDeviceGrabInfo, info);
8413 * gtk_window_group_get_current_device_grab:
8414 * @window_group: a #GtkWindowGroup
8415 * @device: a #GdkDevice
8417 * Returns the current grab widget for @device, or %NULL if none.
8419 * Returns: The grab widget, or %NULL
8424 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8427 GtkWindowGroupPrivate *priv;
8428 GtkDeviceGrabInfo *info;
8429 GdkDevice *other_device;
8432 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8433 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8435 priv = window_group->priv;
8436 list = priv->device_grabs;
8437 other_device = gdk_device_get_associated_device (device);
8444 if (info->device == device ||
8445 info->device == other_device)
8446 return info->widget;
8453 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8457 GtkWindowGroupPrivate *priv;
8458 GtkDeviceGrabInfo *info;
8459 GdkDevice *other_device;
8462 priv = window_group->priv;
8463 other_device = gdk_device_get_associated_device (device);
8464 list = priv->device_grabs;
8471 /* Look for blocking grabs on other device pairs
8472 * that have the passed widget within the GTK+ grab.
8474 if (info->block_others &&
8475 info->device != device &&
8476 info->device != other_device &&
8477 (info->widget == widget ||
8478 gtk_widget_is_ancestor (widget, info->widget)))
8486 Derived from XParseGeometry() in XFree86
8488 Copyright 1985, 1986, 1987,1998 The Open Group
8490 All Rights Reserved.
8492 The above copyright notice and this permission notice shall be included
8493 in all copies or substantial portions of the Software.
8495 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8496 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8497 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8498 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8499 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8500 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8501 OTHER DEALINGS IN THE SOFTWARE.
8503 Except as contained in this notice, the name of The Open Group shall
8504 not be used in advertising or otherwise to promote the sale, use or
8505 other dealings in this Software without prior written authorization
8506 from The Open Group.
8511 * XParseGeometry parses strings of the form
8512 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8513 * width, height, xoffset, and yoffset are unsigned integers.
8514 * Example: "=80x24+300-49"
8515 * The equal sign is optional.
8516 * It returns a bitmask that indicates which of the four values
8517 * were actually found in the string. For each value found,
8518 * the corresponding argument is updated; for each value
8519 * not found, the corresponding argument is left unchanged.
8522 /* The following code is from Xlib, and is minimally modified, so we
8523 * can track any upstream changes if required. Don't change this
8524 * code. Or if you do, put in a huge comment marking which thing
8529 read_int (gchar *string,
8537 else if (*string == '-')
8543 for (; (*string >= '0') && (*string <= '9'); string++)
8545 result = (result * 10) + (*string - '0');
8557 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8558 * value (x, y, width, height) was found in the parsed string.
8560 #define NoValue 0x0000
8561 #define XValue 0x0001
8562 #define YValue 0x0002
8563 #define WidthValue 0x0004
8564 #define HeightValue 0x0008
8565 #define AllValues 0x000F
8566 #define XNegative 0x0010
8567 #define YNegative 0x0020
8569 /* Try not to reformat/modify, so we can compare/sync with X sources */
8571 gtk_XParseGeometry (const char *string,
8574 unsigned int *width,
8575 unsigned int *height)
8579 unsigned int tempWidth, tempHeight;
8581 char *nextCharacter;
8583 /* These initializations are just to silence gcc */
8589 if ( (string == NULL) || (*string == '\0')) return(mask);
8591 string++; /* ignore possible '=' at beg of geometry spec */
8593 strind = (char *)string;
8594 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8595 tempWidth = read_int(strind, &nextCharacter);
8596 if (strind == nextCharacter)
8598 strind = nextCharacter;
8602 if (*strind == 'x' || *strind == 'X') {
8604 tempHeight = read_int(strind, &nextCharacter);
8605 if (strind == nextCharacter)
8607 strind = nextCharacter;
8608 mask |= HeightValue;
8611 if ((*strind == '+') || (*strind == '-')) {
8612 if (*strind == '-') {
8614 tempX = -read_int(strind, &nextCharacter);
8615 if (strind == nextCharacter)
8617 strind = nextCharacter;
8623 tempX = read_int(strind, &nextCharacter);
8624 if (strind == nextCharacter)
8626 strind = nextCharacter;
8629 if ((*strind == '+') || (*strind == '-')) {
8630 if (*strind == '-') {
8632 tempY = -read_int(strind, &nextCharacter);
8633 if (strind == nextCharacter)
8635 strind = nextCharacter;
8642 tempY = read_int(strind, &nextCharacter);
8643 if (strind == nextCharacter)
8645 strind = nextCharacter;
8651 /* If strind isn't at the end of the string the it's an invalid
8652 geometry specification. */
8654 if (*strind != '\0') return (0);
8660 if (mask & WidthValue)
8662 if (mask & HeightValue)
8663 *height = tempHeight;
8668 * gtk_window_parse_geometry:
8669 * @window: a #GtkWindow
8670 * @geometry: geometry string
8672 * Parses a standard X Window System geometry string - see the
8673 * manual page for X (type 'man X') for details on this.
8674 * gtk_window_parse_geometry() does work on all GTK+ ports
8675 * including Win32 but is primarily intended for an X environment.
8677 * If either a size or a position can be extracted from the
8678 * geometry string, gtk_window_parse_geometry() returns %TRUE
8679 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8680 * to resize/move the window.
8682 * If gtk_window_parse_geometry() returns %TRUE, it will also
8683 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8684 * indicating to the window manager that the size/position of
8685 * the window was user-specified. This causes most window
8686 * managers to honor the geometry.
8688 * Note that for gtk_window_parse_geometry() to work as expected, it has
8689 * to be called when the window has its "final" size, i.e. after calling
8690 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8693 * #include <gtk/gtk.h>
8696 * fill_with_content (GtkWidget *vbox)
8698 * /* fill with content... */
8702 * main (int argc, char *argv[])
8704 * GtkWidget *window, *vbox;
8705 * GdkGeometry size_hints = {
8706 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8709 * gtk_init (&argc, &argv);
8711 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8712 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8714 * gtk_container_add (GTK_CONTAINER (window), vbox);
8715 * fill_with_content (vbox);
8716 * gtk_widget_show_all (vbox);
8718 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8721 * GDK_HINT_MIN_SIZE |
8722 * GDK_HINT_BASE_SIZE |
8723 * GDK_HINT_RESIZE_INC);
8727 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8728 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8731 * gtk_widget_show_all (window);
8738 * Return value: %TRUE if string was parsed successfully
8741 gtk_window_parse_geometry (GtkWindow *window,
8742 const gchar *geometry)
8744 gint result, x = 0, y = 0;
8748 gboolean size_set, pos_set;
8751 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8752 g_return_val_if_fail (geometry != NULL, FALSE);
8754 child = gtk_bin_get_child (GTK_BIN (window));
8755 if (!child || !gtk_widget_get_visible (child))
8756 g_warning ("gtk_window_parse_geometry() called on a window with no "
8757 "visible children; the window should be set up before "
8758 "gtk_window_parse_geometry() is called.");
8760 screen = gtk_window_check_screen (window);
8762 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8765 if ((result & WidthValue) || (result & HeightValue))
8767 gtk_window_set_default_size_internal (window,
8768 TRUE, result & WidthValue ? w : -1,
8769 TRUE, result & HeightValue ? h : -1,
8774 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8776 grav = GDK_GRAVITY_NORTH_WEST;
8778 if ((result & XNegative) && (result & YNegative))
8779 grav = GDK_GRAVITY_SOUTH_EAST;
8780 else if (result & XNegative)
8781 grav = GDK_GRAVITY_NORTH_EAST;
8782 else if (result & YNegative)
8783 grav = GDK_GRAVITY_SOUTH_WEST;
8785 if ((result & XValue) == 0)
8788 if ((result & YValue) == 0)
8791 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8792 grav == GDK_GRAVITY_SOUTH_EAST)
8793 y = gdk_screen_get_height (screen) - h + y;
8795 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8796 grav == GDK_GRAVITY_NORTH_EAST)
8797 x = gdk_screen_get_width (screen) - w + x;
8799 /* we don't let you put a window offscreen; maybe some people would
8800 * prefer to be able to, but it's kind of a bogus thing to do.
8809 if ((result & XValue) || (result & YValue))
8811 gtk_window_set_gravity (window, grav);
8812 gtk_window_move (window, x, y);
8816 if (size_set || pos_set)
8818 /* Set USSize, USPosition hints */
8819 GtkWindowGeometryInfo *info;
8821 info = gtk_window_get_geometry_info (window, TRUE);
8824 info->mask |= GDK_HINT_USER_POS;
8826 info->mask |= GDK_HINT_USER_SIZE;
8833 gtk_window_mnemonic_hash_foreach (guint keyval,
8839 GtkWindowKeysForeachFunc func;
8843 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8847 _gtk_window_keys_foreach (GtkWindow *window,
8848 GtkWindowKeysForeachFunc func,
8852 GtkMnemonicHash *mnemonic_hash;
8856 GtkWindowKeysForeachFunc func;
8860 info.window = window;
8862 info.func_data = func_data;
8864 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8866 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8867 gtk_window_mnemonic_hash_foreach, &info);
8869 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8872 GtkAccelGroup *group = groups->data;
8875 for (i = 0; i < group->priv->n_accels; i++)
8877 GtkAccelKey *key = &group->priv->priv_accels[i].key;
8880 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8883 groups = groups->next;
8888 gtk_window_keys_changed (GtkWindow *window)
8890 gtk_window_free_key_hash (window);
8891 gtk_window_get_key_hash (window);
8894 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8896 struct _GtkWindowKeyEntry
8900 guint is_mnemonic : 1;
8904 window_key_entry_destroy (gpointer data)
8906 g_slice_free (GtkWindowKeyEntry, data);
8910 add_to_key_hash (GtkWindow *window,
8912 GdkModifierType modifiers,
8913 gboolean is_mnemonic,
8916 GtkKeyHash *key_hash = data;
8918 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8920 entry->keyval = keyval;
8921 entry->modifiers = modifiers;
8922 entry->is_mnemonic = is_mnemonic;
8924 /* GtkAccelGroup stores lowercased accelerators. To deal
8925 * with this, if <Shift> was specified, uppercase.
8927 if (modifiers & GDK_SHIFT_MASK)
8929 if (keyval == GDK_KEY_Tab)
8930 keyval = GDK_KEY_ISO_Left_Tab;
8932 keyval = gdk_keyval_to_upper (keyval);
8935 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8939 gtk_window_get_key_hash (GtkWindow *window)
8941 GdkScreen *screen = gtk_window_check_screen (window);
8942 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8947 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8948 (GDestroyNotify)window_key_entry_destroy);
8949 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8950 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8956 gtk_window_free_key_hash (GtkWindow *window)
8958 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8961 _gtk_key_hash_free (key_hash);
8962 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8967 * gtk_window_activate_key:
8968 * @window: a #GtkWindow
8969 * @event: a #GdkEventKey
8971 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8972 * called by the default ::key_press_event handler for toplevel windows,
8973 * however in some cases it may be useful to call this directly when
8974 * overriding the standard key handling for a toplevel window.
8976 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8981 gtk_window_activate_key (GtkWindow *window,
8984 GtkKeyHash *key_hash;
8985 GtkWindowKeyEntry *found_entry = NULL;
8986 gboolean enable_mnemonics;
8987 gboolean enable_accels;
8989 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8990 g_return_val_if_fail (event != NULL, FALSE);
8992 key_hash = gtk_window_get_key_hash (window);
8997 GSList *entries = _gtk_key_hash_lookup (key_hash,
8998 event->hardware_keycode,
9000 gtk_accelerator_get_default_mod_mask (),
9003 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9004 "gtk-enable-mnemonics", &enable_mnemonics,
9005 "gtk-enable-accels", &enable_accels,
9008 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9010 GtkWindowKeyEntry *entry = tmp_list->data;
9011 if (entry->is_mnemonic)
9013 if (enable_mnemonics)
9015 found_entry = entry;
9021 if (enable_accels && !found_entry)
9023 found_entry = entry;
9028 g_slist_free (entries);
9033 if (found_entry->is_mnemonic)
9035 if (enable_mnemonics)
9036 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9037 found_entry->modifiers);
9042 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9043 found_entry->modifiers);
9051 window_update_has_focus (GtkWindow *window)
9053 GtkWindowPrivate *priv = window->priv;
9054 GtkWidget *widget = GTK_WIDGET (window);
9055 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9057 if (has_focus != priv->has_focus)
9059 priv->has_focus = has_focus;
9063 if (priv->focus_widget &&
9064 priv->focus_widget != widget &&
9065 !gtk_widget_has_focus (priv->focus_widget))
9066 do_focus_change (priv->focus_widget, TRUE);
9070 if (priv->focus_widget &&
9071 priv->focus_widget != widget &&
9072 gtk_widget_has_focus (priv->focus_widget))
9073 do_focus_change (priv->focus_widget, FALSE);
9079 * _gtk_window_set_is_active:
9080 * @window: a #GtkWindow
9081 * @is_active: %TRUE if the window is in the currently active toplevel
9083 * Internal function that sets whether the #GtkWindow is part
9084 * of the currently active toplevel window (taking into account inter-process
9088 _gtk_window_set_is_active (GtkWindow *window,
9091 GtkWindowPrivate *priv;
9093 g_return_if_fail (GTK_IS_WINDOW (window));
9095 priv = window->priv;
9097 is_active = is_active != FALSE;
9099 if (is_active != priv->is_active)
9101 priv->is_active = is_active;
9102 window_update_has_focus (window);
9104 g_object_notify (G_OBJECT (window), "is-active");
9109 * _gtk_window_set_is_toplevel:
9110 * @window: a #GtkWindow
9111 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9112 * child of the root window); %FALSE if it is not (for example, for an
9113 * in-process, parented GtkPlug)
9115 * Internal function used by #GtkPlug when it gets parented/unparented by a
9116 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9117 * global list of toplevel windows.
9120 _gtk_window_set_is_toplevel (GtkWindow *window,
9121 gboolean is_toplevel)
9125 widget = GTK_WIDGET (window);
9127 if (gtk_widget_is_toplevel (widget))
9128 g_assert (g_slist_find (toplevel_list, window) != NULL);
9130 g_assert (g_slist_find (toplevel_list, window) == NULL);
9132 if (is_toplevel == gtk_widget_is_toplevel (widget))
9137 _gtk_widget_set_is_toplevel (widget, TRUE);
9138 toplevel_list = g_slist_prepend (toplevel_list, window);
9142 _gtk_widget_set_is_toplevel (widget, FALSE);
9143 toplevel_list = g_slist_remove (toplevel_list, window);
9148 * _gtk_window_set_has_toplevel_focus:
9149 * @window: a #GtkWindow
9150 * @has_toplevel_focus: %TRUE if the in
9152 * Internal function that sets whether the keyboard focus for the
9153 * toplevel window (taking into account inter-process embedding.)
9156 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9157 gboolean has_toplevel_focus)
9159 GtkWindowPrivate *priv;
9161 g_return_if_fail (GTK_IS_WINDOW (window));
9163 priv = window->priv;
9165 has_toplevel_focus = has_toplevel_focus != FALSE;
9167 if (has_toplevel_focus != priv->has_toplevel_focus)
9169 priv->has_toplevel_focus = has_toplevel_focus;
9170 window_update_has_focus (window);
9172 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9177 * gtk_window_set_auto_startup_notification:
9178 * @setting: %TRUE to automatically do startup notification
9180 * By default, after showing the first #GtkWindow, GTK+ calls
9181 * gdk_notify_startup_complete(). Call this function to disable
9182 * the automatic startup notification. You might do this if your
9183 * first window is a splash screen, and you want to delay notification
9184 * until after your real main window has been shown, for example.
9186 * In that example, you would disable startup notification
9187 * temporarily, show your splash screen, then re-enable it so that
9188 * showing the main window would automatically result in notification.
9193 gtk_window_set_auto_startup_notification (gboolean setting)
9195 disable_startup_notification = !setting;
9199 * gtk_window_get_window_type:
9200 * @window: a #GtkWindow
9202 * Gets the type of the window. See #GtkWindowType.
9204 * Return value: the type of the window
9209 gtk_window_get_window_type (GtkWindow *window)
9211 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9213 return window->priv->type;
9217 * gtk_window_get_mnemonics_visible:
9218 * @window: a #GtkWindow
9220 * Gets the value of the #GtkWindow:mnemonics-visible property.
9222 * Returns: %TRUE if mnemonics are supposed to be visible
9228 gtk_window_get_mnemonics_visible (GtkWindow *window)
9230 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9232 return window->priv->mnemonics_visible;
9236 * gtk_window_set_mnemonics_visible:
9237 * @window: a #GtkWindow
9238 * @setting: the new value
9240 * Sets the #GtkWindow:mnemonics-visible property.
9245 gtk_window_set_mnemonics_visible (GtkWindow *window,
9248 GtkWindowPrivate *priv;
9250 g_return_if_fail (GTK_IS_WINDOW (window));
9252 priv = window->priv;
9254 setting = setting != FALSE;
9256 if (priv->mnemonics_visible != setting)
9258 priv->mnemonics_visible = setting;
9259 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9262 priv->mnemonics_visible_set = TRUE;
9266 _gtk_window_get_wmclass (GtkWindow *window,
9267 gchar **wmclass_name,
9268 gchar **wmclass_class)
9270 GtkWindowPrivate *priv = window->priv;
9272 *wmclass_name = priv->wmclass_name;
9273 *wmclass_class = priv->wmclass_class;