1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
33 #include "gdk/gdkkeysyms.h"
37 #include "gtkprivate.h"
39 #include "gtkwindow.h"
40 #include "gtkwindow-decorate.h"
41 #include "gtkbindings.h"
42 #include "gtkkeyhash.h"
44 #include "gtkmnemonichash.h"
45 #include "gtkmenubar.h"
46 #include "gtkiconfactory.h"
47 #include "gtkicontheme.h"
48 #include "gtkmarshalers.h"
50 #include "gtkbuildable.h"
52 #ifdef GDK_WINDOWING_X11
59 * @short_description: Toplevel which can contain other widgets
61 * A GtkWindow is a toplevel window which can contain other widgets.
62 * Windows normally have decorations that are under the control
63 * of the windowing system and allow the user to manipulate the window
64 * (resize it, move it, close it,...).
66 * GTK+ also allows windows to have a resize grip (a small area in the lower
67 * right or left corner) which can be clicked to reszie the window. To
68 * control whether a window has a resize grip, use
69 * gtk_window_set_has_resize_grip().
71 * <refsect2 id="GtkWindow-BUILDER-UI">
72 * <title>GtkWindow as GtkBuildable</title>
74 * The GtkWindow implementation of the GtkBuildable interface supports a
75 * custom <tag class="starttag">accel-groups</tag> element, which supports
76 * any number of <tag class="starttag">group</tag> elements representing the
77 * #GtkAccelGroup objects you want to add to your window (synonymous with
78 * gtk_window_add_accel_group().
81 * <title>A UI definition fragment with accel groups</title>
82 * <programlisting><![CDATA[
83 * <object class="GtkWindow">
85 * <group name="accelgroup1"/>
91 * <object class="GtkAccelGroup" id="accelgroup1"/>
92 * ]]></programlisting>
97 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
98 typedef struct _GtkWindowGroupPrivate GtkWindowGroupPrivate;
100 struct _GtkWindowPrivate
102 GtkMnemonicHash *mnemonic_hash;
104 GtkWidget *default_widget;
105 GtkWidget *focus_widget;
106 GtkWindow *transient_parent;
107 GtkWindowGeometryInfo *geometry_info;
108 GtkWindowGroup *group;
110 GdkModifierType mnemonic_modifier;
113 GdkWindowTypeHint gdk_type_hint;
117 gboolean has_resize_grip;
118 GdkWindow *grip_window;
122 gchar *wmclass_class;
130 guint keys_changed_handler;
132 /* Don't use this value, it's only used for determining when
133 * to fire notify events on the "resize-grip-visible" property.
135 gboolean resize_grip_visible;
137 guint16 configure_request_count;
139 /* The following flags are initially TRUE (before a window is mapped).
140 * They cause us to compute a configure request that involves
141 * default-only parameters. Once mapped, we set them to FALSE.
142 * Then we set them to TRUE again on unmap (for position)
143 * and on unrealize (for size).
145 guint need_default_position : 1;
146 guint need_default_size : 1;
148 guint above_initially : 1;
149 guint accept_focus : 1;
150 guint below_initially : 1;
151 guint builder_visible : 1;
152 guint configure_notify_received : 1;
155 guint destroy_with_parent : 1;
156 guint focus_on_map : 1;
157 guint fullscreen_initially : 1;
158 guint gravity : 5; /* GdkGravity */
160 guint has_user_ref_count : 1;
162 guint has_toplevel_focus : 1;
163 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
165 guint maximize_initially : 1;
166 guint mnemonics_visible : 1;
167 guint mnemonics_visible_set : 1;
169 guint opacity_set : 1;
171 guint reset_type_hint : 1;
173 guint skips_pager : 1;
174 guint skips_taskbar : 1;
175 guint stick_initially : 1;
176 guint transient_parent_group : 1;
177 guint type : 4; /* GtkWindowType */
178 guint type_hint : 3; /* GdkWindowTypeHint if the hint is one of the original eight. If not, then
179 * it contains GDK_WINDOW_TYPE_HINT_NORMAL */
206 PROP_DESTROY_WITH_PARENT,
211 PROP_SKIP_TASKBAR_HINT,
212 PROP_SKIP_PAGER_HINT,
221 PROP_HAS_RESIZE_GRIP,
222 PROP_RESIZE_GRIP_VISIBLE,
224 /* Readonly properties */
226 PROP_HAS_TOPLEVEL_FOCUS,
228 /* Writeonly properties */
231 PROP_MNEMONICS_VISIBLE,
241 guint using_default_icon : 1;
242 guint using_parent_icon : 1;
243 guint using_themed_icon : 1;
247 GdkGeometry geometry; /* Last set of geometry hints we set */
248 GdkWindowHints flags;
249 GdkRectangle configure_request;
250 } GtkWindowLastGeometryInfo;
252 struct _GtkWindowGeometryInfo
254 /* Properties that the app has set on the window
256 GdkGeometry geometry; /* Geometry hints */
258 GtkWidget *widget; /* subwidget to which hints apply */
259 /* from last gtk_window_resize () - if > 0, indicates that
260 * we should resize to this size.
265 /* From last gtk_window_move () prior to mapping -
266 * only used if initial_pos_set
271 /* Default size - used only the FIRST time we map a window,
276 /* whether to use initial_x, initial_y */
277 guint initial_pos_set : 1;
278 /* CENTER_ALWAYS or other position constraint changed since
279 * we sent the last configure request.
281 guint position_constraints_changed : 1;
283 /* if true, default_width, height come from gtk_window_parse_geometry,
284 * and thus should be multiplied by the increments and affect the
285 * geometry widget only
287 guint default_is_geometry : 1;
289 GtkWindowLastGeometryInfo last;
292 #define GTK_WINDOW_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW_GROUP, GtkWindowGroupPrivate))
294 struct _GtkDeviceGrabInfo
298 guint block_others : 1;
301 struct _GtkWindowGroupPrivate
303 GSList *device_grabs;
306 static void gtk_window_dispose (GObject *object);
307 static void gtk_window_finalize (GObject *object);
308 static void gtk_window_destroy (GtkWidget *widget);
309 static void gtk_window_show (GtkWidget *widget);
310 static void gtk_window_hide (GtkWidget *widget);
311 static void gtk_window_map (GtkWidget *widget);
312 static void gtk_window_unmap (GtkWidget *widget);
313 static void gtk_window_realize (GtkWidget *widget);
314 static void gtk_window_unrealize (GtkWidget *widget);
315 static void gtk_window_size_allocate (GtkWidget *widget,
316 GtkAllocation *allocation);
317 static gint gtk_window_event (GtkWidget *widget,
319 static gboolean gtk_window_map_event (GtkWidget *widget,
321 static gboolean gtk_window_frame_event (GtkWindow *window,
323 static gint gtk_window_configure_event (GtkWidget *widget,
324 GdkEventConfigure *event);
325 static gint gtk_window_key_press_event (GtkWidget *widget,
327 static gint gtk_window_key_release_event (GtkWidget *widget,
329 static gint gtk_window_button_press_event (GtkWidget *widget,
330 GdkEventButton *event);
331 static gint gtk_window_enter_notify_event (GtkWidget *widget,
332 GdkEventCrossing *event);
333 static gint gtk_window_leave_notify_event (GtkWidget *widget,
334 GdkEventCrossing *event);
335 static gint gtk_window_focus_in_event (GtkWidget *widget,
336 GdkEventFocus *event);
337 static gint gtk_window_focus_out_event (GtkWidget *widget,
338 GdkEventFocus *event);
339 static gint gtk_window_client_event (GtkWidget *widget,
340 GdkEventClient *event);
341 static gboolean gtk_window_state_event (GtkWidget *widget,
342 GdkEventWindowState *event);
343 static void gtk_window_check_resize (GtkContainer *container);
344 static gint gtk_window_focus (GtkWidget *widget,
345 GtkDirectionType direction);
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_move_focus (GtkWindow *window,
356 GtkDirectionType dir);
357 static void gtk_window_keys_changed (GtkWindow *window);
358 static gint gtk_window_draw (GtkWidget *widget,
360 static void gtk_window_unset_transient_for (GtkWindow *window);
361 static void gtk_window_transient_parent_realized (GtkWidget *parent,
363 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
366 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
368 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
371 static void gtk_window_move_resize (GtkWindow *window);
372 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
374 GdkGeometry *geometry_b,
376 static void gtk_window_constrain_size (GtkWindow *window,
377 GdkGeometry *geometry,
383 static void gtk_window_constrain_position (GtkWindow *window,
388 static void gtk_window_compute_hints (GtkWindow *window,
389 GdkGeometry *new_geometry,
391 static void gtk_window_compute_configure_request (GtkWindow *window,
392 GdkRectangle *request,
393 GdkGeometry *geometry,
396 static void gtk_window_set_default_size_internal (GtkWindow *window,
397 gboolean change_width,
399 gboolean change_height,
401 gboolean is_geometry);
403 static void update_themed_icon (GtkIconTheme *theme,
405 static GList *icon_list_from_theme (GtkWidget *widget,
407 static void gtk_window_realize_icon (GtkWindow *window);
408 static void gtk_window_unrealize_icon (GtkWindow *window);
409 static void resize_grip_create_window (GtkWindow *window);
410 static void resize_grip_destroy_window (GtkWindow *window);
411 static void update_grip_visibility (GtkWindow *window);
413 static void gtk_window_notify_keys_changed (GtkWindow *window);
414 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
415 static void gtk_window_free_key_hash (GtkWindow *window);
416 static void gtk_window_on_composited_changed (GdkScreen *screen,
419 static GSList *toplevel_list = NULL;
420 static guint window_signals[LAST_SIGNAL] = { 0 };
421 static GList *default_icon_list = NULL;
422 static gchar *default_icon_name = NULL;
423 static guint default_icon_serial = 0;
424 static gboolean disable_startup_notification = FALSE;
425 static gboolean sent_startup_notification = FALSE;
427 static GQuark quark_gtk_embedded = 0;
428 static GQuark quark_gtk_window_key_hash = 0;
429 static GQuark quark_gtk_window_icon_info = 0;
430 static GQuark quark_gtk_buildable_accels = 0;
432 static GtkBuildableIface *parent_buildable_iface;
434 static void gtk_window_set_property (GObject *object,
438 static void gtk_window_get_property (GObject *object,
444 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
445 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
448 const GValue *value);
449 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
450 GtkBuilder *builder);
451 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
454 const gchar *tagname,
455 GMarkupParser *parser,
457 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
460 const gchar *tagname,
464 static void gtk_window_get_preferred_width (GtkWidget *widget,
467 static void gtk_window_get_preferred_height (GtkWidget *widget,
471 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
472 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
473 gtk_window_buildable_interface_init))
476 add_tab_bindings (GtkBindingSet *binding_set,
477 GdkModifierType modifiers,
478 GtkDirectionType direction)
480 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
482 GTK_TYPE_DIRECTION_TYPE, direction);
483 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
485 GTK_TYPE_DIRECTION_TYPE, direction);
489 add_arrow_bindings (GtkBindingSet *binding_set,
491 GtkDirectionType direction)
493 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
495 gtk_binding_entry_add_signal (binding_set, keysym, 0,
497 GTK_TYPE_DIRECTION_TYPE, direction);
498 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
500 GTK_TYPE_DIRECTION_TYPE, direction);
501 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
503 GTK_TYPE_DIRECTION_TYPE, direction);
504 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
506 GTK_TYPE_DIRECTION_TYPE, direction);
510 extract_time_from_startup_id (const gchar* startup_id)
512 gchar *timestr = g_strrstr (startup_id, "_TIME");
513 guint32 retval = GDK_CURRENT_TIME;
520 /* Skip past the "_TIME" part */
524 timestamp = strtoul (timestr, &end, 0);
525 if (end != timestr && errno == 0)
533 startup_id_is_fake (const gchar* startup_id)
535 return strncmp (startup_id, "_TIME", 5) == 0;
539 gtk_window_class_init (GtkWindowClass *klass)
541 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
542 GtkWidgetClass *widget_class;
543 GtkContainerClass *container_class;
544 GtkBindingSet *binding_set;
546 widget_class = (GtkWidgetClass*) klass;
547 container_class = (GtkContainerClass*) klass;
549 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
550 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
551 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
552 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
554 gobject_class->dispose = gtk_window_dispose;
555 gobject_class->finalize = gtk_window_finalize;
557 gobject_class->set_property = gtk_window_set_property;
558 gobject_class->get_property = gtk_window_get_property;
560 widget_class->destroy = gtk_window_destroy;
561 widget_class->show = gtk_window_show;
562 widget_class->hide = gtk_window_hide;
563 widget_class->map = gtk_window_map;
564 widget_class->map_event = gtk_window_map_event;
565 widget_class->unmap = gtk_window_unmap;
566 widget_class->realize = gtk_window_realize;
567 widget_class->unrealize = gtk_window_unrealize;
568 widget_class->size_allocate = gtk_window_size_allocate;
569 widget_class->configure_event = gtk_window_configure_event;
570 widget_class->key_press_event = gtk_window_key_press_event;
571 widget_class->key_release_event = gtk_window_key_release_event;
572 widget_class->enter_notify_event = gtk_window_enter_notify_event;
573 widget_class->leave_notify_event = gtk_window_leave_notify_event;
574 widget_class->focus_in_event = gtk_window_focus_in_event;
575 widget_class->button_press_event = gtk_window_button_press_event;
576 widget_class->focus_out_event = gtk_window_focus_out_event;
577 widget_class->client_event = gtk_window_client_event;
578 widget_class->focus = gtk_window_focus;
579 widget_class->draw = gtk_window_draw;
580 widget_class->get_preferred_width = gtk_window_get_preferred_width;
581 widget_class->get_preferred_height = gtk_window_get_preferred_height;
582 widget_class->window_state_event = gtk_window_state_event;
583 widget_class->direction_changed = gtk_window_direction_changed;
584 widget_class->state_changed = gtk_window_state_changed;
586 container_class->check_resize = gtk_window_check_resize;
588 klass->set_focus = gtk_window_real_set_focus;
589 klass->frame_event = gtk_window_frame_event;
591 klass->activate_default = gtk_window_real_activate_default;
592 klass->activate_focus = gtk_window_real_activate_focus;
593 klass->move_focus = gtk_window_move_focus;
594 klass->keys_changed = gtk_window_keys_changed;
596 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
599 g_object_class_install_property (gobject_class,
601 g_param_spec_enum ("type",
603 P_("The type of the window"),
604 GTK_TYPE_WINDOW_TYPE,
606 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
608 g_object_class_install_property (gobject_class,
610 g_param_spec_string ("title",
612 P_("The title of the window"),
614 GTK_PARAM_READWRITE));
616 g_object_class_install_property (gobject_class,
618 g_param_spec_string ("role",
620 P_("Unique identifier for the window to be used when restoring a session"),
622 GTK_PARAM_READWRITE));
625 * GtkWindow:startup-id:
627 * The :startup-id is a write-only property for setting window's
628 * startup notification identifier. See gtk_window_set_startup_id()
633 g_object_class_install_property (gobject_class,
635 g_param_spec_string ("startup-id",
637 P_("Unique startup identifier for the window used by startup-notification"),
639 GTK_PARAM_WRITABLE));
641 g_object_class_install_property (gobject_class,
643 g_param_spec_boolean ("resizable",
645 P_("If TRUE, users can resize the window"),
647 GTK_PARAM_READWRITE));
649 g_object_class_install_property (gobject_class,
651 g_param_spec_boolean ("modal",
653 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
655 GTK_PARAM_READWRITE));
657 g_object_class_install_property (gobject_class,
659 g_param_spec_enum ("window-position",
660 P_("Window Position"),
661 P_("The initial position of the window"),
662 GTK_TYPE_WINDOW_POSITION,
664 GTK_PARAM_READWRITE));
666 g_object_class_install_property (gobject_class,
668 g_param_spec_int ("default-width",
670 P_("The default width of the window, used when initially showing the window"),
674 GTK_PARAM_READWRITE));
676 g_object_class_install_property (gobject_class,
678 g_param_spec_int ("default-height",
679 P_("Default Height"),
680 P_("The default height of the window, used when initially showing the window"),
684 GTK_PARAM_READWRITE));
686 g_object_class_install_property (gobject_class,
687 PROP_DESTROY_WITH_PARENT,
688 g_param_spec_boolean ("destroy-with-parent",
689 P_("Destroy with Parent"),
690 P_("If this window should be destroyed when the parent is destroyed"),
692 GTK_PARAM_READWRITE));
694 g_object_class_install_property (gobject_class,
696 g_param_spec_object ("icon",
698 P_("Icon for this window"),
700 GTK_PARAM_READWRITE));
701 g_object_class_install_property (gobject_class,
702 PROP_MNEMONICS_VISIBLE,
703 g_param_spec_boolean ("mnemonics-visible",
704 P_("Mnemonics Visible"),
705 P_("Whether mnemonics are currently visible in this window"),
707 GTK_PARAM_READWRITE));
710 * GtkWindow:icon-name:
712 * The :icon-name property specifies the name of the themed icon to
713 * use as the window icon. See #GtkIconTheme for more details.
717 g_object_class_install_property (gobject_class,
719 g_param_spec_string ("icon-name",
721 P_("Name of the themed icon for this window"),
723 GTK_PARAM_READWRITE));
725 g_object_class_install_property (gobject_class,
727 g_param_spec_object ("screen",
729 P_("The screen where this window will be displayed"),
731 GTK_PARAM_READWRITE));
733 g_object_class_install_property (gobject_class,
735 g_param_spec_boolean ("is-active",
737 P_("Whether the toplevel is the current active window"),
739 GTK_PARAM_READABLE));
741 g_object_class_install_property (gobject_class,
742 PROP_HAS_TOPLEVEL_FOCUS,
743 g_param_spec_boolean ("has-toplevel-focus",
744 P_("Focus in Toplevel"),
745 P_("Whether the input focus is within this GtkWindow"),
747 GTK_PARAM_READABLE));
749 g_object_class_install_property (gobject_class,
751 g_param_spec_enum ("type-hint",
753 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
754 GDK_TYPE_WINDOW_TYPE_HINT,
755 GDK_WINDOW_TYPE_HINT_NORMAL,
756 GTK_PARAM_READWRITE));
758 g_object_class_install_property (gobject_class,
759 PROP_SKIP_TASKBAR_HINT,
760 g_param_spec_boolean ("skip-taskbar-hint",
762 P_("TRUE if the window should not be in the task bar."),
764 GTK_PARAM_READWRITE));
766 g_object_class_install_property (gobject_class,
767 PROP_SKIP_PAGER_HINT,
768 g_param_spec_boolean ("skip-pager-hint",
770 P_("TRUE if the window should not be in the pager."),
772 GTK_PARAM_READWRITE));
774 g_object_class_install_property (gobject_class,
776 g_param_spec_boolean ("urgency-hint",
778 P_("TRUE if the window should be brought to the user's attention."),
780 GTK_PARAM_READWRITE));
783 * GtkWindow:accept-focus:
785 * Whether the window should receive the input focus.
789 g_object_class_install_property (gobject_class,
791 g_param_spec_boolean ("accept-focus",
793 P_("TRUE if the window should receive the input focus."),
795 GTK_PARAM_READWRITE));
798 * GtkWindow:focus-on-map:
800 * Whether the window should receive the input focus when mapped.
804 g_object_class_install_property (gobject_class,
806 g_param_spec_boolean ("focus-on-map",
808 P_("TRUE if the window should receive the input focus when mapped."),
810 GTK_PARAM_READWRITE));
813 * GtkWindow:decorated:
815 * Whether the window should be decorated by the window manager.
819 g_object_class_install_property (gobject_class,
821 g_param_spec_boolean ("decorated",
823 P_("Whether the window should be decorated by the window manager"),
825 GTK_PARAM_READWRITE));
828 * GtkWindow:deletable:
830 * Whether the window frame should have a close button.
834 g_object_class_install_property (gobject_class,
836 g_param_spec_boolean ("deletable",
838 P_("Whether the window frame should have a close button"),
840 GTK_PARAM_READWRITE));
843 * GtkWindow:has-resize-grip
845 * Whether the window has a corner resize grip.
847 * Note that the resize grip is only shown if the window is
848 * actually resizable and not maximized. Use
849 * #GtkWindow:resize-grip-visible to find out if the resize
850 * grip is currently shown.
854 g_object_class_install_property (gobject_class,
855 PROP_HAS_RESIZE_GRIP,
856 g_param_spec_boolean ("has-resize-grip",
858 P_("Specifies whether the window should have a resize grip"),
860 GTK_PARAM_READWRITE));
863 * GtkWindow: resize-grip-visible:
865 * Whether a corner resize grip is currently shown.
869 g_object_class_install_property (gobject_class,
870 PROP_RESIZE_GRIP_VISIBLE,
871 g_param_spec_boolean ("resize-grip-visible",
872 P_("Resize grip is visible"),
873 P_("Specifies whether the window's resize grip is visible."),
875 GTK_PARAM_READABLE));
881 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
882 * more details about window gravity.
886 g_object_class_install_property (gobject_class,
888 g_param_spec_enum ("gravity",
890 P_("The window gravity of the window"),
892 GDK_GRAVITY_NORTH_WEST,
893 GTK_PARAM_READWRITE));
897 * GtkWindow:transient-for:
899 * The transient parent of the window. See gtk_window_set_transient_for() for
900 * more details about transient windows.
904 g_object_class_install_property (gobject_class,
906 g_param_spec_object ("transient-for",
907 P_("Transient for Window"),
908 P_("The transient parent of the dialog"),
910 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
915 * The requested opacity of the window. See gtk_window_set_opacity() for
916 * more details about window opacity.
920 g_object_class_install_property (gobject_class,
922 g_param_spec_double ("opacity",
923 P_("Opacity for Window"),
924 P_("The opacity of the window, from 0 to 1"),
928 GTK_PARAM_READWRITE));
933 gtk_widget_class_install_style_property (widget_class,
934 g_param_spec_int ("resize-grip-width",
935 P_("Width of resize grip"),
936 P_("Width of resize grip"),
937 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
939 gtk_widget_class_install_style_property (widget_class,
940 g_param_spec_int ("resize-grip-height",
941 P_("Height of resize grip"),
942 P_("Height of resize grip"),
943 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
948 window_signals[SET_FOCUS] =
949 g_signal_new (I_("set-focus"),
950 G_TYPE_FROM_CLASS (gobject_class),
952 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
954 _gtk_marshal_VOID__OBJECT,
958 window_signals[FRAME_EVENT] =
959 g_signal_new (I_("frame-event"),
960 G_TYPE_FROM_CLASS (gobject_class),
962 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
963 _gtk_boolean_handled_accumulator, NULL,
964 _gtk_marshal_BOOLEAN__BOXED,
969 * GtkWindow::activate-focus:
970 * @window: the window which received the signal
972 * The ::activate-focus signal is a
973 * <link linkend="keybinding-signals">keybinding signal</link>
974 * which gets emitted when the user activates the currently
975 * focused widget of @window.
977 window_signals[ACTIVATE_FOCUS] =
978 g_signal_new (I_("activate-focus"),
979 G_TYPE_FROM_CLASS (gobject_class),
980 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
981 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
983 _gtk_marshal_VOID__VOID,
988 * GtkWindow::activate-default:
989 * @window: the window which received the signal
991 * The ::activate-default signal is a
992 * <link linkend="keybinding-signals">keybinding signal</link>
993 * which gets emitted when the user activates the default widget
996 window_signals[ACTIVATE_DEFAULT] =
997 g_signal_new (I_("activate-default"),
998 G_TYPE_FROM_CLASS (gobject_class),
999 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1000 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1002 _gtk_marshal_VOID__VOID,
1007 * GtkWindow::keys-changed:
1008 * @window: the window which received the signal
1010 * The ::keys-changed signal gets emitted when the set of accelerators
1011 * or mnemonics that are associated with @window changes.
1013 window_signals[KEYS_CHANGED] =
1014 g_signal_new (I_("keys-changed"),
1015 G_TYPE_FROM_CLASS (gobject_class),
1017 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1019 _gtk_marshal_VOID__VOID,
1027 binding_set = gtk_binding_set_by_class (klass);
1029 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1030 "activate-focus", 0);
1031 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1032 "activate-focus", 0);
1034 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1035 "activate-default", 0);
1036 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1037 "activate-default", 0);
1038 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1039 "activate-default", 0);
1041 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1042 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1043 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1044 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1046 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1047 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1048 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1049 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1053 gtk_window_init (GtkWindow *window)
1055 GtkWindowPrivate *priv;
1057 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1060 priv = window->priv;
1062 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1063 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1065 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1067 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1070 priv->wmclass_name = g_strdup (g_get_prgname ());
1071 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1072 priv->wm_role = NULL;
1073 priv->geometry_info = NULL;
1074 priv->type = GTK_WINDOW_TOPLEVEL;
1075 priv->focus_widget = NULL;
1076 priv->default_widget = NULL;
1077 priv->configure_request_count = 0;
1078 priv->resizable = TRUE;
1079 priv->configure_notify_received = FALSE;
1080 priv->position = GTK_WIN_POS_NONE;
1081 priv->need_default_size = TRUE;
1082 priv->need_default_position = TRUE;
1083 priv->modal = FALSE;
1085 priv->has_frame = FALSE;
1086 priv->frame_left = 0;
1087 priv->frame_right = 0;
1088 priv->frame_top = 0;
1089 priv->frame_bottom = 0;
1090 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1091 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1092 priv->decorated = TRUE;
1093 priv->mnemonic_modifier = GDK_MOD1_MASK;
1094 priv->screen = gdk_screen_get_default ();
1096 priv->accept_focus = TRUE;
1097 priv->focus_on_map = TRUE;
1098 priv->deletable = TRUE;
1099 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1100 priv->opacity = 1.0;
1101 priv->startup_id = NULL;
1102 priv->has_resize_grip = TRUE;
1103 priv->mnemonics_visible = TRUE;
1105 g_object_ref_sink (window);
1106 priv->has_user_ref_count = TRUE;
1107 toplevel_list = g_slist_prepend (toplevel_list, window);
1109 gtk_decorated_window_init (window);
1111 g_signal_connect (priv->screen, "composited-changed",
1112 G_CALLBACK (gtk_window_on_composited_changed), window);
1116 gtk_window_set_property (GObject *object,
1118 const GValue *value,
1121 GtkWindow *window = GTK_WINDOW (object);
1122 GtkWindowPrivate *priv = window->priv;
1127 priv->type = g_value_get_enum (value);
1130 gtk_window_set_title (window, g_value_get_string (value));
1133 gtk_window_set_role (window, g_value_get_string (value));
1135 case PROP_STARTUP_ID:
1136 gtk_window_set_startup_id (window, g_value_get_string (value));
1138 case PROP_RESIZABLE:
1139 gtk_window_set_resizable (window, g_value_get_boolean (value));
1142 gtk_window_set_modal (window, g_value_get_boolean (value));
1145 gtk_window_set_position (window, g_value_get_enum (value));
1147 case PROP_DEFAULT_WIDTH:
1148 gtk_window_set_default_size_internal (window,
1149 TRUE, g_value_get_int (value),
1152 case PROP_DEFAULT_HEIGHT:
1153 gtk_window_set_default_size_internal (window,
1155 TRUE, g_value_get_int (value), FALSE);
1157 case PROP_DESTROY_WITH_PARENT:
1158 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1161 gtk_window_set_icon (window,
1162 g_value_get_object (value));
1164 case PROP_ICON_NAME:
1165 gtk_window_set_icon_name (window, g_value_get_string (value));
1168 gtk_window_set_screen (window, g_value_get_object (value));
1170 case PROP_TYPE_HINT:
1171 gtk_window_set_type_hint (window,
1172 g_value_get_enum (value));
1174 case PROP_SKIP_TASKBAR_HINT:
1175 gtk_window_set_skip_taskbar_hint (window,
1176 g_value_get_boolean (value));
1178 case PROP_SKIP_PAGER_HINT:
1179 gtk_window_set_skip_pager_hint (window,
1180 g_value_get_boolean (value));
1182 case PROP_URGENCY_HINT:
1183 gtk_window_set_urgency_hint (window,
1184 g_value_get_boolean (value));
1186 case PROP_ACCEPT_FOCUS:
1187 gtk_window_set_accept_focus (window,
1188 g_value_get_boolean (value));
1190 case PROP_FOCUS_ON_MAP:
1191 gtk_window_set_focus_on_map (window,
1192 g_value_get_boolean (value));
1194 case PROP_DECORATED:
1195 gtk_window_set_decorated (window, g_value_get_boolean (value));
1197 case PROP_DELETABLE:
1198 gtk_window_set_deletable (window, g_value_get_boolean (value));
1201 gtk_window_set_gravity (window, g_value_get_enum (value));
1203 case PROP_TRANSIENT_FOR:
1204 gtk_window_set_transient_for (window, g_value_get_object (value));
1207 gtk_window_set_opacity (window, g_value_get_double (value));
1209 case PROP_HAS_RESIZE_GRIP:
1210 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1212 case PROP_MNEMONICS_VISIBLE:
1213 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1216 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1222 gtk_window_get_property (GObject *object,
1227 GtkWindow *window = GTK_WINDOW (object);
1228 GtkWindowPrivate *priv = window->priv;
1232 GtkWindowGeometryInfo *info;
1234 g_value_set_enum (value, priv->type);
1237 g_value_set_string (value, priv->wm_role);
1240 g_value_set_string (value, priv->title);
1242 case PROP_RESIZABLE:
1243 g_value_set_boolean (value, priv->resizable);
1246 g_value_set_boolean (value, priv->modal);
1249 g_value_set_enum (value, priv->position);
1251 case PROP_DEFAULT_WIDTH:
1252 info = gtk_window_get_geometry_info (window, FALSE);
1254 g_value_set_int (value, -1);
1256 g_value_set_int (value, info->default_width);
1258 case PROP_DEFAULT_HEIGHT:
1259 info = gtk_window_get_geometry_info (window, FALSE);
1261 g_value_set_int (value, -1);
1263 g_value_set_int (value, info->default_height);
1265 case PROP_DESTROY_WITH_PARENT:
1266 g_value_set_boolean (value, priv->destroy_with_parent);
1269 g_value_set_object (value, gtk_window_get_icon (window));
1271 case PROP_ICON_NAME:
1272 g_value_set_string (value, gtk_window_get_icon_name (window));
1275 g_value_set_object (value, priv->screen);
1277 case PROP_IS_ACTIVE:
1278 g_value_set_boolean (value, priv->is_active);
1280 case PROP_HAS_TOPLEVEL_FOCUS:
1281 g_value_set_boolean (value, priv->has_toplevel_focus);
1283 case PROP_TYPE_HINT:
1284 g_value_set_enum (value, priv->type_hint);
1286 case PROP_SKIP_TASKBAR_HINT:
1287 g_value_set_boolean (value,
1288 gtk_window_get_skip_taskbar_hint (window));
1290 case PROP_SKIP_PAGER_HINT:
1291 g_value_set_boolean (value,
1292 gtk_window_get_skip_pager_hint (window));
1294 case PROP_URGENCY_HINT:
1295 g_value_set_boolean (value,
1296 gtk_window_get_urgency_hint (window));
1298 case PROP_ACCEPT_FOCUS:
1299 g_value_set_boolean (value,
1300 gtk_window_get_accept_focus (window));
1302 case PROP_FOCUS_ON_MAP:
1303 g_value_set_boolean (value,
1304 gtk_window_get_focus_on_map (window));
1306 case PROP_DECORATED:
1307 g_value_set_boolean (value, gtk_window_get_decorated (window));
1309 case PROP_DELETABLE:
1310 g_value_set_boolean (value, gtk_window_get_deletable (window));
1313 g_value_set_enum (value, gtk_window_get_gravity (window));
1315 case PROP_TRANSIENT_FOR:
1316 g_value_set_object (value, gtk_window_get_transient_for (window));
1319 g_value_set_double (value, gtk_window_get_opacity (window));
1321 case PROP_HAS_RESIZE_GRIP:
1322 g_value_set_boolean (value, priv->has_resize_grip);
1324 case PROP_RESIZE_GRIP_VISIBLE:
1325 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1327 case PROP_MNEMONICS_VISIBLE:
1328 g_value_set_boolean (value, priv->mnemonics_visible);
1331 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1337 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1339 parent_buildable_iface = g_type_interface_peek_parent (iface);
1340 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1341 iface->parser_finished = gtk_window_buildable_parser_finished;
1342 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1343 iface->custom_finished = gtk_window_buildable_custom_finished;
1347 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1348 GtkBuilder *builder,
1350 const GValue *value)
1352 GtkWindow *window = GTK_WINDOW (buildable);
1353 GtkWindowPrivate *priv = window->priv;
1355 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1356 priv->builder_visible = TRUE;
1358 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1362 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1363 GtkBuilder *builder)
1365 GtkWindow *window = GTK_WINDOW (buildable);
1366 GtkWindowPrivate *priv = window->priv;
1370 if (priv->builder_visible)
1371 gtk_widget_show (GTK_WIDGET (buildable));
1373 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1374 for (l = accels; l; l = l->next)
1376 object = gtk_builder_get_object (builder, l->data);
1379 g_warning ("Unknown accel group %s specified in window %s",
1380 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1383 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1384 GTK_ACCEL_GROUP (object));
1388 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1390 parent_buildable_iface->parser_finished (buildable, builder);
1396 } GSListSubParserData;
1399 window_start_element (GMarkupParseContext *context,
1400 const gchar *element_name,
1401 const gchar **names,
1402 const gchar **values,
1407 GSListSubParserData *data = (GSListSubParserData*)user_data;
1409 if (strcmp (element_name, "group") == 0)
1411 for (i = 0; names[i]; i++)
1413 if (strcmp (names[i], "name") == 0)
1414 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1417 else if (strcmp (element_name, "accel-groups") == 0)
1420 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1425 static const GMarkupParser window_parser =
1427 window_start_element
1431 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1432 GtkBuilder *builder,
1434 const gchar *tagname,
1435 GMarkupParser *parser,
1438 GSListSubParserData *parser_data;
1440 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1441 tagname, parser, data))
1444 if (strcmp (tagname, "accel-groups") == 0)
1446 parser_data = g_slice_new0 (GSListSubParserData);
1447 parser_data->items = NULL;
1448 parser_data->object = G_OBJECT (buildable);
1450 *parser = window_parser;
1451 *data = parser_data;
1459 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1460 GtkBuilder *builder,
1462 const gchar *tagname,
1465 GSListSubParserData *data;
1467 parent_buildable_iface->custom_finished (buildable, builder, child,
1468 tagname, user_data);
1470 if (strcmp (tagname, "accel-groups") != 0)
1473 data = (GSListSubParserData*)user_data;
1475 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1476 data->items, (GDestroyNotify) g_slist_free);
1478 g_slice_free (GSListSubParserData, data);
1483 * @type: type of window
1485 * Creates a new #GtkWindow, which is a toplevel window that can
1486 * contain other widgets. Nearly always, the type of the window should
1487 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1488 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1489 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1490 * dialogs, though in some other toolkits dialogs are called "popups".
1491 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1492 * On X11, popup windows are not controlled by the <link
1493 * linkend="gtk-X11-arch">window manager</link>.
1495 * If you simply want an undecorated window (no window borders), use
1496 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1498 * Return value: a new #GtkWindow.
1501 gtk_window_new (GtkWindowType type)
1503 GtkWindowPrivate *priv;
1506 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1508 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1509 priv = window->priv;
1513 return GTK_WIDGET (window);
1517 * gtk_window_set_title:
1518 * @window: a #GtkWindow
1519 * @title: title of the window
1521 * Sets the title of the #GtkWindow. The title of a window will be
1522 * displayed in its title bar; on the X Window System, the title bar
1523 * is rendered by the <link linkend="gtk-X11-arch">window
1524 * manager</link>, so exactly how the title appears to users may vary
1525 * according to a user's exact configuration. The title should help a
1526 * user distinguish this window from other windows they may have
1527 * open. A good title might include the application name and current
1528 * document filename, for example.
1532 gtk_window_set_title (GtkWindow *window,
1535 GtkWindowPrivate *priv;
1539 g_return_if_fail (GTK_IS_WINDOW (window));
1541 priv = window->priv;
1542 widget = GTK_WIDGET (window);
1544 new_title = g_strdup (title);
1545 g_free (priv->title);
1546 priv->title = new_title;
1548 if (gtk_widget_get_realized (widget))
1550 gdk_window_set_title (gtk_widget_get_window (widget),
1553 gtk_decorated_window_set_title (window, title);
1556 g_object_notify (G_OBJECT (window), "title");
1560 * gtk_window_get_title:
1561 * @window: a #GtkWindow
1563 * Retrieves the title of the window. See gtk_window_set_title().
1565 * Return value: the title of the window, or %NULL if none has
1566 * been set explicitely. The returned string is owned by the widget
1567 * and must not be modified or freed.
1569 G_CONST_RETURN gchar *
1570 gtk_window_get_title (GtkWindow *window)
1572 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1574 return window->priv->title;
1578 * gtk_window_set_wmclass:
1579 * @window: a #GtkWindow
1580 * @wmclass_name: window name hint
1581 * @wmclass_class: window class hint
1583 * Don't use this function. It sets the X Window System "class" and
1584 * "name" hints for a window. According to the ICCCM, you should
1585 * always set these to the same value for all windows in an
1586 * application, and GTK+ sets them to that value by default, so calling
1587 * this function is sort of pointless. However, you may want to call
1588 * gtk_window_set_role() on each window in your application, for the
1589 * benefit of the session manager. Setting the role allows the window
1590 * manager to restore window positions when loading a saved session.
1594 gtk_window_set_wmclass (GtkWindow *window,
1595 const gchar *wmclass_name,
1596 const gchar *wmclass_class)
1598 GtkWindowPrivate *priv;
1600 g_return_if_fail (GTK_IS_WINDOW (window));
1602 priv = window->priv;
1604 g_free (priv->wmclass_name);
1605 priv->wmclass_name = g_strdup (wmclass_name);
1607 g_free (priv->wmclass_class);
1608 priv->wmclass_class = g_strdup (wmclass_class);
1610 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1611 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1615 * gtk_window_set_role:
1616 * @window: a #GtkWindow
1617 * @role: unique identifier for the window to be used when restoring a session
1619 * This function is only useful on X11, not with other GTK+ targets.
1621 * In combination with the window title, the window role allows a
1622 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1623 * same" window when an application is restarted. So for example you
1624 * might set the "toolbox" role on your app's toolbox window, so that
1625 * when the user restarts their session, the window manager can put
1626 * the toolbox back in the same place.
1628 * If a window already has a unique title, you don't need to set the
1629 * role, since the WM can use the title to identify the window when
1630 * restoring the session.
1634 gtk_window_set_role (GtkWindow *window,
1637 GtkWindowPrivate *priv;
1640 g_return_if_fail (GTK_IS_WINDOW (window));
1642 priv = window->priv;
1644 new_role = g_strdup (role);
1645 g_free (priv->wm_role);
1646 priv->wm_role = new_role;
1648 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1649 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1652 g_object_notify (G_OBJECT (window), "role");
1656 * gtk_window_set_startup_id:
1657 * @window: a #GtkWindow
1658 * @startup_id: a string with startup-notification identifier
1660 * Startup notification identifiers are used by desktop environment to
1661 * track application startup, to provide user feedback and other
1662 * features. This function changes the corresponding property on the
1663 * underlying GdkWindow. Normally, startup identifier is managed
1664 * automatically and you should only use this function in special cases
1665 * like transferring focus from other processes. You should use this
1666 * function before calling gtk_window_present() or any equivalent
1667 * function generating a window map event.
1669 * This function is only useful on X11, not with other GTK+ targets.
1674 gtk_window_set_startup_id (GtkWindow *window,
1675 const gchar *startup_id)
1677 GtkWindowPrivate *priv;
1680 g_return_if_fail (GTK_IS_WINDOW (window));
1682 priv = window->priv;
1683 widget = GTK_WIDGET (window);
1685 g_free (priv->startup_id);
1686 priv->startup_id = g_strdup (startup_id);
1688 if (gtk_widget_get_realized (widget))
1690 GdkWindow *gdk_window;
1691 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1693 gdk_window = gtk_widget_get_window (widget);
1695 #ifdef GDK_WINDOWING_X11
1696 if (timestamp != GDK_CURRENT_TIME)
1697 gdk_x11_window_set_user_time (gdk_window, timestamp);
1700 /* Here we differentiate real and "fake" startup notification IDs,
1701 * constructed on purpose just to pass interaction timestamp
1703 if (startup_id_is_fake (priv->startup_id))
1704 gtk_window_present_with_time (window, timestamp);
1707 gdk_window_set_startup_id (gdk_window,
1710 /* If window is mapped, terminate the startup-notification too */
1711 if (gtk_widget_get_mapped (widget) &&
1712 !disable_startup_notification)
1713 gdk_notify_startup_complete_with_id (priv->startup_id);
1717 g_object_notify (G_OBJECT (window), "startup-id");
1721 * gtk_window_get_role:
1722 * @window: a #GtkWindow
1724 * Returns the role of the window. See gtk_window_set_role() for
1725 * further explanation.
1727 * Return value: the role of the window if set, or %NULL. The
1728 * returned is owned by the widget and must not be modified
1731 G_CONST_RETURN gchar *
1732 gtk_window_get_role (GtkWindow *window)
1734 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1736 return window->priv->wm_role;
1740 * gtk_window_set_focus:
1741 * @window: a #GtkWindow
1742 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1743 * any focus widget for the toplevel window.
1745 * If @focus is not the current focus widget, and is focusable, sets
1746 * it as the focus widget for the window. If @focus is %NULL, unsets
1747 * the focus widget for this window. To set the focus to a particular
1748 * widget in the toplevel, it is usually more convenient to use
1749 * gtk_widget_grab_focus() instead of this function.
1752 gtk_window_set_focus (GtkWindow *window,
1755 GtkWindowPrivate *priv;
1758 g_return_if_fail (GTK_IS_WINDOW (window));
1760 priv = window->priv;
1764 g_return_if_fail (GTK_IS_WIDGET (focus));
1765 g_return_if_fail (gtk_widget_get_can_focus (focus));
1769 gtk_widget_grab_focus (focus);
1772 /* Clear the existing focus chain, so that when we focus into
1773 * the window again, we start at the beginnning.
1775 GtkWidget *widget = priv->focus_widget;
1778 while ((parent = gtk_widget_get_parent (widget)))
1781 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1785 _gtk_window_internal_set_focus (window, NULL);
1790 _gtk_window_internal_set_focus (GtkWindow *window,
1793 GtkWindowPrivate *priv;
1795 g_return_if_fail (GTK_IS_WINDOW (window));
1797 priv = window->priv;
1799 if ((priv->focus_widget != focus) ||
1800 (focus && !gtk_widget_has_focus (focus)))
1801 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1805 * gtk_window_set_default:
1806 * @window: a #GtkWindow
1807 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1808 * default widget for the toplevel.
1810 * The default widget is the widget that's activated when the user
1811 * presses Enter in a dialog (for example). This function sets or
1812 * unsets the default widget for a #GtkWindow about. When setting
1813 * (rather than unsetting) the default widget it's generally easier to
1814 * call gtk_widget_grab_focus() on the widget. Before making a widget
1815 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1816 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1819 gtk_window_set_default (GtkWindow *window,
1820 GtkWidget *default_widget)
1822 GtkWindowPrivate *priv;
1824 g_return_if_fail (GTK_IS_WINDOW (window));
1826 priv = window->priv;
1829 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1831 if (priv->default_widget != default_widget)
1833 GtkWidget *old_default_widget = NULL;
1836 g_object_ref (default_widget);
1838 if (priv->default_widget)
1840 old_default_widget = priv->default_widget;
1842 if (priv->focus_widget != priv->default_widget ||
1843 !gtk_widget_get_receives_default (priv->default_widget))
1844 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1846 gtk_widget_queue_draw (priv->default_widget);
1849 priv->default_widget = default_widget;
1851 if (priv->default_widget)
1853 if (priv->focus_widget == NULL ||
1854 !gtk_widget_get_receives_default (priv->focus_widget))
1855 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1857 gtk_widget_queue_draw (priv->default_widget);
1860 if (old_default_widget)
1861 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1865 g_object_notify (G_OBJECT (default_widget), "has-default");
1866 g_object_unref (default_widget);
1872 * gtk_window_get_default_widget:
1873 * @window: a #GtkWindow
1875 * Returns the default widget for @window. See gtk_window_set_default()
1878 * Returns: (transfer none): the default widget, or %NULL if there is none.
1883 gtk_window_get_default_widget (GtkWindow *window)
1885 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1887 return window->priv->default_widget;
1891 handle_keys_changed (gpointer data)
1893 GtkWindow *window = GTK_WINDOW (data);
1894 GtkWindowPrivate *priv = window->priv;
1896 if (priv->keys_changed_handler)
1898 g_source_remove (priv->keys_changed_handler);
1899 priv->keys_changed_handler = 0;
1902 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1908 gtk_window_notify_keys_changed (GtkWindow *window)
1910 GtkWindowPrivate *priv = window->priv;
1912 if (!priv->keys_changed_handler)
1913 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1917 * gtk_window_add_accel_group:
1918 * @window: window to attach accelerator group to
1919 * @accel_group: a #GtkAccelGroup
1921 * Associate @accel_group with @window, such that calling
1922 * gtk_accel_groups_activate() on @window will activate accelerators
1926 gtk_window_add_accel_group (GtkWindow *window,
1927 GtkAccelGroup *accel_group)
1929 g_return_if_fail (GTK_IS_WINDOW (window));
1930 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1932 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1933 g_signal_connect_object (accel_group, "accel-changed",
1934 G_CALLBACK (gtk_window_notify_keys_changed),
1935 window, G_CONNECT_SWAPPED);
1936 gtk_window_notify_keys_changed (window);
1940 * gtk_window_remove_accel_group:
1941 * @window: a #GtkWindow
1942 * @accel_group: a #GtkAccelGroup
1944 * Reverses the effects of gtk_window_add_accel_group().
1947 gtk_window_remove_accel_group (GtkWindow *window,
1948 GtkAccelGroup *accel_group)
1950 g_return_if_fail (GTK_IS_WINDOW (window));
1951 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1953 g_signal_handlers_disconnect_by_func (accel_group,
1954 gtk_window_notify_keys_changed,
1956 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1957 gtk_window_notify_keys_changed (window);
1960 static GtkMnemonicHash *
1961 gtk_window_get_mnemonic_hash (GtkWindow *window,
1964 GtkWindowPrivate *private = window->priv;
1966 if (!private->mnemonic_hash && create)
1967 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1969 return private->mnemonic_hash;
1973 * gtk_window_add_mnemonic:
1974 * @window: a #GtkWindow
1975 * @keyval: the mnemonic
1976 * @target: the widget that gets activated by the mnemonic
1978 * Adds a mnemonic to this window.
1981 gtk_window_add_mnemonic (GtkWindow *window,
1985 g_return_if_fail (GTK_IS_WINDOW (window));
1986 g_return_if_fail (GTK_IS_WIDGET (target));
1988 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1990 gtk_window_notify_keys_changed (window);
1994 * gtk_window_remove_mnemonic:
1995 * @window: a #GtkWindow
1996 * @keyval: the mnemonic
1997 * @target: the widget that gets activated by the mnemonic
1999 * Removes a mnemonic from this window.
2002 gtk_window_remove_mnemonic (GtkWindow *window,
2006 g_return_if_fail (GTK_IS_WINDOW (window));
2007 g_return_if_fail (GTK_IS_WIDGET (target));
2009 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2011 gtk_window_notify_keys_changed (window);
2015 * gtk_window_mnemonic_activate:
2016 * @window: a #GtkWindow
2017 * @keyval: the mnemonic
2018 * @modifier: the modifiers
2019 * @returns: %TRUE if the activation is done.
2021 * Activates the targets associated with the mnemonic.
2024 gtk_window_mnemonic_activate (GtkWindow *window,
2026 GdkModifierType modifier)
2028 GtkWindowPrivate *priv;
2030 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2032 priv = window->priv;
2034 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2036 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2038 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2045 * gtk_window_set_mnemonic_modifier:
2046 * @window: a #GtkWindow
2047 * @modifier: the modifier mask used to activate
2048 * mnemonics on this window.
2050 * Sets the mnemonic modifier for this window.
2053 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2054 GdkModifierType modifier)
2056 GtkWindowPrivate *priv;
2058 g_return_if_fail (GTK_IS_WINDOW (window));
2059 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2061 priv = window->priv;
2063 priv->mnemonic_modifier = modifier;
2064 gtk_window_notify_keys_changed (window);
2068 * gtk_window_get_mnemonic_modifier:
2069 * @window: a #GtkWindow
2071 * Returns the mnemonic modifier for this window. See
2072 * gtk_window_set_mnemonic_modifier().
2074 * Return value: the modifier mask used to activate
2075 * mnemonics on this window.
2078 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2080 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2082 return window->priv->mnemonic_modifier;
2086 * gtk_window_set_position:
2087 * @window: a #GtkWindow.
2088 * @position: a position constraint.
2090 * Sets a position constraint for this window. If the old or new
2091 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2092 * the window to be repositioned to satisfy the new constraint.
2095 gtk_window_set_position (GtkWindow *window,
2096 GtkWindowPosition position)
2098 GtkWindowPrivate *priv;
2100 g_return_if_fail (GTK_IS_WINDOW (window));
2102 priv = window->priv;
2104 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2105 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2107 GtkWindowGeometryInfo *info;
2109 info = gtk_window_get_geometry_info (window, TRUE);
2111 /* this flag causes us to re-request the CENTER_ALWAYS
2112 * constraint in gtk_window_move_resize(), see
2113 * comment in that function.
2115 info->position_constraints_changed = TRUE;
2117 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2120 priv->position = position;
2122 g_object_notify (G_OBJECT (window), "window-position");
2126 * gtk_window_activate_focus:
2127 * @window: a #GtkWindow
2129 * Activates the current focused widget within the window.
2131 * Return value: %TRUE if a widget got activated.
2134 gtk_window_activate_focus (GtkWindow *window)
2136 GtkWindowPrivate *priv;
2138 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2140 priv = window->priv;
2142 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2143 return gtk_widget_activate (priv->focus_widget);
2149 * gtk_window_get_focus:
2150 * @window: a #GtkWindow
2152 * Retrieves the current focused widget within the window.
2153 * Note that this is the widget that would have the focus
2154 * if the toplevel window focused; if the toplevel window
2155 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2156 * not be %TRUE for the widget.
2158 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2161 gtk_window_get_focus (GtkWindow *window)
2163 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2165 return window->priv->focus_widget;
2169 * gtk_window_activate_default:
2170 * @window: a #GtkWindow
2172 * Activates the default widget for the window, unless the current
2173 * focused widget has been configured to receive the default action
2174 * (see gtk_widget_set_receives_default()), in which case the
2175 * focused widget is activated.
2177 * Return value: %TRUE if a widget got activated.
2180 gtk_window_activate_default (GtkWindow *window)
2182 GtkWindowPrivate *priv;
2184 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2186 priv = window->priv;
2188 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2189 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2190 return gtk_widget_activate (priv->default_widget);
2191 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2192 return gtk_widget_activate (priv->focus_widget);
2198 * gtk_window_set_modal:
2199 * @window: a #GtkWindow
2200 * @modal: whether the window is modal
2202 * Sets a window modal or non-modal. Modal windows prevent interaction
2203 * with other windows in the same application. To keep modal dialogs
2204 * on top of main application windows, use
2205 * gtk_window_set_transient_for() to make the dialog transient for the
2206 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2207 * will then disallow lowering the dialog below the parent.
2212 gtk_window_set_modal (GtkWindow *window,
2215 GtkWindowPrivate *priv;
2218 g_return_if_fail (GTK_IS_WINDOW (window));
2220 priv = window->priv;
2222 modal = modal != FALSE;
2223 if (priv->modal == modal)
2226 priv->modal = modal;
2227 widget = GTK_WIDGET (window);
2229 /* adjust desired modality state */
2230 if (gtk_widget_get_realized (widget))
2233 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2235 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2238 if (gtk_widget_get_visible (widget))
2241 gtk_grab_add (widget);
2243 gtk_grab_remove (widget);
2246 g_object_notify (G_OBJECT (window), "modal");
2250 * gtk_window_get_modal:
2251 * @window: a #GtkWindow
2253 * Returns whether the window is modal. See gtk_window_set_modal().
2255 * Return value: %TRUE if the window is set to be modal and
2256 * establishes a grab when shown
2259 gtk_window_get_modal (GtkWindow *window)
2261 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2263 return window->priv->modal;
2267 * gtk_window_list_toplevels:
2269 * Returns a list of all existing toplevel windows. The widgets
2270 * in the list are not individually referenced. If you want
2271 * to iterate through the list and perform actions involving
2272 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2273 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2274 * then unref all the widgets afterwards.
2276 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2279 gtk_window_list_toplevels (void)
2284 for (slist = toplevel_list; slist; slist = slist->next)
2285 list = g_list_prepend (list, slist->data);
2291 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2293 GList *embedded_windows;
2295 g_return_if_fail (GTK_IS_WINDOW (window));
2297 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2298 if (embedded_windows)
2299 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2300 embedded_windows = g_list_prepend (embedded_windows,
2301 GUINT_TO_POINTER (xid));
2303 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2306 (GDestroyNotify) g_list_free : NULL);
2310 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2312 GList *embedded_windows;
2315 g_return_if_fail (GTK_IS_WINDOW (window));
2317 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2318 if (embedded_windows)
2319 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2321 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2324 embedded_windows = g_list_remove_link (embedded_windows, node);
2325 g_list_free_1 (node);
2328 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2331 (GDestroyNotify) g_list_free : NULL);
2335 gtk_window_dispose (GObject *object)
2337 GtkWindow *window = GTK_WINDOW (object);
2339 gtk_window_set_focus (window, NULL);
2340 gtk_window_set_default (window, NULL);
2342 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2346 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2348 gtk_widget_destroy (GTK_WIDGET (child));
2352 connect_parent_destroyed (GtkWindow *window)
2354 GtkWindowPrivate *priv = window->priv;
2356 if (priv->transient_parent)
2358 g_signal_connect (priv->transient_parent,
2360 G_CALLBACK (parent_destroyed_callback),
2366 disconnect_parent_destroyed (GtkWindow *window)
2368 GtkWindowPrivate *priv = window->priv;
2370 if (priv->transient_parent)
2372 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2373 parent_destroyed_callback,
2379 gtk_window_transient_parent_realized (GtkWidget *parent,
2382 if (gtk_widget_get_realized (window))
2383 gdk_window_set_transient_for (gtk_widget_get_window (window),
2384 gtk_widget_get_window (parent));
2388 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2391 if (gtk_widget_get_realized (window))
2392 gdk_property_delete (gtk_widget_get_window (window),
2393 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2397 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2401 gtk_window_set_screen (window, parent->priv->screen);
2405 gtk_window_unset_transient_for (GtkWindow *window)
2407 GtkWindowPrivate *priv = window->priv;
2409 if (priv->transient_parent)
2411 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2412 gtk_window_transient_parent_realized,
2414 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2415 gtk_window_transient_parent_unrealized,
2417 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2418 gtk_window_transient_parent_screen_changed,
2420 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2421 gtk_widget_destroyed,
2422 &priv->transient_parent);
2424 if (priv->destroy_with_parent)
2425 disconnect_parent_destroyed (window);
2427 priv->transient_parent = NULL;
2429 if (priv->transient_parent_group)
2431 priv->transient_parent_group = FALSE;
2432 gtk_window_group_remove_window (priv->group,
2439 * gtk_window_set_transient_for:
2440 * @window: a #GtkWindow
2441 * @parent: (allow-none): parent window, or %NULL
2443 * Dialog windows should be set transient for the main application
2444 * window they were spawned from. This allows <link
2445 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2446 * dialog on top of the main window, or center the dialog over the
2447 * main window. gtk_dialog_new_with_buttons() and other convenience
2448 * functions in GTK+ will sometimes call
2449 * gtk_window_set_transient_for() on your behalf.
2451 * Passing %NULL for @parent unsets the current transient window.
2453 * On Windows, this function puts the child window on top of the parent,
2454 * much as the window manager would have done on X.
2457 gtk_window_set_transient_for (GtkWindow *window,
2460 GtkWindowPrivate *priv;
2462 g_return_if_fail (GTK_IS_WINDOW (window));
2463 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2464 g_return_if_fail (window != parent);
2466 priv = window->priv;
2468 if (priv->transient_parent)
2470 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2471 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2472 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2473 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2474 GTK_WIDGET (window));
2476 gtk_window_unset_transient_for (window);
2479 priv->transient_parent = parent;
2483 g_signal_connect (parent, "destroy",
2484 G_CALLBACK (gtk_widget_destroyed),
2485 &priv->transient_parent);
2486 g_signal_connect (parent, "realize",
2487 G_CALLBACK (gtk_window_transient_parent_realized),
2489 g_signal_connect (parent, "unrealize",
2490 G_CALLBACK (gtk_window_transient_parent_unrealized),
2492 g_signal_connect (parent, "notify::screen",
2493 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2496 gtk_window_set_screen (window, parent->priv->screen);
2498 if (priv->destroy_with_parent)
2499 connect_parent_destroyed (window);
2501 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2502 gtk_widget_get_realized (GTK_WIDGET (parent)))
2503 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2504 GTK_WIDGET (window));
2506 if (parent->priv->group)
2508 gtk_window_group_add_window (parent->priv->group, window);
2509 priv->transient_parent_group = TRUE;
2515 * gtk_window_get_transient_for:
2516 * @window: a #GtkWindow
2518 * Fetches the transient parent for this window. See
2519 * gtk_window_set_transient_for().
2521 * Return value: (transfer none): the transient parent for this window, or %NULL
2522 * if no transient parent has been set.
2525 gtk_window_get_transient_for (GtkWindow *window)
2527 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2529 return window->priv->transient_parent;
2533 * gtk_window_set_opacity:
2534 * @window: a #GtkWindow
2535 * @opacity: desired opacity, between 0 and 1
2537 * Request the windowing system to make @window partially transparent,
2538 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2539 * of the opacity parameter are clamped to the [0,1] range.) On X11
2540 * this has any effect only on X screens with a compositing manager
2541 * running. See gtk_widget_is_composited(). On Windows it should work
2544 * Note that setting a window's opacity after the window has been
2545 * shown causes it to flicker once on Windows.
2550 gtk_window_set_opacity (GtkWindow *window,
2553 GtkWindowPrivate *priv;
2555 g_return_if_fail (GTK_IS_WINDOW (window));
2557 priv = window->priv;
2561 else if (opacity > 1.0)
2564 priv->opacity_set = TRUE;
2565 priv->opacity = opacity;
2567 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2568 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2573 * gtk_window_get_opacity:
2574 * @window: a #GtkWindow
2576 * Fetches the requested opacity for this window. See
2577 * gtk_window_set_opacity().
2579 * Return value: the requested opacity for this window.
2584 gtk_window_get_opacity (GtkWindow *window)
2586 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2588 return window->priv->opacity;
2592 * gtk_window_set_type_hint:
2593 * @window: a #GtkWindow
2594 * @hint: the window type
2596 * By setting the type hint for the window, you allow the window
2597 * manager to decorate and handle the window in a way which is
2598 * suitable to the function of the window in your application.
2600 * This function should be called before the window becomes visible.
2602 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2603 * will sometimes call gtk_window_set_type_hint() on your behalf.
2607 gtk_window_set_type_hint (GtkWindow *window,
2608 GdkWindowTypeHint hint)
2610 GtkWindowPrivate *priv;
2612 g_return_if_fail (GTK_IS_WINDOW (window));
2613 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2615 priv = window->priv;
2617 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2618 priv->gdk_type_hint = hint;
2620 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2622 priv->reset_type_hint = TRUE;
2623 priv->type_hint = hint;
2627 * gtk_window_get_type_hint:
2628 * @window: a #GtkWindow
2630 * Gets the type hint for this window. See gtk_window_set_type_hint().
2632 * Return value: the type hint for @window.
2635 gtk_window_get_type_hint (GtkWindow *window)
2637 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2639 return window->priv->type_hint;
2643 * gtk_window_set_skip_taskbar_hint:
2644 * @window: a #GtkWindow
2645 * @setting: %TRUE to keep this window from appearing in the task bar
2647 * Windows may set a hint asking the desktop environment not to display
2648 * the window in the task bar. This function sets this hint.
2653 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2656 GtkWindowPrivate *priv;
2658 g_return_if_fail (GTK_IS_WINDOW (window));
2660 priv = window->priv;
2662 setting = setting != FALSE;
2664 if (priv->skips_taskbar != setting)
2666 priv->skips_taskbar = setting;
2667 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2668 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2669 priv->skips_taskbar);
2670 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2675 * gtk_window_get_skip_taskbar_hint:
2676 * @window: a #GtkWindow
2678 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2680 * Return value: %TRUE if window shouldn't be in taskbar
2685 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2687 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2689 return window->priv->skips_taskbar;
2693 * gtk_window_set_skip_pager_hint:
2694 * @window: a #GtkWindow
2695 * @setting: %TRUE to keep this window from appearing in the pager
2697 * Windows may set a hint asking the desktop environment not to display
2698 * the window in the pager. This function sets this hint.
2699 * (A "pager" is any desktop navigation tool such as a workspace
2700 * switcher that displays a thumbnail representation of the windows
2706 gtk_window_set_skip_pager_hint (GtkWindow *window,
2709 GtkWindowPrivate *priv;
2711 g_return_if_fail (GTK_IS_WINDOW (window));
2713 priv = window->priv;
2715 setting = setting != FALSE;
2717 if (priv->skips_pager != setting)
2719 priv->skips_pager = setting;
2720 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2721 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2723 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2728 * gtk_window_get_skip_pager_hint:
2729 * @window: a #GtkWindow
2731 * Gets the value set by gtk_window_set_skip_pager_hint().
2733 * Return value: %TRUE if window shouldn't be in pager
2738 gtk_window_get_skip_pager_hint (GtkWindow *window)
2740 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2742 return window->priv->skips_pager;
2746 * gtk_window_set_urgency_hint:
2747 * @window: a #GtkWindow
2748 * @setting: %TRUE to mark this window as urgent
2750 * Windows may set a hint asking the desktop environment to draw
2751 * the users attention to the window. This function sets this hint.
2756 gtk_window_set_urgency_hint (GtkWindow *window,
2759 GtkWindowPrivate *priv;
2761 g_return_if_fail (GTK_IS_WINDOW (window));
2763 priv = window->priv;
2765 setting = setting != FALSE;
2767 if (priv->urgent != setting)
2769 priv->urgent = setting;
2770 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2771 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2773 g_object_notify (G_OBJECT (window), "urgency-hint");
2778 * gtk_window_get_urgency_hint:
2779 * @window: a #GtkWindow
2781 * Gets the value set by gtk_window_set_urgency_hint()
2783 * Return value: %TRUE if window is urgent
2788 gtk_window_get_urgency_hint (GtkWindow *window)
2790 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2792 return window->priv->urgent;
2796 * gtk_window_set_accept_focus:
2797 * @window: a #GtkWindow
2798 * @setting: %TRUE to let this window receive input focus
2800 * Windows may set a hint asking the desktop environment not to receive
2801 * the input focus. This function sets this hint.
2806 gtk_window_set_accept_focus (GtkWindow *window,
2809 GtkWindowPrivate *priv;
2811 g_return_if_fail (GTK_IS_WINDOW (window));
2813 priv = window->priv;
2815 setting = setting != FALSE;
2817 if (priv->accept_focus != setting)
2819 priv->accept_focus = setting;
2820 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2821 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2822 priv->accept_focus);
2823 g_object_notify (G_OBJECT (window), "accept-focus");
2828 * gtk_window_get_accept_focus:
2829 * @window: a #GtkWindow
2831 * Gets the value set by gtk_window_set_accept_focus().
2833 * Return value: %TRUE if window should receive the input focus
2838 gtk_window_get_accept_focus (GtkWindow *window)
2840 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2842 return window->priv->accept_focus;
2846 * gtk_window_set_focus_on_map:
2847 * @window: a #GtkWindow
2848 * @setting: %TRUE to let this window receive input focus on map
2850 * Windows may set a hint asking the desktop environment not to receive
2851 * the input focus when the window is mapped. This function sets this
2857 gtk_window_set_focus_on_map (GtkWindow *window,
2860 GtkWindowPrivate *priv;
2862 g_return_if_fail (GTK_IS_WINDOW (window));
2864 priv = window->priv;
2866 setting = setting != FALSE;
2868 if (priv->focus_on_map != setting)
2870 priv->focus_on_map = setting;
2871 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2872 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2873 priv->focus_on_map);
2874 g_object_notify (G_OBJECT (window), "focus-on-map");
2879 * gtk_window_get_focus_on_map:
2880 * @window: a #GtkWindow
2882 * Gets the value set by gtk_window_set_focus_on_map().
2884 * Return value: %TRUE if window should receive the input focus when
2890 gtk_window_get_focus_on_map (GtkWindow *window)
2892 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2894 return window->priv->focus_on_map;
2898 * gtk_window_set_destroy_with_parent:
2899 * @window: a #GtkWindow
2900 * @setting: whether to destroy @window with its transient parent
2902 * If @setting is %TRUE, then destroying the transient parent of @window
2903 * will also destroy @window itself. This is useful for dialogs that
2904 * shouldn't persist beyond the lifetime of the main window they're
2905 * associated with, for example.
2908 gtk_window_set_destroy_with_parent (GtkWindow *window,
2911 GtkWindowPrivate *priv;
2913 g_return_if_fail (GTK_IS_WINDOW (window));
2915 priv = window->priv;
2917 if (priv->destroy_with_parent == (setting != FALSE))
2920 if (priv->destroy_with_parent)
2922 disconnect_parent_destroyed (window);
2926 connect_parent_destroyed (window);
2929 priv->destroy_with_parent = setting;
2931 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2935 * gtk_window_get_destroy_with_parent:
2936 * @window: a #GtkWindow
2938 * Returns whether the window will be destroyed with its transient parent. See
2939 * gtk_window_set_destroy_with_parent ().
2941 * Return value: %TRUE if the window will be destroyed with its transient parent.
2944 gtk_window_get_destroy_with_parent (GtkWindow *window)
2946 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2948 return window->priv->destroy_with_parent;
2951 static GtkWindowGeometryInfo*
2952 gtk_window_get_geometry_info (GtkWindow *window,
2955 GtkWindowPrivate *priv = window->priv;
2956 GtkWindowGeometryInfo *info;
2958 info = priv->geometry_info;
2959 if (!info && create)
2961 info = g_new0 (GtkWindowGeometryInfo, 1);
2963 info->default_width = -1;
2964 info->default_height = -1;
2965 info->resize_width = -1;
2966 info->resize_height = -1;
2967 info->initial_x = 0;
2968 info->initial_y = 0;
2969 info->initial_pos_set = FALSE;
2970 info->default_is_geometry = FALSE;
2971 info->position_constraints_changed = FALSE;
2972 info->last.configure_request.x = 0;
2973 info->last.configure_request.y = 0;
2974 info->last.configure_request.width = -1;
2975 info->last.configure_request.height = -1;
2976 info->widget = NULL;
2978 priv->geometry_info = info;
2985 * gtk_window_set_geometry_hints:
2986 * @window: a #GtkWindow
2987 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
2988 * @geometry: (allow-none): struct containing geometry information or %NULL
2989 * @geom_mask: mask indicating which struct fields should be paid attention to
2991 * This function sets up hints about how a window can be resized by
2992 * the user. You can set a minimum and maximum size; allowed resize
2993 * increments (e.g. for xterm, you can only resize by the size of a
2994 * character); aspect ratios; and more. See the #GdkGeometry struct.
2998 gtk_window_set_geometry_hints (GtkWindow *window,
2999 GtkWidget *geometry_widget,
3000 GdkGeometry *geometry,
3001 GdkWindowHints geom_mask)
3003 GtkWindowGeometryInfo *info;
3005 g_return_if_fail (GTK_IS_WINDOW (window));
3006 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3008 info = gtk_window_get_geometry_info (window, TRUE);
3011 g_signal_handlers_disconnect_by_func (info->widget,
3012 gtk_widget_destroyed,
3015 info->widget = geometry_widget;
3017 g_signal_connect (geometry_widget, "destroy",
3018 G_CALLBACK (gtk_widget_destroyed),
3022 info->geometry = *geometry;
3024 /* We store gravity in priv->gravity not in the hints. */
3025 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3027 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3029 gtk_window_set_gravity (window, geometry->win_gravity);
3032 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3036 * gtk_window_set_decorated:
3037 * @window: a #GtkWindow
3038 * @setting: %TRUE to decorate the window
3040 * By default, windows are decorated with a title bar, resize
3041 * controls, etc. Some <link linkend="gtk-X11-arch">window
3042 * managers</link> allow GTK+ to disable these decorations, creating a
3043 * borderless window. If you set the decorated property to %FALSE
3044 * using this function, GTK+ will do its best to convince the window
3045 * manager not to decorate the window. Depending on the system, this
3046 * function may not have any effect when called on a window that is
3047 * already visible, so you should call it before calling gtk_window_show().
3049 * On Windows, this function always works, since there's no window manager
3054 gtk_window_set_decorated (GtkWindow *window,
3057 GtkWindowPrivate *priv;
3058 GdkWindow *gdk_window;
3060 g_return_if_fail (GTK_IS_WINDOW (window));
3062 priv = window->priv;
3064 setting = setting != FALSE;
3066 if (setting == priv->decorated)
3069 priv->decorated = setting;
3071 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3074 if (priv->decorated)
3075 gdk_window_set_decorations (gdk_window,
3078 gdk_window_set_decorations (gdk_window,
3082 g_object_notify (G_OBJECT (window), "decorated");
3086 * gtk_window_get_decorated:
3087 * @window: a #GtkWindow
3089 * Returns whether the window has been set to have decorations
3090 * such as a title bar via gtk_window_set_decorated().
3092 * Return value: %TRUE if the window has been set to have decorations
3095 gtk_window_get_decorated (GtkWindow *window)
3097 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3099 return window->priv->decorated;
3103 * gtk_window_set_deletable:
3104 * @window: a #GtkWindow
3105 * @setting: %TRUE to decorate the window as deletable
3107 * By default, windows have a close button in the window frame. Some
3108 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3109 * disable this button. If you set the deletable property to %FALSE
3110 * using this function, GTK+ will do its best to convince the window
3111 * manager not to show a close button. Depending on the system, this
3112 * function may not have any effect when called on a window that is
3113 * already visible, so you should call it before calling gtk_window_show().
3115 * On Windows, this function always works, since there's no window manager
3121 gtk_window_set_deletable (GtkWindow *window,
3124 GtkWindowPrivate *priv;
3125 GdkWindow *gdk_window;
3127 g_return_if_fail (GTK_IS_WINDOW (window));
3129 priv = window->priv;
3131 setting = setting != FALSE;
3133 if (setting == priv->deletable)
3136 priv->deletable = setting;
3138 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3141 if (priv->deletable)
3142 gdk_window_set_functions (gdk_window,
3145 gdk_window_set_functions (gdk_window,
3146 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3149 g_object_notify (G_OBJECT (window), "deletable");
3153 * gtk_window_get_deletable:
3154 * @window: a #GtkWindow
3156 * Returns whether the window has been set to have a close button
3157 * via gtk_window_set_deletable().
3159 * Return value: %TRUE if the window has been set to have a close button
3164 gtk_window_get_deletable (GtkWindow *window)
3166 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3168 return window->priv->deletable;
3171 static GtkWindowIconInfo*
3172 get_icon_info (GtkWindow *window)
3174 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3178 free_icon_info (GtkWindowIconInfo *info)
3180 g_free (info->icon_name);
3181 g_slice_free (GtkWindowIconInfo, info);
3185 static GtkWindowIconInfo*
3186 ensure_icon_info (GtkWindow *window)
3188 GtkWindowIconInfo *info;
3190 info = get_icon_info (window);
3194 info = g_slice_new0 (GtkWindowIconInfo);
3195 g_object_set_qdata_full (G_OBJECT (window),
3196 quark_gtk_window_icon_info,
3198 (GDestroyNotify)free_icon_info);
3205 icon_list_from_theme (GtkWidget *widget,
3210 GtkIconTheme *icon_theme;
3215 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3217 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3220 for (i = 0; sizes[i]; i++)
3223 * We need an EWMH extension to handle scalable icons
3224 * by passing their name to the WM. For now just use a
3228 icon = gtk_icon_theme_load_icon (icon_theme, name,
3231 icon = gtk_icon_theme_load_icon (icon_theme, name,
3234 list = g_list_append (list, icon);
3244 gtk_window_realize_icon (GtkWindow *window)
3246 GtkWindowPrivate *priv = window->priv;
3248 GtkWindowIconInfo *info;
3249 GdkWindow *gdk_window;
3252 widget = GTK_WIDGET (window);
3253 gdk_window = gtk_widget_get_window (widget);
3255 g_return_if_fail (gdk_window != NULL);
3257 /* no point setting an icon on override-redirect */
3258 if (priv->type == GTK_WINDOW_POPUP)
3263 info = ensure_icon_info (window);
3268 info->using_default_icon = FALSE;
3269 info->using_parent_icon = FALSE;
3270 info->using_themed_icon = FALSE;
3272 icon_list = info->icon_list;
3274 /* Look up themed icon */
3275 if (icon_list == NULL && info->icon_name)
3277 icon_list = icon_list_from_theme (widget, info->icon_name);
3279 info->using_themed_icon = TRUE;
3282 /* Inherit from transient parent */
3283 if (icon_list == NULL && priv->transient_parent)
3285 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3287 info->using_parent_icon = TRUE;
3290 /* Inherit from default */
3291 if (icon_list == NULL)
3293 icon_list = default_icon_list;
3295 info->using_default_icon = TRUE;
3298 /* Look up themed icon */
3299 if (icon_list == NULL && default_icon_name)
3301 icon_list = icon_list_from_theme (widget, default_icon_name);
3302 info->using_default_icon = TRUE;
3303 info->using_themed_icon = TRUE;
3306 info->realized = TRUE;
3308 if (info->using_themed_icon)
3310 GtkIconTheme *icon_theme;
3312 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3313 g_list_free (icon_list);
3315 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3316 g_signal_connect (icon_theme, "changed",
3317 G_CALLBACK (update_themed_icon), window);
3322 gtk_window_unrealize_icon (GtkWindow *window)
3324 GtkWindowIconInfo *info;
3326 info = get_icon_info (window);
3331 if (info->using_themed_icon)
3333 GtkIconTheme *icon_theme;
3335 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3337 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3340 /* We don't clear the properties on the window, just figure the
3341 * window is going away.
3344 info->realized = FALSE;
3349 * gtk_window_set_icon_list:
3350 * @window: a #GtkWindow
3351 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3353 * Sets up the icon representing a #GtkWindow. The icon is used when
3354 * the window is minimized (also known as iconified). Some window
3355 * managers or desktop environments may also place it in the window
3356 * frame, or display it in other contexts.
3358 * gtk_window_set_icon_list() allows you to pass in the same icon in
3359 * several hand-drawn sizes. The list should contain the natural sizes
3360 * your icon is available in; that is, don't scale the image before
3361 * passing it to GTK+. Scaling is postponed until the last minute,
3362 * when the desired final size is known, to allow best quality.
3364 * By passing several sizes, you may improve the final image quality
3365 * of the icon, by reducing or eliminating automatic image scaling.
3367 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3368 * larger images (64x64, 128x128) if you have them.
3370 * See also gtk_window_set_default_icon_list() to set the icon
3371 * for all windows in your application in one go.
3373 * Note that transient windows (those who have been set transient for another
3374 * window using gtk_window_set_transient_for()) will inherit their
3375 * icon from their transient parent. So there's no need to explicitly
3376 * set the icon on transient windows.
3379 gtk_window_set_icon_list (GtkWindow *window,
3382 GtkWindowIconInfo *info;
3384 g_return_if_fail (GTK_IS_WINDOW (window));
3386 info = ensure_icon_info (window);
3388 if (info->icon_list == list) /* check for NULL mostly */
3391 g_list_foreach (list,
3392 (GFunc) g_object_ref, NULL);
3394 g_list_foreach (info->icon_list,
3395 (GFunc) g_object_unref, NULL);
3397 g_list_free (info->icon_list);
3399 info->icon_list = g_list_copy (list);
3401 g_object_notify (G_OBJECT (window), "icon");
3403 gtk_window_unrealize_icon (window);
3405 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3406 gtk_window_realize_icon (window);
3408 /* We could try to update our transient children, but I don't think
3409 * it's really worth it. If we did it, the best way would probably
3410 * be to have children connect to notify::icon-list
3415 * gtk_window_get_icon_list:
3416 * @window: a #GtkWindow
3418 * Retrieves the list of icons set by gtk_window_set_icon_list().
3419 * The list is copied, but the reference count on each
3420 * member won't be incremented.
3422 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3425 gtk_window_get_icon_list (GtkWindow *window)
3427 GtkWindowIconInfo *info;
3429 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3431 info = get_icon_info (window);
3434 return g_list_copy (info->icon_list);
3440 * gtk_window_set_icon:
3441 * @window: a #GtkWindow
3442 * @icon: (allow-none): icon image, or %NULL
3444 * Sets up the icon representing a #GtkWindow. This icon is used when
3445 * the window is minimized (also known as iconified). Some window
3446 * managers or desktop environments may also place it in the window
3447 * frame, or display it in other contexts.
3449 * The icon should be provided in whatever size it was naturally
3450 * drawn; that is, don't scale the image before passing it to
3451 * GTK+. Scaling is postponed until the last minute, when the desired
3452 * final size is known, to allow best quality.
3454 * If you have your icon hand-drawn in multiple sizes, use
3455 * gtk_window_set_icon_list(). Then the best size will be used.
3457 * This function is equivalent to calling gtk_window_set_icon_list()
3458 * with a 1-element list.
3460 * See also gtk_window_set_default_icon_list() to set the icon
3461 * for all windows in your application in one go.
3464 gtk_window_set_icon (GtkWindow *window,
3469 g_return_if_fail (GTK_IS_WINDOW (window));
3470 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3475 list = g_list_append (list, icon);
3477 gtk_window_set_icon_list (window, list);
3483 update_themed_icon (GtkIconTheme *icon_theme,
3486 g_object_notify (G_OBJECT (window), "icon");
3488 gtk_window_unrealize_icon (window);
3490 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3491 gtk_window_realize_icon (window);
3495 * gtk_window_set_icon_name:
3496 * @window: a #GtkWindow
3497 * @name: (allow-none): the name of the themed icon
3499 * Sets the icon for the window from a named themed icon. See
3500 * the docs for #GtkIconTheme for more details.
3502 * Note that this has nothing to do with the WM_ICON_NAME
3503 * property which is mentioned in the ICCCM.
3508 gtk_window_set_icon_name (GtkWindow *window,
3511 GtkWindowIconInfo *info;
3514 g_return_if_fail (GTK_IS_WINDOW (window));
3516 info = ensure_icon_info (window);
3518 if (g_strcmp0 (info->icon_name, name) == 0)
3521 tmp = info->icon_name;
3522 info->icon_name = g_strdup (name);
3525 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3526 g_list_free (info->icon_list);
3527 info->icon_list = NULL;
3529 update_themed_icon (NULL, window);
3531 g_object_notify (G_OBJECT (window), "icon-name");
3535 * gtk_window_get_icon_name:
3536 * @window: a #GtkWindow
3538 * Returns the name of the themed icon for the window,
3539 * see gtk_window_set_icon_name().
3541 * Returns: the icon name or %NULL if the window has
3547 gtk_window_get_icon_name (GtkWindow *window)
3549 GtkWindowIconInfo *info;
3551 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3553 info = ensure_icon_info (window);
3555 return info->icon_name;
3559 * gtk_window_get_icon:
3560 * @window: a #GtkWindow
3562 * Gets the value set by gtk_window_set_icon() (or if you've
3563 * called gtk_window_set_icon_list(), gets the first icon in
3566 * Return value: (transfer none): icon for window
3569 gtk_window_get_icon (GtkWindow *window)
3571 GtkWindowIconInfo *info;
3573 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3575 info = get_icon_info (window);
3576 if (info && info->icon_list)
3577 return GDK_PIXBUF (info->icon_list->data);
3582 /* Load pixbuf, printing warning on failure if error == NULL
3585 load_pixbuf_verbosely (const char *filename,
3588 GError *local_err = NULL;
3591 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3599 g_warning ("Error loading icon from file '%s':\n\t%s",
3600 filename, local_err->message);
3601 g_error_free (local_err);
3609 * gtk_window_set_icon_from_file:
3610 * @window: a #GtkWindow
3611 * @filename: location of icon file
3612 * @err: (allow-none): location to store error, or %NULL.
3614 * Sets the icon for @window.
3615 * Warns on failure if @err is %NULL.
3617 * This function is equivalent to calling gtk_window_set_icon()
3618 * with a pixbuf created by loading the image from @filename.
3620 * Returns: %TRUE if setting the icon succeeded.
3625 gtk_window_set_icon_from_file (GtkWindow *window,
3626 const gchar *filename,
3629 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3633 gtk_window_set_icon (window, pixbuf);
3634 g_object_unref (pixbuf);
3643 * gtk_window_set_default_icon_list:
3644 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3646 * Sets an icon list to be used as fallback for windows that haven't
3647 * had gtk_window_set_icon_list() called on them to set up a
3648 * window-specific icon list. This function allows you to set up the
3649 * icon for all windows in your app at once.
3651 * See gtk_window_set_icon_list() for more details.
3655 gtk_window_set_default_icon_list (GList *list)
3659 if (list == default_icon_list)
3662 /* Update serial so we don't used cached pixmaps/masks
3664 default_icon_serial++;
3666 g_list_foreach (list,
3667 (GFunc) g_object_ref, NULL);
3669 g_list_foreach (default_icon_list,
3670 (GFunc) g_object_unref, NULL);
3672 g_list_free (default_icon_list);
3674 default_icon_list = g_list_copy (list);
3676 /* Update all toplevels */
3677 toplevels = gtk_window_list_toplevels ();
3678 tmp_list = toplevels;
3679 while (tmp_list != NULL)
3681 GtkWindowIconInfo *info;
3682 GtkWindow *w = tmp_list->data;
3684 info = get_icon_info (w);
3685 if (info && info->using_default_icon)
3687 gtk_window_unrealize_icon (w);
3688 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3689 gtk_window_realize_icon (w);
3692 tmp_list = tmp_list->next;
3694 g_list_free (toplevels);
3698 * gtk_window_set_default_icon:
3701 * Sets an icon to be used as fallback for windows that haven't
3702 * had gtk_window_set_icon() called on them from a pixbuf.
3707 gtk_window_set_default_icon (GdkPixbuf *icon)
3711 g_return_if_fail (GDK_IS_PIXBUF (icon));
3713 list = g_list_prepend (NULL, icon);
3714 gtk_window_set_default_icon_list (list);
3719 * gtk_window_set_default_icon_name:
3720 * @name: the name of the themed icon
3722 * Sets an icon to be used as fallback for windows that haven't
3723 * had gtk_window_set_icon_list() called on them from a named
3724 * themed icon, see gtk_window_set_icon_name().
3729 gtk_window_set_default_icon_name (const gchar *name)
3734 /* Update serial so we don't used cached pixmaps/masks
3736 default_icon_serial++;
3738 g_free (default_icon_name);
3739 default_icon_name = g_strdup (name);
3741 g_list_foreach (default_icon_list,
3742 (GFunc) g_object_unref, NULL);
3744 g_list_free (default_icon_list);
3745 default_icon_list = NULL;
3747 /* Update all toplevels */
3748 toplevels = gtk_window_list_toplevels ();
3749 tmp_list = toplevels;
3750 while (tmp_list != NULL)
3752 GtkWindowIconInfo *info;
3753 GtkWindow *w = tmp_list->data;
3755 info = get_icon_info (w);
3756 if (info && info->using_default_icon && info->using_themed_icon)
3758 gtk_window_unrealize_icon (w);
3759 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3760 gtk_window_realize_icon (w);
3763 tmp_list = tmp_list->next;
3765 g_list_free (toplevels);
3769 * gtk_window_get_default_icon_name:
3771 * Returns the fallback icon name for windows that has been set
3772 * with gtk_window_set_default_icon_name(). The returned
3773 * string is owned by GTK+ and should not be modified. It
3774 * is only valid until the next call to
3775 * gtk_window_set_default_icon_name().
3777 * Returns: the fallback icon name for windows
3782 gtk_window_get_default_icon_name (void)
3784 return default_icon_name;
3788 * gtk_window_set_default_icon_from_file:
3789 * @filename: location of icon file
3790 * @err: (allow-none): location to store error, or %NULL.
3792 * Sets an icon to be used as fallback for windows that haven't
3793 * had gtk_window_set_icon_list() called on them from a file
3794 * on disk. Warns on failure if @err is %NULL.
3796 * Returns: %TRUE if setting the icon succeeded.
3801 gtk_window_set_default_icon_from_file (const gchar *filename,
3804 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3808 gtk_window_set_default_icon (pixbuf);
3809 g_object_unref (pixbuf);
3818 * gtk_window_get_default_icon_list:
3820 * Gets the value set by gtk_window_set_default_icon_list().
3821 * The list is a copy and should be freed with g_list_free(),
3822 * but the pixbufs in the list have not had their reference count
3825 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3828 gtk_window_get_default_icon_list (void)
3830 return g_list_copy (default_icon_list);
3834 gtk_window_set_default_size_internal (GtkWindow *window,
3835 gboolean change_width,
3837 gboolean change_height,
3839 gboolean is_geometry)
3841 GtkWindowGeometryInfo *info;
3843 g_return_if_fail (change_width == FALSE || width >= -1);
3844 g_return_if_fail (change_height == FALSE || height >= -1);
3846 info = gtk_window_get_geometry_info (window, TRUE);
3848 g_object_freeze_notify (G_OBJECT (window));
3850 info->default_is_geometry = is_geometry != FALSE;
3860 info->default_width = width;
3862 g_object_notify (G_OBJECT (window), "default-width");
3873 info->default_height = height;
3875 g_object_notify (G_OBJECT (window), "default-height");
3878 g_object_thaw_notify (G_OBJECT (window));
3880 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3884 * gtk_window_set_default_size:
3885 * @window: a #GtkWindow
3886 * @width: width in pixels, or -1 to unset the default width
3887 * @height: height in pixels, or -1 to unset the default height
3889 * Sets the default size of a window. If the window's "natural" size
3890 * (its size request) is larger than the default, the default will be
3891 * ignored. More generally, if the default size does not obey the
3892 * geometry hints for the window (gtk_window_set_geometry_hints() can
3893 * be used to set these explicitly), the default size will be clamped
3894 * to the nearest permitted size.
3896 * Unlike gtk_widget_set_size_request(), which sets a size request for
3897 * a widget and thus would keep users from shrinking the window, this
3898 * function only sets the initial size, just as if the user had
3899 * resized the window themselves. Users can still shrink the window
3900 * again as they normally would. Setting a default size of -1 means to
3901 * use the "natural" default size (the size request of the window).
3903 * For more control over a window's initial size and how resizing works,
3904 * investigate gtk_window_set_geometry_hints().
3906 * For some uses, gtk_window_resize() is a more appropriate function.
3907 * gtk_window_resize() changes the current size of the window, rather
3908 * than the size to be used on initial display. gtk_window_resize() always
3909 * affects the window itself, not the geometry widget.
3911 * The default size of a window only affects the first time a window is
3912 * shown; if a window is hidden and re-shown, it will remember the size
3913 * it had prior to hiding, rather than using the default size.
3915 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3916 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3919 gtk_window_set_default_size (GtkWindow *window,
3923 g_return_if_fail (GTK_IS_WINDOW (window));
3924 g_return_if_fail (width >= -1);
3925 g_return_if_fail (height >= -1);
3927 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3931 * gtk_window_get_default_size:
3932 * @window: a #GtkWindow
3933 * @width: (out) (allow-none): location to store the default width, or %NULL
3934 * @height: (out) (allow-none): location to store the default height, or %NULL
3936 * Gets the default size of the window. A value of -1 for the width or
3937 * height indicates that a default size has not been explicitly set
3938 * for that dimension, so the "natural" size of the window will be
3943 gtk_window_get_default_size (GtkWindow *window,
3947 GtkWindowGeometryInfo *info;
3949 g_return_if_fail (GTK_IS_WINDOW (window));
3951 info = gtk_window_get_geometry_info (window, FALSE);
3954 *width = info ? info->default_width : -1;
3957 *height = info ? info->default_height : -1;
3961 * gtk_window_resize:
3962 * @window: a #GtkWindow
3963 * @width: width in pixels to resize the window to
3964 * @height: height in pixels to resize the window to
3966 * Resizes the window as if the user had done so, obeying geometry
3967 * constraints. The default geometry constraint is that windows may
3968 * not be smaller than their size request; to override this
3969 * constraint, call gtk_widget_set_size_request() to set the window's
3970 * request to a smaller value.
3972 * If gtk_window_resize() is called before showing a window for the
3973 * first time, it overrides any default size set with
3974 * gtk_window_set_default_size().
3976 * Windows may not be resized smaller than 1 by 1 pixels.
3980 gtk_window_resize (GtkWindow *window,
3984 GtkWindowGeometryInfo *info;
3986 g_return_if_fail (GTK_IS_WINDOW (window));
3987 g_return_if_fail (width > 0);
3988 g_return_if_fail (height > 0);
3990 info = gtk_window_get_geometry_info (window, TRUE);
3992 info->resize_width = width;
3993 info->resize_height = height;
3995 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3999 * gtk_window_get_size:
4000 * @window: a #GtkWindow
4001 * @width: (out) (allow-none): return location for width, or %NULL
4002 * @height: (out) (allow-none): return location for height, or %NULL
4004 * Obtains the current size of @window. If @window is not onscreen,
4005 * it returns the size GTK+ will suggest to the <link
4006 * linkend="gtk-X11-arch">window manager</link> for the initial window
4007 * size (but this is not reliably the same as the size the window
4008 * manager will actually select). The size obtained by
4009 * gtk_window_get_size() is the last size received in a
4010 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4011 * rather than querying the X server for the size. As a result, if you
4012 * call gtk_window_resize() then immediately call
4013 * gtk_window_get_size(), the size won't have taken effect yet. After
4014 * the window manager processes the resize request, GTK+ receives
4015 * notification that the size has changed via a configure event, and
4016 * the size of the window gets updated.
4018 * Note 1: Nearly any use of this function creates a race condition,
4019 * because the size of the window may change between the time that you
4020 * get the size and the time that you perform some action assuming
4021 * that size is the current size. To avoid race conditions, connect to
4022 * "configure-event" on the window and adjust your size-dependent
4023 * state to match the size delivered in the #GdkEventConfigure.
4025 * Note 2: The returned size does <emphasis>not</emphasis> include the
4026 * size of the window manager decorations (aka the window frame or
4027 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4028 * method of determining their size.
4030 * Note 3: If you are getting a window size in order to position
4031 * the window onscreen, there may be a better way. The preferred
4032 * way is to simply set the window's semantic type with
4033 * gtk_window_set_type_hint(), which allows the window manager to
4034 * e.g. center dialogs. Also, if you set the transient parent of
4035 * dialogs with gtk_window_set_transient_for() window managers
4036 * will often center the dialog over its parent window. It's
4037 * much preferred to let the window manager handle these
4038 * things rather than doing it yourself, because all apps will
4039 * behave consistently and according to user prefs if the window
4040 * manager handles it. Also, the window manager can take the size
4041 * of the window decorations/border into account, while your
4042 * application cannot.
4044 * In any case, if you insist on application-specified window
4045 * positioning, there's <emphasis>still</emphasis> a better way than
4046 * doing it yourself - gtk_window_set_position() will frequently
4047 * handle the details for you.
4051 gtk_window_get_size (GtkWindow *window,
4057 g_return_if_fail (GTK_IS_WINDOW (window));
4059 if (width == NULL && height == NULL)
4062 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4064 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4065 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4069 GdkRectangle configure_request;
4071 gtk_window_compute_configure_request (window,
4075 w = configure_request.width;
4076 h = configure_request.height;
4087 * @window: a #GtkWindow
4088 * @x: X coordinate to move window to
4089 * @y: Y coordinate to move window to
4091 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4092 * @window to the given position. Window managers are free to ignore
4093 * this; most window managers ignore requests for initial window
4094 * positions (instead using a user-defined placement algorithm) and
4095 * honor requests after the window has already been shown.
4097 * Note: the position is the position of the gravity-determined
4098 * reference point for the window. The gravity determines two things:
4099 * first, the location of the reference point in root window
4100 * coordinates; and second, which point on the window is positioned at
4101 * the reference point.
4103 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4104 * point is simply the @x, @y supplied to gtk_window_move(). The
4105 * top-left corner of the window decorations (aka window frame or
4106 * border) will be placed at @x, @y. Therefore, to position a window
4107 * at the top left of the screen, you want to use the default gravity
4108 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4110 * To position a window at the bottom right corner of the screen, you
4111 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4112 * point is at @x + the window width and @y + the window height, and
4113 * the bottom-right corner of the window border will be placed at that
4114 * reference point. So, to place a window in the bottom right corner
4115 * you would first set gravity to south east, then write:
4116 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4117 * gdk_screen_height () - window_height)</literal> (note that this
4118 * example does not take multi-head scenarios into account).
4120 * The Extended Window Manager Hints specification at <ulink
4121 * url="http://www.freedesktop.org/Standards/wm-spec">
4122 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4123 * nice table of gravities in the "implementation notes" section.
4125 * The gtk_window_get_position() documentation may also be relevant.
4128 gtk_window_move (GtkWindow *window,
4132 GtkWindowPrivate *priv;
4133 GtkWindowGeometryInfo *info;
4136 g_return_if_fail (GTK_IS_WINDOW (window));
4138 priv = window->priv;
4139 widget = GTK_WIDGET (window);
4141 info = gtk_window_get_geometry_info (window, TRUE);
4143 if (gtk_widget_get_mapped (widget))
4145 GtkAllocation allocation;
4147 gtk_widget_get_allocation (widget, &allocation);
4149 /* we have now sent a request with this position
4150 * with currently-active constraints, so toggle flag.
4152 info->position_constraints_changed = FALSE;
4154 /* we only constrain if mapped - if not mapped,
4155 * then gtk_window_compute_configure_request()
4156 * will apply the constraints later, and we
4157 * don't want to lose information about
4158 * what position the user set before then.
4159 * i.e. if you do a move() then turn off POS_CENTER
4160 * then show the window, your move() will work.
4162 gtk_window_constrain_position (window,
4163 allocation.width, allocation.height,
4166 /* Note that this request doesn't go through our standard request
4167 * framework, e.g. doesn't increment configure_request_count,
4168 * doesn't set info->last, etc.; that's because
4169 * we don't save the info needed to arrive at this same request
4172 * To gtk_window_move_resize(), this will end up looking exactly
4173 * the same as the position being changed by the window
4177 /* FIXME are we handling gravity properly for framed windows? */
4179 gdk_window_move (priv->frame,
4180 x - priv->frame_left,
4181 y - priv->frame_top);
4183 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)),
4188 /* Save this position to apply on mapping */
4189 info->initial_x = x;
4190 info->initial_y = y;
4191 info->initial_pos_set = TRUE;
4196 * gtk_window_get_position:
4197 * @window: a #GtkWindow
4198 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4199 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4201 * This function returns the position you need to pass to
4202 * gtk_window_move() to keep @window in its current position. This
4203 * means that the meaning of the returned value varies with window
4204 * gravity. See gtk_window_move() for more details.
4206 * If you haven't changed the window gravity, its gravity will be
4207 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4208 * gets the position of the top-left corner of the window manager
4209 * frame for the window. gtk_window_move() sets the position of this
4210 * same top-left corner.
4212 * gtk_window_get_position() is not 100% reliable because the X Window System
4213 * does not specify a way to obtain the geometry of the
4214 * decorations placed on a window by the window manager.
4215 * Thus GTK+ is using a "best guess" that works with most
4218 * Moreover, nearly all window managers are historically broken with
4219 * respect to their handling of window gravity. So moving a window to
4220 * its current position as returned by gtk_window_get_position() tends
4221 * to result in moving the window slightly. Window managers are
4222 * slowly getting better over time.
4224 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4225 * frame is not relevant, and thus gtk_window_get_position() will
4226 * always produce accurate results. However you can't use static
4227 * gravity to do things like place a window in a corner of the screen,
4228 * because static gravity ignores the window manager decorations.
4230 * If you are saving and restoring your application's window
4231 * positions, you should know that it's impossible for applications to
4232 * do this without getting it somewhat wrong because applications do
4233 * not have sufficient knowledge of window manager state. The Correct
4234 * Mechanism is to support the session management protocol (see the
4235 * "GnomeClient" object in the GNOME libraries for example) and allow
4236 * the window manager to save your window sizes and positions.
4241 gtk_window_get_position (GtkWindow *window,
4245 GtkWindowPrivate *priv;
4247 GdkWindow *gdk_window;
4249 g_return_if_fail (GTK_IS_WINDOW (window));
4251 priv = window->priv;
4252 widget = GTK_WIDGET (window);
4253 gdk_window = gtk_widget_get_window (widget);
4255 if (priv->gravity == GDK_GRAVITY_STATIC)
4257 if (gtk_widget_get_mapped (widget))
4259 /* This does a server round-trip, which is sort of wrong;
4260 * but a server round-trip is inevitable for
4261 * gdk_window_get_frame_extents() in the usual
4262 * NorthWestGravity case below, so not sure what else to
4263 * do. We should likely be consistent about whether we get
4264 * the client-side info or the server-side info.
4266 gdk_window_get_origin (gdk_window, root_x, root_y);
4270 GdkRectangle configure_request;
4272 gtk_window_compute_configure_request (window,
4276 *root_x = configure_request.x;
4277 *root_y = configure_request.y;
4282 GdkRectangle frame_extents;
4287 if (gtk_widget_get_mapped (widget))
4290 gdk_window_get_frame_extents (priv->frame, &frame_extents);
4292 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4293 x = frame_extents.x;
4294 y = frame_extents.y;
4295 gtk_window_get_size (window, &w, &h);
4299 /* We just say the frame has 0 size on all sides.
4300 * Not sure what else to do.
4302 gtk_window_compute_configure_request (window,
4305 x = frame_extents.x;
4306 y = frame_extents.y;
4307 w = frame_extents.width;
4308 h = frame_extents.height;
4311 switch (priv->gravity)
4313 case GDK_GRAVITY_NORTH:
4314 case GDK_GRAVITY_CENTER:
4315 case GDK_GRAVITY_SOUTH:
4316 /* Find center of frame. */
4317 x += frame_extents.width / 2;
4318 /* Center client window on that point. */
4322 case GDK_GRAVITY_SOUTH_EAST:
4323 case GDK_GRAVITY_EAST:
4324 case GDK_GRAVITY_NORTH_EAST:
4325 /* Find right edge of frame */
4326 x += frame_extents.width;
4327 /* Align left edge of client at that point. */
4334 switch (priv->gravity)
4336 case GDK_GRAVITY_WEST:
4337 case GDK_GRAVITY_CENTER:
4338 case GDK_GRAVITY_EAST:
4339 /* Find center of frame. */
4340 y += frame_extents.height / 2;
4341 /* Center client window there. */
4344 case GDK_GRAVITY_SOUTH_WEST:
4345 case GDK_GRAVITY_SOUTH:
4346 case GDK_GRAVITY_SOUTH_EAST:
4347 /* Find south edge of frame */
4348 y += frame_extents.height;
4349 /* Place bottom edge of client there */
4364 * gtk_window_reshow_with_initial_size:
4365 * @window: a #GtkWindow
4367 * Hides @window, then reshows it, resetting the
4368 * default size and position of the window. Used
4369 * by GUI builders only.
4372 gtk_window_reshow_with_initial_size (GtkWindow *window)
4376 g_return_if_fail (GTK_IS_WINDOW (window));
4378 widget = GTK_WIDGET (window);
4380 gtk_widget_hide (widget);
4381 gtk_widget_unrealize (widget);
4382 gtk_widget_show (widget);
4386 gtk_window_destroy (GtkWidget *widget)
4388 GtkWindow *window = GTK_WINDOW (widget);
4389 GtkWindowPrivate *priv = window->priv;
4391 toplevel_list = g_slist_remove (toplevel_list, window);
4393 if (priv->transient_parent)
4394 gtk_window_set_transient_for (window, NULL);
4396 /* frees the icons */
4397 gtk_window_set_icon_list (window, NULL);
4399 if (priv->has_user_ref_count)
4401 priv->has_user_ref_count = FALSE;
4402 g_object_unref (window);
4406 gtk_window_group_remove_window (priv->group, window);
4408 gtk_window_free_key_hash (window);
4410 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4414 gtk_window_finalize (GObject *object)
4416 GtkWindow *window = GTK_WINDOW (object);
4417 GtkWindowPrivate *priv = window->priv;
4418 GtkMnemonicHash *mnemonic_hash;
4420 g_free (priv->title);
4421 g_free (priv->wmclass_name);
4422 g_free (priv->wmclass_class);
4423 g_free (priv->wm_role);
4425 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4427 _gtk_mnemonic_hash_free (mnemonic_hash);
4429 if (priv->geometry_info)
4431 if (priv->geometry_info->widget)
4432 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4433 gtk_widget_destroyed,
4434 &priv->geometry_info->widget);
4435 g_free (priv->geometry_info);
4438 if (priv->keys_changed_handler)
4440 g_source_remove (priv->keys_changed_handler);
4441 priv->keys_changed_handler = 0;
4445 g_signal_handlers_disconnect_by_func (priv->screen,
4446 gtk_window_on_composited_changed, window);
4448 g_free (priv->startup_id);
4450 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4454 gtk_window_show (GtkWidget *widget)
4456 GtkWindow *window = GTK_WINDOW (widget);
4457 GtkWindowPrivate *priv = window->priv;
4458 GtkContainer *container = GTK_CONTAINER (window);
4459 gboolean need_resize;
4461 _gtk_widget_set_visible_flag (widget, TRUE);
4463 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4464 _gtk_container_set_need_resize (container, FALSE);
4468 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4469 GtkAllocation allocation = { 0, 0 };
4470 GdkRectangle configure_request;
4471 GdkGeometry new_geometry;
4473 gboolean was_realized;
4475 /* We are going to go ahead and perform this configure request
4476 * and then emulate a configure notify by going ahead and
4477 * doing a size allocate. Sort of a synchronous
4478 * mini-copy of gtk_window_move_resize() here.
4480 gtk_window_compute_configure_request (window,
4485 /* We update this because we are going to go ahead
4486 * and gdk_window_resize() below, rather than
4489 info->last.configure_request.width = configure_request.width;
4490 info->last.configure_request.height = configure_request.height;
4492 /* and allocate the window - this is normally done
4493 * in move_resize in response to configure notify
4495 allocation.width = configure_request.width;
4496 allocation.height = configure_request.height;
4497 gtk_widget_size_allocate (widget, &allocation);
4499 /* Then we guarantee we have a realize */
4500 was_realized = FALSE;
4501 if (!gtk_widget_get_realized (widget))
4503 gtk_widget_realize (widget);
4504 was_realized = TRUE;
4507 /* Must be done after the windows are realized,
4508 * so that the decorations can be read
4510 gtk_decorated_window_calculate_frame_size (window);
4512 /* We only send configure request if we didn't just finish
4513 * creating the window; if we just created the window
4514 * then we created it with widget->allocation anyhow.
4517 gdk_window_move_resize (gtk_widget_get_window (widget),
4518 configure_request.x,
4519 configure_request.y,
4520 configure_request.width,
4521 configure_request.height);
4524 gtk_container_check_resize (container);
4526 gtk_widget_map (widget);
4528 /* Try to make sure that we have some focused widget
4530 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4531 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4534 gtk_grab_add (widget);
4538 gtk_window_hide (GtkWidget *widget)
4540 GtkWindow *window = GTK_WINDOW (widget);
4541 GtkWindowPrivate *priv = window->priv;
4543 _gtk_widget_set_visible_flag (widget, FALSE);
4544 gtk_widget_unmap (widget);
4547 gtk_grab_remove (widget);
4551 gtk_window_map (GtkWidget *widget)
4554 GtkWindow *window = GTK_WINDOW (widget);
4555 GtkWindowPrivate *priv = window->priv;
4556 GdkWindow *toplevel;
4557 GdkWindow *gdk_window;
4558 gboolean auto_mnemonics;
4560 gdk_window = gtk_widget_get_window (widget);
4562 gtk_widget_set_mapped (widget, TRUE);
4564 child = gtk_bin_get_child (&(window->bin));
4566 gtk_widget_get_visible (child) &&
4567 !gtk_widget_get_mapped (child))
4568 gtk_widget_map (child);
4571 toplevel = priv->frame;
4573 toplevel = gdk_window;
4575 if (priv->maximize_initially)
4576 gdk_window_maximize (toplevel);
4578 gdk_window_unmaximize (toplevel);
4580 if (priv->stick_initially)
4581 gdk_window_stick (toplevel);
4583 gdk_window_unstick (toplevel);
4585 if (priv->iconify_initially)
4586 gdk_window_iconify (toplevel);
4588 gdk_window_deiconify (toplevel);
4590 if (priv->fullscreen_initially)
4591 gdk_window_fullscreen (toplevel);
4593 gdk_window_unfullscreen (toplevel);
4595 gdk_window_set_keep_above (toplevel, priv->above_initially);
4597 gdk_window_set_keep_below (toplevel, priv->below_initially);
4599 /* No longer use the default settings */
4600 priv->need_default_size = FALSE;
4601 priv->need_default_position = FALSE;
4603 if (priv->reset_type_hint)
4605 /* We should only reset the type hint when the application
4606 * used gtk_window_set_type_hint() to change the hint.
4607 * Some applications use X directly to change the properties;
4608 * in that case, we shouldn't overwrite what they did.
4610 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4611 priv->reset_type_hint = FALSE;
4614 gdk_window_show (gdk_window);
4617 gdk_window_show (priv->frame);
4619 if (priv->grip_window)
4620 gdk_window_show (priv->grip_window);
4622 if (!disable_startup_notification)
4624 /* Do we have a custom startup-notification id? */
4625 if (priv->startup_id != NULL)
4627 /* Make sure we have a "real" id */
4628 if (!startup_id_is_fake (priv->startup_id))
4629 gdk_notify_startup_complete_with_id (priv->startup_id);
4631 g_free (priv->startup_id);
4632 priv->startup_id = NULL;
4634 else if (!sent_startup_notification)
4636 sent_startup_notification = TRUE;
4637 gdk_notify_startup_complete ();
4641 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4642 * (as in the case of popup menus), then hide mnemonics initially
4644 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4645 &auto_mnemonics, NULL);
4646 if (auto_mnemonics && !priv->mnemonics_visible_set)
4647 gtk_window_set_mnemonics_visible (window, FALSE);
4651 gtk_window_map_event (GtkWidget *widget,
4654 if (!gtk_widget_get_mapped (widget))
4656 /* we should be be unmapped, but are getting a MapEvent, this may happen
4657 * to toplevel XWindows if mapping was intercepted by a window manager
4658 * and an unmap request occoured while the MapRequestEvent was still
4659 * being handled. we work around this situaiton here by re-requesting
4660 * the window being unmapped. more details can be found in:
4661 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4663 gdk_window_hide (gtk_widget_get_window (widget));
4669 gtk_window_unmap (GtkWidget *widget)
4671 GtkWindow *window = GTK_WINDOW (widget);
4672 GtkWindowPrivate *priv = window->priv;
4673 GtkWindowGeometryInfo *info;
4674 GdkWindow *gdk_window;
4675 GdkWindowState state;
4677 gdk_window = gtk_widget_get_window (widget);
4679 gtk_widget_set_mapped (widget, FALSE);
4681 gdk_window_withdraw (priv->frame);
4683 gdk_window_withdraw (gdk_window);
4685 priv->configure_request_count = 0;
4686 priv->configure_notify_received = FALSE;
4688 /* on unmap, we reset the default positioning of the window,
4689 * so it's placed again, but we don't reset the default
4690 * size of the window, so it's remembered.
4692 priv->need_default_position = TRUE;
4694 info = gtk_window_get_geometry_info (window, FALSE);
4697 info->initial_pos_set = FALSE;
4698 info->position_constraints_changed = FALSE;
4701 state = gdk_window_get_state (gdk_window);
4702 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4703 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4704 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4705 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4706 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4710 gtk_window_realize (GtkWidget *widget)
4712 GtkAllocation allocation;
4715 GdkWindow *parent_window;
4716 GdkWindow *gdk_window;
4717 GdkWindowAttr attributes;
4718 gint attributes_mask;
4719 GtkWindowPrivate *priv;
4721 window = GTK_WINDOW (widget);
4722 priv = window->priv;
4724 gtk_widget_get_allocation (widget, &allocation);
4726 /* ensure widget tree is properly size allocated */
4727 if (allocation.x == -1 &&
4728 allocation.y == -1 &&
4729 allocation.width == 1 &&
4730 allocation.height == 1)
4732 GtkRequisition requisition;
4736 allocation.width = 200;
4737 allocation.height = 200;
4739 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4740 if (requisition.width || requisition.height)
4742 /* non-empty window */
4743 allocation.width = requisition.width;
4744 allocation.height = requisition.height;
4746 gtk_widget_size_allocate (widget, &allocation);
4748 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4750 g_return_if_fail (!gtk_widget_get_realized (widget));
4753 gtk_widget_set_realized (widget, TRUE);
4757 case GTK_WINDOW_TOPLEVEL:
4758 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4760 case GTK_WINDOW_POPUP:
4761 attributes.window_type = GDK_WINDOW_TEMP;
4764 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4768 attributes.title = priv->title;
4769 attributes.wmclass_name = priv->wmclass_name;
4770 attributes.wmclass_class = priv->wmclass_class;
4771 attributes.wclass = GDK_INPUT_OUTPUT;
4772 attributes.visual = gtk_widget_get_visual (widget);
4774 if (priv->has_frame)
4776 gtk_widget_get_allocation (widget, &allocation);
4777 attributes.width = allocation.width + priv->frame_left + priv->frame_right;
4778 attributes.height = allocation.height + priv->frame_top + priv->frame_bottom;
4779 attributes.event_mask = (GDK_EXPOSURE_MASK |
4780 GDK_KEY_PRESS_MASK |
4781 GDK_ENTER_NOTIFY_MASK |
4782 GDK_LEAVE_NOTIFY_MASK |
4783 GDK_FOCUS_CHANGE_MASK |
4784 GDK_STRUCTURE_MASK |
4785 GDK_BUTTON_MOTION_MASK |
4786 GDK_POINTER_MOTION_HINT_MASK |
4787 GDK_BUTTON_PRESS_MASK |
4788 GDK_BUTTON_RELEASE_MASK);
4790 attributes_mask = GDK_WA_VISUAL;
4792 priv->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4793 &attributes, attributes_mask);
4795 if (priv->opacity_set)
4796 gdk_window_set_opacity (priv->frame, priv->opacity);
4798 gdk_window_set_user_data (priv->frame, widget);
4800 attributes.window_type = GDK_WINDOW_CHILD;
4801 attributes.x = priv->frame_left;
4802 attributes.y = priv->frame_top;
4804 attributes_mask = GDK_WA_X | GDK_WA_Y;
4806 parent_window = priv->frame;
4808 g_signal_connect (window,
4810 G_CALLBACK (gtk_window_event),
4815 attributes_mask = 0;
4816 parent_window = gtk_widget_get_root_window (widget);
4819 gtk_widget_get_allocation (widget, &allocation);
4820 attributes.width = allocation.width;
4821 attributes.height = allocation.height;
4822 attributes.event_mask = gtk_widget_get_events (widget);
4823 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4824 GDK_KEY_PRESS_MASK |
4825 GDK_KEY_RELEASE_MASK |
4826 GDK_ENTER_NOTIFY_MASK |
4827 GDK_LEAVE_NOTIFY_MASK |
4828 GDK_FOCUS_CHANGE_MASK |
4829 GDK_STRUCTURE_MASK);
4830 attributes.type_hint = priv->type_hint;
4832 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4833 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4834 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4836 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4837 gtk_widget_set_window (widget, gdk_window);
4839 if (!priv->has_frame && priv->opacity_set)
4840 gdk_window_set_opacity (gdk_window, priv->opacity);
4842 gdk_window_enable_synchronized_configure (gdk_window);
4844 gdk_window_set_user_data (gdk_window, window);
4846 gtk_widget_style_attach (widget);
4847 style = gtk_widget_get_style (widget);
4848 gtk_style_set_background (style, gdk_window, GTK_STATE_NORMAL);
4850 gtk_style_set_background (style, priv->frame, GTK_STATE_NORMAL);
4852 if (priv->transient_parent &&
4853 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4854 gdk_window_set_transient_for (gdk_window,
4855 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4858 gdk_window_set_role (gdk_window, priv->wm_role);
4860 if (!priv->decorated)
4861 gdk_window_set_decorations (gdk_window, 0);
4863 if (!priv->deletable)
4864 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4866 if (gtk_window_get_skip_pager_hint (window))
4867 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4869 if (gtk_window_get_skip_taskbar_hint (window))
4870 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4872 if (gtk_window_get_accept_focus (window))
4873 gdk_window_set_accept_focus (gdk_window, TRUE);
4875 gdk_window_set_accept_focus (gdk_window, FALSE);
4877 if (gtk_window_get_focus_on_map (window))
4878 gdk_window_set_focus_on_map (gdk_window, TRUE);
4880 gdk_window_set_focus_on_map (gdk_window, FALSE);
4883 gdk_window_set_modal_hint (gdk_window, TRUE);
4885 gdk_window_set_modal_hint (gdk_window, FALSE);
4887 if (priv->startup_id)
4889 #ifdef GDK_WINDOWING_X11
4890 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4891 if (timestamp != GDK_CURRENT_TIME)
4892 gdk_x11_window_set_user_time (gdk_window, timestamp);
4894 if (!startup_id_is_fake (priv->startup_id))
4895 gdk_window_set_startup_id (gdk_window, priv->startup_id);
4899 gtk_window_realize_icon (window);
4901 if (priv->has_resize_grip)
4902 resize_grip_create_window (window);
4906 gtk_window_unrealize (GtkWidget *widget)
4908 GtkWindow *window = GTK_WINDOW (widget);
4909 GtkWindowPrivate *priv = window->priv;
4910 GtkWindowGeometryInfo *info;
4912 /* On unrealize, we reset the size of the window such
4913 * that we will re-apply the default sizing stuff
4914 * next time we show the window.
4916 * Default positioning is reset on unmap, instead of unrealize.
4918 priv->need_default_size = TRUE;
4919 info = gtk_window_get_geometry_info (window, FALSE);
4922 info->resize_width = -1;
4923 info->resize_height = -1;
4924 info->last.configure_request.x = 0;
4925 info->last.configure_request.y = 0;
4926 info->last.configure_request.width = -1;
4927 info->last.configure_request.height = -1;
4928 /* be sure we reset geom hints on re-realize */
4929 info->last.flags = 0;
4934 gdk_window_set_user_data (priv->frame, NULL);
4935 gdk_window_destroy (priv->frame);
4940 gtk_window_unrealize_icon (window);
4942 if (priv->grip_window != NULL)
4943 resize_grip_destroy_window (window);
4945 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
4948 static GdkWindowEdge
4949 get_grip_edge (GtkWidget *widget)
4951 return gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
4955 set_grip_cursor (GtkWindow *window)
4957 GtkWidget *widget = GTK_WIDGET (window);
4958 GtkWindowPrivate *priv = window->priv;
4960 GdkDisplay *display;
4961 GdkCursorType cursor_type;
4964 if (priv->grip_window == NULL)
4967 if (gtk_widget_is_sensitive (widget))
4969 edge = get_grip_edge (widget);
4971 if (edge == GDK_WINDOW_EDGE_SOUTH_EAST)
4972 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
4974 cursor_type = GDK_BOTTOM_LEFT_CORNER;
4976 display = gtk_widget_get_display (widget);
4977 cursor = gdk_cursor_new_for_display (display, cursor_type);
4978 gdk_window_set_cursor (priv->grip_window, cursor);
4979 gdk_cursor_unref (cursor);
4982 gdk_window_set_cursor (priv->grip_window, NULL);
4986 set_grip_shape (GtkWindow *window)
4988 GtkWindowPrivate *priv = window->priv;
4989 cairo_region_t *region;
4990 cairo_surface_t *surface;
4992 double width, height;
4994 if (priv->grip_window == NULL)
4997 width = gdk_window_get_width (priv->grip_window);
4998 height = gdk_window_get_height (priv->grip_window);
4999 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5001 cr = cairo_create (surface);
5002 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5004 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5005 if (get_grip_edge (GTK_WIDGET (window)) == GDK_WINDOW_EDGE_SOUTH_EAST)
5007 cairo_move_to (cr, width, 0.0);
5008 cairo_line_to (cr, width, height);
5009 cairo_line_to (cr, 0.0, height);
5013 cairo_move_to (cr, 0.0, 0.0);
5014 cairo_line_to (cr, width, height);
5015 cairo_line_to (cr, 0.0, height);
5017 cairo_close_path (cr);
5020 region = gdk_cairo_region_create_from_surface (surface);
5021 cairo_surface_destroy (surface);
5023 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5027 set_grip_position (GtkWindow *window)
5029 GtkWindowPrivate *priv = window->priv;
5032 if (priv->grip_window == NULL)
5035 gtk_window_get_resize_grip_area (window, &rect);
5036 gdk_window_raise (priv->grip_window);
5037 gdk_window_move_resize (priv->grip_window,
5039 rect.width, rect.height);
5043 gtk_window_size_allocate (GtkWidget *widget,
5044 GtkAllocation *allocation)
5046 GtkWindow *window = GTK_WINDOW (widget);
5047 GtkWindowPrivate *priv = window->priv;
5048 GtkAllocation child_allocation;
5052 gtk_widget_set_allocation (widget, allocation);
5054 child = gtk_bin_get_child (&(window->bin));
5055 if (child && gtk_widget_get_visible (child))
5057 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5058 child_allocation.x = border_width;
5059 child_allocation.y = border_width;
5060 child_allocation.width =
5061 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5062 child_allocation.height =
5063 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5065 gtk_widget_size_allocate (child, &child_allocation);
5068 if (gtk_widget_get_realized (widget))
5071 gdk_window_resize (priv->frame,
5072 allocation->width + priv->frame_left + priv->frame_right,
5073 allocation->height + priv->frame_top + priv->frame_bottom);
5074 set_grip_position (window);
5079 gtk_window_event (GtkWidget *widget, GdkEvent *event)
5081 GtkWindow *window = GTK_WINDOW (widget);
5082 GtkWindowPrivate *priv = window->priv;
5083 gboolean return_val;
5085 if (priv->frame && (event->any.window == priv->frame))
5087 if ((event->type != GDK_KEY_PRESS) &&
5088 (event->type != GDK_KEY_RELEASE) &&
5089 (event->type != GDK_FOCUS_CHANGE))
5091 g_signal_stop_emission_by_name (widget, "event");
5093 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
5098 g_object_unref (event->any.window);
5099 event->any.window = g_object_ref (gtk_widget_get_window (widget));
5107 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
5109 GtkWindowPrivate *priv = window->priv;
5110 GdkEventConfigure *configure_event;
5113 switch (event->type)
5116 configure_event = (GdkEventConfigure *)event;
5118 /* Invalidate the decorations */
5121 rect.width = configure_event->width;
5122 rect.height = configure_event->height;
5124 gdk_window_invalidate_rect (priv->frame, &rect, FALSE);
5126 /* Pass on the (modified) configure event */
5127 configure_event->width -= priv->frame_left + priv->frame_right;
5128 configure_event->height -= priv->frame_top + priv->frame_bottom;
5129 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5138 gtk_window_configure_event (GtkWidget *widget,
5139 GdkEventConfigure *event)
5141 GtkAllocation allocation;
5142 GtkWindow *window = GTK_WINDOW (widget);
5143 GtkWindowPrivate *priv = window->priv;
5144 gboolean expected_reply = priv->configure_request_count > 0;
5146 /* priv->configure_request_count incremented for each
5147 * configure request, and decremented to a min of 0 for
5148 * each configure notify.
5150 * All it means is that we know we will get at least
5151 * priv->configure_request_count more configure notifies.
5152 * We could get more configure notifies than that; some
5153 * of the configure notifies we get may be unrelated to
5154 * the configure requests. But we will get at least
5155 * priv->configure_request_count notifies.
5158 if (priv->configure_request_count > 0)
5160 priv->configure_request_count -= 1;
5161 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5164 /* As an optimization, we avoid a resize when possible.
5166 * The only times we can avoid a resize are:
5167 * - we know only the position changed, not the size
5168 * - we know we have made more requests and so will get more
5169 * notifies and can wait to resize when we get them
5171 gtk_widget_get_allocation (widget, &allocation);
5172 if (!expected_reply &&
5173 (allocation.width == event->width &&
5174 allocation.height == event->height))
5176 gdk_window_configure_finished (gtk_widget_get_window (widget));
5181 * If we do need to resize, we do that by:
5182 * - filling in widget->allocation with the new size
5183 * - setting configure_notify_received to TRUE
5184 * for use in gtk_window_move_resize()
5185 * - queueing a resize, leading to invocation of
5186 * gtk_window_move_resize() in an idle handler
5190 priv->configure_notify_received = TRUE;
5192 allocation.width = event->width;
5193 allocation.height = event->height;
5194 gtk_widget_set_allocation (widget, &allocation);
5196 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5198 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5204 gtk_window_state_event (GtkWidget *widget,
5205 GdkEventWindowState *event)
5207 update_grip_visibility (GTK_WINDOW (widget));
5213 gtk_window_direction_changed (GtkWidget *widget,
5214 GtkTextDirection prev_dir)
5216 GtkWindow *window = GTK_WINDOW (widget);
5218 set_grip_cursor (window);
5219 set_grip_position (window);
5220 set_grip_shape (window);
5224 gtk_window_state_changed (GtkWidget *widget,
5225 GtkStateType previous_state)
5227 GtkWindow *window = GTK_WINDOW (widget);
5229 set_grip_cursor (window);
5230 update_grip_visibility (window);
5234 resize_grip_create_window (GtkWindow *window)
5237 GtkWindowPrivate *priv;
5238 GdkWindowAttr attributes;
5239 gint attributes_mask;
5242 priv = window->priv;
5243 widget = GTK_WIDGET (window);
5245 g_return_if_fail (gtk_widget_get_realized (widget));
5246 g_return_if_fail (priv->grip_window == NULL);
5248 gtk_window_get_resize_grip_area (window, &rect);
5250 attributes.x = rect.x;
5251 attributes.y = rect.y;
5252 attributes.width = rect.width;
5253 attributes.height = rect.height;
5254 attributes.window_type = GDK_WINDOW_CHILD;
5255 attributes.wclass = GDK_INPUT_OUTPUT;
5256 attributes.event_mask = gtk_widget_get_events (widget) |
5258 GDK_BUTTON_PRESS_MASK;
5260 attributes_mask = GDK_WA_X | GDK_WA_Y;
5262 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5266 gdk_window_set_user_data (priv->grip_window, widget);
5268 gdk_window_raise (priv->grip_window);
5270 set_grip_cursor (window);
5271 set_grip_shape (window);
5272 update_grip_visibility (window);
5276 resize_grip_destroy_window (GtkWindow *window)
5278 GtkWindowPrivate *priv = window->priv;
5280 gdk_window_set_user_data (priv->grip_window, NULL);
5281 gdk_window_destroy (priv->grip_window);
5282 priv->grip_window = NULL;
5283 update_grip_visibility (window);
5287 * gtk_window_set_has_resize_grip:
5288 * @window: a #GtkWindow
5289 * @value: %TRUE to allow a resize grip
5291 * Sets whether @window has a corner resize grip.
5293 * Note that the resize grip is only shown if the window
5294 * is actually resizable and not maximized. Use
5295 * gtk_window_resize_grip_is_visible() to find out if the
5296 * resize grip is currently shown.
5301 gtk_window_set_has_resize_grip (GtkWindow *window,
5304 GtkWidget *widget = GTK_WIDGET (window);
5305 GtkWindowPrivate *priv = window->priv;
5307 value = value != FALSE;
5309 if (value != priv->has_resize_grip)
5311 priv->has_resize_grip = value;
5312 gtk_widget_queue_draw (widget);
5314 if (gtk_widget_get_realized (widget))
5316 if (priv->has_resize_grip && priv->grip_window == NULL)
5317 resize_grip_create_window (window);
5318 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5319 resize_grip_destroy_window (window);
5322 g_object_notify (G_OBJECT (window), "has-resize-grip");
5327 update_grip_visibility (GtkWindow *window)
5329 GtkWindowPrivate *priv = window->priv;
5332 val = gtk_window_resize_grip_is_visible (window);
5334 if (priv->grip_window != NULL)
5337 gdk_window_show (priv->grip_window);
5339 gdk_window_hide (priv->grip_window);
5342 if (priv->resize_grip_visible != val)
5344 priv->resize_grip_visible = val;
5346 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5351 * gtk_window_resize_grip_is_visible:
5352 * @window: a #GtkWindow
5354 * Determines whether a resize grip is visible for the specified window.
5356 * Returns %TRUE if a resize grip exists and is visible.
5361 gtk_window_resize_grip_is_visible (GtkWindow *window)
5363 GtkWindowPrivate *priv;
5365 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5367 priv = window->priv;
5369 if (priv->type == GTK_WINDOW_POPUP)
5372 if (!priv->resizable)
5375 if (gtk_widget_get_realized (GTK_WIDGET (window)))
5377 GdkWindowState state;
5379 state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
5381 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5385 return window->priv->has_resize_grip;
5389 * gtk_window_get_has_resize_grip:
5390 * @window: a #GtkWindow
5392 * Determines whether the window may has a resize grip.
5394 * Returns: %TRUE if the window has a resize grip.
5399 gtk_window_get_has_resize_grip (GtkWindow *window)
5401 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5403 return window->priv->has_resize_grip;
5407 * gtk_window_get_resize_grip_area:
5408 * @window: a #GtkWindow
5409 * @rect: a pointer to a #GdkRectangle which we should store the
5412 * If a window has a resize grip, this will retrieve the grip
5413 * position, width and height into the specified #GdkRectangle.
5415 * Returns: %TRUE if the resize grip's area was retrieved.
5420 gtk_window_get_resize_grip_area (GtkWindow *window,
5423 GtkWidget *widget = GTK_WIDGET (window);
5424 GtkAllocation allocation;
5429 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5431 if (!window->priv->has_resize_grip)
5434 gtk_widget_get_allocation (widget, &allocation);
5435 style = gtk_widget_get_style (widget);
5437 gtk_widget_style_get (widget,
5438 "resize-grip-width", &grip_width,
5439 "resize-grip-height", &grip_height,
5442 if (grip_width > allocation.width)
5443 grip_width = allocation.width;
5445 if (grip_height > allocation.height)
5446 grip_height = allocation.height;
5448 rect->width = grip_width;
5449 rect->height = grip_height;
5450 rect->y = allocation.y + allocation.height - grip_height;
5452 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5453 rect->x = allocation.x + allocation.width - grip_width;
5455 rect->x = allocation.x;
5460 /* the accel_key and accel_mods fields of the key have to be setup
5461 * upon calling this function. it'll then return whether that key
5462 * is at all used as accelerator, and if so will OR in the
5463 * accel_flags member of the key.
5466 _gtk_window_query_nonaccels (GtkWindow *window,
5468 GdkModifierType accel_mods)
5470 GtkWindowPrivate *priv;
5472 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5474 priv = window->priv;
5476 /* movement keys are considered locked accels */
5479 static const guint bindings[] = {
5480 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,
5481 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,
5485 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5486 if (bindings[i] == accel_key)
5490 /* mnemonics are considered locked accels */
5491 if (accel_mods == priv->mnemonic_modifier)
5493 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5494 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5502 * gtk_window_propagate_key_event:
5503 * @window: a #GtkWindow
5504 * @event: a #GdkEventKey
5506 * Propagate a key press or release event to the focus widget and
5507 * up the focus container chain until a widget handles @event.
5508 * This is normally called by the default ::key_press_event and
5509 * ::key_release_event handlers for toplevel windows,
5510 * however in some cases it may be useful to call this directly when
5511 * overriding the standard key handling for a toplevel window.
5513 * Return value: %TRUE if a widget in the focus chain handled the event.
5518 gtk_window_propagate_key_event (GtkWindow *window,
5521 GtkWindowPrivate *priv;
5522 gboolean handled = FALSE;
5523 GtkWidget *widget, *focus;
5525 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5527 priv = window->priv;
5528 widget = GTK_WIDGET (window);
5530 focus = priv->focus_widget;
5532 g_object_ref (focus);
5535 focus && focus != widget &&
5536 gtk_widget_get_toplevel (focus) == widget)
5540 if (gtk_widget_is_sensitive (focus))
5541 handled = gtk_widget_event (focus, (GdkEvent*) event);
5543 parent = gtk_widget_get_parent (focus);
5545 g_object_ref (parent);
5547 g_object_unref (focus);
5553 g_object_unref (focus);
5559 gtk_window_key_press_event (GtkWidget *widget,
5562 GtkWindow *window = GTK_WINDOW (widget);
5563 gboolean handled = FALSE;
5565 /* handle mnemonics and accelerators */
5567 handled = gtk_window_activate_key (window, event);
5569 /* handle focus widget key events */
5571 handled = gtk_window_propagate_key_event (window, event);
5573 /* Chain up, invokes binding set */
5575 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5581 gtk_window_key_release_event (GtkWidget *widget,
5584 GtkWindow *window = GTK_WINDOW (widget);
5585 gboolean handled = FALSE;
5587 /* handle focus widget key events */
5589 handled = gtk_window_propagate_key_event (window, event);
5591 /* Chain up, invokes binding set */
5593 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5599 gtk_window_button_press_event (GtkWidget *widget,
5600 GdkEventButton *event)
5602 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5604 if (event->window == priv->grip_window)
5605 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5606 get_grip_edge (widget),
5616 gtk_window_real_activate_default (GtkWindow *window)
5618 gtk_window_activate_default (window);
5622 gtk_window_real_activate_focus (GtkWindow *window)
5624 gtk_window_activate_focus (window);
5628 gtk_window_move_focus (GtkWindow *window,
5629 GtkDirectionType dir)
5631 gtk_widget_child_focus (GTK_WIDGET (window), dir);
5633 if (!gtk_container_get_focus_child (GTK_CONTAINER (window)))
5634 gtk_window_set_focus (window, NULL);
5638 gtk_window_enter_notify_event (GtkWidget *widget,
5639 GdkEventCrossing *event)
5645 gtk_window_leave_notify_event (GtkWidget *widget,
5646 GdkEventCrossing *event)
5652 do_focus_change (GtkWidget *widget,
5656 GdkDeviceManager *device_manager;
5659 g_object_ref (widget);
5661 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5662 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5663 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5664 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5666 for (d = devices; d; d = d->next)
5668 GdkDevice *dev = d->data;
5671 if (dev->source != GDK_SOURCE_KEYBOARD)
5674 /* Skip non-master keyboards that haven't
5675 * selected for events from this window
5677 window = gtk_widget_get_window (widget);
5678 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5679 window && !gdk_window_get_device_events (window, dev))
5682 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5684 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5685 fevent->focus_change.window = window;
5687 g_object_ref (window);
5688 fevent->focus_change.in = in;
5689 gdk_event_set_device (fevent, dev);
5691 gtk_widget_send_focus_change (widget, fevent);
5693 gdk_event_free (fevent);
5696 g_list_free (devices);
5697 g_object_unref (widget);
5701 gtk_window_focus_in_event (GtkWidget *widget,
5702 GdkEventFocus *event)
5704 GtkWindow *window = GTK_WINDOW (widget);
5706 /* It appears spurious focus in events can occur when
5707 * the window is hidden. So we'll just check to see if
5708 * the window is visible before actually handling the
5711 if (gtk_widget_get_visible (widget))
5713 _gtk_window_set_has_toplevel_focus (window, TRUE);
5714 _gtk_window_set_is_active (window, TRUE);
5721 gtk_window_focus_out_event (GtkWidget *widget,
5722 GdkEventFocus *event)
5724 GtkWindow *window = GTK_WINDOW (widget);
5725 gboolean auto_mnemonics;
5727 _gtk_window_set_has_toplevel_focus (window, FALSE);
5728 _gtk_window_set_is_active (window, FALSE);
5730 /* set the mnemonic-visible property to false */
5731 g_object_get (gtk_widget_get_settings (widget),
5732 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5734 gtk_window_set_mnemonics_visible (window, FALSE);
5739 static GdkAtom atom_rcfiles = GDK_NONE;
5740 static GdkAtom atom_iconthemes = GDK_NONE;
5743 send_client_message_to_embedded_windows (GtkWidget *widget,
5744 GdkAtom message_type)
5746 GList *embedded_windows;
5748 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5749 if (embedded_windows)
5751 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5754 for (i = 0; i < 5; i++)
5755 send_event->client.data.l[i] = 0;
5756 send_event->client.data_format = 32;
5757 send_event->client.message_type = message_type;
5759 while (embedded_windows)
5761 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5762 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5763 embedded_windows = embedded_windows->next;
5766 gdk_event_free (send_event);
5771 gtk_window_client_event (GtkWidget *widget,
5772 GdkEventClient *event)
5776 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5777 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5780 if (event->message_type == atom_rcfiles)
5782 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5783 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5786 if (event->message_type == atom_iconthemes)
5788 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5789 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5796 gtk_window_check_resize (GtkContainer *container)
5798 if (gtk_widget_get_visible (GTK_WIDGET (container)))
5799 gtk_window_move_resize (GTK_WINDOW (container));
5803 gtk_window_focus (GtkWidget *widget,
5804 GtkDirectionType direction)
5806 GtkWindowPrivate *priv;
5809 GtkContainer *container;
5811 GtkWidget *old_focus_child;
5814 container = GTK_CONTAINER (widget);
5815 window = GTK_WINDOW (widget);
5816 priv = window->priv;
5817 bin = GTK_BIN (widget);
5819 old_focus_child = gtk_container_get_focus_child (container);
5821 /* We need a special implementation here to deal properly with wrapping
5822 * around in the tab chain without the danger of going into an
5825 if (old_focus_child)
5827 if (gtk_widget_child_focus (old_focus_child, direction))
5831 if (priv->focus_widget)
5833 if (direction == GTK_DIR_LEFT ||
5834 direction == GTK_DIR_RIGHT ||
5835 direction == GTK_DIR_UP ||
5836 direction == GTK_DIR_DOWN)
5841 /* Wrapped off the end, clear the focus setting for the toplpevel */
5842 parent = gtk_widget_get_parent (priv->focus_widget);
5845 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5846 parent = gtk_widget_get_parent (parent);
5849 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5852 /* Now try to focus the first widget in the window */
5853 child = gtk_bin_get_child (bin);
5856 if (gtk_widget_child_focus (child, direction))
5864 gtk_window_real_set_focus (GtkWindow *window,
5867 GtkWindowPrivate *priv = window->priv;
5868 GtkWidget *old_focus = priv->focus_widget;
5869 gboolean had_default = FALSE;
5870 gboolean focus_had_default = FALSE;
5871 gboolean old_focus_had_default = FALSE;
5875 g_object_ref (old_focus);
5876 g_object_freeze_notify (G_OBJECT (old_focus));
5877 old_focus_had_default = gtk_widget_has_default (old_focus);
5881 g_object_ref (focus);
5882 g_object_freeze_notify (G_OBJECT (focus));
5883 focus_had_default = gtk_widget_has_default (focus);
5886 if (priv->default_widget)
5887 had_default = gtk_widget_has_default (priv->default_widget);
5889 if (priv->focus_widget)
5891 if (gtk_widget_get_receives_default (priv->focus_widget) &&
5892 (priv->focus_widget != priv->default_widget))
5894 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
5895 gtk_widget_queue_draw (priv->focus_widget);
5897 if (priv->default_widget)
5898 _gtk_widget_set_has_default (priv->default_widget, TRUE);
5901 priv->focus_widget = NULL;
5903 if (priv->has_focus)
5904 do_focus_change (old_focus, FALSE);
5906 g_object_notify (G_OBJECT (old_focus), "is-focus");
5909 /* The above notifications may have set a new focus widget,
5910 * if so, we don't want to override it.
5912 if (focus && !priv->focus_widget)
5914 priv->focus_widget = focus;
5916 if (gtk_widget_get_receives_default (priv->focus_widget) &&
5917 (priv->focus_widget != priv->default_widget))
5919 if (gtk_widget_get_can_default (priv->focus_widget))
5920 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
5922 if (priv->default_widget)
5923 _gtk_widget_set_has_default (priv->default_widget, FALSE);
5926 if (priv->has_focus)
5927 do_focus_change (priv->focus_widget, TRUE);
5929 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
5932 /* If the default widget changed, a redraw will have been queued
5933 * on the old and new default widgets by gtk_window_set_default(), so
5934 * we only have to worry about the case where it didn't change.
5935 * We'll sometimes queue a draw twice on the new widget but that
5938 if (priv->default_widget &&
5939 (had_default != gtk_widget_has_default (priv->default_widget)))
5940 gtk_widget_queue_draw (priv->default_widget);
5944 if (old_focus_had_default != gtk_widget_has_default (old_focus))
5945 gtk_widget_queue_draw (old_focus);
5947 g_object_thaw_notify (G_OBJECT (old_focus));
5948 g_object_unref (old_focus);
5952 if (focus_had_default != gtk_widget_has_default (focus))
5953 gtk_widget_queue_draw (focus);
5955 g_object_thaw_notify (G_OBJECT (focus));
5956 g_object_unref (focus);
5962 gtk_window_get_preferred_width (GtkWidget *widget,
5970 window = GTK_WINDOW (widget);
5971 child = gtk_bin_get_child (GTK_BIN (window));
5973 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5974 *minimum_size = border_width * 2;
5975 *natural_size = border_width * 2;
5977 if (child && gtk_widget_get_visible (child))
5979 gint child_min, child_nat;
5980 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
5982 *minimum_size += child_min;
5983 *natural_size += child_nat;
5988 gtk_window_get_preferred_height (GtkWidget *widget,
5996 window = GTK_WINDOW (widget);
5997 child = gtk_bin_get_child (GTK_BIN (window));
5999 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6000 *minimum_size = border_width * 2;
6001 *natural_size = border_width * 2;
6003 if (child && gtk_widget_get_visible (child))
6005 gint child_min, child_nat;
6006 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6008 *minimum_size += child_min;
6009 *natural_size += child_nat;
6015 * _gtk_window_unset_focus_and_default:
6016 * @window: a #GtkWindow
6017 * @widget: a widget inside of @window
6019 * Checks whether the focus and default widgets of @window are
6020 * @widget or a descendent of @widget, and if so, unset them.
6023 _gtk_window_unset_focus_and_default (GtkWindow *window,
6027 GtkWindowPrivate *priv = window->priv;
6031 g_object_ref (window);
6032 g_object_ref (widget);
6034 parent = gtk_widget_get_parent (widget);
6035 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6037 child = priv->focus_widget;
6039 while (child && child != widget)
6040 child = gtk_widget_get_parent (child);
6042 if (child == widget)
6043 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6046 child = priv->default_widget;
6048 while (child && child != widget)
6049 child = gtk_widget_get_parent (child);
6051 if (child == widget)
6052 gtk_window_set_default (window, NULL);
6054 g_object_unref (widget);
6055 g_object_unref (window);
6058 /*********************************
6059 * Functions related to resizing *
6060 *********************************/
6062 /* This function doesn't constrain to geometry hints */
6064 gtk_window_compute_configure_request_size (GtkWindow *window,
6068 GtkWindowPrivate *priv = window->priv;
6069 GtkRequisition requisition;
6070 GtkWindowGeometryInfo *info;
6074 * - we've done a size request
6077 widget = GTK_WIDGET (window);
6079 info = gtk_window_get_geometry_info (window, FALSE);
6081 if (priv->need_default_size)
6083 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6085 /* Default to requisition */
6086 *width = requisition.width;
6087 *height = requisition.height;
6089 /* If window is empty so requests 0, default to random nonzero size */
6090 if (*width == 0 && *height == 0)
6096 /* Override requisition with default size */
6100 gint base_width = 0;
6101 gint base_height = 0;
6103 gint min_height = 0;
6105 gint height_inc = 1;
6107 if (info->default_is_geometry &&
6108 (info->default_width > 0 || info->default_height > 0))
6110 GdkGeometry geometry;
6113 gtk_window_compute_hints (window, &geometry, &flags);
6115 if (flags & GDK_HINT_BASE_SIZE)
6117 base_width = geometry.base_width;
6118 base_height = geometry.base_height;
6120 if (flags & GDK_HINT_MIN_SIZE)
6122 min_width = geometry.min_width;
6123 min_height = geometry.min_height;
6125 if (flags & GDK_HINT_RESIZE_INC)
6127 width_inc = geometry.width_inc;
6128 height_inc = geometry.height_inc;
6132 if (info->default_width > 0)
6133 *width = MAX (info->default_width * width_inc + base_width, min_width);
6135 if (info->default_height > 0)
6136 *height = MAX (info->default_height * height_inc + base_height, min_height);
6141 GtkAllocation allocation;
6143 gtk_widget_get_allocation (widget, &allocation);
6145 /* Default to keeping current size */
6146 *width = allocation.width;
6147 *height = allocation.height;
6150 /* Override any size with gtk_window_resize() values */
6153 if (info->resize_width > 0)
6154 *width = info->resize_width;
6156 if (info->resize_height > 0)
6157 *height = info->resize_height;
6160 /* Don't ever request zero width or height, its not supported by
6161 gdk. The size allocation code will round it to 1 anyway but if
6162 we do it then the value returned from this function will is
6163 not comparable to the size allocation read from the GtkWindow. */
6164 *width = MAX (*width, 1);
6165 *height = MAX (*height, 1);
6168 static GtkWindowPosition
6169 get_effective_position (GtkWindow *window)
6171 GtkWindowPrivate *priv = window->priv;
6172 GtkWindowPosition pos = priv->position;
6174 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6175 (priv->transient_parent == NULL ||
6176 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6177 pos = GTK_WIN_POS_NONE;
6183 get_center_monitor_of_window (GtkWindow *window)
6185 /* We could try to sort out the relative positions of the monitors and
6186 * stuff, or we could just be losers and assume you have a row
6187 * or column of monitors.
6189 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6193 get_monitor_containing_pointer (GtkWindow *window)
6197 GdkScreen *window_screen;
6198 GdkScreen *pointer_screen;
6199 GdkDisplay *display;
6200 GdkDeviceManager *device_manager;
6203 window_screen = gtk_window_check_screen (window);
6204 display = gdk_screen_get_display (window_screen);
6205 device_manager = gdk_display_get_device_manager (display);
6206 pointer = gdk_device_manager_get_client_pointer (device_manager);
6208 gdk_display_get_device_state (display, pointer,
6212 if (pointer_screen == window_screen)
6213 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6221 center_window_on_monitor (GtkWindow *window,
6227 GdkRectangle monitor;
6230 monitor_num = get_monitor_containing_pointer (window);
6232 if (monitor_num == -1)
6233 monitor_num = get_center_monitor_of_window (window);
6235 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6236 monitor_num, &monitor);
6238 *x = (monitor.width - w) / 2 + monitor.x;
6239 *y = (monitor.height - h) / 2 + monitor.y;
6241 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6242 * and WM decorations.
6256 if (extent > clamp_extent)
6258 *base = clamp_base + clamp_extent/2 - extent/2;
6259 else if (*base < clamp_base)
6261 else if (*base + extent > clamp_base + clamp_extent)
6262 *base = clamp_base + clamp_extent - extent;
6266 clamp_window_to_rectangle (gint *x,
6270 const GdkRectangle *rect)
6272 #ifdef DEBUGGING_OUTPUT
6273 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);
6276 /* If it is too large, center it. If it fits on the monitor but is
6277 * partially outside, move it to the closest edge. Do this
6278 * separately in x and y directions.
6280 clamp (x, w, rect->x, rect->width);
6281 clamp (y, h, rect->y, rect->height);
6282 #ifdef DEBUGGING_OUTPUT
6283 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6289 gtk_window_compute_configure_request (GtkWindow *window,
6290 GdkRectangle *request,
6291 GdkGeometry *geometry,
6294 GtkWindowPrivate *priv = window->priv;
6295 GdkGeometry new_geometry;
6299 GtkWindowPosition pos;
6300 GtkWidget *parent_widget;
6301 GtkWindowGeometryInfo *info;
6305 widget = GTK_WIDGET (window);
6307 screen = gtk_window_check_screen (window);
6309 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
6311 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6312 gtk_window_constrain_size (window,
6313 &new_geometry, new_flags,
6317 parent_widget = (GtkWidget*) priv->transient_parent;
6319 pos = get_effective_position (window);
6320 info = gtk_window_get_geometry_info (window, FALSE);
6322 /* by default, don't change position requested */
6325 x = info->last.configure_request.x;
6326 y = info->last.configure_request.y;
6335 if (priv->need_default_position)
6338 /* FIXME this all interrelates with window gravity.
6339 * For most of them I think we want to set GRAVITY_CENTER.
6341 * Not sure how to go about that.
6346 /* here we are only handling CENTER_ALWAYS
6347 * as it relates to default positioning,
6348 * where it's equivalent to simply CENTER
6350 case GTK_WIN_POS_CENTER_ALWAYS:
6351 case GTK_WIN_POS_CENTER:
6352 center_window_on_monitor (window, w, h, &x, &y);
6355 case GTK_WIN_POS_CENTER_ON_PARENT:
6357 GtkAllocation allocation;
6358 GdkWindow *gdk_window;
6360 GdkRectangle monitor;
6363 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6365 gdk_window = gtk_widget_get_window (parent_widget);
6367 if (gdk_window != NULL)
6368 monitor_num = gdk_screen_get_monitor_at_window (screen,
6373 gdk_window_get_origin (gdk_window,
6376 gtk_widget_get_allocation (parent_widget, &allocation);
6377 x = ox + (allocation.width - w) / 2;
6378 y = oy + (allocation.height - h) / 2;
6380 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6381 * WM decorations. If parent wasn't on a monitor, just
6384 if (monitor_num >= 0)
6386 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6387 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6392 case GTK_WIN_POS_MOUSE:
6394 gint screen_width = gdk_screen_get_width (screen);
6395 gint screen_height = gdk_screen_get_height (screen);
6397 GdkRectangle monitor;
6398 GdkDisplay *display;
6399 GdkDeviceManager *device_manager;
6401 GdkScreen *pointer_screen;
6404 display = gdk_screen_get_display (screen);
6405 device_manager = gdk_display_get_device_manager (display);
6406 pointer = gdk_device_manager_get_client_pointer (device_manager);
6408 gdk_display_get_device_state (display, pointer,
6412 if (pointer_screen == screen)
6413 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6419 x = CLAMP (x, 0, screen_width - w);
6420 y = CLAMP (y, 0, screen_height - h);
6422 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6423 * WM decorations. Don't try to figure out what's going
6424 * on if the mouse wasn't inside a monitor.
6426 if (monitor_num >= 0)
6428 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6429 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6437 } /* if (priv->need_default_position) */
6439 if (priv->need_default_position && info &&
6440 info->initial_pos_set)
6442 x = info->initial_x;
6443 y = info->initial_y;
6444 gtk_window_constrain_position (window, w, h, &x, &y);
6450 request->height = h;
6453 *geometry = new_geometry;
6459 gtk_window_constrain_position (GtkWindow *window,
6465 GtkWindowPrivate *priv = window->priv;
6467 /* See long comments in gtk_window_move_resize()
6468 * on when it's safe to call this function.
6470 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6472 gint center_x, center_y;
6474 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6482 gtk_window_move_resize (GtkWindow *window)
6486 * First we determine whether any information has changed that would
6487 * cause us to revise our last configure request. If we would send
6488 * a different configure request from last time, then
6489 * configure_request_size_changed = TRUE or
6490 * configure_request_pos_changed = TRUE. configure_request_size_changed
6491 * may be true due to new hints, a gtk_window_resize(), or whatever.
6492 * configure_request_pos_changed may be true due to gtk_window_set_position()
6493 * or gtk_window_move().
6495 * If the configure request has changed, we send off a new one. To
6496 * ensure GTK+ invariants are maintained (resize queue does what it
6497 * should), we go ahead and size_allocate the requested size in this
6500 * If the configure request has not changed, we don't ever resend
6501 * it, because it could mean fighting the user or window manager.
6504 * To prepare the configure request, we come up with a base size/pos:
6505 * - the one from gtk_window_move()/gtk_window_resize()
6506 * - else default_width, default_height if we haven't ever
6508 * - else the size request if we haven't ever been mapped,
6509 * as a substitute default size
6510 * - else the current size of the window, as received from
6511 * configure notifies (i.e. the current allocation)
6513 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6514 * the position request to be centered.
6516 GtkWindowPrivate *priv = window->priv;
6517 GtkAllocation allocation;
6519 GtkContainer *container;
6520 GtkWindowGeometryInfo *info;
6521 GdkGeometry new_geometry;
6522 GdkWindow *gdk_window;
6524 GdkRectangle new_request;
6525 gboolean configure_request_size_changed;
6526 gboolean configure_request_pos_changed;
6527 gboolean hints_changed; /* do we need to send these again */
6528 GtkWindowLastGeometryInfo saved_last_info;
6530 widget = GTK_WIDGET (window);
6531 gdk_window = gtk_widget_get_window (widget);
6532 container = GTK_CONTAINER (widget);
6533 info = gtk_window_get_geometry_info (window, TRUE);
6535 configure_request_size_changed = FALSE;
6536 configure_request_pos_changed = FALSE;
6538 gtk_window_compute_configure_request (window, &new_request,
6539 &new_geometry, &new_flags);
6541 /* This check implies the invariant that we never set info->last
6542 * without setting the hints and sending off a configure request.
6544 * If we change info->last without sending the request, we may
6547 if (info->last.configure_request.x != new_request.x ||
6548 info->last.configure_request.y != new_request.y)
6549 configure_request_pos_changed = TRUE;
6551 if ((info->last.configure_request.width != new_request.width ||
6552 info->last.configure_request.height != new_request.height))
6553 configure_request_size_changed = TRUE;
6555 hints_changed = FALSE;
6557 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6558 &new_geometry, new_flags))
6560 hints_changed = TRUE;
6563 /* Position Constraints
6564 * ====================
6566 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6567 * a default. The other POS_ values are used only when the
6568 * window is shown, not after that.
6570 * However, we can't implement a position constraint as
6571 * "anytime the window size changes, center the window"
6572 * because this may well end up fighting the WM or user. In
6573 * fact it gets in an infinite loop with at least one WM.
6575 * Basically, applications are in no way in a position to
6576 * constrain the position of a window, with one exception:
6577 * override redirect windows. (Really the intended purpose
6578 * of CENTER_ALWAYS anyhow, I would think.)
6580 * So the way we implement this "constraint" is to say that when WE
6581 * cause a move or resize, i.e. we make a configure request changing
6582 * window size, we recompute the CENTER_ALWAYS position to reflect
6583 * the new window size, and include it in our request. Also, if we
6584 * just turned on CENTER_ALWAYS we snap to center with a new
6585 * request. Otherwise, if we are just NOTIFIED of a move or resize
6586 * done by someone else e.g. the window manager, we do NOT send a
6587 * new configure request.
6589 * For override redirect windows, this works fine; all window
6590 * sizes are from our configure requests. For managed windows,
6591 * it is at least semi-sane, though who knows what the
6592 * app author is thinking.
6595 /* This condition should be kept in sync with the condition later on
6596 * that determines whether we send a configure request. i.e. we
6597 * should do this position constraining anytime we were going to
6598 * send a configure request anyhow, plus when constraints have
6601 if (configure_request_pos_changed ||
6602 configure_request_size_changed ||
6604 info->position_constraints_changed)
6606 /* We request the constrained position if:
6607 * - we were changing position, and need to clamp
6608 * the change to the constraint
6609 * - we're changing the size anyway
6610 * - set_position() was called to toggle CENTER_ALWAYS on
6613 gtk_window_constrain_position (window,
6619 /* Update whether we need to request a move */
6620 if (info->last.configure_request.x != new_request.x ||
6621 info->last.configure_request.y != new_request.y)
6622 configure_request_pos_changed = TRUE;
6624 configure_request_pos_changed = FALSE;
6628 if (priv->type == GTK_WINDOW_TOPLEVEL)
6630 int notify_x, notify_y;
6632 /* this is the position from the last configure notify */
6633 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6635 g_message ("--- %s ---\n"
6636 "last : %d,%d\t%d x %d\n"
6637 "this : %d,%d\t%d x %d\n"
6638 "alloc : %d,%d\t%d x %d\n"
6640 "resize: \t%d x %d\n"
6641 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6642 "configure_notify_received: %d\n"
6643 "configure_request_count: %d\n"
6644 "position_constraints_changed: %d\n",
6645 priv->title ? priv->title : "(no title)",
6646 info->last.configure_request.x,
6647 info->last.configure_request.y,
6648 info->last.configure_request.width,
6649 info->last.configure_request.height,
6655 widget->allocation.width,
6656 widget->allocation.height,
6657 widget->requisition.width,
6658 widget->requisition.height,
6660 info->resize_height,
6661 configure_request_pos_changed,
6662 configure_request_size_changed,
6664 priv->configure_notify_received,
6665 priv->configure_request_count,
6666 info->position_constraints_changed);
6670 saved_last_info = info->last;
6671 info->last.geometry = new_geometry;
6672 info->last.flags = new_flags;
6673 info->last.configure_request = new_request;
6675 /* need to set PPosition so the WM will look at our position,
6676 * but we don't want to count PPosition coming and going as a hints
6677 * change for future iterations. So we saved info->last prior to
6681 /* Also, if the initial position was explicitly set, then we always
6682 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6686 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6687 * this is an initial map
6690 if ((configure_request_pos_changed ||
6691 info->initial_pos_set ||
6692 (priv->need_default_position &&
6693 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6694 (new_flags & GDK_HINT_POS) == 0)
6696 new_flags |= GDK_HINT_POS;
6697 hints_changed = TRUE;
6700 /* Set hints if necessary
6703 gdk_window_set_geometry_hints (gdk_window,
6707 gtk_widget_get_allocation (widget, &allocation);
6709 /* handle resizing/moving and widget tree allocation
6711 if (priv->configure_notify_received)
6713 /* If we have received a configure event since
6714 * the last time in this function, we need to
6715 * accept our new size and size_allocate child widgets.
6716 * (see gtk_window_configure_event() for more details).
6718 * 1 or more configure notifies may have been received.
6719 * Also, configure_notify_received will only be TRUE
6720 * if all expected configure notifies have been received
6721 * (one per configure request), as an optimization.
6724 priv->configure_notify_received = FALSE;
6726 /* gtk_window_configure_event() filled in widget->allocation */
6727 gtk_widget_size_allocate (widget, &allocation);
6729 set_grip_position (window);
6730 set_grip_cursor (window);
6731 set_grip_shape (window);
6733 gdk_window_process_updates (gdk_window, TRUE);
6735 gdk_window_configure_finished (gdk_window);
6737 /* If the configure request changed, it means that
6739 * 1) coincidentally changed hints or widget properties
6740 * impacting the configure request before getting
6741 * a configure notify, or
6742 * 2) some broken widget is changing its size request
6743 * during size allocation, resulting in
6744 * a false appearance of changed configure request.
6746 * For 1), we could just go ahead and ask for the
6747 * new size right now, but doing that for 2)
6748 * might well be fighting the user (and can even
6749 * trigger a loop). Since we really don't want to
6750 * do that, we requeue a resize in hopes that
6751 * by the time it gets handled, the child has seen
6752 * the light and is willing to go along with the
6753 * new size. (this happens for the zvt widget, since
6754 * the size_allocate() above will have stored the
6755 * requisition corresponding to the new size in the
6758 * This doesn't buy us anything for 1), but it shouldn't
6759 * hurt us too badly, since it is what would have
6760 * happened if we had gotten the configure event before
6761 * the new size had been set.
6764 if (configure_request_size_changed ||
6765 configure_request_pos_changed)
6767 /* Don't change the recorded last info after all, because we
6768 * haven't actually updated to the new info yet - we decided
6769 * to postpone our configure request until later.
6771 info->last = saved_last_info;
6773 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6776 return; /* Bail out, we didn't really process the move/resize */
6778 else if ((configure_request_size_changed || hints_changed) &&
6779 (allocation.width != new_request.width || allocation.height != new_request.height))
6782 /* We are in one of the following situations:
6783 * A. configure_request_size_changed
6784 * our requisition has changed and we need a different window size,
6785 * so we request it from the window manager.
6786 * B. !configure_request_size_changed && hints_changed
6787 * the window manager rejects our size, but we have just changed the
6788 * window manager hints, so there's a chance our request will
6789 * be honoured this time, so we try again.
6791 * However, if the new requisition is the same as the current allocation,
6792 * we don't request it again, since we won't get a ConfigureNotify back from
6793 * the window manager unless it decides to change our requisition. If
6794 * we don't get the ConfigureNotify back, the resize queue will never be run.
6797 /* Now send the configure request */
6798 if (configure_request_pos_changed)
6802 gdk_window_move_resize (priv->frame,
6803 new_request.x - priv->frame_left,
6804 new_request.y - priv->frame_top,
6805 new_request.width + priv->frame_left + priv->frame_right,
6806 new_request.height + priv->frame_top + priv->frame_bottom);
6807 gdk_window_resize (gdk_window,
6808 new_request.width, new_request.height);
6811 gdk_window_move_resize (gdk_window,
6812 new_request.x, new_request.y,
6813 new_request.width, new_request.height);
6815 else /* only size changed */
6818 gdk_window_resize (priv->frame,
6819 new_request.width + priv->frame_left + priv->frame_right,
6820 new_request.height + priv->frame_top + priv->frame_bottom);
6821 gdk_window_resize (gdk_window,
6822 new_request.width, new_request.height);
6825 if (priv->type == GTK_WINDOW_POPUP)
6827 GtkAllocation allocation;
6829 /* Directly size allocate for override redirect (popup) windows. */
6832 allocation.width = new_request.width;
6833 allocation.height = new_request.height;
6835 gtk_widget_size_allocate (widget, &allocation);
6837 gdk_window_process_updates (gdk_window, TRUE);
6839 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6840 gtk_widget_queue_draw (widget);
6844 /* Increment the number of have-not-yet-received-notify requests */
6845 priv->configure_request_count += 1;
6846 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
6848 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6849 * configure event in response to our resizing request.
6850 * the configure event will cause a new resize with
6851 * ->configure_notify_received=TRUE.
6852 * until then, we want to
6853 * - discard expose events
6854 * - coalesce resizes for our children
6855 * - defer any window resizes until the configure event arrived
6856 * to achieve this, we queue a resize for the window, but remove its
6857 * resizing handler, so resizing will not be handled from the next
6858 * idle handler but when the configure event arrives.
6860 * FIXME: we should also dequeue the pending redraws here, since
6861 * we handle those ourselves upon ->configure_notify_received==TRUE.
6863 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6865 gtk_widget_queue_resize_no_redraw (widget);
6866 _gtk_container_dequeue_resize_handler (container);
6872 /* Handle any position changes.
6874 if (configure_request_pos_changed)
6878 gdk_window_move (priv->frame,
6879 new_request.x - priv->frame_left,
6880 new_request.y - priv->frame_top);
6883 gdk_window_move (gdk_window,
6884 new_request.x, new_request.y);
6887 /* And run the resize queue.
6889 gtk_container_resize_children (container);
6892 /* We have now processed a move/resize since the last position
6893 * constraint change, setting of the initial position, or resize.
6894 * (Not resetting these flags here can lead to infinite loops for
6895 * GTK_RESIZE_IMMEDIATE containers)
6897 info->position_constraints_changed = FALSE;
6898 info->initial_pos_set = FALSE;
6899 info->resize_width = -1;
6900 info->resize_height = -1;
6903 /* Compare two sets of Geometry hints for equality.
6906 gtk_window_compare_hints (GdkGeometry *geometry_a,
6908 GdkGeometry *geometry_b,
6911 if (flags_a != flags_b)
6914 if ((flags_a & GDK_HINT_MIN_SIZE) &&
6915 (geometry_a->min_width != geometry_b->min_width ||
6916 geometry_a->min_height != geometry_b->min_height))
6919 if ((flags_a & GDK_HINT_MAX_SIZE) &&
6920 (geometry_a->max_width != geometry_b->max_width ||
6921 geometry_a->max_height != geometry_b->max_height))
6924 if ((flags_a & GDK_HINT_BASE_SIZE) &&
6925 (geometry_a->base_width != geometry_b->base_width ||
6926 geometry_a->base_height != geometry_b->base_height))
6929 if ((flags_a & GDK_HINT_ASPECT) &&
6930 (geometry_a->min_aspect != geometry_b->min_aspect ||
6931 geometry_a->max_aspect != geometry_b->max_aspect))
6934 if ((flags_a & GDK_HINT_RESIZE_INC) &&
6935 (geometry_a->width_inc != geometry_b->width_inc ||
6936 geometry_a->height_inc != geometry_b->height_inc))
6939 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
6940 geometry_a->win_gravity != geometry_b->win_gravity)
6947 _gtk_window_constrain_size (GtkWindow *window,
6953 GtkWindowPrivate *priv;
6954 GtkWindowGeometryInfo *info;
6956 g_return_if_fail (GTK_IS_WINDOW (window));
6958 priv = window->priv;
6960 info = priv->geometry_info;
6963 GdkWindowHints flags = info->last.flags;
6964 GdkGeometry *geometry = &info->last.geometry;
6966 gtk_window_constrain_size (window,
6977 gtk_window_constrain_size (GtkWindow *window,
6978 GdkGeometry *geometry,
6985 gdk_window_constrain_size (geometry, flags, width, height,
6986 new_width, new_height);
6989 /* Compute the set of geometry hints and flags for a window
6990 * based on the application set geometry, and requisition
6991 * of the window. gtk_widget_get_preferred_size() must have been
6995 gtk_window_compute_hints (GtkWindow *window,
6996 GdkGeometry *new_geometry,
6999 GtkWindowPrivate *priv = window->priv;
7001 gint extra_width = 0;
7002 gint extra_height = 0;
7003 GtkWindowGeometryInfo *geometry_info;
7004 GtkRequisition requisition;
7006 widget = GTK_WIDGET (window);
7008 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7009 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7013 *new_flags = geometry_info->mask;
7014 *new_geometry = geometry_info->geometry;
7021 if (geometry_info && geometry_info->widget)
7023 GtkRequisition requisition;
7024 GtkRequisition child_requisition;
7026 /* FIXME: This really isn't right. It gets the min size wrong and forces
7027 * callers to do horrible hacks like set a huge usize on the child requisition
7028 * to get the base size right. We really want to find the answers to:
7030 * - If the geometry widget was infinitely big, how much extra space
7031 * would be needed for the stuff around it.
7033 * - If the geometry widget was infinitely small, how big would the
7034 * window still have to be.
7036 * Finding these answers would be a bit of a mess here. (Bug #68668)
7038 gtk_widget_get_preferred_size (geometry_info->widget,
7039 &child_requisition, NULL);
7041 gtk_widget_get_preferred_size (widget,
7042 &requisition, NULL);
7043 extra_width = requisition.width - child_requisition.width;
7044 extra_height = requisition.height - child_requisition.height;
7047 /* We don't want to set GDK_HINT_POS in here, we just set it
7048 * in gtk_window_move_resize() when we want the position
7052 if (*new_flags & GDK_HINT_BASE_SIZE)
7054 new_geometry->base_width += extra_width;
7055 new_geometry->base_height += extra_height;
7057 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
7058 (*new_flags & GDK_HINT_RESIZE_INC) &&
7059 ((extra_width != 0) || (extra_height != 0)))
7061 *new_flags |= GDK_HINT_BASE_SIZE;
7063 new_geometry->base_width = extra_width;
7064 new_geometry->base_height = extra_height;
7067 if (*new_flags & GDK_HINT_MIN_SIZE)
7069 if (new_geometry->min_width < 0)
7070 new_geometry->min_width = requisition.width;
7072 new_geometry->min_width += extra_width;
7074 if (new_geometry->min_height < 0)
7075 new_geometry->min_height = requisition.height;
7077 new_geometry->min_height += extra_height;
7081 *new_flags |= GDK_HINT_MIN_SIZE;
7083 new_geometry->min_width = requisition.width;
7084 new_geometry->min_height = requisition.height;
7087 if (*new_flags & GDK_HINT_MAX_SIZE)
7089 if (new_geometry->max_width < 0)
7090 new_geometry->max_width = requisition.width;
7092 new_geometry->max_width += extra_width;
7094 if (new_geometry->max_height < 0)
7095 new_geometry->max_height = requisition.height;
7097 new_geometry->max_height += extra_height;
7099 else if (!priv->resizable)
7101 *new_flags |= GDK_HINT_MAX_SIZE;
7103 new_geometry->max_width = requisition.width;
7104 new_geometry->max_height = requisition.height;
7107 *new_flags |= GDK_HINT_WIN_GRAVITY;
7108 new_geometry->win_gravity = priv->gravity;
7111 /***********************
7112 * Redrawing functions *
7113 ***********************/
7116 gtk_window_draw (GtkWidget *widget,
7119 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7120 gboolean ret = FALSE;
7122 if (!gtk_widget_get_app_paintable (widget))
7123 gtk_paint_flat_box (gtk_widget_get_style (widget),
7126 GTK_SHADOW_NONE, widget, "base",
7128 gtk_widget_get_allocated_width (widget),
7129 gtk_widget_get_allocated_height (widget));
7131 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7132 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7134 if (priv->has_resize_grip &&
7135 gtk_cairo_should_draw_window (cr, priv->grip_window))
7140 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7141 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7142 gtk_paint_resize_grip (gtk_widget_get_style (widget),
7144 gtk_widget_get_state (widget),
7147 get_grip_edge (widget),
7149 rect.width, rect.height);
7157 * gtk_window_set_has_frame:
7158 * @window: a #GtkWindow
7159 * @setting: a boolean
7161 * (Note: this is a special-purpose function for the framebuffer port,
7162 * that causes GTK+ to draw its own window border. For most applications,
7163 * you want gtk_window_set_decorated() instead, which tells the window
7164 * manager whether to draw the window border.)
7166 * If this function is called on a window with setting of %TRUE, before
7167 * it is realized or showed, it will have a "frame" window around
7168 * @window->window, accessible in @window->frame. Using the signal
7169 * frame_event you can receive all events targeted at the frame.
7171 * This function is used by the linux-fb port to implement managed
7172 * windows, but it could conceivably be used by X-programs that
7173 * want to do their own window decorations.
7177 gtk_window_set_has_frame (GtkWindow *window,
7180 GtkWindowPrivate *priv;
7182 g_return_if_fail (GTK_IS_WINDOW (window));
7183 g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
7185 priv = window->priv;
7187 priv->has_frame = setting != FALSE;
7191 * gtk_window_get_has_frame:
7192 * @window: a #GtkWindow
7194 * Accessor for whether the window has a frame window exterior to
7195 * @window->window. Gets the value set by gtk_window_set_has_frame ().
7197 * Return value: %TRUE if a frame has been added to the window
7198 * via gtk_window_set_has_frame().
7201 gtk_window_get_has_frame (GtkWindow *window)
7203 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7205 return window->priv->has_frame;
7209 * gtk_window_set_frame_dimensions:
7210 * @window: a #GtkWindow that has a frame
7211 * @left: The width of the left border
7212 * @top: The height of the top border
7213 * @right: The width of the right border
7214 * @bottom: The height of the bottom border
7216 * (Note: this is a special-purpose function intended for the framebuffer
7217 * port; see gtk_window_set_has_frame(). It will have no effect on the
7218 * window border drawn by the window manager, which is the normal
7219 * case when using the X Window system.)
7221 * For windows with frames (see gtk_window_set_has_frame()) this function
7222 * can be used to change the size of the frame border.
7225 gtk_window_set_frame_dimensions (GtkWindow *window,
7231 GtkWindowPrivate *priv;
7232 GtkAllocation allocation;
7235 g_return_if_fail (GTK_IS_WINDOW (window));
7237 priv = window->priv;
7238 widget = GTK_WIDGET (window);
7240 if (priv->frame_left == left &&
7241 priv->frame_top == top &&
7242 priv->frame_right == right &&
7243 priv->frame_bottom == bottom)
7246 priv->frame_left = left;
7247 priv->frame_top = top;
7248 priv->frame_right = right;
7249 priv->frame_bottom = bottom;
7251 if (gtk_widget_get_realized (widget) && priv->frame)
7253 gtk_widget_get_allocation (widget, &allocation);
7255 gint width = allocation.width + left + right;
7256 gint height = allocation.height + top + bottom;
7257 gdk_window_resize (priv->frame, width, height);
7258 gtk_decorated_window_move_resize_window (window,
7266 * gtk_window_present:
7267 * @window: a #GtkWindow
7269 * Presents a window to the user. This may mean raising the window
7270 * in the stacking order, deiconifying it, moving it to the current
7271 * desktop, and/or giving it the keyboard focus, possibly dependent
7272 * on the user's platform, window manager, and preferences.
7274 * If @window is hidden, this function calls gtk_widget_show()
7277 * This function should be used when the user tries to open a window
7278 * that's already open. Say for example the preferences dialog is
7279 * currently open, and the user chooses Preferences from the menu
7280 * a second time; use gtk_window_present() to move the already-open dialog
7281 * where the user can see it.
7283 * If you are calling this function in response to a user interaction,
7284 * it is preferable to use gtk_window_present_with_time().
7288 gtk_window_present (GtkWindow *window)
7290 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7294 * gtk_window_present_with_time:
7295 * @window: a #GtkWindow
7296 * @timestamp: the timestamp of the user interaction (typically a
7297 * button or key press event) which triggered this call
7299 * Presents a window to the user in response to a user interaction.
7300 * If you need to present a window without a timestamp, use
7301 * gtk_window_present(). See gtk_window_present() for details.
7306 gtk_window_present_with_time (GtkWindow *window,
7310 GdkWindow *gdk_window;
7312 g_return_if_fail (GTK_IS_WINDOW (window));
7314 widget = GTK_WIDGET (window);
7316 if (gtk_widget_get_visible (widget))
7318 gdk_window = gtk_widget_get_window (widget);
7320 g_assert (gdk_window != NULL);
7322 gdk_window_show (gdk_window);
7324 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7325 if (timestamp == GDK_CURRENT_TIME)
7327 #ifdef GDK_WINDOWING_X11
7328 GdkDisplay *display;
7330 display = gtk_widget_get_display (GTK_WIDGET (window));
7331 timestamp = gdk_x11_display_get_user_time (display);
7333 timestamp = gtk_get_current_event_time ();
7337 gdk_window_focus (gdk_window, timestamp);
7341 gtk_widget_show (widget);
7346 * gtk_window_iconify:
7347 * @window: a #GtkWindow
7349 * Asks to iconify (i.e. minimize) the specified @window. Note that
7350 * you shouldn't assume the window is definitely iconified afterward,
7351 * because other entities (e.g. the user or <link
7352 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7353 * again, or there may not be a window manager in which case
7354 * iconification isn't possible, etc. But normally the window will end
7355 * up iconified. Just don't write code that crashes if not.
7357 * It's permitted to call this function before showing a window,
7358 * in which case the window will be iconified before it ever appears
7361 * You can track iconification via the "window-state-event" signal
7366 gtk_window_iconify (GtkWindow *window)
7368 GtkWindowPrivate *priv;
7370 GdkWindow *toplevel;
7372 g_return_if_fail (GTK_IS_WINDOW (window));
7374 priv = window->priv;
7375 widget = GTK_WIDGET (window);
7377 priv->iconify_initially = TRUE;
7380 toplevel = priv->frame;
7382 toplevel = gtk_widget_get_window (widget);
7384 if (toplevel != NULL)
7385 gdk_window_iconify (toplevel);
7389 * gtk_window_deiconify:
7390 * @window: a #GtkWindow
7392 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7393 * that you shouldn't assume the window is definitely deiconified
7394 * afterward, because other entities (e.g. the user or <link
7395 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7396 * again before your code which assumes deiconification gets to run.
7398 * You can track iconification via the "window-state-event" signal
7402 gtk_window_deiconify (GtkWindow *window)
7404 GtkWindowPrivate *priv;
7406 GdkWindow *toplevel;
7408 g_return_if_fail (GTK_IS_WINDOW (window));
7410 priv = window->priv;
7411 widget = GTK_WIDGET (window);
7413 priv->iconify_initially = FALSE;
7416 toplevel = priv->frame;
7418 toplevel = gtk_widget_get_window (widget);
7420 if (toplevel != NULL)
7421 gdk_window_deiconify (toplevel);
7426 * @window: a #GtkWindow
7428 * Asks to stick @window, which means that it will appear on all user
7429 * desktops. Note that you shouldn't assume the window is definitely
7430 * stuck afterward, because other entities (e.g. the user or <link
7431 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7432 * again, and some window managers do not support sticking
7433 * windows. But normally the window will end up stuck. Just don't
7434 * write code that crashes if not.
7436 * It's permitted to call this function before showing a window.
7438 * You can track stickiness via the "window-state-event" signal
7443 gtk_window_stick (GtkWindow *window)
7445 GtkWindowPrivate *priv;
7447 GdkWindow *toplevel;
7449 g_return_if_fail (GTK_IS_WINDOW (window));
7451 priv = window->priv;
7452 widget = GTK_WIDGET (window);
7454 priv->stick_initially = TRUE;
7457 toplevel = priv->frame;
7459 toplevel = gtk_widget_get_window (widget);
7461 if (toplevel != NULL)
7462 gdk_window_stick (toplevel);
7466 * gtk_window_unstick:
7467 * @window: a #GtkWindow
7469 * Asks to unstick @window, which means that it will appear on only
7470 * one of the user's desktops. Note that you shouldn't assume the
7471 * window is definitely unstuck afterward, because other entities
7472 * (e.g. the user or <link linkend="gtk-X11-arch">window
7473 * manager</link>) could stick it again. But normally the window will
7474 * end up stuck. Just don't write code that crashes if not.
7476 * You can track stickiness via the "window-state-event" signal
7481 gtk_window_unstick (GtkWindow *window)
7483 GtkWindowPrivate *priv;
7485 GdkWindow *toplevel;
7487 g_return_if_fail (GTK_IS_WINDOW (window));
7489 priv = window->priv;
7490 widget = GTK_WIDGET (window);
7492 priv->stick_initially = FALSE;
7495 toplevel = priv->frame;
7497 toplevel = gtk_widget_get_window (widget);
7499 if (toplevel != NULL)
7500 gdk_window_unstick (toplevel);
7504 * gtk_window_maximize:
7505 * @window: a #GtkWindow
7507 * Asks to maximize @window, so that it becomes full-screen. Note that
7508 * you shouldn't assume the window is definitely maximized afterward,
7509 * because other entities (e.g. the user or <link
7510 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7511 * again, and not all window managers support maximization. But
7512 * normally the window will end up maximized. Just don't write code
7513 * that crashes if not.
7515 * It's permitted to call this function before showing a window,
7516 * in which case the window will be maximized when it appears onscreen
7519 * You can track maximization via the "window-state-event" signal
7524 gtk_window_maximize (GtkWindow *window)
7526 GtkWindowPrivate *priv;
7528 GdkWindow *toplevel;
7530 g_return_if_fail (GTK_IS_WINDOW (window));
7532 priv = window->priv;
7533 widget = GTK_WIDGET (window);
7535 priv->maximize_initially = TRUE;
7538 toplevel = priv->frame;
7540 toplevel = gtk_widget_get_window (widget);
7542 if (toplevel != NULL)
7543 gdk_window_maximize (toplevel);
7547 * gtk_window_unmaximize:
7548 * @window: a #GtkWindow
7550 * Asks to unmaximize @window. Note that you shouldn't assume the
7551 * window is definitely unmaximized afterward, because other entities
7552 * (e.g. the user or <link linkend="gtk-X11-arch">window
7553 * manager</link>) could maximize it again, and not all window
7554 * managers honor requests to unmaximize. But normally the window will
7555 * end up unmaximized. Just don't write code that crashes if not.
7557 * You can track maximization via the "window-state-event" signal
7562 gtk_window_unmaximize (GtkWindow *window)
7564 GtkWindowPrivate *priv;
7566 GdkWindow *toplevel;
7568 g_return_if_fail (GTK_IS_WINDOW (window));
7570 priv = window->priv;
7571 widget = GTK_WIDGET (window);
7573 priv->maximize_initially = FALSE;
7576 toplevel = priv->frame;
7578 toplevel = gtk_widget_get_window (widget);
7580 if (toplevel != NULL)
7581 gdk_window_unmaximize (toplevel);
7585 * gtk_window_fullscreen:
7586 * @window: a #GtkWindow
7588 * Asks to place @window in the fullscreen state. Note that you
7589 * shouldn't assume the window is definitely full screen afterward,
7590 * because other entities (e.g. the user or <link
7591 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7592 * again, and not all window managers honor requests to fullscreen
7593 * windows. But normally the window will end up fullscreen. Just
7594 * don't write code that crashes if not.
7596 * You can track the fullscreen state via the "window-state-event" signal
7602 gtk_window_fullscreen (GtkWindow *window)
7604 GtkWindowPrivate *priv;
7606 GdkWindow *toplevel;
7608 g_return_if_fail (GTK_IS_WINDOW (window));
7610 priv = window->priv;
7611 widget = GTK_WIDGET (window);
7613 priv->fullscreen_initially = TRUE;
7616 toplevel = priv->frame;
7618 toplevel = gtk_widget_get_window (widget);
7620 if (toplevel != NULL)
7621 gdk_window_fullscreen (toplevel);
7625 * gtk_window_unfullscreen:
7626 * @window: a #GtkWindow
7628 * Asks to toggle off the fullscreen state for @window. Note that you
7629 * shouldn't assume the window is definitely not full screen
7630 * afterward, because other entities (e.g. the user or <link
7631 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7632 * again, and not all window managers honor requests to unfullscreen
7633 * windows. But normally the window will end up restored to its normal
7634 * state. Just don't write code that crashes if not.
7636 * You can track the fullscreen state via the "window-state-event" signal
7642 gtk_window_unfullscreen (GtkWindow *window)
7645 GdkWindow *toplevel;
7646 GtkWindowPrivate *priv;
7648 g_return_if_fail (GTK_IS_WINDOW (window));
7650 priv = window->priv;
7651 widget = GTK_WIDGET (window);
7653 priv->fullscreen_initially = FALSE;
7656 toplevel = priv->frame;
7658 toplevel = gtk_widget_get_window (widget);
7660 if (toplevel != NULL)
7661 gdk_window_unfullscreen (toplevel);
7665 * gtk_window_set_keep_above:
7666 * @window: a #GtkWindow
7667 * @setting: whether to keep @window above other windows
7669 * Asks to keep @window above, so that it stays on top. Note that
7670 * you shouldn't assume the window is definitely above afterward,
7671 * because other entities (e.g. the user or <link
7672 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7673 * and not all window managers support keeping windows above. But
7674 * normally the window will end kept above. Just don't write code
7675 * that crashes if not.
7677 * It's permitted to call this function before showing a window,
7678 * in which case the window will be kept above when it appears onscreen
7681 * You can track the above state via the "window-state-event" signal
7684 * Note that, according to the <ulink
7685 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7686 * Manager Hints</ulink> specification, the above state is mainly meant
7687 * for user preferences and should not be used by applications e.g. for
7688 * drawing attention to their dialogs.
7693 gtk_window_set_keep_above (GtkWindow *window,
7697 GtkWindowPrivate *priv;
7698 GdkWindow *toplevel;
7700 g_return_if_fail (GTK_IS_WINDOW (window));
7702 priv = window->priv;
7703 widget = GTK_WIDGET (window);
7705 priv->above_initially = setting != FALSE;
7707 priv->below_initially = FALSE;
7710 toplevel = priv->frame;
7712 toplevel = gtk_widget_get_window (widget);
7714 if (toplevel != NULL)
7715 gdk_window_set_keep_above (toplevel, setting);
7719 * gtk_window_set_keep_below:
7720 * @window: a #GtkWindow
7721 * @setting: whether to keep @window below other windows
7723 * Asks to keep @window below, so that it stays in bottom. Note that
7724 * you shouldn't assume the window is definitely below afterward,
7725 * because other entities (e.g. the user or <link
7726 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7727 * and not all window managers support putting windows below. But
7728 * normally the window will be kept below. Just don't write code
7729 * that crashes if not.
7731 * It's permitted to call this function before showing a window,
7732 * in which case the window will be kept below when it appears onscreen
7735 * You can track the below state via the "window-state-event" signal
7738 * Note that, according to the <ulink
7739 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7740 * Manager Hints</ulink> specification, the above state is mainly meant
7741 * for user preferences and should not be used by applications e.g. for
7742 * drawing attention to their dialogs.
7747 gtk_window_set_keep_below (GtkWindow *window,
7751 GtkWindowPrivate *priv;
7752 GdkWindow *toplevel;
7754 g_return_if_fail (GTK_IS_WINDOW (window));
7756 priv = window->priv;
7757 widget = GTK_WIDGET (window);
7759 priv->below_initially = setting != FALSE;
7761 priv->above_initially = FALSE;
7764 toplevel = priv->frame;
7766 toplevel = gtk_widget_get_window (widget);
7768 if (toplevel != NULL)
7769 gdk_window_set_keep_below (toplevel, setting);
7773 * gtk_window_set_resizable:
7774 * @window: a #GtkWindow
7775 * @resizable: %TRUE if the user can resize this window
7777 * Sets whether the user can resize a window. Windows are user resizable
7781 gtk_window_set_resizable (GtkWindow *window,
7784 GtkWindowPrivate *priv;
7786 g_return_if_fail (GTK_IS_WINDOW (window));
7788 priv = window->priv;
7790 priv->resizable = (resizable != FALSE);
7792 g_object_notify (G_OBJECT (window), "resizable");
7794 if (priv->grip_window != NULL)
7795 update_grip_visibility (window);
7797 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7801 * gtk_window_get_resizable:
7802 * @window: a #GtkWindow
7804 * Gets the value set by gtk_window_set_resizable().
7806 * Return value: %TRUE if the user can resize the window
7809 gtk_window_get_resizable (GtkWindow *window)
7811 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7813 return window->priv->resizable;
7817 * gtk_window_set_gravity:
7818 * @window: a #GtkWindow
7819 * @gravity: window gravity
7821 * Window gravity defines the meaning of coordinates passed to
7822 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7825 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7826 * typically "do what you mean."
7830 gtk_window_set_gravity (GtkWindow *window,
7833 GtkWindowPrivate *priv;
7835 g_return_if_fail (GTK_IS_WINDOW (window));
7837 priv = window->priv;
7839 if (gravity != priv->gravity)
7841 priv->gravity = gravity;
7843 /* gtk_window_move_resize() will adapt gravity
7845 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7847 g_object_notify (G_OBJECT (window), "gravity");
7852 * gtk_window_get_gravity:
7853 * @window: a #GtkWindow
7855 * Gets the value set by gtk_window_set_gravity().
7857 * Return value: (transfer none): window gravity
7860 gtk_window_get_gravity (GtkWindow *window)
7862 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7864 return window->priv->gravity;
7868 * gtk_window_begin_resize_drag:
7869 * @window: a #GtkWindow
7870 * @button: mouse button that initiated the drag
7871 * @edge: position of the resize control
7872 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7873 * @root_y: Y position where the user clicked to initiate the drag
7874 * @timestamp: timestamp from the click event that initiated the drag
7876 * Starts resizing a window. This function is used if an application
7877 * has window resizing controls. When GDK can support it, the resize
7878 * will be done using the standard mechanism for the <link
7879 * linkend="gtk-X11-arch">window manager</link> or windowing
7880 * system. Otherwise, GDK will try to emulate window resizing,
7881 * potentially not all that well, depending on the windowing system.
7885 gtk_window_begin_resize_drag (GtkWindow *window,
7892 GtkWindowPrivate *priv;
7894 GdkWindow *toplevel;
7896 g_return_if_fail (GTK_IS_WINDOW (window));
7897 widget = GTK_WIDGET (window);
7898 g_return_if_fail (gtk_widget_get_visible (widget));
7900 priv = window->priv;
7903 toplevel = priv->frame;
7905 toplevel = gtk_widget_get_window (widget);
7907 gdk_window_begin_resize_drag (toplevel,
7914 * gtk_window_get_frame_dimensions:
7915 * @window: a #GtkWindow
7916 * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
7917 * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
7918 * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
7919 * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
7921 * (Note: this is a special-purpose function intended for the
7922 * framebuffer port; see gtk_window_set_has_frame(). It will not
7923 * return the size of the window border drawn by the <link
7924 * linkend="gtk-X11-arch">window manager</link>, which is the normal
7925 * case when using a windowing system. See
7926 * gdk_window_get_frame_extents() to get the standard window border
7929 * Retrieves the dimensions of the frame window for this toplevel.
7930 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
7933 gtk_window_get_frame_dimensions (GtkWindow *window,
7939 GtkWindowPrivate *priv;
7941 g_return_if_fail (GTK_IS_WINDOW (window));
7943 priv = window->priv;
7946 *left = priv->frame_left;
7948 *top = priv->frame_top;
7950 *right = priv->frame_right;
7952 *bottom = priv->frame_bottom;
7956 * gtk_window_begin_move_drag:
7957 * @window: a #GtkWindow
7958 * @button: mouse button that initiated the drag
7959 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7960 * @root_y: Y position where the user clicked to initiate the drag
7961 * @timestamp: timestamp from the click event that initiated the drag
7963 * Starts moving a window. This function is used if an application has
7964 * window movement grips. When GDK can support it, the window movement
7965 * will be done using the standard mechanism for the <link
7966 * linkend="gtk-X11-arch">window manager</link> or windowing
7967 * system. Otherwise, GDK will try to emulate window movement,
7968 * potentially not all that well, depending on the windowing system.
7972 gtk_window_begin_move_drag (GtkWindow *window,
7978 GtkWindowPrivate *priv;
7980 GdkWindow *toplevel;
7982 g_return_if_fail (GTK_IS_WINDOW (window));
7983 widget = GTK_WIDGET (window);
7984 g_return_if_fail (gtk_widget_get_visible (widget));
7986 priv = window->priv;
7989 toplevel = priv->frame;
7991 toplevel = gtk_widget_get_window (widget);
7993 gdk_window_begin_move_drag (toplevel,
8000 * gtk_window_set_screen:
8001 * @window: a #GtkWindow.
8002 * @screen: a #GdkScreen.
8004 * Sets the #GdkScreen where the @window is displayed; if
8005 * the window is already mapped, it will be unmapped, and
8006 * then remapped on the new screen.
8011 gtk_window_set_screen (GtkWindow *window,
8014 GtkWindowPrivate *priv;
8016 GdkScreen *previous_screen;
8017 gboolean was_mapped;
8019 g_return_if_fail (GTK_IS_WINDOW (window));
8020 g_return_if_fail (GDK_IS_SCREEN (screen));
8022 priv = window->priv;
8024 if (screen == priv->screen)
8027 widget = GTK_WIDGET (window);
8029 previous_screen = priv->screen;
8030 was_mapped = gtk_widget_get_mapped (widget);
8033 gtk_widget_unmap (widget);
8034 if (gtk_widget_get_realized (widget))
8035 gtk_widget_unrealize (widget);
8037 gtk_window_free_key_hash (window);
8038 priv->screen = screen;
8039 gtk_widget_reset_rc_styles (widget);
8040 if (screen != previous_screen)
8042 g_signal_handlers_disconnect_by_func (previous_screen,
8043 gtk_window_on_composited_changed, window);
8044 g_signal_connect (screen, "composited-changed",
8045 G_CALLBACK (gtk_window_on_composited_changed), window);
8047 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8048 _gtk_widget_propagate_composited_changed (widget);
8050 g_object_notify (G_OBJECT (window), "screen");
8053 gtk_widget_map (widget);
8057 gtk_window_on_composited_changed (GdkScreen *screen,
8060 gtk_widget_queue_draw (GTK_WIDGET (window));
8062 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8066 gtk_window_check_screen (GtkWindow *window)
8068 GtkWindowPrivate *priv = window->priv;
8071 return priv->screen;
8074 g_warning ("Screen for GtkWindow not set; you must always set\n"
8075 "a screen for a GtkWindow before using the window");
8081 * gtk_window_get_screen:
8082 * @window: a #GtkWindow.
8084 * Returns the #GdkScreen associated with @window.
8086 * Return value: (transfer none): a #GdkScreen.
8091 gtk_window_get_screen (GtkWindow *window)
8093 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8095 return window->priv->screen;
8099 * gtk_window_is_active:
8100 * @window: a #GtkWindow
8102 * Returns whether the window is part of the current active toplevel.
8103 * (That is, the toplevel window receiving keystrokes.)
8104 * The return value is %TRUE if the window is active toplevel
8105 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8106 * You might use this function if you wanted to draw a widget
8107 * differently in an active window from a widget in an inactive window.
8108 * See gtk_window_has_toplevel_focus()
8110 * Return value: %TRUE if the window part of the current active window.
8115 gtk_window_is_active (GtkWindow *window)
8117 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8119 return window->priv->is_active;
8123 * gtk_window_has_toplevel_focus:
8124 * @window: a #GtkWindow
8126 * Returns whether the input focus is within this GtkWindow.
8127 * For real toplevel windows, this is identical to gtk_window_is_active(),
8128 * but for embedded windows, like #GtkPlug, the results will differ.
8130 * Return value: %TRUE if the input focus is within this GtkWindow
8135 gtk_window_has_toplevel_focus (GtkWindow *window)
8137 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8139 return window->priv->has_toplevel_focus;
8143 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8145 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8149 gtk_window_group_get_type (void)
8151 static GType window_group_type = 0;
8153 if (!window_group_type)
8155 const GTypeInfo window_group_info =
8157 sizeof (GtkWindowGroupClass),
8158 NULL, /* base_init */
8159 NULL, /* base_finalize */
8160 (GClassInitFunc) gtk_window_group_class_init,
8161 NULL, /* class_finalize */
8162 NULL, /* class_data */
8163 sizeof (GtkWindowGroup),
8164 0, /* n_preallocs */
8165 (GInstanceInitFunc) NULL,
8168 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
8169 &window_group_info, 0);
8172 return window_group_type;
8176 * gtk_window_group_new:
8178 * Creates a new #GtkWindowGroup object. Grabs added with
8179 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8181 * Return value: a new #GtkWindowGroup.
8184 gtk_window_group_new (void)
8186 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8190 window_group_cleanup_grabs (GtkWindowGroup *group,
8193 GtkWindowGroupPrivate *priv;
8194 GtkDeviceGrabInfo *info;
8196 GSList *to_remove = NULL;
8198 tmp_list = group->grabs;
8201 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8202 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8203 tmp_list = tmp_list->next;
8208 gtk_grab_remove (to_remove->data);
8209 g_object_unref (to_remove->data);
8210 to_remove = g_slist_delete_link (to_remove, to_remove);
8213 priv = GTK_WINDOW_GROUP_GET_PRIVATE (group);
8214 tmp_list = priv->device_grabs;
8218 info = tmp_list->data;
8220 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8221 to_remove = g_slist_prepend (to_remove, info);
8223 tmp_list = tmp_list->next;
8228 info = to_remove->data;
8230 gtk_device_grab_remove (info->widget, info->device);
8231 to_remove = g_slist_delete_link (to_remove, to_remove);
8236 * gtk_window_group_add_window:
8237 * @window_group: a #GtkWindowGroup
8238 * @window: the #GtkWindow to add
8240 * Adds a window to a #GtkWindowGroup.
8243 gtk_window_group_add_window (GtkWindowGroup *window_group,
8246 GtkWindowPrivate *priv;
8248 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8249 g_return_if_fail (GTK_IS_WINDOW (window));
8251 priv = window->priv;
8253 if (priv->group != window_group)
8255 g_object_ref (window);
8256 g_object_ref (window_group);
8259 gtk_window_group_remove_window (priv->group, window);
8261 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8263 priv->group = window_group;
8265 g_object_unref (window);
8270 * gtk_window_group_remove_window:
8271 * @window_group: a #GtkWindowGroup
8272 * @window: the #GtkWindow to remove
8274 * Removes a window from a #GtkWindowGroup.
8277 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8280 GtkWindowPrivate *priv;
8282 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8283 g_return_if_fail (GTK_IS_WINDOW (window));
8284 priv = window->priv;
8285 g_return_if_fail (priv->group == window_group);
8287 g_object_ref (window);
8289 window_group_cleanup_grabs (window_group, window);
8292 g_object_unref (window_group);
8293 g_object_unref (window);
8297 * gtk_window_group_list_windows:
8298 * @window_group: a #GtkWindowGroup
8300 * Returns a list of the #GtkWindows that belong to @window_group.
8302 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8303 * windows inside the group.
8308 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8310 GList *toplevels, *toplevel, *group_windows;
8312 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8314 group_windows = NULL;
8315 toplevels = gtk_window_list_toplevels ();
8317 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8319 GtkWindow *window = toplevel->data;
8321 if (window_group == window->priv->group)
8322 group_windows = g_list_prepend (group_windows, window);
8325 return g_list_reverse (group_windows);
8329 * gtk_window_get_group:
8330 * @window: (allow-none): a #GtkWindow, or %NULL
8332 * Returns the group for @window or the default group, if
8333 * @window is %NULL or if @window does not have an explicit
8336 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8341 gtk_window_get_group (GtkWindow *window)
8343 if (window && window->priv->group)
8344 return window->priv->group;
8347 static GtkWindowGroup *default_group = NULL;
8350 default_group = gtk_window_group_new ();
8352 return default_group;
8357 * gtk_window_has_group:
8358 * @window: a #GtkWindow
8360 * Returns whether @window has an explicit window group.
8362 * Return value: %TRUE if @window has an explicit window group.
8367 gtk_window_has_group (GtkWindow *window)
8369 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8371 return window->priv->group != NULL;
8375 * gtk_window_group_get_current_grab:
8376 * @window_group: a #GtkWindowGroup
8378 * Gets the current grab widget of the given group,
8379 * see gtk_grab_add().
8381 * Returns: the current grab widget of the group
8386 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8388 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8390 if (window_group->grabs)
8391 return GTK_WIDGET (window_group->grabs->data);
8396 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8399 gboolean block_others)
8401 GtkWindowGroupPrivate *priv;
8402 GtkDeviceGrabInfo *info;
8404 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8406 info = g_slice_new0 (GtkDeviceGrabInfo);
8407 info->widget = widget;
8408 info->device = device;
8409 info->block_others = block_others;
8411 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8415 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8419 GtkWindowGroupPrivate *priv;
8420 GtkDeviceGrabInfo *info;
8421 GSList *list, *node = NULL;
8422 GdkDevice *other_device;
8424 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8425 other_device = gdk_device_get_associated_device (device);
8426 list = priv->device_grabs;
8432 if (info->widget == widget &&
8433 (info->device == device ||
8434 info->device == other_device))
8447 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8448 g_slice_free (GtkDeviceGrabInfo, info);
8453 * gtk_window_group_get_current_device_grab:
8454 * @window_group: a #GtkWindowGroup
8455 * @device: a #GdkDevice
8457 * Returns the current grab widget for @device, or %NULL if none.
8459 * Returns: The grab widget, or %NULL
8464 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8467 GtkWindowGroupPrivate *priv;
8468 GtkDeviceGrabInfo *info;
8469 GdkDevice *other_device;
8472 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8473 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8475 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8476 list = priv->device_grabs;
8477 other_device = gdk_device_get_associated_device (device);
8484 if (info->device == device ||
8485 info->device == other_device)
8486 return info->widget;
8493 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8497 GtkWindowGroupPrivate *priv;
8498 GtkDeviceGrabInfo *info;
8499 GdkDevice *other_device;
8502 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8503 other_device = gdk_device_get_associated_device (device);
8504 list = priv->device_grabs;
8511 /* Look for blocking grabs on other device pairs
8512 * that have the passed widget within the GTK+ grab.
8514 if (info->block_others &&
8515 info->device != device &&
8516 info->device != other_device &&
8517 (info->widget == widget ||
8518 gtk_widget_is_ancestor (widget, info->widget)))
8526 Derived from XParseGeometry() in XFree86
8528 Copyright 1985, 1986, 1987,1998 The Open Group
8530 All Rights Reserved.
8532 The above copyright notice and this permission notice shall be included
8533 in all copies or substantial portions of the Software.
8535 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8536 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8537 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8538 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8539 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8540 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8541 OTHER DEALINGS IN THE SOFTWARE.
8543 Except as contained in this notice, the name of The Open Group shall
8544 not be used in advertising or otherwise to promote the sale, use or
8545 other dealings in this Software without prior written authorization
8546 from The Open Group.
8551 * XParseGeometry parses strings of the form
8552 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8553 * width, height, xoffset, and yoffset are unsigned integers.
8554 * Example: "=80x24+300-49"
8555 * The equal sign is optional.
8556 * It returns a bitmask that indicates which of the four values
8557 * were actually found in the string. For each value found,
8558 * the corresponding argument is updated; for each value
8559 * not found, the corresponding argument is left unchanged.
8562 /* The following code is from Xlib, and is minimally modified, so we
8563 * can track any upstream changes if required. Don't change this
8564 * code. Or if you do, put in a huge comment marking which thing
8569 read_int (gchar *string,
8577 else if (*string == '-')
8583 for (; (*string >= '0') && (*string <= '9'); string++)
8585 result = (result * 10) + (*string - '0');
8597 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8598 * value (x, y, width, height) was found in the parsed string.
8600 #define NoValue 0x0000
8601 #define XValue 0x0001
8602 #define YValue 0x0002
8603 #define WidthValue 0x0004
8604 #define HeightValue 0x0008
8605 #define AllValues 0x000F
8606 #define XNegative 0x0010
8607 #define YNegative 0x0020
8609 /* Try not to reformat/modify, so we can compare/sync with X sources */
8611 gtk_XParseGeometry (const char *string,
8614 unsigned int *width,
8615 unsigned int *height)
8619 unsigned int tempWidth, tempHeight;
8621 char *nextCharacter;
8623 /* These initializations are just to silence gcc */
8629 if ( (string == NULL) || (*string == '\0')) return(mask);
8631 string++; /* ignore possible '=' at beg of geometry spec */
8633 strind = (char *)string;
8634 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8635 tempWidth = read_int(strind, &nextCharacter);
8636 if (strind == nextCharacter)
8638 strind = nextCharacter;
8642 if (*strind == 'x' || *strind == 'X') {
8644 tempHeight = read_int(strind, &nextCharacter);
8645 if (strind == nextCharacter)
8647 strind = nextCharacter;
8648 mask |= HeightValue;
8651 if ((*strind == '+') || (*strind == '-')) {
8652 if (*strind == '-') {
8654 tempX = -read_int(strind, &nextCharacter);
8655 if (strind == nextCharacter)
8657 strind = nextCharacter;
8663 tempX = read_int(strind, &nextCharacter);
8664 if (strind == nextCharacter)
8666 strind = nextCharacter;
8669 if ((*strind == '+') || (*strind == '-')) {
8670 if (*strind == '-') {
8672 tempY = -read_int(strind, &nextCharacter);
8673 if (strind == nextCharacter)
8675 strind = nextCharacter;
8682 tempY = read_int(strind, &nextCharacter);
8683 if (strind == nextCharacter)
8685 strind = nextCharacter;
8691 /* If strind isn't at the end of the string the it's an invalid
8692 geometry specification. */
8694 if (*strind != '\0') return (0);
8700 if (mask & WidthValue)
8702 if (mask & HeightValue)
8703 *height = tempHeight;
8708 * gtk_window_parse_geometry:
8709 * @window: a #GtkWindow
8710 * @geometry: geometry string
8712 * Parses a standard X Window System geometry string - see the
8713 * manual page for X (type 'man X') for details on this.
8714 * gtk_window_parse_geometry() does work on all GTK+ ports
8715 * including Win32 but is primarily intended for an X environment.
8717 * If either a size or a position can be extracted from the
8718 * geometry string, gtk_window_parse_geometry() returns %TRUE
8719 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8720 * to resize/move the window.
8722 * If gtk_window_parse_geometry() returns %TRUE, it will also
8723 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8724 * indicating to the window manager that the size/position of
8725 * the window was user-specified. This causes most window
8726 * managers to honor the geometry.
8728 * Note that for gtk_window_parse_geometry() to work as expected, it has
8729 * to be called when the window has its "final" size, i.e. after calling
8730 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8733 * #include <gtk/gtk.h>
8736 * fill_with_content (GtkWidget *vbox)
8738 * /* fill with content... */
8742 * main (int argc, char *argv[])
8744 * GtkWidget *window, *vbox;
8745 * GdkGeometry size_hints = {
8746 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8749 * gtk_init (&argc, &argv);
8751 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8752 * vbox = gtk_vbox_new (FALSE, 0);
8754 * gtk_container_add (GTK_CONTAINER (window), vbox);
8755 * fill_with_content (vbox);
8756 * gtk_widget_show_all (vbox);
8758 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8761 * GDK_HINT_MIN_SIZE |
8762 * GDK_HINT_BASE_SIZE |
8763 * GDK_HINT_RESIZE_INC);
8767 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8768 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8771 * gtk_widget_show_all (window);
8778 * Return value: %TRUE if string was parsed successfully
8781 gtk_window_parse_geometry (GtkWindow *window,
8782 const gchar *geometry)
8784 gint result, x = 0, y = 0;
8787 gboolean size_set, pos_set;
8790 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8791 g_return_val_if_fail (geometry != NULL, FALSE);
8793 screen = gtk_window_check_screen (window);
8795 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8798 if ((result & WidthValue) || (result & HeightValue))
8800 gtk_window_set_default_size_internal (window,
8801 TRUE, result & WidthValue ? w : -1,
8802 TRUE, result & HeightValue ? h : -1,
8807 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8809 grav = GDK_GRAVITY_NORTH_WEST;
8811 if ((result & XNegative) && (result & YNegative))
8812 grav = GDK_GRAVITY_SOUTH_EAST;
8813 else if (result & XNegative)
8814 grav = GDK_GRAVITY_NORTH_EAST;
8815 else if (result & YNegative)
8816 grav = GDK_GRAVITY_SOUTH_WEST;
8818 if ((result & XValue) == 0)
8821 if ((result & YValue) == 0)
8824 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8825 grav == GDK_GRAVITY_SOUTH_EAST)
8826 y = gdk_screen_get_height (screen) - h + y;
8828 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8829 grav == GDK_GRAVITY_NORTH_EAST)
8830 x = gdk_screen_get_width (screen) - w + x;
8832 /* we don't let you put a window offscreen; maybe some people would
8833 * prefer to be able to, but it's kind of a bogus thing to do.
8842 if ((result & XValue) || (result & YValue))
8844 gtk_window_set_gravity (window, grav);
8845 gtk_window_move (window, x, y);
8849 if (size_set || pos_set)
8851 /* Set USSize, USPosition hints */
8852 GtkWindowGeometryInfo *info;
8854 info = gtk_window_get_geometry_info (window, TRUE);
8857 info->mask |= GDK_HINT_USER_POS;
8859 info->mask |= GDK_HINT_USER_SIZE;
8866 gtk_window_mnemonic_hash_foreach (guint keyval,
8872 GtkWindowKeysForeachFunc func;
8876 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8880 _gtk_window_keys_foreach (GtkWindow *window,
8881 GtkWindowKeysForeachFunc func,
8885 GtkMnemonicHash *mnemonic_hash;
8889 GtkWindowKeysForeachFunc func;
8893 info.window = window;
8895 info.func_data = func_data;
8897 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8899 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8900 gtk_window_mnemonic_hash_foreach, &info);
8902 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8905 GtkAccelGroup *group = groups->data;
8908 for (i = 0; i < group->priv->n_accels; i++)
8910 GtkAccelKey *key = &group->priv->priv_accels[i].key;
8913 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8916 groups = groups->next;
8921 gtk_window_keys_changed (GtkWindow *window)
8923 gtk_window_free_key_hash (window);
8924 gtk_window_get_key_hash (window);
8927 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8929 struct _GtkWindowKeyEntry
8933 guint is_mnemonic : 1;
8937 window_key_entry_destroy (gpointer data)
8939 g_slice_free (GtkWindowKeyEntry, data);
8943 add_to_key_hash (GtkWindow *window,
8945 GdkModifierType modifiers,
8946 gboolean is_mnemonic,
8949 GtkKeyHash *key_hash = data;
8951 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8953 entry->keyval = keyval;
8954 entry->modifiers = modifiers;
8955 entry->is_mnemonic = is_mnemonic;
8957 /* GtkAccelGroup stores lowercased accelerators. To deal
8958 * with this, if <Shift> was specified, uppercase.
8960 if (modifiers & GDK_SHIFT_MASK)
8962 if (keyval == GDK_KEY_Tab)
8963 keyval = GDK_KEY_ISO_Left_Tab;
8965 keyval = gdk_keyval_to_upper (keyval);
8968 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8972 gtk_window_get_key_hash (GtkWindow *window)
8974 GdkScreen *screen = gtk_window_check_screen (window);
8975 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8980 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8981 (GDestroyNotify)window_key_entry_destroy);
8982 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8983 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8989 gtk_window_free_key_hash (GtkWindow *window)
8991 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8994 _gtk_key_hash_free (key_hash);
8995 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9000 * gtk_window_activate_key:
9001 * @window: a #GtkWindow
9002 * @event: a #GdkEventKey
9004 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9005 * called by the default ::key_press_event handler for toplevel windows,
9006 * however in some cases it may be useful to call this directly when
9007 * overriding the standard key handling for a toplevel window.
9009 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9014 gtk_window_activate_key (GtkWindow *window,
9017 GtkKeyHash *key_hash;
9018 GtkWindowKeyEntry *found_entry = NULL;
9019 gboolean enable_mnemonics;
9020 gboolean enable_accels;
9022 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9023 g_return_val_if_fail (event != NULL, FALSE);
9025 key_hash = gtk_window_get_key_hash (window);
9030 GSList *entries = _gtk_key_hash_lookup (key_hash,
9031 event->hardware_keycode,
9033 gtk_accelerator_get_default_mod_mask (),
9036 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9037 "gtk-enable-mnemonics", &enable_mnemonics,
9038 "gtk-enable-accels", &enable_accels,
9041 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9043 GtkWindowKeyEntry *entry = tmp_list->data;
9044 if (entry->is_mnemonic)
9046 if (enable_mnemonics)
9048 found_entry = entry;
9054 if (enable_accels && !found_entry)
9056 found_entry = entry;
9061 g_slist_free (entries);
9066 if (found_entry->is_mnemonic)
9068 if (enable_mnemonics)
9069 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9070 found_entry->modifiers);
9075 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9076 found_entry->modifiers);
9084 window_update_has_focus (GtkWindow *window)
9086 GtkWindowPrivate *priv = window->priv;
9087 GtkWidget *widget = GTK_WIDGET (window);
9088 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9090 if (has_focus != priv->has_focus)
9092 priv->has_focus = has_focus;
9096 if (priv->focus_widget &&
9097 priv->focus_widget != widget &&
9098 !gtk_widget_has_focus (priv->focus_widget))
9099 do_focus_change (priv->focus_widget, TRUE);
9103 if (priv->focus_widget &&
9104 priv->focus_widget != widget &&
9105 gtk_widget_has_focus (priv->focus_widget))
9106 do_focus_change (priv->focus_widget, FALSE);
9112 * _gtk_window_set_is_active:
9113 * @window: a #GtkWindow
9114 * @is_active: %TRUE if the window is in the currently active toplevel
9116 * Internal function that sets whether the #GtkWindow is part
9117 * of the currently active toplevel window (taking into account inter-process
9121 _gtk_window_set_is_active (GtkWindow *window,
9124 GtkWindowPrivate *priv;
9126 g_return_if_fail (GTK_IS_WINDOW (window));
9128 priv = window->priv;
9130 is_active = is_active != FALSE;
9132 if (is_active != priv->is_active)
9134 priv->is_active = is_active;
9135 window_update_has_focus (window);
9137 g_object_notify (G_OBJECT (window), "is-active");
9142 * _gtk_window_set_is_toplevel:
9143 * @window: a #GtkWindow
9144 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9145 * parent of the root window); %FALSE if it is not (for example, for an
9146 * in-process, parented GtkPlug)
9148 * Internal function used by #GtkPlug when it gets parented/unparented by a
9149 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9150 * global list of toplevel windows.
9153 _gtk_window_set_is_toplevel (GtkWindow *window,
9154 gboolean is_toplevel)
9158 widget = GTK_WIDGET (window);
9160 if (gtk_widget_is_toplevel (widget))
9161 g_assert (g_slist_find (toplevel_list, window) != NULL);
9163 g_assert (g_slist_find (toplevel_list, window) == NULL);
9165 if (is_toplevel == gtk_widget_is_toplevel (widget))
9170 _gtk_widget_set_is_toplevel (widget, TRUE);
9171 toplevel_list = g_slist_prepend (toplevel_list, window);
9175 _gtk_widget_set_is_toplevel (widget, FALSE);
9176 toplevel_list = g_slist_remove (toplevel_list, window);
9181 * _gtk_window_set_has_toplevel_focus:
9182 * @window: a #GtkWindow
9183 * @has_toplevel_focus: %TRUE if the in
9185 * Internal function that sets whether the keyboard focus for the
9186 * toplevel window (taking into account inter-process embedding.)
9189 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9190 gboolean has_toplevel_focus)
9192 GtkWindowPrivate *priv;
9194 g_return_if_fail (GTK_IS_WINDOW (window));
9196 priv = window->priv;
9198 has_toplevel_focus = has_toplevel_focus != FALSE;
9200 if (has_toplevel_focus != priv->has_toplevel_focus)
9202 priv->has_toplevel_focus = has_toplevel_focus;
9203 window_update_has_focus (window);
9205 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9210 * gtk_window_set_auto_startup_notification:
9211 * @setting: %TRUE to automatically do startup notification
9213 * By default, after showing the first #GtkWindow, GTK+ calls
9214 * gdk_notify_startup_complete(). Call this function to disable
9215 * the automatic startup notification. You might do this if your
9216 * first window is a splash screen, and you want to delay notification
9217 * until after your real main window has been shown, for example.
9219 * In that example, you would disable startup notification
9220 * temporarily, show your splash screen, then re-enable it so that
9221 * showing the main window would automatically result in notification.
9226 gtk_window_set_auto_startup_notification (gboolean setting)
9228 disable_startup_notification = !setting;
9232 * gtk_window_get_window_type:
9233 * @window: a #GtkWindow
9235 * Gets the type of the window. See #GtkWindowType.
9237 * Return value: the type of the window
9242 gtk_window_get_window_type (GtkWindow *window)
9244 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9246 return window->priv->type;
9250 * gtk_window_get_mnemonics_visible:
9251 * @window: a #GtkWindow
9253 * Gets the value of the #GtkWindow:mnemonics-visible property.
9255 * Returns: %TRUE if mnemonics are supposed to be visible
9261 gtk_window_get_mnemonics_visible (GtkWindow *window)
9263 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9265 return window->priv->mnemonics_visible;
9269 * gtk_window_set_mnemonics_visible:
9270 * @window: a #GtkWindow
9271 * @setting: the new value
9273 * Sets the #GtkWindow:mnemonics-visible property.
9278 gtk_window_set_mnemonics_visible (GtkWindow *window,
9281 GtkWindowPrivate *priv;
9283 g_return_if_fail (GTK_IS_WINDOW (window));
9285 priv = window->priv;
9287 setting = setting != FALSE;
9289 if (priv->mnemonics_visible != setting)
9291 priv->mnemonics_visible = setting;
9292 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9295 priv->mnemonics_visible_set = TRUE;
9299 _gtk_window_get_wmclass (GtkWindow *window,
9300 gchar **wmclass_name,
9301 gchar **wmclass_class)
9303 GtkWindowPrivate *priv = window->priv;
9305 *wmclass_name = priv->wmclass_name;
9306 *wmclass_class = priv->wmclass_class;