1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
33 #include "gdk/gdkkeysyms.h"
37 #include "gtkprivate.h"
39 #include "gtkwindow.h"
40 #include "gtkwindow-decorate.h"
41 #include "gtkbindings.h"
42 #include "gtkkeyhash.h"
44 #include "gtkmnemonichash.h"
45 #include "gtkmenubar.h"
46 #include "gtkiconfactory.h"
47 #include "gtkicontheme.h"
48 #include "gtkmarshalers.h"
50 #include "gtkbuildable.h"
51 #include "gtksizerequest.h"
53 #ifdef GDK_WINDOWING_X11
60 * @short_description: Toplevel which can contain other widgets
62 * <refsect2 id="GtkWindow-BUILDER-UI">
63 * <title>GtkWindow as GtkBuildable</title>
65 * The GtkWindow implementation of the GtkBuildable interface supports a
66 * custom <tag class="starttag">accel-groups</tag> element, which supports
67 * any number of <tag class="starttag">group</tag> elements representing the
68 * #GtkAccelGroup objects you want to add to your window (synonymous with
69 * gtk_window_add_accel_group().
72 * <title>A UI definition fragment with accel groups</title>
73 * <programlisting><![CDATA[
74 * <object class="GtkWindow">
76 * <group name="accelgroup1"/>
82 * <object class="GtkAccelGroup" id="accelgroup1"/>
83 * ]]></programlisting>
88 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
89 typedef struct _GtkWindowGroupPrivate GtkWindowGroupPrivate;
91 struct _GtkWindowPrivate
93 GtkMnemonicHash *mnemonic_hash;
95 GtkWidget *default_widget;
96 GtkWidget *focus_widget;
97 GtkWindow *transient_parent;
98 GtkWindowGeometryInfo *geometry_info;
99 GtkWindowGroup *group;
101 GdkModifierType mnemonic_modifier;
104 GdkWindowTypeHint gdk_type_hint;
110 gchar *wmclass_class;
118 guint keys_changed_handler;
120 guint16 configure_request_count;
122 /* The following flags are initially TRUE (before a window is mapped).
123 * They cause us to compute a configure request that involves
124 * default-only parameters. Once mapped, we set them to FALSE.
125 * Then we set them to TRUE again on unmap (for position)
126 * and on unrealize (for size).
128 guint need_default_position : 1;
129 guint need_default_size : 1;
131 guint above_initially : 1;
132 guint accept_focus : 1;
133 guint below_initially : 1;
134 guint builder_visible : 1;
135 guint configure_notify_received : 1;
138 guint destroy_with_parent : 1;
139 guint focus_on_map : 1;
140 guint fullscreen_initially : 1;
141 guint gravity : 5; /* GdkGravity */
143 guint has_user_ref_count : 1;
145 guint has_toplevel_focus : 1;
146 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
148 guint maximize_initially : 1;
149 guint mnemonics_visible : 1;
150 guint mnemonics_visible_set : 1;
152 guint opacity_set : 1;
154 guint reset_type_hint : 1;
156 guint skips_pager : 1;
157 guint skips_taskbar : 1;
158 guint stick_initially : 1;
159 guint transient_parent_group : 1;
160 guint type : 4; /* GtkWindowType */
161 guint type_hint : 3; /* GdkWindowTypeHint if the hint is one of the original eight. If not, then
162 * it contains GDK_WINDOW_TYPE_HINT_NORMAL */
189 PROP_DESTROY_WITH_PARENT,
195 PROP_SKIP_TASKBAR_HINT,
196 PROP_SKIP_PAGER_HINT,
206 /* Readonly properties */
208 PROP_HAS_TOPLEVEL_FOCUS,
210 /* Writeonly properties */
213 PROP_MNEMONICS_VISIBLE,
223 guint using_default_icon : 1;
224 guint using_parent_icon : 1;
225 guint using_themed_icon : 1;
229 GdkGeometry geometry; /* Last set of geometry hints we set */
230 GdkWindowHints flags;
231 GdkRectangle configure_request;
232 } GtkWindowLastGeometryInfo;
234 struct _GtkWindowGeometryInfo
236 /* Properties that the app has set on the window
238 GdkGeometry geometry; /* Geometry hints */
240 GtkWidget *widget; /* subwidget to which hints apply */
241 /* from last gtk_window_resize () - if > 0, indicates that
242 * we should resize to this size.
247 /* From last gtk_window_move () prior to mapping -
248 * only used if initial_pos_set
253 /* Default size - used only the FIRST time we map a window,
258 /* whether to use initial_x, initial_y */
259 guint initial_pos_set : 1;
260 /* CENTER_ALWAYS or other position constraint changed since
261 * we sent the last configure request.
263 guint position_constraints_changed : 1;
265 /* if true, default_width, height come from gtk_window_parse_geometry,
266 * and thus should be multiplied by the increments and affect the
267 * geometry widget only
269 guint default_is_geometry : 1;
271 GtkWindowLastGeometryInfo last;
274 #define GTK_WINDOW_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW_GROUP, GtkWindowGroupPrivate))
276 struct _GtkDeviceGrabInfo
280 guint block_others : 1;
283 struct _GtkWindowGroupPrivate
285 GSList *device_grabs;
288 static void gtk_window_dispose (GObject *object);
289 static void gtk_window_destroy (GtkObject *object);
290 static void gtk_window_finalize (GObject *object);
291 static void gtk_window_show (GtkWidget *widget);
292 static void gtk_window_hide (GtkWidget *widget);
293 static void gtk_window_map (GtkWidget *widget);
294 static void gtk_window_unmap (GtkWidget *widget);
295 static void gtk_window_realize (GtkWidget *widget);
296 static void gtk_window_unrealize (GtkWidget *widget);
297 static void gtk_window_size_allocate (GtkWidget *widget,
298 GtkAllocation *allocation);
299 static gint gtk_window_event (GtkWidget *widget,
301 static gboolean gtk_window_map_event (GtkWidget *widget,
303 static gboolean gtk_window_frame_event (GtkWindow *window,
305 static gint gtk_window_configure_event (GtkWidget *widget,
306 GdkEventConfigure *event);
307 static gint gtk_window_key_press_event (GtkWidget *widget,
309 static gint gtk_window_key_release_event (GtkWidget *widget,
311 static gint gtk_window_enter_notify_event (GtkWidget *widget,
312 GdkEventCrossing *event);
313 static gint gtk_window_leave_notify_event (GtkWidget *widget,
314 GdkEventCrossing *event);
315 static gint gtk_window_focus_in_event (GtkWidget *widget,
316 GdkEventFocus *event);
317 static gint gtk_window_focus_out_event (GtkWidget *widget,
318 GdkEventFocus *event);
319 static gint gtk_window_client_event (GtkWidget *widget,
320 GdkEventClient *event);
321 static void gtk_window_check_resize (GtkContainer *container);
322 static gint gtk_window_focus (GtkWidget *widget,
323 GtkDirectionType direction);
324 static void gtk_window_real_set_focus (GtkWindow *window,
327 static void gtk_window_real_activate_default (GtkWindow *window);
328 static void gtk_window_real_activate_focus (GtkWindow *window);
329 static void gtk_window_move_focus (GtkWindow *window,
330 GtkDirectionType dir);
331 static void gtk_window_keys_changed (GtkWindow *window);
332 static gint gtk_window_draw (GtkWidget *widget,
334 static void gtk_window_unset_transient_for (GtkWindow *window);
335 static void gtk_window_transient_parent_realized (GtkWidget *parent,
337 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
340 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
342 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
345 static void gtk_window_move_resize (GtkWindow *window);
346 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
348 GdkGeometry *geometry_b,
350 static void gtk_window_constrain_size (GtkWindow *window,
351 GdkGeometry *geometry,
357 static void gtk_window_constrain_position (GtkWindow *window,
362 static void gtk_window_compute_hints (GtkWindow *window,
363 GdkGeometry *new_geometry,
365 static void gtk_window_compute_configure_request (GtkWindow *window,
366 GdkRectangle *request,
367 GdkGeometry *geometry,
370 static void gtk_window_set_default_size_internal (GtkWindow *window,
371 gboolean change_width,
373 gboolean change_height,
375 gboolean is_geometry);
377 static void update_themed_icon (GtkIconTheme *theme,
379 static GList *icon_list_from_theme (GtkWidget *widget,
381 static void gtk_window_realize_icon (GtkWindow *window);
382 static void gtk_window_unrealize_icon (GtkWindow *window);
384 static void gtk_window_notify_keys_changed (GtkWindow *window);
385 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
386 static void gtk_window_free_key_hash (GtkWindow *window);
387 static void gtk_window_on_composited_changed (GdkScreen *screen,
390 static GSList *toplevel_list = NULL;
391 static guint window_signals[LAST_SIGNAL] = { 0 };
392 static GList *default_icon_list = NULL;
393 static gchar *default_icon_name = NULL;
394 static guint default_icon_serial = 0;
395 static gboolean disable_startup_notification = FALSE;
396 static gboolean sent_startup_notification = FALSE;
398 static GQuark quark_gtk_embedded = 0;
399 static GQuark quark_gtk_window_key_hash = 0;
400 static GQuark quark_gtk_window_icon_info = 0;
401 static GQuark quark_gtk_buildable_accels = 0;
403 static GtkBuildableIface *parent_buildable_iface;
405 static void gtk_window_set_property (GObject *object,
409 static void gtk_window_get_property (GObject *object,
415 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
416 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
419 const GValue *value);
420 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
421 GtkBuilder *builder);
422 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
425 const gchar *tagname,
426 GMarkupParser *parser,
428 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
431 const gchar *tagname,
435 static void gtk_window_size_request_init (GtkSizeRequestIface *iface);
436 static void gtk_window_get_width (GtkSizeRequest *widget,
439 static void gtk_window_get_height (GtkSizeRequest *widget,
443 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
444 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
445 gtk_window_buildable_interface_init)
446 G_IMPLEMENT_INTERFACE (GTK_TYPE_SIZE_REQUEST,
447 gtk_window_size_request_init))
450 add_tab_bindings (GtkBindingSet *binding_set,
451 GdkModifierType modifiers,
452 GtkDirectionType direction)
454 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
456 GTK_TYPE_DIRECTION_TYPE, direction);
457 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
459 GTK_TYPE_DIRECTION_TYPE, direction);
463 add_arrow_bindings (GtkBindingSet *binding_set,
465 GtkDirectionType direction)
467 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
469 gtk_binding_entry_add_signal (binding_set, keysym, 0,
471 GTK_TYPE_DIRECTION_TYPE, direction);
472 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
474 GTK_TYPE_DIRECTION_TYPE, direction);
475 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
477 GTK_TYPE_DIRECTION_TYPE, direction);
478 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
480 GTK_TYPE_DIRECTION_TYPE, direction);
484 extract_time_from_startup_id (const gchar* startup_id)
486 gchar *timestr = g_strrstr (startup_id, "_TIME");
487 guint32 retval = GDK_CURRENT_TIME;
494 /* Skip past the "_TIME" part */
498 timestamp = strtoul (timestr, &end, 0);
499 if (end != timestr && errno == 0)
507 startup_id_is_fake (const gchar* startup_id)
509 return strncmp (startup_id, "_TIME", 5) == 0;
513 gtk_window_class_init (GtkWindowClass *klass)
515 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
516 GtkObjectClass *object_class;
517 GtkWidgetClass *widget_class;
518 GtkContainerClass *container_class;
519 GtkBindingSet *binding_set;
521 object_class = (GtkObjectClass*) klass;
522 widget_class = (GtkWidgetClass*) klass;
523 container_class = (GtkContainerClass*) klass;
525 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
526 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
527 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
528 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
530 gobject_class->dispose = gtk_window_dispose;
531 gobject_class->finalize = gtk_window_finalize;
533 gobject_class->set_property = gtk_window_set_property;
534 gobject_class->get_property = gtk_window_get_property;
536 object_class->destroy = gtk_window_destroy;
538 widget_class->show = gtk_window_show;
539 widget_class->hide = gtk_window_hide;
540 widget_class->map = gtk_window_map;
541 widget_class->map_event = gtk_window_map_event;
542 widget_class->unmap = gtk_window_unmap;
543 widget_class->realize = gtk_window_realize;
544 widget_class->unrealize = gtk_window_unrealize;
545 widget_class->size_allocate = gtk_window_size_allocate;
546 widget_class->configure_event = gtk_window_configure_event;
547 widget_class->key_press_event = gtk_window_key_press_event;
548 widget_class->key_release_event = gtk_window_key_release_event;
549 widget_class->enter_notify_event = gtk_window_enter_notify_event;
550 widget_class->leave_notify_event = gtk_window_leave_notify_event;
551 widget_class->focus_in_event = gtk_window_focus_in_event;
552 widget_class->focus_out_event = gtk_window_focus_out_event;
553 widget_class->client_event = gtk_window_client_event;
554 widget_class->focus = gtk_window_focus;
555 widget_class->draw = gtk_window_draw;
557 container_class->check_resize = gtk_window_check_resize;
559 klass->set_focus = gtk_window_real_set_focus;
560 klass->frame_event = gtk_window_frame_event;
562 klass->activate_default = gtk_window_real_activate_default;
563 klass->activate_focus = gtk_window_real_activate_focus;
564 klass->move_focus = gtk_window_move_focus;
565 klass->keys_changed = gtk_window_keys_changed;
567 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
570 g_object_class_install_property (gobject_class,
572 g_param_spec_enum ("type",
574 P_("The type of the window"),
575 GTK_TYPE_WINDOW_TYPE,
577 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
579 g_object_class_install_property (gobject_class,
581 g_param_spec_string ("title",
583 P_("The title of the window"),
585 GTK_PARAM_READWRITE));
587 g_object_class_install_property (gobject_class,
589 g_param_spec_string ("role",
591 P_("Unique identifier for the window to be used when restoring a session"),
593 GTK_PARAM_READWRITE));
596 * GtkWindow:startup-id:
598 * The :startup-id is a write-only property for setting window's
599 * startup notification identifier. See gtk_window_set_startup_id()
604 g_object_class_install_property (gobject_class,
606 g_param_spec_string ("startup-id",
608 P_("Unique startup identifier for the window used by startup-notification"),
610 GTK_PARAM_WRITABLE));
612 g_object_class_install_property (gobject_class,
614 g_param_spec_boolean ("resizable",
616 P_("If TRUE, users can resize the window"),
618 GTK_PARAM_READWRITE));
620 g_object_class_install_property (gobject_class,
622 g_param_spec_boolean ("modal",
624 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
626 GTK_PARAM_READWRITE));
628 g_object_class_install_property (gobject_class,
630 g_param_spec_enum ("window-position",
631 P_("Window Position"),
632 P_("The initial position of the window"),
633 GTK_TYPE_WINDOW_POSITION,
635 GTK_PARAM_READWRITE));
637 g_object_class_install_property (gobject_class,
639 g_param_spec_int ("default-width",
641 P_("The default width of the window, used when initially showing the window"),
645 GTK_PARAM_READWRITE));
647 g_object_class_install_property (gobject_class,
649 g_param_spec_int ("default-height",
650 P_("Default Height"),
651 P_("The default height of the window, used when initially showing the window"),
655 GTK_PARAM_READWRITE));
657 g_object_class_install_property (gobject_class,
658 PROP_DESTROY_WITH_PARENT,
659 g_param_spec_boolean ("destroy-with-parent",
660 P_("Destroy with Parent"),
661 P_("If this window should be destroyed when the parent is destroyed"),
663 GTK_PARAM_READWRITE));
665 g_object_class_install_property (gobject_class,
667 g_param_spec_object ("icon",
669 P_("Icon for this window"),
671 GTK_PARAM_READWRITE));
672 g_object_class_install_property (gobject_class,
673 PROP_MNEMONICS_VISIBLE,
674 g_param_spec_boolean ("mnemonics-visible",
675 P_("Mnemonics Visible"),
676 P_("Whether mnemonics are currently visible in this window"),
678 GTK_PARAM_READWRITE));
681 * GtkWindow:icon-name:
683 * The :icon-name property specifies the name of the themed icon to
684 * use as the window icon. See #GtkIconTheme for more details.
688 g_object_class_install_property (gobject_class,
690 g_param_spec_string ("icon-name",
692 P_("Name of the themed icon for this window"),
694 GTK_PARAM_READWRITE));
696 g_object_class_install_property (gobject_class,
698 g_param_spec_object ("screen",
700 P_("The screen where this window will be displayed"),
702 GTK_PARAM_READWRITE));
707 * Specifies the visual used to create the window with. See gtk_window_set_visual()
710 g_object_class_install_property (gobject_class,
712 g_param_spec_object ("visual",
714 P_("The visual this window is created from"),
716 GTK_PARAM_READWRITE));
718 g_object_class_install_property (gobject_class,
720 g_param_spec_boolean ("is-active",
722 P_("Whether the toplevel is the current active window"),
724 GTK_PARAM_READABLE));
726 g_object_class_install_property (gobject_class,
727 PROP_HAS_TOPLEVEL_FOCUS,
728 g_param_spec_boolean ("has-toplevel-focus",
729 P_("Focus in Toplevel"),
730 P_("Whether the input focus is within this GtkWindow"),
732 GTK_PARAM_READABLE));
734 g_object_class_install_property (gobject_class,
736 g_param_spec_enum ("type-hint",
738 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
739 GDK_TYPE_WINDOW_TYPE_HINT,
740 GDK_WINDOW_TYPE_HINT_NORMAL,
741 GTK_PARAM_READWRITE));
743 g_object_class_install_property (gobject_class,
744 PROP_SKIP_TASKBAR_HINT,
745 g_param_spec_boolean ("skip-taskbar-hint",
747 P_("TRUE if the window should not be in the task bar."),
749 GTK_PARAM_READWRITE));
751 g_object_class_install_property (gobject_class,
752 PROP_SKIP_PAGER_HINT,
753 g_param_spec_boolean ("skip-pager-hint",
755 P_("TRUE if the window should not be in the pager."),
757 GTK_PARAM_READWRITE));
759 g_object_class_install_property (gobject_class,
761 g_param_spec_boolean ("urgency-hint",
763 P_("TRUE if the window should be brought to the user's attention."),
765 GTK_PARAM_READWRITE));
768 * GtkWindow:accept-focus:
770 * Whether the window should receive the input focus.
774 g_object_class_install_property (gobject_class,
776 g_param_spec_boolean ("accept-focus",
778 P_("TRUE if the window should receive the input focus."),
780 GTK_PARAM_READWRITE));
783 * GtkWindow:focus-on-map:
785 * Whether the window should receive the input focus when mapped.
789 g_object_class_install_property (gobject_class,
791 g_param_spec_boolean ("focus-on-map",
793 P_("TRUE if the window should receive the input focus when mapped."),
795 GTK_PARAM_READWRITE));
798 * GtkWindow:decorated:
800 * Whether the window should be decorated by the window manager.
804 g_object_class_install_property (gobject_class,
806 g_param_spec_boolean ("decorated",
808 P_("Whether the window should be decorated by the window manager"),
810 GTK_PARAM_READWRITE));
813 * GtkWindow:deletable:
815 * Whether the window frame should have a close button.
819 g_object_class_install_property (gobject_class,
821 g_param_spec_boolean ("deletable",
823 P_("Whether the window frame should have a close button"),
825 GTK_PARAM_READWRITE));
831 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
832 * more details about window gravity.
836 g_object_class_install_property (gobject_class,
838 g_param_spec_enum ("gravity",
840 P_("The window gravity of the window"),
842 GDK_GRAVITY_NORTH_WEST,
843 GTK_PARAM_READWRITE));
847 * GtkWindow:transient-for:
849 * The transient parent of the window. See gtk_window_set_transient_for() for
850 * more details about transient windows.
854 g_object_class_install_property (gobject_class,
856 g_param_spec_object ("transient-for",
857 P_("Transient for Window"),
858 P_("The transient parent of the dialog"),
860 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
865 * The requested opacity of the window. See gtk_window_set_opacity() for
866 * more details about window opacity.
870 g_object_class_install_property (gobject_class,
872 g_param_spec_double ("opacity",
873 P_("Opacity for Window"),
874 P_("The opacity of the window, from 0 to 1"),
878 GTK_PARAM_READWRITE));
880 window_signals[SET_FOCUS] =
881 g_signal_new (I_("set-focus"),
882 G_TYPE_FROM_CLASS (gobject_class),
884 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
886 _gtk_marshal_VOID__OBJECT,
890 window_signals[FRAME_EVENT] =
891 g_signal_new (I_("frame-event"),
892 G_TYPE_FROM_CLASS (gobject_class),
894 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
895 _gtk_boolean_handled_accumulator, NULL,
896 _gtk_marshal_BOOLEAN__BOXED,
901 * GtkWindow::activate-focus:
902 * @window: the window which received the signal
904 * The ::activate-focus signal is a
905 * <link linkend="keybinding-signals">keybinding signal</link>
906 * which gets emitted when the user activates the currently
907 * focused widget of @window.
909 window_signals[ACTIVATE_FOCUS] =
910 g_signal_new (I_("activate-focus"),
911 G_TYPE_FROM_CLASS (gobject_class),
912 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
913 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
915 _gtk_marshal_VOID__VOID,
920 * GtkWindow::activate-default:
921 * @window: the window which received the signal
923 * The ::activate-default signal is a
924 * <link linkend="keybinding-signals">keybinding signal</link>
925 * which gets emitted when the user activates the default widget
928 window_signals[ACTIVATE_DEFAULT] =
929 g_signal_new (I_("activate-default"),
930 G_TYPE_FROM_CLASS (gobject_class),
931 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
932 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
934 _gtk_marshal_VOID__VOID,
939 * GtkWindow::keys-changed:
940 * @window: the window which received the signal
942 * The ::keys-changed signal gets emitted when the set of accelerators
943 * or mnemonics that are associated with @window changes.
945 window_signals[KEYS_CHANGED] =
946 g_signal_new (I_("keys-changed"),
947 G_TYPE_FROM_CLASS (gobject_class),
949 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
951 _gtk_marshal_VOID__VOID,
959 binding_set = gtk_binding_set_by_class (klass);
961 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
962 "activate-focus", 0);
963 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
964 "activate-focus", 0);
966 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
967 "activate-default", 0);
968 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
969 "activate-default", 0);
970 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
971 "activate-default", 0);
973 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
974 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
975 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
976 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
978 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
979 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
980 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
981 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
985 gtk_window_init (GtkWindow *window)
987 GtkWindowPrivate *priv;
989 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
994 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
995 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
997 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
999 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1002 priv->wmclass_name = g_strdup (g_get_prgname ());
1003 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1004 priv->wm_role = NULL;
1005 priv->geometry_info = NULL;
1006 priv->type = GTK_WINDOW_TOPLEVEL;
1007 priv->focus_widget = NULL;
1008 priv->default_widget = NULL;
1009 priv->configure_request_count = 0;
1010 priv->resizable = TRUE;
1011 priv->configure_notify_received = FALSE;
1012 priv->position = GTK_WIN_POS_NONE;
1013 priv->need_default_size = TRUE;
1014 priv->need_default_position = TRUE;
1015 priv->modal = FALSE;
1017 priv->has_frame = FALSE;
1018 priv->frame_left = 0;
1019 priv->frame_right = 0;
1020 priv->frame_top = 0;
1021 priv->frame_bottom = 0;
1022 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1023 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1024 priv->decorated = TRUE;
1025 priv->mnemonic_modifier = GDK_MOD1_MASK;
1026 priv->visual = gdk_screen_get_system_visual (gdk_screen_get_default ());
1028 priv->accept_focus = TRUE;
1029 priv->focus_on_map = TRUE;
1030 priv->deletable = TRUE;
1031 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1032 priv->opacity = 1.0;
1033 priv->startup_id = NULL;
1034 priv->mnemonics_visible = TRUE;
1036 g_object_ref_sink (window);
1037 priv->has_user_ref_count = TRUE;
1038 toplevel_list = g_slist_prepend (toplevel_list, window);
1040 gtk_decorated_window_init (window);
1042 g_signal_connect (gdk_screen_get_default (), "composited-changed",
1043 G_CALLBACK (gtk_window_on_composited_changed), window);
1047 gtk_window_set_property (GObject *object,
1049 const GValue *value,
1052 GtkWindow *window = GTK_WINDOW (object);
1053 GtkWindowPrivate *priv = window->priv;
1058 priv->type = g_value_get_enum (value);
1061 gtk_window_set_title (window, g_value_get_string (value));
1064 gtk_window_set_role (window, g_value_get_string (value));
1066 case PROP_STARTUP_ID:
1067 gtk_window_set_startup_id (window, g_value_get_string (value));
1069 case PROP_RESIZABLE:
1070 priv->resizable = g_value_get_boolean (value);
1071 gtk_widget_queue_resize (GTK_WIDGET (window));
1074 gtk_window_set_modal (window, g_value_get_boolean (value));
1077 gtk_window_set_position (window, g_value_get_enum (value));
1079 case PROP_DEFAULT_WIDTH:
1080 gtk_window_set_default_size_internal (window,
1081 TRUE, g_value_get_int (value),
1084 case PROP_DEFAULT_HEIGHT:
1085 gtk_window_set_default_size_internal (window,
1087 TRUE, g_value_get_int (value), FALSE);
1089 case PROP_DESTROY_WITH_PARENT:
1090 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1093 gtk_window_set_icon (window,
1094 g_value_get_object (value));
1096 case PROP_ICON_NAME:
1097 gtk_window_set_icon_name (window, g_value_get_string (value));
1100 gtk_window_set_screen (window, g_value_get_object (value));
1103 gtk_window_set_visual (window, g_value_get_object (value));
1105 case PROP_TYPE_HINT:
1106 gtk_window_set_type_hint (window,
1107 g_value_get_enum (value));
1109 case PROP_SKIP_TASKBAR_HINT:
1110 gtk_window_set_skip_taskbar_hint (window,
1111 g_value_get_boolean (value));
1113 case PROP_SKIP_PAGER_HINT:
1114 gtk_window_set_skip_pager_hint (window,
1115 g_value_get_boolean (value));
1117 case PROP_URGENCY_HINT:
1118 gtk_window_set_urgency_hint (window,
1119 g_value_get_boolean (value));
1121 case PROP_ACCEPT_FOCUS:
1122 gtk_window_set_accept_focus (window,
1123 g_value_get_boolean (value));
1125 case PROP_FOCUS_ON_MAP:
1126 gtk_window_set_focus_on_map (window,
1127 g_value_get_boolean (value));
1129 case PROP_DECORATED:
1130 gtk_window_set_decorated (window, g_value_get_boolean (value));
1132 case PROP_DELETABLE:
1133 gtk_window_set_deletable (window, g_value_get_boolean (value));
1136 gtk_window_set_gravity (window, g_value_get_enum (value));
1138 case PROP_TRANSIENT_FOR:
1139 gtk_window_set_transient_for (window, g_value_get_object (value));
1142 gtk_window_set_opacity (window, g_value_get_double (value));
1144 case PROP_MNEMONICS_VISIBLE:
1145 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1148 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1154 gtk_window_get_property (GObject *object,
1159 GtkWindow *window = GTK_WINDOW (object);
1160 GtkWindowPrivate *priv = window->priv;
1164 GtkWindowGeometryInfo *info;
1166 g_value_set_enum (value, priv->type);
1169 g_value_set_string (value, priv->wm_role);
1172 g_value_set_string (value, priv->title);
1174 case PROP_RESIZABLE:
1175 g_value_set_boolean (value, priv->resizable);
1178 g_value_set_boolean (value, priv->modal);
1181 g_value_set_enum (value, priv->position);
1183 case PROP_DEFAULT_WIDTH:
1184 info = gtk_window_get_geometry_info (window, FALSE);
1186 g_value_set_int (value, -1);
1188 g_value_set_int (value, info->default_width);
1190 case PROP_DEFAULT_HEIGHT:
1191 info = gtk_window_get_geometry_info (window, FALSE);
1193 g_value_set_int (value, -1);
1195 g_value_set_int (value, info->default_height);
1197 case PROP_DESTROY_WITH_PARENT:
1198 g_value_set_boolean (value, priv->destroy_with_parent);
1201 g_value_set_object (value, gtk_window_get_icon (window));
1203 case PROP_ICON_NAME:
1204 g_value_set_string (value, gtk_window_get_icon_name (window));
1207 g_value_set_object (value, gdk_visual_get_screen (priv->visual));
1210 g_value_set_object (value, priv->visual);
1212 case PROP_IS_ACTIVE:
1213 g_value_set_boolean (value, priv->is_active);
1215 case PROP_HAS_TOPLEVEL_FOCUS:
1216 g_value_set_boolean (value, priv->has_toplevel_focus);
1218 case PROP_TYPE_HINT:
1219 g_value_set_enum (value, priv->type_hint);
1221 case PROP_SKIP_TASKBAR_HINT:
1222 g_value_set_boolean (value,
1223 gtk_window_get_skip_taskbar_hint (window));
1225 case PROP_SKIP_PAGER_HINT:
1226 g_value_set_boolean (value,
1227 gtk_window_get_skip_pager_hint (window));
1229 case PROP_URGENCY_HINT:
1230 g_value_set_boolean (value,
1231 gtk_window_get_urgency_hint (window));
1233 case PROP_ACCEPT_FOCUS:
1234 g_value_set_boolean (value,
1235 gtk_window_get_accept_focus (window));
1237 case PROP_FOCUS_ON_MAP:
1238 g_value_set_boolean (value,
1239 gtk_window_get_focus_on_map (window));
1241 case PROP_DECORATED:
1242 g_value_set_boolean (value, gtk_window_get_decorated (window));
1244 case PROP_DELETABLE:
1245 g_value_set_boolean (value, gtk_window_get_deletable (window));
1248 g_value_set_enum (value, gtk_window_get_gravity (window));
1250 case PROP_TRANSIENT_FOR:
1251 g_value_set_object (value, gtk_window_get_transient_for (window));
1254 g_value_set_double (value, gtk_window_get_opacity (window));
1256 case PROP_MNEMONICS_VISIBLE:
1257 g_value_set_boolean (value, priv->mnemonics_visible);
1260 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1266 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1268 parent_buildable_iface = g_type_interface_peek_parent (iface);
1269 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1270 iface->parser_finished = gtk_window_buildable_parser_finished;
1271 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1272 iface->custom_finished = gtk_window_buildable_custom_finished;
1276 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1277 GtkBuilder *builder,
1279 const GValue *value)
1281 GtkWindow *window = GTK_WINDOW (buildable);
1282 GtkWindowPrivate *priv = window->priv;
1284 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1285 priv->builder_visible = TRUE;
1287 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1291 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1292 GtkBuilder *builder)
1294 GtkWindow *window = GTK_WINDOW (buildable);
1295 GtkWindowPrivate *priv = window->priv;
1299 if (priv->builder_visible)
1300 gtk_widget_show (GTK_WIDGET (buildable));
1302 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1303 for (l = accels; l; l = l->next)
1305 object = gtk_builder_get_object (builder, l->data);
1308 g_warning ("Unknown accel group %s specified in window %s",
1309 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1312 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1313 GTK_ACCEL_GROUP (object));
1317 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1319 parent_buildable_iface->parser_finished (buildable, builder);
1325 } GSListSubParserData;
1328 window_start_element (GMarkupParseContext *context,
1329 const gchar *element_name,
1330 const gchar **names,
1331 const gchar **values,
1336 GSListSubParserData *data = (GSListSubParserData*)user_data;
1338 if (strcmp (element_name, "group") == 0)
1340 for (i = 0; names[i]; i++)
1342 if (strcmp (names[i], "name") == 0)
1343 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1346 else if (strcmp (element_name, "accel-groups") == 0)
1349 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1354 static const GMarkupParser window_parser =
1356 window_start_element
1360 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1361 GtkBuilder *builder,
1363 const gchar *tagname,
1364 GMarkupParser *parser,
1367 GSListSubParserData *parser_data;
1369 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1370 tagname, parser, data))
1373 if (strcmp (tagname, "accel-groups") == 0)
1375 parser_data = g_slice_new0 (GSListSubParserData);
1376 parser_data->items = NULL;
1377 parser_data->object = G_OBJECT (buildable);
1379 *parser = window_parser;
1380 *data = parser_data;
1388 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1389 GtkBuilder *builder,
1391 const gchar *tagname,
1394 GSListSubParserData *data;
1396 parent_buildable_iface->custom_finished (buildable, builder, child,
1397 tagname, user_data);
1399 if (strcmp (tagname, "accel-groups") != 0)
1402 data = (GSListSubParserData*)user_data;
1404 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1405 data->items, (GDestroyNotify) g_slist_free);
1407 g_slice_free (GSListSubParserData, data);
1412 * @type: type of window
1414 * Creates a new #GtkWindow, which is a toplevel window that can
1415 * contain other widgets. Nearly always, the type of the window should
1416 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1417 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1418 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1419 * dialogs, though in some other toolkits dialogs are called "popups".
1420 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1421 * On X11, popup windows are not controlled by the <link
1422 * linkend="gtk-X11-arch">window manager</link>.
1424 * If you simply want an undecorated window (no window borders), use
1425 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1427 * Return value: a new #GtkWindow.
1430 gtk_window_new (GtkWindowType type)
1432 GtkWindowPrivate *priv;
1435 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1437 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1438 priv = window->priv;
1442 return GTK_WIDGET (window);
1446 * gtk_window_set_title:
1447 * @window: a #GtkWindow
1448 * @title: title of the window
1450 * Sets the title of the #GtkWindow. The title of a window will be
1451 * displayed in its title bar; on the X Window System, the title bar
1452 * is rendered by the <link linkend="gtk-X11-arch">window
1453 * manager</link>, so exactly how the title appears to users may vary
1454 * according to a user's exact configuration. The title should help a
1455 * user distinguish this window from other windows they may have
1456 * open. A good title might include the application name and current
1457 * document filename, for example.
1461 gtk_window_set_title (GtkWindow *window,
1464 GtkWindowPrivate *priv;
1468 g_return_if_fail (GTK_IS_WINDOW (window));
1470 priv = window->priv;
1471 widget = GTK_WIDGET (window);
1473 new_title = g_strdup (title);
1474 g_free (priv->title);
1475 priv->title = new_title;
1477 if (gtk_widget_get_realized (widget))
1479 gdk_window_set_title (gtk_widget_get_window (widget),
1482 gtk_decorated_window_set_title (window, title);
1485 g_object_notify (G_OBJECT (window), "title");
1489 * gtk_window_get_title:
1490 * @window: a #GtkWindow
1492 * Retrieves the title of the window. See gtk_window_set_title().
1494 * Return value: the title of the window, or %NULL if none has
1495 * been set explicitely. The returned string is owned by the widget
1496 * and must not be modified or freed.
1498 G_CONST_RETURN gchar *
1499 gtk_window_get_title (GtkWindow *window)
1501 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1503 return window->priv->title;
1507 * gtk_window_set_wmclass:
1508 * @window: a #GtkWindow
1509 * @wmclass_name: window name hint
1510 * @wmclass_class: window class hint
1512 * Don't use this function. It sets the X Window System "class" and
1513 * "name" hints for a window. According to the ICCCM, you should
1514 * always set these to the same value for all windows in an
1515 * application, and GTK+ sets them to that value by default, so calling
1516 * this function is sort of pointless. However, you may want to call
1517 * gtk_window_set_role() on each window in your application, for the
1518 * benefit of the session manager. Setting the role allows the window
1519 * manager to restore window positions when loading a saved session.
1523 gtk_window_set_wmclass (GtkWindow *window,
1524 const gchar *wmclass_name,
1525 const gchar *wmclass_class)
1527 GtkWindowPrivate *priv;
1529 g_return_if_fail (GTK_IS_WINDOW (window));
1531 priv = window->priv;
1533 g_free (priv->wmclass_name);
1534 priv->wmclass_name = g_strdup (wmclass_name);
1536 g_free (priv->wmclass_class);
1537 priv->wmclass_class = g_strdup (wmclass_class);
1539 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1540 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1544 * gtk_window_set_role:
1545 * @window: a #GtkWindow
1546 * @role: unique identifier for the window to be used when restoring a session
1548 * This function is only useful on X11, not with other GTK+ targets.
1550 * In combination with the window title, the window role allows a
1551 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1552 * same" window when an application is restarted. So for example you
1553 * might set the "toolbox" role on your app's toolbox window, so that
1554 * when the user restarts their session, the window manager can put
1555 * the toolbox back in the same place.
1557 * If a window already has a unique title, you don't need to set the
1558 * role, since the WM can use the title to identify the window when
1559 * restoring the session.
1563 gtk_window_set_role (GtkWindow *window,
1566 GtkWindowPrivate *priv;
1569 g_return_if_fail (GTK_IS_WINDOW (window));
1571 priv = window->priv;
1573 new_role = g_strdup (role);
1574 g_free (priv->wm_role);
1575 priv->wm_role = new_role;
1577 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1578 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1581 g_object_notify (G_OBJECT (window), "role");
1585 * gtk_window_set_startup_id:
1586 * @window: a #GtkWindow
1587 * @startup_id: a string with startup-notification identifier
1589 * Startup notification identifiers are used by desktop environment to
1590 * track application startup, to provide user feedback and other
1591 * features. This function changes the corresponding property on the
1592 * underlying GdkWindow. Normally, startup identifier is managed
1593 * automatically and you should only use this function in special cases
1594 * like transferring focus from other processes. You should use this
1595 * function before calling gtk_window_present() or any equivalent
1596 * function generating a window map event.
1598 * This function is only useful on X11, not with other GTK+ targets.
1603 gtk_window_set_startup_id (GtkWindow *window,
1604 const gchar *startup_id)
1606 GtkWindowPrivate *priv;
1609 g_return_if_fail (GTK_IS_WINDOW (window));
1611 priv = window->priv;
1612 widget = GTK_WIDGET (window);
1614 g_free (priv->startup_id);
1615 priv->startup_id = g_strdup (startup_id);
1617 if (gtk_widget_get_realized (widget))
1619 GdkWindow *gdk_window;
1620 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1622 gdk_window = gtk_widget_get_window (widget);
1624 #ifdef GDK_WINDOWING_X11
1625 if (timestamp != GDK_CURRENT_TIME)
1626 gdk_x11_window_set_user_time (gdk_window, timestamp);
1629 /* Here we differentiate real and "fake" startup notification IDs,
1630 * constructed on purpose just to pass interaction timestamp
1632 if (startup_id_is_fake (priv->startup_id))
1633 gtk_window_present_with_time (window, timestamp);
1636 gdk_window_set_startup_id (gdk_window,
1639 /* If window is mapped, terminate the startup-notification too */
1640 if (gtk_widget_get_mapped (widget) &&
1641 !disable_startup_notification)
1642 gdk_notify_startup_complete_with_id (priv->startup_id);
1646 g_object_notify (G_OBJECT (window), "startup-id");
1650 * gtk_window_get_role:
1651 * @window: a #GtkWindow
1653 * Returns the role of the window. See gtk_window_set_role() for
1654 * further explanation.
1656 * Return value: the role of the window if set, or %NULL. The
1657 * returned is owned by the widget and must not be modified
1660 G_CONST_RETURN gchar *
1661 gtk_window_get_role (GtkWindow *window)
1663 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1665 return window->priv->wm_role;
1669 * gtk_window_set_focus:
1670 * @window: a #GtkWindow
1671 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1672 * any focus widget for the toplevel window.
1674 * If @focus is not the current focus widget, and is focusable, sets
1675 * it as the focus widget for the window. If @focus is %NULL, unsets
1676 * the focus widget for this window. To set the focus to a particular
1677 * widget in the toplevel, it is usually more convenient to use
1678 * gtk_widget_grab_focus() instead of this function.
1681 gtk_window_set_focus (GtkWindow *window,
1684 GtkWindowPrivate *priv;
1687 g_return_if_fail (GTK_IS_WINDOW (window));
1689 priv = window->priv;
1693 g_return_if_fail (GTK_IS_WIDGET (focus));
1694 g_return_if_fail (gtk_widget_get_can_focus (focus));
1698 gtk_widget_grab_focus (focus);
1701 /* Clear the existing focus chain, so that when we focus into
1702 * the window again, we start at the beginnning.
1704 GtkWidget *widget = priv->focus_widget;
1707 while ((parent = gtk_widget_get_parent (widget)))
1710 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1714 _gtk_window_internal_set_focus (window, NULL);
1719 _gtk_window_internal_set_focus (GtkWindow *window,
1722 GtkWindowPrivate *priv;
1724 g_return_if_fail (GTK_IS_WINDOW (window));
1726 priv = window->priv;
1728 if ((priv->focus_widget != focus) ||
1729 (focus && !gtk_widget_has_focus (focus)))
1730 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1734 * gtk_window_set_default:
1735 * @window: a #GtkWindow
1736 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1737 * default widget for the toplevel.
1739 * The default widget is the widget that's activated when the user
1740 * presses Enter in a dialog (for example). This function sets or
1741 * unsets the default widget for a #GtkWindow about. When setting
1742 * (rather than unsetting) the default widget it's generally easier to
1743 * call gtk_widget_grab_focus() on the widget. Before making a widget
1744 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1745 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1748 gtk_window_set_default (GtkWindow *window,
1749 GtkWidget *default_widget)
1751 GtkWindowPrivate *priv;
1753 g_return_if_fail (GTK_IS_WINDOW (window));
1755 priv = window->priv;
1758 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1760 if (priv->default_widget != default_widget)
1762 GtkWidget *old_default_widget = NULL;
1765 g_object_ref (default_widget);
1767 if (priv->default_widget)
1769 old_default_widget = priv->default_widget;
1771 if (priv->focus_widget != priv->default_widget ||
1772 !gtk_widget_get_receives_default (priv->default_widget))
1773 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1775 gtk_widget_queue_draw (priv->default_widget);
1778 priv->default_widget = default_widget;
1780 if (priv->default_widget)
1782 if (priv->focus_widget == NULL ||
1783 !gtk_widget_get_receives_default (priv->focus_widget))
1784 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1786 gtk_widget_queue_draw (priv->default_widget);
1789 if (old_default_widget)
1790 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1794 g_object_notify (G_OBJECT (default_widget), "has-default");
1795 g_object_unref (default_widget);
1801 * gtk_window_get_default_widget:
1802 * @window: a #GtkWindow
1804 * Returns the default widget for @window. See gtk_window_set_default()
1807 * Returns: (transfer none): the default widget, or %NULL if there is none.
1812 gtk_window_get_default_widget (GtkWindow *window)
1814 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1816 return window->priv->default_widget;
1820 handle_keys_changed (gpointer data)
1822 GtkWindow *window = GTK_WINDOW (data);
1823 GtkWindowPrivate *priv = window->priv;
1825 if (priv->keys_changed_handler)
1827 g_source_remove (priv->keys_changed_handler);
1828 priv->keys_changed_handler = 0;
1831 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1837 gtk_window_notify_keys_changed (GtkWindow *window)
1839 GtkWindowPrivate *priv = window->priv;
1841 if (!priv->keys_changed_handler)
1842 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1846 * gtk_window_add_accel_group:
1847 * @window: window to attach accelerator group to
1848 * @accel_group: a #GtkAccelGroup
1850 * Associate @accel_group with @window, such that calling
1851 * gtk_accel_groups_activate() on @window will activate accelerators
1855 gtk_window_add_accel_group (GtkWindow *window,
1856 GtkAccelGroup *accel_group)
1858 g_return_if_fail (GTK_IS_WINDOW (window));
1859 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1861 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1862 g_signal_connect_object (accel_group, "accel-changed",
1863 G_CALLBACK (gtk_window_notify_keys_changed),
1864 window, G_CONNECT_SWAPPED);
1865 gtk_window_notify_keys_changed (window);
1869 * gtk_window_remove_accel_group:
1870 * @window: a #GtkWindow
1871 * @accel_group: a #GtkAccelGroup
1873 * Reverses the effects of gtk_window_add_accel_group().
1876 gtk_window_remove_accel_group (GtkWindow *window,
1877 GtkAccelGroup *accel_group)
1879 g_return_if_fail (GTK_IS_WINDOW (window));
1880 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1882 g_signal_handlers_disconnect_by_func (accel_group,
1883 gtk_window_notify_keys_changed,
1885 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1886 gtk_window_notify_keys_changed (window);
1889 static GtkMnemonicHash *
1890 gtk_window_get_mnemonic_hash (GtkWindow *window,
1893 GtkWindowPrivate *private = window->priv;
1895 if (!private->mnemonic_hash && create)
1896 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1898 return private->mnemonic_hash;
1902 * gtk_window_add_mnemonic:
1903 * @window: a #GtkWindow
1904 * @keyval: the mnemonic
1905 * @target: the widget that gets activated by the mnemonic
1907 * Adds a mnemonic to this window.
1910 gtk_window_add_mnemonic (GtkWindow *window,
1914 g_return_if_fail (GTK_IS_WINDOW (window));
1915 g_return_if_fail (GTK_IS_WIDGET (target));
1917 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1919 gtk_window_notify_keys_changed (window);
1923 * gtk_window_remove_mnemonic:
1924 * @window: a #GtkWindow
1925 * @keyval: the mnemonic
1926 * @target: the widget that gets activated by the mnemonic
1928 * Removes a mnemonic from this window.
1931 gtk_window_remove_mnemonic (GtkWindow *window,
1935 g_return_if_fail (GTK_IS_WINDOW (window));
1936 g_return_if_fail (GTK_IS_WIDGET (target));
1938 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1940 gtk_window_notify_keys_changed (window);
1944 * gtk_window_mnemonic_activate:
1945 * @window: a #GtkWindow
1946 * @keyval: the mnemonic
1947 * @modifier: the modifiers
1948 * @returns: %TRUE if the activation is done.
1950 * Activates the targets associated with the mnemonic.
1953 gtk_window_mnemonic_activate (GtkWindow *window,
1955 GdkModifierType modifier)
1957 GtkWindowPrivate *priv;
1959 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1961 priv = window->priv;
1963 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1965 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1967 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1974 * gtk_window_set_mnemonic_modifier:
1975 * @window: a #GtkWindow
1976 * @modifier: the modifier mask used to activate
1977 * mnemonics on this window.
1979 * Sets the mnemonic modifier for this window.
1982 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1983 GdkModifierType modifier)
1985 GtkWindowPrivate *priv;
1987 g_return_if_fail (GTK_IS_WINDOW (window));
1988 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1990 priv = window->priv;
1992 priv->mnemonic_modifier = modifier;
1993 gtk_window_notify_keys_changed (window);
1997 * gtk_window_get_mnemonic_modifier:
1998 * @window: a #GtkWindow
2000 * Returns the mnemonic modifier for this window. See
2001 * gtk_window_set_mnemonic_modifier().
2003 * Return value: the modifier mask used to activate
2004 * mnemonics on this window.
2007 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2009 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2011 return window->priv->mnemonic_modifier;
2015 * gtk_window_set_position:
2016 * @window: a #GtkWindow.
2017 * @position: a position constraint.
2019 * Sets a position constraint for this window. If the old or new
2020 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2021 * the window to be repositioned to satisfy the new constraint.
2024 gtk_window_set_position (GtkWindow *window,
2025 GtkWindowPosition position)
2027 GtkWindowPrivate *priv;
2029 g_return_if_fail (GTK_IS_WINDOW (window));
2031 priv = window->priv;
2033 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2034 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2036 GtkWindowGeometryInfo *info;
2038 info = gtk_window_get_geometry_info (window, TRUE);
2040 /* this flag causes us to re-request the CENTER_ALWAYS
2041 * constraint in gtk_window_move_resize(), see
2042 * comment in that function.
2044 info->position_constraints_changed = TRUE;
2046 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2049 priv->position = position;
2051 g_object_notify (G_OBJECT (window), "window-position");
2055 * gtk_window_activate_focus:
2056 * @window: a #GtkWindow
2058 * Activates the current focused widget within the window.
2060 * Return value: %TRUE if a widget got activated.
2063 gtk_window_activate_focus (GtkWindow *window)
2065 GtkWindowPrivate *priv;
2067 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2069 priv = window->priv;
2071 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2072 return gtk_widget_activate (priv->focus_widget);
2078 * gtk_window_get_focus:
2079 * @window: a #GtkWindow
2081 * Retrieves the current focused widget within the window.
2082 * Note that this is the widget that would have the focus
2083 * if the toplevel window focused; if the toplevel window
2084 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2085 * not be %TRUE for the widget.
2087 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2090 gtk_window_get_focus (GtkWindow *window)
2092 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2094 return window->priv->focus_widget;
2098 * gtk_window_activate_default:
2099 * @window: a #GtkWindow
2101 * Activates the default widget for the window, unless the current
2102 * focused widget has been configured to receive the default action
2103 * (see gtk_widget_set_receives_default()), in which case the
2104 * focused widget is activated.
2106 * Return value: %TRUE if a widget got activated.
2109 gtk_window_activate_default (GtkWindow *window)
2111 GtkWindowPrivate *priv;
2113 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2115 priv = window->priv;
2117 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2118 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2119 return gtk_widget_activate (priv->default_widget);
2120 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2121 return gtk_widget_activate (priv->focus_widget);
2127 * gtk_window_set_modal:
2128 * @window: a #GtkWindow
2129 * @modal: whether the window is modal
2131 * Sets a window modal or non-modal. Modal windows prevent interaction
2132 * with other windows in the same application. To keep modal dialogs
2133 * on top of main application windows, use
2134 * gtk_window_set_transient_for() to make the dialog transient for the
2135 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2136 * will then disallow lowering the dialog below the parent.
2141 gtk_window_set_modal (GtkWindow *window,
2144 GtkWindowPrivate *priv;
2147 g_return_if_fail (GTK_IS_WINDOW (window));
2149 priv = window->priv;
2151 modal = modal != FALSE;
2152 if (priv->modal == modal)
2155 priv->modal = modal;
2156 widget = GTK_WIDGET (window);
2158 /* adjust desired modality state */
2159 if (gtk_widget_get_realized (widget))
2162 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2164 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2167 if (gtk_widget_get_visible (widget))
2170 gtk_grab_add (widget);
2172 gtk_grab_remove (widget);
2175 g_object_notify (G_OBJECT (window), "modal");
2179 * gtk_window_get_modal:
2180 * @window: a #GtkWindow
2182 * Returns whether the window is modal. See gtk_window_set_modal().
2184 * Return value: %TRUE if the window is set to be modal and
2185 * establishes a grab when shown
2188 gtk_window_get_modal (GtkWindow *window)
2190 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2192 return window->priv->modal;
2196 * gtk_window_list_toplevels:
2198 * Returns a list of all existing toplevel windows. The widgets
2199 * in the list are not individually referenced. If you want
2200 * to iterate through the list and perform actions involving
2201 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2202 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2203 * then unref all the widgets afterwards.
2205 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2208 gtk_window_list_toplevels (void)
2213 for (slist = toplevel_list; slist; slist = slist->next)
2214 list = g_list_prepend (list, slist->data);
2220 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2222 GList *embedded_windows;
2224 g_return_if_fail (GTK_IS_WINDOW (window));
2226 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2227 if (embedded_windows)
2228 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2229 embedded_windows = g_list_prepend (embedded_windows,
2230 GUINT_TO_POINTER (xid));
2232 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2235 (GDestroyNotify) g_list_free : NULL);
2239 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2241 GList *embedded_windows;
2244 g_return_if_fail (GTK_IS_WINDOW (window));
2246 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2247 if (embedded_windows)
2248 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2250 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2253 embedded_windows = g_list_remove_link (embedded_windows, node);
2254 g_list_free_1 (node);
2257 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2260 (GDestroyNotify) g_list_free : NULL);
2264 gtk_window_dispose (GObject *object)
2266 GtkWindow *window = GTK_WINDOW (object);
2268 gtk_window_set_focus (window, NULL);
2269 gtk_window_set_default (window, NULL);
2271 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2275 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2277 gtk_widget_destroy (GTK_WIDGET (child));
2281 connect_parent_destroyed (GtkWindow *window)
2283 GtkWindowPrivate *priv = window->priv;
2285 if (priv->transient_parent)
2287 g_signal_connect (priv->transient_parent,
2289 G_CALLBACK (parent_destroyed_callback),
2295 disconnect_parent_destroyed (GtkWindow *window)
2297 GtkWindowPrivate *priv = window->priv;
2299 if (priv->transient_parent)
2301 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2302 parent_destroyed_callback,
2308 gtk_window_transient_parent_realized (GtkWidget *parent,
2311 if (gtk_widget_get_realized (window))
2312 gdk_window_set_transient_for (gtk_widget_get_window (window),
2313 gtk_widget_get_window (parent));
2317 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2320 if (gtk_widget_get_realized (window))
2321 gdk_property_delete (gtk_widget_get_window (window),
2322 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2326 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2330 gtk_window_set_screen (window, gtk_window_get_screen (parent));
2334 gtk_window_unset_transient_for (GtkWindow *window)
2336 GtkWindowPrivate *priv = window->priv;
2338 if (priv->transient_parent)
2340 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2341 gtk_window_transient_parent_realized,
2343 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2344 gtk_window_transient_parent_unrealized,
2346 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2347 gtk_window_transient_parent_screen_changed,
2349 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2350 gtk_widget_destroyed,
2351 &priv->transient_parent);
2353 if (priv->destroy_with_parent)
2354 disconnect_parent_destroyed (window);
2356 priv->transient_parent = NULL;
2358 if (priv->transient_parent_group)
2360 priv->transient_parent_group = FALSE;
2361 gtk_window_group_remove_window (priv->group,
2368 * gtk_window_set_transient_for:
2369 * @window: a #GtkWindow
2370 * @parent: (allow-none): parent window, or %NULL
2372 * Dialog windows should be set transient for the main application
2373 * window they were spawned from. This allows <link
2374 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2375 * dialog on top of the main window, or center the dialog over the
2376 * main window. gtk_dialog_new_with_buttons() and other convenience
2377 * functions in GTK+ will sometimes call
2378 * gtk_window_set_transient_for() on your behalf.
2380 * Passing %NULL for @parent unsets the current transient window.
2382 * On Windows, this function puts the child window on top of the parent,
2383 * much as the window manager would have done on X.
2386 gtk_window_set_transient_for (GtkWindow *window,
2389 GtkWindowPrivate *priv;
2391 g_return_if_fail (GTK_IS_WINDOW (window));
2392 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2393 g_return_if_fail (window != parent);
2395 priv = window->priv;
2397 if (priv->transient_parent)
2399 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2400 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2401 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2402 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2403 GTK_WIDGET (window));
2405 gtk_window_unset_transient_for (window);
2408 priv->transient_parent = parent;
2412 g_signal_connect (parent, "destroy",
2413 G_CALLBACK (gtk_widget_destroyed),
2414 &priv->transient_parent);
2415 g_signal_connect (parent, "realize",
2416 G_CALLBACK (gtk_window_transient_parent_realized),
2418 g_signal_connect (parent, "unrealize",
2419 G_CALLBACK (gtk_window_transient_parent_unrealized),
2421 g_signal_connect (parent, "notify::screen",
2422 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2425 gtk_window_set_screen (window, gtk_window_get_screen (parent));
2427 if (priv->destroy_with_parent)
2428 connect_parent_destroyed (window);
2430 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2431 gtk_widget_get_realized (GTK_WIDGET (parent)))
2432 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2433 GTK_WIDGET (window));
2435 if (parent->priv->group)
2437 gtk_window_group_add_window (parent->priv->group, window);
2438 priv->transient_parent_group = TRUE;
2444 * gtk_window_get_transient_for:
2445 * @window: a #GtkWindow
2447 * Fetches the transient parent for this window. See
2448 * gtk_window_set_transient_for().
2450 * Return value: (transfer none): the transient parent for this window, or %NULL
2451 * if no transient parent has been set.
2454 gtk_window_get_transient_for (GtkWindow *window)
2456 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2458 return window->priv->transient_parent;
2462 * gtk_window_set_opacity:
2463 * @window: a #GtkWindow
2464 * @opacity: desired opacity, between 0 and 1
2466 * Request the windowing system to make @window partially transparent,
2467 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2468 * of the opacity parameter are clamped to the [0,1] range.) On X11
2469 * this has any effect only on X screens with a compositing manager
2470 * running. See gtk_widget_is_composited(). On Windows it should work
2473 * Note that setting a window's opacity after the window has been
2474 * shown causes it to flicker once on Windows.
2479 gtk_window_set_opacity (GtkWindow *window,
2482 GtkWindowPrivate *priv;
2484 g_return_if_fail (GTK_IS_WINDOW (window));
2486 priv = window->priv;
2490 else if (opacity > 1.0)
2493 priv->opacity_set = TRUE;
2494 priv->opacity = opacity;
2496 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2497 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2502 * gtk_window_get_opacity:
2503 * @window: a #GtkWindow
2505 * Fetches the requested opacity for this window. See
2506 * gtk_window_set_opacity().
2508 * Return value: the requested opacity for this window.
2513 gtk_window_get_opacity (GtkWindow *window)
2515 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2517 return window->priv->opacity;
2521 * gtk_window_set_type_hint:
2522 * @window: a #GtkWindow
2523 * @hint: the window type
2525 * By setting the type hint for the window, you allow the window
2526 * manager to decorate and handle the window in a way which is
2527 * suitable to the function of the window in your application.
2529 * This function should be called before the window becomes visible.
2531 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2532 * will sometimes call gtk_window_set_type_hint() on your behalf.
2536 gtk_window_set_type_hint (GtkWindow *window,
2537 GdkWindowTypeHint hint)
2539 GtkWindowPrivate *priv;
2541 g_return_if_fail (GTK_IS_WINDOW (window));
2542 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2544 priv = window->priv;
2546 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2547 priv->gdk_type_hint = hint;
2549 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2551 priv->reset_type_hint = TRUE;
2552 priv->type_hint = hint;
2556 * gtk_window_get_type_hint:
2557 * @window: a #GtkWindow
2559 * Gets the type hint for this window. See gtk_window_set_type_hint().
2561 * Return value: the type hint for @window.
2564 gtk_window_get_type_hint (GtkWindow *window)
2566 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2568 return window->priv->type_hint;
2572 * gtk_window_set_skip_taskbar_hint:
2573 * @window: a #GtkWindow
2574 * @setting: %TRUE to keep this window from appearing in the task bar
2576 * Windows may set a hint asking the desktop environment not to display
2577 * the window in the task bar. This function sets this hint.
2582 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2585 GtkWindowPrivate *priv;
2587 g_return_if_fail (GTK_IS_WINDOW (window));
2589 priv = window->priv;
2591 setting = setting != FALSE;
2593 if (priv->skips_taskbar != setting)
2595 priv->skips_taskbar = setting;
2596 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2597 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2598 priv->skips_taskbar);
2599 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2604 * gtk_window_get_skip_taskbar_hint:
2605 * @window: a #GtkWindow
2607 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2609 * Return value: %TRUE if window shouldn't be in taskbar
2614 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2616 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2618 return window->priv->skips_taskbar;
2622 * gtk_window_set_skip_pager_hint:
2623 * @window: a #GtkWindow
2624 * @setting: %TRUE to keep this window from appearing in the pager
2626 * Windows may set a hint asking the desktop environment not to display
2627 * the window in the pager. This function sets this hint.
2628 * (A "pager" is any desktop navigation tool such as a workspace
2629 * switcher that displays a thumbnail representation of the windows
2635 gtk_window_set_skip_pager_hint (GtkWindow *window,
2638 GtkWindowPrivate *priv;
2640 g_return_if_fail (GTK_IS_WINDOW (window));
2642 priv = window->priv;
2644 setting = setting != FALSE;
2646 if (priv->skips_pager != setting)
2648 priv->skips_pager = setting;
2649 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2650 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2652 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2657 * gtk_window_get_skip_pager_hint:
2658 * @window: a #GtkWindow
2660 * Gets the value set by gtk_window_set_skip_pager_hint().
2662 * Return value: %TRUE if window shouldn't be in pager
2667 gtk_window_get_skip_pager_hint (GtkWindow *window)
2669 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2671 return window->priv->skips_pager;
2675 * gtk_window_set_urgency_hint:
2676 * @window: a #GtkWindow
2677 * @setting: %TRUE to mark this window as urgent
2679 * Windows may set a hint asking the desktop environment to draw
2680 * the users attention to the window. This function sets this hint.
2685 gtk_window_set_urgency_hint (GtkWindow *window,
2688 GtkWindowPrivate *priv;
2690 g_return_if_fail (GTK_IS_WINDOW (window));
2692 priv = window->priv;
2694 setting = setting != FALSE;
2696 if (priv->urgent != setting)
2698 priv->urgent = setting;
2699 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2700 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2702 g_object_notify (G_OBJECT (window), "urgency-hint");
2707 * gtk_window_get_urgency_hint:
2708 * @window: a #GtkWindow
2710 * Gets the value set by gtk_window_set_urgency_hint()
2712 * Return value: %TRUE if window is urgent
2717 gtk_window_get_urgency_hint (GtkWindow *window)
2719 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2721 return window->priv->urgent;
2725 * gtk_window_set_accept_focus:
2726 * @window: a #GtkWindow
2727 * @setting: %TRUE to let this window receive input focus
2729 * Windows may set a hint asking the desktop environment not to receive
2730 * the input focus. This function sets this hint.
2735 gtk_window_set_accept_focus (GtkWindow *window,
2738 GtkWindowPrivate *priv;
2740 g_return_if_fail (GTK_IS_WINDOW (window));
2742 priv = window->priv;
2744 setting = setting != FALSE;
2746 if (priv->accept_focus != setting)
2748 priv->accept_focus = setting;
2749 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2750 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2751 priv->accept_focus);
2752 g_object_notify (G_OBJECT (window), "accept-focus");
2757 * gtk_window_get_accept_focus:
2758 * @window: a #GtkWindow
2760 * Gets the value set by gtk_window_set_accept_focus().
2762 * Return value: %TRUE if window should receive the input focus
2767 gtk_window_get_accept_focus (GtkWindow *window)
2769 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2771 return window->priv->accept_focus;
2775 * gtk_window_set_focus_on_map:
2776 * @window: a #GtkWindow
2777 * @setting: %TRUE to let this window receive input focus on map
2779 * Windows may set a hint asking the desktop environment not to receive
2780 * the input focus when the window is mapped. This function sets this
2786 gtk_window_set_focus_on_map (GtkWindow *window,
2789 GtkWindowPrivate *priv;
2791 g_return_if_fail (GTK_IS_WINDOW (window));
2793 priv = window->priv;
2795 setting = setting != FALSE;
2797 if (priv->focus_on_map != setting)
2799 priv->focus_on_map = setting;
2800 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2801 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2802 priv->focus_on_map);
2803 g_object_notify (G_OBJECT (window), "focus-on-map");
2808 * gtk_window_get_focus_on_map:
2809 * @window: a #GtkWindow
2811 * Gets the value set by gtk_window_set_focus_on_map().
2813 * Return value: %TRUE if window should receive the input focus when
2819 gtk_window_get_focus_on_map (GtkWindow *window)
2821 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2823 return window->priv->focus_on_map;
2827 * gtk_window_set_destroy_with_parent:
2828 * @window: a #GtkWindow
2829 * @setting: whether to destroy @window with its transient parent
2831 * If @setting is %TRUE, then destroying the transient parent of @window
2832 * will also destroy @window itself. This is useful for dialogs that
2833 * shouldn't persist beyond the lifetime of the main window they're
2834 * associated with, for example.
2837 gtk_window_set_destroy_with_parent (GtkWindow *window,
2840 GtkWindowPrivate *priv;
2842 g_return_if_fail (GTK_IS_WINDOW (window));
2844 priv = window->priv;
2846 if (priv->destroy_with_parent == (setting != FALSE))
2849 if (priv->destroy_with_parent)
2851 disconnect_parent_destroyed (window);
2855 connect_parent_destroyed (window);
2858 priv->destroy_with_parent = setting;
2860 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2864 * gtk_window_get_destroy_with_parent:
2865 * @window: a #GtkWindow
2867 * Returns whether the window will be destroyed with its transient parent. See
2868 * gtk_window_set_destroy_with_parent ().
2870 * Return value: %TRUE if the window will be destroyed with its transient parent.
2873 gtk_window_get_destroy_with_parent (GtkWindow *window)
2875 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2877 return window->priv->destroy_with_parent;
2880 static GtkWindowGeometryInfo*
2881 gtk_window_get_geometry_info (GtkWindow *window,
2884 GtkWindowPrivate *priv = window->priv;
2885 GtkWindowGeometryInfo *info;
2887 info = priv->geometry_info;
2888 if (!info && create)
2890 info = g_new0 (GtkWindowGeometryInfo, 1);
2892 info->default_width = -1;
2893 info->default_height = -1;
2894 info->resize_width = -1;
2895 info->resize_height = -1;
2896 info->initial_x = 0;
2897 info->initial_y = 0;
2898 info->initial_pos_set = FALSE;
2899 info->default_is_geometry = FALSE;
2900 info->position_constraints_changed = FALSE;
2901 info->last.configure_request.x = 0;
2902 info->last.configure_request.y = 0;
2903 info->last.configure_request.width = -1;
2904 info->last.configure_request.height = -1;
2905 info->widget = NULL;
2907 priv->geometry_info = info;
2914 * gtk_window_set_geometry_hints:
2915 * @window: a #GtkWindow
2916 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
2917 * @geometry: (allow-none): struct containing geometry information or %NULL
2918 * @geom_mask: mask indicating which struct fields should be paid attention to
2920 * This function sets up hints about how a window can be resized by
2921 * the user. You can set a minimum and maximum size; allowed resize
2922 * increments (e.g. for xterm, you can only resize by the size of a
2923 * character); aspect ratios; and more. See the #GdkGeometry struct.
2927 gtk_window_set_geometry_hints (GtkWindow *window,
2928 GtkWidget *geometry_widget,
2929 GdkGeometry *geometry,
2930 GdkWindowHints geom_mask)
2932 GtkWindowGeometryInfo *info;
2934 g_return_if_fail (GTK_IS_WINDOW (window));
2935 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2937 info = gtk_window_get_geometry_info (window, TRUE);
2940 g_signal_handlers_disconnect_by_func (info->widget,
2941 gtk_widget_destroyed,
2944 info->widget = geometry_widget;
2946 g_signal_connect (geometry_widget, "destroy",
2947 G_CALLBACK (gtk_widget_destroyed),
2951 info->geometry = *geometry;
2953 /* We store gravity in priv->gravity not in the hints. */
2954 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2956 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2958 gtk_window_set_gravity (window, geometry->win_gravity);
2961 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2965 * gtk_window_set_decorated:
2966 * @window: a #GtkWindow
2967 * @setting: %TRUE to decorate the window
2969 * By default, windows are decorated with a title bar, resize
2970 * controls, etc. Some <link linkend="gtk-X11-arch">window
2971 * managers</link> allow GTK+ to disable these decorations, creating a
2972 * borderless window. If you set the decorated property to %FALSE
2973 * using this function, GTK+ will do its best to convince the window
2974 * manager not to decorate the window. Depending on the system, this
2975 * function may not have any effect when called on a window that is
2976 * already visible, so you should call it before calling gtk_window_show().
2978 * On Windows, this function always works, since there's no window manager
2983 gtk_window_set_decorated (GtkWindow *window,
2986 GtkWindowPrivate *priv;
2987 GdkWindow *gdk_window;
2989 g_return_if_fail (GTK_IS_WINDOW (window));
2991 priv = window->priv;
2993 setting = setting != FALSE;
2995 if (setting == priv->decorated)
2998 priv->decorated = setting;
3000 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3003 if (priv->decorated)
3004 gdk_window_set_decorations (gdk_window,
3007 gdk_window_set_decorations (gdk_window,
3011 g_object_notify (G_OBJECT (window), "decorated");
3015 * gtk_window_get_decorated:
3016 * @window: a #GtkWindow
3018 * Returns whether the window has been set to have decorations
3019 * such as a title bar via gtk_window_set_decorated().
3021 * Return value: %TRUE if the window has been set to have decorations
3024 gtk_window_get_decorated (GtkWindow *window)
3026 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3028 return window->priv->decorated;
3032 * gtk_window_set_deletable:
3033 * @window: a #GtkWindow
3034 * @setting: %TRUE to decorate the window as deletable
3036 * By default, windows have a close button in the window frame. Some
3037 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3038 * disable this button. If you set the deletable property to %FALSE
3039 * using this function, GTK+ will do its best to convince the window
3040 * manager not to show a close button. Depending on the system, this
3041 * function may not have any effect when called on a window that is
3042 * already visible, so you should call it before calling gtk_window_show().
3044 * On Windows, this function always works, since there's no window manager
3050 gtk_window_set_deletable (GtkWindow *window,
3053 GtkWindowPrivate *priv;
3054 GdkWindow *gdk_window;
3056 g_return_if_fail (GTK_IS_WINDOW (window));
3058 priv = window->priv;
3060 setting = setting != FALSE;
3062 if (setting == priv->deletable)
3065 priv->deletable = setting;
3067 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3070 if (priv->deletable)
3071 gdk_window_set_functions (gdk_window,
3074 gdk_window_set_functions (gdk_window,
3075 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3078 g_object_notify (G_OBJECT (window), "deletable");
3082 * gtk_window_get_deletable:
3083 * @window: a #GtkWindow
3085 * Returns whether the window has been set to have a close button
3086 * via gtk_window_set_deletable().
3088 * Return value: %TRUE if the window has been set to have a close button
3093 gtk_window_get_deletable (GtkWindow *window)
3095 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3097 return window->priv->deletable;
3100 static GtkWindowIconInfo*
3101 get_icon_info (GtkWindow *window)
3103 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3107 free_icon_info (GtkWindowIconInfo *info)
3109 g_free (info->icon_name);
3110 g_slice_free (GtkWindowIconInfo, info);
3114 static GtkWindowIconInfo*
3115 ensure_icon_info (GtkWindow *window)
3117 GtkWindowIconInfo *info;
3119 info = get_icon_info (window);
3123 info = g_slice_new0 (GtkWindowIconInfo);
3124 g_object_set_qdata_full (G_OBJECT (window),
3125 quark_gtk_window_icon_info,
3127 (GDestroyNotify)free_icon_info);
3134 icon_list_from_theme (GtkWidget *widget,
3139 GtkIconTheme *icon_theme;
3144 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3146 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3149 for (i = 0; sizes[i]; i++)
3152 * We need an EWMH extension to handle scalable icons
3153 * by passing their name to the WM. For now just use a
3157 icon = gtk_icon_theme_load_icon (icon_theme, name,
3160 icon = gtk_icon_theme_load_icon (icon_theme, name,
3163 list = g_list_append (list, icon);
3173 gtk_window_realize_icon (GtkWindow *window)
3175 GtkWindowPrivate *priv = window->priv;
3177 GtkWindowIconInfo *info;
3178 GdkWindow *gdk_window;
3181 widget = GTK_WIDGET (window);
3182 gdk_window = gtk_widget_get_window (widget);
3184 g_return_if_fail (gdk_window != NULL);
3186 /* no point setting an icon on override-redirect */
3187 if (priv->type == GTK_WINDOW_POPUP)
3192 info = ensure_icon_info (window);
3197 info->using_default_icon = FALSE;
3198 info->using_parent_icon = FALSE;
3199 info->using_themed_icon = FALSE;
3201 icon_list = info->icon_list;
3203 /* Look up themed icon */
3204 if (icon_list == NULL && info->icon_name)
3206 icon_list = icon_list_from_theme (widget, info->icon_name);
3208 info->using_themed_icon = TRUE;
3211 /* Inherit from transient parent */
3212 if (icon_list == NULL && priv->transient_parent)
3214 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3216 info->using_parent_icon = TRUE;
3219 /* Inherit from default */
3220 if (icon_list == NULL)
3222 icon_list = default_icon_list;
3224 info->using_default_icon = TRUE;
3227 /* Look up themed icon */
3228 if (icon_list == NULL && default_icon_name)
3230 icon_list = icon_list_from_theme (widget, default_icon_name);
3231 info->using_default_icon = TRUE;
3232 info->using_themed_icon = TRUE;
3235 info->realized = TRUE;
3237 if (info->using_themed_icon)
3239 GtkIconTheme *icon_theme;
3241 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3242 g_list_free (icon_list);
3244 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3245 g_signal_connect (icon_theme, "changed",
3246 G_CALLBACK (update_themed_icon), window);
3251 gtk_window_unrealize_icon (GtkWindow *window)
3253 GtkWindowIconInfo *info;
3255 info = get_icon_info (window);
3260 if (info->using_themed_icon)
3262 GtkIconTheme *icon_theme;
3264 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3266 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3269 /* We don't clear the properties on the window, just figure the
3270 * window is going away.
3273 info->realized = FALSE;
3278 * gtk_window_set_icon_list:
3279 * @window: a #GtkWindow
3280 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3282 * Sets up the icon representing a #GtkWindow. The icon is used when
3283 * the window is minimized (also known as iconified). Some window
3284 * managers or desktop environments may also place it in the window
3285 * frame, or display it in other contexts.
3287 * gtk_window_set_icon_list() allows you to pass in the same icon in
3288 * several hand-drawn sizes. The list should contain the natural sizes
3289 * your icon is available in; that is, don't scale the image before
3290 * passing it to GTK+. Scaling is postponed until the last minute,
3291 * when the desired final size is known, to allow best quality.
3293 * By passing several sizes, you may improve the final image quality
3294 * of the icon, by reducing or eliminating automatic image scaling.
3296 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3297 * larger images (64x64, 128x128) if you have them.
3299 * See also gtk_window_set_default_icon_list() to set the icon
3300 * for all windows in your application in one go.
3302 * Note that transient windows (those who have been set transient for another
3303 * window using gtk_window_set_transient_for()) will inherit their
3304 * icon from their transient parent. So there's no need to explicitly
3305 * set the icon on transient windows.
3308 gtk_window_set_icon_list (GtkWindow *window,
3311 GtkWindowIconInfo *info;
3313 g_return_if_fail (GTK_IS_WINDOW (window));
3315 info = ensure_icon_info (window);
3317 if (info->icon_list == list) /* check for NULL mostly */
3320 g_list_foreach (list,
3321 (GFunc) g_object_ref, NULL);
3323 g_list_foreach (info->icon_list,
3324 (GFunc) g_object_unref, NULL);
3326 g_list_free (info->icon_list);
3328 info->icon_list = g_list_copy (list);
3330 g_object_notify (G_OBJECT (window), "icon");
3332 gtk_window_unrealize_icon (window);
3334 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3335 gtk_window_realize_icon (window);
3337 /* We could try to update our transient children, but I don't think
3338 * it's really worth it. If we did it, the best way would probably
3339 * be to have children connect to notify::icon-list
3344 * gtk_window_get_icon_list:
3345 * @window: a #GtkWindow
3347 * Retrieves the list of icons set by gtk_window_set_icon_list().
3348 * The list is copied, but the reference count on each
3349 * member won't be incremented.
3351 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3354 gtk_window_get_icon_list (GtkWindow *window)
3356 GtkWindowIconInfo *info;
3358 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3360 info = get_icon_info (window);
3363 return g_list_copy (info->icon_list);
3369 * gtk_window_set_icon:
3370 * @window: a #GtkWindow
3371 * @icon: (allow-none): icon image, or %NULL
3373 * Sets up the icon representing a #GtkWindow. This icon is used when
3374 * the window is minimized (also known as iconified). Some window
3375 * managers or desktop environments may also place it in the window
3376 * frame, or display it in other contexts.
3378 * The icon should be provided in whatever size it was naturally
3379 * drawn; that is, don't scale the image before passing it to
3380 * GTK+. Scaling is postponed until the last minute, when the desired
3381 * final size is known, to allow best quality.
3383 * If you have your icon hand-drawn in multiple sizes, use
3384 * gtk_window_set_icon_list(). Then the best size will be used.
3386 * This function is equivalent to calling gtk_window_set_icon_list()
3387 * with a 1-element list.
3389 * See also gtk_window_set_default_icon_list() to set the icon
3390 * for all windows in your application in one go.
3393 gtk_window_set_icon (GtkWindow *window,
3398 g_return_if_fail (GTK_IS_WINDOW (window));
3399 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3404 list = g_list_append (list, icon);
3406 gtk_window_set_icon_list (window, list);
3412 update_themed_icon (GtkIconTheme *icon_theme,
3415 g_object_notify (G_OBJECT (window), "icon");
3417 gtk_window_unrealize_icon (window);
3419 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3420 gtk_window_realize_icon (window);
3424 * gtk_window_set_icon_name:
3425 * @window: a #GtkWindow
3426 * @name: (allow-none): the name of the themed icon
3428 * Sets the icon for the window from a named themed icon. See
3429 * the docs for #GtkIconTheme for more details.
3431 * Note that this has nothing to do with the WM_ICON_NAME
3432 * property which is mentioned in the ICCCM.
3437 gtk_window_set_icon_name (GtkWindow *window,
3440 GtkWindowIconInfo *info;
3443 g_return_if_fail (GTK_IS_WINDOW (window));
3445 info = ensure_icon_info (window);
3447 if (g_strcmp0 (info->icon_name, name) == 0)
3450 tmp = info->icon_name;
3451 info->icon_name = g_strdup (name);
3454 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3455 g_list_free (info->icon_list);
3456 info->icon_list = NULL;
3458 update_themed_icon (NULL, window);
3460 g_object_notify (G_OBJECT (window), "icon-name");
3464 * gtk_window_get_icon_name:
3465 * @window: a #GtkWindow
3467 * Returns the name of the themed icon for the window,
3468 * see gtk_window_set_icon_name().
3470 * Returns: the icon name or %NULL if the window has
3476 gtk_window_get_icon_name (GtkWindow *window)
3478 GtkWindowIconInfo *info;
3480 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3482 info = ensure_icon_info (window);
3484 return info->icon_name;
3488 * gtk_window_get_icon:
3489 * @window: a #GtkWindow
3491 * Gets the value set by gtk_window_set_icon() (or if you've
3492 * called gtk_window_set_icon_list(), gets the first icon in
3495 * Return value: (transfer none): icon for window
3498 gtk_window_get_icon (GtkWindow *window)
3500 GtkWindowIconInfo *info;
3502 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3504 info = get_icon_info (window);
3505 if (info && info->icon_list)
3506 return GDK_PIXBUF (info->icon_list->data);
3511 /* Load pixbuf, printing warning on failure if error == NULL
3514 load_pixbuf_verbosely (const char *filename,
3517 GError *local_err = NULL;
3520 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3528 g_warning ("Error loading icon from file '%s':\n\t%s",
3529 filename, local_err->message);
3530 g_error_free (local_err);
3538 * gtk_window_set_icon_from_file:
3539 * @window: a #GtkWindow
3540 * @filename: location of icon file
3541 * @err: (allow-none): location to store error, or %NULL.
3543 * Sets the icon for @window.
3544 * Warns on failure if @err is %NULL.
3546 * This function is equivalent to calling gtk_window_set_icon()
3547 * with a pixbuf created by loading the image from @filename.
3549 * Returns: %TRUE if setting the icon succeeded.
3554 gtk_window_set_icon_from_file (GtkWindow *window,
3555 const gchar *filename,
3558 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3562 gtk_window_set_icon (window, pixbuf);
3563 g_object_unref (pixbuf);
3572 * gtk_window_set_default_icon_list:
3573 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3575 * Sets an icon list to be used as fallback for windows that haven't
3576 * had gtk_window_set_icon_list() called on them to set up a
3577 * window-specific icon list. This function allows you to set up the
3578 * icon for all windows in your app at once.
3580 * See gtk_window_set_icon_list() for more details.
3584 gtk_window_set_default_icon_list (GList *list)
3588 if (list == default_icon_list)
3591 /* Update serial so we don't used cached pixmaps/masks
3593 default_icon_serial++;
3595 g_list_foreach (list,
3596 (GFunc) g_object_ref, NULL);
3598 g_list_foreach (default_icon_list,
3599 (GFunc) g_object_unref, NULL);
3601 g_list_free (default_icon_list);
3603 default_icon_list = g_list_copy (list);
3605 /* Update all toplevels */
3606 toplevels = gtk_window_list_toplevels ();
3607 tmp_list = toplevels;
3608 while (tmp_list != NULL)
3610 GtkWindowIconInfo *info;
3611 GtkWindow *w = tmp_list->data;
3613 info = get_icon_info (w);
3614 if (info && info->using_default_icon)
3616 gtk_window_unrealize_icon (w);
3617 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3618 gtk_window_realize_icon (w);
3621 tmp_list = tmp_list->next;
3623 g_list_free (toplevels);
3627 * gtk_window_set_default_icon:
3630 * Sets an icon to be used as fallback for windows that haven't
3631 * had gtk_window_set_icon() called on them from a pixbuf.
3636 gtk_window_set_default_icon (GdkPixbuf *icon)
3640 g_return_if_fail (GDK_IS_PIXBUF (icon));
3642 list = g_list_prepend (NULL, icon);
3643 gtk_window_set_default_icon_list (list);
3648 * gtk_window_set_default_icon_name:
3649 * @name: the name of the themed icon
3651 * Sets an icon to be used as fallback for windows that haven't
3652 * had gtk_window_set_icon_list() called on them from a named
3653 * themed icon, see gtk_window_set_icon_name().
3658 gtk_window_set_default_icon_name (const gchar *name)
3663 /* Update serial so we don't used cached pixmaps/masks
3665 default_icon_serial++;
3667 g_free (default_icon_name);
3668 default_icon_name = g_strdup (name);
3670 g_list_foreach (default_icon_list,
3671 (GFunc) g_object_unref, NULL);
3673 g_list_free (default_icon_list);
3674 default_icon_list = NULL;
3676 /* Update all toplevels */
3677 toplevels = gtk_window_list_toplevels ();
3678 tmp_list = toplevels;
3679 while (tmp_list != NULL)
3681 GtkWindowIconInfo *info;
3682 GtkWindow *w = tmp_list->data;
3684 info = get_icon_info (w);
3685 if (info && info->using_default_icon && info->using_themed_icon)
3687 gtk_window_unrealize_icon (w);
3688 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3689 gtk_window_realize_icon (w);
3692 tmp_list = tmp_list->next;
3694 g_list_free (toplevels);
3698 * gtk_window_get_default_icon_name:
3700 * Returns the fallback icon name for windows that has been set
3701 * with gtk_window_set_default_icon_name(). The returned
3702 * string is owned by GTK+ and should not be modified. It
3703 * is only valid until the next call to
3704 * gtk_window_set_default_icon_name().
3706 * Returns: the fallback icon name for windows
3711 gtk_window_get_default_icon_name (void)
3713 return default_icon_name;
3717 * gtk_window_set_default_icon_from_file:
3718 * @filename: location of icon file
3719 * @err: (allow-none): location to store error, or %NULL.
3721 * Sets an icon to be used as fallback for windows that haven't
3722 * had gtk_window_set_icon_list() called on them from a file
3723 * on disk. Warns on failure if @err is %NULL.
3725 * Returns: %TRUE if setting the icon succeeded.
3730 gtk_window_set_default_icon_from_file (const gchar *filename,
3733 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3737 gtk_window_set_default_icon (pixbuf);
3738 g_object_unref (pixbuf);
3747 * gtk_window_get_default_icon_list:
3749 * Gets the value set by gtk_window_set_default_icon_list().
3750 * The list is a copy and should be freed with g_list_free(),
3751 * but the pixbufs in the list have not had their reference count
3754 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3757 gtk_window_get_default_icon_list (void)
3759 return g_list_copy (default_icon_list);
3763 gtk_window_set_default_size_internal (GtkWindow *window,
3764 gboolean change_width,
3766 gboolean change_height,
3768 gboolean is_geometry)
3770 GtkWindowGeometryInfo *info;
3772 g_return_if_fail (change_width == FALSE || width >= -1);
3773 g_return_if_fail (change_height == FALSE || height >= -1);
3775 info = gtk_window_get_geometry_info (window, TRUE);
3777 g_object_freeze_notify (G_OBJECT (window));
3779 info->default_is_geometry = is_geometry != FALSE;
3789 info->default_width = width;
3791 g_object_notify (G_OBJECT (window), "default-width");
3802 info->default_height = height;
3804 g_object_notify (G_OBJECT (window), "default-height");
3807 g_object_thaw_notify (G_OBJECT (window));
3809 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3813 * gtk_window_set_default_size:
3814 * @window: a #GtkWindow
3815 * @width: width in pixels, or -1 to unset the default width
3816 * @height: height in pixels, or -1 to unset the default height
3818 * Sets the default size of a window. If the window's "natural" size
3819 * (its size request) is larger than the default, the default will be
3820 * ignored. More generally, if the default size does not obey the
3821 * geometry hints for the window (gtk_window_set_geometry_hints() can
3822 * be used to set these explicitly), the default size will be clamped
3823 * to the nearest permitted size.
3825 * Unlike gtk_widget_set_size_request(), which sets a size request for
3826 * a widget and thus would keep users from shrinking the window, this
3827 * function only sets the initial size, just as if the user had
3828 * resized the window themselves. Users can still shrink the window
3829 * again as they normally would. Setting a default size of -1 means to
3830 * use the "natural" default size (the size request of the window).
3832 * For more control over a window's initial size and how resizing works,
3833 * investigate gtk_window_set_geometry_hints().
3835 * For some uses, gtk_window_resize() is a more appropriate function.
3836 * gtk_window_resize() changes the current size of the window, rather
3837 * than the size to be used on initial display. gtk_window_resize() always
3838 * affects the window itself, not the geometry widget.
3840 * The default size of a window only affects the first time a window is
3841 * shown; if a window is hidden and re-shown, it will remember the size
3842 * it had prior to hiding, rather than using the default size.
3844 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3845 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3848 gtk_window_set_default_size (GtkWindow *window,
3852 g_return_if_fail (GTK_IS_WINDOW (window));
3853 g_return_if_fail (width >= -1);
3854 g_return_if_fail (height >= -1);
3856 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3860 * gtk_window_get_default_size:
3861 * @window: a #GtkWindow
3862 * @width: (out) (allow-none): location to store the default width, or %NULL
3863 * @height: (out) (allow-none): location to store the default height, or %NULL
3865 * Gets the default size of the window. A value of -1 for the width or
3866 * height indicates that a default size has not been explicitly set
3867 * for that dimension, so the "natural" size of the window will be
3872 gtk_window_get_default_size (GtkWindow *window,
3876 GtkWindowGeometryInfo *info;
3878 g_return_if_fail (GTK_IS_WINDOW (window));
3880 info = gtk_window_get_geometry_info (window, FALSE);
3883 *width = info ? info->default_width : -1;
3886 *height = info ? info->default_height : -1;
3890 * gtk_window_resize:
3891 * @window: a #GtkWindow
3892 * @width: width in pixels to resize the window to
3893 * @height: height in pixels to resize the window to
3895 * Resizes the window as if the user had done so, obeying geometry
3896 * constraints. The default geometry constraint is that windows may
3897 * not be smaller than their size request; to override this
3898 * constraint, call gtk_widget_set_size_request() to set the window's
3899 * request to a smaller value.
3901 * If gtk_window_resize() is called before showing a window for the
3902 * first time, it overrides any default size set with
3903 * gtk_window_set_default_size().
3905 * Windows may not be resized smaller than 1 by 1 pixels.
3909 gtk_window_resize (GtkWindow *window,
3913 GtkWindowGeometryInfo *info;
3915 g_return_if_fail (GTK_IS_WINDOW (window));
3916 g_return_if_fail (width > 0);
3917 g_return_if_fail (height > 0);
3919 info = gtk_window_get_geometry_info (window, TRUE);
3921 info->resize_width = width;
3922 info->resize_height = height;
3924 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3928 * gtk_window_get_size:
3929 * @window: a #GtkWindow
3930 * @width: (out) (allow-none): return location for width, or %NULL
3931 * @height: (out) (allow-none): return location for height, or %NULL
3933 * Obtains the current size of @window. If @window is not onscreen,
3934 * it returns the size GTK+ will suggest to the <link
3935 * linkend="gtk-X11-arch">window manager</link> for the initial window
3936 * size (but this is not reliably the same as the size the window
3937 * manager will actually select). The size obtained by
3938 * gtk_window_get_size() is the last size received in a
3939 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3940 * rather than querying the X server for the size. As a result, if you
3941 * call gtk_window_resize() then immediately call
3942 * gtk_window_get_size(), the size won't have taken effect yet. After
3943 * the window manager processes the resize request, GTK+ receives
3944 * notification that the size has changed via a configure event, and
3945 * the size of the window gets updated.
3947 * Note 1: Nearly any use of this function creates a race condition,
3948 * because the size of the window may change between the time that you
3949 * get the size and the time that you perform some action assuming
3950 * that size is the current size. To avoid race conditions, connect to
3951 * "configure-event" on the window and adjust your size-dependent
3952 * state to match the size delivered in the #GdkEventConfigure.
3954 * Note 2: The returned size does <emphasis>not</emphasis> include the
3955 * size of the window manager decorations (aka the window frame or
3956 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3957 * method of determining their size.
3959 * Note 3: If you are getting a window size in order to position
3960 * the window onscreen, there may be a better way. The preferred
3961 * way is to simply set the window's semantic type with
3962 * gtk_window_set_type_hint(), which allows the window manager to
3963 * e.g. center dialogs. Also, if you set the transient parent of
3964 * dialogs with gtk_window_set_transient_for() window managers
3965 * will often center the dialog over its parent window. It's
3966 * much preferred to let the window manager handle these
3967 * things rather than doing it yourself, because all apps will
3968 * behave consistently and according to user prefs if the window
3969 * manager handles it. Also, the window manager can take the size
3970 * of the window decorations/border into account, while your
3971 * application cannot.
3973 * In any case, if you insist on application-specified window
3974 * positioning, there's <emphasis>still</emphasis> a better way than
3975 * doing it yourself - gtk_window_set_position() will frequently
3976 * handle the details for you.
3980 gtk_window_get_size (GtkWindow *window,
3986 g_return_if_fail (GTK_IS_WINDOW (window));
3988 if (width == NULL && height == NULL)
3991 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
3993 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
3994 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
3998 GdkRectangle configure_request;
4000 gtk_window_compute_configure_request (window,
4004 w = configure_request.width;
4005 h = configure_request.height;
4016 * @window: a #GtkWindow
4017 * @x: X coordinate to move window to
4018 * @y: Y coordinate to move window to
4020 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4021 * @window to the given position. Window managers are free to ignore
4022 * this; most window managers ignore requests for initial window
4023 * positions (instead using a user-defined placement algorithm) and
4024 * honor requests after the window has already been shown.
4026 * Note: the position is the position of the gravity-determined
4027 * reference point for the window. The gravity determines two things:
4028 * first, the location of the reference point in root window
4029 * coordinates; and second, which point on the window is positioned at
4030 * the reference point.
4032 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4033 * point is simply the @x, @y supplied to gtk_window_move(). The
4034 * top-left corner of the window decorations (aka window frame or
4035 * border) will be placed at @x, @y. Therefore, to position a window
4036 * at the top left of the screen, you want to use the default gravity
4037 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4039 * To position a window at the bottom right corner of the screen, you
4040 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4041 * point is at @x + the window width and @y + the window height, and
4042 * the bottom-right corner of the window border will be placed at that
4043 * reference point. So, to place a window in the bottom right corner
4044 * you would first set gravity to south east, then write:
4045 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4046 * gdk_screen_height () - window_height)</literal> (note that this
4047 * example does not take multi-head scenarios into account).
4049 * The Extended Window Manager Hints specification at <ulink
4050 * url="http://www.freedesktop.org/Standards/wm-spec">
4051 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4052 * nice table of gravities in the "implementation notes" section.
4054 * The gtk_window_get_position() documentation may also be relevant.
4057 gtk_window_move (GtkWindow *window,
4061 GtkWindowPrivate *priv;
4062 GtkWindowGeometryInfo *info;
4065 g_return_if_fail (GTK_IS_WINDOW (window));
4067 priv = window->priv;
4068 widget = GTK_WIDGET (window);
4070 info = gtk_window_get_geometry_info (window, TRUE);
4072 if (gtk_widget_get_mapped (widget))
4074 GtkAllocation allocation;
4076 gtk_widget_get_allocation (widget, &allocation);
4078 /* we have now sent a request with this position
4079 * with currently-active constraints, so toggle flag.
4081 info->position_constraints_changed = FALSE;
4083 /* we only constrain if mapped - if not mapped,
4084 * then gtk_window_compute_configure_request()
4085 * will apply the constraints later, and we
4086 * don't want to lose information about
4087 * what position the user set before then.
4088 * i.e. if you do a move() then turn off POS_CENTER
4089 * then show the window, your move() will work.
4091 gtk_window_constrain_position (window,
4092 allocation.width, allocation.height,
4095 /* Note that this request doesn't go through our standard request
4096 * framework, e.g. doesn't increment configure_request_count,
4097 * doesn't set info->last, etc.; that's because
4098 * we don't save the info needed to arrive at this same request
4101 * To gtk_window_move_resize(), this will end up looking exactly
4102 * the same as the position being changed by the window
4106 /* FIXME are we handling gravity properly for framed windows? */
4108 gdk_window_move (priv->frame,
4109 x - priv->frame_left,
4110 y - priv->frame_top);
4112 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)),
4117 /* Save this position to apply on mapping */
4118 info->initial_x = x;
4119 info->initial_y = y;
4120 info->initial_pos_set = TRUE;
4125 * gtk_window_get_position:
4126 * @window: a #GtkWindow
4127 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4128 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4130 * This function returns the position you need to pass to
4131 * gtk_window_move() to keep @window in its current position. This
4132 * means that the meaning of the returned value varies with window
4133 * gravity. See gtk_window_move() for more details.
4135 * If you haven't changed the window gravity, its gravity will be
4136 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4137 * gets the position of the top-left corner of the window manager
4138 * frame for the window. gtk_window_move() sets the position of this
4139 * same top-left corner.
4141 * gtk_window_get_position() is not 100% reliable because the X Window System
4142 * does not specify a way to obtain the geometry of the
4143 * decorations placed on a window by the window manager.
4144 * Thus GTK+ is using a "best guess" that works with most
4147 * Moreover, nearly all window managers are historically broken with
4148 * respect to their handling of window gravity. So moving a window to
4149 * its current position as returned by gtk_window_get_position() tends
4150 * to result in moving the window slightly. Window managers are
4151 * slowly getting better over time.
4153 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4154 * frame is not relevant, and thus gtk_window_get_position() will
4155 * always produce accurate results. However you can't use static
4156 * gravity to do things like place a window in a corner of the screen,
4157 * because static gravity ignores the window manager decorations.
4159 * If you are saving and restoring your application's window
4160 * positions, you should know that it's impossible for applications to
4161 * do this without getting it somewhat wrong because applications do
4162 * not have sufficient knowledge of window manager state. The Correct
4163 * Mechanism is to support the session management protocol (see the
4164 * "GnomeClient" object in the GNOME libraries for example) and allow
4165 * the window manager to save your window sizes and positions.
4170 gtk_window_get_position (GtkWindow *window,
4174 GtkWindowPrivate *priv;
4176 GdkWindow *gdk_window;
4178 g_return_if_fail (GTK_IS_WINDOW (window));
4180 priv = window->priv;
4181 widget = GTK_WIDGET (window);
4182 gdk_window = gtk_widget_get_window (widget);
4184 if (priv->gravity == GDK_GRAVITY_STATIC)
4186 if (gtk_widget_get_mapped (widget))
4188 /* This does a server round-trip, which is sort of wrong;
4189 * but a server round-trip is inevitable for
4190 * gdk_window_get_frame_extents() in the usual
4191 * NorthWestGravity case below, so not sure what else to
4192 * do. We should likely be consistent about whether we get
4193 * the client-side info or the server-side info.
4195 gdk_window_get_origin (gdk_window, root_x, root_y);
4199 GdkRectangle configure_request;
4201 gtk_window_compute_configure_request (window,
4205 *root_x = configure_request.x;
4206 *root_y = configure_request.y;
4211 GdkRectangle frame_extents;
4216 if (gtk_widget_get_mapped (widget))
4219 gdk_window_get_frame_extents (priv->frame, &frame_extents);
4221 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4222 x = frame_extents.x;
4223 y = frame_extents.y;
4224 gtk_window_get_size (window, &w, &h);
4228 /* We just say the frame has 0 size on all sides.
4229 * Not sure what else to do.
4231 gtk_window_compute_configure_request (window,
4234 x = frame_extents.x;
4235 y = frame_extents.y;
4236 w = frame_extents.width;
4237 h = frame_extents.height;
4240 switch (priv->gravity)
4242 case GDK_GRAVITY_NORTH:
4243 case GDK_GRAVITY_CENTER:
4244 case GDK_GRAVITY_SOUTH:
4245 /* Find center of frame. */
4246 x += frame_extents.width / 2;
4247 /* Center client window on that point. */
4251 case GDK_GRAVITY_SOUTH_EAST:
4252 case GDK_GRAVITY_EAST:
4253 case GDK_GRAVITY_NORTH_EAST:
4254 /* Find right edge of frame */
4255 x += frame_extents.width;
4256 /* Align left edge of client at that point. */
4263 switch (priv->gravity)
4265 case GDK_GRAVITY_WEST:
4266 case GDK_GRAVITY_CENTER:
4267 case GDK_GRAVITY_EAST:
4268 /* Find center of frame. */
4269 y += frame_extents.height / 2;
4270 /* Center client window there. */
4273 case GDK_GRAVITY_SOUTH_WEST:
4274 case GDK_GRAVITY_SOUTH:
4275 case GDK_GRAVITY_SOUTH_EAST:
4276 /* Find south edge of frame */
4277 y += frame_extents.height;
4278 /* Place bottom edge of client there */
4293 * gtk_window_reshow_with_initial_size:
4294 * @window: a #GtkWindow
4296 * Hides @window, then reshows it, resetting the
4297 * default size and position of the window. Used
4298 * by GUI builders only.
4301 gtk_window_reshow_with_initial_size (GtkWindow *window)
4305 g_return_if_fail (GTK_IS_WINDOW (window));
4307 widget = GTK_WIDGET (window);
4309 gtk_widget_hide (widget);
4310 gtk_widget_unrealize (widget);
4311 gtk_widget_show (widget);
4315 gtk_window_destroy (GtkObject *object)
4317 GtkWindow *window = GTK_WINDOW (object);
4318 GtkWindowPrivate *priv = window->priv;
4320 toplevel_list = g_slist_remove (toplevel_list, window);
4322 if (priv->transient_parent)
4323 gtk_window_set_transient_for (window, NULL);
4325 /* frees the icons */
4326 gtk_window_set_icon_list (window, NULL);
4328 if (priv->has_user_ref_count)
4330 priv->has_user_ref_count = FALSE;
4331 g_object_unref (window);
4335 gtk_window_group_remove_window (priv->group, window);
4337 gtk_window_free_key_hash (window);
4339 GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
4343 gtk_window_finalize (GObject *object)
4345 GtkWindow *window = GTK_WINDOW (object);
4346 GtkWindowPrivate *priv = window->priv;
4347 GtkMnemonicHash *mnemonic_hash;
4349 g_free (priv->title);
4350 g_free (priv->wmclass_name);
4351 g_free (priv->wmclass_class);
4352 g_free (priv->wm_role);
4354 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4356 _gtk_mnemonic_hash_free (mnemonic_hash);
4358 if (priv->geometry_info)
4360 if (priv->geometry_info->widget)
4361 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4362 gtk_widget_destroyed,
4363 &priv->geometry_info->widget);
4364 g_free (priv->geometry_info);
4367 if (priv->keys_changed_handler)
4369 g_source_remove (priv->keys_changed_handler);
4370 priv->keys_changed_handler = 0;
4374 g_signal_handlers_disconnect_by_func (gdk_visual_get_screen (priv->visual),
4375 gtk_window_on_composited_changed, window);
4377 g_free (priv->startup_id);
4379 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4383 gtk_window_show (GtkWidget *widget)
4385 GtkWindow *window = GTK_WINDOW (widget);
4386 GtkWindowPrivate *priv = window->priv;
4387 GtkContainer *container = GTK_CONTAINER (window);
4388 gboolean need_resize;
4390 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4392 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4393 _gtk_container_set_need_resize (container, FALSE);
4397 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4398 GtkAllocation allocation = { 0, 0 };
4399 GdkRectangle configure_request;
4400 GdkGeometry new_geometry;
4402 gboolean was_realized;
4404 /* We are going to go ahead and perform this configure request
4405 * and then emulate a configure notify by going ahead and
4406 * doing a size allocate. Sort of a synchronous
4407 * mini-copy of gtk_window_move_resize() here.
4409 gtk_window_compute_configure_request (window,
4414 /* We update this because we are going to go ahead
4415 * and gdk_window_resize() below, rather than
4418 info->last.configure_request.width = configure_request.width;
4419 info->last.configure_request.height = configure_request.height;
4421 /* and allocate the window - this is normally done
4422 * in move_resize in response to configure notify
4424 allocation.width = configure_request.width;
4425 allocation.height = configure_request.height;
4426 gtk_widget_size_allocate (widget, &allocation);
4428 /* Then we guarantee we have a realize */
4429 was_realized = FALSE;
4430 if (!gtk_widget_get_realized (widget))
4432 gtk_widget_realize (widget);
4433 was_realized = TRUE;
4436 /* Must be done after the windows are realized,
4437 * so that the decorations can be read
4439 gtk_decorated_window_calculate_frame_size (window);
4441 /* We only send configure request if we didn't just finish
4442 * creating the window; if we just created the window
4443 * then we created it with widget->allocation anyhow.
4446 gdk_window_move_resize (gtk_widget_get_window (widget),
4447 configure_request.x,
4448 configure_request.y,
4449 configure_request.width,
4450 configure_request.height);
4453 gtk_container_check_resize (container);
4455 gtk_widget_map (widget);
4457 /* Try to make sure that we have some focused widget
4459 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4460 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4463 gtk_grab_add (widget);
4467 gtk_window_hide (GtkWidget *widget)
4469 GtkWindow *window = GTK_WINDOW (widget);
4470 GtkWindowPrivate *priv = window->priv;
4472 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4473 gtk_widget_unmap (widget);
4476 gtk_grab_remove (widget);
4480 gtk_window_map (GtkWidget *widget)
4483 GtkWindow *window = GTK_WINDOW (widget);
4484 GtkWindowPrivate *priv = window->priv;
4485 GdkWindow *toplevel;
4486 GdkWindow *gdk_window;
4487 gboolean auto_mnemonics;
4489 gdk_window = gtk_widget_get_window (widget);
4491 gtk_widget_set_mapped (widget, TRUE);
4493 child = gtk_bin_get_child (&(window->bin));
4495 gtk_widget_get_visible (child) &&
4496 !gtk_widget_get_mapped (child))
4497 gtk_widget_map (child);
4500 toplevel = priv->frame;
4502 toplevel = gdk_window;
4504 if (priv->maximize_initially)
4505 gdk_window_maximize (toplevel);
4507 gdk_window_unmaximize (toplevel);
4509 if (priv->stick_initially)
4510 gdk_window_stick (toplevel);
4512 gdk_window_unstick (toplevel);
4514 if (priv->iconify_initially)
4515 gdk_window_iconify (toplevel);
4517 gdk_window_deiconify (toplevel);
4519 if (priv->fullscreen_initially)
4520 gdk_window_fullscreen (toplevel);
4522 gdk_window_unfullscreen (toplevel);
4524 gdk_window_set_keep_above (toplevel, priv->above_initially);
4526 gdk_window_set_keep_below (toplevel, priv->below_initially);
4528 /* No longer use the default settings */
4529 priv->need_default_size = FALSE;
4530 priv->need_default_position = FALSE;
4532 if (priv->reset_type_hint)
4534 /* We should only reset the type hint when the application
4535 * used gtk_window_set_type_hint() to change the hint.
4536 * Some applications use X directly to change the properties;
4537 * in that case, we shouldn't overwrite what they did.
4539 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4540 priv->reset_type_hint = FALSE;
4543 gdk_window_show (gdk_window);
4546 gdk_window_show (priv->frame);
4548 if (!disable_startup_notification)
4550 /* Do we have a custom startup-notification id? */
4551 if (priv->startup_id != NULL)
4553 /* Make sure we have a "real" id */
4554 if (!startup_id_is_fake (priv->startup_id))
4555 gdk_notify_startup_complete_with_id (priv->startup_id);
4557 g_free (priv->startup_id);
4558 priv->startup_id = NULL;
4560 else if (!sent_startup_notification)
4562 sent_startup_notification = TRUE;
4563 gdk_notify_startup_complete ();
4567 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4568 * (as in the case of popup menus), then hide mnemonics initially
4570 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4571 &auto_mnemonics, NULL);
4572 if (auto_mnemonics && !priv->mnemonics_visible_set)
4573 gtk_window_set_mnemonics_visible (window, FALSE);
4577 gtk_window_map_event (GtkWidget *widget,
4580 if (!gtk_widget_get_mapped (widget))
4582 /* we should be be unmapped, but are getting a MapEvent, this may happen
4583 * to toplevel XWindows if mapping was intercepted by a window manager
4584 * and an unmap request occoured while the MapRequestEvent was still
4585 * being handled. we work around this situaiton here by re-requesting
4586 * the window being unmapped. more details can be found in:
4587 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4589 gdk_window_hide (gtk_widget_get_window (widget));
4595 gtk_window_unmap (GtkWidget *widget)
4597 GtkWindow *window = GTK_WINDOW (widget);
4598 GtkWindowPrivate *priv = window->priv;
4599 GtkWindowGeometryInfo *info;
4600 GdkWindow *gdk_window;
4601 GdkWindowState state;
4603 gdk_window = gtk_widget_get_window (widget);
4605 gtk_widget_set_mapped (widget, FALSE);
4607 gdk_window_withdraw (priv->frame);
4609 gdk_window_withdraw (gdk_window);
4611 priv->configure_request_count = 0;
4612 priv->configure_notify_received = FALSE;
4614 /* on unmap, we reset the default positioning of the window,
4615 * so it's placed again, but we don't reset the default
4616 * size of the window, so it's remembered.
4618 priv->need_default_position = TRUE;
4620 info = gtk_window_get_geometry_info (window, FALSE);
4623 info->initial_pos_set = FALSE;
4624 info->position_constraints_changed = FALSE;
4627 state = gdk_window_get_state (gdk_window);
4628 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4629 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4630 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4631 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4632 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4636 gtk_window_realize (GtkWidget *widget)
4638 GtkAllocation allocation;
4641 GdkWindow *parent_window;
4642 GdkWindow *gdk_window;
4643 GdkWindowAttr attributes;
4644 gint attributes_mask;
4645 GtkWindowPrivate *priv;
4647 window = GTK_WINDOW (widget);
4648 priv = window->priv;
4650 gtk_widget_get_allocation (widget, &allocation);
4652 /* ensure widget tree is properly size allocated */
4653 if (allocation.x == -1 &&
4654 allocation.y == -1 &&
4655 allocation.width == 1 &&
4656 allocation.height == 1)
4658 GtkRequisition requisition;
4659 GtkAllocation allocation = { 0, 0, 200, 200 };
4661 gtk_size_request_get_size (GTK_SIZE_REQUEST (widget),
4662 &requisition, NULL);
4663 if (requisition.width || requisition.height)
4665 /* non-empty window */
4666 allocation.width = requisition.width;
4667 allocation.height = requisition.height;
4669 gtk_widget_size_allocate (widget, &allocation);
4671 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4673 g_return_if_fail (!gtk_widget_get_realized (widget));
4676 gtk_widget_set_realized (widget, TRUE);
4680 case GTK_WINDOW_TOPLEVEL:
4681 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4683 case GTK_WINDOW_POPUP:
4684 attributes.window_type = GDK_WINDOW_TEMP;
4687 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4691 attributes.title = priv->title;
4692 attributes.wmclass_name = priv->wmclass_name;
4693 attributes.wmclass_class = priv->wmclass_class;
4694 attributes.wclass = GDK_INPUT_OUTPUT;
4695 attributes.visual = gtk_widget_get_visual (widget);
4697 if (priv->has_frame)
4699 gtk_widget_get_allocation (widget, &allocation);
4700 attributes.width = allocation.width + priv->frame_left + priv->frame_right;
4701 attributes.height = allocation.height + priv->frame_top + priv->frame_bottom;
4702 attributes.event_mask = (GDK_EXPOSURE_MASK |
4703 GDK_KEY_PRESS_MASK |
4704 GDK_ENTER_NOTIFY_MASK |
4705 GDK_LEAVE_NOTIFY_MASK |
4706 GDK_FOCUS_CHANGE_MASK |
4707 GDK_STRUCTURE_MASK |
4708 GDK_BUTTON_MOTION_MASK |
4709 GDK_POINTER_MOTION_HINT_MASK |
4710 GDK_BUTTON_PRESS_MASK |
4711 GDK_BUTTON_RELEASE_MASK);
4713 attributes_mask = GDK_WA_VISUAL;
4715 priv->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4716 &attributes, attributes_mask);
4718 if (priv->opacity_set)
4719 gdk_window_set_opacity (priv->frame, priv->opacity);
4721 gdk_window_set_user_data (priv->frame, widget);
4723 attributes.window_type = GDK_WINDOW_CHILD;
4724 attributes.x = priv->frame_left;
4725 attributes.y = priv->frame_top;
4727 attributes_mask = GDK_WA_X | GDK_WA_Y;
4729 parent_window = priv->frame;
4731 g_signal_connect (window,
4733 G_CALLBACK (gtk_window_event),
4738 attributes_mask = 0;
4739 parent_window = gtk_widget_get_root_window (widget);
4742 gtk_widget_get_allocation (widget, &allocation);
4743 attributes.width = allocation.width;
4744 attributes.height = allocation.height;
4745 attributes.event_mask = gtk_widget_get_events (widget);
4746 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4747 GDK_KEY_PRESS_MASK |
4748 GDK_KEY_RELEASE_MASK |
4749 GDK_ENTER_NOTIFY_MASK |
4750 GDK_LEAVE_NOTIFY_MASK |
4751 GDK_FOCUS_CHANGE_MASK |
4752 GDK_STRUCTURE_MASK);
4753 attributes.type_hint = priv->type_hint;
4755 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4756 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4757 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4759 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4760 gtk_widget_set_window (widget, gdk_window);
4762 if (!priv->has_frame && priv->opacity_set)
4763 gdk_window_set_opacity (gdk_window, priv->opacity);
4765 gdk_window_enable_synchronized_configure (gdk_window);
4767 gdk_window_set_user_data (gdk_window, window);
4769 gtk_widget_style_attach (widget);
4770 style = gtk_widget_get_style (widget);
4771 gtk_style_set_background (style, gdk_window, GTK_STATE_NORMAL);
4773 gtk_style_set_background (style, priv->frame, GTK_STATE_NORMAL);
4775 if (priv->transient_parent &&
4776 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4777 gdk_window_set_transient_for (gdk_window,
4778 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4781 gdk_window_set_role (gdk_window, priv->wm_role);
4783 if (!priv->decorated)
4784 gdk_window_set_decorations (gdk_window, 0);
4786 if (!priv->deletable)
4787 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4789 if (gtk_window_get_skip_pager_hint (window))
4790 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4792 if (gtk_window_get_skip_taskbar_hint (window))
4793 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4795 if (gtk_window_get_accept_focus (window))
4796 gdk_window_set_accept_focus (gdk_window, TRUE);
4798 gdk_window_set_accept_focus (gdk_window, FALSE);
4800 if (gtk_window_get_focus_on_map (window))
4801 gdk_window_set_focus_on_map (gdk_window, TRUE);
4803 gdk_window_set_focus_on_map (gdk_window, FALSE);
4806 gdk_window_set_modal_hint (gdk_window, TRUE);
4808 gdk_window_set_modal_hint (gdk_window, FALSE);
4810 if (priv->startup_id)
4812 #ifdef GDK_WINDOWING_X11
4813 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4814 if (timestamp != GDK_CURRENT_TIME)
4815 gdk_x11_window_set_user_time (gdk_window, timestamp);
4817 if (!startup_id_is_fake (priv->startup_id))
4818 gdk_window_set_startup_id (gdk_window, priv->startup_id);
4822 gtk_window_realize_icon (window);
4826 gtk_window_unrealize (GtkWidget *widget)
4828 GtkWindow *window = GTK_WINDOW (widget);
4829 GtkWindowPrivate *priv = window->priv;
4830 GtkWindowGeometryInfo *info;
4832 /* On unrealize, we reset the size of the window such
4833 * that we will re-apply the default sizing stuff
4834 * next time we show the window.
4836 * Default positioning is reset on unmap, instead of unrealize.
4838 priv->need_default_size = TRUE;
4839 info = gtk_window_get_geometry_info (window, FALSE);
4842 info->resize_width = -1;
4843 info->resize_height = -1;
4844 info->last.configure_request.x = 0;
4845 info->last.configure_request.y = 0;
4846 info->last.configure_request.width = -1;
4847 info->last.configure_request.height = -1;
4848 /* be sure we reset geom hints on re-realize */
4849 info->last.flags = 0;
4854 gdk_window_set_user_data (priv->frame, NULL);
4855 gdk_window_destroy (priv->frame);
4860 gtk_window_unrealize_icon (window);
4862 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
4866 gtk_window_size_allocate (GtkWidget *widget,
4867 GtkAllocation *allocation)
4869 GtkWindow *window = GTK_WINDOW (widget);
4870 GtkWindowPrivate *priv = window->priv;
4871 GtkAllocation child_allocation;
4875 gtk_widget_set_allocation (widget, allocation);
4877 child = gtk_bin_get_child (&(window->bin));
4878 if (child && gtk_widget_get_visible (child))
4880 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
4881 child_allocation.x = border_width;
4882 child_allocation.y = border_width;
4883 child_allocation.width =
4884 MAX (1, (gint)allocation->width - child_allocation.x * 2);
4885 child_allocation.height =
4886 MAX (1, (gint)allocation->height - child_allocation.y * 2);
4888 gtk_widget_size_allocate (child, &child_allocation);
4891 if (gtk_widget_get_realized (widget) && priv->frame)
4893 gdk_window_resize (priv->frame,
4894 allocation->width + priv->frame_left + priv->frame_right,
4895 allocation->height + priv->frame_top + priv->frame_bottom);
4900 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4902 GtkWindow *window = GTK_WINDOW (widget);
4903 GtkWindowPrivate *priv = window->priv;
4904 gboolean return_val;
4906 if (priv->frame && (event->any.window == priv->frame))
4908 if ((event->type != GDK_KEY_PRESS) &&
4909 (event->type != GDK_KEY_RELEASE) &&
4910 (event->type != GDK_FOCUS_CHANGE))
4912 g_signal_stop_emission_by_name (widget, "event");
4914 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4919 g_object_unref (event->any.window);
4920 event->any.window = g_object_ref (gtk_widget_get_window (widget));
4928 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4930 GtkWindowPrivate *priv = window->priv;
4931 GdkEventConfigure *configure_event;
4934 switch (event->type)
4937 configure_event = (GdkEventConfigure *)event;
4939 /* Invalidate the decorations */
4942 rect.width = configure_event->width;
4943 rect.height = configure_event->height;
4945 gdk_window_invalidate_rect (priv->frame, &rect, FALSE);
4947 /* Pass on the (modified) configure event */
4948 configure_event->width -= priv->frame_left + priv->frame_right;
4949 configure_event->height -= priv->frame_top + priv->frame_bottom;
4950 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4959 gtk_window_configure_event (GtkWidget *widget,
4960 GdkEventConfigure *event)
4962 GtkAllocation allocation;
4963 GtkWindow *window = GTK_WINDOW (widget);
4964 GtkWindowPrivate *priv = window->priv;
4965 gboolean expected_reply = priv->configure_request_count > 0;
4967 /* priv->configure_request_count incremented for each
4968 * configure request, and decremented to a min of 0 for
4969 * each configure notify.
4971 * All it means is that we know we will get at least
4972 * priv->configure_request_count more configure notifies.
4973 * We could get more configure notifies than that; some
4974 * of the configure notifies we get may be unrelated to
4975 * the configure requests. But we will get at least
4976 * priv->configure_request_count notifies.
4979 if (priv->configure_request_count > 0)
4981 priv->configure_request_count -= 1;
4982 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
4985 /* As an optimization, we avoid a resize when possible.
4987 * The only times we can avoid a resize are:
4988 * - we know only the position changed, not the size
4989 * - we know we have made more requests and so will get more
4990 * notifies and can wait to resize when we get them
4992 gtk_widget_get_allocation (widget, &allocation);
4993 if (!expected_reply &&
4994 (allocation.width == event->width &&
4995 allocation.height == event->height))
4997 gdk_window_configure_finished (gtk_widget_get_window (widget));
5002 * If we do need to resize, we do that by:
5003 * - filling in widget->allocation with the new size
5004 * - setting configure_notify_received to TRUE
5005 * for use in gtk_window_move_resize()
5006 * - queueing a resize, leading to invocation of
5007 * gtk_window_move_resize() in an idle handler
5011 priv->configure_notify_received = TRUE;
5013 allocation.width = event->width;
5014 allocation.height = event->height;
5015 gtk_widget_set_allocation (widget, &allocation);
5017 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5022 /* the accel_key and accel_mods fields of the key have to be setup
5023 * upon calling this function. it'll then return whether that key
5024 * is at all used as accelerator, and if so will OR in the
5025 * accel_flags member of the key.
5028 _gtk_window_query_nonaccels (GtkWindow *window,
5030 GdkModifierType accel_mods)
5032 GtkWindowPrivate *priv;
5034 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5036 priv = window->priv;
5038 /* movement keys are considered locked accels */
5041 static const guint bindings[] = {
5042 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,
5043 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,
5047 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5048 if (bindings[i] == accel_key)
5052 /* mnemonics are considered locked accels */
5053 if (accel_mods == priv->mnemonic_modifier)
5055 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5056 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5064 * gtk_window_propagate_key_event:
5065 * @window: a #GtkWindow
5066 * @event: a #GdkEventKey
5068 * Propagate a key press or release event to the focus widget and
5069 * up the focus container chain until a widget handles @event.
5070 * This is normally called by the default ::key_press_event and
5071 * ::key_release_event handlers for toplevel windows,
5072 * however in some cases it may be useful to call this directly when
5073 * overriding the standard key handling for a toplevel window.
5075 * Return value: %TRUE if a widget in the focus chain handled the event.
5080 gtk_window_propagate_key_event (GtkWindow *window,
5083 GtkWindowPrivate *priv;
5084 gboolean handled = FALSE;
5085 GtkWidget *widget, *focus;
5087 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5089 priv = window->priv;
5090 widget = GTK_WIDGET (window);
5092 focus = priv->focus_widget;
5094 g_object_ref (focus);
5097 focus && focus != widget &&
5098 gtk_widget_get_toplevel (focus) == widget)
5102 if (gtk_widget_is_sensitive (focus))
5103 handled = gtk_widget_event (focus, (GdkEvent*) event);
5105 parent = gtk_widget_get_parent (focus);
5107 g_object_ref (parent);
5109 g_object_unref (focus);
5115 g_object_unref (focus);
5121 gtk_window_key_press_event (GtkWidget *widget,
5124 GtkWindow *window = GTK_WINDOW (widget);
5125 gboolean handled = FALSE;
5127 /* handle mnemonics and accelerators */
5129 handled = gtk_window_activate_key (window, event);
5131 /* handle focus widget key events */
5133 handled = gtk_window_propagate_key_event (window, event);
5135 /* Chain up, invokes binding set */
5137 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5143 gtk_window_key_release_event (GtkWidget *widget,
5146 GtkWindow *window = GTK_WINDOW (widget);
5147 gboolean handled = FALSE;
5149 /* handle focus widget key events */
5151 handled = gtk_window_propagate_key_event (window, event);
5153 /* Chain up, invokes binding set */
5155 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5161 gtk_window_real_activate_default (GtkWindow *window)
5163 gtk_window_activate_default (window);
5167 gtk_window_real_activate_focus (GtkWindow *window)
5169 gtk_window_activate_focus (window);
5173 gtk_window_move_focus (GtkWindow *window,
5174 GtkDirectionType dir)
5176 gtk_widget_child_focus (GTK_WIDGET (window), dir);
5178 if (!gtk_container_get_focus_child (GTK_CONTAINER (window)))
5179 gtk_window_set_focus (window, NULL);
5183 gtk_window_enter_notify_event (GtkWidget *widget,
5184 GdkEventCrossing *event)
5190 gtk_window_leave_notify_event (GtkWidget *widget,
5191 GdkEventCrossing *event)
5197 do_focus_change (GtkWidget *widget,
5201 GdkDeviceManager *device_manager;
5204 g_object_ref (widget);
5206 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5207 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5208 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5209 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5211 for (d = devices; d; d = d->next)
5213 GdkDevice *dev = d->data;
5216 if (dev->source != GDK_SOURCE_KEYBOARD)
5219 /* Skip non-master keyboards that haven't
5220 * selected for events from this window
5222 window = gtk_widget_get_window (widget);
5223 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5224 window && !gdk_window_get_device_events (window, dev))
5227 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5229 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5230 fevent->focus_change.window = window;
5232 g_object_ref (window);
5233 fevent->focus_change.in = in;
5234 gdk_event_set_device (fevent, dev);
5236 gtk_widget_send_focus_change (widget, fevent);
5238 gdk_event_free (fevent);
5241 g_list_free (devices);
5242 g_object_unref (widget);
5246 gtk_window_focus_in_event (GtkWidget *widget,
5247 GdkEventFocus *event)
5249 GtkWindow *window = GTK_WINDOW (widget);
5251 /* It appears spurious focus in events can occur when
5252 * the window is hidden. So we'll just check to see if
5253 * the window is visible before actually handling the
5256 if (gtk_widget_get_visible (widget))
5258 _gtk_window_set_has_toplevel_focus (window, TRUE);
5259 _gtk_window_set_is_active (window, TRUE);
5266 gtk_window_focus_out_event (GtkWidget *widget,
5267 GdkEventFocus *event)
5269 GtkWindow *window = GTK_WINDOW (widget);
5270 gboolean auto_mnemonics;
5272 _gtk_window_set_has_toplevel_focus (window, FALSE);
5273 _gtk_window_set_is_active (window, FALSE);
5275 /* set the mnemonic-visible property to false */
5276 g_object_get (gtk_widget_get_settings (widget),
5277 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5279 gtk_window_set_mnemonics_visible (window, FALSE);
5284 static GdkAtom atom_rcfiles = GDK_NONE;
5285 static GdkAtom atom_iconthemes = GDK_NONE;
5288 send_client_message_to_embedded_windows (GtkWidget *widget,
5289 GdkAtom message_type)
5291 GList *embedded_windows;
5293 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5294 if (embedded_windows)
5296 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5299 for (i = 0; i < 5; i++)
5300 send_event->client.data.l[i] = 0;
5301 send_event->client.data_format = 32;
5302 send_event->client.message_type = message_type;
5304 while (embedded_windows)
5306 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5307 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5308 embedded_windows = embedded_windows->next;
5311 gdk_event_free (send_event);
5316 gtk_window_client_event (GtkWidget *widget,
5317 GdkEventClient *event)
5321 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5322 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5325 if (event->message_type == atom_rcfiles)
5327 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5328 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5331 if (event->message_type == atom_iconthemes)
5333 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5334 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5341 gtk_window_check_resize (GtkContainer *container)
5343 if (gtk_widget_get_visible (GTK_WIDGET (container)))
5344 gtk_window_move_resize (GTK_WINDOW (container));
5348 gtk_window_focus (GtkWidget *widget,
5349 GtkDirectionType direction)
5351 GtkWindowPrivate *priv;
5354 GtkContainer *container;
5356 GtkWidget *old_focus_child;
5359 container = GTK_CONTAINER (widget);
5360 window = GTK_WINDOW (widget);
5361 priv = window->priv;
5362 bin = GTK_BIN (widget);
5364 old_focus_child = gtk_container_get_focus_child (container);
5366 /* We need a special implementation here to deal properly with wrapping
5367 * around in the tab chain without the danger of going into an
5370 if (old_focus_child)
5372 if (gtk_widget_child_focus (old_focus_child, direction))
5376 if (priv->focus_widget)
5378 if (direction == GTK_DIR_LEFT ||
5379 direction == GTK_DIR_RIGHT ||
5380 direction == GTK_DIR_UP ||
5381 direction == GTK_DIR_DOWN)
5386 /* Wrapped off the end, clear the focus setting for the toplpevel */
5387 parent = gtk_widget_get_parent (priv->focus_widget);
5390 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5391 parent = gtk_widget_get_parent (parent);
5394 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5397 /* Now try to focus the first widget in the window */
5398 child = gtk_bin_get_child (bin);
5401 if (gtk_widget_child_focus (child, direction))
5409 gtk_window_real_set_focus (GtkWindow *window,
5412 GtkWindowPrivate *priv = window->priv;
5413 GtkWidget *old_focus = priv->focus_widget;
5414 gboolean had_default = FALSE;
5415 gboolean focus_had_default = FALSE;
5416 gboolean old_focus_had_default = FALSE;
5420 g_object_ref (old_focus);
5421 g_object_freeze_notify (G_OBJECT (old_focus));
5422 old_focus_had_default = gtk_widget_has_default (old_focus);
5426 g_object_ref (focus);
5427 g_object_freeze_notify (G_OBJECT (focus));
5428 focus_had_default = gtk_widget_has_default (focus);
5431 if (priv->default_widget)
5432 had_default = gtk_widget_has_default (priv->default_widget);
5434 if (priv->focus_widget)
5436 if (gtk_widget_get_receives_default (priv->focus_widget) &&
5437 (priv->focus_widget != priv->default_widget))
5439 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
5440 gtk_widget_queue_draw (priv->focus_widget);
5442 if (priv->default_widget)
5443 _gtk_widget_set_has_default (priv->default_widget, TRUE);
5446 priv->focus_widget = NULL;
5448 if (priv->has_focus)
5449 do_focus_change (old_focus, FALSE);
5451 g_object_notify (G_OBJECT (old_focus), "is-focus");
5454 /* The above notifications may have set a new focus widget,
5455 * if so, we don't want to override it.
5457 if (focus && !priv->focus_widget)
5459 priv->focus_widget = focus;
5461 if (gtk_widget_get_receives_default (priv->focus_widget) &&
5462 (priv->focus_widget != priv->default_widget))
5464 if (gtk_widget_get_can_default (priv->focus_widget))
5465 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
5467 if (priv->default_widget)
5468 _gtk_widget_set_has_default (priv->default_widget, FALSE);
5471 if (priv->has_focus)
5472 do_focus_change (priv->focus_widget, TRUE);
5474 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
5477 /* If the default widget changed, a redraw will have been queued
5478 * on the old and new default widgets by gtk_window_set_default(), so
5479 * we only have to worry about the case where it didn't change.
5480 * We'll sometimes queue a draw twice on the new widget but that
5483 if (priv->default_widget &&
5484 (had_default != gtk_widget_has_default (priv->default_widget)))
5485 gtk_widget_queue_draw (priv->default_widget);
5489 if (old_focus_had_default != gtk_widget_has_default (old_focus))
5490 gtk_widget_queue_draw (old_focus);
5492 g_object_thaw_notify (G_OBJECT (old_focus));
5493 g_object_unref (old_focus);
5497 if (focus_had_default != gtk_widget_has_default (focus))
5498 gtk_widget_queue_draw (focus);
5500 g_object_thaw_notify (G_OBJECT (focus));
5501 g_object_unref (focus);
5507 gtk_window_size_request_init (GtkSizeRequestIface *iface)
5509 iface->get_width = gtk_window_get_width;
5510 iface->get_height = gtk_window_get_height;
5515 gtk_window_get_width (GtkSizeRequest *widget,
5523 window = GTK_WINDOW (widget);
5524 child = gtk_bin_get_child (GTK_BIN (window));
5526 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5527 *minimum_size = border_width * 2;
5528 *natural_size = border_width * 2;
5530 if (child && gtk_widget_get_visible (child))
5532 gint child_min, child_nat;
5533 gtk_size_request_get_width (GTK_SIZE_REQUEST (child), &child_min, &child_nat);
5535 *minimum_size += child_min;
5536 *natural_size += child_nat;
5541 gtk_window_get_height (GtkSizeRequest *widget,
5549 window = GTK_WINDOW (widget);
5550 child = gtk_bin_get_child (GTK_BIN (window));
5552 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5553 *minimum_size = border_width * 2;
5554 *natural_size = border_width * 2;
5556 if (child && gtk_widget_get_visible (child))
5558 gint child_min, child_nat;
5559 gtk_size_request_get_height (GTK_SIZE_REQUEST (child), &child_min, &child_nat);
5561 *minimum_size += child_min;
5562 *natural_size += child_nat;
5568 * _gtk_window_unset_focus_and_default:
5569 * @window: a #GtkWindow
5570 * @widget: a widget inside of @window
5572 * Checks whether the focus and default widgets of @window are
5573 * @widget or a descendent of @widget, and if so, unset them.
5576 _gtk_window_unset_focus_and_default (GtkWindow *window,
5580 GtkWindowPrivate *priv = window->priv;
5584 g_object_ref (window);
5585 g_object_ref (widget);
5587 parent = gtk_widget_get_parent (widget);
5588 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
5590 child = priv->focus_widget;
5592 while (child && child != widget)
5593 child = gtk_widget_get_parent (child);
5595 if (child == widget)
5596 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5599 child = priv->default_widget;
5601 while (child && child != widget)
5602 child = gtk_widget_get_parent (child);
5604 if (child == widget)
5605 gtk_window_set_default (window, NULL);
5607 g_object_unref (widget);
5608 g_object_unref (window);
5611 /*********************************
5612 * Functions related to resizing *
5613 *********************************/
5615 /* This function doesn't constrain to geometry hints */
5617 gtk_window_compute_configure_request_size (GtkWindow *window,
5621 GtkWindowPrivate *priv = window->priv;
5622 GtkRequisition requisition;
5623 GtkWindowGeometryInfo *info;
5627 * - we've done a size request
5630 widget = GTK_WIDGET (window);
5632 info = gtk_window_get_geometry_info (window, FALSE);
5634 if (priv->need_default_size)
5636 gtk_size_request_get_size (GTK_SIZE_REQUEST (widget),
5637 &requisition, NULL);
5639 /* Default to requisition */
5640 *width = requisition.width;
5641 *height = requisition.height;
5643 /* If window is empty so requests 0, default to random nonzero size */
5644 if (*width == 0 && *height == 0)
5650 /* Override requisition with default size */
5654 gint base_width = 0;
5655 gint base_height = 0;
5657 gint min_height = 0;
5659 gint height_inc = 1;
5661 if (info->default_is_geometry &&
5662 (info->default_width > 0 || info->default_height > 0))
5664 GdkGeometry geometry;
5667 gtk_window_compute_hints (window, &geometry, &flags);
5669 if (flags & GDK_HINT_BASE_SIZE)
5671 base_width = geometry.base_width;
5672 base_height = geometry.base_height;
5674 if (flags & GDK_HINT_MIN_SIZE)
5676 min_width = geometry.min_width;
5677 min_height = geometry.min_height;
5679 if (flags & GDK_HINT_RESIZE_INC)
5681 width_inc = geometry.width_inc;
5682 height_inc = geometry.height_inc;
5686 if (info->default_width > 0)
5687 *width = MAX (info->default_width * width_inc + base_width, min_width);
5689 if (info->default_height > 0)
5690 *height = MAX (info->default_height * height_inc + base_height, min_height);
5695 GtkAllocation allocation;
5697 gtk_widget_get_allocation (widget, &allocation);
5699 /* Default to keeping current size */
5700 *width = allocation.width;
5701 *height = allocation.height;
5704 /* Override any size with gtk_window_resize() values */
5707 if (info->resize_width > 0)
5708 *width = info->resize_width;
5710 if (info->resize_height > 0)
5711 *height = info->resize_height;
5714 /* Don't ever request zero width or height, its not supported by
5715 gdk. The size allocation code will round it to 1 anyway but if
5716 we do it then the value returned from this function will is
5717 not comparable to the size allocation read from the GtkWindow. */
5718 *width = MAX (*width, 1);
5719 *height = MAX (*height, 1);
5722 static GtkWindowPosition
5723 get_effective_position (GtkWindow *window)
5725 GtkWindowPrivate *priv = window->priv;
5726 GtkWindowPosition pos = priv->position;
5728 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5729 (priv->transient_parent == NULL ||
5730 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
5731 pos = GTK_WIN_POS_NONE;
5737 get_center_monitor_of_window (GtkWindow *window)
5739 /* We could try to sort out the relative positions of the monitors and
5740 * stuff, or we could just be losers and assume you have a row
5741 * or column of monitors.
5743 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5747 get_monitor_containing_pointer (GtkWindow *window)
5751 GdkScreen *window_screen;
5752 GdkScreen *pointer_screen;
5753 GdkDisplay *display;
5754 GdkDeviceManager *device_manager;
5757 window_screen = gtk_window_check_screen (window);
5758 display = gdk_screen_get_display (window_screen);
5759 device_manager = gdk_display_get_device_manager (display);
5760 pointer = gdk_device_manager_get_client_pointer (device_manager);
5762 gdk_display_get_device_state (display, pointer,
5766 if (pointer_screen == window_screen)
5767 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5775 center_window_on_monitor (GtkWindow *window,
5781 GdkRectangle monitor;
5784 monitor_num = get_monitor_containing_pointer (window);
5786 if (monitor_num == -1)
5787 monitor_num = get_center_monitor_of_window (window);
5789 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5790 monitor_num, &monitor);
5792 *x = (monitor.width - w) / 2 + monitor.x;
5793 *y = (monitor.height - h) / 2 + monitor.y;
5795 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5796 * and WM decorations.
5810 if (extent > clamp_extent)
5812 *base = clamp_base + clamp_extent/2 - extent/2;
5813 else if (*base < clamp_base)
5815 else if (*base + extent > clamp_base + clamp_extent)
5816 *base = clamp_base + clamp_extent - extent;
5820 clamp_window_to_rectangle (gint *x,
5824 const GdkRectangle *rect)
5826 #ifdef DEBUGGING_OUTPUT
5827 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);
5830 /* If it is too large, center it. If it fits on the monitor but is
5831 * partially outside, move it to the closest edge. Do this
5832 * separately in x and y directions.
5834 clamp (x, w, rect->x, rect->width);
5835 clamp (y, h, rect->y, rect->height);
5836 #ifdef DEBUGGING_OUTPUT
5837 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
5843 gtk_window_compute_configure_request (GtkWindow *window,
5844 GdkRectangle *request,
5845 GdkGeometry *geometry,
5848 GtkWindowPrivate *priv = window->priv;
5849 GdkGeometry new_geometry;
5853 GtkWindowPosition pos;
5854 GtkWidget *parent_widget;
5855 GtkWindowGeometryInfo *info;
5859 widget = GTK_WIDGET (window);
5861 screen = gtk_window_check_screen (window);
5863 gtk_size_request_get_size (GTK_SIZE_REQUEST (widget),
5865 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5867 gtk_window_compute_hints (window, &new_geometry, &new_flags);
5868 gtk_window_constrain_size (window,
5869 &new_geometry, new_flags,
5873 parent_widget = (GtkWidget*) priv->transient_parent;
5875 pos = get_effective_position (window);
5876 info = gtk_window_get_geometry_info (window, FALSE);
5878 /* by default, don't change position requested */
5881 x = info->last.configure_request.x;
5882 y = info->last.configure_request.y;
5891 if (priv->need_default_position)
5894 /* FIXME this all interrelates with window gravity.
5895 * For most of them I think we want to set GRAVITY_CENTER.
5897 * Not sure how to go about that.
5902 /* here we are only handling CENTER_ALWAYS
5903 * as it relates to default positioning,
5904 * where it's equivalent to simply CENTER
5906 case GTK_WIN_POS_CENTER_ALWAYS:
5907 case GTK_WIN_POS_CENTER:
5908 center_window_on_monitor (window, w, h, &x, &y);
5911 case GTK_WIN_POS_CENTER_ON_PARENT:
5913 GtkAllocation allocation;
5914 GdkWindow *gdk_window;
5916 GdkRectangle monitor;
5919 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
5921 gdk_window = gtk_widget_get_window (parent_widget);
5923 if (gdk_window != NULL)
5924 monitor_num = gdk_screen_get_monitor_at_window (screen,
5929 gdk_window_get_origin (gdk_window,
5932 gtk_widget_get_allocation (parent_widget, &allocation);
5933 x = ox + (allocation.width - w) / 2;
5934 y = oy + (allocation.height - h) / 2;
5936 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5937 * WM decorations. If parent wasn't on a monitor, just
5940 if (monitor_num >= 0)
5942 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5943 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5948 case GTK_WIN_POS_MOUSE:
5950 gint screen_width = gdk_screen_get_width (screen);
5951 gint screen_height = gdk_screen_get_height (screen);
5953 GdkRectangle monitor;
5954 GdkDisplay *display;
5955 GdkDeviceManager *device_manager;
5957 GdkScreen *pointer_screen;
5960 display = gdk_screen_get_display (screen);
5961 device_manager = gdk_display_get_device_manager (display);
5962 pointer = gdk_device_manager_get_client_pointer (device_manager);
5964 gdk_display_get_device_state (display, pointer,
5968 if (pointer_screen == screen)
5969 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5975 x = CLAMP (x, 0, screen_width - w);
5976 y = CLAMP (y, 0, screen_height - h);
5978 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5979 * WM decorations. Don't try to figure out what's going
5980 * on if the mouse wasn't inside a monitor.
5982 if (monitor_num >= 0)
5984 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5985 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5993 } /* if (priv->need_default_position) */
5995 if (priv->need_default_position && info &&
5996 info->initial_pos_set)
5998 x = info->initial_x;
5999 y = info->initial_y;
6000 gtk_window_constrain_position (window, w, h, &x, &y);
6006 request->height = h;
6009 *geometry = new_geometry;
6015 gtk_window_constrain_position (GtkWindow *window,
6021 GtkWindowPrivate *priv = window->priv;
6023 /* See long comments in gtk_window_move_resize()
6024 * on when it's safe to call this function.
6026 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6028 gint center_x, center_y;
6030 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6038 gtk_window_move_resize (GtkWindow *window)
6042 * First we determine whether any information has changed that would
6043 * cause us to revise our last configure request. If we would send
6044 * a different configure request from last time, then
6045 * configure_request_size_changed = TRUE or
6046 * configure_request_pos_changed = TRUE. configure_request_size_changed
6047 * may be true due to new hints, a gtk_window_resize(), or whatever.
6048 * configure_request_pos_changed may be true due to gtk_window_set_position()
6049 * or gtk_window_move().
6051 * If the configure request has changed, we send off a new one. To
6052 * ensure GTK+ invariants are maintained (resize queue does what it
6053 * should), we go ahead and size_allocate the requested size in this
6056 * If the configure request has not changed, we don't ever resend
6057 * it, because it could mean fighting the user or window manager.
6060 * To prepare the configure request, we come up with a base size/pos:
6061 * - the one from gtk_window_move()/gtk_window_resize()
6062 * - else default_width, default_height if we haven't ever
6064 * - else the size request if we haven't ever been mapped,
6065 * as a substitute default size
6066 * - else the current size of the window, as received from
6067 * configure notifies (i.e. the current allocation)
6069 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6070 * the position request to be centered.
6072 GtkWindowPrivate *priv = window->priv;
6073 GtkAllocation allocation;
6075 GtkContainer *container;
6076 GtkWindowGeometryInfo *info;
6077 GdkGeometry new_geometry;
6078 GdkWindow *gdk_window;
6080 GdkRectangle new_request;
6081 gboolean configure_request_size_changed;
6082 gboolean configure_request_pos_changed;
6083 gboolean hints_changed; /* do we need to send these again */
6084 GtkWindowLastGeometryInfo saved_last_info;
6086 widget = GTK_WIDGET (window);
6087 gdk_window = gtk_widget_get_window (widget);
6088 container = GTK_CONTAINER (widget);
6089 info = gtk_window_get_geometry_info (window, TRUE);
6091 configure_request_size_changed = FALSE;
6092 configure_request_pos_changed = FALSE;
6094 gtk_window_compute_configure_request (window, &new_request,
6095 &new_geometry, &new_flags);
6097 /* This check implies the invariant that we never set info->last
6098 * without setting the hints and sending off a configure request.
6100 * If we change info->last without sending the request, we may
6103 if (info->last.configure_request.x != new_request.x ||
6104 info->last.configure_request.y != new_request.y)
6105 configure_request_pos_changed = TRUE;
6107 if ((info->last.configure_request.width != new_request.width ||
6108 info->last.configure_request.height != new_request.height))
6109 configure_request_size_changed = TRUE;
6111 hints_changed = FALSE;
6113 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6114 &new_geometry, new_flags))
6116 hints_changed = TRUE;
6119 /* Position Constraints
6120 * ====================
6122 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6123 * a default. The other POS_ values are used only when the
6124 * window is shown, not after that.
6126 * However, we can't implement a position constraint as
6127 * "anytime the window size changes, center the window"
6128 * because this may well end up fighting the WM or user. In
6129 * fact it gets in an infinite loop with at least one WM.
6131 * Basically, applications are in no way in a position to
6132 * constrain the position of a window, with one exception:
6133 * override redirect windows. (Really the intended purpose
6134 * of CENTER_ALWAYS anyhow, I would think.)
6136 * So the way we implement this "constraint" is to say that when WE
6137 * cause a move or resize, i.e. we make a configure request changing
6138 * window size, we recompute the CENTER_ALWAYS position to reflect
6139 * the new window size, and include it in our request. Also, if we
6140 * just turned on CENTER_ALWAYS we snap to center with a new
6141 * request. Otherwise, if we are just NOTIFIED of a move or resize
6142 * done by someone else e.g. the window manager, we do NOT send a
6143 * new configure request.
6145 * For override redirect windows, this works fine; all window
6146 * sizes are from our configure requests. For managed windows,
6147 * it is at least semi-sane, though who knows what the
6148 * app author is thinking.
6151 /* This condition should be kept in sync with the condition later on
6152 * that determines whether we send a configure request. i.e. we
6153 * should do this position constraining anytime we were going to
6154 * send a configure request anyhow, plus when constraints have
6157 if (configure_request_pos_changed ||
6158 configure_request_size_changed ||
6160 info->position_constraints_changed)
6162 /* We request the constrained position if:
6163 * - we were changing position, and need to clamp
6164 * the change to the constraint
6165 * - we're changing the size anyway
6166 * - set_position() was called to toggle CENTER_ALWAYS on
6169 gtk_window_constrain_position (window,
6175 /* Update whether we need to request a move */
6176 if (info->last.configure_request.x != new_request.x ||
6177 info->last.configure_request.y != new_request.y)
6178 configure_request_pos_changed = TRUE;
6180 configure_request_pos_changed = FALSE;
6184 if (priv->type == GTK_WINDOW_TOPLEVEL)
6186 int notify_x, notify_y;
6188 /* this is the position from the last configure notify */
6189 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6191 g_message ("--- %s ---\n"
6192 "last : %d,%d\t%d x %d\n"
6193 "this : %d,%d\t%d x %d\n"
6194 "alloc : %d,%d\t%d x %d\n"
6196 "resize: \t%d x %d\n"
6197 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6198 "configure_notify_received: %d\n"
6199 "configure_request_count: %d\n"
6200 "position_constraints_changed: %d\n",
6201 priv->title ? priv->title : "(no title)",
6202 info->last.configure_request.x,
6203 info->last.configure_request.y,
6204 info->last.configure_request.width,
6205 info->last.configure_request.height,
6211 widget->allocation.width,
6212 widget->allocation.height,
6213 widget->requisition.width,
6214 widget->requisition.height,
6216 info->resize_height,
6217 configure_request_pos_changed,
6218 configure_request_size_changed,
6220 priv->configure_notify_received,
6221 priv->configure_request_count,
6222 info->position_constraints_changed);
6226 saved_last_info = info->last;
6227 info->last.geometry = new_geometry;
6228 info->last.flags = new_flags;
6229 info->last.configure_request = new_request;
6231 /* need to set PPosition so the WM will look at our position,
6232 * but we don't want to count PPosition coming and going as a hints
6233 * change for future iterations. So we saved info->last prior to
6237 /* Also, if the initial position was explicitly set, then we always
6238 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6242 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6243 * this is an initial map
6246 if ((configure_request_pos_changed ||
6247 info->initial_pos_set ||
6248 (priv->need_default_position &&
6249 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6250 (new_flags & GDK_HINT_POS) == 0)
6252 new_flags |= GDK_HINT_POS;
6253 hints_changed = TRUE;
6256 /* Set hints if necessary
6259 gdk_window_set_geometry_hints (gdk_window,
6263 gtk_widget_get_allocation (widget, &allocation);
6265 /* handle resizing/moving and widget tree allocation
6267 if (priv->configure_notify_received)
6269 /* If we have received a configure event since
6270 * the last time in this function, we need to
6271 * accept our new size and size_allocate child widgets.
6272 * (see gtk_window_configure_event() for more details).
6274 * 1 or more configure notifies may have been received.
6275 * Also, configure_notify_received will only be TRUE
6276 * if all expected configure notifies have been received
6277 * (one per configure request), as an optimization.
6280 priv->configure_notify_received = FALSE;
6282 /* gtk_window_configure_event() filled in widget->allocation */
6283 gtk_widget_size_allocate (widget, &allocation);
6285 gdk_window_process_updates (gdk_window, TRUE);
6287 gdk_window_configure_finished (gdk_window);
6289 /* If the configure request changed, it means that
6291 * 1) coincidentally changed hints or widget properties
6292 * impacting the configure request before getting
6293 * a configure notify, or
6294 * 2) some broken widget is changing its size request
6295 * during size allocation, resulting in
6296 * a false appearance of changed configure request.
6298 * For 1), we could just go ahead and ask for the
6299 * new size right now, but doing that for 2)
6300 * might well be fighting the user (and can even
6301 * trigger a loop). Since we really don't want to
6302 * do that, we requeue a resize in hopes that
6303 * by the time it gets handled, the child has seen
6304 * the light and is willing to go along with the
6305 * new size. (this happens for the zvt widget, since
6306 * the size_allocate() above will have stored the
6307 * requisition corresponding to the new size in the
6310 * This doesn't buy us anything for 1), but it shouldn't
6311 * hurt us too badly, since it is what would have
6312 * happened if we had gotten the configure event before
6313 * the new size had been set.
6316 if (configure_request_size_changed ||
6317 configure_request_pos_changed)
6319 /* Don't change the recorded last info after all, because we
6320 * haven't actually updated to the new info yet - we decided
6321 * to postpone our configure request until later.
6323 info->last = saved_last_info;
6325 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6328 return; /* Bail out, we didn't really process the move/resize */
6330 else if ((configure_request_size_changed || hints_changed) &&
6331 (allocation.width != new_request.width || allocation.height != new_request.height))
6334 /* We are in one of the following situations:
6335 * A. configure_request_size_changed
6336 * our requisition has changed and we need a different window size,
6337 * so we request it from the window manager.
6338 * B. !configure_request_size_changed && hints_changed
6339 * the window manager rejects our size, but we have just changed the
6340 * window manager hints, so there's a chance our request will
6341 * be honoured this time, so we try again.
6343 * However, if the new requisition is the same as the current allocation,
6344 * we don't request it again, since we won't get a ConfigureNotify back from
6345 * the window manager unless it decides to change our requisition. If
6346 * we don't get the ConfigureNotify back, the resize queue will never be run.
6349 /* Now send the configure request */
6350 if (configure_request_pos_changed)
6354 gdk_window_move_resize (priv->frame,
6355 new_request.x - priv->frame_left,
6356 new_request.y - priv->frame_top,
6357 new_request.width + priv->frame_left + priv->frame_right,
6358 new_request.height + priv->frame_top + priv->frame_bottom);
6359 gdk_window_resize (gdk_window,
6360 new_request.width, new_request.height);
6363 gdk_window_move_resize (gdk_window,
6364 new_request.x, new_request.y,
6365 new_request.width, new_request.height);
6367 else /* only size changed */
6370 gdk_window_resize (priv->frame,
6371 new_request.width + priv->frame_left + priv->frame_right,
6372 new_request.height + priv->frame_top + priv->frame_bottom);
6373 gdk_window_resize (gdk_window,
6374 new_request.width, new_request.height);
6377 if (priv->type == GTK_WINDOW_POPUP)
6379 GtkAllocation allocation;
6381 /* Directly size allocate for override redirect (popup) windows. */
6384 allocation.width = new_request.width;
6385 allocation.height = new_request.height;
6387 gtk_widget_size_allocate (widget, &allocation);
6389 gdk_window_process_updates (gdk_window, TRUE);
6391 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6392 gtk_widget_queue_draw (widget);
6396 /* Increment the number of have-not-yet-received-notify requests */
6397 priv->configure_request_count += 1;
6398 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
6400 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6401 * configure event in response to our resizing request.
6402 * the configure event will cause a new resize with
6403 * ->configure_notify_received=TRUE.
6404 * until then, we want to
6405 * - discard expose events
6406 * - coalesce resizes for our children
6407 * - defer any window resizes until the configure event arrived
6408 * to achieve this, we queue a resize for the window, but remove its
6409 * resizing handler, so resizing will not be handled from the next
6410 * idle handler but when the configure event arrives.
6412 * FIXME: we should also dequeue the pending redraws here, since
6413 * we handle those ourselves upon ->configure_notify_received==TRUE.
6415 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6417 gtk_widget_queue_resize_no_redraw (widget);
6418 _gtk_container_dequeue_resize_handler (container);
6424 /* Handle any position changes.
6426 if (configure_request_pos_changed)
6430 gdk_window_move (priv->frame,
6431 new_request.x - priv->frame_left,
6432 new_request.y - priv->frame_top);
6435 gdk_window_move (gdk_window,
6436 new_request.x, new_request.y);
6439 /* And run the resize queue.
6441 gtk_container_resize_children (container);
6444 /* We have now processed a move/resize since the last position
6445 * constraint change, setting of the initial position, or resize.
6446 * (Not resetting these flags here can lead to infinite loops for
6447 * GTK_RESIZE_IMMEDIATE containers)
6449 info->position_constraints_changed = FALSE;
6450 info->initial_pos_set = FALSE;
6451 info->resize_width = -1;
6452 info->resize_height = -1;
6455 /* Compare two sets of Geometry hints for equality.
6458 gtk_window_compare_hints (GdkGeometry *geometry_a,
6460 GdkGeometry *geometry_b,
6463 if (flags_a != flags_b)
6466 if ((flags_a & GDK_HINT_MIN_SIZE) &&
6467 (geometry_a->min_width != geometry_b->min_width ||
6468 geometry_a->min_height != geometry_b->min_height))
6471 if ((flags_a & GDK_HINT_MAX_SIZE) &&
6472 (geometry_a->max_width != geometry_b->max_width ||
6473 geometry_a->max_height != geometry_b->max_height))
6476 if ((flags_a & GDK_HINT_BASE_SIZE) &&
6477 (geometry_a->base_width != geometry_b->base_width ||
6478 geometry_a->base_height != geometry_b->base_height))
6481 if ((flags_a & GDK_HINT_ASPECT) &&
6482 (geometry_a->min_aspect != geometry_b->min_aspect ||
6483 geometry_a->max_aspect != geometry_b->max_aspect))
6486 if ((flags_a & GDK_HINT_RESIZE_INC) &&
6487 (geometry_a->width_inc != geometry_b->width_inc ||
6488 geometry_a->height_inc != geometry_b->height_inc))
6491 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
6492 geometry_a->win_gravity != geometry_b->win_gravity)
6499 _gtk_window_constrain_size (GtkWindow *window,
6505 GtkWindowPrivate *priv;
6506 GtkWindowGeometryInfo *info;
6508 g_return_if_fail (GTK_IS_WINDOW (window));
6510 priv = window->priv;
6512 info = priv->geometry_info;
6515 GdkWindowHints flags = info->last.flags;
6516 GdkGeometry *geometry = &info->last.geometry;
6518 gtk_window_constrain_size (window,
6529 gtk_window_constrain_size (GtkWindow *window,
6530 GdkGeometry *geometry,
6537 gdk_window_constrain_size (geometry, flags, width, height,
6538 new_width, new_height);
6541 /* Compute the set of geometry hints and flags for a window
6542 * based on the application set geometry, and requisition
6543 * of the window. gtk_size_request_get_size() must have been
6547 gtk_window_compute_hints (GtkWindow *window,
6548 GdkGeometry *new_geometry,
6551 GtkWindowPrivate *priv = window->priv;
6553 gint extra_width = 0;
6554 gint extra_height = 0;
6555 GtkWindowGeometryInfo *geometry_info;
6556 GtkRequisition requisition;
6558 widget = GTK_WIDGET (window);
6560 gtk_size_request_get_size (GTK_SIZE_REQUEST (widget), &requisition, NULL);
6561 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
6565 *new_flags = geometry_info->mask;
6566 *new_geometry = geometry_info->geometry;
6573 if (geometry_info && geometry_info->widget)
6575 GtkRequisition requisition;
6576 GtkRequisition child_requisition;
6578 /* FIXME: This really isn't right. It gets the min size wrong and forces
6579 * callers to do horrible hacks like set a huge usize on the child requisition
6580 * to get the base size right. We really want to find the answers to:
6582 * - If the geometry widget was infinitely big, how much extra space
6583 * would be needed for the stuff around it.
6585 * - If the geometry widget was infinitely small, how big would the
6586 * window still have to be.
6588 * Finding these answers would be a bit of a mess here. (Bug #68668)
6590 gtk_size_request_get_size (GTK_SIZE_REQUEST (geometry_info->widget),
6591 &child_requisition, NULL);
6593 gtk_size_request_get_size (GTK_SIZE_REQUEST (widget),
6594 &requisition, NULL);
6595 extra_width = requisition.width - child_requisition.width;
6596 extra_height = requisition.height - child_requisition.height;
6599 /* We don't want to set GDK_HINT_POS in here, we just set it
6600 * in gtk_window_move_resize() when we want the position
6604 if (*new_flags & GDK_HINT_BASE_SIZE)
6606 new_geometry->base_width += extra_width;
6607 new_geometry->base_height += extra_height;
6609 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
6610 (*new_flags & GDK_HINT_RESIZE_INC) &&
6611 ((extra_width != 0) || (extra_height != 0)))
6613 *new_flags |= GDK_HINT_BASE_SIZE;
6615 new_geometry->base_width = extra_width;
6616 new_geometry->base_height = extra_height;
6619 if (*new_flags & GDK_HINT_MIN_SIZE)
6621 if (new_geometry->min_width < 0)
6622 new_geometry->min_width = requisition.width;
6624 new_geometry->min_width += extra_width;
6626 if (new_geometry->min_height < 0)
6627 new_geometry->min_height = requisition.height;
6629 new_geometry->min_height += extra_height;
6633 *new_flags |= GDK_HINT_MIN_SIZE;
6635 new_geometry->min_width = requisition.width;
6636 new_geometry->min_height = requisition.height;
6639 if (*new_flags & GDK_HINT_MAX_SIZE)
6641 if (new_geometry->max_width < 0)
6642 new_geometry->max_width = requisition.width;
6644 new_geometry->max_width += extra_width;
6646 if (new_geometry->max_height < 0)
6647 new_geometry->max_height = requisition.height;
6649 new_geometry->max_height += extra_height;
6651 else if (!priv->resizable)
6653 *new_flags |= GDK_HINT_MAX_SIZE;
6655 new_geometry->max_width = requisition.width;
6656 new_geometry->max_height = requisition.height;
6659 *new_flags |= GDK_HINT_WIN_GRAVITY;
6660 new_geometry->win_gravity = priv->gravity;
6663 /***********************
6664 * Redrawing functions *
6665 ***********************/
6668 gtk_window_draw (GtkWidget *widget,
6671 if (!gtk_widget_get_app_paintable (widget))
6672 gtk_paint_flat_box (gtk_widget_get_style (widget),
6675 GTK_SHADOW_NONE, widget, "base",
6677 gtk_widget_get_allocated_width (widget),
6678 gtk_widget_get_allocated_height (widget));
6680 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
6681 return GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
6687 * gtk_window_set_has_frame:
6688 * @window: a #GtkWindow
6689 * @setting: a boolean
6691 * (Note: this is a special-purpose function for the framebuffer port,
6692 * that causes GTK+ to draw its own window border. For most applications,
6693 * you want gtk_window_set_decorated() instead, which tells the window
6694 * manager whether to draw the window border.)
6696 * If this function is called on a window with setting of %TRUE, before
6697 * it is realized or showed, it will have a "frame" window around
6698 * @window->window, accessible in @window->frame. Using the signal
6699 * frame_event you can receive all events targeted at the frame.
6701 * This function is used by the linux-fb port to implement managed
6702 * windows, but it could conceivably be used by X-programs that
6703 * want to do their own window decorations.
6707 gtk_window_set_has_frame (GtkWindow *window,
6710 GtkWindowPrivate *priv;
6712 g_return_if_fail (GTK_IS_WINDOW (window));
6713 g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
6715 priv = window->priv;
6717 priv->has_frame = setting != FALSE;
6721 * gtk_window_get_has_frame:
6722 * @window: a #GtkWindow
6724 * Accessor for whether the window has a frame window exterior to
6725 * @window->window. Gets the value set by gtk_window_set_has_frame ().
6727 * Return value: %TRUE if a frame has been added to the window
6728 * via gtk_window_set_has_frame().
6731 gtk_window_get_has_frame (GtkWindow *window)
6733 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6735 return window->priv->has_frame;
6739 * gtk_window_set_frame_dimensions:
6740 * @window: a #GtkWindow that has a frame
6741 * @left: The width of the left border
6742 * @top: The height of the top border
6743 * @right: The width of the right border
6744 * @bottom: The height of the bottom border
6746 * (Note: this is a special-purpose function intended for the framebuffer
6747 * port; see gtk_window_set_has_frame(). It will have no effect on the
6748 * window border drawn by the window manager, which is the normal
6749 * case when using the X Window system.)
6751 * For windows with frames (see gtk_window_set_has_frame()) this function
6752 * can be used to change the size of the frame border.
6755 gtk_window_set_frame_dimensions (GtkWindow *window,
6761 GtkWindowPrivate *priv;
6762 GtkAllocation allocation;
6765 g_return_if_fail (GTK_IS_WINDOW (window));
6767 priv = window->priv;
6768 widget = GTK_WIDGET (window);
6770 if (priv->frame_left == left &&
6771 priv->frame_top == top &&
6772 priv->frame_right == right &&
6773 priv->frame_bottom == bottom)
6776 priv->frame_left = left;
6777 priv->frame_top = top;
6778 priv->frame_right = right;
6779 priv->frame_bottom = bottom;
6781 if (gtk_widget_get_realized (widget) && priv->frame)
6783 gtk_widget_get_allocation (widget, &allocation);
6785 gint width = allocation.width + left + right;
6786 gint height = allocation.height + top + bottom;
6787 gdk_window_resize (priv->frame, width, height);
6788 gtk_decorated_window_move_resize_window (window,
6796 * gtk_window_present:
6797 * @window: a #GtkWindow
6799 * Presents a window to the user. This may mean raising the window
6800 * in the stacking order, deiconifying it, moving it to the current
6801 * desktop, and/or giving it the keyboard focus, possibly dependent
6802 * on the user's platform, window manager, and preferences.
6804 * If @window is hidden, this function calls gtk_widget_show()
6807 * This function should be used when the user tries to open a window
6808 * that's already open. Say for example the preferences dialog is
6809 * currently open, and the user chooses Preferences from the menu
6810 * a second time; use gtk_window_present() to move the already-open dialog
6811 * where the user can see it.
6813 * If you are calling this function in response to a user interaction,
6814 * it is preferable to use gtk_window_present_with_time().
6818 gtk_window_present (GtkWindow *window)
6820 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6824 * gtk_window_present_with_time:
6825 * @window: a #GtkWindow
6826 * @timestamp: the timestamp of the user interaction (typically a
6827 * button or key press event) which triggered this call
6829 * Presents a window to the user in response to a user interaction.
6830 * If you need to present a window without a timestamp, use
6831 * gtk_window_present(). See gtk_window_present() for details.
6836 gtk_window_present_with_time (GtkWindow *window,
6840 GdkWindow *gdk_window;
6842 g_return_if_fail (GTK_IS_WINDOW (window));
6844 widget = GTK_WIDGET (window);
6846 if (gtk_widget_get_visible (widget))
6848 gdk_window = gtk_widget_get_window (widget);
6850 g_assert (gdk_window != NULL);
6852 gdk_window_show (gdk_window);
6854 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6855 if (timestamp == GDK_CURRENT_TIME)
6857 #ifdef GDK_WINDOWING_X11
6858 GdkDisplay *display;
6860 display = gtk_widget_get_display (GTK_WIDGET (window));
6861 timestamp = gdk_x11_display_get_user_time (display);
6863 timestamp = gtk_get_current_event_time ();
6867 gdk_window_focus (gdk_window, timestamp);
6871 gtk_widget_show (widget);
6876 * gtk_window_iconify:
6877 * @window: a #GtkWindow
6879 * Asks to iconify (i.e. minimize) the specified @window. Note that
6880 * you shouldn't assume the window is definitely iconified afterward,
6881 * because other entities (e.g. the user or <link
6882 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6883 * again, or there may not be a window manager in which case
6884 * iconification isn't possible, etc. But normally the window will end
6885 * up iconified. Just don't write code that crashes if not.
6887 * It's permitted to call this function before showing a window,
6888 * in which case the window will be iconified before it ever appears
6891 * You can track iconification via the "window-state-event" signal
6896 gtk_window_iconify (GtkWindow *window)
6898 GtkWindowPrivate *priv;
6900 GdkWindow *toplevel;
6902 g_return_if_fail (GTK_IS_WINDOW (window));
6904 priv = window->priv;
6905 widget = GTK_WIDGET (window);
6907 priv->iconify_initially = TRUE;
6910 toplevel = priv->frame;
6912 toplevel = gtk_widget_get_window (widget);
6914 if (toplevel != NULL)
6915 gdk_window_iconify (toplevel);
6919 * gtk_window_deiconify:
6920 * @window: a #GtkWindow
6922 * Asks to deiconify (i.e. unminimize) the specified @window. Note
6923 * that you shouldn't assume the window is definitely deiconified
6924 * afterward, because other entities (e.g. the user or <link
6925 * linkend="gtk-X11-arch">window manager</link>) could iconify it
6926 * again before your code which assumes deiconification gets to run.
6928 * You can track iconification via the "window-state-event" signal
6932 gtk_window_deiconify (GtkWindow *window)
6934 GtkWindowPrivate *priv;
6936 GdkWindow *toplevel;
6938 g_return_if_fail (GTK_IS_WINDOW (window));
6940 priv = window->priv;
6941 widget = GTK_WIDGET (window);
6943 priv->iconify_initially = FALSE;
6946 toplevel = priv->frame;
6948 toplevel = gtk_widget_get_window (widget);
6950 if (toplevel != NULL)
6951 gdk_window_deiconify (toplevel);
6956 * @window: a #GtkWindow
6958 * Asks to stick @window, which means that it will appear on all user
6959 * desktops. Note that you shouldn't assume the window is definitely
6960 * stuck afterward, because other entities (e.g. the user or <link
6961 * linkend="gtk-X11-arch">window manager</link>) could unstick it
6962 * again, and some window managers do not support sticking
6963 * windows. But normally the window will end up stuck. Just don't
6964 * write code that crashes if not.
6966 * It's permitted to call this function before showing a window.
6968 * You can track stickiness via the "window-state-event" signal
6973 gtk_window_stick (GtkWindow *window)
6975 GtkWindowPrivate *priv;
6977 GdkWindow *toplevel;
6979 g_return_if_fail (GTK_IS_WINDOW (window));
6981 priv = window->priv;
6982 widget = GTK_WIDGET (window);
6984 priv->stick_initially = TRUE;
6987 toplevel = priv->frame;
6989 toplevel = gtk_widget_get_window (widget);
6991 if (toplevel != NULL)
6992 gdk_window_stick (toplevel);
6996 * gtk_window_unstick:
6997 * @window: a #GtkWindow
6999 * Asks to unstick @window, which means that it will appear on only
7000 * one of the user's desktops. Note that you shouldn't assume the
7001 * window is definitely unstuck afterward, because other entities
7002 * (e.g. the user or <link linkend="gtk-X11-arch">window
7003 * manager</link>) could stick it again. But normally the window will
7004 * end up stuck. Just don't write code that crashes if not.
7006 * You can track stickiness via the "window-state-event" signal
7011 gtk_window_unstick (GtkWindow *window)
7013 GtkWindowPrivate *priv;
7015 GdkWindow *toplevel;
7017 g_return_if_fail (GTK_IS_WINDOW (window));
7019 priv = window->priv;
7020 widget = GTK_WIDGET (window);
7022 priv->stick_initially = FALSE;
7025 toplevel = priv->frame;
7027 toplevel = gtk_widget_get_window (widget);
7029 if (toplevel != NULL)
7030 gdk_window_unstick (toplevel);
7034 * gtk_window_maximize:
7035 * @window: a #GtkWindow
7037 * Asks to maximize @window, so that it becomes full-screen. Note that
7038 * you shouldn't assume the window is definitely maximized afterward,
7039 * because other entities (e.g. the user or <link
7040 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7041 * again, and not all window managers support maximization. But
7042 * normally the window will end up maximized. Just don't write code
7043 * that crashes if not.
7045 * It's permitted to call this function before showing a window,
7046 * in which case the window will be maximized when it appears onscreen
7049 * You can track maximization via the "window-state-event" signal
7054 gtk_window_maximize (GtkWindow *window)
7056 GtkWindowPrivate *priv;
7058 GdkWindow *toplevel;
7060 g_return_if_fail (GTK_IS_WINDOW (window));
7062 priv = window->priv;
7063 widget = GTK_WIDGET (window);
7065 priv->maximize_initially = TRUE;
7068 toplevel = priv->frame;
7070 toplevel = gtk_widget_get_window (widget);
7072 if (toplevel != NULL)
7073 gdk_window_maximize (toplevel);
7077 * gtk_window_unmaximize:
7078 * @window: a #GtkWindow
7080 * Asks to unmaximize @window. Note that you shouldn't assume the
7081 * window is definitely unmaximized afterward, because other entities
7082 * (e.g. the user or <link linkend="gtk-X11-arch">window
7083 * manager</link>) could maximize it again, and not all window
7084 * managers honor requests to unmaximize. But normally the window will
7085 * end up unmaximized. Just don't write code that crashes if not.
7087 * You can track maximization via the "window-state-event" signal
7092 gtk_window_unmaximize (GtkWindow *window)
7094 GtkWindowPrivate *priv;
7096 GdkWindow *toplevel;
7098 g_return_if_fail (GTK_IS_WINDOW (window));
7100 priv = window->priv;
7101 widget = GTK_WIDGET (window);
7103 priv->maximize_initially = FALSE;
7106 toplevel = priv->frame;
7108 toplevel = gtk_widget_get_window (widget);
7110 if (toplevel != NULL)
7111 gdk_window_unmaximize (toplevel);
7115 * gtk_window_fullscreen:
7116 * @window: a #GtkWindow
7118 * Asks to place @window in the fullscreen state. Note that you
7119 * shouldn't assume the window is definitely full screen afterward,
7120 * because other entities (e.g. the user or <link
7121 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7122 * again, and not all window managers honor requests to fullscreen
7123 * windows. But normally the window will end up fullscreen. Just
7124 * don't write code that crashes if not.
7126 * You can track the fullscreen state via the "window-state-event" signal
7132 gtk_window_fullscreen (GtkWindow *window)
7134 GtkWindowPrivate *priv;
7136 GdkWindow *toplevel;
7138 g_return_if_fail (GTK_IS_WINDOW (window));
7140 priv = window->priv;
7141 widget = GTK_WIDGET (window);
7143 priv->fullscreen_initially = TRUE;
7146 toplevel = priv->frame;
7148 toplevel = gtk_widget_get_window (widget);
7150 if (toplevel != NULL)
7151 gdk_window_fullscreen (toplevel);
7155 * gtk_window_unfullscreen:
7156 * @window: a #GtkWindow
7158 * Asks to toggle off the fullscreen state for @window. Note that you
7159 * shouldn't assume the window is definitely not full screen
7160 * afterward, because other entities (e.g. the user or <link
7161 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7162 * again, and not all window managers honor requests to unfullscreen
7163 * windows. But normally the window will end up restored to its normal
7164 * state. Just don't write code that crashes if not.
7166 * You can track the fullscreen state via the "window-state-event" signal
7172 gtk_window_unfullscreen (GtkWindow *window)
7175 GdkWindow *toplevel;
7176 GtkWindowPrivate *priv;
7178 g_return_if_fail (GTK_IS_WINDOW (window));
7180 priv = window->priv;
7181 widget = GTK_WIDGET (window);
7183 priv->fullscreen_initially = FALSE;
7186 toplevel = priv->frame;
7188 toplevel = gtk_widget_get_window (widget);
7190 if (toplevel != NULL)
7191 gdk_window_unfullscreen (toplevel);
7195 * gtk_window_set_keep_above:
7196 * @window: a #GtkWindow
7197 * @setting: whether to keep @window above other windows
7199 * Asks to keep @window above, so that it stays on top. Note that
7200 * you shouldn't assume the window is definitely above afterward,
7201 * because other entities (e.g. the user or <link
7202 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7203 * and not all window managers support keeping windows above. But
7204 * normally the window will end kept above. Just don't write code
7205 * that crashes if not.
7207 * It's permitted to call this function before showing a window,
7208 * in which case the window will be kept above when it appears onscreen
7211 * You can track the above state via the "window-state-event" signal
7214 * Note that, according to the <ulink
7215 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7216 * Manager Hints</ulink> specification, the above state is mainly meant
7217 * for user preferences and should not be used by applications e.g. for
7218 * drawing attention to their dialogs.
7223 gtk_window_set_keep_above (GtkWindow *window,
7227 GtkWindowPrivate *priv;
7228 GdkWindow *toplevel;
7230 g_return_if_fail (GTK_IS_WINDOW (window));
7232 priv = window->priv;
7233 widget = GTK_WIDGET (window);
7235 priv->above_initially = setting != FALSE;
7237 priv->below_initially = FALSE;
7240 toplevel = priv->frame;
7242 toplevel = gtk_widget_get_window (widget);
7244 if (toplevel != NULL)
7245 gdk_window_set_keep_above (toplevel, setting);
7249 * gtk_window_set_keep_below:
7250 * @window: a #GtkWindow
7251 * @setting: whether to keep @window below other windows
7253 * Asks to keep @window below, so that it stays in bottom. Note that
7254 * you shouldn't assume the window is definitely below afterward,
7255 * because other entities (e.g. the user or <link
7256 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7257 * and not all window managers support putting windows below. But
7258 * normally the window will be kept below. Just don't write code
7259 * that crashes if not.
7261 * It's permitted to call this function before showing a window,
7262 * in which case the window will be kept below when it appears onscreen
7265 * You can track the below state via the "window-state-event" signal
7268 * Note that, according to the <ulink
7269 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7270 * Manager Hints</ulink> specification, the above state is mainly meant
7271 * for user preferences and should not be used by applications e.g. for
7272 * drawing attention to their dialogs.
7277 gtk_window_set_keep_below (GtkWindow *window,
7281 GtkWindowPrivate *priv;
7282 GdkWindow *toplevel;
7284 g_return_if_fail (GTK_IS_WINDOW (window));
7286 priv = window->priv;
7287 widget = GTK_WIDGET (window);
7289 priv->below_initially = setting != FALSE;
7291 priv->above_initially = FALSE;
7294 toplevel = priv->frame;
7296 toplevel = gtk_widget_get_window (widget);
7298 if (toplevel != NULL)
7299 gdk_window_set_keep_below (toplevel, setting);
7303 * gtk_window_set_resizable:
7304 * @window: a #GtkWindow
7305 * @resizable: %TRUE if the user can resize this window
7307 * Sets whether the user can resize a window. Windows are user resizable
7311 gtk_window_set_resizable (GtkWindow *window,
7314 GtkWindowPrivate *priv;
7316 g_return_if_fail (GTK_IS_WINDOW (window));
7318 priv = window->priv;
7320 priv->resizable = (resizable != FALSE);
7322 g_object_notify (G_OBJECT (window), "resizable");
7324 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7328 * gtk_window_get_resizable:
7329 * @window: a #GtkWindow
7331 * Gets the value set by gtk_window_set_resizable().
7333 * Return value: %TRUE if the user can resize the window
7336 gtk_window_get_resizable (GtkWindow *window)
7338 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7340 return window->priv->resizable;
7344 * gtk_window_set_gravity:
7345 * @window: a #GtkWindow
7346 * @gravity: window gravity
7348 * Window gravity defines the meaning of coordinates passed to
7349 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7352 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7353 * typically "do what you mean."
7357 gtk_window_set_gravity (GtkWindow *window,
7360 GtkWindowPrivate *priv;
7362 g_return_if_fail (GTK_IS_WINDOW (window));
7364 priv = window->priv;
7366 if (gravity != priv->gravity)
7368 priv->gravity = gravity;
7370 /* gtk_window_move_resize() will adapt gravity
7372 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7374 g_object_notify (G_OBJECT (window), "gravity");
7379 * gtk_window_get_gravity:
7380 * @window: a #GtkWindow
7382 * Gets the value set by gtk_window_set_gravity().
7384 * Return value: (transfer none): window gravity
7387 gtk_window_get_gravity (GtkWindow *window)
7389 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7391 return window->priv->gravity;
7395 * gtk_window_begin_resize_drag:
7396 * @window: a #GtkWindow
7397 * @button: mouse button that initiated the drag
7398 * @edge: position of the resize control
7399 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7400 * @root_y: Y position where the user clicked to initiate the drag
7401 * @timestamp: timestamp from the click event that initiated the drag
7403 * Starts resizing a window. This function is used if an application
7404 * has window resizing controls. When GDK can support it, the resize
7405 * will be done using the standard mechanism for the <link
7406 * linkend="gtk-X11-arch">window manager</link> or windowing
7407 * system. Otherwise, GDK will try to emulate window resizing,
7408 * potentially not all that well, depending on the windowing system.
7412 gtk_window_begin_resize_drag (GtkWindow *window,
7419 GtkWindowPrivate *priv;
7421 GdkWindow *toplevel;
7423 g_return_if_fail (GTK_IS_WINDOW (window));
7424 widget = GTK_WIDGET (window);
7425 g_return_if_fail (gtk_widget_get_visible (widget));
7427 priv = window->priv;
7430 toplevel = priv->frame;
7432 toplevel = gtk_widget_get_window (widget);
7434 gdk_window_begin_resize_drag (toplevel,
7441 * gtk_window_get_frame_dimensions:
7442 * @window: a #GtkWindow
7443 * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
7444 * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
7445 * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
7446 * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
7448 * (Note: this is a special-purpose function intended for the
7449 * framebuffer port; see gtk_window_set_has_frame(). It will not
7450 * return the size of the window border drawn by the <link
7451 * linkend="gtk-X11-arch">window manager</link>, which is the normal
7452 * case when using a windowing system. See
7453 * gdk_window_get_frame_extents() to get the standard window border
7456 * Retrieves the dimensions of the frame window for this toplevel.
7457 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
7460 gtk_window_get_frame_dimensions (GtkWindow *window,
7466 GtkWindowPrivate *priv;
7468 g_return_if_fail (GTK_IS_WINDOW (window));
7470 priv = window->priv;
7473 *left = priv->frame_left;
7475 *top = priv->frame_top;
7477 *right = priv->frame_right;
7479 *bottom = priv->frame_bottom;
7483 * gtk_window_begin_move_drag:
7484 * @window: a #GtkWindow
7485 * @button: mouse button that initiated the drag
7486 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7487 * @root_y: Y position where the user clicked to initiate the drag
7488 * @timestamp: timestamp from the click event that initiated the drag
7490 * Starts moving a window. This function is used if an application has
7491 * window movement grips. When GDK can support it, the window movement
7492 * will be done using the standard mechanism for the <link
7493 * linkend="gtk-X11-arch">window manager</link> or windowing
7494 * system. Otherwise, GDK will try to emulate window movement,
7495 * potentially not all that well, depending on the windowing system.
7499 gtk_window_begin_move_drag (GtkWindow *window,
7505 GtkWindowPrivate *priv;
7507 GdkWindow *toplevel;
7509 g_return_if_fail (GTK_IS_WINDOW (window));
7510 widget = GTK_WIDGET (window);
7511 g_return_if_fail (gtk_widget_get_visible (widget));
7513 priv = window->priv;
7516 toplevel = priv->frame;
7518 toplevel = gtk_widget_get_window (widget);
7520 gdk_window_begin_move_drag (toplevel,
7527 _gtk_window_get_visual (GtkWindow *window)
7529 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
7531 return window->priv->visual;
7535 * gtk_window_set_visual:
7536 * @window: window to set the visual from
7537 * @visual: the new visual to use
7539 * Sets the #GdkVisual used to display @window; if the window
7540 * is already mapped, it will be unmapped, and then remapped
7541 * with the new visual. It is fine if @visual is on a
7542 * different #GdkScreen.
7544 * By default, a window's visual is set to the system visual
7545 * of the default screen.
7548 gtk_window_set_visual (GtkWindow *window,
7551 GtkWindowPrivate *priv;
7553 GdkVisual *previous_visual;
7554 GdkScreen *previous_screen, *screen;
7555 gboolean was_mapped;
7557 g_return_if_fail (GTK_IS_WINDOW (window));
7558 g_return_if_fail (GDK_IS_VISUAL (visual));
7560 priv = window->priv;
7562 if (priv->visual == visual)
7565 widget = GTK_WIDGET (window);
7567 previous_visual = priv->visual;
7568 previous_screen = gdk_visual_get_screen (previous_visual);
7569 screen = gdk_visual_get_screen (visual);
7570 was_mapped = gtk_widget_get_mapped (widget);
7573 gtk_widget_unmap (widget);
7574 if (gtk_widget_get_realized (widget))
7575 gtk_widget_unrealize (widget);
7576 g_object_freeze_notify (G_OBJECT (window));
7578 gtk_window_free_key_hash (window);
7579 priv->visual = visual;
7580 gtk_widget_reset_rc_styles (widget);
7581 if (previous_screen != screen)
7583 g_signal_handlers_disconnect_by_func (previous_screen,
7584 gtk_window_on_composited_changed, window);
7585 g_signal_connect (screen, "composited-changed",
7586 G_CALLBACK (gtk_window_on_composited_changed), window);
7588 _gtk_widget_propagate_screen_changed (widget, previous_screen);
7589 _gtk_widget_propagate_composited_changed (widget);
7590 g_object_notify (G_OBJECT (window), "screen");
7592 g_object_notify (G_OBJECT (window), "visual");
7594 g_object_thaw_notify (G_OBJECT (window));
7596 gtk_widget_map (widget);
7600 * gtk_window_set_screen:
7601 * @window: a #GtkWindow.
7602 * @screen: a #GdkScreen.
7604 * Sets the #GdkScreen where the @window is displayed. If
7605 * the @screen is equal to @window's current screen, this
7606 * function does nothing. If it is not and the window is
7607 * already mapped, it will be unmapped, and then remapped
7608 * on the new screen.
7610 * This function resets @window's visual to the system
7611 * visual of the given @screen. If you want to use a
7612 * different visual, consider using gtk_window_set_visual()
7618 gtk_window_set_screen (GtkWindow *window,
7621 g_return_if_fail (GTK_IS_WINDOW (window));
7622 g_return_if_fail (GDK_IS_SCREEN (screen));
7624 if (screen == gdk_visual_get_screen (window->priv->visual))
7627 gtk_window_set_visual (window,
7628 gdk_screen_get_system_visual (screen));
7632 gtk_window_on_composited_changed (GdkScreen *screen,
7635 gtk_widget_queue_draw (GTK_WIDGET (window));
7637 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
7641 gtk_window_check_screen (GtkWindow *window)
7643 GtkWindowPrivate *priv = window->priv;
7646 return gdk_visual_get_screen (priv->visual);
7649 g_warning ("Screen for GtkWindow not set; you must always set\n"
7650 "a screen for a GtkWindow before using the window");
7656 * gtk_window_get_screen:
7657 * @window: a #GtkWindow.
7659 * Returns the #GdkScreen associated with @window.
7661 * Return value: (transfer none): a #GdkScreen.
7666 gtk_window_get_screen (GtkWindow *window)
7668 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
7670 return gdk_visual_get_screen (window->priv->visual);
7674 * gtk_window_is_active:
7675 * @window: a #GtkWindow
7677 * Returns whether the window is part of the current active toplevel.
7678 * (That is, the toplevel window receiving keystrokes.)
7679 * The return value is %TRUE if the window is active toplevel
7680 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
7681 * You might use this function if you wanted to draw a widget
7682 * differently in an active window from a widget in an inactive window.
7683 * See gtk_window_has_toplevel_focus()
7685 * Return value: %TRUE if the window part of the current active window.
7690 gtk_window_is_active (GtkWindow *window)
7692 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7694 return window->priv->is_active;
7698 * gtk_window_has_toplevel_focus:
7699 * @window: a #GtkWindow
7701 * Returns whether the input focus is within this GtkWindow.
7702 * For real toplevel windows, this is identical to gtk_window_is_active(),
7703 * but for embedded windows, like #GtkPlug, the results will differ.
7705 * Return value: %TRUE if the input focus is within this GtkWindow
7710 gtk_window_has_toplevel_focus (GtkWindow *window)
7712 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7714 return window->priv->has_toplevel_focus;
7718 gtk_window_group_class_init (GtkWindowGroupClass *klass)
7720 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
7724 gtk_window_group_get_type (void)
7726 static GType window_group_type = 0;
7728 if (!window_group_type)
7730 const GTypeInfo window_group_info =
7732 sizeof (GtkWindowGroupClass),
7733 NULL, /* base_init */
7734 NULL, /* base_finalize */
7735 (GClassInitFunc) gtk_window_group_class_init,
7736 NULL, /* class_finalize */
7737 NULL, /* class_data */
7738 sizeof (GtkWindowGroup),
7739 0, /* n_preallocs */
7740 (GInstanceInitFunc) NULL,
7743 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
7744 &window_group_info, 0);
7747 return window_group_type;
7751 * gtk_window_group_new:
7753 * Creates a new #GtkWindowGroup object. Grabs added with
7754 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7756 * Return value: a new #GtkWindowGroup.
7759 gtk_window_group_new (void)
7761 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7765 window_group_cleanup_grabs (GtkWindowGroup *group,
7768 GtkWindowGroupPrivate *priv;
7769 GtkDeviceGrabInfo *info;
7771 GSList *to_remove = NULL;
7773 tmp_list = group->grabs;
7776 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7777 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7778 tmp_list = tmp_list->next;
7783 gtk_grab_remove (to_remove->data);
7784 g_object_unref (to_remove->data);
7785 to_remove = g_slist_delete_link (to_remove, to_remove);
7788 priv = GTK_WINDOW_GROUP_GET_PRIVATE (group);
7789 tmp_list = priv->device_grabs;
7793 info = tmp_list->data;
7795 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
7796 to_remove = g_slist_prepend (to_remove, info);
7798 tmp_list = tmp_list->next;
7803 info = to_remove->data;
7805 gtk_device_grab_remove (info->widget, info->device);
7806 to_remove = g_slist_delete_link (to_remove, to_remove);
7811 * gtk_window_group_add_window:
7812 * @window_group: a #GtkWindowGroup
7813 * @window: the #GtkWindow to add
7815 * Adds a window to a #GtkWindowGroup.
7818 gtk_window_group_add_window (GtkWindowGroup *window_group,
7821 GtkWindowPrivate *priv;
7823 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7824 g_return_if_fail (GTK_IS_WINDOW (window));
7826 priv = window->priv;
7828 if (priv->group != window_group)
7830 g_object_ref (window);
7831 g_object_ref (window_group);
7834 gtk_window_group_remove_window (priv->group, window);
7836 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7838 priv->group = window_group;
7840 g_object_unref (window);
7845 * gtk_window_group_remove_window:
7846 * @window_group: a #GtkWindowGroup
7847 * @window: the #GtkWindow to remove
7849 * Removes a window from a #GtkWindowGroup.
7852 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7855 GtkWindowPrivate *priv;
7857 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7858 g_return_if_fail (GTK_IS_WINDOW (window));
7859 priv = window->priv;
7860 g_return_if_fail (priv->group == window_group);
7862 g_object_ref (window);
7864 window_group_cleanup_grabs (window_group, window);
7867 g_object_unref (window_group);
7868 g_object_unref (window);
7872 * gtk_window_group_list_windows:
7873 * @window_group: a #GtkWindowGroup
7875 * Returns a list of the #GtkWindows that belong to @window_group.
7877 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
7878 * windows inside the group.
7883 gtk_window_group_list_windows (GtkWindowGroup *window_group)
7885 GList *toplevels, *toplevel, *group_windows;
7887 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
7889 group_windows = NULL;
7890 toplevels = gtk_window_list_toplevels ();
7892 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
7894 GtkWindow *window = toplevel->data;
7896 if (window_group == window->priv->group)
7897 group_windows = g_list_prepend (group_windows, window);
7900 return g_list_reverse (group_windows);
7904 * gtk_window_get_group:
7905 * @window: (allow-none): a #GtkWindow, or %NULL
7907 * Returns the group for @window or the default group, if
7908 * @window is %NULL or if @window does not have an explicit
7911 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
7916 gtk_window_get_group (GtkWindow *window)
7918 if (window && window->priv->group)
7919 return window->priv->group;
7922 static GtkWindowGroup *default_group = NULL;
7925 default_group = gtk_window_group_new ();
7927 return default_group;
7932 * gtk_window_has_group:
7933 * @window: a #GtkWindow
7935 * Returns whether @window has an explicit window group.
7937 * Return value: %TRUE if @window has an explicit window group.
7942 gtk_window_has_group (GtkWindow *window)
7944 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7946 return window->priv->group != NULL;
7950 * gtk_window_group_get_current_grab:
7951 * @window_group: a #GtkWindowGroup
7953 * Gets the current grab widget of the given group,
7954 * see gtk_grab_add().
7956 * Returns: the current grab widget of the group
7961 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7963 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
7965 if (window_group->grabs)
7966 return GTK_WIDGET (window_group->grabs->data);
7971 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
7974 gboolean block_others)
7976 GtkWindowGroupPrivate *priv;
7977 GtkDeviceGrabInfo *info;
7979 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
7981 info = g_slice_new0 (GtkDeviceGrabInfo);
7982 info->widget = widget;
7983 info->device = device;
7984 info->block_others = block_others;
7986 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
7990 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
7994 GtkWindowGroupPrivate *priv;
7995 GtkDeviceGrabInfo *info;
7996 GSList *list, *node = NULL;
7997 GdkDevice *other_device;
7999 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8000 other_device = gdk_device_get_associated_device (device);
8001 list = priv->device_grabs;
8007 if (info->widget == widget &&
8008 (info->device == device ||
8009 info->device == other_device))
8022 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8023 g_slice_free (GtkDeviceGrabInfo, info);
8028 * gtk_window_group_get_current_device_grab:
8029 * @window_group: a #GtkWindowGroup
8030 * @device: a #GdkDevice
8032 * Returns the current grab widget for @device, or %NULL if none.
8034 * Returns: The grab widget, or %NULL
8039 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8042 GtkWindowGroupPrivate *priv;
8043 GtkDeviceGrabInfo *info;
8044 GdkDevice *other_device;
8047 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8048 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8050 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8051 list = priv->device_grabs;
8052 other_device = gdk_device_get_associated_device (device);
8059 if (info->device == device ||
8060 info->device == other_device)
8061 return info->widget;
8068 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8072 GtkWindowGroupPrivate *priv;
8073 GtkDeviceGrabInfo *info;
8074 GdkDevice *other_device;
8077 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8078 other_device = gdk_device_get_associated_device (device);
8079 list = priv->device_grabs;
8086 /* Look for blocking grabs on other device pairs
8087 * that have the passed widget within the GTK+ grab.
8089 if (info->block_others &&
8090 info->device != device &&
8091 info->device != other_device &&
8092 (info->widget == widget ||
8093 gtk_widget_is_ancestor (widget, info->widget)))
8101 Derived from XParseGeometry() in XFree86
8103 Copyright 1985, 1986, 1987,1998 The Open Group
8105 All Rights Reserved.
8107 The above copyright notice and this permission notice shall be included
8108 in all copies or substantial portions of the Software.
8110 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8111 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8112 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8113 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8114 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8115 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8116 OTHER DEALINGS IN THE SOFTWARE.
8118 Except as contained in this notice, the name of The Open Group shall
8119 not be used in advertising or otherwise to promote the sale, use or
8120 other dealings in this Software without prior written authorization
8121 from The Open Group.
8126 * XParseGeometry parses strings of the form
8127 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8128 * width, height, xoffset, and yoffset are unsigned integers.
8129 * Example: "=80x24+300-49"
8130 * The equal sign is optional.
8131 * It returns a bitmask that indicates which of the four values
8132 * were actually found in the string. For each value found,
8133 * the corresponding argument is updated; for each value
8134 * not found, the corresponding argument is left unchanged.
8137 /* The following code is from Xlib, and is minimally modified, so we
8138 * can track any upstream changes if required. Don't change this
8139 * code. Or if you do, put in a huge comment marking which thing
8144 read_int (gchar *string,
8152 else if (*string == '-')
8158 for (; (*string >= '0') && (*string <= '9'); string++)
8160 result = (result * 10) + (*string - '0');
8172 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8173 * value (x, y, width, height) was found in the parsed string.
8175 #define NoValue 0x0000
8176 #define XValue 0x0001
8177 #define YValue 0x0002
8178 #define WidthValue 0x0004
8179 #define HeightValue 0x0008
8180 #define AllValues 0x000F
8181 #define XNegative 0x0010
8182 #define YNegative 0x0020
8184 /* Try not to reformat/modify, so we can compare/sync with X sources */
8186 gtk_XParseGeometry (const char *string,
8189 unsigned int *width,
8190 unsigned int *height)
8194 unsigned int tempWidth, tempHeight;
8196 char *nextCharacter;
8198 /* These initializations are just to silence gcc */
8204 if ( (string == NULL) || (*string == '\0')) return(mask);
8206 string++; /* ignore possible '=' at beg of geometry spec */
8208 strind = (char *)string;
8209 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8210 tempWidth = read_int(strind, &nextCharacter);
8211 if (strind == nextCharacter)
8213 strind = nextCharacter;
8217 if (*strind == 'x' || *strind == 'X') {
8219 tempHeight = read_int(strind, &nextCharacter);
8220 if (strind == nextCharacter)
8222 strind = nextCharacter;
8223 mask |= HeightValue;
8226 if ((*strind == '+') || (*strind == '-')) {
8227 if (*strind == '-') {
8229 tempX = -read_int(strind, &nextCharacter);
8230 if (strind == nextCharacter)
8232 strind = nextCharacter;
8238 tempX = read_int(strind, &nextCharacter);
8239 if (strind == nextCharacter)
8241 strind = nextCharacter;
8244 if ((*strind == '+') || (*strind == '-')) {
8245 if (*strind == '-') {
8247 tempY = -read_int(strind, &nextCharacter);
8248 if (strind == nextCharacter)
8250 strind = nextCharacter;
8257 tempY = read_int(strind, &nextCharacter);
8258 if (strind == nextCharacter)
8260 strind = nextCharacter;
8266 /* If strind isn't at the end of the string the it's an invalid
8267 geometry specification. */
8269 if (*strind != '\0') return (0);
8275 if (mask & WidthValue)
8277 if (mask & HeightValue)
8278 *height = tempHeight;
8283 * gtk_window_parse_geometry:
8284 * @window: a #GtkWindow
8285 * @geometry: geometry string
8287 * Parses a standard X Window System geometry string - see the
8288 * manual page for X (type 'man X') for details on this.
8289 * gtk_window_parse_geometry() does work on all GTK+ ports
8290 * including Win32 but is primarily intended for an X environment.
8292 * If either a size or a position can be extracted from the
8293 * geometry string, gtk_window_parse_geometry() returns %TRUE
8294 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8295 * to resize/move the window.
8297 * If gtk_window_parse_geometry() returns %TRUE, it will also
8298 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8299 * indicating to the window manager that the size/position of
8300 * the window was user-specified. This causes most window
8301 * managers to honor the geometry.
8303 * Note that for gtk_window_parse_geometry() to work as expected, it has
8304 * to be called when the window has its "final" size, i.e. after calling
8305 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8308 * #include <gtk/gtk.h>
8311 * fill_with_content (GtkWidget *vbox)
8313 * /* fill with content... */
8317 * main (int argc, char *argv[])
8319 * GtkWidget *window, *vbox;
8320 * GdkGeometry size_hints = {
8321 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8324 * gtk_init (&argc, &argv);
8326 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8327 * vbox = gtk_vbox_new (FALSE, 0);
8329 * gtk_container_add (GTK_CONTAINER (window), vbox);
8330 * fill_with_content (vbox);
8331 * gtk_widget_show_all (vbox);
8333 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8336 * GDK_HINT_MIN_SIZE |
8337 * GDK_HINT_BASE_SIZE |
8338 * GDK_HINT_RESIZE_INC);
8342 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8343 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8346 * gtk_widget_show_all (window);
8353 * Return value: %TRUE if string was parsed successfully
8356 gtk_window_parse_geometry (GtkWindow *window,
8357 const gchar *geometry)
8359 gint result, x = 0, y = 0;
8362 gboolean size_set, pos_set;
8365 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8366 g_return_val_if_fail (geometry != NULL, FALSE);
8368 screen = gtk_window_check_screen (window);
8370 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8373 if ((result & WidthValue) || (result & HeightValue))
8375 gtk_window_set_default_size_internal (window,
8376 TRUE, result & WidthValue ? w : -1,
8377 TRUE, result & HeightValue ? h : -1,
8382 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8384 grav = GDK_GRAVITY_NORTH_WEST;
8386 if ((result & XNegative) && (result & YNegative))
8387 grav = GDK_GRAVITY_SOUTH_EAST;
8388 else if (result & XNegative)
8389 grav = GDK_GRAVITY_NORTH_EAST;
8390 else if (result & YNegative)
8391 grav = GDK_GRAVITY_SOUTH_WEST;
8393 if ((result & XValue) == 0)
8396 if ((result & YValue) == 0)
8399 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8400 grav == GDK_GRAVITY_SOUTH_EAST)
8401 y = gdk_screen_get_height (screen) - h + y;
8403 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8404 grav == GDK_GRAVITY_NORTH_EAST)
8405 x = gdk_screen_get_width (screen) - w + x;
8407 /* we don't let you put a window offscreen; maybe some people would
8408 * prefer to be able to, but it's kind of a bogus thing to do.
8417 if ((result & XValue) || (result & YValue))
8419 gtk_window_set_gravity (window, grav);
8420 gtk_window_move (window, x, y);
8424 if (size_set || pos_set)
8426 /* Set USSize, USPosition hints */
8427 GtkWindowGeometryInfo *info;
8429 info = gtk_window_get_geometry_info (window, TRUE);
8432 info->mask |= GDK_HINT_USER_POS;
8434 info->mask |= GDK_HINT_USER_SIZE;
8441 gtk_window_mnemonic_hash_foreach (guint keyval,
8447 GtkWindowKeysForeachFunc func;
8451 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8455 _gtk_window_keys_foreach (GtkWindow *window,
8456 GtkWindowKeysForeachFunc func,
8460 GtkMnemonicHash *mnemonic_hash;
8464 GtkWindowKeysForeachFunc func;
8468 info.window = window;
8470 info.func_data = func_data;
8472 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8474 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8475 gtk_window_mnemonic_hash_foreach, &info);
8477 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8480 GtkAccelGroup *group = groups->data;
8483 for (i = 0; i < group->priv->n_accels; i++)
8485 GtkAccelKey *key = &group->priv->priv_accels[i].key;
8488 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8491 groups = groups->next;
8496 gtk_window_keys_changed (GtkWindow *window)
8498 gtk_window_free_key_hash (window);
8499 gtk_window_get_key_hash (window);
8502 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8504 struct _GtkWindowKeyEntry
8508 guint is_mnemonic : 1;
8512 window_key_entry_destroy (gpointer data)
8514 g_slice_free (GtkWindowKeyEntry, data);
8518 add_to_key_hash (GtkWindow *window,
8520 GdkModifierType modifiers,
8521 gboolean is_mnemonic,
8524 GtkKeyHash *key_hash = data;
8526 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8528 entry->keyval = keyval;
8529 entry->modifiers = modifiers;
8530 entry->is_mnemonic = is_mnemonic;
8532 /* GtkAccelGroup stores lowercased accelerators. To deal
8533 * with this, if <Shift> was specified, uppercase.
8535 if (modifiers & GDK_SHIFT_MASK)
8537 if (keyval == GDK_KEY_Tab)
8538 keyval = GDK_KEY_ISO_Left_Tab;
8540 keyval = gdk_keyval_to_upper (keyval);
8543 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8547 gtk_window_get_key_hash (GtkWindow *window)
8549 GdkScreen *screen = gtk_window_check_screen (window);
8550 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8555 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8556 (GDestroyNotify)window_key_entry_destroy);
8557 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8558 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8564 gtk_window_free_key_hash (GtkWindow *window)
8566 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8569 _gtk_key_hash_free (key_hash);
8570 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8575 * gtk_window_activate_key:
8576 * @window: a #GtkWindow
8577 * @event: a #GdkEventKey
8579 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8580 * called by the default ::key_press_event handler for toplevel windows,
8581 * however in some cases it may be useful to call this directly when
8582 * overriding the standard key handling for a toplevel window.
8584 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8589 gtk_window_activate_key (GtkWindow *window,
8592 GtkKeyHash *key_hash;
8593 GtkWindowKeyEntry *found_entry = NULL;
8594 gboolean enable_mnemonics;
8595 gboolean enable_accels;
8597 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8598 g_return_val_if_fail (event != NULL, FALSE);
8600 key_hash = gtk_window_get_key_hash (window);
8605 GSList *entries = _gtk_key_hash_lookup (key_hash,
8606 event->hardware_keycode,
8608 gtk_accelerator_get_default_mod_mask (),
8611 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
8612 "gtk-enable-mnemonics", &enable_mnemonics,
8613 "gtk-enable-accels", &enable_accels,
8616 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
8618 GtkWindowKeyEntry *entry = tmp_list->data;
8619 if (entry->is_mnemonic)
8621 if (enable_mnemonics)
8623 found_entry = entry;
8629 if (enable_accels && !found_entry)
8631 found_entry = entry;
8636 g_slist_free (entries);
8641 if (found_entry->is_mnemonic)
8643 if (enable_mnemonics)
8644 return gtk_window_mnemonic_activate (window, found_entry->keyval,
8645 found_entry->modifiers);
8650 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
8651 found_entry->modifiers);
8659 window_update_has_focus (GtkWindow *window)
8661 GtkWindowPrivate *priv = window->priv;
8662 GtkWidget *widget = GTK_WIDGET (window);
8663 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
8665 if (has_focus != priv->has_focus)
8667 priv->has_focus = has_focus;
8671 if (priv->focus_widget &&
8672 priv->focus_widget != widget &&
8673 !gtk_widget_has_focus (priv->focus_widget))
8674 do_focus_change (priv->focus_widget, TRUE);
8678 if (priv->focus_widget &&
8679 priv->focus_widget != widget &&
8680 gtk_widget_has_focus (priv->focus_widget))
8681 do_focus_change (priv->focus_widget, FALSE);
8687 * _gtk_window_set_is_active:
8688 * @window: a #GtkWindow
8689 * @is_active: %TRUE if the window is in the currently active toplevel
8691 * Internal function that sets whether the #GtkWindow is part
8692 * of the currently active toplevel window (taking into account inter-process
8696 _gtk_window_set_is_active (GtkWindow *window,
8699 GtkWindowPrivate *priv;
8701 g_return_if_fail (GTK_IS_WINDOW (window));
8703 priv = window->priv;
8705 is_active = is_active != FALSE;
8707 if (is_active != priv->is_active)
8709 priv->is_active = is_active;
8710 window_update_has_focus (window);
8712 g_object_notify (G_OBJECT (window), "is-active");
8717 * _gtk_window_set_is_toplevel:
8718 * @window: a #GtkWindow
8719 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
8720 * parent of the root window); %FALSE if it is not (for example, for an
8721 * in-process, parented GtkPlug)
8723 * Internal function used by #GtkPlug when it gets parented/unparented by a
8724 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
8725 * global list of toplevel windows.
8728 _gtk_window_set_is_toplevel (GtkWindow *window,
8729 gboolean is_toplevel)
8733 widget = GTK_WIDGET (window);
8735 if (gtk_widget_is_toplevel (widget))
8736 g_assert (g_slist_find (toplevel_list, window) != NULL);
8738 g_assert (g_slist_find (toplevel_list, window) == NULL);
8740 if (is_toplevel == gtk_widget_is_toplevel (widget))
8745 _gtk_widget_set_is_toplevel (widget, TRUE);
8746 toplevel_list = g_slist_prepend (toplevel_list, window);
8750 _gtk_widget_set_is_toplevel (widget, FALSE);
8751 toplevel_list = g_slist_remove (toplevel_list, window);
8756 * _gtk_window_set_has_toplevel_focus:
8757 * @window: a #GtkWindow
8758 * @has_toplevel_focus: %TRUE if the in
8760 * Internal function that sets whether the keyboard focus for the
8761 * toplevel window (taking into account inter-process embedding.)
8764 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
8765 gboolean has_toplevel_focus)
8767 GtkWindowPrivate *priv;
8769 g_return_if_fail (GTK_IS_WINDOW (window));
8771 priv = window->priv;
8773 has_toplevel_focus = has_toplevel_focus != FALSE;
8775 if (has_toplevel_focus != priv->has_toplevel_focus)
8777 priv->has_toplevel_focus = has_toplevel_focus;
8778 window_update_has_focus (window);
8780 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
8785 * gtk_window_set_auto_startup_notification:
8786 * @setting: %TRUE to automatically do startup notification
8788 * By default, after showing the first #GtkWindow, GTK+ calls
8789 * gdk_notify_startup_complete(). Call this function to disable
8790 * the automatic startup notification. You might do this if your
8791 * first window is a splash screen, and you want to delay notification
8792 * until after your real main window has been shown, for example.
8794 * In that example, you would disable startup notification
8795 * temporarily, show your splash screen, then re-enable it so that
8796 * showing the main window would automatically result in notification.
8801 gtk_window_set_auto_startup_notification (gboolean setting)
8803 disable_startup_notification = !setting;
8807 * gtk_window_get_window_type:
8808 * @window: a #GtkWindow
8810 * Gets the type of the window. See #GtkWindowType.
8812 * Return value: the type of the window
8817 gtk_window_get_window_type (GtkWindow *window)
8819 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
8821 return window->priv->type;
8825 * gtk_window_get_mnemonics_visible:
8826 * @window: a #GtkWindow
8828 * Gets the value of the #GtkWindow:mnemonics-visible property.
8830 * Returns: %TRUE if mnemonics are supposed to be visible
8836 gtk_window_get_mnemonics_visible (GtkWindow *window)
8838 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8840 return window->priv->mnemonics_visible;
8844 * gtk_window_set_mnemonics_visible:
8845 * @window: a #GtkWindow
8846 * @setting: the new value
8848 * Sets the #GtkWindow:mnemonics-visible property.
8853 gtk_window_set_mnemonics_visible (GtkWindow *window,
8856 GtkWindowPrivate *priv;
8858 g_return_if_fail (GTK_IS_WINDOW (window));
8860 priv = window->priv;
8862 setting = setting != FALSE;
8864 if (priv->mnemonics_visible != setting)
8866 priv->mnemonics_visible = setting;
8867 g_object_notify (G_OBJECT (window), "mnemonics-visible");
8870 priv->mnemonics_visible_set = TRUE;
8874 _gtk_window_get_wmclass (GtkWindow *window,
8875 gchar **wmclass_name,
8876 gchar **wmclass_class)
8878 GtkWindowPrivate *priv = window->priv;
8880 *wmclass_name = priv->wmclass_name;
8881 *wmclass_class = priv->wmclass_class;