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 #include "deprecated/gtkstyle.h"
57 #ifdef GDK_WINDOWING_X11
64 * @short_description: Toplevel which can contain other widgets
66 * A GtkWindow is a toplevel window which can contain other widgets.
67 * Windows normally have decorations that are under the control
68 * of the windowing system and allow the user to manipulate the window
69 * (resize it, move it, close it,...).
71 * GTK+ also allows windows to have a resize grip (a small area in the lower
72 * right or left corner) which can be clicked to reszie the window. To
73 * control whether a window has a resize grip, use
74 * gtk_window_set_has_resize_grip().
76 * <refsect2 id="GtkWindow-BUILDER-UI">
77 * <title>GtkWindow as GtkBuildable</title>
79 * The GtkWindow implementation of the GtkBuildable interface supports a
80 * custom <tag class="starttag">accel-groups</tag> element, which supports
81 * any number of <tag class="starttag">group</tag> elements representing the
82 * #GtkAccelGroup objects you want to add to your window (synonymous with
83 * gtk_window_add_accel_group().
86 * <title>A UI definition fragment with accel groups</title>
87 * <programlisting><![CDATA[
88 * <object class="GtkWindow">
90 * <group name="accelgroup1"/>
96 * <object class="GtkAccelGroup" id="accelgroup1"/>
97 * ]]></programlisting>
102 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
104 struct _GtkWindowPrivate
106 GtkMnemonicHash *mnemonic_hash;
108 GtkWidget *default_widget;
109 GtkWidget *focus_widget;
110 GtkWindow *transient_parent;
111 GtkWindowGeometryInfo *geometry_info;
112 GtkWindowGroup *group;
114 GtkApplication *application;
116 GdkModifierType mnemonic_modifier;
117 GdkWindowTypeHint gdk_type_hint;
121 GdkWindow *grip_window;
125 gchar *wmclass_class;
129 guint keys_changed_handler;
131 guint32 initial_timestamp;
133 guint16 configure_request_count;
135 /* The following flags are initially TRUE (before a window is mapped).
136 * They cause us to compute a configure request that involves
137 * default-only parameters. Once mapped, we set them to FALSE.
138 * Then we set them to TRUE again on unmap (for position)
139 * and on unrealize (for size).
141 guint need_default_position : 1;
142 guint need_default_size : 1;
144 guint above_initially : 1;
145 guint accept_focus : 1;
146 guint below_initially : 1;
147 guint builder_visible : 1;
148 guint configure_notify_received : 1;
151 guint destroy_with_parent : 1;
152 guint focus_on_map : 1;
153 guint fullscreen_initially : 1;
155 guint has_user_ref_count : 1;
156 guint has_toplevel_focus : 1;
157 guint hide_titlebar_when_maximized : 1;
158 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
160 guint maximize_initially : 1;
161 guint mnemonics_visible : 1;
162 guint mnemonics_visible_set : 1;
163 guint focus_visible : 1;
165 guint opacity_set : 1;
167 guint reset_type_hint : 1;
169 guint skips_pager : 1;
170 guint skips_taskbar : 1;
171 guint stick_initially : 1;
172 guint transient_parent_group : 1;
173 guint type : 4; /* GtkWindowType */
174 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
175 * one of the original eight. If not,
177 * GDK_WINDOW_TYPE_HINT_NORMAL
180 guint has_resize_grip : 1;
181 guint resize_grip_visible : 1; /* don't use, just for "resize-
182 * grip-visible" notification
184 guint gravity : 5; /* GdkGravity */
211 PROP_DESTROY_WITH_PARENT,
212 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
217 PROP_SKIP_TASKBAR_HINT,
218 PROP_SKIP_PAGER_HINT,
227 PROP_HAS_RESIZE_GRIP,
228 PROP_RESIZE_GRIP_VISIBLE,
230 /* Readonly properties */
232 PROP_HAS_TOPLEVEL_FOCUS,
234 /* Writeonly properties */
237 PROP_MNEMONICS_VISIBLE,
248 guint using_default_icon : 1;
249 guint using_parent_icon : 1;
250 guint using_themed_icon : 1;
254 GdkGeometry geometry; /* Last set of geometry hints we set */
255 GdkWindowHints flags;
256 GdkRectangle configure_request;
257 } GtkWindowLastGeometryInfo;
259 struct _GtkWindowGeometryInfo
261 /* Properties that the app has set on the window
263 GdkGeometry geometry; /* Geometry hints */
265 GtkWidget *widget; /* subwidget to which hints apply */
266 /* from last gtk_window_resize () - if > 0, indicates that
267 * we should resize to this size.
272 /* From last gtk_window_move () prior to mapping -
273 * only used if initial_pos_set
278 /* Default size - used only the FIRST time we map a window,
283 /* whether to use initial_x, initial_y */
284 guint initial_pos_set : 1;
285 /* CENTER_ALWAYS or other position constraint changed since
286 * we sent the last configure request.
288 guint position_constraints_changed : 1;
290 /* if true, default_width, height should be multiplied by the
291 * increments and affect the geometry widget only
293 guint default_is_geometry : 1;
295 /* if true, resize_width, height should be multiplied by the
296 * increments and affect the geometry widget only
298 guint resize_is_geometry : 1;
300 GtkWindowLastGeometryInfo last;
304 struct _GtkDeviceGrabInfo
308 guint block_others : 1;
311 struct _GtkWindowGroupPrivate
314 GSList *device_grabs;
317 static void gtk_window_dispose (GObject *object);
318 static void gtk_window_finalize (GObject *object);
319 static void gtk_window_destroy (GtkWidget *widget);
320 static void gtk_window_show (GtkWidget *widget);
321 static void gtk_window_hide (GtkWidget *widget);
322 static void gtk_window_map (GtkWidget *widget);
323 static void gtk_window_unmap (GtkWidget *widget);
324 static void gtk_window_realize (GtkWidget *widget);
325 static void gtk_window_unrealize (GtkWidget *widget);
326 static void gtk_window_size_allocate (GtkWidget *widget,
327 GtkAllocation *allocation);
328 static gboolean gtk_window_map_event (GtkWidget *widget,
330 static gint gtk_window_configure_event (GtkWidget *widget,
331 GdkEventConfigure *event);
332 static gint gtk_window_key_press_event (GtkWidget *widget,
334 static gint gtk_window_key_release_event (GtkWidget *widget,
336 static gint gtk_window_button_press_event (GtkWidget *widget,
337 GdkEventButton *event);
338 static gint gtk_window_enter_notify_event (GtkWidget *widget,
339 GdkEventCrossing *event);
340 static gint gtk_window_leave_notify_event (GtkWidget *widget,
341 GdkEventCrossing *event);
342 static gint gtk_window_focus_in_event (GtkWidget *widget,
343 GdkEventFocus *event);
344 static gint gtk_window_focus_out_event (GtkWidget *widget,
345 GdkEventFocus *event);
346 static void gtk_window_style_updated (GtkWidget *widget);
347 static gboolean gtk_window_state_event (GtkWidget *widget,
348 GdkEventWindowState *event);
349 static void gtk_window_check_resize (GtkContainer *container);
350 static gint gtk_window_focus (GtkWidget *widget,
351 GtkDirectionType direction);
352 static void gtk_window_move_focus (GtkWidget *widget,
353 GtkDirectionType dir);
354 static void gtk_window_real_set_focus (GtkWindow *window,
356 static void gtk_window_direction_changed (GtkWidget *widget,
357 GtkTextDirection prev_dir);
358 static void gtk_window_state_changed (GtkWidget *widget,
359 GtkStateType previous_state);
361 static void gtk_window_real_activate_default (GtkWindow *window);
362 static void gtk_window_real_activate_focus (GtkWindow *window);
363 static void gtk_window_keys_changed (GtkWindow *window);
364 static gint gtk_window_draw (GtkWidget *widget,
366 static void gtk_window_unset_transient_for (GtkWindow *window);
367 static void gtk_window_transient_parent_realized (GtkWidget *parent,
369 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
372 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
374 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
377 static void gtk_window_move_resize (GtkWindow *window);
378 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
380 GdkGeometry *geometry_b,
382 static void gtk_window_constrain_size (GtkWindow *window,
383 GdkGeometry *geometry,
389 static void gtk_window_constrain_position (GtkWindow *window,
394 static void gtk_window_compute_hints (GtkWindow *window,
395 GdkGeometry *new_geometry,
397 static void gtk_window_compute_configure_request (GtkWindow *window,
398 GdkRectangle *request,
399 GdkGeometry *geometry,
402 static void gtk_window_set_default_size_internal (GtkWindow *window,
403 gboolean change_width,
405 gboolean change_height,
407 gboolean is_geometry);
409 static void update_themed_icon (GtkIconTheme *theme,
411 static GList *icon_list_from_theme (GtkWidget *widget,
413 static void gtk_window_realize_icon (GtkWindow *window);
414 static void gtk_window_unrealize_icon (GtkWindow *window);
415 static void resize_grip_create_window (GtkWindow *window);
416 static void resize_grip_destroy_window (GtkWindow *window);
417 static void update_grip_visibility (GtkWindow *window);
419 static void gtk_window_notify_keys_changed (GtkWindow *window);
420 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
421 static void gtk_window_free_key_hash (GtkWindow *window);
422 static void gtk_window_on_composited_changed (GdkScreen *screen,
424 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
427 static void gtk_window_set_theme_variant (GtkWindow *window);
429 static GSList *toplevel_list = NULL;
430 static guint window_signals[LAST_SIGNAL] = { 0 };
431 static GList *default_icon_list = NULL;
432 static gchar *default_icon_name = NULL;
433 static guint default_icon_serial = 0;
434 static gboolean disable_startup_notification = FALSE;
435 static gboolean sent_startup_notification = FALSE;
437 static GQuark quark_gtk_embedded = 0;
438 static GQuark quark_gtk_window_key_hash = 0;
439 static GQuark quark_gtk_window_icon_info = 0;
440 static GQuark quark_gtk_buildable_accels = 0;
442 static GtkBuildableIface *parent_buildable_iface;
444 static void gtk_window_set_property (GObject *object,
448 static void gtk_window_get_property (GObject *object,
454 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
455 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
458 const GValue *value);
459 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
460 GtkBuilder *builder);
461 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
464 const gchar *tagname,
465 GMarkupParser *parser,
467 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
470 const gchar *tagname,
474 static void gtk_window_get_preferred_width (GtkWidget *widget,
477 static void gtk_window_get_preferred_height (GtkWidget *widget,
481 static void ensure_state_flag_window_unfocused (GtkWidget *widget);
483 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
484 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
485 gtk_window_buildable_interface_init))
488 add_tab_bindings (GtkBindingSet *binding_set,
489 GdkModifierType modifiers,
490 GtkDirectionType direction)
492 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
494 GTK_TYPE_DIRECTION_TYPE, direction);
495 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
497 GTK_TYPE_DIRECTION_TYPE, direction);
501 add_arrow_bindings (GtkBindingSet *binding_set,
503 GtkDirectionType direction)
505 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
507 gtk_binding_entry_add_signal (binding_set, keysym, 0,
509 GTK_TYPE_DIRECTION_TYPE, direction);
510 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
512 GTK_TYPE_DIRECTION_TYPE, direction);
513 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
515 GTK_TYPE_DIRECTION_TYPE, direction);
516 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
518 GTK_TYPE_DIRECTION_TYPE, direction);
522 extract_time_from_startup_id (const gchar* startup_id)
524 gchar *timestr = g_strrstr (startup_id, "_TIME");
525 guint32 retval = GDK_CURRENT_TIME;
532 /* Skip past the "_TIME" part */
537 timestamp = g_ascii_strtoull (timestr, &end, 0);
538 if (errno == 0 && end != timestr)
546 startup_id_is_fake (const gchar* startup_id)
548 return strncmp (startup_id, "_TIME", 5) == 0;
552 gtk_window_class_init (GtkWindowClass *klass)
554 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
555 GtkWidgetClass *widget_class;
556 GtkContainerClass *container_class;
557 GtkBindingSet *binding_set;
559 widget_class = (GtkWidgetClass*) klass;
560 container_class = (GtkContainerClass*) klass;
562 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
563 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
564 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
565 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
567 gobject_class->dispose = gtk_window_dispose;
568 gobject_class->finalize = gtk_window_finalize;
570 gobject_class->set_property = gtk_window_set_property;
571 gobject_class->get_property = gtk_window_get_property;
573 widget_class->destroy = gtk_window_destroy;
574 widget_class->show = gtk_window_show;
575 widget_class->hide = gtk_window_hide;
576 widget_class->map = gtk_window_map;
577 widget_class->map_event = gtk_window_map_event;
578 widget_class->unmap = gtk_window_unmap;
579 widget_class->realize = gtk_window_realize;
580 widget_class->unrealize = gtk_window_unrealize;
581 widget_class->size_allocate = gtk_window_size_allocate;
582 widget_class->configure_event = gtk_window_configure_event;
583 widget_class->key_press_event = gtk_window_key_press_event;
584 widget_class->key_release_event = gtk_window_key_release_event;
585 widget_class->enter_notify_event = gtk_window_enter_notify_event;
586 widget_class->leave_notify_event = gtk_window_leave_notify_event;
587 widget_class->focus_in_event = gtk_window_focus_in_event;
588 widget_class->button_press_event = gtk_window_button_press_event;
589 widget_class->focus_out_event = gtk_window_focus_out_event;
590 widget_class->focus = gtk_window_focus;
591 widget_class->move_focus = gtk_window_move_focus;
592 widget_class->draw = gtk_window_draw;
593 widget_class->get_preferred_width = gtk_window_get_preferred_width;
594 widget_class->get_preferred_height = gtk_window_get_preferred_height;
595 widget_class->window_state_event = gtk_window_state_event;
596 widget_class->direction_changed = gtk_window_direction_changed;
597 widget_class->state_changed = gtk_window_state_changed;
598 widget_class->style_updated = gtk_window_style_updated;
600 container_class->check_resize = gtk_window_check_resize;
602 klass->set_focus = gtk_window_real_set_focus;
604 klass->activate_default = gtk_window_real_activate_default;
605 klass->activate_focus = gtk_window_real_activate_focus;
606 klass->keys_changed = gtk_window_keys_changed;
608 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
611 g_object_class_install_property (gobject_class,
613 g_param_spec_enum ("type",
615 P_("The type of the window"),
616 GTK_TYPE_WINDOW_TYPE,
618 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
620 g_object_class_install_property (gobject_class,
622 g_param_spec_string ("title",
624 P_("The title of the window"),
626 GTK_PARAM_READWRITE));
628 g_object_class_install_property (gobject_class,
630 g_param_spec_string ("role",
632 P_("Unique identifier for the window to be used when restoring a session"),
634 GTK_PARAM_READWRITE));
637 * GtkWindow:startup-id:
639 * The :startup-id is a write-only property for setting window's
640 * startup notification identifier. See gtk_window_set_startup_id()
645 g_object_class_install_property (gobject_class,
647 g_param_spec_string ("startup-id",
649 P_("Unique startup identifier for the window used by startup-notification"),
651 GTK_PARAM_WRITABLE));
653 g_object_class_install_property (gobject_class,
655 g_param_spec_boolean ("resizable",
657 P_("If TRUE, users can resize the window"),
659 GTK_PARAM_READWRITE));
661 g_object_class_install_property (gobject_class,
663 g_param_spec_boolean ("modal",
665 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
667 GTK_PARAM_READWRITE));
669 g_object_class_install_property (gobject_class,
671 g_param_spec_enum ("window-position",
672 P_("Window Position"),
673 P_("The initial position of the window"),
674 GTK_TYPE_WINDOW_POSITION,
676 GTK_PARAM_READWRITE));
678 g_object_class_install_property (gobject_class,
680 g_param_spec_int ("default-width",
682 P_("The default width of the window, used when initially showing the window"),
686 GTK_PARAM_READWRITE));
688 g_object_class_install_property (gobject_class,
690 g_param_spec_int ("default-height",
691 P_("Default Height"),
692 P_("The default height of the window, used when initially showing the window"),
696 GTK_PARAM_READWRITE));
698 g_object_class_install_property (gobject_class,
699 PROP_DESTROY_WITH_PARENT,
700 g_param_spec_boolean ("destroy-with-parent",
701 P_("Destroy with Parent"),
702 P_("If this window should be destroyed when the parent is destroyed"),
704 GTK_PARAM_READWRITE));
707 * GtkWindow:hide-titlebar-when-maximized:
709 * Whether the titlebar should be hidden during maximization.
713 g_object_class_install_property (gobject_class,
714 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
715 g_param_spec_boolean ("hide-titlebar-when-maximized",
716 P_("Hide the titlebar during maximization"),
717 P_("If this window's titlebar should be hidden when the window is maximized"),
719 GTK_PARAM_READWRITE));
721 g_object_class_install_property (gobject_class,
723 g_param_spec_object ("icon",
725 P_("Icon for this window"),
727 GTK_PARAM_READWRITE));
730 * GtkWindow:mnemonics-visible:
732 * Whether mnemonics are currently visible in this window.
734 * This property is maintained by GTK+ based on the
735 * #GtkSettings:gtk-auto-mnemonics setting and user input,
736 * and should not be set by applications.
740 g_object_class_install_property (gobject_class,
741 PROP_MNEMONICS_VISIBLE,
742 g_param_spec_boolean ("mnemonics-visible",
743 P_("Mnemonics Visible"),
744 P_("Whether mnemonics are currently visible in this window"),
746 GTK_PARAM_READWRITE));
749 * GtkWindow:focus-visible:
751 * Whether 'focus rectangles' are currently visible in this window.
753 * This property is maintained by GTK+ based on the
754 * #GtkSettings:gtk-visible-focus setting and user input
755 * and should not be set by applications.
759 g_object_class_install_property (gobject_class,
761 g_param_spec_boolean ("focus-visible",
763 P_("Whether focus rectangles are currently visible in this window"),
765 GTK_PARAM_READWRITE));
768 * GtkWindow:icon-name:
770 * The :icon-name property specifies the name of the themed icon to
771 * use as the window icon. See #GtkIconTheme for more details.
775 g_object_class_install_property (gobject_class,
777 g_param_spec_string ("icon-name",
779 P_("Name of the themed icon for this window"),
781 GTK_PARAM_READWRITE));
783 g_object_class_install_property (gobject_class,
785 g_param_spec_object ("screen",
787 P_("The screen where this window will be displayed"),
789 GTK_PARAM_READWRITE));
791 g_object_class_install_property (gobject_class,
793 g_param_spec_boolean ("is-active",
795 P_("Whether the toplevel is the current active window"),
797 GTK_PARAM_READABLE));
799 g_object_class_install_property (gobject_class,
800 PROP_HAS_TOPLEVEL_FOCUS,
801 g_param_spec_boolean ("has-toplevel-focus",
802 P_("Focus in Toplevel"),
803 P_("Whether the input focus is within this GtkWindow"),
805 GTK_PARAM_READABLE));
807 g_object_class_install_property (gobject_class,
809 g_param_spec_enum ("type-hint",
811 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
812 GDK_TYPE_WINDOW_TYPE_HINT,
813 GDK_WINDOW_TYPE_HINT_NORMAL,
814 GTK_PARAM_READWRITE));
816 g_object_class_install_property (gobject_class,
817 PROP_SKIP_TASKBAR_HINT,
818 g_param_spec_boolean ("skip-taskbar-hint",
820 P_("TRUE if the window should not be in the task bar."),
822 GTK_PARAM_READWRITE));
824 g_object_class_install_property (gobject_class,
825 PROP_SKIP_PAGER_HINT,
826 g_param_spec_boolean ("skip-pager-hint",
828 P_("TRUE if the window should not be in the pager."),
830 GTK_PARAM_READWRITE));
832 g_object_class_install_property (gobject_class,
834 g_param_spec_boolean ("urgency-hint",
836 P_("TRUE if the window should be brought to the user's attention."),
838 GTK_PARAM_READWRITE));
841 * GtkWindow:accept-focus:
843 * Whether the window should receive the input focus.
847 g_object_class_install_property (gobject_class,
849 g_param_spec_boolean ("accept-focus",
851 P_("TRUE if the window should receive the input focus."),
853 GTK_PARAM_READWRITE));
856 * GtkWindow:focus-on-map:
858 * Whether the window should receive the input focus when mapped.
862 g_object_class_install_property (gobject_class,
864 g_param_spec_boolean ("focus-on-map",
866 P_("TRUE if the window should receive the input focus when mapped."),
868 GTK_PARAM_READWRITE));
871 * GtkWindow:decorated:
873 * Whether the window should be decorated by the window manager.
877 g_object_class_install_property (gobject_class,
879 g_param_spec_boolean ("decorated",
881 P_("Whether the window should be decorated by the window manager"),
883 GTK_PARAM_READWRITE));
886 * GtkWindow:deletable:
888 * Whether the window frame should have a close button.
892 g_object_class_install_property (gobject_class,
894 g_param_spec_boolean ("deletable",
896 P_("Whether the window frame should have a close button"),
898 GTK_PARAM_READWRITE));
901 * GtkWindow:has-resize-grip
903 * Whether the window has a corner resize grip.
905 * Note that the resize grip is only shown if the window is
906 * actually resizable and not maximized. Use
907 * #GtkWindow:resize-grip-visible to find out if the resize
908 * grip is currently shown.
912 g_object_class_install_property (gobject_class,
913 PROP_HAS_RESIZE_GRIP,
914 g_param_spec_boolean ("has-resize-grip",
916 P_("Specifies whether the window should have a resize grip"),
918 GTK_PARAM_READWRITE));
921 * GtkWindow:resize-grip-visible:
923 * Whether a corner resize grip is currently shown.
927 g_object_class_install_property (gobject_class,
928 PROP_RESIZE_GRIP_VISIBLE,
929 g_param_spec_boolean ("resize-grip-visible",
930 P_("Resize grip is visible"),
931 P_("Specifies whether the window's resize grip is visible."),
933 GTK_PARAM_READABLE));
939 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
940 * more details about window gravity.
944 g_object_class_install_property (gobject_class,
946 g_param_spec_enum ("gravity",
948 P_("The window gravity of the window"),
950 GDK_GRAVITY_NORTH_WEST,
951 GTK_PARAM_READWRITE));
955 * GtkWindow:transient-for:
957 * The transient parent of the window. See gtk_window_set_transient_for() for
958 * more details about transient windows.
962 g_object_class_install_property (gobject_class,
964 g_param_spec_object ("transient-for",
965 P_("Transient for Window"),
966 P_("The transient parent of the dialog"),
968 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
973 * The requested opacity of the window. See gtk_window_set_opacity() for
974 * more details about window opacity.
978 g_object_class_install_property (gobject_class,
980 g_param_spec_double ("opacity",
981 P_("Opacity for Window"),
982 P_("The opacity of the window, from 0 to 1"),
986 GTK_PARAM_READWRITE));
990 gtk_widget_class_install_style_property (widget_class,
991 g_param_spec_int ("resize-grip-width",
992 P_("Width of resize grip"),
993 P_("Width of resize grip"),
994 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
996 gtk_widget_class_install_style_property (widget_class,
997 g_param_spec_int ("resize-grip-height",
998 P_("Height of resize grip"),
999 P_("Height of resize grip"),
1000 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1004 * GtkWindow:application:
1006 * The #GtkApplication associated with the window.
1008 * The application will be kept alive for at least as long as it
1009 * has any windows associated with it (see g_application_hold()
1010 * for a way to keep it alive without windows).
1012 * Normally, the connection between the application and the window
1013 * will remain until the window is destroyed, but you can explicitly
1014 * remove it by setting the ::application property to %NULL.
1018 g_object_class_install_property (gobject_class,
1020 g_param_spec_object ("application",
1021 P_("GtkApplication"),
1022 P_("The GtkApplication for the window"),
1023 GTK_TYPE_APPLICATION,
1024 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1026 window_signals[SET_FOCUS] =
1027 g_signal_new (I_("set-focus"),
1028 G_TYPE_FROM_CLASS (gobject_class),
1030 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1032 _gtk_marshal_VOID__OBJECT,
1037 * GtkWindow::activate-focus:
1038 * @window: the window which received the signal
1040 * The ::activate-focus signal is a
1041 * <link linkend="keybinding-signals">keybinding signal</link>
1042 * which gets emitted when the user activates the currently
1043 * focused widget of @window.
1045 window_signals[ACTIVATE_FOCUS] =
1046 g_signal_new (I_("activate-focus"),
1047 G_TYPE_FROM_CLASS (gobject_class),
1048 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1049 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1051 _gtk_marshal_VOID__VOID,
1056 * GtkWindow::activate-default:
1057 * @window: the window which received the signal
1059 * The ::activate-default signal is a
1060 * <link linkend="keybinding-signals">keybinding signal</link>
1061 * which gets emitted when the user activates the default widget
1064 window_signals[ACTIVATE_DEFAULT] =
1065 g_signal_new (I_("activate-default"),
1066 G_TYPE_FROM_CLASS (gobject_class),
1067 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1068 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1070 _gtk_marshal_VOID__VOID,
1075 * GtkWindow::keys-changed:
1076 * @window: the window which received the signal
1078 * The ::keys-changed signal gets emitted when the set of accelerators
1079 * or mnemonics that are associated with @window changes.
1081 window_signals[KEYS_CHANGED] =
1082 g_signal_new (I_("keys-changed"),
1083 G_TYPE_FROM_CLASS (gobject_class),
1085 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1087 _gtk_marshal_VOID__VOID,
1095 binding_set = gtk_binding_set_by_class (klass);
1097 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1098 "activate-focus", 0);
1099 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1100 "activate-focus", 0);
1102 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1103 "activate-default", 0);
1104 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1105 "activate-default", 0);
1106 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1107 "activate-default", 0);
1109 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1110 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1111 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1112 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1114 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1115 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1116 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1117 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1119 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1123 gtk_window_init (GtkWindow *window)
1125 GtkWindowPrivate *priv;
1127 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1130 priv = window->priv;
1132 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1133 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1135 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1137 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1140 priv->wmclass_name = g_strdup (g_get_prgname ());
1141 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1142 priv->wm_role = NULL;
1143 priv->geometry_info = NULL;
1144 priv->type = GTK_WINDOW_TOPLEVEL;
1145 priv->focus_widget = NULL;
1146 priv->default_widget = NULL;
1147 priv->configure_request_count = 0;
1148 priv->resizable = TRUE;
1149 priv->configure_notify_received = FALSE;
1150 priv->position = GTK_WIN_POS_NONE;
1151 priv->need_default_size = TRUE;
1152 priv->need_default_position = TRUE;
1153 priv->modal = FALSE;
1154 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1155 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1156 priv->decorated = TRUE;
1157 priv->mnemonic_modifier = GDK_MOD1_MASK;
1158 priv->screen = gdk_screen_get_default ();
1160 priv->accept_focus = TRUE;
1161 priv->focus_on_map = TRUE;
1162 priv->deletable = TRUE;
1163 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1164 priv->opacity = 1.0;
1165 priv->startup_id = NULL;
1166 priv->initial_timestamp = GDK_CURRENT_TIME;
1167 priv->has_resize_grip = TRUE;
1168 priv->mnemonics_visible = TRUE;
1169 priv->focus_visible = TRUE;
1171 g_object_ref_sink (window);
1172 priv->has_user_ref_count = TRUE;
1173 toplevel_list = g_slist_prepend (toplevel_list, window);
1176 g_signal_connect (priv->screen, "composited-changed",
1177 G_CALLBACK (gtk_window_on_composited_changed), window);
1179 #ifdef GDK_WINDOWING_X11
1180 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1181 "notify::gtk-application-prefer-dark-theme",
1182 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1187 gtk_window_set_property (GObject *object,
1189 const GValue *value,
1192 GtkWindow *window = GTK_WINDOW (object);
1193 GtkWindowPrivate *priv = window->priv;
1198 priv->type = g_value_get_enum (value);
1201 gtk_window_set_title (window, g_value_get_string (value));
1204 gtk_window_set_role (window, g_value_get_string (value));
1206 case PROP_STARTUP_ID:
1207 gtk_window_set_startup_id (window, g_value_get_string (value));
1209 case PROP_RESIZABLE:
1210 gtk_window_set_resizable (window, g_value_get_boolean (value));
1213 gtk_window_set_modal (window, g_value_get_boolean (value));
1216 gtk_window_set_position (window, g_value_get_enum (value));
1218 case PROP_DEFAULT_WIDTH:
1219 gtk_window_set_default_size_internal (window,
1220 TRUE, g_value_get_int (value),
1223 case PROP_DEFAULT_HEIGHT:
1224 gtk_window_set_default_size_internal (window,
1226 TRUE, g_value_get_int (value), FALSE);
1228 case PROP_DESTROY_WITH_PARENT:
1229 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1231 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1232 gtk_window_set_hide_titlebar_when_maximized (window, g_value_get_boolean (value));
1235 gtk_window_set_icon (window,
1236 g_value_get_object (value));
1238 case PROP_ICON_NAME:
1239 gtk_window_set_icon_name (window, g_value_get_string (value));
1242 gtk_window_set_screen (window, g_value_get_object (value));
1244 case PROP_TYPE_HINT:
1245 gtk_window_set_type_hint (window,
1246 g_value_get_enum (value));
1248 case PROP_SKIP_TASKBAR_HINT:
1249 gtk_window_set_skip_taskbar_hint (window,
1250 g_value_get_boolean (value));
1252 case PROP_SKIP_PAGER_HINT:
1253 gtk_window_set_skip_pager_hint (window,
1254 g_value_get_boolean (value));
1256 case PROP_URGENCY_HINT:
1257 gtk_window_set_urgency_hint (window,
1258 g_value_get_boolean (value));
1260 case PROP_ACCEPT_FOCUS:
1261 gtk_window_set_accept_focus (window,
1262 g_value_get_boolean (value));
1264 case PROP_FOCUS_ON_MAP:
1265 gtk_window_set_focus_on_map (window,
1266 g_value_get_boolean (value));
1268 case PROP_DECORATED:
1269 gtk_window_set_decorated (window, g_value_get_boolean (value));
1271 case PROP_DELETABLE:
1272 gtk_window_set_deletable (window, g_value_get_boolean (value));
1275 gtk_window_set_gravity (window, g_value_get_enum (value));
1277 case PROP_TRANSIENT_FOR:
1278 gtk_window_set_transient_for (window, g_value_get_object (value));
1281 gtk_window_set_opacity (window, g_value_get_double (value));
1283 case PROP_HAS_RESIZE_GRIP:
1284 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1286 case PROP_APPLICATION:
1287 gtk_window_set_application (window, g_value_get_object (value));
1289 case PROP_MNEMONICS_VISIBLE:
1290 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1292 case PROP_FOCUS_VISIBLE:
1293 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1296 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1302 gtk_window_get_property (GObject *object,
1307 GtkWindow *window = GTK_WINDOW (object);
1308 GtkWindowPrivate *priv = window->priv;
1312 GtkWindowGeometryInfo *info;
1314 g_value_set_enum (value, priv->type);
1317 g_value_set_string (value, priv->wm_role);
1320 g_value_set_string (value, priv->title);
1322 case PROP_RESIZABLE:
1323 g_value_set_boolean (value, priv->resizable);
1326 g_value_set_boolean (value, priv->modal);
1329 g_value_set_enum (value, priv->position);
1331 case PROP_DEFAULT_WIDTH:
1332 info = gtk_window_get_geometry_info (window, FALSE);
1334 g_value_set_int (value, -1);
1336 g_value_set_int (value, info->default_width);
1338 case PROP_DEFAULT_HEIGHT:
1339 info = gtk_window_get_geometry_info (window, FALSE);
1341 g_value_set_int (value, -1);
1343 g_value_set_int (value, info->default_height);
1345 case PROP_DESTROY_WITH_PARENT:
1346 g_value_set_boolean (value, priv->destroy_with_parent);
1348 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1349 g_value_set_boolean (value, priv->hide_titlebar_when_maximized);
1352 g_value_set_object (value, gtk_window_get_icon (window));
1354 case PROP_ICON_NAME:
1355 g_value_set_string (value, gtk_window_get_icon_name (window));
1358 g_value_set_object (value, priv->screen);
1360 case PROP_IS_ACTIVE:
1361 g_value_set_boolean (value, priv->is_active);
1363 case PROP_HAS_TOPLEVEL_FOCUS:
1364 g_value_set_boolean (value, priv->has_toplevel_focus);
1366 case PROP_TYPE_HINT:
1367 g_value_set_enum (value, priv->type_hint);
1369 case PROP_SKIP_TASKBAR_HINT:
1370 g_value_set_boolean (value,
1371 gtk_window_get_skip_taskbar_hint (window));
1373 case PROP_SKIP_PAGER_HINT:
1374 g_value_set_boolean (value,
1375 gtk_window_get_skip_pager_hint (window));
1377 case PROP_URGENCY_HINT:
1378 g_value_set_boolean (value,
1379 gtk_window_get_urgency_hint (window));
1381 case PROP_ACCEPT_FOCUS:
1382 g_value_set_boolean (value,
1383 gtk_window_get_accept_focus (window));
1385 case PROP_FOCUS_ON_MAP:
1386 g_value_set_boolean (value,
1387 gtk_window_get_focus_on_map (window));
1389 case PROP_DECORATED:
1390 g_value_set_boolean (value, gtk_window_get_decorated (window));
1392 case PROP_DELETABLE:
1393 g_value_set_boolean (value, gtk_window_get_deletable (window));
1396 g_value_set_enum (value, gtk_window_get_gravity (window));
1398 case PROP_TRANSIENT_FOR:
1399 g_value_set_object (value, gtk_window_get_transient_for (window));
1402 g_value_set_double (value, gtk_window_get_opacity (window));
1404 case PROP_HAS_RESIZE_GRIP:
1405 g_value_set_boolean (value, priv->has_resize_grip);
1407 case PROP_RESIZE_GRIP_VISIBLE:
1408 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1410 case PROP_APPLICATION:
1411 g_value_set_object (value, gtk_window_get_application (window));
1413 case PROP_MNEMONICS_VISIBLE:
1414 g_value_set_boolean (value, priv->mnemonics_visible);
1416 case PROP_FOCUS_VISIBLE:
1417 g_value_set_boolean (value, priv->focus_visible);
1420 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1426 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1428 parent_buildable_iface = g_type_interface_peek_parent (iface);
1429 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1430 iface->parser_finished = gtk_window_buildable_parser_finished;
1431 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1432 iface->custom_finished = gtk_window_buildable_custom_finished;
1436 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1437 GtkBuilder *builder,
1439 const GValue *value)
1441 GtkWindow *window = GTK_WINDOW (buildable);
1442 GtkWindowPrivate *priv = window->priv;
1444 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1445 priv->builder_visible = TRUE;
1447 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1451 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1452 GtkBuilder *builder)
1454 GtkWindow *window = GTK_WINDOW (buildable);
1455 GtkWindowPrivate *priv = window->priv;
1459 if (priv->builder_visible)
1460 gtk_widget_show (GTK_WIDGET (buildable));
1462 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1463 for (l = accels; l; l = l->next)
1465 object = gtk_builder_get_object (builder, l->data);
1468 g_warning ("Unknown accel group %s specified in window %s",
1469 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1472 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1473 GTK_ACCEL_GROUP (object));
1477 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1479 parent_buildable_iface->parser_finished (buildable, builder);
1485 } GSListSubParserData;
1488 window_start_element (GMarkupParseContext *context,
1489 const gchar *element_name,
1490 const gchar **names,
1491 const gchar **values,
1496 GSListSubParserData *data = (GSListSubParserData*)user_data;
1498 if (strcmp (element_name, "group") == 0)
1500 for (i = 0; names[i]; i++)
1502 if (strcmp (names[i], "name") == 0)
1503 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1506 else if (strcmp (element_name, "accel-groups") == 0)
1509 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1514 static const GMarkupParser window_parser =
1516 window_start_element
1520 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1521 GtkBuilder *builder,
1523 const gchar *tagname,
1524 GMarkupParser *parser,
1527 GSListSubParserData *parser_data;
1529 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1530 tagname, parser, data))
1533 if (strcmp (tagname, "accel-groups") == 0)
1535 parser_data = g_slice_new0 (GSListSubParserData);
1536 parser_data->items = NULL;
1537 parser_data->object = G_OBJECT (buildable);
1539 *parser = window_parser;
1540 *data = parser_data;
1548 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1549 GtkBuilder *builder,
1551 const gchar *tagname,
1554 GSListSubParserData *data;
1556 parent_buildable_iface->custom_finished (buildable, builder, child,
1557 tagname, user_data);
1559 if (strcmp (tagname, "accel-groups") != 0)
1562 data = (GSListSubParserData*)user_data;
1564 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1565 data->items, (GDestroyNotify) g_slist_free);
1567 g_slice_free (GSListSubParserData, data);
1572 * @type: type of window
1574 * Creates a new #GtkWindow, which is a toplevel window that can
1575 * contain other widgets. Nearly always, the type of the window should
1576 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1577 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1578 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1579 * dialogs, though in some other toolkits dialogs are called "popups".
1580 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1581 * On X11, popup windows are not controlled by the <link
1582 * linkend="gtk-X11-arch">window manager</link>.
1584 * If you simply want an undecorated window (no window borders), use
1585 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1587 * Return value: a new #GtkWindow.
1590 gtk_window_new (GtkWindowType type)
1592 GtkWindowPrivate *priv;
1595 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1597 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1598 priv = window->priv;
1602 return GTK_WIDGET (window);
1606 * gtk_window_set_title:
1607 * @window: a #GtkWindow
1608 * @title: title of the window
1610 * Sets the title of the #GtkWindow. The title of a window will be
1611 * displayed in its title bar; on the X Window System, the title bar
1612 * is rendered by the <link linkend="gtk-X11-arch">window
1613 * manager</link>, so exactly how the title appears to users may vary
1614 * according to a user's exact configuration. The title should help a
1615 * user distinguish this window from other windows they may have
1616 * open. A good title might include the application name and current
1617 * document filename, for example.
1621 gtk_window_set_title (GtkWindow *window,
1624 GtkWindowPrivate *priv;
1628 g_return_if_fail (GTK_IS_WINDOW (window));
1630 priv = window->priv;
1631 widget = GTK_WIDGET (window);
1633 new_title = g_strdup (title);
1634 g_free (priv->title);
1635 priv->title = new_title;
1637 if (gtk_widget_get_realized (widget))
1639 gdk_window_set_title (gtk_widget_get_window (widget),
1643 g_object_notify (G_OBJECT (window), "title");
1647 * gtk_window_get_title:
1648 * @window: a #GtkWindow
1650 * Retrieves the title of the window. See gtk_window_set_title().
1652 * Return value: the title of the window, or %NULL if none has
1653 * been set explicitely. The returned string is owned by the widget
1654 * and must not be modified or freed.
1657 gtk_window_get_title (GtkWindow *window)
1659 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1661 return window->priv->title;
1665 * gtk_window_set_wmclass:
1666 * @window: a #GtkWindow
1667 * @wmclass_name: window name hint
1668 * @wmclass_class: window class hint
1670 * Don't use this function. It sets the X Window System "class" and
1671 * "name" hints for a window. According to the ICCCM, you should
1672 * always set these to the same value for all windows in an
1673 * application, and GTK+ sets them to that value by default, so calling
1674 * this function is sort of pointless. However, you may want to call
1675 * gtk_window_set_role() on each window in your application, for the
1676 * benefit of the session manager. Setting the role allows the window
1677 * manager to restore window positions when loading a saved session.
1681 gtk_window_set_wmclass (GtkWindow *window,
1682 const gchar *wmclass_name,
1683 const gchar *wmclass_class)
1685 GtkWindowPrivate *priv;
1687 g_return_if_fail (GTK_IS_WINDOW (window));
1689 priv = window->priv;
1691 g_free (priv->wmclass_name);
1692 priv->wmclass_name = g_strdup (wmclass_name);
1694 g_free (priv->wmclass_class);
1695 priv->wmclass_class = g_strdup (wmclass_class);
1697 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1698 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1702 * gtk_window_set_role:
1703 * @window: a #GtkWindow
1704 * @role: unique identifier for the window to be used when restoring a session
1706 * This function is only useful on X11, not with other GTK+ targets.
1708 * In combination with the window title, the window role allows a
1709 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1710 * same" window when an application is restarted. So for example you
1711 * might set the "toolbox" role on your app's toolbox window, so that
1712 * when the user restarts their session, the window manager can put
1713 * the toolbox back in the same place.
1715 * If a window already has a unique title, you don't need to set the
1716 * role, since the WM can use the title to identify the window when
1717 * restoring the session.
1721 gtk_window_set_role (GtkWindow *window,
1724 GtkWindowPrivate *priv;
1727 g_return_if_fail (GTK_IS_WINDOW (window));
1729 priv = window->priv;
1731 new_role = g_strdup (role);
1732 g_free (priv->wm_role);
1733 priv->wm_role = new_role;
1735 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1736 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1739 g_object_notify (G_OBJECT (window), "role");
1743 * gtk_window_set_startup_id:
1744 * @window: a #GtkWindow
1745 * @startup_id: a string with startup-notification identifier
1747 * Startup notification identifiers are used by desktop environment to
1748 * track application startup, to provide user feedback and other
1749 * features. This function changes the corresponding property on the
1750 * underlying GdkWindow. Normally, startup identifier is managed
1751 * automatically and you should only use this function in special cases
1752 * like transferring focus from other processes. You should use this
1753 * function before calling gtk_window_present() or any equivalent
1754 * function generating a window map event.
1756 * This function is only useful on X11, not with other GTK+ targets.
1761 gtk_window_set_startup_id (GtkWindow *window,
1762 const gchar *startup_id)
1764 GtkWindowPrivate *priv;
1767 g_return_if_fail (GTK_IS_WINDOW (window));
1769 priv = window->priv;
1770 widget = GTK_WIDGET (window);
1772 g_free (priv->startup_id);
1773 priv->startup_id = g_strdup (startup_id);
1775 if (gtk_widget_get_realized (widget))
1777 GdkWindow *gdk_window;
1778 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1780 gdk_window = gtk_widget_get_window (widget);
1782 #ifdef GDK_WINDOWING_X11
1783 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1784 gdk_x11_window_set_user_time (gdk_window, timestamp);
1787 /* Here we differentiate real and "fake" startup notification IDs,
1788 * constructed on purpose just to pass interaction timestamp
1790 if (startup_id_is_fake (priv->startup_id))
1791 gtk_window_present_with_time (window, timestamp);
1794 gdk_window_set_startup_id (gdk_window,
1797 /* If window is mapped, terminate the startup-notification too */
1798 if (gtk_widget_get_mapped (widget) &&
1799 !disable_startup_notification)
1800 gdk_notify_startup_complete_with_id (priv->startup_id);
1804 g_object_notify (G_OBJECT (window), "startup-id");
1808 * gtk_window_get_role:
1809 * @window: a #GtkWindow
1811 * Returns the role of the window. See gtk_window_set_role() for
1812 * further explanation.
1814 * Return value: the role of the window if set, or %NULL. The
1815 * returned is owned by the widget and must not be modified
1819 gtk_window_get_role (GtkWindow *window)
1821 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1823 return window->priv->wm_role;
1827 * gtk_window_set_focus:
1828 * @window: a #GtkWindow
1829 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1830 * any focus widget for the toplevel window.
1832 * If @focus is not the current focus widget, and is focusable, sets
1833 * it as the focus widget for the window. If @focus is %NULL, unsets
1834 * the focus widget for this window. To set the focus to a particular
1835 * widget in the toplevel, it is usually more convenient to use
1836 * gtk_widget_grab_focus() instead of this function.
1839 gtk_window_set_focus (GtkWindow *window,
1842 GtkWindowPrivate *priv;
1845 g_return_if_fail (GTK_IS_WINDOW (window));
1847 priv = window->priv;
1851 g_return_if_fail (GTK_IS_WIDGET (focus));
1852 g_return_if_fail (gtk_widget_get_can_focus (focus));
1856 gtk_widget_grab_focus (focus);
1859 /* Clear the existing focus chain, so that when we focus into
1860 * the window again, we start at the beginnning.
1862 GtkWidget *widget = priv->focus_widget;
1865 while ((parent = gtk_widget_get_parent (widget)))
1868 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1872 _gtk_window_internal_set_focus (window, NULL);
1877 _gtk_window_internal_set_focus (GtkWindow *window,
1880 GtkWindowPrivate *priv;
1882 g_return_if_fail (GTK_IS_WINDOW (window));
1884 priv = window->priv;
1886 if ((priv->focus_widget != focus) ||
1887 (focus && !gtk_widget_has_focus (focus)))
1888 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1892 * gtk_window_set_default:
1893 * @window: a #GtkWindow
1894 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1895 * default widget for the toplevel.
1897 * The default widget is the widget that's activated when the user
1898 * presses Enter in a dialog (for example). This function sets or
1899 * unsets the default widget for a #GtkWindow about. When setting
1900 * (rather than unsetting) the default widget it's generally easier to
1901 * call gtk_widget_grab_focus() on the widget. Before making a widget
1902 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1903 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1906 gtk_window_set_default (GtkWindow *window,
1907 GtkWidget *default_widget)
1909 GtkWindowPrivate *priv;
1911 g_return_if_fail (GTK_IS_WINDOW (window));
1913 priv = window->priv;
1916 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1918 if (priv->default_widget != default_widget)
1920 GtkWidget *old_default_widget = NULL;
1923 g_object_ref (default_widget);
1925 if (priv->default_widget)
1927 old_default_widget = priv->default_widget;
1929 if (priv->focus_widget != priv->default_widget ||
1930 !gtk_widget_get_receives_default (priv->default_widget))
1931 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1933 gtk_widget_queue_draw (priv->default_widget);
1936 priv->default_widget = default_widget;
1938 if (priv->default_widget)
1940 if (priv->focus_widget == NULL ||
1941 !gtk_widget_get_receives_default (priv->focus_widget))
1942 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1944 gtk_widget_queue_draw (priv->default_widget);
1947 if (old_default_widget)
1948 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1952 g_object_notify (G_OBJECT (default_widget), "has-default");
1953 g_object_unref (default_widget);
1959 * gtk_window_get_default_widget:
1960 * @window: a #GtkWindow
1962 * Returns the default widget for @window. See gtk_window_set_default()
1965 * Returns: (transfer none): the default widget, or %NULL if there is none.
1970 gtk_window_get_default_widget (GtkWindow *window)
1972 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1974 return window->priv->default_widget;
1978 handle_keys_changed (gpointer data)
1980 GtkWindow *window = GTK_WINDOW (data);
1981 GtkWindowPrivate *priv = window->priv;
1983 if (priv->keys_changed_handler)
1985 g_source_remove (priv->keys_changed_handler);
1986 priv->keys_changed_handler = 0;
1989 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1995 gtk_window_notify_keys_changed (GtkWindow *window)
1997 GtkWindowPrivate *priv = window->priv;
1999 if (!priv->keys_changed_handler)
2000 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
2004 * gtk_window_add_accel_group:
2005 * @window: window to attach accelerator group to
2006 * @accel_group: a #GtkAccelGroup
2008 * Associate @accel_group with @window, such that calling
2009 * gtk_accel_groups_activate() on @window will activate accelerators
2013 gtk_window_add_accel_group (GtkWindow *window,
2014 GtkAccelGroup *accel_group)
2016 g_return_if_fail (GTK_IS_WINDOW (window));
2017 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2019 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
2020 g_signal_connect_object (accel_group, "accel-changed",
2021 G_CALLBACK (gtk_window_notify_keys_changed),
2022 window, G_CONNECT_SWAPPED);
2023 gtk_window_notify_keys_changed (window);
2027 * gtk_window_remove_accel_group:
2028 * @window: a #GtkWindow
2029 * @accel_group: a #GtkAccelGroup
2031 * Reverses the effects of gtk_window_add_accel_group().
2034 gtk_window_remove_accel_group (GtkWindow *window,
2035 GtkAccelGroup *accel_group)
2037 g_return_if_fail (GTK_IS_WINDOW (window));
2038 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2040 g_signal_handlers_disconnect_by_func (accel_group,
2041 gtk_window_notify_keys_changed,
2043 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2044 gtk_window_notify_keys_changed (window);
2047 static GtkMnemonicHash *
2048 gtk_window_get_mnemonic_hash (GtkWindow *window,
2051 GtkWindowPrivate *private = window->priv;
2053 if (!private->mnemonic_hash && create)
2054 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2056 return private->mnemonic_hash;
2060 * gtk_window_add_mnemonic:
2061 * @window: a #GtkWindow
2062 * @keyval: the mnemonic
2063 * @target: the widget that gets activated by the mnemonic
2065 * Adds a mnemonic to this window.
2068 gtk_window_add_mnemonic (GtkWindow *window,
2072 g_return_if_fail (GTK_IS_WINDOW (window));
2073 g_return_if_fail (GTK_IS_WIDGET (target));
2075 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2077 gtk_window_notify_keys_changed (window);
2081 * gtk_window_remove_mnemonic:
2082 * @window: a #GtkWindow
2083 * @keyval: the mnemonic
2084 * @target: the widget that gets activated by the mnemonic
2086 * Removes a mnemonic from this window.
2089 gtk_window_remove_mnemonic (GtkWindow *window,
2093 g_return_if_fail (GTK_IS_WINDOW (window));
2094 g_return_if_fail (GTK_IS_WIDGET (target));
2096 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2098 gtk_window_notify_keys_changed (window);
2102 * gtk_window_mnemonic_activate:
2103 * @window: a #GtkWindow
2104 * @keyval: the mnemonic
2105 * @modifier: the modifiers
2107 * Activates the targets associated with the mnemonic.
2109 * Returns: %TRUE if the activation is done.
2112 gtk_window_mnemonic_activate (GtkWindow *window,
2114 GdkModifierType modifier)
2116 GtkWindowPrivate *priv;
2118 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2120 priv = window->priv;
2122 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2124 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2126 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2133 * gtk_window_set_mnemonic_modifier:
2134 * @window: a #GtkWindow
2135 * @modifier: the modifier mask used to activate
2136 * mnemonics on this window.
2138 * Sets the mnemonic modifier for this window.
2141 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2142 GdkModifierType modifier)
2144 GtkWindowPrivate *priv;
2146 g_return_if_fail (GTK_IS_WINDOW (window));
2147 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2149 priv = window->priv;
2151 priv->mnemonic_modifier = modifier;
2152 gtk_window_notify_keys_changed (window);
2156 * gtk_window_get_mnemonic_modifier:
2157 * @window: a #GtkWindow
2159 * Returns the mnemonic modifier for this window. See
2160 * gtk_window_set_mnemonic_modifier().
2162 * Return value: the modifier mask used to activate
2163 * mnemonics on this window.
2166 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2168 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2170 return window->priv->mnemonic_modifier;
2174 * gtk_window_set_position:
2175 * @window: a #GtkWindow.
2176 * @position: a position constraint.
2178 * Sets a position constraint for this window. If the old or new
2179 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2180 * the window to be repositioned to satisfy the new constraint.
2183 gtk_window_set_position (GtkWindow *window,
2184 GtkWindowPosition position)
2186 GtkWindowPrivate *priv;
2188 g_return_if_fail (GTK_IS_WINDOW (window));
2190 priv = window->priv;
2192 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2193 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2195 GtkWindowGeometryInfo *info;
2197 info = gtk_window_get_geometry_info (window, TRUE);
2199 /* this flag causes us to re-request the CENTER_ALWAYS
2200 * constraint in gtk_window_move_resize(), see
2201 * comment in that function.
2203 info->position_constraints_changed = TRUE;
2205 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2208 priv->position = position;
2210 g_object_notify (G_OBJECT (window), "window-position");
2214 * gtk_window_activate_focus:
2215 * @window: a #GtkWindow
2217 * Activates the current focused widget within the window.
2219 * Return value: %TRUE if a widget got activated.
2222 gtk_window_activate_focus (GtkWindow *window)
2224 GtkWindowPrivate *priv;
2226 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2228 priv = window->priv;
2230 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2231 return gtk_widget_activate (priv->focus_widget);
2237 * gtk_window_get_focus:
2238 * @window: a #GtkWindow
2240 * Retrieves the current focused widget within the window.
2241 * Note that this is the widget that would have the focus
2242 * if the toplevel window focused; if the toplevel window
2243 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2244 * not be %TRUE for the widget.
2246 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2249 gtk_window_get_focus (GtkWindow *window)
2251 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2253 return window->priv->focus_widget;
2257 * gtk_window_activate_default:
2258 * @window: a #GtkWindow
2260 * Activates the default widget for the window, unless the current
2261 * focused widget has been configured to receive the default action
2262 * (see gtk_widget_set_receives_default()), in which case the
2263 * focused widget is activated.
2265 * Return value: %TRUE if a widget got activated.
2268 gtk_window_activate_default (GtkWindow *window)
2270 GtkWindowPrivate *priv;
2272 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2274 priv = window->priv;
2276 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2277 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2278 return gtk_widget_activate (priv->default_widget);
2279 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2280 return gtk_widget_activate (priv->focus_widget);
2286 * gtk_window_set_modal:
2287 * @window: a #GtkWindow
2288 * @modal: whether the window is modal
2290 * Sets a window modal or non-modal. Modal windows prevent interaction
2291 * with other windows in the same application. To keep modal dialogs
2292 * on top of main application windows, use
2293 * gtk_window_set_transient_for() to make the dialog transient for the
2294 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2295 * will then disallow lowering the dialog below the parent.
2300 gtk_window_set_modal (GtkWindow *window,
2303 GtkWindowPrivate *priv;
2306 g_return_if_fail (GTK_IS_WINDOW (window));
2308 priv = window->priv;
2310 modal = modal != FALSE;
2311 if (priv->modal == modal)
2314 priv->modal = modal;
2315 widget = GTK_WIDGET (window);
2317 /* adjust desired modality state */
2318 if (gtk_widget_get_realized (widget))
2321 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2323 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2326 if (gtk_widget_get_visible (widget))
2329 gtk_grab_add (widget);
2331 gtk_grab_remove (widget);
2334 g_object_notify (G_OBJECT (window), "modal");
2338 * gtk_window_get_modal:
2339 * @window: a #GtkWindow
2341 * Returns whether the window is modal. See gtk_window_set_modal().
2343 * Return value: %TRUE if the window is set to be modal and
2344 * establishes a grab when shown
2347 gtk_window_get_modal (GtkWindow *window)
2349 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2351 return window->priv->modal;
2355 * gtk_window_list_toplevels:
2357 * Returns a list of all existing toplevel windows. The widgets
2358 * in the list are not individually referenced. If you want
2359 * to iterate through the list and perform actions involving
2360 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2361 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2362 * then unref all the widgets afterwards.
2364 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2367 gtk_window_list_toplevels (void)
2372 for (slist = toplevel_list; slist; slist = slist->next)
2373 list = g_list_prepend (list, slist->data);
2379 gtk_window_dispose (GObject *object)
2381 GtkWindow *window = GTK_WINDOW (object);
2383 gtk_window_set_focus (window, NULL);
2384 gtk_window_set_default (window, NULL);
2386 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2390 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2392 gtk_widget_destroy (GTK_WIDGET (child));
2396 connect_parent_destroyed (GtkWindow *window)
2398 GtkWindowPrivate *priv = window->priv;
2400 if (priv->transient_parent)
2402 g_signal_connect (priv->transient_parent,
2404 G_CALLBACK (parent_destroyed_callback),
2410 disconnect_parent_destroyed (GtkWindow *window)
2412 GtkWindowPrivate *priv = window->priv;
2414 if (priv->transient_parent)
2416 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2417 parent_destroyed_callback,
2423 gtk_window_transient_parent_realized (GtkWidget *parent,
2426 if (gtk_widget_get_realized (window))
2427 gdk_window_set_transient_for (gtk_widget_get_window (window),
2428 gtk_widget_get_window (parent));
2432 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2435 if (gtk_widget_get_realized (window))
2436 gdk_property_delete (gtk_widget_get_window (window),
2437 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2441 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2445 gtk_window_set_screen (window, parent->priv->screen);
2449 gtk_window_unset_transient_for (GtkWindow *window)
2451 GtkWindowPrivate *priv = window->priv;
2453 if (priv->transient_parent)
2455 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2456 gtk_window_transient_parent_realized,
2458 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2459 gtk_window_transient_parent_unrealized,
2461 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2462 gtk_window_transient_parent_screen_changed,
2464 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2465 gtk_widget_destroyed,
2466 &priv->transient_parent);
2468 if (priv->destroy_with_parent)
2469 disconnect_parent_destroyed (window);
2471 priv->transient_parent = NULL;
2473 if (priv->transient_parent_group)
2475 priv->transient_parent_group = FALSE;
2476 gtk_window_group_remove_window (priv->group,
2483 * gtk_window_set_transient_for:
2484 * @window: a #GtkWindow
2485 * @parent: (allow-none): parent window, or %NULL
2487 * Dialog windows should be set transient for the main application
2488 * window they were spawned from. This allows <link
2489 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2490 * dialog on top of the main window, or center the dialog over the
2491 * main window. gtk_dialog_new_with_buttons() and other convenience
2492 * functions in GTK+ will sometimes call
2493 * gtk_window_set_transient_for() on your behalf.
2495 * Passing %NULL for @parent unsets the current transient window.
2497 * On Windows, this function puts the child window on top of the parent,
2498 * much as the window manager would have done on X.
2501 gtk_window_set_transient_for (GtkWindow *window,
2504 GtkWindowPrivate *priv;
2506 g_return_if_fail (GTK_IS_WINDOW (window));
2507 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2508 g_return_if_fail (window != parent);
2510 priv = window->priv;
2512 if (priv->transient_parent)
2514 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2515 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2516 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2517 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2518 GTK_WIDGET (window));
2520 gtk_window_unset_transient_for (window);
2523 priv->transient_parent = parent;
2527 g_signal_connect (parent, "destroy",
2528 G_CALLBACK (gtk_widget_destroyed),
2529 &priv->transient_parent);
2530 g_signal_connect (parent, "realize",
2531 G_CALLBACK (gtk_window_transient_parent_realized),
2533 g_signal_connect (parent, "unrealize",
2534 G_CALLBACK (gtk_window_transient_parent_unrealized),
2536 g_signal_connect (parent, "notify::screen",
2537 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2540 gtk_window_set_screen (window, parent->priv->screen);
2542 if (priv->destroy_with_parent)
2543 connect_parent_destroyed (window);
2545 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2546 gtk_widget_get_realized (GTK_WIDGET (parent)))
2547 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2548 GTK_WIDGET (window));
2550 if (parent->priv->group)
2552 gtk_window_group_add_window (parent->priv->group, window);
2553 priv->transient_parent_group = TRUE;
2559 * gtk_window_get_transient_for:
2560 * @window: a #GtkWindow
2562 * Fetches the transient parent for this window. See
2563 * gtk_window_set_transient_for().
2565 * Return value: (transfer none): the transient parent for this window, or %NULL
2566 * if no transient parent has been set.
2569 gtk_window_get_transient_for (GtkWindow *window)
2571 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2573 return window->priv->transient_parent;
2577 * gtk_window_set_opacity:
2578 * @window: a #GtkWindow
2579 * @opacity: desired opacity, between 0 and 1
2581 * Request the windowing system to make @window partially transparent,
2582 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2583 * of the opacity parameter are clamped to the [0,1] range.) On X11
2584 * this has any effect only on X screens with a compositing manager
2585 * running. See gtk_widget_is_composited(). On Windows it should work
2588 * Note that setting a window's opacity after the window has been
2589 * shown causes it to flicker once on Windows.
2594 gtk_window_set_opacity (GtkWindow *window,
2597 GtkWindowPrivate *priv;
2599 g_return_if_fail (GTK_IS_WINDOW (window));
2601 priv = window->priv;
2605 else if (opacity > 1.0)
2608 priv->opacity_set = TRUE;
2609 priv->opacity = opacity;
2611 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2612 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2617 * gtk_window_get_opacity:
2618 * @window: a #GtkWindow
2620 * Fetches the requested opacity for this window. See
2621 * gtk_window_set_opacity().
2623 * Return value: the requested opacity for this window.
2628 gtk_window_get_opacity (GtkWindow *window)
2630 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2632 return window->priv->opacity;
2636 * gtk_window_get_application:
2637 * @window: a #GtkWindow
2639 * Gets the #GtkApplication associated with the window (if any).
2641 * Return value: (transfer none): a #GtkApplication, or %NULL
2646 gtk_window_get_application (GtkWindow *window)
2648 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2650 return window->priv->application;
2654 gtk_window_release_application (GtkWindow *window)
2656 if (window->priv->application)
2658 GtkApplication *application;
2660 /* steal reference into temp variable */
2661 application = window->priv->application;
2662 window->priv->application = NULL;
2664 gtk_application_remove_window (application, window);
2665 g_object_unref (application);
2670 * gtk_window_set_application:
2671 * @window: a #GtkWindow
2672 * @application: (allow-none): a #GtkApplication, or %NULL
2674 * Sets or unsets the #GtkApplication associated with the window.
2676 * The application will be kept alive for at least as long as the window
2682 gtk_window_set_application (GtkWindow *window,
2683 GtkApplication *application)
2685 GtkWindowPrivate *priv;
2687 g_return_if_fail (GTK_IS_WINDOW (window));
2689 priv = window->priv;
2690 if (priv->application != application)
2692 gtk_window_release_application (window);
2694 priv->application = application;
2696 if (priv->application != NULL)
2698 g_object_ref (priv->application);
2700 gtk_application_add_window (priv->application, window);
2703 g_object_notify (G_OBJECT (window), "application");
2708 * gtk_window_set_type_hint:
2709 * @window: a #GtkWindow
2710 * @hint: the window type
2712 * By setting the type hint for the window, you allow the window
2713 * manager to decorate and handle the window in a way which is
2714 * suitable to the function of the window in your application.
2716 * This function should be called before the window becomes visible.
2718 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2719 * will sometimes call gtk_window_set_type_hint() on your behalf.
2723 gtk_window_set_type_hint (GtkWindow *window,
2724 GdkWindowTypeHint hint)
2726 GtkWindowPrivate *priv;
2728 g_return_if_fail (GTK_IS_WINDOW (window));
2729 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2731 priv = window->priv;
2733 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2734 priv->type_hint = hint;
2736 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2738 priv->reset_type_hint = TRUE;
2739 priv->gdk_type_hint = hint;
2743 * gtk_window_get_type_hint:
2744 * @window: a #GtkWindow
2746 * Gets the type hint for this window. See gtk_window_set_type_hint().
2748 * Return value: the type hint for @window.
2751 gtk_window_get_type_hint (GtkWindow *window)
2753 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2755 return window->priv->gdk_type_hint;
2759 * gtk_window_set_skip_taskbar_hint:
2760 * @window: a #GtkWindow
2761 * @setting: %TRUE to keep this window from appearing in the task bar
2763 * Windows may set a hint asking the desktop environment not to display
2764 * the window in the task bar. This function sets this hint.
2769 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2772 GtkWindowPrivate *priv;
2774 g_return_if_fail (GTK_IS_WINDOW (window));
2776 priv = window->priv;
2778 setting = setting != FALSE;
2780 if (priv->skips_taskbar != setting)
2782 priv->skips_taskbar = setting;
2783 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2784 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2785 priv->skips_taskbar);
2786 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2791 * gtk_window_get_skip_taskbar_hint:
2792 * @window: a #GtkWindow
2794 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2796 * Return value: %TRUE if window shouldn't be in taskbar
2801 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2803 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2805 return window->priv->skips_taskbar;
2809 * gtk_window_set_skip_pager_hint:
2810 * @window: a #GtkWindow
2811 * @setting: %TRUE to keep this window from appearing in the pager
2813 * Windows may set a hint asking the desktop environment not to display
2814 * the window in the pager. This function sets this hint.
2815 * (A "pager" is any desktop navigation tool such as a workspace
2816 * switcher that displays a thumbnail representation of the windows
2822 gtk_window_set_skip_pager_hint (GtkWindow *window,
2825 GtkWindowPrivate *priv;
2827 g_return_if_fail (GTK_IS_WINDOW (window));
2829 priv = window->priv;
2831 setting = setting != FALSE;
2833 if (priv->skips_pager != setting)
2835 priv->skips_pager = setting;
2836 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2837 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2839 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2844 * gtk_window_get_skip_pager_hint:
2845 * @window: a #GtkWindow
2847 * Gets the value set by gtk_window_set_skip_pager_hint().
2849 * Return value: %TRUE if window shouldn't be in pager
2854 gtk_window_get_skip_pager_hint (GtkWindow *window)
2856 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2858 return window->priv->skips_pager;
2862 * gtk_window_set_urgency_hint:
2863 * @window: a #GtkWindow
2864 * @setting: %TRUE to mark this window as urgent
2866 * Windows may set a hint asking the desktop environment to draw
2867 * the users attention to the window. This function sets this hint.
2872 gtk_window_set_urgency_hint (GtkWindow *window,
2875 GtkWindowPrivate *priv;
2877 g_return_if_fail (GTK_IS_WINDOW (window));
2879 priv = window->priv;
2881 setting = setting != FALSE;
2883 if (priv->urgent != setting)
2885 priv->urgent = setting;
2886 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2887 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2889 g_object_notify (G_OBJECT (window), "urgency-hint");
2894 * gtk_window_get_urgency_hint:
2895 * @window: a #GtkWindow
2897 * Gets the value set by gtk_window_set_urgency_hint()
2899 * Return value: %TRUE if window is urgent
2904 gtk_window_get_urgency_hint (GtkWindow *window)
2906 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2908 return window->priv->urgent;
2912 * gtk_window_set_accept_focus:
2913 * @window: a #GtkWindow
2914 * @setting: %TRUE to let this window receive input focus
2916 * Windows may set a hint asking the desktop environment not to receive
2917 * the input focus. This function sets this hint.
2922 gtk_window_set_accept_focus (GtkWindow *window,
2925 GtkWindowPrivate *priv;
2927 g_return_if_fail (GTK_IS_WINDOW (window));
2929 priv = window->priv;
2931 setting = setting != FALSE;
2933 if (priv->accept_focus != setting)
2935 priv->accept_focus = setting;
2936 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2937 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2938 priv->accept_focus);
2939 g_object_notify (G_OBJECT (window), "accept-focus");
2944 * gtk_window_get_accept_focus:
2945 * @window: a #GtkWindow
2947 * Gets the value set by gtk_window_set_accept_focus().
2949 * Return value: %TRUE if window should receive the input focus
2954 gtk_window_get_accept_focus (GtkWindow *window)
2956 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2958 return window->priv->accept_focus;
2962 * gtk_window_set_focus_on_map:
2963 * @window: a #GtkWindow
2964 * @setting: %TRUE to let this window receive input focus on map
2966 * Windows may set a hint asking the desktop environment not to receive
2967 * the input focus when the window is mapped. This function sets this
2973 gtk_window_set_focus_on_map (GtkWindow *window,
2976 GtkWindowPrivate *priv;
2978 g_return_if_fail (GTK_IS_WINDOW (window));
2980 priv = window->priv;
2982 setting = setting != FALSE;
2984 if (priv->focus_on_map != setting)
2986 priv->focus_on_map = setting;
2987 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2988 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2989 priv->focus_on_map);
2990 g_object_notify (G_OBJECT (window), "focus-on-map");
2995 * gtk_window_get_focus_on_map:
2996 * @window: a #GtkWindow
2998 * Gets the value set by gtk_window_set_focus_on_map().
3000 * Return value: %TRUE if window should receive the input focus when
3006 gtk_window_get_focus_on_map (GtkWindow *window)
3008 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3010 return window->priv->focus_on_map;
3014 * gtk_window_set_destroy_with_parent:
3015 * @window: a #GtkWindow
3016 * @setting: whether to destroy @window with its transient parent
3018 * If @setting is %TRUE, then destroying the transient parent of @window
3019 * will also destroy @window itself. This is useful for dialogs that
3020 * shouldn't persist beyond the lifetime of the main window they're
3021 * associated with, for example.
3024 gtk_window_set_destroy_with_parent (GtkWindow *window,
3027 GtkWindowPrivate *priv;
3029 g_return_if_fail (GTK_IS_WINDOW (window));
3031 priv = window->priv;
3033 if (priv->destroy_with_parent == (setting != FALSE))
3036 if (priv->destroy_with_parent)
3038 disconnect_parent_destroyed (window);
3042 connect_parent_destroyed (window);
3045 priv->destroy_with_parent = setting;
3047 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3051 * gtk_window_get_destroy_with_parent:
3052 * @window: a #GtkWindow
3054 * Returns whether the window will be destroyed with its transient parent. See
3055 * gtk_window_set_destroy_with_parent ().
3057 * Return value: %TRUE if the window will be destroyed with its transient parent.
3060 gtk_window_get_destroy_with_parent (GtkWindow *window)
3062 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3064 return window->priv->destroy_with_parent;
3068 * gtk_window_set_hide_titlebar_when_maximized:
3069 * @window: a #GtkWindow
3070 * @setting: whether to hide the titlebar when @window is maximized
3072 * If @setting is %TRUE, then @window will request that it's titlebar
3073 * should be hidden when maximized.
3074 * This is useful for windows that don't convey any information other
3075 * than the application name in the titlebar, to put the available
3076 * screen space to better use. If the underlying window system does not
3077 * support the request, the setting will not have any effect.
3082 gtk_window_set_hide_titlebar_when_maximized (GtkWindow *window,
3085 g_return_if_fail (GTK_IS_WINDOW (window));
3087 #ifdef GDK_WINDOWING_X11
3089 GdkWindow *gdk_window;
3091 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3093 if (GDK_IS_X11_WINDOW (gdk_window))
3094 gdk_x11_window_set_hide_titlebar_when_maximized (gdk_window, setting);
3098 window->priv->hide_titlebar_when_maximized = setting;
3099 g_object_notify (G_OBJECT (window), "hide-titlebar-when-maximized");
3103 * gtk_window_get_hide_titlebar_when_maximized:
3104 * @window: a #GtkWindow
3106 * Returns whether the window has requested to have its titlebar hidden
3107 * when maximized. See gtk_window_set_hide_titlebar_when_maximized ().
3109 * Return value: %TRUE if the window has requested to have its titlebar
3110 * hidden when maximized
3115 gtk_window_get_hide_titlebar_when_maximized (GtkWindow *window)
3117 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3119 return window->priv->hide_titlebar_when_maximized;
3122 static GtkWindowGeometryInfo*
3123 gtk_window_get_geometry_info (GtkWindow *window,
3126 GtkWindowPrivate *priv = window->priv;
3127 GtkWindowGeometryInfo *info;
3129 info = priv->geometry_info;
3130 if (!info && create)
3132 info = g_new0 (GtkWindowGeometryInfo, 1);
3134 info->default_width = -1;
3135 info->default_height = -1;
3136 info->resize_width = -1;
3137 info->resize_height = -1;
3138 info->initial_x = 0;
3139 info->initial_y = 0;
3140 info->initial_pos_set = FALSE;
3141 info->default_is_geometry = FALSE;
3142 info->position_constraints_changed = FALSE;
3143 info->last.configure_request.x = 0;
3144 info->last.configure_request.y = 0;
3145 info->last.configure_request.width = -1;
3146 info->last.configure_request.height = -1;
3147 info->widget = NULL;
3149 priv->geometry_info = info;
3156 * gtk_window_set_geometry_hints:
3157 * @window: a #GtkWindow
3158 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3159 * @geometry: (allow-none): struct containing geometry information or %NULL
3160 * @geom_mask: mask indicating which struct fields should be paid attention to
3162 * This function sets up hints about how a window can be resized by
3163 * the user. You can set a minimum and maximum size; allowed resize
3164 * increments (e.g. for xterm, you can only resize by the size of a
3165 * character); aspect ratios; and more. See the #GdkGeometry struct.
3169 gtk_window_set_geometry_hints (GtkWindow *window,
3170 GtkWidget *geometry_widget,
3171 GdkGeometry *geometry,
3172 GdkWindowHints geom_mask)
3174 GtkWindowGeometryInfo *info;
3176 g_return_if_fail (GTK_IS_WINDOW (window));
3177 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3179 info = gtk_window_get_geometry_info (window, TRUE);
3182 g_signal_handlers_disconnect_by_func (info->widget,
3183 gtk_widget_destroyed,
3186 info->widget = geometry_widget;
3188 g_signal_connect (geometry_widget, "destroy",
3189 G_CALLBACK (gtk_widget_destroyed),
3193 info->geometry = *geometry;
3195 /* We store gravity in priv->gravity not in the hints. */
3196 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3198 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3200 gtk_window_set_gravity (window, geometry->win_gravity);
3203 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3207 * gtk_window_set_decorated:
3208 * @window: a #GtkWindow
3209 * @setting: %TRUE to decorate the window
3211 * By default, windows are decorated with a title bar, resize
3212 * controls, etc. Some <link linkend="gtk-X11-arch">window
3213 * managers</link> allow GTK+ to disable these decorations, creating a
3214 * borderless window. If you set the decorated property to %FALSE
3215 * using this function, GTK+ will do its best to convince the window
3216 * manager not to decorate the window. Depending on the system, this
3217 * function may not have any effect when called on a window that is
3218 * already visible, so you should call it before calling gtk_widget_show().
3220 * On Windows, this function always works, since there's no window manager
3225 gtk_window_set_decorated (GtkWindow *window,
3228 GtkWindowPrivate *priv;
3229 GdkWindow *gdk_window;
3231 g_return_if_fail (GTK_IS_WINDOW (window));
3233 priv = window->priv;
3235 setting = setting != FALSE;
3237 if (setting == priv->decorated)
3240 priv->decorated = setting;
3242 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3245 if (priv->decorated)
3246 gdk_window_set_decorations (gdk_window,
3249 gdk_window_set_decorations (gdk_window,
3253 g_object_notify (G_OBJECT (window), "decorated");
3257 * gtk_window_get_decorated:
3258 * @window: a #GtkWindow
3260 * Returns whether the window has been set to have decorations
3261 * such as a title bar via gtk_window_set_decorated().
3263 * Return value: %TRUE if the window has been set to have decorations
3266 gtk_window_get_decorated (GtkWindow *window)
3268 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3270 return window->priv->decorated;
3274 * gtk_window_set_deletable:
3275 * @window: a #GtkWindow
3276 * @setting: %TRUE to decorate the window as deletable
3278 * By default, windows have a close button in the window frame. Some
3279 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3280 * disable this button. If you set the deletable property to %FALSE
3281 * using this function, GTK+ will do its best to convince the window
3282 * manager not to show a close button. Depending on the system, this
3283 * function may not have any effect when called on a window that is
3284 * already visible, so you should call it before calling gtk_window_show().
3286 * On Windows, this function always works, since there's no window manager
3292 gtk_window_set_deletable (GtkWindow *window,
3295 GtkWindowPrivate *priv;
3296 GdkWindow *gdk_window;
3298 g_return_if_fail (GTK_IS_WINDOW (window));
3300 priv = window->priv;
3302 setting = setting != FALSE;
3304 if (setting == priv->deletable)
3307 priv->deletable = setting;
3309 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3312 if (priv->deletable)
3313 gdk_window_set_functions (gdk_window,
3316 gdk_window_set_functions (gdk_window,
3317 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3320 g_object_notify (G_OBJECT (window), "deletable");
3324 * gtk_window_get_deletable:
3325 * @window: a #GtkWindow
3327 * Returns whether the window has been set to have a close button
3328 * via gtk_window_set_deletable().
3330 * Return value: %TRUE if the window has been set to have a close button
3335 gtk_window_get_deletable (GtkWindow *window)
3337 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3339 return window->priv->deletable;
3342 static GtkWindowIconInfo*
3343 get_icon_info (GtkWindow *window)
3345 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3349 free_icon_info (GtkWindowIconInfo *info)
3351 g_free (info->icon_name);
3352 g_slice_free (GtkWindowIconInfo, info);
3356 static GtkWindowIconInfo*
3357 ensure_icon_info (GtkWindow *window)
3359 GtkWindowIconInfo *info;
3361 info = get_icon_info (window);
3365 info = g_slice_new0 (GtkWindowIconInfo);
3366 g_object_set_qdata_full (G_OBJECT (window),
3367 quark_gtk_window_icon_info,
3369 (GDestroyNotify)free_icon_info);
3376 icon_list_from_theme (GtkWidget *widget,
3381 GtkIconTheme *icon_theme;
3386 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3388 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3391 for (i = 0; sizes[i]; i++)
3394 * We need an EWMH extension to handle scalable icons
3395 * by passing their name to the WM. For now just use a
3399 icon = gtk_icon_theme_load_icon (icon_theme, name,
3402 icon = gtk_icon_theme_load_icon (icon_theme, name,
3405 list = g_list_append (list, icon);
3415 gtk_window_realize_icon (GtkWindow *window)
3417 GtkWindowPrivate *priv = window->priv;
3419 GtkWindowIconInfo *info;
3420 GdkWindow *gdk_window;
3423 widget = GTK_WIDGET (window);
3424 gdk_window = gtk_widget_get_window (widget);
3426 g_return_if_fail (gdk_window != NULL);
3428 /* no point setting an icon on override-redirect */
3429 if (priv->type == GTK_WINDOW_POPUP)
3434 info = ensure_icon_info (window);
3439 info->using_default_icon = FALSE;
3440 info->using_parent_icon = FALSE;
3441 info->using_themed_icon = FALSE;
3443 icon_list = info->icon_list;
3445 /* Look up themed icon */
3446 if (icon_list == NULL && info->icon_name)
3448 icon_list = icon_list_from_theme (widget, info->icon_name);
3450 info->using_themed_icon = TRUE;
3453 /* Inherit from transient parent */
3454 if (icon_list == NULL && priv->transient_parent)
3456 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3458 info->using_parent_icon = TRUE;
3461 /* Inherit from default */
3462 if (icon_list == NULL)
3464 icon_list = default_icon_list;
3466 info->using_default_icon = TRUE;
3469 /* Look up themed icon */
3470 if (icon_list == NULL && default_icon_name)
3472 icon_list = icon_list_from_theme (widget, default_icon_name);
3473 info->using_default_icon = TRUE;
3474 info->using_themed_icon = TRUE;
3477 info->realized = TRUE;
3479 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3481 if (info->using_themed_icon)
3483 GtkIconTheme *icon_theme;
3485 g_list_free_full (icon_list, g_object_unref);
3487 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3488 g_signal_connect (icon_theme, "changed",
3489 G_CALLBACK (update_themed_icon), window);
3494 gtk_window_unrealize_icon (GtkWindow *window)
3496 GtkWindowIconInfo *info;
3498 info = get_icon_info (window);
3503 if (info->using_themed_icon)
3505 GtkIconTheme *icon_theme;
3507 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3509 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3512 /* We don't clear the properties on the window, just figure the
3513 * window is going away.
3516 info->realized = FALSE;
3521 * gtk_window_set_icon_list:
3522 * @window: a #GtkWindow
3523 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3525 * Sets up the icon representing a #GtkWindow. The icon is used when
3526 * the window is minimized (also known as iconified). Some window
3527 * managers or desktop environments may also place it in the window
3528 * frame, or display it in other contexts.
3530 * gtk_window_set_icon_list() allows you to pass in the same icon in
3531 * several hand-drawn sizes. The list should contain the natural sizes
3532 * your icon is available in; that is, don't scale the image before
3533 * passing it to GTK+. Scaling is postponed until the last minute,
3534 * when the desired final size is known, to allow best quality.
3536 * By passing several sizes, you may improve the final image quality
3537 * of the icon, by reducing or eliminating automatic image scaling.
3539 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3540 * larger images (64x64, 128x128) if you have them.
3542 * See also gtk_window_set_default_icon_list() to set the icon
3543 * for all windows in your application in one go.
3545 * Note that transient windows (those who have been set transient for another
3546 * window using gtk_window_set_transient_for()) will inherit their
3547 * icon from their transient parent. So there's no need to explicitly
3548 * set the icon on transient windows.
3551 gtk_window_set_icon_list (GtkWindow *window,
3554 GtkWindowIconInfo *info;
3556 g_return_if_fail (GTK_IS_WINDOW (window));
3558 info = ensure_icon_info (window);
3560 if (info->icon_list == list) /* check for NULL mostly */
3563 g_list_foreach (list,
3564 (GFunc) g_object_ref, NULL);
3566 g_list_free_full (info->icon_list, g_object_unref);
3568 info->icon_list = g_list_copy (list);
3570 g_object_notify (G_OBJECT (window), "icon");
3572 gtk_window_unrealize_icon (window);
3574 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3575 gtk_window_realize_icon (window);
3577 /* We could try to update our transient children, but I don't think
3578 * it's really worth it. If we did it, the best way would probably
3579 * be to have children connect to notify::icon-list
3584 * gtk_window_get_icon_list:
3585 * @window: a #GtkWindow
3587 * Retrieves the list of icons set by gtk_window_set_icon_list().
3588 * The list is copied, but the reference count on each
3589 * member won't be incremented.
3591 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3594 gtk_window_get_icon_list (GtkWindow *window)
3596 GtkWindowIconInfo *info;
3598 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3600 info = get_icon_info (window);
3603 return g_list_copy (info->icon_list);
3609 * gtk_window_set_icon:
3610 * @window: a #GtkWindow
3611 * @icon: (allow-none): icon image, or %NULL
3613 * Sets up the icon representing a #GtkWindow. This icon is used when
3614 * the window is minimized (also known as iconified). Some window
3615 * managers or desktop environments may also place it in the window
3616 * frame, or display it in other contexts.
3618 * The icon should be provided in whatever size it was naturally
3619 * drawn; that is, don't scale the image before passing it to
3620 * GTK+. Scaling is postponed until the last minute, when the desired
3621 * final size is known, to allow best quality.
3623 * If you have your icon hand-drawn in multiple sizes, use
3624 * gtk_window_set_icon_list(). Then the best size will be used.
3626 * This function is equivalent to calling gtk_window_set_icon_list()
3627 * with a 1-element list.
3629 * See also gtk_window_set_default_icon_list() to set the icon
3630 * for all windows in your application in one go.
3633 gtk_window_set_icon (GtkWindow *window,
3638 g_return_if_fail (GTK_IS_WINDOW (window));
3639 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3644 list = g_list_append (list, icon);
3646 gtk_window_set_icon_list (window, list);
3652 update_themed_icon (GtkIconTheme *icon_theme,
3655 g_object_notify (G_OBJECT (window), "icon");
3657 gtk_window_unrealize_icon (window);
3659 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3660 gtk_window_realize_icon (window);
3664 * gtk_window_set_icon_name:
3665 * @window: a #GtkWindow
3666 * @name: (allow-none): the name of the themed icon
3668 * Sets the icon for the window from a named themed icon. See
3669 * the docs for #GtkIconTheme for more details.
3671 * Note that this has nothing to do with the WM_ICON_NAME
3672 * property which is mentioned in the ICCCM.
3677 gtk_window_set_icon_name (GtkWindow *window,
3680 GtkWindowIconInfo *info;
3683 g_return_if_fail (GTK_IS_WINDOW (window));
3685 info = ensure_icon_info (window);
3687 if (g_strcmp0 (info->icon_name, name) == 0)
3690 tmp = info->icon_name;
3691 info->icon_name = g_strdup (name);
3694 g_list_free_full (info->icon_list, g_object_unref);
3695 info->icon_list = NULL;
3697 update_themed_icon (NULL, window);
3699 g_object_notify (G_OBJECT (window), "icon-name");
3703 * gtk_window_get_icon_name:
3704 * @window: a #GtkWindow
3706 * Returns the name of the themed icon for the window,
3707 * see gtk_window_set_icon_name().
3709 * Returns: the icon name or %NULL if the window has
3715 gtk_window_get_icon_name (GtkWindow *window)
3717 GtkWindowIconInfo *info;
3719 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3721 info = ensure_icon_info (window);
3723 return info->icon_name;
3727 * gtk_window_get_icon:
3728 * @window: a #GtkWindow
3730 * Gets the value set by gtk_window_set_icon() (or if you've
3731 * called gtk_window_set_icon_list(), gets the first icon in
3734 * Return value: (transfer none): icon for window
3737 gtk_window_get_icon (GtkWindow *window)
3739 GtkWindowIconInfo *info;
3741 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3743 info = get_icon_info (window);
3744 if (info && info->icon_list)
3745 return GDK_PIXBUF (info->icon_list->data);
3750 /* Load pixbuf, printing warning on failure if error == NULL
3753 load_pixbuf_verbosely (const char *filename,
3756 GError *local_err = NULL;
3759 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3767 g_warning ("Error loading icon from file '%s':\n\t%s",
3768 filename, local_err->message);
3769 g_error_free (local_err);
3777 * gtk_window_set_icon_from_file:
3778 * @window: a #GtkWindow
3779 * @filename: (type filename): location of icon file
3780 * @err: (allow-none): location to store error, or %NULL.
3782 * Sets the icon for @window.
3783 * Warns on failure if @err is %NULL.
3785 * This function is equivalent to calling gtk_window_set_icon()
3786 * with a pixbuf created by loading the image from @filename.
3788 * Returns: %TRUE if setting the icon succeeded.
3793 gtk_window_set_icon_from_file (GtkWindow *window,
3794 const gchar *filename,
3797 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3801 gtk_window_set_icon (window, pixbuf);
3802 g_object_unref (pixbuf);
3811 * gtk_window_set_default_icon_list:
3812 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3814 * Sets an icon list to be used as fallback for windows that haven't
3815 * had gtk_window_set_icon_list() called on them to set up a
3816 * window-specific icon list. This function allows you to set up the
3817 * icon for all windows in your app at once.
3819 * See gtk_window_set_icon_list() for more details.
3823 gtk_window_set_default_icon_list (GList *list)
3827 if (list == default_icon_list)
3830 /* Update serial so we don't used cached pixmaps/masks
3832 default_icon_serial++;
3834 g_list_foreach (list,
3835 (GFunc) g_object_ref, NULL);
3837 g_list_free_full (default_icon_list, g_object_unref);
3839 default_icon_list = g_list_copy (list);
3841 /* Update all toplevels */
3842 toplevels = gtk_window_list_toplevels ();
3843 tmp_list = toplevels;
3844 while (tmp_list != NULL)
3846 GtkWindowIconInfo *info;
3847 GtkWindow *w = tmp_list->data;
3849 info = get_icon_info (w);
3850 if (info && info->using_default_icon)
3852 gtk_window_unrealize_icon (w);
3853 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3854 gtk_window_realize_icon (w);
3857 tmp_list = tmp_list->next;
3859 g_list_free (toplevels);
3863 * gtk_window_set_default_icon:
3866 * Sets an icon to be used as fallback for windows that haven't
3867 * had gtk_window_set_icon() called on them from a pixbuf.
3872 gtk_window_set_default_icon (GdkPixbuf *icon)
3876 g_return_if_fail (GDK_IS_PIXBUF (icon));
3878 list = g_list_prepend (NULL, icon);
3879 gtk_window_set_default_icon_list (list);
3884 * gtk_window_set_default_icon_name:
3885 * @name: the name of the themed icon
3887 * Sets an icon to be used as fallback for windows that haven't
3888 * had gtk_window_set_icon_list() called on them from a named
3889 * themed icon, see gtk_window_set_icon_name().
3894 gtk_window_set_default_icon_name (const gchar *name)
3899 /* Update serial so we don't used cached pixmaps/masks
3901 default_icon_serial++;
3903 g_free (default_icon_name);
3904 default_icon_name = g_strdup (name);
3906 g_list_free_full (default_icon_list, g_object_unref);
3907 default_icon_list = NULL;
3909 /* Update all toplevels */
3910 toplevels = gtk_window_list_toplevels ();
3911 tmp_list = toplevels;
3912 while (tmp_list != NULL)
3914 GtkWindowIconInfo *info;
3915 GtkWindow *w = tmp_list->data;
3917 info = get_icon_info (w);
3918 if (info && info->using_default_icon && info->using_themed_icon)
3920 gtk_window_unrealize_icon (w);
3921 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3922 gtk_window_realize_icon (w);
3925 tmp_list = tmp_list->next;
3927 g_list_free (toplevels);
3931 * gtk_window_get_default_icon_name:
3933 * Returns the fallback icon name for windows that has been set
3934 * with gtk_window_set_default_icon_name(). The returned
3935 * string is owned by GTK+ and should not be modified. It
3936 * is only valid until the next call to
3937 * gtk_window_set_default_icon_name().
3939 * Returns: the fallback icon name for windows
3944 gtk_window_get_default_icon_name (void)
3946 return default_icon_name;
3950 * gtk_window_set_default_icon_from_file:
3951 * @filename: (type filename): location of icon file
3952 * @err: (allow-none): location to store error, or %NULL.
3954 * Sets an icon to be used as fallback for windows that haven't
3955 * had gtk_window_set_icon_list() called on them from a file
3956 * on disk. Warns on failure if @err is %NULL.
3958 * Returns: %TRUE if setting the icon succeeded.
3963 gtk_window_set_default_icon_from_file (const gchar *filename,
3966 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3970 gtk_window_set_default_icon (pixbuf);
3971 g_object_unref (pixbuf);
3980 * gtk_window_get_default_icon_list:
3982 * Gets the value set by gtk_window_set_default_icon_list().
3983 * The list is a copy and should be freed with g_list_free(),
3984 * but the pixbufs in the list have not had their reference count
3987 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3990 gtk_window_get_default_icon_list (void)
3992 return g_list_copy (default_icon_list);
3996 gtk_window_set_default_size_internal (GtkWindow *window,
3997 gboolean change_width,
3999 gboolean change_height,
4001 gboolean is_geometry)
4003 GtkWindowGeometryInfo *info;
4005 g_return_if_fail (change_width == FALSE || width >= -1);
4006 g_return_if_fail (change_height == FALSE || height >= -1);
4008 info = gtk_window_get_geometry_info (window, TRUE);
4010 g_object_freeze_notify (G_OBJECT (window));
4012 info->default_is_geometry = is_geometry != FALSE;
4022 info->default_width = width;
4024 g_object_notify (G_OBJECT (window), "default-width");
4035 info->default_height = height;
4037 g_object_notify (G_OBJECT (window), "default-height");
4040 g_object_thaw_notify (G_OBJECT (window));
4042 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4046 * gtk_window_set_default_size:
4047 * @window: a #GtkWindow
4048 * @width: width in pixels, or -1 to unset the default width
4049 * @height: height in pixels, or -1 to unset the default height
4051 * Sets the default size of a window. If the window's "natural" size
4052 * (its size request) is larger than the default, the default will be
4053 * ignored. More generally, if the default size does not obey the
4054 * geometry hints for the window (gtk_window_set_geometry_hints() can
4055 * be used to set these explicitly), the default size will be clamped
4056 * to the nearest permitted size.
4058 * Unlike gtk_widget_set_size_request(), which sets a size request for
4059 * a widget and thus would keep users from shrinking the window, this
4060 * function only sets the initial size, just as if the user had
4061 * resized the window themselves. Users can still shrink the window
4062 * again as they normally would. Setting a default size of -1 means to
4063 * use the "natural" default size (the size request of the window).
4065 * For more control over a window's initial size and how resizing works,
4066 * investigate gtk_window_set_geometry_hints().
4068 * For some uses, gtk_window_resize() is a more appropriate function.
4069 * gtk_window_resize() changes the current size of the window, rather
4070 * than the size to be used on initial display. gtk_window_resize() always
4071 * affects the window itself, not the geometry widget.
4073 * The default size of a window only affects the first time a window is
4074 * shown; if a window is hidden and re-shown, it will remember the size
4075 * it had prior to hiding, rather than using the default size.
4077 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4078 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4081 gtk_window_set_default_size (GtkWindow *window,
4085 g_return_if_fail (GTK_IS_WINDOW (window));
4086 g_return_if_fail (width >= -1);
4087 g_return_if_fail (height >= -1);
4089 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4093 * gtk_window_set_default_geometry:
4094 * @window: a #GtkWindow
4095 * @width: width in resize increments, or -1 to unset the default width
4096 * @height: height in resize increments, or -1 to unset the default height
4098 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4099 * in terms of the base size and increment set with
4100 * gtk_window_set_geometry_hints.
4105 gtk_window_set_default_geometry (GtkWindow *window,
4109 g_return_if_fail (GTK_IS_WINDOW (window));
4110 g_return_if_fail (width >= -1);
4111 g_return_if_fail (height >= -1);
4113 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4117 * gtk_window_get_default_size:
4118 * @window: a #GtkWindow
4119 * @width: (out) (allow-none): location to store the default width, or %NULL
4120 * @height: (out) (allow-none): location to store the default height, or %NULL
4122 * Gets the default size of the window. A value of -1 for the width or
4123 * height indicates that a default size has not been explicitly set
4124 * for that dimension, so the "natural" size of the window will be
4129 gtk_window_get_default_size (GtkWindow *window,
4133 GtkWindowGeometryInfo *info;
4135 g_return_if_fail (GTK_IS_WINDOW (window));
4137 info = gtk_window_get_geometry_info (window, FALSE);
4140 *width = info ? info->default_width : -1;
4143 *height = info ? info->default_height : -1;
4147 * gtk_window_resize:
4148 * @window: a #GtkWindow
4149 * @width: width in pixels to resize the window to
4150 * @height: height in pixels to resize the window to
4152 * Resizes the window as if the user had done so, obeying geometry
4153 * constraints. The default geometry constraint is that windows may
4154 * not be smaller than their size request; to override this
4155 * constraint, call gtk_widget_set_size_request() to set the window's
4156 * request to a smaller value.
4158 * If gtk_window_resize() is called before showing a window for the
4159 * first time, it overrides any default size set with
4160 * gtk_window_set_default_size().
4162 * Windows may not be resized smaller than 1 by 1 pixels.
4166 gtk_window_resize (GtkWindow *window,
4170 GtkWindowGeometryInfo *info;
4172 g_return_if_fail (GTK_IS_WINDOW (window));
4173 g_return_if_fail (width > 0);
4174 g_return_if_fail (height > 0);
4176 info = gtk_window_get_geometry_info (window, TRUE);
4178 info->resize_width = width;
4179 info->resize_height = height;
4180 info->resize_is_geometry = FALSE;
4182 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4186 * gtk_window_resize_to_geometry:
4187 * @window: a #GtkWindow
4188 * @width: width in resize increments to resize the window to
4189 * @height: height in resize increments to resize the window to
4191 * Like gtk_window_resize(), but @width and @height are interpreted
4192 * in terms of the base size and increment set with
4193 * gtk_window_set_geometry_hints.
4198 gtk_window_resize_to_geometry (GtkWindow *window,
4202 GtkWindowGeometryInfo *info;
4204 g_return_if_fail (GTK_IS_WINDOW (window));
4205 g_return_if_fail (width > 0);
4206 g_return_if_fail (height > 0);
4208 info = gtk_window_get_geometry_info (window, TRUE);
4210 info->resize_width = width;
4211 info->resize_height = height;
4212 info->resize_is_geometry = TRUE;
4214 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4218 * gtk_window_get_size:
4219 * @window: a #GtkWindow
4220 * @width: (out) (allow-none): return location for width, or %NULL
4221 * @height: (out) (allow-none): return location for height, or %NULL
4223 * Obtains the current size of @window. If @window is not onscreen,
4224 * it returns the size GTK+ will suggest to the <link
4225 * linkend="gtk-X11-arch">window manager</link> for the initial window
4226 * size (but this is not reliably the same as the size the window
4227 * manager will actually select). The size obtained by
4228 * gtk_window_get_size() is the last size received in a
4229 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4230 * rather than querying the X server for the size. As a result, if you
4231 * call gtk_window_resize() then immediately call
4232 * gtk_window_get_size(), the size won't have taken effect yet. After
4233 * the window manager processes the resize request, GTK+ receives
4234 * notification that the size has changed via a configure event, and
4235 * the size of the window gets updated.
4237 * Note 1: Nearly any use of this function creates a race condition,
4238 * because the size of the window may change between the time that you
4239 * get the size and the time that you perform some action assuming
4240 * that size is the current size. To avoid race conditions, connect to
4241 * "configure-event" on the window and adjust your size-dependent
4242 * state to match the size delivered in the #GdkEventConfigure.
4244 * Note 2: The returned size does <emphasis>not</emphasis> include the
4245 * size of the window manager decorations (aka the window frame or
4246 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4247 * method of determining their size.
4249 * Note 3: If you are getting a window size in order to position
4250 * the window onscreen, there may be a better way. The preferred
4251 * way is to simply set the window's semantic type with
4252 * gtk_window_set_type_hint(), which allows the window manager to
4253 * e.g. center dialogs. Also, if you set the transient parent of
4254 * dialogs with gtk_window_set_transient_for() window managers
4255 * will often center the dialog over its parent window. It's
4256 * much preferred to let the window manager handle these
4257 * things rather than doing it yourself, because all apps will
4258 * behave consistently and according to user prefs if the window
4259 * manager handles it. Also, the window manager can take the size
4260 * of the window decorations/border into account, while your
4261 * application cannot.
4263 * In any case, if you insist on application-specified window
4264 * positioning, there's <emphasis>still</emphasis> a better way than
4265 * doing it yourself - gtk_window_set_position() will frequently
4266 * handle the details for you.
4270 gtk_window_get_size (GtkWindow *window,
4276 g_return_if_fail (GTK_IS_WINDOW (window));
4278 if (width == NULL && height == NULL)
4281 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4283 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4284 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4288 GdkRectangle configure_request;
4290 gtk_window_compute_configure_request (window,
4294 w = configure_request.width;
4295 h = configure_request.height;
4306 * @window: a #GtkWindow
4307 * @x: X coordinate to move window to
4308 * @y: Y coordinate to move window to
4310 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4311 * @window to the given position. Window managers are free to ignore
4312 * this; most window managers ignore requests for initial window
4313 * positions (instead using a user-defined placement algorithm) and
4314 * honor requests after the window has already been shown.
4316 * Note: the position is the position of the gravity-determined
4317 * reference point for the window. The gravity determines two things:
4318 * first, the location of the reference point in root window
4319 * coordinates; and second, which point on the window is positioned at
4320 * the reference point.
4322 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4323 * point is simply the @x, @y supplied to gtk_window_move(). The
4324 * top-left corner of the window decorations (aka window frame or
4325 * border) will be placed at @x, @y. Therefore, to position a window
4326 * at the top left of the screen, you want to use the default gravity
4327 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4329 * To position a window at the bottom right corner of the screen, you
4330 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4331 * point is at @x + the window width and @y + the window height, and
4332 * the bottom-right corner of the window border will be placed at that
4333 * reference point. So, to place a window in the bottom right corner
4334 * you would first set gravity to south east, then write:
4335 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4336 * gdk_screen_height () - window_height)</literal> (note that this
4337 * example does not take multi-head scenarios into account).
4339 * The Extended Window Manager Hints specification at <ulink
4340 * url="http://www.freedesktop.org/Standards/wm-spec">
4341 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4342 * nice table of gravities in the "implementation notes" section.
4344 * The gtk_window_get_position() documentation may also be relevant.
4347 gtk_window_move (GtkWindow *window,
4351 GtkWindowGeometryInfo *info;
4354 g_return_if_fail (GTK_IS_WINDOW (window));
4356 widget = GTK_WIDGET (window);
4358 info = gtk_window_get_geometry_info (window, TRUE);
4360 if (gtk_widget_get_mapped (widget))
4362 GtkAllocation allocation;
4364 gtk_widget_get_allocation (widget, &allocation);
4366 /* we have now sent a request with this position
4367 * with currently-active constraints, so toggle flag.
4369 info->position_constraints_changed = FALSE;
4371 /* we only constrain if mapped - if not mapped,
4372 * then gtk_window_compute_configure_request()
4373 * will apply the constraints later, and we
4374 * don't want to lose information about
4375 * what position the user set before then.
4376 * i.e. if you do a move() then turn off POS_CENTER
4377 * then show the window, your move() will work.
4379 gtk_window_constrain_position (window,
4380 allocation.width, allocation.height,
4383 /* Note that this request doesn't go through our standard request
4384 * framework, e.g. doesn't increment configure_request_count,
4385 * doesn't set info->last, etc.; that's because
4386 * we don't save the info needed to arrive at this same request
4389 * To gtk_window_move_resize(), this will end up looking exactly
4390 * the same as the position being changed by the window
4393 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4397 /* Save this position to apply on mapping */
4398 info->initial_x = x;
4399 info->initial_y = y;
4400 info->initial_pos_set = TRUE;
4405 * gtk_window_get_position:
4406 * @window: a #GtkWindow
4407 * @root_x: (out) (allow-none): eturn location for X coordinate of
4408 * gravity-determined reference point, or %NULL
4409 * @root_y: (out) (allow-none): return location for Y coordinate of
4410 * gravity-determined reference point, or %NULL
4412 * This function returns the position you need to pass to
4413 * gtk_window_move() to keep @window in its current position.
4414 * This means that the meaning of the returned value varies with
4415 * window gravity. See gtk_window_move() for more details.
4417 * If you haven't changed the window gravity, its gravity will be
4418 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4419 * gets the position of the top-left corner of the window manager
4420 * frame for the window. gtk_window_move() sets the position of this
4421 * same top-left corner.
4423 * gtk_window_get_position() is not 100% reliable because the X Window System
4424 * does not specify a way to obtain the geometry of the
4425 * decorations placed on a window by the window manager.
4426 * Thus GTK+ is using a "best guess" that works with most
4429 * Moreover, nearly all window managers are historically broken with
4430 * respect to their handling of window gravity. So moving a window to
4431 * its current position as returned by gtk_window_get_position() tends
4432 * to result in moving the window slightly. Window managers are
4433 * slowly getting better over time.
4435 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4436 * frame is not relevant, and thus gtk_window_get_position() will
4437 * always produce accurate results. However you can't use static
4438 * gravity to do things like place a window in a corner of the screen,
4439 * because static gravity ignores the window manager decorations.
4441 * If you are saving and restoring your application's window
4442 * positions, you should know that it's impossible for applications to
4443 * do this without getting it somewhat wrong because applications do
4444 * not have sufficient knowledge of window manager state. The Correct
4445 * Mechanism is to support the session management protocol (see the
4446 * "GnomeClient" object in the GNOME libraries for example) and allow
4447 * the window manager to save your window sizes and positions.
4452 gtk_window_get_position (GtkWindow *window,
4456 GtkWindowPrivate *priv;
4458 GdkWindow *gdk_window;
4460 g_return_if_fail (GTK_IS_WINDOW (window));
4462 priv = window->priv;
4463 widget = GTK_WIDGET (window);
4464 gdk_window = gtk_widget_get_window (widget);
4466 if (priv->gravity == GDK_GRAVITY_STATIC)
4468 if (gtk_widget_get_mapped (widget))
4470 /* This does a server round-trip, which is sort of wrong;
4471 * but a server round-trip is inevitable for
4472 * gdk_window_get_frame_extents() in the usual
4473 * NorthWestGravity case below, so not sure what else to
4474 * do. We should likely be consistent about whether we get
4475 * the client-side info or the server-side info.
4477 gdk_window_get_origin (gdk_window, root_x, root_y);
4481 GdkRectangle configure_request;
4483 gtk_window_compute_configure_request (window,
4487 *root_x = configure_request.x;
4488 *root_y = configure_request.y;
4493 GdkRectangle frame_extents;
4498 if (gtk_widget_get_mapped (widget))
4500 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4501 x = frame_extents.x;
4502 y = frame_extents.y;
4503 gtk_window_get_size (window, &w, &h);
4507 /* We just say the frame has 0 size on all sides.
4508 * Not sure what else to do.
4510 gtk_window_compute_configure_request (window,
4513 x = frame_extents.x;
4514 y = frame_extents.y;
4515 w = frame_extents.width;
4516 h = frame_extents.height;
4519 switch (priv->gravity)
4521 case GDK_GRAVITY_NORTH:
4522 case GDK_GRAVITY_CENTER:
4523 case GDK_GRAVITY_SOUTH:
4524 /* Find center of frame. */
4525 x += frame_extents.width / 2;
4526 /* Center client window on that point. */
4530 case GDK_GRAVITY_SOUTH_EAST:
4531 case GDK_GRAVITY_EAST:
4532 case GDK_GRAVITY_NORTH_EAST:
4533 /* Find right edge of frame */
4534 x += frame_extents.width;
4535 /* Align left edge of client at that point. */
4542 switch (priv->gravity)
4544 case GDK_GRAVITY_WEST:
4545 case GDK_GRAVITY_CENTER:
4546 case GDK_GRAVITY_EAST:
4547 /* Find center of frame. */
4548 y += frame_extents.height / 2;
4549 /* Center client window there. */
4552 case GDK_GRAVITY_SOUTH_WEST:
4553 case GDK_GRAVITY_SOUTH:
4554 case GDK_GRAVITY_SOUTH_EAST:
4555 /* Find south edge of frame */
4556 y += frame_extents.height;
4557 /* Place bottom edge of client there */
4572 * gtk_window_reshow_with_initial_size:
4573 * @window: a #GtkWindow
4575 * Hides @window, then reshows it, resetting the
4576 * default size and position of the window. Used
4577 * by GUI builders only.
4580 gtk_window_reshow_with_initial_size (GtkWindow *window)
4584 g_return_if_fail (GTK_IS_WINDOW (window));
4586 widget = GTK_WIDGET (window);
4588 gtk_widget_hide (widget);
4589 gtk_widget_unrealize (widget);
4590 gtk_widget_show (widget);
4594 gtk_window_destroy (GtkWidget *widget)
4596 GtkWindow *window = GTK_WINDOW (widget);
4597 GtkWindowPrivate *priv = window->priv;
4599 gtk_window_release_application (window);
4601 toplevel_list = g_slist_remove (toplevel_list, window);
4603 if (priv->transient_parent)
4604 gtk_window_set_transient_for (window, NULL);
4606 /* frees the icons */
4607 gtk_window_set_icon_list (window, NULL);
4609 if (priv->has_user_ref_count)
4611 priv->has_user_ref_count = FALSE;
4612 g_object_unref (window);
4616 gtk_window_group_remove_window (priv->group, window);
4618 gtk_window_free_key_hash (window);
4620 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4624 gtk_window_finalize (GObject *object)
4626 GtkWindow *window = GTK_WINDOW (object);
4627 GtkWindowPrivate *priv = window->priv;
4628 GtkMnemonicHash *mnemonic_hash;
4630 g_free (priv->title);
4631 g_free (priv->wmclass_name);
4632 g_free (priv->wmclass_class);
4633 g_free (priv->wm_role);
4634 gtk_window_release_application (window);
4636 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4638 _gtk_mnemonic_hash_free (mnemonic_hash);
4640 if (priv->geometry_info)
4642 if (priv->geometry_info->widget)
4643 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4644 gtk_widget_destroyed,
4645 &priv->geometry_info->widget);
4646 g_free (priv->geometry_info);
4649 if (priv->keys_changed_handler)
4651 g_source_remove (priv->keys_changed_handler);
4652 priv->keys_changed_handler = 0;
4656 g_signal_handlers_disconnect_by_func (priv->screen,
4657 gtk_window_on_composited_changed, window);
4659 g_free (priv->startup_id);
4661 #ifdef GDK_WINDOWING_X11
4662 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4663 gtk_window_on_theme_variant_changed,
4667 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4671 gtk_window_show (GtkWidget *widget)
4673 GtkWindow *window = GTK_WINDOW (widget);
4674 GtkWindowPrivate *priv = window->priv;
4675 GtkContainer *container = GTK_CONTAINER (window);
4676 gboolean need_resize;
4679 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4681 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4685 _gtk_widget_set_visible_flag (widget, TRUE);
4687 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4688 _gtk_container_set_need_resize (container, FALSE);
4692 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4693 GtkAllocation allocation = { 0, 0 };
4694 GdkRectangle configure_request;
4695 GdkGeometry new_geometry;
4697 gboolean was_realized;
4699 /* We are going to go ahead and perform this configure request
4700 * and then emulate a configure notify by going ahead and
4701 * doing a size allocate. Sort of a synchronous
4702 * mini-copy of gtk_window_move_resize() here.
4704 gtk_window_compute_configure_request (window,
4709 /* We update this because we are going to go ahead
4710 * and gdk_window_resize() below, rather than
4713 info->last.configure_request.width = configure_request.width;
4714 info->last.configure_request.height = configure_request.height;
4716 /* and allocate the window - this is normally done
4717 * in move_resize in response to configure notify
4719 allocation.width = configure_request.width;
4720 allocation.height = configure_request.height;
4721 gtk_widget_size_allocate (widget, &allocation);
4723 /* Then we guarantee we have a realize */
4724 was_realized = FALSE;
4725 if (!gtk_widget_get_realized (widget))
4727 gtk_widget_realize (widget);
4728 was_realized = TRUE;
4731 /* We only send configure request if we didn't just finish
4732 * creating the window; if we just created the window
4733 * then we created it with widget->allocation anyhow.
4736 gdk_window_move_resize (gtk_widget_get_window (widget),
4737 configure_request.x,
4738 configure_request.y,
4739 configure_request.width,
4740 configure_request.height);
4743 gtk_container_check_resize (container);
4745 gtk_widget_map (widget);
4747 /* Try to make sure that we have some focused widget
4749 #ifdef GDK_WINDOWING_X11
4750 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4751 GTK_IS_PLUG (window);
4755 if (!priv->focus_widget && !is_plug)
4756 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4759 gtk_grab_add (widget);
4763 gtk_window_hide (GtkWidget *widget)
4765 GtkWindow *window = GTK_WINDOW (widget);
4766 GtkWindowPrivate *priv = window->priv;
4768 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4770 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4774 _gtk_widget_set_visible_flag (widget, FALSE);
4775 gtk_widget_unmap (widget);
4778 gtk_grab_remove (widget);
4782 gtk_window_map (GtkWidget *widget)
4785 GtkWindow *window = GTK_WINDOW (widget);
4786 GtkWindowPrivate *priv = window->priv;
4787 GdkWindow *gdk_window;
4788 gboolean auto_mnemonics;
4789 GtkPolicyType visible_focus;
4791 if (!gtk_widget_is_toplevel (widget))
4793 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4797 gtk_widget_set_mapped (widget, TRUE);
4799 child = gtk_bin_get_child (&(window->bin));
4801 gtk_widget_get_visible (child) &&
4802 !gtk_widget_get_mapped (child))
4803 gtk_widget_map (child);
4805 gdk_window = gtk_widget_get_window (widget);
4807 if (priv->maximize_initially)
4808 gdk_window_maximize (gdk_window);
4810 gdk_window_unmaximize (gdk_window);
4812 if (priv->stick_initially)
4813 gdk_window_stick (gdk_window);
4815 gdk_window_unstick (gdk_window);
4817 if (priv->iconify_initially)
4818 gdk_window_iconify (gdk_window);
4820 gdk_window_deiconify (gdk_window);
4822 if (priv->fullscreen_initially)
4823 gdk_window_fullscreen (gdk_window);
4825 gdk_window_unfullscreen (gdk_window);
4827 gdk_window_set_keep_above (gdk_window, priv->above_initially);
4829 gdk_window_set_keep_below (gdk_window, priv->below_initially);
4831 if (priv->type == GTK_WINDOW_TOPLEVEL)
4833 gtk_window_set_theme_variant (window);
4834 gtk_window_set_hide_titlebar_when_maximized (window,
4835 priv->hide_titlebar_when_maximized);
4838 /* No longer use the default settings */
4839 priv->need_default_size = FALSE;
4840 priv->need_default_position = FALSE;
4842 if (priv->reset_type_hint)
4844 /* We should only reset the type hint when the application
4845 * used gtk_window_set_type_hint() to change the hint.
4846 * Some applications use X directly to change the properties;
4847 * in that case, we shouldn't overwrite what they did.
4849 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4850 priv->reset_type_hint = FALSE;
4853 gdk_window_show (gdk_window);
4855 if (priv->grip_window)
4856 gdk_window_show (priv->grip_window);
4858 if (!disable_startup_notification)
4860 /* Do we have a custom startup-notification id? */
4861 if (priv->startup_id != NULL)
4863 /* Make sure we have a "real" id */
4864 if (!startup_id_is_fake (priv->startup_id))
4865 gdk_notify_startup_complete_with_id (priv->startup_id);
4867 g_free (priv->startup_id);
4868 priv->startup_id = NULL;
4870 else if (!sent_startup_notification)
4872 sent_startup_notification = TRUE;
4873 gdk_notify_startup_complete ();
4877 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4878 * (as in the case of popup menus), then hide mnemonics initially
4880 g_object_get (gtk_widget_get_settings (widget),
4881 "gtk-auto-mnemonics", &auto_mnemonics,
4882 "gtk-visible-focus", &visible_focus,
4885 if (auto_mnemonics && !priv->mnemonics_visible_set)
4886 gtk_window_set_mnemonics_visible (window, FALSE);
4888 /* inherit from transient parent, so that a dialog that is
4889 * opened via keynav shows focus initially
4891 if (priv->transient_parent)
4892 gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
4894 gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
4896 ensure_state_flag_window_unfocused (widget);
4900 gtk_window_map_event (GtkWidget *widget,
4903 if (!gtk_widget_get_mapped (widget))
4905 /* we should be be unmapped, but are getting a MapEvent, this may happen
4906 * to toplevel XWindows if mapping was intercepted by a window manager
4907 * and an unmap request occoured while the MapRequestEvent was still
4908 * being handled. we work around this situaiton here by re-requesting
4909 * the window being unmapped. more details can be found in:
4910 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4912 gdk_window_hide (gtk_widget_get_window (widget));
4918 gtk_window_unmap (GtkWidget *widget)
4920 GtkWindow *window = GTK_WINDOW (widget);
4921 GtkWindowPrivate *priv = window->priv;
4923 GtkWindowGeometryInfo *info;
4924 GdkWindow *gdk_window;
4925 GdkWindowState state;
4927 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4929 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
4933 gdk_window = gtk_widget_get_window (widget);
4935 gtk_widget_set_mapped (widget, FALSE);
4936 gdk_window_withdraw (gdk_window);
4938 priv->configure_request_count = 0;
4939 priv->configure_notify_received = FALSE;
4941 /* on unmap, we reset the default positioning of the window,
4942 * so it's placed again, but we don't reset the default
4943 * size of the window, so it's remembered.
4945 priv->need_default_position = TRUE;
4947 info = gtk_window_get_geometry_info (window, FALSE);
4950 info->initial_pos_set = FALSE;
4951 info->position_constraints_changed = FALSE;
4954 state = gdk_window_get_state (gdk_window);
4955 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4956 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4957 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4958 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4959 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4961 child = gtk_bin_get_child (&(window->bin));
4963 gtk_widget_unmap (child);
4966 /* (Note: Replace "size" with "width" or "height". Also, the request
4967 * mode is honoured.)
4968 * For selecting the default window size, the following conditions
4969 * should hold (in order of importance):
4970 * - the size is not below the minimum size
4971 * Windows cannot be resized below their minimum size, so we must
4972 * ensure we don't do that either.
4973 * - the size is not above the natural size
4974 * It seems weird to allocate more than this in an initial guess.
4975 * - the size does not exceed that of a maximized window
4976 * We want to see the whole window after all.
4977 * (Note that this may not be possible to achieve due to imperfect
4978 * information from the windowing system.)
4981 /* We use these for now to not make windows too big by accident. Note
4982 * that we still clamp these numbers by screen size. Also note that
4983 * minimum size still overrides this. So keep your windows small! :)
4985 #define MAX_DEFAULT_WINDOW_WIDTH 640
4986 #define MAX_DEFAULT_WINDOW_HEIGHT 480
4989 gtk_window_guess_default_size (GtkWindow *window,
4993 GtkWidget *widget = GTK_WIDGET (window);
4995 int minimum, natural;
4997 screen = gtk_widget_get_screen (widget);
4999 *width = gdk_screen_get_width (screen);
5000 *height = gdk_screen_get_height (screen);
5002 if (*width >= *height)
5005 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
5006 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
5011 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
5012 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
5015 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
5017 gtk_widget_get_preferred_height (widget, &minimum, &natural);
5018 *height = MAX (minimum, MIN (*height, natural));
5020 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
5021 *width = MAX (minimum, MIN (*width, natural));
5023 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
5025 gtk_widget_get_preferred_width (widget, &minimum, &natural);
5026 *width = MAX (minimum, MIN (*width, natural));
5028 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
5029 *height = MAX (minimum, MIN (*height, natural));
5034 gtk_window_realize (GtkWidget *widget)
5036 GtkAllocation allocation;
5038 GdkWindow *parent_window;
5039 GdkWindow *gdk_window;
5040 GdkWindowAttr attributes;
5041 gint attributes_mask;
5042 GtkWindowPrivate *priv;
5043 GtkStyleContext *context;
5045 window = GTK_WINDOW (widget);
5046 priv = window->priv;
5048 gtk_widget_get_allocation (widget, &allocation);
5050 if (gtk_widget_get_parent_window (widget))
5052 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
5054 gtk_widget_set_realized (widget, TRUE);
5056 attributes.x = allocation.x;
5057 attributes.y = allocation.y;
5058 attributes.width = allocation.width;
5059 attributes.height = allocation.height;
5060 attributes.window_type = GDK_WINDOW_CHILD;
5062 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
5064 attributes.visual = gtk_widget_get_visual (widget);
5065 attributes.wclass = GDK_INPUT_OUTPUT;
5067 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
5069 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
5070 &attributes, attributes_mask);
5071 gtk_widget_set_window (widget, gdk_window);
5072 gdk_window_set_user_data (gdk_window, widget);
5074 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
5076 gdk_window_enable_synchronized_configure (gdk_window);
5080 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5082 /* ensure widget tree is properly size allocated */
5083 if (allocation.x == -1 &&
5084 allocation.y == -1 &&
5085 allocation.width == 1 &&
5086 allocation.height == 1)
5092 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5093 if (allocation.width == 0 || allocation.height == 0)
5095 /* non-empty window */
5096 allocation.width = 200;
5097 allocation.height = 200;
5099 gtk_widget_size_allocate (widget, &allocation);
5101 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5103 g_return_if_fail (!gtk_widget_get_realized (widget));
5106 gtk_widget_set_realized (widget, TRUE);
5110 case GTK_WINDOW_TOPLEVEL:
5111 attributes.window_type = GDK_WINDOW_TOPLEVEL;
5113 case GTK_WINDOW_POPUP:
5114 attributes.window_type = GDK_WINDOW_TEMP;
5117 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5121 attributes.title = priv->title;
5122 attributes.wmclass_name = priv->wmclass_name;
5123 attributes.wmclass_class = priv->wmclass_class;
5124 attributes.wclass = GDK_INPUT_OUTPUT;
5125 attributes.visual = gtk_widget_get_visual (widget);
5127 attributes_mask = 0;
5128 parent_window = gtk_widget_get_root_window (widget);
5130 gtk_widget_get_allocation (widget, &allocation);
5131 attributes.width = allocation.width;
5132 attributes.height = allocation.height;
5133 attributes.event_mask = gtk_widget_get_events (widget);
5134 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5135 GDK_KEY_PRESS_MASK |
5136 GDK_KEY_RELEASE_MASK |
5137 GDK_ENTER_NOTIFY_MASK |
5138 GDK_LEAVE_NOTIFY_MASK |
5139 GDK_FOCUS_CHANGE_MASK |
5140 GDK_STRUCTURE_MASK);
5141 attributes.type_hint = priv->type_hint;
5143 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5144 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5145 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5147 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5148 gtk_widget_set_window (widget, gdk_window);
5150 if (priv->opacity_set)
5151 gdk_window_set_opacity (gdk_window, priv->opacity);
5153 gdk_window_enable_synchronized_configure (gdk_window);
5155 gdk_window_set_user_data (gdk_window, window);
5157 context = gtk_widget_get_style_context (widget);
5158 gtk_style_context_set_background (context, gdk_window);
5161 if (priv->transient_parent &&
5162 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5163 gdk_window_set_transient_for (gdk_window,
5164 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5167 gdk_window_set_role (gdk_window, priv->wm_role);
5169 if (!priv->decorated)
5170 gdk_window_set_decorations (gdk_window, 0);
5172 if (!priv->deletable)
5173 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5175 if (gtk_window_get_skip_pager_hint (window))
5176 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5178 if (gtk_window_get_skip_taskbar_hint (window))
5179 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5181 if (gtk_window_get_accept_focus (window))
5182 gdk_window_set_accept_focus (gdk_window, TRUE);
5184 gdk_window_set_accept_focus (gdk_window, FALSE);
5186 if (gtk_window_get_focus_on_map (window))
5187 gdk_window_set_focus_on_map (gdk_window, TRUE);
5189 gdk_window_set_focus_on_map (gdk_window, FALSE);
5192 gdk_window_set_modal_hint (gdk_window, TRUE);
5194 gdk_window_set_modal_hint (gdk_window, FALSE);
5196 if (priv->startup_id)
5198 #ifdef GDK_WINDOWING_X11
5199 if (GDK_IS_X11_WINDOW (gdk_window))
5201 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5202 if (timestamp != GDK_CURRENT_TIME)
5203 gdk_x11_window_set_user_time (gdk_window, timestamp);
5206 if (!startup_id_is_fake (priv->startup_id))
5207 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5210 #ifdef GDK_WINDOWING_X11
5211 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5213 if (GDK_IS_X11_WINDOW (gdk_window))
5214 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5218 gtk_window_set_application (window, gtk_window_get_application (window));
5221 gtk_window_realize_icon (window);
5223 if (priv->has_resize_grip)
5224 resize_grip_create_window (window);
5228 gtk_window_unrealize (GtkWidget *widget)
5230 GtkWindow *window = GTK_WINDOW (widget);
5231 GtkWindowPrivate *priv = window->priv;
5232 GtkWindowGeometryInfo *info;
5234 /* On unrealize, we reset the size of the window such
5235 * that we will re-apply the default sizing stuff
5236 * next time we show the window.
5238 * Default positioning is reset on unmap, instead of unrealize.
5240 priv->need_default_size = TRUE;
5241 info = gtk_window_get_geometry_info (window, FALSE);
5244 info->resize_width = -1;
5245 info->resize_height = -1;
5246 info->last.configure_request.x = 0;
5247 info->last.configure_request.y = 0;
5248 info->last.configure_request.width = -1;
5249 info->last.configure_request.height = -1;
5250 /* be sure we reset geom hints on re-realize */
5251 info->last.flags = 0;
5255 gtk_window_unrealize_icon (window);
5257 if (priv->grip_window != NULL)
5258 resize_grip_destroy_window (window);
5260 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5263 static GtkJunctionSides
5264 get_grip_junction (GtkWidget *widget)
5266 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5267 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5269 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5273 get_drag_edge (GtkWidget *widget,
5274 GdkWindowEdge *edge)
5276 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5277 gboolean hresizable;
5278 gboolean vresizable;
5279 GtkTextDirection dir;
5280 GtkWindowGeometryInfo *info;
5285 info = priv->geometry_info;
5288 GdkWindowHints flags = info->last.flags;
5289 GdkGeometry *geometry = &info->last.geometry;
5291 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5293 hresizable = geometry->min_width < geometry->max_width;
5294 vresizable = geometry->min_height < geometry->max_height;
5298 dir = gtk_widget_get_direction (widget);
5300 if (hresizable && vresizable)
5301 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5302 else if (hresizable)
5303 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5304 else if (vresizable)
5305 *edge = GDK_WINDOW_EDGE_SOUTH;
5313 set_grip_cursor (GtkWindow *window)
5315 GtkWidget *widget = GTK_WIDGET (window);
5316 GtkWindowPrivate *priv = window->priv;
5318 if (priv->grip_window == NULL)
5321 if (gtk_widget_is_sensitive (widget))
5324 GdkDisplay *display;
5325 GdkCursorType cursor_type;
5328 cursor_type = GDK_LEFT_PTR;
5330 if (get_drag_edge (widget, &edge))
5334 case GDK_WINDOW_EDGE_EAST:
5335 cursor_type = GDK_RIGHT_SIDE;
5337 case GDK_WINDOW_EDGE_SOUTH_EAST:
5338 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5340 case GDK_WINDOW_EDGE_SOUTH:
5341 cursor_type = GDK_BOTTOM_SIDE;
5343 case GDK_WINDOW_EDGE_SOUTH_WEST:
5344 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5346 case GDK_WINDOW_EDGE_WEST:
5347 cursor_type = GDK_LEFT_SIDE;
5353 display = gtk_widget_get_display (widget);
5354 cursor = gdk_cursor_new_for_display (display, cursor_type);
5355 gdk_window_set_cursor (priv->grip_window, cursor);
5356 g_object_unref (cursor);
5359 gdk_window_set_cursor (priv->grip_window, NULL);
5363 set_grip_shape (GtkWindow *window)
5365 GtkWindowPrivate *priv = window->priv;
5366 cairo_region_t *region;
5367 cairo_surface_t *surface;
5369 double width, height;
5371 if (priv->grip_window == NULL)
5374 width = gdk_window_get_width (priv->grip_window);
5375 height = gdk_window_get_height (priv->grip_window);
5376 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
5378 cr = cairo_create (surface);
5379 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5381 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5382 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5384 cairo_move_to (cr, width, 0.0);
5385 cairo_line_to (cr, width, height);
5386 cairo_line_to (cr, 0.0, height);
5390 cairo_move_to (cr, 0.0, 0.0);
5391 cairo_line_to (cr, width, height);
5392 cairo_line_to (cr, 0.0, height);
5394 cairo_close_path (cr);
5397 region = gdk_cairo_region_create_from_surface (surface);
5398 cairo_surface_destroy (surface);
5400 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5401 cairo_region_destroy (region);
5405 set_grip_position (GtkWindow *window)
5407 GtkWindowPrivate *priv = window->priv;
5410 if (priv->grip_window == NULL)
5413 gtk_window_get_resize_grip_area (window, &rect);
5414 gdk_window_raise (priv->grip_window);
5415 gdk_window_move_resize (priv->grip_window,
5417 rect.width, rect.height);
5421 gtk_window_size_allocate (GtkWidget *widget,
5422 GtkAllocation *allocation)
5424 GtkWindow *window = GTK_WINDOW (widget);
5425 GtkAllocation child_allocation;
5429 gtk_widget_set_allocation (widget, allocation);
5431 if (gtk_widget_get_realized (widget))
5433 /* If it's not a toplevel we're embedded, we need to resize the window's
5434 * window and skip the grip.
5436 if (!gtk_widget_is_toplevel (widget))
5438 gdk_window_move_resize (gtk_widget_get_window (widget),
5439 allocation->x, allocation->y,
5440 allocation->width, allocation->height);
5444 update_grip_visibility (window);
5445 set_grip_position (window);
5449 child = gtk_bin_get_child (&(window->bin));
5450 if (child && gtk_widget_get_visible (child))
5452 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5453 child_allocation.x = border_width;
5454 child_allocation.y = border_width;
5455 child_allocation.width =
5456 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5457 child_allocation.height =
5458 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5460 gtk_widget_size_allocate (child, &child_allocation);
5465 gtk_window_configure_event (GtkWidget *widget,
5466 GdkEventConfigure *event)
5468 GtkAllocation allocation;
5469 GtkWindow *window = GTK_WINDOW (widget);
5470 GtkWindowPrivate *priv = window->priv;
5471 gboolean expected_reply = priv->configure_request_count > 0;
5473 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5475 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5476 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5478 gdk_window_configure_finished (gtk_widget_get_window (widget));
5482 /* priv->configure_request_count incremented for each
5483 * configure request, and decremented to a min of 0 for
5484 * each configure notify.
5486 * All it means is that we know we will get at least
5487 * priv->configure_request_count more configure notifies.
5488 * We could get more configure notifies than that; some
5489 * of the configure notifies we get may be unrelated to
5490 * the configure requests. But we will get at least
5491 * priv->configure_request_count notifies.
5494 if (priv->configure_request_count > 0)
5496 priv->configure_request_count -= 1;
5497 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5500 /* As an optimization, we avoid a resize when possible.
5502 * The only times we can avoid a resize are:
5503 * - we know only the position changed, not the size
5504 * - we know we have made more requests and so will get more
5505 * notifies and can wait to resize when we get them
5507 gtk_widget_get_allocation (widget, &allocation);
5508 if (!expected_reply &&
5509 (allocation.width == event->width &&
5510 allocation.height == event->height))
5512 gdk_window_configure_finished (gtk_widget_get_window (widget));
5517 * If we do need to resize, we do that by:
5518 * - filling in widget->allocation with the new size
5519 * - setting configure_notify_received to TRUE
5520 * for use in gtk_window_move_resize()
5521 * - queueing a resize, leading to invocation of
5522 * gtk_window_move_resize() in an idle handler
5526 priv->configure_notify_received = TRUE;
5528 allocation.width = event->width;
5529 allocation.height = event->height;
5530 gtk_widget_set_allocation (widget, &allocation);
5532 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5534 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5540 gtk_window_state_event (GtkWidget *widget,
5541 GdkEventWindowState *event)
5543 update_grip_visibility (GTK_WINDOW (widget));
5545 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
5546 ensure_state_flag_window_unfocused (widget);
5552 gtk_window_direction_changed (GtkWidget *widget,
5553 GtkTextDirection prev_dir)
5555 GtkWindow *window = GTK_WINDOW (widget);
5557 set_grip_cursor (window);
5558 set_grip_position (window);
5559 set_grip_shape (window);
5563 gtk_window_state_changed (GtkWidget *widget,
5564 GtkStateType previous_state)
5566 GtkWindow *window = GTK_WINDOW (widget);
5568 update_grip_visibility (window);
5572 gtk_window_style_updated (GtkWidget *widget)
5574 GtkWindow *window = GTK_WINDOW (widget);
5575 GtkWindowPrivate *priv = window->priv;
5578 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5580 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5582 gdk_window_move_resize (priv->grip_window,
5584 rect.width, rect.height);
5586 set_grip_shape (window);
5587 gtk_widget_queue_resize (widget);
5592 resize_grip_create_window (GtkWindow *window)
5595 GtkWindowPrivate *priv;
5596 GdkWindowAttr attributes;
5597 gint attributes_mask;
5599 GdkRGBA transparent = {0, 0, 0, 0};
5601 priv = window->priv;
5602 widget = GTK_WIDGET (window);
5604 g_return_if_fail (gtk_widget_get_realized (widget));
5605 g_return_if_fail (priv->grip_window == NULL);
5607 gtk_window_get_resize_grip_area (window, &rect);
5609 attributes.x = rect.x;
5610 attributes.y = rect.y;
5611 attributes.width = rect.width;
5612 attributes.height = rect.height;
5613 attributes.window_type = GDK_WINDOW_CHILD;
5614 attributes.wclass = GDK_INPUT_OUTPUT;
5615 attributes.event_mask = gtk_widget_get_events (widget) |
5617 GDK_BUTTON_PRESS_MASK;
5619 attributes_mask = GDK_WA_X | GDK_WA_Y;
5621 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5624 gdk_window_set_background_rgba (priv->grip_window, &transparent);
5626 gdk_window_set_user_data (priv->grip_window, widget);
5628 gdk_window_raise (priv->grip_window);
5630 set_grip_shape (window);
5631 update_grip_visibility (window);
5635 resize_grip_destroy_window (GtkWindow *window)
5637 GtkWindowPrivate *priv = window->priv;
5639 gdk_window_set_user_data (priv->grip_window, NULL);
5640 gdk_window_destroy (priv->grip_window);
5641 priv->grip_window = NULL;
5642 update_grip_visibility (window);
5646 * gtk_window_set_has_resize_grip:
5647 * @window: a #GtkWindow
5648 * @value: %TRUE to allow a resize grip
5650 * Sets whether @window has a corner resize grip.
5652 * Note that the resize grip is only shown if the window
5653 * is actually resizable and not maximized. Use
5654 * gtk_window_resize_grip_is_visible() to find out if the
5655 * resize grip is currently shown.
5660 gtk_window_set_has_resize_grip (GtkWindow *window,
5663 GtkWidget *widget = GTK_WIDGET (window);
5664 GtkWindowPrivate *priv = window->priv;
5666 value = value != FALSE;
5668 if (value != priv->has_resize_grip)
5670 priv->has_resize_grip = value;
5671 gtk_widget_queue_draw (widget);
5673 if (gtk_widget_get_realized (widget) &&
5674 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5676 if (priv->has_resize_grip && priv->grip_window == NULL)
5677 resize_grip_create_window (window);
5678 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5679 resize_grip_destroy_window (window);
5682 g_object_notify (G_OBJECT (window), "has-resize-grip");
5687 update_grip_visibility (GtkWindow *window)
5689 GtkWindowPrivate *priv = window->priv;
5692 val = gtk_window_resize_grip_is_visible (window);
5694 if (priv->grip_window != NULL)
5698 gdk_window_show (priv->grip_window);
5699 set_grip_cursor (window);
5703 gdk_window_hide (priv->grip_window);
5707 if (priv->resize_grip_visible != val)
5709 priv->resize_grip_visible = val;
5711 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5716 * gtk_window_resize_grip_is_visible:
5717 * @window: a #GtkWindow
5719 * Determines whether a resize grip is visible for the specified window.
5721 * Returns: %TRUE if a resize grip exists and is visible
5726 gtk_window_resize_grip_is_visible (GtkWindow *window)
5729 GtkWindowPrivate *priv;
5732 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5734 priv = window->priv;
5735 widget = GTK_WIDGET (window);
5737 if (priv->type == GTK_WINDOW_POPUP)
5740 if (!priv->resizable)
5743 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5746 if (gtk_widget_get_realized (widget))
5748 GdkWindowState state;
5750 state = gdk_window_get_state (gtk_widget_get_window (widget));
5752 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5756 if (!get_drag_edge (widget, &edge))
5759 return window->priv->has_resize_grip;
5763 * gtk_window_get_has_resize_grip:
5764 * @window: a #GtkWindow
5766 * Determines whether the window may have a resize grip.
5768 * Returns: %TRUE if the window has a resize grip
5773 gtk_window_get_has_resize_grip (GtkWindow *window)
5775 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5777 return window->priv->has_resize_grip;
5781 * gtk_window_get_resize_grip_area:
5782 * @window: a #GtkWindow
5783 * @rect: (out): a pointer to a #GdkRectangle which we should store
5784 * the resize grip area
5786 * If a window has a resize grip, this will retrieve the grip
5787 * position, width and height into the specified #GdkRectangle.
5789 * Returns: %TRUE if the resize grip's area was retrieved
5794 gtk_window_get_resize_grip_area (GtkWindow *window,
5797 GtkWidget *widget = GTK_WIDGET (window);
5798 GtkAllocation allocation;
5802 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5804 if (!window->priv->has_resize_grip)
5807 gtk_widget_get_allocation (widget, &allocation);
5809 gtk_widget_style_get (widget,
5810 "resize-grip-width", &grip_width,
5811 "resize-grip-height", &grip_height,
5814 if (grip_width > allocation.width)
5815 grip_width = allocation.width;
5817 if (grip_height > allocation.height)
5818 grip_height = allocation.height;
5820 rect->width = grip_width;
5821 rect->height = grip_height;
5822 rect->y = allocation.y + allocation.height - grip_height;
5824 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5825 rect->x = allocation.x + allocation.width - grip_width;
5827 rect->x = allocation.x;
5832 /* the accel_key and accel_mods fields of the key have to be setup
5833 * upon calling this function. it'll then return whether that key
5834 * is at all used as accelerator, and if so will OR in the
5835 * accel_flags member of the key.
5838 _gtk_window_query_nonaccels (GtkWindow *window,
5840 GdkModifierType accel_mods)
5842 GtkWindowPrivate *priv;
5844 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5846 priv = window->priv;
5848 /* movement keys are considered locked accels */
5851 static const guint bindings[] = {
5852 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,
5853 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,
5857 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5858 if (bindings[i] == accel_key)
5862 /* mnemonics are considered locked accels */
5863 if (accel_mods == priv->mnemonic_modifier)
5865 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5866 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5874 * gtk_window_propagate_key_event:
5875 * @window: a #GtkWindow
5876 * @event: a #GdkEventKey
5878 * Propagate a key press or release event to the focus widget and
5879 * up the focus container chain until a widget handles @event.
5880 * This is normally called by the default ::key_press_event and
5881 * ::key_release_event handlers for toplevel windows,
5882 * however in some cases it may be useful to call this directly when
5883 * overriding the standard key handling for a toplevel window.
5885 * Return value: %TRUE if a widget in the focus chain handled the event.
5890 gtk_window_propagate_key_event (GtkWindow *window,
5893 GtkWindowPrivate *priv;
5894 gboolean handled = FALSE;
5895 GtkWidget *widget, *focus;
5897 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5899 priv = window->priv;
5900 widget = GTK_WIDGET (window);
5902 focus = priv->focus_widget;
5904 g_object_ref (focus);
5907 focus && focus != widget &&
5908 gtk_widget_get_toplevel (focus) == widget)
5912 if (gtk_widget_is_sensitive (focus))
5913 handled = gtk_widget_event (focus, (GdkEvent*) event);
5915 parent = gtk_widget_get_parent (focus);
5917 g_object_ref (parent);
5919 g_object_unref (focus);
5925 g_object_unref (focus);
5931 gtk_window_key_press_event (GtkWidget *widget,
5934 GtkWindow *window = GTK_WINDOW (widget);
5935 gboolean handled = FALSE;
5937 /* handle mnemonics and accelerators */
5939 handled = gtk_window_activate_key (window, event);
5941 /* handle focus widget key events */
5943 handled = gtk_window_propagate_key_event (window, event);
5945 /* Chain up, invokes binding set */
5947 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5953 gtk_window_key_release_event (GtkWidget *widget,
5956 GtkWindow *window = GTK_WINDOW (widget);
5957 gboolean handled = FALSE;
5959 /* handle focus widget key events */
5961 handled = gtk_window_propagate_key_event (window, event);
5963 /* Chain up, invokes binding set */
5965 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5971 gtk_window_button_press_event (GtkWidget *widget,
5972 GdkEventButton *event)
5974 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5977 if (event->window == priv->grip_window)
5979 if (get_drag_edge (widget, &edge))
5980 gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
5982 gdk_event_get_device ((GdkEvent *) event),
5995 gtk_window_real_activate_default (GtkWindow *window)
5997 gtk_window_activate_default (window);
6001 gtk_window_real_activate_focus (GtkWindow *window)
6003 gtk_window_activate_focus (window);
6007 gtk_window_enter_notify_event (GtkWidget *widget,
6008 GdkEventCrossing *event)
6014 gtk_window_leave_notify_event (GtkWidget *widget,
6015 GdkEventCrossing *event)
6021 do_focus_change (GtkWidget *widget,
6025 GdkDeviceManager *device_manager;
6028 g_object_ref (widget);
6030 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
6031 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6032 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
6033 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
6035 for (d = devices; d; d = d->next)
6037 GdkDevice *dev = d->data;
6040 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
6043 /* Skip non-master keyboards that haven't
6044 * selected for events from this window
6046 window = gtk_widget_get_window (widget);
6047 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
6048 window && !gdk_window_get_device_events (window, dev))
6051 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
6053 fevent->focus_change.type = GDK_FOCUS_CHANGE;
6054 fevent->focus_change.window = window;
6056 g_object_ref (window);
6057 fevent->focus_change.in = in;
6058 gdk_event_set_device (fevent, dev);
6060 gtk_widget_send_focus_change (widget, fevent);
6062 gdk_event_free (fevent);
6065 g_list_free (devices);
6066 g_object_unref (widget);
6070 maybe_set_mnemonics_visible (GtkWindow *window)
6073 GdkDeviceManager *device_manager;
6075 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
6076 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6078 for (d = devices; d; d = d->next)
6080 GdkDevice *dev = d->data;
6082 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6084 GdkModifierType mask;
6086 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6088 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6090 gtk_window_set_mnemonics_visible (window, TRUE);
6096 g_list_free (devices);
6100 gtk_window_focus_in_event (GtkWidget *widget,
6101 GdkEventFocus *event)
6103 GtkWindow *window = GTK_WINDOW (widget);
6104 gboolean auto_mnemonics;
6106 /* It appears spurious focus in events can occur when
6107 * the window is hidden. So we'll just check to see if
6108 * the window is visible before actually handling the
6111 if (gtk_widget_get_visible (widget))
6113 _gtk_window_set_has_toplevel_focus (window, TRUE);
6114 _gtk_window_set_is_active (window, TRUE);
6116 g_object_get (gtk_widget_get_settings (widget),
6117 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6119 maybe_set_mnemonics_visible (window);
6126 gtk_window_focus_out_event (GtkWidget *widget,
6127 GdkEventFocus *event)
6129 GtkWindow *window = GTK_WINDOW (widget);
6130 gboolean auto_mnemonics;
6132 _gtk_window_set_has_toplevel_focus (window, FALSE);
6133 _gtk_window_set_is_active (window, FALSE);
6135 /* set the mnemonic-visible property to false */
6136 g_object_get (gtk_widget_get_settings (widget),
6137 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6139 gtk_window_set_mnemonics_visible (window, FALSE);
6145 gtk_window_check_resize (GtkContainer *container)
6147 /* If the window is not toplevel anymore than it's embedded somewhere,
6148 * so handle it like a normal window */
6149 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6150 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6151 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6152 gtk_window_move_resize (GTK_WINDOW (container));
6156 gtk_window_focus (GtkWidget *widget,
6157 GtkDirectionType direction)
6159 GtkWindowPrivate *priv;
6162 GtkContainer *container;
6164 GtkWidget *old_focus_child;
6167 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6168 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6170 container = GTK_CONTAINER (widget);
6171 window = GTK_WINDOW (widget);
6172 priv = window->priv;
6173 bin = GTK_BIN (widget);
6175 old_focus_child = gtk_container_get_focus_child (container);
6177 /* We need a special implementation here to deal properly with wrapping
6178 * around in the tab chain without the danger of going into an
6181 if (old_focus_child)
6183 if (gtk_widget_child_focus (old_focus_child, direction))
6187 if (priv->focus_widget)
6189 if (direction == GTK_DIR_LEFT ||
6190 direction == GTK_DIR_RIGHT ||
6191 direction == GTK_DIR_UP ||
6192 direction == GTK_DIR_DOWN)
6197 /* Wrapped off the end, clear the focus setting for the toplpevel */
6198 parent = gtk_widget_get_parent (priv->focus_widget);
6201 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6202 parent = gtk_widget_get_parent (parent);
6205 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6208 /* Now try to focus the first widget in the window */
6209 child = gtk_bin_get_child (bin);
6212 if (gtk_widget_child_focus (child, direction))
6220 gtk_window_move_focus (GtkWidget *widget,
6221 GtkDirectionType dir)
6223 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6225 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6229 gtk_widget_child_focus (widget, dir);
6231 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6232 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6236 gtk_window_real_set_focus (GtkWindow *window,
6239 GtkWindowPrivate *priv = window->priv;
6240 GtkWidget *old_focus = priv->focus_widget;
6241 gboolean had_default = FALSE;
6242 gboolean focus_had_default = FALSE;
6243 gboolean old_focus_had_default = FALSE;
6247 g_object_ref (old_focus);
6248 g_object_freeze_notify (G_OBJECT (old_focus));
6249 old_focus_had_default = gtk_widget_has_default (old_focus);
6253 g_object_ref (focus);
6254 g_object_freeze_notify (G_OBJECT (focus));
6255 focus_had_default = gtk_widget_has_default (focus);
6258 if (priv->default_widget)
6259 had_default = gtk_widget_has_default (priv->default_widget);
6261 if (priv->focus_widget)
6263 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6264 (priv->focus_widget != priv->default_widget))
6266 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6267 gtk_widget_queue_draw (priv->focus_widget);
6269 if (priv->default_widget)
6270 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6273 priv->focus_widget = NULL;
6275 if (priv->has_focus)
6276 do_focus_change (old_focus, FALSE);
6278 g_object_notify (G_OBJECT (old_focus), "is-focus");
6281 /* The above notifications may have set a new focus widget,
6282 * if so, we don't want to override it.
6284 if (focus && !priv->focus_widget)
6286 priv->focus_widget = focus;
6288 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6289 (priv->focus_widget != priv->default_widget))
6291 if (gtk_widget_get_can_default (priv->focus_widget))
6292 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6294 if (priv->default_widget)
6295 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6298 if (priv->has_focus)
6299 do_focus_change (priv->focus_widget, TRUE);
6301 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6304 /* If the default widget changed, a redraw will have been queued
6305 * on the old and new default widgets by gtk_window_set_default(), so
6306 * we only have to worry about the case where it didn't change.
6307 * We'll sometimes queue a draw twice on the new widget but that
6310 if (priv->default_widget &&
6311 (had_default != gtk_widget_has_default (priv->default_widget)))
6312 gtk_widget_queue_draw (priv->default_widget);
6316 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6317 gtk_widget_queue_draw (old_focus);
6319 g_object_thaw_notify (G_OBJECT (old_focus));
6320 g_object_unref (old_focus);
6324 if (focus_had_default != gtk_widget_has_default (focus))
6325 gtk_widget_queue_draw (focus);
6327 g_object_thaw_notify (G_OBJECT (focus));
6328 g_object_unref (focus);
6334 gtk_window_get_preferred_width (GtkWidget *widget,
6342 window = GTK_WINDOW (widget);
6343 child = gtk_bin_get_child (GTK_BIN (window));
6345 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6346 *minimum_size = border_width * 2;
6347 *natural_size = border_width * 2;
6349 if (child && gtk_widget_get_visible (child))
6351 gint child_min, child_nat;
6352 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6354 *minimum_size += child_min;
6355 *natural_size += child_nat;
6360 gtk_window_get_preferred_height (GtkWidget *widget,
6368 window = GTK_WINDOW (widget);
6369 child = gtk_bin_get_child (GTK_BIN (window));
6371 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6372 *minimum_size = border_width * 2;
6373 *natural_size = border_width * 2;
6375 if (child && gtk_widget_get_visible (child))
6377 gint child_min, child_nat;
6378 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6380 *minimum_size += child_min;
6381 *natural_size += child_nat;
6387 * _gtk_window_unset_focus_and_default:
6388 * @window: a #GtkWindow
6389 * @widget: a widget inside of @window
6391 * Checks whether the focus and default widgets of @window are
6392 * @widget or a descendent of @widget, and if so, unset them.
6395 _gtk_window_unset_focus_and_default (GtkWindow *window,
6399 GtkWindowPrivate *priv = window->priv;
6403 g_object_ref (window);
6404 g_object_ref (widget);
6406 parent = gtk_widget_get_parent (widget);
6407 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6409 child = priv->focus_widget;
6411 while (child && child != widget)
6412 child = gtk_widget_get_parent (child);
6414 if (child == widget)
6415 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6418 child = priv->default_widget;
6420 while (child && child != widget)
6421 child = gtk_widget_get_parent (child);
6423 if (child == widget)
6424 gtk_window_set_default (window, NULL);
6426 g_object_unref (widget);
6427 g_object_unref (window);
6430 /*********************************
6431 * Functions related to resizing *
6432 *********************************/
6435 geometry_size_to_pixels (GdkGeometry *geometry,
6440 gint base_width = 0;
6441 gint base_height = 0;
6443 gint min_height = 0;
6445 gint height_inc = 1;
6447 if (flags & GDK_HINT_BASE_SIZE)
6449 base_width = geometry->base_width;
6450 base_height = geometry->base_height;
6452 if (flags & GDK_HINT_MIN_SIZE)
6454 min_width = geometry->min_width;
6455 min_height = geometry->min_height;
6457 if (flags & GDK_HINT_RESIZE_INC)
6459 width_inc = geometry->width_inc;
6460 height_inc = geometry->height_inc;
6464 *width = MAX (*width * width_inc + base_width, min_width);
6466 *height = MAX (*height * height_inc + base_height, min_height);
6469 /* This function doesn't constrain to geometry hints */
6471 gtk_window_compute_configure_request_size (GtkWindow *window,
6472 GdkGeometry *geometry,
6477 GtkWindowPrivate *priv = window->priv;
6478 GtkWindowGeometryInfo *info;
6481 * - we've done a size request
6484 info = gtk_window_get_geometry_info (window, FALSE);
6486 if (priv->need_default_size)
6488 gtk_window_guess_default_size (window, width, height);
6490 /* If window is empty so requests 0, default to random nonzero size */
6491 if (*width == 0 && *height == 0)
6497 /* Override with default size */
6501 if (info->default_width > 0)
6502 *width = info->default_width;
6503 if (info->default_height > 0)
6504 *height = info->default_height;
6506 if (info->default_is_geometry)
6507 geometry_size_to_pixels (geometry, flags,
6508 info->default_width > 0 ? width : NULL,
6509 info->default_height > 0 ? height : NULL);
6514 GtkAllocation allocation;
6516 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6518 /* Default to keeping current size */
6519 *width = allocation.width;
6520 *height = allocation.height;
6523 /* Override any size with gtk_window_resize() values */
6526 if (info->resize_width > 0)
6527 *width = info->resize_width;
6528 if (info->resize_height > 0)
6529 *height = info->resize_height;
6531 if (info->resize_is_geometry)
6532 geometry_size_to_pixels (geometry, flags,
6533 info->resize_width > 0 ? width : NULL,
6534 info->resize_height > 0 ? height : NULL);
6537 /* Don't ever request zero width or height, its not supported by
6538 gdk. The size allocation code will round it to 1 anyway but if
6539 we do it then the value returned from this function will is
6540 not comparable to the size allocation read from the GtkWindow. */
6541 *width = MAX (*width, 1);
6542 *height = MAX (*height, 1);
6545 static GtkWindowPosition
6546 get_effective_position (GtkWindow *window)
6548 GtkWindowPrivate *priv = window->priv;
6549 GtkWindowPosition pos = priv->position;
6551 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6552 (priv->transient_parent == NULL ||
6553 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6554 pos = GTK_WIN_POS_NONE;
6560 get_center_monitor_of_window (GtkWindow *window)
6562 /* We could try to sort out the relative positions of the monitors and
6563 * stuff, or we could just be losers and assume you have a row
6564 * or column of monitors.
6566 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6570 get_monitor_containing_pointer (GtkWindow *window)
6574 GdkScreen *window_screen;
6575 GdkScreen *pointer_screen;
6576 GdkDisplay *display;
6577 GdkDeviceManager *device_manager;
6580 window_screen = gtk_window_check_screen (window);
6581 display = gdk_screen_get_display (window_screen);
6582 device_manager = gdk_display_get_device_manager (display);
6583 pointer = gdk_device_manager_get_client_pointer (device_manager);
6585 gdk_device_get_position (pointer,
6589 if (pointer_screen == window_screen)
6590 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6598 center_window_on_monitor (GtkWindow *window,
6604 GdkRectangle monitor;
6607 monitor_num = get_monitor_containing_pointer (window);
6609 if (monitor_num == -1)
6610 monitor_num = get_center_monitor_of_window (window);
6612 gdk_screen_get_monitor_workarea (gtk_window_check_screen (window),
6613 monitor_num, &monitor);
6615 *x = (monitor.width - w) / 2 + monitor.x;
6616 *y = (monitor.height - h) / 2 + monitor.y;
6618 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6619 * and WM decorations.
6633 if (extent > clamp_extent)
6635 *base = clamp_base + clamp_extent/2 - extent/2;
6636 else if (*base < clamp_base)
6638 else if (*base + extent > clamp_base + clamp_extent)
6639 *base = clamp_base + clamp_extent - extent;
6643 clamp_window_to_rectangle (gint *x,
6647 const GdkRectangle *rect)
6649 #ifdef DEBUGGING_OUTPUT
6650 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);
6653 /* If it is too large, center it. If it fits on the monitor but is
6654 * partially outside, move it to the closest edge. Do this
6655 * separately in x and y directions.
6657 clamp (x, w, rect->x, rect->width);
6658 clamp (y, h, rect->y, rect->height);
6659 #ifdef DEBUGGING_OUTPUT
6660 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6666 gtk_window_compute_configure_request (GtkWindow *window,
6667 GdkRectangle *request,
6668 GdkGeometry *geometry,
6671 GtkWindowPrivate *priv = window->priv;
6672 GdkGeometry new_geometry;
6675 GtkWindowPosition pos;
6676 GtkWidget *parent_widget;
6677 GtkWindowGeometryInfo *info;
6681 screen = gtk_window_check_screen (window);
6683 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6684 gtk_window_compute_configure_request_size (window,
6685 &new_geometry, new_flags,
6688 gtk_window_constrain_size (window,
6689 &new_geometry, new_flags,
6693 parent_widget = (GtkWidget*) priv->transient_parent;
6695 pos = get_effective_position (window);
6696 info = gtk_window_get_geometry_info (window, FALSE);
6698 /* by default, don't change position requested */
6701 x = info->last.configure_request.x;
6702 y = info->last.configure_request.y;
6711 if (priv->need_default_position)
6714 /* FIXME this all interrelates with window gravity.
6715 * For most of them I think we want to set GRAVITY_CENTER.
6717 * Not sure how to go about that.
6721 /* here we are only handling CENTER_ALWAYS
6722 * as it relates to default positioning,
6723 * where it's equivalent to simply CENTER
6725 case GTK_WIN_POS_CENTER_ALWAYS:
6726 case GTK_WIN_POS_CENTER:
6727 center_window_on_monitor (window, w, h, &x, &y);
6730 case GTK_WIN_POS_CENTER_ON_PARENT:
6732 GtkAllocation allocation;
6733 GdkWindow *gdk_window;
6735 GdkRectangle monitor;
6738 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6740 gdk_window = gtk_widget_get_window (parent_widget);
6742 if (gdk_window != NULL)
6743 monitor_num = gdk_screen_get_monitor_at_window (screen,
6748 gdk_window_get_origin (gdk_window,
6751 gtk_widget_get_allocation (parent_widget, &allocation);
6752 x = ox + (allocation.width - w) / 2;
6753 y = oy + (allocation.height - h) / 2;
6755 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6756 * WM decorations. If parent wasn't on a monitor, just
6759 if (monitor_num >= 0)
6761 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6762 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6767 case GTK_WIN_POS_MOUSE:
6769 gint screen_width = gdk_screen_get_width (screen);
6770 gint screen_height = gdk_screen_get_height (screen);
6772 GdkRectangle monitor;
6773 GdkDisplay *display;
6774 GdkDeviceManager *device_manager;
6776 GdkScreen *pointer_screen;
6779 display = gdk_screen_get_display (screen);
6780 device_manager = gdk_display_get_device_manager (display);
6781 pointer = gdk_device_manager_get_client_pointer (device_manager);
6783 gdk_device_get_position (pointer,
6787 if (pointer_screen == screen)
6788 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6794 x = CLAMP (x, 0, screen_width - w);
6795 y = CLAMP (y, 0, screen_height - h);
6797 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6798 * WM decorations. Don't try to figure out what's going
6799 * on if the mouse wasn't inside a monitor.
6801 if (monitor_num >= 0)
6803 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6804 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6812 } /* if (priv->need_default_position) */
6814 if (priv->need_default_position && info &&
6815 info->initial_pos_set)
6817 x = info->initial_x;
6818 y = info->initial_y;
6819 gtk_window_constrain_position (window, w, h, &x, &y);
6825 request->height = h;
6828 *geometry = new_geometry;
6834 gtk_window_constrain_position (GtkWindow *window,
6840 GtkWindowPrivate *priv = window->priv;
6842 /* See long comments in gtk_window_move_resize()
6843 * on when it's safe to call this function.
6845 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6847 gint center_x, center_y;
6849 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6857 gtk_window_move_resize (GtkWindow *window)
6861 * First we determine whether any information has changed that would
6862 * cause us to revise our last configure request. If we would send
6863 * a different configure request from last time, then
6864 * configure_request_size_changed = TRUE or
6865 * configure_request_pos_changed = TRUE. configure_request_size_changed
6866 * may be true due to new hints, a gtk_window_resize(), or whatever.
6867 * configure_request_pos_changed may be true due to gtk_window_set_position()
6868 * or gtk_window_move().
6870 * If the configure request has changed, we send off a new one. To
6871 * ensure GTK+ invariants are maintained (resize queue does what it
6872 * should), we go ahead and size_allocate the requested size in this
6875 * If the configure request has not changed, we don't ever resend
6876 * it, because it could mean fighting the user or window manager.
6879 * To prepare the configure request, we come up with a base size/pos:
6880 * - the one from gtk_window_move()/gtk_window_resize()
6881 * - else default_width, default_height if we haven't ever
6883 * - else the size request if we haven't ever been mapped,
6884 * as a substitute default size
6885 * - else the current size of the window, as received from
6886 * configure notifies (i.e. the current allocation)
6888 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6889 * the position request to be centered.
6891 GtkWindowPrivate *priv = window->priv;
6892 GtkAllocation allocation;
6894 GtkContainer *container;
6895 GtkWindowGeometryInfo *info;
6896 GdkGeometry new_geometry;
6897 GdkWindow *gdk_window;
6899 GdkRectangle new_request;
6900 gboolean configure_request_size_changed;
6901 gboolean configure_request_pos_changed;
6902 gboolean hints_changed; /* do we need to send these again */
6903 GtkWindowLastGeometryInfo saved_last_info;
6905 widget = GTK_WIDGET (window);
6907 gdk_window = gtk_widget_get_window (widget);
6908 container = GTK_CONTAINER (widget);
6909 info = gtk_window_get_geometry_info (window, TRUE);
6911 configure_request_size_changed = FALSE;
6912 configure_request_pos_changed = FALSE;
6914 gtk_window_compute_configure_request (window, &new_request,
6915 &new_geometry, &new_flags);
6917 /* This check implies the invariant that we never set info->last
6918 * without setting the hints and sending off a configure request.
6920 * If we change info->last without sending the request, we may
6923 if (info->last.configure_request.x != new_request.x ||
6924 info->last.configure_request.y != new_request.y)
6925 configure_request_pos_changed = TRUE;
6927 if ((info->last.configure_request.width != new_request.width ||
6928 info->last.configure_request.height != new_request.height))
6929 configure_request_size_changed = TRUE;
6931 hints_changed = FALSE;
6933 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6934 &new_geometry, new_flags))
6936 hints_changed = TRUE;
6939 /* Position Constraints
6940 * ====================
6942 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6943 * a default. The other POS_ values are used only when the
6944 * window is shown, not after that.
6946 * However, we can't implement a position constraint as
6947 * "anytime the window size changes, center the window"
6948 * because this may well end up fighting the WM or user. In
6949 * fact it gets in an infinite loop with at least one WM.
6951 * Basically, applications are in no way in a position to
6952 * constrain the position of a window, with one exception:
6953 * override redirect windows. (Really the intended purpose
6954 * of CENTER_ALWAYS anyhow, I would think.)
6956 * So the way we implement this "constraint" is to say that when WE
6957 * cause a move or resize, i.e. we make a configure request changing
6958 * window size, we recompute the CENTER_ALWAYS position to reflect
6959 * the new window size, and include it in our request. Also, if we
6960 * just turned on CENTER_ALWAYS we snap to center with a new
6961 * request. Otherwise, if we are just NOTIFIED of a move or resize
6962 * done by someone else e.g. the window manager, we do NOT send a
6963 * new configure request.
6965 * For override redirect windows, this works fine; all window
6966 * sizes are from our configure requests. For managed windows,
6967 * it is at least semi-sane, though who knows what the
6968 * app author is thinking.
6971 /* This condition should be kept in sync with the condition later on
6972 * that determines whether we send a configure request. i.e. we
6973 * should do this position constraining anytime we were going to
6974 * send a configure request anyhow, plus when constraints have
6977 if (configure_request_pos_changed ||
6978 configure_request_size_changed ||
6980 info->position_constraints_changed)
6982 /* We request the constrained position if:
6983 * - we were changing position, and need to clamp
6984 * the change to the constraint
6985 * - we're changing the size anyway
6986 * - set_position() was called to toggle CENTER_ALWAYS on
6989 gtk_window_constrain_position (window,
6995 /* Update whether we need to request a move */
6996 if (info->last.configure_request.x != new_request.x ||
6997 info->last.configure_request.y != new_request.y)
6998 configure_request_pos_changed = TRUE;
7000 configure_request_pos_changed = FALSE;
7004 if (priv->type == GTK_WINDOW_TOPLEVEL)
7006 int notify_x, notify_y;
7008 /* this is the position from the last configure notify */
7009 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
7011 g_message ("--- %s ---\n"
7012 "last : %d,%d\t%d x %d\n"
7013 "this : %d,%d\t%d x %d\n"
7014 "alloc : %d,%d\t%d x %d\n"
7016 "resize: \t%d x %d\n"
7017 "size_changed: %d pos_changed: %d hints_changed: %d\n"
7018 "configure_notify_received: %d\n"
7019 "configure_request_count: %d\n"
7020 "position_constraints_changed: %d\n",
7021 priv->title ? priv->title : "(no title)",
7022 info->last.configure_request.x,
7023 info->last.configure_request.y,
7024 info->last.configure_request.width,
7025 info->last.configure_request.height,
7031 widget->allocation.width,
7032 widget->allocation.height,
7033 widget->requisition.width,
7034 widget->requisition.height,
7036 info->resize_height,
7037 configure_request_pos_changed,
7038 configure_request_size_changed,
7040 priv->configure_notify_received,
7041 priv->configure_request_count,
7042 info->position_constraints_changed);
7046 saved_last_info = info->last;
7047 info->last.geometry = new_geometry;
7048 info->last.flags = new_flags;
7049 info->last.configure_request = new_request;
7051 /* need to set PPosition so the WM will look at our position,
7052 * but we don't want to count PPosition coming and going as a hints
7053 * change for future iterations. So we saved info->last prior to
7057 /* Also, if the initial position was explicitly set, then we always
7058 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
7062 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
7063 * this is an initial map
7066 if ((configure_request_pos_changed ||
7067 info->initial_pos_set ||
7068 (priv->need_default_position &&
7069 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
7070 (new_flags & GDK_HINT_POS) == 0)
7072 new_flags |= GDK_HINT_POS;
7073 hints_changed = TRUE;
7076 /* Set hints if necessary
7079 gdk_window_set_geometry_hints (gdk_window,
7083 gtk_widget_get_allocation (widget, &allocation);
7085 /* handle resizing/moving and widget tree allocation
7087 if (priv->configure_notify_received)
7089 /* If we have received a configure event since
7090 * the last time in this function, we need to
7091 * accept our new size and size_allocate child widgets.
7092 * (see gtk_window_configure_event() for more details).
7094 * 1 or more configure notifies may have been received.
7095 * Also, configure_notify_received will only be TRUE
7096 * if all expected configure notifies have been received
7097 * (one per configure request), as an optimization.
7100 priv->configure_notify_received = FALSE;
7102 /* gtk_window_configure_event() filled in widget->allocation */
7103 gtk_widget_size_allocate (widget, &allocation);
7105 set_grip_position (window);
7106 update_grip_visibility (window);
7108 gdk_window_process_updates (gdk_window, TRUE);
7110 gdk_window_configure_finished (gdk_window);
7112 /* If the configure request changed, it means that
7114 * 1) coincidentally changed hints or widget properties
7115 * impacting the configure request before getting
7116 * a configure notify, or
7117 * 2) some broken widget is changing its size request
7118 * during size allocation, resulting in
7119 * a false appearance of changed configure request.
7121 * For 1), we could just go ahead and ask for the
7122 * new size right now, but doing that for 2)
7123 * might well be fighting the user (and can even
7124 * trigger a loop). Since we really don't want to
7125 * do that, we requeue a resize in hopes that
7126 * by the time it gets handled, the child has seen
7127 * the light and is willing to go along with the
7128 * new size. (this happens for the zvt widget, since
7129 * the size_allocate() above will have stored the
7130 * requisition corresponding to the new size in the
7133 * This doesn't buy us anything for 1), but it shouldn't
7134 * hurt us too badly, since it is what would have
7135 * happened if we had gotten the configure event before
7136 * the new size had been set.
7139 if (configure_request_size_changed ||
7140 configure_request_pos_changed)
7142 /* Don't change the recorded last info after all, because we
7143 * haven't actually updated to the new info yet - we decided
7144 * to postpone our configure request until later.
7146 info->last = saved_last_info;
7148 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7151 return; /* Bail out, we didn't really process the move/resize */
7153 else if ((configure_request_size_changed || hints_changed) &&
7154 (allocation.width != new_request.width || allocation.height != new_request.height))
7157 /* We are in one of the following situations:
7158 * A. configure_request_size_changed
7159 * our requisition has changed and we need a different window size,
7160 * so we request it from the window manager.
7161 * B. !configure_request_size_changed && hints_changed
7162 * the window manager rejects our size, but we have just changed the
7163 * window manager hints, so there's a chance our request will
7164 * be honoured this time, so we try again.
7166 * However, if the new requisition is the same as the current allocation,
7167 * we don't request it again, since we won't get a ConfigureNotify back from
7168 * the window manager unless it decides to change our requisition. If
7169 * we don't get the ConfigureNotify back, the resize queue will never be run.
7172 /* Now send the configure request */
7173 if (configure_request_pos_changed)
7175 gdk_window_move_resize (gdk_window,
7176 new_request.x, new_request.y,
7177 new_request.width, new_request.height);
7179 else /* only size changed */
7181 gdk_window_resize (gdk_window,
7182 new_request.width, new_request.height);
7185 if (priv->type == GTK_WINDOW_POPUP)
7187 GtkAllocation allocation;
7189 /* Directly size allocate for override redirect (popup) windows. */
7192 allocation.width = new_request.width;
7193 allocation.height = new_request.height;
7195 gtk_widget_size_allocate (widget, &allocation);
7197 gdk_window_process_updates (gdk_window, TRUE);
7199 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7200 gtk_widget_queue_draw (widget);
7204 /* Increment the number of have-not-yet-received-notify requests */
7205 priv->configure_request_count += 1;
7206 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7208 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7209 * configure event in response to our resizing request.
7210 * the configure event will cause a new resize with
7211 * ->configure_notify_received=TRUE.
7212 * until then, we want to
7213 * - discard expose events
7214 * - coalesce resizes for our children
7215 * - defer any window resizes until the configure event arrived
7216 * to achieve this, we queue a resize for the window, but remove its
7217 * resizing handler, so resizing will not be handled from the next
7218 * idle handler but when the configure event arrives.
7220 * FIXME: we should also dequeue the pending redraws here, since
7221 * we handle those ourselves upon ->configure_notify_received==TRUE.
7223 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7225 gtk_widget_queue_resize_no_redraw (widget);
7226 _gtk_container_dequeue_resize_handler (container);
7232 /* Handle any position changes.
7234 if (configure_request_pos_changed)
7236 gdk_window_move (gdk_window,
7237 new_request.x, new_request.y);
7240 /* And run the resize queue.
7242 gtk_container_resize_children (container);
7245 /* We have now processed a move/resize since the last position
7246 * constraint change, setting of the initial position, or resize.
7247 * (Not resetting these flags here can lead to infinite loops for
7248 * GTK_RESIZE_IMMEDIATE containers)
7250 info->position_constraints_changed = FALSE;
7251 info->initial_pos_set = FALSE;
7252 info->resize_width = -1;
7253 info->resize_height = -1;
7256 /* Compare two sets of Geometry hints for equality.
7259 gtk_window_compare_hints (GdkGeometry *geometry_a,
7261 GdkGeometry *geometry_b,
7264 if (flags_a != flags_b)
7267 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7268 (geometry_a->min_width != geometry_b->min_width ||
7269 geometry_a->min_height != geometry_b->min_height))
7272 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7273 (geometry_a->max_width != geometry_b->max_width ||
7274 geometry_a->max_height != geometry_b->max_height))
7277 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7278 (geometry_a->base_width != geometry_b->base_width ||
7279 geometry_a->base_height != geometry_b->base_height))
7282 if ((flags_a & GDK_HINT_ASPECT) &&
7283 (geometry_a->min_aspect != geometry_b->min_aspect ||
7284 geometry_a->max_aspect != geometry_b->max_aspect))
7287 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7288 (geometry_a->width_inc != geometry_b->width_inc ||
7289 geometry_a->height_inc != geometry_b->height_inc))
7292 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7293 geometry_a->win_gravity != geometry_b->win_gravity)
7300 _gtk_window_constrain_size (GtkWindow *window,
7306 GtkWindowPrivate *priv;
7307 GtkWindowGeometryInfo *info;
7309 g_return_if_fail (GTK_IS_WINDOW (window));
7311 priv = window->priv;
7313 info = priv->geometry_info;
7316 GdkWindowHints flags = info->last.flags;
7317 GdkGeometry *geometry = &info->last.geometry;
7319 gtk_window_constrain_size (window,
7330 gtk_window_constrain_size (GtkWindow *window,
7331 GdkGeometry *geometry,
7338 gdk_window_constrain_size (geometry, flags, width, height,
7339 new_width, new_height);
7342 /* Compute the set of geometry hints and flags for a window
7343 * based on the application set geometry, and requisition
7344 * of the window. gtk_widget_get_preferred_size() must have been
7348 gtk_window_compute_hints (GtkWindow *window,
7349 GdkGeometry *new_geometry,
7352 GtkWindowPrivate *priv = window->priv;
7354 gint extra_width = 0;
7355 gint extra_height = 0;
7356 GtkWindowGeometryInfo *geometry_info;
7357 GtkRequisition requisition;
7359 widget = GTK_WIDGET (window);
7361 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7362 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7366 *new_flags = geometry_info->mask;
7367 *new_geometry = geometry_info->geometry;
7374 if (geometry_info && geometry_info->widget)
7376 /* If the geometry widget is set, then the hints really apply to that
7377 * widget. This is pretty much meaningless unless the window layout
7378 * is such that the rest of the window adds fixed size borders to
7379 * the geometry widget. Our job is to figure the size of the borders;
7380 * We do that by asking how big the toplevel would be if the
7381 * geometry widget was *really big*.
7384 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7385 * |GGGGG B| in the border can confuse things
7391 * |AAAAAAAAA | When the geometry widget is large, things are
7392 * |GGGGGGGGGGB| clearer.
7397 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7398 GtkRequisition requisition;
7399 int current_width, current_height;
7401 _gtk_widget_override_size_request (geometry_info->widget,
7402 TEMPORARY_SIZE, TEMPORARY_SIZE,
7403 ¤t_width, ¤t_height);
7404 gtk_widget_get_preferred_size (widget,
7405 &requisition, NULL);
7406 _gtk_widget_restore_size_request (geometry_info->widget,
7407 current_width, current_height);
7409 extra_width = requisition.width - TEMPORARY_SIZE;
7410 extra_height = requisition.height - TEMPORARY_SIZE;
7412 if (extra_width < 0 || extra_height < 0)
7414 g_warning("Toplevel size doesn't seem to directly depend on the "
7415 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7416 "The geometry widget might not be in the window, or it might not "
7417 "be packed into the window appropriately");
7418 extra_width = MAX(extra_width, 0);
7419 extra_height = MAX(extra_height, 0);
7421 #undef TEMPORARY_SIZE
7424 /* We don't want to set GDK_HINT_POS in here, we just set it
7425 * in gtk_window_move_resize() when we want the position
7429 if (*new_flags & GDK_HINT_BASE_SIZE)
7431 new_geometry->base_width += extra_width;
7432 new_geometry->base_height += extra_height;
7436 /* For simplicity, we always set the base hint, even when we
7437 * don't expect it to have any visible effect.
7438 * (Note: geometry_size_to_pixels() depends on this.)
7440 *new_flags |= GDK_HINT_BASE_SIZE;
7442 new_geometry->base_width = extra_width;
7443 new_geometry->base_height = extra_height;
7445 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7446 * base size is the minimum size */
7447 if (*new_flags & GDK_HINT_MIN_SIZE)
7449 if (new_geometry->min_width > 0)
7450 new_geometry->base_width += new_geometry->min_width;
7451 if (new_geometry->min_height > 0)
7452 new_geometry->base_height += new_geometry->min_height;
7456 /* Please use a good size for unresizable widgets, not the minimum one. */
7457 if (!priv->resizable)
7458 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7460 if (*new_flags & GDK_HINT_MIN_SIZE)
7462 if (new_geometry->min_width < 0)
7463 new_geometry->min_width = requisition.width;
7465 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7467 if (new_geometry->min_height < 0)
7468 new_geometry->min_height = requisition.height;
7470 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7474 *new_flags |= GDK_HINT_MIN_SIZE;
7476 new_geometry->min_width = requisition.width;
7477 new_geometry->min_height = requisition.height;
7480 if (*new_flags & GDK_HINT_MAX_SIZE)
7482 if (new_geometry->max_width < 0)
7483 new_geometry->max_width = requisition.width;
7485 new_geometry->max_width += extra_width;
7487 if (new_geometry->max_height < 0)
7488 new_geometry->max_height = requisition.height;
7490 new_geometry->max_height += extra_height;
7492 else if (!priv->resizable)
7494 *new_flags |= GDK_HINT_MAX_SIZE;
7496 new_geometry->max_width = requisition.width;
7497 new_geometry->max_height = requisition.height;
7500 *new_flags |= GDK_HINT_WIN_GRAVITY;
7501 new_geometry->win_gravity = priv->gravity;
7504 /***********************
7505 * Redrawing functions *
7506 ***********************/
7509 gtk_window_draw (GtkWidget *widget,
7512 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7513 GtkStyleContext *context;
7514 gboolean ret = FALSE;
7516 context = gtk_widget_get_style_context (widget);
7518 gtk_style_context_save (context);
7520 if (!gtk_widget_get_app_paintable (widget) &&
7521 gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
7523 GtkStateFlags state;
7525 state = gtk_widget_get_state_flags (widget);
7527 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7528 state |= GTK_STATE_FLAG_FOCUSED;
7530 gtk_style_context_set_state (context, state);
7531 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7532 gtk_render_background (context, cr, 0, 0,
7533 gtk_widget_get_allocated_width (widget),
7534 gtk_widget_get_allocated_height (widget));
7537 gtk_style_context_restore (context);
7539 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7540 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7542 if (priv->grip_window &&
7543 gtk_cairo_should_draw_window (cr, priv->grip_window))
7547 gtk_style_context_save (context);
7550 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7551 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7553 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7554 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7555 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7558 gtk_style_context_restore (context);
7565 * gtk_window_present:
7566 * @window: a #GtkWindow
7568 * Presents a window to the user. This may mean raising the window
7569 * in the stacking order, deiconifying it, moving it to the current
7570 * desktop, and/or giving it the keyboard focus, possibly dependent
7571 * on the user's platform, window manager, and preferences.
7573 * If @window is hidden, this function calls gtk_widget_show()
7576 * This function should be used when the user tries to open a window
7577 * that's already open. Say for example the preferences dialog is
7578 * currently open, and the user chooses Preferences from the menu
7579 * a second time; use gtk_window_present() to move the already-open dialog
7580 * where the user can see it.
7582 * If you are calling this function in response to a user interaction,
7583 * it is preferable to use gtk_window_present_with_time().
7587 gtk_window_present (GtkWindow *window)
7589 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7593 * gtk_window_present_with_time:
7594 * @window: a #GtkWindow
7595 * @timestamp: the timestamp of the user interaction (typically a
7596 * button or key press event) which triggered this call
7598 * Presents a window to the user in response to a user interaction.
7599 * If you need to present a window without a timestamp, use
7600 * gtk_window_present(). See gtk_window_present() for details.
7605 gtk_window_present_with_time (GtkWindow *window,
7608 GtkWindowPrivate *priv;
7610 GdkWindow *gdk_window;
7612 g_return_if_fail (GTK_IS_WINDOW (window));
7614 priv = window->priv;
7615 widget = GTK_WIDGET (window);
7617 if (gtk_widget_get_visible (widget))
7619 gdk_window = gtk_widget_get_window (widget);
7621 g_assert (gdk_window != NULL);
7623 gdk_window_show (gdk_window);
7625 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7626 if (timestamp == GDK_CURRENT_TIME)
7628 #ifdef GDK_WINDOWING_X11
7629 if (GDK_IS_X11_WINDOW(gdk_window))
7631 GdkDisplay *display;
7633 display = gtk_widget_get_display (GTK_WIDGET (window));
7634 timestamp = gdk_x11_display_get_user_time (display);
7638 timestamp = gtk_get_current_event_time ();
7641 gdk_window_focus (gdk_window, timestamp);
7645 priv->initial_timestamp = timestamp;
7646 gtk_widget_show (widget);
7651 * gtk_window_iconify:
7652 * @window: a #GtkWindow
7654 * Asks to iconify (i.e. minimize) the specified @window. Note that
7655 * you shouldn't assume the window is definitely iconified afterward,
7656 * because other entities (e.g. the user or <link
7657 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7658 * again, or there may not be a window manager in which case
7659 * iconification isn't possible, etc. But normally the window will end
7660 * up iconified. Just don't write code that crashes if not.
7662 * It's permitted to call this function before showing a window,
7663 * in which case the window will be iconified before it ever appears
7666 * You can track iconification via the "window-state-event" signal
7671 gtk_window_iconify (GtkWindow *window)
7673 GtkWindowPrivate *priv;
7675 GdkWindow *toplevel;
7677 g_return_if_fail (GTK_IS_WINDOW (window));
7679 priv = window->priv;
7680 widget = GTK_WIDGET (window);
7682 priv->iconify_initially = TRUE;
7684 toplevel = gtk_widget_get_window (widget);
7686 if (toplevel != NULL)
7687 gdk_window_iconify (toplevel);
7691 * gtk_window_deiconify:
7692 * @window: a #GtkWindow
7694 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7695 * that you shouldn't assume the window is definitely deiconified
7696 * afterward, because other entities (e.g. the user or <link
7697 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7698 * again before your code which assumes deiconification gets to run.
7700 * You can track iconification via the "window-state-event" signal
7704 gtk_window_deiconify (GtkWindow *window)
7706 GtkWindowPrivate *priv;
7708 GdkWindow *toplevel;
7710 g_return_if_fail (GTK_IS_WINDOW (window));
7712 priv = window->priv;
7713 widget = GTK_WIDGET (window);
7715 priv->iconify_initially = FALSE;
7717 toplevel = gtk_widget_get_window (widget);
7719 if (toplevel != NULL)
7720 gdk_window_deiconify (toplevel);
7725 * @window: a #GtkWindow
7727 * Asks to stick @window, which means that it will appear on all user
7728 * desktops. Note that you shouldn't assume the window is definitely
7729 * stuck afterward, because other entities (e.g. the user or <link
7730 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7731 * again, and some window managers do not support sticking
7732 * windows. But normally the window will end up stuck. Just don't
7733 * write code that crashes if not.
7735 * It's permitted to call this function before showing a window.
7737 * You can track stickiness via the "window-state-event" signal
7742 gtk_window_stick (GtkWindow *window)
7744 GtkWindowPrivate *priv;
7746 GdkWindow *toplevel;
7748 g_return_if_fail (GTK_IS_WINDOW (window));
7750 priv = window->priv;
7751 widget = GTK_WIDGET (window);
7753 priv->stick_initially = TRUE;
7755 toplevel = gtk_widget_get_window (widget);
7757 if (toplevel != NULL)
7758 gdk_window_stick (toplevel);
7762 * gtk_window_unstick:
7763 * @window: a #GtkWindow
7765 * Asks to unstick @window, which means that it will appear on only
7766 * one of the user's desktops. Note that you shouldn't assume the
7767 * window is definitely unstuck afterward, because other entities
7768 * (e.g. the user or <link linkend="gtk-X11-arch">window
7769 * manager</link>) could stick it again. But normally the window will
7770 * end up stuck. Just don't write code that crashes if not.
7772 * You can track stickiness via the "window-state-event" signal
7777 gtk_window_unstick (GtkWindow *window)
7779 GtkWindowPrivate *priv;
7781 GdkWindow *toplevel;
7783 g_return_if_fail (GTK_IS_WINDOW (window));
7785 priv = window->priv;
7786 widget = GTK_WIDGET (window);
7788 priv->stick_initially = FALSE;
7790 toplevel = gtk_widget_get_window (widget);
7792 if (toplevel != NULL)
7793 gdk_window_unstick (toplevel);
7797 * gtk_window_maximize:
7798 * @window: a #GtkWindow
7800 * Asks to maximize @window, so that it becomes full-screen. Note that
7801 * you shouldn't assume the window is definitely maximized afterward,
7802 * because other entities (e.g. the user or <link
7803 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7804 * again, and not all window managers support maximization. But
7805 * normally the window will end up maximized. Just don't write code
7806 * that crashes if not.
7808 * It's permitted to call this function before showing a window,
7809 * in which case the window will be maximized when it appears onscreen
7812 * You can track maximization via the "window-state-event" signal
7817 gtk_window_maximize (GtkWindow *window)
7819 GtkWindowPrivate *priv;
7821 GdkWindow *toplevel;
7823 g_return_if_fail (GTK_IS_WINDOW (window));
7825 priv = window->priv;
7826 widget = GTK_WIDGET (window);
7828 priv->maximize_initially = TRUE;
7830 toplevel = gtk_widget_get_window (widget);
7832 if (toplevel != NULL)
7833 gdk_window_maximize (toplevel);
7837 * gtk_window_unmaximize:
7838 * @window: a #GtkWindow
7840 * Asks to unmaximize @window. Note that you shouldn't assume the
7841 * window is definitely unmaximized afterward, because other entities
7842 * (e.g. the user or <link linkend="gtk-X11-arch">window
7843 * manager</link>) could maximize it again, and not all window
7844 * managers honor requests to unmaximize. But normally the window will
7845 * end up unmaximized. Just don't write code that crashes if not.
7847 * You can track maximization via the "window-state-event" signal
7852 gtk_window_unmaximize (GtkWindow *window)
7854 GtkWindowPrivate *priv;
7856 GdkWindow *toplevel;
7858 g_return_if_fail (GTK_IS_WINDOW (window));
7860 priv = window->priv;
7861 widget = GTK_WIDGET (window);
7863 priv->maximize_initially = FALSE;
7865 toplevel = gtk_widget_get_window (widget);
7867 if (toplevel != NULL)
7868 gdk_window_unmaximize (toplevel);
7872 * gtk_window_fullscreen:
7873 * @window: a #GtkWindow
7875 * Asks to place @window in the fullscreen state. Note that you
7876 * shouldn't assume the window is definitely full screen afterward,
7877 * because other entities (e.g. the user or <link
7878 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7879 * again, and not all window managers honor requests to fullscreen
7880 * windows. But normally the window will end up fullscreen. Just
7881 * don't write code that crashes if not.
7883 * You can track the fullscreen state via the "window-state-event" signal
7889 gtk_window_fullscreen (GtkWindow *window)
7891 GtkWindowPrivate *priv;
7893 GdkWindow *toplevel;
7895 g_return_if_fail (GTK_IS_WINDOW (window));
7897 priv = window->priv;
7898 widget = GTK_WIDGET (window);
7900 priv->fullscreen_initially = TRUE;
7902 toplevel = gtk_widget_get_window (widget);
7904 if (toplevel != NULL)
7905 gdk_window_fullscreen (toplevel);
7909 * gtk_window_unfullscreen:
7910 * @window: a #GtkWindow
7912 * Asks to toggle off the fullscreen state for @window. Note that you
7913 * shouldn't assume the window is definitely not full screen
7914 * afterward, because other entities (e.g. the user or <link
7915 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7916 * again, and not all window managers honor requests to unfullscreen
7917 * windows. But normally the window will end up restored to its normal
7918 * state. Just don't write code that crashes if not.
7920 * You can track the fullscreen state via the "window-state-event" signal
7926 gtk_window_unfullscreen (GtkWindow *window)
7929 GdkWindow *toplevel;
7930 GtkWindowPrivate *priv;
7932 g_return_if_fail (GTK_IS_WINDOW (window));
7934 priv = window->priv;
7935 widget = GTK_WIDGET (window);
7937 priv->fullscreen_initially = FALSE;
7939 toplevel = gtk_widget_get_window (widget);
7941 if (toplevel != NULL)
7942 gdk_window_unfullscreen (toplevel);
7946 * gtk_window_set_keep_above:
7947 * @window: a #GtkWindow
7948 * @setting: whether to keep @window above other windows
7950 * Asks to keep @window above, so that it stays on top. Note that
7951 * you shouldn't assume the window is definitely above afterward,
7952 * because other entities (e.g. the user or <link
7953 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7954 * and not all window managers support keeping windows above. But
7955 * normally the window will end kept above. Just don't write code
7956 * that crashes if not.
7958 * It's permitted to call this function before showing a window,
7959 * in which case the window will be kept above when it appears onscreen
7962 * You can track the above state via the "window-state-event" signal
7965 * Note that, according to the <ulink
7966 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7967 * Manager Hints</ulink> specification, the above state is mainly meant
7968 * for user preferences and should not be used by applications e.g. for
7969 * drawing attention to their dialogs.
7974 gtk_window_set_keep_above (GtkWindow *window,
7978 GtkWindowPrivate *priv;
7979 GdkWindow *toplevel;
7981 g_return_if_fail (GTK_IS_WINDOW (window));
7983 priv = window->priv;
7984 widget = GTK_WIDGET (window);
7986 priv->above_initially = setting != FALSE;
7988 priv->below_initially = FALSE;
7990 toplevel = gtk_widget_get_window (widget);
7992 if (toplevel != NULL)
7993 gdk_window_set_keep_above (toplevel, setting);
7997 * gtk_window_set_keep_below:
7998 * @window: a #GtkWindow
7999 * @setting: whether to keep @window below other windows
8001 * Asks to keep @window below, so that it stays in bottom. Note that
8002 * you shouldn't assume the window is definitely below afterward,
8003 * because other entities (e.g. the user or <link
8004 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8005 * and not all window managers support putting windows below. But
8006 * normally the window will be kept below. Just don't write code
8007 * that crashes if not.
8009 * It's permitted to call this function before showing a window,
8010 * in which case the window will be kept below when it appears onscreen
8013 * You can track the below state via the "window-state-event" signal
8016 * Note that, according to the <ulink
8017 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8018 * Manager Hints</ulink> specification, the above state is mainly meant
8019 * for user preferences and should not be used by applications e.g. for
8020 * drawing attention to their dialogs.
8025 gtk_window_set_keep_below (GtkWindow *window,
8029 GtkWindowPrivate *priv;
8030 GdkWindow *toplevel;
8032 g_return_if_fail (GTK_IS_WINDOW (window));
8034 priv = window->priv;
8035 widget = GTK_WIDGET (window);
8037 priv->below_initially = setting != FALSE;
8039 priv->above_initially = FALSE;
8041 toplevel = gtk_widget_get_window (widget);
8043 if (toplevel != NULL)
8044 gdk_window_set_keep_below (toplevel, setting);
8048 * gtk_window_set_resizable:
8049 * @window: a #GtkWindow
8050 * @resizable: %TRUE if the user can resize this window
8052 * Sets whether the user can resize a window. Windows are user resizable
8056 gtk_window_set_resizable (GtkWindow *window,
8059 GtkWindowPrivate *priv;
8061 g_return_if_fail (GTK_IS_WINDOW (window));
8063 priv = window->priv;
8065 resizable = (resizable != FALSE);
8067 if (priv->resizable != resizable)
8069 priv->resizable = (resizable != FALSE);
8071 update_grip_visibility (window);
8073 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8075 g_object_notify (G_OBJECT (window), "resizable");
8080 * gtk_window_get_resizable:
8081 * @window: a #GtkWindow
8083 * Gets the value set by gtk_window_set_resizable().
8085 * Return value: %TRUE if the user can resize the window
8088 gtk_window_get_resizable (GtkWindow *window)
8090 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8092 return window->priv->resizable;
8096 * gtk_window_set_gravity:
8097 * @window: a #GtkWindow
8098 * @gravity: window gravity
8100 * Window gravity defines the meaning of coordinates passed to
8101 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8104 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8105 * typically "do what you mean."
8109 gtk_window_set_gravity (GtkWindow *window,
8112 GtkWindowPrivate *priv;
8114 g_return_if_fail (GTK_IS_WINDOW (window));
8116 priv = window->priv;
8118 if (gravity != priv->gravity)
8120 priv->gravity = gravity;
8122 /* gtk_window_move_resize() will adapt gravity
8124 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8126 g_object_notify (G_OBJECT (window), "gravity");
8131 * gtk_window_get_gravity:
8132 * @window: a #GtkWindow
8134 * Gets the value set by gtk_window_set_gravity().
8136 * Return value: (transfer none): window gravity
8139 gtk_window_get_gravity (GtkWindow *window)
8141 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8143 return window->priv->gravity;
8147 * gtk_window_begin_resize_drag:
8148 * @window: a #GtkWindow
8149 * @button: mouse button that initiated the drag
8150 * @edge: position of the resize control
8151 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8152 * @root_y: Y position where the user clicked to initiate the drag
8153 * @timestamp: timestamp from the click event that initiated the drag
8155 * Starts resizing a window. This function is used if an application
8156 * has window resizing controls. When GDK can support it, the resize
8157 * will be done using the standard mechanism for the <link
8158 * linkend="gtk-X11-arch">window manager</link> or windowing
8159 * system. Otherwise, GDK will try to emulate window resizing,
8160 * potentially not all that well, depending on the windowing system.
8164 gtk_window_begin_resize_drag (GtkWindow *window,
8172 GdkWindow *toplevel;
8174 g_return_if_fail (GTK_IS_WINDOW (window));
8175 widget = GTK_WIDGET (window);
8176 g_return_if_fail (gtk_widget_get_visible (widget));
8178 toplevel = gtk_widget_get_window (widget);
8180 gdk_window_begin_resize_drag (toplevel,
8187 * gtk_window_begin_move_drag:
8188 * @window: a #GtkWindow
8189 * @button: mouse button that initiated the drag
8190 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8191 * @root_y: Y position where the user clicked to initiate the drag
8192 * @timestamp: timestamp from the click event that initiated the drag
8194 * Starts moving a window. This function is used if an application has
8195 * window movement grips. When GDK can support it, the window movement
8196 * will be done using the standard mechanism for the <link
8197 * linkend="gtk-X11-arch">window manager</link> or windowing
8198 * system. Otherwise, GDK will try to emulate window movement,
8199 * potentially not all that well, depending on the windowing system.
8203 gtk_window_begin_move_drag (GtkWindow *window,
8210 GdkWindow *toplevel;
8212 g_return_if_fail (GTK_IS_WINDOW (window));
8213 widget = GTK_WIDGET (window);
8214 g_return_if_fail (gtk_widget_get_visible (widget));
8216 toplevel = gtk_widget_get_window (widget);
8218 gdk_window_begin_move_drag (toplevel,
8225 * gtk_window_set_screen:
8226 * @window: a #GtkWindow.
8227 * @screen: a #GdkScreen.
8229 * Sets the #GdkScreen where the @window is displayed; if
8230 * the window is already mapped, it will be unmapped, and
8231 * then remapped on the new screen.
8236 gtk_window_set_screen (GtkWindow *window,
8239 GtkWindowPrivate *priv;
8241 GdkScreen *previous_screen;
8242 gboolean was_mapped;
8244 g_return_if_fail (GTK_IS_WINDOW (window));
8245 g_return_if_fail (GDK_IS_SCREEN (screen));
8247 priv = window->priv;
8249 if (screen == priv->screen)
8252 widget = GTK_WIDGET (window);
8254 previous_screen = priv->screen;
8255 was_mapped = gtk_widget_get_mapped (widget);
8258 gtk_widget_unmap (widget);
8259 if (gtk_widget_get_realized (widget))
8260 gtk_widget_unrealize (widget);
8262 gtk_window_free_key_hash (window);
8263 priv->screen = screen;
8264 gtk_widget_reset_rc_styles (widget);
8265 if (screen != previous_screen)
8267 if (previous_screen)
8269 g_signal_handlers_disconnect_by_func (previous_screen,
8270 gtk_window_on_composited_changed, window);
8271 #ifdef GDK_WINDOWING_X11
8272 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8273 gtk_window_on_theme_variant_changed, window);
8276 g_signal_connect (screen, "composited-changed",
8277 G_CALLBACK (gtk_window_on_composited_changed), window);
8278 #ifdef GDK_WINDOWING_X11
8279 g_signal_connect (gtk_settings_get_for_screen (screen),
8280 "notify::gtk-application-prefer-dark-theme",
8281 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8284 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8285 _gtk_widget_propagate_composited_changed (widget);
8287 g_object_notify (G_OBJECT (window), "screen");
8290 gtk_widget_map (widget);
8294 gtk_window_set_theme_variant (GtkWindow *window)
8296 #ifdef GDK_WINDOWING_X11
8297 GdkWindow *gdk_window;
8298 gboolean dark_theme_requested;
8300 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8301 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8304 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8306 if (GDK_IS_X11_WINDOW (gdk_window))
8307 gdk_x11_window_set_theme_variant (gdk_window,
8308 dark_theme_requested ? "dark" : NULL);
8313 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8317 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8318 gtk_window_set_theme_variant (window);
8322 gtk_window_on_composited_changed (GdkScreen *screen,
8325 gtk_widget_queue_draw (GTK_WIDGET (window));
8327 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8331 gtk_window_check_screen (GtkWindow *window)
8333 GtkWindowPrivate *priv = window->priv;
8336 return priv->screen;
8339 g_warning ("Screen for GtkWindow not set; you must always set\n"
8340 "a screen for a GtkWindow before using the window");
8346 * gtk_window_get_screen:
8347 * @window: a #GtkWindow.
8349 * Returns the #GdkScreen associated with @window.
8351 * Return value: (transfer none): a #GdkScreen.
8356 gtk_window_get_screen (GtkWindow *window)
8358 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8360 return window->priv->screen;
8364 * gtk_window_is_active:
8365 * @window: a #GtkWindow
8367 * Returns whether the window is part of the current active toplevel.
8368 * (That is, the toplevel window receiving keystrokes.)
8369 * The return value is %TRUE if the window is active toplevel
8370 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8371 * You might use this function if you wanted to draw a widget
8372 * differently in an active window from a widget in an inactive window.
8373 * See gtk_window_has_toplevel_focus()
8375 * Return value: %TRUE if the window part of the current active window.
8380 gtk_window_is_active (GtkWindow *window)
8382 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8384 return window->priv->is_active;
8388 * gtk_window_has_toplevel_focus:
8389 * @window: a #GtkWindow
8391 * Returns whether the input focus is within this GtkWindow.
8392 * For real toplevel windows, this is identical to gtk_window_is_active(),
8393 * but for embedded windows, like #GtkPlug, the results will differ.
8395 * Return value: %TRUE if the input focus is within this GtkWindow
8400 gtk_window_has_toplevel_focus (GtkWindow *window)
8402 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8404 return window->priv->has_toplevel_focus;
8409 * SECTION:gtkwindowgroup
8410 * @Short_description: Limit the effect of grabs
8411 * @Title: GtkWindowGroup
8413 * #GtkWindowGroup objects are referenced by each window in the group,
8414 * so once you have added all windows to a #GtkWindowGroup, you can drop
8415 * the initial reference to the window group with g_object_unref(). If the
8416 * windows in the window group are subsequently destroyed, then they will
8417 * be removed from the window group and drop their references on the window
8418 * group; when all window have been removed, the window group will be
8422 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8425 gtk_window_group_init (GtkWindowGroup *group)
8427 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8428 GTK_TYPE_WINDOW_GROUP,
8429 GtkWindowGroupPrivate);
8433 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8435 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8439 * gtk_window_group_new:
8441 * Creates a new #GtkWindowGroup object. Grabs added with
8442 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8444 * Return value: a new #GtkWindowGroup.
8447 gtk_window_group_new (void)
8449 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8453 window_group_cleanup_grabs (GtkWindowGroup *group,
8456 GtkWindowGroupPrivate *priv;
8457 GtkDeviceGrabInfo *info;
8459 GSList *to_remove = NULL;
8463 tmp_list = priv->grabs;
8466 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8467 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8468 tmp_list = tmp_list->next;
8473 gtk_grab_remove (to_remove->data);
8474 g_object_unref (to_remove->data);
8475 to_remove = g_slist_delete_link (to_remove, to_remove);
8478 tmp_list = priv->device_grabs;
8482 info = tmp_list->data;
8484 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8485 to_remove = g_slist_prepend (to_remove, info);
8487 tmp_list = tmp_list->next;
8492 info = to_remove->data;
8494 gtk_device_grab_remove (info->widget, info->device);
8495 to_remove = g_slist_delete_link (to_remove, to_remove);
8500 * gtk_window_group_add_window:
8501 * @window_group: a #GtkWindowGroup
8502 * @window: the #GtkWindow to add
8504 * Adds a window to a #GtkWindowGroup.
8507 gtk_window_group_add_window (GtkWindowGroup *window_group,
8510 GtkWindowPrivate *priv;
8512 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8513 g_return_if_fail (GTK_IS_WINDOW (window));
8515 priv = window->priv;
8517 if (priv->group != window_group)
8519 g_object_ref (window);
8520 g_object_ref (window_group);
8523 gtk_window_group_remove_window (priv->group, window);
8525 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8527 priv->group = window_group;
8529 g_object_unref (window);
8534 * gtk_window_group_remove_window:
8535 * @window_group: a #GtkWindowGroup
8536 * @window: the #GtkWindow to remove
8538 * Removes a window from a #GtkWindowGroup.
8541 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8544 GtkWindowPrivate *priv;
8546 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8547 g_return_if_fail (GTK_IS_WINDOW (window));
8548 priv = window->priv;
8549 g_return_if_fail (priv->group == window_group);
8551 g_object_ref (window);
8553 window_group_cleanup_grabs (window_group, window);
8556 g_object_unref (window_group);
8557 g_object_unref (window);
8561 * gtk_window_group_list_windows:
8562 * @window_group: a #GtkWindowGroup
8564 * Returns a list of the #GtkWindows that belong to @window_group.
8566 * Returns: (element-type GtkWindow) (transfer container): A
8567 * newly-allocated list of windows inside the group.
8572 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8574 GList *toplevels, *toplevel, *group_windows;
8576 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8578 group_windows = NULL;
8579 toplevels = gtk_window_list_toplevels ();
8581 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8583 GtkWindow *window = toplevel->data;
8585 if (window_group == window->priv->group)
8586 group_windows = g_list_prepend (group_windows, window);
8589 g_list_free (toplevels);
8591 return g_list_reverse (group_windows);
8595 * gtk_window_get_group:
8596 * @window: (allow-none): a #GtkWindow, or %NULL
8598 * Returns the group for @window or the default group, if
8599 * @window is %NULL or if @window does not have an explicit
8602 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8607 gtk_window_get_group (GtkWindow *window)
8609 if (window && window->priv->group)
8610 return window->priv->group;
8613 static GtkWindowGroup *default_group = NULL;
8616 default_group = gtk_window_group_new ();
8618 return default_group;
8623 * gtk_window_has_group:
8624 * @window: a #GtkWindow
8626 * Returns whether @window has an explicit window group.
8628 * Return value: %TRUE if @window has an explicit window group.
8633 gtk_window_has_group (GtkWindow *window)
8635 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8637 return window->priv->group != NULL;
8641 * gtk_window_group_get_current_grab:
8642 * @window_group: a #GtkWindowGroup
8644 * Gets the current grab widget of the given group,
8645 * see gtk_grab_add().
8647 * Returns: (transfer none): the current grab widget of the group
8652 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8654 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8656 if (window_group->priv->grabs)
8657 return GTK_WIDGET (window_group->priv->grabs->data);
8662 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8665 GtkWindowGroupPrivate *priv;
8667 priv = window_group->priv;
8668 priv->grabs = g_slist_prepend (priv->grabs, widget);
8672 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8675 GtkWindowGroupPrivate *priv;
8677 priv = window_group->priv;
8678 priv->grabs = g_slist_remove (priv->grabs, widget);
8683 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8686 gboolean block_others)
8688 GtkWindowGroupPrivate *priv;
8689 GtkDeviceGrabInfo *info;
8691 priv = window_group->priv;
8693 info = g_slice_new0 (GtkDeviceGrabInfo);
8694 info->widget = widget;
8695 info->device = device;
8696 info->block_others = block_others;
8698 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8702 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8706 GtkWindowGroupPrivate *priv;
8707 GtkDeviceGrabInfo *info;
8708 GSList *list, *node = NULL;
8709 GdkDevice *other_device;
8711 priv = window_group->priv;
8712 other_device = gdk_device_get_associated_device (device);
8713 list = priv->device_grabs;
8719 if (info->widget == widget &&
8720 (info->device == device ||
8721 info->device == other_device))
8734 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8735 g_slice_free (GtkDeviceGrabInfo, info);
8740 * gtk_window_group_get_current_device_grab:
8741 * @window_group: a #GtkWindowGroup
8742 * @device: a #GdkDevice
8744 * Returns the current grab widget for @device, or %NULL if none.
8746 * Returns: (transfer none): The grab widget, or %NULL
8751 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8754 GtkWindowGroupPrivate *priv;
8755 GtkDeviceGrabInfo *info;
8756 GdkDevice *other_device;
8759 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8760 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8762 priv = window_group->priv;
8763 list = priv->device_grabs;
8764 other_device = gdk_device_get_associated_device (device);
8771 if (info->device == device ||
8772 info->device == other_device)
8773 return info->widget;
8780 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8784 GtkWindowGroupPrivate *priv;
8785 GtkDeviceGrabInfo *info;
8786 GdkDevice *other_device;
8789 priv = window_group->priv;
8790 other_device = gdk_device_get_associated_device (device);
8791 list = priv->device_grabs;
8798 /* Look for blocking grabs on other device pairs
8799 * that have the passed widget within the GTK+ grab.
8801 if (info->block_others &&
8802 info->device != device &&
8803 info->device != other_device &&
8804 (info->widget == widget ||
8805 gtk_widget_is_ancestor (widget, info->widget)))
8813 Derived from XParseGeometry() in XFree86
8815 Copyright 1985, 1986, 1987,1998 The Open Group
8817 All Rights Reserved.
8819 The above copyright notice and this permission notice shall be included
8820 in all copies or substantial portions of the Software.
8822 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8823 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8824 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8825 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8826 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8827 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8828 OTHER DEALINGS IN THE SOFTWARE.
8830 Except as contained in this notice, the name of The Open Group shall
8831 not be used in advertising or otherwise to promote the sale, use or
8832 other dealings in this Software without prior written authorization
8833 from The Open Group.
8838 * XParseGeometry parses strings of the form
8839 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8840 * width, height, xoffset, and yoffset are unsigned integers.
8841 * Example: "=80x24+300-49"
8842 * The equal sign is optional.
8843 * It returns a bitmask that indicates which of the four values
8844 * were actually found in the string. For each value found,
8845 * the corresponding argument is updated; for each value
8846 * not found, the corresponding argument is left unchanged.
8849 /* The following code is from Xlib, and is minimally modified, so we
8850 * can track any upstream changes if required. Don't change this
8851 * code. Or if you do, put in a huge comment marking which thing
8856 read_int (gchar *string,
8864 else if (*string == '-')
8870 for (; (*string >= '0') && (*string <= '9'); string++)
8872 result = (result * 10) + (*string - '0');
8884 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8885 * value (x, y, width, height) was found in the parsed string.
8887 #define NoValue 0x0000
8888 #define XValue 0x0001
8889 #define YValue 0x0002
8890 #define WidthValue 0x0004
8891 #define HeightValue 0x0008
8892 #define AllValues 0x000F
8893 #define XNegative 0x0010
8894 #define YNegative 0x0020
8896 /* Try not to reformat/modify, so we can compare/sync with X sources */
8898 gtk_XParseGeometry (const char *string,
8901 unsigned int *width,
8902 unsigned int *height)
8906 unsigned int tempWidth, tempHeight;
8908 char *nextCharacter;
8910 /* These initializations are just to silence gcc */
8916 if ( (string == NULL) || (*string == '\0')) return(mask);
8918 string++; /* ignore possible '=' at beg of geometry spec */
8920 strind = (char *)string;
8921 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8922 tempWidth = read_int(strind, &nextCharacter);
8923 if (strind == nextCharacter)
8925 strind = nextCharacter;
8929 if (*strind == 'x' || *strind == 'X') {
8931 tempHeight = read_int(strind, &nextCharacter);
8932 if (strind == nextCharacter)
8934 strind = nextCharacter;
8935 mask |= HeightValue;
8938 if ((*strind == '+') || (*strind == '-')) {
8939 if (*strind == '-') {
8941 tempX = -read_int(strind, &nextCharacter);
8942 if (strind == nextCharacter)
8944 strind = nextCharacter;
8950 tempX = read_int(strind, &nextCharacter);
8951 if (strind == nextCharacter)
8953 strind = nextCharacter;
8956 if ((*strind == '+') || (*strind == '-')) {
8957 if (*strind == '-') {
8959 tempY = -read_int(strind, &nextCharacter);
8960 if (strind == nextCharacter)
8962 strind = nextCharacter;
8969 tempY = read_int(strind, &nextCharacter);
8970 if (strind == nextCharacter)
8972 strind = nextCharacter;
8978 /* If strind isn't at the end of the string the it's an invalid
8979 geometry specification. */
8981 if (*strind != '\0') return (0);
8987 if (mask & WidthValue)
8989 if (mask & HeightValue)
8990 *height = tempHeight;
8995 * gtk_window_parse_geometry:
8996 * @window: a #GtkWindow
8997 * @geometry: geometry string
8999 * Parses a standard X Window System geometry string - see the
9000 * manual page for X (type 'man X') for details on this.
9001 * gtk_window_parse_geometry() does work on all GTK+ ports
9002 * including Win32 but is primarily intended for an X environment.
9004 * If either a size or a position can be extracted from the
9005 * geometry string, gtk_window_parse_geometry() returns %TRUE
9006 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9007 * to resize/move the window.
9009 * If gtk_window_parse_geometry() returns %TRUE, it will also
9010 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9011 * indicating to the window manager that the size/position of
9012 * the window was user-specified. This causes most window
9013 * managers to honor the geometry.
9015 * Note that for gtk_window_parse_geometry() to work as expected, it has
9016 * to be called when the window has its "final" size, i.e. after calling
9017 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9020 * #include <gtk/gtk.h>
9023 * fill_with_content (GtkWidget *vbox)
9025 * /* fill with content... */
9029 * main (int argc, char *argv[])
9031 * GtkWidget *window, *vbox;
9032 * GdkGeometry size_hints = {
9033 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9036 * gtk_init (&argc, &argv);
9038 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9039 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9041 * gtk_container_add (GTK_CONTAINER (window), vbox);
9042 * fill_with_content (vbox);
9043 * gtk_widget_show_all (vbox);
9045 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9048 * GDK_HINT_MIN_SIZE |
9049 * GDK_HINT_BASE_SIZE |
9050 * GDK_HINT_RESIZE_INC);
9054 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9055 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9058 * gtk_widget_show_all (window);
9065 * Return value: %TRUE if string was parsed successfully
9068 gtk_window_parse_geometry (GtkWindow *window,
9069 const gchar *geometry)
9071 gint result, x = 0, y = 0;
9075 gboolean size_set, pos_set;
9078 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9079 g_return_val_if_fail (geometry != NULL, FALSE);
9081 child = gtk_bin_get_child (GTK_BIN (window));
9082 if (!child || !gtk_widget_get_visible (child))
9083 g_warning ("gtk_window_parse_geometry() called on a window with no "
9084 "visible children; the window should be set up before "
9085 "gtk_window_parse_geometry() is called.");
9087 screen = gtk_window_check_screen (window);
9089 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9092 if ((result & WidthValue) || (result & HeightValue))
9094 gtk_window_set_default_size_internal (window,
9095 TRUE, result & WidthValue ? w : -1,
9096 TRUE, result & HeightValue ? h : -1,
9101 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9103 grav = GDK_GRAVITY_NORTH_WEST;
9105 if ((result & XNegative) && (result & YNegative))
9106 grav = GDK_GRAVITY_SOUTH_EAST;
9107 else if (result & XNegative)
9108 grav = GDK_GRAVITY_NORTH_EAST;
9109 else if (result & YNegative)
9110 grav = GDK_GRAVITY_SOUTH_WEST;
9112 if ((result & XValue) == 0)
9115 if ((result & YValue) == 0)
9118 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9119 grav == GDK_GRAVITY_SOUTH_EAST)
9120 y = gdk_screen_get_height (screen) - h + y;
9122 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9123 grav == GDK_GRAVITY_NORTH_EAST)
9124 x = gdk_screen_get_width (screen) - w + x;
9126 /* we don't let you put a window offscreen; maybe some people would
9127 * prefer to be able to, but it's kind of a bogus thing to do.
9136 if ((result & XValue) || (result & YValue))
9138 gtk_window_set_gravity (window, grav);
9139 gtk_window_move (window, x, y);
9143 if (size_set || pos_set)
9145 /* Set USSize, USPosition hints */
9146 GtkWindowGeometryInfo *info;
9148 info = gtk_window_get_geometry_info (window, TRUE);
9151 info->mask |= GDK_HINT_USER_POS;
9153 info->mask |= GDK_HINT_USER_SIZE;
9160 gtk_window_mnemonic_hash_foreach (guint keyval,
9166 GtkWindowKeysForeachFunc func;
9170 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9174 _gtk_window_keys_foreach (GtkWindow *window,
9175 GtkWindowKeysForeachFunc func,
9179 GtkMnemonicHash *mnemonic_hash;
9183 GtkWindowKeysForeachFunc func;
9187 info.window = window;
9189 info.func_data = func_data;
9191 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9193 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9194 gtk_window_mnemonic_hash_foreach, &info);
9196 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9199 GtkAccelGroup *group = groups->data;
9202 for (i = 0; i < group->priv->n_accels; i++)
9204 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9207 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9210 groups = groups->next;
9215 gtk_window_keys_changed (GtkWindow *window)
9217 gtk_window_free_key_hash (window);
9218 gtk_window_get_key_hash (window);
9221 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9223 struct _GtkWindowKeyEntry
9227 guint is_mnemonic : 1;
9231 window_key_entry_destroy (gpointer data)
9233 g_slice_free (GtkWindowKeyEntry, data);
9237 add_to_key_hash (GtkWindow *window,
9239 GdkModifierType modifiers,
9240 gboolean is_mnemonic,
9243 GtkKeyHash *key_hash = data;
9245 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9247 entry->keyval = keyval;
9248 entry->modifiers = modifiers;
9249 entry->is_mnemonic = is_mnemonic;
9251 /* GtkAccelGroup stores lowercased accelerators. To deal
9252 * with this, if <Shift> was specified, uppercase.
9254 if (modifiers & GDK_SHIFT_MASK)
9256 if (keyval == GDK_KEY_Tab)
9257 keyval = GDK_KEY_ISO_Left_Tab;
9259 keyval = gdk_keyval_to_upper (keyval);
9262 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9266 gtk_window_get_key_hash (GtkWindow *window)
9268 GdkScreen *screen = gtk_window_check_screen (window);
9269 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9274 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9275 (GDestroyNotify)window_key_entry_destroy);
9276 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9277 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9283 gtk_window_free_key_hash (GtkWindow *window)
9285 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9288 _gtk_key_hash_free (key_hash);
9289 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9294 * gtk_window_activate_key:
9295 * @window: a #GtkWindow
9296 * @event: a #GdkEventKey
9298 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9299 * called by the default ::key_press_event handler for toplevel windows,
9300 * however in some cases it may be useful to call this directly when
9301 * overriding the standard key handling for a toplevel window.
9303 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9308 gtk_window_activate_key (GtkWindow *window,
9311 GtkKeyHash *key_hash;
9312 GtkWindowKeyEntry *found_entry = NULL;
9313 gboolean enable_mnemonics;
9314 gboolean enable_accels;
9316 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9317 g_return_val_if_fail (event != NULL, FALSE);
9319 key_hash = gtk_window_get_key_hash (window);
9324 GSList *entries = _gtk_key_hash_lookup (key_hash,
9325 event->hardware_keycode,
9327 gtk_accelerator_get_default_mod_mask (),
9330 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9331 "gtk-enable-mnemonics", &enable_mnemonics,
9332 "gtk-enable-accels", &enable_accels,
9335 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9337 GtkWindowKeyEntry *entry = tmp_list->data;
9338 if (entry->is_mnemonic)
9340 if (enable_mnemonics)
9342 found_entry = entry;
9348 if (enable_accels && !found_entry)
9350 found_entry = entry;
9355 g_slist_free (entries);
9360 if (found_entry->is_mnemonic)
9362 if (enable_mnemonics)
9363 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9364 found_entry->modifiers);
9369 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9370 found_entry->modifiers);
9378 window_update_has_focus (GtkWindow *window)
9380 GtkWindowPrivate *priv = window->priv;
9381 GtkWidget *widget = GTK_WIDGET (window);
9382 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9384 if (has_focus != priv->has_focus)
9386 priv->has_focus = has_focus;
9390 if (priv->focus_widget &&
9391 priv->focus_widget != widget &&
9392 !gtk_widget_has_focus (priv->focus_widget))
9393 do_focus_change (priv->focus_widget, TRUE);
9397 if (priv->focus_widget &&
9398 priv->focus_widget != widget &&
9399 gtk_widget_has_focus (priv->focus_widget))
9400 do_focus_change (priv->focus_widget, FALSE);
9406 * _gtk_window_set_is_active:
9407 * @window: a #GtkWindow
9408 * @is_active: %TRUE if the window is in the currently active toplevel
9410 * Internal function that sets whether the #GtkWindow is part
9411 * of the currently active toplevel window (taking into account inter-process
9415 _gtk_window_set_is_active (GtkWindow *window,
9418 GtkWindowPrivate *priv;
9420 g_return_if_fail (GTK_IS_WINDOW (window));
9422 priv = window->priv;
9424 is_active = is_active != FALSE;
9426 if (is_active != priv->is_active)
9428 priv->is_active = is_active;
9429 window_update_has_focus (window);
9431 g_object_notify (G_OBJECT (window), "is-active");
9436 * _gtk_window_set_is_toplevel:
9437 * @window: a #GtkWindow
9438 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9439 * child of the root window); %FALSE if it is not (for example, for an
9440 * in-process, parented GtkPlug)
9442 * Internal function used by #GtkPlug when it gets parented/unparented by a
9443 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9444 * global list of toplevel windows.
9447 _gtk_window_set_is_toplevel (GtkWindow *window,
9448 gboolean is_toplevel)
9451 GtkWidget *toplevel;
9453 widget = GTK_WIDGET (window);
9455 if (gtk_widget_is_toplevel (widget))
9456 g_assert (g_slist_find (toplevel_list, window) != NULL);
9458 g_assert (g_slist_find (toplevel_list, window) == NULL);
9460 if (is_toplevel == gtk_widget_is_toplevel (widget))
9465 /* Pass through regular pathways of an embedded toplevel
9466 * to go through unmapping and hiding the widget before
9467 * becomming a toplevel again.
9469 * We remain hidden after becomming toplevel in order to
9470 * avoid problems during an embedded toplevel's dispose cycle
9471 * (When a toplevel window is shown it tries to grab focus again,
9472 * this causes problems while disposing).
9474 gtk_widget_hide (widget);
9476 /* Save the toplevel this widget was previously anchored into before
9477 * propagating a hierarchy-changed.
9479 * Usually this happens by way of gtk_widget_unparent() and we are
9480 * already unanchored at this point, just adding this clause incase
9481 * things happen differently.
9483 toplevel = gtk_widget_get_toplevel (widget);
9484 if (!gtk_widget_is_toplevel (toplevel))
9487 _gtk_widget_set_is_toplevel (widget, TRUE);
9489 /* When a window becomes toplevel after being embedded and anchored
9490 * into another window we need to unset its anchored flag so that
9491 * the hierarchy changed signal kicks in properly.
9493 _gtk_widget_set_anchored (widget, FALSE);
9494 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9496 toplevel_list = g_slist_prepend (toplevel_list, window);
9500 _gtk_widget_set_is_toplevel (widget, FALSE);
9501 toplevel_list = g_slist_remove (toplevel_list, window);
9503 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9508 * _gtk_window_set_has_toplevel_focus:
9509 * @window: a #GtkWindow
9510 * @has_toplevel_focus: %TRUE if the in
9512 * Internal function that sets whether the keyboard focus for the
9513 * toplevel window (taking into account inter-process embedding.)
9516 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9517 gboolean has_toplevel_focus)
9519 GtkWindowPrivate *priv;
9521 g_return_if_fail (GTK_IS_WINDOW (window));
9523 priv = window->priv;
9525 has_toplevel_focus = has_toplevel_focus != FALSE;
9527 if (has_toplevel_focus != priv->has_toplevel_focus)
9529 priv->has_toplevel_focus = has_toplevel_focus;
9530 window_update_has_focus (window);
9532 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9537 * gtk_window_set_auto_startup_notification:
9538 * @setting: %TRUE to automatically do startup notification
9540 * By default, after showing the first #GtkWindow, GTK+ calls
9541 * gdk_notify_startup_complete(). Call this function to disable
9542 * the automatic startup notification. You might do this if your
9543 * first window is a splash screen, and you want to delay notification
9544 * until after your real main window has been shown, for example.
9546 * In that example, you would disable startup notification
9547 * temporarily, show your splash screen, then re-enable it so that
9548 * showing the main window would automatically result in notification.
9553 gtk_window_set_auto_startup_notification (gboolean setting)
9555 disable_startup_notification = !setting;
9559 * gtk_window_get_window_type:
9560 * @window: a #GtkWindow
9562 * Gets the type of the window. See #GtkWindowType.
9564 * Return value: the type of the window
9569 gtk_window_get_window_type (GtkWindow *window)
9571 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9573 return window->priv->type;
9577 * gtk_window_get_mnemonics_visible:
9578 * @window: a #GtkWindow
9580 * Gets the value of the #GtkWindow:mnemonics-visible property.
9582 * Returns: %TRUE if mnemonics are supposed to be visible
9588 gtk_window_get_mnemonics_visible (GtkWindow *window)
9590 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9592 return window->priv->mnemonics_visible;
9596 * gtk_window_set_mnemonics_visible:
9597 * @window: a #GtkWindow
9598 * @setting: the new value
9600 * Sets the #GtkWindow:mnemonics-visible property.
9605 gtk_window_set_mnemonics_visible (GtkWindow *window,
9608 GtkWindowPrivate *priv;
9610 g_return_if_fail (GTK_IS_WINDOW (window));
9612 priv = window->priv;
9614 setting = setting != FALSE;
9616 if (priv->mnemonics_visible != setting)
9618 priv->mnemonics_visible = setting;
9619 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9622 priv->mnemonics_visible_set = TRUE;
9626 * gtk_window_get_focus_visible:
9627 * @window: a #GtkWindow
9629 * Gets the value of the #GtkWindow:focus-visible property.
9631 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9637 gtk_window_get_focus_visible (GtkWindow *window)
9639 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9641 return window->priv->focus_visible;
9645 * gtk_window_set_focus_visible:
9646 * @window: a #GtkWindow
9647 * @setting: the new value
9649 * Sets the #GtkWindow:focus-visible property.
9654 gtk_window_set_focus_visible (GtkWindow *window,
9657 GtkWindowPrivate *priv;
9659 g_return_if_fail (GTK_IS_WINDOW (window));
9661 priv = window->priv;
9663 setting = setting != FALSE;
9665 if (priv->focus_visible != setting)
9667 priv->focus_visible = setting;
9668 g_object_notify (G_OBJECT (window), "focus-visible");
9673 _gtk_window_get_wmclass (GtkWindow *window,
9674 gchar **wmclass_name,
9675 gchar **wmclass_class)
9677 GtkWindowPrivate *priv = window->priv;
9679 *wmclass_name = priv->wmclass_name;
9680 *wmclass_class = priv->wmclass_class;
9684 * gtk_window_set_has_user_ref_count:
9685 * @window: a #GtkWindow
9686 * @setting: the new value
9688 * Tells GTK+ whether to drop its extra reference to the window
9689 * when gtk_window_destroy() is called.
9691 * This function is only exported for the benefit of language
9692 * bindings which may need to keep the window alive until their
9693 * wrapper object is garbage collected. There is no justification
9694 * for ever calling this function in an application.
9699 gtk_window_set_has_user_ref_count (GtkWindow *window,
9702 g_return_if_fail (GTK_IS_WINDOW (window));
9704 window->priv->has_user_ref_count = setting;
9708 ensure_state_flag_window_unfocused (GtkWidget *widget)
9711 gboolean window_focused = TRUE;
9713 window = gtk_widget_get_window (widget);
9715 window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9717 if (!window_focused)
9718 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED, FALSE);
9720 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED);
9722 gtk_widget_queue_draw (widget);