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 GdkModifierType mnemonic_modifier;
113 GdkWindowTypeHint gdk_type_hint;
115 GtkApplication *application;
119 GdkWindow *grip_window;
123 gchar *wmclass_class;
127 guint keys_changed_handler;
129 guint16 configure_request_count;
131 /* The following flags are initially TRUE (before a window is mapped).
132 * They cause us to compute a configure request that involves
133 * default-only parameters. Once mapped, we set them to FALSE.
134 * Then we set them to TRUE again on unmap (for position)
135 * and on unrealize (for size).
137 guint need_default_position : 1;
138 guint need_default_size : 1;
140 guint above_initially : 1;
141 guint accept_focus : 1;
142 guint below_initially : 1;
143 guint builder_visible : 1;
144 guint configure_notify_received : 1;
147 guint destroy_with_parent : 1;
148 guint focus_on_map : 1;
149 guint fullscreen_initially : 1;
150 guint gravity : 5; /* GdkGravity */
152 guint has_user_ref_count : 1;
153 guint has_toplevel_focus : 1;
154 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
156 guint maximize_initially : 1;
157 guint mnemonics_visible : 1;
158 guint mnemonics_visible_set : 1;
160 guint opacity_set : 1;
162 guint reset_type_hint : 1;
164 guint skips_pager : 1;
165 guint skips_taskbar : 1;
166 guint stick_initially : 1;
167 guint transient_parent_group : 1;
168 guint type : 4; /* GtkWindowType */
169 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
170 * one of the original eight. If not,
172 * GDK_WINDOW_TYPE_HINT_NORMAL
175 guint has_resize_grip : 1;
176 guint resize_grip_visible : 1; /* don't use, just for "resize-
177 * grip-visible" notification
205 PROP_DESTROY_WITH_PARENT,
210 PROP_SKIP_TASKBAR_HINT,
211 PROP_SKIP_PAGER_HINT,
220 PROP_HAS_RESIZE_GRIP,
221 PROP_RESIZE_GRIP_VISIBLE,
223 /* Readonly properties */
225 PROP_HAS_TOPLEVEL_FOCUS,
227 /* Writeonly properties */
230 PROP_MNEMONICS_VISIBLE,
240 guint using_default_icon : 1;
241 guint using_parent_icon : 1;
242 guint using_themed_icon : 1;
246 GdkGeometry geometry; /* Last set of geometry hints we set */
247 GdkWindowHints flags;
248 GdkRectangle configure_request;
249 } GtkWindowLastGeometryInfo;
251 struct _GtkWindowGeometryInfo
253 /* Properties that the app has set on the window
255 GdkGeometry geometry; /* Geometry hints */
257 GtkWidget *widget; /* subwidget to which hints apply */
258 /* from last gtk_window_resize () - if > 0, indicates that
259 * we should resize to this size.
264 /* From last gtk_window_move () prior to mapping -
265 * only used if initial_pos_set
270 /* Default size - used only the FIRST time we map a window,
275 /* whether to use initial_x, initial_y */
276 guint initial_pos_set : 1;
277 /* CENTER_ALWAYS or other position constraint changed since
278 * we sent the last configure request.
280 guint position_constraints_changed : 1;
282 /* if true, default_width, height should be multiplied by the
283 * increments and affect the geometry widget only
285 guint default_is_geometry : 1;
287 /* if true, resize_width, height should be multiplied by the
288 * increments and affect the geometry widget only
290 guint resize_is_geometry : 1;
292 GtkWindowLastGeometryInfo last;
296 struct _GtkDeviceGrabInfo
300 guint block_others : 1;
303 struct _GtkWindowGroupPrivate
306 GSList *device_grabs;
309 static void gtk_window_dispose (GObject *object);
310 static void gtk_window_finalize (GObject *object);
311 static void gtk_window_destroy (GtkWidget *widget);
312 static void gtk_window_show (GtkWidget *widget);
313 static void gtk_window_hide (GtkWidget *widget);
314 static void gtk_window_map (GtkWidget *widget);
315 static void gtk_window_unmap (GtkWidget *widget);
316 static void gtk_window_realize (GtkWidget *widget);
317 static void gtk_window_unrealize (GtkWidget *widget);
318 static void gtk_window_size_allocate (GtkWidget *widget,
319 GtkAllocation *allocation);
320 static gboolean gtk_window_map_event (GtkWidget *widget,
322 static gint gtk_window_configure_event (GtkWidget *widget,
323 GdkEventConfigure *event);
324 static gint gtk_window_key_press_event (GtkWidget *widget,
326 static gint gtk_window_key_release_event (GtkWidget *widget,
328 static gint gtk_window_button_press_event (GtkWidget *widget,
329 GdkEventButton *event);
330 static gint gtk_window_enter_notify_event (GtkWidget *widget,
331 GdkEventCrossing *event);
332 static gint gtk_window_leave_notify_event (GtkWidget *widget,
333 GdkEventCrossing *event);
334 static gint gtk_window_focus_in_event (GtkWidget *widget,
335 GdkEventFocus *event);
336 static gint gtk_window_focus_out_event (GtkWidget *widget,
337 GdkEventFocus *event);
338 static void gtk_window_style_updated (GtkWidget *widget);
339 static gboolean gtk_window_state_event (GtkWidget *widget,
340 GdkEventWindowState *event);
341 static void gtk_window_check_resize (GtkContainer *container);
342 static gint gtk_window_focus (GtkWidget *widget,
343 GtkDirectionType direction);
344 static void gtk_window_move_focus (GtkWidget *widget,
345 GtkDirectionType dir);
346 static void gtk_window_real_set_focus (GtkWindow *window,
348 static void gtk_window_direction_changed (GtkWidget *widget,
349 GtkTextDirection prev_dir);
350 static void gtk_window_state_changed (GtkWidget *widget,
351 GtkStateType previous_state);
353 static void gtk_window_real_activate_default (GtkWindow *window);
354 static void gtk_window_real_activate_focus (GtkWindow *window);
355 static void gtk_window_keys_changed (GtkWindow *window);
356 static gint gtk_window_draw (GtkWidget *widget,
358 static void gtk_window_unset_transient_for (GtkWindow *window);
359 static void gtk_window_transient_parent_realized (GtkWidget *parent,
361 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
364 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
366 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
369 static void gtk_window_move_resize (GtkWindow *window);
370 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
372 GdkGeometry *geometry_b,
374 static void gtk_window_constrain_size (GtkWindow *window,
375 GdkGeometry *geometry,
381 static void gtk_window_constrain_position (GtkWindow *window,
386 static void gtk_window_compute_hints (GtkWindow *window,
387 GdkGeometry *new_geometry,
389 static void gtk_window_compute_configure_request (GtkWindow *window,
390 GdkRectangle *request,
391 GdkGeometry *geometry,
394 static void gtk_window_set_default_size_internal (GtkWindow *window,
395 gboolean change_width,
397 gboolean change_height,
399 gboolean is_geometry);
401 static void update_themed_icon (GtkIconTheme *theme,
403 static GList *icon_list_from_theme (GtkWidget *widget,
405 static void gtk_window_realize_icon (GtkWindow *window);
406 static void gtk_window_unrealize_icon (GtkWindow *window);
407 static void resize_grip_create_window (GtkWindow *window);
408 static void resize_grip_destroy_window (GtkWindow *window);
409 static void update_grip_visibility (GtkWindow *window);
411 static void gtk_window_notify_keys_changed (GtkWindow *window);
412 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
413 static void gtk_window_free_key_hash (GtkWindow *window);
414 static void gtk_window_on_composited_changed (GdkScreen *screen,
417 static GSList *toplevel_list = NULL;
418 static guint window_signals[LAST_SIGNAL] = { 0 };
419 static GList *default_icon_list = NULL;
420 static gchar *default_icon_name = NULL;
421 static guint default_icon_serial = 0;
422 static gboolean disable_startup_notification = FALSE;
423 static gboolean sent_startup_notification = FALSE;
425 static GQuark quark_gtk_embedded = 0;
426 static GQuark quark_gtk_window_key_hash = 0;
427 static GQuark quark_gtk_window_icon_info = 0;
428 static GQuark quark_gtk_buildable_accels = 0;
430 static GtkBuildableIface *parent_buildable_iface;
432 static void gtk_window_set_property (GObject *object,
436 static void gtk_window_get_property (GObject *object,
442 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
443 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
446 const GValue *value);
447 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
448 GtkBuilder *builder);
449 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
452 const gchar *tagname,
453 GMarkupParser *parser,
455 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
458 const gchar *tagname,
462 static void gtk_window_get_preferred_width (GtkWidget *widget,
465 static void gtk_window_get_preferred_height (GtkWidget *widget,
469 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
470 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
471 gtk_window_buildable_interface_init))
474 add_tab_bindings (GtkBindingSet *binding_set,
475 GdkModifierType modifiers,
476 GtkDirectionType direction)
478 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
480 GTK_TYPE_DIRECTION_TYPE, direction);
481 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
483 GTK_TYPE_DIRECTION_TYPE, direction);
487 add_arrow_bindings (GtkBindingSet *binding_set,
489 GtkDirectionType direction)
491 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
493 gtk_binding_entry_add_signal (binding_set, keysym, 0,
495 GTK_TYPE_DIRECTION_TYPE, direction);
496 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
498 GTK_TYPE_DIRECTION_TYPE, direction);
499 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
501 GTK_TYPE_DIRECTION_TYPE, direction);
502 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
504 GTK_TYPE_DIRECTION_TYPE, direction);
508 extract_time_from_startup_id (const gchar* startup_id)
510 gchar *timestr = g_strrstr (startup_id, "_TIME");
511 guint32 retval = GDK_CURRENT_TIME;
518 /* Skip past the "_TIME" part */
523 timestamp = g_ascii_strtoull (timestr, &end, 0);
524 if (errno == 0 && end != timestr)
532 startup_id_is_fake (const gchar* startup_id)
534 return strncmp (startup_id, "_TIME", 5) == 0;
538 gtk_window_class_init (GtkWindowClass *klass)
540 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
541 GtkWidgetClass *widget_class;
542 GtkContainerClass *container_class;
543 GtkBindingSet *binding_set;
545 widget_class = (GtkWidgetClass*) klass;
546 container_class = (GtkContainerClass*) klass;
548 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
549 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
550 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
551 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
553 gobject_class->dispose = gtk_window_dispose;
554 gobject_class->finalize = gtk_window_finalize;
556 gobject_class->set_property = gtk_window_set_property;
557 gobject_class->get_property = gtk_window_get_property;
559 widget_class->destroy = gtk_window_destroy;
560 widget_class->show = gtk_window_show;
561 widget_class->hide = gtk_window_hide;
562 widget_class->map = gtk_window_map;
563 widget_class->map_event = gtk_window_map_event;
564 widget_class->unmap = gtk_window_unmap;
565 widget_class->realize = gtk_window_realize;
566 widget_class->unrealize = gtk_window_unrealize;
567 widget_class->size_allocate = gtk_window_size_allocate;
568 widget_class->configure_event = gtk_window_configure_event;
569 widget_class->key_press_event = gtk_window_key_press_event;
570 widget_class->key_release_event = gtk_window_key_release_event;
571 widget_class->enter_notify_event = gtk_window_enter_notify_event;
572 widget_class->leave_notify_event = gtk_window_leave_notify_event;
573 widget_class->focus_in_event = gtk_window_focus_in_event;
574 widget_class->button_press_event = gtk_window_button_press_event;
575 widget_class->focus_out_event = gtk_window_focus_out_event;
576 widget_class->focus = gtk_window_focus;
577 widget_class->move_focus = gtk_window_move_focus;
578 widget_class->draw = gtk_window_draw;
579 widget_class->get_preferred_width = gtk_window_get_preferred_width;
580 widget_class->get_preferred_height = gtk_window_get_preferred_height;
581 widget_class->window_state_event = gtk_window_state_event;
582 widget_class->direction_changed = gtk_window_direction_changed;
583 widget_class->state_changed = gtk_window_state_changed;
584 widget_class->style_updated = gtk_window_style_updated;
586 container_class->check_resize = gtk_window_check_resize;
588 klass->set_focus = gtk_window_real_set_focus;
590 klass->activate_default = gtk_window_real_activate_default;
591 klass->activate_focus = gtk_window_real_activate_focus;
592 klass->keys_changed = gtk_window_keys_changed;
594 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
597 g_object_class_install_property (gobject_class,
599 g_param_spec_enum ("type",
601 P_("The type of the window"),
602 GTK_TYPE_WINDOW_TYPE,
604 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
606 g_object_class_install_property (gobject_class,
608 g_param_spec_string ("title",
610 P_("The title of the window"),
612 GTK_PARAM_READWRITE));
614 g_object_class_install_property (gobject_class,
616 g_param_spec_string ("role",
618 P_("Unique identifier for the window to be used when restoring a session"),
620 GTK_PARAM_READWRITE));
623 * GtkWindow:startup-id:
625 * The :startup-id is a write-only property for setting window's
626 * startup notification identifier. See gtk_window_set_startup_id()
631 g_object_class_install_property (gobject_class,
633 g_param_spec_string ("startup-id",
635 P_("Unique startup identifier for the window used by startup-notification"),
637 GTK_PARAM_WRITABLE));
639 g_object_class_install_property (gobject_class,
641 g_param_spec_boolean ("resizable",
643 P_("If TRUE, users can resize the window"),
645 GTK_PARAM_READWRITE));
647 g_object_class_install_property (gobject_class,
649 g_param_spec_boolean ("modal",
651 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
653 GTK_PARAM_READWRITE));
655 g_object_class_install_property (gobject_class,
657 g_param_spec_enum ("window-position",
658 P_("Window Position"),
659 P_("The initial position of the window"),
660 GTK_TYPE_WINDOW_POSITION,
662 GTK_PARAM_READWRITE));
664 g_object_class_install_property (gobject_class,
666 g_param_spec_int ("default-width",
668 P_("The default width of the window, used when initially showing the window"),
672 GTK_PARAM_READWRITE));
674 g_object_class_install_property (gobject_class,
676 g_param_spec_int ("default-height",
677 P_("Default Height"),
678 P_("The default height of the window, used when initially showing the window"),
682 GTK_PARAM_READWRITE));
684 g_object_class_install_property (gobject_class,
685 PROP_DESTROY_WITH_PARENT,
686 g_param_spec_boolean ("destroy-with-parent",
687 P_("Destroy with Parent"),
688 P_("If this window should be destroyed when the parent is destroyed"),
690 GTK_PARAM_READWRITE));
692 g_object_class_install_property (gobject_class,
694 g_param_spec_object ("icon",
696 P_("Icon for this window"),
698 GTK_PARAM_READWRITE));
699 g_object_class_install_property (gobject_class,
700 PROP_MNEMONICS_VISIBLE,
701 g_param_spec_boolean ("mnemonics-visible",
702 P_("Mnemonics Visible"),
703 P_("Whether mnemonics are currently visible in this window"),
705 GTK_PARAM_READWRITE));
708 * GtkWindow:icon-name:
710 * The :icon-name property specifies the name of the themed icon to
711 * use as the window icon. See #GtkIconTheme for more details.
715 g_object_class_install_property (gobject_class,
717 g_param_spec_string ("icon-name",
719 P_("Name of the themed icon for this window"),
721 GTK_PARAM_READWRITE));
723 g_object_class_install_property (gobject_class,
725 g_param_spec_object ("screen",
727 P_("The screen where this window will be displayed"),
729 GTK_PARAM_READWRITE));
731 g_object_class_install_property (gobject_class,
733 g_param_spec_boolean ("is-active",
735 P_("Whether the toplevel is the current active window"),
737 GTK_PARAM_READABLE));
739 g_object_class_install_property (gobject_class,
740 PROP_HAS_TOPLEVEL_FOCUS,
741 g_param_spec_boolean ("has-toplevel-focus",
742 P_("Focus in Toplevel"),
743 P_("Whether the input focus is within this GtkWindow"),
745 GTK_PARAM_READABLE));
747 g_object_class_install_property (gobject_class,
749 g_param_spec_enum ("type-hint",
751 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
752 GDK_TYPE_WINDOW_TYPE_HINT,
753 GDK_WINDOW_TYPE_HINT_NORMAL,
754 GTK_PARAM_READWRITE));
756 g_object_class_install_property (gobject_class,
757 PROP_SKIP_TASKBAR_HINT,
758 g_param_spec_boolean ("skip-taskbar-hint",
760 P_("TRUE if the window should not be in the task bar."),
762 GTK_PARAM_READWRITE));
764 g_object_class_install_property (gobject_class,
765 PROP_SKIP_PAGER_HINT,
766 g_param_spec_boolean ("skip-pager-hint",
768 P_("TRUE if the window should not be in the pager."),
770 GTK_PARAM_READWRITE));
772 g_object_class_install_property (gobject_class,
774 g_param_spec_boolean ("urgency-hint",
776 P_("TRUE if the window should be brought to the user's attention."),
778 GTK_PARAM_READWRITE));
781 * GtkWindow:accept-focus:
783 * Whether the window should receive the input focus.
787 g_object_class_install_property (gobject_class,
789 g_param_spec_boolean ("accept-focus",
791 P_("TRUE if the window should receive the input focus."),
793 GTK_PARAM_READWRITE));
796 * GtkWindow:focus-on-map:
798 * Whether the window should receive the input focus when mapped.
802 g_object_class_install_property (gobject_class,
804 g_param_spec_boolean ("focus-on-map",
806 P_("TRUE if the window should receive the input focus when mapped."),
808 GTK_PARAM_READWRITE));
811 * GtkWindow:decorated:
813 * Whether the window should be decorated by the window manager.
817 g_object_class_install_property (gobject_class,
819 g_param_spec_boolean ("decorated",
821 P_("Whether the window should be decorated by the window manager"),
823 GTK_PARAM_READWRITE));
826 * GtkWindow:deletable:
828 * Whether the window frame should have a close button.
832 g_object_class_install_property (gobject_class,
834 g_param_spec_boolean ("deletable",
836 P_("Whether the window frame should have a close button"),
838 GTK_PARAM_READWRITE));
841 * GtkWindow:has-resize-grip
843 * Whether the window has a corner resize grip.
845 * Note that the resize grip is only shown if the window is
846 * actually resizable and not maximized. Use
847 * #GtkWindow:resize-grip-visible to find out if the resize
848 * grip is currently shown.
852 g_object_class_install_property (gobject_class,
853 PROP_HAS_RESIZE_GRIP,
854 g_param_spec_boolean ("has-resize-grip",
856 P_("Specifies whether the window should have a resize grip"),
858 GTK_PARAM_READWRITE));
861 * GtkWindow:resize-grip-visible:
863 * Whether a corner resize grip is currently shown.
867 g_object_class_install_property (gobject_class,
868 PROP_RESIZE_GRIP_VISIBLE,
869 g_param_spec_boolean ("resize-grip-visible",
870 P_("Resize grip is visible"),
871 P_("Specifies whether the window's resize grip is visible."),
873 GTK_PARAM_READABLE));
879 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
880 * more details about window gravity.
884 g_object_class_install_property (gobject_class,
886 g_param_spec_enum ("gravity",
888 P_("The window gravity of the window"),
890 GDK_GRAVITY_NORTH_WEST,
891 GTK_PARAM_READWRITE));
895 * GtkWindow:transient-for:
897 * The transient parent of the window. See gtk_window_set_transient_for() for
898 * more details about transient windows.
902 g_object_class_install_property (gobject_class,
904 g_param_spec_object ("transient-for",
905 P_("Transient for Window"),
906 P_("The transient parent of the dialog"),
908 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
913 * The requested opacity of the window. See gtk_window_set_opacity() for
914 * more details about window opacity.
918 g_object_class_install_property (gobject_class,
920 g_param_spec_double ("opacity",
921 P_("Opacity for Window"),
922 P_("The opacity of the window, from 0 to 1"),
926 GTK_PARAM_READWRITE));
930 gtk_widget_class_install_style_property (widget_class,
931 g_param_spec_int ("resize-grip-width",
932 P_("Width of resize grip"),
933 P_("Width of resize grip"),
934 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
936 gtk_widget_class_install_style_property (widget_class,
937 g_param_spec_int ("resize-grip-height",
938 P_("Height of resize grip"),
939 P_("Height of resize grip"),
940 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
944 * GtkWindow:application:
946 * The #GtkApplication associated with the window.
948 * The application will be kept alive for at least as long as it
949 * has any windows associated with it (see g_application_hold()
950 * for a way to keep it alive without windows).
952 * Normally, the connection between the application and the window
953 * will remain until the window is destroyed, but you can explicitly
954 * remove it by setting the ::application property to %NULL.
958 g_object_class_install_property (gobject_class,
960 g_param_spec_object ("application",
961 P_("GtkApplication"),
962 P_("The GtkApplication for the window"),
963 GTK_TYPE_APPLICATION,
964 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
966 window_signals[SET_FOCUS] =
967 g_signal_new (I_("set-focus"),
968 G_TYPE_FROM_CLASS (gobject_class),
970 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
972 _gtk_marshal_VOID__OBJECT,
977 * GtkWindow::activate-focus:
978 * @window: the window which received the signal
980 * The ::activate-focus signal is a
981 * <link linkend="keybinding-signals">keybinding signal</link>
982 * which gets emitted when the user activates the currently
983 * focused widget of @window.
985 window_signals[ACTIVATE_FOCUS] =
986 g_signal_new (I_("activate-focus"),
987 G_TYPE_FROM_CLASS (gobject_class),
988 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
989 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
991 _gtk_marshal_VOID__VOID,
996 * GtkWindow::activate-default:
997 * @window: the window which received the signal
999 * The ::activate-default signal is a
1000 * <link linkend="keybinding-signals">keybinding signal</link>
1001 * which gets emitted when the user activates the default widget
1004 window_signals[ACTIVATE_DEFAULT] =
1005 g_signal_new (I_("activate-default"),
1006 G_TYPE_FROM_CLASS (gobject_class),
1007 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1008 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1010 _gtk_marshal_VOID__VOID,
1015 * GtkWindow::keys-changed:
1016 * @window: the window which received the signal
1018 * The ::keys-changed signal gets emitted when the set of accelerators
1019 * or mnemonics that are associated with @window changes.
1021 window_signals[KEYS_CHANGED] =
1022 g_signal_new (I_("keys-changed"),
1023 G_TYPE_FROM_CLASS (gobject_class),
1025 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1027 _gtk_marshal_VOID__VOID,
1035 binding_set = gtk_binding_set_by_class (klass);
1037 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1038 "activate-focus", 0);
1039 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1040 "activate-focus", 0);
1042 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1043 "activate-default", 0);
1044 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1045 "activate-default", 0);
1046 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1047 "activate-default", 0);
1049 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1050 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1051 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1052 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1054 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1055 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1056 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1057 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1061 gtk_window_init (GtkWindow *window)
1063 GtkWindowPrivate *priv;
1065 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1068 priv = window->priv;
1070 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1071 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1073 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1075 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1078 priv->wmclass_name = g_strdup (g_get_prgname ());
1079 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1080 priv->wm_role = NULL;
1081 priv->geometry_info = NULL;
1082 priv->type = GTK_WINDOW_TOPLEVEL;
1083 priv->focus_widget = NULL;
1084 priv->default_widget = NULL;
1085 priv->configure_request_count = 0;
1086 priv->resizable = TRUE;
1087 priv->configure_notify_received = FALSE;
1088 priv->position = GTK_WIN_POS_NONE;
1089 priv->need_default_size = TRUE;
1090 priv->need_default_position = TRUE;
1091 priv->modal = FALSE;
1092 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1093 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1094 priv->decorated = TRUE;
1095 priv->mnemonic_modifier = GDK_MOD1_MASK;
1096 priv->screen = gdk_screen_get_default ();
1098 priv->accept_focus = TRUE;
1099 priv->focus_on_map = TRUE;
1100 priv->deletable = TRUE;
1101 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1102 priv->opacity = 1.0;
1103 priv->startup_id = NULL;
1104 priv->has_resize_grip = TRUE;
1105 priv->mnemonics_visible = TRUE;
1107 g_object_ref_sink (window);
1108 priv->has_user_ref_count = TRUE;
1109 toplevel_list = g_slist_prepend (toplevel_list, window);
1112 g_signal_connect (priv->screen, "composited-changed",
1113 G_CALLBACK (gtk_window_on_composited_changed), window);
1117 gtk_window_set_property (GObject *object,
1119 const GValue *value,
1122 GtkWindow *window = GTK_WINDOW (object);
1123 GtkWindowPrivate *priv = window->priv;
1128 priv->type = g_value_get_enum (value);
1131 gtk_window_set_title (window, g_value_get_string (value));
1134 gtk_window_set_role (window, g_value_get_string (value));
1136 case PROP_STARTUP_ID:
1137 gtk_window_set_startup_id (window, g_value_get_string (value));
1139 case PROP_RESIZABLE:
1140 gtk_window_set_resizable (window, g_value_get_boolean (value));
1143 gtk_window_set_modal (window, g_value_get_boolean (value));
1146 gtk_window_set_position (window, g_value_get_enum (value));
1148 case PROP_DEFAULT_WIDTH:
1149 gtk_window_set_default_size_internal (window,
1150 TRUE, g_value_get_int (value),
1153 case PROP_DEFAULT_HEIGHT:
1154 gtk_window_set_default_size_internal (window,
1156 TRUE, g_value_get_int (value), FALSE);
1158 case PROP_DESTROY_WITH_PARENT:
1159 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1162 gtk_window_set_icon (window,
1163 g_value_get_object (value));
1165 case PROP_ICON_NAME:
1166 gtk_window_set_icon_name (window, g_value_get_string (value));
1169 gtk_window_set_screen (window, g_value_get_object (value));
1171 case PROP_TYPE_HINT:
1172 gtk_window_set_type_hint (window,
1173 g_value_get_enum (value));
1175 case PROP_SKIP_TASKBAR_HINT:
1176 gtk_window_set_skip_taskbar_hint (window,
1177 g_value_get_boolean (value));
1179 case PROP_SKIP_PAGER_HINT:
1180 gtk_window_set_skip_pager_hint (window,
1181 g_value_get_boolean (value));
1183 case PROP_URGENCY_HINT:
1184 gtk_window_set_urgency_hint (window,
1185 g_value_get_boolean (value));
1187 case PROP_ACCEPT_FOCUS:
1188 gtk_window_set_accept_focus (window,
1189 g_value_get_boolean (value));
1191 case PROP_FOCUS_ON_MAP:
1192 gtk_window_set_focus_on_map (window,
1193 g_value_get_boolean (value));
1195 case PROP_DECORATED:
1196 gtk_window_set_decorated (window, g_value_get_boolean (value));
1198 case PROP_DELETABLE:
1199 gtk_window_set_deletable (window, g_value_get_boolean (value));
1202 gtk_window_set_gravity (window, g_value_get_enum (value));
1204 case PROP_TRANSIENT_FOR:
1205 gtk_window_set_transient_for (window, g_value_get_object (value));
1208 gtk_window_set_opacity (window, g_value_get_double (value));
1210 case PROP_HAS_RESIZE_GRIP:
1211 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1213 case PROP_APPLICATION:
1214 gtk_window_set_application (window, g_value_get_object (value));
1216 case PROP_MNEMONICS_VISIBLE:
1217 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1220 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1226 gtk_window_get_property (GObject *object,
1231 GtkWindow *window = GTK_WINDOW (object);
1232 GtkWindowPrivate *priv = window->priv;
1236 GtkWindowGeometryInfo *info;
1238 g_value_set_enum (value, priv->type);
1241 g_value_set_string (value, priv->wm_role);
1244 g_value_set_string (value, priv->title);
1246 case PROP_RESIZABLE:
1247 g_value_set_boolean (value, priv->resizable);
1250 g_value_set_boolean (value, priv->modal);
1253 g_value_set_enum (value, priv->position);
1255 case PROP_DEFAULT_WIDTH:
1256 info = gtk_window_get_geometry_info (window, FALSE);
1258 g_value_set_int (value, -1);
1260 g_value_set_int (value, info->default_width);
1262 case PROP_DEFAULT_HEIGHT:
1263 info = gtk_window_get_geometry_info (window, FALSE);
1265 g_value_set_int (value, -1);
1267 g_value_set_int (value, info->default_height);
1269 case PROP_DESTROY_WITH_PARENT:
1270 g_value_set_boolean (value, priv->destroy_with_parent);
1273 g_value_set_object (value, gtk_window_get_icon (window));
1275 case PROP_ICON_NAME:
1276 g_value_set_string (value, gtk_window_get_icon_name (window));
1279 g_value_set_object (value, priv->screen);
1281 case PROP_IS_ACTIVE:
1282 g_value_set_boolean (value, priv->is_active);
1284 case PROP_HAS_TOPLEVEL_FOCUS:
1285 g_value_set_boolean (value, priv->has_toplevel_focus);
1287 case PROP_TYPE_HINT:
1288 g_value_set_enum (value, priv->type_hint);
1290 case PROP_SKIP_TASKBAR_HINT:
1291 g_value_set_boolean (value,
1292 gtk_window_get_skip_taskbar_hint (window));
1294 case PROP_SKIP_PAGER_HINT:
1295 g_value_set_boolean (value,
1296 gtk_window_get_skip_pager_hint (window));
1298 case PROP_URGENCY_HINT:
1299 g_value_set_boolean (value,
1300 gtk_window_get_urgency_hint (window));
1302 case PROP_ACCEPT_FOCUS:
1303 g_value_set_boolean (value,
1304 gtk_window_get_accept_focus (window));
1306 case PROP_FOCUS_ON_MAP:
1307 g_value_set_boolean (value,
1308 gtk_window_get_focus_on_map (window));
1310 case PROP_DECORATED:
1311 g_value_set_boolean (value, gtk_window_get_decorated (window));
1313 case PROP_DELETABLE:
1314 g_value_set_boolean (value, gtk_window_get_deletable (window));
1317 g_value_set_enum (value, gtk_window_get_gravity (window));
1319 case PROP_TRANSIENT_FOR:
1320 g_value_set_object (value, gtk_window_get_transient_for (window));
1323 g_value_set_double (value, gtk_window_get_opacity (window));
1325 case PROP_HAS_RESIZE_GRIP:
1326 g_value_set_boolean (value, priv->has_resize_grip);
1328 case PROP_RESIZE_GRIP_VISIBLE:
1329 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1331 case PROP_APPLICATION:
1332 g_value_set_object (value, gtk_window_get_application (window));
1334 case PROP_MNEMONICS_VISIBLE:
1335 g_value_set_boolean (value, priv->mnemonics_visible);
1338 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1344 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1346 parent_buildable_iface = g_type_interface_peek_parent (iface);
1347 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1348 iface->parser_finished = gtk_window_buildable_parser_finished;
1349 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1350 iface->custom_finished = gtk_window_buildable_custom_finished;
1354 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1355 GtkBuilder *builder,
1357 const GValue *value)
1359 GtkWindow *window = GTK_WINDOW (buildable);
1360 GtkWindowPrivate *priv = window->priv;
1362 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1363 priv->builder_visible = TRUE;
1365 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1369 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1370 GtkBuilder *builder)
1372 GtkWindow *window = GTK_WINDOW (buildable);
1373 GtkWindowPrivate *priv = window->priv;
1377 if (priv->builder_visible)
1378 gtk_widget_show (GTK_WIDGET (buildable));
1380 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1381 for (l = accels; l; l = l->next)
1383 object = gtk_builder_get_object (builder, l->data);
1386 g_warning ("Unknown accel group %s specified in window %s",
1387 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1390 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1391 GTK_ACCEL_GROUP (object));
1395 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1397 parent_buildable_iface->parser_finished (buildable, builder);
1403 } GSListSubParserData;
1406 window_start_element (GMarkupParseContext *context,
1407 const gchar *element_name,
1408 const gchar **names,
1409 const gchar **values,
1414 GSListSubParserData *data = (GSListSubParserData*)user_data;
1416 if (strcmp (element_name, "group") == 0)
1418 for (i = 0; names[i]; i++)
1420 if (strcmp (names[i], "name") == 0)
1421 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1424 else if (strcmp (element_name, "accel-groups") == 0)
1427 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1432 static const GMarkupParser window_parser =
1434 window_start_element
1438 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1439 GtkBuilder *builder,
1441 const gchar *tagname,
1442 GMarkupParser *parser,
1445 GSListSubParserData *parser_data;
1447 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1448 tagname, parser, data))
1451 if (strcmp (tagname, "accel-groups") == 0)
1453 parser_data = g_slice_new0 (GSListSubParserData);
1454 parser_data->items = NULL;
1455 parser_data->object = G_OBJECT (buildable);
1457 *parser = window_parser;
1458 *data = parser_data;
1466 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1467 GtkBuilder *builder,
1469 const gchar *tagname,
1472 GSListSubParserData *data;
1474 parent_buildable_iface->custom_finished (buildable, builder, child,
1475 tagname, user_data);
1477 if (strcmp (tagname, "accel-groups") != 0)
1480 data = (GSListSubParserData*)user_data;
1482 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1483 data->items, (GDestroyNotify) g_slist_free);
1485 g_slice_free (GSListSubParserData, data);
1490 * @type: type of window
1492 * Creates a new #GtkWindow, which is a toplevel window that can
1493 * contain other widgets. Nearly always, the type of the window should
1494 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1495 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1496 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1497 * dialogs, though in some other toolkits dialogs are called "popups".
1498 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1499 * On X11, popup windows are not controlled by the <link
1500 * linkend="gtk-X11-arch">window manager</link>.
1502 * If you simply want an undecorated window (no window borders), use
1503 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1505 * Return value: a new #GtkWindow.
1508 gtk_window_new (GtkWindowType type)
1510 GtkWindowPrivate *priv;
1513 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1515 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1516 priv = window->priv;
1520 return GTK_WIDGET (window);
1524 * gtk_window_set_title:
1525 * @window: a #GtkWindow
1526 * @title: title of the window
1528 * Sets the title of the #GtkWindow. The title of a window will be
1529 * displayed in its title bar; on the X Window System, the title bar
1530 * is rendered by the <link linkend="gtk-X11-arch">window
1531 * manager</link>, so exactly how the title appears to users may vary
1532 * according to a user's exact configuration. The title should help a
1533 * user distinguish this window from other windows they may have
1534 * open. A good title might include the application name and current
1535 * document filename, for example.
1539 gtk_window_set_title (GtkWindow *window,
1542 GtkWindowPrivate *priv;
1546 g_return_if_fail (GTK_IS_WINDOW (window));
1548 priv = window->priv;
1549 widget = GTK_WIDGET (window);
1551 new_title = g_strdup (title);
1552 g_free (priv->title);
1553 priv->title = new_title;
1555 if (gtk_widget_get_realized (widget))
1557 gdk_window_set_title (gtk_widget_get_window (widget),
1561 g_object_notify (G_OBJECT (window), "title");
1565 * gtk_window_get_title:
1566 * @window: a #GtkWindow
1568 * Retrieves the title of the window. See gtk_window_set_title().
1570 * Return value: the title of the window, or %NULL if none has
1571 * been set explicitely. The returned string is owned by the widget
1572 * and must not be modified or freed.
1574 G_CONST_RETURN gchar *
1575 gtk_window_get_title (GtkWindow *window)
1577 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1579 return window->priv->title;
1583 * gtk_window_set_wmclass:
1584 * @window: a #GtkWindow
1585 * @wmclass_name: window name hint
1586 * @wmclass_class: window class hint
1588 * Don't use this function. It sets the X Window System "class" and
1589 * "name" hints for a window. According to the ICCCM, you should
1590 * always set these to the same value for all windows in an
1591 * application, and GTK+ sets them to that value by default, so calling
1592 * this function is sort of pointless. However, you may want to call
1593 * gtk_window_set_role() on each window in your application, for the
1594 * benefit of the session manager. Setting the role allows the window
1595 * manager to restore window positions when loading a saved session.
1599 gtk_window_set_wmclass (GtkWindow *window,
1600 const gchar *wmclass_name,
1601 const gchar *wmclass_class)
1603 GtkWindowPrivate *priv;
1605 g_return_if_fail (GTK_IS_WINDOW (window));
1607 priv = window->priv;
1609 g_free (priv->wmclass_name);
1610 priv->wmclass_name = g_strdup (wmclass_name);
1612 g_free (priv->wmclass_class);
1613 priv->wmclass_class = g_strdup (wmclass_class);
1615 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1616 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1620 * gtk_window_set_role:
1621 * @window: a #GtkWindow
1622 * @role: unique identifier for the window to be used when restoring a session
1624 * This function is only useful on X11, not with other GTK+ targets.
1626 * In combination with the window title, the window role allows a
1627 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1628 * same" window when an application is restarted. So for example you
1629 * might set the "toolbox" role on your app's toolbox window, so that
1630 * when the user restarts their session, the window manager can put
1631 * the toolbox back in the same place.
1633 * If a window already has a unique title, you don't need to set the
1634 * role, since the WM can use the title to identify the window when
1635 * restoring the session.
1639 gtk_window_set_role (GtkWindow *window,
1642 GtkWindowPrivate *priv;
1645 g_return_if_fail (GTK_IS_WINDOW (window));
1647 priv = window->priv;
1649 new_role = g_strdup (role);
1650 g_free (priv->wm_role);
1651 priv->wm_role = new_role;
1653 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1654 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1657 g_object_notify (G_OBJECT (window), "role");
1661 * gtk_window_set_startup_id:
1662 * @window: a #GtkWindow
1663 * @startup_id: a string with startup-notification identifier
1665 * Startup notification identifiers are used by desktop environment to
1666 * track application startup, to provide user feedback and other
1667 * features. This function changes the corresponding property on the
1668 * underlying GdkWindow. Normally, startup identifier is managed
1669 * automatically and you should only use this function in special cases
1670 * like transferring focus from other processes. You should use this
1671 * function before calling gtk_window_present() or any equivalent
1672 * function generating a window map event.
1674 * This function is only useful on X11, not with other GTK+ targets.
1679 gtk_window_set_startup_id (GtkWindow *window,
1680 const gchar *startup_id)
1682 GtkWindowPrivate *priv;
1685 g_return_if_fail (GTK_IS_WINDOW (window));
1687 priv = window->priv;
1688 widget = GTK_WIDGET (window);
1690 g_free (priv->startup_id);
1691 priv->startup_id = g_strdup (startup_id);
1693 if (gtk_widget_get_realized (widget))
1695 GdkWindow *gdk_window;
1696 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1698 gdk_window = gtk_widget_get_window (widget);
1700 #ifdef GDK_WINDOWING_X11
1701 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1702 gdk_x11_window_set_user_time (gdk_window, timestamp);
1705 /* Here we differentiate real and "fake" startup notification IDs,
1706 * constructed on purpose just to pass interaction timestamp
1708 if (startup_id_is_fake (priv->startup_id))
1709 gtk_window_present_with_time (window, timestamp);
1712 gdk_window_set_startup_id (gdk_window,
1715 /* If window is mapped, terminate the startup-notification too */
1716 if (gtk_widget_get_mapped (widget) &&
1717 !disable_startup_notification)
1718 gdk_notify_startup_complete_with_id (priv->startup_id);
1722 g_object_notify (G_OBJECT (window), "startup-id");
1726 * gtk_window_get_role:
1727 * @window: a #GtkWindow
1729 * Returns the role of the window. See gtk_window_set_role() for
1730 * further explanation.
1732 * Return value: the role of the window if set, or %NULL. The
1733 * returned is owned by the widget and must not be modified
1736 G_CONST_RETURN gchar *
1737 gtk_window_get_role (GtkWindow *window)
1739 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1741 return window->priv->wm_role;
1745 * gtk_window_set_focus:
1746 * @window: a #GtkWindow
1747 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1748 * any focus widget for the toplevel window.
1750 * If @focus is not the current focus widget, and is focusable, sets
1751 * it as the focus widget for the window. If @focus is %NULL, unsets
1752 * the focus widget for this window. To set the focus to a particular
1753 * widget in the toplevel, it is usually more convenient to use
1754 * gtk_widget_grab_focus() instead of this function.
1757 gtk_window_set_focus (GtkWindow *window,
1760 GtkWindowPrivate *priv;
1763 g_return_if_fail (GTK_IS_WINDOW (window));
1765 priv = window->priv;
1769 g_return_if_fail (GTK_IS_WIDGET (focus));
1770 g_return_if_fail (gtk_widget_get_can_focus (focus));
1774 gtk_widget_grab_focus (focus);
1777 /* Clear the existing focus chain, so that when we focus into
1778 * the window again, we start at the beginnning.
1780 GtkWidget *widget = priv->focus_widget;
1783 while ((parent = gtk_widget_get_parent (widget)))
1786 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1790 _gtk_window_internal_set_focus (window, NULL);
1795 _gtk_window_internal_set_focus (GtkWindow *window,
1798 GtkWindowPrivate *priv;
1800 g_return_if_fail (GTK_IS_WINDOW (window));
1802 priv = window->priv;
1804 if ((priv->focus_widget != focus) ||
1805 (focus && !gtk_widget_has_focus (focus)))
1806 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1810 * gtk_window_set_default:
1811 * @window: a #GtkWindow
1812 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1813 * default widget for the toplevel.
1815 * The default widget is the widget that's activated when the user
1816 * presses Enter in a dialog (for example). This function sets or
1817 * unsets the default widget for a #GtkWindow about. When setting
1818 * (rather than unsetting) the default widget it's generally easier to
1819 * call gtk_widget_grab_focus() on the widget. Before making a widget
1820 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1821 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1824 gtk_window_set_default (GtkWindow *window,
1825 GtkWidget *default_widget)
1827 GtkWindowPrivate *priv;
1829 g_return_if_fail (GTK_IS_WINDOW (window));
1831 priv = window->priv;
1834 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1836 if (priv->default_widget != default_widget)
1838 GtkWidget *old_default_widget = NULL;
1841 g_object_ref (default_widget);
1843 if (priv->default_widget)
1845 old_default_widget = priv->default_widget;
1847 if (priv->focus_widget != priv->default_widget ||
1848 !gtk_widget_get_receives_default (priv->default_widget))
1849 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1851 gtk_widget_queue_draw (priv->default_widget);
1854 priv->default_widget = default_widget;
1856 if (priv->default_widget)
1858 if (priv->focus_widget == NULL ||
1859 !gtk_widget_get_receives_default (priv->focus_widget))
1860 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1862 gtk_widget_queue_draw (priv->default_widget);
1865 if (old_default_widget)
1866 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1870 g_object_notify (G_OBJECT (default_widget), "has-default");
1871 g_object_unref (default_widget);
1877 * gtk_window_get_default_widget:
1878 * @window: a #GtkWindow
1880 * Returns the default widget for @window. See gtk_window_set_default()
1883 * Returns: (transfer none): the default widget, or %NULL if there is none.
1888 gtk_window_get_default_widget (GtkWindow *window)
1890 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1892 return window->priv->default_widget;
1896 handle_keys_changed (gpointer data)
1898 GtkWindow *window = GTK_WINDOW (data);
1899 GtkWindowPrivate *priv = window->priv;
1901 if (priv->keys_changed_handler)
1903 g_source_remove (priv->keys_changed_handler);
1904 priv->keys_changed_handler = 0;
1907 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1913 gtk_window_notify_keys_changed (GtkWindow *window)
1915 GtkWindowPrivate *priv = window->priv;
1917 if (!priv->keys_changed_handler)
1918 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1922 * gtk_window_add_accel_group:
1923 * @window: window to attach accelerator group to
1924 * @accel_group: a #GtkAccelGroup
1926 * Associate @accel_group with @window, such that calling
1927 * gtk_accel_groups_activate() on @window will activate accelerators
1931 gtk_window_add_accel_group (GtkWindow *window,
1932 GtkAccelGroup *accel_group)
1934 g_return_if_fail (GTK_IS_WINDOW (window));
1935 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1937 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1938 g_signal_connect_object (accel_group, "accel-changed",
1939 G_CALLBACK (gtk_window_notify_keys_changed),
1940 window, G_CONNECT_SWAPPED);
1941 gtk_window_notify_keys_changed (window);
1945 * gtk_window_remove_accel_group:
1946 * @window: a #GtkWindow
1947 * @accel_group: a #GtkAccelGroup
1949 * Reverses the effects of gtk_window_add_accel_group().
1952 gtk_window_remove_accel_group (GtkWindow *window,
1953 GtkAccelGroup *accel_group)
1955 g_return_if_fail (GTK_IS_WINDOW (window));
1956 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1958 g_signal_handlers_disconnect_by_func (accel_group,
1959 gtk_window_notify_keys_changed,
1961 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1962 gtk_window_notify_keys_changed (window);
1965 static GtkMnemonicHash *
1966 gtk_window_get_mnemonic_hash (GtkWindow *window,
1969 GtkWindowPrivate *private = window->priv;
1971 if (!private->mnemonic_hash && create)
1972 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1974 return private->mnemonic_hash;
1978 * gtk_window_add_mnemonic:
1979 * @window: a #GtkWindow
1980 * @keyval: the mnemonic
1981 * @target: the widget that gets activated by the mnemonic
1983 * Adds a mnemonic to this window.
1986 gtk_window_add_mnemonic (GtkWindow *window,
1990 g_return_if_fail (GTK_IS_WINDOW (window));
1991 g_return_if_fail (GTK_IS_WIDGET (target));
1993 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1995 gtk_window_notify_keys_changed (window);
1999 * gtk_window_remove_mnemonic:
2000 * @window: a #GtkWindow
2001 * @keyval: the mnemonic
2002 * @target: the widget that gets activated by the mnemonic
2004 * Removes a mnemonic from this window.
2007 gtk_window_remove_mnemonic (GtkWindow *window,
2011 g_return_if_fail (GTK_IS_WINDOW (window));
2012 g_return_if_fail (GTK_IS_WIDGET (target));
2014 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2016 gtk_window_notify_keys_changed (window);
2020 * gtk_window_mnemonic_activate:
2021 * @window: a #GtkWindow
2022 * @keyval: the mnemonic
2023 * @modifier: the modifiers
2024 * @returns: %TRUE if the activation is done.
2026 * Activates the targets associated with the mnemonic.
2029 gtk_window_mnemonic_activate (GtkWindow *window,
2031 GdkModifierType modifier)
2033 GtkWindowPrivate *priv;
2035 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2037 priv = window->priv;
2039 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2041 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2043 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2050 * gtk_window_set_mnemonic_modifier:
2051 * @window: a #GtkWindow
2052 * @modifier: the modifier mask used to activate
2053 * mnemonics on this window.
2055 * Sets the mnemonic modifier for this window.
2058 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2059 GdkModifierType modifier)
2061 GtkWindowPrivate *priv;
2063 g_return_if_fail (GTK_IS_WINDOW (window));
2064 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2066 priv = window->priv;
2068 priv->mnemonic_modifier = modifier;
2069 gtk_window_notify_keys_changed (window);
2073 * gtk_window_get_mnemonic_modifier:
2074 * @window: a #GtkWindow
2076 * Returns the mnemonic modifier for this window. See
2077 * gtk_window_set_mnemonic_modifier().
2079 * Return value: the modifier mask used to activate
2080 * mnemonics on this window.
2083 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2085 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2087 return window->priv->mnemonic_modifier;
2091 * gtk_window_set_position:
2092 * @window: a #GtkWindow.
2093 * @position: a position constraint.
2095 * Sets a position constraint for this window. If the old or new
2096 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2097 * the window to be repositioned to satisfy the new constraint.
2100 gtk_window_set_position (GtkWindow *window,
2101 GtkWindowPosition position)
2103 GtkWindowPrivate *priv;
2105 g_return_if_fail (GTK_IS_WINDOW (window));
2107 priv = window->priv;
2109 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2110 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2112 GtkWindowGeometryInfo *info;
2114 info = gtk_window_get_geometry_info (window, TRUE);
2116 /* this flag causes us to re-request the CENTER_ALWAYS
2117 * constraint in gtk_window_move_resize(), see
2118 * comment in that function.
2120 info->position_constraints_changed = TRUE;
2122 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2125 priv->position = position;
2127 g_object_notify (G_OBJECT (window), "window-position");
2131 * gtk_window_activate_focus:
2132 * @window: a #GtkWindow
2134 * Activates the current focused widget within the window.
2136 * Return value: %TRUE if a widget got activated.
2139 gtk_window_activate_focus (GtkWindow *window)
2141 GtkWindowPrivate *priv;
2143 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2145 priv = window->priv;
2147 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2148 return gtk_widget_activate (priv->focus_widget);
2154 * gtk_window_get_focus:
2155 * @window: a #GtkWindow
2157 * Retrieves the current focused widget within the window.
2158 * Note that this is the widget that would have the focus
2159 * if the toplevel window focused; if the toplevel window
2160 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2161 * not be %TRUE for the widget.
2163 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2166 gtk_window_get_focus (GtkWindow *window)
2168 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2170 return window->priv->focus_widget;
2174 * gtk_window_activate_default:
2175 * @window: a #GtkWindow
2177 * Activates the default widget for the window, unless the current
2178 * focused widget has been configured to receive the default action
2179 * (see gtk_widget_set_receives_default()), in which case the
2180 * focused widget is activated.
2182 * Return value: %TRUE if a widget got activated.
2185 gtk_window_activate_default (GtkWindow *window)
2187 GtkWindowPrivate *priv;
2189 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2191 priv = window->priv;
2193 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2194 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2195 return gtk_widget_activate (priv->default_widget);
2196 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2197 return gtk_widget_activate (priv->focus_widget);
2203 * gtk_window_set_modal:
2204 * @window: a #GtkWindow
2205 * @modal: whether the window is modal
2207 * Sets a window modal or non-modal. Modal windows prevent interaction
2208 * with other windows in the same application. To keep modal dialogs
2209 * on top of main application windows, use
2210 * gtk_window_set_transient_for() to make the dialog transient for the
2211 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2212 * will then disallow lowering the dialog below the parent.
2217 gtk_window_set_modal (GtkWindow *window,
2220 GtkWindowPrivate *priv;
2223 g_return_if_fail (GTK_IS_WINDOW (window));
2225 priv = window->priv;
2227 modal = modal != FALSE;
2228 if (priv->modal == modal)
2231 priv->modal = modal;
2232 widget = GTK_WIDGET (window);
2234 /* adjust desired modality state */
2235 if (gtk_widget_get_realized (widget))
2238 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2240 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2243 if (gtk_widget_get_visible (widget))
2246 gtk_grab_add (widget);
2248 gtk_grab_remove (widget);
2251 g_object_notify (G_OBJECT (window), "modal");
2255 * gtk_window_get_modal:
2256 * @window: a #GtkWindow
2258 * Returns whether the window is modal. See gtk_window_set_modal().
2260 * Return value: %TRUE if the window is set to be modal and
2261 * establishes a grab when shown
2264 gtk_window_get_modal (GtkWindow *window)
2266 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2268 return window->priv->modal;
2272 * gtk_window_list_toplevels:
2274 * Returns a list of all existing toplevel windows. The widgets
2275 * in the list are not individually referenced. If you want
2276 * to iterate through the list and perform actions involving
2277 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2278 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2279 * then unref all the widgets afterwards.
2281 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2284 gtk_window_list_toplevels (void)
2289 for (slist = toplevel_list; slist; slist = slist->next)
2290 list = g_list_prepend (list, slist->data);
2296 gtk_window_dispose (GObject *object)
2298 GtkWindow *window = GTK_WINDOW (object);
2300 gtk_window_set_focus (window, NULL);
2301 gtk_window_set_default (window, NULL);
2303 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2307 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2309 gtk_widget_destroy (GTK_WIDGET (child));
2313 connect_parent_destroyed (GtkWindow *window)
2315 GtkWindowPrivate *priv = window->priv;
2317 if (priv->transient_parent)
2319 g_signal_connect (priv->transient_parent,
2321 G_CALLBACK (parent_destroyed_callback),
2327 disconnect_parent_destroyed (GtkWindow *window)
2329 GtkWindowPrivate *priv = window->priv;
2331 if (priv->transient_parent)
2333 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2334 parent_destroyed_callback,
2340 gtk_window_transient_parent_realized (GtkWidget *parent,
2343 if (gtk_widget_get_realized (window))
2344 gdk_window_set_transient_for (gtk_widget_get_window (window),
2345 gtk_widget_get_window (parent));
2349 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2352 if (gtk_widget_get_realized (window))
2353 gdk_property_delete (gtk_widget_get_window (window),
2354 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2358 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2362 gtk_window_set_screen (window, parent->priv->screen);
2366 gtk_window_unset_transient_for (GtkWindow *window)
2368 GtkWindowPrivate *priv = window->priv;
2370 if (priv->transient_parent)
2372 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2373 gtk_window_transient_parent_realized,
2375 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2376 gtk_window_transient_parent_unrealized,
2378 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2379 gtk_window_transient_parent_screen_changed,
2381 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2382 gtk_widget_destroyed,
2383 &priv->transient_parent);
2385 if (priv->destroy_with_parent)
2386 disconnect_parent_destroyed (window);
2388 priv->transient_parent = NULL;
2390 if (priv->transient_parent_group)
2392 priv->transient_parent_group = FALSE;
2393 gtk_window_group_remove_window (priv->group,
2400 * gtk_window_set_transient_for:
2401 * @window: a #GtkWindow
2402 * @parent: (allow-none): parent window, or %NULL
2404 * Dialog windows should be set transient for the main application
2405 * window they were spawned from. This allows <link
2406 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2407 * dialog on top of the main window, or center the dialog over the
2408 * main window. gtk_dialog_new_with_buttons() and other convenience
2409 * functions in GTK+ will sometimes call
2410 * gtk_window_set_transient_for() on your behalf.
2412 * Passing %NULL for @parent unsets the current transient window.
2414 * On Windows, this function puts the child window on top of the parent,
2415 * much as the window manager would have done on X.
2418 gtk_window_set_transient_for (GtkWindow *window,
2421 GtkWindowPrivate *priv;
2423 g_return_if_fail (GTK_IS_WINDOW (window));
2424 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2425 g_return_if_fail (window != parent);
2427 priv = window->priv;
2429 if (priv->transient_parent)
2431 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2432 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2433 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2434 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2435 GTK_WIDGET (window));
2437 gtk_window_unset_transient_for (window);
2440 priv->transient_parent = parent;
2444 g_signal_connect (parent, "destroy",
2445 G_CALLBACK (gtk_widget_destroyed),
2446 &priv->transient_parent);
2447 g_signal_connect (parent, "realize",
2448 G_CALLBACK (gtk_window_transient_parent_realized),
2450 g_signal_connect (parent, "unrealize",
2451 G_CALLBACK (gtk_window_transient_parent_unrealized),
2453 g_signal_connect (parent, "notify::screen",
2454 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2457 gtk_window_set_screen (window, parent->priv->screen);
2459 if (priv->destroy_with_parent)
2460 connect_parent_destroyed (window);
2462 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2463 gtk_widget_get_realized (GTK_WIDGET (parent)))
2464 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2465 GTK_WIDGET (window));
2467 if (parent->priv->group)
2469 gtk_window_group_add_window (parent->priv->group, window);
2470 priv->transient_parent_group = TRUE;
2476 * gtk_window_get_transient_for:
2477 * @window: a #GtkWindow
2479 * Fetches the transient parent for this window. See
2480 * gtk_window_set_transient_for().
2482 * Return value: (transfer none): the transient parent for this window, or %NULL
2483 * if no transient parent has been set.
2486 gtk_window_get_transient_for (GtkWindow *window)
2488 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2490 return window->priv->transient_parent;
2494 * gtk_window_set_opacity:
2495 * @window: a #GtkWindow
2496 * @opacity: desired opacity, between 0 and 1
2498 * Request the windowing system to make @window partially transparent,
2499 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2500 * of the opacity parameter are clamped to the [0,1] range.) On X11
2501 * this has any effect only on X screens with a compositing manager
2502 * running. See gtk_widget_is_composited(). On Windows it should work
2505 * Note that setting a window's opacity after the window has been
2506 * shown causes it to flicker once on Windows.
2511 gtk_window_set_opacity (GtkWindow *window,
2514 GtkWindowPrivate *priv;
2516 g_return_if_fail (GTK_IS_WINDOW (window));
2518 priv = window->priv;
2522 else if (opacity > 1.0)
2525 priv->opacity_set = TRUE;
2526 priv->opacity = opacity;
2528 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2529 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2534 * gtk_window_get_opacity:
2535 * @window: a #GtkWindow
2537 * Fetches the requested opacity for this window. See
2538 * gtk_window_set_opacity().
2540 * Return value: the requested opacity for this window.
2545 gtk_window_get_opacity (GtkWindow *window)
2547 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2549 return window->priv->opacity;
2553 * gtk_window_get_application:
2554 * @window: a #GtkWindow
2556 * Gets the #GtkApplication associated with the window (if any).
2558 * Return value: (transfer none): a #GtkApplication, or %NULL
2563 gtk_window_get_application (GtkWindow *window)
2565 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2567 return window->priv->application;
2571 gtk_window_release_application (GtkWindow *window)
2573 if (window->priv->application)
2575 GtkApplication *application;
2577 /* steal reference into temp variable */
2578 application = window->priv->application;
2579 window->priv->application = NULL;
2581 gtk_application_remove_window (application, window);
2582 g_object_unref (application);
2587 * gtk_window_set_application:
2588 * @window: a #GtkWindow
2589 * @application: (allow-none): a #GtkApplication, or %NULL
2591 * Sets or unsets the #GtkApplication associated with the window.
2593 * The application will be kept alive for at least as long as the window
2599 gtk_window_set_application (GtkWindow *window,
2600 GtkApplication *application)
2602 GtkWindowPrivate *priv;
2604 g_return_if_fail (GTK_IS_WINDOW (window));
2606 priv = window->priv;
2607 if (priv->application != application)
2609 gtk_window_release_application (window);
2611 priv->application = application;
2613 if (priv->application != NULL)
2615 g_object_ref (priv->application);
2617 gtk_application_add_window (priv->application, window);
2620 g_object_notify (G_OBJECT (window), "application");
2625 * gtk_window_set_type_hint:
2626 * @window: a #GtkWindow
2627 * @hint: the window type
2629 * By setting the type hint for the window, you allow the window
2630 * manager to decorate and handle the window in a way which is
2631 * suitable to the function of the window in your application.
2633 * This function should be called before the window becomes visible.
2635 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2636 * will sometimes call gtk_window_set_type_hint() on your behalf.
2640 gtk_window_set_type_hint (GtkWindow *window,
2641 GdkWindowTypeHint hint)
2643 GtkWindowPrivate *priv;
2645 g_return_if_fail (GTK_IS_WINDOW (window));
2646 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2648 priv = window->priv;
2650 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2651 priv->gdk_type_hint = hint;
2653 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2655 priv->reset_type_hint = TRUE;
2656 priv->type_hint = hint;
2660 * gtk_window_get_type_hint:
2661 * @window: a #GtkWindow
2663 * Gets the type hint for this window. See gtk_window_set_type_hint().
2665 * Return value: the type hint for @window.
2668 gtk_window_get_type_hint (GtkWindow *window)
2670 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2672 return window->priv->type_hint;
2676 * gtk_window_set_skip_taskbar_hint:
2677 * @window: a #GtkWindow
2678 * @setting: %TRUE to keep this window from appearing in the task bar
2680 * Windows may set a hint asking the desktop environment not to display
2681 * the window in the task bar. This function sets this hint.
2686 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2689 GtkWindowPrivate *priv;
2691 g_return_if_fail (GTK_IS_WINDOW (window));
2693 priv = window->priv;
2695 setting = setting != FALSE;
2697 if (priv->skips_taskbar != setting)
2699 priv->skips_taskbar = setting;
2700 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2701 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2702 priv->skips_taskbar);
2703 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2708 * gtk_window_get_skip_taskbar_hint:
2709 * @window: a #GtkWindow
2711 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2713 * Return value: %TRUE if window shouldn't be in taskbar
2718 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2720 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2722 return window->priv->skips_taskbar;
2726 * gtk_window_set_skip_pager_hint:
2727 * @window: a #GtkWindow
2728 * @setting: %TRUE to keep this window from appearing in the pager
2730 * Windows may set a hint asking the desktop environment not to display
2731 * the window in the pager. This function sets this hint.
2732 * (A "pager" is any desktop navigation tool such as a workspace
2733 * switcher that displays a thumbnail representation of the windows
2739 gtk_window_set_skip_pager_hint (GtkWindow *window,
2742 GtkWindowPrivate *priv;
2744 g_return_if_fail (GTK_IS_WINDOW (window));
2746 priv = window->priv;
2748 setting = setting != FALSE;
2750 if (priv->skips_pager != setting)
2752 priv->skips_pager = setting;
2753 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2754 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2756 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2761 * gtk_window_get_skip_pager_hint:
2762 * @window: a #GtkWindow
2764 * Gets the value set by gtk_window_set_skip_pager_hint().
2766 * Return value: %TRUE if window shouldn't be in pager
2771 gtk_window_get_skip_pager_hint (GtkWindow *window)
2773 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2775 return window->priv->skips_pager;
2779 * gtk_window_set_urgency_hint:
2780 * @window: a #GtkWindow
2781 * @setting: %TRUE to mark this window as urgent
2783 * Windows may set a hint asking the desktop environment to draw
2784 * the users attention to the window. This function sets this hint.
2789 gtk_window_set_urgency_hint (GtkWindow *window,
2792 GtkWindowPrivate *priv;
2794 g_return_if_fail (GTK_IS_WINDOW (window));
2796 priv = window->priv;
2798 setting = setting != FALSE;
2800 if (priv->urgent != setting)
2802 priv->urgent = setting;
2803 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2804 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2806 g_object_notify (G_OBJECT (window), "urgency-hint");
2811 * gtk_window_get_urgency_hint:
2812 * @window: a #GtkWindow
2814 * Gets the value set by gtk_window_set_urgency_hint()
2816 * Return value: %TRUE if window is urgent
2821 gtk_window_get_urgency_hint (GtkWindow *window)
2823 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2825 return window->priv->urgent;
2829 * gtk_window_set_accept_focus:
2830 * @window: a #GtkWindow
2831 * @setting: %TRUE to let this window receive input focus
2833 * Windows may set a hint asking the desktop environment not to receive
2834 * the input focus. This function sets this hint.
2839 gtk_window_set_accept_focus (GtkWindow *window,
2842 GtkWindowPrivate *priv;
2844 g_return_if_fail (GTK_IS_WINDOW (window));
2846 priv = window->priv;
2848 setting = setting != FALSE;
2850 if (priv->accept_focus != setting)
2852 priv->accept_focus = setting;
2853 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2854 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2855 priv->accept_focus);
2856 g_object_notify (G_OBJECT (window), "accept-focus");
2861 * gtk_window_get_accept_focus:
2862 * @window: a #GtkWindow
2864 * Gets the value set by gtk_window_set_accept_focus().
2866 * Return value: %TRUE if window should receive the input focus
2871 gtk_window_get_accept_focus (GtkWindow *window)
2873 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2875 return window->priv->accept_focus;
2879 * gtk_window_set_focus_on_map:
2880 * @window: a #GtkWindow
2881 * @setting: %TRUE to let this window receive input focus on map
2883 * Windows may set a hint asking the desktop environment not to receive
2884 * the input focus when the window is mapped. This function sets this
2890 gtk_window_set_focus_on_map (GtkWindow *window,
2893 GtkWindowPrivate *priv;
2895 g_return_if_fail (GTK_IS_WINDOW (window));
2897 priv = window->priv;
2899 setting = setting != FALSE;
2901 if (priv->focus_on_map != setting)
2903 priv->focus_on_map = setting;
2904 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2905 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2906 priv->focus_on_map);
2907 g_object_notify (G_OBJECT (window), "focus-on-map");
2912 * gtk_window_get_focus_on_map:
2913 * @window: a #GtkWindow
2915 * Gets the value set by gtk_window_set_focus_on_map().
2917 * Return value: %TRUE if window should receive the input focus when
2923 gtk_window_get_focus_on_map (GtkWindow *window)
2925 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2927 return window->priv->focus_on_map;
2931 * gtk_window_set_destroy_with_parent:
2932 * @window: a #GtkWindow
2933 * @setting: whether to destroy @window with its transient parent
2935 * If @setting is %TRUE, then destroying the transient parent of @window
2936 * will also destroy @window itself. This is useful for dialogs that
2937 * shouldn't persist beyond the lifetime of the main window they're
2938 * associated with, for example.
2941 gtk_window_set_destroy_with_parent (GtkWindow *window,
2944 GtkWindowPrivate *priv;
2946 g_return_if_fail (GTK_IS_WINDOW (window));
2948 priv = window->priv;
2950 if (priv->destroy_with_parent == (setting != FALSE))
2953 if (priv->destroy_with_parent)
2955 disconnect_parent_destroyed (window);
2959 connect_parent_destroyed (window);
2962 priv->destroy_with_parent = setting;
2964 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2968 * gtk_window_get_destroy_with_parent:
2969 * @window: a #GtkWindow
2971 * Returns whether the window will be destroyed with its transient parent. See
2972 * gtk_window_set_destroy_with_parent ().
2974 * Return value: %TRUE if the window will be destroyed with its transient parent.
2977 gtk_window_get_destroy_with_parent (GtkWindow *window)
2979 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2981 return window->priv->destroy_with_parent;
2984 static GtkWindowGeometryInfo*
2985 gtk_window_get_geometry_info (GtkWindow *window,
2988 GtkWindowPrivate *priv = window->priv;
2989 GtkWindowGeometryInfo *info;
2991 info = priv->geometry_info;
2992 if (!info && create)
2994 info = g_new0 (GtkWindowGeometryInfo, 1);
2996 info->default_width = -1;
2997 info->default_height = -1;
2998 info->resize_width = -1;
2999 info->resize_height = -1;
3000 info->initial_x = 0;
3001 info->initial_y = 0;
3002 info->initial_pos_set = FALSE;
3003 info->default_is_geometry = FALSE;
3004 info->position_constraints_changed = FALSE;
3005 info->last.configure_request.x = 0;
3006 info->last.configure_request.y = 0;
3007 info->last.configure_request.width = -1;
3008 info->last.configure_request.height = -1;
3009 info->widget = NULL;
3011 priv->geometry_info = info;
3018 * gtk_window_set_geometry_hints:
3019 * @window: a #GtkWindow
3020 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3021 * @geometry: (allow-none): struct containing geometry information or %NULL
3022 * @geom_mask: mask indicating which struct fields should be paid attention to
3024 * This function sets up hints about how a window can be resized by
3025 * the user. You can set a minimum and maximum size; allowed resize
3026 * increments (e.g. for xterm, you can only resize by the size of a
3027 * character); aspect ratios; and more. See the #GdkGeometry struct.
3031 gtk_window_set_geometry_hints (GtkWindow *window,
3032 GtkWidget *geometry_widget,
3033 GdkGeometry *geometry,
3034 GdkWindowHints geom_mask)
3036 GtkWindowGeometryInfo *info;
3038 g_return_if_fail (GTK_IS_WINDOW (window));
3039 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3041 info = gtk_window_get_geometry_info (window, TRUE);
3044 g_signal_handlers_disconnect_by_func (info->widget,
3045 gtk_widget_destroyed,
3048 info->widget = geometry_widget;
3050 g_signal_connect (geometry_widget, "destroy",
3051 G_CALLBACK (gtk_widget_destroyed),
3055 info->geometry = *geometry;
3057 /* We store gravity in priv->gravity not in the hints. */
3058 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3060 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3062 gtk_window_set_gravity (window, geometry->win_gravity);
3065 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3069 * gtk_window_set_decorated:
3070 * @window: a #GtkWindow
3071 * @setting: %TRUE to decorate the window
3073 * By default, windows are decorated with a title bar, resize
3074 * controls, etc. Some <link linkend="gtk-X11-arch">window
3075 * managers</link> allow GTK+ to disable these decorations, creating a
3076 * borderless window. If you set the decorated property to %FALSE
3077 * using this function, GTK+ will do its best to convince the window
3078 * manager not to decorate the window. Depending on the system, this
3079 * function may not have any effect when called on a window that is
3080 * already visible, so you should call it before calling gtk_widget_show().
3082 * On Windows, this function always works, since there's no window manager
3087 gtk_window_set_decorated (GtkWindow *window,
3090 GtkWindowPrivate *priv;
3091 GdkWindow *gdk_window;
3093 g_return_if_fail (GTK_IS_WINDOW (window));
3095 priv = window->priv;
3097 setting = setting != FALSE;
3099 if (setting == priv->decorated)
3102 priv->decorated = setting;
3104 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3107 if (priv->decorated)
3108 gdk_window_set_decorations (gdk_window,
3111 gdk_window_set_decorations (gdk_window,
3115 g_object_notify (G_OBJECT (window), "decorated");
3119 * gtk_window_get_decorated:
3120 * @window: a #GtkWindow
3122 * Returns whether the window has been set to have decorations
3123 * such as a title bar via gtk_window_set_decorated().
3125 * Return value: %TRUE if the window has been set to have decorations
3128 gtk_window_get_decorated (GtkWindow *window)
3130 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3132 return window->priv->decorated;
3136 * gtk_window_set_deletable:
3137 * @window: a #GtkWindow
3138 * @setting: %TRUE to decorate the window as deletable
3140 * By default, windows have a close button in the window frame. Some
3141 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3142 * disable this button. If you set the deletable property to %FALSE
3143 * using this function, GTK+ will do its best to convince the window
3144 * manager not to show a close button. Depending on the system, this
3145 * function may not have any effect when called on a window that is
3146 * already visible, so you should call it before calling gtk_window_show().
3148 * On Windows, this function always works, since there's no window manager
3154 gtk_window_set_deletable (GtkWindow *window,
3157 GtkWindowPrivate *priv;
3158 GdkWindow *gdk_window;
3160 g_return_if_fail (GTK_IS_WINDOW (window));
3162 priv = window->priv;
3164 setting = setting != FALSE;
3166 if (setting == priv->deletable)
3169 priv->deletable = setting;
3171 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3174 if (priv->deletable)
3175 gdk_window_set_functions (gdk_window,
3178 gdk_window_set_functions (gdk_window,
3179 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3182 g_object_notify (G_OBJECT (window), "deletable");
3186 * gtk_window_get_deletable:
3187 * @window: a #GtkWindow
3189 * Returns whether the window has been set to have a close button
3190 * via gtk_window_set_deletable().
3192 * Return value: %TRUE if the window has been set to have a close button
3197 gtk_window_get_deletable (GtkWindow *window)
3199 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3201 return window->priv->deletable;
3204 static GtkWindowIconInfo*
3205 get_icon_info (GtkWindow *window)
3207 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3211 free_icon_info (GtkWindowIconInfo *info)
3213 g_free (info->icon_name);
3214 g_slice_free (GtkWindowIconInfo, info);
3218 static GtkWindowIconInfo*
3219 ensure_icon_info (GtkWindow *window)
3221 GtkWindowIconInfo *info;
3223 info = get_icon_info (window);
3227 info = g_slice_new0 (GtkWindowIconInfo);
3228 g_object_set_qdata_full (G_OBJECT (window),
3229 quark_gtk_window_icon_info,
3231 (GDestroyNotify)free_icon_info);
3238 icon_list_from_theme (GtkWidget *widget,
3243 GtkIconTheme *icon_theme;
3248 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3250 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3253 for (i = 0; sizes[i]; i++)
3256 * We need an EWMH extension to handle scalable icons
3257 * by passing their name to the WM. For now just use a
3261 icon = gtk_icon_theme_load_icon (icon_theme, name,
3264 icon = gtk_icon_theme_load_icon (icon_theme, name,
3267 list = g_list_append (list, icon);
3277 gtk_window_realize_icon (GtkWindow *window)
3279 GtkWindowPrivate *priv = window->priv;
3281 GtkWindowIconInfo *info;
3282 GdkWindow *gdk_window;
3285 widget = GTK_WIDGET (window);
3286 gdk_window = gtk_widget_get_window (widget);
3288 g_return_if_fail (gdk_window != NULL);
3290 /* no point setting an icon on override-redirect */
3291 if (priv->type == GTK_WINDOW_POPUP)
3296 info = ensure_icon_info (window);
3301 info->using_default_icon = FALSE;
3302 info->using_parent_icon = FALSE;
3303 info->using_themed_icon = FALSE;
3305 icon_list = info->icon_list;
3307 /* Look up themed icon */
3308 if (icon_list == NULL && info->icon_name)
3310 icon_list = icon_list_from_theme (widget, info->icon_name);
3312 info->using_themed_icon = TRUE;
3315 /* Inherit from transient parent */
3316 if (icon_list == NULL && priv->transient_parent)
3318 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3320 info->using_parent_icon = TRUE;
3323 /* Inherit from default */
3324 if (icon_list == NULL)
3326 icon_list = default_icon_list;
3328 info->using_default_icon = TRUE;
3331 /* Look up themed icon */
3332 if (icon_list == NULL && default_icon_name)
3334 icon_list = icon_list_from_theme (widget, default_icon_name);
3335 info->using_default_icon = TRUE;
3336 info->using_themed_icon = TRUE;
3339 info->realized = TRUE;
3341 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3343 if (info->using_themed_icon)
3345 GtkIconTheme *icon_theme;
3347 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3348 g_list_free (icon_list);
3350 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3351 g_signal_connect (icon_theme, "changed",
3352 G_CALLBACK (update_themed_icon), window);
3357 gtk_window_unrealize_icon (GtkWindow *window)
3359 GtkWindowIconInfo *info;
3361 info = get_icon_info (window);
3366 if (info->using_themed_icon)
3368 GtkIconTheme *icon_theme;
3370 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3372 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3375 /* We don't clear the properties on the window, just figure the
3376 * window is going away.
3379 info->realized = FALSE;
3384 * gtk_window_set_icon_list:
3385 * @window: a #GtkWindow
3386 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3388 * Sets up the icon representing a #GtkWindow. The icon is used when
3389 * the window is minimized (also known as iconified). Some window
3390 * managers or desktop environments may also place it in the window
3391 * frame, or display it in other contexts.
3393 * gtk_window_set_icon_list() allows you to pass in the same icon in
3394 * several hand-drawn sizes. The list should contain the natural sizes
3395 * your icon is available in; that is, don't scale the image before
3396 * passing it to GTK+. Scaling is postponed until the last minute,
3397 * when the desired final size is known, to allow best quality.
3399 * By passing several sizes, you may improve the final image quality
3400 * of the icon, by reducing or eliminating automatic image scaling.
3402 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3403 * larger images (64x64, 128x128) if you have them.
3405 * See also gtk_window_set_default_icon_list() to set the icon
3406 * for all windows in your application in one go.
3408 * Note that transient windows (those who have been set transient for another
3409 * window using gtk_window_set_transient_for()) will inherit their
3410 * icon from their transient parent. So there's no need to explicitly
3411 * set the icon on transient windows.
3414 gtk_window_set_icon_list (GtkWindow *window,
3417 GtkWindowIconInfo *info;
3419 g_return_if_fail (GTK_IS_WINDOW (window));
3421 info = ensure_icon_info (window);
3423 if (info->icon_list == list) /* check for NULL mostly */
3426 g_list_foreach (list,
3427 (GFunc) g_object_ref, NULL);
3429 g_list_foreach (info->icon_list,
3430 (GFunc) g_object_unref, NULL);
3432 g_list_free (info->icon_list);
3434 info->icon_list = g_list_copy (list);
3436 g_object_notify (G_OBJECT (window), "icon");
3438 gtk_window_unrealize_icon (window);
3440 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3441 gtk_window_realize_icon (window);
3443 /* We could try to update our transient children, but I don't think
3444 * it's really worth it. If we did it, the best way would probably
3445 * be to have children connect to notify::icon-list
3450 * gtk_window_get_icon_list:
3451 * @window: a #GtkWindow
3453 * Retrieves the list of icons set by gtk_window_set_icon_list().
3454 * The list is copied, but the reference count on each
3455 * member won't be incremented.
3457 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3460 gtk_window_get_icon_list (GtkWindow *window)
3462 GtkWindowIconInfo *info;
3464 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3466 info = get_icon_info (window);
3469 return g_list_copy (info->icon_list);
3475 * gtk_window_set_icon:
3476 * @window: a #GtkWindow
3477 * @icon: (allow-none): icon image, or %NULL
3479 * Sets up the icon representing a #GtkWindow. This icon is used when
3480 * the window is minimized (also known as iconified). Some window
3481 * managers or desktop environments may also place it in the window
3482 * frame, or display it in other contexts.
3484 * The icon should be provided in whatever size it was naturally
3485 * drawn; that is, don't scale the image before passing it to
3486 * GTK+. Scaling is postponed until the last minute, when the desired
3487 * final size is known, to allow best quality.
3489 * If you have your icon hand-drawn in multiple sizes, use
3490 * gtk_window_set_icon_list(). Then the best size will be used.
3492 * This function is equivalent to calling gtk_window_set_icon_list()
3493 * with a 1-element list.
3495 * See also gtk_window_set_default_icon_list() to set the icon
3496 * for all windows in your application in one go.
3499 gtk_window_set_icon (GtkWindow *window,
3504 g_return_if_fail (GTK_IS_WINDOW (window));
3505 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3510 list = g_list_append (list, icon);
3512 gtk_window_set_icon_list (window, list);
3518 update_themed_icon (GtkIconTheme *icon_theme,
3521 g_object_notify (G_OBJECT (window), "icon");
3523 gtk_window_unrealize_icon (window);
3525 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3526 gtk_window_realize_icon (window);
3530 * gtk_window_set_icon_name:
3531 * @window: a #GtkWindow
3532 * @name: (allow-none): the name of the themed icon
3534 * Sets the icon for the window from a named themed icon. See
3535 * the docs for #GtkIconTheme for more details.
3537 * Note that this has nothing to do with the WM_ICON_NAME
3538 * property which is mentioned in the ICCCM.
3543 gtk_window_set_icon_name (GtkWindow *window,
3546 GtkWindowIconInfo *info;
3549 g_return_if_fail (GTK_IS_WINDOW (window));
3551 info = ensure_icon_info (window);
3553 if (g_strcmp0 (info->icon_name, name) == 0)
3556 tmp = info->icon_name;
3557 info->icon_name = g_strdup (name);
3560 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3561 g_list_free (info->icon_list);
3562 info->icon_list = NULL;
3564 update_themed_icon (NULL, window);
3566 g_object_notify (G_OBJECT (window), "icon-name");
3570 * gtk_window_get_icon_name:
3571 * @window: a #GtkWindow
3573 * Returns the name of the themed icon for the window,
3574 * see gtk_window_set_icon_name().
3576 * Returns: the icon name or %NULL if the window has
3582 gtk_window_get_icon_name (GtkWindow *window)
3584 GtkWindowIconInfo *info;
3586 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3588 info = ensure_icon_info (window);
3590 return info->icon_name;
3594 * gtk_window_get_icon:
3595 * @window: a #GtkWindow
3597 * Gets the value set by gtk_window_set_icon() (or if you've
3598 * called gtk_window_set_icon_list(), gets the first icon in
3601 * Return value: (transfer none): icon for window
3604 gtk_window_get_icon (GtkWindow *window)
3606 GtkWindowIconInfo *info;
3608 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3610 info = get_icon_info (window);
3611 if (info && info->icon_list)
3612 return GDK_PIXBUF (info->icon_list->data);
3617 /* Load pixbuf, printing warning on failure if error == NULL
3620 load_pixbuf_verbosely (const char *filename,
3623 GError *local_err = NULL;
3626 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3634 g_warning ("Error loading icon from file '%s':\n\t%s",
3635 filename, local_err->message);
3636 g_error_free (local_err);
3644 * gtk_window_set_icon_from_file:
3645 * @window: a #GtkWindow
3646 * @filename: (type filename): location of icon file
3647 * @err: (allow-none): location to store error, or %NULL.
3649 * Sets the icon for @window.
3650 * Warns on failure if @err is %NULL.
3652 * This function is equivalent to calling gtk_window_set_icon()
3653 * with a pixbuf created by loading the image from @filename.
3655 * Returns: %TRUE if setting the icon succeeded.
3660 gtk_window_set_icon_from_file (GtkWindow *window,
3661 const gchar *filename,
3664 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3668 gtk_window_set_icon (window, pixbuf);
3669 g_object_unref (pixbuf);
3678 * gtk_window_set_default_icon_list:
3679 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3681 * Sets an icon list to be used as fallback for windows that haven't
3682 * had gtk_window_set_icon_list() called on them to set up a
3683 * window-specific icon list. This function allows you to set up the
3684 * icon for all windows in your app at once.
3686 * See gtk_window_set_icon_list() for more details.
3690 gtk_window_set_default_icon_list (GList *list)
3694 if (list == default_icon_list)
3697 /* Update serial so we don't used cached pixmaps/masks
3699 default_icon_serial++;
3701 g_list_foreach (list,
3702 (GFunc) g_object_ref, NULL);
3704 g_list_foreach (default_icon_list,
3705 (GFunc) g_object_unref, NULL);
3707 g_list_free (default_icon_list);
3709 default_icon_list = g_list_copy (list);
3711 /* Update all toplevels */
3712 toplevels = gtk_window_list_toplevels ();
3713 tmp_list = toplevels;
3714 while (tmp_list != NULL)
3716 GtkWindowIconInfo *info;
3717 GtkWindow *w = tmp_list->data;
3719 info = get_icon_info (w);
3720 if (info && info->using_default_icon)
3722 gtk_window_unrealize_icon (w);
3723 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3724 gtk_window_realize_icon (w);
3727 tmp_list = tmp_list->next;
3729 g_list_free (toplevels);
3733 * gtk_window_set_default_icon:
3736 * Sets an icon to be used as fallback for windows that haven't
3737 * had gtk_window_set_icon() called on them from a pixbuf.
3742 gtk_window_set_default_icon (GdkPixbuf *icon)
3746 g_return_if_fail (GDK_IS_PIXBUF (icon));
3748 list = g_list_prepend (NULL, icon);
3749 gtk_window_set_default_icon_list (list);
3754 * gtk_window_set_default_icon_name:
3755 * @name: the name of the themed icon
3757 * Sets an icon to be used as fallback for windows that haven't
3758 * had gtk_window_set_icon_list() called on them from a named
3759 * themed icon, see gtk_window_set_icon_name().
3764 gtk_window_set_default_icon_name (const gchar *name)
3769 /* Update serial so we don't used cached pixmaps/masks
3771 default_icon_serial++;
3773 g_free (default_icon_name);
3774 default_icon_name = g_strdup (name);
3776 g_list_foreach (default_icon_list,
3777 (GFunc) g_object_unref, NULL);
3779 g_list_free (default_icon_list);
3780 default_icon_list = NULL;
3782 /* Update all toplevels */
3783 toplevels = gtk_window_list_toplevels ();
3784 tmp_list = toplevels;
3785 while (tmp_list != NULL)
3787 GtkWindowIconInfo *info;
3788 GtkWindow *w = tmp_list->data;
3790 info = get_icon_info (w);
3791 if (info && info->using_default_icon && info->using_themed_icon)
3793 gtk_window_unrealize_icon (w);
3794 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3795 gtk_window_realize_icon (w);
3798 tmp_list = tmp_list->next;
3800 g_list_free (toplevels);
3804 * gtk_window_get_default_icon_name:
3806 * Returns the fallback icon name for windows that has been set
3807 * with gtk_window_set_default_icon_name(). The returned
3808 * string is owned by GTK+ and should not be modified. It
3809 * is only valid until the next call to
3810 * gtk_window_set_default_icon_name().
3812 * Returns: the fallback icon name for windows
3817 gtk_window_get_default_icon_name (void)
3819 return default_icon_name;
3823 * gtk_window_set_default_icon_from_file:
3824 * @filename: (type filename): location of icon file
3825 * @err: (allow-none): location to store error, or %NULL.
3827 * Sets an icon to be used as fallback for windows that haven't
3828 * had gtk_window_set_icon_list() called on them from a file
3829 * on disk. Warns on failure if @err is %NULL.
3831 * Returns: %TRUE if setting the icon succeeded.
3836 gtk_window_set_default_icon_from_file (const gchar *filename,
3839 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3843 gtk_window_set_default_icon (pixbuf);
3844 g_object_unref (pixbuf);
3853 * gtk_window_get_default_icon_list:
3855 * Gets the value set by gtk_window_set_default_icon_list().
3856 * The list is a copy and should be freed with g_list_free(),
3857 * but the pixbufs in the list have not had their reference count
3860 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3863 gtk_window_get_default_icon_list (void)
3865 return g_list_copy (default_icon_list);
3869 gtk_window_set_default_size_internal (GtkWindow *window,
3870 gboolean change_width,
3872 gboolean change_height,
3874 gboolean is_geometry)
3876 GtkWindowGeometryInfo *info;
3878 g_return_if_fail (change_width == FALSE || width >= -1);
3879 g_return_if_fail (change_height == FALSE || height >= -1);
3881 info = gtk_window_get_geometry_info (window, TRUE);
3883 g_object_freeze_notify (G_OBJECT (window));
3885 info->default_is_geometry = is_geometry != FALSE;
3895 info->default_width = width;
3897 g_object_notify (G_OBJECT (window), "default-width");
3908 info->default_height = height;
3910 g_object_notify (G_OBJECT (window), "default-height");
3913 g_object_thaw_notify (G_OBJECT (window));
3915 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3919 * gtk_window_set_default_size:
3920 * @window: a #GtkWindow
3921 * @width: width in pixels, or -1 to unset the default width
3922 * @height: height in pixels, or -1 to unset the default height
3924 * Sets the default size of a window. If the window's "natural" size
3925 * (its size request) is larger than the default, the default will be
3926 * ignored. More generally, if the default size does not obey the
3927 * geometry hints for the window (gtk_window_set_geometry_hints() can
3928 * be used to set these explicitly), the default size will be clamped
3929 * to the nearest permitted size.
3931 * Unlike gtk_widget_set_size_request(), which sets a size request for
3932 * a widget and thus would keep users from shrinking the window, this
3933 * function only sets the initial size, just as if the user had
3934 * resized the window themselves. Users can still shrink the window
3935 * again as they normally would. Setting a default size of -1 means to
3936 * use the "natural" default size (the size request of the window).
3938 * For more control over a window's initial size and how resizing works,
3939 * investigate gtk_window_set_geometry_hints().
3941 * For some uses, gtk_window_resize() is a more appropriate function.
3942 * gtk_window_resize() changes the current size of the window, rather
3943 * than the size to be used on initial display. gtk_window_resize() always
3944 * affects the window itself, not the geometry widget.
3946 * The default size of a window only affects the first time a window is
3947 * shown; if a window is hidden and re-shown, it will remember the size
3948 * it had prior to hiding, rather than using the default size.
3950 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3951 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3954 gtk_window_set_default_size (GtkWindow *window,
3958 g_return_if_fail (GTK_IS_WINDOW (window));
3959 g_return_if_fail (width >= -1);
3960 g_return_if_fail (height >= -1);
3962 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3966 * gtk_window_set_default_geometry:
3967 * @window: a #GtkWindow
3968 * @width: width in resize increments, or -1 to unset the default width
3969 * @height: height in resize increments, or -1 to unset the default height
3971 * Like gtk_window_set_default_size(), but @width and @height are interpreted
3972 * in terms of the base size and increment set with
3973 * gtk_window_set_geometry_hints.
3978 gtk_window_set_default_geometry (GtkWindow *window,
3982 g_return_if_fail (GTK_IS_WINDOW (window));
3983 g_return_if_fail (width >= -1);
3984 g_return_if_fail (height >= -1);
3986 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
3990 * gtk_window_get_default_size:
3991 * @window: a #GtkWindow
3992 * @width: (out) (allow-none): location to store the default width, or %NULL
3993 * @height: (out) (allow-none): location to store the default height, or %NULL
3995 * Gets the default size of the window. A value of -1 for the width or
3996 * height indicates that a default size has not been explicitly set
3997 * for that dimension, so the "natural" size of the window will be
4002 gtk_window_get_default_size (GtkWindow *window,
4006 GtkWindowGeometryInfo *info;
4008 g_return_if_fail (GTK_IS_WINDOW (window));
4010 info = gtk_window_get_geometry_info (window, FALSE);
4013 *width = info ? info->default_width : -1;
4016 *height = info ? info->default_height : -1;
4020 * gtk_window_resize:
4021 * @window: a #GtkWindow
4022 * @width: width in pixels to resize the window to
4023 * @height: height in pixels to resize the window to
4025 * Resizes the window as if the user had done so, obeying geometry
4026 * constraints. The default geometry constraint is that windows may
4027 * not be smaller than their size request; to override this
4028 * constraint, call gtk_widget_set_size_request() to set the window's
4029 * request to a smaller value.
4031 * If gtk_window_resize() is called before showing a window for the
4032 * first time, it overrides any default size set with
4033 * gtk_window_set_default_size().
4035 * Windows may not be resized smaller than 1 by 1 pixels.
4039 gtk_window_resize (GtkWindow *window,
4043 GtkWindowGeometryInfo *info;
4045 g_return_if_fail (GTK_IS_WINDOW (window));
4046 g_return_if_fail (width > 0);
4047 g_return_if_fail (height > 0);
4049 info = gtk_window_get_geometry_info (window, TRUE);
4051 info->resize_width = width;
4052 info->resize_height = height;
4053 info->resize_is_geometry = FALSE;
4055 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4059 * gtk_window_resize_to_geometry:
4060 * @window: a #GtkWindow
4061 * @width: width in resize increments to resize the window to
4062 * @height: height in resize increments to resize the window to
4064 * Like gtk_window_resize(), but @width and @height are interpreted
4065 * in terms of the base size and increment set with
4066 * gtk_window_set_geometry_hints.
4071 gtk_window_resize_to_geometry (GtkWindow *window,
4075 GtkWindowGeometryInfo *info;
4077 g_return_if_fail (GTK_IS_WINDOW (window));
4078 g_return_if_fail (width > 0);
4079 g_return_if_fail (height > 0);
4081 info = gtk_window_get_geometry_info (window, TRUE);
4083 info->resize_width = width;
4084 info->resize_height = height;
4085 info->resize_is_geometry = TRUE;
4087 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4091 * gtk_window_get_size:
4092 * @window: a #GtkWindow
4093 * @width: (out) (allow-none): return location for width, or %NULL
4094 * @height: (out) (allow-none): return location for height, or %NULL
4096 * Obtains the current size of @window. If @window is not onscreen,
4097 * it returns the size GTK+ will suggest to the <link
4098 * linkend="gtk-X11-arch">window manager</link> for the initial window
4099 * size (but this is not reliably the same as the size the window
4100 * manager will actually select). The size obtained by
4101 * gtk_window_get_size() is the last size received in a
4102 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4103 * rather than querying the X server for the size. As a result, if you
4104 * call gtk_window_resize() then immediately call
4105 * gtk_window_get_size(), the size won't have taken effect yet. After
4106 * the window manager processes the resize request, GTK+ receives
4107 * notification that the size has changed via a configure event, and
4108 * the size of the window gets updated.
4110 * Note 1: Nearly any use of this function creates a race condition,
4111 * because the size of the window may change between the time that you
4112 * get the size and the time that you perform some action assuming
4113 * that size is the current size. To avoid race conditions, connect to
4114 * "configure-event" on the window and adjust your size-dependent
4115 * state to match the size delivered in the #GdkEventConfigure.
4117 * Note 2: The returned size does <emphasis>not</emphasis> include the
4118 * size of the window manager decorations (aka the window frame or
4119 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4120 * method of determining their size.
4122 * Note 3: If you are getting a window size in order to position
4123 * the window onscreen, there may be a better way. The preferred
4124 * way is to simply set the window's semantic type with
4125 * gtk_window_set_type_hint(), which allows the window manager to
4126 * e.g. center dialogs. Also, if you set the transient parent of
4127 * dialogs with gtk_window_set_transient_for() window managers
4128 * will often center the dialog over its parent window. It's
4129 * much preferred to let the window manager handle these
4130 * things rather than doing it yourself, because all apps will
4131 * behave consistently and according to user prefs if the window
4132 * manager handles it. Also, the window manager can take the size
4133 * of the window decorations/border into account, while your
4134 * application cannot.
4136 * In any case, if you insist on application-specified window
4137 * positioning, there's <emphasis>still</emphasis> a better way than
4138 * doing it yourself - gtk_window_set_position() will frequently
4139 * handle the details for you.
4143 gtk_window_get_size (GtkWindow *window,
4149 g_return_if_fail (GTK_IS_WINDOW (window));
4151 if (width == NULL && height == NULL)
4154 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4156 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4157 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4161 GdkRectangle configure_request;
4163 gtk_window_compute_configure_request (window,
4167 w = configure_request.width;
4168 h = configure_request.height;
4179 * @window: a #GtkWindow
4180 * @x: X coordinate to move window to
4181 * @y: Y coordinate to move window to
4183 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4184 * @window to the given position. Window managers are free to ignore
4185 * this; most window managers ignore requests for initial window
4186 * positions (instead using a user-defined placement algorithm) and
4187 * honor requests after the window has already been shown.
4189 * Note: the position is the position of the gravity-determined
4190 * reference point for the window. The gravity determines two things:
4191 * first, the location of the reference point in root window
4192 * coordinates; and second, which point on the window is positioned at
4193 * the reference point.
4195 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4196 * point is simply the @x, @y supplied to gtk_window_move(). The
4197 * top-left corner of the window decorations (aka window frame or
4198 * border) will be placed at @x, @y. Therefore, to position a window
4199 * at the top left of the screen, you want to use the default gravity
4200 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4202 * To position a window at the bottom right corner of the screen, you
4203 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4204 * point is at @x + the window width and @y + the window height, and
4205 * the bottom-right corner of the window border will be placed at that
4206 * reference point. So, to place a window in the bottom right corner
4207 * you would first set gravity to south east, then write:
4208 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4209 * gdk_screen_height () - window_height)</literal> (note that this
4210 * example does not take multi-head scenarios into account).
4212 * The Extended Window Manager Hints specification at <ulink
4213 * url="http://www.freedesktop.org/Standards/wm-spec">
4214 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4215 * nice table of gravities in the "implementation notes" section.
4217 * The gtk_window_get_position() documentation may also be relevant.
4220 gtk_window_move (GtkWindow *window,
4224 GtkWindowGeometryInfo *info;
4227 g_return_if_fail (GTK_IS_WINDOW (window));
4229 widget = GTK_WIDGET (window);
4231 info = gtk_window_get_geometry_info (window, TRUE);
4233 if (gtk_widget_get_mapped (widget))
4235 GtkAllocation allocation;
4237 gtk_widget_get_allocation (widget, &allocation);
4239 /* we have now sent a request with this position
4240 * with currently-active constraints, so toggle flag.
4242 info->position_constraints_changed = FALSE;
4244 /* we only constrain if mapped - if not mapped,
4245 * then gtk_window_compute_configure_request()
4246 * will apply the constraints later, and we
4247 * don't want to lose information about
4248 * what position the user set before then.
4249 * i.e. if you do a move() then turn off POS_CENTER
4250 * then show the window, your move() will work.
4252 gtk_window_constrain_position (window,
4253 allocation.width, allocation.height,
4256 /* Note that this request doesn't go through our standard request
4257 * framework, e.g. doesn't increment configure_request_count,
4258 * doesn't set info->last, etc.; that's because
4259 * we don't save the info needed to arrive at this same request
4262 * To gtk_window_move_resize(), this will end up looking exactly
4263 * the same as the position being changed by the window
4266 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4270 /* Save this position to apply on mapping */
4271 info->initial_x = x;
4272 info->initial_y = y;
4273 info->initial_pos_set = TRUE;
4278 * gtk_window_get_position:
4279 * @window: a #GtkWindow
4280 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4281 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4283 * This function returns the position you need to pass to
4284 * gtk_window_move() to keep @window in its current position. This
4285 * means that the meaning of the returned value varies with window
4286 * gravity. See gtk_window_move() for more details.
4288 * If you haven't changed the window gravity, its gravity will be
4289 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4290 * gets the position of the top-left corner of the window manager
4291 * frame for the window. gtk_window_move() sets the position of this
4292 * same top-left corner.
4294 * gtk_window_get_position() is not 100% reliable because the X Window System
4295 * does not specify a way to obtain the geometry of the
4296 * decorations placed on a window by the window manager.
4297 * Thus GTK+ is using a "best guess" that works with most
4300 * Moreover, nearly all window managers are historically broken with
4301 * respect to their handling of window gravity. So moving a window to
4302 * its current position as returned by gtk_window_get_position() tends
4303 * to result in moving the window slightly. Window managers are
4304 * slowly getting better over time.
4306 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4307 * frame is not relevant, and thus gtk_window_get_position() will
4308 * always produce accurate results. However you can't use static
4309 * gravity to do things like place a window in a corner of the screen,
4310 * because static gravity ignores the window manager decorations.
4312 * If you are saving and restoring your application's window
4313 * positions, you should know that it's impossible for applications to
4314 * do this without getting it somewhat wrong because applications do
4315 * not have sufficient knowledge of window manager state. The Correct
4316 * Mechanism is to support the session management protocol (see the
4317 * "GnomeClient" object in the GNOME libraries for example) and allow
4318 * the window manager to save your window sizes and positions.
4323 gtk_window_get_position (GtkWindow *window,
4327 GtkWindowPrivate *priv;
4329 GdkWindow *gdk_window;
4331 g_return_if_fail (GTK_IS_WINDOW (window));
4333 priv = window->priv;
4334 widget = GTK_WIDGET (window);
4335 gdk_window = gtk_widget_get_window (widget);
4337 if (priv->gravity == GDK_GRAVITY_STATIC)
4339 if (gtk_widget_get_mapped (widget))
4341 /* This does a server round-trip, which is sort of wrong;
4342 * but a server round-trip is inevitable for
4343 * gdk_window_get_frame_extents() in the usual
4344 * NorthWestGravity case below, so not sure what else to
4345 * do. We should likely be consistent about whether we get
4346 * the client-side info or the server-side info.
4348 gdk_window_get_origin (gdk_window, root_x, root_y);
4352 GdkRectangle configure_request;
4354 gtk_window_compute_configure_request (window,
4358 *root_x = configure_request.x;
4359 *root_y = configure_request.y;
4364 GdkRectangle frame_extents;
4369 if (gtk_widget_get_mapped (widget))
4371 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4372 x = frame_extents.x;
4373 y = frame_extents.y;
4374 gtk_window_get_size (window, &w, &h);
4378 /* We just say the frame has 0 size on all sides.
4379 * Not sure what else to do.
4381 gtk_window_compute_configure_request (window,
4384 x = frame_extents.x;
4385 y = frame_extents.y;
4386 w = frame_extents.width;
4387 h = frame_extents.height;
4390 switch (priv->gravity)
4392 case GDK_GRAVITY_NORTH:
4393 case GDK_GRAVITY_CENTER:
4394 case GDK_GRAVITY_SOUTH:
4395 /* Find center of frame. */
4396 x += frame_extents.width / 2;
4397 /* Center client window on that point. */
4401 case GDK_GRAVITY_SOUTH_EAST:
4402 case GDK_GRAVITY_EAST:
4403 case GDK_GRAVITY_NORTH_EAST:
4404 /* Find right edge of frame */
4405 x += frame_extents.width;
4406 /* Align left edge of client at that point. */
4413 switch (priv->gravity)
4415 case GDK_GRAVITY_WEST:
4416 case GDK_GRAVITY_CENTER:
4417 case GDK_GRAVITY_EAST:
4418 /* Find center of frame. */
4419 y += frame_extents.height / 2;
4420 /* Center client window there. */
4423 case GDK_GRAVITY_SOUTH_WEST:
4424 case GDK_GRAVITY_SOUTH:
4425 case GDK_GRAVITY_SOUTH_EAST:
4426 /* Find south edge of frame */
4427 y += frame_extents.height;
4428 /* Place bottom edge of client there */
4443 * gtk_window_reshow_with_initial_size:
4444 * @window: a #GtkWindow
4446 * Hides @window, then reshows it, resetting the
4447 * default size and position of the window. Used
4448 * by GUI builders only.
4451 gtk_window_reshow_with_initial_size (GtkWindow *window)
4455 g_return_if_fail (GTK_IS_WINDOW (window));
4457 widget = GTK_WIDGET (window);
4459 gtk_widget_hide (widget);
4460 gtk_widget_unrealize (widget);
4461 gtk_widget_show (widget);
4465 gtk_window_destroy (GtkWidget *widget)
4467 GtkWindow *window = GTK_WINDOW (widget);
4468 GtkWindowPrivate *priv = window->priv;
4470 gtk_window_release_application (window);
4472 toplevel_list = g_slist_remove (toplevel_list, window);
4474 if (priv->transient_parent)
4475 gtk_window_set_transient_for (window, NULL);
4477 /* frees the icons */
4478 gtk_window_set_icon_list (window, NULL);
4480 if (priv->has_user_ref_count)
4482 priv->has_user_ref_count = FALSE;
4483 g_object_unref (window);
4487 gtk_window_group_remove_window (priv->group, window);
4489 gtk_window_free_key_hash (window);
4491 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4495 gtk_window_finalize (GObject *object)
4497 GtkWindow *window = GTK_WINDOW (object);
4498 GtkWindowPrivate *priv = window->priv;
4499 GtkMnemonicHash *mnemonic_hash;
4501 g_free (priv->title);
4502 g_free (priv->wmclass_name);
4503 g_free (priv->wmclass_class);
4504 g_free (priv->wm_role);
4505 gtk_window_release_application (window);
4507 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4509 _gtk_mnemonic_hash_free (mnemonic_hash);
4511 if (priv->geometry_info)
4513 if (priv->geometry_info->widget)
4514 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4515 gtk_widget_destroyed,
4516 &priv->geometry_info->widget);
4517 g_free (priv->geometry_info);
4520 if (priv->keys_changed_handler)
4522 g_source_remove (priv->keys_changed_handler);
4523 priv->keys_changed_handler = 0;
4527 g_signal_handlers_disconnect_by_func (priv->screen,
4528 gtk_window_on_composited_changed, window);
4530 g_free (priv->startup_id);
4532 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4536 gtk_window_show (GtkWidget *widget)
4538 GtkWindow *window = GTK_WINDOW (widget);
4539 GtkWindowPrivate *priv = window->priv;
4540 GtkContainer *container = GTK_CONTAINER (window);
4541 gboolean need_resize;
4544 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4546 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4550 _gtk_widget_set_visible_flag (widget, TRUE);
4552 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4553 _gtk_container_set_need_resize (container, FALSE);
4557 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4558 GtkAllocation allocation = { 0, 0 };
4559 GdkRectangle configure_request;
4560 GdkGeometry new_geometry;
4562 gboolean was_realized;
4564 /* We are going to go ahead and perform this configure request
4565 * and then emulate a configure notify by going ahead and
4566 * doing a size allocate. Sort of a synchronous
4567 * mini-copy of gtk_window_move_resize() here.
4569 gtk_window_compute_configure_request (window,
4574 /* We update this because we are going to go ahead
4575 * and gdk_window_resize() below, rather than
4578 info->last.configure_request.width = configure_request.width;
4579 info->last.configure_request.height = configure_request.height;
4581 /* and allocate the window - this is normally done
4582 * in move_resize in response to configure notify
4584 allocation.width = configure_request.width;
4585 allocation.height = configure_request.height;
4586 gtk_widget_size_allocate (widget, &allocation);
4588 /* Then we guarantee we have a realize */
4589 was_realized = FALSE;
4590 if (!gtk_widget_get_realized (widget))
4592 gtk_widget_realize (widget);
4593 was_realized = TRUE;
4596 /* We only send configure request if we didn't just finish
4597 * creating the window; if we just created the window
4598 * then we created it with widget->allocation anyhow.
4601 gdk_window_move_resize (gtk_widget_get_window (widget),
4602 configure_request.x,
4603 configure_request.y,
4604 configure_request.width,
4605 configure_request.height);
4608 gtk_container_check_resize (container);
4610 gtk_widget_map (widget);
4612 /* Try to make sure that we have some focused widget
4614 #ifdef GDK_WINDOWING_X11
4615 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4616 GTK_IS_PLUG (window);
4620 if (!priv->focus_widget && !is_plug)
4621 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4624 gtk_grab_add (widget);
4628 gtk_window_hide (GtkWidget *widget)
4630 GtkWindow *window = GTK_WINDOW (widget);
4631 GtkWindowPrivate *priv = window->priv;
4633 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4635 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4639 _gtk_widget_set_visible_flag (widget, FALSE);
4640 gtk_widget_unmap (widget);
4643 gtk_grab_remove (widget);
4647 gtk_window_map (GtkWidget *widget)
4650 GtkWindow *window = GTK_WINDOW (widget);
4651 GtkWindowPrivate *priv = window->priv;
4652 GdkWindow *toplevel;
4653 GdkWindow *gdk_window;
4654 gboolean auto_mnemonics;
4656 gdk_window = gtk_widget_get_window (widget);
4658 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4660 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4664 gtk_widget_set_mapped (widget, TRUE);
4666 child = gtk_bin_get_child (&(window->bin));
4668 gtk_widget_get_visible (child) &&
4669 !gtk_widget_get_mapped (child))
4670 gtk_widget_map (child);
4672 toplevel = gdk_window;
4674 if (priv->maximize_initially)
4675 gdk_window_maximize (toplevel);
4677 gdk_window_unmaximize (toplevel);
4679 if (priv->stick_initially)
4680 gdk_window_stick (toplevel);
4682 gdk_window_unstick (toplevel);
4684 if (priv->iconify_initially)
4685 gdk_window_iconify (toplevel);
4687 gdk_window_deiconify (toplevel);
4689 if (priv->fullscreen_initially)
4690 gdk_window_fullscreen (toplevel);
4692 gdk_window_unfullscreen (toplevel);
4694 gdk_window_set_keep_above (toplevel, priv->above_initially);
4696 gdk_window_set_keep_below (toplevel, priv->below_initially);
4698 /* No longer use the default settings */
4699 priv->need_default_size = FALSE;
4700 priv->need_default_position = FALSE;
4702 if (priv->reset_type_hint)
4704 /* We should only reset the type hint when the application
4705 * used gtk_window_set_type_hint() to change the hint.
4706 * Some applications use X directly to change the properties;
4707 * in that case, we shouldn't overwrite what they did.
4709 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4710 priv->reset_type_hint = FALSE;
4713 gdk_window_show (gdk_window);
4715 if (priv->grip_window)
4716 gdk_window_show (priv->grip_window);
4718 if (!disable_startup_notification)
4720 /* Do we have a custom startup-notification id? */
4721 if (priv->startup_id != NULL)
4723 /* Make sure we have a "real" id */
4724 if (!startup_id_is_fake (priv->startup_id))
4725 gdk_notify_startup_complete_with_id (priv->startup_id);
4727 g_free (priv->startup_id);
4728 priv->startup_id = NULL;
4730 else if (!sent_startup_notification)
4732 sent_startup_notification = TRUE;
4733 gdk_notify_startup_complete ();
4737 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4738 * (as in the case of popup menus), then hide mnemonics initially
4740 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4741 &auto_mnemonics, NULL);
4742 if (auto_mnemonics && !priv->mnemonics_visible_set)
4743 gtk_window_set_mnemonics_visible (window, FALSE);
4747 gtk_window_map_event (GtkWidget *widget,
4750 if (!gtk_widget_get_mapped (widget))
4752 /* we should be be unmapped, but are getting a MapEvent, this may happen
4753 * to toplevel XWindows if mapping was intercepted by a window manager
4754 * and an unmap request occoured while the MapRequestEvent was still
4755 * being handled. we work around this situaiton here by re-requesting
4756 * the window being unmapped. more details can be found in:
4757 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4759 gdk_window_hide (gtk_widget_get_window (widget));
4765 gtk_window_unmap (GtkWidget *widget)
4767 GtkWindow *window = GTK_WINDOW (widget);
4768 GtkWindowPrivate *priv = window->priv;
4770 GtkWindowGeometryInfo *info;
4771 GdkWindow *gdk_window;
4772 GdkWindowState state;
4774 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4776 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
4780 gdk_window = gtk_widget_get_window (widget);
4782 gtk_widget_set_mapped (widget, FALSE);
4783 gdk_window_withdraw (gdk_window);
4785 priv->configure_request_count = 0;
4786 priv->configure_notify_received = FALSE;
4788 /* on unmap, we reset the default positioning of the window,
4789 * so it's placed again, but we don't reset the default
4790 * size of the window, so it's remembered.
4792 priv->need_default_position = TRUE;
4794 info = gtk_window_get_geometry_info (window, FALSE);
4797 info->initial_pos_set = FALSE;
4798 info->position_constraints_changed = FALSE;
4801 state = gdk_window_get_state (gdk_window);
4802 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4803 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4804 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4805 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4806 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4808 child = gtk_bin_get_child (&(window->bin));
4810 gtk_widget_unmap (child);
4814 gtk_window_realize (GtkWidget *widget)
4816 GtkAllocation allocation;
4818 GdkWindow *parent_window;
4819 GdkWindow *gdk_window;
4820 GdkWindowAttr attributes;
4821 gint attributes_mask;
4822 GtkWindowPrivate *priv;
4823 GtkStyleContext *context;
4825 window = GTK_WINDOW (widget);
4826 priv = window->priv;
4828 gtk_widget_get_allocation (widget, &allocation);
4830 if (gtk_widget_get_parent_window (widget))
4832 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
4834 gtk_widget_set_realized (widget, TRUE);
4836 attributes.x = allocation.x;
4837 attributes.y = allocation.y;
4838 attributes.width = allocation.width;
4839 attributes.height = allocation.height;
4840 attributes.window_type = GDK_WINDOW_CHILD;
4842 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
4844 attributes.visual = gtk_widget_get_visual (widget);
4845 attributes.wclass = GDK_INPUT_OUTPUT;
4847 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
4849 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
4850 &attributes, attributes_mask);
4851 gtk_widget_set_window (widget, gdk_window);
4852 gdk_window_set_user_data (gdk_window, widget);
4854 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
4856 gdk_window_enable_synchronized_configure (gdk_window);
4860 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
4862 /* ensure widget tree is properly size allocated */
4863 if (allocation.x == -1 &&
4864 allocation.y == -1 &&
4865 allocation.width == 1 &&
4866 allocation.height == 1)
4868 GtkRequisition requisition;
4872 allocation.width = 200;
4873 allocation.height = 200;
4875 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4876 if (requisition.width || requisition.height)
4878 /* non-empty window */
4879 allocation.width = requisition.width;
4880 allocation.height = requisition.height;
4882 gtk_widget_size_allocate (widget, &allocation);
4884 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4886 g_return_if_fail (!gtk_widget_get_realized (widget));
4889 gtk_widget_set_realized (widget, TRUE);
4893 case GTK_WINDOW_TOPLEVEL:
4894 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4896 case GTK_WINDOW_POPUP:
4897 attributes.window_type = GDK_WINDOW_TEMP;
4900 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4904 attributes.title = priv->title;
4905 attributes.wmclass_name = priv->wmclass_name;
4906 attributes.wmclass_class = priv->wmclass_class;
4907 attributes.wclass = GDK_INPUT_OUTPUT;
4908 attributes.visual = gtk_widget_get_visual (widget);
4910 attributes_mask = 0;
4911 parent_window = gtk_widget_get_root_window (widget);
4913 gtk_widget_get_allocation (widget, &allocation);
4914 attributes.width = allocation.width;
4915 attributes.height = allocation.height;
4916 attributes.event_mask = gtk_widget_get_events (widget);
4917 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4918 GDK_KEY_PRESS_MASK |
4919 GDK_KEY_RELEASE_MASK |
4920 GDK_ENTER_NOTIFY_MASK |
4921 GDK_LEAVE_NOTIFY_MASK |
4922 GDK_FOCUS_CHANGE_MASK |
4923 GDK_STRUCTURE_MASK);
4924 attributes.type_hint = priv->type_hint;
4926 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4927 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4928 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4930 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4931 gtk_widget_set_window (widget, gdk_window);
4933 if (priv->opacity_set)
4934 gdk_window_set_opacity (gdk_window, priv->opacity);
4936 gdk_window_enable_synchronized_configure (gdk_window);
4938 gdk_window_set_user_data (gdk_window, window);
4940 context = gtk_widget_get_style_context (widget);
4941 gtk_style_context_set_background (context, gdk_window);
4944 if (priv->transient_parent &&
4945 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4946 gdk_window_set_transient_for (gdk_window,
4947 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4950 gdk_window_set_role (gdk_window, priv->wm_role);
4952 if (!priv->decorated)
4953 gdk_window_set_decorations (gdk_window, 0);
4955 if (!priv->deletable)
4956 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4958 if (gtk_window_get_skip_pager_hint (window))
4959 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4961 if (gtk_window_get_skip_taskbar_hint (window))
4962 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4964 if (gtk_window_get_accept_focus (window))
4965 gdk_window_set_accept_focus (gdk_window, TRUE);
4967 gdk_window_set_accept_focus (gdk_window, FALSE);
4969 if (gtk_window_get_focus_on_map (window))
4970 gdk_window_set_focus_on_map (gdk_window, TRUE);
4972 gdk_window_set_focus_on_map (gdk_window, FALSE);
4975 gdk_window_set_modal_hint (gdk_window, TRUE);
4977 gdk_window_set_modal_hint (gdk_window, FALSE);
4979 if (priv->startup_id)
4981 #ifdef GDK_WINDOWING_X11
4982 if (GDK_IS_X11_WINDOW (gdk_window))
4984 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4985 if (timestamp != GDK_CURRENT_TIME)
4986 gdk_x11_window_set_user_time (gdk_window, timestamp);
4991 if (!startup_id_is_fake (priv->startup_id))
4992 gdk_window_set_startup_id (gdk_window, priv->startup_id);
4997 gtk_window_realize_icon (window);
4999 if (priv->has_resize_grip)
5000 resize_grip_create_window (window);
5004 gtk_window_unrealize (GtkWidget *widget)
5006 GtkWindow *window = GTK_WINDOW (widget);
5007 GtkWindowPrivate *priv = window->priv;
5008 GtkWindowGeometryInfo *info;
5010 /* On unrealize, we reset the size of the window such
5011 * that we will re-apply the default sizing stuff
5012 * next time we show the window.
5014 * Default positioning is reset on unmap, instead of unrealize.
5016 priv->need_default_size = TRUE;
5017 info = gtk_window_get_geometry_info (window, FALSE);
5020 info->resize_width = -1;
5021 info->resize_height = -1;
5022 info->last.configure_request.x = 0;
5023 info->last.configure_request.y = 0;
5024 info->last.configure_request.width = -1;
5025 info->last.configure_request.height = -1;
5026 /* be sure we reset geom hints on re-realize */
5027 info->last.flags = 0;
5031 gtk_window_unrealize_icon (window);
5033 if (priv->grip_window != NULL)
5034 resize_grip_destroy_window (window);
5036 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5039 static GtkJunctionSides
5040 get_grip_junction (GtkWidget *widget)
5042 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5043 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5045 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5049 get_drag_edge (GtkWidget *widget,
5050 GdkWindowEdge *edge)
5052 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5053 gboolean hresizable;
5054 gboolean vresizable;
5055 GtkTextDirection dir;
5056 GtkWindowGeometryInfo *info;
5061 info = priv->geometry_info;
5064 GdkWindowHints flags = info->last.flags;
5065 GdkGeometry *geometry = &info->last.geometry;
5067 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5069 hresizable = geometry->min_width < geometry->max_width;
5070 vresizable = geometry->min_height < geometry->max_height;
5074 dir = gtk_widget_get_direction (widget);
5076 if (hresizable && vresizable)
5077 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5078 else if (hresizable)
5079 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5080 else if (vresizable)
5081 *edge = GDK_WINDOW_EDGE_SOUTH;
5089 set_grip_cursor (GtkWindow *window)
5091 GtkWidget *widget = GTK_WIDGET (window);
5092 GtkWindowPrivate *priv = window->priv;
5094 if (priv->grip_window == NULL)
5097 if (gtk_widget_is_sensitive (widget))
5100 GdkDisplay *display;
5101 GdkCursorType cursor_type;
5104 cursor_type = GDK_LEFT_PTR;
5106 if (get_drag_edge (widget, &edge))
5110 case GDK_WINDOW_EDGE_EAST:
5111 cursor_type = GDK_RIGHT_SIDE;
5113 case GDK_WINDOW_EDGE_SOUTH_EAST:
5114 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5116 case GDK_WINDOW_EDGE_SOUTH:
5117 cursor_type = GDK_BOTTOM_SIDE;
5119 case GDK_WINDOW_EDGE_SOUTH_WEST:
5120 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5122 case GDK_WINDOW_EDGE_WEST:
5123 cursor_type = GDK_LEFT_SIDE;
5129 display = gtk_widget_get_display (widget);
5130 cursor = gdk_cursor_new_for_display (display, cursor_type);
5131 gdk_window_set_cursor (priv->grip_window, cursor);
5132 g_object_unref (cursor);
5135 gdk_window_set_cursor (priv->grip_window, NULL);
5139 set_grip_shape (GtkWindow *window)
5141 GtkWindowPrivate *priv = window->priv;
5142 cairo_region_t *region;
5143 cairo_surface_t *surface;
5145 double width, height;
5147 if (priv->grip_window == NULL)
5150 width = gdk_window_get_width (priv->grip_window);
5151 height = gdk_window_get_height (priv->grip_window);
5152 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5154 cr = cairo_create (surface);
5155 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5157 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5158 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5160 cairo_move_to (cr, width, 0.0);
5161 cairo_line_to (cr, width, height);
5162 cairo_line_to (cr, 0.0, height);
5166 cairo_move_to (cr, 0.0, 0.0);
5167 cairo_line_to (cr, width, height);
5168 cairo_line_to (cr, 0.0, height);
5170 cairo_close_path (cr);
5173 region = gdk_cairo_region_create_from_surface (surface);
5174 cairo_surface_destroy (surface);
5176 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5177 cairo_region_destroy (region);
5181 set_grip_position (GtkWindow *window)
5183 GtkWindowPrivate *priv = window->priv;
5186 if (priv->grip_window == NULL)
5189 gtk_window_get_resize_grip_area (window, &rect);
5190 gdk_window_raise (priv->grip_window);
5191 gdk_window_move_resize (priv->grip_window,
5193 rect.width, rect.height);
5197 gtk_window_size_allocate (GtkWidget *widget,
5198 GtkAllocation *allocation)
5200 GtkWindow *window = GTK_WINDOW (widget);
5201 GtkAllocation child_allocation;
5205 gtk_widget_set_allocation (widget, allocation);
5207 if (gtk_widget_get_realized (widget))
5209 /* If it's not a toplevel we're embedded, we need to resize the window's
5210 * window and skip the grip.
5212 if (!gtk_widget_is_toplevel (widget))
5214 gdk_window_move_resize (gtk_widget_get_window (widget),
5215 allocation->x, allocation->y,
5216 allocation->width, allocation->height);
5220 update_grip_visibility (window);
5221 set_grip_position (window);
5225 child = gtk_bin_get_child (&(window->bin));
5226 if (child && gtk_widget_get_visible (child))
5228 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5229 child_allocation.x = border_width;
5230 child_allocation.y = border_width;
5231 child_allocation.width =
5232 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5233 child_allocation.height =
5234 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5236 gtk_widget_size_allocate (child, &child_allocation);
5241 gtk_window_configure_event (GtkWidget *widget,
5242 GdkEventConfigure *event)
5244 GtkAllocation allocation;
5245 GtkWindow *window = GTK_WINDOW (widget);
5246 GtkWindowPrivate *priv = window->priv;
5247 gboolean expected_reply = priv->configure_request_count > 0;
5249 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5251 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5252 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5254 gdk_window_configure_finished (gtk_widget_get_window (widget));
5258 /* priv->configure_request_count incremented for each
5259 * configure request, and decremented to a min of 0 for
5260 * each configure notify.
5262 * All it means is that we know we will get at least
5263 * priv->configure_request_count more configure notifies.
5264 * We could get more configure notifies than that; some
5265 * of the configure notifies we get may be unrelated to
5266 * the configure requests. But we will get at least
5267 * priv->configure_request_count notifies.
5270 if (priv->configure_request_count > 0)
5272 priv->configure_request_count -= 1;
5273 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5276 /* As an optimization, we avoid a resize when possible.
5278 * The only times we can avoid a resize are:
5279 * - we know only the position changed, not the size
5280 * - we know we have made more requests and so will get more
5281 * notifies and can wait to resize when we get them
5283 gtk_widget_get_allocation (widget, &allocation);
5284 if (!expected_reply &&
5285 (allocation.width == event->width &&
5286 allocation.height == event->height))
5288 gdk_window_configure_finished (gtk_widget_get_window (widget));
5293 * If we do need to resize, we do that by:
5294 * - filling in widget->allocation with the new size
5295 * - setting configure_notify_received to TRUE
5296 * for use in gtk_window_move_resize()
5297 * - queueing a resize, leading to invocation of
5298 * gtk_window_move_resize() in an idle handler
5302 priv->configure_notify_received = TRUE;
5304 allocation.width = event->width;
5305 allocation.height = event->height;
5306 gtk_widget_set_allocation (widget, &allocation);
5308 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5310 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5316 gtk_window_state_event (GtkWidget *widget,
5317 GdkEventWindowState *event)
5319 update_grip_visibility (GTK_WINDOW (widget));
5325 gtk_window_direction_changed (GtkWidget *widget,
5326 GtkTextDirection prev_dir)
5328 GtkWindow *window = GTK_WINDOW (widget);
5330 set_grip_cursor (window);
5331 set_grip_position (window);
5332 set_grip_shape (window);
5336 gtk_window_state_changed (GtkWidget *widget,
5337 GtkStateType previous_state)
5339 GtkWindow *window = GTK_WINDOW (widget);
5341 update_grip_visibility (window);
5345 gtk_window_style_updated (GtkWidget *widget)
5347 GtkWindow *window = GTK_WINDOW (widget);
5348 GtkWindowPrivate *priv = window->priv;
5351 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5353 gdk_window_move_resize (priv->grip_window,
5355 rect.width, rect.height);
5357 set_grip_shape (window);
5358 gtk_widget_queue_resize (widget);
5363 resize_grip_create_window (GtkWindow *window)
5366 GtkWindowPrivate *priv;
5367 GdkWindowAttr attributes;
5368 gint attributes_mask;
5371 priv = window->priv;
5372 widget = GTK_WIDGET (window);
5374 g_return_if_fail (gtk_widget_get_realized (widget));
5375 g_return_if_fail (priv->grip_window == NULL);
5377 gtk_window_get_resize_grip_area (window, &rect);
5379 attributes.x = rect.x;
5380 attributes.y = rect.y;
5381 attributes.width = rect.width;
5382 attributes.height = rect.height;
5383 attributes.window_type = GDK_WINDOW_CHILD;
5384 attributes.wclass = GDK_INPUT_OUTPUT;
5385 attributes.event_mask = gtk_widget_get_events (widget) |
5387 GDK_BUTTON_PRESS_MASK;
5389 attributes_mask = GDK_WA_X | GDK_WA_Y;
5391 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5395 gdk_window_set_user_data (priv->grip_window, widget);
5397 gdk_window_raise (priv->grip_window);
5399 set_grip_shape (window);
5400 update_grip_visibility (window);
5404 resize_grip_destroy_window (GtkWindow *window)
5406 GtkWindowPrivate *priv = window->priv;
5408 gdk_window_set_user_data (priv->grip_window, NULL);
5409 gdk_window_destroy (priv->grip_window);
5410 priv->grip_window = NULL;
5411 update_grip_visibility (window);
5415 * gtk_window_set_has_resize_grip:
5416 * @window: a #GtkWindow
5417 * @value: %TRUE to allow a resize grip
5419 * Sets whether @window has a corner resize grip.
5421 * Note that the resize grip is only shown if the window
5422 * is actually resizable and not maximized. Use
5423 * gtk_window_resize_grip_is_visible() to find out if the
5424 * resize grip is currently shown.
5429 gtk_window_set_has_resize_grip (GtkWindow *window,
5432 GtkWidget *widget = GTK_WIDGET (window);
5433 GtkWindowPrivate *priv = window->priv;
5435 value = value != FALSE;
5437 if (value != priv->has_resize_grip)
5439 priv->has_resize_grip = value;
5440 gtk_widget_queue_draw (widget);
5442 if (gtk_widget_get_realized (widget) &&
5443 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5445 if (priv->has_resize_grip && priv->grip_window == NULL)
5446 resize_grip_create_window (window);
5447 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5448 resize_grip_destroy_window (window);
5451 g_object_notify (G_OBJECT (window), "has-resize-grip");
5456 update_grip_visibility (GtkWindow *window)
5458 GtkWindowPrivate *priv = window->priv;
5461 val = gtk_window_resize_grip_is_visible (window);
5463 if (priv->grip_window != NULL)
5467 gdk_window_show (priv->grip_window);
5468 set_grip_cursor (window);
5472 gdk_window_hide (priv->grip_window);
5476 if (priv->resize_grip_visible != val)
5478 priv->resize_grip_visible = val;
5480 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5485 * gtk_window_resize_grip_is_visible:
5486 * @window: a #GtkWindow
5488 * Determines whether a resize grip is visible for the specified window.
5490 * Returns: %TRUE if a resize grip exists and is visible
5495 gtk_window_resize_grip_is_visible (GtkWindow *window)
5498 GtkWindowPrivate *priv;
5501 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5503 priv = window->priv;
5504 widget = GTK_WIDGET (window);
5506 if (priv->type == GTK_WINDOW_POPUP)
5509 if (!priv->resizable)
5512 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5515 if (gtk_widget_get_realized (widget))
5517 GdkWindowState state;
5519 state = gdk_window_get_state (gtk_widget_get_window (widget));
5521 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5525 if (!get_drag_edge (widget, &edge))
5528 return window->priv->has_resize_grip;
5532 * gtk_window_get_has_resize_grip:
5533 * @window: a #GtkWindow
5535 * Determines whether the window may have a resize grip.
5537 * Returns: %TRUE if the window has a resize grip
5542 gtk_window_get_has_resize_grip (GtkWindow *window)
5544 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5546 return window->priv->has_resize_grip;
5550 * gtk_window_get_resize_grip_area:
5551 * @window: a #GtkWindow
5552 * @rect: (out): a pointer to a #GdkRectangle which we should store
5553 * the resize grip area
5555 * If a window has a resize grip, this will retrieve the grip
5556 * position, width and height into the specified #GdkRectangle.
5558 * Returns: %TRUE if the resize grip's area was retrieved
5563 gtk_window_get_resize_grip_area (GtkWindow *window,
5566 GtkWidget *widget = GTK_WIDGET (window);
5567 GtkAllocation allocation;
5571 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5573 if (!window->priv->has_resize_grip)
5576 gtk_widget_get_allocation (widget, &allocation);
5578 gtk_widget_style_get (widget,
5579 "resize-grip-width", &grip_width,
5580 "resize-grip-height", &grip_height,
5583 if (grip_width > allocation.width)
5584 grip_width = allocation.width;
5586 if (grip_height > allocation.height)
5587 grip_height = allocation.height;
5589 rect->width = grip_width;
5590 rect->height = grip_height;
5591 rect->y = allocation.y + allocation.height - grip_height;
5593 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5594 rect->x = allocation.x + allocation.width - grip_width;
5596 rect->x = allocation.x;
5601 /* the accel_key and accel_mods fields of the key have to be setup
5602 * upon calling this function. it'll then return whether that key
5603 * is at all used as accelerator, and if so will OR in the
5604 * accel_flags member of the key.
5607 _gtk_window_query_nonaccels (GtkWindow *window,
5609 GdkModifierType accel_mods)
5611 GtkWindowPrivate *priv;
5613 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5615 priv = window->priv;
5617 /* movement keys are considered locked accels */
5620 static const guint bindings[] = {
5621 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,
5622 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,
5626 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5627 if (bindings[i] == accel_key)
5631 /* mnemonics are considered locked accels */
5632 if (accel_mods == priv->mnemonic_modifier)
5634 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5635 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5643 * gtk_window_propagate_key_event:
5644 * @window: a #GtkWindow
5645 * @event: a #GdkEventKey
5647 * Propagate a key press or release event to the focus widget and
5648 * up the focus container chain until a widget handles @event.
5649 * This is normally called by the default ::key_press_event and
5650 * ::key_release_event handlers for toplevel windows,
5651 * however in some cases it may be useful to call this directly when
5652 * overriding the standard key handling for a toplevel window.
5654 * Return value: %TRUE if a widget in the focus chain handled the event.
5659 gtk_window_propagate_key_event (GtkWindow *window,
5662 GtkWindowPrivate *priv;
5663 gboolean handled = FALSE;
5664 GtkWidget *widget, *focus;
5666 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5668 priv = window->priv;
5669 widget = GTK_WIDGET (window);
5671 focus = priv->focus_widget;
5673 g_object_ref (focus);
5676 focus && focus != widget &&
5677 gtk_widget_get_toplevel (focus) == widget)
5681 if (gtk_widget_is_sensitive (focus))
5682 handled = gtk_widget_event (focus, (GdkEvent*) event);
5684 parent = gtk_widget_get_parent (focus);
5686 g_object_ref (parent);
5688 g_object_unref (focus);
5694 g_object_unref (focus);
5700 gtk_window_key_press_event (GtkWidget *widget,
5703 GtkWindow *window = GTK_WINDOW (widget);
5704 gboolean handled = FALSE;
5706 /* handle mnemonics and accelerators */
5708 handled = gtk_window_activate_key (window, event);
5710 /* handle focus widget key events */
5712 handled = gtk_window_propagate_key_event (window, event);
5714 /* Chain up, invokes binding set */
5716 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5722 gtk_window_key_release_event (GtkWidget *widget,
5725 GtkWindow *window = GTK_WINDOW (widget);
5726 gboolean handled = FALSE;
5728 /* handle focus widget key events */
5730 handled = gtk_window_propagate_key_event (window, event);
5732 /* Chain up, invokes binding set */
5734 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5740 gtk_window_button_press_event (GtkWidget *widget,
5741 GdkEventButton *event)
5743 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5746 if (event->window == priv->grip_window)
5748 if (get_drag_edge (widget, &edge))
5749 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5763 gtk_window_real_activate_default (GtkWindow *window)
5765 gtk_window_activate_default (window);
5769 gtk_window_real_activate_focus (GtkWindow *window)
5771 gtk_window_activate_focus (window);
5775 gtk_window_enter_notify_event (GtkWidget *widget,
5776 GdkEventCrossing *event)
5782 gtk_window_leave_notify_event (GtkWidget *widget,
5783 GdkEventCrossing *event)
5789 do_focus_change (GtkWidget *widget,
5793 GdkDeviceManager *device_manager;
5796 g_object_ref (widget);
5798 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5799 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5800 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5801 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5803 for (d = devices; d; d = d->next)
5805 GdkDevice *dev = d->data;
5808 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5811 /* Skip non-master keyboards that haven't
5812 * selected for events from this window
5814 window = gtk_widget_get_window (widget);
5815 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5816 window && !gdk_window_get_device_events (window, dev))
5819 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5821 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5822 fevent->focus_change.window = window;
5824 g_object_ref (window);
5825 fevent->focus_change.in = in;
5826 gdk_event_set_device (fevent, dev);
5828 gtk_widget_send_focus_change (widget, fevent);
5830 gdk_event_free (fevent);
5833 g_list_free (devices);
5834 g_object_unref (widget);
5838 gtk_window_focus_in_event (GtkWidget *widget,
5839 GdkEventFocus *event)
5841 GtkWindow *window = GTK_WINDOW (widget);
5843 /* It appears spurious focus in events can occur when
5844 * the window is hidden. So we'll just check to see if
5845 * the window is visible before actually handling the
5848 if (gtk_widget_get_visible (widget))
5850 _gtk_window_set_has_toplevel_focus (window, TRUE);
5851 _gtk_window_set_is_active (window, TRUE);
5858 gtk_window_focus_out_event (GtkWidget *widget,
5859 GdkEventFocus *event)
5861 GtkWindow *window = GTK_WINDOW (widget);
5862 gboolean auto_mnemonics;
5864 _gtk_window_set_has_toplevel_focus (window, FALSE);
5865 _gtk_window_set_is_active (window, FALSE);
5867 /* set the mnemonic-visible property to false */
5868 g_object_get (gtk_widget_get_settings (widget),
5869 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5871 gtk_window_set_mnemonics_visible (window, FALSE);
5877 gtk_window_check_resize (GtkContainer *container)
5879 /* If the window is not toplevel anymore than it's embedded somewhere,
5880 * so handle it like a normal window */
5881 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
5882 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
5883 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
5884 gtk_window_move_resize (GTK_WINDOW (container));
5888 gtk_window_focus (GtkWidget *widget,
5889 GtkDirectionType direction)
5891 GtkWindowPrivate *priv;
5894 GtkContainer *container;
5896 GtkWidget *old_focus_child;
5899 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5900 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
5902 container = GTK_CONTAINER (widget);
5903 window = GTK_WINDOW (widget);
5904 priv = window->priv;
5905 bin = GTK_BIN (widget);
5907 old_focus_child = gtk_container_get_focus_child (container);
5909 /* We need a special implementation here to deal properly with wrapping
5910 * around in the tab chain without the danger of going into an
5913 if (old_focus_child)
5915 if (gtk_widget_child_focus (old_focus_child, direction))
5919 if (priv->focus_widget)
5921 if (direction == GTK_DIR_LEFT ||
5922 direction == GTK_DIR_RIGHT ||
5923 direction == GTK_DIR_UP ||
5924 direction == GTK_DIR_DOWN)
5929 /* Wrapped off the end, clear the focus setting for the toplpevel */
5930 parent = gtk_widget_get_parent (priv->focus_widget);
5933 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5934 parent = gtk_widget_get_parent (parent);
5937 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5940 /* Now try to focus the first widget in the window */
5941 child = gtk_bin_get_child (bin);
5944 if (gtk_widget_child_focus (child, direction))
5952 gtk_window_move_focus (GtkWidget *widget,
5953 GtkDirectionType dir)
5955 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5957 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
5961 gtk_widget_child_focus (widget, dir);
5963 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
5964 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
5968 gtk_window_real_set_focus (GtkWindow *window,
5971 GtkWindowPrivate *priv = window->priv;
5972 GtkWidget *old_focus = priv->focus_widget;
5973 gboolean had_default = FALSE;
5974 gboolean focus_had_default = FALSE;
5975 gboolean old_focus_had_default = FALSE;
5979 g_object_ref (old_focus);
5980 g_object_freeze_notify (G_OBJECT (old_focus));
5981 old_focus_had_default = gtk_widget_has_default (old_focus);
5985 g_object_ref (focus);
5986 g_object_freeze_notify (G_OBJECT (focus));
5987 focus_had_default = gtk_widget_has_default (focus);
5990 if (priv->default_widget)
5991 had_default = gtk_widget_has_default (priv->default_widget);
5993 if (priv->focus_widget)
5995 if (gtk_widget_get_receives_default (priv->focus_widget) &&
5996 (priv->focus_widget != priv->default_widget))
5998 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
5999 gtk_widget_queue_draw (priv->focus_widget);
6001 if (priv->default_widget)
6002 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6005 priv->focus_widget = NULL;
6007 if (priv->has_focus)
6008 do_focus_change (old_focus, FALSE);
6010 g_object_notify (G_OBJECT (old_focus), "is-focus");
6013 /* The above notifications may have set a new focus widget,
6014 * if so, we don't want to override it.
6016 if (focus && !priv->focus_widget)
6018 priv->focus_widget = focus;
6020 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6021 (priv->focus_widget != priv->default_widget))
6023 if (gtk_widget_get_can_default (priv->focus_widget))
6024 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6026 if (priv->default_widget)
6027 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6030 if (priv->has_focus)
6031 do_focus_change (priv->focus_widget, TRUE);
6033 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6036 /* If the default widget changed, a redraw will have been queued
6037 * on the old and new default widgets by gtk_window_set_default(), so
6038 * we only have to worry about the case where it didn't change.
6039 * We'll sometimes queue a draw twice on the new widget but that
6042 if (priv->default_widget &&
6043 (had_default != gtk_widget_has_default (priv->default_widget)))
6044 gtk_widget_queue_draw (priv->default_widget);
6048 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6049 gtk_widget_queue_draw (old_focus);
6051 g_object_thaw_notify (G_OBJECT (old_focus));
6052 g_object_unref (old_focus);
6056 if (focus_had_default != gtk_widget_has_default (focus))
6057 gtk_widget_queue_draw (focus);
6059 g_object_thaw_notify (G_OBJECT (focus));
6060 g_object_unref (focus);
6066 gtk_window_get_preferred_width (GtkWidget *widget,
6074 window = GTK_WINDOW (widget);
6075 child = gtk_bin_get_child (GTK_BIN (window));
6077 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6078 *minimum_size = border_width * 2;
6079 *natural_size = border_width * 2;
6081 if (child && gtk_widget_get_visible (child))
6083 gint child_min, child_nat;
6084 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6086 *minimum_size += child_min;
6087 *natural_size += child_nat;
6092 gtk_window_get_preferred_height (GtkWidget *widget,
6100 window = GTK_WINDOW (widget);
6101 child = gtk_bin_get_child (GTK_BIN (window));
6103 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6104 *minimum_size = border_width * 2;
6105 *natural_size = border_width * 2;
6107 if (child && gtk_widget_get_visible (child))
6109 gint child_min, child_nat;
6110 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6112 *minimum_size += child_min;
6113 *natural_size += child_nat;
6119 * _gtk_window_unset_focus_and_default:
6120 * @window: a #GtkWindow
6121 * @widget: a widget inside of @window
6123 * Checks whether the focus and default widgets of @window are
6124 * @widget or a descendent of @widget, and if so, unset them.
6127 _gtk_window_unset_focus_and_default (GtkWindow *window,
6131 GtkWindowPrivate *priv = window->priv;
6135 g_object_ref (window);
6136 g_object_ref (widget);
6138 parent = gtk_widget_get_parent (widget);
6139 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6141 child = priv->focus_widget;
6143 while (child && child != widget)
6144 child = gtk_widget_get_parent (child);
6146 if (child == widget)
6147 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6150 child = priv->default_widget;
6152 while (child && child != widget)
6153 child = gtk_widget_get_parent (child);
6155 if (child == widget)
6156 gtk_window_set_default (window, NULL);
6158 g_object_unref (widget);
6159 g_object_unref (window);
6162 /*********************************
6163 * Functions related to resizing *
6164 *********************************/
6167 geometry_size_to_pixels (GdkGeometry *geometry,
6172 gint base_width = 0;
6173 gint base_height = 0;
6175 gint min_height = 0;
6177 gint height_inc = 1;
6179 if (flags & GDK_HINT_BASE_SIZE)
6181 base_width = geometry->base_width;
6182 base_height = geometry->base_height;
6184 if (flags & GDK_HINT_MIN_SIZE)
6186 min_width = geometry->min_width;
6187 min_height = geometry->min_height;
6189 if (flags & GDK_HINT_RESIZE_INC)
6191 width_inc = geometry->width_inc;
6192 height_inc = geometry->height_inc;
6196 *width = MAX (*width * width_inc + base_width, min_width);
6198 *height = MAX (*height * height_inc + base_height, min_height);
6201 /* This function doesn't constrain to geometry hints */
6203 gtk_window_compute_configure_request_size (GtkWindow *window,
6204 GdkGeometry *geometry,
6209 GtkWindowPrivate *priv = window->priv;
6210 GtkRequisition requisition;
6211 GtkWindowGeometryInfo *info;
6215 * - we've done a size request
6218 widget = GTK_WIDGET (window);
6220 info = gtk_window_get_geometry_info (window, FALSE);
6222 if (priv->need_default_size)
6224 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6226 /* Default to requisition */
6227 *width = requisition.width;
6228 *height = requisition.height;
6230 /* If window is empty so requests 0, default to random nonzero size */
6231 if (*width == 0 && *height == 0)
6237 /* Override requisition with default size */
6241 if (info->default_width > 0)
6242 *width = info->default_width;
6243 if (info->default_height > 0)
6244 *height = info->default_height;
6246 if (info->default_is_geometry)
6247 geometry_size_to_pixels (geometry, flags,
6248 info->default_width > 0 ? width : NULL,
6249 info->default_height > 0 ? height : NULL);
6254 GtkAllocation allocation;
6256 gtk_widget_get_allocation (widget, &allocation);
6258 /* Default to keeping current size */
6259 *width = allocation.width;
6260 *height = allocation.height;
6263 /* Override any size with gtk_window_resize() values */
6266 if (info->resize_width > 0)
6267 *width = info->resize_width;
6268 if (info->resize_height > 0)
6269 *height = info->resize_height;
6271 if (info->resize_is_geometry)
6272 geometry_size_to_pixels (geometry, flags,
6273 info->resize_width > 0 ? width : NULL,
6274 info->resize_height > 0 ? height : NULL);
6277 /* Don't ever request zero width or height, its not supported by
6278 gdk. The size allocation code will round it to 1 anyway but if
6279 we do it then the value returned from this function will is
6280 not comparable to the size allocation read from the GtkWindow. */
6281 *width = MAX (*width, 1);
6282 *height = MAX (*height, 1);
6285 static GtkWindowPosition
6286 get_effective_position (GtkWindow *window)
6288 GtkWindowPrivate *priv = window->priv;
6289 GtkWindowPosition pos = priv->position;
6291 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6292 (priv->transient_parent == NULL ||
6293 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6294 pos = GTK_WIN_POS_NONE;
6300 get_center_monitor_of_window (GtkWindow *window)
6302 /* We could try to sort out the relative positions of the monitors and
6303 * stuff, or we could just be losers and assume you have a row
6304 * or column of monitors.
6306 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6310 get_monitor_containing_pointer (GtkWindow *window)
6314 GdkScreen *window_screen;
6315 GdkScreen *pointer_screen;
6316 GdkDisplay *display;
6317 GdkDeviceManager *device_manager;
6320 window_screen = gtk_window_check_screen (window);
6321 display = gdk_screen_get_display (window_screen);
6322 device_manager = gdk_display_get_device_manager (display);
6323 pointer = gdk_device_manager_get_client_pointer (device_manager);
6325 gdk_device_get_position (pointer,
6329 if (pointer_screen == window_screen)
6330 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6338 center_window_on_monitor (GtkWindow *window,
6344 GdkRectangle monitor;
6347 monitor_num = get_monitor_containing_pointer (window);
6349 if (monitor_num == -1)
6350 monitor_num = get_center_monitor_of_window (window);
6352 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6353 monitor_num, &monitor);
6355 *x = (monitor.width - w) / 2 + monitor.x;
6356 *y = (monitor.height - h) / 2 + monitor.y;
6358 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6359 * and WM decorations.
6373 if (extent > clamp_extent)
6375 *base = clamp_base + clamp_extent/2 - extent/2;
6376 else if (*base < clamp_base)
6378 else if (*base + extent > clamp_base + clamp_extent)
6379 *base = clamp_base + clamp_extent - extent;
6383 clamp_window_to_rectangle (gint *x,
6387 const GdkRectangle *rect)
6389 #ifdef DEBUGGING_OUTPUT
6390 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);
6393 /* If it is too large, center it. If it fits on the monitor but is
6394 * partially outside, move it to the closest edge. Do this
6395 * separately in x and y directions.
6397 clamp (x, w, rect->x, rect->width);
6398 clamp (y, h, rect->y, rect->height);
6399 #ifdef DEBUGGING_OUTPUT
6400 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6406 gtk_window_compute_configure_request (GtkWindow *window,
6407 GdkRectangle *request,
6408 GdkGeometry *geometry,
6411 GtkWindowPrivate *priv = window->priv;
6412 GdkGeometry new_geometry;
6415 GtkWindowPosition pos;
6416 GtkWidget *parent_widget;
6417 GtkWindowGeometryInfo *info;
6421 screen = gtk_window_check_screen (window);
6423 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6424 gtk_window_compute_configure_request_size (window,
6425 &new_geometry, new_flags,
6426 (guint *)&w, (guint *)&h);
6428 gtk_window_constrain_size (window,
6429 &new_geometry, new_flags,
6433 parent_widget = (GtkWidget*) priv->transient_parent;
6435 pos = get_effective_position (window);
6436 info = gtk_window_get_geometry_info (window, FALSE);
6438 /* by default, don't change position requested */
6441 x = info->last.configure_request.x;
6442 y = info->last.configure_request.y;
6451 if (priv->need_default_position)
6454 /* FIXME this all interrelates with window gravity.
6455 * For most of them I think we want to set GRAVITY_CENTER.
6457 * Not sure how to go about that.
6461 /* here we are only handling CENTER_ALWAYS
6462 * as it relates to default positioning,
6463 * where it's equivalent to simply CENTER
6465 case GTK_WIN_POS_CENTER_ALWAYS:
6466 case GTK_WIN_POS_CENTER:
6467 center_window_on_monitor (window, w, h, &x, &y);
6470 case GTK_WIN_POS_CENTER_ON_PARENT:
6472 GtkAllocation allocation;
6473 GdkWindow *gdk_window;
6475 GdkRectangle monitor;
6478 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6480 gdk_window = gtk_widget_get_window (parent_widget);
6482 if (gdk_window != NULL)
6483 monitor_num = gdk_screen_get_monitor_at_window (screen,
6488 gdk_window_get_origin (gdk_window,
6491 gtk_widget_get_allocation (parent_widget, &allocation);
6492 x = ox + (allocation.width - w) / 2;
6493 y = oy + (allocation.height - h) / 2;
6495 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6496 * WM decorations. If parent wasn't on a monitor, just
6499 if (monitor_num >= 0)
6501 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6502 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6507 case GTK_WIN_POS_MOUSE:
6509 gint screen_width = gdk_screen_get_width (screen);
6510 gint screen_height = gdk_screen_get_height (screen);
6512 GdkRectangle monitor;
6513 GdkDisplay *display;
6514 GdkDeviceManager *device_manager;
6516 GdkScreen *pointer_screen;
6519 display = gdk_screen_get_display (screen);
6520 device_manager = gdk_display_get_device_manager (display);
6521 pointer = gdk_device_manager_get_client_pointer (device_manager);
6523 gdk_device_get_position (pointer,
6527 if (pointer_screen == screen)
6528 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6534 x = CLAMP (x, 0, screen_width - w);
6535 y = CLAMP (y, 0, screen_height - h);
6537 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6538 * WM decorations. Don't try to figure out what's going
6539 * on if the mouse wasn't inside a monitor.
6541 if (monitor_num >= 0)
6543 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6544 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6552 } /* if (priv->need_default_position) */
6554 if (priv->need_default_position && info &&
6555 info->initial_pos_set)
6557 x = info->initial_x;
6558 y = info->initial_y;
6559 gtk_window_constrain_position (window, w, h, &x, &y);
6565 request->height = h;
6568 *geometry = new_geometry;
6574 gtk_window_constrain_position (GtkWindow *window,
6580 GtkWindowPrivate *priv = window->priv;
6582 /* See long comments in gtk_window_move_resize()
6583 * on when it's safe to call this function.
6585 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6587 gint center_x, center_y;
6589 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6597 gtk_window_move_resize (GtkWindow *window)
6601 * First we determine whether any information has changed that would
6602 * cause us to revise our last configure request. If we would send
6603 * a different configure request from last time, then
6604 * configure_request_size_changed = TRUE or
6605 * configure_request_pos_changed = TRUE. configure_request_size_changed
6606 * may be true due to new hints, a gtk_window_resize(), or whatever.
6607 * configure_request_pos_changed may be true due to gtk_window_set_position()
6608 * or gtk_window_move().
6610 * If the configure request has changed, we send off a new one. To
6611 * ensure GTK+ invariants are maintained (resize queue does what it
6612 * should), we go ahead and size_allocate the requested size in this
6615 * If the configure request has not changed, we don't ever resend
6616 * it, because it could mean fighting the user or window manager.
6619 * To prepare the configure request, we come up with a base size/pos:
6620 * - the one from gtk_window_move()/gtk_window_resize()
6621 * - else default_width, default_height if we haven't ever
6623 * - else the size request if we haven't ever been mapped,
6624 * as a substitute default size
6625 * - else the current size of the window, as received from
6626 * configure notifies (i.e. the current allocation)
6628 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6629 * the position request to be centered.
6631 GtkWindowPrivate *priv = window->priv;
6632 GtkAllocation allocation;
6634 GtkContainer *container;
6635 GtkWindowGeometryInfo *info;
6636 GdkGeometry new_geometry;
6637 GdkWindow *gdk_window;
6639 GdkRectangle new_request;
6640 gboolean configure_request_size_changed;
6641 gboolean configure_request_pos_changed;
6642 gboolean hints_changed; /* do we need to send these again */
6643 GtkWindowLastGeometryInfo saved_last_info;
6645 widget = GTK_WIDGET (window);
6647 gdk_window = gtk_widget_get_window (widget);
6648 container = GTK_CONTAINER (widget);
6649 info = gtk_window_get_geometry_info (window, TRUE);
6651 configure_request_size_changed = FALSE;
6652 configure_request_pos_changed = FALSE;
6654 gtk_window_compute_configure_request (window, &new_request,
6655 &new_geometry, &new_flags);
6657 /* This check implies the invariant that we never set info->last
6658 * without setting the hints and sending off a configure request.
6660 * If we change info->last without sending the request, we may
6663 if (info->last.configure_request.x != new_request.x ||
6664 info->last.configure_request.y != new_request.y)
6665 configure_request_pos_changed = TRUE;
6667 if ((info->last.configure_request.width != new_request.width ||
6668 info->last.configure_request.height != new_request.height))
6669 configure_request_size_changed = TRUE;
6671 hints_changed = FALSE;
6673 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6674 &new_geometry, new_flags))
6676 hints_changed = TRUE;
6679 /* Position Constraints
6680 * ====================
6682 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6683 * a default. The other POS_ values are used only when the
6684 * window is shown, not after that.
6686 * However, we can't implement a position constraint as
6687 * "anytime the window size changes, center the window"
6688 * because this may well end up fighting the WM or user. In
6689 * fact it gets in an infinite loop with at least one WM.
6691 * Basically, applications are in no way in a position to
6692 * constrain the position of a window, with one exception:
6693 * override redirect windows. (Really the intended purpose
6694 * of CENTER_ALWAYS anyhow, I would think.)
6696 * So the way we implement this "constraint" is to say that when WE
6697 * cause a move or resize, i.e. we make a configure request changing
6698 * window size, we recompute the CENTER_ALWAYS position to reflect
6699 * the new window size, and include it in our request. Also, if we
6700 * just turned on CENTER_ALWAYS we snap to center with a new
6701 * request. Otherwise, if we are just NOTIFIED of a move or resize
6702 * done by someone else e.g. the window manager, we do NOT send a
6703 * new configure request.
6705 * For override redirect windows, this works fine; all window
6706 * sizes are from our configure requests. For managed windows,
6707 * it is at least semi-sane, though who knows what the
6708 * app author is thinking.
6711 /* This condition should be kept in sync with the condition later on
6712 * that determines whether we send a configure request. i.e. we
6713 * should do this position constraining anytime we were going to
6714 * send a configure request anyhow, plus when constraints have
6717 if (configure_request_pos_changed ||
6718 configure_request_size_changed ||
6720 info->position_constraints_changed)
6722 /* We request the constrained position if:
6723 * - we were changing position, and need to clamp
6724 * the change to the constraint
6725 * - we're changing the size anyway
6726 * - set_position() was called to toggle CENTER_ALWAYS on
6729 gtk_window_constrain_position (window,
6735 /* Update whether we need to request a move */
6736 if (info->last.configure_request.x != new_request.x ||
6737 info->last.configure_request.y != new_request.y)
6738 configure_request_pos_changed = TRUE;
6740 configure_request_pos_changed = FALSE;
6744 if (priv->type == GTK_WINDOW_TOPLEVEL)
6746 int notify_x, notify_y;
6748 /* this is the position from the last configure notify */
6749 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6751 g_message ("--- %s ---\n"
6752 "last : %d,%d\t%d x %d\n"
6753 "this : %d,%d\t%d x %d\n"
6754 "alloc : %d,%d\t%d x %d\n"
6756 "resize: \t%d x %d\n"
6757 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6758 "configure_notify_received: %d\n"
6759 "configure_request_count: %d\n"
6760 "position_constraints_changed: %d\n",
6761 priv->title ? priv->title : "(no title)",
6762 info->last.configure_request.x,
6763 info->last.configure_request.y,
6764 info->last.configure_request.width,
6765 info->last.configure_request.height,
6771 widget->allocation.width,
6772 widget->allocation.height,
6773 widget->requisition.width,
6774 widget->requisition.height,
6776 info->resize_height,
6777 configure_request_pos_changed,
6778 configure_request_size_changed,
6780 priv->configure_notify_received,
6781 priv->configure_request_count,
6782 info->position_constraints_changed);
6786 saved_last_info = info->last;
6787 info->last.geometry = new_geometry;
6788 info->last.flags = new_flags;
6789 info->last.configure_request = new_request;
6791 /* need to set PPosition so the WM will look at our position,
6792 * but we don't want to count PPosition coming and going as a hints
6793 * change for future iterations. So we saved info->last prior to
6797 /* Also, if the initial position was explicitly set, then we always
6798 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6802 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6803 * this is an initial map
6806 if ((configure_request_pos_changed ||
6807 info->initial_pos_set ||
6808 (priv->need_default_position &&
6809 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6810 (new_flags & GDK_HINT_POS) == 0)
6812 new_flags |= GDK_HINT_POS;
6813 hints_changed = TRUE;
6816 /* Set hints if necessary
6819 gdk_window_set_geometry_hints (gdk_window,
6823 gtk_widget_get_allocation (widget, &allocation);
6825 /* handle resizing/moving and widget tree allocation
6827 if (priv->configure_notify_received)
6829 /* If we have received a configure event since
6830 * the last time in this function, we need to
6831 * accept our new size and size_allocate child widgets.
6832 * (see gtk_window_configure_event() for more details).
6834 * 1 or more configure notifies may have been received.
6835 * Also, configure_notify_received will only be TRUE
6836 * if all expected configure notifies have been received
6837 * (one per configure request), as an optimization.
6840 priv->configure_notify_received = FALSE;
6842 /* gtk_window_configure_event() filled in widget->allocation */
6843 gtk_widget_size_allocate (widget, &allocation);
6845 set_grip_position (window);
6846 update_grip_visibility (window);
6848 gdk_window_process_updates (gdk_window, TRUE);
6850 gdk_window_configure_finished (gdk_window);
6852 /* If the configure request changed, it means that
6854 * 1) coincidentally changed hints or widget properties
6855 * impacting the configure request before getting
6856 * a configure notify, or
6857 * 2) some broken widget is changing its size request
6858 * during size allocation, resulting in
6859 * a false appearance of changed configure request.
6861 * For 1), we could just go ahead and ask for the
6862 * new size right now, but doing that for 2)
6863 * might well be fighting the user (and can even
6864 * trigger a loop). Since we really don't want to
6865 * do that, we requeue a resize in hopes that
6866 * by the time it gets handled, the child has seen
6867 * the light and is willing to go along with the
6868 * new size. (this happens for the zvt widget, since
6869 * the size_allocate() above will have stored the
6870 * requisition corresponding to the new size in the
6873 * This doesn't buy us anything for 1), but it shouldn't
6874 * hurt us too badly, since it is what would have
6875 * happened if we had gotten the configure event before
6876 * the new size had been set.
6879 if (configure_request_size_changed ||
6880 configure_request_pos_changed)
6882 /* Don't change the recorded last info after all, because we
6883 * haven't actually updated to the new info yet - we decided
6884 * to postpone our configure request until later.
6886 info->last = saved_last_info;
6888 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6891 return; /* Bail out, we didn't really process the move/resize */
6893 else if ((configure_request_size_changed || hints_changed) &&
6894 (allocation.width != new_request.width || allocation.height != new_request.height))
6897 /* We are in one of the following situations:
6898 * A. configure_request_size_changed
6899 * our requisition has changed and we need a different window size,
6900 * so we request it from the window manager.
6901 * B. !configure_request_size_changed && hints_changed
6902 * the window manager rejects our size, but we have just changed the
6903 * window manager hints, so there's a chance our request will
6904 * be honoured this time, so we try again.
6906 * However, if the new requisition is the same as the current allocation,
6907 * we don't request it again, since we won't get a ConfigureNotify back from
6908 * the window manager unless it decides to change our requisition. If
6909 * we don't get the ConfigureNotify back, the resize queue will never be run.
6912 /* Now send the configure request */
6913 if (configure_request_pos_changed)
6915 gdk_window_move_resize (gdk_window,
6916 new_request.x, new_request.y,
6917 new_request.width, new_request.height);
6919 else /* only size changed */
6921 gdk_window_resize (gdk_window,
6922 new_request.width, new_request.height);
6925 if (priv->type == GTK_WINDOW_POPUP)
6927 GtkAllocation allocation;
6929 /* Directly size allocate for override redirect (popup) windows. */
6932 allocation.width = new_request.width;
6933 allocation.height = new_request.height;
6935 gtk_widget_size_allocate (widget, &allocation);
6937 gdk_window_process_updates (gdk_window, TRUE);
6939 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6940 gtk_widget_queue_draw (widget);
6944 /* Increment the number of have-not-yet-received-notify requests */
6945 priv->configure_request_count += 1;
6946 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
6948 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6949 * configure event in response to our resizing request.
6950 * the configure event will cause a new resize with
6951 * ->configure_notify_received=TRUE.
6952 * until then, we want to
6953 * - discard expose events
6954 * - coalesce resizes for our children
6955 * - defer any window resizes until the configure event arrived
6956 * to achieve this, we queue a resize for the window, but remove its
6957 * resizing handler, so resizing will not be handled from the next
6958 * idle handler but when the configure event arrives.
6960 * FIXME: we should also dequeue the pending redraws here, since
6961 * we handle those ourselves upon ->configure_notify_received==TRUE.
6963 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6965 gtk_widget_queue_resize_no_redraw (widget);
6966 _gtk_container_dequeue_resize_handler (container);
6972 /* Handle any position changes.
6974 if (configure_request_pos_changed)
6976 gdk_window_move (gdk_window,
6977 new_request.x, new_request.y);
6980 /* And run the resize queue.
6982 gtk_container_resize_children (container);
6985 /* We have now processed a move/resize since the last position
6986 * constraint change, setting of the initial position, or resize.
6987 * (Not resetting these flags here can lead to infinite loops for
6988 * GTK_RESIZE_IMMEDIATE containers)
6990 info->position_constraints_changed = FALSE;
6991 info->initial_pos_set = FALSE;
6992 info->resize_width = -1;
6993 info->resize_height = -1;
6996 /* Compare two sets of Geometry hints for equality.
6999 gtk_window_compare_hints (GdkGeometry *geometry_a,
7001 GdkGeometry *geometry_b,
7004 if (flags_a != flags_b)
7007 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7008 (geometry_a->min_width != geometry_b->min_width ||
7009 geometry_a->min_height != geometry_b->min_height))
7012 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7013 (geometry_a->max_width != geometry_b->max_width ||
7014 geometry_a->max_height != geometry_b->max_height))
7017 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7018 (geometry_a->base_width != geometry_b->base_width ||
7019 geometry_a->base_height != geometry_b->base_height))
7022 if ((flags_a & GDK_HINT_ASPECT) &&
7023 (geometry_a->min_aspect != geometry_b->min_aspect ||
7024 geometry_a->max_aspect != geometry_b->max_aspect))
7027 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7028 (geometry_a->width_inc != geometry_b->width_inc ||
7029 geometry_a->height_inc != geometry_b->height_inc))
7032 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7033 geometry_a->win_gravity != geometry_b->win_gravity)
7040 _gtk_window_constrain_size (GtkWindow *window,
7046 GtkWindowPrivate *priv;
7047 GtkWindowGeometryInfo *info;
7049 g_return_if_fail (GTK_IS_WINDOW (window));
7051 priv = window->priv;
7053 info = priv->geometry_info;
7056 GdkWindowHints flags = info->last.flags;
7057 GdkGeometry *geometry = &info->last.geometry;
7059 gtk_window_constrain_size (window,
7070 gtk_window_constrain_size (GtkWindow *window,
7071 GdkGeometry *geometry,
7078 gdk_window_constrain_size (geometry, flags, width, height,
7079 new_width, new_height);
7082 /* Compute the set of geometry hints and flags for a window
7083 * based on the application set geometry, and requisition
7084 * of the window. gtk_widget_get_preferred_size() must have been
7088 gtk_window_compute_hints (GtkWindow *window,
7089 GdkGeometry *new_geometry,
7092 GtkWindowPrivate *priv = window->priv;
7094 gint extra_width = 0;
7095 gint extra_height = 0;
7096 GtkWindowGeometryInfo *geometry_info;
7097 GtkRequisition requisition;
7099 widget = GTK_WIDGET (window);
7101 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7102 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7106 *new_flags = geometry_info->mask;
7107 *new_geometry = geometry_info->geometry;
7114 if (geometry_info && geometry_info->widget)
7116 /* If the geometry widget is set, then the hints really apply to that
7117 * widget. This is pretty much meaningless unless the window layout
7118 * is such that the rest of the window adds fixed size borders to
7119 * the geometry widget. Our job is to figure the size of the borders;
7120 * We do that by asking how big the toplevel would be if the
7121 * geometry widget was *really big*.
7124 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7125 * |GGGGG B| in the border can confuse things
7131 * |AAAAAAAAA | When the geometry widget is large, things are
7132 * |GGGGGGGGGGB| clearer.
7137 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7138 GtkRequisition requisition;
7139 int current_width, current_height;
7141 _gtk_widget_override_size_request (geometry_info->widget,
7142 TEMPORARY_SIZE, TEMPORARY_SIZE,
7143 ¤t_width, ¤t_height);
7144 gtk_widget_get_preferred_size (widget,
7145 &requisition, NULL);
7146 _gtk_widget_restore_size_request (geometry_info->widget,
7147 current_width, current_height);
7149 extra_width = requisition.width - TEMPORARY_SIZE;
7150 extra_height = requisition.height - TEMPORARY_SIZE;
7152 if (extra_width < 0 || extra_width < 0)
7154 g_warning("Toplevel size doesn't seem to directly depend on the "
7155 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7156 "The geometry widget might not be in the window, or it might not "
7157 "be packed into the window appropriately");
7158 extra_width = MAX(extra_width, 0);
7159 extra_height = MAX(extra_height, 0);
7161 #undef TEMPORARY_SIZE
7164 /* We don't want to set GDK_HINT_POS in here, we just set it
7165 * in gtk_window_move_resize() when we want the position
7169 if (*new_flags & GDK_HINT_BASE_SIZE)
7171 new_geometry->base_width += extra_width;
7172 new_geometry->base_height += extra_height;
7176 /* For simplicity, we always set the base hint, even when we
7177 * don't expect it to have any visible effect.
7178 * (Note: geometry_size_to_pixels() depends on this.)
7180 *new_flags |= GDK_HINT_BASE_SIZE;
7182 new_geometry->base_width = extra_width;
7183 new_geometry->base_height = extra_height;
7185 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7186 * base size is the minimum size */
7187 if (*new_flags & GDK_HINT_MIN_SIZE)
7189 if (new_geometry->min_width > 0)
7190 new_geometry->base_width += new_geometry->min_width;
7191 if (new_geometry->min_height > 0)
7192 new_geometry->base_height += new_geometry->min_height;
7196 if (*new_flags & GDK_HINT_MIN_SIZE)
7198 if (new_geometry->min_width < 0)
7199 new_geometry->min_width = requisition.width;
7201 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7203 if (new_geometry->min_height < 0)
7204 new_geometry->min_height = requisition.height;
7206 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7210 *new_flags |= GDK_HINT_MIN_SIZE;
7212 new_geometry->min_width = requisition.width;
7213 new_geometry->min_height = requisition.height;
7216 if (*new_flags & GDK_HINT_MAX_SIZE)
7218 if (new_geometry->max_width < 0)
7219 new_geometry->max_width = requisition.width;
7221 new_geometry->max_width += extra_width;
7223 if (new_geometry->max_height < 0)
7224 new_geometry->max_height = requisition.height;
7226 new_geometry->max_height += extra_height;
7228 else if (!priv->resizable)
7230 *new_flags |= GDK_HINT_MAX_SIZE;
7232 new_geometry->max_width = requisition.width;
7233 new_geometry->max_height = requisition.height;
7236 *new_flags |= GDK_HINT_WIN_GRAVITY;
7237 new_geometry->win_gravity = priv->gravity;
7240 /***********************
7241 * Redrawing functions *
7242 ***********************/
7245 gtk_window_draw (GtkWidget *widget,
7248 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7249 GtkStyleContext *context;
7250 gboolean ret = FALSE;
7252 context = gtk_widget_get_style_context (widget);
7254 gtk_style_context_save (context);
7256 if (!gtk_widget_get_app_paintable (widget))
7258 GtkStateFlags state;
7260 state = gtk_widget_get_state_flags (widget);
7262 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7263 state |= GTK_STATE_FLAG_FOCUSED;
7265 gtk_style_context_set_state (context, state);
7266 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7267 gtk_render_background (context, cr, 0, 0,
7268 gtk_widget_get_allocated_width (widget),
7269 gtk_widget_get_allocated_height (widget));
7272 gtk_style_context_restore (context);
7274 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7275 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7277 if (priv->grip_window != NULL &&
7278 gtk_cairo_should_draw_window (cr, priv->grip_window))
7282 gtk_style_context_save (context);
7285 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7286 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7288 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7289 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7290 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7293 gtk_style_context_restore (context);
7300 * gtk_window_present:
7301 * @window: a #GtkWindow
7303 * Presents a window to the user. This may mean raising the window
7304 * in the stacking order, deiconifying it, moving it to the current
7305 * desktop, and/or giving it the keyboard focus, possibly dependent
7306 * on the user's platform, window manager, and preferences.
7308 * If @window is hidden, this function calls gtk_widget_show()
7311 * This function should be used when the user tries to open a window
7312 * that's already open. Say for example the preferences dialog is
7313 * currently open, and the user chooses Preferences from the menu
7314 * a second time; use gtk_window_present() to move the already-open dialog
7315 * where the user can see it.
7317 * If you are calling this function in response to a user interaction,
7318 * it is preferable to use gtk_window_present_with_time().
7322 gtk_window_present (GtkWindow *window)
7324 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7328 * gtk_window_present_with_time:
7329 * @window: a #GtkWindow
7330 * @timestamp: the timestamp of the user interaction (typically a
7331 * button or key press event) which triggered this call
7333 * Presents a window to the user in response to a user interaction.
7334 * If you need to present a window without a timestamp, use
7335 * gtk_window_present(). See gtk_window_present() for details.
7340 gtk_window_present_with_time (GtkWindow *window,
7344 GdkWindow *gdk_window;
7346 g_return_if_fail (GTK_IS_WINDOW (window));
7348 widget = GTK_WIDGET (window);
7350 if (gtk_widget_get_visible (widget))
7352 gdk_window = gtk_widget_get_window (widget);
7354 g_assert (gdk_window != NULL);
7356 gdk_window_show (gdk_window);
7358 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7359 if (timestamp == GDK_CURRENT_TIME)
7361 #ifdef GDK_WINDOWING_X11
7362 if (GDK_IS_X11_WINDOW(gdk_window))
7364 GdkDisplay *display;
7366 display = gtk_widget_get_display (GTK_WIDGET (window));
7367 timestamp = gdk_x11_display_get_user_time (display);
7371 timestamp = gtk_get_current_event_time ();
7374 gdk_window_focus (gdk_window, timestamp);
7378 gtk_widget_show (widget);
7383 * gtk_window_iconify:
7384 * @window: a #GtkWindow
7386 * Asks to iconify (i.e. minimize) the specified @window. Note that
7387 * you shouldn't assume the window is definitely iconified afterward,
7388 * because other entities (e.g. the user or <link
7389 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7390 * again, or there may not be a window manager in which case
7391 * iconification isn't possible, etc. But normally the window will end
7392 * up iconified. Just don't write code that crashes if not.
7394 * It's permitted to call this function before showing a window,
7395 * in which case the window will be iconified before it ever appears
7398 * You can track iconification via the "window-state-event" signal
7403 gtk_window_iconify (GtkWindow *window)
7405 GtkWindowPrivate *priv;
7407 GdkWindow *toplevel;
7409 g_return_if_fail (GTK_IS_WINDOW (window));
7411 priv = window->priv;
7412 widget = GTK_WIDGET (window);
7414 priv->iconify_initially = TRUE;
7416 toplevel = gtk_widget_get_window (widget);
7418 if (toplevel != NULL)
7419 gdk_window_iconify (toplevel);
7423 * gtk_window_deiconify:
7424 * @window: a #GtkWindow
7426 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7427 * that you shouldn't assume the window is definitely deiconified
7428 * afterward, because other entities (e.g. the user or <link
7429 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7430 * again before your code which assumes deiconification gets to run.
7432 * You can track iconification via the "window-state-event" signal
7436 gtk_window_deiconify (GtkWindow *window)
7438 GtkWindowPrivate *priv;
7440 GdkWindow *toplevel;
7442 g_return_if_fail (GTK_IS_WINDOW (window));
7444 priv = window->priv;
7445 widget = GTK_WIDGET (window);
7447 priv->iconify_initially = FALSE;
7449 toplevel = gtk_widget_get_window (widget);
7451 if (toplevel != NULL)
7452 gdk_window_deiconify (toplevel);
7457 * @window: a #GtkWindow
7459 * Asks to stick @window, which means that it will appear on all user
7460 * desktops. Note that you shouldn't assume the window is definitely
7461 * stuck afterward, because other entities (e.g. the user or <link
7462 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7463 * again, and some window managers do not support sticking
7464 * windows. But normally the window will end up stuck. Just don't
7465 * write code that crashes if not.
7467 * It's permitted to call this function before showing a window.
7469 * You can track stickiness via the "window-state-event" signal
7474 gtk_window_stick (GtkWindow *window)
7476 GtkWindowPrivate *priv;
7478 GdkWindow *toplevel;
7480 g_return_if_fail (GTK_IS_WINDOW (window));
7482 priv = window->priv;
7483 widget = GTK_WIDGET (window);
7485 priv->stick_initially = TRUE;
7487 toplevel = gtk_widget_get_window (widget);
7489 if (toplevel != NULL)
7490 gdk_window_stick (toplevel);
7494 * gtk_window_unstick:
7495 * @window: a #GtkWindow
7497 * Asks to unstick @window, which means that it will appear on only
7498 * one of the user's desktops. Note that you shouldn't assume the
7499 * window is definitely unstuck afterward, because other entities
7500 * (e.g. the user or <link linkend="gtk-X11-arch">window
7501 * manager</link>) could stick it again. But normally the window will
7502 * end up stuck. Just don't write code that crashes if not.
7504 * You can track stickiness via the "window-state-event" signal
7509 gtk_window_unstick (GtkWindow *window)
7511 GtkWindowPrivate *priv;
7513 GdkWindow *toplevel;
7515 g_return_if_fail (GTK_IS_WINDOW (window));
7517 priv = window->priv;
7518 widget = GTK_WIDGET (window);
7520 priv->stick_initially = FALSE;
7522 toplevel = gtk_widget_get_window (widget);
7524 if (toplevel != NULL)
7525 gdk_window_unstick (toplevel);
7529 * gtk_window_maximize:
7530 * @window: a #GtkWindow
7532 * Asks to maximize @window, so that it becomes full-screen. Note that
7533 * you shouldn't assume the window is definitely maximized afterward,
7534 * because other entities (e.g. the user or <link
7535 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7536 * again, and not all window managers support maximization. But
7537 * normally the window will end up maximized. Just don't write code
7538 * that crashes if not.
7540 * It's permitted to call this function before showing a window,
7541 * in which case the window will be maximized when it appears onscreen
7544 * You can track maximization via the "window-state-event" signal
7549 gtk_window_maximize (GtkWindow *window)
7551 GtkWindowPrivate *priv;
7553 GdkWindow *toplevel;
7555 g_return_if_fail (GTK_IS_WINDOW (window));
7557 priv = window->priv;
7558 widget = GTK_WIDGET (window);
7560 priv->maximize_initially = TRUE;
7562 toplevel = gtk_widget_get_window (widget);
7564 if (toplevel != NULL)
7565 gdk_window_maximize (toplevel);
7569 * gtk_window_unmaximize:
7570 * @window: a #GtkWindow
7572 * Asks to unmaximize @window. Note that you shouldn't assume the
7573 * window is definitely unmaximized afterward, because other entities
7574 * (e.g. the user or <link linkend="gtk-X11-arch">window
7575 * manager</link>) could maximize it again, and not all window
7576 * managers honor requests to unmaximize. But normally the window will
7577 * end up unmaximized. Just don't write code that crashes if not.
7579 * You can track maximization via the "window-state-event" signal
7584 gtk_window_unmaximize (GtkWindow *window)
7586 GtkWindowPrivate *priv;
7588 GdkWindow *toplevel;
7590 g_return_if_fail (GTK_IS_WINDOW (window));
7592 priv = window->priv;
7593 widget = GTK_WIDGET (window);
7595 priv->maximize_initially = FALSE;
7597 toplevel = gtk_widget_get_window (widget);
7599 if (toplevel != NULL)
7600 gdk_window_unmaximize (toplevel);
7604 * gtk_window_fullscreen:
7605 * @window: a #GtkWindow
7607 * Asks to place @window in the fullscreen state. Note that you
7608 * shouldn't assume the window is definitely full screen afterward,
7609 * because other entities (e.g. the user or <link
7610 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7611 * again, and not all window managers honor requests to fullscreen
7612 * windows. But normally the window will end up fullscreen. Just
7613 * don't write code that crashes if not.
7615 * You can track the fullscreen state via the "window-state-event" signal
7621 gtk_window_fullscreen (GtkWindow *window)
7623 GtkWindowPrivate *priv;
7625 GdkWindow *toplevel;
7627 g_return_if_fail (GTK_IS_WINDOW (window));
7629 priv = window->priv;
7630 widget = GTK_WIDGET (window);
7632 priv->fullscreen_initially = TRUE;
7634 toplevel = gtk_widget_get_window (widget);
7636 if (toplevel != NULL)
7637 gdk_window_fullscreen (toplevel);
7641 * gtk_window_unfullscreen:
7642 * @window: a #GtkWindow
7644 * Asks to toggle off the fullscreen state for @window. Note that you
7645 * shouldn't assume the window is definitely not full screen
7646 * afterward, because other entities (e.g. the user or <link
7647 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7648 * again, and not all window managers honor requests to unfullscreen
7649 * windows. But normally the window will end up restored to its normal
7650 * state. Just don't write code that crashes if not.
7652 * You can track the fullscreen state via the "window-state-event" signal
7658 gtk_window_unfullscreen (GtkWindow *window)
7661 GdkWindow *toplevel;
7662 GtkWindowPrivate *priv;
7664 g_return_if_fail (GTK_IS_WINDOW (window));
7666 priv = window->priv;
7667 widget = GTK_WIDGET (window);
7669 priv->fullscreen_initially = FALSE;
7671 toplevel = gtk_widget_get_window (widget);
7673 if (toplevel != NULL)
7674 gdk_window_unfullscreen (toplevel);
7678 * gtk_window_set_keep_above:
7679 * @window: a #GtkWindow
7680 * @setting: whether to keep @window above other windows
7682 * Asks to keep @window above, so that it stays on top. Note that
7683 * you shouldn't assume the window is definitely above afterward,
7684 * because other entities (e.g. the user or <link
7685 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7686 * and not all window managers support keeping windows above. But
7687 * normally the window will end kept above. Just don't write code
7688 * that crashes if not.
7690 * It's permitted to call this function before showing a window,
7691 * in which case the window will be kept above when it appears onscreen
7694 * You can track the above state via the "window-state-event" signal
7697 * Note that, according to the <ulink
7698 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7699 * Manager Hints</ulink> specification, the above state is mainly meant
7700 * for user preferences and should not be used by applications e.g. for
7701 * drawing attention to their dialogs.
7706 gtk_window_set_keep_above (GtkWindow *window,
7710 GtkWindowPrivate *priv;
7711 GdkWindow *toplevel;
7713 g_return_if_fail (GTK_IS_WINDOW (window));
7715 priv = window->priv;
7716 widget = GTK_WIDGET (window);
7718 priv->above_initially = setting != FALSE;
7720 priv->below_initially = FALSE;
7722 toplevel = gtk_widget_get_window (widget);
7724 if (toplevel != NULL)
7725 gdk_window_set_keep_above (toplevel, setting);
7729 * gtk_window_set_keep_below:
7730 * @window: a #GtkWindow
7731 * @setting: whether to keep @window below other windows
7733 * Asks to keep @window below, so that it stays in bottom. Note that
7734 * you shouldn't assume the window is definitely below afterward,
7735 * because other entities (e.g. the user or <link
7736 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7737 * and not all window managers support putting windows below. But
7738 * normally the window will be kept below. Just don't write code
7739 * that crashes if not.
7741 * It's permitted to call this function before showing a window,
7742 * in which case the window will be kept below when it appears onscreen
7745 * You can track the below state via the "window-state-event" signal
7748 * Note that, according to the <ulink
7749 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7750 * Manager Hints</ulink> specification, the above state is mainly meant
7751 * for user preferences and should not be used by applications e.g. for
7752 * drawing attention to their dialogs.
7757 gtk_window_set_keep_below (GtkWindow *window,
7761 GtkWindowPrivate *priv;
7762 GdkWindow *toplevel;
7764 g_return_if_fail (GTK_IS_WINDOW (window));
7766 priv = window->priv;
7767 widget = GTK_WIDGET (window);
7769 priv->below_initially = setting != FALSE;
7771 priv->above_initially = FALSE;
7773 toplevel = gtk_widget_get_window (widget);
7775 if (toplevel != NULL)
7776 gdk_window_set_keep_below (toplevel, setting);
7780 * gtk_window_set_resizable:
7781 * @window: a #GtkWindow
7782 * @resizable: %TRUE if the user can resize this window
7784 * Sets whether the user can resize a window. Windows are user resizable
7788 gtk_window_set_resizable (GtkWindow *window,
7791 GtkWindowPrivate *priv;
7793 g_return_if_fail (GTK_IS_WINDOW (window));
7795 priv = window->priv;
7797 resizable = (resizable != FALSE);
7799 if (priv->resizable != resizable)
7801 priv->resizable = (resizable != FALSE);
7803 update_grip_visibility (window);
7805 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7807 g_object_notify (G_OBJECT (window), "resizable");
7812 * gtk_window_get_resizable:
7813 * @window: a #GtkWindow
7815 * Gets the value set by gtk_window_set_resizable().
7817 * Return value: %TRUE if the user can resize the window
7820 gtk_window_get_resizable (GtkWindow *window)
7822 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7824 return window->priv->resizable;
7828 * gtk_window_set_gravity:
7829 * @window: a #GtkWindow
7830 * @gravity: window gravity
7832 * Window gravity defines the meaning of coordinates passed to
7833 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7836 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7837 * typically "do what you mean."
7841 gtk_window_set_gravity (GtkWindow *window,
7844 GtkWindowPrivate *priv;
7846 g_return_if_fail (GTK_IS_WINDOW (window));
7848 priv = window->priv;
7850 if (gravity != priv->gravity)
7852 priv->gravity = gravity;
7854 /* gtk_window_move_resize() will adapt gravity
7856 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7858 g_object_notify (G_OBJECT (window), "gravity");
7863 * gtk_window_get_gravity:
7864 * @window: a #GtkWindow
7866 * Gets the value set by gtk_window_set_gravity().
7868 * Return value: (transfer none): window gravity
7871 gtk_window_get_gravity (GtkWindow *window)
7873 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7875 return window->priv->gravity;
7879 * gtk_window_begin_resize_drag:
7880 * @window: a #GtkWindow
7881 * @button: mouse button that initiated the drag
7882 * @edge: position of the resize control
7883 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7884 * @root_y: Y position where the user clicked to initiate the drag
7885 * @timestamp: timestamp from the click event that initiated the drag
7887 * Starts resizing a window. This function is used if an application
7888 * has window resizing controls. When GDK can support it, the resize
7889 * will be done using the standard mechanism for the <link
7890 * linkend="gtk-X11-arch">window manager</link> or windowing
7891 * system. Otherwise, GDK will try to emulate window resizing,
7892 * potentially not all that well, depending on the windowing system.
7896 gtk_window_begin_resize_drag (GtkWindow *window,
7904 GdkWindow *toplevel;
7906 g_return_if_fail (GTK_IS_WINDOW (window));
7907 widget = GTK_WIDGET (window);
7908 g_return_if_fail (gtk_widget_get_visible (widget));
7910 toplevel = gtk_widget_get_window (widget);
7912 gdk_window_begin_resize_drag (toplevel,
7919 * gtk_window_begin_move_drag:
7920 * @window: a #GtkWindow
7921 * @button: mouse button that initiated the drag
7922 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7923 * @root_y: Y position where the user clicked to initiate the drag
7924 * @timestamp: timestamp from the click event that initiated the drag
7926 * Starts moving a window. This function is used if an application has
7927 * window movement grips. When GDK can support it, the window movement
7928 * will be done using the standard mechanism for the <link
7929 * linkend="gtk-X11-arch">window manager</link> or windowing
7930 * system. Otherwise, GDK will try to emulate window movement,
7931 * potentially not all that well, depending on the windowing system.
7935 gtk_window_begin_move_drag (GtkWindow *window,
7942 GdkWindow *toplevel;
7944 g_return_if_fail (GTK_IS_WINDOW (window));
7945 widget = GTK_WIDGET (window);
7946 g_return_if_fail (gtk_widget_get_visible (widget));
7948 toplevel = gtk_widget_get_window (widget);
7950 gdk_window_begin_move_drag (toplevel,
7957 * gtk_window_set_screen:
7958 * @window: a #GtkWindow.
7959 * @screen: a #GdkScreen.
7961 * Sets the #GdkScreen where the @window is displayed; if
7962 * the window is already mapped, it will be unmapped, and
7963 * then remapped on the new screen.
7968 gtk_window_set_screen (GtkWindow *window,
7971 GtkWindowPrivate *priv;
7973 GdkScreen *previous_screen;
7974 gboolean was_mapped;
7976 g_return_if_fail (GTK_IS_WINDOW (window));
7977 g_return_if_fail (GDK_IS_SCREEN (screen));
7979 priv = window->priv;
7981 if (screen == priv->screen)
7984 widget = GTK_WIDGET (window);
7986 previous_screen = priv->screen;
7987 was_mapped = gtk_widget_get_mapped (widget);
7990 gtk_widget_unmap (widget);
7991 if (gtk_widget_get_realized (widget))
7992 gtk_widget_unrealize (widget);
7994 gtk_window_free_key_hash (window);
7995 priv->screen = screen;
7996 gtk_widget_reset_rc_styles (widget);
7997 if (screen != previous_screen)
7999 if (previous_screen)
8000 g_signal_handlers_disconnect_by_func (previous_screen,
8001 gtk_window_on_composited_changed, window);
8002 g_signal_connect (screen, "composited-changed",
8003 G_CALLBACK (gtk_window_on_composited_changed), window);
8005 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8006 _gtk_widget_propagate_composited_changed (widget);
8008 g_object_notify (G_OBJECT (window), "screen");
8011 gtk_widget_map (widget);
8015 gtk_window_on_composited_changed (GdkScreen *screen,
8018 gtk_widget_queue_draw (GTK_WIDGET (window));
8020 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8024 gtk_window_check_screen (GtkWindow *window)
8026 GtkWindowPrivate *priv = window->priv;
8029 return priv->screen;
8032 g_warning ("Screen for GtkWindow not set; you must always set\n"
8033 "a screen for a GtkWindow before using the window");
8039 * gtk_window_get_screen:
8040 * @window: a #GtkWindow.
8042 * Returns the #GdkScreen associated with @window.
8044 * Return value: (transfer none): a #GdkScreen.
8049 gtk_window_get_screen (GtkWindow *window)
8051 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8053 return window->priv->screen;
8057 * gtk_window_is_active:
8058 * @window: a #GtkWindow
8060 * Returns whether the window is part of the current active toplevel.
8061 * (That is, the toplevel window receiving keystrokes.)
8062 * The return value is %TRUE if the window is active toplevel
8063 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8064 * You might use this function if you wanted to draw a widget
8065 * differently in an active window from a widget in an inactive window.
8066 * See gtk_window_has_toplevel_focus()
8068 * Return value: %TRUE if the window part of the current active window.
8073 gtk_window_is_active (GtkWindow *window)
8075 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8077 return window->priv->is_active;
8081 * gtk_window_has_toplevel_focus:
8082 * @window: a #GtkWindow
8084 * Returns whether the input focus is within this GtkWindow.
8085 * For real toplevel windows, this is identical to gtk_window_is_active(),
8086 * but for embedded windows, like #GtkPlug, the results will differ.
8088 * Return value: %TRUE if the input focus is within this GtkWindow
8093 gtk_window_has_toplevel_focus (GtkWindow *window)
8095 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8097 return window->priv->has_toplevel_focus;
8100 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8103 gtk_window_group_init (GtkWindowGroup *group)
8105 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8106 GTK_TYPE_WINDOW_GROUP,
8107 GtkWindowGroupPrivate);
8111 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8113 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8117 * gtk_window_group_new:
8119 * Creates a new #GtkWindowGroup object. Grabs added with
8120 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8122 * Return value: a new #GtkWindowGroup.
8125 gtk_window_group_new (void)
8127 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8131 window_group_cleanup_grabs (GtkWindowGroup *group,
8134 GtkWindowGroupPrivate *priv;
8135 GtkDeviceGrabInfo *info;
8137 GSList *to_remove = NULL;
8141 tmp_list = priv->grabs;
8144 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8145 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8146 tmp_list = tmp_list->next;
8151 gtk_grab_remove (to_remove->data);
8152 g_object_unref (to_remove->data);
8153 to_remove = g_slist_delete_link (to_remove, to_remove);
8156 tmp_list = priv->device_grabs;
8160 info = tmp_list->data;
8162 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8163 to_remove = g_slist_prepend (to_remove, info);
8165 tmp_list = tmp_list->next;
8170 info = to_remove->data;
8172 gtk_device_grab_remove (info->widget, info->device);
8173 to_remove = g_slist_delete_link (to_remove, to_remove);
8178 * gtk_window_group_add_window:
8179 * @window_group: a #GtkWindowGroup
8180 * @window: the #GtkWindow to add
8182 * Adds a window to a #GtkWindowGroup.
8185 gtk_window_group_add_window (GtkWindowGroup *window_group,
8188 GtkWindowPrivate *priv;
8190 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8191 g_return_if_fail (GTK_IS_WINDOW (window));
8193 priv = window->priv;
8195 if (priv->group != window_group)
8197 g_object_ref (window);
8198 g_object_ref (window_group);
8201 gtk_window_group_remove_window (priv->group, window);
8203 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8205 priv->group = window_group;
8207 g_object_unref (window);
8212 * gtk_window_group_remove_window:
8213 * @window_group: a #GtkWindowGroup
8214 * @window: the #GtkWindow to remove
8216 * Removes a window from a #GtkWindowGroup.
8219 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8222 GtkWindowPrivate *priv;
8224 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8225 g_return_if_fail (GTK_IS_WINDOW (window));
8226 priv = window->priv;
8227 g_return_if_fail (priv->group == window_group);
8229 g_object_ref (window);
8231 window_group_cleanup_grabs (window_group, window);
8234 g_object_unref (window_group);
8235 g_object_unref (window);
8239 * gtk_window_group_list_windows:
8240 * @window_group: a #GtkWindowGroup
8242 * Returns a list of the #GtkWindows that belong to @window_group.
8244 * Returns: (element-type GtkWindow) (transfer container): A
8245 * newly-allocated list of windows inside the group.
8250 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8252 GList *toplevels, *toplevel, *group_windows;
8254 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8256 group_windows = NULL;
8257 toplevels = gtk_window_list_toplevels ();
8259 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8261 GtkWindow *window = toplevel->data;
8263 if (window_group == window->priv->group)
8264 group_windows = g_list_prepend (group_windows, window);
8267 g_list_free (toplevels);
8269 return g_list_reverse (group_windows);
8273 * gtk_window_get_group:
8274 * @window: (allow-none): a #GtkWindow, or %NULL
8276 * Returns the group for @window or the default group, if
8277 * @window is %NULL or if @window does not have an explicit
8280 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8285 gtk_window_get_group (GtkWindow *window)
8287 if (window && window->priv->group)
8288 return window->priv->group;
8291 static GtkWindowGroup *default_group = NULL;
8294 default_group = gtk_window_group_new ();
8296 return default_group;
8301 * gtk_window_has_group:
8302 * @window: a #GtkWindow
8304 * Returns whether @window has an explicit window group.
8306 * Return value: %TRUE if @window has an explicit window group.
8311 gtk_window_has_group (GtkWindow *window)
8313 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8315 return window->priv->group != NULL;
8319 * gtk_window_group_get_current_grab:
8320 * @window_group: a #GtkWindowGroup
8322 * Gets the current grab widget of the given group,
8323 * see gtk_grab_add().
8325 * Returns: (transfer none): the current grab widget of the group
8330 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8332 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8334 if (window_group->priv->grabs)
8335 return GTK_WIDGET (window_group->priv->grabs->data);
8340 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8343 GtkWindowGroupPrivate *priv;
8345 priv = window_group->priv;
8346 priv->grabs = g_slist_prepend (priv->grabs, widget);
8350 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8353 GtkWindowGroupPrivate *priv;
8355 priv = window_group->priv;
8356 priv->grabs = g_slist_remove (priv->grabs, widget);
8361 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8364 gboolean block_others)
8366 GtkWindowGroupPrivate *priv;
8367 GtkDeviceGrabInfo *info;
8369 priv = window_group->priv;
8371 info = g_slice_new0 (GtkDeviceGrabInfo);
8372 info->widget = widget;
8373 info->device = device;
8374 info->block_others = block_others;
8376 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8380 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8384 GtkWindowGroupPrivate *priv;
8385 GtkDeviceGrabInfo *info;
8386 GSList *list, *node = NULL;
8387 GdkDevice *other_device;
8389 priv = window_group->priv;
8390 other_device = gdk_device_get_associated_device (device);
8391 list = priv->device_grabs;
8397 if (info->widget == widget &&
8398 (info->device == device ||
8399 info->device == other_device))
8412 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8413 g_slice_free (GtkDeviceGrabInfo, info);
8418 * gtk_window_group_get_current_device_grab:
8419 * @window_group: a #GtkWindowGroup
8420 * @device: a #GdkDevice
8422 * Returns the current grab widget for @device, or %NULL if none.
8424 * Returns: (transfer none): The grab widget, or %NULL
8429 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8432 GtkWindowGroupPrivate *priv;
8433 GtkDeviceGrabInfo *info;
8434 GdkDevice *other_device;
8437 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8438 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8440 priv = window_group->priv;
8441 list = priv->device_grabs;
8442 other_device = gdk_device_get_associated_device (device);
8449 if (info->device == device ||
8450 info->device == other_device)
8451 return info->widget;
8458 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8462 GtkWindowGroupPrivate *priv;
8463 GtkDeviceGrabInfo *info;
8464 GdkDevice *other_device;
8467 priv = window_group->priv;
8468 other_device = gdk_device_get_associated_device (device);
8469 list = priv->device_grabs;
8476 /* Look for blocking grabs on other device pairs
8477 * that have the passed widget within the GTK+ grab.
8479 if (info->block_others &&
8480 info->device != device &&
8481 info->device != other_device &&
8482 (info->widget == widget ||
8483 gtk_widget_is_ancestor (widget, info->widget)))
8491 Derived from XParseGeometry() in XFree86
8493 Copyright 1985, 1986, 1987,1998 The Open Group
8495 All Rights Reserved.
8497 The above copyright notice and this permission notice shall be included
8498 in all copies or substantial portions of the Software.
8500 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8501 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8502 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8503 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8504 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8505 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8506 OTHER DEALINGS IN THE SOFTWARE.
8508 Except as contained in this notice, the name of The Open Group shall
8509 not be used in advertising or otherwise to promote the sale, use or
8510 other dealings in this Software without prior written authorization
8511 from The Open Group.
8516 * XParseGeometry parses strings of the form
8517 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8518 * width, height, xoffset, and yoffset are unsigned integers.
8519 * Example: "=80x24+300-49"
8520 * The equal sign is optional.
8521 * It returns a bitmask that indicates which of the four values
8522 * were actually found in the string. For each value found,
8523 * the corresponding argument is updated; for each value
8524 * not found, the corresponding argument is left unchanged.
8527 /* The following code is from Xlib, and is minimally modified, so we
8528 * can track any upstream changes if required. Don't change this
8529 * code. Or if you do, put in a huge comment marking which thing
8534 read_int (gchar *string,
8542 else if (*string == '-')
8548 for (; (*string >= '0') && (*string <= '9'); string++)
8550 result = (result * 10) + (*string - '0');
8562 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8563 * value (x, y, width, height) was found in the parsed string.
8565 #define NoValue 0x0000
8566 #define XValue 0x0001
8567 #define YValue 0x0002
8568 #define WidthValue 0x0004
8569 #define HeightValue 0x0008
8570 #define AllValues 0x000F
8571 #define XNegative 0x0010
8572 #define YNegative 0x0020
8574 /* Try not to reformat/modify, so we can compare/sync with X sources */
8576 gtk_XParseGeometry (const char *string,
8579 unsigned int *width,
8580 unsigned int *height)
8584 unsigned int tempWidth, tempHeight;
8586 char *nextCharacter;
8588 /* These initializations are just to silence gcc */
8594 if ( (string == NULL) || (*string == '\0')) return(mask);
8596 string++; /* ignore possible '=' at beg of geometry spec */
8598 strind = (char *)string;
8599 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8600 tempWidth = read_int(strind, &nextCharacter);
8601 if (strind == nextCharacter)
8603 strind = nextCharacter;
8607 if (*strind == 'x' || *strind == 'X') {
8609 tempHeight = read_int(strind, &nextCharacter);
8610 if (strind == nextCharacter)
8612 strind = nextCharacter;
8613 mask |= HeightValue;
8616 if ((*strind == '+') || (*strind == '-')) {
8617 if (*strind == '-') {
8619 tempX = -read_int(strind, &nextCharacter);
8620 if (strind == nextCharacter)
8622 strind = nextCharacter;
8628 tempX = read_int(strind, &nextCharacter);
8629 if (strind == nextCharacter)
8631 strind = nextCharacter;
8634 if ((*strind == '+') || (*strind == '-')) {
8635 if (*strind == '-') {
8637 tempY = -read_int(strind, &nextCharacter);
8638 if (strind == nextCharacter)
8640 strind = nextCharacter;
8647 tempY = read_int(strind, &nextCharacter);
8648 if (strind == nextCharacter)
8650 strind = nextCharacter;
8656 /* If strind isn't at the end of the string the it's an invalid
8657 geometry specification. */
8659 if (*strind != '\0') return (0);
8665 if (mask & WidthValue)
8667 if (mask & HeightValue)
8668 *height = tempHeight;
8673 * gtk_window_parse_geometry:
8674 * @window: a #GtkWindow
8675 * @geometry: geometry string
8677 * Parses a standard X Window System geometry string - see the
8678 * manual page for X (type 'man X') for details on this.
8679 * gtk_window_parse_geometry() does work on all GTK+ ports
8680 * including Win32 but is primarily intended for an X environment.
8682 * If either a size or a position can be extracted from the
8683 * geometry string, gtk_window_parse_geometry() returns %TRUE
8684 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8685 * to resize/move the window.
8687 * If gtk_window_parse_geometry() returns %TRUE, it will also
8688 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8689 * indicating to the window manager that the size/position of
8690 * the window was user-specified. This causes most window
8691 * managers to honor the geometry.
8693 * Note that for gtk_window_parse_geometry() to work as expected, it has
8694 * to be called when the window has its "final" size, i.e. after calling
8695 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8698 * #include <gtk/gtk.h>
8701 * fill_with_content (GtkWidget *vbox)
8703 * /* fill with content... */
8707 * main (int argc, char *argv[])
8709 * GtkWidget *window, *vbox;
8710 * GdkGeometry size_hints = {
8711 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8714 * gtk_init (&argc, &argv);
8716 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8717 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8719 * gtk_container_add (GTK_CONTAINER (window), vbox);
8720 * fill_with_content (vbox);
8721 * gtk_widget_show_all (vbox);
8723 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8726 * GDK_HINT_MIN_SIZE |
8727 * GDK_HINT_BASE_SIZE |
8728 * GDK_HINT_RESIZE_INC);
8732 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8733 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8736 * gtk_widget_show_all (window);
8743 * Return value: %TRUE if string was parsed successfully
8746 gtk_window_parse_geometry (GtkWindow *window,
8747 const gchar *geometry)
8749 gint result, x = 0, y = 0;
8753 gboolean size_set, pos_set;
8756 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8757 g_return_val_if_fail (geometry != NULL, FALSE);
8759 child = gtk_bin_get_child (GTK_BIN (window));
8760 if (!child || !gtk_widget_get_visible (child))
8761 g_warning ("gtk_window_parse_geometry() called on a window with no "
8762 "visible children; the window should be set up before "
8763 "gtk_window_parse_geometry() is called.");
8765 screen = gtk_window_check_screen (window);
8767 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8770 if ((result & WidthValue) || (result & HeightValue))
8772 gtk_window_set_default_size_internal (window,
8773 TRUE, result & WidthValue ? w : -1,
8774 TRUE, result & HeightValue ? h : -1,
8779 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8781 grav = GDK_GRAVITY_NORTH_WEST;
8783 if ((result & XNegative) && (result & YNegative))
8784 grav = GDK_GRAVITY_SOUTH_EAST;
8785 else if (result & XNegative)
8786 grav = GDK_GRAVITY_NORTH_EAST;
8787 else if (result & YNegative)
8788 grav = GDK_GRAVITY_SOUTH_WEST;
8790 if ((result & XValue) == 0)
8793 if ((result & YValue) == 0)
8796 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8797 grav == GDK_GRAVITY_SOUTH_EAST)
8798 y = gdk_screen_get_height (screen) - h + y;
8800 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8801 grav == GDK_GRAVITY_NORTH_EAST)
8802 x = gdk_screen_get_width (screen) - w + x;
8804 /* we don't let you put a window offscreen; maybe some people would
8805 * prefer to be able to, but it's kind of a bogus thing to do.
8814 if ((result & XValue) || (result & YValue))
8816 gtk_window_set_gravity (window, grav);
8817 gtk_window_move (window, x, y);
8821 if (size_set || pos_set)
8823 /* Set USSize, USPosition hints */
8824 GtkWindowGeometryInfo *info;
8826 info = gtk_window_get_geometry_info (window, TRUE);
8829 info->mask |= GDK_HINT_USER_POS;
8831 info->mask |= GDK_HINT_USER_SIZE;
8838 gtk_window_mnemonic_hash_foreach (guint keyval,
8844 GtkWindowKeysForeachFunc func;
8848 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8852 _gtk_window_keys_foreach (GtkWindow *window,
8853 GtkWindowKeysForeachFunc func,
8857 GtkMnemonicHash *mnemonic_hash;
8861 GtkWindowKeysForeachFunc func;
8865 info.window = window;
8867 info.func_data = func_data;
8869 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8871 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8872 gtk_window_mnemonic_hash_foreach, &info);
8874 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8877 GtkAccelGroup *group = groups->data;
8880 for (i = 0; i < group->priv->n_accels; i++)
8882 GtkAccelKey *key = &group->priv->priv_accels[i].key;
8885 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8888 groups = groups->next;
8893 gtk_window_keys_changed (GtkWindow *window)
8895 gtk_window_free_key_hash (window);
8896 gtk_window_get_key_hash (window);
8899 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8901 struct _GtkWindowKeyEntry
8905 guint is_mnemonic : 1;
8909 window_key_entry_destroy (gpointer data)
8911 g_slice_free (GtkWindowKeyEntry, data);
8915 add_to_key_hash (GtkWindow *window,
8917 GdkModifierType modifiers,
8918 gboolean is_mnemonic,
8921 GtkKeyHash *key_hash = data;
8923 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8925 entry->keyval = keyval;
8926 entry->modifiers = modifiers;
8927 entry->is_mnemonic = is_mnemonic;
8929 /* GtkAccelGroup stores lowercased accelerators. To deal
8930 * with this, if <Shift> was specified, uppercase.
8932 if (modifiers & GDK_SHIFT_MASK)
8934 if (keyval == GDK_KEY_Tab)
8935 keyval = GDK_KEY_ISO_Left_Tab;
8937 keyval = gdk_keyval_to_upper (keyval);
8940 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8944 gtk_window_get_key_hash (GtkWindow *window)
8946 GdkScreen *screen = gtk_window_check_screen (window);
8947 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8952 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8953 (GDestroyNotify)window_key_entry_destroy);
8954 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8955 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8961 gtk_window_free_key_hash (GtkWindow *window)
8963 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8966 _gtk_key_hash_free (key_hash);
8967 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8972 * gtk_window_activate_key:
8973 * @window: a #GtkWindow
8974 * @event: a #GdkEventKey
8976 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8977 * called by the default ::key_press_event handler for toplevel windows,
8978 * however in some cases it may be useful to call this directly when
8979 * overriding the standard key handling for a toplevel window.
8981 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8986 gtk_window_activate_key (GtkWindow *window,
8989 GtkKeyHash *key_hash;
8990 GtkWindowKeyEntry *found_entry = NULL;
8991 gboolean enable_mnemonics;
8992 gboolean enable_accels;
8994 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8995 g_return_val_if_fail (event != NULL, FALSE);
8997 key_hash = gtk_window_get_key_hash (window);
9002 GSList *entries = _gtk_key_hash_lookup (key_hash,
9003 event->hardware_keycode,
9005 gtk_accelerator_get_default_mod_mask (),
9008 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9009 "gtk-enable-mnemonics", &enable_mnemonics,
9010 "gtk-enable-accels", &enable_accels,
9013 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9015 GtkWindowKeyEntry *entry = tmp_list->data;
9016 if (entry->is_mnemonic)
9018 if (enable_mnemonics)
9020 found_entry = entry;
9026 if (enable_accels && !found_entry)
9028 found_entry = entry;
9033 g_slist_free (entries);
9038 if (found_entry->is_mnemonic)
9040 if (enable_mnemonics)
9041 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9042 found_entry->modifiers);
9047 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9048 found_entry->modifiers);
9056 window_update_has_focus (GtkWindow *window)
9058 GtkWindowPrivate *priv = window->priv;
9059 GtkWidget *widget = GTK_WIDGET (window);
9060 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9062 if (has_focus != priv->has_focus)
9064 priv->has_focus = has_focus;
9068 if (priv->focus_widget &&
9069 priv->focus_widget != widget &&
9070 !gtk_widget_has_focus (priv->focus_widget))
9071 do_focus_change (priv->focus_widget, TRUE);
9075 if (priv->focus_widget &&
9076 priv->focus_widget != widget &&
9077 gtk_widget_has_focus (priv->focus_widget))
9078 do_focus_change (priv->focus_widget, FALSE);
9084 * _gtk_window_set_is_active:
9085 * @window: a #GtkWindow
9086 * @is_active: %TRUE if the window is in the currently active toplevel
9088 * Internal function that sets whether the #GtkWindow is part
9089 * of the currently active toplevel window (taking into account inter-process
9093 _gtk_window_set_is_active (GtkWindow *window,
9096 GtkWindowPrivate *priv;
9098 g_return_if_fail (GTK_IS_WINDOW (window));
9100 priv = window->priv;
9102 is_active = is_active != FALSE;
9104 if (is_active != priv->is_active)
9106 priv->is_active = is_active;
9107 window_update_has_focus (window);
9109 g_object_notify (G_OBJECT (window), "is-active");
9114 * _gtk_window_set_is_toplevel:
9115 * @window: a #GtkWindow
9116 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9117 * child of the root window); %FALSE if it is not (for example, for an
9118 * in-process, parented GtkPlug)
9120 * Internal function used by #GtkPlug when it gets parented/unparented by a
9121 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9122 * global list of toplevel windows.
9125 _gtk_window_set_is_toplevel (GtkWindow *window,
9126 gboolean is_toplevel)
9129 GtkWidget *toplevel;
9131 widget = GTK_WIDGET (window);
9133 if (gtk_widget_is_toplevel (widget))
9134 g_assert (g_slist_find (toplevel_list, window) != NULL);
9136 g_assert (g_slist_find (toplevel_list, window) == NULL);
9138 if (is_toplevel == gtk_widget_is_toplevel (widget))
9143 /* Pass through regular pathways of an embedded toplevel
9144 * to go through unmapping and hiding the widget before
9145 * becomming a toplevel again.
9147 * We remain hidden after becomming toplevel in order to
9148 * avoid problems during an embedded toplevel's dispose cycle
9149 * (When a toplevel window is shown it tries to grab focus again,
9150 * this causes problems while disposing).
9152 gtk_widget_hide (widget);
9154 /* Save the toplevel this widget was previously anchored into before
9155 * propagating a hierarchy-changed.
9157 * Usually this happens by way of gtk_widget_unparent() and we are
9158 * already unanchored at this point, just adding this clause incase
9159 * things happen differently.
9161 toplevel = gtk_widget_get_toplevel (widget);
9162 if (!gtk_widget_is_toplevel (toplevel))
9165 _gtk_widget_set_is_toplevel (widget, TRUE);
9167 /* When a window becomes toplevel after being embedded and anchored
9168 * into another window we need to unset it's anchored flag so that
9169 * the hierarchy changed signal kicks in properly.
9171 _gtk_widget_set_anchored (widget, FALSE);
9172 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9174 toplevel_list = g_slist_prepend (toplevel_list, window);
9178 _gtk_widget_set_is_toplevel (widget, FALSE);
9179 toplevel_list = g_slist_remove (toplevel_list, window);
9181 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9186 * _gtk_window_set_has_toplevel_focus:
9187 * @window: a #GtkWindow
9188 * @has_toplevel_focus: %TRUE if the in
9190 * Internal function that sets whether the keyboard focus for the
9191 * toplevel window (taking into account inter-process embedding.)
9194 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9195 gboolean has_toplevel_focus)
9197 GtkWindowPrivate *priv;
9199 g_return_if_fail (GTK_IS_WINDOW (window));
9201 priv = window->priv;
9203 has_toplevel_focus = has_toplevel_focus != FALSE;
9205 if (has_toplevel_focus != priv->has_toplevel_focus)
9207 priv->has_toplevel_focus = has_toplevel_focus;
9208 window_update_has_focus (window);
9210 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9215 * gtk_window_set_auto_startup_notification:
9216 * @setting: %TRUE to automatically do startup notification
9218 * By default, after showing the first #GtkWindow, GTK+ calls
9219 * gdk_notify_startup_complete(). Call this function to disable
9220 * the automatic startup notification. You might do this if your
9221 * first window is a splash screen, and you want to delay notification
9222 * until after your real main window has been shown, for example.
9224 * In that example, you would disable startup notification
9225 * temporarily, show your splash screen, then re-enable it so that
9226 * showing the main window would automatically result in notification.
9231 gtk_window_set_auto_startup_notification (gboolean setting)
9233 disable_startup_notification = !setting;
9237 * gtk_window_get_window_type:
9238 * @window: a #GtkWindow
9240 * Gets the type of the window. See #GtkWindowType.
9242 * Return value: the type of the window
9247 gtk_window_get_window_type (GtkWindow *window)
9249 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9251 return window->priv->type;
9255 * gtk_window_get_mnemonics_visible:
9256 * @window: a #GtkWindow
9258 * Gets the value of the #GtkWindow:mnemonics-visible property.
9260 * Returns: %TRUE if mnemonics are supposed to be visible
9266 gtk_window_get_mnemonics_visible (GtkWindow *window)
9268 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9270 return window->priv->mnemonics_visible;
9274 * gtk_window_set_mnemonics_visible:
9275 * @window: a #GtkWindow
9276 * @setting: the new value
9278 * Sets the #GtkWindow:mnemonics-visible property.
9283 gtk_window_set_mnemonics_visible (GtkWindow *window,
9286 GtkWindowPrivate *priv;
9288 g_return_if_fail (GTK_IS_WINDOW (window));
9290 priv = window->priv;
9292 setting = setting != FALSE;
9294 if (priv->mnemonics_visible != setting)
9296 priv->mnemonics_visible = setting;
9297 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9300 priv->mnemonics_visible_set = TRUE;
9304 _gtk_window_get_wmclass (GtkWindow *window,
9305 gchar **wmclass_name,
9306 gchar **wmclass_class)
9308 GtkWindowPrivate *priv = window->priv;
9310 *wmclass_name = priv->wmclass_name;
9311 *wmclass_class = priv->wmclass_class;
9315 * gtk_window_set_has_user_ref_count:
9316 * @window: a #GtkWindow
9317 * @setting: the new value
9319 * Tells GTK+ whether to drop its extra reference to the window
9320 * when gtk_window_destroy() is called.
9322 * This function is only exported for the benefit of language
9323 * bindings which may need to keep the window alive until their
9324 * wrapper object is garbage collected. There is no justification
9325 * for ever calling this function in an application.
9330 gtk_window_set_has_user_ref_count (GtkWindow *window,
9333 g_return_if_fail (GTK_IS_WINDOW (window));
9335 window->priv->has_user_ref_count = setting;