1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gtkwindow.h"
36 #include "gtkprivate.h"
38 #include "gtkwindowprivate.h"
39 #include "gtkaccelgroupprivate.h"
40 #include "gtkbindings.h"
41 #include "gtkkeyhash.h"
43 #include "gtkmnemonichash.h"
44 #include "gtkmenubar.h"
45 #include "gtkiconfactory.h"
46 #include "gtkicontheme.h"
47 #include "gtkmarshalers.h"
49 #include "gtkbuildable.h"
50 #include "gtkwidgetprivate.h"
52 #include "gtktypebuiltins.h"
54 #ifdef GDK_WINDOWING_X11
61 * @short_description: Toplevel which can contain other widgets
63 * A GtkWindow is a toplevel window which can contain other widgets.
64 * Windows normally have decorations that are under the control
65 * of the windowing system and allow the user to manipulate the window
66 * (resize it, move it, close it,...).
68 * GTK+ also allows windows to have a resize grip (a small area in the lower
69 * right or left corner) which can be clicked to reszie the window. To
70 * control whether a window has a resize grip, use
71 * gtk_window_set_has_resize_grip().
73 * <refsect2 id="GtkWindow-BUILDER-UI">
74 * <title>GtkWindow as GtkBuildable</title>
76 * The GtkWindow implementation of the GtkBuildable interface supports a
77 * custom <tag class="starttag">accel-groups</tag> element, which supports
78 * any number of <tag class="starttag">group</tag> elements representing the
79 * #GtkAccelGroup objects you want to add to your window (synonymous with
80 * gtk_window_add_accel_group().
83 * <title>A UI definition fragment with accel groups</title>
84 * <programlisting><![CDATA[
85 * <object class="GtkWindow">
87 * <group name="accelgroup1"/>
93 * <object class="GtkAccelGroup" id="accelgroup1"/>
94 * ]]></programlisting>
99 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
101 struct _GtkWindowPrivate
103 GtkMnemonicHash *mnemonic_hash;
105 GtkWidget *default_widget;
106 GtkWidget *focus_widget;
107 GtkWindow *transient_parent;
108 GtkWindowGeometryInfo *geometry_info;
109 GtkWindowGroup *group;
111 GtkApplication *application;
113 GdkModifierType mnemonic_modifier;
114 GdkWindowTypeHint gdk_type_hint;
118 GdkWindow *grip_window;
122 gchar *wmclass_class;
126 guint keys_changed_handler;
128 guint16 configure_request_count;
130 /* The following flags are initially TRUE (before a window is mapped).
131 * They cause us to compute a configure request that involves
132 * default-only parameters. Once mapped, we set them to FALSE.
133 * Then we set them to TRUE again on unmap (for position)
134 * and on unrealize (for size).
136 guint need_default_position : 1;
137 guint need_default_size : 1;
139 guint above_initially : 1;
140 guint accept_focus : 1;
141 guint below_initially : 1;
142 guint builder_visible : 1;
143 guint configure_notify_received : 1;
146 guint destroy_with_parent : 1;
147 guint focus_on_map : 1;
148 guint fullscreen_initially : 1;
150 guint has_user_ref_count : 1;
151 guint has_toplevel_focus : 1;
152 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
154 guint maximize_initially : 1;
155 guint mnemonics_visible : 1;
156 guint mnemonics_visible_set : 1;
158 guint opacity_set : 1;
160 guint reset_type_hint : 1;
162 guint skips_pager : 1;
163 guint skips_taskbar : 1;
164 guint stick_initially : 1;
165 guint transient_parent_group : 1;
166 guint type : 4; /* GtkWindowType */
167 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
168 * one of the original eight. If not,
170 * GDK_WINDOW_TYPE_HINT_NORMAL
173 guint has_resize_grip : 1;
174 guint resize_grip_visible : 1; /* don't use, just for "resize-
175 * grip-visible" notification
177 guint gravity : 5; /* GdkGravity */
204 PROP_DESTROY_WITH_PARENT,
209 PROP_SKIP_TASKBAR_HINT,
210 PROP_SKIP_PAGER_HINT,
219 PROP_HAS_RESIZE_GRIP,
220 PROP_RESIZE_GRIP_VISIBLE,
222 /* Readonly properties */
224 PROP_HAS_TOPLEVEL_FOCUS,
226 /* Writeonly properties */
229 PROP_MNEMONICS_VISIBLE,
239 guint using_default_icon : 1;
240 guint using_parent_icon : 1;
241 guint using_themed_icon : 1;
245 GdkGeometry geometry; /* Last set of geometry hints we set */
246 GdkWindowHints flags;
247 GdkRectangle configure_request;
248 } GtkWindowLastGeometryInfo;
250 struct _GtkWindowGeometryInfo
252 /* Properties that the app has set on the window
254 GdkGeometry geometry; /* Geometry hints */
256 GtkWidget *widget; /* subwidget to which hints apply */
257 /* from last gtk_window_resize () - if > 0, indicates that
258 * we should resize to this size.
263 /* From last gtk_window_move () prior to mapping -
264 * only used if initial_pos_set
269 /* Default size - used only the FIRST time we map a window,
274 /* whether to use initial_x, initial_y */
275 guint initial_pos_set : 1;
276 /* CENTER_ALWAYS or other position constraint changed since
277 * we sent the last configure request.
279 guint position_constraints_changed : 1;
281 /* if true, default_width, height should be multiplied by the
282 * increments and affect the geometry widget only
284 guint default_is_geometry : 1;
286 /* if true, resize_width, height should be multiplied by the
287 * increments and affect the geometry widget only
289 guint resize_is_geometry : 1;
291 GtkWindowLastGeometryInfo last;
295 struct _GtkDeviceGrabInfo
299 guint block_others : 1;
302 struct _GtkWindowGroupPrivate
305 GSList *device_grabs;
308 static void gtk_window_dispose (GObject *object);
309 static void gtk_window_finalize (GObject *object);
310 static void gtk_window_destroy (GtkWidget *widget);
311 static void gtk_window_show (GtkWidget *widget);
312 static void gtk_window_hide (GtkWidget *widget);
313 static void gtk_window_map (GtkWidget *widget);
314 static void gtk_window_unmap (GtkWidget *widget);
315 static void gtk_window_realize (GtkWidget *widget);
316 static void gtk_window_unrealize (GtkWidget *widget);
317 static void gtk_window_size_allocate (GtkWidget *widget,
318 GtkAllocation *allocation);
319 static gboolean gtk_window_map_event (GtkWidget *widget,
321 static gint gtk_window_configure_event (GtkWidget *widget,
322 GdkEventConfigure *event);
323 static gint gtk_window_key_press_event (GtkWidget *widget,
325 static gint gtk_window_key_release_event (GtkWidget *widget,
327 static gint gtk_window_button_press_event (GtkWidget *widget,
328 GdkEventButton *event);
329 static gint gtk_window_enter_notify_event (GtkWidget *widget,
330 GdkEventCrossing *event);
331 static gint gtk_window_leave_notify_event (GtkWidget *widget,
332 GdkEventCrossing *event);
333 static gint gtk_window_focus_in_event (GtkWidget *widget,
334 GdkEventFocus *event);
335 static gint gtk_window_focus_out_event (GtkWidget *widget,
336 GdkEventFocus *event);
337 static void gtk_window_style_updated (GtkWidget *widget);
338 static gboolean gtk_window_state_event (GtkWidget *widget,
339 GdkEventWindowState *event);
340 static void gtk_window_check_resize (GtkContainer *container);
341 static gint gtk_window_focus (GtkWidget *widget,
342 GtkDirectionType direction);
343 static void gtk_window_move_focus (GtkWidget *widget,
344 GtkDirectionType dir);
345 static void gtk_window_real_set_focus (GtkWindow *window,
347 static void gtk_window_direction_changed (GtkWidget *widget,
348 GtkTextDirection prev_dir);
349 static void gtk_window_state_changed (GtkWidget *widget,
350 GtkStateType previous_state);
352 static void gtk_window_real_activate_default (GtkWindow *window);
353 static void gtk_window_real_activate_focus (GtkWindow *window);
354 static void gtk_window_keys_changed (GtkWindow *window);
355 static gint gtk_window_draw (GtkWidget *widget,
357 static void gtk_window_unset_transient_for (GtkWindow *window);
358 static void gtk_window_transient_parent_realized (GtkWidget *parent,
360 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
363 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
365 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
368 static void gtk_window_move_resize (GtkWindow *window);
369 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
371 GdkGeometry *geometry_b,
373 static void gtk_window_constrain_size (GtkWindow *window,
374 GdkGeometry *geometry,
380 static void gtk_window_constrain_position (GtkWindow *window,
385 static void gtk_window_compute_hints (GtkWindow *window,
386 GdkGeometry *new_geometry,
388 static void gtk_window_compute_configure_request (GtkWindow *window,
389 GdkRectangle *request,
390 GdkGeometry *geometry,
393 static void gtk_window_set_default_size_internal (GtkWindow *window,
394 gboolean change_width,
396 gboolean change_height,
398 gboolean is_geometry);
400 static void update_themed_icon (GtkIconTheme *theme,
402 static GList *icon_list_from_theme (GtkWidget *widget,
404 static void gtk_window_realize_icon (GtkWindow *window);
405 static void gtk_window_unrealize_icon (GtkWindow *window);
406 static void resize_grip_create_window (GtkWindow *window);
407 static void resize_grip_destroy_window (GtkWindow *window);
408 static void update_grip_visibility (GtkWindow *window);
410 static void gtk_window_notify_keys_changed (GtkWindow *window);
411 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
412 static void gtk_window_free_key_hash (GtkWindow *window);
413 static void gtk_window_on_composited_changed (GdkScreen *screen,
415 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
418 static void gtk_window_set_theme_variant (GtkWindow *window);
420 static GSList *toplevel_list = NULL;
421 static guint window_signals[LAST_SIGNAL] = { 0 };
422 static GList *default_icon_list = NULL;
423 static gchar *default_icon_name = NULL;
424 static guint default_icon_serial = 0;
425 static gboolean disable_startup_notification = FALSE;
426 static gboolean sent_startup_notification = FALSE;
428 static GQuark quark_gtk_embedded = 0;
429 static GQuark quark_gtk_window_key_hash = 0;
430 static GQuark quark_gtk_window_icon_info = 0;
431 static GQuark quark_gtk_buildable_accels = 0;
433 static GtkBuildableIface *parent_buildable_iface;
435 static void gtk_window_set_property (GObject *object,
439 static void gtk_window_get_property (GObject *object,
445 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
446 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
449 const GValue *value);
450 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
451 GtkBuilder *builder);
452 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
455 const gchar *tagname,
456 GMarkupParser *parser,
458 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
461 const gchar *tagname,
465 static void gtk_window_get_preferred_width (GtkWidget *widget,
468 static void gtk_window_get_preferred_height (GtkWidget *widget,
472 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
473 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
474 gtk_window_buildable_interface_init))
477 add_tab_bindings (GtkBindingSet *binding_set,
478 GdkModifierType modifiers,
479 GtkDirectionType direction)
481 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
483 GTK_TYPE_DIRECTION_TYPE, direction);
484 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
486 GTK_TYPE_DIRECTION_TYPE, direction);
490 add_arrow_bindings (GtkBindingSet *binding_set,
492 GtkDirectionType direction)
494 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
496 gtk_binding_entry_add_signal (binding_set, keysym, 0,
498 GTK_TYPE_DIRECTION_TYPE, direction);
499 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
501 GTK_TYPE_DIRECTION_TYPE, direction);
502 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
504 GTK_TYPE_DIRECTION_TYPE, direction);
505 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
507 GTK_TYPE_DIRECTION_TYPE, direction);
511 extract_time_from_startup_id (const gchar* startup_id)
513 gchar *timestr = g_strrstr (startup_id, "_TIME");
514 guint32 retval = GDK_CURRENT_TIME;
521 /* Skip past the "_TIME" part */
526 timestamp = g_ascii_strtoull (timestr, &end, 0);
527 if (errno == 0 && end != timestr)
535 startup_id_is_fake (const gchar* startup_id)
537 return strncmp (startup_id, "_TIME", 5) == 0;
541 gtk_window_class_init (GtkWindowClass *klass)
543 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
544 GtkWidgetClass *widget_class;
545 GtkContainerClass *container_class;
546 GtkBindingSet *binding_set;
548 widget_class = (GtkWidgetClass*) klass;
549 container_class = (GtkContainerClass*) klass;
551 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
552 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
553 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
554 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
556 gobject_class->dispose = gtk_window_dispose;
557 gobject_class->finalize = gtk_window_finalize;
559 gobject_class->set_property = gtk_window_set_property;
560 gobject_class->get_property = gtk_window_get_property;
562 widget_class->destroy = gtk_window_destroy;
563 widget_class->show = gtk_window_show;
564 widget_class->hide = gtk_window_hide;
565 widget_class->map = gtk_window_map;
566 widget_class->map_event = gtk_window_map_event;
567 widget_class->unmap = gtk_window_unmap;
568 widget_class->realize = gtk_window_realize;
569 widget_class->unrealize = gtk_window_unrealize;
570 widget_class->size_allocate = gtk_window_size_allocate;
571 widget_class->configure_event = gtk_window_configure_event;
572 widget_class->key_press_event = gtk_window_key_press_event;
573 widget_class->key_release_event = gtk_window_key_release_event;
574 widget_class->enter_notify_event = gtk_window_enter_notify_event;
575 widget_class->leave_notify_event = gtk_window_leave_notify_event;
576 widget_class->focus_in_event = gtk_window_focus_in_event;
577 widget_class->button_press_event = gtk_window_button_press_event;
578 widget_class->focus_out_event = gtk_window_focus_out_event;
579 widget_class->focus = gtk_window_focus;
580 widget_class->move_focus = gtk_window_move_focus;
581 widget_class->draw = gtk_window_draw;
582 widget_class->get_preferred_width = gtk_window_get_preferred_width;
583 widget_class->get_preferred_height = gtk_window_get_preferred_height;
584 widget_class->window_state_event = gtk_window_state_event;
585 widget_class->direction_changed = gtk_window_direction_changed;
586 widget_class->state_changed = gtk_window_state_changed;
587 widget_class->style_updated = gtk_window_style_updated;
589 container_class->check_resize = gtk_window_check_resize;
591 klass->set_focus = gtk_window_real_set_focus;
593 klass->activate_default = gtk_window_real_activate_default;
594 klass->activate_focus = gtk_window_real_activate_focus;
595 klass->keys_changed = gtk_window_keys_changed;
597 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
600 g_object_class_install_property (gobject_class,
602 g_param_spec_enum ("type",
604 P_("The type of the window"),
605 GTK_TYPE_WINDOW_TYPE,
607 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
609 g_object_class_install_property (gobject_class,
611 g_param_spec_string ("title",
613 P_("The title of the window"),
615 GTK_PARAM_READWRITE));
617 g_object_class_install_property (gobject_class,
619 g_param_spec_string ("role",
621 P_("Unique identifier for the window to be used when restoring a session"),
623 GTK_PARAM_READWRITE));
626 * GtkWindow:startup-id:
628 * The :startup-id is a write-only property for setting window's
629 * startup notification identifier. See gtk_window_set_startup_id()
634 g_object_class_install_property (gobject_class,
636 g_param_spec_string ("startup-id",
638 P_("Unique startup identifier for the window used by startup-notification"),
640 GTK_PARAM_WRITABLE));
642 g_object_class_install_property (gobject_class,
644 g_param_spec_boolean ("resizable",
646 P_("If TRUE, users can resize the window"),
648 GTK_PARAM_READWRITE));
650 g_object_class_install_property (gobject_class,
652 g_param_spec_boolean ("modal",
654 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
656 GTK_PARAM_READWRITE));
658 g_object_class_install_property (gobject_class,
660 g_param_spec_enum ("window-position",
661 P_("Window Position"),
662 P_("The initial position of the window"),
663 GTK_TYPE_WINDOW_POSITION,
665 GTK_PARAM_READWRITE));
667 g_object_class_install_property (gobject_class,
669 g_param_spec_int ("default-width",
671 P_("The default width of the window, used when initially showing the window"),
675 GTK_PARAM_READWRITE));
677 g_object_class_install_property (gobject_class,
679 g_param_spec_int ("default-height",
680 P_("Default Height"),
681 P_("The default height of the window, used when initially showing the window"),
685 GTK_PARAM_READWRITE));
687 g_object_class_install_property (gobject_class,
688 PROP_DESTROY_WITH_PARENT,
689 g_param_spec_boolean ("destroy-with-parent",
690 P_("Destroy with Parent"),
691 P_("If this window should be destroyed when the parent is destroyed"),
693 GTK_PARAM_READWRITE));
695 g_object_class_install_property (gobject_class,
697 g_param_spec_object ("icon",
699 P_("Icon for this window"),
701 GTK_PARAM_READWRITE));
702 g_object_class_install_property (gobject_class,
703 PROP_MNEMONICS_VISIBLE,
704 g_param_spec_boolean ("mnemonics-visible",
705 P_("Mnemonics Visible"),
706 P_("Whether mnemonics are currently visible in this window"),
708 GTK_PARAM_READWRITE));
711 * GtkWindow:icon-name:
713 * The :icon-name property specifies the name of the themed icon to
714 * use as the window icon. See #GtkIconTheme for more details.
718 g_object_class_install_property (gobject_class,
720 g_param_spec_string ("icon-name",
722 P_("Name of the themed icon for this window"),
724 GTK_PARAM_READWRITE));
726 g_object_class_install_property (gobject_class,
728 g_param_spec_object ("screen",
730 P_("The screen where this window will be displayed"),
732 GTK_PARAM_READWRITE));
734 g_object_class_install_property (gobject_class,
736 g_param_spec_boolean ("is-active",
738 P_("Whether the toplevel is the current active window"),
740 GTK_PARAM_READABLE));
742 g_object_class_install_property (gobject_class,
743 PROP_HAS_TOPLEVEL_FOCUS,
744 g_param_spec_boolean ("has-toplevel-focus",
745 P_("Focus in Toplevel"),
746 P_("Whether the input focus is within this GtkWindow"),
748 GTK_PARAM_READABLE));
750 g_object_class_install_property (gobject_class,
752 g_param_spec_enum ("type-hint",
754 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
755 GDK_TYPE_WINDOW_TYPE_HINT,
756 GDK_WINDOW_TYPE_HINT_NORMAL,
757 GTK_PARAM_READWRITE));
759 g_object_class_install_property (gobject_class,
760 PROP_SKIP_TASKBAR_HINT,
761 g_param_spec_boolean ("skip-taskbar-hint",
763 P_("TRUE if the window should not be in the task bar."),
765 GTK_PARAM_READWRITE));
767 g_object_class_install_property (gobject_class,
768 PROP_SKIP_PAGER_HINT,
769 g_param_spec_boolean ("skip-pager-hint",
771 P_("TRUE if the window should not be in the pager."),
773 GTK_PARAM_READWRITE));
775 g_object_class_install_property (gobject_class,
777 g_param_spec_boolean ("urgency-hint",
779 P_("TRUE if the window should be brought to the user's attention."),
781 GTK_PARAM_READWRITE));
784 * GtkWindow:accept-focus:
786 * Whether the window should receive the input focus.
790 g_object_class_install_property (gobject_class,
792 g_param_spec_boolean ("accept-focus",
794 P_("TRUE if the window should receive the input focus."),
796 GTK_PARAM_READWRITE));
799 * GtkWindow:focus-on-map:
801 * Whether the window should receive the input focus when mapped.
805 g_object_class_install_property (gobject_class,
807 g_param_spec_boolean ("focus-on-map",
809 P_("TRUE if the window should receive the input focus when mapped."),
811 GTK_PARAM_READWRITE));
814 * GtkWindow:decorated:
816 * Whether the window should be decorated by the window manager.
820 g_object_class_install_property (gobject_class,
822 g_param_spec_boolean ("decorated",
824 P_("Whether the window should be decorated by the window manager"),
826 GTK_PARAM_READWRITE));
829 * GtkWindow:deletable:
831 * Whether the window frame should have a close button.
835 g_object_class_install_property (gobject_class,
837 g_param_spec_boolean ("deletable",
839 P_("Whether the window frame should have a close button"),
841 GTK_PARAM_READWRITE));
844 * GtkWindow:has-resize-grip
846 * Whether the window has a corner resize grip.
848 * Note that the resize grip is only shown if the window is
849 * actually resizable and not maximized. Use
850 * #GtkWindow:resize-grip-visible to find out if the resize
851 * grip is currently shown.
855 g_object_class_install_property (gobject_class,
856 PROP_HAS_RESIZE_GRIP,
857 g_param_spec_boolean ("has-resize-grip",
859 P_("Specifies whether the window should have a resize grip"),
861 GTK_PARAM_READWRITE));
864 * GtkWindow:resize-grip-visible:
866 * Whether a corner resize grip is currently shown.
870 g_object_class_install_property (gobject_class,
871 PROP_RESIZE_GRIP_VISIBLE,
872 g_param_spec_boolean ("resize-grip-visible",
873 P_("Resize grip is visible"),
874 P_("Specifies whether the window's resize grip is visible."),
876 GTK_PARAM_READABLE));
882 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
883 * more details about window gravity.
887 g_object_class_install_property (gobject_class,
889 g_param_spec_enum ("gravity",
891 P_("The window gravity of the window"),
893 GDK_GRAVITY_NORTH_WEST,
894 GTK_PARAM_READWRITE));
898 * GtkWindow:transient-for:
900 * The transient parent of the window. See gtk_window_set_transient_for() for
901 * more details about transient windows.
905 g_object_class_install_property (gobject_class,
907 g_param_spec_object ("transient-for",
908 P_("Transient for Window"),
909 P_("The transient parent of the dialog"),
911 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
916 * The requested opacity of the window. See gtk_window_set_opacity() for
917 * more details about window opacity.
921 g_object_class_install_property (gobject_class,
923 g_param_spec_double ("opacity",
924 P_("Opacity for Window"),
925 P_("The opacity of the window, from 0 to 1"),
929 GTK_PARAM_READWRITE));
933 gtk_widget_class_install_style_property (widget_class,
934 g_param_spec_int ("resize-grip-width",
935 P_("Width of resize grip"),
936 P_("Width of resize grip"),
937 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
939 gtk_widget_class_install_style_property (widget_class,
940 g_param_spec_int ("resize-grip-height",
941 P_("Height of resize grip"),
942 P_("Height of resize grip"),
943 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
947 * GtkWindow:application:
949 * The #GtkApplication associated with the window.
951 * The application will be kept alive for at least as long as it
952 * has any windows associated with it (see g_application_hold()
953 * for a way to keep it alive without windows).
955 * Normally, the connection between the application and the window
956 * will remain until the window is destroyed, but you can explicitly
957 * remove it by setting the ::application property to %NULL.
961 g_object_class_install_property (gobject_class,
963 g_param_spec_object ("application",
964 P_("GtkApplication"),
965 P_("The GtkApplication for the window"),
966 GTK_TYPE_APPLICATION,
967 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
969 window_signals[SET_FOCUS] =
970 g_signal_new (I_("set-focus"),
971 G_TYPE_FROM_CLASS (gobject_class),
973 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
975 _gtk_marshal_VOID__OBJECT,
980 * GtkWindow::activate-focus:
981 * @window: the window which received the signal
983 * The ::activate-focus signal is a
984 * <link linkend="keybinding-signals">keybinding signal</link>
985 * which gets emitted when the user activates the currently
986 * focused widget of @window.
988 window_signals[ACTIVATE_FOCUS] =
989 g_signal_new (I_("activate-focus"),
990 G_TYPE_FROM_CLASS (gobject_class),
991 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
992 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
994 _gtk_marshal_VOID__VOID,
999 * GtkWindow::activate-default:
1000 * @window: the window which received the signal
1002 * The ::activate-default signal is a
1003 * <link linkend="keybinding-signals">keybinding signal</link>
1004 * which gets emitted when the user activates the default widget
1007 window_signals[ACTIVATE_DEFAULT] =
1008 g_signal_new (I_("activate-default"),
1009 G_TYPE_FROM_CLASS (gobject_class),
1010 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1011 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1013 _gtk_marshal_VOID__VOID,
1018 * GtkWindow::keys-changed:
1019 * @window: the window which received the signal
1021 * The ::keys-changed signal gets emitted when the set of accelerators
1022 * or mnemonics that are associated with @window changes.
1024 window_signals[KEYS_CHANGED] =
1025 g_signal_new (I_("keys-changed"),
1026 G_TYPE_FROM_CLASS (gobject_class),
1028 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1030 _gtk_marshal_VOID__VOID,
1038 binding_set = gtk_binding_set_by_class (klass);
1040 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1041 "activate-focus", 0);
1042 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1043 "activate-focus", 0);
1045 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1046 "activate-default", 0);
1047 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1048 "activate-default", 0);
1049 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1050 "activate-default", 0);
1052 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1053 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1054 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1055 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1057 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1058 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1059 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1060 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1064 gtk_window_init (GtkWindow *window)
1066 GtkWindowPrivate *priv;
1068 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1071 priv = window->priv;
1073 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1074 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1076 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1078 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1081 priv->wmclass_name = g_strdup (g_get_prgname ());
1082 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1083 priv->wm_role = NULL;
1084 priv->geometry_info = NULL;
1085 priv->type = GTK_WINDOW_TOPLEVEL;
1086 priv->focus_widget = NULL;
1087 priv->default_widget = NULL;
1088 priv->configure_request_count = 0;
1089 priv->resizable = TRUE;
1090 priv->configure_notify_received = FALSE;
1091 priv->position = GTK_WIN_POS_NONE;
1092 priv->need_default_size = TRUE;
1093 priv->need_default_position = TRUE;
1094 priv->modal = FALSE;
1095 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1096 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1097 priv->decorated = TRUE;
1098 priv->mnemonic_modifier = GDK_MOD1_MASK;
1099 priv->screen = gdk_screen_get_default ();
1101 priv->accept_focus = TRUE;
1102 priv->focus_on_map = TRUE;
1103 priv->deletable = TRUE;
1104 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1105 priv->opacity = 1.0;
1106 priv->startup_id = NULL;
1107 priv->has_resize_grip = TRUE;
1108 priv->mnemonics_visible = TRUE;
1110 g_object_ref_sink (window);
1111 priv->has_user_ref_count = TRUE;
1112 toplevel_list = g_slist_prepend (toplevel_list, window);
1115 g_signal_connect (priv->screen, "composited-changed",
1116 G_CALLBACK (gtk_window_on_composited_changed), window);
1118 #ifdef GDK_WINDOWING_X11
1119 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1120 "notify::gtk-application-prefer-dark-theme",
1121 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1126 gtk_window_set_property (GObject *object,
1128 const GValue *value,
1131 GtkWindow *window = GTK_WINDOW (object);
1132 GtkWindowPrivate *priv = window->priv;
1137 priv->type = g_value_get_enum (value);
1140 gtk_window_set_title (window, g_value_get_string (value));
1143 gtk_window_set_role (window, g_value_get_string (value));
1145 case PROP_STARTUP_ID:
1146 gtk_window_set_startup_id (window, g_value_get_string (value));
1148 case PROP_RESIZABLE:
1149 gtk_window_set_resizable (window, g_value_get_boolean (value));
1152 gtk_window_set_modal (window, g_value_get_boolean (value));
1155 gtk_window_set_position (window, g_value_get_enum (value));
1157 case PROP_DEFAULT_WIDTH:
1158 gtk_window_set_default_size_internal (window,
1159 TRUE, g_value_get_int (value),
1162 case PROP_DEFAULT_HEIGHT:
1163 gtk_window_set_default_size_internal (window,
1165 TRUE, g_value_get_int (value), FALSE);
1167 case PROP_DESTROY_WITH_PARENT:
1168 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1171 gtk_window_set_icon (window,
1172 g_value_get_object (value));
1174 case PROP_ICON_NAME:
1175 gtk_window_set_icon_name (window, g_value_get_string (value));
1178 gtk_window_set_screen (window, g_value_get_object (value));
1180 case PROP_TYPE_HINT:
1181 gtk_window_set_type_hint (window,
1182 g_value_get_enum (value));
1184 case PROP_SKIP_TASKBAR_HINT:
1185 gtk_window_set_skip_taskbar_hint (window,
1186 g_value_get_boolean (value));
1188 case PROP_SKIP_PAGER_HINT:
1189 gtk_window_set_skip_pager_hint (window,
1190 g_value_get_boolean (value));
1192 case PROP_URGENCY_HINT:
1193 gtk_window_set_urgency_hint (window,
1194 g_value_get_boolean (value));
1196 case PROP_ACCEPT_FOCUS:
1197 gtk_window_set_accept_focus (window,
1198 g_value_get_boolean (value));
1200 case PROP_FOCUS_ON_MAP:
1201 gtk_window_set_focus_on_map (window,
1202 g_value_get_boolean (value));
1204 case PROP_DECORATED:
1205 gtk_window_set_decorated (window, g_value_get_boolean (value));
1207 case PROP_DELETABLE:
1208 gtk_window_set_deletable (window, g_value_get_boolean (value));
1211 gtk_window_set_gravity (window, g_value_get_enum (value));
1213 case PROP_TRANSIENT_FOR:
1214 gtk_window_set_transient_for (window, g_value_get_object (value));
1217 gtk_window_set_opacity (window, g_value_get_double (value));
1219 case PROP_HAS_RESIZE_GRIP:
1220 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1222 case PROP_APPLICATION:
1223 gtk_window_set_application (window, g_value_get_object (value));
1225 case PROP_MNEMONICS_VISIBLE:
1226 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1229 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1235 gtk_window_get_property (GObject *object,
1240 GtkWindow *window = GTK_WINDOW (object);
1241 GtkWindowPrivate *priv = window->priv;
1245 GtkWindowGeometryInfo *info;
1247 g_value_set_enum (value, priv->type);
1250 g_value_set_string (value, priv->wm_role);
1253 g_value_set_string (value, priv->title);
1255 case PROP_RESIZABLE:
1256 g_value_set_boolean (value, priv->resizable);
1259 g_value_set_boolean (value, priv->modal);
1262 g_value_set_enum (value, priv->position);
1264 case PROP_DEFAULT_WIDTH:
1265 info = gtk_window_get_geometry_info (window, FALSE);
1267 g_value_set_int (value, -1);
1269 g_value_set_int (value, info->default_width);
1271 case PROP_DEFAULT_HEIGHT:
1272 info = gtk_window_get_geometry_info (window, FALSE);
1274 g_value_set_int (value, -1);
1276 g_value_set_int (value, info->default_height);
1278 case PROP_DESTROY_WITH_PARENT:
1279 g_value_set_boolean (value, priv->destroy_with_parent);
1282 g_value_set_object (value, gtk_window_get_icon (window));
1284 case PROP_ICON_NAME:
1285 g_value_set_string (value, gtk_window_get_icon_name (window));
1288 g_value_set_object (value, priv->screen);
1290 case PROP_IS_ACTIVE:
1291 g_value_set_boolean (value, priv->is_active);
1293 case PROP_HAS_TOPLEVEL_FOCUS:
1294 g_value_set_boolean (value, priv->has_toplevel_focus);
1296 case PROP_TYPE_HINT:
1297 g_value_set_enum (value, priv->type_hint);
1299 case PROP_SKIP_TASKBAR_HINT:
1300 g_value_set_boolean (value,
1301 gtk_window_get_skip_taskbar_hint (window));
1303 case PROP_SKIP_PAGER_HINT:
1304 g_value_set_boolean (value,
1305 gtk_window_get_skip_pager_hint (window));
1307 case PROP_URGENCY_HINT:
1308 g_value_set_boolean (value,
1309 gtk_window_get_urgency_hint (window));
1311 case PROP_ACCEPT_FOCUS:
1312 g_value_set_boolean (value,
1313 gtk_window_get_accept_focus (window));
1315 case PROP_FOCUS_ON_MAP:
1316 g_value_set_boolean (value,
1317 gtk_window_get_focus_on_map (window));
1319 case PROP_DECORATED:
1320 g_value_set_boolean (value, gtk_window_get_decorated (window));
1322 case PROP_DELETABLE:
1323 g_value_set_boolean (value, gtk_window_get_deletable (window));
1326 g_value_set_enum (value, gtk_window_get_gravity (window));
1328 case PROP_TRANSIENT_FOR:
1329 g_value_set_object (value, gtk_window_get_transient_for (window));
1332 g_value_set_double (value, gtk_window_get_opacity (window));
1334 case PROP_HAS_RESIZE_GRIP:
1335 g_value_set_boolean (value, priv->has_resize_grip);
1337 case PROP_RESIZE_GRIP_VISIBLE:
1338 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1340 case PROP_APPLICATION:
1341 g_value_set_object (value, gtk_window_get_application (window));
1343 case PROP_MNEMONICS_VISIBLE:
1344 g_value_set_boolean (value, priv->mnemonics_visible);
1347 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1353 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1355 parent_buildable_iface = g_type_interface_peek_parent (iface);
1356 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1357 iface->parser_finished = gtk_window_buildable_parser_finished;
1358 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1359 iface->custom_finished = gtk_window_buildable_custom_finished;
1363 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1364 GtkBuilder *builder,
1366 const GValue *value)
1368 GtkWindow *window = GTK_WINDOW (buildable);
1369 GtkWindowPrivate *priv = window->priv;
1371 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1372 priv->builder_visible = TRUE;
1374 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1378 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1379 GtkBuilder *builder)
1381 GtkWindow *window = GTK_WINDOW (buildable);
1382 GtkWindowPrivate *priv = window->priv;
1386 if (priv->builder_visible)
1387 gtk_widget_show (GTK_WIDGET (buildable));
1389 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1390 for (l = accels; l; l = l->next)
1392 object = gtk_builder_get_object (builder, l->data);
1395 g_warning ("Unknown accel group %s specified in window %s",
1396 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1399 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1400 GTK_ACCEL_GROUP (object));
1404 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1406 parent_buildable_iface->parser_finished (buildable, builder);
1412 } GSListSubParserData;
1415 window_start_element (GMarkupParseContext *context,
1416 const gchar *element_name,
1417 const gchar **names,
1418 const gchar **values,
1423 GSListSubParserData *data = (GSListSubParserData*)user_data;
1425 if (strcmp (element_name, "group") == 0)
1427 for (i = 0; names[i]; i++)
1429 if (strcmp (names[i], "name") == 0)
1430 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1433 else if (strcmp (element_name, "accel-groups") == 0)
1436 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1441 static const GMarkupParser window_parser =
1443 window_start_element
1447 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1448 GtkBuilder *builder,
1450 const gchar *tagname,
1451 GMarkupParser *parser,
1454 GSListSubParserData *parser_data;
1456 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1457 tagname, parser, data))
1460 if (strcmp (tagname, "accel-groups") == 0)
1462 parser_data = g_slice_new0 (GSListSubParserData);
1463 parser_data->items = NULL;
1464 parser_data->object = G_OBJECT (buildable);
1466 *parser = window_parser;
1467 *data = parser_data;
1475 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1476 GtkBuilder *builder,
1478 const gchar *tagname,
1481 GSListSubParserData *data;
1483 parent_buildable_iface->custom_finished (buildable, builder, child,
1484 tagname, user_data);
1486 if (strcmp (tagname, "accel-groups") != 0)
1489 data = (GSListSubParserData*)user_data;
1491 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1492 data->items, (GDestroyNotify) g_slist_free);
1494 g_slice_free (GSListSubParserData, data);
1499 * @type: type of window
1501 * Creates a new #GtkWindow, which is a toplevel window that can
1502 * contain other widgets. Nearly always, the type of the window should
1503 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1504 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1505 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1506 * dialogs, though in some other toolkits dialogs are called "popups".
1507 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1508 * On X11, popup windows are not controlled by the <link
1509 * linkend="gtk-X11-arch">window manager</link>.
1511 * If you simply want an undecorated window (no window borders), use
1512 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1514 * Return value: a new #GtkWindow.
1517 gtk_window_new (GtkWindowType type)
1519 GtkWindowPrivate *priv;
1522 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1524 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1525 priv = window->priv;
1529 return GTK_WIDGET (window);
1533 * gtk_window_set_title:
1534 * @window: a #GtkWindow
1535 * @title: title of the window
1537 * Sets the title of the #GtkWindow. The title of a window will be
1538 * displayed in its title bar; on the X Window System, the title bar
1539 * is rendered by the <link linkend="gtk-X11-arch">window
1540 * manager</link>, so exactly how the title appears to users may vary
1541 * according to a user's exact configuration. The title should help a
1542 * user distinguish this window from other windows they may have
1543 * open. A good title might include the application name and current
1544 * document filename, for example.
1548 gtk_window_set_title (GtkWindow *window,
1551 GtkWindowPrivate *priv;
1555 g_return_if_fail (GTK_IS_WINDOW (window));
1557 priv = window->priv;
1558 widget = GTK_WIDGET (window);
1560 new_title = g_strdup (title);
1561 g_free (priv->title);
1562 priv->title = new_title;
1564 if (gtk_widget_get_realized (widget))
1566 gdk_window_set_title (gtk_widget_get_window (widget),
1570 g_object_notify (G_OBJECT (window), "title");
1574 * gtk_window_get_title:
1575 * @window: a #GtkWindow
1577 * Retrieves the title of the window. See gtk_window_set_title().
1579 * Return value: the title of the window, or %NULL if none has
1580 * been set explicitely. The returned string is owned by the widget
1581 * and must not be modified or freed.
1583 G_CONST_RETURN gchar *
1584 gtk_window_get_title (GtkWindow *window)
1586 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1588 return window->priv->title;
1592 * gtk_window_set_wmclass:
1593 * @window: a #GtkWindow
1594 * @wmclass_name: window name hint
1595 * @wmclass_class: window class hint
1597 * Don't use this function. It sets the X Window System "class" and
1598 * "name" hints for a window. According to the ICCCM, you should
1599 * always set these to the same value for all windows in an
1600 * application, and GTK+ sets them to that value by default, so calling
1601 * this function is sort of pointless. However, you may want to call
1602 * gtk_window_set_role() on each window in your application, for the
1603 * benefit of the session manager. Setting the role allows the window
1604 * manager to restore window positions when loading a saved session.
1608 gtk_window_set_wmclass (GtkWindow *window,
1609 const gchar *wmclass_name,
1610 const gchar *wmclass_class)
1612 GtkWindowPrivate *priv;
1614 g_return_if_fail (GTK_IS_WINDOW (window));
1616 priv = window->priv;
1618 g_free (priv->wmclass_name);
1619 priv->wmclass_name = g_strdup (wmclass_name);
1621 g_free (priv->wmclass_class);
1622 priv->wmclass_class = g_strdup (wmclass_class);
1624 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1625 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1629 * gtk_window_set_role:
1630 * @window: a #GtkWindow
1631 * @role: unique identifier for the window to be used when restoring a session
1633 * This function is only useful on X11, not with other GTK+ targets.
1635 * In combination with the window title, the window role allows a
1636 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1637 * same" window when an application is restarted. So for example you
1638 * might set the "toolbox" role on your app's toolbox window, so that
1639 * when the user restarts their session, the window manager can put
1640 * the toolbox back in the same place.
1642 * If a window already has a unique title, you don't need to set the
1643 * role, since the WM can use the title to identify the window when
1644 * restoring the session.
1648 gtk_window_set_role (GtkWindow *window,
1651 GtkWindowPrivate *priv;
1654 g_return_if_fail (GTK_IS_WINDOW (window));
1656 priv = window->priv;
1658 new_role = g_strdup (role);
1659 g_free (priv->wm_role);
1660 priv->wm_role = new_role;
1662 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1663 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1666 g_object_notify (G_OBJECT (window), "role");
1670 * gtk_window_set_startup_id:
1671 * @window: a #GtkWindow
1672 * @startup_id: a string with startup-notification identifier
1674 * Startup notification identifiers are used by desktop environment to
1675 * track application startup, to provide user feedback and other
1676 * features. This function changes the corresponding property on the
1677 * underlying GdkWindow. Normally, startup identifier is managed
1678 * automatically and you should only use this function in special cases
1679 * like transferring focus from other processes. You should use this
1680 * function before calling gtk_window_present() or any equivalent
1681 * function generating a window map event.
1683 * This function is only useful on X11, not with other GTK+ targets.
1688 gtk_window_set_startup_id (GtkWindow *window,
1689 const gchar *startup_id)
1691 GtkWindowPrivate *priv;
1694 g_return_if_fail (GTK_IS_WINDOW (window));
1696 priv = window->priv;
1697 widget = GTK_WIDGET (window);
1699 g_free (priv->startup_id);
1700 priv->startup_id = g_strdup (startup_id);
1702 if (gtk_widget_get_realized (widget))
1704 GdkWindow *gdk_window;
1705 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1707 gdk_window = gtk_widget_get_window (widget);
1709 #ifdef GDK_WINDOWING_X11
1710 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1711 gdk_x11_window_set_user_time (gdk_window, timestamp);
1714 /* Here we differentiate real and "fake" startup notification IDs,
1715 * constructed on purpose just to pass interaction timestamp
1717 if (startup_id_is_fake (priv->startup_id))
1718 gtk_window_present_with_time (window, timestamp);
1721 gdk_window_set_startup_id (gdk_window,
1724 /* If window is mapped, terminate the startup-notification too */
1725 if (gtk_widget_get_mapped (widget) &&
1726 !disable_startup_notification)
1727 gdk_notify_startup_complete_with_id (priv->startup_id);
1731 g_object_notify (G_OBJECT (window), "startup-id");
1735 * gtk_window_get_role:
1736 * @window: a #GtkWindow
1738 * Returns the role of the window. See gtk_window_set_role() for
1739 * further explanation.
1741 * Return value: the role of the window if set, or %NULL. The
1742 * returned is owned by the widget and must not be modified
1745 G_CONST_RETURN gchar *
1746 gtk_window_get_role (GtkWindow *window)
1748 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1750 return window->priv->wm_role;
1754 * gtk_window_set_focus:
1755 * @window: a #GtkWindow
1756 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1757 * any focus widget for the toplevel window.
1759 * If @focus is not the current focus widget, and is focusable, sets
1760 * it as the focus widget for the window. If @focus is %NULL, unsets
1761 * the focus widget for this window. To set the focus to a particular
1762 * widget in the toplevel, it is usually more convenient to use
1763 * gtk_widget_grab_focus() instead of this function.
1766 gtk_window_set_focus (GtkWindow *window,
1769 GtkWindowPrivate *priv;
1772 g_return_if_fail (GTK_IS_WINDOW (window));
1774 priv = window->priv;
1778 g_return_if_fail (GTK_IS_WIDGET (focus));
1779 g_return_if_fail (gtk_widget_get_can_focus (focus));
1783 gtk_widget_grab_focus (focus);
1786 /* Clear the existing focus chain, so that when we focus into
1787 * the window again, we start at the beginnning.
1789 GtkWidget *widget = priv->focus_widget;
1792 while ((parent = gtk_widget_get_parent (widget)))
1795 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1799 _gtk_window_internal_set_focus (window, NULL);
1804 _gtk_window_internal_set_focus (GtkWindow *window,
1807 GtkWindowPrivate *priv;
1809 g_return_if_fail (GTK_IS_WINDOW (window));
1811 priv = window->priv;
1813 if ((priv->focus_widget != focus) ||
1814 (focus && !gtk_widget_has_focus (focus)))
1815 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1819 * gtk_window_set_default:
1820 * @window: a #GtkWindow
1821 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1822 * default widget for the toplevel.
1824 * The default widget is the widget that's activated when the user
1825 * presses Enter in a dialog (for example). This function sets or
1826 * unsets the default widget for a #GtkWindow about. When setting
1827 * (rather than unsetting) the default widget it's generally easier to
1828 * call gtk_widget_grab_focus() on the widget. Before making a widget
1829 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1830 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1833 gtk_window_set_default (GtkWindow *window,
1834 GtkWidget *default_widget)
1836 GtkWindowPrivate *priv;
1838 g_return_if_fail (GTK_IS_WINDOW (window));
1840 priv = window->priv;
1843 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1845 if (priv->default_widget != default_widget)
1847 GtkWidget *old_default_widget = NULL;
1850 g_object_ref (default_widget);
1852 if (priv->default_widget)
1854 old_default_widget = priv->default_widget;
1856 if (priv->focus_widget != priv->default_widget ||
1857 !gtk_widget_get_receives_default (priv->default_widget))
1858 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1860 gtk_widget_queue_draw (priv->default_widget);
1863 priv->default_widget = default_widget;
1865 if (priv->default_widget)
1867 if (priv->focus_widget == NULL ||
1868 !gtk_widget_get_receives_default (priv->focus_widget))
1869 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1871 gtk_widget_queue_draw (priv->default_widget);
1874 if (old_default_widget)
1875 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1879 g_object_notify (G_OBJECT (default_widget), "has-default");
1880 g_object_unref (default_widget);
1886 * gtk_window_get_default_widget:
1887 * @window: a #GtkWindow
1889 * Returns the default widget for @window. See gtk_window_set_default()
1892 * Returns: (transfer none): the default widget, or %NULL if there is none.
1897 gtk_window_get_default_widget (GtkWindow *window)
1899 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1901 return window->priv->default_widget;
1905 handle_keys_changed (gpointer data)
1907 GtkWindow *window = GTK_WINDOW (data);
1908 GtkWindowPrivate *priv = window->priv;
1910 if (priv->keys_changed_handler)
1912 g_source_remove (priv->keys_changed_handler);
1913 priv->keys_changed_handler = 0;
1916 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1922 gtk_window_notify_keys_changed (GtkWindow *window)
1924 GtkWindowPrivate *priv = window->priv;
1926 if (!priv->keys_changed_handler)
1927 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1931 * gtk_window_add_accel_group:
1932 * @window: window to attach accelerator group to
1933 * @accel_group: a #GtkAccelGroup
1935 * Associate @accel_group with @window, such that calling
1936 * gtk_accel_groups_activate() on @window will activate accelerators
1940 gtk_window_add_accel_group (GtkWindow *window,
1941 GtkAccelGroup *accel_group)
1943 g_return_if_fail (GTK_IS_WINDOW (window));
1944 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1946 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1947 g_signal_connect_object (accel_group, "accel-changed",
1948 G_CALLBACK (gtk_window_notify_keys_changed),
1949 window, G_CONNECT_SWAPPED);
1950 gtk_window_notify_keys_changed (window);
1954 * gtk_window_remove_accel_group:
1955 * @window: a #GtkWindow
1956 * @accel_group: a #GtkAccelGroup
1958 * Reverses the effects of gtk_window_add_accel_group().
1961 gtk_window_remove_accel_group (GtkWindow *window,
1962 GtkAccelGroup *accel_group)
1964 g_return_if_fail (GTK_IS_WINDOW (window));
1965 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1967 g_signal_handlers_disconnect_by_func (accel_group,
1968 gtk_window_notify_keys_changed,
1970 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1971 gtk_window_notify_keys_changed (window);
1974 static GtkMnemonicHash *
1975 gtk_window_get_mnemonic_hash (GtkWindow *window,
1978 GtkWindowPrivate *private = window->priv;
1980 if (!private->mnemonic_hash && create)
1981 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1983 return private->mnemonic_hash;
1987 * gtk_window_add_mnemonic:
1988 * @window: a #GtkWindow
1989 * @keyval: the mnemonic
1990 * @target: the widget that gets activated by the mnemonic
1992 * Adds a mnemonic to this window.
1995 gtk_window_add_mnemonic (GtkWindow *window,
1999 g_return_if_fail (GTK_IS_WINDOW (window));
2000 g_return_if_fail (GTK_IS_WIDGET (target));
2002 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2004 gtk_window_notify_keys_changed (window);
2008 * gtk_window_remove_mnemonic:
2009 * @window: a #GtkWindow
2010 * @keyval: the mnemonic
2011 * @target: the widget that gets activated by the mnemonic
2013 * Removes a mnemonic from this window.
2016 gtk_window_remove_mnemonic (GtkWindow *window,
2020 g_return_if_fail (GTK_IS_WINDOW (window));
2021 g_return_if_fail (GTK_IS_WIDGET (target));
2023 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2025 gtk_window_notify_keys_changed (window);
2029 * gtk_window_mnemonic_activate:
2030 * @window: a #GtkWindow
2031 * @keyval: the mnemonic
2032 * @modifier: the modifiers
2033 * @returns: %TRUE if the activation is done.
2035 * Activates the targets associated with the mnemonic.
2038 gtk_window_mnemonic_activate (GtkWindow *window,
2040 GdkModifierType modifier)
2042 GtkWindowPrivate *priv;
2044 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2046 priv = window->priv;
2048 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2050 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2052 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2059 * gtk_window_set_mnemonic_modifier:
2060 * @window: a #GtkWindow
2061 * @modifier: the modifier mask used to activate
2062 * mnemonics on this window.
2064 * Sets the mnemonic modifier for this window.
2067 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2068 GdkModifierType modifier)
2070 GtkWindowPrivate *priv;
2072 g_return_if_fail (GTK_IS_WINDOW (window));
2073 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2075 priv = window->priv;
2077 priv->mnemonic_modifier = modifier;
2078 gtk_window_notify_keys_changed (window);
2082 * gtk_window_get_mnemonic_modifier:
2083 * @window: a #GtkWindow
2085 * Returns the mnemonic modifier for this window. See
2086 * gtk_window_set_mnemonic_modifier().
2088 * Return value: the modifier mask used to activate
2089 * mnemonics on this window.
2092 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2094 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2096 return window->priv->mnemonic_modifier;
2100 * gtk_window_set_position:
2101 * @window: a #GtkWindow.
2102 * @position: a position constraint.
2104 * Sets a position constraint for this window. If the old or new
2105 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2106 * the window to be repositioned to satisfy the new constraint.
2109 gtk_window_set_position (GtkWindow *window,
2110 GtkWindowPosition position)
2112 GtkWindowPrivate *priv;
2114 g_return_if_fail (GTK_IS_WINDOW (window));
2116 priv = window->priv;
2118 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2119 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2121 GtkWindowGeometryInfo *info;
2123 info = gtk_window_get_geometry_info (window, TRUE);
2125 /* this flag causes us to re-request the CENTER_ALWAYS
2126 * constraint in gtk_window_move_resize(), see
2127 * comment in that function.
2129 info->position_constraints_changed = TRUE;
2131 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2134 priv->position = position;
2136 g_object_notify (G_OBJECT (window), "window-position");
2140 * gtk_window_activate_focus:
2141 * @window: a #GtkWindow
2143 * Activates the current focused widget within the window.
2145 * Return value: %TRUE if a widget got activated.
2148 gtk_window_activate_focus (GtkWindow *window)
2150 GtkWindowPrivate *priv;
2152 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2154 priv = window->priv;
2156 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2157 return gtk_widget_activate (priv->focus_widget);
2163 * gtk_window_get_focus:
2164 * @window: a #GtkWindow
2166 * Retrieves the current focused widget within the window.
2167 * Note that this is the widget that would have the focus
2168 * if the toplevel window focused; if the toplevel window
2169 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2170 * not be %TRUE for the widget.
2172 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2175 gtk_window_get_focus (GtkWindow *window)
2177 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2179 return window->priv->focus_widget;
2183 * gtk_window_activate_default:
2184 * @window: a #GtkWindow
2186 * Activates the default widget for the window, unless the current
2187 * focused widget has been configured to receive the default action
2188 * (see gtk_widget_set_receives_default()), in which case the
2189 * focused widget is activated.
2191 * Return value: %TRUE if a widget got activated.
2194 gtk_window_activate_default (GtkWindow *window)
2196 GtkWindowPrivate *priv;
2198 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2200 priv = window->priv;
2202 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2203 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2204 return gtk_widget_activate (priv->default_widget);
2205 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2206 return gtk_widget_activate (priv->focus_widget);
2212 * gtk_window_set_modal:
2213 * @window: a #GtkWindow
2214 * @modal: whether the window is modal
2216 * Sets a window modal or non-modal. Modal windows prevent interaction
2217 * with other windows in the same application. To keep modal dialogs
2218 * on top of main application windows, use
2219 * gtk_window_set_transient_for() to make the dialog transient for the
2220 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2221 * will then disallow lowering the dialog below the parent.
2226 gtk_window_set_modal (GtkWindow *window,
2229 GtkWindowPrivate *priv;
2232 g_return_if_fail (GTK_IS_WINDOW (window));
2234 priv = window->priv;
2236 modal = modal != FALSE;
2237 if (priv->modal == modal)
2240 priv->modal = modal;
2241 widget = GTK_WIDGET (window);
2243 /* adjust desired modality state */
2244 if (gtk_widget_get_realized (widget))
2247 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2249 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2252 if (gtk_widget_get_visible (widget))
2255 gtk_grab_add (widget);
2257 gtk_grab_remove (widget);
2260 g_object_notify (G_OBJECT (window), "modal");
2264 * gtk_window_get_modal:
2265 * @window: a #GtkWindow
2267 * Returns whether the window is modal. See gtk_window_set_modal().
2269 * Return value: %TRUE if the window is set to be modal and
2270 * establishes a grab when shown
2273 gtk_window_get_modal (GtkWindow *window)
2275 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2277 return window->priv->modal;
2281 * gtk_window_list_toplevels:
2283 * Returns a list of all existing toplevel windows. The widgets
2284 * in the list are not individually referenced. If you want
2285 * to iterate through the list and perform actions involving
2286 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2287 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2288 * then unref all the widgets afterwards.
2290 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2293 gtk_window_list_toplevels (void)
2298 for (slist = toplevel_list; slist; slist = slist->next)
2299 list = g_list_prepend (list, slist->data);
2305 gtk_window_dispose (GObject *object)
2307 GtkWindow *window = GTK_WINDOW (object);
2309 gtk_window_set_focus (window, NULL);
2310 gtk_window_set_default (window, NULL);
2312 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2316 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2318 gtk_widget_destroy (GTK_WIDGET (child));
2322 connect_parent_destroyed (GtkWindow *window)
2324 GtkWindowPrivate *priv = window->priv;
2326 if (priv->transient_parent)
2328 g_signal_connect (priv->transient_parent,
2330 G_CALLBACK (parent_destroyed_callback),
2336 disconnect_parent_destroyed (GtkWindow *window)
2338 GtkWindowPrivate *priv = window->priv;
2340 if (priv->transient_parent)
2342 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2343 parent_destroyed_callback,
2349 gtk_window_transient_parent_realized (GtkWidget *parent,
2352 if (gtk_widget_get_realized (window))
2353 gdk_window_set_transient_for (gtk_widget_get_window (window),
2354 gtk_widget_get_window (parent));
2358 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2361 if (gtk_widget_get_realized (window))
2362 gdk_property_delete (gtk_widget_get_window (window),
2363 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2367 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2371 gtk_window_set_screen (window, parent->priv->screen);
2375 gtk_window_unset_transient_for (GtkWindow *window)
2377 GtkWindowPrivate *priv = window->priv;
2379 if (priv->transient_parent)
2381 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2382 gtk_window_transient_parent_realized,
2384 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2385 gtk_window_transient_parent_unrealized,
2387 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2388 gtk_window_transient_parent_screen_changed,
2390 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2391 gtk_widget_destroyed,
2392 &priv->transient_parent);
2394 if (priv->destroy_with_parent)
2395 disconnect_parent_destroyed (window);
2397 priv->transient_parent = NULL;
2399 if (priv->transient_parent_group)
2401 priv->transient_parent_group = FALSE;
2402 gtk_window_group_remove_window (priv->group,
2409 * gtk_window_set_transient_for:
2410 * @window: a #GtkWindow
2411 * @parent: (allow-none): parent window, or %NULL
2413 * Dialog windows should be set transient for the main application
2414 * window they were spawned from. This allows <link
2415 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2416 * dialog on top of the main window, or center the dialog over the
2417 * main window. gtk_dialog_new_with_buttons() and other convenience
2418 * functions in GTK+ will sometimes call
2419 * gtk_window_set_transient_for() on your behalf.
2421 * Passing %NULL for @parent unsets the current transient window.
2423 * On Windows, this function puts the child window on top of the parent,
2424 * much as the window manager would have done on X.
2427 gtk_window_set_transient_for (GtkWindow *window,
2430 GtkWindowPrivate *priv;
2432 g_return_if_fail (GTK_IS_WINDOW (window));
2433 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2434 g_return_if_fail (window != parent);
2436 priv = window->priv;
2438 if (priv->transient_parent)
2440 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2441 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2442 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2443 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2444 GTK_WIDGET (window));
2446 gtk_window_unset_transient_for (window);
2449 priv->transient_parent = parent;
2453 g_signal_connect (parent, "destroy",
2454 G_CALLBACK (gtk_widget_destroyed),
2455 &priv->transient_parent);
2456 g_signal_connect (parent, "realize",
2457 G_CALLBACK (gtk_window_transient_parent_realized),
2459 g_signal_connect (parent, "unrealize",
2460 G_CALLBACK (gtk_window_transient_parent_unrealized),
2462 g_signal_connect (parent, "notify::screen",
2463 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2466 gtk_window_set_screen (window, parent->priv->screen);
2468 if (priv->destroy_with_parent)
2469 connect_parent_destroyed (window);
2471 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2472 gtk_widget_get_realized (GTK_WIDGET (parent)))
2473 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2474 GTK_WIDGET (window));
2476 if (parent->priv->group)
2478 gtk_window_group_add_window (parent->priv->group, window);
2479 priv->transient_parent_group = TRUE;
2485 * gtk_window_get_transient_for:
2486 * @window: a #GtkWindow
2488 * Fetches the transient parent for this window. See
2489 * gtk_window_set_transient_for().
2491 * Return value: (transfer none): the transient parent for this window, or %NULL
2492 * if no transient parent has been set.
2495 gtk_window_get_transient_for (GtkWindow *window)
2497 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2499 return window->priv->transient_parent;
2503 * gtk_window_set_opacity:
2504 * @window: a #GtkWindow
2505 * @opacity: desired opacity, between 0 and 1
2507 * Request the windowing system to make @window partially transparent,
2508 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2509 * of the opacity parameter are clamped to the [0,1] range.) On X11
2510 * this has any effect only on X screens with a compositing manager
2511 * running. See gtk_widget_is_composited(). On Windows it should work
2514 * Note that setting a window's opacity after the window has been
2515 * shown causes it to flicker once on Windows.
2520 gtk_window_set_opacity (GtkWindow *window,
2523 GtkWindowPrivate *priv;
2525 g_return_if_fail (GTK_IS_WINDOW (window));
2527 priv = window->priv;
2531 else if (opacity > 1.0)
2534 priv->opacity_set = TRUE;
2535 priv->opacity = opacity;
2537 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2538 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2543 * gtk_window_get_opacity:
2544 * @window: a #GtkWindow
2546 * Fetches the requested opacity for this window. See
2547 * gtk_window_set_opacity().
2549 * Return value: the requested opacity for this window.
2554 gtk_window_get_opacity (GtkWindow *window)
2556 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2558 return window->priv->opacity;
2562 * gtk_window_get_application:
2563 * @window: a #GtkWindow
2565 * Gets the #GtkApplication associated with the window (if any).
2567 * Return value: (transfer none): a #GtkApplication, or %NULL
2572 gtk_window_get_application (GtkWindow *window)
2574 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2576 return window->priv->application;
2580 gtk_window_release_application (GtkWindow *window)
2582 if (window->priv->application)
2584 GtkApplication *application;
2586 /* steal reference into temp variable */
2587 application = window->priv->application;
2588 window->priv->application = NULL;
2590 gtk_application_remove_window (application, window);
2591 g_object_unref (application);
2596 * gtk_window_set_application:
2597 * @window: a #GtkWindow
2598 * @application: (allow-none): a #GtkApplication, or %NULL
2600 * Sets or unsets the #GtkApplication associated with the window.
2602 * The application will be kept alive for at least as long as the window
2608 gtk_window_set_application (GtkWindow *window,
2609 GtkApplication *application)
2611 GtkWindowPrivate *priv;
2613 g_return_if_fail (GTK_IS_WINDOW (window));
2615 priv = window->priv;
2616 if (priv->application != application)
2618 gtk_window_release_application (window);
2620 priv->application = application;
2622 if (priv->application != NULL)
2624 g_object_ref (priv->application);
2626 gtk_application_add_window (priv->application, window);
2629 g_object_notify (G_OBJECT (window), "application");
2634 * gtk_window_set_type_hint:
2635 * @window: a #GtkWindow
2636 * @hint: the window type
2638 * By setting the type hint for the window, you allow the window
2639 * manager to decorate and handle the window in a way which is
2640 * suitable to the function of the window in your application.
2642 * This function should be called before the window becomes visible.
2644 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2645 * will sometimes call gtk_window_set_type_hint() on your behalf.
2649 gtk_window_set_type_hint (GtkWindow *window,
2650 GdkWindowTypeHint hint)
2652 GtkWindowPrivate *priv;
2654 g_return_if_fail (GTK_IS_WINDOW (window));
2655 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2657 priv = window->priv;
2659 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2660 priv->type_hint = hint;
2662 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2664 priv->reset_type_hint = TRUE;
2665 priv->gdk_type_hint = hint;
2669 * gtk_window_get_type_hint:
2670 * @window: a #GtkWindow
2672 * Gets the type hint for this window. See gtk_window_set_type_hint().
2674 * Return value: the type hint for @window.
2677 gtk_window_get_type_hint (GtkWindow *window)
2679 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2681 return window->priv->gdk_type_hint;
2685 * gtk_window_set_skip_taskbar_hint:
2686 * @window: a #GtkWindow
2687 * @setting: %TRUE to keep this window from appearing in the task bar
2689 * Windows may set a hint asking the desktop environment not to display
2690 * the window in the task bar. This function sets this hint.
2695 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2698 GtkWindowPrivate *priv;
2700 g_return_if_fail (GTK_IS_WINDOW (window));
2702 priv = window->priv;
2704 setting = setting != FALSE;
2706 if (priv->skips_taskbar != setting)
2708 priv->skips_taskbar = setting;
2709 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2710 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2711 priv->skips_taskbar);
2712 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2717 * gtk_window_get_skip_taskbar_hint:
2718 * @window: a #GtkWindow
2720 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2722 * Return value: %TRUE if window shouldn't be in taskbar
2727 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2729 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2731 return window->priv->skips_taskbar;
2735 * gtk_window_set_skip_pager_hint:
2736 * @window: a #GtkWindow
2737 * @setting: %TRUE to keep this window from appearing in the pager
2739 * Windows may set a hint asking the desktop environment not to display
2740 * the window in the pager. This function sets this hint.
2741 * (A "pager" is any desktop navigation tool such as a workspace
2742 * switcher that displays a thumbnail representation of the windows
2748 gtk_window_set_skip_pager_hint (GtkWindow *window,
2751 GtkWindowPrivate *priv;
2753 g_return_if_fail (GTK_IS_WINDOW (window));
2755 priv = window->priv;
2757 setting = setting != FALSE;
2759 if (priv->skips_pager != setting)
2761 priv->skips_pager = setting;
2762 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2763 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2765 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2770 * gtk_window_get_skip_pager_hint:
2771 * @window: a #GtkWindow
2773 * Gets the value set by gtk_window_set_skip_pager_hint().
2775 * Return value: %TRUE if window shouldn't be in pager
2780 gtk_window_get_skip_pager_hint (GtkWindow *window)
2782 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2784 return window->priv->skips_pager;
2788 * gtk_window_set_urgency_hint:
2789 * @window: a #GtkWindow
2790 * @setting: %TRUE to mark this window as urgent
2792 * Windows may set a hint asking the desktop environment to draw
2793 * the users attention to the window. This function sets this hint.
2798 gtk_window_set_urgency_hint (GtkWindow *window,
2801 GtkWindowPrivate *priv;
2803 g_return_if_fail (GTK_IS_WINDOW (window));
2805 priv = window->priv;
2807 setting = setting != FALSE;
2809 if (priv->urgent != setting)
2811 priv->urgent = setting;
2812 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2813 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2815 g_object_notify (G_OBJECT (window), "urgency-hint");
2820 * gtk_window_get_urgency_hint:
2821 * @window: a #GtkWindow
2823 * Gets the value set by gtk_window_set_urgency_hint()
2825 * Return value: %TRUE if window is urgent
2830 gtk_window_get_urgency_hint (GtkWindow *window)
2832 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2834 return window->priv->urgent;
2838 * gtk_window_set_accept_focus:
2839 * @window: a #GtkWindow
2840 * @setting: %TRUE to let this window receive input focus
2842 * Windows may set a hint asking the desktop environment not to receive
2843 * the input focus. This function sets this hint.
2848 gtk_window_set_accept_focus (GtkWindow *window,
2851 GtkWindowPrivate *priv;
2853 g_return_if_fail (GTK_IS_WINDOW (window));
2855 priv = window->priv;
2857 setting = setting != FALSE;
2859 if (priv->accept_focus != setting)
2861 priv->accept_focus = setting;
2862 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2863 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2864 priv->accept_focus);
2865 g_object_notify (G_OBJECT (window), "accept-focus");
2870 * gtk_window_get_accept_focus:
2871 * @window: a #GtkWindow
2873 * Gets the value set by gtk_window_set_accept_focus().
2875 * Return value: %TRUE if window should receive the input focus
2880 gtk_window_get_accept_focus (GtkWindow *window)
2882 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2884 return window->priv->accept_focus;
2888 * gtk_window_set_focus_on_map:
2889 * @window: a #GtkWindow
2890 * @setting: %TRUE to let this window receive input focus on map
2892 * Windows may set a hint asking the desktop environment not to receive
2893 * the input focus when the window is mapped. This function sets this
2899 gtk_window_set_focus_on_map (GtkWindow *window,
2902 GtkWindowPrivate *priv;
2904 g_return_if_fail (GTK_IS_WINDOW (window));
2906 priv = window->priv;
2908 setting = setting != FALSE;
2910 if (priv->focus_on_map != setting)
2912 priv->focus_on_map = setting;
2913 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2914 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2915 priv->focus_on_map);
2916 g_object_notify (G_OBJECT (window), "focus-on-map");
2921 * gtk_window_get_focus_on_map:
2922 * @window: a #GtkWindow
2924 * Gets the value set by gtk_window_set_focus_on_map().
2926 * Return value: %TRUE if window should receive the input focus when
2932 gtk_window_get_focus_on_map (GtkWindow *window)
2934 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2936 return window->priv->focus_on_map;
2940 * gtk_window_set_destroy_with_parent:
2941 * @window: a #GtkWindow
2942 * @setting: whether to destroy @window with its transient parent
2944 * If @setting is %TRUE, then destroying the transient parent of @window
2945 * will also destroy @window itself. This is useful for dialogs that
2946 * shouldn't persist beyond the lifetime of the main window they're
2947 * associated with, for example.
2950 gtk_window_set_destroy_with_parent (GtkWindow *window,
2953 GtkWindowPrivate *priv;
2955 g_return_if_fail (GTK_IS_WINDOW (window));
2957 priv = window->priv;
2959 if (priv->destroy_with_parent == (setting != FALSE))
2962 if (priv->destroy_with_parent)
2964 disconnect_parent_destroyed (window);
2968 connect_parent_destroyed (window);
2971 priv->destroy_with_parent = setting;
2973 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2977 * gtk_window_get_destroy_with_parent:
2978 * @window: a #GtkWindow
2980 * Returns whether the window will be destroyed with its transient parent. See
2981 * gtk_window_set_destroy_with_parent ().
2983 * Return value: %TRUE if the window will be destroyed with its transient parent.
2986 gtk_window_get_destroy_with_parent (GtkWindow *window)
2988 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2990 return window->priv->destroy_with_parent;
2993 static GtkWindowGeometryInfo*
2994 gtk_window_get_geometry_info (GtkWindow *window,
2997 GtkWindowPrivate *priv = window->priv;
2998 GtkWindowGeometryInfo *info;
3000 info = priv->geometry_info;
3001 if (!info && create)
3003 info = g_new0 (GtkWindowGeometryInfo, 1);
3005 info->default_width = -1;
3006 info->default_height = -1;
3007 info->resize_width = -1;
3008 info->resize_height = -1;
3009 info->initial_x = 0;
3010 info->initial_y = 0;
3011 info->initial_pos_set = FALSE;
3012 info->default_is_geometry = FALSE;
3013 info->position_constraints_changed = FALSE;
3014 info->last.configure_request.x = 0;
3015 info->last.configure_request.y = 0;
3016 info->last.configure_request.width = -1;
3017 info->last.configure_request.height = -1;
3018 info->widget = NULL;
3020 priv->geometry_info = info;
3027 * gtk_window_set_geometry_hints:
3028 * @window: a #GtkWindow
3029 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3030 * @geometry: (allow-none): struct containing geometry information or %NULL
3031 * @geom_mask: mask indicating which struct fields should be paid attention to
3033 * This function sets up hints about how a window can be resized by
3034 * the user. You can set a minimum and maximum size; allowed resize
3035 * increments (e.g. for xterm, you can only resize by the size of a
3036 * character); aspect ratios; and more. See the #GdkGeometry struct.
3040 gtk_window_set_geometry_hints (GtkWindow *window,
3041 GtkWidget *geometry_widget,
3042 GdkGeometry *geometry,
3043 GdkWindowHints geom_mask)
3045 GtkWindowGeometryInfo *info;
3047 g_return_if_fail (GTK_IS_WINDOW (window));
3048 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3050 info = gtk_window_get_geometry_info (window, TRUE);
3053 g_signal_handlers_disconnect_by_func (info->widget,
3054 gtk_widget_destroyed,
3057 info->widget = geometry_widget;
3059 g_signal_connect (geometry_widget, "destroy",
3060 G_CALLBACK (gtk_widget_destroyed),
3064 info->geometry = *geometry;
3066 /* We store gravity in priv->gravity not in the hints. */
3067 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3069 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3071 gtk_window_set_gravity (window, geometry->win_gravity);
3074 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3078 * gtk_window_set_decorated:
3079 * @window: a #GtkWindow
3080 * @setting: %TRUE to decorate the window
3082 * By default, windows are decorated with a title bar, resize
3083 * controls, etc. Some <link linkend="gtk-X11-arch">window
3084 * managers</link> allow GTK+ to disable these decorations, creating a
3085 * borderless window. If you set the decorated property to %FALSE
3086 * using this function, GTK+ will do its best to convince the window
3087 * manager not to decorate the window. Depending on the system, this
3088 * function may not have any effect when called on a window that is
3089 * already visible, so you should call it before calling gtk_widget_show().
3091 * On Windows, this function always works, since there's no window manager
3096 gtk_window_set_decorated (GtkWindow *window,
3099 GtkWindowPrivate *priv;
3100 GdkWindow *gdk_window;
3102 g_return_if_fail (GTK_IS_WINDOW (window));
3104 priv = window->priv;
3106 setting = setting != FALSE;
3108 if (setting == priv->decorated)
3111 priv->decorated = setting;
3113 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3116 if (priv->decorated)
3117 gdk_window_set_decorations (gdk_window,
3120 gdk_window_set_decorations (gdk_window,
3124 g_object_notify (G_OBJECT (window), "decorated");
3128 * gtk_window_get_decorated:
3129 * @window: a #GtkWindow
3131 * Returns whether the window has been set to have decorations
3132 * such as a title bar via gtk_window_set_decorated().
3134 * Return value: %TRUE if the window has been set to have decorations
3137 gtk_window_get_decorated (GtkWindow *window)
3139 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3141 return window->priv->decorated;
3145 * gtk_window_set_deletable:
3146 * @window: a #GtkWindow
3147 * @setting: %TRUE to decorate the window as deletable
3149 * By default, windows have a close button in the window frame. Some
3150 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3151 * disable this button. If you set the deletable property to %FALSE
3152 * using this function, GTK+ will do its best to convince the window
3153 * manager not to show a close button. Depending on the system, this
3154 * function may not have any effect when called on a window that is
3155 * already visible, so you should call it before calling gtk_window_show().
3157 * On Windows, this function always works, since there's no window manager
3163 gtk_window_set_deletable (GtkWindow *window,
3166 GtkWindowPrivate *priv;
3167 GdkWindow *gdk_window;
3169 g_return_if_fail (GTK_IS_WINDOW (window));
3171 priv = window->priv;
3173 setting = setting != FALSE;
3175 if (setting == priv->deletable)
3178 priv->deletable = setting;
3180 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3183 if (priv->deletable)
3184 gdk_window_set_functions (gdk_window,
3187 gdk_window_set_functions (gdk_window,
3188 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3191 g_object_notify (G_OBJECT (window), "deletable");
3195 * gtk_window_get_deletable:
3196 * @window: a #GtkWindow
3198 * Returns whether the window has been set to have a close button
3199 * via gtk_window_set_deletable().
3201 * Return value: %TRUE if the window has been set to have a close button
3206 gtk_window_get_deletable (GtkWindow *window)
3208 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3210 return window->priv->deletable;
3213 static GtkWindowIconInfo*
3214 get_icon_info (GtkWindow *window)
3216 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3220 free_icon_info (GtkWindowIconInfo *info)
3222 g_free (info->icon_name);
3223 g_slice_free (GtkWindowIconInfo, info);
3227 static GtkWindowIconInfo*
3228 ensure_icon_info (GtkWindow *window)
3230 GtkWindowIconInfo *info;
3232 info = get_icon_info (window);
3236 info = g_slice_new0 (GtkWindowIconInfo);
3237 g_object_set_qdata_full (G_OBJECT (window),
3238 quark_gtk_window_icon_info,
3240 (GDestroyNotify)free_icon_info);
3247 icon_list_from_theme (GtkWidget *widget,
3252 GtkIconTheme *icon_theme;
3257 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3259 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3262 for (i = 0; sizes[i]; i++)
3265 * We need an EWMH extension to handle scalable icons
3266 * by passing their name to the WM. For now just use a
3270 icon = gtk_icon_theme_load_icon (icon_theme, name,
3273 icon = gtk_icon_theme_load_icon (icon_theme, name,
3276 list = g_list_append (list, icon);
3286 gtk_window_realize_icon (GtkWindow *window)
3288 GtkWindowPrivate *priv = window->priv;
3290 GtkWindowIconInfo *info;
3291 GdkWindow *gdk_window;
3294 widget = GTK_WIDGET (window);
3295 gdk_window = gtk_widget_get_window (widget);
3297 g_return_if_fail (gdk_window != NULL);
3299 /* no point setting an icon on override-redirect */
3300 if (priv->type == GTK_WINDOW_POPUP)
3305 info = ensure_icon_info (window);
3310 info->using_default_icon = FALSE;
3311 info->using_parent_icon = FALSE;
3312 info->using_themed_icon = FALSE;
3314 icon_list = info->icon_list;
3316 /* Look up themed icon */
3317 if (icon_list == NULL && info->icon_name)
3319 icon_list = icon_list_from_theme (widget, info->icon_name);
3321 info->using_themed_icon = TRUE;
3324 /* Inherit from transient parent */
3325 if (icon_list == NULL && priv->transient_parent)
3327 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3329 info->using_parent_icon = TRUE;
3332 /* Inherit from default */
3333 if (icon_list == NULL)
3335 icon_list = default_icon_list;
3337 info->using_default_icon = TRUE;
3340 /* Look up themed icon */
3341 if (icon_list == NULL && default_icon_name)
3343 icon_list = icon_list_from_theme (widget, default_icon_name);
3344 info->using_default_icon = TRUE;
3345 info->using_themed_icon = TRUE;
3348 info->realized = TRUE;
3350 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3352 if (info->using_themed_icon)
3354 GtkIconTheme *icon_theme;
3356 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3357 g_list_free (icon_list);
3359 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3360 g_signal_connect (icon_theme, "changed",
3361 G_CALLBACK (update_themed_icon), window);
3366 gtk_window_unrealize_icon (GtkWindow *window)
3368 GtkWindowIconInfo *info;
3370 info = get_icon_info (window);
3375 if (info->using_themed_icon)
3377 GtkIconTheme *icon_theme;
3379 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3381 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3384 /* We don't clear the properties on the window, just figure the
3385 * window is going away.
3388 info->realized = FALSE;
3393 * gtk_window_set_icon_list:
3394 * @window: a #GtkWindow
3395 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3397 * Sets up the icon representing a #GtkWindow. The icon is used when
3398 * the window is minimized (also known as iconified). Some window
3399 * managers or desktop environments may also place it in the window
3400 * frame, or display it in other contexts.
3402 * gtk_window_set_icon_list() allows you to pass in the same icon in
3403 * several hand-drawn sizes. The list should contain the natural sizes
3404 * your icon is available in; that is, don't scale the image before
3405 * passing it to GTK+. Scaling is postponed until the last minute,
3406 * when the desired final size is known, to allow best quality.
3408 * By passing several sizes, you may improve the final image quality
3409 * of the icon, by reducing or eliminating automatic image scaling.
3411 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3412 * larger images (64x64, 128x128) if you have them.
3414 * See also gtk_window_set_default_icon_list() to set the icon
3415 * for all windows in your application in one go.
3417 * Note that transient windows (those who have been set transient for another
3418 * window using gtk_window_set_transient_for()) will inherit their
3419 * icon from their transient parent. So there's no need to explicitly
3420 * set the icon on transient windows.
3423 gtk_window_set_icon_list (GtkWindow *window,
3426 GtkWindowIconInfo *info;
3428 g_return_if_fail (GTK_IS_WINDOW (window));
3430 info = ensure_icon_info (window);
3432 if (info->icon_list == list) /* check for NULL mostly */
3435 g_list_foreach (list,
3436 (GFunc) g_object_ref, NULL);
3438 g_list_foreach (info->icon_list,
3439 (GFunc) g_object_unref, NULL);
3441 g_list_free (info->icon_list);
3443 info->icon_list = g_list_copy (list);
3445 g_object_notify (G_OBJECT (window), "icon");
3447 gtk_window_unrealize_icon (window);
3449 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3450 gtk_window_realize_icon (window);
3452 /* We could try to update our transient children, but I don't think
3453 * it's really worth it. If we did it, the best way would probably
3454 * be to have children connect to notify::icon-list
3459 * gtk_window_get_icon_list:
3460 * @window: a #GtkWindow
3462 * Retrieves the list of icons set by gtk_window_set_icon_list().
3463 * The list is copied, but the reference count on each
3464 * member won't be incremented.
3466 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3469 gtk_window_get_icon_list (GtkWindow *window)
3471 GtkWindowIconInfo *info;
3473 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3475 info = get_icon_info (window);
3478 return g_list_copy (info->icon_list);
3484 * gtk_window_set_icon:
3485 * @window: a #GtkWindow
3486 * @icon: (allow-none): icon image, or %NULL
3488 * Sets up the icon representing a #GtkWindow. This icon is used when
3489 * the window is minimized (also known as iconified). Some window
3490 * managers or desktop environments may also place it in the window
3491 * frame, or display it in other contexts.
3493 * The icon should be provided in whatever size it was naturally
3494 * drawn; that is, don't scale the image before passing it to
3495 * GTK+. Scaling is postponed until the last minute, when the desired
3496 * final size is known, to allow best quality.
3498 * If you have your icon hand-drawn in multiple sizes, use
3499 * gtk_window_set_icon_list(). Then the best size will be used.
3501 * This function is equivalent to calling gtk_window_set_icon_list()
3502 * with a 1-element list.
3504 * See also gtk_window_set_default_icon_list() to set the icon
3505 * for all windows in your application in one go.
3508 gtk_window_set_icon (GtkWindow *window,
3513 g_return_if_fail (GTK_IS_WINDOW (window));
3514 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3519 list = g_list_append (list, icon);
3521 gtk_window_set_icon_list (window, list);
3527 update_themed_icon (GtkIconTheme *icon_theme,
3530 g_object_notify (G_OBJECT (window), "icon");
3532 gtk_window_unrealize_icon (window);
3534 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3535 gtk_window_realize_icon (window);
3539 * gtk_window_set_icon_name:
3540 * @window: a #GtkWindow
3541 * @name: (allow-none): the name of the themed icon
3543 * Sets the icon for the window from a named themed icon. See
3544 * the docs for #GtkIconTheme for more details.
3546 * Note that this has nothing to do with the WM_ICON_NAME
3547 * property which is mentioned in the ICCCM.
3552 gtk_window_set_icon_name (GtkWindow *window,
3555 GtkWindowIconInfo *info;
3558 g_return_if_fail (GTK_IS_WINDOW (window));
3560 info = ensure_icon_info (window);
3562 if (g_strcmp0 (info->icon_name, name) == 0)
3565 tmp = info->icon_name;
3566 info->icon_name = g_strdup (name);
3569 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3570 g_list_free (info->icon_list);
3571 info->icon_list = NULL;
3573 update_themed_icon (NULL, window);
3575 g_object_notify (G_OBJECT (window), "icon-name");
3579 * gtk_window_get_icon_name:
3580 * @window: a #GtkWindow
3582 * Returns the name of the themed icon for the window,
3583 * see gtk_window_set_icon_name().
3585 * Returns: the icon name or %NULL if the window has
3591 gtk_window_get_icon_name (GtkWindow *window)
3593 GtkWindowIconInfo *info;
3595 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3597 info = ensure_icon_info (window);
3599 return info->icon_name;
3603 * gtk_window_get_icon:
3604 * @window: a #GtkWindow
3606 * Gets the value set by gtk_window_set_icon() (or if you've
3607 * called gtk_window_set_icon_list(), gets the first icon in
3610 * Return value: (transfer none): icon for window
3613 gtk_window_get_icon (GtkWindow *window)
3615 GtkWindowIconInfo *info;
3617 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3619 info = get_icon_info (window);
3620 if (info && info->icon_list)
3621 return GDK_PIXBUF (info->icon_list->data);
3626 /* Load pixbuf, printing warning on failure if error == NULL
3629 load_pixbuf_verbosely (const char *filename,
3632 GError *local_err = NULL;
3635 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3643 g_warning ("Error loading icon from file '%s':\n\t%s",
3644 filename, local_err->message);
3645 g_error_free (local_err);
3653 * gtk_window_set_icon_from_file:
3654 * @window: a #GtkWindow
3655 * @filename: (type filename): location of icon file
3656 * @err: (allow-none): location to store error, or %NULL.
3658 * Sets the icon for @window.
3659 * Warns on failure if @err is %NULL.
3661 * This function is equivalent to calling gtk_window_set_icon()
3662 * with a pixbuf created by loading the image from @filename.
3664 * Returns: %TRUE if setting the icon succeeded.
3669 gtk_window_set_icon_from_file (GtkWindow *window,
3670 const gchar *filename,
3673 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3677 gtk_window_set_icon (window, pixbuf);
3678 g_object_unref (pixbuf);
3687 * gtk_window_set_default_icon_list:
3688 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3690 * Sets an icon list to be used as fallback for windows that haven't
3691 * had gtk_window_set_icon_list() called on them to set up a
3692 * window-specific icon list. This function allows you to set up the
3693 * icon for all windows in your app at once.
3695 * See gtk_window_set_icon_list() for more details.
3699 gtk_window_set_default_icon_list (GList *list)
3703 if (list == default_icon_list)
3706 /* Update serial so we don't used cached pixmaps/masks
3708 default_icon_serial++;
3710 g_list_foreach (list,
3711 (GFunc) g_object_ref, NULL);
3713 g_list_foreach (default_icon_list,
3714 (GFunc) g_object_unref, NULL);
3716 g_list_free (default_icon_list);
3718 default_icon_list = g_list_copy (list);
3720 /* Update all toplevels */
3721 toplevels = gtk_window_list_toplevels ();
3722 tmp_list = toplevels;
3723 while (tmp_list != NULL)
3725 GtkWindowIconInfo *info;
3726 GtkWindow *w = tmp_list->data;
3728 info = get_icon_info (w);
3729 if (info && info->using_default_icon)
3731 gtk_window_unrealize_icon (w);
3732 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3733 gtk_window_realize_icon (w);
3736 tmp_list = tmp_list->next;
3738 g_list_free (toplevels);
3742 * gtk_window_set_default_icon:
3745 * Sets an icon to be used as fallback for windows that haven't
3746 * had gtk_window_set_icon() called on them from a pixbuf.
3751 gtk_window_set_default_icon (GdkPixbuf *icon)
3755 g_return_if_fail (GDK_IS_PIXBUF (icon));
3757 list = g_list_prepend (NULL, icon);
3758 gtk_window_set_default_icon_list (list);
3763 * gtk_window_set_default_icon_name:
3764 * @name: the name of the themed icon
3766 * Sets an icon to be used as fallback for windows that haven't
3767 * had gtk_window_set_icon_list() called on them from a named
3768 * themed icon, see gtk_window_set_icon_name().
3773 gtk_window_set_default_icon_name (const gchar *name)
3778 /* Update serial so we don't used cached pixmaps/masks
3780 default_icon_serial++;
3782 g_free (default_icon_name);
3783 default_icon_name = g_strdup (name);
3785 g_list_foreach (default_icon_list,
3786 (GFunc) g_object_unref, NULL);
3788 g_list_free (default_icon_list);
3789 default_icon_list = NULL;
3791 /* Update all toplevels */
3792 toplevels = gtk_window_list_toplevels ();
3793 tmp_list = toplevels;
3794 while (tmp_list != NULL)
3796 GtkWindowIconInfo *info;
3797 GtkWindow *w = tmp_list->data;
3799 info = get_icon_info (w);
3800 if (info && info->using_default_icon && info->using_themed_icon)
3802 gtk_window_unrealize_icon (w);
3803 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3804 gtk_window_realize_icon (w);
3807 tmp_list = tmp_list->next;
3809 g_list_free (toplevels);
3813 * gtk_window_get_default_icon_name:
3815 * Returns the fallback icon name for windows that has been set
3816 * with gtk_window_set_default_icon_name(). The returned
3817 * string is owned by GTK+ and should not be modified. It
3818 * is only valid until the next call to
3819 * gtk_window_set_default_icon_name().
3821 * Returns: the fallback icon name for windows
3826 gtk_window_get_default_icon_name (void)
3828 return default_icon_name;
3832 * gtk_window_set_default_icon_from_file:
3833 * @filename: (type filename): location of icon file
3834 * @err: (allow-none): location to store error, or %NULL.
3836 * Sets an icon to be used as fallback for windows that haven't
3837 * had gtk_window_set_icon_list() called on them from a file
3838 * on disk. Warns on failure if @err is %NULL.
3840 * Returns: %TRUE if setting the icon succeeded.
3845 gtk_window_set_default_icon_from_file (const gchar *filename,
3848 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3852 gtk_window_set_default_icon (pixbuf);
3853 g_object_unref (pixbuf);
3862 * gtk_window_get_default_icon_list:
3864 * Gets the value set by gtk_window_set_default_icon_list().
3865 * The list is a copy and should be freed with g_list_free(),
3866 * but the pixbufs in the list have not had their reference count
3869 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3872 gtk_window_get_default_icon_list (void)
3874 return g_list_copy (default_icon_list);
3878 gtk_window_set_default_size_internal (GtkWindow *window,
3879 gboolean change_width,
3881 gboolean change_height,
3883 gboolean is_geometry)
3885 GtkWindowGeometryInfo *info;
3887 g_return_if_fail (change_width == FALSE || width >= -1);
3888 g_return_if_fail (change_height == FALSE || height >= -1);
3890 info = gtk_window_get_geometry_info (window, TRUE);
3892 g_object_freeze_notify (G_OBJECT (window));
3894 info->default_is_geometry = is_geometry != FALSE;
3904 info->default_width = width;
3906 g_object_notify (G_OBJECT (window), "default-width");
3917 info->default_height = height;
3919 g_object_notify (G_OBJECT (window), "default-height");
3922 g_object_thaw_notify (G_OBJECT (window));
3924 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3928 * gtk_window_set_default_size:
3929 * @window: a #GtkWindow
3930 * @width: width in pixels, or -1 to unset the default width
3931 * @height: height in pixels, or -1 to unset the default height
3933 * Sets the default size of a window. If the window's "natural" size
3934 * (its size request) is larger than the default, the default will be
3935 * ignored. More generally, if the default size does not obey the
3936 * geometry hints for the window (gtk_window_set_geometry_hints() can
3937 * be used to set these explicitly), the default size will be clamped
3938 * to the nearest permitted size.
3940 * Unlike gtk_widget_set_size_request(), which sets a size request for
3941 * a widget and thus would keep users from shrinking the window, this
3942 * function only sets the initial size, just as if the user had
3943 * resized the window themselves. Users can still shrink the window
3944 * again as they normally would. Setting a default size of -1 means to
3945 * use the "natural" default size (the size request of the window).
3947 * For more control over a window's initial size and how resizing works,
3948 * investigate gtk_window_set_geometry_hints().
3950 * For some uses, gtk_window_resize() is a more appropriate function.
3951 * gtk_window_resize() changes the current size of the window, rather
3952 * than the size to be used on initial display. gtk_window_resize() always
3953 * affects the window itself, not the geometry widget.
3955 * The default size of a window only affects the first time a window is
3956 * shown; if a window is hidden and re-shown, it will remember the size
3957 * it had prior to hiding, rather than using the default size.
3959 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3960 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3963 gtk_window_set_default_size (GtkWindow *window,
3967 g_return_if_fail (GTK_IS_WINDOW (window));
3968 g_return_if_fail (width >= -1);
3969 g_return_if_fail (height >= -1);
3971 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3975 * gtk_window_set_default_geometry:
3976 * @window: a #GtkWindow
3977 * @width: width in resize increments, or -1 to unset the default width
3978 * @height: height in resize increments, or -1 to unset the default height
3980 * Like gtk_window_set_default_size(), but @width and @height are interpreted
3981 * in terms of the base size and increment set with
3982 * gtk_window_set_geometry_hints.
3987 gtk_window_set_default_geometry (GtkWindow *window,
3991 g_return_if_fail (GTK_IS_WINDOW (window));
3992 g_return_if_fail (width >= -1);
3993 g_return_if_fail (height >= -1);
3995 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
3999 * gtk_window_get_default_size:
4000 * @window: a #GtkWindow
4001 * @width: (out) (allow-none): location to store the default width, or %NULL
4002 * @height: (out) (allow-none): location to store the default height, or %NULL
4004 * Gets the default size of the window. A value of -1 for the width or
4005 * height indicates that a default size has not been explicitly set
4006 * for that dimension, so the "natural" size of the window will be
4011 gtk_window_get_default_size (GtkWindow *window,
4015 GtkWindowGeometryInfo *info;
4017 g_return_if_fail (GTK_IS_WINDOW (window));
4019 info = gtk_window_get_geometry_info (window, FALSE);
4022 *width = info ? info->default_width : -1;
4025 *height = info ? info->default_height : -1;
4029 * gtk_window_resize:
4030 * @window: a #GtkWindow
4031 * @width: width in pixels to resize the window to
4032 * @height: height in pixels to resize the window to
4034 * Resizes the window as if the user had done so, obeying geometry
4035 * constraints. The default geometry constraint is that windows may
4036 * not be smaller than their size request; to override this
4037 * constraint, call gtk_widget_set_size_request() to set the window's
4038 * request to a smaller value.
4040 * If gtk_window_resize() is called before showing a window for the
4041 * first time, it overrides any default size set with
4042 * gtk_window_set_default_size().
4044 * Windows may not be resized smaller than 1 by 1 pixels.
4048 gtk_window_resize (GtkWindow *window,
4052 GtkWindowGeometryInfo *info;
4054 g_return_if_fail (GTK_IS_WINDOW (window));
4055 g_return_if_fail (width > 0);
4056 g_return_if_fail (height > 0);
4058 info = gtk_window_get_geometry_info (window, TRUE);
4060 info->resize_width = width;
4061 info->resize_height = height;
4062 info->resize_is_geometry = FALSE;
4064 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4068 * gtk_window_resize_to_geometry:
4069 * @window: a #GtkWindow
4070 * @width: width in resize increments to resize the window to
4071 * @height: height in resize increments to resize the window to
4073 * Like gtk_window_resize(), but @width and @height are interpreted
4074 * in terms of the base size and increment set with
4075 * gtk_window_set_geometry_hints.
4080 gtk_window_resize_to_geometry (GtkWindow *window,
4084 GtkWindowGeometryInfo *info;
4086 g_return_if_fail (GTK_IS_WINDOW (window));
4087 g_return_if_fail (width > 0);
4088 g_return_if_fail (height > 0);
4090 info = gtk_window_get_geometry_info (window, TRUE);
4092 info->resize_width = width;
4093 info->resize_height = height;
4094 info->resize_is_geometry = TRUE;
4096 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4100 * gtk_window_get_size:
4101 * @window: a #GtkWindow
4102 * @width: (out) (allow-none): return location for width, or %NULL
4103 * @height: (out) (allow-none): return location for height, or %NULL
4105 * Obtains the current size of @window. If @window is not onscreen,
4106 * it returns the size GTK+ will suggest to the <link
4107 * linkend="gtk-X11-arch">window manager</link> for the initial window
4108 * size (but this is not reliably the same as the size the window
4109 * manager will actually select). The size obtained by
4110 * gtk_window_get_size() is the last size received in a
4111 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4112 * rather than querying the X server for the size. As a result, if you
4113 * call gtk_window_resize() then immediately call
4114 * gtk_window_get_size(), the size won't have taken effect yet. After
4115 * the window manager processes the resize request, GTK+ receives
4116 * notification that the size has changed via a configure event, and
4117 * the size of the window gets updated.
4119 * Note 1: Nearly any use of this function creates a race condition,
4120 * because the size of the window may change between the time that you
4121 * get the size and the time that you perform some action assuming
4122 * that size is the current size. To avoid race conditions, connect to
4123 * "configure-event" on the window and adjust your size-dependent
4124 * state to match the size delivered in the #GdkEventConfigure.
4126 * Note 2: The returned size does <emphasis>not</emphasis> include the
4127 * size of the window manager decorations (aka the window frame or
4128 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4129 * method of determining their size.
4131 * Note 3: If you are getting a window size in order to position
4132 * the window onscreen, there may be a better way. The preferred
4133 * way is to simply set the window's semantic type with
4134 * gtk_window_set_type_hint(), which allows the window manager to
4135 * e.g. center dialogs. Also, if you set the transient parent of
4136 * dialogs with gtk_window_set_transient_for() window managers
4137 * will often center the dialog over its parent window. It's
4138 * much preferred to let the window manager handle these
4139 * things rather than doing it yourself, because all apps will
4140 * behave consistently and according to user prefs if the window
4141 * manager handles it. Also, the window manager can take the size
4142 * of the window decorations/border into account, while your
4143 * application cannot.
4145 * In any case, if you insist on application-specified window
4146 * positioning, there's <emphasis>still</emphasis> a better way than
4147 * doing it yourself - gtk_window_set_position() will frequently
4148 * handle the details for you.
4152 gtk_window_get_size (GtkWindow *window,
4158 g_return_if_fail (GTK_IS_WINDOW (window));
4160 if (width == NULL && height == NULL)
4163 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4165 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4166 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4170 GdkRectangle configure_request;
4172 gtk_window_compute_configure_request (window,
4176 w = configure_request.width;
4177 h = configure_request.height;
4188 * @window: a #GtkWindow
4189 * @x: X coordinate to move window to
4190 * @y: Y coordinate to move window to
4192 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4193 * @window to the given position. Window managers are free to ignore
4194 * this; most window managers ignore requests for initial window
4195 * positions (instead using a user-defined placement algorithm) and
4196 * honor requests after the window has already been shown.
4198 * Note: the position is the position of the gravity-determined
4199 * reference point for the window. The gravity determines two things:
4200 * first, the location of the reference point in root window
4201 * coordinates; and second, which point on the window is positioned at
4202 * the reference point.
4204 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4205 * point is simply the @x, @y supplied to gtk_window_move(). The
4206 * top-left corner of the window decorations (aka window frame or
4207 * border) will be placed at @x, @y. Therefore, to position a window
4208 * at the top left of the screen, you want to use the default gravity
4209 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4211 * To position a window at the bottom right corner of the screen, you
4212 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4213 * point is at @x + the window width and @y + the window height, and
4214 * the bottom-right corner of the window border will be placed at that
4215 * reference point. So, to place a window in the bottom right corner
4216 * you would first set gravity to south east, then write:
4217 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4218 * gdk_screen_height () - window_height)</literal> (note that this
4219 * example does not take multi-head scenarios into account).
4221 * The Extended Window Manager Hints specification at <ulink
4222 * url="http://www.freedesktop.org/Standards/wm-spec">
4223 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4224 * nice table of gravities in the "implementation notes" section.
4226 * The gtk_window_get_position() documentation may also be relevant.
4229 gtk_window_move (GtkWindow *window,
4233 GtkWindowGeometryInfo *info;
4236 g_return_if_fail (GTK_IS_WINDOW (window));
4238 widget = GTK_WIDGET (window);
4240 info = gtk_window_get_geometry_info (window, TRUE);
4242 if (gtk_widget_get_mapped (widget))
4244 GtkAllocation allocation;
4246 gtk_widget_get_allocation (widget, &allocation);
4248 /* we have now sent a request with this position
4249 * with currently-active constraints, so toggle flag.
4251 info->position_constraints_changed = FALSE;
4253 /* we only constrain if mapped - if not mapped,
4254 * then gtk_window_compute_configure_request()
4255 * will apply the constraints later, and we
4256 * don't want to lose information about
4257 * what position the user set before then.
4258 * i.e. if you do a move() then turn off POS_CENTER
4259 * then show the window, your move() will work.
4261 gtk_window_constrain_position (window,
4262 allocation.width, allocation.height,
4265 /* Note that this request doesn't go through our standard request
4266 * framework, e.g. doesn't increment configure_request_count,
4267 * doesn't set info->last, etc.; that's because
4268 * we don't save the info needed to arrive at this same request
4271 * To gtk_window_move_resize(), this will end up looking exactly
4272 * the same as the position being changed by the window
4275 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4279 /* Save this position to apply on mapping */
4280 info->initial_x = x;
4281 info->initial_y = y;
4282 info->initial_pos_set = TRUE;
4287 * gtk_window_get_position:
4288 * @window: a #GtkWindow
4289 * @root_x: (out) (allow-none): eturn location for X coordinate of
4290 * gravity-determined reference point, or %NULL
4291 * @root_y: (out) (allow-none): return location for Y coordinate of
4292 * gravity-determined reference point, or %NULL
4294 * This function returns the position you need to pass to
4295 * gtk_window_move() to keep @window in its current position.
4296 * This means that the meaning of the returned value varies with
4297 * window gravity. See gtk_window_move() for more details.
4299 * If you haven't changed the window gravity, its gravity will be
4300 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4301 * gets the position of the top-left corner of the window manager
4302 * frame for the window. gtk_window_move() sets the position of this
4303 * same top-left corner.
4305 * gtk_window_get_position() is not 100% reliable because the X Window System
4306 * does not specify a way to obtain the geometry of the
4307 * decorations placed on a window by the window manager.
4308 * Thus GTK+ is using a "best guess" that works with most
4311 * Moreover, nearly all window managers are historically broken with
4312 * respect to their handling of window gravity. So moving a window to
4313 * its current position as returned by gtk_window_get_position() tends
4314 * to result in moving the window slightly. Window managers are
4315 * slowly getting better over time.
4317 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4318 * frame is not relevant, and thus gtk_window_get_position() will
4319 * always produce accurate results. However you can't use static
4320 * gravity to do things like place a window in a corner of the screen,
4321 * because static gravity ignores the window manager decorations.
4323 * If you are saving and restoring your application's window
4324 * positions, you should know that it's impossible for applications to
4325 * do this without getting it somewhat wrong because applications do
4326 * not have sufficient knowledge of window manager state. The Correct
4327 * Mechanism is to support the session management protocol (see the
4328 * "GnomeClient" object in the GNOME libraries for example) and allow
4329 * the window manager to save your window sizes and positions.
4334 gtk_window_get_position (GtkWindow *window,
4338 GtkWindowPrivate *priv;
4340 GdkWindow *gdk_window;
4342 g_return_if_fail (GTK_IS_WINDOW (window));
4344 priv = window->priv;
4345 widget = GTK_WIDGET (window);
4346 gdk_window = gtk_widget_get_window (widget);
4348 if (priv->gravity == GDK_GRAVITY_STATIC)
4350 if (gtk_widget_get_mapped (widget))
4352 /* This does a server round-trip, which is sort of wrong;
4353 * but a server round-trip is inevitable for
4354 * gdk_window_get_frame_extents() in the usual
4355 * NorthWestGravity case below, so not sure what else to
4356 * do. We should likely be consistent about whether we get
4357 * the client-side info or the server-side info.
4359 gdk_window_get_origin (gdk_window, root_x, root_y);
4363 GdkRectangle configure_request;
4365 gtk_window_compute_configure_request (window,
4369 *root_x = configure_request.x;
4370 *root_y = configure_request.y;
4375 GdkRectangle frame_extents;
4380 if (gtk_widget_get_mapped (widget))
4382 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4383 x = frame_extents.x;
4384 y = frame_extents.y;
4385 gtk_window_get_size (window, &w, &h);
4389 /* We just say the frame has 0 size on all sides.
4390 * Not sure what else to do.
4392 gtk_window_compute_configure_request (window,
4395 x = frame_extents.x;
4396 y = frame_extents.y;
4397 w = frame_extents.width;
4398 h = frame_extents.height;
4401 switch (priv->gravity)
4403 case GDK_GRAVITY_NORTH:
4404 case GDK_GRAVITY_CENTER:
4405 case GDK_GRAVITY_SOUTH:
4406 /* Find center of frame. */
4407 x += frame_extents.width / 2;
4408 /* Center client window on that point. */
4412 case GDK_GRAVITY_SOUTH_EAST:
4413 case GDK_GRAVITY_EAST:
4414 case GDK_GRAVITY_NORTH_EAST:
4415 /* Find right edge of frame */
4416 x += frame_extents.width;
4417 /* Align left edge of client at that point. */
4424 switch (priv->gravity)
4426 case GDK_GRAVITY_WEST:
4427 case GDK_GRAVITY_CENTER:
4428 case GDK_GRAVITY_EAST:
4429 /* Find center of frame. */
4430 y += frame_extents.height / 2;
4431 /* Center client window there. */
4434 case GDK_GRAVITY_SOUTH_WEST:
4435 case GDK_GRAVITY_SOUTH:
4436 case GDK_GRAVITY_SOUTH_EAST:
4437 /* Find south edge of frame */
4438 y += frame_extents.height;
4439 /* Place bottom edge of client there */
4454 * gtk_window_reshow_with_initial_size:
4455 * @window: a #GtkWindow
4457 * Hides @window, then reshows it, resetting the
4458 * default size and position of the window. Used
4459 * by GUI builders only.
4462 gtk_window_reshow_with_initial_size (GtkWindow *window)
4466 g_return_if_fail (GTK_IS_WINDOW (window));
4468 widget = GTK_WIDGET (window);
4470 gtk_widget_hide (widget);
4471 gtk_widget_unrealize (widget);
4472 gtk_widget_show (widget);
4476 gtk_window_destroy (GtkWidget *widget)
4478 GtkWindow *window = GTK_WINDOW (widget);
4479 GtkWindowPrivate *priv = window->priv;
4481 gtk_window_release_application (window);
4483 toplevel_list = g_slist_remove (toplevel_list, window);
4485 if (priv->transient_parent)
4486 gtk_window_set_transient_for (window, NULL);
4488 /* frees the icons */
4489 gtk_window_set_icon_list (window, NULL);
4491 if (priv->has_user_ref_count)
4493 priv->has_user_ref_count = FALSE;
4494 g_object_unref (window);
4498 gtk_window_group_remove_window (priv->group, window);
4500 gtk_window_free_key_hash (window);
4502 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4506 gtk_window_finalize (GObject *object)
4508 GtkWindow *window = GTK_WINDOW (object);
4509 GtkWindowPrivate *priv = window->priv;
4510 GtkMnemonicHash *mnemonic_hash;
4512 g_free (priv->title);
4513 g_free (priv->wmclass_name);
4514 g_free (priv->wmclass_class);
4515 g_free (priv->wm_role);
4516 gtk_window_release_application (window);
4518 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4520 _gtk_mnemonic_hash_free (mnemonic_hash);
4522 if (priv->geometry_info)
4524 if (priv->geometry_info->widget)
4525 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4526 gtk_widget_destroyed,
4527 &priv->geometry_info->widget);
4528 g_free (priv->geometry_info);
4531 if (priv->keys_changed_handler)
4533 g_source_remove (priv->keys_changed_handler);
4534 priv->keys_changed_handler = 0;
4538 g_signal_handlers_disconnect_by_func (priv->screen,
4539 gtk_window_on_composited_changed, window);
4541 g_free (priv->startup_id);
4543 #ifdef GDK_WINDOWING_X11
4544 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4545 gtk_window_on_theme_variant_changed,
4549 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4553 gtk_window_show (GtkWidget *widget)
4555 GtkWindow *window = GTK_WINDOW (widget);
4556 GtkWindowPrivate *priv = window->priv;
4557 GtkContainer *container = GTK_CONTAINER (window);
4558 gboolean need_resize;
4561 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4563 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4567 _gtk_widget_set_visible_flag (widget, TRUE);
4569 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4570 _gtk_container_set_need_resize (container, FALSE);
4574 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4575 GtkAllocation allocation = { 0, 0 };
4576 GdkRectangle configure_request;
4577 GdkGeometry new_geometry;
4579 gboolean was_realized;
4581 /* We are going to go ahead and perform this configure request
4582 * and then emulate a configure notify by going ahead and
4583 * doing a size allocate. Sort of a synchronous
4584 * mini-copy of gtk_window_move_resize() here.
4586 gtk_window_compute_configure_request (window,
4591 /* We update this because we are going to go ahead
4592 * and gdk_window_resize() below, rather than
4595 info->last.configure_request.width = configure_request.width;
4596 info->last.configure_request.height = configure_request.height;
4598 /* and allocate the window - this is normally done
4599 * in move_resize in response to configure notify
4601 allocation.width = configure_request.width;
4602 allocation.height = configure_request.height;
4603 gtk_widget_size_allocate (widget, &allocation);
4605 /* Then we guarantee we have a realize */
4606 was_realized = FALSE;
4607 if (!gtk_widget_get_realized (widget))
4609 gtk_widget_realize (widget);
4610 was_realized = TRUE;
4613 /* We only send configure request if we didn't just finish
4614 * creating the window; if we just created the window
4615 * then we created it with widget->allocation anyhow.
4618 gdk_window_move_resize (gtk_widget_get_window (widget),
4619 configure_request.x,
4620 configure_request.y,
4621 configure_request.width,
4622 configure_request.height);
4625 gtk_container_check_resize (container);
4627 gtk_widget_map (widget);
4629 /* Try to make sure that we have some focused widget
4631 #ifdef GDK_WINDOWING_X11
4632 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4633 GTK_IS_PLUG (window);
4637 if (!priv->focus_widget && !is_plug)
4638 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4641 gtk_grab_add (widget);
4645 gtk_window_hide (GtkWidget *widget)
4647 GtkWindow *window = GTK_WINDOW (widget);
4648 GtkWindowPrivate *priv = window->priv;
4650 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4652 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4656 _gtk_widget_set_visible_flag (widget, FALSE);
4657 gtk_widget_unmap (widget);
4660 gtk_grab_remove (widget);
4664 gtk_window_map (GtkWidget *widget)
4667 GtkWindow *window = GTK_WINDOW (widget);
4668 GtkWindowPrivate *priv = window->priv;
4669 GdkWindow *toplevel;
4670 GdkWindow *gdk_window;
4671 gboolean auto_mnemonics;
4673 gdk_window = gtk_widget_get_window (widget);
4675 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4677 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4681 gtk_widget_set_mapped (widget, TRUE);
4683 child = gtk_bin_get_child (&(window->bin));
4685 gtk_widget_get_visible (child) &&
4686 !gtk_widget_get_mapped (child))
4687 gtk_widget_map (child);
4689 toplevel = gdk_window;
4691 if (priv->maximize_initially)
4692 gdk_window_maximize (toplevel);
4694 gdk_window_unmaximize (toplevel);
4696 if (priv->stick_initially)
4697 gdk_window_stick (toplevel);
4699 gdk_window_unstick (toplevel);
4701 if (priv->iconify_initially)
4702 gdk_window_iconify (toplevel);
4704 gdk_window_deiconify (toplevel);
4706 if (priv->fullscreen_initially)
4707 gdk_window_fullscreen (toplevel);
4709 gdk_window_unfullscreen (toplevel);
4711 gdk_window_set_keep_above (toplevel, priv->above_initially);
4713 gdk_window_set_keep_below (toplevel, priv->below_initially);
4715 if (priv->type == GTK_WINDOW_TOPLEVEL)
4716 gtk_window_set_theme_variant (window);
4718 /* No longer use the default settings */
4719 priv->need_default_size = FALSE;
4720 priv->need_default_position = FALSE;
4722 if (priv->reset_type_hint)
4724 /* We should only reset the type hint when the application
4725 * used gtk_window_set_type_hint() to change the hint.
4726 * Some applications use X directly to change the properties;
4727 * in that case, we shouldn't overwrite what they did.
4729 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4730 priv->reset_type_hint = FALSE;
4733 gdk_window_show (gdk_window);
4735 if (priv->grip_window)
4736 gdk_window_show (priv->grip_window);
4738 if (!disable_startup_notification)
4740 /* Do we have a custom startup-notification id? */
4741 if (priv->startup_id != NULL)
4743 /* Make sure we have a "real" id */
4744 if (!startup_id_is_fake (priv->startup_id))
4745 gdk_notify_startup_complete_with_id (priv->startup_id);
4747 g_free (priv->startup_id);
4748 priv->startup_id = NULL;
4750 else if (!sent_startup_notification)
4752 sent_startup_notification = TRUE;
4753 gdk_notify_startup_complete ();
4757 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4758 * (as in the case of popup menus), then hide mnemonics initially
4760 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4761 &auto_mnemonics, NULL);
4762 if (auto_mnemonics && !priv->mnemonics_visible_set)
4763 gtk_window_set_mnemonics_visible (window, FALSE);
4767 gtk_window_map_event (GtkWidget *widget,
4770 if (!gtk_widget_get_mapped (widget))
4772 /* we should be be unmapped, but are getting a MapEvent, this may happen
4773 * to toplevel XWindows if mapping was intercepted by a window manager
4774 * and an unmap request occoured while the MapRequestEvent was still
4775 * being handled. we work around this situaiton here by re-requesting
4776 * the window being unmapped. more details can be found in:
4777 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4779 gdk_window_hide (gtk_widget_get_window (widget));
4785 gtk_window_unmap (GtkWidget *widget)
4787 GtkWindow *window = GTK_WINDOW (widget);
4788 GtkWindowPrivate *priv = window->priv;
4790 GtkWindowGeometryInfo *info;
4791 GdkWindow *gdk_window;
4792 GdkWindowState state;
4794 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4796 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
4800 gdk_window = gtk_widget_get_window (widget);
4802 gtk_widget_set_mapped (widget, FALSE);
4803 gdk_window_withdraw (gdk_window);
4805 priv->configure_request_count = 0;
4806 priv->configure_notify_received = FALSE;
4808 /* on unmap, we reset the default positioning of the window,
4809 * so it's placed again, but we don't reset the default
4810 * size of the window, so it's remembered.
4812 priv->need_default_position = TRUE;
4814 info = gtk_window_get_geometry_info (window, FALSE);
4817 info->initial_pos_set = FALSE;
4818 info->position_constraints_changed = FALSE;
4821 state = gdk_window_get_state (gdk_window);
4822 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4823 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4824 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4825 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4826 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4828 child = gtk_bin_get_child (&(window->bin));
4830 gtk_widget_unmap (child);
4834 gtk_window_realize (GtkWidget *widget)
4836 GtkAllocation allocation;
4838 GdkWindow *parent_window;
4839 GdkWindow *gdk_window;
4840 GdkWindowAttr attributes;
4841 gint attributes_mask;
4842 GtkWindowPrivate *priv;
4843 GtkStyleContext *context;
4845 window = GTK_WINDOW (widget);
4846 priv = window->priv;
4848 gtk_widget_get_allocation (widget, &allocation);
4850 if (gtk_widget_get_parent_window (widget))
4852 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
4854 gtk_widget_set_realized (widget, TRUE);
4856 attributes.x = allocation.x;
4857 attributes.y = allocation.y;
4858 attributes.width = allocation.width;
4859 attributes.height = allocation.height;
4860 attributes.window_type = GDK_WINDOW_CHILD;
4862 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
4864 attributes.visual = gtk_widget_get_visual (widget);
4865 attributes.wclass = GDK_INPUT_OUTPUT;
4867 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
4869 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
4870 &attributes, attributes_mask);
4871 gtk_widget_set_window (widget, gdk_window);
4872 gdk_window_set_user_data (gdk_window, widget);
4874 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
4876 gdk_window_enable_synchronized_configure (gdk_window);
4880 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
4882 /* ensure widget tree is properly size allocated */
4883 if (allocation.x == -1 &&
4884 allocation.y == -1 &&
4885 allocation.width == 1 &&
4886 allocation.height == 1)
4888 GtkRequisition requisition;
4892 allocation.width = 200;
4893 allocation.height = 200;
4895 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4896 if (requisition.width || requisition.height)
4898 /* non-empty window */
4899 allocation.width = requisition.width;
4900 allocation.height = requisition.height;
4902 gtk_widget_size_allocate (widget, &allocation);
4904 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4906 g_return_if_fail (!gtk_widget_get_realized (widget));
4909 gtk_widget_set_realized (widget, TRUE);
4913 case GTK_WINDOW_TOPLEVEL:
4914 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4916 case GTK_WINDOW_POPUP:
4917 attributes.window_type = GDK_WINDOW_TEMP;
4920 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4924 attributes.title = priv->title;
4925 attributes.wmclass_name = priv->wmclass_name;
4926 attributes.wmclass_class = priv->wmclass_class;
4927 attributes.wclass = GDK_INPUT_OUTPUT;
4928 attributes.visual = gtk_widget_get_visual (widget);
4930 attributes_mask = 0;
4931 parent_window = gtk_widget_get_root_window (widget);
4933 gtk_widget_get_allocation (widget, &allocation);
4934 attributes.width = allocation.width;
4935 attributes.height = allocation.height;
4936 attributes.event_mask = gtk_widget_get_events (widget);
4937 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4938 GDK_KEY_PRESS_MASK |
4939 GDK_KEY_RELEASE_MASK |
4940 GDK_ENTER_NOTIFY_MASK |
4941 GDK_LEAVE_NOTIFY_MASK |
4942 GDK_FOCUS_CHANGE_MASK |
4943 GDK_STRUCTURE_MASK);
4944 attributes.type_hint = priv->type_hint;
4946 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4947 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4948 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4950 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4951 gtk_widget_set_window (widget, gdk_window);
4953 if (priv->opacity_set)
4954 gdk_window_set_opacity (gdk_window, priv->opacity);
4956 gdk_window_enable_synchronized_configure (gdk_window);
4958 gdk_window_set_user_data (gdk_window, window);
4960 context = gtk_widget_get_style_context (widget);
4961 gtk_style_context_set_background (context, gdk_window);
4964 if (priv->transient_parent &&
4965 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4966 gdk_window_set_transient_for (gdk_window,
4967 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4970 gdk_window_set_role (gdk_window, priv->wm_role);
4972 if (!priv->decorated)
4973 gdk_window_set_decorations (gdk_window, 0);
4975 if (!priv->deletable)
4976 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4978 if (gtk_window_get_skip_pager_hint (window))
4979 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4981 if (gtk_window_get_skip_taskbar_hint (window))
4982 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4984 if (gtk_window_get_accept_focus (window))
4985 gdk_window_set_accept_focus (gdk_window, TRUE);
4987 gdk_window_set_accept_focus (gdk_window, FALSE);
4989 if (gtk_window_get_focus_on_map (window))
4990 gdk_window_set_focus_on_map (gdk_window, TRUE);
4992 gdk_window_set_focus_on_map (gdk_window, FALSE);
4995 gdk_window_set_modal_hint (gdk_window, TRUE);
4997 gdk_window_set_modal_hint (gdk_window, FALSE);
4999 if (priv->startup_id)
5001 #ifdef GDK_WINDOWING_X11
5002 if (GDK_IS_X11_WINDOW (gdk_window))
5004 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5005 if (timestamp != GDK_CURRENT_TIME)
5006 gdk_x11_window_set_user_time (gdk_window, timestamp);
5009 if (!startup_id_is_fake (priv->startup_id))
5010 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5014 gtk_window_realize_icon (window);
5016 if (priv->has_resize_grip)
5017 resize_grip_create_window (window);
5021 gtk_window_unrealize (GtkWidget *widget)
5023 GtkWindow *window = GTK_WINDOW (widget);
5024 GtkWindowPrivate *priv = window->priv;
5025 GtkWindowGeometryInfo *info;
5027 /* On unrealize, we reset the size of the window such
5028 * that we will re-apply the default sizing stuff
5029 * next time we show the window.
5031 * Default positioning is reset on unmap, instead of unrealize.
5033 priv->need_default_size = TRUE;
5034 info = gtk_window_get_geometry_info (window, FALSE);
5037 info->resize_width = -1;
5038 info->resize_height = -1;
5039 info->last.configure_request.x = 0;
5040 info->last.configure_request.y = 0;
5041 info->last.configure_request.width = -1;
5042 info->last.configure_request.height = -1;
5043 /* be sure we reset geom hints on re-realize */
5044 info->last.flags = 0;
5048 gtk_window_unrealize_icon (window);
5050 if (priv->grip_window != NULL)
5051 resize_grip_destroy_window (window);
5053 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5056 static GtkJunctionSides
5057 get_grip_junction (GtkWidget *widget)
5059 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5060 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5062 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5066 get_drag_edge (GtkWidget *widget,
5067 GdkWindowEdge *edge)
5069 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5070 gboolean hresizable;
5071 gboolean vresizable;
5072 GtkTextDirection dir;
5073 GtkWindowGeometryInfo *info;
5078 info = priv->geometry_info;
5081 GdkWindowHints flags = info->last.flags;
5082 GdkGeometry *geometry = &info->last.geometry;
5084 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5086 hresizable = geometry->min_width < geometry->max_width;
5087 vresizable = geometry->min_height < geometry->max_height;
5091 dir = gtk_widget_get_direction (widget);
5093 if (hresizable && vresizable)
5094 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5095 else if (hresizable)
5096 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5097 else if (vresizable)
5098 *edge = GDK_WINDOW_EDGE_SOUTH;
5106 set_grip_cursor (GtkWindow *window)
5108 GtkWidget *widget = GTK_WIDGET (window);
5109 GtkWindowPrivate *priv = window->priv;
5111 if (priv->grip_window == NULL)
5114 if (gtk_widget_is_sensitive (widget))
5117 GdkDisplay *display;
5118 GdkCursorType cursor_type;
5121 cursor_type = GDK_LEFT_PTR;
5123 if (get_drag_edge (widget, &edge))
5127 case GDK_WINDOW_EDGE_EAST:
5128 cursor_type = GDK_RIGHT_SIDE;
5130 case GDK_WINDOW_EDGE_SOUTH_EAST:
5131 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5133 case GDK_WINDOW_EDGE_SOUTH:
5134 cursor_type = GDK_BOTTOM_SIDE;
5136 case GDK_WINDOW_EDGE_SOUTH_WEST:
5137 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5139 case GDK_WINDOW_EDGE_WEST:
5140 cursor_type = GDK_LEFT_SIDE;
5146 display = gtk_widget_get_display (widget);
5147 cursor = gdk_cursor_new_for_display (display, cursor_type);
5148 gdk_window_set_cursor (priv->grip_window, cursor);
5149 g_object_unref (cursor);
5152 gdk_window_set_cursor (priv->grip_window, NULL);
5156 set_grip_shape (GtkWindow *window)
5158 GtkWindowPrivate *priv = window->priv;
5159 cairo_region_t *region;
5160 cairo_surface_t *surface;
5162 double width, height;
5164 if (priv->grip_window == NULL)
5167 width = gdk_window_get_width (priv->grip_window);
5168 height = gdk_window_get_height (priv->grip_window);
5169 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5171 cr = cairo_create (surface);
5172 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5174 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5175 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5177 cairo_move_to (cr, width, 0.0);
5178 cairo_line_to (cr, width, height);
5179 cairo_line_to (cr, 0.0, height);
5183 cairo_move_to (cr, 0.0, 0.0);
5184 cairo_line_to (cr, width, height);
5185 cairo_line_to (cr, 0.0, height);
5187 cairo_close_path (cr);
5190 region = gdk_cairo_region_create_from_surface (surface);
5191 cairo_surface_destroy (surface);
5193 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5194 cairo_region_destroy (region);
5198 set_grip_position (GtkWindow *window)
5200 GtkWindowPrivate *priv = window->priv;
5203 if (priv->grip_window == NULL)
5206 gtk_window_get_resize_grip_area (window, &rect);
5207 gdk_window_raise (priv->grip_window);
5208 gdk_window_move_resize (priv->grip_window,
5210 rect.width, rect.height);
5214 gtk_window_size_allocate (GtkWidget *widget,
5215 GtkAllocation *allocation)
5217 GtkWindow *window = GTK_WINDOW (widget);
5218 GtkAllocation child_allocation;
5222 gtk_widget_set_allocation (widget, allocation);
5224 if (gtk_widget_get_realized (widget))
5226 /* If it's not a toplevel we're embedded, we need to resize the window's
5227 * window and skip the grip.
5229 if (!gtk_widget_is_toplevel (widget))
5231 gdk_window_move_resize (gtk_widget_get_window (widget),
5232 allocation->x, allocation->y,
5233 allocation->width, allocation->height);
5237 update_grip_visibility (window);
5238 set_grip_position (window);
5242 child = gtk_bin_get_child (&(window->bin));
5243 if (child && gtk_widget_get_visible (child))
5245 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5246 child_allocation.x = border_width;
5247 child_allocation.y = border_width;
5248 child_allocation.width =
5249 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5250 child_allocation.height =
5251 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5253 gtk_widget_size_allocate (child, &child_allocation);
5258 gtk_window_configure_event (GtkWidget *widget,
5259 GdkEventConfigure *event)
5261 GtkAllocation allocation;
5262 GtkWindow *window = GTK_WINDOW (widget);
5263 GtkWindowPrivate *priv = window->priv;
5264 gboolean expected_reply = priv->configure_request_count > 0;
5266 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5268 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5269 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5271 gdk_window_configure_finished (gtk_widget_get_window (widget));
5275 /* priv->configure_request_count incremented for each
5276 * configure request, and decremented to a min of 0 for
5277 * each configure notify.
5279 * All it means is that we know we will get at least
5280 * priv->configure_request_count more configure notifies.
5281 * We could get more configure notifies than that; some
5282 * of the configure notifies we get may be unrelated to
5283 * the configure requests. But we will get at least
5284 * priv->configure_request_count notifies.
5287 if (priv->configure_request_count > 0)
5289 priv->configure_request_count -= 1;
5290 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5293 /* As an optimization, we avoid a resize when possible.
5295 * The only times we can avoid a resize are:
5296 * - we know only the position changed, not the size
5297 * - we know we have made more requests and so will get more
5298 * notifies and can wait to resize when we get them
5300 gtk_widget_get_allocation (widget, &allocation);
5301 if (!expected_reply &&
5302 (allocation.width == event->width &&
5303 allocation.height == event->height))
5305 gdk_window_configure_finished (gtk_widget_get_window (widget));
5310 * If we do need to resize, we do that by:
5311 * - filling in widget->allocation with the new size
5312 * - setting configure_notify_received to TRUE
5313 * for use in gtk_window_move_resize()
5314 * - queueing a resize, leading to invocation of
5315 * gtk_window_move_resize() in an idle handler
5319 priv->configure_notify_received = TRUE;
5321 allocation.width = event->width;
5322 allocation.height = event->height;
5323 gtk_widget_set_allocation (widget, &allocation);
5325 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5327 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5333 gtk_window_state_event (GtkWidget *widget,
5334 GdkEventWindowState *event)
5336 update_grip_visibility (GTK_WINDOW (widget));
5342 gtk_window_direction_changed (GtkWidget *widget,
5343 GtkTextDirection prev_dir)
5345 GtkWindow *window = GTK_WINDOW (widget);
5347 set_grip_cursor (window);
5348 set_grip_position (window);
5349 set_grip_shape (window);
5353 gtk_window_state_changed (GtkWidget *widget,
5354 GtkStateType previous_state)
5356 GtkWindow *window = GTK_WINDOW (widget);
5358 update_grip_visibility (window);
5362 gtk_window_style_updated (GtkWidget *widget)
5364 GtkWindow *window = GTK_WINDOW (widget);
5365 GtkWindowPrivate *priv = window->priv;
5368 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5370 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5372 gdk_window_move_resize (priv->grip_window,
5374 rect.width, rect.height);
5376 set_grip_shape (window);
5377 gtk_widget_queue_resize (widget);
5382 resize_grip_create_window (GtkWindow *window)
5385 GtkWindowPrivate *priv;
5386 GdkWindowAttr attributes;
5387 gint attributes_mask;
5390 priv = window->priv;
5391 widget = GTK_WIDGET (window);
5393 g_return_if_fail (gtk_widget_get_realized (widget));
5394 g_return_if_fail (priv->grip_window == NULL);
5396 gtk_window_get_resize_grip_area (window, &rect);
5398 attributes.x = rect.x;
5399 attributes.y = rect.y;
5400 attributes.width = rect.width;
5401 attributes.height = rect.height;
5402 attributes.window_type = GDK_WINDOW_CHILD;
5403 attributes.wclass = GDK_INPUT_OUTPUT;
5404 attributes.event_mask = gtk_widget_get_events (widget) |
5406 GDK_BUTTON_PRESS_MASK;
5408 attributes_mask = GDK_WA_X | GDK_WA_Y;
5410 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5414 gdk_window_set_user_data (priv->grip_window, widget);
5416 gdk_window_raise (priv->grip_window);
5418 set_grip_shape (window);
5419 update_grip_visibility (window);
5423 resize_grip_destroy_window (GtkWindow *window)
5425 GtkWindowPrivate *priv = window->priv;
5427 gdk_window_set_user_data (priv->grip_window, NULL);
5428 gdk_window_destroy (priv->grip_window);
5429 priv->grip_window = NULL;
5430 update_grip_visibility (window);
5434 * gtk_window_set_has_resize_grip:
5435 * @window: a #GtkWindow
5436 * @value: %TRUE to allow a resize grip
5438 * Sets whether @window has a corner resize grip.
5440 * Note that the resize grip is only shown if the window
5441 * is actually resizable and not maximized. Use
5442 * gtk_window_resize_grip_is_visible() to find out if the
5443 * resize grip is currently shown.
5448 gtk_window_set_has_resize_grip (GtkWindow *window,
5451 GtkWidget *widget = GTK_WIDGET (window);
5452 GtkWindowPrivate *priv = window->priv;
5454 value = value != FALSE;
5456 if (value != priv->has_resize_grip)
5458 priv->has_resize_grip = value;
5459 gtk_widget_queue_draw (widget);
5461 if (gtk_widget_get_realized (widget) &&
5462 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5464 if (priv->has_resize_grip && priv->grip_window == NULL)
5465 resize_grip_create_window (window);
5466 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5467 resize_grip_destroy_window (window);
5470 g_object_notify (G_OBJECT (window), "has-resize-grip");
5475 update_grip_visibility (GtkWindow *window)
5477 GtkWindowPrivate *priv = window->priv;
5480 val = gtk_window_resize_grip_is_visible (window);
5482 if (priv->grip_window != NULL)
5486 gdk_window_show (priv->grip_window);
5487 set_grip_cursor (window);
5491 gdk_window_hide (priv->grip_window);
5495 if (priv->resize_grip_visible != val)
5497 priv->resize_grip_visible = val;
5499 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5504 * gtk_window_resize_grip_is_visible:
5505 * @window: a #GtkWindow
5507 * Determines whether a resize grip is visible for the specified window.
5509 * Returns: %TRUE if a resize grip exists and is visible
5514 gtk_window_resize_grip_is_visible (GtkWindow *window)
5517 GtkWindowPrivate *priv;
5520 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5522 priv = window->priv;
5523 widget = GTK_WIDGET (window);
5525 if (priv->type == GTK_WINDOW_POPUP)
5528 if (!priv->resizable)
5531 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5534 if (gtk_widget_get_realized (widget))
5536 GdkWindowState state;
5538 state = gdk_window_get_state (gtk_widget_get_window (widget));
5540 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5544 if (!get_drag_edge (widget, &edge))
5547 return window->priv->has_resize_grip;
5551 * gtk_window_get_has_resize_grip:
5552 * @window: a #GtkWindow
5554 * Determines whether the window may have a resize grip.
5556 * Returns: %TRUE if the window has a resize grip
5561 gtk_window_get_has_resize_grip (GtkWindow *window)
5563 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5565 return window->priv->has_resize_grip;
5569 * gtk_window_get_resize_grip_area:
5570 * @window: a #GtkWindow
5571 * @rect: (out): a pointer to a #GdkRectangle which we should store
5572 * the resize grip area
5574 * If a window has a resize grip, this will retrieve the grip
5575 * position, width and height into the specified #GdkRectangle.
5577 * Returns: %TRUE if the resize grip's area was retrieved
5582 gtk_window_get_resize_grip_area (GtkWindow *window,
5585 GtkWidget *widget = GTK_WIDGET (window);
5586 GtkAllocation allocation;
5590 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5592 if (!window->priv->has_resize_grip)
5595 gtk_widget_get_allocation (widget, &allocation);
5597 gtk_widget_style_get (widget,
5598 "resize-grip-width", &grip_width,
5599 "resize-grip-height", &grip_height,
5602 if (grip_width > allocation.width)
5603 grip_width = allocation.width;
5605 if (grip_height > allocation.height)
5606 grip_height = allocation.height;
5608 rect->width = grip_width;
5609 rect->height = grip_height;
5610 rect->y = allocation.y + allocation.height - grip_height;
5612 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5613 rect->x = allocation.x + allocation.width - grip_width;
5615 rect->x = allocation.x;
5620 /* the accel_key and accel_mods fields of the key have to be setup
5621 * upon calling this function. it'll then return whether that key
5622 * is at all used as accelerator, and if so will OR in the
5623 * accel_flags member of the key.
5626 _gtk_window_query_nonaccels (GtkWindow *window,
5628 GdkModifierType accel_mods)
5630 GtkWindowPrivate *priv;
5632 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5634 priv = window->priv;
5636 /* movement keys are considered locked accels */
5639 static const guint bindings[] = {
5640 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,
5641 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,
5645 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5646 if (bindings[i] == accel_key)
5650 /* mnemonics are considered locked accels */
5651 if (accel_mods == priv->mnemonic_modifier)
5653 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5654 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5662 * gtk_window_propagate_key_event:
5663 * @window: a #GtkWindow
5664 * @event: a #GdkEventKey
5666 * Propagate a key press or release event to the focus widget and
5667 * up the focus container chain until a widget handles @event.
5668 * This is normally called by the default ::key_press_event and
5669 * ::key_release_event handlers for toplevel windows,
5670 * however in some cases it may be useful to call this directly when
5671 * overriding the standard key handling for a toplevel window.
5673 * Return value: %TRUE if a widget in the focus chain handled the event.
5678 gtk_window_propagate_key_event (GtkWindow *window,
5681 GtkWindowPrivate *priv;
5682 gboolean handled = FALSE;
5683 GtkWidget *widget, *focus;
5685 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5687 priv = window->priv;
5688 widget = GTK_WIDGET (window);
5690 focus = priv->focus_widget;
5692 g_object_ref (focus);
5695 focus && focus != widget &&
5696 gtk_widget_get_toplevel (focus) == widget)
5700 if (gtk_widget_is_sensitive (focus))
5701 handled = gtk_widget_event (focus, (GdkEvent*) event);
5703 parent = gtk_widget_get_parent (focus);
5705 g_object_ref (parent);
5707 g_object_unref (focus);
5713 g_object_unref (focus);
5719 gtk_window_key_press_event (GtkWidget *widget,
5722 GtkWindow *window = GTK_WINDOW (widget);
5723 gboolean handled = FALSE;
5725 /* handle mnemonics and accelerators */
5727 handled = gtk_window_activate_key (window, event);
5729 /* handle focus widget key events */
5731 handled = gtk_window_propagate_key_event (window, event);
5733 /* Chain up, invokes binding set */
5735 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5741 gtk_window_key_release_event (GtkWidget *widget,
5744 GtkWindow *window = GTK_WINDOW (widget);
5745 gboolean handled = FALSE;
5747 /* handle focus widget key events */
5749 handled = gtk_window_propagate_key_event (window, event);
5751 /* Chain up, invokes binding set */
5753 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5759 gtk_window_button_press_event (GtkWidget *widget,
5760 GdkEventButton *event)
5762 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5765 if (event->window == priv->grip_window)
5767 if (get_drag_edge (widget, &edge))
5768 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5782 gtk_window_real_activate_default (GtkWindow *window)
5784 gtk_window_activate_default (window);
5788 gtk_window_real_activate_focus (GtkWindow *window)
5790 gtk_window_activate_focus (window);
5794 gtk_window_enter_notify_event (GtkWidget *widget,
5795 GdkEventCrossing *event)
5801 gtk_window_leave_notify_event (GtkWidget *widget,
5802 GdkEventCrossing *event)
5808 do_focus_change (GtkWidget *widget,
5812 GdkDeviceManager *device_manager;
5815 g_object_ref (widget);
5817 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5818 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5819 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5820 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5822 for (d = devices; d; d = d->next)
5824 GdkDevice *dev = d->data;
5827 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5830 /* Skip non-master keyboards that haven't
5831 * selected for events from this window
5833 window = gtk_widget_get_window (widget);
5834 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5835 window && !gdk_window_get_device_events (window, dev))
5838 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5840 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5841 fevent->focus_change.window = window;
5843 g_object_ref (window);
5844 fevent->focus_change.in = in;
5845 gdk_event_set_device (fevent, dev);
5847 gtk_widget_send_focus_change (widget, fevent);
5849 gdk_event_free (fevent);
5852 g_list_free (devices);
5853 g_object_unref (widget);
5857 gtk_window_focus_in_event (GtkWidget *widget,
5858 GdkEventFocus *event)
5860 GtkWindow *window = GTK_WINDOW (widget);
5862 /* It appears spurious focus in events can occur when
5863 * the window is hidden. So we'll just check to see if
5864 * the window is visible before actually handling the
5867 if (gtk_widget_get_visible (widget))
5869 _gtk_window_set_has_toplevel_focus (window, TRUE);
5870 _gtk_window_set_is_active (window, TRUE);
5877 gtk_window_focus_out_event (GtkWidget *widget,
5878 GdkEventFocus *event)
5880 GtkWindow *window = GTK_WINDOW (widget);
5881 gboolean auto_mnemonics;
5883 _gtk_window_set_has_toplevel_focus (window, FALSE);
5884 _gtk_window_set_is_active (window, FALSE);
5886 /* set the mnemonic-visible property to false */
5887 g_object_get (gtk_widget_get_settings (widget),
5888 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5890 gtk_window_set_mnemonics_visible (window, FALSE);
5896 gtk_window_check_resize (GtkContainer *container)
5898 /* If the window is not toplevel anymore than it's embedded somewhere,
5899 * so handle it like a normal window */
5900 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
5901 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
5902 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
5903 gtk_window_move_resize (GTK_WINDOW (container));
5907 gtk_window_focus (GtkWidget *widget,
5908 GtkDirectionType direction)
5910 GtkWindowPrivate *priv;
5913 GtkContainer *container;
5915 GtkWidget *old_focus_child;
5918 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5919 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
5921 container = GTK_CONTAINER (widget);
5922 window = GTK_WINDOW (widget);
5923 priv = window->priv;
5924 bin = GTK_BIN (widget);
5926 old_focus_child = gtk_container_get_focus_child (container);
5928 /* We need a special implementation here to deal properly with wrapping
5929 * around in the tab chain without the danger of going into an
5932 if (old_focus_child)
5934 if (gtk_widget_child_focus (old_focus_child, direction))
5938 if (priv->focus_widget)
5940 if (direction == GTK_DIR_LEFT ||
5941 direction == GTK_DIR_RIGHT ||
5942 direction == GTK_DIR_UP ||
5943 direction == GTK_DIR_DOWN)
5948 /* Wrapped off the end, clear the focus setting for the toplpevel */
5949 parent = gtk_widget_get_parent (priv->focus_widget);
5952 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5953 parent = gtk_widget_get_parent (parent);
5956 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5959 /* Now try to focus the first widget in the window */
5960 child = gtk_bin_get_child (bin);
5963 if (gtk_widget_child_focus (child, direction))
5971 gtk_window_move_focus (GtkWidget *widget,
5972 GtkDirectionType dir)
5974 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5976 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
5980 gtk_widget_child_focus (widget, dir);
5982 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
5983 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
5987 gtk_window_real_set_focus (GtkWindow *window,
5990 GtkWindowPrivate *priv = window->priv;
5991 GtkWidget *old_focus = priv->focus_widget;
5992 gboolean had_default = FALSE;
5993 gboolean focus_had_default = FALSE;
5994 gboolean old_focus_had_default = FALSE;
5998 g_object_ref (old_focus);
5999 g_object_freeze_notify (G_OBJECT (old_focus));
6000 old_focus_had_default = gtk_widget_has_default (old_focus);
6004 g_object_ref (focus);
6005 g_object_freeze_notify (G_OBJECT (focus));
6006 focus_had_default = gtk_widget_has_default (focus);
6009 if (priv->default_widget)
6010 had_default = gtk_widget_has_default (priv->default_widget);
6012 if (priv->focus_widget)
6014 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6015 (priv->focus_widget != priv->default_widget))
6017 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6018 gtk_widget_queue_draw (priv->focus_widget);
6020 if (priv->default_widget)
6021 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6024 priv->focus_widget = NULL;
6026 if (priv->has_focus)
6027 do_focus_change (old_focus, FALSE);
6029 g_object_notify (G_OBJECT (old_focus), "is-focus");
6032 /* The above notifications may have set a new focus widget,
6033 * if so, we don't want to override it.
6035 if (focus && !priv->focus_widget)
6037 priv->focus_widget = focus;
6039 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6040 (priv->focus_widget != priv->default_widget))
6042 if (gtk_widget_get_can_default (priv->focus_widget))
6043 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6045 if (priv->default_widget)
6046 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6049 if (priv->has_focus)
6050 do_focus_change (priv->focus_widget, TRUE);
6052 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6055 /* If the default widget changed, a redraw will have been queued
6056 * on the old and new default widgets by gtk_window_set_default(), so
6057 * we only have to worry about the case where it didn't change.
6058 * We'll sometimes queue a draw twice on the new widget but that
6061 if (priv->default_widget &&
6062 (had_default != gtk_widget_has_default (priv->default_widget)))
6063 gtk_widget_queue_draw (priv->default_widget);
6067 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6068 gtk_widget_queue_draw (old_focus);
6070 g_object_thaw_notify (G_OBJECT (old_focus));
6071 g_object_unref (old_focus);
6075 if (focus_had_default != gtk_widget_has_default (focus))
6076 gtk_widget_queue_draw (focus);
6078 g_object_thaw_notify (G_OBJECT (focus));
6079 g_object_unref (focus);
6085 gtk_window_get_preferred_width (GtkWidget *widget,
6093 window = GTK_WINDOW (widget);
6094 child = gtk_bin_get_child (GTK_BIN (window));
6096 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6097 *minimum_size = border_width * 2;
6098 *natural_size = border_width * 2;
6100 if (child && gtk_widget_get_visible (child))
6102 gint child_min, child_nat;
6103 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6105 *minimum_size += child_min;
6106 *natural_size += child_nat;
6111 gtk_window_get_preferred_height (GtkWidget *widget,
6119 window = GTK_WINDOW (widget);
6120 child = gtk_bin_get_child (GTK_BIN (window));
6122 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6123 *minimum_size = border_width * 2;
6124 *natural_size = border_width * 2;
6126 if (child && gtk_widget_get_visible (child))
6128 gint child_min, child_nat;
6129 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6131 *minimum_size += child_min;
6132 *natural_size += child_nat;
6138 * _gtk_window_unset_focus_and_default:
6139 * @window: a #GtkWindow
6140 * @widget: a widget inside of @window
6142 * Checks whether the focus and default widgets of @window are
6143 * @widget or a descendent of @widget, and if so, unset them.
6146 _gtk_window_unset_focus_and_default (GtkWindow *window,
6150 GtkWindowPrivate *priv = window->priv;
6154 g_object_ref (window);
6155 g_object_ref (widget);
6157 parent = gtk_widget_get_parent (widget);
6158 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6160 child = priv->focus_widget;
6162 while (child && child != widget)
6163 child = gtk_widget_get_parent (child);
6165 if (child == widget)
6166 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6169 child = priv->default_widget;
6171 while (child && child != widget)
6172 child = gtk_widget_get_parent (child);
6174 if (child == widget)
6175 gtk_window_set_default (window, NULL);
6177 g_object_unref (widget);
6178 g_object_unref (window);
6181 /*********************************
6182 * Functions related to resizing *
6183 *********************************/
6186 geometry_size_to_pixels (GdkGeometry *geometry,
6191 gint base_width = 0;
6192 gint base_height = 0;
6194 gint min_height = 0;
6196 gint height_inc = 1;
6198 if (flags & GDK_HINT_BASE_SIZE)
6200 base_width = geometry->base_width;
6201 base_height = geometry->base_height;
6203 if (flags & GDK_HINT_MIN_SIZE)
6205 min_width = geometry->min_width;
6206 min_height = geometry->min_height;
6208 if (flags & GDK_HINT_RESIZE_INC)
6210 width_inc = geometry->width_inc;
6211 height_inc = geometry->height_inc;
6215 *width = MAX (*width * width_inc + base_width, min_width);
6217 *height = MAX (*height * height_inc + base_height, min_height);
6220 /* This function doesn't constrain to geometry hints */
6222 gtk_window_compute_configure_request_size (GtkWindow *window,
6223 GdkGeometry *geometry,
6228 GtkWindowPrivate *priv = window->priv;
6229 GtkRequisition requisition;
6230 GtkWindowGeometryInfo *info;
6234 * - we've done a size request
6237 widget = GTK_WIDGET (window);
6239 info = gtk_window_get_geometry_info (window, FALSE);
6241 if (priv->need_default_size)
6243 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6245 /* Default to requisition */
6246 *width = requisition.width;
6247 *height = requisition.height;
6249 /* If window is empty so requests 0, default to random nonzero size */
6250 if (*width == 0 && *height == 0)
6256 /* Override requisition with default size */
6260 if (info->default_width > 0)
6261 *width = info->default_width;
6262 if (info->default_height > 0)
6263 *height = info->default_height;
6265 if (info->default_is_geometry)
6266 geometry_size_to_pixels (geometry, flags,
6267 info->default_width > 0 ? width : NULL,
6268 info->default_height > 0 ? height : NULL);
6273 GtkAllocation allocation;
6275 gtk_widget_get_allocation (widget, &allocation);
6277 /* Default to keeping current size */
6278 *width = allocation.width;
6279 *height = allocation.height;
6282 /* Override any size with gtk_window_resize() values */
6285 if (info->resize_width > 0)
6286 *width = info->resize_width;
6287 if (info->resize_height > 0)
6288 *height = info->resize_height;
6290 if (info->resize_is_geometry)
6291 geometry_size_to_pixels (geometry, flags,
6292 info->resize_width > 0 ? width : NULL,
6293 info->resize_height > 0 ? height : NULL);
6296 /* Don't ever request zero width or height, its not supported by
6297 gdk. The size allocation code will round it to 1 anyway but if
6298 we do it then the value returned from this function will is
6299 not comparable to the size allocation read from the GtkWindow. */
6300 *width = MAX (*width, 1);
6301 *height = MAX (*height, 1);
6304 static GtkWindowPosition
6305 get_effective_position (GtkWindow *window)
6307 GtkWindowPrivate *priv = window->priv;
6308 GtkWindowPosition pos = priv->position;
6310 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6311 (priv->transient_parent == NULL ||
6312 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6313 pos = GTK_WIN_POS_NONE;
6319 get_center_monitor_of_window (GtkWindow *window)
6321 /* We could try to sort out the relative positions of the monitors and
6322 * stuff, or we could just be losers and assume you have a row
6323 * or column of monitors.
6325 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6329 get_monitor_containing_pointer (GtkWindow *window)
6333 GdkScreen *window_screen;
6334 GdkScreen *pointer_screen;
6335 GdkDisplay *display;
6336 GdkDeviceManager *device_manager;
6339 window_screen = gtk_window_check_screen (window);
6340 display = gdk_screen_get_display (window_screen);
6341 device_manager = gdk_display_get_device_manager (display);
6342 pointer = gdk_device_manager_get_client_pointer (device_manager);
6344 gdk_device_get_position (pointer,
6348 if (pointer_screen == window_screen)
6349 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6357 center_window_on_monitor (GtkWindow *window,
6363 GdkRectangle monitor;
6366 monitor_num = get_monitor_containing_pointer (window);
6368 if (monitor_num == -1)
6369 monitor_num = get_center_monitor_of_window (window);
6371 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6372 monitor_num, &monitor);
6374 *x = (monitor.width - w) / 2 + monitor.x;
6375 *y = (monitor.height - h) / 2 + monitor.y;
6377 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6378 * and WM decorations.
6392 if (extent > clamp_extent)
6394 *base = clamp_base + clamp_extent/2 - extent/2;
6395 else if (*base < clamp_base)
6397 else if (*base + extent > clamp_base + clamp_extent)
6398 *base = clamp_base + clamp_extent - extent;
6402 clamp_window_to_rectangle (gint *x,
6406 const GdkRectangle *rect)
6408 #ifdef DEBUGGING_OUTPUT
6409 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);
6412 /* If it is too large, center it. If it fits on the monitor but is
6413 * partially outside, move it to the closest edge. Do this
6414 * separately in x and y directions.
6416 clamp (x, w, rect->x, rect->width);
6417 clamp (y, h, rect->y, rect->height);
6418 #ifdef DEBUGGING_OUTPUT
6419 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6425 gtk_window_compute_configure_request (GtkWindow *window,
6426 GdkRectangle *request,
6427 GdkGeometry *geometry,
6430 GtkWindowPrivate *priv = window->priv;
6431 GdkGeometry new_geometry;
6434 GtkWindowPosition pos;
6435 GtkWidget *parent_widget;
6436 GtkWindowGeometryInfo *info;
6440 screen = gtk_window_check_screen (window);
6442 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6443 gtk_window_compute_configure_request_size (window,
6444 &new_geometry, new_flags,
6445 (guint *)&w, (guint *)&h);
6447 gtk_window_constrain_size (window,
6448 &new_geometry, new_flags,
6452 parent_widget = (GtkWidget*) priv->transient_parent;
6454 pos = get_effective_position (window);
6455 info = gtk_window_get_geometry_info (window, FALSE);
6457 /* by default, don't change position requested */
6460 x = info->last.configure_request.x;
6461 y = info->last.configure_request.y;
6470 if (priv->need_default_position)
6473 /* FIXME this all interrelates with window gravity.
6474 * For most of them I think we want to set GRAVITY_CENTER.
6476 * Not sure how to go about that.
6480 /* here we are only handling CENTER_ALWAYS
6481 * as it relates to default positioning,
6482 * where it's equivalent to simply CENTER
6484 case GTK_WIN_POS_CENTER_ALWAYS:
6485 case GTK_WIN_POS_CENTER:
6486 center_window_on_monitor (window, w, h, &x, &y);
6489 case GTK_WIN_POS_CENTER_ON_PARENT:
6491 GtkAllocation allocation;
6492 GdkWindow *gdk_window;
6494 GdkRectangle monitor;
6497 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6499 gdk_window = gtk_widget_get_window (parent_widget);
6501 if (gdk_window != NULL)
6502 monitor_num = gdk_screen_get_monitor_at_window (screen,
6507 gdk_window_get_origin (gdk_window,
6510 gtk_widget_get_allocation (parent_widget, &allocation);
6511 x = ox + (allocation.width - w) / 2;
6512 y = oy + (allocation.height - h) / 2;
6514 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6515 * WM decorations. If parent wasn't on a monitor, just
6518 if (monitor_num >= 0)
6520 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6521 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6526 case GTK_WIN_POS_MOUSE:
6528 gint screen_width = gdk_screen_get_width (screen);
6529 gint screen_height = gdk_screen_get_height (screen);
6531 GdkRectangle monitor;
6532 GdkDisplay *display;
6533 GdkDeviceManager *device_manager;
6535 GdkScreen *pointer_screen;
6538 display = gdk_screen_get_display (screen);
6539 device_manager = gdk_display_get_device_manager (display);
6540 pointer = gdk_device_manager_get_client_pointer (device_manager);
6542 gdk_device_get_position (pointer,
6546 if (pointer_screen == screen)
6547 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6553 x = CLAMP (x, 0, screen_width - w);
6554 y = CLAMP (y, 0, screen_height - h);
6556 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6557 * WM decorations. Don't try to figure out what's going
6558 * on if the mouse wasn't inside a monitor.
6560 if (monitor_num >= 0)
6562 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6563 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6571 } /* if (priv->need_default_position) */
6573 if (priv->need_default_position && info &&
6574 info->initial_pos_set)
6576 x = info->initial_x;
6577 y = info->initial_y;
6578 gtk_window_constrain_position (window, w, h, &x, &y);
6584 request->height = h;
6587 *geometry = new_geometry;
6593 gtk_window_constrain_position (GtkWindow *window,
6599 GtkWindowPrivate *priv = window->priv;
6601 /* See long comments in gtk_window_move_resize()
6602 * on when it's safe to call this function.
6604 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6606 gint center_x, center_y;
6608 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6616 gtk_window_move_resize (GtkWindow *window)
6620 * First we determine whether any information has changed that would
6621 * cause us to revise our last configure request. If we would send
6622 * a different configure request from last time, then
6623 * configure_request_size_changed = TRUE or
6624 * configure_request_pos_changed = TRUE. configure_request_size_changed
6625 * may be true due to new hints, a gtk_window_resize(), or whatever.
6626 * configure_request_pos_changed may be true due to gtk_window_set_position()
6627 * or gtk_window_move().
6629 * If the configure request has changed, we send off a new one. To
6630 * ensure GTK+ invariants are maintained (resize queue does what it
6631 * should), we go ahead and size_allocate the requested size in this
6634 * If the configure request has not changed, we don't ever resend
6635 * it, because it could mean fighting the user or window manager.
6638 * To prepare the configure request, we come up with a base size/pos:
6639 * - the one from gtk_window_move()/gtk_window_resize()
6640 * - else default_width, default_height if we haven't ever
6642 * - else the size request if we haven't ever been mapped,
6643 * as a substitute default size
6644 * - else the current size of the window, as received from
6645 * configure notifies (i.e. the current allocation)
6647 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6648 * the position request to be centered.
6650 GtkWindowPrivate *priv = window->priv;
6651 GtkAllocation allocation;
6653 GtkContainer *container;
6654 GtkWindowGeometryInfo *info;
6655 GdkGeometry new_geometry;
6656 GdkWindow *gdk_window;
6658 GdkRectangle new_request;
6659 gboolean configure_request_size_changed;
6660 gboolean configure_request_pos_changed;
6661 gboolean hints_changed; /* do we need to send these again */
6662 GtkWindowLastGeometryInfo saved_last_info;
6664 widget = GTK_WIDGET (window);
6666 gdk_window = gtk_widget_get_window (widget);
6667 container = GTK_CONTAINER (widget);
6668 info = gtk_window_get_geometry_info (window, TRUE);
6670 configure_request_size_changed = FALSE;
6671 configure_request_pos_changed = FALSE;
6673 gtk_window_compute_configure_request (window, &new_request,
6674 &new_geometry, &new_flags);
6676 /* This check implies the invariant that we never set info->last
6677 * without setting the hints and sending off a configure request.
6679 * If we change info->last without sending the request, we may
6682 if (info->last.configure_request.x != new_request.x ||
6683 info->last.configure_request.y != new_request.y)
6684 configure_request_pos_changed = TRUE;
6686 if ((info->last.configure_request.width != new_request.width ||
6687 info->last.configure_request.height != new_request.height))
6688 configure_request_size_changed = TRUE;
6690 hints_changed = FALSE;
6692 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6693 &new_geometry, new_flags))
6695 hints_changed = TRUE;
6698 /* Position Constraints
6699 * ====================
6701 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6702 * a default. The other POS_ values are used only when the
6703 * window is shown, not after that.
6705 * However, we can't implement a position constraint as
6706 * "anytime the window size changes, center the window"
6707 * because this may well end up fighting the WM or user. In
6708 * fact it gets in an infinite loop with at least one WM.
6710 * Basically, applications are in no way in a position to
6711 * constrain the position of a window, with one exception:
6712 * override redirect windows. (Really the intended purpose
6713 * of CENTER_ALWAYS anyhow, I would think.)
6715 * So the way we implement this "constraint" is to say that when WE
6716 * cause a move or resize, i.e. we make a configure request changing
6717 * window size, we recompute the CENTER_ALWAYS position to reflect
6718 * the new window size, and include it in our request. Also, if we
6719 * just turned on CENTER_ALWAYS we snap to center with a new
6720 * request. Otherwise, if we are just NOTIFIED of a move or resize
6721 * done by someone else e.g. the window manager, we do NOT send a
6722 * new configure request.
6724 * For override redirect windows, this works fine; all window
6725 * sizes are from our configure requests. For managed windows,
6726 * it is at least semi-sane, though who knows what the
6727 * app author is thinking.
6730 /* This condition should be kept in sync with the condition later on
6731 * that determines whether we send a configure request. i.e. we
6732 * should do this position constraining anytime we were going to
6733 * send a configure request anyhow, plus when constraints have
6736 if (configure_request_pos_changed ||
6737 configure_request_size_changed ||
6739 info->position_constraints_changed)
6741 /* We request the constrained position if:
6742 * - we were changing position, and need to clamp
6743 * the change to the constraint
6744 * - we're changing the size anyway
6745 * - set_position() was called to toggle CENTER_ALWAYS on
6748 gtk_window_constrain_position (window,
6754 /* Update whether we need to request a move */
6755 if (info->last.configure_request.x != new_request.x ||
6756 info->last.configure_request.y != new_request.y)
6757 configure_request_pos_changed = TRUE;
6759 configure_request_pos_changed = FALSE;
6763 if (priv->type == GTK_WINDOW_TOPLEVEL)
6765 int notify_x, notify_y;
6767 /* this is the position from the last configure notify */
6768 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6770 g_message ("--- %s ---\n"
6771 "last : %d,%d\t%d x %d\n"
6772 "this : %d,%d\t%d x %d\n"
6773 "alloc : %d,%d\t%d x %d\n"
6775 "resize: \t%d x %d\n"
6776 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6777 "configure_notify_received: %d\n"
6778 "configure_request_count: %d\n"
6779 "position_constraints_changed: %d\n",
6780 priv->title ? priv->title : "(no title)",
6781 info->last.configure_request.x,
6782 info->last.configure_request.y,
6783 info->last.configure_request.width,
6784 info->last.configure_request.height,
6790 widget->allocation.width,
6791 widget->allocation.height,
6792 widget->requisition.width,
6793 widget->requisition.height,
6795 info->resize_height,
6796 configure_request_pos_changed,
6797 configure_request_size_changed,
6799 priv->configure_notify_received,
6800 priv->configure_request_count,
6801 info->position_constraints_changed);
6805 saved_last_info = info->last;
6806 info->last.geometry = new_geometry;
6807 info->last.flags = new_flags;
6808 info->last.configure_request = new_request;
6810 /* need to set PPosition so the WM will look at our position,
6811 * but we don't want to count PPosition coming and going as a hints
6812 * change for future iterations. So we saved info->last prior to
6816 /* Also, if the initial position was explicitly set, then we always
6817 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6821 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6822 * this is an initial map
6825 if ((configure_request_pos_changed ||
6826 info->initial_pos_set ||
6827 (priv->need_default_position &&
6828 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6829 (new_flags & GDK_HINT_POS) == 0)
6831 new_flags |= GDK_HINT_POS;
6832 hints_changed = TRUE;
6835 /* Set hints if necessary
6838 gdk_window_set_geometry_hints (gdk_window,
6842 gtk_widget_get_allocation (widget, &allocation);
6844 /* handle resizing/moving and widget tree allocation
6846 if (priv->configure_notify_received)
6848 /* If we have received a configure event since
6849 * the last time in this function, we need to
6850 * accept our new size and size_allocate child widgets.
6851 * (see gtk_window_configure_event() for more details).
6853 * 1 or more configure notifies may have been received.
6854 * Also, configure_notify_received will only be TRUE
6855 * if all expected configure notifies have been received
6856 * (one per configure request), as an optimization.
6859 priv->configure_notify_received = FALSE;
6861 /* gtk_window_configure_event() filled in widget->allocation */
6862 gtk_widget_size_allocate (widget, &allocation);
6864 set_grip_position (window);
6865 update_grip_visibility (window);
6867 gdk_window_process_updates (gdk_window, TRUE);
6869 gdk_window_configure_finished (gdk_window);
6871 /* If the configure request changed, it means that
6873 * 1) coincidentally changed hints or widget properties
6874 * impacting the configure request before getting
6875 * a configure notify, or
6876 * 2) some broken widget is changing its size request
6877 * during size allocation, resulting in
6878 * a false appearance of changed configure request.
6880 * For 1), we could just go ahead and ask for the
6881 * new size right now, but doing that for 2)
6882 * might well be fighting the user (and can even
6883 * trigger a loop). Since we really don't want to
6884 * do that, we requeue a resize in hopes that
6885 * by the time it gets handled, the child has seen
6886 * the light and is willing to go along with the
6887 * new size. (this happens for the zvt widget, since
6888 * the size_allocate() above will have stored the
6889 * requisition corresponding to the new size in the
6892 * This doesn't buy us anything for 1), but it shouldn't
6893 * hurt us too badly, since it is what would have
6894 * happened if we had gotten the configure event before
6895 * the new size had been set.
6898 if (configure_request_size_changed ||
6899 configure_request_pos_changed)
6901 /* Don't change the recorded last info after all, because we
6902 * haven't actually updated to the new info yet - we decided
6903 * to postpone our configure request until later.
6905 info->last = saved_last_info;
6907 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6910 return; /* Bail out, we didn't really process the move/resize */
6912 else if ((configure_request_size_changed || hints_changed) &&
6913 (allocation.width != new_request.width || allocation.height != new_request.height))
6916 /* We are in one of the following situations:
6917 * A. configure_request_size_changed
6918 * our requisition has changed and we need a different window size,
6919 * so we request it from the window manager.
6920 * B. !configure_request_size_changed && hints_changed
6921 * the window manager rejects our size, but we have just changed the
6922 * window manager hints, so there's a chance our request will
6923 * be honoured this time, so we try again.
6925 * However, if the new requisition is the same as the current allocation,
6926 * we don't request it again, since we won't get a ConfigureNotify back from
6927 * the window manager unless it decides to change our requisition. If
6928 * we don't get the ConfigureNotify back, the resize queue will never be run.
6931 /* Now send the configure request */
6932 if (configure_request_pos_changed)
6934 gdk_window_move_resize (gdk_window,
6935 new_request.x, new_request.y,
6936 new_request.width, new_request.height);
6938 else /* only size changed */
6940 gdk_window_resize (gdk_window,
6941 new_request.width, new_request.height);
6944 if (priv->type == GTK_WINDOW_POPUP)
6946 GtkAllocation allocation;
6948 /* Directly size allocate for override redirect (popup) windows. */
6951 allocation.width = new_request.width;
6952 allocation.height = new_request.height;
6954 gtk_widget_size_allocate (widget, &allocation);
6956 gdk_window_process_updates (gdk_window, TRUE);
6958 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6959 gtk_widget_queue_draw (widget);
6963 /* Increment the number of have-not-yet-received-notify requests */
6964 priv->configure_request_count += 1;
6965 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
6967 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6968 * configure event in response to our resizing request.
6969 * the configure event will cause a new resize with
6970 * ->configure_notify_received=TRUE.
6971 * until then, we want to
6972 * - discard expose events
6973 * - coalesce resizes for our children
6974 * - defer any window resizes until the configure event arrived
6975 * to achieve this, we queue a resize for the window, but remove its
6976 * resizing handler, so resizing will not be handled from the next
6977 * idle handler but when the configure event arrives.
6979 * FIXME: we should also dequeue the pending redraws here, since
6980 * we handle those ourselves upon ->configure_notify_received==TRUE.
6982 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6984 gtk_widget_queue_resize_no_redraw (widget);
6985 _gtk_container_dequeue_resize_handler (container);
6991 /* Handle any position changes.
6993 if (configure_request_pos_changed)
6995 gdk_window_move (gdk_window,
6996 new_request.x, new_request.y);
6999 /* And run the resize queue.
7001 gtk_container_resize_children (container);
7004 /* We have now processed a move/resize since the last position
7005 * constraint change, setting of the initial position, or resize.
7006 * (Not resetting these flags here can lead to infinite loops for
7007 * GTK_RESIZE_IMMEDIATE containers)
7009 info->position_constraints_changed = FALSE;
7010 info->initial_pos_set = FALSE;
7011 info->resize_width = -1;
7012 info->resize_height = -1;
7015 /* Compare two sets of Geometry hints for equality.
7018 gtk_window_compare_hints (GdkGeometry *geometry_a,
7020 GdkGeometry *geometry_b,
7023 if (flags_a != flags_b)
7026 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7027 (geometry_a->min_width != geometry_b->min_width ||
7028 geometry_a->min_height != geometry_b->min_height))
7031 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7032 (geometry_a->max_width != geometry_b->max_width ||
7033 geometry_a->max_height != geometry_b->max_height))
7036 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7037 (geometry_a->base_width != geometry_b->base_width ||
7038 geometry_a->base_height != geometry_b->base_height))
7041 if ((flags_a & GDK_HINT_ASPECT) &&
7042 (geometry_a->min_aspect != geometry_b->min_aspect ||
7043 geometry_a->max_aspect != geometry_b->max_aspect))
7046 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7047 (geometry_a->width_inc != geometry_b->width_inc ||
7048 geometry_a->height_inc != geometry_b->height_inc))
7051 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7052 geometry_a->win_gravity != geometry_b->win_gravity)
7059 _gtk_window_constrain_size (GtkWindow *window,
7065 GtkWindowPrivate *priv;
7066 GtkWindowGeometryInfo *info;
7068 g_return_if_fail (GTK_IS_WINDOW (window));
7070 priv = window->priv;
7072 info = priv->geometry_info;
7075 GdkWindowHints flags = info->last.flags;
7076 GdkGeometry *geometry = &info->last.geometry;
7078 gtk_window_constrain_size (window,
7089 gtk_window_constrain_size (GtkWindow *window,
7090 GdkGeometry *geometry,
7097 gdk_window_constrain_size (geometry, flags, width, height,
7098 new_width, new_height);
7101 /* Compute the set of geometry hints and flags for a window
7102 * based on the application set geometry, and requisition
7103 * of the window. gtk_widget_get_preferred_size() must have been
7107 gtk_window_compute_hints (GtkWindow *window,
7108 GdkGeometry *new_geometry,
7111 GtkWindowPrivate *priv = window->priv;
7113 gint extra_width = 0;
7114 gint extra_height = 0;
7115 GtkWindowGeometryInfo *geometry_info;
7116 GtkRequisition requisition;
7118 widget = GTK_WIDGET (window);
7120 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7121 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7125 *new_flags = geometry_info->mask;
7126 *new_geometry = geometry_info->geometry;
7133 if (geometry_info && geometry_info->widget)
7135 /* If the geometry widget is set, then the hints really apply to that
7136 * widget. This is pretty much meaningless unless the window layout
7137 * is such that the rest of the window adds fixed size borders to
7138 * the geometry widget. Our job is to figure the size of the borders;
7139 * We do that by asking how big the toplevel would be if the
7140 * geometry widget was *really big*.
7143 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7144 * |GGGGG B| in the border can confuse things
7150 * |AAAAAAAAA | When the geometry widget is large, things are
7151 * |GGGGGGGGGGB| clearer.
7156 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7157 GtkRequisition requisition;
7158 int current_width, current_height;
7160 _gtk_widget_override_size_request (geometry_info->widget,
7161 TEMPORARY_SIZE, TEMPORARY_SIZE,
7162 ¤t_width, ¤t_height);
7163 gtk_widget_get_preferred_size (widget,
7164 &requisition, NULL);
7165 _gtk_widget_restore_size_request (geometry_info->widget,
7166 current_width, current_height);
7168 extra_width = requisition.width - TEMPORARY_SIZE;
7169 extra_height = requisition.height - TEMPORARY_SIZE;
7171 if (extra_width < 0 || extra_height < 0)
7173 g_warning("Toplevel size doesn't seem to directly depend on the "
7174 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7175 "The geometry widget might not be in the window, or it might not "
7176 "be packed into the window appropriately");
7177 extra_width = MAX(extra_width, 0);
7178 extra_height = MAX(extra_height, 0);
7180 #undef TEMPORARY_SIZE
7183 /* We don't want to set GDK_HINT_POS in here, we just set it
7184 * in gtk_window_move_resize() when we want the position
7188 if (*new_flags & GDK_HINT_BASE_SIZE)
7190 new_geometry->base_width += extra_width;
7191 new_geometry->base_height += extra_height;
7195 /* For simplicity, we always set the base hint, even when we
7196 * don't expect it to have any visible effect.
7197 * (Note: geometry_size_to_pixels() depends on this.)
7199 *new_flags |= GDK_HINT_BASE_SIZE;
7201 new_geometry->base_width = extra_width;
7202 new_geometry->base_height = extra_height;
7204 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7205 * base size is the minimum size */
7206 if (*new_flags & GDK_HINT_MIN_SIZE)
7208 if (new_geometry->min_width > 0)
7209 new_geometry->base_width += new_geometry->min_width;
7210 if (new_geometry->min_height > 0)
7211 new_geometry->base_height += new_geometry->min_height;
7215 if (*new_flags & GDK_HINT_MIN_SIZE)
7217 if (new_geometry->min_width < 0)
7218 new_geometry->min_width = requisition.width;
7220 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7222 if (new_geometry->min_height < 0)
7223 new_geometry->min_height = requisition.height;
7225 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7229 *new_flags |= GDK_HINT_MIN_SIZE;
7231 new_geometry->min_width = requisition.width;
7232 new_geometry->min_height = requisition.height;
7235 if (*new_flags & GDK_HINT_MAX_SIZE)
7237 if (new_geometry->max_width < 0)
7238 new_geometry->max_width = requisition.width;
7240 new_geometry->max_width += extra_width;
7242 if (new_geometry->max_height < 0)
7243 new_geometry->max_height = requisition.height;
7245 new_geometry->max_height += extra_height;
7247 else if (!priv->resizable)
7249 *new_flags |= GDK_HINT_MAX_SIZE;
7251 new_geometry->max_width = requisition.width;
7252 new_geometry->max_height = requisition.height;
7255 *new_flags |= GDK_HINT_WIN_GRAVITY;
7256 new_geometry->win_gravity = priv->gravity;
7259 /***********************
7260 * Redrawing functions *
7261 ***********************/
7264 gtk_window_draw (GtkWidget *widget,
7267 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7268 GtkStyleContext *context;
7269 gboolean ret = FALSE;
7271 context = gtk_widget_get_style_context (widget);
7273 gtk_style_context_save (context);
7275 if (!gtk_widget_get_app_paintable (widget))
7277 GtkStateFlags state;
7279 state = gtk_widget_get_state_flags (widget);
7281 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7282 state |= GTK_STATE_FLAG_FOCUSED;
7284 gtk_style_context_set_state (context, state);
7285 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7286 gtk_render_background (context, cr, 0, 0,
7287 gtk_widget_get_allocated_width (widget),
7288 gtk_widget_get_allocated_height (widget));
7291 gtk_style_context_restore (context);
7293 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7294 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7296 if (priv->grip_window != NULL &&
7297 gtk_cairo_should_draw_window (cr, priv->grip_window))
7301 gtk_style_context_save (context);
7304 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7305 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7307 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7308 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7309 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7312 gtk_style_context_restore (context);
7319 * gtk_window_present:
7320 * @window: a #GtkWindow
7322 * Presents a window to the user. This may mean raising the window
7323 * in the stacking order, deiconifying it, moving it to the current
7324 * desktop, and/or giving it the keyboard focus, possibly dependent
7325 * on the user's platform, window manager, and preferences.
7327 * If @window is hidden, this function calls gtk_widget_show()
7330 * This function should be used when the user tries to open a window
7331 * that's already open. Say for example the preferences dialog is
7332 * currently open, and the user chooses Preferences from the menu
7333 * a second time; use gtk_window_present() to move the already-open dialog
7334 * where the user can see it.
7336 * If you are calling this function in response to a user interaction,
7337 * it is preferable to use gtk_window_present_with_time().
7341 gtk_window_present (GtkWindow *window)
7343 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7347 * gtk_window_present_with_time:
7348 * @window: a #GtkWindow
7349 * @timestamp: the timestamp of the user interaction (typically a
7350 * button or key press event) which triggered this call
7352 * Presents a window to the user in response to a user interaction.
7353 * If you need to present a window without a timestamp, use
7354 * gtk_window_present(). See gtk_window_present() for details.
7359 gtk_window_present_with_time (GtkWindow *window,
7363 GdkWindow *gdk_window;
7365 g_return_if_fail (GTK_IS_WINDOW (window));
7367 widget = GTK_WIDGET (window);
7369 if (gtk_widget_get_visible (widget))
7371 gdk_window = gtk_widget_get_window (widget);
7373 g_assert (gdk_window != NULL);
7375 gdk_window_show (gdk_window);
7377 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7378 if (timestamp == GDK_CURRENT_TIME)
7380 #ifdef GDK_WINDOWING_X11
7381 if (GDK_IS_X11_WINDOW(gdk_window))
7383 GdkDisplay *display;
7385 display = gtk_widget_get_display (GTK_WIDGET (window));
7386 timestamp = gdk_x11_display_get_user_time (display);
7390 timestamp = gtk_get_current_event_time ();
7393 gdk_window_focus (gdk_window, timestamp);
7397 gtk_widget_show (widget);
7402 * gtk_window_iconify:
7403 * @window: a #GtkWindow
7405 * Asks to iconify (i.e. minimize) the specified @window. Note that
7406 * you shouldn't assume the window is definitely iconified afterward,
7407 * because other entities (e.g. the user or <link
7408 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7409 * again, or there may not be a window manager in which case
7410 * iconification isn't possible, etc. But normally the window will end
7411 * up iconified. Just don't write code that crashes if not.
7413 * It's permitted to call this function before showing a window,
7414 * in which case the window will be iconified before it ever appears
7417 * You can track iconification via the "window-state-event" signal
7422 gtk_window_iconify (GtkWindow *window)
7424 GtkWindowPrivate *priv;
7426 GdkWindow *toplevel;
7428 g_return_if_fail (GTK_IS_WINDOW (window));
7430 priv = window->priv;
7431 widget = GTK_WIDGET (window);
7433 priv->iconify_initially = TRUE;
7435 toplevel = gtk_widget_get_window (widget);
7437 if (toplevel != NULL)
7438 gdk_window_iconify (toplevel);
7442 * gtk_window_deiconify:
7443 * @window: a #GtkWindow
7445 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7446 * that you shouldn't assume the window is definitely deiconified
7447 * afterward, because other entities (e.g. the user or <link
7448 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7449 * again before your code which assumes deiconification gets to run.
7451 * You can track iconification via the "window-state-event" signal
7455 gtk_window_deiconify (GtkWindow *window)
7457 GtkWindowPrivate *priv;
7459 GdkWindow *toplevel;
7461 g_return_if_fail (GTK_IS_WINDOW (window));
7463 priv = window->priv;
7464 widget = GTK_WIDGET (window);
7466 priv->iconify_initially = FALSE;
7468 toplevel = gtk_widget_get_window (widget);
7470 if (toplevel != NULL)
7471 gdk_window_deiconify (toplevel);
7476 * @window: a #GtkWindow
7478 * Asks to stick @window, which means that it will appear on all user
7479 * desktops. Note that you shouldn't assume the window is definitely
7480 * stuck afterward, because other entities (e.g. the user or <link
7481 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7482 * again, and some window managers do not support sticking
7483 * windows. But normally the window will end up stuck. Just don't
7484 * write code that crashes if not.
7486 * It's permitted to call this function before showing a window.
7488 * You can track stickiness via the "window-state-event" signal
7493 gtk_window_stick (GtkWindow *window)
7495 GtkWindowPrivate *priv;
7497 GdkWindow *toplevel;
7499 g_return_if_fail (GTK_IS_WINDOW (window));
7501 priv = window->priv;
7502 widget = GTK_WIDGET (window);
7504 priv->stick_initially = TRUE;
7506 toplevel = gtk_widget_get_window (widget);
7508 if (toplevel != NULL)
7509 gdk_window_stick (toplevel);
7513 * gtk_window_unstick:
7514 * @window: a #GtkWindow
7516 * Asks to unstick @window, which means that it will appear on only
7517 * one of the user's desktops. Note that you shouldn't assume the
7518 * window is definitely unstuck afterward, because other entities
7519 * (e.g. the user or <link linkend="gtk-X11-arch">window
7520 * manager</link>) could stick it again. But normally the window will
7521 * end up stuck. Just don't write code that crashes if not.
7523 * You can track stickiness via the "window-state-event" signal
7528 gtk_window_unstick (GtkWindow *window)
7530 GtkWindowPrivate *priv;
7532 GdkWindow *toplevel;
7534 g_return_if_fail (GTK_IS_WINDOW (window));
7536 priv = window->priv;
7537 widget = GTK_WIDGET (window);
7539 priv->stick_initially = FALSE;
7541 toplevel = gtk_widget_get_window (widget);
7543 if (toplevel != NULL)
7544 gdk_window_unstick (toplevel);
7548 * gtk_window_maximize:
7549 * @window: a #GtkWindow
7551 * Asks to maximize @window, so that it becomes full-screen. Note that
7552 * you shouldn't assume the window is definitely maximized afterward,
7553 * because other entities (e.g. the user or <link
7554 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7555 * again, and not all window managers support maximization. But
7556 * normally the window will end up maximized. Just don't write code
7557 * that crashes if not.
7559 * It's permitted to call this function before showing a window,
7560 * in which case the window will be maximized when it appears onscreen
7563 * You can track maximization via the "window-state-event" signal
7568 gtk_window_maximize (GtkWindow *window)
7570 GtkWindowPrivate *priv;
7572 GdkWindow *toplevel;
7574 g_return_if_fail (GTK_IS_WINDOW (window));
7576 priv = window->priv;
7577 widget = GTK_WIDGET (window);
7579 priv->maximize_initially = TRUE;
7581 toplevel = gtk_widget_get_window (widget);
7583 if (toplevel != NULL)
7584 gdk_window_maximize (toplevel);
7588 * gtk_window_unmaximize:
7589 * @window: a #GtkWindow
7591 * Asks to unmaximize @window. Note that you shouldn't assume the
7592 * window is definitely unmaximized afterward, because other entities
7593 * (e.g. the user or <link linkend="gtk-X11-arch">window
7594 * manager</link>) could maximize it again, and not all window
7595 * managers honor requests to unmaximize. But normally the window will
7596 * end up unmaximized. Just don't write code that crashes if not.
7598 * You can track maximization via the "window-state-event" signal
7603 gtk_window_unmaximize (GtkWindow *window)
7605 GtkWindowPrivate *priv;
7607 GdkWindow *toplevel;
7609 g_return_if_fail (GTK_IS_WINDOW (window));
7611 priv = window->priv;
7612 widget = GTK_WIDGET (window);
7614 priv->maximize_initially = FALSE;
7616 toplevel = gtk_widget_get_window (widget);
7618 if (toplevel != NULL)
7619 gdk_window_unmaximize (toplevel);
7623 * gtk_window_fullscreen:
7624 * @window: a #GtkWindow
7626 * Asks to place @window in the fullscreen state. Note that you
7627 * shouldn't assume the window is definitely full screen afterward,
7628 * because other entities (e.g. the user or <link
7629 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7630 * again, and not all window managers honor requests to fullscreen
7631 * windows. But normally the window will end up fullscreen. Just
7632 * don't write code that crashes if not.
7634 * You can track the fullscreen state via the "window-state-event" signal
7640 gtk_window_fullscreen (GtkWindow *window)
7642 GtkWindowPrivate *priv;
7644 GdkWindow *toplevel;
7646 g_return_if_fail (GTK_IS_WINDOW (window));
7648 priv = window->priv;
7649 widget = GTK_WIDGET (window);
7651 priv->fullscreen_initially = TRUE;
7653 toplevel = gtk_widget_get_window (widget);
7655 if (toplevel != NULL)
7656 gdk_window_fullscreen (toplevel);
7660 * gtk_window_unfullscreen:
7661 * @window: a #GtkWindow
7663 * Asks to toggle off the fullscreen state for @window. Note that you
7664 * shouldn't assume the window is definitely not full screen
7665 * afterward, because other entities (e.g. the user or <link
7666 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7667 * again, and not all window managers honor requests to unfullscreen
7668 * windows. But normally the window will end up restored to its normal
7669 * state. Just don't write code that crashes if not.
7671 * You can track the fullscreen state via the "window-state-event" signal
7677 gtk_window_unfullscreen (GtkWindow *window)
7680 GdkWindow *toplevel;
7681 GtkWindowPrivate *priv;
7683 g_return_if_fail (GTK_IS_WINDOW (window));
7685 priv = window->priv;
7686 widget = GTK_WIDGET (window);
7688 priv->fullscreen_initially = FALSE;
7690 toplevel = gtk_widget_get_window (widget);
7692 if (toplevel != NULL)
7693 gdk_window_unfullscreen (toplevel);
7697 * gtk_window_set_keep_above:
7698 * @window: a #GtkWindow
7699 * @setting: whether to keep @window above other windows
7701 * Asks to keep @window above, so that it stays on top. Note that
7702 * you shouldn't assume the window is definitely above afterward,
7703 * because other entities (e.g. the user or <link
7704 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7705 * and not all window managers support keeping windows above. But
7706 * normally the window will end kept above. Just don't write code
7707 * that crashes if not.
7709 * It's permitted to call this function before showing a window,
7710 * in which case the window will be kept above when it appears onscreen
7713 * You can track the above state via the "window-state-event" signal
7716 * Note that, according to the <ulink
7717 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7718 * Manager Hints</ulink> specification, the above state is mainly meant
7719 * for user preferences and should not be used by applications e.g. for
7720 * drawing attention to their dialogs.
7725 gtk_window_set_keep_above (GtkWindow *window,
7729 GtkWindowPrivate *priv;
7730 GdkWindow *toplevel;
7732 g_return_if_fail (GTK_IS_WINDOW (window));
7734 priv = window->priv;
7735 widget = GTK_WIDGET (window);
7737 priv->above_initially = setting != FALSE;
7739 priv->below_initially = FALSE;
7741 toplevel = gtk_widget_get_window (widget);
7743 if (toplevel != NULL)
7744 gdk_window_set_keep_above (toplevel, setting);
7748 * gtk_window_set_keep_below:
7749 * @window: a #GtkWindow
7750 * @setting: whether to keep @window below other windows
7752 * Asks to keep @window below, so that it stays in bottom. Note that
7753 * you shouldn't assume the window is definitely below afterward,
7754 * because other entities (e.g. the user or <link
7755 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7756 * and not all window managers support putting windows below. But
7757 * normally the window will be kept below. Just don't write code
7758 * that crashes if not.
7760 * It's permitted to call this function before showing a window,
7761 * in which case the window will be kept below when it appears onscreen
7764 * You can track the below state via the "window-state-event" signal
7767 * Note that, according to the <ulink
7768 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7769 * Manager Hints</ulink> specification, the above state is mainly meant
7770 * for user preferences and should not be used by applications e.g. for
7771 * drawing attention to their dialogs.
7776 gtk_window_set_keep_below (GtkWindow *window,
7780 GtkWindowPrivate *priv;
7781 GdkWindow *toplevel;
7783 g_return_if_fail (GTK_IS_WINDOW (window));
7785 priv = window->priv;
7786 widget = GTK_WIDGET (window);
7788 priv->below_initially = setting != FALSE;
7790 priv->above_initially = FALSE;
7792 toplevel = gtk_widget_get_window (widget);
7794 if (toplevel != NULL)
7795 gdk_window_set_keep_below (toplevel, setting);
7799 * gtk_window_set_resizable:
7800 * @window: a #GtkWindow
7801 * @resizable: %TRUE if the user can resize this window
7803 * Sets whether the user can resize a window. Windows are user resizable
7807 gtk_window_set_resizable (GtkWindow *window,
7810 GtkWindowPrivate *priv;
7812 g_return_if_fail (GTK_IS_WINDOW (window));
7814 priv = window->priv;
7816 resizable = (resizable != FALSE);
7818 if (priv->resizable != resizable)
7820 priv->resizable = (resizable != FALSE);
7822 update_grip_visibility (window);
7824 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7826 g_object_notify (G_OBJECT (window), "resizable");
7831 * gtk_window_get_resizable:
7832 * @window: a #GtkWindow
7834 * Gets the value set by gtk_window_set_resizable().
7836 * Return value: %TRUE if the user can resize the window
7839 gtk_window_get_resizable (GtkWindow *window)
7841 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7843 return window->priv->resizable;
7847 * gtk_window_set_gravity:
7848 * @window: a #GtkWindow
7849 * @gravity: window gravity
7851 * Window gravity defines the meaning of coordinates passed to
7852 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7855 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7856 * typically "do what you mean."
7860 gtk_window_set_gravity (GtkWindow *window,
7863 GtkWindowPrivate *priv;
7865 g_return_if_fail (GTK_IS_WINDOW (window));
7867 priv = window->priv;
7869 if (gravity != priv->gravity)
7871 priv->gravity = gravity;
7873 /* gtk_window_move_resize() will adapt gravity
7875 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7877 g_object_notify (G_OBJECT (window), "gravity");
7882 * gtk_window_get_gravity:
7883 * @window: a #GtkWindow
7885 * Gets the value set by gtk_window_set_gravity().
7887 * Return value: (transfer none): window gravity
7890 gtk_window_get_gravity (GtkWindow *window)
7892 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7894 return window->priv->gravity;
7898 * gtk_window_begin_resize_drag:
7899 * @window: a #GtkWindow
7900 * @button: mouse button that initiated the drag
7901 * @edge: position of the resize control
7902 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7903 * @root_y: Y position where the user clicked to initiate the drag
7904 * @timestamp: timestamp from the click event that initiated the drag
7906 * Starts resizing a window. This function is used if an application
7907 * has window resizing controls. When GDK can support it, the resize
7908 * will be done using the standard mechanism for the <link
7909 * linkend="gtk-X11-arch">window manager</link> or windowing
7910 * system. Otherwise, GDK will try to emulate window resizing,
7911 * potentially not all that well, depending on the windowing system.
7915 gtk_window_begin_resize_drag (GtkWindow *window,
7923 GdkWindow *toplevel;
7925 g_return_if_fail (GTK_IS_WINDOW (window));
7926 widget = GTK_WIDGET (window);
7927 g_return_if_fail (gtk_widget_get_visible (widget));
7929 toplevel = gtk_widget_get_window (widget);
7931 gdk_window_begin_resize_drag (toplevel,
7938 * gtk_window_begin_move_drag:
7939 * @window: a #GtkWindow
7940 * @button: mouse button that initiated the drag
7941 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7942 * @root_y: Y position where the user clicked to initiate the drag
7943 * @timestamp: timestamp from the click event that initiated the drag
7945 * Starts moving a window. This function is used if an application has
7946 * window movement grips. When GDK can support it, the window movement
7947 * will be done using the standard mechanism for the <link
7948 * linkend="gtk-X11-arch">window manager</link> or windowing
7949 * system. Otherwise, GDK will try to emulate window movement,
7950 * potentially not all that well, depending on the windowing system.
7954 gtk_window_begin_move_drag (GtkWindow *window,
7961 GdkWindow *toplevel;
7963 g_return_if_fail (GTK_IS_WINDOW (window));
7964 widget = GTK_WIDGET (window);
7965 g_return_if_fail (gtk_widget_get_visible (widget));
7967 toplevel = gtk_widget_get_window (widget);
7969 gdk_window_begin_move_drag (toplevel,
7976 * gtk_window_set_screen:
7977 * @window: a #GtkWindow.
7978 * @screen: a #GdkScreen.
7980 * Sets the #GdkScreen where the @window is displayed; if
7981 * the window is already mapped, it will be unmapped, and
7982 * then remapped on the new screen.
7987 gtk_window_set_screen (GtkWindow *window,
7990 GtkWindowPrivate *priv;
7992 GdkScreen *previous_screen;
7993 gboolean was_mapped;
7995 g_return_if_fail (GTK_IS_WINDOW (window));
7996 g_return_if_fail (GDK_IS_SCREEN (screen));
7998 priv = window->priv;
8000 if (screen == priv->screen)
8003 widget = GTK_WIDGET (window);
8005 previous_screen = priv->screen;
8006 was_mapped = gtk_widget_get_mapped (widget);
8009 gtk_widget_unmap (widget);
8010 if (gtk_widget_get_realized (widget))
8011 gtk_widget_unrealize (widget);
8013 gtk_window_free_key_hash (window);
8014 priv->screen = screen;
8015 gtk_widget_reset_rc_styles (widget);
8016 if (screen != previous_screen)
8018 if (previous_screen)
8020 g_signal_handlers_disconnect_by_func (previous_screen,
8021 gtk_window_on_composited_changed, window);
8022 #ifdef GDK_WINDOWING_X11
8023 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8024 gtk_window_on_theme_variant_changed, window);
8027 g_signal_connect (screen, "composited-changed",
8028 G_CALLBACK (gtk_window_on_composited_changed), window);
8029 #ifdef GDK_WINDOWING_X11
8030 g_signal_connect (gtk_settings_get_for_screen (screen),
8031 "notify::gtk-application-prefer-dark-theme",
8032 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8035 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8036 _gtk_widget_propagate_composited_changed (widget);
8038 g_object_notify (G_OBJECT (window), "screen");
8041 gtk_widget_map (widget);
8045 gtk_window_set_theme_variant (GtkWindow *window)
8047 #ifdef GDK_WINDOWING_X11
8048 GdkWindow *gdk_window;
8049 gboolean dark_theme_requested;
8051 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8052 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8055 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8057 if (GDK_IS_X11_WINDOW (gdk_window))
8058 gdk_x11_window_set_theme_variant (gdk_window,
8059 dark_theme_requested ? "dark" : NULL);
8064 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8068 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8069 gtk_window_set_theme_variant (window);
8073 gtk_window_on_composited_changed (GdkScreen *screen,
8076 gtk_widget_queue_draw (GTK_WIDGET (window));
8078 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8082 gtk_window_check_screen (GtkWindow *window)
8084 GtkWindowPrivate *priv = window->priv;
8087 return priv->screen;
8090 g_warning ("Screen for GtkWindow not set; you must always set\n"
8091 "a screen for a GtkWindow before using the window");
8097 * gtk_window_get_screen:
8098 * @window: a #GtkWindow.
8100 * Returns the #GdkScreen associated with @window.
8102 * Return value: (transfer none): a #GdkScreen.
8107 gtk_window_get_screen (GtkWindow *window)
8109 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8111 return window->priv->screen;
8115 * gtk_window_is_active:
8116 * @window: a #GtkWindow
8118 * Returns whether the window is part of the current active toplevel.
8119 * (That is, the toplevel window receiving keystrokes.)
8120 * The return value is %TRUE if the window is active toplevel
8121 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8122 * You might use this function if you wanted to draw a widget
8123 * differently in an active window from a widget in an inactive window.
8124 * See gtk_window_has_toplevel_focus()
8126 * Return value: %TRUE if the window part of the current active window.
8131 gtk_window_is_active (GtkWindow *window)
8133 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8135 return window->priv->is_active;
8139 * gtk_window_has_toplevel_focus:
8140 * @window: a #GtkWindow
8142 * Returns whether the input focus is within this GtkWindow.
8143 * For real toplevel windows, this is identical to gtk_window_is_active(),
8144 * but for embedded windows, like #GtkPlug, the results will differ.
8146 * Return value: %TRUE if the input focus is within this GtkWindow
8151 gtk_window_has_toplevel_focus (GtkWindow *window)
8153 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8155 return window->priv->has_toplevel_focus;
8158 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8161 gtk_window_group_init (GtkWindowGroup *group)
8163 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8164 GTK_TYPE_WINDOW_GROUP,
8165 GtkWindowGroupPrivate);
8169 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8171 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8175 * gtk_window_group_new:
8177 * Creates a new #GtkWindowGroup object. Grabs added with
8178 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8180 * Return value: a new #GtkWindowGroup.
8183 gtk_window_group_new (void)
8185 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8189 window_group_cleanup_grabs (GtkWindowGroup *group,
8192 GtkWindowGroupPrivate *priv;
8193 GtkDeviceGrabInfo *info;
8195 GSList *to_remove = NULL;
8199 tmp_list = priv->grabs;
8202 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8203 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8204 tmp_list = tmp_list->next;
8209 gtk_grab_remove (to_remove->data);
8210 g_object_unref (to_remove->data);
8211 to_remove = g_slist_delete_link (to_remove, to_remove);
8214 tmp_list = priv->device_grabs;
8218 info = tmp_list->data;
8220 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8221 to_remove = g_slist_prepend (to_remove, info);
8223 tmp_list = tmp_list->next;
8228 info = to_remove->data;
8230 gtk_device_grab_remove (info->widget, info->device);
8231 to_remove = g_slist_delete_link (to_remove, to_remove);
8236 * gtk_window_group_add_window:
8237 * @window_group: a #GtkWindowGroup
8238 * @window: the #GtkWindow to add
8240 * Adds a window to a #GtkWindowGroup.
8243 gtk_window_group_add_window (GtkWindowGroup *window_group,
8246 GtkWindowPrivate *priv;
8248 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8249 g_return_if_fail (GTK_IS_WINDOW (window));
8251 priv = window->priv;
8253 if (priv->group != window_group)
8255 g_object_ref (window);
8256 g_object_ref (window_group);
8259 gtk_window_group_remove_window (priv->group, window);
8261 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8263 priv->group = window_group;
8265 g_object_unref (window);
8270 * gtk_window_group_remove_window:
8271 * @window_group: a #GtkWindowGroup
8272 * @window: the #GtkWindow to remove
8274 * Removes a window from a #GtkWindowGroup.
8277 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8280 GtkWindowPrivate *priv;
8282 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8283 g_return_if_fail (GTK_IS_WINDOW (window));
8284 priv = window->priv;
8285 g_return_if_fail (priv->group == window_group);
8287 g_object_ref (window);
8289 window_group_cleanup_grabs (window_group, window);
8292 g_object_unref (window_group);
8293 g_object_unref (window);
8297 * gtk_window_group_list_windows:
8298 * @window_group: a #GtkWindowGroup
8300 * Returns a list of the #GtkWindows that belong to @window_group.
8302 * Returns: (element-type GtkWindow) (transfer container): A
8303 * newly-allocated list of windows inside the group.
8308 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8310 GList *toplevels, *toplevel, *group_windows;
8312 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8314 group_windows = NULL;
8315 toplevels = gtk_window_list_toplevels ();
8317 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8319 GtkWindow *window = toplevel->data;
8321 if (window_group == window->priv->group)
8322 group_windows = g_list_prepend (group_windows, window);
8325 g_list_free (toplevels);
8327 return g_list_reverse (group_windows);
8331 * gtk_window_get_group:
8332 * @window: (allow-none): a #GtkWindow, or %NULL
8334 * Returns the group for @window or the default group, if
8335 * @window is %NULL or if @window does not have an explicit
8338 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8343 gtk_window_get_group (GtkWindow *window)
8345 if (window && window->priv->group)
8346 return window->priv->group;
8349 static GtkWindowGroup *default_group = NULL;
8352 default_group = gtk_window_group_new ();
8354 return default_group;
8359 * gtk_window_has_group:
8360 * @window: a #GtkWindow
8362 * Returns whether @window has an explicit window group.
8364 * Return value: %TRUE if @window has an explicit window group.
8369 gtk_window_has_group (GtkWindow *window)
8371 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8373 return window->priv->group != NULL;
8377 * gtk_window_group_get_current_grab:
8378 * @window_group: a #GtkWindowGroup
8380 * Gets the current grab widget of the given group,
8381 * see gtk_grab_add().
8383 * Returns: (transfer none): the current grab widget of the group
8388 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8390 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8392 if (window_group->priv->grabs)
8393 return GTK_WIDGET (window_group->priv->grabs->data);
8398 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8401 GtkWindowGroupPrivate *priv;
8403 priv = window_group->priv;
8404 priv->grabs = g_slist_prepend (priv->grabs, widget);
8408 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8411 GtkWindowGroupPrivate *priv;
8413 priv = window_group->priv;
8414 priv->grabs = g_slist_remove (priv->grabs, widget);
8419 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8422 gboolean block_others)
8424 GtkWindowGroupPrivate *priv;
8425 GtkDeviceGrabInfo *info;
8427 priv = window_group->priv;
8429 info = g_slice_new0 (GtkDeviceGrabInfo);
8430 info->widget = widget;
8431 info->device = device;
8432 info->block_others = block_others;
8434 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8438 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8442 GtkWindowGroupPrivate *priv;
8443 GtkDeviceGrabInfo *info;
8444 GSList *list, *node = NULL;
8445 GdkDevice *other_device;
8447 priv = window_group->priv;
8448 other_device = gdk_device_get_associated_device (device);
8449 list = priv->device_grabs;
8455 if (info->widget == widget &&
8456 (info->device == device ||
8457 info->device == other_device))
8470 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8471 g_slice_free (GtkDeviceGrabInfo, info);
8476 * gtk_window_group_get_current_device_grab:
8477 * @window_group: a #GtkWindowGroup
8478 * @device: a #GdkDevice
8480 * Returns the current grab widget for @device, or %NULL if none.
8482 * Returns: (transfer none): The grab widget, or %NULL
8487 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8490 GtkWindowGroupPrivate *priv;
8491 GtkDeviceGrabInfo *info;
8492 GdkDevice *other_device;
8495 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8496 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8498 priv = window_group->priv;
8499 list = priv->device_grabs;
8500 other_device = gdk_device_get_associated_device (device);
8507 if (info->device == device ||
8508 info->device == other_device)
8509 return info->widget;
8516 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8520 GtkWindowGroupPrivate *priv;
8521 GtkDeviceGrabInfo *info;
8522 GdkDevice *other_device;
8525 priv = window_group->priv;
8526 other_device = gdk_device_get_associated_device (device);
8527 list = priv->device_grabs;
8534 /* Look for blocking grabs on other device pairs
8535 * that have the passed widget within the GTK+ grab.
8537 if (info->block_others &&
8538 info->device != device &&
8539 info->device != other_device &&
8540 (info->widget == widget ||
8541 gtk_widget_is_ancestor (widget, info->widget)))
8549 Derived from XParseGeometry() in XFree86
8551 Copyright 1985, 1986, 1987,1998 The Open Group
8553 All Rights Reserved.
8555 The above copyright notice and this permission notice shall be included
8556 in all copies or substantial portions of the Software.
8558 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8559 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8560 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8561 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8562 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8563 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8564 OTHER DEALINGS IN THE SOFTWARE.
8566 Except as contained in this notice, the name of The Open Group shall
8567 not be used in advertising or otherwise to promote the sale, use or
8568 other dealings in this Software without prior written authorization
8569 from The Open Group.
8574 * XParseGeometry parses strings of the form
8575 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8576 * width, height, xoffset, and yoffset are unsigned integers.
8577 * Example: "=80x24+300-49"
8578 * The equal sign is optional.
8579 * It returns a bitmask that indicates which of the four values
8580 * were actually found in the string. For each value found,
8581 * the corresponding argument is updated; for each value
8582 * not found, the corresponding argument is left unchanged.
8585 /* The following code is from Xlib, and is minimally modified, so we
8586 * can track any upstream changes if required. Don't change this
8587 * code. Or if you do, put in a huge comment marking which thing
8592 read_int (gchar *string,
8600 else if (*string == '-')
8606 for (; (*string >= '0') && (*string <= '9'); string++)
8608 result = (result * 10) + (*string - '0');
8620 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8621 * value (x, y, width, height) was found in the parsed string.
8623 #define NoValue 0x0000
8624 #define XValue 0x0001
8625 #define YValue 0x0002
8626 #define WidthValue 0x0004
8627 #define HeightValue 0x0008
8628 #define AllValues 0x000F
8629 #define XNegative 0x0010
8630 #define YNegative 0x0020
8632 /* Try not to reformat/modify, so we can compare/sync with X sources */
8634 gtk_XParseGeometry (const char *string,
8637 unsigned int *width,
8638 unsigned int *height)
8642 unsigned int tempWidth, tempHeight;
8644 char *nextCharacter;
8646 /* These initializations are just to silence gcc */
8652 if ( (string == NULL) || (*string == '\0')) return(mask);
8654 string++; /* ignore possible '=' at beg of geometry spec */
8656 strind = (char *)string;
8657 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8658 tempWidth = read_int(strind, &nextCharacter);
8659 if (strind == nextCharacter)
8661 strind = nextCharacter;
8665 if (*strind == 'x' || *strind == 'X') {
8667 tempHeight = read_int(strind, &nextCharacter);
8668 if (strind == nextCharacter)
8670 strind = nextCharacter;
8671 mask |= HeightValue;
8674 if ((*strind == '+') || (*strind == '-')) {
8675 if (*strind == '-') {
8677 tempX = -read_int(strind, &nextCharacter);
8678 if (strind == nextCharacter)
8680 strind = nextCharacter;
8686 tempX = read_int(strind, &nextCharacter);
8687 if (strind == nextCharacter)
8689 strind = nextCharacter;
8692 if ((*strind == '+') || (*strind == '-')) {
8693 if (*strind == '-') {
8695 tempY = -read_int(strind, &nextCharacter);
8696 if (strind == nextCharacter)
8698 strind = nextCharacter;
8705 tempY = read_int(strind, &nextCharacter);
8706 if (strind == nextCharacter)
8708 strind = nextCharacter;
8714 /* If strind isn't at the end of the string the it's an invalid
8715 geometry specification. */
8717 if (*strind != '\0') return (0);
8723 if (mask & WidthValue)
8725 if (mask & HeightValue)
8726 *height = tempHeight;
8731 * gtk_window_parse_geometry:
8732 * @window: a #GtkWindow
8733 * @geometry: geometry string
8735 * Parses a standard X Window System geometry string - see the
8736 * manual page for X (type 'man X') for details on this.
8737 * gtk_window_parse_geometry() does work on all GTK+ ports
8738 * including Win32 but is primarily intended for an X environment.
8740 * If either a size or a position can be extracted from the
8741 * geometry string, gtk_window_parse_geometry() returns %TRUE
8742 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8743 * to resize/move the window.
8745 * If gtk_window_parse_geometry() returns %TRUE, it will also
8746 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8747 * indicating to the window manager that the size/position of
8748 * the window was user-specified. This causes most window
8749 * managers to honor the geometry.
8751 * Note that for gtk_window_parse_geometry() to work as expected, it has
8752 * to be called when the window has its "final" size, i.e. after calling
8753 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8756 * #include <gtk/gtk.h>
8759 * fill_with_content (GtkWidget *vbox)
8761 * /* fill with content... */
8765 * main (int argc, char *argv[])
8767 * GtkWidget *window, *vbox;
8768 * GdkGeometry size_hints = {
8769 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8772 * gtk_init (&argc, &argv);
8774 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8775 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8777 * gtk_container_add (GTK_CONTAINER (window), vbox);
8778 * fill_with_content (vbox);
8779 * gtk_widget_show_all (vbox);
8781 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8784 * GDK_HINT_MIN_SIZE |
8785 * GDK_HINT_BASE_SIZE |
8786 * GDK_HINT_RESIZE_INC);
8790 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8791 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8794 * gtk_widget_show_all (window);
8801 * Return value: %TRUE if string was parsed successfully
8804 gtk_window_parse_geometry (GtkWindow *window,
8805 const gchar *geometry)
8807 gint result, x = 0, y = 0;
8811 gboolean size_set, pos_set;
8814 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8815 g_return_val_if_fail (geometry != NULL, FALSE);
8817 child = gtk_bin_get_child (GTK_BIN (window));
8818 if (!child || !gtk_widget_get_visible (child))
8819 g_warning ("gtk_window_parse_geometry() called on a window with no "
8820 "visible children; the window should be set up before "
8821 "gtk_window_parse_geometry() is called.");
8823 screen = gtk_window_check_screen (window);
8825 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8828 if ((result & WidthValue) || (result & HeightValue))
8830 gtk_window_set_default_size_internal (window,
8831 TRUE, result & WidthValue ? w : -1,
8832 TRUE, result & HeightValue ? h : -1,
8837 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8839 grav = GDK_GRAVITY_NORTH_WEST;
8841 if ((result & XNegative) && (result & YNegative))
8842 grav = GDK_GRAVITY_SOUTH_EAST;
8843 else if (result & XNegative)
8844 grav = GDK_GRAVITY_NORTH_EAST;
8845 else if (result & YNegative)
8846 grav = GDK_GRAVITY_SOUTH_WEST;
8848 if ((result & XValue) == 0)
8851 if ((result & YValue) == 0)
8854 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8855 grav == GDK_GRAVITY_SOUTH_EAST)
8856 y = gdk_screen_get_height (screen) - h + y;
8858 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8859 grav == GDK_GRAVITY_NORTH_EAST)
8860 x = gdk_screen_get_width (screen) - w + x;
8862 /* we don't let you put a window offscreen; maybe some people would
8863 * prefer to be able to, but it's kind of a bogus thing to do.
8872 if ((result & XValue) || (result & YValue))
8874 gtk_window_set_gravity (window, grav);
8875 gtk_window_move (window, x, y);
8879 if (size_set || pos_set)
8881 /* Set USSize, USPosition hints */
8882 GtkWindowGeometryInfo *info;
8884 info = gtk_window_get_geometry_info (window, TRUE);
8887 info->mask |= GDK_HINT_USER_POS;
8889 info->mask |= GDK_HINT_USER_SIZE;
8896 gtk_window_mnemonic_hash_foreach (guint keyval,
8902 GtkWindowKeysForeachFunc func;
8906 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8910 _gtk_window_keys_foreach (GtkWindow *window,
8911 GtkWindowKeysForeachFunc func,
8915 GtkMnemonicHash *mnemonic_hash;
8919 GtkWindowKeysForeachFunc func;
8923 info.window = window;
8925 info.func_data = func_data;
8927 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8929 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8930 gtk_window_mnemonic_hash_foreach, &info);
8932 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8935 GtkAccelGroup *group = groups->data;
8938 for (i = 0; i < group->priv->n_accels; i++)
8940 GtkAccelKey *key = &group->priv->priv_accels[i].key;
8943 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8946 groups = groups->next;
8951 gtk_window_keys_changed (GtkWindow *window)
8953 gtk_window_free_key_hash (window);
8954 gtk_window_get_key_hash (window);
8957 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8959 struct _GtkWindowKeyEntry
8963 guint is_mnemonic : 1;
8967 window_key_entry_destroy (gpointer data)
8969 g_slice_free (GtkWindowKeyEntry, data);
8973 add_to_key_hash (GtkWindow *window,
8975 GdkModifierType modifiers,
8976 gboolean is_mnemonic,
8979 GtkKeyHash *key_hash = data;
8981 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8983 entry->keyval = keyval;
8984 entry->modifiers = modifiers;
8985 entry->is_mnemonic = is_mnemonic;
8987 /* GtkAccelGroup stores lowercased accelerators. To deal
8988 * with this, if <Shift> was specified, uppercase.
8990 if (modifiers & GDK_SHIFT_MASK)
8992 if (keyval == GDK_KEY_Tab)
8993 keyval = GDK_KEY_ISO_Left_Tab;
8995 keyval = gdk_keyval_to_upper (keyval);
8998 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9002 gtk_window_get_key_hash (GtkWindow *window)
9004 GdkScreen *screen = gtk_window_check_screen (window);
9005 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9010 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9011 (GDestroyNotify)window_key_entry_destroy);
9012 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9013 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9019 gtk_window_free_key_hash (GtkWindow *window)
9021 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9024 _gtk_key_hash_free (key_hash);
9025 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9030 * gtk_window_activate_key:
9031 * @window: a #GtkWindow
9032 * @event: a #GdkEventKey
9034 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9035 * called by the default ::key_press_event handler for toplevel windows,
9036 * however in some cases it may be useful to call this directly when
9037 * overriding the standard key handling for a toplevel window.
9039 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9044 gtk_window_activate_key (GtkWindow *window,
9047 GtkKeyHash *key_hash;
9048 GtkWindowKeyEntry *found_entry = NULL;
9049 gboolean enable_mnemonics;
9050 gboolean enable_accels;
9052 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9053 g_return_val_if_fail (event != NULL, FALSE);
9055 key_hash = gtk_window_get_key_hash (window);
9060 GSList *entries = _gtk_key_hash_lookup (key_hash,
9061 event->hardware_keycode,
9063 gtk_accelerator_get_default_mod_mask (),
9066 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9067 "gtk-enable-mnemonics", &enable_mnemonics,
9068 "gtk-enable-accels", &enable_accels,
9071 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9073 GtkWindowKeyEntry *entry = tmp_list->data;
9074 if (entry->is_mnemonic)
9076 if (enable_mnemonics)
9078 found_entry = entry;
9084 if (enable_accels && !found_entry)
9086 found_entry = entry;
9091 g_slist_free (entries);
9096 if (found_entry->is_mnemonic)
9098 if (enable_mnemonics)
9099 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9100 found_entry->modifiers);
9105 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9106 found_entry->modifiers);
9114 window_update_has_focus (GtkWindow *window)
9116 GtkWindowPrivate *priv = window->priv;
9117 GtkWidget *widget = GTK_WIDGET (window);
9118 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9120 if (has_focus != priv->has_focus)
9122 priv->has_focus = has_focus;
9126 if (priv->focus_widget &&
9127 priv->focus_widget != widget &&
9128 !gtk_widget_has_focus (priv->focus_widget))
9129 do_focus_change (priv->focus_widget, TRUE);
9133 if (priv->focus_widget &&
9134 priv->focus_widget != widget &&
9135 gtk_widget_has_focus (priv->focus_widget))
9136 do_focus_change (priv->focus_widget, FALSE);
9142 * _gtk_window_set_is_active:
9143 * @window: a #GtkWindow
9144 * @is_active: %TRUE if the window is in the currently active toplevel
9146 * Internal function that sets whether the #GtkWindow is part
9147 * of the currently active toplevel window (taking into account inter-process
9151 _gtk_window_set_is_active (GtkWindow *window,
9154 GtkWindowPrivate *priv;
9156 g_return_if_fail (GTK_IS_WINDOW (window));
9158 priv = window->priv;
9160 is_active = is_active != FALSE;
9162 if (is_active != priv->is_active)
9164 priv->is_active = is_active;
9165 window_update_has_focus (window);
9167 g_object_notify (G_OBJECT (window), "is-active");
9172 * _gtk_window_set_is_toplevel:
9173 * @window: a #GtkWindow
9174 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9175 * child of the root window); %FALSE if it is not (for example, for an
9176 * in-process, parented GtkPlug)
9178 * Internal function used by #GtkPlug when it gets parented/unparented by a
9179 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9180 * global list of toplevel windows.
9183 _gtk_window_set_is_toplevel (GtkWindow *window,
9184 gboolean is_toplevel)
9187 GtkWidget *toplevel;
9189 widget = GTK_WIDGET (window);
9191 if (gtk_widget_is_toplevel (widget))
9192 g_assert (g_slist_find (toplevel_list, window) != NULL);
9194 g_assert (g_slist_find (toplevel_list, window) == NULL);
9196 if (is_toplevel == gtk_widget_is_toplevel (widget))
9201 /* Pass through regular pathways of an embedded toplevel
9202 * to go through unmapping and hiding the widget before
9203 * becomming a toplevel again.
9205 * We remain hidden after becomming toplevel in order to
9206 * avoid problems during an embedded toplevel's dispose cycle
9207 * (When a toplevel window is shown it tries to grab focus again,
9208 * this causes problems while disposing).
9210 gtk_widget_hide (widget);
9212 /* Save the toplevel this widget was previously anchored into before
9213 * propagating a hierarchy-changed.
9215 * Usually this happens by way of gtk_widget_unparent() and we are
9216 * already unanchored at this point, just adding this clause incase
9217 * things happen differently.
9219 toplevel = gtk_widget_get_toplevel (widget);
9220 if (!gtk_widget_is_toplevel (toplevel))
9223 _gtk_widget_set_is_toplevel (widget, TRUE);
9225 /* When a window becomes toplevel after being embedded and anchored
9226 * into another window we need to unset its anchored flag so that
9227 * the hierarchy changed signal kicks in properly.
9229 _gtk_widget_set_anchored (widget, FALSE);
9230 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9232 toplevel_list = g_slist_prepend (toplevel_list, window);
9236 _gtk_widget_set_is_toplevel (widget, FALSE);
9237 toplevel_list = g_slist_remove (toplevel_list, window);
9239 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9244 * _gtk_window_set_has_toplevel_focus:
9245 * @window: a #GtkWindow
9246 * @has_toplevel_focus: %TRUE if the in
9248 * Internal function that sets whether the keyboard focus for the
9249 * toplevel window (taking into account inter-process embedding.)
9252 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9253 gboolean has_toplevel_focus)
9255 GtkWindowPrivate *priv;
9257 g_return_if_fail (GTK_IS_WINDOW (window));
9259 priv = window->priv;
9261 has_toplevel_focus = has_toplevel_focus != FALSE;
9263 if (has_toplevel_focus != priv->has_toplevel_focus)
9265 priv->has_toplevel_focus = has_toplevel_focus;
9266 window_update_has_focus (window);
9268 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9273 * gtk_window_set_auto_startup_notification:
9274 * @setting: %TRUE to automatically do startup notification
9276 * By default, after showing the first #GtkWindow, GTK+ calls
9277 * gdk_notify_startup_complete(). Call this function to disable
9278 * the automatic startup notification. You might do this if your
9279 * first window is a splash screen, and you want to delay notification
9280 * until after your real main window has been shown, for example.
9282 * In that example, you would disable startup notification
9283 * temporarily, show your splash screen, then re-enable it so that
9284 * showing the main window would automatically result in notification.
9289 gtk_window_set_auto_startup_notification (gboolean setting)
9291 disable_startup_notification = !setting;
9295 * gtk_window_get_window_type:
9296 * @window: a #GtkWindow
9298 * Gets the type of the window. See #GtkWindowType.
9300 * Return value: the type of the window
9305 gtk_window_get_window_type (GtkWindow *window)
9307 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9309 return window->priv->type;
9313 * gtk_window_get_mnemonics_visible:
9314 * @window: a #GtkWindow
9316 * Gets the value of the #GtkWindow:mnemonics-visible property.
9318 * Returns: %TRUE if mnemonics are supposed to be visible
9324 gtk_window_get_mnemonics_visible (GtkWindow *window)
9326 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9328 return window->priv->mnemonics_visible;
9332 * gtk_window_set_mnemonics_visible:
9333 * @window: a #GtkWindow
9334 * @setting: the new value
9336 * Sets the #GtkWindow:mnemonics-visible property.
9341 gtk_window_set_mnemonics_visible (GtkWindow *window,
9344 GtkWindowPrivate *priv;
9346 g_return_if_fail (GTK_IS_WINDOW (window));
9348 priv = window->priv;
9350 setting = setting != FALSE;
9352 if (priv->mnemonics_visible != setting)
9354 priv->mnemonics_visible = setting;
9355 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9358 priv->mnemonics_visible_set = TRUE;
9362 _gtk_window_get_wmclass (GtkWindow *window,
9363 gchar **wmclass_name,
9364 gchar **wmclass_class)
9366 GtkWindowPrivate *priv = window->priv;
9368 *wmclass_name = priv->wmclass_name;
9369 *wmclass_class = priv->wmclass_class;
9373 * gtk_window_set_has_user_ref_count:
9374 * @window: a #GtkWindow
9375 * @setting: the new value
9377 * Tells GTK+ whether to drop its extra reference to the window
9378 * when gtk_window_destroy() is called.
9380 * This function is only exported for the benefit of language
9381 * bindings which may need to keep the window alive until their
9382 * wrapper object is garbage collected. There is no justification
9383 * for ever calling this function in an application.
9388 gtk_window_set_has_user_ref_count (GtkWindow *window,
9391 g_return_if_fail (GTK_IS_WINDOW (window));
9393 window->priv->has_user_ref_count = setting;