1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gtkwindow.h"
36 #include "gtkprivate.h"
38 #include "gtkwindowprivate.h"
39 #include "gtkaccelgroupprivate.h"
40 #include "gtkbindings.h"
41 #include "gtkkeyhash.h"
43 #include "gtkmnemonichash.h"
44 #include "gtkmenubar.h"
45 #include "gtkiconfactory.h"
46 #include "gtkicontheme.h"
47 #include "gtkmarshalers.h"
49 #include "gtkbuildable.h"
50 #include "gtkwidgetprivate.h"
52 #include "gtktypebuiltins.h"
54 #ifdef GDK_WINDOWING_X11
61 * @short_description: Toplevel which can contain other widgets
63 * A GtkWindow is a toplevel window which can contain other widgets.
64 * Windows normally have decorations that are under the control
65 * of the windowing system and allow the user to manipulate the window
66 * (resize it, move it, close it,...).
68 * GTK+ also allows windows to have a resize grip (a small area in the lower
69 * right or left corner) which can be clicked to reszie the window. To
70 * control whether a window has a resize grip, use
71 * gtk_window_set_has_resize_grip().
73 * <refsect2 id="GtkWindow-BUILDER-UI">
74 * <title>GtkWindow as GtkBuildable</title>
76 * The GtkWindow implementation of the GtkBuildable interface supports a
77 * custom <tag class="starttag">accel-groups</tag> element, which supports
78 * any number of <tag class="starttag">group</tag> elements representing the
79 * #GtkAccelGroup objects you want to add to your window (synonymous with
80 * gtk_window_add_accel_group().
83 * <title>A UI definition fragment with accel groups</title>
84 * <programlisting><![CDATA[
85 * <object class="GtkWindow">
87 * <group name="accelgroup1"/>
93 * <object class="GtkAccelGroup" id="accelgroup1"/>
94 * ]]></programlisting>
99 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
101 struct _GtkWindowPrivate
103 GtkMnemonicHash *mnemonic_hash;
105 GtkWidget *default_widget;
106 GtkWidget *focus_widget;
107 GtkWindow *transient_parent;
108 GtkWindowGeometryInfo *geometry_info;
109 GtkWindowGroup *group;
111 GtkApplication *application;
113 GdkModifierType mnemonic_modifier;
114 GdkWindowTypeHint gdk_type_hint;
118 GdkWindow *grip_window;
122 gchar *wmclass_class;
126 guint keys_changed_handler;
128 guint32 initial_timestamp;
130 guint16 configure_request_count;
132 /* The following flags are initially TRUE (before a window is mapped).
133 * They cause us to compute a configure request that involves
134 * default-only parameters. Once mapped, we set them to FALSE.
135 * Then we set them to TRUE again on unmap (for position)
136 * and on unrealize (for size).
138 guint need_default_position : 1;
139 guint need_default_size : 1;
141 guint above_initially : 1;
142 guint accept_focus : 1;
143 guint below_initially : 1;
144 guint builder_visible : 1;
145 guint configure_notify_received : 1;
148 guint destroy_with_parent : 1;
149 guint focus_on_map : 1;
150 guint fullscreen_initially : 1;
152 guint has_user_ref_count : 1;
153 guint has_toplevel_focus : 1;
154 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
156 guint maximize_initially : 1;
157 guint mnemonics_visible : 1;
158 guint mnemonics_visible_set : 1;
160 guint opacity_set : 1;
162 guint reset_type_hint : 1;
164 guint skips_pager : 1;
165 guint skips_taskbar : 1;
166 guint stick_initially : 1;
167 guint transient_parent_group : 1;
168 guint type : 4; /* GtkWindowType */
169 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
170 * one of the original eight. If not,
172 * GDK_WINDOW_TYPE_HINT_NORMAL
175 guint has_resize_grip : 1;
176 guint resize_grip_visible : 1; /* don't use, just for "resize-
177 * grip-visible" notification
179 guint gravity : 5; /* GdkGravity */
206 PROP_DESTROY_WITH_PARENT,
211 PROP_SKIP_TASKBAR_HINT,
212 PROP_SKIP_PAGER_HINT,
221 PROP_HAS_RESIZE_GRIP,
222 PROP_RESIZE_GRIP_VISIBLE,
224 /* Readonly properties */
226 PROP_HAS_TOPLEVEL_FOCUS,
228 /* Writeonly properties */
231 PROP_MNEMONICS_VISIBLE,
241 guint using_default_icon : 1;
242 guint using_parent_icon : 1;
243 guint using_themed_icon : 1;
247 GdkGeometry geometry; /* Last set of geometry hints we set */
248 GdkWindowHints flags;
249 GdkRectangle configure_request;
250 } GtkWindowLastGeometryInfo;
252 struct _GtkWindowGeometryInfo
254 /* Properties that the app has set on the window
256 GdkGeometry geometry; /* Geometry hints */
258 GtkWidget *widget; /* subwidget to which hints apply */
259 /* from last gtk_window_resize () - if > 0, indicates that
260 * we should resize to this size.
265 /* From last gtk_window_move () prior to mapping -
266 * only used if initial_pos_set
271 /* Default size - used only the FIRST time we map a window,
276 /* whether to use initial_x, initial_y */
277 guint initial_pos_set : 1;
278 /* CENTER_ALWAYS or other position constraint changed since
279 * we sent the last configure request.
281 guint position_constraints_changed : 1;
283 /* if true, default_width, height should be multiplied by the
284 * increments and affect the geometry widget only
286 guint default_is_geometry : 1;
288 /* if true, resize_width, height should be multiplied by the
289 * increments and affect the geometry widget only
291 guint resize_is_geometry : 1;
293 GtkWindowLastGeometryInfo last;
297 struct _GtkDeviceGrabInfo
301 guint block_others : 1;
304 struct _GtkWindowGroupPrivate
307 GSList *device_grabs;
310 static void gtk_window_dispose (GObject *object);
311 static void gtk_window_finalize (GObject *object);
312 static void gtk_window_destroy (GtkWidget *widget);
313 static void gtk_window_show (GtkWidget *widget);
314 static void gtk_window_hide (GtkWidget *widget);
315 static void gtk_window_map (GtkWidget *widget);
316 static void gtk_window_unmap (GtkWidget *widget);
317 static void gtk_window_realize (GtkWidget *widget);
318 static void gtk_window_unrealize (GtkWidget *widget);
319 static void gtk_window_size_allocate (GtkWidget *widget,
320 GtkAllocation *allocation);
321 static gboolean gtk_window_map_event (GtkWidget *widget,
323 static gint gtk_window_configure_event (GtkWidget *widget,
324 GdkEventConfigure *event);
325 static gint gtk_window_key_press_event (GtkWidget *widget,
327 static gint gtk_window_key_release_event (GtkWidget *widget,
329 static gint gtk_window_button_press_event (GtkWidget *widget,
330 GdkEventButton *event);
331 static gint gtk_window_enter_notify_event (GtkWidget *widget,
332 GdkEventCrossing *event);
333 static gint gtk_window_leave_notify_event (GtkWidget *widget,
334 GdkEventCrossing *event);
335 static gint gtk_window_focus_in_event (GtkWidget *widget,
336 GdkEventFocus *event);
337 static gint gtk_window_focus_out_event (GtkWidget *widget,
338 GdkEventFocus *event);
339 static void gtk_window_style_updated (GtkWidget *widget);
340 static gboolean gtk_window_state_event (GtkWidget *widget,
341 GdkEventWindowState *event);
342 static void gtk_window_check_resize (GtkContainer *container);
343 static gint gtk_window_focus (GtkWidget *widget,
344 GtkDirectionType direction);
345 static void gtk_window_move_focus (GtkWidget *widget,
346 GtkDirectionType dir);
347 static void gtk_window_real_set_focus (GtkWindow *window,
349 static void gtk_window_direction_changed (GtkWidget *widget,
350 GtkTextDirection prev_dir);
351 static void gtk_window_state_changed (GtkWidget *widget,
352 GtkStateType previous_state);
354 static void gtk_window_real_activate_default (GtkWindow *window);
355 static void gtk_window_real_activate_focus (GtkWindow *window);
356 static void gtk_window_keys_changed (GtkWindow *window);
357 static gint gtk_window_draw (GtkWidget *widget,
359 static void gtk_window_unset_transient_for (GtkWindow *window);
360 static void gtk_window_transient_parent_realized (GtkWidget *parent,
362 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
365 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
367 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
370 static void gtk_window_move_resize (GtkWindow *window);
371 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
373 GdkGeometry *geometry_b,
375 static void gtk_window_constrain_size (GtkWindow *window,
376 GdkGeometry *geometry,
382 static void gtk_window_constrain_position (GtkWindow *window,
387 static void gtk_window_compute_hints (GtkWindow *window,
388 GdkGeometry *new_geometry,
390 static void gtk_window_compute_configure_request (GtkWindow *window,
391 GdkRectangle *request,
392 GdkGeometry *geometry,
395 static void gtk_window_set_default_size_internal (GtkWindow *window,
396 gboolean change_width,
398 gboolean change_height,
400 gboolean is_geometry);
402 static void update_themed_icon (GtkIconTheme *theme,
404 static GList *icon_list_from_theme (GtkWidget *widget,
406 static void gtk_window_realize_icon (GtkWindow *window);
407 static void gtk_window_unrealize_icon (GtkWindow *window);
408 static void resize_grip_create_window (GtkWindow *window);
409 static void resize_grip_destroy_window (GtkWindow *window);
410 static void update_grip_visibility (GtkWindow *window);
412 static void gtk_window_notify_keys_changed (GtkWindow *window);
413 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
414 static void gtk_window_free_key_hash (GtkWindow *window);
415 static void gtk_window_on_composited_changed (GdkScreen *screen,
417 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
420 static void gtk_window_set_theme_variant (GtkWindow *window);
422 static GSList *toplevel_list = NULL;
423 static guint window_signals[LAST_SIGNAL] = { 0 };
424 static GList *default_icon_list = NULL;
425 static gchar *default_icon_name = NULL;
426 static guint default_icon_serial = 0;
427 static gboolean disable_startup_notification = FALSE;
428 static gboolean sent_startup_notification = FALSE;
430 static GQuark quark_gtk_embedded = 0;
431 static GQuark quark_gtk_window_key_hash = 0;
432 static GQuark quark_gtk_window_icon_info = 0;
433 static GQuark quark_gtk_buildable_accels = 0;
435 static GtkBuildableIface *parent_buildable_iface;
437 static void gtk_window_set_property (GObject *object,
441 static void gtk_window_get_property (GObject *object,
447 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
448 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
451 const GValue *value);
452 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
453 GtkBuilder *builder);
454 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
457 const gchar *tagname,
458 GMarkupParser *parser,
460 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
463 const gchar *tagname,
467 static void gtk_window_get_preferred_width (GtkWidget *widget,
470 static void gtk_window_get_preferred_height (GtkWidget *widget,
474 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
475 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
476 gtk_window_buildable_interface_init))
479 add_tab_bindings (GtkBindingSet *binding_set,
480 GdkModifierType modifiers,
481 GtkDirectionType direction)
483 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
485 GTK_TYPE_DIRECTION_TYPE, direction);
486 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
488 GTK_TYPE_DIRECTION_TYPE, direction);
492 add_arrow_bindings (GtkBindingSet *binding_set,
494 GtkDirectionType direction)
496 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
498 gtk_binding_entry_add_signal (binding_set, keysym, 0,
500 GTK_TYPE_DIRECTION_TYPE, direction);
501 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
503 GTK_TYPE_DIRECTION_TYPE, direction);
504 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
506 GTK_TYPE_DIRECTION_TYPE, direction);
507 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
509 GTK_TYPE_DIRECTION_TYPE, direction);
513 extract_time_from_startup_id (const gchar* startup_id)
515 gchar *timestr = g_strrstr (startup_id, "_TIME");
516 guint32 retval = GDK_CURRENT_TIME;
523 /* Skip past the "_TIME" part */
528 timestamp = g_ascii_strtoull (timestr, &end, 0);
529 if (errno == 0 && end != timestr)
537 startup_id_is_fake (const gchar* startup_id)
539 return strncmp (startup_id, "_TIME", 5) == 0;
543 gtk_window_class_init (GtkWindowClass *klass)
545 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
546 GtkWidgetClass *widget_class;
547 GtkContainerClass *container_class;
548 GtkBindingSet *binding_set;
550 widget_class = (GtkWidgetClass*) klass;
551 container_class = (GtkContainerClass*) klass;
553 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
554 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
555 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
556 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
558 gobject_class->dispose = gtk_window_dispose;
559 gobject_class->finalize = gtk_window_finalize;
561 gobject_class->set_property = gtk_window_set_property;
562 gobject_class->get_property = gtk_window_get_property;
564 widget_class->destroy = gtk_window_destroy;
565 widget_class->show = gtk_window_show;
566 widget_class->hide = gtk_window_hide;
567 widget_class->map = gtk_window_map;
568 widget_class->map_event = gtk_window_map_event;
569 widget_class->unmap = gtk_window_unmap;
570 widget_class->realize = gtk_window_realize;
571 widget_class->unrealize = gtk_window_unrealize;
572 widget_class->size_allocate = gtk_window_size_allocate;
573 widget_class->configure_event = gtk_window_configure_event;
574 widget_class->key_press_event = gtk_window_key_press_event;
575 widget_class->key_release_event = gtk_window_key_release_event;
576 widget_class->enter_notify_event = gtk_window_enter_notify_event;
577 widget_class->leave_notify_event = gtk_window_leave_notify_event;
578 widget_class->focus_in_event = gtk_window_focus_in_event;
579 widget_class->button_press_event = gtk_window_button_press_event;
580 widget_class->focus_out_event = gtk_window_focus_out_event;
581 widget_class->focus = gtk_window_focus;
582 widget_class->move_focus = gtk_window_move_focus;
583 widget_class->draw = gtk_window_draw;
584 widget_class->get_preferred_width = gtk_window_get_preferred_width;
585 widget_class->get_preferred_height = gtk_window_get_preferred_height;
586 widget_class->window_state_event = gtk_window_state_event;
587 widget_class->direction_changed = gtk_window_direction_changed;
588 widget_class->state_changed = gtk_window_state_changed;
589 widget_class->style_updated = gtk_window_style_updated;
591 container_class->check_resize = gtk_window_check_resize;
593 klass->set_focus = gtk_window_real_set_focus;
595 klass->activate_default = gtk_window_real_activate_default;
596 klass->activate_focus = gtk_window_real_activate_focus;
597 klass->keys_changed = gtk_window_keys_changed;
599 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
602 g_object_class_install_property (gobject_class,
604 g_param_spec_enum ("type",
606 P_("The type of the window"),
607 GTK_TYPE_WINDOW_TYPE,
609 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
611 g_object_class_install_property (gobject_class,
613 g_param_spec_string ("title",
615 P_("The title of the window"),
617 GTK_PARAM_READWRITE));
619 g_object_class_install_property (gobject_class,
621 g_param_spec_string ("role",
623 P_("Unique identifier for the window to be used when restoring a session"),
625 GTK_PARAM_READWRITE));
628 * GtkWindow:startup-id:
630 * The :startup-id is a write-only property for setting window's
631 * startup notification identifier. See gtk_window_set_startup_id()
636 g_object_class_install_property (gobject_class,
638 g_param_spec_string ("startup-id",
640 P_("Unique startup identifier for the window used by startup-notification"),
642 GTK_PARAM_WRITABLE));
644 g_object_class_install_property (gobject_class,
646 g_param_spec_boolean ("resizable",
648 P_("If TRUE, users can resize the window"),
650 GTK_PARAM_READWRITE));
652 g_object_class_install_property (gobject_class,
654 g_param_spec_boolean ("modal",
656 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
658 GTK_PARAM_READWRITE));
660 g_object_class_install_property (gobject_class,
662 g_param_spec_enum ("window-position",
663 P_("Window Position"),
664 P_("The initial position of the window"),
665 GTK_TYPE_WINDOW_POSITION,
667 GTK_PARAM_READWRITE));
669 g_object_class_install_property (gobject_class,
671 g_param_spec_int ("default-width",
673 P_("The default width of the window, used when initially showing the window"),
677 GTK_PARAM_READWRITE));
679 g_object_class_install_property (gobject_class,
681 g_param_spec_int ("default-height",
682 P_("Default Height"),
683 P_("The default height of the window, used when initially showing the window"),
687 GTK_PARAM_READWRITE));
689 g_object_class_install_property (gobject_class,
690 PROP_DESTROY_WITH_PARENT,
691 g_param_spec_boolean ("destroy-with-parent",
692 P_("Destroy with Parent"),
693 P_("If this window should be destroyed when the parent is destroyed"),
695 GTK_PARAM_READWRITE));
697 g_object_class_install_property (gobject_class,
699 g_param_spec_object ("icon",
701 P_("Icon for this window"),
703 GTK_PARAM_READWRITE));
704 g_object_class_install_property (gobject_class,
705 PROP_MNEMONICS_VISIBLE,
706 g_param_spec_boolean ("mnemonics-visible",
707 P_("Mnemonics Visible"),
708 P_("Whether mnemonics are currently visible in this window"),
710 GTK_PARAM_READWRITE));
713 * GtkWindow:icon-name:
715 * The :icon-name property specifies the name of the themed icon to
716 * use as the window icon. See #GtkIconTheme for more details.
720 g_object_class_install_property (gobject_class,
722 g_param_spec_string ("icon-name",
724 P_("Name of the themed icon for this window"),
726 GTK_PARAM_READWRITE));
728 g_object_class_install_property (gobject_class,
730 g_param_spec_object ("screen",
732 P_("The screen where this window will be displayed"),
734 GTK_PARAM_READWRITE));
736 g_object_class_install_property (gobject_class,
738 g_param_spec_boolean ("is-active",
740 P_("Whether the toplevel is the current active window"),
742 GTK_PARAM_READABLE));
744 g_object_class_install_property (gobject_class,
745 PROP_HAS_TOPLEVEL_FOCUS,
746 g_param_spec_boolean ("has-toplevel-focus",
747 P_("Focus in Toplevel"),
748 P_("Whether the input focus is within this GtkWindow"),
750 GTK_PARAM_READABLE));
752 g_object_class_install_property (gobject_class,
754 g_param_spec_enum ("type-hint",
756 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
757 GDK_TYPE_WINDOW_TYPE_HINT,
758 GDK_WINDOW_TYPE_HINT_NORMAL,
759 GTK_PARAM_READWRITE));
761 g_object_class_install_property (gobject_class,
762 PROP_SKIP_TASKBAR_HINT,
763 g_param_spec_boolean ("skip-taskbar-hint",
765 P_("TRUE if the window should not be in the task bar."),
767 GTK_PARAM_READWRITE));
769 g_object_class_install_property (gobject_class,
770 PROP_SKIP_PAGER_HINT,
771 g_param_spec_boolean ("skip-pager-hint",
773 P_("TRUE if the window should not be in the pager."),
775 GTK_PARAM_READWRITE));
777 g_object_class_install_property (gobject_class,
779 g_param_spec_boolean ("urgency-hint",
781 P_("TRUE if the window should be brought to the user's attention."),
783 GTK_PARAM_READWRITE));
786 * GtkWindow:accept-focus:
788 * Whether the window should receive the input focus.
792 g_object_class_install_property (gobject_class,
794 g_param_spec_boolean ("accept-focus",
796 P_("TRUE if the window should receive the input focus."),
798 GTK_PARAM_READWRITE));
801 * GtkWindow:focus-on-map:
803 * Whether the window should receive the input focus when mapped.
807 g_object_class_install_property (gobject_class,
809 g_param_spec_boolean ("focus-on-map",
811 P_("TRUE if the window should receive the input focus when mapped."),
813 GTK_PARAM_READWRITE));
816 * GtkWindow:decorated:
818 * Whether the window should be decorated by the window manager.
822 g_object_class_install_property (gobject_class,
824 g_param_spec_boolean ("decorated",
826 P_("Whether the window should be decorated by the window manager"),
828 GTK_PARAM_READWRITE));
831 * GtkWindow:deletable:
833 * Whether the window frame should have a close button.
837 g_object_class_install_property (gobject_class,
839 g_param_spec_boolean ("deletable",
841 P_("Whether the window frame should have a close button"),
843 GTK_PARAM_READWRITE));
846 * GtkWindow:has-resize-grip
848 * Whether the window has a corner resize grip.
850 * Note that the resize grip is only shown if the window is
851 * actually resizable and not maximized. Use
852 * #GtkWindow:resize-grip-visible to find out if the resize
853 * grip is currently shown.
857 g_object_class_install_property (gobject_class,
858 PROP_HAS_RESIZE_GRIP,
859 g_param_spec_boolean ("has-resize-grip",
861 P_("Specifies whether the window should have a resize grip"),
863 GTK_PARAM_READWRITE));
866 * GtkWindow:resize-grip-visible:
868 * Whether a corner resize grip is currently shown.
872 g_object_class_install_property (gobject_class,
873 PROP_RESIZE_GRIP_VISIBLE,
874 g_param_spec_boolean ("resize-grip-visible",
875 P_("Resize grip is visible"),
876 P_("Specifies whether the window's resize grip is visible."),
878 GTK_PARAM_READABLE));
884 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
885 * more details about window gravity.
889 g_object_class_install_property (gobject_class,
891 g_param_spec_enum ("gravity",
893 P_("The window gravity of the window"),
895 GDK_GRAVITY_NORTH_WEST,
896 GTK_PARAM_READWRITE));
900 * GtkWindow:transient-for:
902 * The transient parent of the window. See gtk_window_set_transient_for() for
903 * more details about transient windows.
907 g_object_class_install_property (gobject_class,
909 g_param_spec_object ("transient-for",
910 P_("Transient for Window"),
911 P_("The transient parent of the dialog"),
913 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
918 * The requested opacity of the window. See gtk_window_set_opacity() for
919 * more details about window opacity.
923 g_object_class_install_property (gobject_class,
925 g_param_spec_double ("opacity",
926 P_("Opacity for Window"),
927 P_("The opacity of the window, from 0 to 1"),
931 GTK_PARAM_READWRITE));
935 gtk_widget_class_install_style_property (widget_class,
936 g_param_spec_int ("resize-grip-width",
937 P_("Width of resize grip"),
938 P_("Width of resize grip"),
939 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
941 gtk_widget_class_install_style_property (widget_class,
942 g_param_spec_int ("resize-grip-height",
943 P_("Height of resize grip"),
944 P_("Height of resize grip"),
945 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
949 * GtkWindow:application:
951 * The #GtkApplication associated with the window.
953 * The application will be kept alive for at least as long as it
954 * has any windows associated with it (see g_application_hold()
955 * for a way to keep it alive without windows).
957 * Normally, the connection between the application and the window
958 * will remain until the window is destroyed, but you can explicitly
959 * remove it by setting the ::application property to %NULL.
963 g_object_class_install_property (gobject_class,
965 g_param_spec_object ("application",
966 P_("GtkApplication"),
967 P_("The GtkApplication for the window"),
968 GTK_TYPE_APPLICATION,
969 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
971 window_signals[SET_FOCUS] =
972 g_signal_new (I_("set-focus"),
973 G_TYPE_FROM_CLASS (gobject_class),
975 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
977 _gtk_marshal_VOID__OBJECT,
982 * GtkWindow::activate-focus:
983 * @window: the window which received the signal
985 * The ::activate-focus signal is a
986 * <link linkend="keybinding-signals">keybinding signal</link>
987 * which gets emitted when the user activates the currently
988 * focused widget of @window.
990 window_signals[ACTIVATE_FOCUS] =
991 g_signal_new (I_("activate-focus"),
992 G_TYPE_FROM_CLASS (gobject_class),
993 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
994 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
996 _gtk_marshal_VOID__VOID,
1001 * GtkWindow::activate-default:
1002 * @window: the window which received the signal
1004 * The ::activate-default signal is a
1005 * <link linkend="keybinding-signals">keybinding signal</link>
1006 * which gets emitted when the user activates the default widget
1009 window_signals[ACTIVATE_DEFAULT] =
1010 g_signal_new (I_("activate-default"),
1011 G_TYPE_FROM_CLASS (gobject_class),
1012 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1013 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1015 _gtk_marshal_VOID__VOID,
1020 * GtkWindow::keys-changed:
1021 * @window: the window which received the signal
1023 * The ::keys-changed signal gets emitted when the set of accelerators
1024 * or mnemonics that are associated with @window changes.
1026 window_signals[KEYS_CHANGED] =
1027 g_signal_new (I_("keys-changed"),
1028 G_TYPE_FROM_CLASS (gobject_class),
1030 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1032 _gtk_marshal_VOID__VOID,
1040 binding_set = gtk_binding_set_by_class (klass);
1042 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1043 "activate-focus", 0);
1044 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1045 "activate-focus", 0);
1047 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1048 "activate-default", 0);
1049 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1050 "activate-default", 0);
1051 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1052 "activate-default", 0);
1054 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1055 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1056 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1057 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1059 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1060 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1061 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1062 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1066 gtk_window_init (GtkWindow *window)
1068 GtkWindowPrivate *priv;
1070 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1073 priv = window->priv;
1075 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1076 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1078 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1080 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1083 priv->wmclass_name = g_strdup (g_get_prgname ());
1084 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1085 priv->wm_role = NULL;
1086 priv->geometry_info = NULL;
1087 priv->type = GTK_WINDOW_TOPLEVEL;
1088 priv->focus_widget = NULL;
1089 priv->default_widget = NULL;
1090 priv->configure_request_count = 0;
1091 priv->resizable = TRUE;
1092 priv->configure_notify_received = FALSE;
1093 priv->position = GTK_WIN_POS_NONE;
1094 priv->need_default_size = TRUE;
1095 priv->need_default_position = TRUE;
1096 priv->modal = FALSE;
1097 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1098 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1099 priv->decorated = TRUE;
1100 priv->mnemonic_modifier = GDK_MOD1_MASK;
1101 priv->screen = gdk_screen_get_default ();
1103 priv->accept_focus = TRUE;
1104 priv->focus_on_map = TRUE;
1105 priv->deletable = TRUE;
1106 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1107 priv->opacity = 1.0;
1108 priv->startup_id = NULL;
1109 priv->initial_timestamp = GDK_CURRENT_TIME;
1110 priv->has_resize_grip = TRUE;
1111 priv->mnemonics_visible = TRUE;
1113 g_object_ref_sink (window);
1114 priv->has_user_ref_count = TRUE;
1115 toplevel_list = g_slist_prepend (toplevel_list, window);
1118 g_signal_connect (priv->screen, "composited-changed",
1119 G_CALLBACK (gtk_window_on_composited_changed), window);
1121 #ifdef GDK_WINDOWING_X11
1122 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1123 "notify::gtk-application-prefer-dark-theme",
1124 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1129 gtk_window_set_property (GObject *object,
1131 const GValue *value,
1134 GtkWindow *window = GTK_WINDOW (object);
1135 GtkWindowPrivate *priv = window->priv;
1140 priv->type = g_value_get_enum (value);
1143 gtk_window_set_title (window, g_value_get_string (value));
1146 gtk_window_set_role (window, g_value_get_string (value));
1148 case PROP_STARTUP_ID:
1149 gtk_window_set_startup_id (window, g_value_get_string (value));
1151 case PROP_RESIZABLE:
1152 gtk_window_set_resizable (window, g_value_get_boolean (value));
1155 gtk_window_set_modal (window, g_value_get_boolean (value));
1158 gtk_window_set_position (window, g_value_get_enum (value));
1160 case PROP_DEFAULT_WIDTH:
1161 gtk_window_set_default_size_internal (window,
1162 TRUE, g_value_get_int (value),
1165 case PROP_DEFAULT_HEIGHT:
1166 gtk_window_set_default_size_internal (window,
1168 TRUE, g_value_get_int (value), FALSE);
1170 case PROP_DESTROY_WITH_PARENT:
1171 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1174 gtk_window_set_icon (window,
1175 g_value_get_object (value));
1177 case PROP_ICON_NAME:
1178 gtk_window_set_icon_name (window, g_value_get_string (value));
1181 gtk_window_set_screen (window, g_value_get_object (value));
1183 case PROP_TYPE_HINT:
1184 gtk_window_set_type_hint (window,
1185 g_value_get_enum (value));
1187 case PROP_SKIP_TASKBAR_HINT:
1188 gtk_window_set_skip_taskbar_hint (window,
1189 g_value_get_boolean (value));
1191 case PROP_SKIP_PAGER_HINT:
1192 gtk_window_set_skip_pager_hint (window,
1193 g_value_get_boolean (value));
1195 case PROP_URGENCY_HINT:
1196 gtk_window_set_urgency_hint (window,
1197 g_value_get_boolean (value));
1199 case PROP_ACCEPT_FOCUS:
1200 gtk_window_set_accept_focus (window,
1201 g_value_get_boolean (value));
1203 case PROP_FOCUS_ON_MAP:
1204 gtk_window_set_focus_on_map (window,
1205 g_value_get_boolean (value));
1207 case PROP_DECORATED:
1208 gtk_window_set_decorated (window, g_value_get_boolean (value));
1210 case PROP_DELETABLE:
1211 gtk_window_set_deletable (window, g_value_get_boolean (value));
1214 gtk_window_set_gravity (window, g_value_get_enum (value));
1216 case PROP_TRANSIENT_FOR:
1217 gtk_window_set_transient_for (window, g_value_get_object (value));
1220 gtk_window_set_opacity (window, g_value_get_double (value));
1222 case PROP_HAS_RESIZE_GRIP:
1223 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1225 case PROP_APPLICATION:
1226 gtk_window_set_application (window, g_value_get_object (value));
1228 case PROP_MNEMONICS_VISIBLE:
1229 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1232 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1238 gtk_window_get_property (GObject *object,
1243 GtkWindow *window = GTK_WINDOW (object);
1244 GtkWindowPrivate *priv = window->priv;
1248 GtkWindowGeometryInfo *info;
1250 g_value_set_enum (value, priv->type);
1253 g_value_set_string (value, priv->wm_role);
1256 g_value_set_string (value, priv->title);
1258 case PROP_RESIZABLE:
1259 g_value_set_boolean (value, priv->resizable);
1262 g_value_set_boolean (value, priv->modal);
1265 g_value_set_enum (value, priv->position);
1267 case PROP_DEFAULT_WIDTH:
1268 info = gtk_window_get_geometry_info (window, FALSE);
1270 g_value_set_int (value, -1);
1272 g_value_set_int (value, info->default_width);
1274 case PROP_DEFAULT_HEIGHT:
1275 info = gtk_window_get_geometry_info (window, FALSE);
1277 g_value_set_int (value, -1);
1279 g_value_set_int (value, info->default_height);
1281 case PROP_DESTROY_WITH_PARENT:
1282 g_value_set_boolean (value, priv->destroy_with_parent);
1285 g_value_set_object (value, gtk_window_get_icon (window));
1287 case PROP_ICON_NAME:
1288 g_value_set_string (value, gtk_window_get_icon_name (window));
1291 g_value_set_object (value, priv->screen);
1293 case PROP_IS_ACTIVE:
1294 g_value_set_boolean (value, priv->is_active);
1296 case PROP_HAS_TOPLEVEL_FOCUS:
1297 g_value_set_boolean (value, priv->has_toplevel_focus);
1299 case PROP_TYPE_HINT:
1300 g_value_set_enum (value, priv->type_hint);
1302 case PROP_SKIP_TASKBAR_HINT:
1303 g_value_set_boolean (value,
1304 gtk_window_get_skip_taskbar_hint (window));
1306 case PROP_SKIP_PAGER_HINT:
1307 g_value_set_boolean (value,
1308 gtk_window_get_skip_pager_hint (window));
1310 case PROP_URGENCY_HINT:
1311 g_value_set_boolean (value,
1312 gtk_window_get_urgency_hint (window));
1314 case PROP_ACCEPT_FOCUS:
1315 g_value_set_boolean (value,
1316 gtk_window_get_accept_focus (window));
1318 case PROP_FOCUS_ON_MAP:
1319 g_value_set_boolean (value,
1320 gtk_window_get_focus_on_map (window));
1322 case PROP_DECORATED:
1323 g_value_set_boolean (value, gtk_window_get_decorated (window));
1325 case PROP_DELETABLE:
1326 g_value_set_boolean (value, gtk_window_get_deletable (window));
1329 g_value_set_enum (value, gtk_window_get_gravity (window));
1331 case PROP_TRANSIENT_FOR:
1332 g_value_set_object (value, gtk_window_get_transient_for (window));
1335 g_value_set_double (value, gtk_window_get_opacity (window));
1337 case PROP_HAS_RESIZE_GRIP:
1338 g_value_set_boolean (value, priv->has_resize_grip);
1340 case PROP_RESIZE_GRIP_VISIBLE:
1341 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1343 case PROP_APPLICATION:
1344 g_value_set_object (value, gtk_window_get_application (window));
1346 case PROP_MNEMONICS_VISIBLE:
1347 g_value_set_boolean (value, priv->mnemonics_visible);
1350 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1356 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1358 parent_buildable_iface = g_type_interface_peek_parent (iface);
1359 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1360 iface->parser_finished = gtk_window_buildable_parser_finished;
1361 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1362 iface->custom_finished = gtk_window_buildable_custom_finished;
1366 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1367 GtkBuilder *builder,
1369 const GValue *value)
1371 GtkWindow *window = GTK_WINDOW (buildable);
1372 GtkWindowPrivate *priv = window->priv;
1374 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1375 priv->builder_visible = TRUE;
1377 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1381 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1382 GtkBuilder *builder)
1384 GtkWindow *window = GTK_WINDOW (buildable);
1385 GtkWindowPrivate *priv = window->priv;
1389 if (priv->builder_visible)
1390 gtk_widget_show (GTK_WIDGET (buildable));
1392 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1393 for (l = accels; l; l = l->next)
1395 object = gtk_builder_get_object (builder, l->data);
1398 g_warning ("Unknown accel group %s specified in window %s",
1399 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1402 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1403 GTK_ACCEL_GROUP (object));
1407 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1409 parent_buildable_iface->parser_finished (buildable, builder);
1415 } GSListSubParserData;
1418 window_start_element (GMarkupParseContext *context,
1419 const gchar *element_name,
1420 const gchar **names,
1421 const gchar **values,
1426 GSListSubParserData *data = (GSListSubParserData*)user_data;
1428 if (strcmp (element_name, "group") == 0)
1430 for (i = 0; names[i]; i++)
1432 if (strcmp (names[i], "name") == 0)
1433 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1436 else if (strcmp (element_name, "accel-groups") == 0)
1439 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1444 static const GMarkupParser window_parser =
1446 window_start_element
1450 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1451 GtkBuilder *builder,
1453 const gchar *tagname,
1454 GMarkupParser *parser,
1457 GSListSubParserData *parser_data;
1459 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1460 tagname, parser, data))
1463 if (strcmp (tagname, "accel-groups") == 0)
1465 parser_data = g_slice_new0 (GSListSubParserData);
1466 parser_data->items = NULL;
1467 parser_data->object = G_OBJECT (buildable);
1469 *parser = window_parser;
1470 *data = parser_data;
1478 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1479 GtkBuilder *builder,
1481 const gchar *tagname,
1484 GSListSubParserData *data;
1486 parent_buildable_iface->custom_finished (buildable, builder, child,
1487 tagname, user_data);
1489 if (strcmp (tagname, "accel-groups") != 0)
1492 data = (GSListSubParserData*)user_data;
1494 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1495 data->items, (GDestroyNotify) g_slist_free);
1497 g_slice_free (GSListSubParserData, data);
1502 * @type: type of window
1504 * Creates a new #GtkWindow, which is a toplevel window that can
1505 * contain other widgets. Nearly always, the type of the window should
1506 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1507 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1508 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1509 * dialogs, though in some other toolkits dialogs are called "popups".
1510 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1511 * On X11, popup windows are not controlled by the <link
1512 * linkend="gtk-X11-arch">window manager</link>.
1514 * If you simply want an undecorated window (no window borders), use
1515 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1517 * Return value: a new #GtkWindow.
1520 gtk_window_new (GtkWindowType type)
1522 GtkWindowPrivate *priv;
1525 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1527 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1528 priv = window->priv;
1532 return GTK_WIDGET (window);
1536 * gtk_window_set_title:
1537 * @window: a #GtkWindow
1538 * @title: title of the window
1540 * Sets the title of the #GtkWindow. The title of a window will be
1541 * displayed in its title bar; on the X Window System, the title bar
1542 * is rendered by the <link linkend="gtk-X11-arch">window
1543 * manager</link>, so exactly how the title appears to users may vary
1544 * according to a user's exact configuration. The title should help a
1545 * user distinguish this window from other windows they may have
1546 * open. A good title might include the application name and current
1547 * document filename, for example.
1551 gtk_window_set_title (GtkWindow *window,
1554 GtkWindowPrivate *priv;
1558 g_return_if_fail (GTK_IS_WINDOW (window));
1560 priv = window->priv;
1561 widget = GTK_WIDGET (window);
1563 new_title = g_strdup (title);
1564 g_free (priv->title);
1565 priv->title = new_title;
1567 if (gtk_widget_get_realized (widget))
1569 gdk_window_set_title (gtk_widget_get_window (widget),
1573 g_object_notify (G_OBJECT (window), "title");
1577 * gtk_window_get_title:
1578 * @window: a #GtkWindow
1580 * Retrieves the title of the window. See gtk_window_set_title().
1582 * Return value: the title of the window, or %NULL if none has
1583 * been set explicitely. The returned string is owned by the widget
1584 * and must not be modified or freed.
1586 G_CONST_RETURN gchar *
1587 gtk_window_get_title (GtkWindow *window)
1589 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1591 return window->priv->title;
1595 * gtk_window_set_wmclass:
1596 * @window: a #GtkWindow
1597 * @wmclass_name: window name hint
1598 * @wmclass_class: window class hint
1600 * Don't use this function. It sets the X Window System "class" and
1601 * "name" hints for a window. According to the ICCCM, you should
1602 * always set these to the same value for all windows in an
1603 * application, and GTK+ sets them to that value by default, so calling
1604 * this function is sort of pointless. However, you may want to call
1605 * gtk_window_set_role() on each window in your application, for the
1606 * benefit of the session manager. Setting the role allows the window
1607 * manager to restore window positions when loading a saved session.
1611 gtk_window_set_wmclass (GtkWindow *window,
1612 const gchar *wmclass_name,
1613 const gchar *wmclass_class)
1615 GtkWindowPrivate *priv;
1617 g_return_if_fail (GTK_IS_WINDOW (window));
1619 priv = window->priv;
1621 g_free (priv->wmclass_name);
1622 priv->wmclass_name = g_strdup (wmclass_name);
1624 g_free (priv->wmclass_class);
1625 priv->wmclass_class = g_strdup (wmclass_class);
1627 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1628 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1632 * gtk_window_set_role:
1633 * @window: a #GtkWindow
1634 * @role: unique identifier for the window to be used when restoring a session
1636 * This function is only useful on X11, not with other GTK+ targets.
1638 * In combination with the window title, the window role allows a
1639 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1640 * same" window when an application is restarted. So for example you
1641 * might set the "toolbox" role on your app's toolbox window, so that
1642 * when the user restarts their session, the window manager can put
1643 * the toolbox back in the same place.
1645 * If a window already has a unique title, you don't need to set the
1646 * role, since the WM can use the title to identify the window when
1647 * restoring the session.
1651 gtk_window_set_role (GtkWindow *window,
1654 GtkWindowPrivate *priv;
1657 g_return_if_fail (GTK_IS_WINDOW (window));
1659 priv = window->priv;
1661 new_role = g_strdup (role);
1662 g_free (priv->wm_role);
1663 priv->wm_role = new_role;
1665 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1666 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1669 g_object_notify (G_OBJECT (window), "role");
1673 * gtk_window_set_startup_id:
1674 * @window: a #GtkWindow
1675 * @startup_id: a string with startup-notification identifier
1677 * Startup notification identifiers are used by desktop environment to
1678 * track application startup, to provide user feedback and other
1679 * features. This function changes the corresponding property on the
1680 * underlying GdkWindow. Normally, startup identifier is managed
1681 * automatically and you should only use this function in special cases
1682 * like transferring focus from other processes. You should use this
1683 * function before calling gtk_window_present() or any equivalent
1684 * function generating a window map event.
1686 * This function is only useful on X11, not with other GTK+ targets.
1691 gtk_window_set_startup_id (GtkWindow *window,
1692 const gchar *startup_id)
1694 GtkWindowPrivate *priv;
1697 g_return_if_fail (GTK_IS_WINDOW (window));
1699 priv = window->priv;
1700 widget = GTK_WIDGET (window);
1702 g_free (priv->startup_id);
1703 priv->startup_id = g_strdup (startup_id);
1705 if (gtk_widget_get_realized (widget))
1707 GdkWindow *gdk_window;
1708 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1710 gdk_window = gtk_widget_get_window (widget);
1712 #ifdef GDK_WINDOWING_X11
1713 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1714 gdk_x11_window_set_user_time (gdk_window, timestamp);
1717 /* Here we differentiate real and "fake" startup notification IDs,
1718 * constructed on purpose just to pass interaction timestamp
1720 if (startup_id_is_fake (priv->startup_id))
1721 gtk_window_present_with_time (window, timestamp);
1724 gdk_window_set_startup_id (gdk_window,
1727 /* If window is mapped, terminate the startup-notification too */
1728 if (gtk_widget_get_mapped (widget) &&
1729 !disable_startup_notification)
1730 gdk_notify_startup_complete_with_id (priv->startup_id);
1734 g_object_notify (G_OBJECT (window), "startup-id");
1738 * gtk_window_get_role:
1739 * @window: a #GtkWindow
1741 * Returns the role of the window. See gtk_window_set_role() for
1742 * further explanation.
1744 * Return value: the role of the window if set, or %NULL. The
1745 * returned is owned by the widget and must not be modified
1748 G_CONST_RETURN gchar *
1749 gtk_window_get_role (GtkWindow *window)
1751 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1753 return window->priv->wm_role;
1757 * gtk_window_set_focus:
1758 * @window: a #GtkWindow
1759 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1760 * any focus widget for the toplevel window.
1762 * If @focus is not the current focus widget, and is focusable, sets
1763 * it as the focus widget for the window. If @focus is %NULL, unsets
1764 * the focus widget for this window. To set the focus to a particular
1765 * widget in the toplevel, it is usually more convenient to use
1766 * gtk_widget_grab_focus() instead of this function.
1769 gtk_window_set_focus (GtkWindow *window,
1772 GtkWindowPrivate *priv;
1775 g_return_if_fail (GTK_IS_WINDOW (window));
1777 priv = window->priv;
1781 g_return_if_fail (GTK_IS_WIDGET (focus));
1782 g_return_if_fail (gtk_widget_get_can_focus (focus));
1786 gtk_widget_grab_focus (focus);
1789 /* Clear the existing focus chain, so that when we focus into
1790 * the window again, we start at the beginnning.
1792 GtkWidget *widget = priv->focus_widget;
1795 while ((parent = gtk_widget_get_parent (widget)))
1798 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1802 _gtk_window_internal_set_focus (window, NULL);
1807 _gtk_window_internal_set_focus (GtkWindow *window,
1810 GtkWindowPrivate *priv;
1812 g_return_if_fail (GTK_IS_WINDOW (window));
1814 priv = window->priv;
1816 if ((priv->focus_widget != focus) ||
1817 (focus && !gtk_widget_has_focus (focus)))
1818 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1822 * gtk_window_set_default:
1823 * @window: a #GtkWindow
1824 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1825 * default widget for the toplevel.
1827 * The default widget is the widget that's activated when the user
1828 * presses Enter in a dialog (for example). This function sets or
1829 * unsets the default widget for a #GtkWindow about. When setting
1830 * (rather than unsetting) the default widget it's generally easier to
1831 * call gtk_widget_grab_focus() on the widget. Before making a widget
1832 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1833 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1836 gtk_window_set_default (GtkWindow *window,
1837 GtkWidget *default_widget)
1839 GtkWindowPrivate *priv;
1841 g_return_if_fail (GTK_IS_WINDOW (window));
1843 priv = window->priv;
1846 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1848 if (priv->default_widget != default_widget)
1850 GtkWidget *old_default_widget = NULL;
1853 g_object_ref (default_widget);
1855 if (priv->default_widget)
1857 old_default_widget = priv->default_widget;
1859 if (priv->focus_widget != priv->default_widget ||
1860 !gtk_widget_get_receives_default (priv->default_widget))
1861 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1863 gtk_widget_queue_draw (priv->default_widget);
1866 priv->default_widget = default_widget;
1868 if (priv->default_widget)
1870 if (priv->focus_widget == NULL ||
1871 !gtk_widget_get_receives_default (priv->focus_widget))
1872 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1874 gtk_widget_queue_draw (priv->default_widget);
1877 if (old_default_widget)
1878 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1882 g_object_notify (G_OBJECT (default_widget), "has-default");
1883 g_object_unref (default_widget);
1889 * gtk_window_get_default_widget:
1890 * @window: a #GtkWindow
1892 * Returns the default widget for @window. See gtk_window_set_default()
1895 * Returns: (transfer none): the default widget, or %NULL if there is none.
1900 gtk_window_get_default_widget (GtkWindow *window)
1902 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1904 return window->priv->default_widget;
1908 handle_keys_changed (gpointer data)
1910 GtkWindow *window = GTK_WINDOW (data);
1911 GtkWindowPrivate *priv = window->priv;
1913 if (priv->keys_changed_handler)
1915 g_source_remove (priv->keys_changed_handler);
1916 priv->keys_changed_handler = 0;
1919 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1925 gtk_window_notify_keys_changed (GtkWindow *window)
1927 GtkWindowPrivate *priv = window->priv;
1929 if (!priv->keys_changed_handler)
1930 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1934 * gtk_window_add_accel_group:
1935 * @window: window to attach accelerator group to
1936 * @accel_group: a #GtkAccelGroup
1938 * Associate @accel_group with @window, such that calling
1939 * gtk_accel_groups_activate() on @window will activate accelerators
1943 gtk_window_add_accel_group (GtkWindow *window,
1944 GtkAccelGroup *accel_group)
1946 g_return_if_fail (GTK_IS_WINDOW (window));
1947 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1949 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1950 g_signal_connect_object (accel_group, "accel-changed",
1951 G_CALLBACK (gtk_window_notify_keys_changed),
1952 window, G_CONNECT_SWAPPED);
1953 gtk_window_notify_keys_changed (window);
1957 * gtk_window_remove_accel_group:
1958 * @window: a #GtkWindow
1959 * @accel_group: a #GtkAccelGroup
1961 * Reverses the effects of gtk_window_add_accel_group().
1964 gtk_window_remove_accel_group (GtkWindow *window,
1965 GtkAccelGroup *accel_group)
1967 g_return_if_fail (GTK_IS_WINDOW (window));
1968 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1970 g_signal_handlers_disconnect_by_func (accel_group,
1971 gtk_window_notify_keys_changed,
1973 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1974 gtk_window_notify_keys_changed (window);
1977 static GtkMnemonicHash *
1978 gtk_window_get_mnemonic_hash (GtkWindow *window,
1981 GtkWindowPrivate *private = window->priv;
1983 if (!private->mnemonic_hash && create)
1984 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1986 return private->mnemonic_hash;
1990 * gtk_window_add_mnemonic:
1991 * @window: a #GtkWindow
1992 * @keyval: the mnemonic
1993 * @target: the widget that gets activated by the mnemonic
1995 * Adds a mnemonic to this window.
1998 gtk_window_add_mnemonic (GtkWindow *window,
2002 g_return_if_fail (GTK_IS_WINDOW (window));
2003 g_return_if_fail (GTK_IS_WIDGET (target));
2005 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2007 gtk_window_notify_keys_changed (window);
2011 * gtk_window_remove_mnemonic:
2012 * @window: a #GtkWindow
2013 * @keyval: the mnemonic
2014 * @target: the widget that gets activated by the mnemonic
2016 * Removes a mnemonic from this window.
2019 gtk_window_remove_mnemonic (GtkWindow *window,
2023 g_return_if_fail (GTK_IS_WINDOW (window));
2024 g_return_if_fail (GTK_IS_WIDGET (target));
2026 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2028 gtk_window_notify_keys_changed (window);
2032 * gtk_window_mnemonic_activate:
2033 * @window: a #GtkWindow
2034 * @keyval: the mnemonic
2035 * @modifier: the modifiers
2036 * @returns: %TRUE if the activation is done.
2038 * Activates the targets associated with the mnemonic.
2041 gtk_window_mnemonic_activate (GtkWindow *window,
2043 GdkModifierType modifier)
2045 GtkWindowPrivate *priv;
2047 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2049 priv = window->priv;
2051 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2053 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2055 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2062 * gtk_window_set_mnemonic_modifier:
2063 * @window: a #GtkWindow
2064 * @modifier: the modifier mask used to activate
2065 * mnemonics on this window.
2067 * Sets the mnemonic modifier for this window.
2070 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2071 GdkModifierType modifier)
2073 GtkWindowPrivate *priv;
2075 g_return_if_fail (GTK_IS_WINDOW (window));
2076 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2078 priv = window->priv;
2080 priv->mnemonic_modifier = modifier;
2081 gtk_window_notify_keys_changed (window);
2085 * gtk_window_get_mnemonic_modifier:
2086 * @window: a #GtkWindow
2088 * Returns the mnemonic modifier for this window. See
2089 * gtk_window_set_mnemonic_modifier().
2091 * Return value: the modifier mask used to activate
2092 * mnemonics on this window.
2095 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2097 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2099 return window->priv->mnemonic_modifier;
2103 * gtk_window_set_position:
2104 * @window: a #GtkWindow.
2105 * @position: a position constraint.
2107 * Sets a position constraint for this window. If the old or new
2108 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2109 * the window to be repositioned to satisfy the new constraint.
2112 gtk_window_set_position (GtkWindow *window,
2113 GtkWindowPosition position)
2115 GtkWindowPrivate *priv;
2117 g_return_if_fail (GTK_IS_WINDOW (window));
2119 priv = window->priv;
2121 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2122 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2124 GtkWindowGeometryInfo *info;
2126 info = gtk_window_get_geometry_info (window, TRUE);
2128 /* this flag causes us to re-request the CENTER_ALWAYS
2129 * constraint in gtk_window_move_resize(), see
2130 * comment in that function.
2132 info->position_constraints_changed = TRUE;
2134 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2137 priv->position = position;
2139 g_object_notify (G_OBJECT (window), "window-position");
2143 * gtk_window_activate_focus:
2144 * @window: a #GtkWindow
2146 * Activates the current focused widget within the window.
2148 * Return value: %TRUE if a widget got activated.
2151 gtk_window_activate_focus (GtkWindow *window)
2153 GtkWindowPrivate *priv;
2155 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2157 priv = window->priv;
2159 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2160 return gtk_widget_activate (priv->focus_widget);
2166 * gtk_window_get_focus:
2167 * @window: a #GtkWindow
2169 * Retrieves the current focused widget within the window.
2170 * Note that this is the widget that would have the focus
2171 * if the toplevel window focused; if the toplevel window
2172 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2173 * not be %TRUE for the widget.
2175 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2178 gtk_window_get_focus (GtkWindow *window)
2180 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2182 return window->priv->focus_widget;
2186 * gtk_window_activate_default:
2187 * @window: a #GtkWindow
2189 * Activates the default widget for the window, unless the current
2190 * focused widget has been configured to receive the default action
2191 * (see gtk_widget_set_receives_default()), in which case the
2192 * focused widget is activated.
2194 * Return value: %TRUE if a widget got activated.
2197 gtk_window_activate_default (GtkWindow *window)
2199 GtkWindowPrivate *priv;
2201 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2203 priv = window->priv;
2205 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2206 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2207 return gtk_widget_activate (priv->default_widget);
2208 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2209 return gtk_widget_activate (priv->focus_widget);
2215 * gtk_window_set_modal:
2216 * @window: a #GtkWindow
2217 * @modal: whether the window is modal
2219 * Sets a window modal or non-modal. Modal windows prevent interaction
2220 * with other windows in the same application. To keep modal dialogs
2221 * on top of main application windows, use
2222 * gtk_window_set_transient_for() to make the dialog transient for the
2223 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2224 * will then disallow lowering the dialog below the parent.
2229 gtk_window_set_modal (GtkWindow *window,
2232 GtkWindowPrivate *priv;
2235 g_return_if_fail (GTK_IS_WINDOW (window));
2237 priv = window->priv;
2239 modal = modal != FALSE;
2240 if (priv->modal == modal)
2243 priv->modal = modal;
2244 widget = GTK_WIDGET (window);
2246 /* adjust desired modality state */
2247 if (gtk_widget_get_realized (widget))
2250 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2252 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2255 if (gtk_widget_get_visible (widget))
2258 gtk_grab_add (widget);
2260 gtk_grab_remove (widget);
2263 g_object_notify (G_OBJECT (window), "modal");
2267 * gtk_window_get_modal:
2268 * @window: a #GtkWindow
2270 * Returns whether the window is modal. See gtk_window_set_modal().
2272 * Return value: %TRUE if the window is set to be modal and
2273 * establishes a grab when shown
2276 gtk_window_get_modal (GtkWindow *window)
2278 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2280 return window->priv->modal;
2284 * gtk_window_list_toplevels:
2286 * Returns a list of all existing toplevel windows. The widgets
2287 * in the list are not individually referenced. If you want
2288 * to iterate through the list and perform actions involving
2289 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2290 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2291 * then unref all the widgets afterwards.
2293 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2296 gtk_window_list_toplevels (void)
2301 for (slist = toplevel_list; slist; slist = slist->next)
2302 list = g_list_prepend (list, slist->data);
2308 gtk_window_dispose (GObject *object)
2310 GtkWindow *window = GTK_WINDOW (object);
2312 gtk_window_set_focus (window, NULL);
2313 gtk_window_set_default (window, NULL);
2315 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2319 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2321 gtk_widget_destroy (GTK_WIDGET (child));
2325 connect_parent_destroyed (GtkWindow *window)
2327 GtkWindowPrivate *priv = window->priv;
2329 if (priv->transient_parent)
2331 g_signal_connect (priv->transient_parent,
2333 G_CALLBACK (parent_destroyed_callback),
2339 disconnect_parent_destroyed (GtkWindow *window)
2341 GtkWindowPrivate *priv = window->priv;
2343 if (priv->transient_parent)
2345 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2346 parent_destroyed_callback,
2352 gtk_window_transient_parent_realized (GtkWidget *parent,
2355 if (gtk_widget_get_realized (window))
2356 gdk_window_set_transient_for (gtk_widget_get_window (window),
2357 gtk_widget_get_window (parent));
2361 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2364 if (gtk_widget_get_realized (window))
2365 gdk_property_delete (gtk_widget_get_window (window),
2366 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2370 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2374 gtk_window_set_screen (window, parent->priv->screen);
2378 gtk_window_unset_transient_for (GtkWindow *window)
2380 GtkWindowPrivate *priv = window->priv;
2382 if (priv->transient_parent)
2384 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2385 gtk_window_transient_parent_realized,
2387 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2388 gtk_window_transient_parent_unrealized,
2390 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2391 gtk_window_transient_parent_screen_changed,
2393 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2394 gtk_widget_destroyed,
2395 &priv->transient_parent);
2397 if (priv->destroy_with_parent)
2398 disconnect_parent_destroyed (window);
2400 priv->transient_parent = NULL;
2402 if (priv->transient_parent_group)
2404 priv->transient_parent_group = FALSE;
2405 gtk_window_group_remove_window (priv->group,
2412 * gtk_window_set_transient_for:
2413 * @window: a #GtkWindow
2414 * @parent: (allow-none): parent window, or %NULL
2416 * Dialog windows should be set transient for the main application
2417 * window they were spawned from. This allows <link
2418 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2419 * dialog on top of the main window, or center the dialog over the
2420 * main window. gtk_dialog_new_with_buttons() and other convenience
2421 * functions in GTK+ will sometimes call
2422 * gtk_window_set_transient_for() on your behalf.
2424 * Passing %NULL for @parent unsets the current transient window.
2426 * On Windows, this function puts the child window on top of the parent,
2427 * much as the window manager would have done on X.
2430 gtk_window_set_transient_for (GtkWindow *window,
2433 GtkWindowPrivate *priv;
2435 g_return_if_fail (GTK_IS_WINDOW (window));
2436 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2437 g_return_if_fail (window != parent);
2439 priv = window->priv;
2441 if (priv->transient_parent)
2443 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2444 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2445 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2446 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2447 GTK_WIDGET (window));
2449 gtk_window_unset_transient_for (window);
2452 priv->transient_parent = parent;
2456 g_signal_connect (parent, "destroy",
2457 G_CALLBACK (gtk_widget_destroyed),
2458 &priv->transient_parent);
2459 g_signal_connect (parent, "realize",
2460 G_CALLBACK (gtk_window_transient_parent_realized),
2462 g_signal_connect (parent, "unrealize",
2463 G_CALLBACK (gtk_window_transient_parent_unrealized),
2465 g_signal_connect (parent, "notify::screen",
2466 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2469 gtk_window_set_screen (window, parent->priv->screen);
2471 if (priv->destroy_with_parent)
2472 connect_parent_destroyed (window);
2474 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2475 gtk_widget_get_realized (GTK_WIDGET (parent)))
2476 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2477 GTK_WIDGET (window));
2479 if (parent->priv->group)
2481 gtk_window_group_add_window (parent->priv->group, window);
2482 priv->transient_parent_group = TRUE;
2488 * gtk_window_get_transient_for:
2489 * @window: a #GtkWindow
2491 * Fetches the transient parent for this window. See
2492 * gtk_window_set_transient_for().
2494 * Return value: (transfer none): the transient parent for this window, or %NULL
2495 * if no transient parent has been set.
2498 gtk_window_get_transient_for (GtkWindow *window)
2500 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2502 return window->priv->transient_parent;
2506 * gtk_window_set_opacity:
2507 * @window: a #GtkWindow
2508 * @opacity: desired opacity, between 0 and 1
2510 * Request the windowing system to make @window partially transparent,
2511 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2512 * of the opacity parameter are clamped to the [0,1] range.) On X11
2513 * this has any effect only on X screens with a compositing manager
2514 * running. See gtk_widget_is_composited(). On Windows it should work
2517 * Note that setting a window's opacity after the window has been
2518 * shown causes it to flicker once on Windows.
2523 gtk_window_set_opacity (GtkWindow *window,
2526 GtkWindowPrivate *priv;
2528 g_return_if_fail (GTK_IS_WINDOW (window));
2530 priv = window->priv;
2534 else if (opacity > 1.0)
2537 priv->opacity_set = TRUE;
2538 priv->opacity = opacity;
2540 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2541 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2546 * gtk_window_get_opacity:
2547 * @window: a #GtkWindow
2549 * Fetches the requested opacity for this window. See
2550 * gtk_window_set_opacity().
2552 * Return value: the requested opacity for this window.
2557 gtk_window_get_opacity (GtkWindow *window)
2559 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2561 return window->priv->opacity;
2565 * gtk_window_get_application:
2566 * @window: a #GtkWindow
2568 * Gets the #GtkApplication associated with the window (if any).
2570 * Return value: (transfer none): a #GtkApplication, or %NULL
2575 gtk_window_get_application (GtkWindow *window)
2577 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2579 return window->priv->application;
2583 gtk_window_release_application (GtkWindow *window)
2585 if (window->priv->application)
2587 GtkApplication *application;
2589 /* steal reference into temp variable */
2590 application = window->priv->application;
2591 window->priv->application = NULL;
2593 gtk_application_remove_window (application, window);
2594 g_object_unref (application);
2599 * gtk_window_set_application:
2600 * @window: a #GtkWindow
2601 * @application: (allow-none): a #GtkApplication, or %NULL
2603 * Sets or unsets the #GtkApplication associated with the window.
2605 * The application will be kept alive for at least as long as the window
2611 gtk_window_set_application (GtkWindow *window,
2612 GtkApplication *application)
2614 GtkWindowPrivate *priv;
2616 g_return_if_fail (GTK_IS_WINDOW (window));
2618 priv = window->priv;
2619 if (priv->application != application)
2621 gtk_window_release_application (window);
2623 priv->application = application;
2625 if (priv->application != NULL)
2627 g_object_ref (priv->application);
2629 gtk_application_add_window (priv->application, window);
2632 g_object_notify (G_OBJECT (window), "application");
2637 * gtk_window_set_type_hint:
2638 * @window: a #GtkWindow
2639 * @hint: the window type
2641 * By setting the type hint for the window, you allow the window
2642 * manager to decorate and handle the window in a way which is
2643 * suitable to the function of the window in your application.
2645 * This function should be called before the window becomes visible.
2647 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2648 * will sometimes call gtk_window_set_type_hint() on your behalf.
2652 gtk_window_set_type_hint (GtkWindow *window,
2653 GdkWindowTypeHint hint)
2655 GtkWindowPrivate *priv;
2657 g_return_if_fail (GTK_IS_WINDOW (window));
2658 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2660 priv = window->priv;
2662 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2663 priv->type_hint = hint;
2665 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2667 priv->reset_type_hint = TRUE;
2668 priv->gdk_type_hint = hint;
2672 * gtk_window_get_type_hint:
2673 * @window: a #GtkWindow
2675 * Gets the type hint for this window. See gtk_window_set_type_hint().
2677 * Return value: the type hint for @window.
2680 gtk_window_get_type_hint (GtkWindow *window)
2682 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2684 return window->priv->gdk_type_hint;
2688 * gtk_window_set_skip_taskbar_hint:
2689 * @window: a #GtkWindow
2690 * @setting: %TRUE to keep this window from appearing in the task bar
2692 * Windows may set a hint asking the desktop environment not to display
2693 * the window in the task bar. This function sets this hint.
2698 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2701 GtkWindowPrivate *priv;
2703 g_return_if_fail (GTK_IS_WINDOW (window));
2705 priv = window->priv;
2707 setting = setting != FALSE;
2709 if (priv->skips_taskbar != setting)
2711 priv->skips_taskbar = setting;
2712 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2713 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2714 priv->skips_taskbar);
2715 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2720 * gtk_window_get_skip_taskbar_hint:
2721 * @window: a #GtkWindow
2723 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2725 * Return value: %TRUE if window shouldn't be in taskbar
2730 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2732 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2734 return window->priv->skips_taskbar;
2738 * gtk_window_set_skip_pager_hint:
2739 * @window: a #GtkWindow
2740 * @setting: %TRUE to keep this window from appearing in the pager
2742 * Windows may set a hint asking the desktop environment not to display
2743 * the window in the pager. This function sets this hint.
2744 * (A "pager" is any desktop navigation tool such as a workspace
2745 * switcher that displays a thumbnail representation of the windows
2751 gtk_window_set_skip_pager_hint (GtkWindow *window,
2754 GtkWindowPrivate *priv;
2756 g_return_if_fail (GTK_IS_WINDOW (window));
2758 priv = window->priv;
2760 setting = setting != FALSE;
2762 if (priv->skips_pager != setting)
2764 priv->skips_pager = setting;
2765 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2766 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2768 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2773 * gtk_window_get_skip_pager_hint:
2774 * @window: a #GtkWindow
2776 * Gets the value set by gtk_window_set_skip_pager_hint().
2778 * Return value: %TRUE if window shouldn't be in pager
2783 gtk_window_get_skip_pager_hint (GtkWindow *window)
2785 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2787 return window->priv->skips_pager;
2791 * gtk_window_set_urgency_hint:
2792 * @window: a #GtkWindow
2793 * @setting: %TRUE to mark this window as urgent
2795 * Windows may set a hint asking the desktop environment to draw
2796 * the users attention to the window. This function sets this hint.
2801 gtk_window_set_urgency_hint (GtkWindow *window,
2804 GtkWindowPrivate *priv;
2806 g_return_if_fail (GTK_IS_WINDOW (window));
2808 priv = window->priv;
2810 setting = setting != FALSE;
2812 if (priv->urgent != setting)
2814 priv->urgent = setting;
2815 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2816 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2818 g_object_notify (G_OBJECT (window), "urgency-hint");
2823 * gtk_window_get_urgency_hint:
2824 * @window: a #GtkWindow
2826 * Gets the value set by gtk_window_set_urgency_hint()
2828 * Return value: %TRUE if window is urgent
2833 gtk_window_get_urgency_hint (GtkWindow *window)
2835 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2837 return window->priv->urgent;
2841 * gtk_window_set_accept_focus:
2842 * @window: a #GtkWindow
2843 * @setting: %TRUE to let this window receive input focus
2845 * Windows may set a hint asking the desktop environment not to receive
2846 * the input focus. This function sets this hint.
2851 gtk_window_set_accept_focus (GtkWindow *window,
2854 GtkWindowPrivate *priv;
2856 g_return_if_fail (GTK_IS_WINDOW (window));
2858 priv = window->priv;
2860 setting = setting != FALSE;
2862 if (priv->accept_focus != setting)
2864 priv->accept_focus = setting;
2865 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2866 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2867 priv->accept_focus);
2868 g_object_notify (G_OBJECT (window), "accept-focus");
2873 * gtk_window_get_accept_focus:
2874 * @window: a #GtkWindow
2876 * Gets the value set by gtk_window_set_accept_focus().
2878 * Return value: %TRUE if window should receive the input focus
2883 gtk_window_get_accept_focus (GtkWindow *window)
2885 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2887 return window->priv->accept_focus;
2891 * gtk_window_set_focus_on_map:
2892 * @window: a #GtkWindow
2893 * @setting: %TRUE to let this window receive input focus on map
2895 * Windows may set a hint asking the desktop environment not to receive
2896 * the input focus when the window is mapped. This function sets this
2902 gtk_window_set_focus_on_map (GtkWindow *window,
2905 GtkWindowPrivate *priv;
2907 g_return_if_fail (GTK_IS_WINDOW (window));
2909 priv = window->priv;
2911 setting = setting != FALSE;
2913 if (priv->focus_on_map != setting)
2915 priv->focus_on_map = setting;
2916 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2917 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2918 priv->focus_on_map);
2919 g_object_notify (G_OBJECT (window), "focus-on-map");
2924 * gtk_window_get_focus_on_map:
2925 * @window: a #GtkWindow
2927 * Gets the value set by gtk_window_set_focus_on_map().
2929 * Return value: %TRUE if window should receive the input focus when
2935 gtk_window_get_focus_on_map (GtkWindow *window)
2937 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2939 return window->priv->focus_on_map;
2943 * gtk_window_set_destroy_with_parent:
2944 * @window: a #GtkWindow
2945 * @setting: whether to destroy @window with its transient parent
2947 * If @setting is %TRUE, then destroying the transient parent of @window
2948 * will also destroy @window itself. This is useful for dialogs that
2949 * shouldn't persist beyond the lifetime of the main window they're
2950 * associated with, for example.
2953 gtk_window_set_destroy_with_parent (GtkWindow *window,
2956 GtkWindowPrivate *priv;
2958 g_return_if_fail (GTK_IS_WINDOW (window));
2960 priv = window->priv;
2962 if (priv->destroy_with_parent == (setting != FALSE))
2965 if (priv->destroy_with_parent)
2967 disconnect_parent_destroyed (window);
2971 connect_parent_destroyed (window);
2974 priv->destroy_with_parent = setting;
2976 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2980 * gtk_window_get_destroy_with_parent:
2981 * @window: a #GtkWindow
2983 * Returns whether the window will be destroyed with its transient parent. See
2984 * gtk_window_set_destroy_with_parent ().
2986 * Return value: %TRUE if the window will be destroyed with its transient parent.
2989 gtk_window_get_destroy_with_parent (GtkWindow *window)
2991 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2993 return window->priv->destroy_with_parent;
2996 static GtkWindowGeometryInfo*
2997 gtk_window_get_geometry_info (GtkWindow *window,
3000 GtkWindowPrivate *priv = window->priv;
3001 GtkWindowGeometryInfo *info;
3003 info = priv->geometry_info;
3004 if (!info && create)
3006 info = g_new0 (GtkWindowGeometryInfo, 1);
3008 info->default_width = -1;
3009 info->default_height = -1;
3010 info->resize_width = -1;
3011 info->resize_height = -1;
3012 info->initial_x = 0;
3013 info->initial_y = 0;
3014 info->initial_pos_set = FALSE;
3015 info->default_is_geometry = FALSE;
3016 info->position_constraints_changed = FALSE;
3017 info->last.configure_request.x = 0;
3018 info->last.configure_request.y = 0;
3019 info->last.configure_request.width = -1;
3020 info->last.configure_request.height = -1;
3021 info->widget = NULL;
3023 priv->geometry_info = info;
3030 * gtk_window_set_geometry_hints:
3031 * @window: a #GtkWindow
3032 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3033 * @geometry: (allow-none): struct containing geometry information or %NULL
3034 * @geom_mask: mask indicating which struct fields should be paid attention to
3036 * This function sets up hints about how a window can be resized by
3037 * the user. You can set a minimum and maximum size; allowed resize
3038 * increments (e.g. for xterm, you can only resize by the size of a
3039 * character); aspect ratios; and more. See the #GdkGeometry struct.
3043 gtk_window_set_geometry_hints (GtkWindow *window,
3044 GtkWidget *geometry_widget,
3045 GdkGeometry *geometry,
3046 GdkWindowHints geom_mask)
3048 GtkWindowGeometryInfo *info;
3050 g_return_if_fail (GTK_IS_WINDOW (window));
3051 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3053 info = gtk_window_get_geometry_info (window, TRUE);
3056 g_signal_handlers_disconnect_by_func (info->widget,
3057 gtk_widget_destroyed,
3060 info->widget = geometry_widget;
3062 g_signal_connect (geometry_widget, "destroy",
3063 G_CALLBACK (gtk_widget_destroyed),
3067 info->geometry = *geometry;
3069 /* We store gravity in priv->gravity not in the hints. */
3070 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3072 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3074 gtk_window_set_gravity (window, geometry->win_gravity);
3077 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3081 * gtk_window_set_decorated:
3082 * @window: a #GtkWindow
3083 * @setting: %TRUE to decorate the window
3085 * By default, windows are decorated with a title bar, resize
3086 * controls, etc. Some <link linkend="gtk-X11-arch">window
3087 * managers</link> allow GTK+ to disable these decorations, creating a
3088 * borderless window. If you set the decorated property to %FALSE
3089 * using this function, GTK+ will do its best to convince the window
3090 * manager not to decorate the window. Depending on the system, this
3091 * function may not have any effect when called on a window that is
3092 * already visible, so you should call it before calling gtk_widget_show().
3094 * On Windows, this function always works, since there's no window manager
3099 gtk_window_set_decorated (GtkWindow *window,
3102 GtkWindowPrivate *priv;
3103 GdkWindow *gdk_window;
3105 g_return_if_fail (GTK_IS_WINDOW (window));
3107 priv = window->priv;
3109 setting = setting != FALSE;
3111 if (setting == priv->decorated)
3114 priv->decorated = setting;
3116 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3119 if (priv->decorated)
3120 gdk_window_set_decorations (gdk_window,
3123 gdk_window_set_decorations (gdk_window,
3127 g_object_notify (G_OBJECT (window), "decorated");
3131 * gtk_window_get_decorated:
3132 * @window: a #GtkWindow
3134 * Returns whether the window has been set to have decorations
3135 * such as a title bar via gtk_window_set_decorated().
3137 * Return value: %TRUE if the window has been set to have decorations
3140 gtk_window_get_decorated (GtkWindow *window)
3142 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3144 return window->priv->decorated;
3148 * gtk_window_set_deletable:
3149 * @window: a #GtkWindow
3150 * @setting: %TRUE to decorate the window as deletable
3152 * By default, windows have a close button in the window frame. Some
3153 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3154 * disable this button. If you set the deletable property to %FALSE
3155 * using this function, GTK+ will do its best to convince the window
3156 * manager not to show a close button. Depending on the system, this
3157 * function may not have any effect when called on a window that is
3158 * already visible, so you should call it before calling gtk_window_show().
3160 * On Windows, this function always works, since there's no window manager
3166 gtk_window_set_deletable (GtkWindow *window,
3169 GtkWindowPrivate *priv;
3170 GdkWindow *gdk_window;
3172 g_return_if_fail (GTK_IS_WINDOW (window));
3174 priv = window->priv;
3176 setting = setting != FALSE;
3178 if (setting == priv->deletable)
3181 priv->deletable = setting;
3183 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3186 if (priv->deletable)
3187 gdk_window_set_functions (gdk_window,
3190 gdk_window_set_functions (gdk_window,
3191 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3194 g_object_notify (G_OBJECT (window), "deletable");
3198 * gtk_window_get_deletable:
3199 * @window: a #GtkWindow
3201 * Returns whether the window has been set to have a close button
3202 * via gtk_window_set_deletable().
3204 * Return value: %TRUE if the window has been set to have a close button
3209 gtk_window_get_deletable (GtkWindow *window)
3211 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3213 return window->priv->deletable;
3216 static GtkWindowIconInfo*
3217 get_icon_info (GtkWindow *window)
3219 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3223 free_icon_info (GtkWindowIconInfo *info)
3225 g_free (info->icon_name);
3226 g_slice_free (GtkWindowIconInfo, info);
3230 static GtkWindowIconInfo*
3231 ensure_icon_info (GtkWindow *window)
3233 GtkWindowIconInfo *info;
3235 info = get_icon_info (window);
3239 info = g_slice_new0 (GtkWindowIconInfo);
3240 g_object_set_qdata_full (G_OBJECT (window),
3241 quark_gtk_window_icon_info,
3243 (GDestroyNotify)free_icon_info);
3250 icon_list_from_theme (GtkWidget *widget,
3255 GtkIconTheme *icon_theme;
3260 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3262 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3265 for (i = 0; sizes[i]; i++)
3268 * We need an EWMH extension to handle scalable icons
3269 * by passing their name to the WM. For now just use a
3273 icon = gtk_icon_theme_load_icon (icon_theme, name,
3276 icon = gtk_icon_theme_load_icon (icon_theme, name,
3279 list = g_list_append (list, icon);
3289 gtk_window_realize_icon (GtkWindow *window)
3291 GtkWindowPrivate *priv = window->priv;
3293 GtkWindowIconInfo *info;
3294 GdkWindow *gdk_window;
3297 widget = GTK_WIDGET (window);
3298 gdk_window = gtk_widget_get_window (widget);
3300 g_return_if_fail (gdk_window != NULL);
3302 /* no point setting an icon on override-redirect */
3303 if (priv->type == GTK_WINDOW_POPUP)
3308 info = ensure_icon_info (window);
3313 info->using_default_icon = FALSE;
3314 info->using_parent_icon = FALSE;
3315 info->using_themed_icon = FALSE;
3317 icon_list = info->icon_list;
3319 /* Look up themed icon */
3320 if (icon_list == NULL && info->icon_name)
3322 icon_list = icon_list_from_theme (widget, info->icon_name);
3324 info->using_themed_icon = TRUE;
3327 /* Inherit from transient parent */
3328 if (icon_list == NULL && priv->transient_parent)
3330 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3332 info->using_parent_icon = TRUE;
3335 /* Inherit from default */
3336 if (icon_list == NULL)
3338 icon_list = default_icon_list;
3340 info->using_default_icon = TRUE;
3343 /* Look up themed icon */
3344 if (icon_list == NULL && default_icon_name)
3346 icon_list = icon_list_from_theme (widget, default_icon_name);
3347 info->using_default_icon = TRUE;
3348 info->using_themed_icon = TRUE;
3351 info->realized = TRUE;
3353 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3355 if (info->using_themed_icon)
3357 GtkIconTheme *icon_theme;
3359 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3360 g_list_free (icon_list);
3362 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3363 g_signal_connect (icon_theme, "changed",
3364 G_CALLBACK (update_themed_icon), window);
3369 gtk_window_unrealize_icon (GtkWindow *window)
3371 GtkWindowIconInfo *info;
3373 info = get_icon_info (window);
3378 if (info->using_themed_icon)
3380 GtkIconTheme *icon_theme;
3382 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3384 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3387 /* We don't clear the properties on the window, just figure the
3388 * window is going away.
3391 info->realized = FALSE;
3396 * gtk_window_set_icon_list:
3397 * @window: a #GtkWindow
3398 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3400 * Sets up the icon representing a #GtkWindow. The icon is used when
3401 * the window is minimized (also known as iconified). Some window
3402 * managers or desktop environments may also place it in the window
3403 * frame, or display it in other contexts.
3405 * gtk_window_set_icon_list() allows you to pass in the same icon in
3406 * several hand-drawn sizes. The list should contain the natural sizes
3407 * your icon is available in; that is, don't scale the image before
3408 * passing it to GTK+. Scaling is postponed until the last minute,
3409 * when the desired final size is known, to allow best quality.
3411 * By passing several sizes, you may improve the final image quality
3412 * of the icon, by reducing or eliminating automatic image scaling.
3414 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3415 * larger images (64x64, 128x128) if you have them.
3417 * See also gtk_window_set_default_icon_list() to set the icon
3418 * for all windows in your application in one go.
3420 * Note that transient windows (those who have been set transient for another
3421 * window using gtk_window_set_transient_for()) will inherit their
3422 * icon from their transient parent. So there's no need to explicitly
3423 * set the icon on transient windows.
3426 gtk_window_set_icon_list (GtkWindow *window,
3429 GtkWindowIconInfo *info;
3431 g_return_if_fail (GTK_IS_WINDOW (window));
3433 info = ensure_icon_info (window);
3435 if (info->icon_list == list) /* check for NULL mostly */
3438 g_list_foreach (list,
3439 (GFunc) g_object_ref, NULL);
3441 g_list_foreach (info->icon_list,
3442 (GFunc) g_object_unref, NULL);
3444 g_list_free (info->icon_list);
3446 info->icon_list = g_list_copy (list);
3448 g_object_notify (G_OBJECT (window), "icon");
3450 gtk_window_unrealize_icon (window);
3452 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3453 gtk_window_realize_icon (window);
3455 /* We could try to update our transient children, but I don't think
3456 * it's really worth it. If we did it, the best way would probably
3457 * be to have children connect to notify::icon-list
3462 * gtk_window_get_icon_list:
3463 * @window: a #GtkWindow
3465 * Retrieves the list of icons set by gtk_window_set_icon_list().
3466 * The list is copied, but the reference count on each
3467 * member won't be incremented.
3469 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3472 gtk_window_get_icon_list (GtkWindow *window)
3474 GtkWindowIconInfo *info;
3476 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3478 info = get_icon_info (window);
3481 return g_list_copy (info->icon_list);
3487 * gtk_window_set_icon:
3488 * @window: a #GtkWindow
3489 * @icon: (allow-none): icon image, or %NULL
3491 * Sets up the icon representing a #GtkWindow. This icon is used when
3492 * the window is minimized (also known as iconified). Some window
3493 * managers or desktop environments may also place it in the window
3494 * frame, or display it in other contexts.
3496 * The icon should be provided in whatever size it was naturally
3497 * drawn; that is, don't scale the image before passing it to
3498 * GTK+. Scaling is postponed until the last minute, when the desired
3499 * final size is known, to allow best quality.
3501 * If you have your icon hand-drawn in multiple sizes, use
3502 * gtk_window_set_icon_list(). Then the best size will be used.
3504 * This function is equivalent to calling gtk_window_set_icon_list()
3505 * with a 1-element list.
3507 * See also gtk_window_set_default_icon_list() to set the icon
3508 * for all windows in your application in one go.
3511 gtk_window_set_icon (GtkWindow *window,
3516 g_return_if_fail (GTK_IS_WINDOW (window));
3517 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3522 list = g_list_append (list, icon);
3524 gtk_window_set_icon_list (window, list);
3530 update_themed_icon (GtkIconTheme *icon_theme,
3533 g_object_notify (G_OBJECT (window), "icon");
3535 gtk_window_unrealize_icon (window);
3537 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3538 gtk_window_realize_icon (window);
3542 * gtk_window_set_icon_name:
3543 * @window: a #GtkWindow
3544 * @name: (allow-none): the name of the themed icon
3546 * Sets the icon for the window from a named themed icon. See
3547 * the docs for #GtkIconTheme for more details.
3549 * Note that this has nothing to do with the WM_ICON_NAME
3550 * property which is mentioned in the ICCCM.
3555 gtk_window_set_icon_name (GtkWindow *window,
3558 GtkWindowIconInfo *info;
3561 g_return_if_fail (GTK_IS_WINDOW (window));
3563 info = ensure_icon_info (window);
3565 if (g_strcmp0 (info->icon_name, name) == 0)
3568 tmp = info->icon_name;
3569 info->icon_name = g_strdup (name);
3572 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3573 g_list_free (info->icon_list);
3574 info->icon_list = NULL;
3576 update_themed_icon (NULL, window);
3578 g_object_notify (G_OBJECT (window), "icon-name");
3582 * gtk_window_get_icon_name:
3583 * @window: a #GtkWindow
3585 * Returns the name of the themed icon for the window,
3586 * see gtk_window_set_icon_name().
3588 * Returns: the icon name or %NULL if the window has
3594 gtk_window_get_icon_name (GtkWindow *window)
3596 GtkWindowIconInfo *info;
3598 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3600 info = ensure_icon_info (window);
3602 return info->icon_name;
3606 * gtk_window_get_icon:
3607 * @window: a #GtkWindow
3609 * Gets the value set by gtk_window_set_icon() (or if you've
3610 * called gtk_window_set_icon_list(), gets the first icon in
3613 * Return value: (transfer none): icon for window
3616 gtk_window_get_icon (GtkWindow *window)
3618 GtkWindowIconInfo *info;
3620 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3622 info = get_icon_info (window);
3623 if (info && info->icon_list)
3624 return GDK_PIXBUF (info->icon_list->data);
3629 /* Load pixbuf, printing warning on failure if error == NULL
3632 load_pixbuf_verbosely (const char *filename,
3635 GError *local_err = NULL;
3638 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3646 g_warning ("Error loading icon from file '%s':\n\t%s",
3647 filename, local_err->message);
3648 g_error_free (local_err);
3656 * gtk_window_set_icon_from_file:
3657 * @window: a #GtkWindow
3658 * @filename: (type filename): location of icon file
3659 * @err: (allow-none): location to store error, or %NULL.
3661 * Sets the icon for @window.
3662 * Warns on failure if @err is %NULL.
3664 * This function is equivalent to calling gtk_window_set_icon()
3665 * with a pixbuf created by loading the image from @filename.
3667 * Returns: %TRUE if setting the icon succeeded.
3672 gtk_window_set_icon_from_file (GtkWindow *window,
3673 const gchar *filename,
3676 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3680 gtk_window_set_icon (window, pixbuf);
3681 g_object_unref (pixbuf);
3690 * gtk_window_set_default_icon_list:
3691 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3693 * Sets an icon list to be used as fallback for windows that haven't
3694 * had gtk_window_set_icon_list() called on them to set up a
3695 * window-specific icon list. This function allows you to set up the
3696 * icon for all windows in your app at once.
3698 * See gtk_window_set_icon_list() for more details.
3702 gtk_window_set_default_icon_list (GList *list)
3706 if (list == default_icon_list)
3709 /* Update serial so we don't used cached pixmaps/masks
3711 default_icon_serial++;
3713 g_list_foreach (list,
3714 (GFunc) g_object_ref, NULL);
3716 g_list_foreach (default_icon_list,
3717 (GFunc) g_object_unref, NULL);
3719 g_list_free (default_icon_list);
3721 default_icon_list = g_list_copy (list);
3723 /* Update all toplevels */
3724 toplevels = gtk_window_list_toplevels ();
3725 tmp_list = toplevels;
3726 while (tmp_list != NULL)
3728 GtkWindowIconInfo *info;
3729 GtkWindow *w = tmp_list->data;
3731 info = get_icon_info (w);
3732 if (info && info->using_default_icon)
3734 gtk_window_unrealize_icon (w);
3735 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3736 gtk_window_realize_icon (w);
3739 tmp_list = tmp_list->next;
3741 g_list_free (toplevels);
3745 * gtk_window_set_default_icon:
3748 * Sets an icon to be used as fallback for windows that haven't
3749 * had gtk_window_set_icon() called on them from a pixbuf.
3754 gtk_window_set_default_icon (GdkPixbuf *icon)
3758 g_return_if_fail (GDK_IS_PIXBUF (icon));
3760 list = g_list_prepend (NULL, icon);
3761 gtk_window_set_default_icon_list (list);
3766 * gtk_window_set_default_icon_name:
3767 * @name: the name of the themed icon
3769 * Sets an icon to be used as fallback for windows that haven't
3770 * had gtk_window_set_icon_list() called on them from a named
3771 * themed icon, see gtk_window_set_icon_name().
3776 gtk_window_set_default_icon_name (const gchar *name)
3781 /* Update serial so we don't used cached pixmaps/masks
3783 default_icon_serial++;
3785 g_free (default_icon_name);
3786 default_icon_name = g_strdup (name);
3788 g_list_foreach (default_icon_list,
3789 (GFunc) g_object_unref, NULL);
3791 g_list_free (default_icon_list);
3792 default_icon_list = NULL;
3794 /* Update all toplevels */
3795 toplevels = gtk_window_list_toplevels ();
3796 tmp_list = toplevels;
3797 while (tmp_list != NULL)
3799 GtkWindowIconInfo *info;
3800 GtkWindow *w = tmp_list->data;
3802 info = get_icon_info (w);
3803 if (info && info->using_default_icon && info->using_themed_icon)
3805 gtk_window_unrealize_icon (w);
3806 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3807 gtk_window_realize_icon (w);
3810 tmp_list = tmp_list->next;
3812 g_list_free (toplevels);
3816 * gtk_window_get_default_icon_name:
3818 * Returns the fallback icon name for windows that has been set
3819 * with gtk_window_set_default_icon_name(). The returned
3820 * string is owned by GTK+ and should not be modified. It
3821 * is only valid until the next call to
3822 * gtk_window_set_default_icon_name().
3824 * Returns: the fallback icon name for windows
3829 gtk_window_get_default_icon_name (void)
3831 return default_icon_name;
3835 * gtk_window_set_default_icon_from_file:
3836 * @filename: (type filename): location of icon file
3837 * @err: (allow-none): location to store error, or %NULL.
3839 * Sets an icon to be used as fallback for windows that haven't
3840 * had gtk_window_set_icon_list() called on them from a file
3841 * on disk. Warns on failure if @err is %NULL.
3843 * Returns: %TRUE if setting the icon succeeded.
3848 gtk_window_set_default_icon_from_file (const gchar *filename,
3851 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3855 gtk_window_set_default_icon (pixbuf);
3856 g_object_unref (pixbuf);
3865 * gtk_window_get_default_icon_list:
3867 * Gets the value set by gtk_window_set_default_icon_list().
3868 * The list is a copy and should be freed with g_list_free(),
3869 * but the pixbufs in the list have not had their reference count
3872 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3875 gtk_window_get_default_icon_list (void)
3877 return g_list_copy (default_icon_list);
3881 gtk_window_set_default_size_internal (GtkWindow *window,
3882 gboolean change_width,
3884 gboolean change_height,
3886 gboolean is_geometry)
3888 GtkWindowGeometryInfo *info;
3890 g_return_if_fail (change_width == FALSE || width >= -1);
3891 g_return_if_fail (change_height == FALSE || height >= -1);
3893 info = gtk_window_get_geometry_info (window, TRUE);
3895 g_object_freeze_notify (G_OBJECT (window));
3897 info->default_is_geometry = is_geometry != FALSE;
3907 info->default_width = width;
3909 g_object_notify (G_OBJECT (window), "default-width");
3920 info->default_height = height;
3922 g_object_notify (G_OBJECT (window), "default-height");
3925 g_object_thaw_notify (G_OBJECT (window));
3927 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3931 * gtk_window_set_default_size:
3932 * @window: a #GtkWindow
3933 * @width: width in pixels, or -1 to unset the default width
3934 * @height: height in pixels, or -1 to unset the default height
3936 * Sets the default size of a window. If the window's "natural" size
3937 * (its size request) is larger than the default, the default will be
3938 * ignored. More generally, if the default size does not obey the
3939 * geometry hints for the window (gtk_window_set_geometry_hints() can
3940 * be used to set these explicitly), the default size will be clamped
3941 * to the nearest permitted size.
3943 * Unlike gtk_widget_set_size_request(), which sets a size request for
3944 * a widget and thus would keep users from shrinking the window, this
3945 * function only sets the initial size, just as if the user had
3946 * resized the window themselves. Users can still shrink the window
3947 * again as they normally would. Setting a default size of -1 means to
3948 * use the "natural" default size (the size request of the window).
3950 * For more control over a window's initial size and how resizing works,
3951 * investigate gtk_window_set_geometry_hints().
3953 * For some uses, gtk_window_resize() is a more appropriate function.
3954 * gtk_window_resize() changes the current size of the window, rather
3955 * than the size to be used on initial display. gtk_window_resize() always
3956 * affects the window itself, not the geometry widget.
3958 * The default size of a window only affects the first time a window is
3959 * shown; if a window is hidden and re-shown, it will remember the size
3960 * it had prior to hiding, rather than using the default size.
3962 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3963 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3966 gtk_window_set_default_size (GtkWindow *window,
3970 g_return_if_fail (GTK_IS_WINDOW (window));
3971 g_return_if_fail (width >= -1);
3972 g_return_if_fail (height >= -1);
3974 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3978 * gtk_window_set_default_geometry:
3979 * @window: a #GtkWindow
3980 * @width: width in resize increments, or -1 to unset the default width
3981 * @height: height in resize increments, or -1 to unset the default height
3983 * Like gtk_window_set_default_size(), but @width and @height are interpreted
3984 * in terms of the base size and increment set with
3985 * gtk_window_set_geometry_hints.
3990 gtk_window_set_default_geometry (GtkWindow *window,
3994 g_return_if_fail (GTK_IS_WINDOW (window));
3995 g_return_if_fail (width >= -1);
3996 g_return_if_fail (height >= -1);
3998 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4002 * gtk_window_get_default_size:
4003 * @window: a #GtkWindow
4004 * @width: (out) (allow-none): location to store the default width, or %NULL
4005 * @height: (out) (allow-none): location to store the default height, or %NULL
4007 * Gets the default size of the window. A value of -1 for the width or
4008 * height indicates that a default size has not been explicitly set
4009 * for that dimension, so the "natural" size of the window will be
4014 gtk_window_get_default_size (GtkWindow *window,
4018 GtkWindowGeometryInfo *info;
4020 g_return_if_fail (GTK_IS_WINDOW (window));
4022 info = gtk_window_get_geometry_info (window, FALSE);
4025 *width = info ? info->default_width : -1;
4028 *height = info ? info->default_height : -1;
4032 * gtk_window_resize:
4033 * @window: a #GtkWindow
4034 * @width: width in pixels to resize the window to
4035 * @height: height in pixels to resize the window to
4037 * Resizes the window as if the user had done so, obeying geometry
4038 * constraints. The default geometry constraint is that windows may
4039 * not be smaller than their size request; to override this
4040 * constraint, call gtk_widget_set_size_request() to set the window's
4041 * request to a smaller value.
4043 * If gtk_window_resize() is called before showing a window for the
4044 * first time, it overrides any default size set with
4045 * gtk_window_set_default_size().
4047 * Windows may not be resized smaller than 1 by 1 pixels.
4051 gtk_window_resize (GtkWindow *window,
4055 GtkWindowGeometryInfo *info;
4057 g_return_if_fail (GTK_IS_WINDOW (window));
4058 g_return_if_fail (width > 0);
4059 g_return_if_fail (height > 0);
4061 info = gtk_window_get_geometry_info (window, TRUE);
4063 info->resize_width = width;
4064 info->resize_height = height;
4065 info->resize_is_geometry = FALSE;
4067 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4071 * gtk_window_resize_to_geometry:
4072 * @window: a #GtkWindow
4073 * @width: width in resize increments to resize the window to
4074 * @height: height in resize increments to resize the window to
4076 * Like gtk_window_resize(), but @width and @height are interpreted
4077 * in terms of the base size and increment set with
4078 * gtk_window_set_geometry_hints.
4083 gtk_window_resize_to_geometry (GtkWindow *window,
4087 GtkWindowGeometryInfo *info;
4089 g_return_if_fail (GTK_IS_WINDOW (window));
4090 g_return_if_fail (width > 0);
4091 g_return_if_fail (height > 0);
4093 info = gtk_window_get_geometry_info (window, TRUE);
4095 info->resize_width = width;
4096 info->resize_height = height;
4097 info->resize_is_geometry = TRUE;
4099 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4103 * gtk_window_get_size:
4104 * @window: a #GtkWindow
4105 * @width: (out) (allow-none): return location for width, or %NULL
4106 * @height: (out) (allow-none): return location for height, or %NULL
4108 * Obtains the current size of @window. If @window is not onscreen,
4109 * it returns the size GTK+ will suggest to the <link
4110 * linkend="gtk-X11-arch">window manager</link> for the initial window
4111 * size (but this is not reliably the same as the size the window
4112 * manager will actually select). The size obtained by
4113 * gtk_window_get_size() is the last size received in a
4114 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4115 * rather than querying the X server for the size. As a result, if you
4116 * call gtk_window_resize() then immediately call
4117 * gtk_window_get_size(), the size won't have taken effect yet. After
4118 * the window manager processes the resize request, GTK+ receives
4119 * notification that the size has changed via a configure event, and
4120 * the size of the window gets updated.
4122 * Note 1: Nearly any use of this function creates a race condition,
4123 * because the size of the window may change between the time that you
4124 * get the size and the time that you perform some action assuming
4125 * that size is the current size. To avoid race conditions, connect to
4126 * "configure-event" on the window and adjust your size-dependent
4127 * state to match the size delivered in the #GdkEventConfigure.
4129 * Note 2: The returned size does <emphasis>not</emphasis> include the
4130 * size of the window manager decorations (aka the window frame or
4131 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4132 * method of determining their size.
4134 * Note 3: If you are getting a window size in order to position
4135 * the window onscreen, there may be a better way. The preferred
4136 * way is to simply set the window's semantic type with
4137 * gtk_window_set_type_hint(), which allows the window manager to
4138 * e.g. center dialogs. Also, if you set the transient parent of
4139 * dialogs with gtk_window_set_transient_for() window managers
4140 * will often center the dialog over its parent window. It's
4141 * much preferred to let the window manager handle these
4142 * things rather than doing it yourself, because all apps will
4143 * behave consistently and according to user prefs if the window
4144 * manager handles it. Also, the window manager can take the size
4145 * of the window decorations/border into account, while your
4146 * application cannot.
4148 * In any case, if you insist on application-specified window
4149 * positioning, there's <emphasis>still</emphasis> a better way than
4150 * doing it yourself - gtk_window_set_position() will frequently
4151 * handle the details for you.
4155 gtk_window_get_size (GtkWindow *window,
4161 g_return_if_fail (GTK_IS_WINDOW (window));
4163 if (width == NULL && height == NULL)
4166 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4168 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4169 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4173 GdkRectangle configure_request;
4175 gtk_window_compute_configure_request (window,
4179 w = configure_request.width;
4180 h = configure_request.height;
4191 * @window: a #GtkWindow
4192 * @x: X coordinate to move window to
4193 * @y: Y coordinate to move window to
4195 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4196 * @window to the given position. Window managers are free to ignore
4197 * this; most window managers ignore requests for initial window
4198 * positions (instead using a user-defined placement algorithm) and
4199 * honor requests after the window has already been shown.
4201 * Note: the position is the position of the gravity-determined
4202 * reference point for the window. The gravity determines two things:
4203 * first, the location of the reference point in root window
4204 * coordinates; and second, which point on the window is positioned at
4205 * the reference point.
4207 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4208 * point is simply the @x, @y supplied to gtk_window_move(). The
4209 * top-left corner of the window decorations (aka window frame or
4210 * border) will be placed at @x, @y. Therefore, to position a window
4211 * at the top left of the screen, you want to use the default gravity
4212 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4214 * To position a window at the bottom right corner of the screen, you
4215 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4216 * point is at @x + the window width and @y + the window height, and
4217 * the bottom-right corner of the window border will be placed at that
4218 * reference point. So, to place a window in the bottom right corner
4219 * you would first set gravity to south east, then write:
4220 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4221 * gdk_screen_height () - window_height)</literal> (note that this
4222 * example does not take multi-head scenarios into account).
4224 * The Extended Window Manager Hints specification at <ulink
4225 * url="http://www.freedesktop.org/Standards/wm-spec">
4226 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4227 * nice table of gravities in the "implementation notes" section.
4229 * The gtk_window_get_position() documentation may also be relevant.
4232 gtk_window_move (GtkWindow *window,
4236 GtkWindowGeometryInfo *info;
4239 g_return_if_fail (GTK_IS_WINDOW (window));
4241 widget = GTK_WIDGET (window);
4243 info = gtk_window_get_geometry_info (window, TRUE);
4245 if (gtk_widget_get_mapped (widget))
4247 GtkAllocation allocation;
4249 gtk_widget_get_allocation (widget, &allocation);
4251 /* we have now sent a request with this position
4252 * with currently-active constraints, so toggle flag.
4254 info->position_constraints_changed = FALSE;
4256 /* we only constrain if mapped - if not mapped,
4257 * then gtk_window_compute_configure_request()
4258 * will apply the constraints later, and we
4259 * don't want to lose information about
4260 * what position the user set before then.
4261 * i.e. if you do a move() then turn off POS_CENTER
4262 * then show the window, your move() will work.
4264 gtk_window_constrain_position (window,
4265 allocation.width, allocation.height,
4268 /* Note that this request doesn't go through our standard request
4269 * framework, e.g. doesn't increment configure_request_count,
4270 * doesn't set info->last, etc.; that's because
4271 * we don't save the info needed to arrive at this same request
4274 * To gtk_window_move_resize(), this will end up looking exactly
4275 * the same as the position being changed by the window
4278 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4282 /* Save this position to apply on mapping */
4283 info->initial_x = x;
4284 info->initial_y = y;
4285 info->initial_pos_set = TRUE;
4290 * gtk_window_get_position:
4291 * @window: a #GtkWindow
4292 * @root_x: (out) (allow-none): eturn location for X coordinate of
4293 * gravity-determined reference point, or %NULL
4294 * @root_y: (out) (allow-none): return location for Y coordinate of
4295 * gravity-determined reference point, or %NULL
4297 * This function returns the position you need to pass to
4298 * gtk_window_move() to keep @window in its current position.
4299 * This means that the meaning of the returned value varies with
4300 * window gravity. See gtk_window_move() for more details.
4302 * If you haven't changed the window gravity, its gravity will be
4303 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4304 * gets the position of the top-left corner of the window manager
4305 * frame for the window. gtk_window_move() sets the position of this
4306 * same top-left corner.
4308 * gtk_window_get_position() is not 100% reliable because the X Window System
4309 * does not specify a way to obtain the geometry of the
4310 * decorations placed on a window by the window manager.
4311 * Thus GTK+ is using a "best guess" that works with most
4314 * Moreover, nearly all window managers are historically broken with
4315 * respect to their handling of window gravity. So moving a window to
4316 * its current position as returned by gtk_window_get_position() tends
4317 * to result in moving the window slightly. Window managers are
4318 * slowly getting better over time.
4320 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4321 * frame is not relevant, and thus gtk_window_get_position() will
4322 * always produce accurate results. However you can't use static
4323 * gravity to do things like place a window in a corner of the screen,
4324 * because static gravity ignores the window manager decorations.
4326 * If you are saving and restoring your application's window
4327 * positions, you should know that it's impossible for applications to
4328 * do this without getting it somewhat wrong because applications do
4329 * not have sufficient knowledge of window manager state. The Correct
4330 * Mechanism is to support the session management protocol (see the
4331 * "GnomeClient" object in the GNOME libraries for example) and allow
4332 * the window manager to save your window sizes and positions.
4337 gtk_window_get_position (GtkWindow *window,
4341 GtkWindowPrivate *priv;
4343 GdkWindow *gdk_window;
4345 g_return_if_fail (GTK_IS_WINDOW (window));
4347 priv = window->priv;
4348 widget = GTK_WIDGET (window);
4349 gdk_window = gtk_widget_get_window (widget);
4351 if (priv->gravity == GDK_GRAVITY_STATIC)
4353 if (gtk_widget_get_mapped (widget))
4355 /* This does a server round-trip, which is sort of wrong;
4356 * but a server round-trip is inevitable for
4357 * gdk_window_get_frame_extents() in the usual
4358 * NorthWestGravity case below, so not sure what else to
4359 * do. We should likely be consistent about whether we get
4360 * the client-side info or the server-side info.
4362 gdk_window_get_origin (gdk_window, root_x, root_y);
4366 GdkRectangle configure_request;
4368 gtk_window_compute_configure_request (window,
4372 *root_x = configure_request.x;
4373 *root_y = configure_request.y;
4378 GdkRectangle frame_extents;
4383 if (gtk_widget_get_mapped (widget))
4385 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4386 x = frame_extents.x;
4387 y = frame_extents.y;
4388 gtk_window_get_size (window, &w, &h);
4392 /* We just say the frame has 0 size on all sides.
4393 * Not sure what else to do.
4395 gtk_window_compute_configure_request (window,
4398 x = frame_extents.x;
4399 y = frame_extents.y;
4400 w = frame_extents.width;
4401 h = frame_extents.height;
4404 switch (priv->gravity)
4406 case GDK_GRAVITY_NORTH:
4407 case GDK_GRAVITY_CENTER:
4408 case GDK_GRAVITY_SOUTH:
4409 /* Find center of frame. */
4410 x += frame_extents.width / 2;
4411 /* Center client window on that point. */
4415 case GDK_GRAVITY_SOUTH_EAST:
4416 case GDK_GRAVITY_EAST:
4417 case GDK_GRAVITY_NORTH_EAST:
4418 /* Find right edge of frame */
4419 x += frame_extents.width;
4420 /* Align left edge of client at that point. */
4427 switch (priv->gravity)
4429 case GDK_GRAVITY_WEST:
4430 case GDK_GRAVITY_CENTER:
4431 case GDK_GRAVITY_EAST:
4432 /* Find center of frame. */
4433 y += frame_extents.height / 2;
4434 /* Center client window there. */
4437 case GDK_GRAVITY_SOUTH_WEST:
4438 case GDK_GRAVITY_SOUTH:
4439 case GDK_GRAVITY_SOUTH_EAST:
4440 /* Find south edge of frame */
4441 y += frame_extents.height;
4442 /* Place bottom edge of client there */
4457 * gtk_window_reshow_with_initial_size:
4458 * @window: a #GtkWindow
4460 * Hides @window, then reshows it, resetting the
4461 * default size and position of the window. Used
4462 * by GUI builders only.
4465 gtk_window_reshow_with_initial_size (GtkWindow *window)
4469 g_return_if_fail (GTK_IS_WINDOW (window));
4471 widget = GTK_WIDGET (window);
4473 gtk_widget_hide (widget);
4474 gtk_widget_unrealize (widget);
4475 gtk_widget_show (widget);
4479 gtk_window_destroy (GtkWidget *widget)
4481 GtkWindow *window = GTK_WINDOW (widget);
4482 GtkWindowPrivate *priv = window->priv;
4484 gtk_window_release_application (window);
4486 toplevel_list = g_slist_remove (toplevel_list, window);
4488 if (priv->transient_parent)
4489 gtk_window_set_transient_for (window, NULL);
4491 /* frees the icons */
4492 gtk_window_set_icon_list (window, NULL);
4494 if (priv->has_user_ref_count)
4496 priv->has_user_ref_count = FALSE;
4497 g_object_unref (window);
4501 gtk_window_group_remove_window (priv->group, window);
4503 gtk_window_free_key_hash (window);
4505 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4509 gtk_window_finalize (GObject *object)
4511 GtkWindow *window = GTK_WINDOW (object);
4512 GtkWindowPrivate *priv = window->priv;
4513 GtkMnemonicHash *mnemonic_hash;
4515 g_free (priv->title);
4516 g_free (priv->wmclass_name);
4517 g_free (priv->wmclass_class);
4518 g_free (priv->wm_role);
4519 gtk_window_release_application (window);
4521 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4523 _gtk_mnemonic_hash_free (mnemonic_hash);
4525 if (priv->geometry_info)
4527 if (priv->geometry_info->widget)
4528 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4529 gtk_widget_destroyed,
4530 &priv->geometry_info->widget);
4531 g_free (priv->geometry_info);
4534 if (priv->keys_changed_handler)
4536 g_source_remove (priv->keys_changed_handler);
4537 priv->keys_changed_handler = 0;
4541 g_signal_handlers_disconnect_by_func (priv->screen,
4542 gtk_window_on_composited_changed, window);
4544 g_free (priv->startup_id);
4546 #ifdef GDK_WINDOWING_X11
4547 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4548 gtk_window_on_theme_variant_changed,
4552 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4556 gtk_window_show (GtkWidget *widget)
4558 GtkWindow *window = GTK_WINDOW (widget);
4559 GtkWindowPrivate *priv = window->priv;
4560 GtkContainer *container = GTK_CONTAINER (window);
4561 gboolean need_resize;
4564 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4566 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4570 _gtk_widget_set_visible_flag (widget, TRUE);
4572 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4573 _gtk_container_set_need_resize (container, FALSE);
4577 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4578 GtkAllocation allocation = { 0, 0 };
4579 GdkRectangle configure_request;
4580 GdkGeometry new_geometry;
4582 gboolean was_realized;
4584 /* We are going to go ahead and perform this configure request
4585 * and then emulate a configure notify by going ahead and
4586 * doing a size allocate. Sort of a synchronous
4587 * mini-copy of gtk_window_move_resize() here.
4589 gtk_window_compute_configure_request (window,
4594 /* We update this because we are going to go ahead
4595 * and gdk_window_resize() below, rather than
4598 info->last.configure_request.width = configure_request.width;
4599 info->last.configure_request.height = configure_request.height;
4601 /* and allocate the window - this is normally done
4602 * in move_resize in response to configure notify
4604 allocation.width = configure_request.width;
4605 allocation.height = configure_request.height;
4606 gtk_widget_size_allocate (widget, &allocation);
4608 /* Then we guarantee we have a realize */
4609 was_realized = FALSE;
4610 if (!gtk_widget_get_realized (widget))
4612 gtk_widget_realize (widget);
4613 was_realized = TRUE;
4616 /* We only send configure request if we didn't just finish
4617 * creating the window; if we just created the window
4618 * then we created it with widget->allocation anyhow.
4621 gdk_window_move_resize (gtk_widget_get_window (widget),
4622 configure_request.x,
4623 configure_request.y,
4624 configure_request.width,
4625 configure_request.height);
4628 gtk_container_check_resize (container);
4630 gtk_widget_map (widget);
4632 /* Try to make sure that we have some focused widget
4634 #ifdef GDK_WINDOWING_X11
4635 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4636 GTK_IS_PLUG (window);
4640 if (!priv->focus_widget && !is_plug)
4641 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4644 gtk_grab_add (widget);
4648 gtk_window_hide (GtkWidget *widget)
4650 GtkWindow *window = GTK_WINDOW (widget);
4651 GtkWindowPrivate *priv = window->priv;
4653 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4655 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4659 _gtk_widget_set_visible_flag (widget, FALSE);
4660 gtk_widget_unmap (widget);
4663 gtk_grab_remove (widget);
4667 gtk_window_map (GtkWidget *widget)
4670 GtkWindow *window = GTK_WINDOW (widget);
4671 GtkWindowPrivate *priv = window->priv;
4672 GdkWindow *toplevel;
4673 GdkWindow *gdk_window;
4674 gboolean auto_mnemonics;
4676 gdk_window = gtk_widget_get_window (widget);
4678 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4680 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4684 gtk_widget_set_mapped (widget, TRUE);
4686 child = gtk_bin_get_child (&(window->bin));
4688 gtk_widget_get_visible (child) &&
4689 !gtk_widget_get_mapped (child))
4690 gtk_widget_map (child);
4692 toplevel = gdk_window;
4694 if (priv->maximize_initially)
4695 gdk_window_maximize (toplevel);
4697 gdk_window_unmaximize (toplevel);
4699 if (priv->stick_initially)
4700 gdk_window_stick (toplevel);
4702 gdk_window_unstick (toplevel);
4704 if (priv->iconify_initially)
4705 gdk_window_iconify (toplevel);
4707 gdk_window_deiconify (toplevel);
4709 if (priv->fullscreen_initially)
4710 gdk_window_fullscreen (toplevel);
4712 gdk_window_unfullscreen (toplevel);
4714 gdk_window_set_keep_above (toplevel, priv->above_initially);
4716 gdk_window_set_keep_below (toplevel, priv->below_initially);
4718 if (priv->type == GTK_WINDOW_TOPLEVEL)
4719 gtk_window_set_theme_variant (window);
4721 /* No longer use the default settings */
4722 priv->need_default_size = FALSE;
4723 priv->need_default_position = FALSE;
4725 if (priv->reset_type_hint)
4727 /* We should only reset the type hint when the application
4728 * used gtk_window_set_type_hint() to change the hint.
4729 * Some applications use X directly to change the properties;
4730 * in that case, we shouldn't overwrite what they did.
4732 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4733 priv->reset_type_hint = FALSE;
4736 gdk_window_show (gdk_window);
4738 if (priv->grip_window)
4739 gdk_window_show (priv->grip_window);
4741 if (!disable_startup_notification)
4743 /* Do we have a custom startup-notification id? */
4744 if (priv->startup_id != NULL)
4746 /* Make sure we have a "real" id */
4747 if (!startup_id_is_fake (priv->startup_id))
4748 gdk_notify_startup_complete_with_id (priv->startup_id);
4750 g_free (priv->startup_id);
4751 priv->startup_id = NULL;
4753 else if (!sent_startup_notification)
4755 sent_startup_notification = TRUE;
4756 gdk_notify_startup_complete ();
4760 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4761 * (as in the case of popup menus), then hide mnemonics initially
4763 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4764 &auto_mnemonics, NULL);
4765 if (auto_mnemonics && !priv->mnemonics_visible_set)
4766 gtk_window_set_mnemonics_visible (window, FALSE);
4770 gtk_window_map_event (GtkWidget *widget,
4773 if (!gtk_widget_get_mapped (widget))
4775 /* we should be be unmapped, but are getting a MapEvent, this may happen
4776 * to toplevel XWindows if mapping was intercepted by a window manager
4777 * and an unmap request occoured while the MapRequestEvent was still
4778 * being handled. we work around this situaiton here by re-requesting
4779 * the window being unmapped. more details can be found in:
4780 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4782 gdk_window_hide (gtk_widget_get_window (widget));
4788 gtk_window_unmap (GtkWidget *widget)
4790 GtkWindow *window = GTK_WINDOW (widget);
4791 GtkWindowPrivate *priv = window->priv;
4793 GtkWindowGeometryInfo *info;
4794 GdkWindow *gdk_window;
4795 GdkWindowState state;
4797 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4799 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
4803 gdk_window = gtk_widget_get_window (widget);
4805 gtk_widget_set_mapped (widget, FALSE);
4806 gdk_window_withdraw (gdk_window);
4808 priv->configure_request_count = 0;
4809 priv->configure_notify_received = FALSE;
4811 /* on unmap, we reset the default positioning of the window,
4812 * so it's placed again, but we don't reset the default
4813 * size of the window, so it's remembered.
4815 priv->need_default_position = TRUE;
4817 info = gtk_window_get_geometry_info (window, FALSE);
4820 info->initial_pos_set = FALSE;
4821 info->position_constraints_changed = FALSE;
4824 state = gdk_window_get_state (gdk_window);
4825 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4826 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4827 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4828 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4829 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4831 child = gtk_bin_get_child (&(window->bin));
4833 gtk_widget_unmap (child);
4836 /* (Note: Replace "size" with "width" or "height". Also, the request
4837 * mode is honoured.)
4838 * For selecting the default window size, the following conditions
4839 * should hold (in order of importance):
4840 * - the size is not below the minimum size
4841 * Windows cannot be resized below their minimum size, so we must
4842 * ensure we don't do that either.
4843 * - the size is not above the natural size
4844 * It seems weird to allocate more than this in an initial guess.
4845 * - the size does not exceed that of a maximized window
4846 * We want to see the whole window after all.
4847 * (Note that this may not be possible to achieve due to imperfect
4848 * information from the windowing system.)
4851 /* We use these for now to not make windows too big by accident. Note
4852 * that we still clamp these numbers by screen size. Also note that
4853 * minimum size still overrides this. So keep your windows small! :)
4855 #define MAX_DEFAULT_WINDOW_WIDTH 640
4856 #define MAX_DEFAULT_WINDOW_HEIGHT 480
4859 gtk_window_guess_default_size (GtkWindow *window,
4863 GtkWidget *widget = GTK_WIDGET (window);
4865 int minimum, natural;
4867 screen = gtk_widget_get_screen (widget);
4869 *width = gdk_screen_get_width (screen);
4870 *height = gdk_screen_get_height (screen);
4872 if (*width >= *height)
4875 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
4876 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
4881 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
4882 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
4885 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
4887 gtk_widget_get_preferred_height (widget, &minimum, &natural);
4888 *height = MAX (minimum, MIN (*height, natural));
4890 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
4891 *width = MAX (minimum, MIN (*width, natural));
4893 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
4895 gtk_widget_get_preferred_width (widget, &minimum, &natural);
4896 *width = MAX (minimum, MIN (*width, natural));
4898 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
4899 *height = MAX (minimum, MIN (*height, natural));
4904 gtk_window_realize (GtkWidget *widget)
4906 GtkAllocation allocation;
4908 GdkWindow *parent_window;
4909 GdkWindow *gdk_window;
4910 GdkWindowAttr attributes;
4911 gint attributes_mask;
4912 GtkWindowPrivate *priv;
4913 GtkStyleContext *context;
4915 window = GTK_WINDOW (widget);
4916 priv = window->priv;
4918 gtk_widget_get_allocation (widget, &allocation);
4920 if (gtk_widget_get_parent_window (widget))
4922 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
4924 gtk_widget_set_realized (widget, TRUE);
4926 attributes.x = allocation.x;
4927 attributes.y = allocation.y;
4928 attributes.width = allocation.width;
4929 attributes.height = allocation.height;
4930 attributes.window_type = GDK_WINDOW_CHILD;
4932 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
4934 attributes.visual = gtk_widget_get_visual (widget);
4935 attributes.wclass = GDK_INPUT_OUTPUT;
4937 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
4939 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
4940 &attributes, attributes_mask);
4941 gtk_widget_set_window (widget, gdk_window);
4942 gdk_window_set_user_data (gdk_window, widget);
4944 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
4946 gdk_window_enable_synchronized_configure (gdk_window);
4950 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
4952 /* ensure widget tree is properly size allocated */
4953 if (allocation.x == -1 &&
4954 allocation.y == -1 &&
4955 allocation.width == 1 &&
4956 allocation.height == 1)
4962 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
4963 if (allocation.width == 0 || allocation.height == 0)
4965 /* non-empty window */
4966 allocation.width = 200;
4967 allocation.height = 200;
4969 gtk_widget_size_allocate (widget, &allocation);
4971 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4973 g_return_if_fail (!gtk_widget_get_realized (widget));
4976 gtk_widget_set_realized (widget, TRUE);
4980 case GTK_WINDOW_TOPLEVEL:
4981 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4983 case GTK_WINDOW_POPUP:
4984 attributes.window_type = GDK_WINDOW_TEMP;
4987 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4991 attributes.title = priv->title;
4992 attributes.wmclass_name = priv->wmclass_name;
4993 attributes.wmclass_class = priv->wmclass_class;
4994 attributes.wclass = GDK_INPUT_OUTPUT;
4995 attributes.visual = gtk_widget_get_visual (widget);
4997 attributes_mask = 0;
4998 parent_window = gtk_widget_get_root_window (widget);
5000 gtk_widget_get_allocation (widget, &allocation);
5001 attributes.width = allocation.width;
5002 attributes.height = allocation.height;
5003 attributes.event_mask = gtk_widget_get_events (widget);
5004 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5005 GDK_KEY_PRESS_MASK |
5006 GDK_KEY_RELEASE_MASK |
5007 GDK_ENTER_NOTIFY_MASK |
5008 GDK_LEAVE_NOTIFY_MASK |
5009 GDK_FOCUS_CHANGE_MASK |
5010 GDK_STRUCTURE_MASK);
5011 attributes.type_hint = priv->type_hint;
5013 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5014 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5015 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5017 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5018 gtk_widget_set_window (widget, gdk_window);
5020 if (priv->opacity_set)
5021 gdk_window_set_opacity (gdk_window, priv->opacity);
5023 gdk_window_enable_synchronized_configure (gdk_window);
5025 gdk_window_set_user_data (gdk_window, window);
5027 context = gtk_widget_get_style_context (widget);
5028 gtk_style_context_set_background (context, gdk_window);
5031 if (priv->transient_parent &&
5032 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5033 gdk_window_set_transient_for (gdk_window,
5034 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5037 gdk_window_set_role (gdk_window, priv->wm_role);
5039 if (!priv->decorated)
5040 gdk_window_set_decorations (gdk_window, 0);
5042 if (!priv->deletable)
5043 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5045 if (gtk_window_get_skip_pager_hint (window))
5046 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5048 if (gtk_window_get_skip_taskbar_hint (window))
5049 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5051 if (gtk_window_get_accept_focus (window))
5052 gdk_window_set_accept_focus (gdk_window, TRUE);
5054 gdk_window_set_accept_focus (gdk_window, FALSE);
5056 if (gtk_window_get_focus_on_map (window))
5057 gdk_window_set_focus_on_map (gdk_window, TRUE);
5059 gdk_window_set_focus_on_map (gdk_window, FALSE);
5062 gdk_window_set_modal_hint (gdk_window, TRUE);
5064 gdk_window_set_modal_hint (gdk_window, FALSE);
5066 if (priv->startup_id)
5068 #ifdef GDK_WINDOWING_X11
5069 if (GDK_IS_X11_WINDOW (gdk_window))
5071 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5072 if (timestamp != GDK_CURRENT_TIME)
5073 gdk_x11_window_set_user_time (gdk_window, timestamp);
5076 if (!startup_id_is_fake (priv->startup_id))
5077 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5080 #ifdef GDK_WINDOWING_X11
5081 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5083 if (GDK_IS_X11_WINDOW (gdk_window))
5084 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5089 gtk_window_realize_icon (window);
5091 if (priv->has_resize_grip)
5092 resize_grip_create_window (window);
5096 gtk_window_unrealize (GtkWidget *widget)
5098 GtkWindow *window = GTK_WINDOW (widget);
5099 GtkWindowPrivate *priv = window->priv;
5100 GtkWindowGeometryInfo *info;
5102 /* On unrealize, we reset the size of the window such
5103 * that we will re-apply the default sizing stuff
5104 * next time we show the window.
5106 * Default positioning is reset on unmap, instead of unrealize.
5108 priv->need_default_size = TRUE;
5109 info = gtk_window_get_geometry_info (window, FALSE);
5112 info->resize_width = -1;
5113 info->resize_height = -1;
5114 info->last.configure_request.x = 0;
5115 info->last.configure_request.y = 0;
5116 info->last.configure_request.width = -1;
5117 info->last.configure_request.height = -1;
5118 /* be sure we reset geom hints on re-realize */
5119 info->last.flags = 0;
5123 gtk_window_unrealize_icon (window);
5125 if (priv->grip_window != NULL)
5126 resize_grip_destroy_window (window);
5128 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5131 static GtkJunctionSides
5132 get_grip_junction (GtkWidget *widget)
5134 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5135 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5137 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5141 get_drag_edge (GtkWidget *widget,
5142 GdkWindowEdge *edge)
5144 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5145 gboolean hresizable;
5146 gboolean vresizable;
5147 GtkTextDirection dir;
5148 GtkWindowGeometryInfo *info;
5153 info = priv->geometry_info;
5156 GdkWindowHints flags = info->last.flags;
5157 GdkGeometry *geometry = &info->last.geometry;
5159 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5161 hresizable = geometry->min_width < geometry->max_width;
5162 vresizable = geometry->min_height < geometry->max_height;
5166 dir = gtk_widget_get_direction (widget);
5168 if (hresizable && vresizable)
5169 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5170 else if (hresizable)
5171 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5172 else if (vresizable)
5173 *edge = GDK_WINDOW_EDGE_SOUTH;
5181 set_grip_cursor (GtkWindow *window)
5183 GtkWidget *widget = GTK_WIDGET (window);
5184 GtkWindowPrivate *priv = window->priv;
5186 if (priv->grip_window == NULL)
5189 if (gtk_widget_is_sensitive (widget))
5192 GdkDisplay *display;
5193 GdkCursorType cursor_type;
5196 cursor_type = GDK_LEFT_PTR;
5198 if (get_drag_edge (widget, &edge))
5202 case GDK_WINDOW_EDGE_EAST:
5203 cursor_type = GDK_RIGHT_SIDE;
5205 case GDK_WINDOW_EDGE_SOUTH_EAST:
5206 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5208 case GDK_WINDOW_EDGE_SOUTH:
5209 cursor_type = GDK_BOTTOM_SIDE;
5211 case GDK_WINDOW_EDGE_SOUTH_WEST:
5212 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5214 case GDK_WINDOW_EDGE_WEST:
5215 cursor_type = GDK_LEFT_SIDE;
5221 display = gtk_widget_get_display (widget);
5222 cursor = gdk_cursor_new_for_display (display, cursor_type);
5223 gdk_window_set_cursor (priv->grip_window, cursor);
5224 g_object_unref (cursor);
5227 gdk_window_set_cursor (priv->grip_window, NULL);
5231 set_grip_shape (GtkWindow *window)
5233 GtkWindowPrivate *priv = window->priv;
5234 cairo_region_t *region;
5235 cairo_surface_t *surface;
5237 double width, height;
5239 if (priv->grip_window == NULL)
5242 width = gdk_window_get_width (priv->grip_window);
5243 height = gdk_window_get_height (priv->grip_window);
5244 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5246 cr = cairo_create (surface);
5247 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5249 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5250 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5252 cairo_move_to (cr, width, 0.0);
5253 cairo_line_to (cr, width, height);
5254 cairo_line_to (cr, 0.0, height);
5258 cairo_move_to (cr, 0.0, 0.0);
5259 cairo_line_to (cr, width, height);
5260 cairo_line_to (cr, 0.0, height);
5262 cairo_close_path (cr);
5265 region = gdk_cairo_region_create_from_surface (surface);
5266 cairo_surface_destroy (surface);
5268 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5269 cairo_region_destroy (region);
5273 set_grip_position (GtkWindow *window)
5275 GtkWindowPrivate *priv = window->priv;
5278 if (priv->grip_window == NULL)
5281 gtk_window_get_resize_grip_area (window, &rect);
5282 gdk_window_raise (priv->grip_window);
5283 gdk_window_move_resize (priv->grip_window,
5285 rect.width, rect.height);
5289 gtk_window_size_allocate (GtkWidget *widget,
5290 GtkAllocation *allocation)
5292 GtkWindow *window = GTK_WINDOW (widget);
5293 GtkAllocation child_allocation;
5297 gtk_widget_set_allocation (widget, allocation);
5299 if (gtk_widget_get_realized (widget))
5301 /* If it's not a toplevel we're embedded, we need to resize the window's
5302 * window and skip the grip.
5304 if (!gtk_widget_is_toplevel (widget))
5306 gdk_window_move_resize (gtk_widget_get_window (widget),
5307 allocation->x, allocation->y,
5308 allocation->width, allocation->height);
5312 update_grip_visibility (window);
5313 set_grip_position (window);
5317 child = gtk_bin_get_child (&(window->bin));
5318 if (child && gtk_widget_get_visible (child))
5320 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5321 child_allocation.x = border_width;
5322 child_allocation.y = border_width;
5323 child_allocation.width =
5324 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5325 child_allocation.height =
5326 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5328 gtk_widget_size_allocate (child, &child_allocation);
5333 gtk_window_configure_event (GtkWidget *widget,
5334 GdkEventConfigure *event)
5336 GtkAllocation allocation;
5337 GtkWindow *window = GTK_WINDOW (widget);
5338 GtkWindowPrivate *priv = window->priv;
5339 gboolean expected_reply = priv->configure_request_count > 0;
5341 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5343 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5344 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5346 gdk_window_configure_finished (gtk_widget_get_window (widget));
5350 /* priv->configure_request_count incremented for each
5351 * configure request, and decremented to a min of 0 for
5352 * each configure notify.
5354 * All it means is that we know we will get at least
5355 * priv->configure_request_count more configure notifies.
5356 * We could get more configure notifies than that; some
5357 * of the configure notifies we get may be unrelated to
5358 * the configure requests. But we will get at least
5359 * priv->configure_request_count notifies.
5362 if (priv->configure_request_count > 0)
5364 priv->configure_request_count -= 1;
5365 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5368 /* As an optimization, we avoid a resize when possible.
5370 * The only times we can avoid a resize are:
5371 * - we know only the position changed, not the size
5372 * - we know we have made more requests and so will get more
5373 * notifies and can wait to resize when we get them
5375 gtk_widget_get_allocation (widget, &allocation);
5376 if (!expected_reply &&
5377 (allocation.width == event->width &&
5378 allocation.height == event->height))
5380 gdk_window_configure_finished (gtk_widget_get_window (widget));
5385 * If we do need to resize, we do that by:
5386 * - filling in widget->allocation with the new size
5387 * - setting configure_notify_received to TRUE
5388 * for use in gtk_window_move_resize()
5389 * - queueing a resize, leading to invocation of
5390 * gtk_window_move_resize() in an idle handler
5394 priv->configure_notify_received = TRUE;
5396 allocation.width = event->width;
5397 allocation.height = event->height;
5398 gtk_widget_set_allocation (widget, &allocation);
5400 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5402 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5408 gtk_window_state_event (GtkWidget *widget,
5409 GdkEventWindowState *event)
5411 update_grip_visibility (GTK_WINDOW (widget));
5417 gtk_window_direction_changed (GtkWidget *widget,
5418 GtkTextDirection prev_dir)
5420 GtkWindow *window = GTK_WINDOW (widget);
5422 set_grip_cursor (window);
5423 set_grip_position (window);
5424 set_grip_shape (window);
5428 gtk_window_state_changed (GtkWidget *widget,
5429 GtkStateType previous_state)
5431 GtkWindow *window = GTK_WINDOW (widget);
5433 update_grip_visibility (window);
5437 gtk_window_style_updated (GtkWidget *widget)
5439 GtkWindow *window = GTK_WINDOW (widget);
5440 GtkWindowPrivate *priv = window->priv;
5443 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5445 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5447 gdk_window_move_resize (priv->grip_window,
5449 rect.width, rect.height);
5451 set_grip_shape (window);
5452 gtk_widget_queue_resize (widget);
5457 resize_grip_create_window (GtkWindow *window)
5460 GtkWindowPrivate *priv;
5461 GdkWindowAttr attributes;
5462 gint attributes_mask;
5465 priv = window->priv;
5466 widget = GTK_WIDGET (window);
5468 g_return_if_fail (gtk_widget_get_realized (widget));
5469 g_return_if_fail (priv->grip_window == NULL);
5471 gtk_window_get_resize_grip_area (window, &rect);
5473 attributes.x = rect.x;
5474 attributes.y = rect.y;
5475 attributes.width = rect.width;
5476 attributes.height = rect.height;
5477 attributes.window_type = GDK_WINDOW_CHILD;
5478 attributes.wclass = GDK_INPUT_OUTPUT;
5479 attributes.event_mask = gtk_widget_get_events (widget) |
5481 GDK_BUTTON_PRESS_MASK;
5483 attributes_mask = GDK_WA_X | GDK_WA_Y;
5485 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5489 gdk_window_set_user_data (priv->grip_window, widget);
5491 gdk_window_raise (priv->grip_window);
5493 set_grip_shape (window);
5494 update_grip_visibility (window);
5498 resize_grip_destroy_window (GtkWindow *window)
5500 GtkWindowPrivate *priv = window->priv;
5502 gdk_window_set_user_data (priv->grip_window, NULL);
5503 gdk_window_destroy (priv->grip_window);
5504 priv->grip_window = NULL;
5505 update_grip_visibility (window);
5509 * gtk_window_set_has_resize_grip:
5510 * @window: a #GtkWindow
5511 * @value: %TRUE to allow a resize grip
5513 * Sets whether @window has a corner resize grip.
5515 * Note that the resize grip is only shown if the window
5516 * is actually resizable and not maximized. Use
5517 * gtk_window_resize_grip_is_visible() to find out if the
5518 * resize grip is currently shown.
5523 gtk_window_set_has_resize_grip (GtkWindow *window,
5526 GtkWidget *widget = GTK_WIDGET (window);
5527 GtkWindowPrivate *priv = window->priv;
5529 value = value != FALSE;
5531 if (value != priv->has_resize_grip)
5533 priv->has_resize_grip = value;
5534 gtk_widget_queue_draw (widget);
5536 if (gtk_widget_get_realized (widget) &&
5537 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5539 if (priv->has_resize_grip && priv->grip_window == NULL)
5540 resize_grip_create_window (window);
5541 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5542 resize_grip_destroy_window (window);
5545 g_object_notify (G_OBJECT (window), "has-resize-grip");
5550 update_grip_visibility (GtkWindow *window)
5552 GtkWindowPrivate *priv = window->priv;
5555 val = gtk_window_resize_grip_is_visible (window);
5557 if (priv->grip_window != NULL)
5561 gdk_window_show (priv->grip_window);
5562 set_grip_cursor (window);
5566 gdk_window_hide (priv->grip_window);
5570 if (priv->resize_grip_visible != val)
5572 priv->resize_grip_visible = val;
5574 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5579 * gtk_window_resize_grip_is_visible:
5580 * @window: a #GtkWindow
5582 * Determines whether a resize grip is visible for the specified window.
5584 * Returns: %TRUE if a resize grip exists and is visible
5589 gtk_window_resize_grip_is_visible (GtkWindow *window)
5592 GtkWindowPrivate *priv;
5595 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5597 priv = window->priv;
5598 widget = GTK_WIDGET (window);
5600 if (priv->type == GTK_WINDOW_POPUP)
5603 if (!priv->resizable)
5606 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5609 if (gtk_widget_get_realized (widget))
5611 GdkWindowState state;
5613 state = gdk_window_get_state (gtk_widget_get_window (widget));
5615 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5619 if (!get_drag_edge (widget, &edge))
5622 return window->priv->has_resize_grip;
5626 * gtk_window_get_has_resize_grip:
5627 * @window: a #GtkWindow
5629 * Determines whether the window may have a resize grip.
5631 * Returns: %TRUE if the window has a resize grip
5636 gtk_window_get_has_resize_grip (GtkWindow *window)
5638 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5640 return window->priv->has_resize_grip;
5644 * gtk_window_get_resize_grip_area:
5645 * @window: a #GtkWindow
5646 * @rect: (out): a pointer to a #GdkRectangle which we should store
5647 * the resize grip area
5649 * If a window has a resize grip, this will retrieve the grip
5650 * position, width and height into the specified #GdkRectangle.
5652 * Returns: %TRUE if the resize grip's area was retrieved
5657 gtk_window_get_resize_grip_area (GtkWindow *window,
5660 GtkWidget *widget = GTK_WIDGET (window);
5661 GtkAllocation allocation;
5665 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5667 if (!window->priv->has_resize_grip)
5670 gtk_widget_get_allocation (widget, &allocation);
5672 gtk_widget_style_get (widget,
5673 "resize-grip-width", &grip_width,
5674 "resize-grip-height", &grip_height,
5677 if (grip_width > allocation.width)
5678 grip_width = allocation.width;
5680 if (grip_height > allocation.height)
5681 grip_height = allocation.height;
5683 rect->width = grip_width;
5684 rect->height = grip_height;
5685 rect->y = allocation.y + allocation.height - grip_height;
5687 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5688 rect->x = allocation.x + allocation.width - grip_width;
5690 rect->x = allocation.x;
5695 /* the accel_key and accel_mods fields of the key have to be setup
5696 * upon calling this function. it'll then return whether that key
5697 * is at all used as accelerator, and if so will OR in the
5698 * accel_flags member of the key.
5701 _gtk_window_query_nonaccels (GtkWindow *window,
5703 GdkModifierType accel_mods)
5705 GtkWindowPrivate *priv;
5707 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5709 priv = window->priv;
5711 /* movement keys are considered locked accels */
5714 static const guint bindings[] = {
5715 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,
5716 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,
5720 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5721 if (bindings[i] == accel_key)
5725 /* mnemonics are considered locked accels */
5726 if (accel_mods == priv->mnemonic_modifier)
5728 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5729 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5737 * gtk_window_propagate_key_event:
5738 * @window: a #GtkWindow
5739 * @event: a #GdkEventKey
5741 * Propagate a key press or release event to the focus widget and
5742 * up the focus container chain until a widget handles @event.
5743 * This is normally called by the default ::key_press_event and
5744 * ::key_release_event handlers for toplevel windows,
5745 * however in some cases it may be useful to call this directly when
5746 * overriding the standard key handling for a toplevel window.
5748 * Return value: %TRUE if a widget in the focus chain handled the event.
5753 gtk_window_propagate_key_event (GtkWindow *window,
5756 GtkWindowPrivate *priv;
5757 gboolean handled = FALSE;
5758 GtkWidget *widget, *focus;
5760 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5762 priv = window->priv;
5763 widget = GTK_WIDGET (window);
5765 focus = priv->focus_widget;
5767 g_object_ref (focus);
5770 focus && focus != widget &&
5771 gtk_widget_get_toplevel (focus) == widget)
5775 if (gtk_widget_is_sensitive (focus))
5776 handled = gtk_widget_event (focus, (GdkEvent*) event);
5778 parent = gtk_widget_get_parent (focus);
5780 g_object_ref (parent);
5782 g_object_unref (focus);
5788 g_object_unref (focus);
5794 gtk_window_key_press_event (GtkWidget *widget,
5797 GtkWindow *window = GTK_WINDOW (widget);
5798 gboolean handled = FALSE;
5800 /* handle mnemonics and accelerators */
5802 handled = gtk_window_activate_key (window, event);
5804 /* handle focus widget key events */
5806 handled = gtk_window_propagate_key_event (window, event);
5808 /* Chain up, invokes binding set */
5810 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5816 gtk_window_key_release_event (GtkWidget *widget,
5819 GtkWindow *window = GTK_WINDOW (widget);
5820 gboolean handled = FALSE;
5822 /* handle focus widget key events */
5824 handled = gtk_window_propagate_key_event (window, event);
5826 /* Chain up, invokes binding set */
5828 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5834 gtk_window_button_press_event (GtkWidget *widget,
5835 GdkEventButton *event)
5837 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5840 if (event->window == priv->grip_window)
5842 if (get_drag_edge (widget, &edge))
5843 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5857 gtk_window_real_activate_default (GtkWindow *window)
5859 gtk_window_activate_default (window);
5863 gtk_window_real_activate_focus (GtkWindow *window)
5865 gtk_window_activate_focus (window);
5869 gtk_window_enter_notify_event (GtkWidget *widget,
5870 GdkEventCrossing *event)
5876 gtk_window_leave_notify_event (GtkWidget *widget,
5877 GdkEventCrossing *event)
5883 do_focus_change (GtkWidget *widget,
5887 GdkDeviceManager *device_manager;
5890 g_object_ref (widget);
5892 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5893 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5894 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5895 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5897 for (d = devices; d; d = d->next)
5899 GdkDevice *dev = d->data;
5902 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5905 /* Skip non-master keyboards that haven't
5906 * selected for events from this window
5908 window = gtk_widget_get_window (widget);
5909 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5910 window && !gdk_window_get_device_events (window, dev))
5913 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5915 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5916 fevent->focus_change.window = window;
5918 g_object_ref (window);
5919 fevent->focus_change.in = in;
5920 gdk_event_set_device (fevent, dev);
5922 gtk_widget_send_focus_change (widget, fevent);
5924 gdk_event_free (fevent);
5927 g_list_free (devices);
5928 g_object_unref (widget);
5932 gtk_window_focus_in_event (GtkWidget *widget,
5933 GdkEventFocus *event)
5935 GtkWindow *window = GTK_WINDOW (widget);
5937 /* It appears spurious focus in events can occur when
5938 * the window is hidden. So we'll just check to see if
5939 * the window is visible before actually handling the
5942 if (gtk_widget_get_visible (widget))
5944 _gtk_window_set_has_toplevel_focus (window, TRUE);
5945 _gtk_window_set_is_active (window, TRUE);
5952 gtk_window_focus_out_event (GtkWidget *widget,
5953 GdkEventFocus *event)
5955 GtkWindow *window = GTK_WINDOW (widget);
5956 gboolean auto_mnemonics;
5958 _gtk_window_set_has_toplevel_focus (window, FALSE);
5959 _gtk_window_set_is_active (window, FALSE);
5961 /* set the mnemonic-visible property to false */
5962 g_object_get (gtk_widget_get_settings (widget),
5963 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5965 gtk_window_set_mnemonics_visible (window, FALSE);
5971 gtk_window_check_resize (GtkContainer *container)
5973 /* If the window is not toplevel anymore than it's embedded somewhere,
5974 * so handle it like a normal window */
5975 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
5976 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
5977 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
5978 gtk_window_move_resize (GTK_WINDOW (container));
5982 gtk_window_focus (GtkWidget *widget,
5983 GtkDirectionType direction)
5985 GtkWindowPrivate *priv;
5988 GtkContainer *container;
5990 GtkWidget *old_focus_child;
5993 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5994 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
5996 container = GTK_CONTAINER (widget);
5997 window = GTK_WINDOW (widget);
5998 priv = window->priv;
5999 bin = GTK_BIN (widget);
6001 old_focus_child = gtk_container_get_focus_child (container);
6003 /* We need a special implementation here to deal properly with wrapping
6004 * around in the tab chain without the danger of going into an
6007 if (old_focus_child)
6009 if (gtk_widget_child_focus (old_focus_child, direction))
6013 if (priv->focus_widget)
6015 if (direction == GTK_DIR_LEFT ||
6016 direction == GTK_DIR_RIGHT ||
6017 direction == GTK_DIR_UP ||
6018 direction == GTK_DIR_DOWN)
6023 /* Wrapped off the end, clear the focus setting for the toplpevel */
6024 parent = gtk_widget_get_parent (priv->focus_widget);
6027 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6028 parent = gtk_widget_get_parent (parent);
6031 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6034 /* Now try to focus the first widget in the window */
6035 child = gtk_bin_get_child (bin);
6038 if (gtk_widget_child_focus (child, direction))
6046 gtk_window_move_focus (GtkWidget *widget,
6047 GtkDirectionType dir)
6049 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6051 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6055 gtk_widget_child_focus (widget, dir);
6057 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6058 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6062 gtk_window_real_set_focus (GtkWindow *window,
6065 GtkWindowPrivate *priv = window->priv;
6066 GtkWidget *old_focus = priv->focus_widget;
6067 gboolean had_default = FALSE;
6068 gboolean focus_had_default = FALSE;
6069 gboolean old_focus_had_default = FALSE;
6073 g_object_ref (old_focus);
6074 g_object_freeze_notify (G_OBJECT (old_focus));
6075 old_focus_had_default = gtk_widget_has_default (old_focus);
6079 g_object_ref (focus);
6080 g_object_freeze_notify (G_OBJECT (focus));
6081 focus_had_default = gtk_widget_has_default (focus);
6084 if (priv->default_widget)
6085 had_default = gtk_widget_has_default (priv->default_widget);
6087 if (priv->focus_widget)
6089 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6090 (priv->focus_widget != priv->default_widget))
6092 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6093 gtk_widget_queue_draw (priv->focus_widget);
6095 if (priv->default_widget)
6096 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6099 priv->focus_widget = NULL;
6101 if (priv->has_focus)
6102 do_focus_change (old_focus, FALSE);
6104 g_object_notify (G_OBJECT (old_focus), "is-focus");
6107 /* The above notifications may have set a new focus widget,
6108 * if so, we don't want to override it.
6110 if (focus && !priv->focus_widget)
6112 priv->focus_widget = focus;
6114 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6115 (priv->focus_widget != priv->default_widget))
6117 if (gtk_widget_get_can_default (priv->focus_widget))
6118 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6120 if (priv->default_widget)
6121 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6124 if (priv->has_focus)
6125 do_focus_change (priv->focus_widget, TRUE);
6127 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6130 /* If the default widget changed, a redraw will have been queued
6131 * on the old and new default widgets by gtk_window_set_default(), so
6132 * we only have to worry about the case where it didn't change.
6133 * We'll sometimes queue a draw twice on the new widget but that
6136 if (priv->default_widget &&
6137 (had_default != gtk_widget_has_default (priv->default_widget)))
6138 gtk_widget_queue_draw (priv->default_widget);
6142 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6143 gtk_widget_queue_draw (old_focus);
6145 g_object_thaw_notify (G_OBJECT (old_focus));
6146 g_object_unref (old_focus);
6150 if (focus_had_default != gtk_widget_has_default (focus))
6151 gtk_widget_queue_draw (focus);
6153 g_object_thaw_notify (G_OBJECT (focus));
6154 g_object_unref (focus);
6160 gtk_window_get_preferred_width (GtkWidget *widget,
6168 window = GTK_WINDOW (widget);
6169 child = gtk_bin_get_child (GTK_BIN (window));
6171 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6172 *minimum_size = border_width * 2;
6173 *natural_size = border_width * 2;
6175 if (child && gtk_widget_get_visible (child))
6177 gint child_min, child_nat;
6178 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6180 *minimum_size += child_min;
6181 *natural_size += child_nat;
6186 gtk_window_get_preferred_height (GtkWidget *widget,
6194 window = GTK_WINDOW (widget);
6195 child = gtk_bin_get_child (GTK_BIN (window));
6197 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6198 *minimum_size = border_width * 2;
6199 *natural_size = border_width * 2;
6201 if (child && gtk_widget_get_visible (child))
6203 gint child_min, child_nat;
6204 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6206 *minimum_size += child_min;
6207 *natural_size += child_nat;
6213 * _gtk_window_unset_focus_and_default:
6214 * @window: a #GtkWindow
6215 * @widget: a widget inside of @window
6217 * Checks whether the focus and default widgets of @window are
6218 * @widget or a descendent of @widget, and if so, unset them.
6221 _gtk_window_unset_focus_and_default (GtkWindow *window,
6225 GtkWindowPrivate *priv = window->priv;
6229 g_object_ref (window);
6230 g_object_ref (widget);
6232 parent = gtk_widget_get_parent (widget);
6233 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6235 child = priv->focus_widget;
6237 while (child && child != widget)
6238 child = gtk_widget_get_parent (child);
6240 if (child == widget)
6241 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6244 child = priv->default_widget;
6246 while (child && child != widget)
6247 child = gtk_widget_get_parent (child);
6249 if (child == widget)
6250 gtk_window_set_default (window, NULL);
6252 g_object_unref (widget);
6253 g_object_unref (window);
6256 /*********************************
6257 * Functions related to resizing *
6258 *********************************/
6261 geometry_size_to_pixels (GdkGeometry *geometry,
6266 gint base_width = 0;
6267 gint base_height = 0;
6269 gint min_height = 0;
6271 gint height_inc = 1;
6273 if (flags & GDK_HINT_BASE_SIZE)
6275 base_width = geometry->base_width;
6276 base_height = geometry->base_height;
6278 if (flags & GDK_HINT_MIN_SIZE)
6280 min_width = geometry->min_width;
6281 min_height = geometry->min_height;
6283 if (flags & GDK_HINT_RESIZE_INC)
6285 width_inc = geometry->width_inc;
6286 height_inc = geometry->height_inc;
6290 *width = MAX (*width * width_inc + base_width, min_width);
6292 *height = MAX (*height * height_inc + base_height, min_height);
6295 /* This function doesn't constrain to geometry hints */
6297 gtk_window_compute_configure_request_size (GtkWindow *window,
6298 GdkGeometry *geometry,
6303 GtkWindowPrivate *priv = window->priv;
6304 GtkWindowGeometryInfo *info;
6307 * - we've done a size request
6310 info = gtk_window_get_geometry_info (window, FALSE);
6312 if (priv->need_default_size)
6314 gtk_window_guess_default_size (window, width, height);
6316 /* If window is empty so requests 0, default to random nonzero size */
6317 if (*width == 0 && *height == 0)
6323 /* Override with default size */
6327 if (info->default_width > 0)
6328 *width = info->default_width;
6329 if (info->default_height > 0)
6330 *height = info->default_height;
6332 if (info->default_is_geometry)
6333 geometry_size_to_pixels (geometry, flags,
6334 info->default_width > 0 ? width : NULL,
6335 info->default_height > 0 ? height : NULL);
6340 GtkAllocation allocation;
6342 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6344 /* Default to keeping current size */
6345 *width = allocation.width;
6346 *height = allocation.height;
6349 /* Override any size with gtk_window_resize() values */
6352 if (info->resize_width > 0)
6353 *width = info->resize_width;
6354 if (info->resize_height > 0)
6355 *height = info->resize_height;
6357 if (info->resize_is_geometry)
6358 geometry_size_to_pixels (geometry, flags,
6359 info->resize_width > 0 ? width : NULL,
6360 info->resize_height > 0 ? height : NULL);
6363 /* Don't ever request zero width or height, its not supported by
6364 gdk. The size allocation code will round it to 1 anyway but if
6365 we do it then the value returned from this function will is
6366 not comparable to the size allocation read from the GtkWindow. */
6367 *width = MAX (*width, 1);
6368 *height = MAX (*height, 1);
6371 static GtkWindowPosition
6372 get_effective_position (GtkWindow *window)
6374 GtkWindowPrivate *priv = window->priv;
6375 GtkWindowPosition pos = priv->position;
6377 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6378 (priv->transient_parent == NULL ||
6379 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6380 pos = GTK_WIN_POS_NONE;
6386 get_center_monitor_of_window (GtkWindow *window)
6388 /* We could try to sort out the relative positions of the monitors and
6389 * stuff, or we could just be losers and assume you have a row
6390 * or column of monitors.
6392 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6396 get_monitor_containing_pointer (GtkWindow *window)
6400 GdkScreen *window_screen;
6401 GdkScreen *pointer_screen;
6402 GdkDisplay *display;
6403 GdkDeviceManager *device_manager;
6406 window_screen = gtk_window_check_screen (window);
6407 display = gdk_screen_get_display (window_screen);
6408 device_manager = gdk_display_get_device_manager (display);
6409 pointer = gdk_device_manager_get_client_pointer (device_manager);
6411 gdk_device_get_position (pointer,
6415 if (pointer_screen == window_screen)
6416 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6424 center_window_on_monitor (GtkWindow *window,
6430 GdkRectangle monitor;
6433 monitor_num = get_monitor_containing_pointer (window);
6435 if (monitor_num == -1)
6436 monitor_num = get_center_monitor_of_window (window);
6438 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6439 monitor_num, &monitor);
6441 *x = (monitor.width - w) / 2 + monitor.x;
6442 *y = (monitor.height - h) / 2 + monitor.y;
6444 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6445 * and WM decorations.
6459 if (extent > clamp_extent)
6461 *base = clamp_base + clamp_extent/2 - extent/2;
6462 else if (*base < clamp_base)
6464 else if (*base + extent > clamp_base + clamp_extent)
6465 *base = clamp_base + clamp_extent - extent;
6469 clamp_window_to_rectangle (gint *x,
6473 const GdkRectangle *rect)
6475 #ifdef DEBUGGING_OUTPUT
6476 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);
6479 /* If it is too large, center it. If it fits on the monitor but is
6480 * partially outside, move it to the closest edge. Do this
6481 * separately in x and y directions.
6483 clamp (x, w, rect->x, rect->width);
6484 clamp (y, h, rect->y, rect->height);
6485 #ifdef DEBUGGING_OUTPUT
6486 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6492 gtk_window_compute_configure_request (GtkWindow *window,
6493 GdkRectangle *request,
6494 GdkGeometry *geometry,
6497 GtkWindowPrivate *priv = window->priv;
6498 GdkGeometry new_geometry;
6501 GtkWindowPosition pos;
6502 GtkWidget *parent_widget;
6503 GtkWindowGeometryInfo *info;
6507 screen = gtk_window_check_screen (window);
6509 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6510 gtk_window_compute_configure_request_size (window,
6511 &new_geometry, new_flags,
6514 gtk_window_constrain_size (window,
6515 &new_geometry, new_flags,
6519 parent_widget = (GtkWidget*) priv->transient_parent;
6521 pos = get_effective_position (window);
6522 info = gtk_window_get_geometry_info (window, FALSE);
6524 /* by default, don't change position requested */
6527 x = info->last.configure_request.x;
6528 y = info->last.configure_request.y;
6537 if (priv->need_default_position)
6540 /* FIXME this all interrelates with window gravity.
6541 * For most of them I think we want to set GRAVITY_CENTER.
6543 * Not sure how to go about that.
6547 /* here we are only handling CENTER_ALWAYS
6548 * as it relates to default positioning,
6549 * where it's equivalent to simply CENTER
6551 case GTK_WIN_POS_CENTER_ALWAYS:
6552 case GTK_WIN_POS_CENTER:
6553 center_window_on_monitor (window, w, h, &x, &y);
6556 case GTK_WIN_POS_CENTER_ON_PARENT:
6558 GtkAllocation allocation;
6559 GdkWindow *gdk_window;
6561 GdkRectangle monitor;
6564 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6566 gdk_window = gtk_widget_get_window (parent_widget);
6568 if (gdk_window != NULL)
6569 monitor_num = gdk_screen_get_monitor_at_window (screen,
6574 gdk_window_get_origin (gdk_window,
6577 gtk_widget_get_allocation (parent_widget, &allocation);
6578 x = ox + (allocation.width - w) / 2;
6579 y = oy + (allocation.height - h) / 2;
6581 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6582 * WM decorations. If parent wasn't on a monitor, just
6585 if (monitor_num >= 0)
6587 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6588 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6593 case GTK_WIN_POS_MOUSE:
6595 gint screen_width = gdk_screen_get_width (screen);
6596 gint screen_height = gdk_screen_get_height (screen);
6598 GdkRectangle monitor;
6599 GdkDisplay *display;
6600 GdkDeviceManager *device_manager;
6602 GdkScreen *pointer_screen;
6605 display = gdk_screen_get_display (screen);
6606 device_manager = gdk_display_get_device_manager (display);
6607 pointer = gdk_device_manager_get_client_pointer (device_manager);
6609 gdk_device_get_position (pointer,
6613 if (pointer_screen == screen)
6614 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6620 x = CLAMP (x, 0, screen_width - w);
6621 y = CLAMP (y, 0, screen_height - h);
6623 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6624 * WM decorations. Don't try to figure out what's going
6625 * on if the mouse wasn't inside a monitor.
6627 if (monitor_num >= 0)
6629 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6630 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6638 } /* if (priv->need_default_position) */
6640 if (priv->need_default_position && info &&
6641 info->initial_pos_set)
6643 x = info->initial_x;
6644 y = info->initial_y;
6645 gtk_window_constrain_position (window, w, h, &x, &y);
6651 request->height = h;
6654 *geometry = new_geometry;
6660 gtk_window_constrain_position (GtkWindow *window,
6666 GtkWindowPrivate *priv = window->priv;
6668 /* See long comments in gtk_window_move_resize()
6669 * on when it's safe to call this function.
6671 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6673 gint center_x, center_y;
6675 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6683 gtk_window_move_resize (GtkWindow *window)
6687 * First we determine whether any information has changed that would
6688 * cause us to revise our last configure request. If we would send
6689 * a different configure request from last time, then
6690 * configure_request_size_changed = TRUE or
6691 * configure_request_pos_changed = TRUE. configure_request_size_changed
6692 * may be true due to new hints, a gtk_window_resize(), or whatever.
6693 * configure_request_pos_changed may be true due to gtk_window_set_position()
6694 * or gtk_window_move().
6696 * If the configure request has changed, we send off a new one. To
6697 * ensure GTK+ invariants are maintained (resize queue does what it
6698 * should), we go ahead and size_allocate the requested size in this
6701 * If the configure request has not changed, we don't ever resend
6702 * it, because it could mean fighting the user or window manager.
6705 * To prepare the configure request, we come up with a base size/pos:
6706 * - the one from gtk_window_move()/gtk_window_resize()
6707 * - else default_width, default_height if we haven't ever
6709 * - else the size request if we haven't ever been mapped,
6710 * as a substitute default size
6711 * - else the current size of the window, as received from
6712 * configure notifies (i.e. the current allocation)
6714 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6715 * the position request to be centered.
6717 GtkWindowPrivate *priv = window->priv;
6718 GtkAllocation allocation;
6720 GtkContainer *container;
6721 GtkWindowGeometryInfo *info;
6722 GdkGeometry new_geometry;
6723 GdkWindow *gdk_window;
6725 GdkRectangle new_request;
6726 gboolean configure_request_size_changed;
6727 gboolean configure_request_pos_changed;
6728 gboolean hints_changed; /* do we need to send these again */
6729 GtkWindowLastGeometryInfo saved_last_info;
6731 widget = GTK_WIDGET (window);
6733 gdk_window = gtk_widget_get_window (widget);
6734 container = GTK_CONTAINER (widget);
6735 info = gtk_window_get_geometry_info (window, TRUE);
6737 configure_request_size_changed = FALSE;
6738 configure_request_pos_changed = FALSE;
6740 gtk_window_compute_configure_request (window, &new_request,
6741 &new_geometry, &new_flags);
6743 /* This check implies the invariant that we never set info->last
6744 * without setting the hints and sending off a configure request.
6746 * If we change info->last without sending the request, we may
6749 if (info->last.configure_request.x != new_request.x ||
6750 info->last.configure_request.y != new_request.y)
6751 configure_request_pos_changed = TRUE;
6753 if ((info->last.configure_request.width != new_request.width ||
6754 info->last.configure_request.height != new_request.height))
6755 configure_request_size_changed = TRUE;
6757 hints_changed = FALSE;
6759 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6760 &new_geometry, new_flags))
6762 hints_changed = TRUE;
6765 /* Position Constraints
6766 * ====================
6768 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6769 * a default. The other POS_ values are used only when the
6770 * window is shown, not after that.
6772 * However, we can't implement a position constraint as
6773 * "anytime the window size changes, center the window"
6774 * because this may well end up fighting the WM or user. In
6775 * fact it gets in an infinite loop with at least one WM.
6777 * Basically, applications are in no way in a position to
6778 * constrain the position of a window, with one exception:
6779 * override redirect windows. (Really the intended purpose
6780 * of CENTER_ALWAYS anyhow, I would think.)
6782 * So the way we implement this "constraint" is to say that when WE
6783 * cause a move or resize, i.e. we make a configure request changing
6784 * window size, we recompute the CENTER_ALWAYS position to reflect
6785 * the new window size, and include it in our request. Also, if we
6786 * just turned on CENTER_ALWAYS we snap to center with a new
6787 * request. Otherwise, if we are just NOTIFIED of a move or resize
6788 * done by someone else e.g. the window manager, we do NOT send a
6789 * new configure request.
6791 * For override redirect windows, this works fine; all window
6792 * sizes are from our configure requests. For managed windows,
6793 * it is at least semi-sane, though who knows what the
6794 * app author is thinking.
6797 /* This condition should be kept in sync with the condition later on
6798 * that determines whether we send a configure request. i.e. we
6799 * should do this position constraining anytime we were going to
6800 * send a configure request anyhow, plus when constraints have
6803 if (configure_request_pos_changed ||
6804 configure_request_size_changed ||
6806 info->position_constraints_changed)
6808 /* We request the constrained position if:
6809 * - we were changing position, and need to clamp
6810 * the change to the constraint
6811 * - we're changing the size anyway
6812 * - set_position() was called to toggle CENTER_ALWAYS on
6815 gtk_window_constrain_position (window,
6821 /* Update whether we need to request a move */
6822 if (info->last.configure_request.x != new_request.x ||
6823 info->last.configure_request.y != new_request.y)
6824 configure_request_pos_changed = TRUE;
6826 configure_request_pos_changed = FALSE;
6830 if (priv->type == GTK_WINDOW_TOPLEVEL)
6832 int notify_x, notify_y;
6834 /* this is the position from the last configure notify */
6835 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6837 g_message ("--- %s ---\n"
6838 "last : %d,%d\t%d x %d\n"
6839 "this : %d,%d\t%d x %d\n"
6840 "alloc : %d,%d\t%d x %d\n"
6842 "resize: \t%d x %d\n"
6843 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6844 "configure_notify_received: %d\n"
6845 "configure_request_count: %d\n"
6846 "position_constraints_changed: %d\n",
6847 priv->title ? priv->title : "(no title)",
6848 info->last.configure_request.x,
6849 info->last.configure_request.y,
6850 info->last.configure_request.width,
6851 info->last.configure_request.height,
6857 widget->allocation.width,
6858 widget->allocation.height,
6859 widget->requisition.width,
6860 widget->requisition.height,
6862 info->resize_height,
6863 configure_request_pos_changed,
6864 configure_request_size_changed,
6866 priv->configure_notify_received,
6867 priv->configure_request_count,
6868 info->position_constraints_changed);
6872 saved_last_info = info->last;
6873 info->last.geometry = new_geometry;
6874 info->last.flags = new_flags;
6875 info->last.configure_request = new_request;
6877 /* need to set PPosition so the WM will look at our position,
6878 * but we don't want to count PPosition coming and going as a hints
6879 * change for future iterations. So we saved info->last prior to
6883 /* Also, if the initial position was explicitly set, then we always
6884 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6888 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6889 * this is an initial map
6892 if ((configure_request_pos_changed ||
6893 info->initial_pos_set ||
6894 (priv->need_default_position &&
6895 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6896 (new_flags & GDK_HINT_POS) == 0)
6898 new_flags |= GDK_HINT_POS;
6899 hints_changed = TRUE;
6902 /* Set hints if necessary
6905 gdk_window_set_geometry_hints (gdk_window,
6909 gtk_widget_get_allocation (widget, &allocation);
6911 /* handle resizing/moving and widget tree allocation
6913 if (priv->configure_notify_received)
6915 /* If we have received a configure event since
6916 * the last time in this function, we need to
6917 * accept our new size and size_allocate child widgets.
6918 * (see gtk_window_configure_event() for more details).
6920 * 1 or more configure notifies may have been received.
6921 * Also, configure_notify_received will only be TRUE
6922 * if all expected configure notifies have been received
6923 * (one per configure request), as an optimization.
6926 priv->configure_notify_received = FALSE;
6928 /* gtk_window_configure_event() filled in widget->allocation */
6929 gtk_widget_size_allocate (widget, &allocation);
6931 set_grip_position (window);
6932 update_grip_visibility (window);
6934 gdk_window_process_updates (gdk_window, TRUE);
6936 gdk_window_configure_finished (gdk_window);
6938 /* If the configure request changed, it means that
6940 * 1) coincidentally changed hints or widget properties
6941 * impacting the configure request before getting
6942 * a configure notify, or
6943 * 2) some broken widget is changing its size request
6944 * during size allocation, resulting in
6945 * a false appearance of changed configure request.
6947 * For 1), we could just go ahead and ask for the
6948 * new size right now, but doing that for 2)
6949 * might well be fighting the user (and can even
6950 * trigger a loop). Since we really don't want to
6951 * do that, we requeue a resize in hopes that
6952 * by the time it gets handled, the child has seen
6953 * the light and is willing to go along with the
6954 * new size. (this happens for the zvt widget, since
6955 * the size_allocate() above will have stored the
6956 * requisition corresponding to the new size in the
6959 * This doesn't buy us anything for 1), but it shouldn't
6960 * hurt us too badly, since it is what would have
6961 * happened if we had gotten the configure event before
6962 * the new size had been set.
6965 if (configure_request_size_changed ||
6966 configure_request_pos_changed)
6968 /* Don't change the recorded last info after all, because we
6969 * haven't actually updated to the new info yet - we decided
6970 * to postpone our configure request until later.
6972 info->last = saved_last_info;
6974 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6977 return; /* Bail out, we didn't really process the move/resize */
6979 else if ((configure_request_size_changed || hints_changed) &&
6980 (allocation.width != new_request.width || allocation.height != new_request.height))
6983 /* We are in one of the following situations:
6984 * A. configure_request_size_changed
6985 * our requisition has changed and we need a different window size,
6986 * so we request it from the window manager.
6987 * B. !configure_request_size_changed && hints_changed
6988 * the window manager rejects our size, but we have just changed the
6989 * window manager hints, so there's a chance our request will
6990 * be honoured this time, so we try again.
6992 * However, if the new requisition is the same as the current allocation,
6993 * we don't request it again, since we won't get a ConfigureNotify back from
6994 * the window manager unless it decides to change our requisition. If
6995 * we don't get the ConfigureNotify back, the resize queue will never be run.
6998 /* Now send the configure request */
6999 if (configure_request_pos_changed)
7001 gdk_window_move_resize (gdk_window,
7002 new_request.x, new_request.y,
7003 new_request.width, new_request.height);
7005 else /* only size changed */
7007 gdk_window_resize (gdk_window,
7008 new_request.width, new_request.height);
7011 if (priv->type == GTK_WINDOW_POPUP)
7013 GtkAllocation allocation;
7015 /* Directly size allocate for override redirect (popup) windows. */
7018 allocation.width = new_request.width;
7019 allocation.height = new_request.height;
7021 gtk_widget_size_allocate (widget, &allocation);
7023 gdk_window_process_updates (gdk_window, TRUE);
7025 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7026 gtk_widget_queue_draw (widget);
7030 /* Increment the number of have-not-yet-received-notify requests */
7031 priv->configure_request_count += 1;
7032 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7034 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7035 * configure event in response to our resizing request.
7036 * the configure event will cause a new resize with
7037 * ->configure_notify_received=TRUE.
7038 * until then, we want to
7039 * - discard expose events
7040 * - coalesce resizes for our children
7041 * - defer any window resizes until the configure event arrived
7042 * to achieve this, we queue a resize for the window, but remove its
7043 * resizing handler, so resizing will not be handled from the next
7044 * idle handler but when the configure event arrives.
7046 * FIXME: we should also dequeue the pending redraws here, since
7047 * we handle those ourselves upon ->configure_notify_received==TRUE.
7049 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7051 gtk_widget_queue_resize_no_redraw (widget);
7052 _gtk_container_dequeue_resize_handler (container);
7058 /* Handle any position changes.
7060 if (configure_request_pos_changed)
7062 gdk_window_move (gdk_window,
7063 new_request.x, new_request.y);
7066 /* And run the resize queue.
7068 gtk_container_resize_children (container);
7071 /* We have now processed a move/resize since the last position
7072 * constraint change, setting of the initial position, or resize.
7073 * (Not resetting these flags here can lead to infinite loops for
7074 * GTK_RESIZE_IMMEDIATE containers)
7076 info->position_constraints_changed = FALSE;
7077 info->initial_pos_set = FALSE;
7078 info->resize_width = -1;
7079 info->resize_height = -1;
7082 /* Compare two sets of Geometry hints for equality.
7085 gtk_window_compare_hints (GdkGeometry *geometry_a,
7087 GdkGeometry *geometry_b,
7090 if (flags_a != flags_b)
7093 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7094 (geometry_a->min_width != geometry_b->min_width ||
7095 geometry_a->min_height != geometry_b->min_height))
7098 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7099 (geometry_a->max_width != geometry_b->max_width ||
7100 geometry_a->max_height != geometry_b->max_height))
7103 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7104 (geometry_a->base_width != geometry_b->base_width ||
7105 geometry_a->base_height != geometry_b->base_height))
7108 if ((flags_a & GDK_HINT_ASPECT) &&
7109 (geometry_a->min_aspect != geometry_b->min_aspect ||
7110 geometry_a->max_aspect != geometry_b->max_aspect))
7113 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7114 (geometry_a->width_inc != geometry_b->width_inc ||
7115 geometry_a->height_inc != geometry_b->height_inc))
7118 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7119 geometry_a->win_gravity != geometry_b->win_gravity)
7126 _gtk_window_constrain_size (GtkWindow *window,
7132 GtkWindowPrivate *priv;
7133 GtkWindowGeometryInfo *info;
7135 g_return_if_fail (GTK_IS_WINDOW (window));
7137 priv = window->priv;
7139 info = priv->geometry_info;
7142 GdkWindowHints flags = info->last.flags;
7143 GdkGeometry *geometry = &info->last.geometry;
7145 gtk_window_constrain_size (window,
7156 gtk_window_constrain_size (GtkWindow *window,
7157 GdkGeometry *geometry,
7164 gdk_window_constrain_size (geometry, flags, width, height,
7165 new_width, new_height);
7168 /* Compute the set of geometry hints and flags for a window
7169 * based on the application set geometry, and requisition
7170 * of the window. gtk_widget_get_preferred_size() must have been
7174 gtk_window_compute_hints (GtkWindow *window,
7175 GdkGeometry *new_geometry,
7178 GtkWindowPrivate *priv = window->priv;
7180 gint extra_width = 0;
7181 gint extra_height = 0;
7182 GtkWindowGeometryInfo *geometry_info;
7183 GtkRequisition requisition;
7185 widget = GTK_WIDGET (window);
7187 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7188 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7192 *new_flags = geometry_info->mask;
7193 *new_geometry = geometry_info->geometry;
7200 if (geometry_info && geometry_info->widget)
7202 /* If the geometry widget is set, then the hints really apply to that
7203 * widget. This is pretty much meaningless unless the window layout
7204 * is such that the rest of the window adds fixed size borders to
7205 * the geometry widget. Our job is to figure the size of the borders;
7206 * We do that by asking how big the toplevel would be if the
7207 * geometry widget was *really big*.
7210 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7211 * |GGGGG B| in the border can confuse things
7217 * |AAAAAAAAA | When the geometry widget is large, things are
7218 * |GGGGGGGGGGB| clearer.
7223 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7224 GtkRequisition requisition;
7225 int current_width, current_height;
7227 _gtk_widget_override_size_request (geometry_info->widget,
7228 TEMPORARY_SIZE, TEMPORARY_SIZE,
7229 ¤t_width, ¤t_height);
7230 gtk_widget_get_preferred_size (widget,
7231 &requisition, NULL);
7232 _gtk_widget_restore_size_request (geometry_info->widget,
7233 current_width, current_height);
7235 extra_width = requisition.width - TEMPORARY_SIZE;
7236 extra_height = requisition.height - TEMPORARY_SIZE;
7238 if (extra_width < 0 || extra_height < 0)
7240 g_warning("Toplevel size doesn't seem to directly depend on the "
7241 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7242 "The geometry widget might not be in the window, or it might not "
7243 "be packed into the window appropriately");
7244 extra_width = MAX(extra_width, 0);
7245 extra_height = MAX(extra_height, 0);
7247 #undef TEMPORARY_SIZE
7250 /* We don't want to set GDK_HINT_POS in here, we just set it
7251 * in gtk_window_move_resize() when we want the position
7255 if (*new_flags & GDK_HINT_BASE_SIZE)
7257 new_geometry->base_width += extra_width;
7258 new_geometry->base_height += extra_height;
7262 /* For simplicity, we always set the base hint, even when we
7263 * don't expect it to have any visible effect.
7264 * (Note: geometry_size_to_pixels() depends on this.)
7266 *new_flags |= GDK_HINT_BASE_SIZE;
7268 new_geometry->base_width = extra_width;
7269 new_geometry->base_height = extra_height;
7271 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7272 * base size is the minimum size */
7273 if (*new_flags & GDK_HINT_MIN_SIZE)
7275 if (new_geometry->min_width > 0)
7276 new_geometry->base_width += new_geometry->min_width;
7277 if (new_geometry->min_height > 0)
7278 new_geometry->base_height += new_geometry->min_height;
7282 if (*new_flags & GDK_HINT_MIN_SIZE)
7284 if (new_geometry->min_width < 0)
7285 new_geometry->min_width = requisition.width;
7287 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7289 if (new_geometry->min_height < 0)
7290 new_geometry->min_height = requisition.height;
7292 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7296 *new_flags |= GDK_HINT_MIN_SIZE;
7298 new_geometry->min_width = requisition.width;
7299 new_geometry->min_height = requisition.height;
7302 if (*new_flags & GDK_HINT_MAX_SIZE)
7304 if (new_geometry->max_width < 0)
7305 new_geometry->max_width = requisition.width;
7307 new_geometry->max_width += extra_width;
7309 if (new_geometry->max_height < 0)
7310 new_geometry->max_height = requisition.height;
7312 new_geometry->max_height += extra_height;
7314 else if (!priv->resizable)
7316 *new_flags |= GDK_HINT_MAX_SIZE;
7318 new_geometry->max_width = requisition.width;
7319 new_geometry->max_height = requisition.height;
7322 *new_flags |= GDK_HINT_WIN_GRAVITY;
7323 new_geometry->win_gravity = priv->gravity;
7326 /***********************
7327 * Redrawing functions *
7328 ***********************/
7331 gtk_window_draw (GtkWidget *widget,
7334 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7335 GtkStyleContext *context;
7336 gboolean ret = FALSE;
7338 context = gtk_widget_get_style_context (widget);
7340 gtk_style_context_save (context);
7342 if (!gtk_widget_get_app_paintable (widget))
7344 GtkStateFlags state;
7346 state = gtk_widget_get_state_flags (widget);
7348 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7349 state |= GTK_STATE_FLAG_FOCUSED;
7351 gtk_style_context_set_state (context, state);
7352 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7353 gtk_render_background (context, cr, 0, 0,
7354 gtk_widget_get_allocated_width (widget),
7355 gtk_widget_get_allocated_height (widget));
7358 gtk_style_context_restore (context);
7360 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7361 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7363 if (priv->resize_grip_visible &&
7364 gtk_cairo_should_draw_window (cr, priv->grip_window))
7368 gtk_style_context_save (context);
7371 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7372 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7374 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7375 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7376 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7379 gtk_style_context_restore (context);
7386 * gtk_window_present:
7387 * @window: a #GtkWindow
7389 * Presents a window to the user. This may mean raising the window
7390 * in the stacking order, deiconifying it, moving it to the current
7391 * desktop, and/or giving it the keyboard focus, possibly dependent
7392 * on the user's platform, window manager, and preferences.
7394 * If @window is hidden, this function calls gtk_widget_show()
7397 * This function should be used when the user tries to open a window
7398 * that's already open. Say for example the preferences dialog is
7399 * currently open, and the user chooses Preferences from the menu
7400 * a second time; use gtk_window_present() to move the already-open dialog
7401 * where the user can see it.
7403 * If you are calling this function in response to a user interaction,
7404 * it is preferable to use gtk_window_present_with_time().
7408 gtk_window_present (GtkWindow *window)
7410 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7414 * gtk_window_present_with_time:
7415 * @window: a #GtkWindow
7416 * @timestamp: the timestamp of the user interaction (typically a
7417 * button or key press event) which triggered this call
7419 * Presents a window to the user in response to a user interaction.
7420 * If you need to present a window without a timestamp, use
7421 * gtk_window_present(). See gtk_window_present() for details.
7426 gtk_window_present_with_time (GtkWindow *window,
7429 GtkWindowPrivate *priv;
7431 GdkWindow *gdk_window;
7433 g_return_if_fail (GTK_IS_WINDOW (window));
7435 priv = window->priv;
7436 widget = GTK_WIDGET (window);
7438 if (gtk_widget_get_visible (widget))
7440 gdk_window = gtk_widget_get_window (widget);
7442 g_assert (gdk_window != NULL);
7444 gdk_window_show (gdk_window);
7446 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7447 if (timestamp == GDK_CURRENT_TIME)
7449 #ifdef GDK_WINDOWING_X11
7450 if (GDK_IS_X11_WINDOW(gdk_window))
7452 GdkDisplay *display;
7454 display = gtk_widget_get_display (GTK_WIDGET (window));
7455 timestamp = gdk_x11_display_get_user_time (display);
7459 timestamp = gtk_get_current_event_time ();
7462 gdk_window_focus (gdk_window, timestamp);
7466 priv->initial_timestamp = timestamp;
7467 gtk_widget_show (widget);
7472 * gtk_window_iconify:
7473 * @window: a #GtkWindow
7475 * Asks to iconify (i.e. minimize) the specified @window. Note that
7476 * you shouldn't assume the window is definitely iconified afterward,
7477 * because other entities (e.g. the user or <link
7478 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7479 * again, or there may not be a window manager in which case
7480 * iconification isn't possible, etc. But normally the window will end
7481 * up iconified. Just don't write code that crashes if not.
7483 * It's permitted to call this function before showing a window,
7484 * in which case the window will be iconified before it ever appears
7487 * You can track iconification via the "window-state-event" signal
7492 gtk_window_iconify (GtkWindow *window)
7494 GtkWindowPrivate *priv;
7496 GdkWindow *toplevel;
7498 g_return_if_fail (GTK_IS_WINDOW (window));
7500 priv = window->priv;
7501 widget = GTK_WIDGET (window);
7503 priv->iconify_initially = TRUE;
7505 toplevel = gtk_widget_get_window (widget);
7507 if (toplevel != NULL)
7508 gdk_window_iconify (toplevel);
7512 * gtk_window_deiconify:
7513 * @window: a #GtkWindow
7515 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7516 * that you shouldn't assume the window is definitely deiconified
7517 * afterward, because other entities (e.g. the user or <link
7518 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7519 * again before your code which assumes deiconification gets to run.
7521 * You can track iconification via the "window-state-event" signal
7525 gtk_window_deiconify (GtkWindow *window)
7527 GtkWindowPrivate *priv;
7529 GdkWindow *toplevel;
7531 g_return_if_fail (GTK_IS_WINDOW (window));
7533 priv = window->priv;
7534 widget = GTK_WIDGET (window);
7536 priv->iconify_initially = FALSE;
7538 toplevel = gtk_widget_get_window (widget);
7540 if (toplevel != NULL)
7541 gdk_window_deiconify (toplevel);
7546 * @window: a #GtkWindow
7548 * Asks to stick @window, which means that it will appear on all user
7549 * desktops. Note that you shouldn't assume the window is definitely
7550 * stuck afterward, because other entities (e.g. the user or <link
7551 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7552 * again, and some window managers do not support sticking
7553 * windows. But normally the window will end up stuck. Just don't
7554 * write code that crashes if not.
7556 * It's permitted to call this function before showing a window.
7558 * You can track stickiness via the "window-state-event" signal
7563 gtk_window_stick (GtkWindow *window)
7565 GtkWindowPrivate *priv;
7567 GdkWindow *toplevel;
7569 g_return_if_fail (GTK_IS_WINDOW (window));
7571 priv = window->priv;
7572 widget = GTK_WIDGET (window);
7574 priv->stick_initially = TRUE;
7576 toplevel = gtk_widget_get_window (widget);
7578 if (toplevel != NULL)
7579 gdk_window_stick (toplevel);
7583 * gtk_window_unstick:
7584 * @window: a #GtkWindow
7586 * Asks to unstick @window, which means that it will appear on only
7587 * one of the user's desktops. Note that you shouldn't assume the
7588 * window is definitely unstuck afterward, because other entities
7589 * (e.g. the user or <link linkend="gtk-X11-arch">window
7590 * manager</link>) could stick it again. But normally the window will
7591 * end up stuck. Just don't write code that crashes if not.
7593 * You can track stickiness via the "window-state-event" signal
7598 gtk_window_unstick (GtkWindow *window)
7600 GtkWindowPrivate *priv;
7602 GdkWindow *toplevel;
7604 g_return_if_fail (GTK_IS_WINDOW (window));
7606 priv = window->priv;
7607 widget = GTK_WIDGET (window);
7609 priv->stick_initially = FALSE;
7611 toplevel = gtk_widget_get_window (widget);
7613 if (toplevel != NULL)
7614 gdk_window_unstick (toplevel);
7618 * gtk_window_maximize:
7619 * @window: a #GtkWindow
7621 * Asks to maximize @window, so that it becomes full-screen. Note that
7622 * you shouldn't assume the window is definitely maximized afterward,
7623 * because other entities (e.g. the user or <link
7624 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7625 * again, and not all window managers support maximization. But
7626 * normally the window will end up maximized. Just don't write code
7627 * that crashes if not.
7629 * It's permitted to call this function before showing a window,
7630 * in which case the window will be maximized when it appears onscreen
7633 * You can track maximization via the "window-state-event" signal
7638 gtk_window_maximize (GtkWindow *window)
7640 GtkWindowPrivate *priv;
7642 GdkWindow *toplevel;
7644 g_return_if_fail (GTK_IS_WINDOW (window));
7646 priv = window->priv;
7647 widget = GTK_WIDGET (window);
7649 priv->maximize_initially = TRUE;
7651 toplevel = gtk_widget_get_window (widget);
7653 if (toplevel != NULL)
7654 gdk_window_maximize (toplevel);
7658 * gtk_window_unmaximize:
7659 * @window: a #GtkWindow
7661 * Asks to unmaximize @window. Note that you shouldn't assume the
7662 * window is definitely unmaximized afterward, because other entities
7663 * (e.g. the user or <link linkend="gtk-X11-arch">window
7664 * manager</link>) could maximize it again, and not all window
7665 * managers honor requests to unmaximize. But normally the window will
7666 * end up unmaximized. Just don't write code that crashes if not.
7668 * You can track maximization via the "window-state-event" signal
7673 gtk_window_unmaximize (GtkWindow *window)
7675 GtkWindowPrivate *priv;
7677 GdkWindow *toplevel;
7679 g_return_if_fail (GTK_IS_WINDOW (window));
7681 priv = window->priv;
7682 widget = GTK_WIDGET (window);
7684 priv->maximize_initially = FALSE;
7686 toplevel = gtk_widget_get_window (widget);
7688 if (toplevel != NULL)
7689 gdk_window_unmaximize (toplevel);
7693 * gtk_window_fullscreen:
7694 * @window: a #GtkWindow
7696 * Asks to place @window in the fullscreen state. Note that you
7697 * shouldn't assume the window is definitely full screen afterward,
7698 * because other entities (e.g. the user or <link
7699 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7700 * again, and not all window managers honor requests to fullscreen
7701 * windows. But normally the window will end up fullscreen. Just
7702 * don't write code that crashes if not.
7704 * You can track the fullscreen state via the "window-state-event" signal
7710 gtk_window_fullscreen (GtkWindow *window)
7712 GtkWindowPrivate *priv;
7714 GdkWindow *toplevel;
7716 g_return_if_fail (GTK_IS_WINDOW (window));
7718 priv = window->priv;
7719 widget = GTK_WIDGET (window);
7721 priv->fullscreen_initially = TRUE;
7723 toplevel = gtk_widget_get_window (widget);
7725 if (toplevel != NULL)
7726 gdk_window_fullscreen (toplevel);
7730 * gtk_window_unfullscreen:
7731 * @window: a #GtkWindow
7733 * Asks to toggle off the fullscreen state for @window. Note that you
7734 * shouldn't assume the window is definitely not full screen
7735 * afterward, because other entities (e.g. the user or <link
7736 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7737 * again, and not all window managers honor requests to unfullscreen
7738 * windows. But normally the window will end up restored to its normal
7739 * state. Just don't write code that crashes if not.
7741 * You can track the fullscreen state via the "window-state-event" signal
7747 gtk_window_unfullscreen (GtkWindow *window)
7750 GdkWindow *toplevel;
7751 GtkWindowPrivate *priv;
7753 g_return_if_fail (GTK_IS_WINDOW (window));
7755 priv = window->priv;
7756 widget = GTK_WIDGET (window);
7758 priv->fullscreen_initially = FALSE;
7760 toplevel = gtk_widget_get_window (widget);
7762 if (toplevel != NULL)
7763 gdk_window_unfullscreen (toplevel);
7767 * gtk_window_set_keep_above:
7768 * @window: a #GtkWindow
7769 * @setting: whether to keep @window above other windows
7771 * Asks to keep @window above, so that it stays on top. Note that
7772 * you shouldn't assume the window is definitely above afterward,
7773 * because other entities (e.g. the user or <link
7774 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7775 * and not all window managers support keeping windows above. But
7776 * normally the window will end kept above. Just don't write code
7777 * that crashes if not.
7779 * It's permitted to call this function before showing a window,
7780 * in which case the window will be kept above when it appears onscreen
7783 * You can track the above state via the "window-state-event" signal
7786 * Note that, according to the <ulink
7787 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7788 * Manager Hints</ulink> specification, the above state is mainly meant
7789 * for user preferences and should not be used by applications e.g. for
7790 * drawing attention to their dialogs.
7795 gtk_window_set_keep_above (GtkWindow *window,
7799 GtkWindowPrivate *priv;
7800 GdkWindow *toplevel;
7802 g_return_if_fail (GTK_IS_WINDOW (window));
7804 priv = window->priv;
7805 widget = GTK_WIDGET (window);
7807 priv->above_initially = setting != FALSE;
7809 priv->below_initially = FALSE;
7811 toplevel = gtk_widget_get_window (widget);
7813 if (toplevel != NULL)
7814 gdk_window_set_keep_above (toplevel, setting);
7818 * gtk_window_set_keep_below:
7819 * @window: a #GtkWindow
7820 * @setting: whether to keep @window below other windows
7822 * Asks to keep @window below, so that it stays in bottom. Note that
7823 * you shouldn't assume the window is definitely below afterward,
7824 * because other entities (e.g. the user or <link
7825 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7826 * and not all window managers support putting windows below. But
7827 * normally the window will be kept below. Just don't write code
7828 * that crashes if not.
7830 * It's permitted to call this function before showing a window,
7831 * in which case the window will be kept below when it appears onscreen
7834 * You can track the below state via the "window-state-event" signal
7837 * Note that, according to the <ulink
7838 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7839 * Manager Hints</ulink> specification, the above state is mainly meant
7840 * for user preferences and should not be used by applications e.g. for
7841 * drawing attention to their dialogs.
7846 gtk_window_set_keep_below (GtkWindow *window,
7850 GtkWindowPrivate *priv;
7851 GdkWindow *toplevel;
7853 g_return_if_fail (GTK_IS_WINDOW (window));
7855 priv = window->priv;
7856 widget = GTK_WIDGET (window);
7858 priv->below_initially = setting != FALSE;
7860 priv->above_initially = FALSE;
7862 toplevel = gtk_widget_get_window (widget);
7864 if (toplevel != NULL)
7865 gdk_window_set_keep_below (toplevel, setting);
7869 * gtk_window_set_resizable:
7870 * @window: a #GtkWindow
7871 * @resizable: %TRUE if the user can resize this window
7873 * Sets whether the user can resize a window. Windows are user resizable
7877 gtk_window_set_resizable (GtkWindow *window,
7880 GtkWindowPrivate *priv;
7882 g_return_if_fail (GTK_IS_WINDOW (window));
7884 priv = window->priv;
7886 resizable = (resizable != FALSE);
7888 if (priv->resizable != resizable)
7890 priv->resizable = (resizable != FALSE);
7892 update_grip_visibility (window);
7894 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7896 g_object_notify (G_OBJECT (window), "resizable");
7901 * gtk_window_get_resizable:
7902 * @window: a #GtkWindow
7904 * Gets the value set by gtk_window_set_resizable().
7906 * Return value: %TRUE if the user can resize the window
7909 gtk_window_get_resizable (GtkWindow *window)
7911 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7913 return window->priv->resizable;
7917 * gtk_window_set_gravity:
7918 * @window: a #GtkWindow
7919 * @gravity: window gravity
7921 * Window gravity defines the meaning of coordinates passed to
7922 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7925 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7926 * typically "do what you mean."
7930 gtk_window_set_gravity (GtkWindow *window,
7933 GtkWindowPrivate *priv;
7935 g_return_if_fail (GTK_IS_WINDOW (window));
7937 priv = window->priv;
7939 if (gravity != priv->gravity)
7941 priv->gravity = gravity;
7943 /* gtk_window_move_resize() will adapt gravity
7945 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7947 g_object_notify (G_OBJECT (window), "gravity");
7952 * gtk_window_get_gravity:
7953 * @window: a #GtkWindow
7955 * Gets the value set by gtk_window_set_gravity().
7957 * Return value: (transfer none): window gravity
7960 gtk_window_get_gravity (GtkWindow *window)
7962 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7964 return window->priv->gravity;
7968 * gtk_window_begin_resize_drag:
7969 * @window: a #GtkWindow
7970 * @button: mouse button that initiated the drag
7971 * @edge: position of the resize control
7972 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7973 * @root_y: Y position where the user clicked to initiate the drag
7974 * @timestamp: timestamp from the click event that initiated the drag
7976 * Starts resizing a window. This function is used if an application
7977 * has window resizing controls. When GDK can support it, the resize
7978 * will be done using the standard mechanism for the <link
7979 * linkend="gtk-X11-arch">window manager</link> or windowing
7980 * system. Otherwise, GDK will try to emulate window resizing,
7981 * potentially not all that well, depending on the windowing system.
7985 gtk_window_begin_resize_drag (GtkWindow *window,
7993 GdkWindow *toplevel;
7995 g_return_if_fail (GTK_IS_WINDOW (window));
7996 widget = GTK_WIDGET (window);
7997 g_return_if_fail (gtk_widget_get_visible (widget));
7999 toplevel = gtk_widget_get_window (widget);
8001 gdk_window_begin_resize_drag (toplevel,
8008 * gtk_window_begin_move_drag:
8009 * @window: a #GtkWindow
8010 * @button: mouse button that initiated the drag
8011 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8012 * @root_y: Y position where the user clicked to initiate the drag
8013 * @timestamp: timestamp from the click event that initiated the drag
8015 * Starts moving a window. This function is used if an application has
8016 * window movement grips. When GDK can support it, the window movement
8017 * will be done using the standard mechanism for the <link
8018 * linkend="gtk-X11-arch">window manager</link> or windowing
8019 * system. Otherwise, GDK will try to emulate window movement,
8020 * potentially not all that well, depending on the windowing system.
8024 gtk_window_begin_move_drag (GtkWindow *window,
8031 GdkWindow *toplevel;
8033 g_return_if_fail (GTK_IS_WINDOW (window));
8034 widget = GTK_WIDGET (window);
8035 g_return_if_fail (gtk_widget_get_visible (widget));
8037 toplevel = gtk_widget_get_window (widget);
8039 gdk_window_begin_move_drag (toplevel,
8046 * gtk_window_set_screen:
8047 * @window: a #GtkWindow.
8048 * @screen: a #GdkScreen.
8050 * Sets the #GdkScreen where the @window is displayed; if
8051 * the window is already mapped, it will be unmapped, and
8052 * then remapped on the new screen.
8057 gtk_window_set_screen (GtkWindow *window,
8060 GtkWindowPrivate *priv;
8062 GdkScreen *previous_screen;
8063 gboolean was_mapped;
8065 g_return_if_fail (GTK_IS_WINDOW (window));
8066 g_return_if_fail (GDK_IS_SCREEN (screen));
8068 priv = window->priv;
8070 if (screen == priv->screen)
8073 widget = GTK_WIDGET (window);
8075 previous_screen = priv->screen;
8076 was_mapped = gtk_widget_get_mapped (widget);
8079 gtk_widget_unmap (widget);
8080 if (gtk_widget_get_realized (widget))
8081 gtk_widget_unrealize (widget);
8083 gtk_window_free_key_hash (window);
8084 priv->screen = screen;
8085 gtk_widget_reset_rc_styles (widget);
8086 if (screen != previous_screen)
8088 if (previous_screen)
8090 g_signal_handlers_disconnect_by_func (previous_screen,
8091 gtk_window_on_composited_changed, window);
8092 #ifdef GDK_WINDOWING_X11
8093 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8094 gtk_window_on_theme_variant_changed, window);
8097 g_signal_connect (screen, "composited-changed",
8098 G_CALLBACK (gtk_window_on_composited_changed), window);
8099 #ifdef GDK_WINDOWING_X11
8100 g_signal_connect (gtk_settings_get_for_screen (screen),
8101 "notify::gtk-application-prefer-dark-theme",
8102 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8105 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8106 _gtk_widget_propagate_composited_changed (widget);
8108 g_object_notify (G_OBJECT (window), "screen");
8111 gtk_widget_map (widget);
8115 gtk_window_set_theme_variant (GtkWindow *window)
8117 #ifdef GDK_WINDOWING_X11
8118 GdkWindow *gdk_window;
8119 gboolean dark_theme_requested;
8121 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8122 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8125 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8127 if (GDK_IS_X11_WINDOW (gdk_window))
8128 gdk_x11_window_set_theme_variant (gdk_window,
8129 dark_theme_requested ? "dark" : NULL);
8134 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8138 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8139 gtk_window_set_theme_variant (window);
8143 gtk_window_on_composited_changed (GdkScreen *screen,
8146 gtk_widget_queue_draw (GTK_WIDGET (window));
8148 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8152 gtk_window_check_screen (GtkWindow *window)
8154 GtkWindowPrivate *priv = window->priv;
8157 return priv->screen;
8160 g_warning ("Screen for GtkWindow not set; you must always set\n"
8161 "a screen for a GtkWindow before using the window");
8167 * gtk_window_get_screen:
8168 * @window: a #GtkWindow.
8170 * Returns the #GdkScreen associated with @window.
8172 * Return value: (transfer none): a #GdkScreen.
8177 gtk_window_get_screen (GtkWindow *window)
8179 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8181 return window->priv->screen;
8185 * gtk_window_is_active:
8186 * @window: a #GtkWindow
8188 * Returns whether the window is part of the current active toplevel.
8189 * (That is, the toplevel window receiving keystrokes.)
8190 * The return value is %TRUE if the window is active toplevel
8191 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8192 * You might use this function if you wanted to draw a widget
8193 * differently in an active window from a widget in an inactive window.
8194 * See gtk_window_has_toplevel_focus()
8196 * Return value: %TRUE if the window part of the current active window.
8201 gtk_window_is_active (GtkWindow *window)
8203 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8205 return window->priv->is_active;
8209 * gtk_window_has_toplevel_focus:
8210 * @window: a #GtkWindow
8212 * Returns whether the input focus is within this GtkWindow.
8213 * For real toplevel windows, this is identical to gtk_window_is_active(),
8214 * but for embedded windows, like #GtkPlug, the results will differ.
8216 * Return value: %TRUE if the input focus is within this GtkWindow
8221 gtk_window_has_toplevel_focus (GtkWindow *window)
8223 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8225 return window->priv->has_toplevel_focus;
8230 * SECTION:gtkwindowgroup
8231 * @Short_description: Limit the effect of grabs
8232 * @Title: GtkWindowGroup
8234 * #GtkWindowGroup objects are referenced by each window in the group,
8235 * so once you have added all windows to a #GtkWindowGroup, you can drop
8236 * the initial reference to the window group with g_object_unref(). If the
8237 * windows in the window group are subsequently destroyed, then they will
8238 * be removed from the window group and drop their references on the window
8239 * group; when all window have been removed, the window group will be
8243 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8246 gtk_window_group_init (GtkWindowGroup *group)
8248 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8249 GTK_TYPE_WINDOW_GROUP,
8250 GtkWindowGroupPrivate);
8254 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8256 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8260 * gtk_window_group_new:
8262 * Creates a new #GtkWindowGroup object. Grabs added with
8263 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8265 * Return value: a new #GtkWindowGroup.
8268 gtk_window_group_new (void)
8270 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8274 window_group_cleanup_grabs (GtkWindowGroup *group,
8277 GtkWindowGroupPrivate *priv;
8278 GtkDeviceGrabInfo *info;
8280 GSList *to_remove = NULL;
8284 tmp_list = priv->grabs;
8287 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8288 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8289 tmp_list = tmp_list->next;
8294 gtk_grab_remove (to_remove->data);
8295 g_object_unref (to_remove->data);
8296 to_remove = g_slist_delete_link (to_remove, to_remove);
8299 tmp_list = priv->device_grabs;
8303 info = tmp_list->data;
8305 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8306 to_remove = g_slist_prepend (to_remove, info);
8308 tmp_list = tmp_list->next;
8313 info = to_remove->data;
8315 gtk_device_grab_remove (info->widget, info->device);
8316 to_remove = g_slist_delete_link (to_remove, to_remove);
8321 * gtk_window_group_add_window:
8322 * @window_group: a #GtkWindowGroup
8323 * @window: the #GtkWindow to add
8325 * Adds a window to a #GtkWindowGroup.
8328 gtk_window_group_add_window (GtkWindowGroup *window_group,
8331 GtkWindowPrivate *priv;
8333 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8334 g_return_if_fail (GTK_IS_WINDOW (window));
8336 priv = window->priv;
8338 if (priv->group != window_group)
8340 g_object_ref (window);
8341 g_object_ref (window_group);
8344 gtk_window_group_remove_window (priv->group, window);
8346 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8348 priv->group = window_group;
8350 g_object_unref (window);
8355 * gtk_window_group_remove_window:
8356 * @window_group: a #GtkWindowGroup
8357 * @window: the #GtkWindow to remove
8359 * Removes a window from a #GtkWindowGroup.
8362 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8365 GtkWindowPrivate *priv;
8367 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8368 g_return_if_fail (GTK_IS_WINDOW (window));
8369 priv = window->priv;
8370 g_return_if_fail (priv->group == window_group);
8372 g_object_ref (window);
8374 window_group_cleanup_grabs (window_group, window);
8377 g_object_unref (window_group);
8378 g_object_unref (window);
8382 * gtk_window_group_list_windows:
8383 * @window_group: a #GtkWindowGroup
8385 * Returns a list of the #GtkWindows that belong to @window_group.
8387 * Returns: (element-type GtkWindow) (transfer container): A
8388 * newly-allocated list of windows inside the group.
8393 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8395 GList *toplevels, *toplevel, *group_windows;
8397 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8399 group_windows = NULL;
8400 toplevels = gtk_window_list_toplevels ();
8402 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8404 GtkWindow *window = toplevel->data;
8406 if (window_group == window->priv->group)
8407 group_windows = g_list_prepend (group_windows, window);
8410 g_list_free (toplevels);
8412 return g_list_reverse (group_windows);
8416 * gtk_window_get_group:
8417 * @window: (allow-none): a #GtkWindow, or %NULL
8419 * Returns the group for @window or the default group, if
8420 * @window is %NULL or if @window does not have an explicit
8423 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8428 gtk_window_get_group (GtkWindow *window)
8430 if (window && window->priv->group)
8431 return window->priv->group;
8434 static GtkWindowGroup *default_group = NULL;
8437 default_group = gtk_window_group_new ();
8439 return default_group;
8444 * gtk_window_has_group:
8445 * @window: a #GtkWindow
8447 * Returns whether @window has an explicit window group.
8449 * Return value: %TRUE if @window has an explicit window group.
8454 gtk_window_has_group (GtkWindow *window)
8456 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8458 return window->priv->group != NULL;
8462 * gtk_window_group_get_current_grab:
8463 * @window_group: a #GtkWindowGroup
8465 * Gets the current grab widget of the given group,
8466 * see gtk_grab_add().
8468 * Returns: (transfer none): the current grab widget of the group
8473 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8475 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8477 if (window_group->priv->grabs)
8478 return GTK_WIDGET (window_group->priv->grabs->data);
8483 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8486 GtkWindowGroupPrivate *priv;
8488 priv = window_group->priv;
8489 priv->grabs = g_slist_prepend (priv->grabs, widget);
8493 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8496 GtkWindowGroupPrivate *priv;
8498 priv = window_group->priv;
8499 priv->grabs = g_slist_remove (priv->grabs, widget);
8504 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8507 gboolean block_others)
8509 GtkWindowGroupPrivate *priv;
8510 GtkDeviceGrabInfo *info;
8512 priv = window_group->priv;
8514 info = g_slice_new0 (GtkDeviceGrabInfo);
8515 info->widget = widget;
8516 info->device = device;
8517 info->block_others = block_others;
8519 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8523 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8527 GtkWindowGroupPrivate *priv;
8528 GtkDeviceGrabInfo *info;
8529 GSList *list, *node = NULL;
8530 GdkDevice *other_device;
8532 priv = window_group->priv;
8533 other_device = gdk_device_get_associated_device (device);
8534 list = priv->device_grabs;
8540 if (info->widget == widget &&
8541 (info->device == device ||
8542 info->device == other_device))
8555 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8556 g_slice_free (GtkDeviceGrabInfo, info);
8561 * gtk_window_group_get_current_device_grab:
8562 * @window_group: a #GtkWindowGroup
8563 * @device: a #GdkDevice
8565 * Returns the current grab widget for @device, or %NULL if none.
8567 * Returns: (transfer none): The grab widget, or %NULL
8572 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8575 GtkWindowGroupPrivate *priv;
8576 GtkDeviceGrabInfo *info;
8577 GdkDevice *other_device;
8580 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8581 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8583 priv = window_group->priv;
8584 list = priv->device_grabs;
8585 other_device = gdk_device_get_associated_device (device);
8592 if (info->device == device ||
8593 info->device == other_device)
8594 return info->widget;
8601 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8605 GtkWindowGroupPrivate *priv;
8606 GtkDeviceGrabInfo *info;
8607 GdkDevice *other_device;
8610 priv = window_group->priv;
8611 other_device = gdk_device_get_associated_device (device);
8612 list = priv->device_grabs;
8619 /* Look for blocking grabs on other device pairs
8620 * that have the passed widget within the GTK+ grab.
8622 if (info->block_others &&
8623 info->device != device &&
8624 info->device != other_device &&
8625 (info->widget == widget ||
8626 gtk_widget_is_ancestor (widget, info->widget)))
8634 Derived from XParseGeometry() in XFree86
8636 Copyright 1985, 1986, 1987,1998 The Open Group
8638 All Rights Reserved.
8640 The above copyright notice and this permission notice shall be included
8641 in all copies or substantial portions of the Software.
8643 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8644 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8645 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8646 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8647 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8648 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8649 OTHER DEALINGS IN THE SOFTWARE.
8651 Except as contained in this notice, the name of The Open Group shall
8652 not be used in advertising or otherwise to promote the sale, use or
8653 other dealings in this Software without prior written authorization
8654 from The Open Group.
8659 * XParseGeometry parses strings of the form
8660 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8661 * width, height, xoffset, and yoffset are unsigned integers.
8662 * Example: "=80x24+300-49"
8663 * The equal sign is optional.
8664 * It returns a bitmask that indicates which of the four values
8665 * were actually found in the string. For each value found,
8666 * the corresponding argument is updated; for each value
8667 * not found, the corresponding argument is left unchanged.
8670 /* The following code is from Xlib, and is minimally modified, so we
8671 * can track any upstream changes if required. Don't change this
8672 * code. Or if you do, put in a huge comment marking which thing
8677 read_int (gchar *string,
8685 else if (*string == '-')
8691 for (; (*string >= '0') && (*string <= '9'); string++)
8693 result = (result * 10) + (*string - '0');
8705 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8706 * value (x, y, width, height) was found in the parsed string.
8708 #define NoValue 0x0000
8709 #define XValue 0x0001
8710 #define YValue 0x0002
8711 #define WidthValue 0x0004
8712 #define HeightValue 0x0008
8713 #define AllValues 0x000F
8714 #define XNegative 0x0010
8715 #define YNegative 0x0020
8717 /* Try not to reformat/modify, so we can compare/sync with X sources */
8719 gtk_XParseGeometry (const char *string,
8722 unsigned int *width,
8723 unsigned int *height)
8727 unsigned int tempWidth, tempHeight;
8729 char *nextCharacter;
8731 /* These initializations are just to silence gcc */
8737 if ( (string == NULL) || (*string == '\0')) return(mask);
8739 string++; /* ignore possible '=' at beg of geometry spec */
8741 strind = (char *)string;
8742 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8743 tempWidth = read_int(strind, &nextCharacter);
8744 if (strind == nextCharacter)
8746 strind = nextCharacter;
8750 if (*strind == 'x' || *strind == 'X') {
8752 tempHeight = read_int(strind, &nextCharacter);
8753 if (strind == nextCharacter)
8755 strind = nextCharacter;
8756 mask |= HeightValue;
8759 if ((*strind == '+') || (*strind == '-')) {
8760 if (*strind == '-') {
8762 tempX = -read_int(strind, &nextCharacter);
8763 if (strind == nextCharacter)
8765 strind = nextCharacter;
8771 tempX = read_int(strind, &nextCharacter);
8772 if (strind == nextCharacter)
8774 strind = nextCharacter;
8777 if ((*strind == '+') || (*strind == '-')) {
8778 if (*strind == '-') {
8780 tempY = -read_int(strind, &nextCharacter);
8781 if (strind == nextCharacter)
8783 strind = nextCharacter;
8790 tempY = read_int(strind, &nextCharacter);
8791 if (strind == nextCharacter)
8793 strind = nextCharacter;
8799 /* If strind isn't at the end of the string the it's an invalid
8800 geometry specification. */
8802 if (*strind != '\0') return (0);
8808 if (mask & WidthValue)
8810 if (mask & HeightValue)
8811 *height = tempHeight;
8816 * gtk_window_parse_geometry:
8817 * @window: a #GtkWindow
8818 * @geometry: geometry string
8820 * Parses a standard X Window System geometry string - see the
8821 * manual page for X (type 'man X') for details on this.
8822 * gtk_window_parse_geometry() does work on all GTK+ ports
8823 * including Win32 but is primarily intended for an X environment.
8825 * If either a size or a position can be extracted from the
8826 * geometry string, gtk_window_parse_geometry() returns %TRUE
8827 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8828 * to resize/move the window.
8830 * If gtk_window_parse_geometry() returns %TRUE, it will also
8831 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8832 * indicating to the window manager that the size/position of
8833 * the window was user-specified. This causes most window
8834 * managers to honor the geometry.
8836 * Note that for gtk_window_parse_geometry() to work as expected, it has
8837 * to be called when the window has its "final" size, i.e. after calling
8838 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8841 * #include <gtk/gtk.h>
8844 * fill_with_content (GtkWidget *vbox)
8846 * /* fill with content... */
8850 * main (int argc, char *argv[])
8852 * GtkWidget *window, *vbox;
8853 * GdkGeometry size_hints = {
8854 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8857 * gtk_init (&argc, &argv);
8859 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8860 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8862 * gtk_container_add (GTK_CONTAINER (window), vbox);
8863 * fill_with_content (vbox);
8864 * gtk_widget_show_all (vbox);
8866 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8869 * GDK_HINT_MIN_SIZE |
8870 * GDK_HINT_BASE_SIZE |
8871 * GDK_HINT_RESIZE_INC);
8875 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8876 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8879 * gtk_widget_show_all (window);
8886 * Return value: %TRUE if string was parsed successfully
8889 gtk_window_parse_geometry (GtkWindow *window,
8890 const gchar *geometry)
8892 gint result, x = 0, y = 0;
8896 gboolean size_set, pos_set;
8899 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8900 g_return_val_if_fail (geometry != NULL, FALSE);
8902 child = gtk_bin_get_child (GTK_BIN (window));
8903 if (!child || !gtk_widget_get_visible (child))
8904 g_warning ("gtk_window_parse_geometry() called on a window with no "
8905 "visible children; the window should be set up before "
8906 "gtk_window_parse_geometry() is called.");
8908 screen = gtk_window_check_screen (window);
8910 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8913 if ((result & WidthValue) || (result & HeightValue))
8915 gtk_window_set_default_size_internal (window,
8916 TRUE, result & WidthValue ? w : -1,
8917 TRUE, result & HeightValue ? h : -1,
8922 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8924 grav = GDK_GRAVITY_NORTH_WEST;
8926 if ((result & XNegative) && (result & YNegative))
8927 grav = GDK_GRAVITY_SOUTH_EAST;
8928 else if (result & XNegative)
8929 grav = GDK_GRAVITY_NORTH_EAST;
8930 else if (result & YNegative)
8931 grav = GDK_GRAVITY_SOUTH_WEST;
8933 if ((result & XValue) == 0)
8936 if ((result & YValue) == 0)
8939 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8940 grav == GDK_GRAVITY_SOUTH_EAST)
8941 y = gdk_screen_get_height (screen) - h + y;
8943 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8944 grav == GDK_GRAVITY_NORTH_EAST)
8945 x = gdk_screen_get_width (screen) - w + x;
8947 /* we don't let you put a window offscreen; maybe some people would
8948 * prefer to be able to, but it's kind of a bogus thing to do.
8957 if ((result & XValue) || (result & YValue))
8959 gtk_window_set_gravity (window, grav);
8960 gtk_window_move (window, x, y);
8964 if (size_set || pos_set)
8966 /* Set USSize, USPosition hints */
8967 GtkWindowGeometryInfo *info;
8969 info = gtk_window_get_geometry_info (window, TRUE);
8972 info->mask |= GDK_HINT_USER_POS;
8974 info->mask |= GDK_HINT_USER_SIZE;
8981 gtk_window_mnemonic_hash_foreach (guint keyval,
8987 GtkWindowKeysForeachFunc func;
8991 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8995 _gtk_window_keys_foreach (GtkWindow *window,
8996 GtkWindowKeysForeachFunc func,
9000 GtkMnemonicHash *mnemonic_hash;
9004 GtkWindowKeysForeachFunc func;
9008 info.window = window;
9010 info.func_data = func_data;
9012 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9014 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9015 gtk_window_mnemonic_hash_foreach, &info);
9017 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9020 GtkAccelGroup *group = groups->data;
9023 for (i = 0; i < group->priv->n_accels; i++)
9025 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9028 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9031 groups = groups->next;
9036 gtk_window_keys_changed (GtkWindow *window)
9038 gtk_window_free_key_hash (window);
9039 gtk_window_get_key_hash (window);
9042 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9044 struct _GtkWindowKeyEntry
9048 guint is_mnemonic : 1;
9052 window_key_entry_destroy (gpointer data)
9054 g_slice_free (GtkWindowKeyEntry, data);
9058 add_to_key_hash (GtkWindow *window,
9060 GdkModifierType modifiers,
9061 gboolean is_mnemonic,
9064 GtkKeyHash *key_hash = data;
9066 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9068 entry->keyval = keyval;
9069 entry->modifiers = modifiers;
9070 entry->is_mnemonic = is_mnemonic;
9072 /* GtkAccelGroup stores lowercased accelerators. To deal
9073 * with this, if <Shift> was specified, uppercase.
9075 if (modifiers & GDK_SHIFT_MASK)
9077 if (keyval == GDK_KEY_Tab)
9078 keyval = GDK_KEY_ISO_Left_Tab;
9080 keyval = gdk_keyval_to_upper (keyval);
9083 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9087 gtk_window_get_key_hash (GtkWindow *window)
9089 GdkScreen *screen = gtk_window_check_screen (window);
9090 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9095 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9096 (GDestroyNotify)window_key_entry_destroy);
9097 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9098 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9104 gtk_window_free_key_hash (GtkWindow *window)
9106 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9109 _gtk_key_hash_free (key_hash);
9110 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9115 * gtk_window_activate_key:
9116 * @window: a #GtkWindow
9117 * @event: a #GdkEventKey
9119 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9120 * called by the default ::key_press_event handler for toplevel windows,
9121 * however in some cases it may be useful to call this directly when
9122 * overriding the standard key handling for a toplevel window.
9124 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9129 gtk_window_activate_key (GtkWindow *window,
9132 GtkKeyHash *key_hash;
9133 GtkWindowKeyEntry *found_entry = NULL;
9134 gboolean enable_mnemonics;
9135 gboolean enable_accels;
9137 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9138 g_return_val_if_fail (event != NULL, FALSE);
9140 key_hash = gtk_window_get_key_hash (window);
9145 GSList *entries = _gtk_key_hash_lookup (key_hash,
9146 event->hardware_keycode,
9148 gtk_accelerator_get_default_mod_mask (),
9151 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9152 "gtk-enable-mnemonics", &enable_mnemonics,
9153 "gtk-enable-accels", &enable_accels,
9156 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9158 GtkWindowKeyEntry *entry = tmp_list->data;
9159 if (entry->is_mnemonic)
9161 if (enable_mnemonics)
9163 found_entry = entry;
9169 if (enable_accels && !found_entry)
9171 found_entry = entry;
9176 g_slist_free (entries);
9181 if (found_entry->is_mnemonic)
9183 if (enable_mnemonics)
9184 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9185 found_entry->modifiers);
9190 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9191 found_entry->modifiers);
9199 window_update_has_focus (GtkWindow *window)
9201 GtkWindowPrivate *priv = window->priv;
9202 GtkWidget *widget = GTK_WIDGET (window);
9203 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9205 if (has_focus != priv->has_focus)
9207 priv->has_focus = has_focus;
9211 if (priv->focus_widget &&
9212 priv->focus_widget != widget &&
9213 !gtk_widget_has_focus (priv->focus_widget))
9214 do_focus_change (priv->focus_widget, TRUE);
9218 if (priv->focus_widget &&
9219 priv->focus_widget != widget &&
9220 gtk_widget_has_focus (priv->focus_widget))
9221 do_focus_change (priv->focus_widget, FALSE);
9227 * _gtk_window_set_is_active:
9228 * @window: a #GtkWindow
9229 * @is_active: %TRUE if the window is in the currently active toplevel
9231 * Internal function that sets whether the #GtkWindow is part
9232 * of the currently active toplevel window (taking into account inter-process
9236 _gtk_window_set_is_active (GtkWindow *window,
9239 GtkWindowPrivate *priv;
9241 g_return_if_fail (GTK_IS_WINDOW (window));
9243 priv = window->priv;
9245 is_active = is_active != FALSE;
9247 if (is_active != priv->is_active)
9249 priv->is_active = is_active;
9250 window_update_has_focus (window);
9252 g_object_notify (G_OBJECT (window), "is-active");
9257 * _gtk_window_set_is_toplevel:
9258 * @window: a #GtkWindow
9259 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9260 * child of the root window); %FALSE if it is not (for example, for an
9261 * in-process, parented GtkPlug)
9263 * Internal function used by #GtkPlug when it gets parented/unparented by a
9264 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9265 * global list of toplevel windows.
9268 _gtk_window_set_is_toplevel (GtkWindow *window,
9269 gboolean is_toplevel)
9272 GtkWidget *toplevel;
9274 widget = GTK_WIDGET (window);
9276 if (gtk_widget_is_toplevel (widget))
9277 g_assert (g_slist_find (toplevel_list, window) != NULL);
9279 g_assert (g_slist_find (toplevel_list, window) == NULL);
9281 if (is_toplevel == gtk_widget_is_toplevel (widget))
9286 /* Pass through regular pathways of an embedded toplevel
9287 * to go through unmapping and hiding the widget before
9288 * becomming a toplevel again.
9290 * We remain hidden after becomming toplevel in order to
9291 * avoid problems during an embedded toplevel's dispose cycle
9292 * (When a toplevel window is shown it tries to grab focus again,
9293 * this causes problems while disposing).
9295 gtk_widget_hide (widget);
9297 /* Save the toplevel this widget was previously anchored into before
9298 * propagating a hierarchy-changed.
9300 * Usually this happens by way of gtk_widget_unparent() and we are
9301 * already unanchored at this point, just adding this clause incase
9302 * things happen differently.
9304 toplevel = gtk_widget_get_toplevel (widget);
9305 if (!gtk_widget_is_toplevel (toplevel))
9308 _gtk_widget_set_is_toplevel (widget, TRUE);
9310 /* When a window becomes toplevel after being embedded and anchored
9311 * into another window we need to unset its anchored flag so that
9312 * the hierarchy changed signal kicks in properly.
9314 _gtk_widget_set_anchored (widget, FALSE);
9315 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9317 toplevel_list = g_slist_prepend (toplevel_list, window);
9321 _gtk_widget_set_is_toplevel (widget, FALSE);
9322 toplevel_list = g_slist_remove (toplevel_list, window);
9324 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9329 * _gtk_window_set_has_toplevel_focus:
9330 * @window: a #GtkWindow
9331 * @has_toplevel_focus: %TRUE if the in
9333 * Internal function that sets whether the keyboard focus for the
9334 * toplevel window (taking into account inter-process embedding.)
9337 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9338 gboolean has_toplevel_focus)
9340 GtkWindowPrivate *priv;
9342 g_return_if_fail (GTK_IS_WINDOW (window));
9344 priv = window->priv;
9346 has_toplevel_focus = has_toplevel_focus != FALSE;
9348 if (has_toplevel_focus != priv->has_toplevel_focus)
9350 priv->has_toplevel_focus = has_toplevel_focus;
9351 window_update_has_focus (window);
9353 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9358 * gtk_window_set_auto_startup_notification:
9359 * @setting: %TRUE to automatically do startup notification
9361 * By default, after showing the first #GtkWindow, GTK+ calls
9362 * gdk_notify_startup_complete(). Call this function to disable
9363 * the automatic startup notification. You might do this if your
9364 * first window is a splash screen, and you want to delay notification
9365 * until after your real main window has been shown, for example.
9367 * In that example, you would disable startup notification
9368 * temporarily, show your splash screen, then re-enable it so that
9369 * showing the main window would automatically result in notification.
9374 gtk_window_set_auto_startup_notification (gboolean setting)
9376 disable_startup_notification = !setting;
9380 * gtk_window_get_window_type:
9381 * @window: a #GtkWindow
9383 * Gets the type of the window. See #GtkWindowType.
9385 * Return value: the type of the window
9390 gtk_window_get_window_type (GtkWindow *window)
9392 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9394 return window->priv->type;
9398 * gtk_window_get_mnemonics_visible:
9399 * @window: a #GtkWindow
9401 * Gets the value of the #GtkWindow:mnemonics-visible property.
9403 * Returns: %TRUE if mnemonics are supposed to be visible
9409 gtk_window_get_mnemonics_visible (GtkWindow *window)
9411 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9413 return window->priv->mnemonics_visible;
9417 * gtk_window_set_mnemonics_visible:
9418 * @window: a #GtkWindow
9419 * @setting: the new value
9421 * Sets the #GtkWindow:mnemonics-visible property.
9426 gtk_window_set_mnemonics_visible (GtkWindow *window,
9429 GtkWindowPrivate *priv;
9431 g_return_if_fail (GTK_IS_WINDOW (window));
9433 priv = window->priv;
9435 setting = setting != FALSE;
9437 if (priv->mnemonics_visible != setting)
9439 priv->mnemonics_visible = setting;
9440 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9443 priv->mnemonics_visible_set = TRUE;
9447 _gtk_window_get_wmclass (GtkWindow *window,
9448 gchar **wmclass_name,
9449 gchar **wmclass_class)
9451 GtkWindowPrivate *priv = window->priv;
9453 *wmclass_name = priv->wmclass_name;
9454 *wmclass_class = priv->wmclass_class;
9458 * gtk_window_set_has_user_ref_count:
9459 * @window: a #GtkWindow
9460 * @setting: the new value
9462 * Tells GTK+ whether to drop its extra reference to the window
9463 * when gtk_window_destroy() is called.
9465 * This function is only exported for the benefit of language
9466 * bindings which may need to keep the window alive until their
9467 * wrapper object is garbage collected. There is no justification
9468 * for ever calling this function in an application.
9473 gtk_window_set_has_user_ref_count (GtkWindow *window,
9476 g_return_if_fail (GTK_IS_WINDOW (window));
9478 window->priv->has_user_ref_count = setting;