1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gtkwindow.h"
36 #include "gtkprivate.h"
37 #include "gtkwindowprivate.h"
38 #include "gtkaccelgroupprivate.h"
39 #include "gtkbindings.h"
40 #include "gtkkeyhash.h"
42 #include "gtkmnemonichash.h"
43 #include "gtkmenubar.h"
44 #include "gtkiconfactory.h"
45 #include "gtkicontheme.h"
46 #include "gtkmarshalers.h"
48 #include "gtkbuildable.h"
49 #include "gtkwidgetprivate.h"
50 #include "gtkcontainerprivate.h"
52 #include "gtktypebuiltins.h"
53 #include "a11y/gtkwindowaccessible.h"
55 #ifdef GDK_WINDOWING_X11
62 * @short_description: Toplevel which can contain other widgets
64 * A GtkWindow is a toplevel window which can contain other widgets.
65 * Windows normally have decorations that are under the control
66 * of the windowing system and allow the user to manipulate the window
67 * (resize it, move it, close it,...).
69 * GTK+ also allows windows to have a resize grip (a small area in the lower
70 * right or left corner) which can be clicked to reszie the window. To
71 * control whether a window has a resize grip, use
72 * gtk_window_set_has_resize_grip().
74 * <refsect2 id="GtkWindow-BUILDER-UI">
75 * <title>GtkWindow as GtkBuildable</title>
77 * The GtkWindow implementation of the GtkBuildable interface supports a
78 * custom <tag class="starttag">accel-groups</tag> element, which supports
79 * any number of <tag class="starttag">group</tag> elements representing the
80 * #GtkAccelGroup objects you want to add to your window (synonymous with
81 * gtk_window_add_accel_group().
84 * <title>A UI definition fragment with accel groups</title>
85 * <programlisting><![CDATA[
86 * <object class="GtkWindow">
88 * <group name="accelgroup1"/>
94 * <object class="GtkAccelGroup" id="accelgroup1"/>
95 * ]]></programlisting>
100 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
102 struct _GtkWindowPrivate
104 GtkMnemonicHash *mnemonic_hash;
106 GtkWidget *default_widget;
107 GtkWidget *focus_widget;
108 GtkWindow *transient_parent;
109 GtkWindowGeometryInfo *geometry_info;
110 GtkWindowGroup *group;
112 GtkApplication *application;
114 GdkModifierType mnemonic_modifier;
115 GdkWindowTypeHint gdk_type_hint;
119 GdkWindow *grip_window;
123 gchar *wmclass_class;
127 guint keys_changed_handler;
129 guint32 initial_timestamp;
131 guint16 configure_request_count;
133 /* The following flags are initially TRUE (before a window is mapped).
134 * They cause us to compute a configure request that involves
135 * default-only parameters. Once mapped, we set them to FALSE.
136 * Then we set them to TRUE again on unmap (for position)
137 * and on unrealize (for size).
139 guint need_default_position : 1;
140 guint need_default_size : 1;
142 guint above_initially : 1;
143 guint accept_focus : 1;
144 guint below_initially : 1;
145 guint builder_visible : 1;
146 guint configure_notify_received : 1;
149 guint destroy_with_parent : 1;
150 guint focus_on_map : 1;
151 guint fullscreen_initially : 1;
153 guint has_user_ref_count : 1;
154 guint has_toplevel_focus : 1;
155 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
157 guint maximize_initially : 1;
158 guint mnemonics_visible : 1;
159 guint mnemonics_visible_set : 1;
160 guint focus_visible : 1;
162 guint opacity_set : 1;
164 guint reset_type_hint : 1;
166 guint skips_pager : 1;
167 guint skips_taskbar : 1;
168 guint stick_initially : 1;
169 guint transient_parent_group : 1;
170 guint type : 4; /* GtkWindowType */
171 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
172 * one of the original eight. If not,
174 * GDK_WINDOW_TYPE_HINT_NORMAL
177 guint has_resize_grip : 1;
178 guint resize_grip_visible : 1; /* don't use, just for "resize-
179 * grip-visible" notification
181 guint gravity : 5; /* GdkGravity */
208 PROP_DESTROY_WITH_PARENT,
213 PROP_SKIP_TASKBAR_HINT,
214 PROP_SKIP_PAGER_HINT,
223 PROP_HAS_RESIZE_GRIP,
224 PROP_RESIZE_GRIP_VISIBLE,
226 /* Readonly properties */
228 PROP_HAS_TOPLEVEL_FOCUS,
230 /* Writeonly properties */
233 PROP_MNEMONICS_VISIBLE,
244 guint using_default_icon : 1;
245 guint using_parent_icon : 1;
246 guint using_themed_icon : 1;
250 GdkGeometry geometry; /* Last set of geometry hints we set */
251 GdkWindowHints flags;
252 GdkRectangle configure_request;
253 } GtkWindowLastGeometryInfo;
255 struct _GtkWindowGeometryInfo
257 /* Properties that the app has set on the window
259 GdkGeometry geometry; /* Geometry hints */
261 GtkWidget *widget; /* subwidget to which hints apply */
262 /* from last gtk_window_resize () - if > 0, indicates that
263 * we should resize to this size.
268 /* From last gtk_window_move () prior to mapping -
269 * only used if initial_pos_set
274 /* Default size - used only the FIRST time we map a window,
279 /* whether to use initial_x, initial_y */
280 guint initial_pos_set : 1;
281 /* CENTER_ALWAYS or other position constraint changed since
282 * we sent the last configure request.
284 guint position_constraints_changed : 1;
286 /* if true, default_width, height should be multiplied by the
287 * increments and affect the geometry widget only
289 guint default_is_geometry : 1;
291 /* if true, resize_width, height should be multiplied by the
292 * increments and affect the geometry widget only
294 guint resize_is_geometry : 1;
296 GtkWindowLastGeometryInfo last;
300 struct _GtkDeviceGrabInfo
304 guint block_others : 1;
307 struct _GtkWindowGroupPrivate
310 GSList *device_grabs;
313 static void gtk_window_dispose (GObject *object);
314 static void gtk_window_finalize (GObject *object);
315 static void gtk_window_destroy (GtkWidget *widget);
316 static void gtk_window_show (GtkWidget *widget);
317 static void gtk_window_hide (GtkWidget *widget);
318 static void gtk_window_map (GtkWidget *widget);
319 static void gtk_window_unmap (GtkWidget *widget);
320 static void gtk_window_realize (GtkWidget *widget);
321 static void gtk_window_unrealize (GtkWidget *widget);
322 static void gtk_window_size_allocate (GtkWidget *widget,
323 GtkAllocation *allocation);
324 static gboolean gtk_window_map_event (GtkWidget *widget,
326 static gint gtk_window_configure_event (GtkWidget *widget,
327 GdkEventConfigure *event);
328 static gint gtk_window_key_press_event (GtkWidget *widget,
330 static gint gtk_window_key_release_event (GtkWidget *widget,
332 static gint gtk_window_button_press_event (GtkWidget *widget,
333 GdkEventButton *event);
334 static gint gtk_window_enter_notify_event (GtkWidget *widget,
335 GdkEventCrossing *event);
336 static gint gtk_window_leave_notify_event (GtkWidget *widget,
337 GdkEventCrossing *event);
338 static gint gtk_window_focus_in_event (GtkWidget *widget,
339 GdkEventFocus *event);
340 static gint gtk_window_focus_out_event (GtkWidget *widget,
341 GdkEventFocus *event);
342 static void gtk_window_style_updated (GtkWidget *widget);
343 static gboolean gtk_window_state_event (GtkWidget *widget,
344 GdkEventWindowState *event);
345 static void gtk_window_check_resize (GtkContainer *container);
346 static gint gtk_window_focus (GtkWidget *widget,
347 GtkDirectionType direction);
348 static void gtk_window_move_focus (GtkWidget *widget,
349 GtkDirectionType dir);
350 static void gtk_window_real_set_focus (GtkWindow *window,
352 static void gtk_window_direction_changed (GtkWidget *widget,
353 GtkTextDirection prev_dir);
354 static void gtk_window_state_changed (GtkWidget *widget,
355 GtkStateType previous_state);
357 static void gtk_window_real_activate_default (GtkWindow *window);
358 static void gtk_window_real_activate_focus (GtkWindow *window);
359 static void gtk_window_keys_changed (GtkWindow *window);
360 static gint gtk_window_draw (GtkWidget *widget,
362 static void gtk_window_unset_transient_for (GtkWindow *window);
363 static void gtk_window_transient_parent_realized (GtkWidget *parent,
365 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
368 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
370 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
373 static void gtk_window_move_resize (GtkWindow *window);
374 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
376 GdkGeometry *geometry_b,
378 static void gtk_window_constrain_size (GtkWindow *window,
379 GdkGeometry *geometry,
385 static void gtk_window_constrain_position (GtkWindow *window,
390 static void gtk_window_compute_hints (GtkWindow *window,
391 GdkGeometry *new_geometry,
393 static void gtk_window_compute_configure_request (GtkWindow *window,
394 GdkRectangle *request,
395 GdkGeometry *geometry,
398 static void gtk_window_set_default_size_internal (GtkWindow *window,
399 gboolean change_width,
401 gboolean change_height,
403 gboolean is_geometry);
405 static void update_themed_icon (GtkIconTheme *theme,
407 static GList *icon_list_from_theme (GtkWidget *widget,
409 static void gtk_window_realize_icon (GtkWindow *window);
410 static void gtk_window_unrealize_icon (GtkWindow *window);
411 static void resize_grip_create_window (GtkWindow *window);
412 static void resize_grip_destroy_window (GtkWindow *window);
413 static void update_grip_visibility (GtkWindow *window);
415 static void gtk_window_notify_keys_changed (GtkWindow *window);
416 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
417 static void gtk_window_free_key_hash (GtkWindow *window);
418 static void gtk_window_on_composited_changed (GdkScreen *screen,
420 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
423 static void gtk_window_set_theme_variant (GtkWindow *window);
425 static GSList *toplevel_list = NULL;
426 static guint window_signals[LAST_SIGNAL] = { 0 };
427 static GList *default_icon_list = NULL;
428 static gchar *default_icon_name = NULL;
429 static guint default_icon_serial = 0;
430 static gboolean disable_startup_notification = FALSE;
431 static gboolean sent_startup_notification = FALSE;
433 static GQuark quark_gtk_embedded = 0;
434 static GQuark quark_gtk_window_key_hash = 0;
435 static GQuark quark_gtk_window_icon_info = 0;
436 static GQuark quark_gtk_buildable_accels = 0;
438 static GtkBuildableIface *parent_buildable_iface;
440 static void gtk_window_set_property (GObject *object,
444 static void gtk_window_get_property (GObject *object,
450 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
451 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
454 const GValue *value);
455 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
456 GtkBuilder *builder);
457 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
460 const gchar *tagname,
461 GMarkupParser *parser,
463 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
466 const gchar *tagname,
470 static void gtk_window_get_preferred_width (GtkWidget *widget,
473 static void gtk_window_get_preferred_height (GtkWidget *widget,
477 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
478 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
479 gtk_window_buildable_interface_init))
482 add_tab_bindings (GtkBindingSet *binding_set,
483 GdkModifierType modifiers,
484 GtkDirectionType direction)
486 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
488 GTK_TYPE_DIRECTION_TYPE, direction);
489 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
491 GTK_TYPE_DIRECTION_TYPE, direction);
495 add_arrow_bindings (GtkBindingSet *binding_set,
497 GtkDirectionType direction)
499 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
501 gtk_binding_entry_add_signal (binding_set, keysym, 0,
503 GTK_TYPE_DIRECTION_TYPE, direction);
504 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
506 GTK_TYPE_DIRECTION_TYPE, direction);
507 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
509 GTK_TYPE_DIRECTION_TYPE, direction);
510 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
512 GTK_TYPE_DIRECTION_TYPE, direction);
516 extract_time_from_startup_id (const gchar* startup_id)
518 gchar *timestr = g_strrstr (startup_id, "_TIME");
519 guint32 retval = GDK_CURRENT_TIME;
526 /* Skip past the "_TIME" part */
531 timestamp = g_ascii_strtoull (timestr, &end, 0);
532 if (errno == 0 && end != timestr)
540 startup_id_is_fake (const gchar* startup_id)
542 return strncmp (startup_id, "_TIME", 5) == 0;
546 gtk_window_class_init (GtkWindowClass *klass)
548 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
549 GtkWidgetClass *widget_class;
550 GtkContainerClass *container_class;
551 GtkBindingSet *binding_set;
553 widget_class = (GtkWidgetClass*) klass;
554 container_class = (GtkContainerClass*) klass;
556 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
557 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
558 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
559 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
561 gobject_class->dispose = gtk_window_dispose;
562 gobject_class->finalize = gtk_window_finalize;
564 gobject_class->set_property = gtk_window_set_property;
565 gobject_class->get_property = gtk_window_get_property;
567 widget_class->destroy = gtk_window_destroy;
568 widget_class->show = gtk_window_show;
569 widget_class->hide = gtk_window_hide;
570 widget_class->map = gtk_window_map;
571 widget_class->map_event = gtk_window_map_event;
572 widget_class->unmap = gtk_window_unmap;
573 widget_class->realize = gtk_window_realize;
574 widget_class->unrealize = gtk_window_unrealize;
575 widget_class->size_allocate = gtk_window_size_allocate;
576 widget_class->configure_event = gtk_window_configure_event;
577 widget_class->key_press_event = gtk_window_key_press_event;
578 widget_class->key_release_event = gtk_window_key_release_event;
579 widget_class->enter_notify_event = gtk_window_enter_notify_event;
580 widget_class->leave_notify_event = gtk_window_leave_notify_event;
581 widget_class->focus_in_event = gtk_window_focus_in_event;
582 widget_class->button_press_event = gtk_window_button_press_event;
583 widget_class->focus_out_event = gtk_window_focus_out_event;
584 widget_class->focus = gtk_window_focus;
585 widget_class->move_focus = gtk_window_move_focus;
586 widget_class->draw = gtk_window_draw;
587 widget_class->get_preferred_width = gtk_window_get_preferred_width;
588 widget_class->get_preferred_height = gtk_window_get_preferred_height;
589 widget_class->window_state_event = gtk_window_state_event;
590 widget_class->direction_changed = gtk_window_direction_changed;
591 widget_class->state_changed = gtk_window_state_changed;
592 widget_class->style_updated = gtk_window_style_updated;
594 container_class->check_resize = gtk_window_check_resize;
596 klass->set_focus = gtk_window_real_set_focus;
598 klass->activate_default = gtk_window_real_activate_default;
599 klass->activate_focus = gtk_window_real_activate_focus;
600 klass->keys_changed = gtk_window_keys_changed;
602 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
605 g_object_class_install_property (gobject_class,
607 g_param_spec_enum ("type",
609 P_("The type of the window"),
610 GTK_TYPE_WINDOW_TYPE,
612 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
614 g_object_class_install_property (gobject_class,
616 g_param_spec_string ("title",
618 P_("The title of the window"),
620 GTK_PARAM_READWRITE));
622 g_object_class_install_property (gobject_class,
624 g_param_spec_string ("role",
626 P_("Unique identifier for the window to be used when restoring a session"),
628 GTK_PARAM_READWRITE));
631 * GtkWindow:startup-id:
633 * The :startup-id is a write-only property for setting window's
634 * startup notification identifier. See gtk_window_set_startup_id()
639 g_object_class_install_property (gobject_class,
641 g_param_spec_string ("startup-id",
643 P_("Unique startup identifier for the window used by startup-notification"),
645 GTK_PARAM_WRITABLE));
647 g_object_class_install_property (gobject_class,
649 g_param_spec_boolean ("resizable",
651 P_("If TRUE, users can resize the window"),
653 GTK_PARAM_READWRITE));
655 g_object_class_install_property (gobject_class,
657 g_param_spec_boolean ("modal",
659 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
661 GTK_PARAM_READWRITE));
663 g_object_class_install_property (gobject_class,
665 g_param_spec_enum ("window-position",
666 P_("Window Position"),
667 P_("The initial position of the window"),
668 GTK_TYPE_WINDOW_POSITION,
670 GTK_PARAM_READWRITE));
672 g_object_class_install_property (gobject_class,
674 g_param_spec_int ("default-width",
676 P_("The default width of the window, used when initially showing the window"),
680 GTK_PARAM_READWRITE));
682 g_object_class_install_property (gobject_class,
684 g_param_spec_int ("default-height",
685 P_("Default Height"),
686 P_("The default height of the window, used when initially showing the window"),
690 GTK_PARAM_READWRITE));
692 g_object_class_install_property (gobject_class,
693 PROP_DESTROY_WITH_PARENT,
694 g_param_spec_boolean ("destroy-with-parent",
695 P_("Destroy with Parent"),
696 P_("If this window should be destroyed when the parent is destroyed"),
698 GTK_PARAM_READWRITE));
700 g_object_class_install_property (gobject_class,
702 g_param_spec_object ("icon",
704 P_("Icon for this window"),
706 GTK_PARAM_READWRITE));
709 * GtkWindow:mnemonics-visible:
711 * Whether mnemonics are currently visible in this window.
713 * This property is maintained by GTK+ based on the
714 * #GtkSettings:gtk-auto-mnemonics setting and user input,
715 * and should not be set by applications.
719 g_object_class_install_property (gobject_class,
720 PROP_MNEMONICS_VISIBLE,
721 g_param_spec_boolean ("mnemonics-visible",
722 P_("Mnemonics Visible"),
723 P_("Whether mnemonics are currently visible in this window"),
725 GTK_PARAM_READWRITE));
728 * GtkWindow:focus-visible:
730 * Whether 'focus rectangles' are currently visible in this window.
732 * This property is maintained by GTK+ based on the
733 * #GtkSettings:gtk-visible-focus setting and user input
734 * and should not be set by applications.
738 g_object_class_install_property (gobject_class,
740 g_param_spec_boolean ("focus-visible",
742 P_("Whether focus rectangles are currently visible in this window"),
744 GTK_PARAM_READWRITE));
747 * GtkWindow:icon-name:
749 * The :icon-name property specifies the name of the themed icon to
750 * use as the window icon. See #GtkIconTheme for more details.
754 g_object_class_install_property (gobject_class,
756 g_param_spec_string ("icon-name",
758 P_("Name of the themed icon for this window"),
760 GTK_PARAM_READWRITE));
762 g_object_class_install_property (gobject_class,
764 g_param_spec_object ("screen",
766 P_("The screen where this window will be displayed"),
768 GTK_PARAM_READWRITE));
770 g_object_class_install_property (gobject_class,
772 g_param_spec_boolean ("is-active",
774 P_("Whether the toplevel is the current active window"),
776 GTK_PARAM_READABLE));
778 g_object_class_install_property (gobject_class,
779 PROP_HAS_TOPLEVEL_FOCUS,
780 g_param_spec_boolean ("has-toplevel-focus",
781 P_("Focus in Toplevel"),
782 P_("Whether the input focus is within this GtkWindow"),
784 GTK_PARAM_READABLE));
786 g_object_class_install_property (gobject_class,
788 g_param_spec_enum ("type-hint",
790 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
791 GDK_TYPE_WINDOW_TYPE_HINT,
792 GDK_WINDOW_TYPE_HINT_NORMAL,
793 GTK_PARAM_READWRITE));
795 g_object_class_install_property (gobject_class,
796 PROP_SKIP_TASKBAR_HINT,
797 g_param_spec_boolean ("skip-taskbar-hint",
799 P_("TRUE if the window should not be in the task bar."),
801 GTK_PARAM_READWRITE));
803 g_object_class_install_property (gobject_class,
804 PROP_SKIP_PAGER_HINT,
805 g_param_spec_boolean ("skip-pager-hint",
807 P_("TRUE if the window should not be in the pager."),
809 GTK_PARAM_READWRITE));
811 g_object_class_install_property (gobject_class,
813 g_param_spec_boolean ("urgency-hint",
815 P_("TRUE if the window should be brought to the user's attention."),
817 GTK_PARAM_READWRITE));
820 * GtkWindow:accept-focus:
822 * Whether the window should receive the input focus.
826 g_object_class_install_property (gobject_class,
828 g_param_spec_boolean ("accept-focus",
830 P_("TRUE if the window should receive the input focus."),
832 GTK_PARAM_READWRITE));
835 * GtkWindow:focus-on-map:
837 * Whether the window should receive the input focus when mapped.
841 g_object_class_install_property (gobject_class,
843 g_param_spec_boolean ("focus-on-map",
845 P_("TRUE if the window should receive the input focus when mapped."),
847 GTK_PARAM_READWRITE));
850 * GtkWindow:decorated:
852 * Whether the window should be decorated by the window manager.
856 g_object_class_install_property (gobject_class,
858 g_param_spec_boolean ("decorated",
860 P_("Whether the window should be decorated by the window manager"),
862 GTK_PARAM_READWRITE));
865 * GtkWindow:deletable:
867 * Whether the window frame should have a close button.
871 g_object_class_install_property (gobject_class,
873 g_param_spec_boolean ("deletable",
875 P_("Whether the window frame should have a close button"),
877 GTK_PARAM_READWRITE));
880 * GtkWindow:has-resize-grip
882 * Whether the window has a corner resize grip.
884 * Note that the resize grip is only shown if the window is
885 * actually resizable and not maximized. Use
886 * #GtkWindow:resize-grip-visible to find out if the resize
887 * grip is currently shown.
891 g_object_class_install_property (gobject_class,
892 PROP_HAS_RESIZE_GRIP,
893 g_param_spec_boolean ("has-resize-grip",
895 P_("Specifies whether the window should have a resize grip"),
897 GTK_PARAM_READWRITE));
900 * GtkWindow:resize-grip-visible:
902 * Whether a corner resize grip is currently shown.
906 g_object_class_install_property (gobject_class,
907 PROP_RESIZE_GRIP_VISIBLE,
908 g_param_spec_boolean ("resize-grip-visible",
909 P_("Resize grip is visible"),
910 P_("Specifies whether the window's resize grip is visible."),
912 GTK_PARAM_READABLE));
918 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
919 * more details about window gravity.
923 g_object_class_install_property (gobject_class,
925 g_param_spec_enum ("gravity",
927 P_("The window gravity of the window"),
929 GDK_GRAVITY_NORTH_WEST,
930 GTK_PARAM_READWRITE));
934 * GtkWindow:transient-for:
936 * The transient parent of the window. See gtk_window_set_transient_for() for
937 * more details about transient windows.
941 g_object_class_install_property (gobject_class,
943 g_param_spec_object ("transient-for",
944 P_("Transient for Window"),
945 P_("The transient parent of the dialog"),
947 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
952 * The requested opacity of the window. See gtk_window_set_opacity() for
953 * more details about window opacity.
957 g_object_class_install_property (gobject_class,
959 g_param_spec_double ("opacity",
960 P_("Opacity for Window"),
961 P_("The opacity of the window, from 0 to 1"),
965 GTK_PARAM_READWRITE));
969 gtk_widget_class_install_style_property (widget_class,
970 g_param_spec_int ("resize-grip-width",
971 P_("Width of resize grip"),
972 P_("Width of resize grip"),
973 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
975 gtk_widget_class_install_style_property (widget_class,
976 g_param_spec_int ("resize-grip-height",
977 P_("Height of resize grip"),
978 P_("Height of resize grip"),
979 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
983 * GtkWindow:application:
985 * The #GtkApplication associated with the window.
987 * The application will be kept alive for at least as long as it
988 * has any windows associated with it (see g_application_hold()
989 * for a way to keep it alive without windows).
991 * Normally, the connection between the application and the window
992 * will remain until the window is destroyed, but you can explicitly
993 * remove it by setting the ::application property to %NULL.
997 g_object_class_install_property (gobject_class,
999 g_param_spec_object ("application",
1000 P_("GtkApplication"),
1001 P_("The GtkApplication for the window"),
1002 GTK_TYPE_APPLICATION,
1003 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1005 window_signals[SET_FOCUS] =
1006 g_signal_new (I_("set-focus"),
1007 G_TYPE_FROM_CLASS (gobject_class),
1009 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1011 _gtk_marshal_VOID__OBJECT,
1016 * GtkWindow::activate-focus:
1017 * @window: the window which received the signal
1019 * The ::activate-focus signal is a
1020 * <link linkend="keybinding-signals">keybinding signal</link>
1021 * which gets emitted when the user activates the currently
1022 * focused widget of @window.
1024 window_signals[ACTIVATE_FOCUS] =
1025 g_signal_new (I_("activate-focus"),
1026 G_TYPE_FROM_CLASS (gobject_class),
1027 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1028 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1030 _gtk_marshal_VOID__VOID,
1035 * GtkWindow::activate-default:
1036 * @window: the window which received the signal
1038 * The ::activate-default signal is a
1039 * <link linkend="keybinding-signals">keybinding signal</link>
1040 * which gets emitted when the user activates the default widget
1043 window_signals[ACTIVATE_DEFAULT] =
1044 g_signal_new (I_("activate-default"),
1045 G_TYPE_FROM_CLASS (gobject_class),
1046 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1047 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1049 _gtk_marshal_VOID__VOID,
1054 * GtkWindow::keys-changed:
1055 * @window: the window which received the signal
1057 * The ::keys-changed signal gets emitted when the set of accelerators
1058 * or mnemonics that are associated with @window changes.
1060 window_signals[KEYS_CHANGED] =
1061 g_signal_new (I_("keys-changed"),
1062 G_TYPE_FROM_CLASS (gobject_class),
1064 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1066 _gtk_marshal_VOID__VOID,
1074 binding_set = gtk_binding_set_by_class (klass);
1076 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1077 "activate-focus", 0);
1078 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1079 "activate-focus", 0);
1081 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1082 "activate-default", 0);
1083 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1084 "activate-default", 0);
1085 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1086 "activate-default", 0);
1088 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1089 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1090 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1091 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1093 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1094 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1095 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1096 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1098 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1102 gtk_window_init (GtkWindow *window)
1104 GtkWindowPrivate *priv;
1106 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1109 priv = window->priv;
1111 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1112 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1114 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1116 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1119 priv->wmclass_name = g_strdup (g_get_prgname ());
1120 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1121 priv->wm_role = NULL;
1122 priv->geometry_info = NULL;
1123 priv->type = GTK_WINDOW_TOPLEVEL;
1124 priv->focus_widget = NULL;
1125 priv->default_widget = NULL;
1126 priv->configure_request_count = 0;
1127 priv->resizable = TRUE;
1128 priv->configure_notify_received = FALSE;
1129 priv->position = GTK_WIN_POS_NONE;
1130 priv->need_default_size = TRUE;
1131 priv->need_default_position = TRUE;
1132 priv->modal = FALSE;
1133 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1134 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1135 priv->decorated = TRUE;
1136 priv->mnemonic_modifier = GDK_MOD1_MASK;
1137 priv->screen = gdk_screen_get_default ();
1139 priv->accept_focus = TRUE;
1140 priv->focus_on_map = TRUE;
1141 priv->deletable = TRUE;
1142 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1143 priv->opacity = 1.0;
1144 priv->startup_id = NULL;
1145 priv->initial_timestamp = GDK_CURRENT_TIME;
1146 priv->has_resize_grip = TRUE;
1147 priv->mnemonics_visible = TRUE;
1148 priv->focus_visible = TRUE;
1150 g_object_ref_sink (window);
1151 priv->has_user_ref_count = TRUE;
1152 toplevel_list = g_slist_prepend (toplevel_list, window);
1155 g_signal_connect (priv->screen, "composited-changed",
1156 G_CALLBACK (gtk_window_on_composited_changed), window);
1158 #ifdef GDK_WINDOWING_X11
1159 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1160 "notify::gtk-application-prefer-dark-theme",
1161 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1166 gtk_window_set_property (GObject *object,
1168 const GValue *value,
1171 GtkWindow *window = GTK_WINDOW (object);
1172 GtkWindowPrivate *priv = window->priv;
1177 priv->type = g_value_get_enum (value);
1180 gtk_window_set_title (window, g_value_get_string (value));
1183 gtk_window_set_role (window, g_value_get_string (value));
1185 case PROP_STARTUP_ID:
1186 gtk_window_set_startup_id (window, g_value_get_string (value));
1188 case PROP_RESIZABLE:
1189 gtk_window_set_resizable (window, g_value_get_boolean (value));
1192 gtk_window_set_modal (window, g_value_get_boolean (value));
1195 gtk_window_set_position (window, g_value_get_enum (value));
1197 case PROP_DEFAULT_WIDTH:
1198 gtk_window_set_default_size_internal (window,
1199 TRUE, g_value_get_int (value),
1202 case PROP_DEFAULT_HEIGHT:
1203 gtk_window_set_default_size_internal (window,
1205 TRUE, g_value_get_int (value), FALSE);
1207 case PROP_DESTROY_WITH_PARENT:
1208 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1211 gtk_window_set_icon (window,
1212 g_value_get_object (value));
1214 case PROP_ICON_NAME:
1215 gtk_window_set_icon_name (window, g_value_get_string (value));
1218 gtk_window_set_screen (window, g_value_get_object (value));
1220 case PROP_TYPE_HINT:
1221 gtk_window_set_type_hint (window,
1222 g_value_get_enum (value));
1224 case PROP_SKIP_TASKBAR_HINT:
1225 gtk_window_set_skip_taskbar_hint (window,
1226 g_value_get_boolean (value));
1228 case PROP_SKIP_PAGER_HINT:
1229 gtk_window_set_skip_pager_hint (window,
1230 g_value_get_boolean (value));
1232 case PROP_URGENCY_HINT:
1233 gtk_window_set_urgency_hint (window,
1234 g_value_get_boolean (value));
1236 case PROP_ACCEPT_FOCUS:
1237 gtk_window_set_accept_focus (window,
1238 g_value_get_boolean (value));
1240 case PROP_FOCUS_ON_MAP:
1241 gtk_window_set_focus_on_map (window,
1242 g_value_get_boolean (value));
1244 case PROP_DECORATED:
1245 gtk_window_set_decorated (window, g_value_get_boolean (value));
1247 case PROP_DELETABLE:
1248 gtk_window_set_deletable (window, g_value_get_boolean (value));
1251 gtk_window_set_gravity (window, g_value_get_enum (value));
1253 case PROP_TRANSIENT_FOR:
1254 gtk_window_set_transient_for (window, g_value_get_object (value));
1257 gtk_window_set_opacity (window, g_value_get_double (value));
1259 case PROP_HAS_RESIZE_GRIP:
1260 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1262 case PROP_APPLICATION:
1263 gtk_window_set_application (window, g_value_get_object (value));
1265 case PROP_MNEMONICS_VISIBLE:
1266 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1268 case PROP_FOCUS_VISIBLE:
1269 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1272 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1278 gtk_window_get_property (GObject *object,
1283 GtkWindow *window = GTK_WINDOW (object);
1284 GtkWindowPrivate *priv = window->priv;
1288 GtkWindowGeometryInfo *info;
1290 g_value_set_enum (value, priv->type);
1293 g_value_set_string (value, priv->wm_role);
1296 g_value_set_string (value, priv->title);
1298 case PROP_RESIZABLE:
1299 g_value_set_boolean (value, priv->resizable);
1302 g_value_set_boolean (value, priv->modal);
1305 g_value_set_enum (value, priv->position);
1307 case PROP_DEFAULT_WIDTH:
1308 info = gtk_window_get_geometry_info (window, FALSE);
1310 g_value_set_int (value, -1);
1312 g_value_set_int (value, info->default_width);
1314 case PROP_DEFAULT_HEIGHT:
1315 info = gtk_window_get_geometry_info (window, FALSE);
1317 g_value_set_int (value, -1);
1319 g_value_set_int (value, info->default_height);
1321 case PROP_DESTROY_WITH_PARENT:
1322 g_value_set_boolean (value, priv->destroy_with_parent);
1325 g_value_set_object (value, gtk_window_get_icon (window));
1327 case PROP_ICON_NAME:
1328 g_value_set_string (value, gtk_window_get_icon_name (window));
1331 g_value_set_object (value, priv->screen);
1333 case PROP_IS_ACTIVE:
1334 g_value_set_boolean (value, priv->is_active);
1336 case PROP_HAS_TOPLEVEL_FOCUS:
1337 g_value_set_boolean (value, priv->has_toplevel_focus);
1339 case PROP_TYPE_HINT:
1340 g_value_set_enum (value, priv->type_hint);
1342 case PROP_SKIP_TASKBAR_HINT:
1343 g_value_set_boolean (value,
1344 gtk_window_get_skip_taskbar_hint (window));
1346 case PROP_SKIP_PAGER_HINT:
1347 g_value_set_boolean (value,
1348 gtk_window_get_skip_pager_hint (window));
1350 case PROP_URGENCY_HINT:
1351 g_value_set_boolean (value,
1352 gtk_window_get_urgency_hint (window));
1354 case PROP_ACCEPT_FOCUS:
1355 g_value_set_boolean (value,
1356 gtk_window_get_accept_focus (window));
1358 case PROP_FOCUS_ON_MAP:
1359 g_value_set_boolean (value,
1360 gtk_window_get_focus_on_map (window));
1362 case PROP_DECORATED:
1363 g_value_set_boolean (value, gtk_window_get_decorated (window));
1365 case PROP_DELETABLE:
1366 g_value_set_boolean (value, gtk_window_get_deletable (window));
1369 g_value_set_enum (value, gtk_window_get_gravity (window));
1371 case PROP_TRANSIENT_FOR:
1372 g_value_set_object (value, gtk_window_get_transient_for (window));
1375 g_value_set_double (value, gtk_window_get_opacity (window));
1377 case PROP_HAS_RESIZE_GRIP:
1378 g_value_set_boolean (value, priv->has_resize_grip);
1380 case PROP_RESIZE_GRIP_VISIBLE:
1381 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1383 case PROP_APPLICATION:
1384 g_value_set_object (value, gtk_window_get_application (window));
1386 case PROP_MNEMONICS_VISIBLE:
1387 g_value_set_boolean (value, priv->mnemonics_visible);
1389 case PROP_FOCUS_VISIBLE:
1390 g_value_set_boolean (value, priv->focus_visible);
1393 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1399 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1401 parent_buildable_iface = g_type_interface_peek_parent (iface);
1402 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1403 iface->parser_finished = gtk_window_buildable_parser_finished;
1404 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1405 iface->custom_finished = gtk_window_buildable_custom_finished;
1409 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1410 GtkBuilder *builder,
1412 const GValue *value)
1414 GtkWindow *window = GTK_WINDOW (buildable);
1415 GtkWindowPrivate *priv = window->priv;
1417 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1418 priv->builder_visible = TRUE;
1420 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1424 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1425 GtkBuilder *builder)
1427 GtkWindow *window = GTK_WINDOW (buildable);
1428 GtkWindowPrivate *priv = window->priv;
1432 if (priv->builder_visible)
1433 gtk_widget_show (GTK_WIDGET (buildable));
1435 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1436 for (l = accels; l; l = l->next)
1438 object = gtk_builder_get_object (builder, l->data);
1441 g_warning ("Unknown accel group %s specified in window %s",
1442 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1445 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1446 GTK_ACCEL_GROUP (object));
1450 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1452 parent_buildable_iface->parser_finished (buildable, builder);
1458 } GSListSubParserData;
1461 window_start_element (GMarkupParseContext *context,
1462 const gchar *element_name,
1463 const gchar **names,
1464 const gchar **values,
1469 GSListSubParserData *data = (GSListSubParserData*)user_data;
1471 if (strcmp (element_name, "group") == 0)
1473 for (i = 0; names[i]; i++)
1475 if (strcmp (names[i], "name") == 0)
1476 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1479 else if (strcmp (element_name, "accel-groups") == 0)
1482 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1487 static const GMarkupParser window_parser =
1489 window_start_element
1493 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1494 GtkBuilder *builder,
1496 const gchar *tagname,
1497 GMarkupParser *parser,
1500 GSListSubParserData *parser_data;
1502 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1503 tagname, parser, data))
1506 if (strcmp (tagname, "accel-groups") == 0)
1508 parser_data = g_slice_new0 (GSListSubParserData);
1509 parser_data->items = NULL;
1510 parser_data->object = G_OBJECT (buildable);
1512 *parser = window_parser;
1513 *data = parser_data;
1521 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1522 GtkBuilder *builder,
1524 const gchar *tagname,
1527 GSListSubParserData *data;
1529 parent_buildable_iface->custom_finished (buildable, builder, child,
1530 tagname, user_data);
1532 if (strcmp (tagname, "accel-groups") != 0)
1535 data = (GSListSubParserData*)user_data;
1537 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1538 data->items, (GDestroyNotify) g_slist_free);
1540 g_slice_free (GSListSubParserData, data);
1545 * @type: type of window
1547 * Creates a new #GtkWindow, which is a toplevel window that can
1548 * contain other widgets. Nearly always, the type of the window should
1549 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1550 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1551 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1552 * dialogs, though in some other toolkits dialogs are called "popups".
1553 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1554 * On X11, popup windows are not controlled by the <link
1555 * linkend="gtk-X11-arch">window manager</link>.
1557 * If you simply want an undecorated window (no window borders), use
1558 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1560 * Return value: a new #GtkWindow.
1563 gtk_window_new (GtkWindowType type)
1565 GtkWindowPrivate *priv;
1568 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1570 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1571 priv = window->priv;
1575 return GTK_WIDGET (window);
1579 * gtk_window_set_title:
1580 * @window: a #GtkWindow
1581 * @title: title of the window
1583 * Sets the title of the #GtkWindow. The title of a window will be
1584 * displayed in its title bar; on the X Window System, the title bar
1585 * is rendered by the <link linkend="gtk-X11-arch">window
1586 * manager</link>, so exactly how the title appears to users may vary
1587 * according to a user's exact configuration. The title should help a
1588 * user distinguish this window from other windows they may have
1589 * open. A good title might include the application name and current
1590 * document filename, for example.
1594 gtk_window_set_title (GtkWindow *window,
1597 GtkWindowPrivate *priv;
1601 g_return_if_fail (GTK_IS_WINDOW (window));
1603 priv = window->priv;
1604 widget = GTK_WIDGET (window);
1606 new_title = g_strdup (title);
1607 g_free (priv->title);
1608 priv->title = new_title;
1610 if (gtk_widget_get_realized (widget))
1612 gdk_window_set_title (gtk_widget_get_window (widget),
1616 g_object_notify (G_OBJECT (window), "title");
1620 * gtk_window_get_title:
1621 * @window: a #GtkWindow
1623 * Retrieves the title of the window. See gtk_window_set_title().
1625 * Return value: the title of the window, or %NULL if none has
1626 * been set explicitely. The returned string is owned by the widget
1627 * and must not be modified or freed.
1630 gtk_window_get_title (GtkWindow *window)
1632 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1634 return window->priv->title;
1638 * gtk_window_set_wmclass:
1639 * @window: a #GtkWindow
1640 * @wmclass_name: window name hint
1641 * @wmclass_class: window class hint
1643 * Don't use this function. It sets the X Window System "class" and
1644 * "name" hints for a window. According to the ICCCM, you should
1645 * always set these to the same value for all windows in an
1646 * application, and GTK+ sets them to that value by default, so calling
1647 * this function is sort of pointless. However, you may want to call
1648 * gtk_window_set_role() on each window in your application, for the
1649 * benefit of the session manager. Setting the role allows the window
1650 * manager to restore window positions when loading a saved session.
1654 gtk_window_set_wmclass (GtkWindow *window,
1655 const gchar *wmclass_name,
1656 const gchar *wmclass_class)
1658 GtkWindowPrivate *priv;
1660 g_return_if_fail (GTK_IS_WINDOW (window));
1662 priv = window->priv;
1664 g_free (priv->wmclass_name);
1665 priv->wmclass_name = g_strdup (wmclass_name);
1667 g_free (priv->wmclass_class);
1668 priv->wmclass_class = g_strdup (wmclass_class);
1670 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1671 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1675 * gtk_window_set_role:
1676 * @window: a #GtkWindow
1677 * @role: unique identifier for the window to be used when restoring a session
1679 * This function is only useful on X11, not with other GTK+ targets.
1681 * In combination with the window title, the window role allows a
1682 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1683 * same" window when an application is restarted. So for example you
1684 * might set the "toolbox" role on your app's toolbox window, so that
1685 * when the user restarts their session, the window manager can put
1686 * the toolbox back in the same place.
1688 * If a window already has a unique title, you don't need to set the
1689 * role, since the WM can use the title to identify the window when
1690 * restoring the session.
1694 gtk_window_set_role (GtkWindow *window,
1697 GtkWindowPrivate *priv;
1700 g_return_if_fail (GTK_IS_WINDOW (window));
1702 priv = window->priv;
1704 new_role = g_strdup (role);
1705 g_free (priv->wm_role);
1706 priv->wm_role = new_role;
1708 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1709 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1712 g_object_notify (G_OBJECT (window), "role");
1716 * gtk_window_set_startup_id:
1717 * @window: a #GtkWindow
1718 * @startup_id: a string with startup-notification identifier
1720 * Startup notification identifiers are used by desktop environment to
1721 * track application startup, to provide user feedback and other
1722 * features. This function changes the corresponding property on the
1723 * underlying GdkWindow. Normally, startup identifier is managed
1724 * automatically and you should only use this function in special cases
1725 * like transferring focus from other processes. You should use this
1726 * function before calling gtk_window_present() or any equivalent
1727 * function generating a window map event.
1729 * This function is only useful on X11, not with other GTK+ targets.
1734 gtk_window_set_startup_id (GtkWindow *window,
1735 const gchar *startup_id)
1737 GtkWindowPrivate *priv;
1740 g_return_if_fail (GTK_IS_WINDOW (window));
1742 priv = window->priv;
1743 widget = GTK_WIDGET (window);
1745 g_free (priv->startup_id);
1746 priv->startup_id = g_strdup (startup_id);
1748 if (gtk_widget_get_realized (widget))
1750 GdkWindow *gdk_window;
1751 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1753 gdk_window = gtk_widget_get_window (widget);
1755 #ifdef GDK_WINDOWING_X11
1756 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1757 gdk_x11_window_set_user_time (gdk_window, timestamp);
1760 /* Here we differentiate real and "fake" startup notification IDs,
1761 * constructed on purpose just to pass interaction timestamp
1763 if (startup_id_is_fake (priv->startup_id))
1764 gtk_window_present_with_time (window, timestamp);
1767 gdk_window_set_startup_id (gdk_window,
1770 /* If window is mapped, terminate the startup-notification too */
1771 if (gtk_widget_get_mapped (widget) &&
1772 !disable_startup_notification)
1773 gdk_notify_startup_complete_with_id (priv->startup_id);
1777 g_object_notify (G_OBJECT (window), "startup-id");
1781 * gtk_window_get_role:
1782 * @window: a #GtkWindow
1784 * Returns the role of the window. See gtk_window_set_role() for
1785 * further explanation.
1787 * Return value: the role of the window if set, or %NULL. The
1788 * returned is owned by the widget and must not be modified
1792 gtk_window_get_role (GtkWindow *window)
1794 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1796 return window->priv->wm_role;
1800 * gtk_window_set_focus:
1801 * @window: a #GtkWindow
1802 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1803 * any focus widget for the toplevel window.
1805 * If @focus is not the current focus widget, and is focusable, sets
1806 * it as the focus widget for the window. If @focus is %NULL, unsets
1807 * the focus widget for this window. To set the focus to a particular
1808 * widget in the toplevel, it is usually more convenient to use
1809 * gtk_widget_grab_focus() instead of this function.
1812 gtk_window_set_focus (GtkWindow *window,
1815 GtkWindowPrivate *priv;
1818 g_return_if_fail (GTK_IS_WINDOW (window));
1820 priv = window->priv;
1824 g_return_if_fail (GTK_IS_WIDGET (focus));
1825 g_return_if_fail (gtk_widget_get_can_focus (focus));
1829 gtk_widget_grab_focus (focus);
1832 /* Clear the existing focus chain, so that when we focus into
1833 * the window again, we start at the beginnning.
1835 GtkWidget *widget = priv->focus_widget;
1838 while ((parent = gtk_widget_get_parent (widget)))
1841 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1845 _gtk_window_internal_set_focus (window, NULL);
1850 _gtk_window_internal_set_focus (GtkWindow *window,
1853 GtkWindowPrivate *priv;
1855 g_return_if_fail (GTK_IS_WINDOW (window));
1857 priv = window->priv;
1859 if ((priv->focus_widget != focus) ||
1860 (focus && !gtk_widget_has_focus (focus)))
1861 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1865 * gtk_window_set_default:
1866 * @window: a #GtkWindow
1867 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1868 * default widget for the toplevel.
1870 * The default widget is the widget that's activated when the user
1871 * presses Enter in a dialog (for example). This function sets or
1872 * unsets the default widget for a #GtkWindow about. When setting
1873 * (rather than unsetting) the default widget it's generally easier to
1874 * call gtk_widget_grab_focus() on the widget. Before making a widget
1875 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1876 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1879 gtk_window_set_default (GtkWindow *window,
1880 GtkWidget *default_widget)
1882 GtkWindowPrivate *priv;
1884 g_return_if_fail (GTK_IS_WINDOW (window));
1886 priv = window->priv;
1889 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1891 if (priv->default_widget != default_widget)
1893 GtkWidget *old_default_widget = NULL;
1896 g_object_ref (default_widget);
1898 if (priv->default_widget)
1900 old_default_widget = priv->default_widget;
1902 if (priv->focus_widget != priv->default_widget ||
1903 !gtk_widget_get_receives_default (priv->default_widget))
1904 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1906 gtk_widget_queue_draw (priv->default_widget);
1909 priv->default_widget = default_widget;
1911 if (priv->default_widget)
1913 if (priv->focus_widget == NULL ||
1914 !gtk_widget_get_receives_default (priv->focus_widget))
1915 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1917 gtk_widget_queue_draw (priv->default_widget);
1920 if (old_default_widget)
1921 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1925 g_object_notify (G_OBJECT (default_widget), "has-default");
1926 g_object_unref (default_widget);
1932 * gtk_window_get_default_widget:
1933 * @window: a #GtkWindow
1935 * Returns the default widget for @window. See gtk_window_set_default()
1938 * Returns: (transfer none): the default widget, or %NULL if there is none.
1943 gtk_window_get_default_widget (GtkWindow *window)
1945 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1947 return window->priv->default_widget;
1951 handle_keys_changed (gpointer data)
1953 GtkWindow *window = GTK_WINDOW (data);
1954 GtkWindowPrivate *priv = window->priv;
1956 if (priv->keys_changed_handler)
1958 g_source_remove (priv->keys_changed_handler);
1959 priv->keys_changed_handler = 0;
1962 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1968 gtk_window_notify_keys_changed (GtkWindow *window)
1970 GtkWindowPrivate *priv = window->priv;
1972 if (!priv->keys_changed_handler)
1973 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1977 * gtk_window_add_accel_group:
1978 * @window: window to attach accelerator group to
1979 * @accel_group: a #GtkAccelGroup
1981 * Associate @accel_group with @window, such that calling
1982 * gtk_accel_groups_activate() on @window will activate accelerators
1986 gtk_window_add_accel_group (GtkWindow *window,
1987 GtkAccelGroup *accel_group)
1989 g_return_if_fail (GTK_IS_WINDOW (window));
1990 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1992 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1993 g_signal_connect_object (accel_group, "accel-changed",
1994 G_CALLBACK (gtk_window_notify_keys_changed),
1995 window, G_CONNECT_SWAPPED);
1996 gtk_window_notify_keys_changed (window);
2000 * gtk_window_remove_accel_group:
2001 * @window: a #GtkWindow
2002 * @accel_group: a #GtkAccelGroup
2004 * Reverses the effects of gtk_window_add_accel_group().
2007 gtk_window_remove_accel_group (GtkWindow *window,
2008 GtkAccelGroup *accel_group)
2010 g_return_if_fail (GTK_IS_WINDOW (window));
2011 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2013 g_signal_handlers_disconnect_by_func (accel_group,
2014 gtk_window_notify_keys_changed,
2016 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2017 gtk_window_notify_keys_changed (window);
2020 static GtkMnemonicHash *
2021 gtk_window_get_mnemonic_hash (GtkWindow *window,
2024 GtkWindowPrivate *private = window->priv;
2026 if (!private->mnemonic_hash && create)
2027 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2029 return private->mnemonic_hash;
2033 * gtk_window_add_mnemonic:
2034 * @window: a #GtkWindow
2035 * @keyval: the mnemonic
2036 * @target: the widget that gets activated by the mnemonic
2038 * Adds a mnemonic to this window.
2041 gtk_window_add_mnemonic (GtkWindow *window,
2045 g_return_if_fail (GTK_IS_WINDOW (window));
2046 g_return_if_fail (GTK_IS_WIDGET (target));
2048 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2050 gtk_window_notify_keys_changed (window);
2054 * gtk_window_remove_mnemonic:
2055 * @window: a #GtkWindow
2056 * @keyval: the mnemonic
2057 * @target: the widget that gets activated by the mnemonic
2059 * Removes a mnemonic from this window.
2062 gtk_window_remove_mnemonic (GtkWindow *window,
2066 g_return_if_fail (GTK_IS_WINDOW (window));
2067 g_return_if_fail (GTK_IS_WIDGET (target));
2069 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2071 gtk_window_notify_keys_changed (window);
2075 * gtk_window_mnemonic_activate:
2076 * @window: a #GtkWindow
2077 * @keyval: the mnemonic
2078 * @modifier: the modifiers
2080 * Activates the targets associated with the mnemonic.
2082 * Returns: %TRUE if the activation is done.
2085 gtk_window_mnemonic_activate (GtkWindow *window,
2087 GdkModifierType modifier)
2089 GtkWindowPrivate *priv;
2091 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2093 priv = window->priv;
2095 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2097 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2099 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2106 * gtk_window_set_mnemonic_modifier:
2107 * @window: a #GtkWindow
2108 * @modifier: the modifier mask used to activate
2109 * mnemonics on this window.
2111 * Sets the mnemonic modifier for this window.
2114 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2115 GdkModifierType modifier)
2117 GtkWindowPrivate *priv;
2119 g_return_if_fail (GTK_IS_WINDOW (window));
2120 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2122 priv = window->priv;
2124 priv->mnemonic_modifier = modifier;
2125 gtk_window_notify_keys_changed (window);
2129 * gtk_window_get_mnemonic_modifier:
2130 * @window: a #GtkWindow
2132 * Returns the mnemonic modifier for this window. See
2133 * gtk_window_set_mnemonic_modifier().
2135 * Return value: the modifier mask used to activate
2136 * mnemonics on this window.
2139 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2141 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2143 return window->priv->mnemonic_modifier;
2147 * gtk_window_set_position:
2148 * @window: a #GtkWindow.
2149 * @position: a position constraint.
2151 * Sets a position constraint for this window. If the old or new
2152 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2153 * the window to be repositioned to satisfy the new constraint.
2156 gtk_window_set_position (GtkWindow *window,
2157 GtkWindowPosition position)
2159 GtkWindowPrivate *priv;
2161 g_return_if_fail (GTK_IS_WINDOW (window));
2163 priv = window->priv;
2165 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2166 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2168 GtkWindowGeometryInfo *info;
2170 info = gtk_window_get_geometry_info (window, TRUE);
2172 /* this flag causes us to re-request the CENTER_ALWAYS
2173 * constraint in gtk_window_move_resize(), see
2174 * comment in that function.
2176 info->position_constraints_changed = TRUE;
2178 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2181 priv->position = position;
2183 g_object_notify (G_OBJECT (window), "window-position");
2187 * gtk_window_activate_focus:
2188 * @window: a #GtkWindow
2190 * Activates the current focused widget within the window.
2192 * Return value: %TRUE if a widget got activated.
2195 gtk_window_activate_focus (GtkWindow *window)
2197 GtkWindowPrivate *priv;
2199 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2201 priv = window->priv;
2203 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2204 return gtk_widget_activate (priv->focus_widget);
2210 * gtk_window_get_focus:
2211 * @window: a #GtkWindow
2213 * Retrieves the current focused widget within the window.
2214 * Note that this is the widget that would have the focus
2215 * if the toplevel window focused; if the toplevel window
2216 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2217 * not be %TRUE for the widget.
2219 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2222 gtk_window_get_focus (GtkWindow *window)
2224 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2226 return window->priv->focus_widget;
2230 * gtk_window_activate_default:
2231 * @window: a #GtkWindow
2233 * Activates the default widget for the window, unless the current
2234 * focused widget has been configured to receive the default action
2235 * (see gtk_widget_set_receives_default()), in which case the
2236 * focused widget is activated.
2238 * Return value: %TRUE if a widget got activated.
2241 gtk_window_activate_default (GtkWindow *window)
2243 GtkWindowPrivate *priv;
2245 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2247 priv = window->priv;
2249 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2250 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2251 return gtk_widget_activate (priv->default_widget);
2252 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2253 return gtk_widget_activate (priv->focus_widget);
2259 * gtk_window_set_modal:
2260 * @window: a #GtkWindow
2261 * @modal: whether the window is modal
2263 * Sets a window modal or non-modal. Modal windows prevent interaction
2264 * with other windows in the same application. To keep modal dialogs
2265 * on top of main application windows, use
2266 * gtk_window_set_transient_for() to make the dialog transient for the
2267 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2268 * will then disallow lowering the dialog below the parent.
2273 gtk_window_set_modal (GtkWindow *window,
2276 GtkWindowPrivate *priv;
2279 g_return_if_fail (GTK_IS_WINDOW (window));
2281 priv = window->priv;
2283 modal = modal != FALSE;
2284 if (priv->modal == modal)
2287 priv->modal = modal;
2288 widget = GTK_WIDGET (window);
2290 /* adjust desired modality state */
2291 if (gtk_widget_get_realized (widget))
2294 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2296 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2299 if (gtk_widget_get_visible (widget))
2302 gtk_grab_add (widget);
2304 gtk_grab_remove (widget);
2307 g_object_notify (G_OBJECT (window), "modal");
2311 * gtk_window_get_modal:
2312 * @window: a #GtkWindow
2314 * Returns whether the window is modal. See gtk_window_set_modal().
2316 * Return value: %TRUE if the window is set to be modal and
2317 * establishes a grab when shown
2320 gtk_window_get_modal (GtkWindow *window)
2322 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2324 return window->priv->modal;
2328 * gtk_window_list_toplevels:
2330 * Returns a list of all existing toplevel windows. The widgets
2331 * in the list are not individually referenced. If you want
2332 * to iterate through the list and perform actions involving
2333 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2334 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2335 * then unref all the widgets afterwards.
2337 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2340 gtk_window_list_toplevels (void)
2345 for (slist = toplevel_list; slist; slist = slist->next)
2346 list = g_list_prepend (list, slist->data);
2352 gtk_window_dispose (GObject *object)
2354 GtkWindow *window = GTK_WINDOW (object);
2356 gtk_window_set_focus (window, NULL);
2357 gtk_window_set_default (window, NULL);
2359 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2363 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2365 gtk_widget_destroy (GTK_WIDGET (child));
2369 connect_parent_destroyed (GtkWindow *window)
2371 GtkWindowPrivate *priv = window->priv;
2373 if (priv->transient_parent)
2375 g_signal_connect (priv->transient_parent,
2377 G_CALLBACK (parent_destroyed_callback),
2383 disconnect_parent_destroyed (GtkWindow *window)
2385 GtkWindowPrivate *priv = window->priv;
2387 if (priv->transient_parent)
2389 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2390 parent_destroyed_callback,
2396 gtk_window_transient_parent_realized (GtkWidget *parent,
2399 if (gtk_widget_get_realized (window))
2400 gdk_window_set_transient_for (gtk_widget_get_window (window),
2401 gtk_widget_get_window (parent));
2405 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2408 if (gtk_widget_get_realized (window))
2409 gdk_property_delete (gtk_widget_get_window (window),
2410 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2414 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2418 gtk_window_set_screen (window, parent->priv->screen);
2422 gtk_window_unset_transient_for (GtkWindow *window)
2424 GtkWindowPrivate *priv = window->priv;
2426 if (priv->transient_parent)
2428 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2429 gtk_window_transient_parent_realized,
2431 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2432 gtk_window_transient_parent_unrealized,
2434 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2435 gtk_window_transient_parent_screen_changed,
2437 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2438 gtk_widget_destroyed,
2439 &priv->transient_parent);
2441 if (priv->destroy_with_parent)
2442 disconnect_parent_destroyed (window);
2444 priv->transient_parent = NULL;
2446 if (priv->transient_parent_group)
2448 priv->transient_parent_group = FALSE;
2449 gtk_window_group_remove_window (priv->group,
2456 * gtk_window_set_transient_for:
2457 * @window: a #GtkWindow
2458 * @parent: (allow-none): parent window, or %NULL
2460 * Dialog windows should be set transient for the main application
2461 * window they were spawned from. This allows <link
2462 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2463 * dialog on top of the main window, or center the dialog over the
2464 * main window. gtk_dialog_new_with_buttons() and other convenience
2465 * functions in GTK+ will sometimes call
2466 * gtk_window_set_transient_for() on your behalf.
2468 * Passing %NULL for @parent unsets the current transient window.
2470 * On Windows, this function puts the child window on top of the parent,
2471 * much as the window manager would have done on X.
2474 gtk_window_set_transient_for (GtkWindow *window,
2477 GtkWindowPrivate *priv;
2479 g_return_if_fail (GTK_IS_WINDOW (window));
2480 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2481 g_return_if_fail (window != parent);
2483 priv = window->priv;
2485 if (priv->transient_parent)
2487 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2488 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2489 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2490 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2491 GTK_WIDGET (window));
2493 gtk_window_unset_transient_for (window);
2496 priv->transient_parent = parent;
2500 g_signal_connect (parent, "destroy",
2501 G_CALLBACK (gtk_widget_destroyed),
2502 &priv->transient_parent);
2503 g_signal_connect (parent, "realize",
2504 G_CALLBACK (gtk_window_transient_parent_realized),
2506 g_signal_connect (parent, "unrealize",
2507 G_CALLBACK (gtk_window_transient_parent_unrealized),
2509 g_signal_connect (parent, "notify::screen",
2510 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2513 gtk_window_set_screen (window, parent->priv->screen);
2515 if (priv->destroy_with_parent)
2516 connect_parent_destroyed (window);
2518 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2519 gtk_widget_get_realized (GTK_WIDGET (parent)))
2520 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2521 GTK_WIDGET (window));
2523 if (parent->priv->group)
2525 gtk_window_group_add_window (parent->priv->group, window);
2526 priv->transient_parent_group = TRUE;
2532 * gtk_window_get_transient_for:
2533 * @window: a #GtkWindow
2535 * Fetches the transient parent for this window. See
2536 * gtk_window_set_transient_for().
2538 * Return value: (transfer none): the transient parent for this window, or %NULL
2539 * if no transient parent has been set.
2542 gtk_window_get_transient_for (GtkWindow *window)
2544 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2546 return window->priv->transient_parent;
2550 * gtk_window_set_opacity:
2551 * @window: a #GtkWindow
2552 * @opacity: desired opacity, between 0 and 1
2554 * Request the windowing system to make @window partially transparent,
2555 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2556 * of the opacity parameter are clamped to the [0,1] range.) On X11
2557 * this has any effect only on X screens with a compositing manager
2558 * running. See gtk_widget_is_composited(). On Windows it should work
2561 * Note that setting a window's opacity after the window has been
2562 * shown causes it to flicker once on Windows.
2567 gtk_window_set_opacity (GtkWindow *window,
2570 GtkWindowPrivate *priv;
2572 g_return_if_fail (GTK_IS_WINDOW (window));
2574 priv = window->priv;
2578 else if (opacity > 1.0)
2581 priv->opacity_set = TRUE;
2582 priv->opacity = opacity;
2584 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2585 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2590 * gtk_window_get_opacity:
2591 * @window: a #GtkWindow
2593 * Fetches the requested opacity for this window. See
2594 * gtk_window_set_opacity().
2596 * Return value: the requested opacity for this window.
2601 gtk_window_get_opacity (GtkWindow *window)
2603 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2605 return window->priv->opacity;
2609 * gtk_window_get_application:
2610 * @window: a #GtkWindow
2612 * Gets the #GtkApplication associated with the window (if any).
2614 * Return value: (transfer none): a #GtkApplication, or %NULL
2619 gtk_window_get_application (GtkWindow *window)
2621 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2623 return window->priv->application;
2627 gtk_window_release_application (GtkWindow *window)
2629 if (window->priv->application)
2631 GtkApplication *application;
2633 /* steal reference into temp variable */
2634 application = window->priv->application;
2635 window->priv->application = NULL;
2637 gtk_application_remove_window (application, window);
2638 g_object_unref (application);
2643 * gtk_window_set_application:
2644 * @window: a #GtkWindow
2645 * @application: (allow-none): a #GtkApplication, or %NULL
2647 * Sets or unsets the #GtkApplication associated with the window.
2649 * The application will be kept alive for at least as long as the window
2655 gtk_window_set_application (GtkWindow *window,
2656 GtkApplication *application)
2658 GtkWindowPrivate *priv;
2660 g_return_if_fail (GTK_IS_WINDOW (window));
2662 priv = window->priv;
2663 if (priv->application != application)
2665 gtk_window_release_application (window);
2667 priv->application = application;
2669 if (priv->application != NULL)
2671 g_object_ref (priv->application);
2673 gtk_application_add_window (priv->application, window);
2676 g_object_notify (G_OBJECT (window), "application");
2681 * gtk_window_set_type_hint:
2682 * @window: a #GtkWindow
2683 * @hint: the window type
2685 * By setting the type hint for the window, you allow the window
2686 * manager to decorate and handle the window in a way which is
2687 * suitable to the function of the window in your application.
2689 * This function should be called before the window becomes visible.
2691 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2692 * will sometimes call gtk_window_set_type_hint() on your behalf.
2696 gtk_window_set_type_hint (GtkWindow *window,
2697 GdkWindowTypeHint hint)
2699 GtkWindowPrivate *priv;
2701 g_return_if_fail (GTK_IS_WINDOW (window));
2702 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2704 priv = window->priv;
2706 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2707 priv->type_hint = hint;
2709 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2711 priv->reset_type_hint = TRUE;
2712 priv->gdk_type_hint = hint;
2716 * gtk_window_get_type_hint:
2717 * @window: a #GtkWindow
2719 * Gets the type hint for this window. See gtk_window_set_type_hint().
2721 * Return value: the type hint for @window.
2724 gtk_window_get_type_hint (GtkWindow *window)
2726 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2728 return window->priv->gdk_type_hint;
2732 * gtk_window_set_skip_taskbar_hint:
2733 * @window: a #GtkWindow
2734 * @setting: %TRUE to keep this window from appearing in the task bar
2736 * Windows may set a hint asking the desktop environment not to display
2737 * the window in the task bar. This function sets this hint.
2742 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2745 GtkWindowPrivate *priv;
2747 g_return_if_fail (GTK_IS_WINDOW (window));
2749 priv = window->priv;
2751 setting = setting != FALSE;
2753 if (priv->skips_taskbar != setting)
2755 priv->skips_taskbar = setting;
2756 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2757 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2758 priv->skips_taskbar);
2759 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2764 * gtk_window_get_skip_taskbar_hint:
2765 * @window: a #GtkWindow
2767 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2769 * Return value: %TRUE if window shouldn't be in taskbar
2774 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2776 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2778 return window->priv->skips_taskbar;
2782 * gtk_window_set_skip_pager_hint:
2783 * @window: a #GtkWindow
2784 * @setting: %TRUE to keep this window from appearing in the pager
2786 * Windows may set a hint asking the desktop environment not to display
2787 * the window in the pager. This function sets this hint.
2788 * (A "pager" is any desktop navigation tool such as a workspace
2789 * switcher that displays a thumbnail representation of the windows
2795 gtk_window_set_skip_pager_hint (GtkWindow *window,
2798 GtkWindowPrivate *priv;
2800 g_return_if_fail (GTK_IS_WINDOW (window));
2802 priv = window->priv;
2804 setting = setting != FALSE;
2806 if (priv->skips_pager != setting)
2808 priv->skips_pager = setting;
2809 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2810 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2812 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2817 * gtk_window_get_skip_pager_hint:
2818 * @window: a #GtkWindow
2820 * Gets the value set by gtk_window_set_skip_pager_hint().
2822 * Return value: %TRUE if window shouldn't be in pager
2827 gtk_window_get_skip_pager_hint (GtkWindow *window)
2829 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2831 return window->priv->skips_pager;
2835 * gtk_window_set_urgency_hint:
2836 * @window: a #GtkWindow
2837 * @setting: %TRUE to mark this window as urgent
2839 * Windows may set a hint asking the desktop environment to draw
2840 * the users attention to the window. This function sets this hint.
2845 gtk_window_set_urgency_hint (GtkWindow *window,
2848 GtkWindowPrivate *priv;
2850 g_return_if_fail (GTK_IS_WINDOW (window));
2852 priv = window->priv;
2854 setting = setting != FALSE;
2856 if (priv->urgent != setting)
2858 priv->urgent = setting;
2859 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2860 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2862 g_object_notify (G_OBJECT (window), "urgency-hint");
2867 * gtk_window_get_urgency_hint:
2868 * @window: a #GtkWindow
2870 * Gets the value set by gtk_window_set_urgency_hint()
2872 * Return value: %TRUE if window is urgent
2877 gtk_window_get_urgency_hint (GtkWindow *window)
2879 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2881 return window->priv->urgent;
2885 * gtk_window_set_accept_focus:
2886 * @window: a #GtkWindow
2887 * @setting: %TRUE to let this window receive input focus
2889 * Windows may set a hint asking the desktop environment not to receive
2890 * the input focus. This function sets this hint.
2895 gtk_window_set_accept_focus (GtkWindow *window,
2898 GtkWindowPrivate *priv;
2900 g_return_if_fail (GTK_IS_WINDOW (window));
2902 priv = window->priv;
2904 setting = setting != FALSE;
2906 if (priv->accept_focus != setting)
2908 priv->accept_focus = setting;
2909 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2910 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2911 priv->accept_focus);
2912 g_object_notify (G_OBJECT (window), "accept-focus");
2917 * gtk_window_get_accept_focus:
2918 * @window: a #GtkWindow
2920 * Gets the value set by gtk_window_set_accept_focus().
2922 * Return value: %TRUE if window should receive the input focus
2927 gtk_window_get_accept_focus (GtkWindow *window)
2929 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2931 return window->priv->accept_focus;
2935 * gtk_window_set_focus_on_map:
2936 * @window: a #GtkWindow
2937 * @setting: %TRUE to let this window receive input focus on map
2939 * Windows may set a hint asking the desktop environment not to receive
2940 * the input focus when the window is mapped. This function sets this
2946 gtk_window_set_focus_on_map (GtkWindow *window,
2949 GtkWindowPrivate *priv;
2951 g_return_if_fail (GTK_IS_WINDOW (window));
2953 priv = window->priv;
2955 setting = setting != FALSE;
2957 if (priv->focus_on_map != setting)
2959 priv->focus_on_map = setting;
2960 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2961 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2962 priv->focus_on_map);
2963 g_object_notify (G_OBJECT (window), "focus-on-map");
2968 * gtk_window_get_focus_on_map:
2969 * @window: a #GtkWindow
2971 * Gets the value set by gtk_window_set_focus_on_map().
2973 * Return value: %TRUE if window should receive the input focus when
2979 gtk_window_get_focus_on_map (GtkWindow *window)
2981 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2983 return window->priv->focus_on_map;
2987 * gtk_window_set_destroy_with_parent:
2988 * @window: a #GtkWindow
2989 * @setting: whether to destroy @window with its transient parent
2991 * If @setting is %TRUE, then destroying the transient parent of @window
2992 * will also destroy @window itself. This is useful for dialogs that
2993 * shouldn't persist beyond the lifetime of the main window they're
2994 * associated with, for example.
2997 gtk_window_set_destroy_with_parent (GtkWindow *window,
3000 GtkWindowPrivate *priv;
3002 g_return_if_fail (GTK_IS_WINDOW (window));
3004 priv = window->priv;
3006 if (priv->destroy_with_parent == (setting != FALSE))
3009 if (priv->destroy_with_parent)
3011 disconnect_parent_destroyed (window);
3015 connect_parent_destroyed (window);
3018 priv->destroy_with_parent = setting;
3020 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3024 * gtk_window_get_destroy_with_parent:
3025 * @window: a #GtkWindow
3027 * Returns whether the window will be destroyed with its transient parent. See
3028 * gtk_window_set_destroy_with_parent ().
3030 * Return value: %TRUE if the window will be destroyed with its transient parent.
3033 gtk_window_get_destroy_with_parent (GtkWindow *window)
3035 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3037 return window->priv->destroy_with_parent;
3040 static GtkWindowGeometryInfo*
3041 gtk_window_get_geometry_info (GtkWindow *window,
3044 GtkWindowPrivate *priv = window->priv;
3045 GtkWindowGeometryInfo *info;
3047 info = priv->geometry_info;
3048 if (!info && create)
3050 info = g_new0 (GtkWindowGeometryInfo, 1);
3052 info->default_width = -1;
3053 info->default_height = -1;
3054 info->resize_width = -1;
3055 info->resize_height = -1;
3056 info->initial_x = 0;
3057 info->initial_y = 0;
3058 info->initial_pos_set = FALSE;
3059 info->default_is_geometry = FALSE;
3060 info->position_constraints_changed = FALSE;
3061 info->last.configure_request.x = 0;
3062 info->last.configure_request.y = 0;
3063 info->last.configure_request.width = -1;
3064 info->last.configure_request.height = -1;
3065 info->widget = NULL;
3067 priv->geometry_info = info;
3074 * gtk_window_set_geometry_hints:
3075 * @window: a #GtkWindow
3076 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3077 * @geometry: (allow-none): struct containing geometry information or %NULL
3078 * @geom_mask: mask indicating which struct fields should be paid attention to
3080 * This function sets up hints about how a window can be resized by
3081 * the user. You can set a minimum and maximum size; allowed resize
3082 * increments (e.g. for xterm, you can only resize by the size of a
3083 * character); aspect ratios; and more. See the #GdkGeometry struct.
3087 gtk_window_set_geometry_hints (GtkWindow *window,
3088 GtkWidget *geometry_widget,
3089 GdkGeometry *geometry,
3090 GdkWindowHints geom_mask)
3092 GtkWindowGeometryInfo *info;
3094 g_return_if_fail (GTK_IS_WINDOW (window));
3095 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3097 info = gtk_window_get_geometry_info (window, TRUE);
3100 g_signal_handlers_disconnect_by_func (info->widget,
3101 gtk_widget_destroyed,
3104 info->widget = geometry_widget;
3106 g_signal_connect (geometry_widget, "destroy",
3107 G_CALLBACK (gtk_widget_destroyed),
3111 info->geometry = *geometry;
3113 /* We store gravity in priv->gravity not in the hints. */
3114 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3116 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3118 gtk_window_set_gravity (window, geometry->win_gravity);
3121 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3125 * gtk_window_set_decorated:
3126 * @window: a #GtkWindow
3127 * @setting: %TRUE to decorate the window
3129 * By default, windows are decorated with a title bar, resize
3130 * controls, etc. Some <link linkend="gtk-X11-arch">window
3131 * managers</link> allow GTK+ to disable these decorations, creating a
3132 * borderless window. If you set the decorated property to %FALSE
3133 * using this function, GTK+ will do its best to convince the window
3134 * manager not to decorate the window. Depending on the system, this
3135 * function may not have any effect when called on a window that is
3136 * already visible, so you should call it before calling gtk_widget_show().
3138 * On Windows, this function always works, since there's no window manager
3143 gtk_window_set_decorated (GtkWindow *window,
3146 GtkWindowPrivate *priv;
3147 GdkWindow *gdk_window;
3149 g_return_if_fail (GTK_IS_WINDOW (window));
3151 priv = window->priv;
3153 setting = setting != FALSE;
3155 if (setting == priv->decorated)
3158 priv->decorated = setting;
3160 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3163 if (priv->decorated)
3164 gdk_window_set_decorations (gdk_window,
3167 gdk_window_set_decorations (gdk_window,
3171 g_object_notify (G_OBJECT (window), "decorated");
3175 * gtk_window_get_decorated:
3176 * @window: a #GtkWindow
3178 * Returns whether the window has been set to have decorations
3179 * such as a title bar via gtk_window_set_decorated().
3181 * Return value: %TRUE if the window has been set to have decorations
3184 gtk_window_get_decorated (GtkWindow *window)
3186 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3188 return window->priv->decorated;
3192 * gtk_window_set_deletable:
3193 * @window: a #GtkWindow
3194 * @setting: %TRUE to decorate the window as deletable
3196 * By default, windows have a close button in the window frame. Some
3197 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3198 * disable this button. If you set the deletable property to %FALSE
3199 * using this function, GTK+ will do its best to convince the window
3200 * manager not to show a close button. Depending on the system, this
3201 * function may not have any effect when called on a window that is
3202 * already visible, so you should call it before calling gtk_window_show().
3204 * On Windows, this function always works, since there's no window manager
3210 gtk_window_set_deletable (GtkWindow *window,
3213 GtkWindowPrivate *priv;
3214 GdkWindow *gdk_window;
3216 g_return_if_fail (GTK_IS_WINDOW (window));
3218 priv = window->priv;
3220 setting = setting != FALSE;
3222 if (setting == priv->deletable)
3225 priv->deletable = setting;
3227 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3230 if (priv->deletable)
3231 gdk_window_set_functions (gdk_window,
3234 gdk_window_set_functions (gdk_window,
3235 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3238 g_object_notify (G_OBJECT (window), "deletable");
3242 * gtk_window_get_deletable:
3243 * @window: a #GtkWindow
3245 * Returns whether the window has been set to have a close button
3246 * via gtk_window_set_deletable().
3248 * Return value: %TRUE if the window has been set to have a close button
3253 gtk_window_get_deletable (GtkWindow *window)
3255 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3257 return window->priv->deletable;
3260 static GtkWindowIconInfo*
3261 get_icon_info (GtkWindow *window)
3263 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3267 free_icon_info (GtkWindowIconInfo *info)
3269 g_free (info->icon_name);
3270 g_slice_free (GtkWindowIconInfo, info);
3274 static GtkWindowIconInfo*
3275 ensure_icon_info (GtkWindow *window)
3277 GtkWindowIconInfo *info;
3279 info = get_icon_info (window);
3283 info = g_slice_new0 (GtkWindowIconInfo);
3284 g_object_set_qdata_full (G_OBJECT (window),
3285 quark_gtk_window_icon_info,
3287 (GDestroyNotify)free_icon_info);
3294 icon_list_from_theme (GtkWidget *widget,
3299 GtkIconTheme *icon_theme;
3304 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3306 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3309 for (i = 0; sizes[i]; i++)
3312 * We need an EWMH extension to handle scalable icons
3313 * by passing their name to the WM. For now just use a
3317 icon = gtk_icon_theme_load_icon (icon_theme, name,
3320 icon = gtk_icon_theme_load_icon (icon_theme, name,
3323 list = g_list_append (list, icon);
3333 gtk_window_realize_icon (GtkWindow *window)
3335 GtkWindowPrivate *priv = window->priv;
3337 GtkWindowIconInfo *info;
3338 GdkWindow *gdk_window;
3341 widget = GTK_WIDGET (window);
3342 gdk_window = gtk_widget_get_window (widget);
3344 g_return_if_fail (gdk_window != NULL);
3346 /* no point setting an icon on override-redirect */
3347 if (priv->type == GTK_WINDOW_POPUP)
3352 info = ensure_icon_info (window);
3357 info->using_default_icon = FALSE;
3358 info->using_parent_icon = FALSE;
3359 info->using_themed_icon = FALSE;
3361 icon_list = info->icon_list;
3363 /* Look up themed icon */
3364 if (icon_list == NULL && info->icon_name)
3366 icon_list = icon_list_from_theme (widget, info->icon_name);
3368 info->using_themed_icon = TRUE;
3371 /* Inherit from transient parent */
3372 if (icon_list == NULL && priv->transient_parent)
3374 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3376 info->using_parent_icon = TRUE;
3379 /* Inherit from default */
3380 if (icon_list == NULL)
3382 icon_list = default_icon_list;
3384 info->using_default_icon = TRUE;
3387 /* Look up themed icon */
3388 if (icon_list == NULL && default_icon_name)
3390 icon_list = icon_list_from_theme (widget, default_icon_name);
3391 info->using_default_icon = TRUE;
3392 info->using_themed_icon = TRUE;
3395 info->realized = TRUE;
3397 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3399 if (info->using_themed_icon)
3401 GtkIconTheme *icon_theme;
3403 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3404 g_list_free (icon_list);
3406 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3407 g_signal_connect (icon_theme, "changed",
3408 G_CALLBACK (update_themed_icon), window);
3413 gtk_window_unrealize_icon (GtkWindow *window)
3415 GtkWindowIconInfo *info;
3417 info = get_icon_info (window);
3422 if (info->using_themed_icon)
3424 GtkIconTheme *icon_theme;
3426 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3428 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3431 /* We don't clear the properties on the window, just figure the
3432 * window is going away.
3435 info->realized = FALSE;
3440 * gtk_window_set_icon_list:
3441 * @window: a #GtkWindow
3442 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3444 * Sets up the icon representing a #GtkWindow. The 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 * gtk_window_set_icon_list() allows you to pass in the same icon in
3450 * several hand-drawn sizes. The list should contain the natural sizes
3451 * your icon is available in; that is, don't scale the image before
3452 * passing it to GTK+. Scaling is postponed until the last minute,
3453 * when the desired final size is known, to allow best quality.
3455 * By passing several sizes, you may improve the final image quality
3456 * of the icon, by reducing or eliminating automatic image scaling.
3458 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3459 * larger images (64x64, 128x128) if you have them.
3461 * See also gtk_window_set_default_icon_list() to set the icon
3462 * for all windows in your application in one go.
3464 * Note that transient windows (those who have been set transient for another
3465 * window using gtk_window_set_transient_for()) will inherit their
3466 * icon from their transient parent. So there's no need to explicitly
3467 * set the icon on transient windows.
3470 gtk_window_set_icon_list (GtkWindow *window,
3473 GtkWindowIconInfo *info;
3475 g_return_if_fail (GTK_IS_WINDOW (window));
3477 info = ensure_icon_info (window);
3479 if (info->icon_list == list) /* check for NULL mostly */
3482 g_list_foreach (list,
3483 (GFunc) g_object_ref, NULL);
3485 g_list_foreach (info->icon_list,
3486 (GFunc) g_object_unref, NULL);
3488 g_list_free (info->icon_list);
3490 info->icon_list = g_list_copy (list);
3492 g_object_notify (G_OBJECT (window), "icon");
3494 gtk_window_unrealize_icon (window);
3496 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3497 gtk_window_realize_icon (window);
3499 /* We could try to update our transient children, but I don't think
3500 * it's really worth it. If we did it, the best way would probably
3501 * be to have children connect to notify::icon-list
3506 * gtk_window_get_icon_list:
3507 * @window: a #GtkWindow
3509 * Retrieves the list of icons set by gtk_window_set_icon_list().
3510 * The list is copied, but the reference count on each
3511 * member won't be incremented.
3513 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3516 gtk_window_get_icon_list (GtkWindow *window)
3518 GtkWindowIconInfo *info;
3520 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3522 info = get_icon_info (window);
3525 return g_list_copy (info->icon_list);
3531 * gtk_window_set_icon:
3532 * @window: a #GtkWindow
3533 * @icon: (allow-none): icon image, or %NULL
3535 * Sets up the icon representing a #GtkWindow. This icon is used when
3536 * the window is minimized (also known as iconified). Some window
3537 * managers or desktop environments may also place it in the window
3538 * frame, or display it in other contexts.
3540 * The icon should be provided in whatever size it was naturally
3541 * drawn; that is, don't scale the image before passing it to
3542 * GTK+. Scaling is postponed until the last minute, when the desired
3543 * final size is known, to allow best quality.
3545 * If you have your icon hand-drawn in multiple sizes, use
3546 * gtk_window_set_icon_list(). Then the best size will be used.
3548 * This function is equivalent to calling gtk_window_set_icon_list()
3549 * with a 1-element list.
3551 * See also gtk_window_set_default_icon_list() to set the icon
3552 * for all windows in your application in one go.
3555 gtk_window_set_icon (GtkWindow *window,
3560 g_return_if_fail (GTK_IS_WINDOW (window));
3561 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3566 list = g_list_append (list, icon);
3568 gtk_window_set_icon_list (window, list);
3574 update_themed_icon (GtkIconTheme *icon_theme,
3577 g_object_notify (G_OBJECT (window), "icon");
3579 gtk_window_unrealize_icon (window);
3581 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3582 gtk_window_realize_icon (window);
3586 * gtk_window_set_icon_name:
3587 * @window: a #GtkWindow
3588 * @name: (allow-none): the name of the themed icon
3590 * Sets the icon for the window from a named themed icon. See
3591 * the docs for #GtkIconTheme for more details.
3593 * Note that this has nothing to do with the WM_ICON_NAME
3594 * property which is mentioned in the ICCCM.
3599 gtk_window_set_icon_name (GtkWindow *window,
3602 GtkWindowIconInfo *info;
3605 g_return_if_fail (GTK_IS_WINDOW (window));
3607 info = ensure_icon_info (window);
3609 if (g_strcmp0 (info->icon_name, name) == 0)
3612 tmp = info->icon_name;
3613 info->icon_name = g_strdup (name);
3616 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3617 g_list_free (info->icon_list);
3618 info->icon_list = NULL;
3620 update_themed_icon (NULL, window);
3622 g_object_notify (G_OBJECT (window), "icon-name");
3626 * gtk_window_get_icon_name:
3627 * @window: a #GtkWindow
3629 * Returns the name of the themed icon for the window,
3630 * see gtk_window_set_icon_name().
3632 * Returns: the icon name or %NULL if the window has
3638 gtk_window_get_icon_name (GtkWindow *window)
3640 GtkWindowIconInfo *info;
3642 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3644 info = ensure_icon_info (window);
3646 return info->icon_name;
3650 * gtk_window_get_icon:
3651 * @window: a #GtkWindow
3653 * Gets the value set by gtk_window_set_icon() (or if you've
3654 * called gtk_window_set_icon_list(), gets the first icon in
3657 * Return value: (transfer none): icon for window
3660 gtk_window_get_icon (GtkWindow *window)
3662 GtkWindowIconInfo *info;
3664 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3666 info = get_icon_info (window);
3667 if (info && info->icon_list)
3668 return GDK_PIXBUF (info->icon_list->data);
3673 /* Load pixbuf, printing warning on failure if error == NULL
3676 load_pixbuf_verbosely (const char *filename,
3679 GError *local_err = NULL;
3682 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3690 g_warning ("Error loading icon from file '%s':\n\t%s",
3691 filename, local_err->message);
3692 g_error_free (local_err);
3700 * gtk_window_set_icon_from_file:
3701 * @window: a #GtkWindow
3702 * @filename: (type filename): location of icon file
3703 * @err: (allow-none): location to store error, or %NULL.
3705 * Sets the icon for @window.
3706 * Warns on failure if @err is %NULL.
3708 * This function is equivalent to calling gtk_window_set_icon()
3709 * with a pixbuf created by loading the image from @filename.
3711 * Returns: %TRUE if setting the icon succeeded.
3716 gtk_window_set_icon_from_file (GtkWindow *window,
3717 const gchar *filename,
3720 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3724 gtk_window_set_icon (window, pixbuf);
3725 g_object_unref (pixbuf);
3734 * gtk_window_set_default_icon_list:
3735 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3737 * Sets an icon list to be used as fallback for windows that haven't
3738 * had gtk_window_set_icon_list() called on them to set up a
3739 * window-specific icon list. This function allows you to set up the
3740 * icon for all windows in your app at once.
3742 * See gtk_window_set_icon_list() for more details.
3746 gtk_window_set_default_icon_list (GList *list)
3750 if (list == default_icon_list)
3753 /* Update serial so we don't used cached pixmaps/masks
3755 default_icon_serial++;
3757 g_list_foreach (list,
3758 (GFunc) g_object_ref, NULL);
3760 g_list_foreach (default_icon_list,
3761 (GFunc) g_object_unref, NULL);
3763 g_list_free (default_icon_list);
3765 default_icon_list = g_list_copy (list);
3767 /* Update all toplevels */
3768 toplevels = gtk_window_list_toplevels ();
3769 tmp_list = toplevels;
3770 while (tmp_list != NULL)
3772 GtkWindowIconInfo *info;
3773 GtkWindow *w = tmp_list->data;
3775 info = get_icon_info (w);
3776 if (info && info->using_default_icon)
3778 gtk_window_unrealize_icon (w);
3779 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3780 gtk_window_realize_icon (w);
3783 tmp_list = tmp_list->next;
3785 g_list_free (toplevels);
3789 * gtk_window_set_default_icon:
3792 * Sets an icon to be used as fallback for windows that haven't
3793 * had gtk_window_set_icon() called on them from a pixbuf.
3798 gtk_window_set_default_icon (GdkPixbuf *icon)
3802 g_return_if_fail (GDK_IS_PIXBUF (icon));
3804 list = g_list_prepend (NULL, icon);
3805 gtk_window_set_default_icon_list (list);
3810 * gtk_window_set_default_icon_name:
3811 * @name: the name of the themed icon
3813 * Sets an icon to be used as fallback for windows that haven't
3814 * had gtk_window_set_icon_list() called on them from a named
3815 * themed icon, see gtk_window_set_icon_name().
3820 gtk_window_set_default_icon_name (const gchar *name)
3825 /* Update serial so we don't used cached pixmaps/masks
3827 default_icon_serial++;
3829 g_free (default_icon_name);
3830 default_icon_name = g_strdup (name);
3832 g_list_foreach (default_icon_list,
3833 (GFunc) g_object_unref, NULL);
3835 g_list_free (default_icon_list);
3836 default_icon_list = NULL;
3838 /* Update all toplevels */
3839 toplevels = gtk_window_list_toplevels ();
3840 tmp_list = toplevels;
3841 while (tmp_list != NULL)
3843 GtkWindowIconInfo *info;
3844 GtkWindow *w = tmp_list->data;
3846 info = get_icon_info (w);
3847 if (info && info->using_default_icon && info->using_themed_icon)
3849 gtk_window_unrealize_icon (w);
3850 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3851 gtk_window_realize_icon (w);
3854 tmp_list = tmp_list->next;
3856 g_list_free (toplevels);
3860 * gtk_window_get_default_icon_name:
3862 * Returns the fallback icon name for windows that has been set
3863 * with gtk_window_set_default_icon_name(). The returned
3864 * string is owned by GTK+ and should not be modified. It
3865 * is only valid until the next call to
3866 * gtk_window_set_default_icon_name().
3868 * Returns: the fallback icon name for windows
3873 gtk_window_get_default_icon_name (void)
3875 return default_icon_name;
3879 * gtk_window_set_default_icon_from_file:
3880 * @filename: (type filename): location of icon file
3881 * @err: (allow-none): location to store error, or %NULL.
3883 * Sets an icon to be used as fallback for windows that haven't
3884 * had gtk_window_set_icon_list() called on them from a file
3885 * on disk. Warns on failure if @err is %NULL.
3887 * Returns: %TRUE if setting the icon succeeded.
3892 gtk_window_set_default_icon_from_file (const gchar *filename,
3895 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3899 gtk_window_set_default_icon (pixbuf);
3900 g_object_unref (pixbuf);
3909 * gtk_window_get_default_icon_list:
3911 * Gets the value set by gtk_window_set_default_icon_list().
3912 * The list is a copy and should be freed with g_list_free(),
3913 * but the pixbufs in the list have not had their reference count
3916 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3919 gtk_window_get_default_icon_list (void)
3921 return g_list_copy (default_icon_list);
3925 gtk_window_set_default_size_internal (GtkWindow *window,
3926 gboolean change_width,
3928 gboolean change_height,
3930 gboolean is_geometry)
3932 GtkWindowGeometryInfo *info;
3934 g_return_if_fail (change_width == FALSE || width >= -1);
3935 g_return_if_fail (change_height == FALSE || height >= -1);
3937 info = gtk_window_get_geometry_info (window, TRUE);
3939 g_object_freeze_notify (G_OBJECT (window));
3941 info->default_is_geometry = is_geometry != FALSE;
3951 info->default_width = width;
3953 g_object_notify (G_OBJECT (window), "default-width");
3964 info->default_height = height;
3966 g_object_notify (G_OBJECT (window), "default-height");
3969 g_object_thaw_notify (G_OBJECT (window));
3971 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3975 * gtk_window_set_default_size:
3976 * @window: a #GtkWindow
3977 * @width: width in pixels, or -1 to unset the default width
3978 * @height: height in pixels, or -1 to unset the default height
3980 * Sets the default size of a window. If the window's "natural" size
3981 * (its size request) is larger than the default, the default will be
3982 * ignored. More generally, if the default size does not obey the
3983 * geometry hints for the window (gtk_window_set_geometry_hints() can
3984 * be used to set these explicitly), the default size will be clamped
3985 * to the nearest permitted size.
3987 * Unlike gtk_widget_set_size_request(), which sets a size request for
3988 * a widget and thus would keep users from shrinking the window, this
3989 * function only sets the initial size, just as if the user had
3990 * resized the window themselves. Users can still shrink the window
3991 * again as they normally would. Setting a default size of -1 means to
3992 * use the "natural" default size (the size request of the window).
3994 * For more control over a window's initial size and how resizing works,
3995 * investigate gtk_window_set_geometry_hints().
3997 * For some uses, gtk_window_resize() is a more appropriate function.
3998 * gtk_window_resize() changes the current size of the window, rather
3999 * than the size to be used on initial display. gtk_window_resize() always
4000 * affects the window itself, not the geometry widget.
4002 * The default size of a window only affects the first time a window is
4003 * shown; if a window is hidden and re-shown, it will remember the size
4004 * it had prior to hiding, rather than using the default size.
4006 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4007 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4010 gtk_window_set_default_size (GtkWindow *window,
4014 g_return_if_fail (GTK_IS_WINDOW (window));
4015 g_return_if_fail (width >= -1);
4016 g_return_if_fail (height >= -1);
4018 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4022 * gtk_window_set_default_geometry:
4023 * @window: a #GtkWindow
4024 * @width: width in resize increments, or -1 to unset the default width
4025 * @height: height in resize increments, or -1 to unset the default height
4027 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4028 * in terms of the base size and increment set with
4029 * gtk_window_set_geometry_hints.
4034 gtk_window_set_default_geometry (GtkWindow *window,
4038 g_return_if_fail (GTK_IS_WINDOW (window));
4039 g_return_if_fail (width >= -1);
4040 g_return_if_fail (height >= -1);
4042 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4046 * gtk_window_get_default_size:
4047 * @window: a #GtkWindow
4048 * @width: (out) (allow-none): location to store the default width, or %NULL
4049 * @height: (out) (allow-none): location to store the default height, or %NULL
4051 * Gets the default size of the window. A value of -1 for the width or
4052 * height indicates that a default size has not been explicitly set
4053 * for that dimension, so the "natural" size of the window will be
4058 gtk_window_get_default_size (GtkWindow *window,
4062 GtkWindowGeometryInfo *info;
4064 g_return_if_fail (GTK_IS_WINDOW (window));
4066 info = gtk_window_get_geometry_info (window, FALSE);
4069 *width = info ? info->default_width : -1;
4072 *height = info ? info->default_height : -1;
4076 * gtk_window_resize:
4077 * @window: a #GtkWindow
4078 * @width: width in pixels to resize the window to
4079 * @height: height in pixels to resize the window to
4081 * Resizes the window as if the user had done so, obeying geometry
4082 * constraints. The default geometry constraint is that windows may
4083 * not be smaller than their size request; to override this
4084 * constraint, call gtk_widget_set_size_request() to set the window's
4085 * request to a smaller value.
4087 * If gtk_window_resize() is called before showing a window for the
4088 * first time, it overrides any default size set with
4089 * gtk_window_set_default_size().
4091 * Windows may not be resized smaller than 1 by 1 pixels.
4095 gtk_window_resize (GtkWindow *window,
4099 GtkWindowGeometryInfo *info;
4101 g_return_if_fail (GTK_IS_WINDOW (window));
4102 g_return_if_fail (width > 0);
4103 g_return_if_fail (height > 0);
4105 info = gtk_window_get_geometry_info (window, TRUE);
4107 info->resize_width = width;
4108 info->resize_height = height;
4109 info->resize_is_geometry = FALSE;
4111 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4115 * gtk_window_resize_to_geometry:
4116 * @window: a #GtkWindow
4117 * @width: width in resize increments to resize the window to
4118 * @height: height in resize increments to resize the window to
4120 * Like gtk_window_resize(), but @width and @height are interpreted
4121 * in terms of the base size and increment set with
4122 * gtk_window_set_geometry_hints.
4127 gtk_window_resize_to_geometry (GtkWindow *window,
4131 GtkWindowGeometryInfo *info;
4133 g_return_if_fail (GTK_IS_WINDOW (window));
4134 g_return_if_fail (width > 0);
4135 g_return_if_fail (height > 0);
4137 info = gtk_window_get_geometry_info (window, TRUE);
4139 info->resize_width = width;
4140 info->resize_height = height;
4141 info->resize_is_geometry = TRUE;
4143 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4147 * gtk_window_get_size:
4148 * @window: a #GtkWindow
4149 * @width: (out) (allow-none): return location for width, or %NULL
4150 * @height: (out) (allow-none): return location for height, or %NULL
4152 * Obtains the current size of @window. If @window is not onscreen,
4153 * it returns the size GTK+ will suggest to the <link
4154 * linkend="gtk-X11-arch">window manager</link> for the initial window
4155 * size (but this is not reliably the same as the size the window
4156 * manager will actually select). The size obtained by
4157 * gtk_window_get_size() is the last size received in a
4158 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4159 * rather than querying the X server for the size. As a result, if you
4160 * call gtk_window_resize() then immediately call
4161 * gtk_window_get_size(), the size won't have taken effect yet. After
4162 * the window manager processes the resize request, GTK+ receives
4163 * notification that the size has changed via a configure event, and
4164 * the size of the window gets updated.
4166 * Note 1: Nearly any use of this function creates a race condition,
4167 * because the size of the window may change between the time that you
4168 * get the size and the time that you perform some action assuming
4169 * that size is the current size. To avoid race conditions, connect to
4170 * "configure-event" on the window and adjust your size-dependent
4171 * state to match the size delivered in the #GdkEventConfigure.
4173 * Note 2: The returned size does <emphasis>not</emphasis> include the
4174 * size of the window manager decorations (aka the window frame or
4175 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4176 * method of determining their size.
4178 * Note 3: If you are getting a window size in order to position
4179 * the window onscreen, there may be a better way. The preferred
4180 * way is to simply set the window's semantic type with
4181 * gtk_window_set_type_hint(), which allows the window manager to
4182 * e.g. center dialogs. Also, if you set the transient parent of
4183 * dialogs with gtk_window_set_transient_for() window managers
4184 * will often center the dialog over its parent window. It's
4185 * much preferred to let the window manager handle these
4186 * things rather than doing it yourself, because all apps will
4187 * behave consistently and according to user prefs if the window
4188 * manager handles it. Also, the window manager can take the size
4189 * of the window decorations/border into account, while your
4190 * application cannot.
4192 * In any case, if you insist on application-specified window
4193 * positioning, there's <emphasis>still</emphasis> a better way than
4194 * doing it yourself - gtk_window_set_position() will frequently
4195 * handle the details for you.
4199 gtk_window_get_size (GtkWindow *window,
4205 g_return_if_fail (GTK_IS_WINDOW (window));
4207 if (width == NULL && height == NULL)
4210 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4212 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4213 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4217 GdkRectangle configure_request;
4219 gtk_window_compute_configure_request (window,
4223 w = configure_request.width;
4224 h = configure_request.height;
4235 * @window: a #GtkWindow
4236 * @x: X coordinate to move window to
4237 * @y: Y coordinate to move window to
4239 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4240 * @window to the given position. Window managers are free to ignore
4241 * this; most window managers ignore requests for initial window
4242 * positions (instead using a user-defined placement algorithm) and
4243 * honor requests after the window has already been shown.
4245 * Note: the position is the position of the gravity-determined
4246 * reference point for the window. The gravity determines two things:
4247 * first, the location of the reference point in root window
4248 * coordinates; and second, which point on the window is positioned at
4249 * the reference point.
4251 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4252 * point is simply the @x, @y supplied to gtk_window_move(). The
4253 * top-left corner of the window decorations (aka window frame or
4254 * border) will be placed at @x, @y. Therefore, to position a window
4255 * at the top left of the screen, you want to use the default gravity
4256 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4258 * To position a window at the bottom right corner of the screen, you
4259 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4260 * point is at @x + the window width and @y + the window height, and
4261 * the bottom-right corner of the window border will be placed at that
4262 * reference point. So, to place a window in the bottom right corner
4263 * you would first set gravity to south east, then write:
4264 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4265 * gdk_screen_height () - window_height)</literal> (note that this
4266 * example does not take multi-head scenarios into account).
4268 * The Extended Window Manager Hints specification at <ulink
4269 * url="http://www.freedesktop.org/Standards/wm-spec">
4270 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4271 * nice table of gravities in the "implementation notes" section.
4273 * The gtk_window_get_position() documentation may also be relevant.
4276 gtk_window_move (GtkWindow *window,
4280 GtkWindowGeometryInfo *info;
4283 g_return_if_fail (GTK_IS_WINDOW (window));
4285 widget = GTK_WIDGET (window);
4287 info = gtk_window_get_geometry_info (window, TRUE);
4289 if (gtk_widget_get_mapped (widget))
4291 GtkAllocation allocation;
4293 gtk_widget_get_allocation (widget, &allocation);
4295 /* we have now sent a request with this position
4296 * with currently-active constraints, so toggle flag.
4298 info->position_constraints_changed = FALSE;
4300 /* we only constrain if mapped - if not mapped,
4301 * then gtk_window_compute_configure_request()
4302 * will apply the constraints later, and we
4303 * don't want to lose information about
4304 * what position the user set before then.
4305 * i.e. if you do a move() then turn off POS_CENTER
4306 * then show the window, your move() will work.
4308 gtk_window_constrain_position (window,
4309 allocation.width, allocation.height,
4312 /* Note that this request doesn't go through our standard request
4313 * framework, e.g. doesn't increment configure_request_count,
4314 * doesn't set info->last, etc.; that's because
4315 * we don't save the info needed to arrive at this same request
4318 * To gtk_window_move_resize(), this will end up looking exactly
4319 * the same as the position being changed by the window
4322 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4326 /* Save this position to apply on mapping */
4327 info->initial_x = x;
4328 info->initial_y = y;
4329 info->initial_pos_set = TRUE;
4334 * gtk_window_get_position:
4335 * @window: a #GtkWindow
4336 * @root_x: (out) (allow-none): eturn location for X coordinate of
4337 * gravity-determined reference point, or %NULL
4338 * @root_y: (out) (allow-none): return location for Y coordinate of
4339 * gravity-determined reference point, or %NULL
4341 * This function returns the position you need to pass to
4342 * gtk_window_move() to keep @window in its current position.
4343 * This means that the meaning of the returned value varies with
4344 * window gravity. See gtk_window_move() for more details.
4346 * If you haven't changed the window gravity, its gravity will be
4347 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4348 * gets the position of the top-left corner of the window manager
4349 * frame for the window. gtk_window_move() sets the position of this
4350 * same top-left corner.
4352 * gtk_window_get_position() is not 100% reliable because the X Window System
4353 * does not specify a way to obtain the geometry of the
4354 * decorations placed on a window by the window manager.
4355 * Thus GTK+ is using a "best guess" that works with most
4358 * Moreover, nearly all window managers are historically broken with
4359 * respect to their handling of window gravity. So moving a window to
4360 * its current position as returned by gtk_window_get_position() tends
4361 * to result in moving the window slightly. Window managers are
4362 * slowly getting better over time.
4364 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4365 * frame is not relevant, and thus gtk_window_get_position() will
4366 * always produce accurate results. However you can't use static
4367 * gravity to do things like place a window in a corner of the screen,
4368 * because static gravity ignores the window manager decorations.
4370 * If you are saving and restoring your application's window
4371 * positions, you should know that it's impossible for applications to
4372 * do this without getting it somewhat wrong because applications do
4373 * not have sufficient knowledge of window manager state. The Correct
4374 * Mechanism is to support the session management protocol (see the
4375 * "GnomeClient" object in the GNOME libraries for example) and allow
4376 * the window manager to save your window sizes and positions.
4381 gtk_window_get_position (GtkWindow *window,
4385 GtkWindowPrivate *priv;
4387 GdkWindow *gdk_window;
4389 g_return_if_fail (GTK_IS_WINDOW (window));
4391 priv = window->priv;
4392 widget = GTK_WIDGET (window);
4393 gdk_window = gtk_widget_get_window (widget);
4395 if (priv->gravity == GDK_GRAVITY_STATIC)
4397 if (gtk_widget_get_mapped (widget))
4399 /* This does a server round-trip, which is sort of wrong;
4400 * but a server round-trip is inevitable for
4401 * gdk_window_get_frame_extents() in the usual
4402 * NorthWestGravity case below, so not sure what else to
4403 * do. We should likely be consistent about whether we get
4404 * the client-side info or the server-side info.
4406 gdk_window_get_origin (gdk_window, root_x, root_y);
4410 GdkRectangle configure_request;
4412 gtk_window_compute_configure_request (window,
4416 *root_x = configure_request.x;
4417 *root_y = configure_request.y;
4422 GdkRectangle frame_extents;
4427 if (gtk_widget_get_mapped (widget))
4429 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4430 x = frame_extents.x;
4431 y = frame_extents.y;
4432 gtk_window_get_size (window, &w, &h);
4436 /* We just say the frame has 0 size on all sides.
4437 * Not sure what else to do.
4439 gtk_window_compute_configure_request (window,
4442 x = frame_extents.x;
4443 y = frame_extents.y;
4444 w = frame_extents.width;
4445 h = frame_extents.height;
4448 switch (priv->gravity)
4450 case GDK_GRAVITY_NORTH:
4451 case GDK_GRAVITY_CENTER:
4452 case GDK_GRAVITY_SOUTH:
4453 /* Find center of frame. */
4454 x += frame_extents.width / 2;
4455 /* Center client window on that point. */
4459 case GDK_GRAVITY_SOUTH_EAST:
4460 case GDK_GRAVITY_EAST:
4461 case GDK_GRAVITY_NORTH_EAST:
4462 /* Find right edge of frame */
4463 x += frame_extents.width;
4464 /* Align left edge of client at that point. */
4471 switch (priv->gravity)
4473 case GDK_GRAVITY_WEST:
4474 case GDK_GRAVITY_CENTER:
4475 case GDK_GRAVITY_EAST:
4476 /* Find center of frame. */
4477 y += frame_extents.height / 2;
4478 /* Center client window there. */
4481 case GDK_GRAVITY_SOUTH_WEST:
4482 case GDK_GRAVITY_SOUTH:
4483 case GDK_GRAVITY_SOUTH_EAST:
4484 /* Find south edge of frame */
4485 y += frame_extents.height;
4486 /* Place bottom edge of client there */
4501 * gtk_window_reshow_with_initial_size:
4502 * @window: a #GtkWindow
4504 * Hides @window, then reshows it, resetting the
4505 * default size and position of the window. Used
4506 * by GUI builders only.
4509 gtk_window_reshow_with_initial_size (GtkWindow *window)
4513 g_return_if_fail (GTK_IS_WINDOW (window));
4515 widget = GTK_WIDGET (window);
4517 gtk_widget_hide (widget);
4518 gtk_widget_unrealize (widget);
4519 gtk_widget_show (widget);
4523 gtk_window_destroy (GtkWidget *widget)
4525 GtkWindow *window = GTK_WINDOW (widget);
4526 GtkWindowPrivate *priv = window->priv;
4528 gtk_window_release_application (window);
4530 toplevel_list = g_slist_remove (toplevel_list, window);
4532 if (priv->transient_parent)
4533 gtk_window_set_transient_for (window, NULL);
4535 /* frees the icons */
4536 gtk_window_set_icon_list (window, NULL);
4538 if (priv->has_user_ref_count)
4540 priv->has_user_ref_count = FALSE;
4541 g_object_unref (window);
4545 gtk_window_group_remove_window (priv->group, window);
4547 gtk_window_free_key_hash (window);
4549 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4553 gtk_window_finalize (GObject *object)
4555 GtkWindow *window = GTK_WINDOW (object);
4556 GtkWindowPrivate *priv = window->priv;
4557 GtkMnemonicHash *mnemonic_hash;
4559 g_free (priv->title);
4560 g_free (priv->wmclass_name);
4561 g_free (priv->wmclass_class);
4562 g_free (priv->wm_role);
4563 gtk_window_release_application (window);
4565 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4567 _gtk_mnemonic_hash_free (mnemonic_hash);
4569 if (priv->geometry_info)
4571 if (priv->geometry_info->widget)
4572 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4573 gtk_widget_destroyed,
4574 &priv->geometry_info->widget);
4575 g_free (priv->geometry_info);
4578 if (priv->keys_changed_handler)
4580 g_source_remove (priv->keys_changed_handler);
4581 priv->keys_changed_handler = 0;
4585 g_signal_handlers_disconnect_by_func (priv->screen,
4586 gtk_window_on_composited_changed, window);
4588 g_free (priv->startup_id);
4590 #ifdef GDK_WINDOWING_X11
4591 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4592 gtk_window_on_theme_variant_changed,
4596 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4600 gtk_window_show (GtkWidget *widget)
4602 GtkWindow *window = GTK_WINDOW (widget);
4603 GtkWindowPrivate *priv = window->priv;
4604 GtkContainer *container = GTK_CONTAINER (window);
4605 gboolean need_resize;
4608 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4610 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4614 _gtk_widget_set_visible_flag (widget, TRUE);
4616 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4617 _gtk_container_set_need_resize (container, FALSE);
4621 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4622 GtkAllocation allocation = { 0, 0 };
4623 GdkRectangle configure_request;
4624 GdkGeometry new_geometry;
4626 gboolean was_realized;
4628 /* We are going to go ahead and perform this configure request
4629 * and then emulate a configure notify by going ahead and
4630 * doing a size allocate. Sort of a synchronous
4631 * mini-copy of gtk_window_move_resize() here.
4633 gtk_window_compute_configure_request (window,
4638 /* We update this because we are going to go ahead
4639 * and gdk_window_resize() below, rather than
4642 info->last.configure_request.width = configure_request.width;
4643 info->last.configure_request.height = configure_request.height;
4645 /* and allocate the window - this is normally done
4646 * in move_resize in response to configure notify
4648 allocation.width = configure_request.width;
4649 allocation.height = configure_request.height;
4650 gtk_widget_size_allocate (widget, &allocation);
4652 /* Then we guarantee we have a realize */
4653 was_realized = FALSE;
4654 if (!gtk_widget_get_realized (widget))
4656 gtk_widget_realize (widget);
4657 was_realized = TRUE;
4660 /* We only send configure request if we didn't just finish
4661 * creating the window; if we just created the window
4662 * then we created it with widget->allocation anyhow.
4665 gdk_window_move_resize (gtk_widget_get_window (widget),
4666 configure_request.x,
4667 configure_request.y,
4668 configure_request.width,
4669 configure_request.height);
4672 gtk_container_check_resize (container);
4674 gtk_widget_map (widget);
4676 /* Try to make sure that we have some focused widget
4678 #ifdef GDK_WINDOWING_X11
4679 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4680 GTK_IS_PLUG (window);
4684 if (!priv->focus_widget && !is_plug)
4685 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4688 gtk_grab_add (widget);
4692 gtk_window_hide (GtkWidget *widget)
4694 GtkWindow *window = GTK_WINDOW (widget);
4695 GtkWindowPrivate *priv = window->priv;
4697 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4699 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4703 _gtk_widget_set_visible_flag (widget, FALSE);
4704 gtk_widget_unmap (widget);
4707 gtk_grab_remove (widget);
4711 gtk_window_map (GtkWidget *widget)
4714 GtkWindow *window = GTK_WINDOW (widget);
4715 GtkWindowPrivate *priv = window->priv;
4716 GdkWindow *gdk_window;
4717 gboolean auto_mnemonics;
4718 GtkPolicyType visible_focus;
4720 if (!gtk_widget_is_toplevel (widget))
4722 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4726 gtk_widget_set_mapped (widget, TRUE);
4728 child = gtk_bin_get_child (&(window->bin));
4730 gtk_widget_get_visible (child) &&
4731 !gtk_widget_get_mapped (child))
4732 gtk_widget_map (child);
4734 gdk_window = gtk_widget_get_window (widget);
4736 if (priv->maximize_initially)
4737 gdk_window_maximize (gdk_window);
4739 gdk_window_unmaximize (gdk_window);
4741 if (priv->stick_initially)
4742 gdk_window_stick (gdk_window);
4744 gdk_window_unstick (gdk_window);
4746 if (priv->iconify_initially)
4747 gdk_window_iconify (gdk_window);
4749 gdk_window_deiconify (gdk_window);
4751 if (priv->fullscreen_initially)
4752 gdk_window_fullscreen (gdk_window);
4754 gdk_window_unfullscreen (gdk_window);
4756 gdk_window_set_keep_above (gdk_window, priv->above_initially);
4758 gdk_window_set_keep_below (gdk_window, priv->below_initially);
4760 if (priv->type == GTK_WINDOW_TOPLEVEL)
4761 gtk_window_set_theme_variant (window);
4763 /* No longer use the default settings */
4764 priv->need_default_size = FALSE;
4765 priv->need_default_position = FALSE;
4767 if (priv->reset_type_hint)
4769 /* We should only reset the type hint when the application
4770 * used gtk_window_set_type_hint() to change the hint.
4771 * Some applications use X directly to change the properties;
4772 * in that case, we shouldn't overwrite what they did.
4774 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4775 priv->reset_type_hint = FALSE;
4778 gdk_window_show (gdk_window);
4780 if (priv->grip_window)
4781 gdk_window_show (priv->grip_window);
4783 if (!disable_startup_notification)
4785 /* Do we have a custom startup-notification id? */
4786 if (priv->startup_id != NULL)
4788 /* Make sure we have a "real" id */
4789 if (!startup_id_is_fake (priv->startup_id))
4790 gdk_notify_startup_complete_with_id (priv->startup_id);
4792 g_free (priv->startup_id);
4793 priv->startup_id = NULL;
4795 else if (!sent_startup_notification)
4797 sent_startup_notification = TRUE;
4798 gdk_notify_startup_complete ();
4802 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4803 * (as in the case of popup menus), then hide mnemonics initially
4805 g_object_get (gtk_widget_get_settings (widget),
4806 "gtk-auto-mnemonics", &auto_mnemonics,
4807 "gtk-visible-focus", &visible_focus,
4810 if (auto_mnemonics && !priv->mnemonics_visible_set)
4811 gtk_window_set_mnemonics_visible (window, FALSE);
4813 /* inherit from transient parent, so that a dialog that is
4814 * opened via keynav shows focus initially
4816 if (priv->transient_parent)
4817 gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
4819 gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
4823 gtk_window_map_event (GtkWidget *widget,
4826 if (!gtk_widget_get_mapped (widget))
4828 /* we should be be unmapped, but are getting a MapEvent, this may happen
4829 * to toplevel XWindows if mapping was intercepted by a window manager
4830 * and an unmap request occoured while the MapRequestEvent was still
4831 * being handled. we work around this situaiton here by re-requesting
4832 * the window being unmapped. more details can be found in:
4833 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4835 gdk_window_hide (gtk_widget_get_window (widget));
4841 gtk_window_unmap (GtkWidget *widget)
4843 GtkWindow *window = GTK_WINDOW (widget);
4844 GtkWindowPrivate *priv = window->priv;
4846 GtkWindowGeometryInfo *info;
4847 GdkWindow *gdk_window;
4848 GdkWindowState state;
4850 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4852 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
4856 gdk_window = gtk_widget_get_window (widget);
4858 gtk_widget_set_mapped (widget, FALSE);
4859 gdk_window_withdraw (gdk_window);
4861 priv->configure_request_count = 0;
4862 priv->configure_notify_received = FALSE;
4864 /* on unmap, we reset the default positioning of the window,
4865 * so it's placed again, but we don't reset the default
4866 * size of the window, so it's remembered.
4868 priv->need_default_position = TRUE;
4870 info = gtk_window_get_geometry_info (window, FALSE);
4873 info->initial_pos_set = FALSE;
4874 info->position_constraints_changed = FALSE;
4877 state = gdk_window_get_state (gdk_window);
4878 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4879 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4880 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4881 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4882 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4884 child = gtk_bin_get_child (&(window->bin));
4886 gtk_widget_unmap (child);
4889 /* (Note: Replace "size" with "width" or "height". Also, the request
4890 * mode is honoured.)
4891 * For selecting the default window size, the following conditions
4892 * should hold (in order of importance):
4893 * - the size is not below the minimum size
4894 * Windows cannot be resized below their minimum size, so we must
4895 * ensure we don't do that either.
4896 * - the size is not above the natural size
4897 * It seems weird to allocate more than this in an initial guess.
4898 * - the size does not exceed that of a maximized window
4899 * We want to see the whole window after all.
4900 * (Note that this may not be possible to achieve due to imperfect
4901 * information from the windowing system.)
4904 /* We use these for now to not make windows too big by accident. Note
4905 * that we still clamp these numbers by screen size. Also note that
4906 * minimum size still overrides this. So keep your windows small! :)
4908 #define MAX_DEFAULT_WINDOW_WIDTH 640
4909 #define MAX_DEFAULT_WINDOW_HEIGHT 480
4912 gtk_window_guess_default_size (GtkWindow *window,
4916 GtkWidget *widget = GTK_WIDGET (window);
4918 int minimum, natural;
4920 screen = gtk_widget_get_screen (widget);
4922 *width = gdk_screen_get_width (screen);
4923 *height = gdk_screen_get_height (screen);
4925 if (*width >= *height)
4928 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
4929 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
4934 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
4935 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
4938 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
4940 gtk_widget_get_preferred_height (widget, &minimum, &natural);
4941 *height = MAX (minimum, MIN (*height, natural));
4943 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
4944 *width = MAX (minimum, MIN (*width, natural));
4946 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
4948 gtk_widget_get_preferred_width (widget, &minimum, &natural);
4949 *width = MAX (minimum, MIN (*width, natural));
4951 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
4952 *height = MAX (minimum, MIN (*height, natural));
4957 gtk_window_realize (GtkWidget *widget)
4959 GtkAllocation allocation;
4961 GdkWindow *parent_window;
4962 GdkWindow *gdk_window;
4963 GdkWindowAttr attributes;
4964 gint attributes_mask;
4965 GtkWindowPrivate *priv;
4966 GtkStyleContext *context;
4968 window = GTK_WINDOW (widget);
4969 priv = window->priv;
4971 gtk_widget_get_allocation (widget, &allocation);
4973 if (gtk_widget_get_parent_window (widget))
4975 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
4977 gtk_widget_set_realized (widget, TRUE);
4979 attributes.x = allocation.x;
4980 attributes.y = allocation.y;
4981 attributes.width = allocation.width;
4982 attributes.height = allocation.height;
4983 attributes.window_type = GDK_WINDOW_CHILD;
4985 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
4987 attributes.visual = gtk_widget_get_visual (widget);
4988 attributes.wclass = GDK_INPUT_OUTPUT;
4990 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
4992 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
4993 &attributes, attributes_mask);
4994 gtk_widget_set_window (widget, gdk_window);
4995 gdk_window_set_user_data (gdk_window, widget);
4997 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
4999 gdk_window_enable_synchronized_configure (gdk_window);
5003 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5005 /* ensure widget tree is properly size allocated */
5006 if (allocation.x == -1 &&
5007 allocation.y == -1 &&
5008 allocation.width == 1 &&
5009 allocation.height == 1)
5015 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5016 if (allocation.width == 0 || allocation.height == 0)
5018 /* non-empty window */
5019 allocation.width = 200;
5020 allocation.height = 200;
5022 gtk_widget_size_allocate (widget, &allocation);
5024 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5026 g_return_if_fail (!gtk_widget_get_realized (widget));
5029 gtk_widget_set_realized (widget, TRUE);
5033 case GTK_WINDOW_TOPLEVEL:
5034 attributes.window_type = GDK_WINDOW_TOPLEVEL;
5036 case GTK_WINDOW_POPUP:
5037 attributes.window_type = GDK_WINDOW_TEMP;
5040 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5044 attributes.title = priv->title;
5045 attributes.wmclass_name = priv->wmclass_name;
5046 attributes.wmclass_class = priv->wmclass_class;
5047 attributes.wclass = GDK_INPUT_OUTPUT;
5048 attributes.visual = gtk_widget_get_visual (widget);
5050 attributes_mask = 0;
5051 parent_window = gtk_widget_get_root_window (widget);
5053 gtk_widget_get_allocation (widget, &allocation);
5054 attributes.width = allocation.width;
5055 attributes.height = allocation.height;
5056 attributes.event_mask = gtk_widget_get_events (widget);
5057 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5058 GDK_KEY_PRESS_MASK |
5059 GDK_KEY_RELEASE_MASK |
5060 GDK_ENTER_NOTIFY_MASK |
5061 GDK_LEAVE_NOTIFY_MASK |
5062 GDK_FOCUS_CHANGE_MASK |
5063 GDK_STRUCTURE_MASK);
5064 attributes.type_hint = priv->type_hint;
5066 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5067 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5068 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5070 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5071 gtk_widget_set_window (widget, gdk_window);
5073 if (priv->opacity_set)
5074 gdk_window_set_opacity (gdk_window, priv->opacity);
5076 gdk_window_enable_synchronized_configure (gdk_window);
5078 gdk_window_set_user_data (gdk_window, window);
5080 context = gtk_widget_get_style_context (widget);
5081 gtk_style_context_set_background (context, gdk_window);
5084 if (priv->transient_parent &&
5085 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5086 gdk_window_set_transient_for (gdk_window,
5087 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5090 gdk_window_set_role (gdk_window, priv->wm_role);
5092 if (!priv->decorated)
5093 gdk_window_set_decorations (gdk_window, 0);
5095 if (!priv->deletable)
5096 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5098 if (gtk_window_get_skip_pager_hint (window))
5099 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5101 if (gtk_window_get_skip_taskbar_hint (window))
5102 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5104 if (gtk_window_get_accept_focus (window))
5105 gdk_window_set_accept_focus (gdk_window, TRUE);
5107 gdk_window_set_accept_focus (gdk_window, FALSE);
5109 if (gtk_window_get_focus_on_map (window))
5110 gdk_window_set_focus_on_map (gdk_window, TRUE);
5112 gdk_window_set_focus_on_map (gdk_window, FALSE);
5115 gdk_window_set_modal_hint (gdk_window, TRUE);
5117 gdk_window_set_modal_hint (gdk_window, FALSE);
5119 if (priv->startup_id)
5121 #ifdef GDK_WINDOWING_X11
5122 if (GDK_IS_X11_WINDOW (gdk_window))
5124 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5125 if (timestamp != GDK_CURRENT_TIME)
5126 gdk_x11_window_set_user_time (gdk_window, timestamp);
5129 if (!startup_id_is_fake (priv->startup_id))
5130 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5133 #ifdef GDK_WINDOWING_X11
5134 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5136 if (GDK_IS_X11_WINDOW (gdk_window))
5137 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5142 gtk_window_realize_icon (window);
5144 if (priv->has_resize_grip)
5145 resize_grip_create_window (window);
5149 gtk_window_unrealize (GtkWidget *widget)
5151 GtkWindow *window = GTK_WINDOW (widget);
5152 GtkWindowPrivate *priv = window->priv;
5153 GtkWindowGeometryInfo *info;
5155 /* On unrealize, we reset the size of the window such
5156 * that we will re-apply the default sizing stuff
5157 * next time we show the window.
5159 * Default positioning is reset on unmap, instead of unrealize.
5161 priv->need_default_size = TRUE;
5162 info = gtk_window_get_geometry_info (window, FALSE);
5165 info->resize_width = -1;
5166 info->resize_height = -1;
5167 info->last.configure_request.x = 0;
5168 info->last.configure_request.y = 0;
5169 info->last.configure_request.width = -1;
5170 info->last.configure_request.height = -1;
5171 /* be sure we reset geom hints on re-realize */
5172 info->last.flags = 0;
5176 gtk_window_unrealize_icon (window);
5178 if (priv->grip_window != NULL)
5179 resize_grip_destroy_window (window);
5181 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5184 static GtkJunctionSides
5185 get_grip_junction (GtkWidget *widget)
5187 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5188 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5190 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5194 get_drag_edge (GtkWidget *widget,
5195 GdkWindowEdge *edge)
5197 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5198 gboolean hresizable;
5199 gboolean vresizable;
5200 GtkTextDirection dir;
5201 GtkWindowGeometryInfo *info;
5206 info = priv->geometry_info;
5209 GdkWindowHints flags = info->last.flags;
5210 GdkGeometry *geometry = &info->last.geometry;
5212 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5214 hresizable = geometry->min_width < geometry->max_width;
5215 vresizable = geometry->min_height < geometry->max_height;
5219 dir = gtk_widget_get_direction (widget);
5221 if (hresizable && vresizable)
5222 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5223 else if (hresizable)
5224 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5225 else if (vresizable)
5226 *edge = GDK_WINDOW_EDGE_SOUTH;
5234 set_grip_cursor (GtkWindow *window)
5236 GtkWidget *widget = GTK_WIDGET (window);
5237 GtkWindowPrivate *priv = window->priv;
5239 if (priv->grip_window == NULL)
5242 if (gtk_widget_is_sensitive (widget))
5245 GdkDisplay *display;
5246 GdkCursorType cursor_type;
5249 cursor_type = GDK_LEFT_PTR;
5251 if (get_drag_edge (widget, &edge))
5255 case GDK_WINDOW_EDGE_EAST:
5256 cursor_type = GDK_RIGHT_SIDE;
5258 case GDK_WINDOW_EDGE_SOUTH_EAST:
5259 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5261 case GDK_WINDOW_EDGE_SOUTH:
5262 cursor_type = GDK_BOTTOM_SIDE;
5264 case GDK_WINDOW_EDGE_SOUTH_WEST:
5265 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5267 case GDK_WINDOW_EDGE_WEST:
5268 cursor_type = GDK_LEFT_SIDE;
5274 display = gtk_widget_get_display (widget);
5275 cursor = gdk_cursor_new_for_display (display, cursor_type);
5276 gdk_window_set_cursor (priv->grip_window, cursor);
5277 g_object_unref (cursor);
5280 gdk_window_set_cursor (priv->grip_window, NULL);
5284 set_grip_shape (GtkWindow *window)
5286 GtkWindowPrivate *priv = window->priv;
5287 cairo_region_t *region;
5288 cairo_surface_t *surface;
5290 double width, height;
5292 if (priv->grip_window == NULL)
5295 width = gdk_window_get_width (priv->grip_window);
5296 height = gdk_window_get_height (priv->grip_window);
5297 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5299 cr = cairo_create (surface);
5300 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5302 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5303 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5305 cairo_move_to (cr, width, 0.0);
5306 cairo_line_to (cr, width, height);
5307 cairo_line_to (cr, 0.0, height);
5311 cairo_move_to (cr, 0.0, 0.0);
5312 cairo_line_to (cr, width, height);
5313 cairo_line_to (cr, 0.0, height);
5315 cairo_close_path (cr);
5318 region = gdk_cairo_region_create_from_surface (surface);
5319 cairo_surface_destroy (surface);
5321 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5322 cairo_region_destroy (region);
5326 set_grip_position (GtkWindow *window)
5328 GtkWindowPrivate *priv = window->priv;
5331 if (priv->grip_window == NULL)
5334 gtk_window_get_resize_grip_area (window, &rect);
5335 gdk_window_raise (priv->grip_window);
5336 gdk_window_move_resize (priv->grip_window,
5338 rect.width, rect.height);
5342 gtk_window_size_allocate (GtkWidget *widget,
5343 GtkAllocation *allocation)
5345 GtkWindow *window = GTK_WINDOW (widget);
5346 GtkAllocation child_allocation;
5350 gtk_widget_set_allocation (widget, allocation);
5352 if (gtk_widget_get_realized (widget))
5354 /* If it's not a toplevel we're embedded, we need to resize the window's
5355 * window and skip the grip.
5357 if (!gtk_widget_is_toplevel (widget))
5359 gdk_window_move_resize (gtk_widget_get_window (widget),
5360 allocation->x, allocation->y,
5361 allocation->width, allocation->height);
5365 update_grip_visibility (window);
5366 set_grip_position (window);
5370 child = gtk_bin_get_child (&(window->bin));
5371 if (child && gtk_widget_get_visible (child))
5373 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5374 child_allocation.x = border_width;
5375 child_allocation.y = border_width;
5376 child_allocation.width =
5377 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5378 child_allocation.height =
5379 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5381 gtk_widget_size_allocate (child, &child_allocation);
5386 gtk_window_configure_event (GtkWidget *widget,
5387 GdkEventConfigure *event)
5389 GtkAllocation allocation;
5390 GtkWindow *window = GTK_WINDOW (widget);
5391 GtkWindowPrivate *priv = window->priv;
5392 gboolean expected_reply = priv->configure_request_count > 0;
5394 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5396 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5397 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5399 gdk_window_configure_finished (gtk_widget_get_window (widget));
5403 /* priv->configure_request_count incremented for each
5404 * configure request, and decremented to a min of 0 for
5405 * each configure notify.
5407 * All it means is that we know we will get at least
5408 * priv->configure_request_count more configure notifies.
5409 * We could get more configure notifies than that; some
5410 * of the configure notifies we get may be unrelated to
5411 * the configure requests. But we will get at least
5412 * priv->configure_request_count notifies.
5415 if (priv->configure_request_count > 0)
5417 priv->configure_request_count -= 1;
5418 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5421 /* As an optimization, we avoid a resize when possible.
5423 * The only times we can avoid a resize are:
5424 * - we know only the position changed, not the size
5425 * - we know we have made more requests and so will get more
5426 * notifies and can wait to resize when we get them
5428 gtk_widget_get_allocation (widget, &allocation);
5429 if (!expected_reply &&
5430 (allocation.width == event->width &&
5431 allocation.height == event->height))
5433 gdk_window_configure_finished (gtk_widget_get_window (widget));
5438 * If we do need to resize, we do that by:
5439 * - filling in widget->allocation with the new size
5440 * - setting configure_notify_received to TRUE
5441 * for use in gtk_window_move_resize()
5442 * - queueing a resize, leading to invocation of
5443 * gtk_window_move_resize() in an idle handler
5447 priv->configure_notify_received = TRUE;
5449 allocation.width = event->width;
5450 allocation.height = event->height;
5451 gtk_widget_set_allocation (widget, &allocation);
5453 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5455 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5461 gtk_window_state_event (GtkWidget *widget,
5462 GdkEventWindowState *event)
5464 update_grip_visibility (GTK_WINDOW (widget));
5470 gtk_window_direction_changed (GtkWidget *widget,
5471 GtkTextDirection prev_dir)
5473 GtkWindow *window = GTK_WINDOW (widget);
5475 set_grip_cursor (window);
5476 set_grip_position (window);
5477 set_grip_shape (window);
5481 gtk_window_state_changed (GtkWidget *widget,
5482 GtkStateType previous_state)
5484 GtkWindow *window = GTK_WINDOW (widget);
5486 update_grip_visibility (window);
5490 gtk_window_style_updated (GtkWidget *widget)
5492 GtkWindow *window = GTK_WINDOW (widget);
5493 GtkWindowPrivate *priv = window->priv;
5496 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5498 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5500 gdk_window_move_resize (priv->grip_window,
5502 rect.width, rect.height);
5504 set_grip_shape (window);
5505 gtk_widget_queue_resize (widget);
5510 resize_grip_create_window (GtkWindow *window)
5513 GtkWindowPrivate *priv;
5514 GdkWindowAttr attributes;
5515 gint attributes_mask;
5518 priv = window->priv;
5519 widget = GTK_WIDGET (window);
5521 g_return_if_fail (gtk_widget_get_realized (widget));
5522 g_return_if_fail (priv->grip_window == NULL);
5524 gtk_window_get_resize_grip_area (window, &rect);
5526 attributes.x = rect.x;
5527 attributes.y = rect.y;
5528 attributes.width = rect.width;
5529 attributes.height = rect.height;
5530 attributes.window_type = GDK_WINDOW_CHILD;
5531 attributes.wclass = GDK_INPUT_OUTPUT;
5532 attributes.event_mask = gtk_widget_get_events (widget) |
5534 GDK_BUTTON_PRESS_MASK;
5536 attributes_mask = GDK_WA_X | GDK_WA_Y;
5538 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5542 gdk_window_set_user_data (priv->grip_window, widget);
5544 gdk_window_raise (priv->grip_window);
5546 set_grip_shape (window);
5547 update_grip_visibility (window);
5551 resize_grip_destroy_window (GtkWindow *window)
5553 GtkWindowPrivate *priv = window->priv;
5555 gdk_window_set_user_data (priv->grip_window, NULL);
5556 gdk_window_destroy (priv->grip_window);
5557 priv->grip_window = NULL;
5558 update_grip_visibility (window);
5562 * gtk_window_set_has_resize_grip:
5563 * @window: a #GtkWindow
5564 * @value: %TRUE to allow a resize grip
5566 * Sets whether @window has a corner resize grip.
5568 * Note that the resize grip is only shown if the window
5569 * is actually resizable and not maximized. Use
5570 * gtk_window_resize_grip_is_visible() to find out if the
5571 * resize grip is currently shown.
5576 gtk_window_set_has_resize_grip (GtkWindow *window,
5579 GtkWidget *widget = GTK_WIDGET (window);
5580 GtkWindowPrivate *priv = window->priv;
5582 value = value != FALSE;
5584 if (value != priv->has_resize_grip)
5586 priv->has_resize_grip = value;
5587 gtk_widget_queue_draw (widget);
5589 if (gtk_widget_get_realized (widget) &&
5590 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5592 if (priv->has_resize_grip && priv->grip_window == NULL)
5593 resize_grip_create_window (window);
5594 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5595 resize_grip_destroy_window (window);
5598 g_object_notify (G_OBJECT (window), "has-resize-grip");
5603 update_grip_visibility (GtkWindow *window)
5605 GtkWindowPrivate *priv = window->priv;
5608 val = gtk_window_resize_grip_is_visible (window);
5610 if (priv->grip_window != NULL)
5614 gdk_window_show (priv->grip_window);
5615 set_grip_cursor (window);
5619 gdk_window_hide (priv->grip_window);
5623 if (priv->resize_grip_visible != val)
5625 priv->resize_grip_visible = val;
5627 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5632 * gtk_window_resize_grip_is_visible:
5633 * @window: a #GtkWindow
5635 * Determines whether a resize grip is visible for the specified window.
5637 * Returns: %TRUE if a resize grip exists and is visible
5642 gtk_window_resize_grip_is_visible (GtkWindow *window)
5645 GtkWindowPrivate *priv;
5648 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5650 priv = window->priv;
5651 widget = GTK_WIDGET (window);
5653 if (priv->type == GTK_WINDOW_POPUP)
5656 if (!priv->resizable)
5659 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5662 if (gtk_widget_get_realized (widget))
5664 GdkWindowState state;
5666 state = gdk_window_get_state (gtk_widget_get_window (widget));
5668 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5672 if (!get_drag_edge (widget, &edge))
5675 return window->priv->has_resize_grip;
5679 * gtk_window_get_has_resize_grip:
5680 * @window: a #GtkWindow
5682 * Determines whether the window may have a resize grip.
5684 * Returns: %TRUE if the window has a resize grip
5689 gtk_window_get_has_resize_grip (GtkWindow *window)
5691 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5693 return window->priv->has_resize_grip;
5697 * gtk_window_get_resize_grip_area:
5698 * @window: a #GtkWindow
5699 * @rect: (out): a pointer to a #GdkRectangle which we should store
5700 * the resize grip area
5702 * If a window has a resize grip, this will retrieve the grip
5703 * position, width and height into the specified #GdkRectangle.
5705 * Returns: %TRUE if the resize grip's area was retrieved
5710 gtk_window_get_resize_grip_area (GtkWindow *window,
5713 GtkWidget *widget = GTK_WIDGET (window);
5714 GtkAllocation allocation;
5718 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5720 if (!window->priv->has_resize_grip)
5723 gtk_widget_get_allocation (widget, &allocation);
5725 gtk_widget_style_get (widget,
5726 "resize-grip-width", &grip_width,
5727 "resize-grip-height", &grip_height,
5730 if (grip_width > allocation.width)
5731 grip_width = allocation.width;
5733 if (grip_height > allocation.height)
5734 grip_height = allocation.height;
5736 rect->width = grip_width;
5737 rect->height = grip_height;
5738 rect->y = allocation.y + allocation.height - grip_height;
5740 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5741 rect->x = allocation.x + allocation.width - grip_width;
5743 rect->x = allocation.x;
5748 /* the accel_key and accel_mods fields of the key have to be setup
5749 * upon calling this function. it'll then return whether that key
5750 * is at all used as accelerator, and if so will OR in the
5751 * accel_flags member of the key.
5754 _gtk_window_query_nonaccels (GtkWindow *window,
5756 GdkModifierType accel_mods)
5758 GtkWindowPrivate *priv;
5760 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5762 priv = window->priv;
5764 /* movement keys are considered locked accels */
5767 static const guint bindings[] = {
5768 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,
5769 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,
5773 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5774 if (bindings[i] == accel_key)
5778 /* mnemonics are considered locked accels */
5779 if (accel_mods == priv->mnemonic_modifier)
5781 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5782 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5790 * gtk_window_propagate_key_event:
5791 * @window: a #GtkWindow
5792 * @event: a #GdkEventKey
5794 * Propagate a key press or release event to the focus widget and
5795 * up the focus container chain until a widget handles @event.
5796 * This is normally called by the default ::key_press_event and
5797 * ::key_release_event handlers for toplevel windows,
5798 * however in some cases it may be useful to call this directly when
5799 * overriding the standard key handling for a toplevel window.
5801 * Return value: %TRUE if a widget in the focus chain handled the event.
5806 gtk_window_propagate_key_event (GtkWindow *window,
5809 GtkWindowPrivate *priv;
5810 gboolean handled = FALSE;
5811 GtkWidget *widget, *focus;
5813 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5815 priv = window->priv;
5816 widget = GTK_WIDGET (window);
5818 focus = priv->focus_widget;
5820 g_object_ref (focus);
5823 focus && focus != widget &&
5824 gtk_widget_get_toplevel (focus) == widget)
5828 if (gtk_widget_is_sensitive (focus))
5829 handled = gtk_widget_event (focus, (GdkEvent*) event);
5831 parent = gtk_widget_get_parent (focus);
5833 g_object_ref (parent);
5835 g_object_unref (focus);
5841 g_object_unref (focus);
5847 gtk_window_key_press_event (GtkWidget *widget,
5850 GtkWindow *window = GTK_WINDOW (widget);
5851 gboolean handled = FALSE;
5853 /* handle mnemonics and accelerators */
5855 handled = gtk_window_activate_key (window, event);
5857 /* handle focus widget key events */
5859 handled = gtk_window_propagate_key_event (window, event);
5861 /* Chain up, invokes binding set */
5863 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5869 gtk_window_key_release_event (GtkWidget *widget,
5872 GtkWindow *window = GTK_WINDOW (widget);
5873 gboolean handled = FALSE;
5875 /* handle focus widget key events */
5877 handled = gtk_window_propagate_key_event (window, event);
5879 /* Chain up, invokes binding set */
5881 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5887 gtk_window_button_press_event (GtkWidget *widget,
5888 GdkEventButton *event)
5890 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5893 if (event->window == priv->grip_window)
5895 if (get_drag_edge (widget, &edge))
5896 gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
5898 gdk_event_get_device (event),
5911 gtk_window_real_activate_default (GtkWindow *window)
5913 gtk_window_activate_default (window);
5917 gtk_window_real_activate_focus (GtkWindow *window)
5919 gtk_window_activate_focus (window);
5923 gtk_window_enter_notify_event (GtkWidget *widget,
5924 GdkEventCrossing *event)
5930 gtk_window_leave_notify_event (GtkWidget *widget,
5931 GdkEventCrossing *event)
5937 do_focus_change (GtkWidget *widget,
5941 GdkDeviceManager *device_manager;
5944 g_object_ref (widget);
5946 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5947 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5948 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5949 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5951 for (d = devices; d; d = d->next)
5953 GdkDevice *dev = d->data;
5956 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5959 /* Skip non-master keyboards that haven't
5960 * selected for events from this window
5962 window = gtk_widget_get_window (widget);
5963 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5964 window && !gdk_window_get_device_events (window, dev))
5967 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5969 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5970 fevent->focus_change.window = window;
5972 g_object_ref (window);
5973 fevent->focus_change.in = in;
5974 gdk_event_set_device (fevent, dev);
5976 gtk_widget_send_focus_change (widget, fevent);
5978 gdk_event_free (fevent);
5981 g_list_free (devices);
5982 g_object_unref (widget);
5986 maybe_set_mnemonics_visible (GtkWindow *window)
5989 GdkDeviceManager *device_manager;
5991 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
5992 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5994 for (d = devices; d; d = d->next)
5996 GdkDevice *dev = d->data;
5998 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6000 GdkModifierType mask;
6002 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6004 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6006 gtk_window_set_mnemonics_visible (window, TRUE);
6012 g_list_free (devices);
6016 gtk_window_focus_in_event (GtkWidget *widget,
6017 GdkEventFocus *event)
6019 GtkWindow *window = GTK_WINDOW (widget);
6020 gboolean auto_mnemonics;
6022 /* It appears spurious focus in events can occur when
6023 * the window is hidden. So we'll just check to see if
6024 * the window is visible before actually handling the
6027 if (gtk_widget_get_visible (widget))
6029 _gtk_window_set_has_toplevel_focus (window, TRUE);
6030 _gtk_window_set_is_active (window, TRUE);
6032 g_object_get (gtk_widget_get_settings (widget),
6033 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6035 maybe_set_mnemonics_visible (window);
6042 gtk_window_focus_out_event (GtkWidget *widget,
6043 GdkEventFocus *event)
6045 GtkWindow *window = GTK_WINDOW (widget);
6046 gboolean auto_mnemonics;
6048 _gtk_window_set_has_toplevel_focus (window, FALSE);
6049 _gtk_window_set_is_active (window, FALSE);
6051 /* set the mnemonic-visible property to false */
6052 g_object_get (gtk_widget_get_settings (widget),
6053 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6055 gtk_window_set_mnemonics_visible (window, FALSE);
6061 gtk_window_check_resize (GtkContainer *container)
6063 /* If the window is not toplevel anymore than it's embedded somewhere,
6064 * so handle it like a normal window */
6065 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6066 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6067 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6068 gtk_window_move_resize (GTK_WINDOW (container));
6072 gtk_window_focus (GtkWidget *widget,
6073 GtkDirectionType direction)
6075 GtkWindowPrivate *priv;
6078 GtkContainer *container;
6080 GtkWidget *old_focus_child;
6083 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6084 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6086 container = GTK_CONTAINER (widget);
6087 window = GTK_WINDOW (widget);
6088 priv = window->priv;
6089 bin = GTK_BIN (widget);
6091 old_focus_child = gtk_container_get_focus_child (container);
6093 /* We need a special implementation here to deal properly with wrapping
6094 * around in the tab chain without the danger of going into an
6097 if (old_focus_child)
6099 if (gtk_widget_child_focus (old_focus_child, direction))
6103 if (priv->focus_widget)
6105 if (direction == GTK_DIR_LEFT ||
6106 direction == GTK_DIR_RIGHT ||
6107 direction == GTK_DIR_UP ||
6108 direction == GTK_DIR_DOWN)
6113 /* Wrapped off the end, clear the focus setting for the toplpevel */
6114 parent = gtk_widget_get_parent (priv->focus_widget);
6117 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6118 parent = gtk_widget_get_parent (parent);
6121 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6124 /* Now try to focus the first widget in the window */
6125 child = gtk_bin_get_child (bin);
6128 if (gtk_widget_child_focus (child, direction))
6136 gtk_window_move_focus (GtkWidget *widget,
6137 GtkDirectionType dir)
6139 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6141 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6145 gtk_widget_child_focus (widget, dir);
6147 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6148 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6152 gtk_window_real_set_focus (GtkWindow *window,
6155 GtkWindowPrivate *priv = window->priv;
6156 GtkWidget *old_focus = priv->focus_widget;
6157 gboolean had_default = FALSE;
6158 gboolean focus_had_default = FALSE;
6159 gboolean old_focus_had_default = FALSE;
6163 g_object_ref (old_focus);
6164 g_object_freeze_notify (G_OBJECT (old_focus));
6165 old_focus_had_default = gtk_widget_has_default (old_focus);
6169 g_object_ref (focus);
6170 g_object_freeze_notify (G_OBJECT (focus));
6171 focus_had_default = gtk_widget_has_default (focus);
6174 if (priv->default_widget)
6175 had_default = gtk_widget_has_default (priv->default_widget);
6177 if (priv->focus_widget)
6179 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6180 (priv->focus_widget != priv->default_widget))
6182 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6183 gtk_widget_queue_draw (priv->focus_widget);
6185 if (priv->default_widget)
6186 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6189 priv->focus_widget = NULL;
6191 if (priv->has_focus)
6192 do_focus_change (old_focus, FALSE);
6194 g_object_notify (G_OBJECT (old_focus), "is-focus");
6197 /* The above notifications may have set a new focus widget,
6198 * if so, we don't want to override it.
6200 if (focus && !priv->focus_widget)
6202 priv->focus_widget = focus;
6204 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6205 (priv->focus_widget != priv->default_widget))
6207 if (gtk_widget_get_can_default (priv->focus_widget))
6208 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6210 if (priv->default_widget)
6211 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6214 if (priv->has_focus)
6215 do_focus_change (priv->focus_widget, TRUE);
6217 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6220 /* If the default widget changed, a redraw will have been queued
6221 * on the old and new default widgets by gtk_window_set_default(), so
6222 * we only have to worry about the case where it didn't change.
6223 * We'll sometimes queue a draw twice on the new widget but that
6226 if (priv->default_widget &&
6227 (had_default != gtk_widget_has_default (priv->default_widget)))
6228 gtk_widget_queue_draw (priv->default_widget);
6232 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6233 gtk_widget_queue_draw (old_focus);
6235 g_object_thaw_notify (G_OBJECT (old_focus));
6236 g_object_unref (old_focus);
6240 if (focus_had_default != gtk_widget_has_default (focus))
6241 gtk_widget_queue_draw (focus);
6243 g_object_thaw_notify (G_OBJECT (focus));
6244 g_object_unref (focus);
6250 gtk_window_get_preferred_width (GtkWidget *widget,
6258 window = GTK_WINDOW (widget);
6259 child = gtk_bin_get_child (GTK_BIN (window));
6261 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6262 *minimum_size = border_width * 2;
6263 *natural_size = border_width * 2;
6265 if (child && gtk_widget_get_visible (child))
6267 gint child_min, child_nat;
6268 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6270 *minimum_size += child_min;
6271 *natural_size += child_nat;
6276 gtk_window_get_preferred_height (GtkWidget *widget,
6284 window = GTK_WINDOW (widget);
6285 child = gtk_bin_get_child (GTK_BIN (window));
6287 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6288 *minimum_size = border_width * 2;
6289 *natural_size = border_width * 2;
6291 if (child && gtk_widget_get_visible (child))
6293 gint child_min, child_nat;
6294 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6296 *minimum_size += child_min;
6297 *natural_size += child_nat;
6303 * _gtk_window_unset_focus_and_default:
6304 * @window: a #GtkWindow
6305 * @widget: a widget inside of @window
6307 * Checks whether the focus and default widgets of @window are
6308 * @widget or a descendent of @widget, and if so, unset them.
6311 _gtk_window_unset_focus_and_default (GtkWindow *window,
6315 GtkWindowPrivate *priv = window->priv;
6319 g_object_ref (window);
6320 g_object_ref (widget);
6322 parent = gtk_widget_get_parent (widget);
6323 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6325 child = priv->focus_widget;
6327 while (child && child != widget)
6328 child = gtk_widget_get_parent (child);
6330 if (child == widget)
6331 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6334 child = priv->default_widget;
6336 while (child && child != widget)
6337 child = gtk_widget_get_parent (child);
6339 if (child == widget)
6340 gtk_window_set_default (window, NULL);
6342 g_object_unref (widget);
6343 g_object_unref (window);
6346 /*********************************
6347 * Functions related to resizing *
6348 *********************************/
6351 geometry_size_to_pixels (GdkGeometry *geometry,
6356 gint base_width = 0;
6357 gint base_height = 0;
6359 gint min_height = 0;
6361 gint height_inc = 1;
6363 if (flags & GDK_HINT_BASE_SIZE)
6365 base_width = geometry->base_width;
6366 base_height = geometry->base_height;
6368 if (flags & GDK_HINT_MIN_SIZE)
6370 min_width = geometry->min_width;
6371 min_height = geometry->min_height;
6373 if (flags & GDK_HINT_RESIZE_INC)
6375 width_inc = geometry->width_inc;
6376 height_inc = geometry->height_inc;
6380 *width = MAX (*width * width_inc + base_width, min_width);
6382 *height = MAX (*height * height_inc + base_height, min_height);
6385 /* This function doesn't constrain to geometry hints */
6387 gtk_window_compute_configure_request_size (GtkWindow *window,
6388 GdkGeometry *geometry,
6393 GtkWindowPrivate *priv = window->priv;
6394 GtkWindowGeometryInfo *info;
6397 * - we've done a size request
6400 info = gtk_window_get_geometry_info (window, FALSE);
6402 if (priv->need_default_size)
6404 gtk_window_guess_default_size (window, width, height);
6406 /* If window is empty so requests 0, default to random nonzero size */
6407 if (*width == 0 && *height == 0)
6413 /* Override with default size */
6417 if (info->default_width > 0)
6418 *width = info->default_width;
6419 if (info->default_height > 0)
6420 *height = info->default_height;
6422 if (info->default_is_geometry)
6423 geometry_size_to_pixels (geometry, flags,
6424 info->default_width > 0 ? width : NULL,
6425 info->default_height > 0 ? height : NULL);
6430 GtkAllocation allocation;
6432 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6434 /* Default to keeping current size */
6435 *width = allocation.width;
6436 *height = allocation.height;
6439 /* Override any size with gtk_window_resize() values */
6442 if (info->resize_width > 0)
6443 *width = info->resize_width;
6444 if (info->resize_height > 0)
6445 *height = info->resize_height;
6447 if (info->resize_is_geometry)
6448 geometry_size_to_pixels (geometry, flags,
6449 info->resize_width > 0 ? width : NULL,
6450 info->resize_height > 0 ? height : NULL);
6453 /* Don't ever request zero width or height, its not supported by
6454 gdk. The size allocation code will round it to 1 anyway but if
6455 we do it then the value returned from this function will is
6456 not comparable to the size allocation read from the GtkWindow. */
6457 *width = MAX (*width, 1);
6458 *height = MAX (*height, 1);
6461 static GtkWindowPosition
6462 get_effective_position (GtkWindow *window)
6464 GtkWindowPrivate *priv = window->priv;
6465 GtkWindowPosition pos = priv->position;
6467 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6468 (priv->transient_parent == NULL ||
6469 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6470 pos = GTK_WIN_POS_NONE;
6476 get_center_monitor_of_window (GtkWindow *window)
6478 /* We could try to sort out the relative positions of the monitors and
6479 * stuff, or we could just be losers and assume you have a row
6480 * or column of monitors.
6482 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6486 get_monitor_containing_pointer (GtkWindow *window)
6490 GdkScreen *window_screen;
6491 GdkScreen *pointer_screen;
6492 GdkDisplay *display;
6493 GdkDeviceManager *device_manager;
6496 window_screen = gtk_window_check_screen (window);
6497 display = gdk_screen_get_display (window_screen);
6498 device_manager = gdk_display_get_device_manager (display);
6499 pointer = gdk_device_manager_get_client_pointer (device_manager);
6501 gdk_device_get_position (pointer,
6505 if (pointer_screen == window_screen)
6506 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6514 center_window_on_monitor (GtkWindow *window,
6520 GdkRectangle monitor;
6523 monitor_num = get_monitor_containing_pointer (window);
6525 if (monitor_num == -1)
6526 monitor_num = get_center_monitor_of_window (window);
6528 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6529 monitor_num, &monitor);
6531 *x = (monitor.width - w) / 2 + monitor.x;
6532 *y = (monitor.height - h) / 2 + monitor.y;
6534 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6535 * and WM decorations.
6549 if (extent > clamp_extent)
6551 *base = clamp_base + clamp_extent/2 - extent/2;
6552 else if (*base < clamp_base)
6554 else if (*base + extent > clamp_base + clamp_extent)
6555 *base = clamp_base + clamp_extent - extent;
6559 clamp_window_to_rectangle (gint *x,
6563 const GdkRectangle *rect)
6565 #ifdef DEBUGGING_OUTPUT
6566 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);
6569 /* If it is too large, center it. If it fits on the monitor but is
6570 * partially outside, move it to the closest edge. Do this
6571 * separately in x and y directions.
6573 clamp (x, w, rect->x, rect->width);
6574 clamp (y, h, rect->y, rect->height);
6575 #ifdef DEBUGGING_OUTPUT
6576 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6582 gtk_window_compute_configure_request (GtkWindow *window,
6583 GdkRectangle *request,
6584 GdkGeometry *geometry,
6587 GtkWindowPrivate *priv = window->priv;
6588 GdkGeometry new_geometry;
6591 GtkWindowPosition pos;
6592 GtkWidget *parent_widget;
6593 GtkWindowGeometryInfo *info;
6597 screen = gtk_window_check_screen (window);
6599 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6600 gtk_window_compute_configure_request_size (window,
6601 &new_geometry, new_flags,
6604 gtk_window_constrain_size (window,
6605 &new_geometry, new_flags,
6609 parent_widget = (GtkWidget*) priv->transient_parent;
6611 pos = get_effective_position (window);
6612 info = gtk_window_get_geometry_info (window, FALSE);
6614 /* by default, don't change position requested */
6617 x = info->last.configure_request.x;
6618 y = info->last.configure_request.y;
6627 if (priv->need_default_position)
6630 /* FIXME this all interrelates with window gravity.
6631 * For most of them I think we want to set GRAVITY_CENTER.
6633 * Not sure how to go about that.
6637 /* here we are only handling CENTER_ALWAYS
6638 * as it relates to default positioning,
6639 * where it's equivalent to simply CENTER
6641 case GTK_WIN_POS_CENTER_ALWAYS:
6642 case GTK_WIN_POS_CENTER:
6643 center_window_on_monitor (window, w, h, &x, &y);
6646 case GTK_WIN_POS_CENTER_ON_PARENT:
6648 GtkAllocation allocation;
6649 GdkWindow *gdk_window;
6651 GdkRectangle monitor;
6654 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6656 gdk_window = gtk_widget_get_window (parent_widget);
6658 if (gdk_window != NULL)
6659 monitor_num = gdk_screen_get_monitor_at_window (screen,
6664 gdk_window_get_origin (gdk_window,
6667 gtk_widget_get_allocation (parent_widget, &allocation);
6668 x = ox + (allocation.width - w) / 2;
6669 y = oy + (allocation.height - h) / 2;
6671 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6672 * WM decorations. If parent wasn't on a monitor, just
6675 if (monitor_num >= 0)
6677 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6678 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6683 case GTK_WIN_POS_MOUSE:
6685 gint screen_width = gdk_screen_get_width (screen);
6686 gint screen_height = gdk_screen_get_height (screen);
6688 GdkRectangle monitor;
6689 GdkDisplay *display;
6690 GdkDeviceManager *device_manager;
6692 GdkScreen *pointer_screen;
6695 display = gdk_screen_get_display (screen);
6696 device_manager = gdk_display_get_device_manager (display);
6697 pointer = gdk_device_manager_get_client_pointer (device_manager);
6699 gdk_device_get_position (pointer,
6703 if (pointer_screen == screen)
6704 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6710 x = CLAMP (x, 0, screen_width - w);
6711 y = CLAMP (y, 0, screen_height - h);
6713 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6714 * WM decorations. Don't try to figure out what's going
6715 * on if the mouse wasn't inside a monitor.
6717 if (monitor_num >= 0)
6719 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6720 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6728 } /* if (priv->need_default_position) */
6730 if (priv->need_default_position && info &&
6731 info->initial_pos_set)
6733 x = info->initial_x;
6734 y = info->initial_y;
6735 gtk_window_constrain_position (window, w, h, &x, &y);
6741 request->height = h;
6744 *geometry = new_geometry;
6750 gtk_window_constrain_position (GtkWindow *window,
6756 GtkWindowPrivate *priv = window->priv;
6758 /* See long comments in gtk_window_move_resize()
6759 * on when it's safe to call this function.
6761 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6763 gint center_x, center_y;
6765 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6773 gtk_window_move_resize (GtkWindow *window)
6777 * First we determine whether any information has changed that would
6778 * cause us to revise our last configure request. If we would send
6779 * a different configure request from last time, then
6780 * configure_request_size_changed = TRUE or
6781 * configure_request_pos_changed = TRUE. configure_request_size_changed
6782 * may be true due to new hints, a gtk_window_resize(), or whatever.
6783 * configure_request_pos_changed may be true due to gtk_window_set_position()
6784 * or gtk_window_move().
6786 * If the configure request has changed, we send off a new one. To
6787 * ensure GTK+ invariants are maintained (resize queue does what it
6788 * should), we go ahead and size_allocate the requested size in this
6791 * If the configure request has not changed, we don't ever resend
6792 * it, because it could mean fighting the user or window manager.
6795 * To prepare the configure request, we come up with a base size/pos:
6796 * - the one from gtk_window_move()/gtk_window_resize()
6797 * - else default_width, default_height if we haven't ever
6799 * - else the size request if we haven't ever been mapped,
6800 * as a substitute default size
6801 * - else the current size of the window, as received from
6802 * configure notifies (i.e. the current allocation)
6804 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6805 * the position request to be centered.
6807 GtkWindowPrivate *priv = window->priv;
6808 GtkAllocation allocation;
6810 GtkContainer *container;
6811 GtkWindowGeometryInfo *info;
6812 GdkGeometry new_geometry;
6813 GdkWindow *gdk_window;
6815 GdkRectangle new_request;
6816 gboolean configure_request_size_changed;
6817 gboolean configure_request_pos_changed;
6818 gboolean hints_changed; /* do we need to send these again */
6819 GtkWindowLastGeometryInfo saved_last_info;
6821 widget = GTK_WIDGET (window);
6823 gdk_window = gtk_widget_get_window (widget);
6824 container = GTK_CONTAINER (widget);
6825 info = gtk_window_get_geometry_info (window, TRUE);
6827 configure_request_size_changed = FALSE;
6828 configure_request_pos_changed = FALSE;
6830 gtk_window_compute_configure_request (window, &new_request,
6831 &new_geometry, &new_flags);
6833 /* This check implies the invariant that we never set info->last
6834 * without setting the hints and sending off a configure request.
6836 * If we change info->last without sending the request, we may
6839 if (info->last.configure_request.x != new_request.x ||
6840 info->last.configure_request.y != new_request.y)
6841 configure_request_pos_changed = TRUE;
6843 if ((info->last.configure_request.width != new_request.width ||
6844 info->last.configure_request.height != new_request.height))
6845 configure_request_size_changed = TRUE;
6847 hints_changed = FALSE;
6849 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6850 &new_geometry, new_flags))
6852 hints_changed = TRUE;
6855 /* Position Constraints
6856 * ====================
6858 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6859 * a default. The other POS_ values are used only when the
6860 * window is shown, not after that.
6862 * However, we can't implement a position constraint as
6863 * "anytime the window size changes, center the window"
6864 * because this may well end up fighting the WM or user. In
6865 * fact it gets in an infinite loop with at least one WM.
6867 * Basically, applications are in no way in a position to
6868 * constrain the position of a window, with one exception:
6869 * override redirect windows. (Really the intended purpose
6870 * of CENTER_ALWAYS anyhow, I would think.)
6872 * So the way we implement this "constraint" is to say that when WE
6873 * cause a move or resize, i.e. we make a configure request changing
6874 * window size, we recompute the CENTER_ALWAYS position to reflect
6875 * the new window size, and include it in our request. Also, if we
6876 * just turned on CENTER_ALWAYS we snap to center with a new
6877 * request. Otherwise, if we are just NOTIFIED of a move or resize
6878 * done by someone else e.g. the window manager, we do NOT send a
6879 * new configure request.
6881 * For override redirect windows, this works fine; all window
6882 * sizes are from our configure requests. For managed windows,
6883 * it is at least semi-sane, though who knows what the
6884 * app author is thinking.
6887 /* This condition should be kept in sync with the condition later on
6888 * that determines whether we send a configure request. i.e. we
6889 * should do this position constraining anytime we were going to
6890 * send a configure request anyhow, plus when constraints have
6893 if (configure_request_pos_changed ||
6894 configure_request_size_changed ||
6896 info->position_constraints_changed)
6898 /* We request the constrained position if:
6899 * - we were changing position, and need to clamp
6900 * the change to the constraint
6901 * - we're changing the size anyway
6902 * - set_position() was called to toggle CENTER_ALWAYS on
6905 gtk_window_constrain_position (window,
6911 /* Update whether we need to request a move */
6912 if (info->last.configure_request.x != new_request.x ||
6913 info->last.configure_request.y != new_request.y)
6914 configure_request_pos_changed = TRUE;
6916 configure_request_pos_changed = FALSE;
6920 if (priv->type == GTK_WINDOW_TOPLEVEL)
6922 int notify_x, notify_y;
6924 /* this is the position from the last configure notify */
6925 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6927 g_message ("--- %s ---\n"
6928 "last : %d,%d\t%d x %d\n"
6929 "this : %d,%d\t%d x %d\n"
6930 "alloc : %d,%d\t%d x %d\n"
6932 "resize: \t%d x %d\n"
6933 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6934 "configure_notify_received: %d\n"
6935 "configure_request_count: %d\n"
6936 "position_constraints_changed: %d\n",
6937 priv->title ? priv->title : "(no title)",
6938 info->last.configure_request.x,
6939 info->last.configure_request.y,
6940 info->last.configure_request.width,
6941 info->last.configure_request.height,
6947 widget->allocation.width,
6948 widget->allocation.height,
6949 widget->requisition.width,
6950 widget->requisition.height,
6952 info->resize_height,
6953 configure_request_pos_changed,
6954 configure_request_size_changed,
6956 priv->configure_notify_received,
6957 priv->configure_request_count,
6958 info->position_constraints_changed);
6962 saved_last_info = info->last;
6963 info->last.geometry = new_geometry;
6964 info->last.flags = new_flags;
6965 info->last.configure_request = new_request;
6967 /* need to set PPosition so the WM will look at our position,
6968 * but we don't want to count PPosition coming and going as a hints
6969 * change for future iterations. So we saved info->last prior to
6973 /* Also, if the initial position was explicitly set, then we always
6974 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6978 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6979 * this is an initial map
6982 if ((configure_request_pos_changed ||
6983 info->initial_pos_set ||
6984 (priv->need_default_position &&
6985 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6986 (new_flags & GDK_HINT_POS) == 0)
6988 new_flags |= GDK_HINT_POS;
6989 hints_changed = TRUE;
6992 /* Set hints if necessary
6995 gdk_window_set_geometry_hints (gdk_window,
6999 gtk_widget_get_allocation (widget, &allocation);
7001 /* handle resizing/moving and widget tree allocation
7003 if (priv->configure_notify_received)
7005 /* If we have received a configure event since
7006 * the last time in this function, we need to
7007 * accept our new size and size_allocate child widgets.
7008 * (see gtk_window_configure_event() for more details).
7010 * 1 or more configure notifies may have been received.
7011 * Also, configure_notify_received will only be TRUE
7012 * if all expected configure notifies have been received
7013 * (one per configure request), as an optimization.
7016 priv->configure_notify_received = FALSE;
7018 /* gtk_window_configure_event() filled in widget->allocation */
7019 gtk_widget_size_allocate (widget, &allocation);
7021 set_grip_position (window);
7022 update_grip_visibility (window);
7024 gdk_window_process_updates (gdk_window, TRUE);
7026 gdk_window_configure_finished (gdk_window);
7028 /* If the configure request changed, it means that
7030 * 1) coincidentally changed hints or widget properties
7031 * impacting the configure request before getting
7032 * a configure notify, or
7033 * 2) some broken widget is changing its size request
7034 * during size allocation, resulting in
7035 * a false appearance of changed configure request.
7037 * For 1), we could just go ahead and ask for the
7038 * new size right now, but doing that for 2)
7039 * might well be fighting the user (and can even
7040 * trigger a loop). Since we really don't want to
7041 * do that, we requeue a resize in hopes that
7042 * by the time it gets handled, the child has seen
7043 * the light and is willing to go along with the
7044 * new size. (this happens for the zvt widget, since
7045 * the size_allocate() above will have stored the
7046 * requisition corresponding to the new size in the
7049 * This doesn't buy us anything for 1), but it shouldn't
7050 * hurt us too badly, since it is what would have
7051 * happened if we had gotten the configure event before
7052 * the new size had been set.
7055 if (configure_request_size_changed ||
7056 configure_request_pos_changed)
7058 /* Don't change the recorded last info after all, because we
7059 * haven't actually updated to the new info yet - we decided
7060 * to postpone our configure request until later.
7062 info->last = saved_last_info;
7064 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7067 return; /* Bail out, we didn't really process the move/resize */
7069 else if ((configure_request_size_changed || hints_changed) &&
7070 (allocation.width != new_request.width || allocation.height != new_request.height))
7073 /* We are in one of the following situations:
7074 * A. configure_request_size_changed
7075 * our requisition has changed and we need a different window size,
7076 * so we request it from the window manager.
7077 * B. !configure_request_size_changed && hints_changed
7078 * the window manager rejects our size, but we have just changed the
7079 * window manager hints, so there's a chance our request will
7080 * be honoured this time, so we try again.
7082 * However, if the new requisition is the same as the current allocation,
7083 * we don't request it again, since we won't get a ConfigureNotify back from
7084 * the window manager unless it decides to change our requisition. If
7085 * we don't get the ConfigureNotify back, the resize queue will never be run.
7088 /* Now send the configure request */
7089 if (configure_request_pos_changed)
7091 gdk_window_move_resize (gdk_window,
7092 new_request.x, new_request.y,
7093 new_request.width, new_request.height);
7095 else /* only size changed */
7097 gdk_window_resize (gdk_window,
7098 new_request.width, new_request.height);
7101 if (priv->type == GTK_WINDOW_POPUP)
7103 GtkAllocation allocation;
7105 /* Directly size allocate for override redirect (popup) windows. */
7108 allocation.width = new_request.width;
7109 allocation.height = new_request.height;
7111 gtk_widget_size_allocate (widget, &allocation);
7113 gdk_window_process_updates (gdk_window, TRUE);
7115 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7116 gtk_widget_queue_draw (widget);
7120 /* Increment the number of have-not-yet-received-notify requests */
7121 priv->configure_request_count += 1;
7122 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7124 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7125 * configure event in response to our resizing request.
7126 * the configure event will cause a new resize with
7127 * ->configure_notify_received=TRUE.
7128 * until then, we want to
7129 * - discard expose events
7130 * - coalesce resizes for our children
7131 * - defer any window resizes until the configure event arrived
7132 * to achieve this, we queue a resize for the window, but remove its
7133 * resizing handler, so resizing will not be handled from the next
7134 * idle handler but when the configure event arrives.
7136 * FIXME: we should also dequeue the pending redraws here, since
7137 * we handle those ourselves upon ->configure_notify_received==TRUE.
7139 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7141 gtk_widget_queue_resize_no_redraw (widget);
7142 _gtk_container_dequeue_resize_handler (container);
7148 /* Handle any position changes.
7150 if (configure_request_pos_changed)
7152 gdk_window_move (gdk_window,
7153 new_request.x, new_request.y);
7156 /* And run the resize queue.
7158 gtk_container_resize_children (container);
7161 /* We have now processed a move/resize since the last position
7162 * constraint change, setting of the initial position, or resize.
7163 * (Not resetting these flags here can lead to infinite loops for
7164 * GTK_RESIZE_IMMEDIATE containers)
7166 info->position_constraints_changed = FALSE;
7167 info->initial_pos_set = FALSE;
7168 info->resize_width = -1;
7169 info->resize_height = -1;
7172 /* Compare two sets of Geometry hints for equality.
7175 gtk_window_compare_hints (GdkGeometry *geometry_a,
7177 GdkGeometry *geometry_b,
7180 if (flags_a != flags_b)
7183 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7184 (geometry_a->min_width != geometry_b->min_width ||
7185 geometry_a->min_height != geometry_b->min_height))
7188 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7189 (geometry_a->max_width != geometry_b->max_width ||
7190 geometry_a->max_height != geometry_b->max_height))
7193 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7194 (geometry_a->base_width != geometry_b->base_width ||
7195 geometry_a->base_height != geometry_b->base_height))
7198 if ((flags_a & GDK_HINT_ASPECT) &&
7199 (geometry_a->min_aspect != geometry_b->min_aspect ||
7200 geometry_a->max_aspect != geometry_b->max_aspect))
7203 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7204 (geometry_a->width_inc != geometry_b->width_inc ||
7205 geometry_a->height_inc != geometry_b->height_inc))
7208 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7209 geometry_a->win_gravity != geometry_b->win_gravity)
7216 _gtk_window_constrain_size (GtkWindow *window,
7222 GtkWindowPrivate *priv;
7223 GtkWindowGeometryInfo *info;
7225 g_return_if_fail (GTK_IS_WINDOW (window));
7227 priv = window->priv;
7229 info = priv->geometry_info;
7232 GdkWindowHints flags = info->last.flags;
7233 GdkGeometry *geometry = &info->last.geometry;
7235 gtk_window_constrain_size (window,
7246 gtk_window_constrain_size (GtkWindow *window,
7247 GdkGeometry *geometry,
7254 gdk_window_constrain_size (geometry, flags, width, height,
7255 new_width, new_height);
7258 /* Compute the set of geometry hints and flags for a window
7259 * based on the application set geometry, and requisition
7260 * of the window. gtk_widget_get_preferred_size() must have been
7264 gtk_window_compute_hints (GtkWindow *window,
7265 GdkGeometry *new_geometry,
7268 GtkWindowPrivate *priv = window->priv;
7270 gint extra_width = 0;
7271 gint extra_height = 0;
7272 GtkWindowGeometryInfo *geometry_info;
7273 GtkRequisition requisition;
7275 widget = GTK_WIDGET (window);
7277 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7278 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7282 *new_flags = geometry_info->mask;
7283 *new_geometry = geometry_info->geometry;
7290 if (geometry_info && geometry_info->widget)
7292 /* If the geometry widget is set, then the hints really apply to that
7293 * widget. This is pretty much meaningless unless the window layout
7294 * is such that the rest of the window adds fixed size borders to
7295 * the geometry widget. Our job is to figure the size of the borders;
7296 * We do that by asking how big the toplevel would be if the
7297 * geometry widget was *really big*.
7300 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7301 * |GGGGG B| in the border can confuse things
7307 * |AAAAAAAAA | When the geometry widget is large, things are
7308 * |GGGGGGGGGGB| clearer.
7313 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7314 GtkRequisition requisition;
7315 int current_width, current_height;
7317 _gtk_widget_override_size_request (geometry_info->widget,
7318 TEMPORARY_SIZE, TEMPORARY_SIZE,
7319 ¤t_width, ¤t_height);
7320 gtk_widget_get_preferred_size (widget,
7321 &requisition, NULL);
7322 _gtk_widget_restore_size_request (geometry_info->widget,
7323 current_width, current_height);
7325 extra_width = requisition.width - TEMPORARY_SIZE;
7326 extra_height = requisition.height - TEMPORARY_SIZE;
7328 if (extra_width < 0 || extra_height < 0)
7330 g_warning("Toplevel size doesn't seem to directly depend on the "
7331 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7332 "The geometry widget might not be in the window, or it might not "
7333 "be packed into the window appropriately");
7334 extra_width = MAX(extra_width, 0);
7335 extra_height = MAX(extra_height, 0);
7337 #undef TEMPORARY_SIZE
7340 /* We don't want to set GDK_HINT_POS in here, we just set it
7341 * in gtk_window_move_resize() when we want the position
7345 if (*new_flags & GDK_HINT_BASE_SIZE)
7347 new_geometry->base_width += extra_width;
7348 new_geometry->base_height += extra_height;
7352 /* For simplicity, we always set the base hint, even when we
7353 * don't expect it to have any visible effect.
7354 * (Note: geometry_size_to_pixels() depends on this.)
7356 *new_flags |= GDK_HINT_BASE_SIZE;
7358 new_geometry->base_width = extra_width;
7359 new_geometry->base_height = extra_height;
7361 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7362 * base size is the minimum size */
7363 if (*new_flags & GDK_HINT_MIN_SIZE)
7365 if (new_geometry->min_width > 0)
7366 new_geometry->base_width += new_geometry->min_width;
7367 if (new_geometry->min_height > 0)
7368 new_geometry->base_height += new_geometry->min_height;
7372 /* Please use a good size for unresizable widgets, not the minimum one. */
7373 if (!priv->resizable)
7374 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7376 if (*new_flags & GDK_HINT_MIN_SIZE)
7378 if (new_geometry->min_width < 0)
7379 new_geometry->min_width = requisition.width;
7381 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7383 if (new_geometry->min_height < 0)
7384 new_geometry->min_height = requisition.height;
7386 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7390 *new_flags |= GDK_HINT_MIN_SIZE;
7392 new_geometry->min_width = requisition.width;
7393 new_geometry->min_height = requisition.height;
7396 if (*new_flags & GDK_HINT_MAX_SIZE)
7398 if (new_geometry->max_width < 0)
7399 new_geometry->max_width = requisition.width;
7401 new_geometry->max_width += extra_width;
7403 if (new_geometry->max_height < 0)
7404 new_geometry->max_height = requisition.height;
7406 new_geometry->max_height += extra_height;
7408 else if (!priv->resizable)
7410 *new_flags |= GDK_HINT_MAX_SIZE;
7412 new_geometry->max_width = requisition.width;
7413 new_geometry->max_height = requisition.height;
7416 *new_flags |= GDK_HINT_WIN_GRAVITY;
7417 new_geometry->win_gravity = priv->gravity;
7420 /***********************
7421 * Redrawing functions *
7422 ***********************/
7425 gtk_window_draw (GtkWidget *widget,
7428 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7429 GtkStyleContext *context;
7430 gboolean ret = FALSE;
7432 context = gtk_widget_get_style_context (widget);
7434 gtk_style_context_save (context);
7436 if (!gtk_widget_get_app_paintable (widget))
7438 GtkStateFlags state;
7440 state = gtk_widget_get_state_flags (widget);
7442 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7443 state |= GTK_STATE_FLAG_FOCUSED;
7445 gtk_style_context_set_state (context, state);
7446 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7447 gtk_render_background (context, cr, 0, 0,
7448 gtk_widget_get_allocated_width (widget),
7449 gtk_widget_get_allocated_height (widget));
7452 gtk_style_context_restore (context);
7454 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7455 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7457 if (priv->grip_window &&
7458 gtk_cairo_should_draw_window (cr, priv->grip_window))
7462 gtk_style_context_save (context);
7465 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7466 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7468 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7469 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7470 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7473 gtk_style_context_restore (context);
7480 * gtk_window_present:
7481 * @window: a #GtkWindow
7483 * Presents a window to the user. This may mean raising the window
7484 * in the stacking order, deiconifying it, moving it to the current
7485 * desktop, and/or giving it the keyboard focus, possibly dependent
7486 * on the user's platform, window manager, and preferences.
7488 * If @window is hidden, this function calls gtk_widget_show()
7491 * This function should be used when the user tries to open a window
7492 * that's already open. Say for example the preferences dialog is
7493 * currently open, and the user chooses Preferences from the menu
7494 * a second time; use gtk_window_present() to move the already-open dialog
7495 * where the user can see it.
7497 * If you are calling this function in response to a user interaction,
7498 * it is preferable to use gtk_window_present_with_time().
7502 gtk_window_present (GtkWindow *window)
7504 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7508 * gtk_window_present_with_time:
7509 * @window: a #GtkWindow
7510 * @timestamp: the timestamp of the user interaction (typically a
7511 * button or key press event) which triggered this call
7513 * Presents a window to the user in response to a user interaction.
7514 * If you need to present a window without a timestamp, use
7515 * gtk_window_present(). See gtk_window_present() for details.
7520 gtk_window_present_with_time (GtkWindow *window,
7523 GtkWindowPrivate *priv;
7525 GdkWindow *gdk_window;
7527 g_return_if_fail (GTK_IS_WINDOW (window));
7529 priv = window->priv;
7530 widget = GTK_WIDGET (window);
7532 if (gtk_widget_get_visible (widget))
7534 gdk_window = gtk_widget_get_window (widget);
7536 g_assert (gdk_window != NULL);
7538 gdk_window_show (gdk_window);
7540 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7541 if (timestamp == GDK_CURRENT_TIME)
7543 #ifdef GDK_WINDOWING_X11
7544 if (GDK_IS_X11_WINDOW(gdk_window))
7546 GdkDisplay *display;
7548 display = gtk_widget_get_display (GTK_WIDGET (window));
7549 timestamp = gdk_x11_display_get_user_time (display);
7553 timestamp = gtk_get_current_event_time ();
7556 gdk_window_focus (gdk_window, timestamp);
7560 priv->initial_timestamp = timestamp;
7561 gtk_widget_show (widget);
7566 * gtk_window_iconify:
7567 * @window: a #GtkWindow
7569 * Asks to iconify (i.e. minimize) the specified @window. Note that
7570 * you shouldn't assume the window is definitely iconified afterward,
7571 * because other entities (e.g. the user or <link
7572 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7573 * again, or there may not be a window manager in which case
7574 * iconification isn't possible, etc. But normally the window will end
7575 * up iconified. Just don't write code that crashes if not.
7577 * It's permitted to call this function before showing a window,
7578 * in which case the window will be iconified before it ever appears
7581 * You can track iconification via the "window-state-event" signal
7586 gtk_window_iconify (GtkWindow *window)
7588 GtkWindowPrivate *priv;
7590 GdkWindow *toplevel;
7592 g_return_if_fail (GTK_IS_WINDOW (window));
7594 priv = window->priv;
7595 widget = GTK_WIDGET (window);
7597 priv->iconify_initially = TRUE;
7599 toplevel = gtk_widget_get_window (widget);
7601 if (toplevel != NULL)
7602 gdk_window_iconify (toplevel);
7606 * gtk_window_deiconify:
7607 * @window: a #GtkWindow
7609 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7610 * that you shouldn't assume the window is definitely deiconified
7611 * afterward, because other entities (e.g. the user or <link
7612 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7613 * again before your code which assumes deiconification gets to run.
7615 * You can track iconification via the "window-state-event" signal
7619 gtk_window_deiconify (GtkWindow *window)
7621 GtkWindowPrivate *priv;
7623 GdkWindow *toplevel;
7625 g_return_if_fail (GTK_IS_WINDOW (window));
7627 priv = window->priv;
7628 widget = GTK_WIDGET (window);
7630 priv->iconify_initially = FALSE;
7632 toplevel = gtk_widget_get_window (widget);
7634 if (toplevel != NULL)
7635 gdk_window_deiconify (toplevel);
7640 * @window: a #GtkWindow
7642 * Asks to stick @window, which means that it will appear on all user
7643 * desktops. Note that you shouldn't assume the window is definitely
7644 * stuck afterward, because other entities (e.g. the user or <link
7645 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7646 * again, and some window managers do not support sticking
7647 * windows. But normally the window will end up stuck. Just don't
7648 * write code that crashes if not.
7650 * It's permitted to call this function before showing a window.
7652 * You can track stickiness via the "window-state-event" signal
7657 gtk_window_stick (GtkWindow *window)
7659 GtkWindowPrivate *priv;
7661 GdkWindow *toplevel;
7663 g_return_if_fail (GTK_IS_WINDOW (window));
7665 priv = window->priv;
7666 widget = GTK_WIDGET (window);
7668 priv->stick_initially = TRUE;
7670 toplevel = gtk_widget_get_window (widget);
7672 if (toplevel != NULL)
7673 gdk_window_stick (toplevel);
7677 * gtk_window_unstick:
7678 * @window: a #GtkWindow
7680 * Asks to unstick @window, which means that it will appear on only
7681 * one of the user's desktops. Note that you shouldn't assume the
7682 * window is definitely unstuck afterward, because other entities
7683 * (e.g. the user or <link linkend="gtk-X11-arch">window
7684 * manager</link>) could stick it again. But normally the window will
7685 * end up stuck. Just don't write code that crashes if not.
7687 * You can track stickiness via the "window-state-event" signal
7692 gtk_window_unstick (GtkWindow *window)
7694 GtkWindowPrivate *priv;
7696 GdkWindow *toplevel;
7698 g_return_if_fail (GTK_IS_WINDOW (window));
7700 priv = window->priv;
7701 widget = GTK_WIDGET (window);
7703 priv->stick_initially = FALSE;
7705 toplevel = gtk_widget_get_window (widget);
7707 if (toplevel != NULL)
7708 gdk_window_unstick (toplevel);
7712 * gtk_window_maximize:
7713 * @window: a #GtkWindow
7715 * Asks to maximize @window, so that it becomes full-screen. Note that
7716 * you shouldn't assume the window is definitely maximized afterward,
7717 * because other entities (e.g. the user or <link
7718 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7719 * again, and not all window managers support maximization. But
7720 * normally the window will end up maximized. Just don't write code
7721 * that crashes if not.
7723 * It's permitted to call this function before showing a window,
7724 * in which case the window will be maximized when it appears onscreen
7727 * You can track maximization via the "window-state-event" signal
7732 gtk_window_maximize (GtkWindow *window)
7734 GtkWindowPrivate *priv;
7736 GdkWindow *toplevel;
7738 g_return_if_fail (GTK_IS_WINDOW (window));
7740 priv = window->priv;
7741 widget = GTK_WIDGET (window);
7743 priv->maximize_initially = TRUE;
7745 toplevel = gtk_widget_get_window (widget);
7747 if (toplevel != NULL)
7748 gdk_window_maximize (toplevel);
7752 * gtk_window_unmaximize:
7753 * @window: a #GtkWindow
7755 * Asks to unmaximize @window. Note that you shouldn't assume the
7756 * window is definitely unmaximized afterward, because other entities
7757 * (e.g. the user or <link linkend="gtk-X11-arch">window
7758 * manager</link>) could maximize it again, and not all window
7759 * managers honor requests to unmaximize. But normally the window will
7760 * end up unmaximized. Just don't write code that crashes if not.
7762 * You can track maximization via the "window-state-event" signal
7767 gtk_window_unmaximize (GtkWindow *window)
7769 GtkWindowPrivate *priv;
7771 GdkWindow *toplevel;
7773 g_return_if_fail (GTK_IS_WINDOW (window));
7775 priv = window->priv;
7776 widget = GTK_WIDGET (window);
7778 priv->maximize_initially = FALSE;
7780 toplevel = gtk_widget_get_window (widget);
7782 if (toplevel != NULL)
7783 gdk_window_unmaximize (toplevel);
7787 * gtk_window_fullscreen:
7788 * @window: a #GtkWindow
7790 * Asks to place @window in the fullscreen state. Note that you
7791 * shouldn't assume the window is definitely full screen afterward,
7792 * because other entities (e.g. the user or <link
7793 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7794 * again, and not all window managers honor requests to fullscreen
7795 * windows. But normally the window will end up fullscreen. Just
7796 * don't write code that crashes if not.
7798 * You can track the fullscreen state via the "window-state-event" signal
7804 gtk_window_fullscreen (GtkWindow *window)
7806 GtkWindowPrivate *priv;
7808 GdkWindow *toplevel;
7810 g_return_if_fail (GTK_IS_WINDOW (window));
7812 priv = window->priv;
7813 widget = GTK_WIDGET (window);
7815 priv->fullscreen_initially = TRUE;
7817 toplevel = gtk_widget_get_window (widget);
7819 if (toplevel != NULL)
7820 gdk_window_fullscreen (toplevel);
7824 * gtk_window_unfullscreen:
7825 * @window: a #GtkWindow
7827 * Asks to toggle off the fullscreen state for @window. Note that you
7828 * shouldn't assume the window is definitely not full screen
7829 * afterward, because other entities (e.g. the user or <link
7830 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7831 * again, and not all window managers honor requests to unfullscreen
7832 * windows. But normally the window will end up restored to its normal
7833 * state. Just don't write code that crashes if not.
7835 * You can track the fullscreen state via the "window-state-event" signal
7841 gtk_window_unfullscreen (GtkWindow *window)
7844 GdkWindow *toplevel;
7845 GtkWindowPrivate *priv;
7847 g_return_if_fail (GTK_IS_WINDOW (window));
7849 priv = window->priv;
7850 widget = GTK_WIDGET (window);
7852 priv->fullscreen_initially = FALSE;
7854 toplevel = gtk_widget_get_window (widget);
7856 if (toplevel != NULL)
7857 gdk_window_unfullscreen (toplevel);
7861 * gtk_window_set_keep_above:
7862 * @window: a #GtkWindow
7863 * @setting: whether to keep @window above other windows
7865 * Asks to keep @window above, so that it stays on top. Note that
7866 * you shouldn't assume the window is definitely above afterward,
7867 * because other entities (e.g. the user or <link
7868 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7869 * and not all window managers support keeping windows above. But
7870 * normally the window will end kept above. Just don't write code
7871 * that crashes if not.
7873 * It's permitted to call this function before showing a window,
7874 * in which case the window will be kept above when it appears onscreen
7877 * You can track the above state via the "window-state-event" signal
7880 * Note that, according to the <ulink
7881 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7882 * Manager Hints</ulink> specification, the above state is mainly meant
7883 * for user preferences and should not be used by applications e.g. for
7884 * drawing attention to their dialogs.
7889 gtk_window_set_keep_above (GtkWindow *window,
7893 GtkWindowPrivate *priv;
7894 GdkWindow *toplevel;
7896 g_return_if_fail (GTK_IS_WINDOW (window));
7898 priv = window->priv;
7899 widget = GTK_WIDGET (window);
7901 priv->above_initially = setting != FALSE;
7903 priv->below_initially = FALSE;
7905 toplevel = gtk_widget_get_window (widget);
7907 if (toplevel != NULL)
7908 gdk_window_set_keep_above (toplevel, setting);
7912 * gtk_window_set_keep_below:
7913 * @window: a #GtkWindow
7914 * @setting: whether to keep @window below other windows
7916 * Asks to keep @window below, so that it stays in bottom. Note that
7917 * you shouldn't assume the window is definitely below afterward,
7918 * because other entities (e.g. the user or <link
7919 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7920 * and not all window managers support putting windows below. But
7921 * normally the window will be kept below. Just don't write code
7922 * that crashes if not.
7924 * It's permitted to call this function before showing a window,
7925 * in which case the window will be kept below when it appears onscreen
7928 * You can track the below state via the "window-state-event" signal
7931 * Note that, according to the <ulink
7932 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7933 * Manager Hints</ulink> specification, the above state is mainly meant
7934 * for user preferences and should not be used by applications e.g. for
7935 * drawing attention to their dialogs.
7940 gtk_window_set_keep_below (GtkWindow *window,
7944 GtkWindowPrivate *priv;
7945 GdkWindow *toplevel;
7947 g_return_if_fail (GTK_IS_WINDOW (window));
7949 priv = window->priv;
7950 widget = GTK_WIDGET (window);
7952 priv->below_initially = setting != FALSE;
7954 priv->above_initially = FALSE;
7956 toplevel = gtk_widget_get_window (widget);
7958 if (toplevel != NULL)
7959 gdk_window_set_keep_below (toplevel, setting);
7963 * gtk_window_set_resizable:
7964 * @window: a #GtkWindow
7965 * @resizable: %TRUE if the user can resize this window
7967 * Sets whether the user can resize a window. Windows are user resizable
7971 gtk_window_set_resizable (GtkWindow *window,
7974 GtkWindowPrivate *priv;
7976 g_return_if_fail (GTK_IS_WINDOW (window));
7978 priv = window->priv;
7980 resizable = (resizable != FALSE);
7982 if (priv->resizable != resizable)
7984 priv->resizable = (resizable != FALSE);
7986 update_grip_visibility (window);
7988 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7990 g_object_notify (G_OBJECT (window), "resizable");
7995 * gtk_window_get_resizable:
7996 * @window: a #GtkWindow
7998 * Gets the value set by gtk_window_set_resizable().
8000 * Return value: %TRUE if the user can resize the window
8003 gtk_window_get_resizable (GtkWindow *window)
8005 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8007 return window->priv->resizable;
8011 * gtk_window_set_gravity:
8012 * @window: a #GtkWindow
8013 * @gravity: window gravity
8015 * Window gravity defines the meaning of coordinates passed to
8016 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8019 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8020 * typically "do what you mean."
8024 gtk_window_set_gravity (GtkWindow *window,
8027 GtkWindowPrivate *priv;
8029 g_return_if_fail (GTK_IS_WINDOW (window));
8031 priv = window->priv;
8033 if (gravity != priv->gravity)
8035 priv->gravity = gravity;
8037 /* gtk_window_move_resize() will adapt gravity
8039 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8041 g_object_notify (G_OBJECT (window), "gravity");
8046 * gtk_window_get_gravity:
8047 * @window: a #GtkWindow
8049 * Gets the value set by gtk_window_set_gravity().
8051 * Return value: (transfer none): window gravity
8054 gtk_window_get_gravity (GtkWindow *window)
8056 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8058 return window->priv->gravity;
8062 * gtk_window_begin_resize_drag:
8063 * @window: a #GtkWindow
8064 * @button: mouse button that initiated the drag
8065 * @edge: position of the resize control
8066 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8067 * @root_y: Y position where the user clicked to initiate the drag
8068 * @timestamp: timestamp from the click event that initiated the drag
8070 * Starts resizing a window. This function is used if an application
8071 * has window resizing controls. When GDK can support it, the resize
8072 * will be done using the standard mechanism for the <link
8073 * linkend="gtk-X11-arch">window manager</link> or windowing
8074 * system. Otherwise, GDK will try to emulate window resizing,
8075 * potentially not all that well, depending on the windowing system.
8079 gtk_window_begin_resize_drag (GtkWindow *window,
8087 GdkWindow *toplevel;
8089 g_return_if_fail (GTK_IS_WINDOW (window));
8090 widget = GTK_WIDGET (window);
8091 g_return_if_fail (gtk_widget_get_visible (widget));
8093 toplevel = gtk_widget_get_window (widget);
8095 gdk_window_begin_resize_drag (toplevel,
8102 * gtk_window_begin_move_drag:
8103 * @window: a #GtkWindow
8104 * @button: mouse button that initiated the drag
8105 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8106 * @root_y: Y position where the user clicked to initiate the drag
8107 * @timestamp: timestamp from the click event that initiated the drag
8109 * Starts moving a window. This function is used if an application has
8110 * window movement grips. When GDK can support it, the window movement
8111 * will be done using the standard mechanism for the <link
8112 * linkend="gtk-X11-arch">window manager</link> or windowing
8113 * system. Otherwise, GDK will try to emulate window movement,
8114 * potentially not all that well, depending on the windowing system.
8118 gtk_window_begin_move_drag (GtkWindow *window,
8125 GdkWindow *toplevel;
8127 g_return_if_fail (GTK_IS_WINDOW (window));
8128 widget = GTK_WIDGET (window);
8129 g_return_if_fail (gtk_widget_get_visible (widget));
8131 toplevel = gtk_widget_get_window (widget);
8133 gdk_window_begin_move_drag (toplevel,
8140 * gtk_window_set_screen:
8141 * @window: a #GtkWindow.
8142 * @screen: a #GdkScreen.
8144 * Sets the #GdkScreen where the @window is displayed; if
8145 * the window is already mapped, it will be unmapped, and
8146 * then remapped on the new screen.
8151 gtk_window_set_screen (GtkWindow *window,
8154 GtkWindowPrivate *priv;
8156 GdkScreen *previous_screen;
8157 gboolean was_mapped;
8159 g_return_if_fail (GTK_IS_WINDOW (window));
8160 g_return_if_fail (GDK_IS_SCREEN (screen));
8162 priv = window->priv;
8164 if (screen == priv->screen)
8167 widget = GTK_WIDGET (window);
8169 previous_screen = priv->screen;
8170 was_mapped = gtk_widget_get_mapped (widget);
8173 gtk_widget_unmap (widget);
8174 if (gtk_widget_get_realized (widget))
8175 gtk_widget_unrealize (widget);
8177 gtk_window_free_key_hash (window);
8178 priv->screen = screen;
8179 gtk_widget_reset_rc_styles (widget);
8180 if (screen != previous_screen)
8182 if (previous_screen)
8184 g_signal_handlers_disconnect_by_func (previous_screen,
8185 gtk_window_on_composited_changed, window);
8186 #ifdef GDK_WINDOWING_X11
8187 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8188 gtk_window_on_theme_variant_changed, window);
8191 g_signal_connect (screen, "composited-changed",
8192 G_CALLBACK (gtk_window_on_composited_changed), window);
8193 #ifdef GDK_WINDOWING_X11
8194 g_signal_connect (gtk_settings_get_for_screen (screen),
8195 "notify::gtk-application-prefer-dark-theme",
8196 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8199 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8200 _gtk_widget_propagate_composited_changed (widget);
8202 g_object_notify (G_OBJECT (window), "screen");
8205 gtk_widget_map (widget);
8209 gtk_window_set_theme_variant (GtkWindow *window)
8211 #ifdef GDK_WINDOWING_X11
8212 GdkWindow *gdk_window;
8213 gboolean dark_theme_requested;
8215 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8216 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8219 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8221 if (GDK_IS_X11_WINDOW (gdk_window))
8222 gdk_x11_window_set_theme_variant (gdk_window,
8223 dark_theme_requested ? "dark" : NULL);
8228 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8232 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8233 gtk_window_set_theme_variant (window);
8237 gtk_window_on_composited_changed (GdkScreen *screen,
8240 gtk_widget_queue_draw (GTK_WIDGET (window));
8242 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8246 gtk_window_check_screen (GtkWindow *window)
8248 GtkWindowPrivate *priv = window->priv;
8251 return priv->screen;
8254 g_warning ("Screen for GtkWindow not set; you must always set\n"
8255 "a screen for a GtkWindow before using the window");
8261 * gtk_window_get_screen:
8262 * @window: a #GtkWindow.
8264 * Returns the #GdkScreen associated with @window.
8266 * Return value: (transfer none): a #GdkScreen.
8271 gtk_window_get_screen (GtkWindow *window)
8273 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8275 return window->priv->screen;
8279 * gtk_window_is_active:
8280 * @window: a #GtkWindow
8282 * Returns whether the window is part of the current active toplevel.
8283 * (That is, the toplevel window receiving keystrokes.)
8284 * The return value is %TRUE if the window is active toplevel
8285 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8286 * You might use this function if you wanted to draw a widget
8287 * differently in an active window from a widget in an inactive window.
8288 * See gtk_window_has_toplevel_focus()
8290 * Return value: %TRUE if the window part of the current active window.
8295 gtk_window_is_active (GtkWindow *window)
8297 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8299 return window->priv->is_active;
8303 * gtk_window_has_toplevel_focus:
8304 * @window: a #GtkWindow
8306 * Returns whether the input focus is within this GtkWindow.
8307 * For real toplevel windows, this is identical to gtk_window_is_active(),
8308 * but for embedded windows, like #GtkPlug, the results will differ.
8310 * Return value: %TRUE if the input focus is within this GtkWindow
8315 gtk_window_has_toplevel_focus (GtkWindow *window)
8317 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8319 return window->priv->has_toplevel_focus;
8324 * SECTION:gtkwindowgroup
8325 * @Short_description: Limit the effect of grabs
8326 * @Title: GtkWindowGroup
8328 * #GtkWindowGroup objects are referenced by each window in the group,
8329 * so once you have added all windows to a #GtkWindowGroup, you can drop
8330 * the initial reference to the window group with g_object_unref(). If the
8331 * windows in the window group are subsequently destroyed, then they will
8332 * be removed from the window group and drop their references on the window
8333 * group; when all window have been removed, the window group will be
8337 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8340 gtk_window_group_init (GtkWindowGroup *group)
8342 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8343 GTK_TYPE_WINDOW_GROUP,
8344 GtkWindowGroupPrivate);
8348 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8350 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8354 * gtk_window_group_new:
8356 * Creates a new #GtkWindowGroup object. Grabs added with
8357 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8359 * Return value: a new #GtkWindowGroup.
8362 gtk_window_group_new (void)
8364 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8368 window_group_cleanup_grabs (GtkWindowGroup *group,
8371 GtkWindowGroupPrivate *priv;
8372 GtkDeviceGrabInfo *info;
8374 GSList *to_remove = NULL;
8378 tmp_list = priv->grabs;
8381 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8382 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8383 tmp_list = tmp_list->next;
8388 gtk_grab_remove (to_remove->data);
8389 g_object_unref (to_remove->data);
8390 to_remove = g_slist_delete_link (to_remove, to_remove);
8393 tmp_list = priv->device_grabs;
8397 info = tmp_list->data;
8399 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8400 to_remove = g_slist_prepend (to_remove, info);
8402 tmp_list = tmp_list->next;
8407 info = to_remove->data;
8409 gtk_device_grab_remove (info->widget, info->device);
8410 to_remove = g_slist_delete_link (to_remove, to_remove);
8415 * gtk_window_group_add_window:
8416 * @window_group: a #GtkWindowGroup
8417 * @window: the #GtkWindow to add
8419 * Adds a window to a #GtkWindowGroup.
8422 gtk_window_group_add_window (GtkWindowGroup *window_group,
8425 GtkWindowPrivate *priv;
8427 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8428 g_return_if_fail (GTK_IS_WINDOW (window));
8430 priv = window->priv;
8432 if (priv->group != window_group)
8434 g_object_ref (window);
8435 g_object_ref (window_group);
8438 gtk_window_group_remove_window (priv->group, window);
8440 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8442 priv->group = window_group;
8444 g_object_unref (window);
8449 * gtk_window_group_remove_window:
8450 * @window_group: a #GtkWindowGroup
8451 * @window: the #GtkWindow to remove
8453 * Removes a window from a #GtkWindowGroup.
8456 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8459 GtkWindowPrivate *priv;
8461 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8462 g_return_if_fail (GTK_IS_WINDOW (window));
8463 priv = window->priv;
8464 g_return_if_fail (priv->group == window_group);
8466 g_object_ref (window);
8468 window_group_cleanup_grabs (window_group, window);
8471 g_object_unref (window_group);
8472 g_object_unref (window);
8476 * gtk_window_group_list_windows:
8477 * @window_group: a #GtkWindowGroup
8479 * Returns a list of the #GtkWindows that belong to @window_group.
8481 * Returns: (element-type GtkWindow) (transfer container): A
8482 * newly-allocated list of windows inside the group.
8487 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8489 GList *toplevels, *toplevel, *group_windows;
8491 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8493 group_windows = NULL;
8494 toplevels = gtk_window_list_toplevels ();
8496 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8498 GtkWindow *window = toplevel->data;
8500 if (window_group == window->priv->group)
8501 group_windows = g_list_prepend (group_windows, window);
8504 g_list_free (toplevels);
8506 return g_list_reverse (group_windows);
8510 * gtk_window_get_group:
8511 * @window: (allow-none): a #GtkWindow, or %NULL
8513 * Returns the group for @window or the default group, if
8514 * @window is %NULL or if @window does not have an explicit
8517 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8522 gtk_window_get_group (GtkWindow *window)
8524 if (window && window->priv->group)
8525 return window->priv->group;
8528 static GtkWindowGroup *default_group = NULL;
8531 default_group = gtk_window_group_new ();
8533 return default_group;
8538 * gtk_window_has_group:
8539 * @window: a #GtkWindow
8541 * Returns whether @window has an explicit window group.
8543 * Return value: %TRUE if @window has an explicit window group.
8548 gtk_window_has_group (GtkWindow *window)
8550 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8552 return window->priv->group != NULL;
8556 * gtk_window_group_get_current_grab:
8557 * @window_group: a #GtkWindowGroup
8559 * Gets the current grab widget of the given group,
8560 * see gtk_grab_add().
8562 * Returns: (transfer none): the current grab widget of the group
8567 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8569 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8571 if (window_group->priv->grabs)
8572 return GTK_WIDGET (window_group->priv->grabs->data);
8577 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8580 GtkWindowGroupPrivate *priv;
8582 priv = window_group->priv;
8583 priv->grabs = g_slist_prepend (priv->grabs, widget);
8587 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8590 GtkWindowGroupPrivate *priv;
8592 priv = window_group->priv;
8593 priv->grabs = g_slist_remove (priv->grabs, widget);
8598 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8601 gboolean block_others)
8603 GtkWindowGroupPrivate *priv;
8604 GtkDeviceGrabInfo *info;
8606 priv = window_group->priv;
8608 info = g_slice_new0 (GtkDeviceGrabInfo);
8609 info->widget = widget;
8610 info->device = device;
8611 info->block_others = block_others;
8613 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8617 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8621 GtkWindowGroupPrivate *priv;
8622 GtkDeviceGrabInfo *info;
8623 GSList *list, *node = NULL;
8624 GdkDevice *other_device;
8626 priv = window_group->priv;
8627 other_device = gdk_device_get_associated_device (device);
8628 list = priv->device_grabs;
8634 if (info->widget == widget &&
8635 (info->device == device ||
8636 info->device == other_device))
8649 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8650 g_slice_free (GtkDeviceGrabInfo, info);
8655 * gtk_window_group_get_current_device_grab:
8656 * @window_group: a #GtkWindowGroup
8657 * @device: a #GdkDevice
8659 * Returns the current grab widget for @device, or %NULL if none.
8661 * Returns: (transfer none): The grab widget, or %NULL
8666 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8669 GtkWindowGroupPrivate *priv;
8670 GtkDeviceGrabInfo *info;
8671 GdkDevice *other_device;
8674 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8675 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8677 priv = window_group->priv;
8678 list = priv->device_grabs;
8679 other_device = gdk_device_get_associated_device (device);
8686 if (info->device == device ||
8687 info->device == other_device)
8688 return info->widget;
8695 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8699 GtkWindowGroupPrivate *priv;
8700 GtkDeviceGrabInfo *info;
8701 GdkDevice *other_device;
8704 priv = window_group->priv;
8705 other_device = gdk_device_get_associated_device (device);
8706 list = priv->device_grabs;
8713 /* Look for blocking grabs on other device pairs
8714 * that have the passed widget within the GTK+ grab.
8716 if (info->block_others &&
8717 info->device != device &&
8718 info->device != other_device &&
8719 (info->widget == widget ||
8720 gtk_widget_is_ancestor (widget, info->widget)))
8728 Derived from XParseGeometry() in XFree86
8730 Copyright 1985, 1986, 1987,1998 The Open Group
8732 All Rights Reserved.
8734 The above copyright notice and this permission notice shall be included
8735 in all copies or substantial portions of the Software.
8737 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8738 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8739 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8740 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8741 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8742 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8743 OTHER DEALINGS IN THE SOFTWARE.
8745 Except as contained in this notice, the name of The Open Group shall
8746 not be used in advertising or otherwise to promote the sale, use or
8747 other dealings in this Software without prior written authorization
8748 from The Open Group.
8753 * XParseGeometry parses strings of the form
8754 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8755 * width, height, xoffset, and yoffset are unsigned integers.
8756 * Example: "=80x24+300-49"
8757 * The equal sign is optional.
8758 * It returns a bitmask that indicates which of the four values
8759 * were actually found in the string. For each value found,
8760 * the corresponding argument is updated; for each value
8761 * not found, the corresponding argument is left unchanged.
8764 /* The following code is from Xlib, and is minimally modified, so we
8765 * can track any upstream changes if required. Don't change this
8766 * code. Or if you do, put in a huge comment marking which thing
8771 read_int (gchar *string,
8779 else if (*string == '-')
8785 for (; (*string >= '0') && (*string <= '9'); string++)
8787 result = (result * 10) + (*string - '0');
8799 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8800 * value (x, y, width, height) was found in the parsed string.
8802 #define NoValue 0x0000
8803 #define XValue 0x0001
8804 #define YValue 0x0002
8805 #define WidthValue 0x0004
8806 #define HeightValue 0x0008
8807 #define AllValues 0x000F
8808 #define XNegative 0x0010
8809 #define YNegative 0x0020
8811 /* Try not to reformat/modify, so we can compare/sync with X sources */
8813 gtk_XParseGeometry (const char *string,
8816 unsigned int *width,
8817 unsigned int *height)
8821 unsigned int tempWidth, tempHeight;
8823 char *nextCharacter;
8825 /* These initializations are just to silence gcc */
8831 if ( (string == NULL) || (*string == '\0')) return(mask);
8833 string++; /* ignore possible '=' at beg of geometry spec */
8835 strind = (char *)string;
8836 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8837 tempWidth = read_int(strind, &nextCharacter);
8838 if (strind == nextCharacter)
8840 strind = nextCharacter;
8844 if (*strind == 'x' || *strind == 'X') {
8846 tempHeight = read_int(strind, &nextCharacter);
8847 if (strind == nextCharacter)
8849 strind = nextCharacter;
8850 mask |= HeightValue;
8853 if ((*strind == '+') || (*strind == '-')) {
8854 if (*strind == '-') {
8856 tempX = -read_int(strind, &nextCharacter);
8857 if (strind == nextCharacter)
8859 strind = nextCharacter;
8865 tempX = read_int(strind, &nextCharacter);
8866 if (strind == nextCharacter)
8868 strind = nextCharacter;
8871 if ((*strind == '+') || (*strind == '-')) {
8872 if (*strind == '-') {
8874 tempY = -read_int(strind, &nextCharacter);
8875 if (strind == nextCharacter)
8877 strind = nextCharacter;
8884 tempY = read_int(strind, &nextCharacter);
8885 if (strind == nextCharacter)
8887 strind = nextCharacter;
8893 /* If strind isn't at the end of the string the it's an invalid
8894 geometry specification. */
8896 if (*strind != '\0') return (0);
8902 if (mask & WidthValue)
8904 if (mask & HeightValue)
8905 *height = tempHeight;
8910 * gtk_window_parse_geometry:
8911 * @window: a #GtkWindow
8912 * @geometry: geometry string
8914 * Parses a standard X Window System geometry string - see the
8915 * manual page for X (type 'man X') for details on this.
8916 * gtk_window_parse_geometry() does work on all GTK+ ports
8917 * including Win32 but is primarily intended for an X environment.
8919 * If either a size or a position can be extracted from the
8920 * geometry string, gtk_window_parse_geometry() returns %TRUE
8921 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8922 * to resize/move the window.
8924 * If gtk_window_parse_geometry() returns %TRUE, it will also
8925 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8926 * indicating to the window manager that the size/position of
8927 * the window was user-specified. This causes most window
8928 * managers to honor the geometry.
8930 * Note that for gtk_window_parse_geometry() to work as expected, it has
8931 * to be called when the window has its "final" size, i.e. after calling
8932 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8935 * #include <gtk/gtk.h>
8938 * fill_with_content (GtkWidget *vbox)
8940 * /* fill with content... */
8944 * main (int argc, char *argv[])
8946 * GtkWidget *window, *vbox;
8947 * GdkGeometry size_hints = {
8948 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8951 * gtk_init (&argc, &argv);
8953 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8954 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8956 * gtk_container_add (GTK_CONTAINER (window), vbox);
8957 * fill_with_content (vbox);
8958 * gtk_widget_show_all (vbox);
8960 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8963 * GDK_HINT_MIN_SIZE |
8964 * GDK_HINT_BASE_SIZE |
8965 * GDK_HINT_RESIZE_INC);
8969 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8970 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8973 * gtk_widget_show_all (window);
8980 * Return value: %TRUE if string was parsed successfully
8983 gtk_window_parse_geometry (GtkWindow *window,
8984 const gchar *geometry)
8986 gint result, x = 0, y = 0;
8990 gboolean size_set, pos_set;
8993 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8994 g_return_val_if_fail (geometry != NULL, FALSE);
8996 child = gtk_bin_get_child (GTK_BIN (window));
8997 if (!child || !gtk_widget_get_visible (child))
8998 g_warning ("gtk_window_parse_geometry() called on a window with no "
8999 "visible children; the window should be set up before "
9000 "gtk_window_parse_geometry() is called.");
9002 screen = gtk_window_check_screen (window);
9004 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9007 if ((result & WidthValue) || (result & HeightValue))
9009 gtk_window_set_default_size_internal (window,
9010 TRUE, result & WidthValue ? w : -1,
9011 TRUE, result & HeightValue ? h : -1,
9016 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9018 grav = GDK_GRAVITY_NORTH_WEST;
9020 if ((result & XNegative) && (result & YNegative))
9021 grav = GDK_GRAVITY_SOUTH_EAST;
9022 else if (result & XNegative)
9023 grav = GDK_GRAVITY_NORTH_EAST;
9024 else if (result & YNegative)
9025 grav = GDK_GRAVITY_SOUTH_WEST;
9027 if ((result & XValue) == 0)
9030 if ((result & YValue) == 0)
9033 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9034 grav == GDK_GRAVITY_SOUTH_EAST)
9035 y = gdk_screen_get_height (screen) - h + y;
9037 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9038 grav == GDK_GRAVITY_NORTH_EAST)
9039 x = gdk_screen_get_width (screen) - w + x;
9041 /* we don't let you put a window offscreen; maybe some people would
9042 * prefer to be able to, but it's kind of a bogus thing to do.
9051 if ((result & XValue) || (result & YValue))
9053 gtk_window_set_gravity (window, grav);
9054 gtk_window_move (window, x, y);
9058 if (size_set || pos_set)
9060 /* Set USSize, USPosition hints */
9061 GtkWindowGeometryInfo *info;
9063 info = gtk_window_get_geometry_info (window, TRUE);
9066 info->mask |= GDK_HINT_USER_POS;
9068 info->mask |= GDK_HINT_USER_SIZE;
9075 gtk_window_mnemonic_hash_foreach (guint keyval,
9081 GtkWindowKeysForeachFunc func;
9085 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9089 _gtk_window_keys_foreach (GtkWindow *window,
9090 GtkWindowKeysForeachFunc func,
9094 GtkMnemonicHash *mnemonic_hash;
9098 GtkWindowKeysForeachFunc func;
9102 info.window = window;
9104 info.func_data = func_data;
9106 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9108 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9109 gtk_window_mnemonic_hash_foreach, &info);
9111 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9114 GtkAccelGroup *group = groups->data;
9117 for (i = 0; i < group->priv->n_accels; i++)
9119 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9122 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9125 groups = groups->next;
9130 gtk_window_keys_changed (GtkWindow *window)
9132 gtk_window_free_key_hash (window);
9133 gtk_window_get_key_hash (window);
9136 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9138 struct _GtkWindowKeyEntry
9142 guint is_mnemonic : 1;
9146 window_key_entry_destroy (gpointer data)
9148 g_slice_free (GtkWindowKeyEntry, data);
9152 add_to_key_hash (GtkWindow *window,
9154 GdkModifierType modifiers,
9155 gboolean is_mnemonic,
9158 GtkKeyHash *key_hash = data;
9160 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9162 entry->keyval = keyval;
9163 entry->modifiers = modifiers;
9164 entry->is_mnemonic = is_mnemonic;
9166 /* GtkAccelGroup stores lowercased accelerators. To deal
9167 * with this, if <Shift> was specified, uppercase.
9169 if (modifiers & GDK_SHIFT_MASK)
9171 if (keyval == GDK_KEY_Tab)
9172 keyval = GDK_KEY_ISO_Left_Tab;
9174 keyval = gdk_keyval_to_upper (keyval);
9177 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9181 gtk_window_get_key_hash (GtkWindow *window)
9183 GdkScreen *screen = gtk_window_check_screen (window);
9184 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9189 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9190 (GDestroyNotify)window_key_entry_destroy);
9191 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9192 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9198 gtk_window_free_key_hash (GtkWindow *window)
9200 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9203 _gtk_key_hash_free (key_hash);
9204 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9209 * gtk_window_activate_key:
9210 * @window: a #GtkWindow
9211 * @event: a #GdkEventKey
9213 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9214 * called by the default ::key_press_event handler for toplevel windows,
9215 * however in some cases it may be useful to call this directly when
9216 * overriding the standard key handling for a toplevel window.
9218 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9223 gtk_window_activate_key (GtkWindow *window,
9226 GtkKeyHash *key_hash;
9227 GtkWindowKeyEntry *found_entry = NULL;
9228 gboolean enable_mnemonics;
9229 gboolean enable_accels;
9231 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9232 g_return_val_if_fail (event != NULL, FALSE);
9234 key_hash = gtk_window_get_key_hash (window);
9239 GSList *entries = _gtk_key_hash_lookup (key_hash,
9240 event->hardware_keycode,
9242 gtk_accelerator_get_default_mod_mask (),
9245 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9246 "gtk-enable-mnemonics", &enable_mnemonics,
9247 "gtk-enable-accels", &enable_accels,
9250 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9252 GtkWindowKeyEntry *entry = tmp_list->data;
9253 if (entry->is_mnemonic)
9255 if (enable_mnemonics)
9257 found_entry = entry;
9263 if (enable_accels && !found_entry)
9265 found_entry = entry;
9270 g_slist_free (entries);
9275 if (found_entry->is_mnemonic)
9277 if (enable_mnemonics)
9278 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9279 found_entry->modifiers);
9284 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9285 found_entry->modifiers);
9293 window_update_has_focus (GtkWindow *window)
9295 GtkWindowPrivate *priv = window->priv;
9296 GtkWidget *widget = GTK_WIDGET (window);
9297 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9299 if (has_focus != priv->has_focus)
9301 priv->has_focus = has_focus;
9305 if (priv->focus_widget &&
9306 priv->focus_widget != widget &&
9307 !gtk_widget_has_focus (priv->focus_widget))
9308 do_focus_change (priv->focus_widget, TRUE);
9312 if (priv->focus_widget &&
9313 priv->focus_widget != widget &&
9314 gtk_widget_has_focus (priv->focus_widget))
9315 do_focus_change (priv->focus_widget, FALSE);
9321 * _gtk_window_set_is_active:
9322 * @window: a #GtkWindow
9323 * @is_active: %TRUE if the window is in the currently active toplevel
9325 * Internal function that sets whether the #GtkWindow is part
9326 * of the currently active toplevel window (taking into account inter-process
9330 _gtk_window_set_is_active (GtkWindow *window,
9333 GtkWindowPrivate *priv;
9335 g_return_if_fail (GTK_IS_WINDOW (window));
9337 priv = window->priv;
9339 is_active = is_active != FALSE;
9341 if (is_active != priv->is_active)
9343 priv->is_active = is_active;
9344 window_update_has_focus (window);
9346 g_object_notify (G_OBJECT (window), "is-active");
9351 * _gtk_window_set_is_toplevel:
9352 * @window: a #GtkWindow
9353 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9354 * child of the root window); %FALSE if it is not (for example, for an
9355 * in-process, parented GtkPlug)
9357 * Internal function used by #GtkPlug when it gets parented/unparented by a
9358 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9359 * global list of toplevel windows.
9362 _gtk_window_set_is_toplevel (GtkWindow *window,
9363 gboolean is_toplevel)
9366 GtkWidget *toplevel;
9368 widget = GTK_WIDGET (window);
9370 if (gtk_widget_is_toplevel (widget))
9371 g_assert (g_slist_find (toplevel_list, window) != NULL);
9373 g_assert (g_slist_find (toplevel_list, window) == NULL);
9375 if (is_toplevel == gtk_widget_is_toplevel (widget))
9380 /* Pass through regular pathways of an embedded toplevel
9381 * to go through unmapping and hiding the widget before
9382 * becomming a toplevel again.
9384 * We remain hidden after becomming toplevel in order to
9385 * avoid problems during an embedded toplevel's dispose cycle
9386 * (When a toplevel window is shown it tries to grab focus again,
9387 * this causes problems while disposing).
9389 gtk_widget_hide (widget);
9391 /* Save the toplevel this widget was previously anchored into before
9392 * propagating a hierarchy-changed.
9394 * Usually this happens by way of gtk_widget_unparent() and we are
9395 * already unanchored at this point, just adding this clause incase
9396 * things happen differently.
9398 toplevel = gtk_widget_get_toplevel (widget);
9399 if (!gtk_widget_is_toplevel (toplevel))
9402 _gtk_widget_set_is_toplevel (widget, TRUE);
9404 /* When a window becomes toplevel after being embedded and anchored
9405 * into another window we need to unset its anchored flag so that
9406 * the hierarchy changed signal kicks in properly.
9408 _gtk_widget_set_anchored (widget, FALSE);
9409 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9411 toplevel_list = g_slist_prepend (toplevel_list, window);
9415 _gtk_widget_set_is_toplevel (widget, FALSE);
9416 toplevel_list = g_slist_remove (toplevel_list, window);
9418 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9423 * _gtk_window_set_has_toplevel_focus:
9424 * @window: a #GtkWindow
9425 * @has_toplevel_focus: %TRUE if the in
9427 * Internal function that sets whether the keyboard focus for the
9428 * toplevel window (taking into account inter-process embedding.)
9431 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9432 gboolean has_toplevel_focus)
9434 GtkWindowPrivate *priv;
9436 g_return_if_fail (GTK_IS_WINDOW (window));
9438 priv = window->priv;
9440 has_toplevel_focus = has_toplevel_focus != FALSE;
9442 if (has_toplevel_focus != priv->has_toplevel_focus)
9444 priv->has_toplevel_focus = has_toplevel_focus;
9445 window_update_has_focus (window);
9447 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9452 * gtk_window_set_auto_startup_notification:
9453 * @setting: %TRUE to automatically do startup notification
9455 * By default, after showing the first #GtkWindow, GTK+ calls
9456 * gdk_notify_startup_complete(). Call this function to disable
9457 * the automatic startup notification. You might do this if your
9458 * first window is a splash screen, and you want to delay notification
9459 * until after your real main window has been shown, for example.
9461 * In that example, you would disable startup notification
9462 * temporarily, show your splash screen, then re-enable it so that
9463 * showing the main window would automatically result in notification.
9468 gtk_window_set_auto_startup_notification (gboolean setting)
9470 disable_startup_notification = !setting;
9474 * gtk_window_get_window_type:
9475 * @window: a #GtkWindow
9477 * Gets the type of the window. See #GtkWindowType.
9479 * Return value: the type of the window
9484 gtk_window_get_window_type (GtkWindow *window)
9486 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9488 return window->priv->type;
9492 * gtk_window_get_mnemonics_visible:
9493 * @window: a #GtkWindow
9495 * Gets the value of the #GtkWindow:mnemonics-visible property.
9497 * Returns: %TRUE if mnemonics are supposed to be visible
9503 gtk_window_get_mnemonics_visible (GtkWindow *window)
9505 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9507 return window->priv->mnemonics_visible;
9511 * gtk_window_set_mnemonics_visible:
9512 * @window: a #GtkWindow
9513 * @setting: the new value
9515 * Sets the #GtkWindow:mnemonics-visible property.
9520 gtk_window_set_mnemonics_visible (GtkWindow *window,
9523 GtkWindowPrivate *priv;
9525 g_return_if_fail (GTK_IS_WINDOW (window));
9527 priv = window->priv;
9529 setting = setting != FALSE;
9531 if (priv->mnemonics_visible != setting)
9533 priv->mnemonics_visible = setting;
9534 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9537 priv->mnemonics_visible_set = TRUE;
9541 * gtk_window_get_focus_visible:
9542 * @window: a #GtkWindow
9544 * Gets the value of the #GtkWindow:focus-visible property.
9546 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9552 gtk_window_get_focus_visible (GtkWindow *window)
9554 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9556 return window->priv->focus_visible;
9560 * gtk_window_set_focus_visible:
9561 * @window: a #GtkWindow
9562 * @setting: the new value
9564 * Sets the #GtkWindow:focus-visible property.
9569 gtk_window_set_focus_visible (GtkWindow *window,
9572 GtkWindowPrivate *priv;
9574 g_return_if_fail (GTK_IS_WINDOW (window));
9576 priv = window->priv;
9578 setting = setting != FALSE;
9580 if (priv->focus_visible != setting)
9582 priv->focus_visible = setting;
9583 g_object_notify (G_OBJECT (window), "focus-visible");
9588 _gtk_window_get_wmclass (GtkWindow *window,
9589 gchar **wmclass_name,
9590 gchar **wmclass_class)
9592 GtkWindowPrivate *priv = window->priv;
9594 *wmclass_name = priv->wmclass_name;
9595 *wmclass_class = priv->wmclass_class;
9599 * gtk_window_set_has_user_ref_count:
9600 * @window: a #GtkWindow
9601 * @setting: the new value
9603 * Tells GTK+ whether to drop its extra reference to the window
9604 * when gtk_window_destroy() is called.
9606 * This function is only exported for the benefit of language
9607 * bindings which may need to keep the window alive until their
9608 * wrapper object is garbage collected. There is no justification
9609 * for ever calling this function in an application.
9614 gtk_window_set_has_user_ref_count (GtkWindow *window,
9617 g_return_if_fail (GTK_IS_WINDOW (window));
9619 window->priv->has_user_ref_count = setting;