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"
51 #include "gtkcontainerprivate.h"
53 #include "gtktypebuiltins.h"
55 #ifdef GDK_WINDOWING_X11
62 * @short_description: Toplevel which can contain other widgets
64 * A GtkWindow is a toplevel window which can contain other widgets.
65 * Windows normally have decorations that are under the control
66 * of the windowing system and allow the user to manipulate the window
67 * (resize it, move it, close it,...).
69 * GTK+ also allows windows to have a resize grip (a small area in the lower
70 * right or left corner) which can be clicked to reszie the window. To
71 * control whether a window has a resize grip, use
72 * gtk_window_set_has_resize_grip().
74 * <refsect2 id="GtkWindow-BUILDER-UI">
75 * <title>GtkWindow as GtkBuildable</title>
77 * The GtkWindow implementation of the GtkBuildable interface supports a
78 * custom <tag class="starttag">accel-groups</tag> element, which supports
79 * any number of <tag class="starttag">group</tag> elements representing the
80 * #GtkAccelGroup objects you want to add to your window (synonymous with
81 * gtk_window_add_accel_group().
84 * <title>A UI definition fragment with accel groups</title>
85 * <programlisting><![CDATA[
86 * <object class="GtkWindow">
88 * <group name="accelgroup1"/>
94 * <object class="GtkAccelGroup" id="accelgroup1"/>
95 * ]]></programlisting>
100 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
102 struct _GtkWindowPrivate
104 GtkMnemonicHash *mnemonic_hash;
106 GtkWidget *default_widget;
107 GtkWidget *focus_widget;
108 GtkWindow *transient_parent;
109 GtkWindowGeometryInfo *geometry_info;
110 GtkWindowGroup *group;
112 GtkApplication *application;
114 GdkModifierType mnemonic_modifier;
115 GdkWindowTypeHint gdk_type_hint;
119 GdkWindow *grip_window;
123 gchar *wmclass_class;
127 guint keys_changed_handler;
129 guint32 initial_timestamp;
131 guint16 configure_request_count;
133 /* The following flags are initially TRUE (before a window is mapped).
134 * They cause us to compute a configure request that involves
135 * default-only parameters. Once mapped, we set them to FALSE.
136 * Then we set them to TRUE again on unmap (for position)
137 * and on unrealize (for size).
139 guint need_default_position : 1;
140 guint need_default_size : 1;
142 guint above_initially : 1;
143 guint accept_focus : 1;
144 guint below_initially : 1;
145 guint builder_visible : 1;
146 guint configure_notify_received : 1;
149 guint destroy_with_parent : 1;
150 guint focus_on_map : 1;
151 guint fullscreen_initially : 1;
153 guint has_user_ref_count : 1;
154 guint has_toplevel_focus : 1;
155 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
157 guint maximize_initially : 1;
158 guint mnemonics_visible : 1;
159 guint mnemonics_visible_set : 1;
161 guint opacity_set : 1;
163 guint reset_type_hint : 1;
165 guint skips_pager : 1;
166 guint skips_taskbar : 1;
167 guint stick_initially : 1;
168 guint transient_parent_group : 1;
169 guint type : 4; /* GtkWindowType */
170 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
171 * one of the original eight. If not,
173 * GDK_WINDOW_TYPE_HINT_NORMAL
176 guint has_resize_grip : 1;
177 guint resize_grip_visible : 1; /* don't use, just for "resize-
178 * grip-visible" notification
180 guint gravity : 5; /* GdkGravity */
207 PROP_DESTROY_WITH_PARENT,
212 PROP_SKIP_TASKBAR_HINT,
213 PROP_SKIP_PAGER_HINT,
222 PROP_HAS_RESIZE_GRIP,
223 PROP_RESIZE_GRIP_VISIBLE,
225 /* Readonly properties */
227 PROP_HAS_TOPLEVEL_FOCUS,
229 /* Writeonly properties */
232 PROP_MNEMONICS_VISIBLE,
242 guint using_default_icon : 1;
243 guint using_parent_icon : 1;
244 guint using_themed_icon : 1;
248 GdkGeometry geometry; /* Last set of geometry hints we set */
249 GdkWindowHints flags;
250 GdkRectangle configure_request;
251 } GtkWindowLastGeometryInfo;
253 struct _GtkWindowGeometryInfo
255 /* Properties that the app has set on the window
257 GdkGeometry geometry; /* Geometry hints */
259 GtkWidget *widget; /* subwidget to which hints apply */
260 /* from last gtk_window_resize () - if > 0, indicates that
261 * we should resize to this size.
266 /* From last gtk_window_move () prior to mapping -
267 * only used if initial_pos_set
272 /* Default size - used only the FIRST time we map a window,
277 /* whether to use initial_x, initial_y */
278 guint initial_pos_set : 1;
279 /* CENTER_ALWAYS or other position constraint changed since
280 * we sent the last configure request.
282 guint position_constraints_changed : 1;
284 /* if true, default_width, height should be multiplied by the
285 * increments and affect the geometry widget only
287 guint default_is_geometry : 1;
289 /* if true, resize_width, height should be multiplied by the
290 * increments and affect the geometry widget only
292 guint resize_is_geometry : 1;
294 GtkWindowLastGeometryInfo last;
298 struct _GtkDeviceGrabInfo
302 guint block_others : 1;
305 struct _GtkWindowGroupPrivate
308 GSList *device_grabs;
311 static void gtk_window_dispose (GObject *object);
312 static void gtk_window_finalize (GObject *object);
313 static void gtk_window_destroy (GtkWidget *widget);
314 static void gtk_window_show (GtkWidget *widget);
315 static void gtk_window_hide (GtkWidget *widget);
316 static void gtk_window_map (GtkWidget *widget);
317 static void gtk_window_unmap (GtkWidget *widget);
318 static void gtk_window_realize (GtkWidget *widget);
319 static void gtk_window_unrealize (GtkWidget *widget);
320 static void gtk_window_size_allocate (GtkWidget *widget,
321 GtkAllocation *allocation);
322 static gboolean gtk_window_map_event (GtkWidget *widget,
324 static gint gtk_window_configure_event (GtkWidget *widget,
325 GdkEventConfigure *event);
326 static gint gtk_window_key_press_event (GtkWidget *widget,
328 static gint gtk_window_key_release_event (GtkWidget *widget,
330 static gint gtk_window_button_press_event (GtkWidget *widget,
331 GdkEventButton *event);
332 static gint gtk_window_enter_notify_event (GtkWidget *widget,
333 GdkEventCrossing *event);
334 static gint gtk_window_leave_notify_event (GtkWidget *widget,
335 GdkEventCrossing *event);
336 static gint gtk_window_focus_in_event (GtkWidget *widget,
337 GdkEventFocus *event);
338 static gint gtk_window_focus_out_event (GtkWidget *widget,
339 GdkEventFocus *event);
340 static void gtk_window_style_updated (GtkWidget *widget);
341 static gboolean gtk_window_state_event (GtkWidget *widget,
342 GdkEventWindowState *event);
343 static void gtk_window_check_resize (GtkContainer *container);
344 static gint gtk_window_focus (GtkWidget *widget,
345 GtkDirectionType direction);
346 static void gtk_window_move_focus (GtkWidget *widget,
347 GtkDirectionType dir);
348 static void gtk_window_real_set_focus (GtkWindow *window,
350 static void gtk_window_direction_changed (GtkWidget *widget,
351 GtkTextDirection prev_dir);
352 static void gtk_window_state_changed (GtkWidget *widget,
353 GtkStateType previous_state);
355 static void gtk_window_real_activate_default (GtkWindow *window);
356 static void gtk_window_real_activate_focus (GtkWindow *window);
357 static void gtk_window_keys_changed (GtkWindow *window);
358 static gint gtk_window_draw (GtkWidget *widget,
360 static void gtk_window_unset_transient_for (GtkWindow *window);
361 static void gtk_window_transient_parent_realized (GtkWidget *parent,
363 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
366 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
368 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
371 static void gtk_window_move_resize (GtkWindow *window);
372 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
374 GdkGeometry *geometry_b,
376 static void gtk_window_constrain_size (GtkWindow *window,
377 GdkGeometry *geometry,
383 static void gtk_window_constrain_position (GtkWindow *window,
388 static void gtk_window_compute_hints (GtkWindow *window,
389 GdkGeometry *new_geometry,
391 static void gtk_window_compute_configure_request (GtkWindow *window,
392 GdkRectangle *request,
393 GdkGeometry *geometry,
396 static void gtk_window_set_default_size_internal (GtkWindow *window,
397 gboolean change_width,
399 gboolean change_height,
401 gboolean is_geometry);
403 static void update_themed_icon (GtkIconTheme *theme,
405 static GList *icon_list_from_theme (GtkWidget *widget,
407 static void gtk_window_realize_icon (GtkWindow *window);
408 static void gtk_window_unrealize_icon (GtkWindow *window);
409 static void resize_grip_create_window (GtkWindow *window);
410 static void resize_grip_destroy_window (GtkWindow *window);
411 static void update_grip_visibility (GtkWindow *window);
413 static void gtk_window_notify_keys_changed (GtkWindow *window);
414 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
415 static void gtk_window_free_key_hash (GtkWindow *window);
416 static void gtk_window_on_composited_changed (GdkScreen *screen,
418 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
421 static void gtk_window_set_theme_variant (GtkWindow *window);
423 static GSList *toplevel_list = NULL;
424 static guint window_signals[LAST_SIGNAL] = { 0 };
425 static GList *default_icon_list = NULL;
426 static gchar *default_icon_name = NULL;
427 static guint default_icon_serial = 0;
428 static gboolean disable_startup_notification = FALSE;
429 static gboolean sent_startup_notification = FALSE;
431 static GQuark quark_gtk_embedded = 0;
432 static GQuark quark_gtk_window_key_hash = 0;
433 static GQuark quark_gtk_window_icon_info = 0;
434 static GQuark quark_gtk_buildable_accels = 0;
436 static GtkBuildableIface *parent_buildable_iface;
438 static void gtk_window_set_property (GObject *object,
442 static void gtk_window_get_property (GObject *object,
448 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
449 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
452 const GValue *value);
453 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
454 GtkBuilder *builder);
455 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
458 const gchar *tagname,
459 GMarkupParser *parser,
461 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
464 const gchar *tagname,
468 static void gtk_window_get_preferred_width (GtkWidget *widget,
471 static void gtk_window_get_preferred_height (GtkWidget *widget,
475 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
476 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
477 gtk_window_buildable_interface_init))
480 add_tab_bindings (GtkBindingSet *binding_set,
481 GdkModifierType modifiers,
482 GtkDirectionType direction)
484 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
486 GTK_TYPE_DIRECTION_TYPE, direction);
487 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
489 GTK_TYPE_DIRECTION_TYPE, direction);
493 add_arrow_bindings (GtkBindingSet *binding_set,
495 GtkDirectionType direction)
497 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
499 gtk_binding_entry_add_signal (binding_set, keysym, 0,
501 GTK_TYPE_DIRECTION_TYPE, direction);
502 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
504 GTK_TYPE_DIRECTION_TYPE, direction);
505 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
507 GTK_TYPE_DIRECTION_TYPE, direction);
508 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
510 GTK_TYPE_DIRECTION_TYPE, direction);
514 extract_time_from_startup_id (const gchar* startup_id)
516 gchar *timestr = g_strrstr (startup_id, "_TIME");
517 guint32 retval = GDK_CURRENT_TIME;
524 /* Skip past the "_TIME" part */
529 timestamp = g_ascii_strtoull (timestr, &end, 0);
530 if (errno == 0 && end != timestr)
538 startup_id_is_fake (const gchar* startup_id)
540 return strncmp (startup_id, "_TIME", 5) == 0;
544 gtk_window_class_init (GtkWindowClass *klass)
546 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
547 GtkWidgetClass *widget_class;
548 GtkContainerClass *container_class;
549 GtkBindingSet *binding_set;
551 widget_class = (GtkWidgetClass*) klass;
552 container_class = (GtkContainerClass*) klass;
554 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
555 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
556 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
557 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
559 gobject_class->dispose = gtk_window_dispose;
560 gobject_class->finalize = gtk_window_finalize;
562 gobject_class->set_property = gtk_window_set_property;
563 gobject_class->get_property = gtk_window_get_property;
565 widget_class->destroy = gtk_window_destroy;
566 widget_class->show = gtk_window_show;
567 widget_class->hide = gtk_window_hide;
568 widget_class->map = gtk_window_map;
569 widget_class->map_event = gtk_window_map_event;
570 widget_class->unmap = gtk_window_unmap;
571 widget_class->realize = gtk_window_realize;
572 widget_class->unrealize = gtk_window_unrealize;
573 widget_class->size_allocate = gtk_window_size_allocate;
574 widget_class->configure_event = gtk_window_configure_event;
575 widget_class->key_press_event = gtk_window_key_press_event;
576 widget_class->key_release_event = gtk_window_key_release_event;
577 widget_class->enter_notify_event = gtk_window_enter_notify_event;
578 widget_class->leave_notify_event = gtk_window_leave_notify_event;
579 widget_class->focus_in_event = gtk_window_focus_in_event;
580 widget_class->button_press_event = gtk_window_button_press_event;
581 widget_class->focus_out_event = gtk_window_focus_out_event;
582 widget_class->focus = gtk_window_focus;
583 widget_class->move_focus = gtk_window_move_focus;
584 widget_class->draw = gtk_window_draw;
585 widget_class->get_preferred_width = gtk_window_get_preferred_width;
586 widget_class->get_preferred_height = gtk_window_get_preferred_height;
587 widget_class->window_state_event = gtk_window_state_event;
588 widget_class->direction_changed = gtk_window_direction_changed;
589 widget_class->state_changed = gtk_window_state_changed;
590 widget_class->style_updated = gtk_window_style_updated;
592 container_class->check_resize = gtk_window_check_resize;
594 klass->set_focus = gtk_window_real_set_focus;
596 klass->activate_default = gtk_window_real_activate_default;
597 klass->activate_focus = gtk_window_real_activate_focus;
598 klass->keys_changed = gtk_window_keys_changed;
600 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
603 g_object_class_install_property (gobject_class,
605 g_param_spec_enum ("type",
607 P_("The type of the window"),
608 GTK_TYPE_WINDOW_TYPE,
610 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
612 g_object_class_install_property (gobject_class,
614 g_param_spec_string ("title",
616 P_("The title of the window"),
618 GTK_PARAM_READWRITE));
620 g_object_class_install_property (gobject_class,
622 g_param_spec_string ("role",
624 P_("Unique identifier for the window to be used when restoring a session"),
626 GTK_PARAM_READWRITE));
629 * GtkWindow:startup-id:
631 * The :startup-id is a write-only property for setting window's
632 * startup notification identifier. See gtk_window_set_startup_id()
637 g_object_class_install_property (gobject_class,
639 g_param_spec_string ("startup-id",
641 P_("Unique startup identifier for the window used by startup-notification"),
643 GTK_PARAM_WRITABLE));
645 g_object_class_install_property (gobject_class,
647 g_param_spec_boolean ("resizable",
649 P_("If TRUE, users can resize the window"),
651 GTK_PARAM_READWRITE));
653 g_object_class_install_property (gobject_class,
655 g_param_spec_boolean ("modal",
657 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
659 GTK_PARAM_READWRITE));
661 g_object_class_install_property (gobject_class,
663 g_param_spec_enum ("window-position",
664 P_("Window Position"),
665 P_("The initial position of the window"),
666 GTK_TYPE_WINDOW_POSITION,
668 GTK_PARAM_READWRITE));
670 g_object_class_install_property (gobject_class,
672 g_param_spec_int ("default-width",
674 P_("The default width of the window, used when initially showing the window"),
678 GTK_PARAM_READWRITE));
680 g_object_class_install_property (gobject_class,
682 g_param_spec_int ("default-height",
683 P_("Default Height"),
684 P_("The default height of the window, used when initially showing the window"),
688 GTK_PARAM_READWRITE));
690 g_object_class_install_property (gobject_class,
691 PROP_DESTROY_WITH_PARENT,
692 g_param_spec_boolean ("destroy-with-parent",
693 P_("Destroy with Parent"),
694 P_("If this window should be destroyed when the parent is destroyed"),
696 GTK_PARAM_READWRITE));
698 g_object_class_install_property (gobject_class,
700 g_param_spec_object ("icon",
702 P_("Icon for this window"),
704 GTK_PARAM_READWRITE));
705 g_object_class_install_property (gobject_class,
706 PROP_MNEMONICS_VISIBLE,
707 g_param_spec_boolean ("mnemonics-visible",
708 P_("Mnemonics Visible"),
709 P_("Whether mnemonics are currently visible in this window"),
711 GTK_PARAM_READWRITE));
714 * GtkWindow:icon-name:
716 * The :icon-name property specifies the name of the themed icon to
717 * use as the window icon. See #GtkIconTheme for more details.
721 g_object_class_install_property (gobject_class,
723 g_param_spec_string ("icon-name",
725 P_("Name of the themed icon for this window"),
727 GTK_PARAM_READWRITE));
729 g_object_class_install_property (gobject_class,
731 g_param_spec_object ("screen",
733 P_("The screen where this window will be displayed"),
735 GTK_PARAM_READWRITE));
737 g_object_class_install_property (gobject_class,
739 g_param_spec_boolean ("is-active",
741 P_("Whether the toplevel is the current active window"),
743 GTK_PARAM_READABLE));
745 g_object_class_install_property (gobject_class,
746 PROP_HAS_TOPLEVEL_FOCUS,
747 g_param_spec_boolean ("has-toplevel-focus",
748 P_("Focus in Toplevel"),
749 P_("Whether the input focus is within this GtkWindow"),
751 GTK_PARAM_READABLE));
753 g_object_class_install_property (gobject_class,
755 g_param_spec_enum ("type-hint",
757 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
758 GDK_TYPE_WINDOW_TYPE_HINT,
759 GDK_WINDOW_TYPE_HINT_NORMAL,
760 GTK_PARAM_READWRITE));
762 g_object_class_install_property (gobject_class,
763 PROP_SKIP_TASKBAR_HINT,
764 g_param_spec_boolean ("skip-taskbar-hint",
766 P_("TRUE if the window should not be in the task bar."),
768 GTK_PARAM_READWRITE));
770 g_object_class_install_property (gobject_class,
771 PROP_SKIP_PAGER_HINT,
772 g_param_spec_boolean ("skip-pager-hint",
774 P_("TRUE if the window should not be in the pager."),
776 GTK_PARAM_READWRITE));
778 g_object_class_install_property (gobject_class,
780 g_param_spec_boolean ("urgency-hint",
782 P_("TRUE if the window should be brought to the user's attention."),
784 GTK_PARAM_READWRITE));
787 * GtkWindow:accept-focus:
789 * Whether the window should receive the input focus.
793 g_object_class_install_property (gobject_class,
795 g_param_spec_boolean ("accept-focus",
797 P_("TRUE if the window should receive the input focus."),
799 GTK_PARAM_READWRITE));
802 * GtkWindow:focus-on-map:
804 * Whether the window should receive the input focus when mapped.
808 g_object_class_install_property (gobject_class,
810 g_param_spec_boolean ("focus-on-map",
812 P_("TRUE if the window should receive the input focus when mapped."),
814 GTK_PARAM_READWRITE));
817 * GtkWindow:decorated:
819 * Whether the window should be decorated by the window manager.
823 g_object_class_install_property (gobject_class,
825 g_param_spec_boolean ("decorated",
827 P_("Whether the window should be decorated by the window manager"),
829 GTK_PARAM_READWRITE));
832 * GtkWindow:deletable:
834 * Whether the window frame should have a close button.
838 g_object_class_install_property (gobject_class,
840 g_param_spec_boolean ("deletable",
842 P_("Whether the window frame should have a close button"),
844 GTK_PARAM_READWRITE));
847 * GtkWindow:has-resize-grip
849 * Whether the window has a corner resize grip.
851 * Note that the resize grip is only shown if the window is
852 * actually resizable and not maximized. Use
853 * #GtkWindow:resize-grip-visible to find out if the resize
854 * grip is currently shown.
858 g_object_class_install_property (gobject_class,
859 PROP_HAS_RESIZE_GRIP,
860 g_param_spec_boolean ("has-resize-grip",
862 P_("Specifies whether the window should have a resize grip"),
864 GTK_PARAM_READWRITE));
867 * GtkWindow:resize-grip-visible:
869 * Whether a corner resize grip is currently shown.
873 g_object_class_install_property (gobject_class,
874 PROP_RESIZE_GRIP_VISIBLE,
875 g_param_spec_boolean ("resize-grip-visible",
876 P_("Resize grip is visible"),
877 P_("Specifies whether the window's resize grip is visible."),
879 GTK_PARAM_READABLE));
885 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
886 * more details about window gravity.
890 g_object_class_install_property (gobject_class,
892 g_param_spec_enum ("gravity",
894 P_("The window gravity of the window"),
896 GDK_GRAVITY_NORTH_WEST,
897 GTK_PARAM_READWRITE));
901 * GtkWindow:transient-for:
903 * The transient parent of the window. See gtk_window_set_transient_for() for
904 * more details about transient windows.
908 g_object_class_install_property (gobject_class,
910 g_param_spec_object ("transient-for",
911 P_("Transient for Window"),
912 P_("The transient parent of the dialog"),
914 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
919 * The requested opacity of the window. See gtk_window_set_opacity() for
920 * more details about window opacity.
924 g_object_class_install_property (gobject_class,
926 g_param_spec_double ("opacity",
927 P_("Opacity for Window"),
928 P_("The opacity of the window, from 0 to 1"),
932 GTK_PARAM_READWRITE));
936 gtk_widget_class_install_style_property (widget_class,
937 g_param_spec_int ("resize-grip-width",
938 P_("Width of resize grip"),
939 P_("Width of resize grip"),
940 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
942 gtk_widget_class_install_style_property (widget_class,
943 g_param_spec_int ("resize-grip-height",
944 P_("Height of resize grip"),
945 P_("Height of resize grip"),
946 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
950 * GtkWindow:application:
952 * The #GtkApplication associated with the window.
954 * The application will be kept alive for at least as long as it
955 * has any windows associated with it (see g_application_hold()
956 * for a way to keep it alive without windows).
958 * Normally, the connection between the application and the window
959 * will remain until the window is destroyed, but you can explicitly
960 * remove it by setting the ::application property to %NULL.
964 g_object_class_install_property (gobject_class,
966 g_param_spec_object ("application",
967 P_("GtkApplication"),
968 P_("The GtkApplication for the window"),
969 GTK_TYPE_APPLICATION,
970 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
972 window_signals[SET_FOCUS] =
973 g_signal_new (I_("set-focus"),
974 G_TYPE_FROM_CLASS (gobject_class),
976 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
978 _gtk_marshal_VOID__OBJECT,
983 * GtkWindow::activate-focus:
984 * @window: the window which received the signal
986 * The ::activate-focus signal is a
987 * <link linkend="keybinding-signals">keybinding signal</link>
988 * which gets emitted when the user activates the currently
989 * focused widget of @window.
991 window_signals[ACTIVATE_FOCUS] =
992 g_signal_new (I_("activate-focus"),
993 G_TYPE_FROM_CLASS (gobject_class),
994 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
995 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
997 _gtk_marshal_VOID__VOID,
1002 * GtkWindow::activate-default:
1003 * @window: the window which received the signal
1005 * The ::activate-default signal is a
1006 * <link linkend="keybinding-signals">keybinding signal</link>
1007 * which gets emitted when the user activates the default widget
1010 window_signals[ACTIVATE_DEFAULT] =
1011 g_signal_new (I_("activate-default"),
1012 G_TYPE_FROM_CLASS (gobject_class),
1013 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1014 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1016 _gtk_marshal_VOID__VOID,
1021 * GtkWindow::keys-changed:
1022 * @window: the window which received the signal
1024 * The ::keys-changed signal gets emitted when the set of accelerators
1025 * or mnemonics that are associated with @window changes.
1027 window_signals[KEYS_CHANGED] =
1028 g_signal_new (I_("keys-changed"),
1029 G_TYPE_FROM_CLASS (gobject_class),
1031 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1033 _gtk_marshal_VOID__VOID,
1041 binding_set = gtk_binding_set_by_class (klass);
1043 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1044 "activate-focus", 0);
1045 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1046 "activate-focus", 0);
1048 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1049 "activate-default", 0);
1050 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1051 "activate-default", 0);
1052 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1053 "activate-default", 0);
1055 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1056 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1057 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1058 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1060 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1061 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1062 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1063 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1067 gtk_window_init (GtkWindow *window)
1069 GtkWindowPrivate *priv;
1071 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1074 priv = window->priv;
1076 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1077 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1079 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1081 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1084 priv->wmclass_name = g_strdup (g_get_prgname ());
1085 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1086 priv->wm_role = NULL;
1087 priv->geometry_info = NULL;
1088 priv->type = GTK_WINDOW_TOPLEVEL;
1089 priv->focus_widget = NULL;
1090 priv->default_widget = NULL;
1091 priv->configure_request_count = 0;
1092 priv->resizable = TRUE;
1093 priv->configure_notify_received = FALSE;
1094 priv->position = GTK_WIN_POS_NONE;
1095 priv->need_default_size = TRUE;
1096 priv->need_default_position = TRUE;
1097 priv->modal = FALSE;
1098 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1099 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1100 priv->decorated = TRUE;
1101 priv->mnemonic_modifier = GDK_MOD1_MASK;
1102 priv->screen = gdk_screen_get_default ();
1104 priv->accept_focus = TRUE;
1105 priv->focus_on_map = TRUE;
1106 priv->deletable = TRUE;
1107 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1108 priv->opacity = 1.0;
1109 priv->startup_id = NULL;
1110 priv->initial_timestamp = GDK_CURRENT_TIME;
1111 priv->has_resize_grip = TRUE;
1112 priv->mnemonics_visible = TRUE;
1114 g_object_ref_sink (window);
1115 priv->has_user_ref_count = TRUE;
1116 toplevel_list = g_slist_prepend (toplevel_list, window);
1119 g_signal_connect (priv->screen, "composited-changed",
1120 G_CALLBACK (gtk_window_on_composited_changed), window);
1122 #ifdef GDK_WINDOWING_X11
1123 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1124 "notify::gtk-application-prefer-dark-theme",
1125 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1130 gtk_window_set_property (GObject *object,
1132 const GValue *value,
1135 GtkWindow *window = GTK_WINDOW (object);
1136 GtkWindowPrivate *priv = window->priv;
1141 priv->type = g_value_get_enum (value);
1144 gtk_window_set_title (window, g_value_get_string (value));
1147 gtk_window_set_role (window, g_value_get_string (value));
1149 case PROP_STARTUP_ID:
1150 gtk_window_set_startup_id (window, g_value_get_string (value));
1152 case PROP_RESIZABLE:
1153 gtk_window_set_resizable (window, g_value_get_boolean (value));
1156 gtk_window_set_modal (window, g_value_get_boolean (value));
1159 gtk_window_set_position (window, g_value_get_enum (value));
1161 case PROP_DEFAULT_WIDTH:
1162 gtk_window_set_default_size_internal (window,
1163 TRUE, g_value_get_int (value),
1166 case PROP_DEFAULT_HEIGHT:
1167 gtk_window_set_default_size_internal (window,
1169 TRUE, g_value_get_int (value), FALSE);
1171 case PROP_DESTROY_WITH_PARENT:
1172 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1175 gtk_window_set_icon (window,
1176 g_value_get_object (value));
1178 case PROP_ICON_NAME:
1179 gtk_window_set_icon_name (window, g_value_get_string (value));
1182 gtk_window_set_screen (window, g_value_get_object (value));
1184 case PROP_TYPE_HINT:
1185 gtk_window_set_type_hint (window,
1186 g_value_get_enum (value));
1188 case PROP_SKIP_TASKBAR_HINT:
1189 gtk_window_set_skip_taskbar_hint (window,
1190 g_value_get_boolean (value));
1192 case PROP_SKIP_PAGER_HINT:
1193 gtk_window_set_skip_pager_hint (window,
1194 g_value_get_boolean (value));
1196 case PROP_URGENCY_HINT:
1197 gtk_window_set_urgency_hint (window,
1198 g_value_get_boolean (value));
1200 case PROP_ACCEPT_FOCUS:
1201 gtk_window_set_accept_focus (window,
1202 g_value_get_boolean (value));
1204 case PROP_FOCUS_ON_MAP:
1205 gtk_window_set_focus_on_map (window,
1206 g_value_get_boolean (value));
1208 case PROP_DECORATED:
1209 gtk_window_set_decorated (window, g_value_get_boolean (value));
1211 case PROP_DELETABLE:
1212 gtk_window_set_deletable (window, g_value_get_boolean (value));
1215 gtk_window_set_gravity (window, g_value_get_enum (value));
1217 case PROP_TRANSIENT_FOR:
1218 gtk_window_set_transient_for (window, g_value_get_object (value));
1221 gtk_window_set_opacity (window, g_value_get_double (value));
1223 case PROP_HAS_RESIZE_GRIP:
1224 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1226 case PROP_APPLICATION:
1227 gtk_window_set_application (window, g_value_get_object (value));
1229 case PROP_MNEMONICS_VISIBLE:
1230 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1233 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1239 gtk_window_get_property (GObject *object,
1244 GtkWindow *window = GTK_WINDOW (object);
1245 GtkWindowPrivate *priv = window->priv;
1249 GtkWindowGeometryInfo *info;
1251 g_value_set_enum (value, priv->type);
1254 g_value_set_string (value, priv->wm_role);
1257 g_value_set_string (value, priv->title);
1259 case PROP_RESIZABLE:
1260 g_value_set_boolean (value, priv->resizable);
1263 g_value_set_boolean (value, priv->modal);
1266 g_value_set_enum (value, priv->position);
1268 case PROP_DEFAULT_WIDTH:
1269 info = gtk_window_get_geometry_info (window, FALSE);
1271 g_value_set_int (value, -1);
1273 g_value_set_int (value, info->default_width);
1275 case PROP_DEFAULT_HEIGHT:
1276 info = gtk_window_get_geometry_info (window, FALSE);
1278 g_value_set_int (value, -1);
1280 g_value_set_int (value, info->default_height);
1282 case PROP_DESTROY_WITH_PARENT:
1283 g_value_set_boolean (value, priv->destroy_with_parent);
1286 g_value_set_object (value, gtk_window_get_icon (window));
1288 case PROP_ICON_NAME:
1289 g_value_set_string (value, gtk_window_get_icon_name (window));
1292 g_value_set_object (value, priv->screen);
1294 case PROP_IS_ACTIVE:
1295 g_value_set_boolean (value, priv->is_active);
1297 case PROP_HAS_TOPLEVEL_FOCUS:
1298 g_value_set_boolean (value, priv->has_toplevel_focus);
1300 case PROP_TYPE_HINT:
1301 g_value_set_enum (value, priv->type_hint);
1303 case PROP_SKIP_TASKBAR_HINT:
1304 g_value_set_boolean (value,
1305 gtk_window_get_skip_taskbar_hint (window));
1307 case PROP_SKIP_PAGER_HINT:
1308 g_value_set_boolean (value,
1309 gtk_window_get_skip_pager_hint (window));
1311 case PROP_URGENCY_HINT:
1312 g_value_set_boolean (value,
1313 gtk_window_get_urgency_hint (window));
1315 case PROP_ACCEPT_FOCUS:
1316 g_value_set_boolean (value,
1317 gtk_window_get_accept_focus (window));
1319 case PROP_FOCUS_ON_MAP:
1320 g_value_set_boolean (value,
1321 gtk_window_get_focus_on_map (window));
1323 case PROP_DECORATED:
1324 g_value_set_boolean (value, gtk_window_get_decorated (window));
1326 case PROP_DELETABLE:
1327 g_value_set_boolean (value, gtk_window_get_deletable (window));
1330 g_value_set_enum (value, gtk_window_get_gravity (window));
1332 case PROP_TRANSIENT_FOR:
1333 g_value_set_object (value, gtk_window_get_transient_for (window));
1336 g_value_set_double (value, gtk_window_get_opacity (window));
1338 case PROP_HAS_RESIZE_GRIP:
1339 g_value_set_boolean (value, priv->has_resize_grip);
1341 case PROP_RESIZE_GRIP_VISIBLE:
1342 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1344 case PROP_APPLICATION:
1345 g_value_set_object (value, gtk_window_get_application (window));
1347 case PROP_MNEMONICS_VISIBLE:
1348 g_value_set_boolean (value, priv->mnemonics_visible);
1351 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1357 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1359 parent_buildable_iface = g_type_interface_peek_parent (iface);
1360 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1361 iface->parser_finished = gtk_window_buildable_parser_finished;
1362 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1363 iface->custom_finished = gtk_window_buildable_custom_finished;
1367 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1368 GtkBuilder *builder,
1370 const GValue *value)
1372 GtkWindow *window = GTK_WINDOW (buildable);
1373 GtkWindowPrivate *priv = window->priv;
1375 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1376 priv->builder_visible = TRUE;
1378 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1382 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1383 GtkBuilder *builder)
1385 GtkWindow *window = GTK_WINDOW (buildable);
1386 GtkWindowPrivate *priv = window->priv;
1390 if (priv->builder_visible)
1391 gtk_widget_show (GTK_WIDGET (buildable));
1393 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1394 for (l = accels; l; l = l->next)
1396 object = gtk_builder_get_object (builder, l->data);
1399 g_warning ("Unknown accel group %s specified in window %s",
1400 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1403 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1404 GTK_ACCEL_GROUP (object));
1408 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1410 parent_buildable_iface->parser_finished (buildable, builder);
1416 } GSListSubParserData;
1419 window_start_element (GMarkupParseContext *context,
1420 const gchar *element_name,
1421 const gchar **names,
1422 const gchar **values,
1427 GSListSubParserData *data = (GSListSubParserData*)user_data;
1429 if (strcmp (element_name, "group") == 0)
1431 for (i = 0; names[i]; i++)
1433 if (strcmp (names[i], "name") == 0)
1434 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1437 else if (strcmp (element_name, "accel-groups") == 0)
1440 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1445 static const GMarkupParser window_parser =
1447 window_start_element
1451 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1452 GtkBuilder *builder,
1454 const gchar *tagname,
1455 GMarkupParser *parser,
1458 GSListSubParserData *parser_data;
1460 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1461 tagname, parser, data))
1464 if (strcmp (tagname, "accel-groups") == 0)
1466 parser_data = g_slice_new0 (GSListSubParserData);
1467 parser_data->items = NULL;
1468 parser_data->object = G_OBJECT (buildable);
1470 *parser = window_parser;
1471 *data = parser_data;
1479 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1480 GtkBuilder *builder,
1482 const gchar *tagname,
1485 GSListSubParserData *data;
1487 parent_buildable_iface->custom_finished (buildable, builder, child,
1488 tagname, user_data);
1490 if (strcmp (tagname, "accel-groups") != 0)
1493 data = (GSListSubParserData*)user_data;
1495 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1496 data->items, (GDestroyNotify) g_slist_free);
1498 g_slice_free (GSListSubParserData, data);
1503 * @type: type of window
1505 * Creates a new #GtkWindow, which is a toplevel window that can
1506 * contain other widgets. Nearly always, the type of the window should
1507 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1508 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1509 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1510 * dialogs, though in some other toolkits dialogs are called "popups".
1511 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1512 * On X11, popup windows are not controlled by the <link
1513 * linkend="gtk-X11-arch">window manager</link>.
1515 * If you simply want an undecorated window (no window borders), use
1516 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1518 * Return value: a new #GtkWindow.
1521 gtk_window_new (GtkWindowType type)
1523 GtkWindowPrivate *priv;
1526 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1528 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1529 priv = window->priv;
1533 return GTK_WIDGET (window);
1537 * gtk_window_set_title:
1538 * @window: a #GtkWindow
1539 * @title: title of the window
1541 * Sets the title of the #GtkWindow. The title of a window will be
1542 * displayed in its title bar; on the X Window System, the title bar
1543 * is rendered by the <link linkend="gtk-X11-arch">window
1544 * manager</link>, so exactly how the title appears to users may vary
1545 * according to a user's exact configuration. The title should help a
1546 * user distinguish this window from other windows they may have
1547 * open. A good title might include the application name and current
1548 * document filename, for example.
1552 gtk_window_set_title (GtkWindow *window,
1555 GtkWindowPrivate *priv;
1559 g_return_if_fail (GTK_IS_WINDOW (window));
1561 priv = window->priv;
1562 widget = GTK_WIDGET (window);
1564 new_title = g_strdup (title);
1565 g_free (priv->title);
1566 priv->title = new_title;
1568 if (gtk_widget_get_realized (widget))
1570 gdk_window_set_title (gtk_widget_get_window (widget),
1574 g_object_notify (G_OBJECT (window), "title");
1578 * gtk_window_get_title:
1579 * @window: a #GtkWindow
1581 * Retrieves the title of the window. See gtk_window_set_title().
1583 * Return value: the title of the window, or %NULL if none has
1584 * been set explicitely. The returned string is owned by the widget
1585 * and must not be modified or freed.
1587 G_CONST_RETURN gchar *
1588 gtk_window_get_title (GtkWindow *window)
1590 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1592 return window->priv->title;
1596 * gtk_window_set_wmclass:
1597 * @window: a #GtkWindow
1598 * @wmclass_name: window name hint
1599 * @wmclass_class: window class hint
1601 * Don't use this function. It sets the X Window System "class" and
1602 * "name" hints for a window. According to the ICCCM, you should
1603 * always set these to the same value for all windows in an
1604 * application, and GTK+ sets them to that value by default, so calling
1605 * this function is sort of pointless. However, you may want to call
1606 * gtk_window_set_role() on each window in your application, for the
1607 * benefit of the session manager. Setting the role allows the window
1608 * manager to restore window positions when loading a saved session.
1612 gtk_window_set_wmclass (GtkWindow *window,
1613 const gchar *wmclass_name,
1614 const gchar *wmclass_class)
1616 GtkWindowPrivate *priv;
1618 g_return_if_fail (GTK_IS_WINDOW (window));
1620 priv = window->priv;
1622 g_free (priv->wmclass_name);
1623 priv->wmclass_name = g_strdup (wmclass_name);
1625 g_free (priv->wmclass_class);
1626 priv->wmclass_class = g_strdup (wmclass_class);
1628 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1629 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1633 * gtk_window_set_role:
1634 * @window: a #GtkWindow
1635 * @role: unique identifier for the window to be used when restoring a session
1637 * This function is only useful on X11, not with other GTK+ targets.
1639 * In combination with the window title, the window role allows a
1640 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1641 * same" window when an application is restarted. So for example you
1642 * might set the "toolbox" role on your app's toolbox window, so that
1643 * when the user restarts their session, the window manager can put
1644 * the toolbox back in the same place.
1646 * If a window already has a unique title, you don't need to set the
1647 * role, since the WM can use the title to identify the window when
1648 * restoring the session.
1652 gtk_window_set_role (GtkWindow *window,
1655 GtkWindowPrivate *priv;
1658 g_return_if_fail (GTK_IS_WINDOW (window));
1660 priv = window->priv;
1662 new_role = g_strdup (role);
1663 g_free (priv->wm_role);
1664 priv->wm_role = new_role;
1666 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1667 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1670 g_object_notify (G_OBJECT (window), "role");
1674 * gtk_window_set_startup_id:
1675 * @window: a #GtkWindow
1676 * @startup_id: a string with startup-notification identifier
1678 * Startup notification identifiers are used by desktop environment to
1679 * track application startup, to provide user feedback and other
1680 * features. This function changes the corresponding property on the
1681 * underlying GdkWindow. Normally, startup identifier is managed
1682 * automatically and you should only use this function in special cases
1683 * like transferring focus from other processes. You should use this
1684 * function before calling gtk_window_present() or any equivalent
1685 * function generating a window map event.
1687 * This function is only useful on X11, not with other GTK+ targets.
1692 gtk_window_set_startup_id (GtkWindow *window,
1693 const gchar *startup_id)
1695 GtkWindowPrivate *priv;
1698 g_return_if_fail (GTK_IS_WINDOW (window));
1700 priv = window->priv;
1701 widget = GTK_WIDGET (window);
1703 g_free (priv->startup_id);
1704 priv->startup_id = g_strdup (startup_id);
1706 if (gtk_widget_get_realized (widget))
1708 GdkWindow *gdk_window;
1709 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1711 gdk_window = gtk_widget_get_window (widget);
1713 #ifdef GDK_WINDOWING_X11
1714 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1715 gdk_x11_window_set_user_time (gdk_window, timestamp);
1718 /* Here we differentiate real and "fake" startup notification IDs,
1719 * constructed on purpose just to pass interaction timestamp
1721 if (startup_id_is_fake (priv->startup_id))
1722 gtk_window_present_with_time (window, timestamp);
1725 gdk_window_set_startup_id (gdk_window,
1728 /* If window is mapped, terminate the startup-notification too */
1729 if (gtk_widget_get_mapped (widget) &&
1730 !disable_startup_notification)
1731 gdk_notify_startup_complete_with_id (priv->startup_id);
1735 g_object_notify (G_OBJECT (window), "startup-id");
1739 * gtk_window_get_role:
1740 * @window: a #GtkWindow
1742 * Returns the role of the window. See gtk_window_set_role() for
1743 * further explanation.
1745 * Return value: the role of the window if set, or %NULL. The
1746 * returned is owned by the widget and must not be modified
1749 G_CONST_RETURN gchar *
1750 gtk_window_get_role (GtkWindow *window)
1752 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1754 return window->priv->wm_role;
1758 * gtk_window_set_focus:
1759 * @window: a #GtkWindow
1760 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1761 * any focus widget for the toplevel window.
1763 * If @focus is not the current focus widget, and is focusable, sets
1764 * it as the focus widget for the window. If @focus is %NULL, unsets
1765 * the focus widget for this window. To set the focus to a particular
1766 * widget in the toplevel, it is usually more convenient to use
1767 * gtk_widget_grab_focus() instead of this function.
1770 gtk_window_set_focus (GtkWindow *window,
1773 GtkWindowPrivate *priv;
1776 g_return_if_fail (GTK_IS_WINDOW (window));
1778 priv = window->priv;
1782 g_return_if_fail (GTK_IS_WIDGET (focus));
1783 g_return_if_fail (gtk_widget_get_can_focus (focus));
1787 gtk_widget_grab_focus (focus);
1790 /* Clear the existing focus chain, so that when we focus into
1791 * the window again, we start at the beginnning.
1793 GtkWidget *widget = priv->focus_widget;
1796 while ((parent = gtk_widget_get_parent (widget)))
1799 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1803 _gtk_window_internal_set_focus (window, NULL);
1808 _gtk_window_internal_set_focus (GtkWindow *window,
1811 GtkWindowPrivate *priv;
1813 g_return_if_fail (GTK_IS_WINDOW (window));
1815 priv = window->priv;
1817 if ((priv->focus_widget != focus) ||
1818 (focus && !gtk_widget_has_focus (focus)))
1819 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1823 * gtk_window_set_default:
1824 * @window: a #GtkWindow
1825 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1826 * default widget for the toplevel.
1828 * The default widget is the widget that's activated when the user
1829 * presses Enter in a dialog (for example). This function sets or
1830 * unsets the default widget for a #GtkWindow about. When setting
1831 * (rather than unsetting) the default widget it's generally easier to
1832 * call gtk_widget_grab_focus() on the widget. Before making a widget
1833 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1834 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1837 gtk_window_set_default (GtkWindow *window,
1838 GtkWidget *default_widget)
1840 GtkWindowPrivate *priv;
1842 g_return_if_fail (GTK_IS_WINDOW (window));
1844 priv = window->priv;
1847 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1849 if (priv->default_widget != default_widget)
1851 GtkWidget *old_default_widget = NULL;
1854 g_object_ref (default_widget);
1856 if (priv->default_widget)
1858 old_default_widget = priv->default_widget;
1860 if (priv->focus_widget != priv->default_widget ||
1861 !gtk_widget_get_receives_default (priv->default_widget))
1862 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1864 gtk_widget_queue_draw (priv->default_widget);
1867 priv->default_widget = default_widget;
1869 if (priv->default_widget)
1871 if (priv->focus_widget == NULL ||
1872 !gtk_widget_get_receives_default (priv->focus_widget))
1873 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1875 gtk_widget_queue_draw (priv->default_widget);
1878 if (old_default_widget)
1879 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1883 g_object_notify (G_OBJECT (default_widget), "has-default");
1884 g_object_unref (default_widget);
1890 * gtk_window_get_default_widget:
1891 * @window: a #GtkWindow
1893 * Returns the default widget for @window. See gtk_window_set_default()
1896 * Returns: (transfer none): the default widget, or %NULL if there is none.
1901 gtk_window_get_default_widget (GtkWindow *window)
1903 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1905 return window->priv->default_widget;
1909 handle_keys_changed (gpointer data)
1911 GtkWindow *window = GTK_WINDOW (data);
1912 GtkWindowPrivate *priv = window->priv;
1914 if (priv->keys_changed_handler)
1916 g_source_remove (priv->keys_changed_handler);
1917 priv->keys_changed_handler = 0;
1920 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1926 gtk_window_notify_keys_changed (GtkWindow *window)
1928 GtkWindowPrivate *priv = window->priv;
1930 if (!priv->keys_changed_handler)
1931 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1935 * gtk_window_add_accel_group:
1936 * @window: window to attach accelerator group to
1937 * @accel_group: a #GtkAccelGroup
1939 * Associate @accel_group with @window, such that calling
1940 * gtk_accel_groups_activate() on @window will activate accelerators
1944 gtk_window_add_accel_group (GtkWindow *window,
1945 GtkAccelGroup *accel_group)
1947 g_return_if_fail (GTK_IS_WINDOW (window));
1948 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1950 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1951 g_signal_connect_object (accel_group, "accel-changed",
1952 G_CALLBACK (gtk_window_notify_keys_changed),
1953 window, G_CONNECT_SWAPPED);
1954 gtk_window_notify_keys_changed (window);
1958 * gtk_window_remove_accel_group:
1959 * @window: a #GtkWindow
1960 * @accel_group: a #GtkAccelGroup
1962 * Reverses the effects of gtk_window_add_accel_group().
1965 gtk_window_remove_accel_group (GtkWindow *window,
1966 GtkAccelGroup *accel_group)
1968 g_return_if_fail (GTK_IS_WINDOW (window));
1969 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1971 g_signal_handlers_disconnect_by_func (accel_group,
1972 gtk_window_notify_keys_changed,
1974 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1975 gtk_window_notify_keys_changed (window);
1978 static GtkMnemonicHash *
1979 gtk_window_get_mnemonic_hash (GtkWindow *window,
1982 GtkWindowPrivate *private = window->priv;
1984 if (!private->mnemonic_hash && create)
1985 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1987 return private->mnemonic_hash;
1991 * gtk_window_add_mnemonic:
1992 * @window: a #GtkWindow
1993 * @keyval: the mnemonic
1994 * @target: the widget that gets activated by the mnemonic
1996 * Adds a mnemonic to this window.
1999 gtk_window_add_mnemonic (GtkWindow *window,
2003 g_return_if_fail (GTK_IS_WINDOW (window));
2004 g_return_if_fail (GTK_IS_WIDGET (target));
2006 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2008 gtk_window_notify_keys_changed (window);
2012 * gtk_window_remove_mnemonic:
2013 * @window: a #GtkWindow
2014 * @keyval: the mnemonic
2015 * @target: the widget that gets activated by the mnemonic
2017 * Removes a mnemonic from this window.
2020 gtk_window_remove_mnemonic (GtkWindow *window,
2024 g_return_if_fail (GTK_IS_WINDOW (window));
2025 g_return_if_fail (GTK_IS_WIDGET (target));
2027 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2029 gtk_window_notify_keys_changed (window);
2033 * gtk_window_mnemonic_activate:
2034 * @window: a #GtkWindow
2035 * @keyval: the mnemonic
2036 * @modifier: the modifiers
2037 * @returns: %TRUE if the activation is done.
2039 * Activates the targets associated with the mnemonic.
2042 gtk_window_mnemonic_activate (GtkWindow *window,
2044 GdkModifierType modifier)
2046 GtkWindowPrivate *priv;
2048 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2050 priv = window->priv;
2052 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2054 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2056 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2063 * gtk_window_set_mnemonic_modifier:
2064 * @window: a #GtkWindow
2065 * @modifier: the modifier mask used to activate
2066 * mnemonics on this window.
2068 * Sets the mnemonic modifier for this window.
2071 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2072 GdkModifierType modifier)
2074 GtkWindowPrivate *priv;
2076 g_return_if_fail (GTK_IS_WINDOW (window));
2077 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2079 priv = window->priv;
2081 priv->mnemonic_modifier = modifier;
2082 gtk_window_notify_keys_changed (window);
2086 * gtk_window_get_mnemonic_modifier:
2087 * @window: a #GtkWindow
2089 * Returns the mnemonic modifier for this window. See
2090 * gtk_window_set_mnemonic_modifier().
2092 * Return value: the modifier mask used to activate
2093 * mnemonics on this window.
2096 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2098 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2100 return window->priv->mnemonic_modifier;
2104 * gtk_window_set_position:
2105 * @window: a #GtkWindow.
2106 * @position: a position constraint.
2108 * Sets a position constraint for this window. If the old or new
2109 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2110 * the window to be repositioned to satisfy the new constraint.
2113 gtk_window_set_position (GtkWindow *window,
2114 GtkWindowPosition position)
2116 GtkWindowPrivate *priv;
2118 g_return_if_fail (GTK_IS_WINDOW (window));
2120 priv = window->priv;
2122 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2123 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2125 GtkWindowGeometryInfo *info;
2127 info = gtk_window_get_geometry_info (window, TRUE);
2129 /* this flag causes us to re-request the CENTER_ALWAYS
2130 * constraint in gtk_window_move_resize(), see
2131 * comment in that function.
2133 info->position_constraints_changed = TRUE;
2135 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2138 priv->position = position;
2140 g_object_notify (G_OBJECT (window), "window-position");
2144 * gtk_window_activate_focus:
2145 * @window: a #GtkWindow
2147 * Activates the current focused widget within the window.
2149 * Return value: %TRUE if a widget got activated.
2152 gtk_window_activate_focus (GtkWindow *window)
2154 GtkWindowPrivate *priv;
2156 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2158 priv = window->priv;
2160 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2161 return gtk_widget_activate (priv->focus_widget);
2167 * gtk_window_get_focus:
2168 * @window: a #GtkWindow
2170 * Retrieves the current focused widget within the window.
2171 * Note that this is the widget that would have the focus
2172 * if the toplevel window focused; if the toplevel window
2173 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2174 * not be %TRUE for the widget.
2176 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2179 gtk_window_get_focus (GtkWindow *window)
2181 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2183 return window->priv->focus_widget;
2187 * gtk_window_activate_default:
2188 * @window: a #GtkWindow
2190 * Activates the default widget for the window, unless the current
2191 * focused widget has been configured to receive the default action
2192 * (see gtk_widget_set_receives_default()), in which case the
2193 * focused widget is activated.
2195 * Return value: %TRUE if a widget got activated.
2198 gtk_window_activate_default (GtkWindow *window)
2200 GtkWindowPrivate *priv;
2202 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2204 priv = window->priv;
2206 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2207 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2208 return gtk_widget_activate (priv->default_widget);
2209 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2210 return gtk_widget_activate (priv->focus_widget);
2216 * gtk_window_set_modal:
2217 * @window: a #GtkWindow
2218 * @modal: whether the window is modal
2220 * Sets a window modal or non-modal. Modal windows prevent interaction
2221 * with other windows in the same application. To keep modal dialogs
2222 * on top of main application windows, use
2223 * gtk_window_set_transient_for() to make the dialog transient for the
2224 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2225 * will then disallow lowering the dialog below the parent.
2230 gtk_window_set_modal (GtkWindow *window,
2233 GtkWindowPrivate *priv;
2236 g_return_if_fail (GTK_IS_WINDOW (window));
2238 priv = window->priv;
2240 modal = modal != FALSE;
2241 if (priv->modal == modal)
2244 priv->modal = modal;
2245 widget = GTK_WIDGET (window);
2247 /* adjust desired modality state */
2248 if (gtk_widget_get_realized (widget))
2251 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2253 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2256 if (gtk_widget_get_visible (widget))
2259 gtk_grab_add (widget);
2261 gtk_grab_remove (widget);
2264 g_object_notify (G_OBJECT (window), "modal");
2268 * gtk_window_get_modal:
2269 * @window: a #GtkWindow
2271 * Returns whether the window is modal. See gtk_window_set_modal().
2273 * Return value: %TRUE if the window is set to be modal and
2274 * establishes a grab when shown
2277 gtk_window_get_modal (GtkWindow *window)
2279 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2281 return window->priv->modal;
2285 * gtk_window_list_toplevels:
2287 * Returns a list of all existing toplevel windows. The widgets
2288 * in the list are not individually referenced. If you want
2289 * to iterate through the list and perform actions involving
2290 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2291 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2292 * then unref all the widgets afterwards.
2294 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2297 gtk_window_list_toplevels (void)
2302 for (slist = toplevel_list; slist; slist = slist->next)
2303 list = g_list_prepend (list, slist->data);
2309 gtk_window_dispose (GObject *object)
2311 GtkWindow *window = GTK_WINDOW (object);
2313 gtk_window_set_focus (window, NULL);
2314 gtk_window_set_default (window, NULL);
2316 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2320 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2322 gtk_widget_destroy (GTK_WIDGET (child));
2326 connect_parent_destroyed (GtkWindow *window)
2328 GtkWindowPrivate *priv = window->priv;
2330 if (priv->transient_parent)
2332 g_signal_connect (priv->transient_parent,
2334 G_CALLBACK (parent_destroyed_callback),
2340 disconnect_parent_destroyed (GtkWindow *window)
2342 GtkWindowPrivate *priv = window->priv;
2344 if (priv->transient_parent)
2346 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2347 parent_destroyed_callback,
2353 gtk_window_transient_parent_realized (GtkWidget *parent,
2356 if (gtk_widget_get_realized (window))
2357 gdk_window_set_transient_for (gtk_widget_get_window (window),
2358 gtk_widget_get_window (parent));
2362 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2365 if (gtk_widget_get_realized (window))
2366 gdk_property_delete (gtk_widget_get_window (window),
2367 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2371 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2375 gtk_window_set_screen (window, parent->priv->screen);
2379 gtk_window_unset_transient_for (GtkWindow *window)
2381 GtkWindowPrivate *priv = window->priv;
2383 if (priv->transient_parent)
2385 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2386 gtk_window_transient_parent_realized,
2388 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2389 gtk_window_transient_parent_unrealized,
2391 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2392 gtk_window_transient_parent_screen_changed,
2394 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2395 gtk_widget_destroyed,
2396 &priv->transient_parent);
2398 if (priv->destroy_with_parent)
2399 disconnect_parent_destroyed (window);
2401 priv->transient_parent = NULL;
2403 if (priv->transient_parent_group)
2405 priv->transient_parent_group = FALSE;
2406 gtk_window_group_remove_window (priv->group,
2413 * gtk_window_set_transient_for:
2414 * @window: a #GtkWindow
2415 * @parent: (allow-none): parent window, or %NULL
2417 * Dialog windows should be set transient for the main application
2418 * window they were spawned from. This allows <link
2419 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2420 * dialog on top of the main window, or center the dialog over the
2421 * main window. gtk_dialog_new_with_buttons() and other convenience
2422 * functions in GTK+ will sometimes call
2423 * gtk_window_set_transient_for() on your behalf.
2425 * Passing %NULL for @parent unsets the current transient window.
2427 * On Windows, this function puts the child window on top of the parent,
2428 * much as the window manager would have done on X.
2431 gtk_window_set_transient_for (GtkWindow *window,
2434 GtkWindowPrivate *priv;
2436 g_return_if_fail (GTK_IS_WINDOW (window));
2437 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2438 g_return_if_fail (window != parent);
2440 priv = window->priv;
2442 if (priv->transient_parent)
2444 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2445 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2446 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2447 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2448 GTK_WIDGET (window));
2450 gtk_window_unset_transient_for (window);
2453 priv->transient_parent = parent;
2457 g_signal_connect (parent, "destroy",
2458 G_CALLBACK (gtk_widget_destroyed),
2459 &priv->transient_parent);
2460 g_signal_connect (parent, "realize",
2461 G_CALLBACK (gtk_window_transient_parent_realized),
2463 g_signal_connect (parent, "unrealize",
2464 G_CALLBACK (gtk_window_transient_parent_unrealized),
2466 g_signal_connect (parent, "notify::screen",
2467 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2470 gtk_window_set_screen (window, parent->priv->screen);
2472 if (priv->destroy_with_parent)
2473 connect_parent_destroyed (window);
2475 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2476 gtk_widget_get_realized (GTK_WIDGET (parent)))
2477 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2478 GTK_WIDGET (window));
2480 if (parent->priv->group)
2482 gtk_window_group_add_window (parent->priv->group, window);
2483 priv->transient_parent_group = TRUE;
2489 * gtk_window_get_transient_for:
2490 * @window: a #GtkWindow
2492 * Fetches the transient parent for this window. See
2493 * gtk_window_set_transient_for().
2495 * Return value: (transfer none): the transient parent for this window, or %NULL
2496 * if no transient parent has been set.
2499 gtk_window_get_transient_for (GtkWindow *window)
2501 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2503 return window->priv->transient_parent;
2507 * gtk_window_set_opacity:
2508 * @window: a #GtkWindow
2509 * @opacity: desired opacity, between 0 and 1
2511 * Request the windowing system to make @window partially transparent,
2512 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2513 * of the opacity parameter are clamped to the [0,1] range.) On X11
2514 * this has any effect only on X screens with a compositing manager
2515 * running. See gtk_widget_is_composited(). On Windows it should work
2518 * Note that setting a window's opacity after the window has been
2519 * shown causes it to flicker once on Windows.
2524 gtk_window_set_opacity (GtkWindow *window,
2527 GtkWindowPrivate *priv;
2529 g_return_if_fail (GTK_IS_WINDOW (window));
2531 priv = window->priv;
2535 else if (opacity > 1.0)
2538 priv->opacity_set = TRUE;
2539 priv->opacity = opacity;
2541 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2542 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2547 * gtk_window_get_opacity:
2548 * @window: a #GtkWindow
2550 * Fetches the requested opacity for this window. See
2551 * gtk_window_set_opacity().
2553 * Return value: the requested opacity for this window.
2558 gtk_window_get_opacity (GtkWindow *window)
2560 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2562 return window->priv->opacity;
2566 * gtk_window_get_application:
2567 * @window: a #GtkWindow
2569 * Gets the #GtkApplication associated with the window (if any).
2571 * Return value: (transfer none): a #GtkApplication, or %NULL
2576 gtk_window_get_application (GtkWindow *window)
2578 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2580 return window->priv->application;
2584 gtk_window_release_application (GtkWindow *window)
2586 if (window->priv->application)
2588 GtkApplication *application;
2590 /* steal reference into temp variable */
2591 application = window->priv->application;
2592 window->priv->application = NULL;
2594 gtk_application_remove_window (application, window);
2595 g_object_unref (application);
2600 * gtk_window_set_application:
2601 * @window: a #GtkWindow
2602 * @application: (allow-none): a #GtkApplication, or %NULL
2604 * Sets or unsets the #GtkApplication associated with the window.
2606 * The application will be kept alive for at least as long as the window
2612 gtk_window_set_application (GtkWindow *window,
2613 GtkApplication *application)
2615 GtkWindowPrivate *priv;
2617 g_return_if_fail (GTK_IS_WINDOW (window));
2619 priv = window->priv;
2620 if (priv->application != application)
2622 gtk_window_release_application (window);
2624 priv->application = application;
2626 if (priv->application != NULL)
2628 g_object_ref (priv->application);
2630 gtk_application_add_window (priv->application, window);
2633 g_object_notify (G_OBJECT (window), "application");
2638 * gtk_window_set_type_hint:
2639 * @window: a #GtkWindow
2640 * @hint: the window type
2642 * By setting the type hint for the window, you allow the window
2643 * manager to decorate and handle the window in a way which is
2644 * suitable to the function of the window in your application.
2646 * This function should be called before the window becomes visible.
2648 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2649 * will sometimes call gtk_window_set_type_hint() on your behalf.
2653 gtk_window_set_type_hint (GtkWindow *window,
2654 GdkWindowTypeHint hint)
2656 GtkWindowPrivate *priv;
2658 g_return_if_fail (GTK_IS_WINDOW (window));
2659 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2661 priv = window->priv;
2663 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2664 priv->type_hint = hint;
2666 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2668 priv->reset_type_hint = TRUE;
2669 priv->gdk_type_hint = hint;
2673 * gtk_window_get_type_hint:
2674 * @window: a #GtkWindow
2676 * Gets the type hint for this window. See gtk_window_set_type_hint().
2678 * Return value: the type hint for @window.
2681 gtk_window_get_type_hint (GtkWindow *window)
2683 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2685 return window->priv->gdk_type_hint;
2689 * gtk_window_set_skip_taskbar_hint:
2690 * @window: a #GtkWindow
2691 * @setting: %TRUE to keep this window from appearing in the task bar
2693 * Windows may set a hint asking the desktop environment not to display
2694 * the window in the task bar. This function sets this hint.
2699 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2702 GtkWindowPrivate *priv;
2704 g_return_if_fail (GTK_IS_WINDOW (window));
2706 priv = window->priv;
2708 setting = setting != FALSE;
2710 if (priv->skips_taskbar != setting)
2712 priv->skips_taskbar = setting;
2713 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2714 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2715 priv->skips_taskbar);
2716 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2721 * gtk_window_get_skip_taskbar_hint:
2722 * @window: a #GtkWindow
2724 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2726 * Return value: %TRUE if window shouldn't be in taskbar
2731 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2733 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2735 return window->priv->skips_taskbar;
2739 * gtk_window_set_skip_pager_hint:
2740 * @window: a #GtkWindow
2741 * @setting: %TRUE to keep this window from appearing in the pager
2743 * Windows may set a hint asking the desktop environment not to display
2744 * the window in the pager. This function sets this hint.
2745 * (A "pager" is any desktop navigation tool such as a workspace
2746 * switcher that displays a thumbnail representation of the windows
2752 gtk_window_set_skip_pager_hint (GtkWindow *window,
2755 GtkWindowPrivate *priv;
2757 g_return_if_fail (GTK_IS_WINDOW (window));
2759 priv = window->priv;
2761 setting = setting != FALSE;
2763 if (priv->skips_pager != setting)
2765 priv->skips_pager = setting;
2766 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2767 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2769 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2774 * gtk_window_get_skip_pager_hint:
2775 * @window: a #GtkWindow
2777 * Gets the value set by gtk_window_set_skip_pager_hint().
2779 * Return value: %TRUE if window shouldn't be in pager
2784 gtk_window_get_skip_pager_hint (GtkWindow *window)
2786 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2788 return window->priv->skips_pager;
2792 * gtk_window_set_urgency_hint:
2793 * @window: a #GtkWindow
2794 * @setting: %TRUE to mark this window as urgent
2796 * Windows may set a hint asking the desktop environment to draw
2797 * the users attention to the window. This function sets this hint.
2802 gtk_window_set_urgency_hint (GtkWindow *window,
2805 GtkWindowPrivate *priv;
2807 g_return_if_fail (GTK_IS_WINDOW (window));
2809 priv = window->priv;
2811 setting = setting != FALSE;
2813 if (priv->urgent != setting)
2815 priv->urgent = setting;
2816 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2817 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2819 g_object_notify (G_OBJECT (window), "urgency-hint");
2824 * gtk_window_get_urgency_hint:
2825 * @window: a #GtkWindow
2827 * Gets the value set by gtk_window_set_urgency_hint()
2829 * Return value: %TRUE if window is urgent
2834 gtk_window_get_urgency_hint (GtkWindow *window)
2836 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2838 return window->priv->urgent;
2842 * gtk_window_set_accept_focus:
2843 * @window: a #GtkWindow
2844 * @setting: %TRUE to let this window receive input focus
2846 * Windows may set a hint asking the desktop environment not to receive
2847 * the input focus. This function sets this hint.
2852 gtk_window_set_accept_focus (GtkWindow *window,
2855 GtkWindowPrivate *priv;
2857 g_return_if_fail (GTK_IS_WINDOW (window));
2859 priv = window->priv;
2861 setting = setting != FALSE;
2863 if (priv->accept_focus != setting)
2865 priv->accept_focus = setting;
2866 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2867 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2868 priv->accept_focus);
2869 g_object_notify (G_OBJECT (window), "accept-focus");
2874 * gtk_window_get_accept_focus:
2875 * @window: a #GtkWindow
2877 * Gets the value set by gtk_window_set_accept_focus().
2879 * Return value: %TRUE if window should receive the input focus
2884 gtk_window_get_accept_focus (GtkWindow *window)
2886 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2888 return window->priv->accept_focus;
2892 * gtk_window_set_focus_on_map:
2893 * @window: a #GtkWindow
2894 * @setting: %TRUE to let this window receive input focus on map
2896 * Windows may set a hint asking the desktop environment not to receive
2897 * the input focus when the window is mapped. This function sets this
2903 gtk_window_set_focus_on_map (GtkWindow *window,
2906 GtkWindowPrivate *priv;
2908 g_return_if_fail (GTK_IS_WINDOW (window));
2910 priv = window->priv;
2912 setting = setting != FALSE;
2914 if (priv->focus_on_map != setting)
2916 priv->focus_on_map = setting;
2917 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2918 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2919 priv->focus_on_map);
2920 g_object_notify (G_OBJECT (window), "focus-on-map");
2925 * gtk_window_get_focus_on_map:
2926 * @window: a #GtkWindow
2928 * Gets the value set by gtk_window_set_focus_on_map().
2930 * Return value: %TRUE if window should receive the input focus when
2936 gtk_window_get_focus_on_map (GtkWindow *window)
2938 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2940 return window->priv->focus_on_map;
2944 * gtk_window_set_destroy_with_parent:
2945 * @window: a #GtkWindow
2946 * @setting: whether to destroy @window with its transient parent
2948 * If @setting is %TRUE, then destroying the transient parent of @window
2949 * will also destroy @window itself. This is useful for dialogs that
2950 * shouldn't persist beyond the lifetime of the main window they're
2951 * associated with, for example.
2954 gtk_window_set_destroy_with_parent (GtkWindow *window,
2957 GtkWindowPrivate *priv;
2959 g_return_if_fail (GTK_IS_WINDOW (window));
2961 priv = window->priv;
2963 if (priv->destroy_with_parent == (setting != FALSE))
2966 if (priv->destroy_with_parent)
2968 disconnect_parent_destroyed (window);
2972 connect_parent_destroyed (window);
2975 priv->destroy_with_parent = setting;
2977 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2981 * gtk_window_get_destroy_with_parent:
2982 * @window: a #GtkWindow
2984 * Returns whether the window will be destroyed with its transient parent. See
2985 * gtk_window_set_destroy_with_parent ().
2987 * Return value: %TRUE if the window will be destroyed with its transient parent.
2990 gtk_window_get_destroy_with_parent (GtkWindow *window)
2992 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2994 return window->priv->destroy_with_parent;
2997 static GtkWindowGeometryInfo*
2998 gtk_window_get_geometry_info (GtkWindow *window,
3001 GtkWindowPrivate *priv = window->priv;
3002 GtkWindowGeometryInfo *info;
3004 info = priv->geometry_info;
3005 if (!info && create)
3007 info = g_new0 (GtkWindowGeometryInfo, 1);
3009 info->default_width = -1;
3010 info->default_height = -1;
3011 info->resize_width = -1;
3012 info->resize_height = -1;
3013 info->initial_x = 0;
3014 info->initial_y = 0;
3015 info->initial_pos_set = FALSE;
3016 info->default_is_geometry = FALSE;
3017 info->position_constraints_changed = FALSE;
3018 info->last.configure_request.x = 0;
3019 info->last.configure_request.y = 0;
3020 info->last.configure_request.width = -1;
3021 info->last.configure_request.height = -1;
3022 info->widget = NULL;
3024 priv->geometry_info = info;
3031 * gtk_window_set_geometry_hints:
3032 * @window: a #GtkWindow
3033 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3034 * @geometry: (allow-none): struct containing geometry information or %NULL
3035 * @geom_mask: mask indicating which struct fields should be paid attention to
3037 * This function sets up hints about how a window can be resized by
3038 * the user. You can set a minimum and maximum size; allowed resize
3039 * increments (e.g. for xterm, you can only resize by the size of a
3040 * character); aspect ratios; and more. See the #GdkGeometry struct.
3044 gtk_window_set_geometry_hints (GtkWindow *window,
3045 GtkWidget *geometry_widget,
3046 GdkGeometry *geometry,
3047 GdkWindowHints geom_mask)
3049 GtkWindowGeometryInfo *info;
3051 g_return_if_fail (GTK_IS_WINDOW (window));
3052 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3054 info = gtk_window_get_geometry_info (window, TRUE);
3057 g_signal_handlers_disconnect_by_func (info->widget,
3058 gtk_widget_destroyed,
3061 info->widget = geometry_widget;
3063 g_signal_connect (geometry_widget, "destroy",
3064 G_CALLBACK (gtk_widget_destroyed),
3068 info->geometry = *geometry;
3070 /* We store gravity in priv->gravity not in the hints. */
3071 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3073 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3075 gtk_window_set_gravity (window, geometry->win_gravity);
3078 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3082 * gtk_window_set_decorated:
3083 * @window: a #GtkWindow
3084 * @setting: %TRUE to decorate the window
3086 * By default, windows are decorated with a title bar, resize
3087 * controls, etc. Some <link linkend="gtk-X11-arch">window
3088 * managers</link> allow GTK+ to disable these decorations, creating a
3089 * borderless window. If you set the decorated property to %FALSE
3090 * using this function, GTK+ will do its best to convince the window
3091 * manager not to decorate the window. Depending on the system, this
3092 * function may not have any effect when called on a window that is
3093 * already visible, so you should call it before calling gtk_widget_show().
3095 * On Windows, this function always works, since there's no window manager
3100 gtk_window_set_decorated (GtkWindow *window,
3103 GtkWindowPrivate *priv;
3104 GdkWindow *gdk_window;
3106 g_return_if_fail (GTK_IS_WINDOW (window));
3108 priv = window->priv;
3110 setting = setting != FALSE;
3112 if (setting == priv->decorated)
3115 priv->decorated = setting;
3117 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3120 if (priv->decorated)
3121 gdk_window_set_decorations (gdk_window,
3124 gdk_window_set_decorations (gdk_window,
3128 g_object_notify (G_OBJECT (window), "decorated");
3132 * gtk_window_get_decorated:
3133 * @window: a #GtkWindow
3135 * Returns whether the window has been set to have decorations
3136 * such as a title bar via gtk_window_set_decorated().
3138 * Return value: %TRUE if the window has been set to have decorations
3141 gtk_window_get_decorated (GtkWindow *window)
3143 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3145 return window->priv->decorated;
3149 * gtk_window_set_deletable:
3150 * @window: a #GtkWindow
3151 * @setting: %TRUE to decorate the window as deletable
3153 * By default, windows have a close button in the window frame. Some
3154 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3155 * disable this button. If you set the deletable property to %FALSE
3156 * using this function, GTK+ will do its best to convince the window
3157 * manager not to show a close button. Depending on the system, this
3158 * function may not have any effect when called on a window that is
3159 * already visible, so you should call it before calling gtk_window_show().
3161 * On Windows, this function always works, since there's no window manager
3167 gtk_window_set_deletable (GtkWindow *window,
3170 GtkWindowPrivate *priv;
3171 GdkWindow *gdk_window;
3173 g_return_if_fail (GTK_IS_WINDOW (window));
3175 priv = window->priv;
3177 setting = setting != FALSE;
3179 if (setting == priv->deletable)
3182 priv->deletable = setting;
3184 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3187 if (priv->deletable)
3188 gdk_window_set_functions (gdk_window,
3191 gdk_window_set_functions (gdk_window,
3192 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3195 g_object_notify (G_OBJECT (window), "deletable");
3199 * gtk_window_get_deletable:
3200 * @window: a #GtkWindow
3202 * Returns whether the window has been set to have a close button
3203 * via gtk_window_set_deletable().
3205 * Return value: %TRUE if the window has been set to have a close button
3210 gtk_window_get_deletable (GtkWindow *window)
3212 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3214 return window->priv->deletable;
3217 static GtkWindowIconInfo*
3218 get_icon_info (GtkWindow *window)
3220 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3224 free_icon_info (GtkWindowIconInfo *info)
3226 g_free (info->icon_name);
3227 g_slice_free (GtkWindowIconInfo, info);
3231 static GtkWindowIconInfo*
3232 ensure_icon_info (GtkWindow *window)
3234 GtkWindowIconInfo *info;
3236 info = get_icon_info (window);
3240 info = g_slice_new0 (GtkWindowIconInfo);
3241 g_object_set_qdata_full (G_OBJECT (window),
3242 quark_gtk_window_icon_info,
3244 (GDestroyNotify)free_icon_info);
3251 icon_list_from_theme (GtkWidget *widget,
3256 GtkIconTheme *icon_theme;
3261 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3263 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3266 for (i = 0; sizes[i]; i++)
3269 * We need an EWMH extension to handle scalable icons
3270 * by passing their name to the WM. For now just use a
3274 icon = gtk_icon_theme_load_icon (icon_theme, name,
3277 icon = gtk_icon_theme_load_icon (icon_theme, name,
3280 list = g_list_append (list, icon);
3290 gtk_window_realize_icon (GtkWindow *window)
3292 GtkWindowPrivate *priv = window->priv;
3294 GtkWindowIconInfo *info;
3295 GdkWindow *gdk_window;
3298 widget = GTK_WIDGET (window);
3299 gdk_window = gtk_widget_get_window (widget);
3301 g_return_if_fail (gdk_window != NULL);
3303 /* no point setting an icon on override-redirect */
3304 if (priv->type == GTK_WINDOW_POPUP)
3309 info = ensure_icon_info (window);
3314 info->using_default_icon = FALSE;
3315 info->using_parent_icon = FALSE;
3316 info->using_themed_icon = FALSE;
3318 icon_list = info->icon_list;
3320 /* Look up themed icon */
3321 if (icon_list == NULL && info->icon_name)
3323 icon_list = icon_list_from_theme (widget, info->icon_name);
3325 info->using_themed_icon = TRUE;
3328 /* Inherit from transient parent */
3329 if (icon_list == NULL && priv->transient_parent)
3331 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3333 info->using_parent_icon = TRUE;
3336 /* Inherit from default */
3337 if (icon_list == NULL)
3339 icon_list = default_icon_list;
3341 info->using_default_icon = TRUE;
3344 /* Look up themed icon */
3345 if (icon_list == NULL && default_icon_name)
3347 icon_list = icon_list_from_theme (widget, default_icon_name);
3348 info->using_default_icon = TRUE;
3349 info->using_themed_icon = TRUE;
3352 info->realized = TRUE;
3354 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3356 if (info->using_themed_icon)
3358 GtkIconTheme *icon_theme;
3360 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3361 g_list_free (icon_list);
3363 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3364 g_signal_connect (icon_theme, "changed",
3365 G_CALLBACK (update_themed_icon), window);
3370 gtk_window_unrealize_icon (GtkWindow *window)
3372 GtkWindowIconInfo *info;
3374 info = get_icon_info (window);
3379 if (info->using_themed_icon)
3381 GtkIconTheme *icon_theme;
3383 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3385 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3388 /* We don't clear the properties on the window, just figure the
3389 * window is going away.
3392 info->realized = FALSE;
3397 * gtk_window_set_icon_list:
3398 * @window: a #GtkWindow
3399 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3401 * Sets up the icon representing a #GtkWindow. The icon is used when
3402 * the window is minimized (also known as iconified). Some window
3403 * managers or desktop environments may also place it in the window
3404 * frame, or display it in other contexts.
3406 * gtk_window_set_icon_list() allows you to pass in the same icon in
3407 * several hand-drawn sizes. The list should contain the natural sizes
3408 * your icon is available in; that is, don't scale the image before
3409 * passing it to GTK+. Scaling is postponed until the last minute,
3410 * when the desired final size is known, to allow best quality.
3412 * By passing several sizes, you may improve the final image quality
3413 * of the icon, by reducing or eliminating automatic image scaling.
3415 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3416 * larger images (64x64, 128x128) if you have them.
3418 * See also gtk_window_set_default_icon_list() to set the icon
3419 * for all windows in your application in one go.
3421 * Note that transient windows (those who have been set transient for another
3422 * window using gtk_window_set_transient_for()) will inherit their
3423 * icon from their transient parent. So there's no need to explicitly
3424 * set the icon on transient windows.
3427 gtk_window_set_icon_list (GtkWindow *window,
3430 GtkWindowIconInfo *info;
3432 g_return_if_fail (GTK_IS_WINDOW (window));
3434 info = ensure_icon_info (window);
3436 if (info->icon_list == list) /* check for NULL mostly */
3439 g_list_foreach (list,
3440 (GFunc) g_object_ref, NULL);
3442 g_list_foreach (info->icon_list,
3443 (GFunc) g_object_unref, NULL);
3445 g_list_free (info->icon_list);
3447 info->icon_list = g_list_copy (list);
3449 g_object_notify (G_OBJECT (window), "icon");
3451 gtk_window_unrealize_icon (window);
3453 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3454 gtk_window_realize_icon (window);
3456 /* We could try to update our transient children, but I don't think
3457 * it's really worth it. If we did it, the best way would probably
3458 * be to have children connect to notify::icon-list
3463 * gtk_window_get_icon_list:
3464 * @window: a #GtkWindow
3466 * Retrieves the list of icons set by gtk_window_set_icon_list().
3467 * The list is copied, but the reference count on each
3468 * member won't be incremented.
3470 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3473 gtk_window_get_icon_list (GtkWindow *window)
3475 GtkWindowIconInfo *info;
3477 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3479 info = get_icon_info (window);
3482 return g_list_copy (info->icon_list);
3488 * gtk_window_set_icon:
3489 * @window: a #GtkWindow
3490 * @icon: (allow-none): icon image, or %NULL
3492 * Sets up the icon representing a #GtkWindow. This icon is used when
3493 * the window is minimized (also known as iconified). Some window
3494 * managers or desktop environments may also place it in the window
3495 * frame, or display it in other contexts.
3497 * The icon should be provided in whatever size it was naturally
3498 * drawn; that is, don't scale the image before passing it to
3499 * GTK+. Scaling is postponed until the last minute, when the desired
3500 * final size is known, to allow best quality.
3502 * If you have your icon hand-drawn in multiple sizes, use
3503 * gtk_window_set_icon_list(). Then the best size will be used.
3505 * This function is equivalent to calling gtk_window_set_icon_list()
3506 * with a 1-element list.
3508 * See also gtk_window_set_default_icon_list() to set the icon
3509 * for all windows in your application in one go.
3512 gtk_window_set_icon (GtkWindow *window,
3517 g_return_if_fail (GTK_IS_WINDOW (window));
3518 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3523 list = g_list_append (list, icon);
3525 gtk_window_set_icon_list (window, list);
3531 update_themed_icon (GtkIconTheme *icon_theme,
3534 g_object_notify (G_OBJECT (window), "icon");
3536 gtk_window_unrealize_icon (window);
3538 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3539 gtk_window_realize_icon (window);
3543 * gtk_window_set_icon_name:
3544 * @window: a #GtkWindow
3545 * @name: (allow-none): the name of the themed icon
3547 * Sets the icon for the window from a named themed icon. See
3548 * the docs for #GtkIconTheme for more details.
3550 * Note that this has nothing to do with the WM_ICON_NAME
3551 * property which is mentioned in the ICCCM.
3556 gtk_window_set_icon_name (GtkWindow *window,
3559 GtkWindowIconInfo *info;
3562 g_return_if_fail (GTK_IS_WINDOW (window));
3564 info = ensure_icon_info (window);
3566 if (g_strcmp0 (info->icon_name, name) == 0)
3569 tmp = info->icon_name;
3570 info->icon_name = g_strdup (name);
3573 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3574 g_list_free (info->icon_list);
3575 info->icon_list = NULL;
3577 update_themed_icon (NULL, window);
3579 g_object_notify (G_OBJECT (window), "icon-name");
3583 * gtk_window_get_icon_name:
3584 * @window: a #GtkWindow
3586 * Returns the name of the themed icon for the window,
3587 * see gtk_window_set_icon_name().
3589 * Returns: the icon name or %NULL if the window has
3595 gtk_window_get_icon_name (GtkWindow *window)
3597 GtkWindowIconInfo *info;
3599 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3601 info = ensure_icon_info (window);
3603 return info->icon_name;
3607 * gtk_window_get_icon:
3608 * @window: a #GtkWindow
3610 * Gets the value set by gtk_window_set_icon() (or if you've
3611 * called gtk_window_set_icon_list(), gets the first icon in
3614 * Return value: (transfer none): icon for window
3617 gtk_window_get_icon (GtkWindow *window)
3619 GtkWindowIconInfo *info;
3621 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3623 info = get_icon_info (window);
3624 if (info && info->icon_list)
3625 return GDK_PIXBUF (info->icon_list->data);
3630 /* Load pixbuf, printing warning on failure if error == NULL
3633 load_pixbuf_verbosely (const char *filename,
3636 GError *local_err = NULL;
3639 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3647 g_warning ("Error loading icon from file '%s':\n\t%s",
3648 filename, local_err->message);
3649 g_error_free (local_err);
3657 * gtk_window_set_icon_from_file:
3658 * @window: a #GtkWindow
3659 * @filename: (type filename): location of icon file
3660 * @err: (allow-none): location to store error, or %NULL.
3662 * Sets the icon for @window.
3663 * Warns on failure if @err is %NULL.
3665 * This function is equivalent to calling gtk_window_set_icon()
3666 * with a pixbuf created by loading the image from @filename.
3668 * Returns: %TRUE if setting the icon succeeded.
3673 gtk_window_set_icon_from_file (GtkWindow *window,
3674 const gchar *filename,
3677 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3681 gtk_window_set_icon (window, pixbuf);
3682 g_object_unref (pixbuf);
3691 * gtk_window_set_default_icon_list:
3692 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3694 * Sets an icon list to be used as fallback for windows that haven't
3695 * had gtk_window_set_icon_list() called on them to set up a
3696 * window-specific icon list. This function allows you to set up the
3697 * icon for all windows in your app at once.
3699 * See gtk_window_set_icon_list() for more details.
3703 gtk_window_set_default_icon_list (GList *list)
3707 if (list == default_icon_list)
3710 /* Update serial so we don't used cached pixmaps/masks
3712 default_icon_serial++;
3714 g_list_foreach (list,
3715 (GFunc) g_object_ref, NULL);
3717 g_list_foreach (default_icon_list,
3718 (GFunc) g_object_unref, NULL);
3720 g_list_free (default_icon_list);
3722 default_icon_list = g_list_copy (list);
3724 /* Update all toplevels */
3725 toplevels = gtk_window_list_toplevels ();
3726 tmp_list = toplevels;
3727 while (tmp_list != NULL)
3729 GtkWindowIconInfo *info;
3730 GtkWindow *w = tmp_list->data;
3732 info = get_icon_info (w);
3733 if (info && info->using_default_icon)
3735 gtk_window_unrealize_icon (w);
3736 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3737 gtk_window_realize_icon (w);
3740 tmp_list = tmp_list->next;
3742 g_list_free (toplevels);
3746 * gtk_window_set_default_icon:
3749 * Sets an icon to be used as fallback for windows that haven't
3750 * had gtk_window_set_icon() called on them from a pixbuf.
3755 gtk_window_set_default_icon (GdkPixbuf *icon)
3759 g_return_if_fail (GDK_IS_PIXBUF (icon));
3761 list = g_list_prepend (NULL, icon);
3762 gtk_window_set_default_icon_list (list);
3767 * gtk_window_set_default_icon_name:
3768 * @name: the name of the themed icon
3770 * Sets an icon to be used as fallback for windows that haven't
3771 * had gtk_window_set_icon_list() called on them from a named
3772 * themed icon, see gtk_window_set_icon_name().
3777 gtk_window_set_default_icon_name (const gchar *name)
3782 /* Update serial so we don't used cached pixmaps/masks
3784 default_icon_serial++;
3786 g_free (default_icon_name);
3787 default_icon_name = g_strdup (name);
3789 g_list_foreach (default_icon_list,
3790 (GFunc) g_object_unref, NULL);
3792 g_list_free (default_icon_list);
3793 default_icon_list = NULL;
3795 /* Update all toplevels */
3796 toplevels = gtk_window_list_toplevels ();
3797 tmp_list = toplevels;
3798 while (tmp_list != NULL)
3800 GtkWindowIconInfo *info;
3801 GtkWindow *w = tmp_list->data;
3803 info = get_icon_info (w);
3804 if (info && info->using_default_icon && info->using_themed_icon)
3806 gtk_window_unrealize_icon (w);
3807 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3808 gtk_window_realize_icon (w);
3811 tmp_list = tmp_list->next;
3813 g_list_free (toplevels);
3817 * gtk_window_get_default_icon_name:
3819 * Returns the fallback icon name for windows that has been set
3820 * with gtk_window_set_default_icon_name(). The returned
3821 * string is owned by GTK+ and should not be modified. It
3822 * is only valid until the next call to
3823 * gtk_window_set_default_icon_name().
3825 * Returns: the fallback icon name for windows
3830 gtk_window_get_default_icon_name (void)
3832 return default_icon_name;
3836 * gtk_window_set_default_icon_from_file:
3837 * @filename: (type filename): location of icon file
3838 * @err: (allow-none): location to store error, or %NULL.
3840 * Sets an icon to be used as fallback for windows that haven't
3841 * had gtk_window_set_icon_list() called on them from a file
3842 * on disk. Warns on failure if @err is %NULL.
3844 * Returns: %TRUE if setting the icon succeeded.
3849 gtk_window_set_default_icon_from_file (const gchar *filename,
3852 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3856 gtk_window_set_default_icon (pixbuf);
3857 g_object_unref (pixbuf);
3866 * gtk_window_get_default_icon_list:
3868 * Gets the value set by gtk_window_set_default_icon_list().
3869 * The list is a copy and should be freed with g_list_free(),
3870 * but the pixbufs in the list have not had their reference count
3873 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3876 gtk_window_get_default_icon_list (void)
3878 return g_list_copy (default_icon_list);
3882 gtk_window_set_default_size_internal (GtkWindow *window,
3883 gboolean change_width,
3885 gboolean change_height,
3887 gboolean is_geometry)
3889 GtkWindowGeometryInfo *info;
3891 g_return_if_fail (change_width == FALSE || width >= -1);
3892 g_return_if_fail (change_height == FALSE || height >= -1);
3894 info = gtk_window_get_geometry_info (window, TRUE);
3896 g_object_freeze_notify (G_OBJECT (window));
3898 info->default_is_geometry = is_geometry != FALSE;
3908 info->default_width = width;
3910 g_object_notify (G_OBJECT (window), "default-width");
3921 info->default_height = height;
3923 g_object_notify (G_OBJECT (window), "default-height");
3926 g_object_thaw_notify (G_OBJECT (window));
3928 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3932 * gtk_window_set_default_size:
3933 * @window: a #GtkWindow
3934 * @width: width in pixels, or -1 to unset the default width
3935 * @height: height in pixels, or -1 to unset the default height
3937 * Sets the default size of a window. If the window's "natural" size
3938 * (its size request) is larger than the default, the default will be
3939 * ignored. More generally, if the default size does not obey the
3940 * geometry hints for the window (gtk_window_set_geometry_hints() can
3941 * be used to set these explicitly), the default size will be clamped
3942 * to the nearest permitted size.
3944 * Unlike gtk_widget_set_size_request(), which sets a size request for
3945 * a widget and thus would keep users from shrinking the window, this
3946 * function only sets the initial size, just as if the user had
3947 * resized the window themselves. Users can still shrink the window
3948 * again as they normally would. Setting a default size of -1 means to
3949 * use the "natural" default size (the size request of the window).
3951 * For more control over a window's initial size and how resizing works,
3952 * investigate gtk_window_set_geometry_hints().
3954 * For some uses, gtk_window_resize() is a more appropriate function.
3955 * gtk_window_resize() changes the current size of the window, rather
3956 * than the size to be used on initial display. gtk_window_resize() always
3957 * affects the window itself, not the geometry widget.
3959 * The default size of a window only affects the first time a window is
3960 * shown; if a window is hidden and re-shown, it will remember the size
3961 * it had prior to hiding, rather than using the default size.
3963 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3964 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3967 gtk_window_set_default_size (GtkWindow *window,
3971 g_return_if_fail (GTK_IS_WINDOW (window));
3972 g_return_if_fail (width >= -1);
3973 g_return_if_fail (height >= -1);
3975 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3979 * gtk_window_set_default_geometry:
3980 * @window: a #GtkWindow
3981 * @width: width in resize increments, or -1 to unset the default width
3982 * @height: height in resize increments, or -1 to unset the default height
3984 * Like gtk_window_set_default_size(), but @width and @height are interpreted
3985 * in terms of the base size and increment set with
3986 * gtk_window_set_geometry_hints.
3991 gtk_window_set_default_geometry (GtkWindow *window,
3995 g_return_if_fail (GTK_IS_WINDOW (window));
3996 g_return_if_fail (width >= -1);
3997 g_return_if_fail (height >= -1);
3999 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4003 * gtk_window_get_default_size:
4004 * @window: a #GtkWindow
4005 * @width: (out) (allow-none): location to store the default width, or %NULL
4006 * @height: (out) (allow-none): location to store the default height, or %NULL
4008 * Gets the default size of the window. A value of -1 for the width or
4009 * height indicates that a default size has not been explicitly set
4010 * for that dimension, so the "natural" size of the window will be
4015 gtk_window_get_default_size (GtkWindow *window,
4019 GtkWindowGeometryInfo *info;
4021 g_return_if_fail (GTK_IS_WINDOW (window));
4023 info = gtk_window_get_geometry_info (window, FALSE);
4026 *width = info ? info->default_width : -1;
4029 *height = info ? info->default_height : -1;
4033 * gtk_window_resize:
4034 * @window: a #GtkWindow
4035 * @width: width in pixels to resize the window to
4036 * @height: height in pixels to resize the window to
4038 * Resizes the window as if the user had done so, obeying geometry
4039 * constraints. The default geometry constraint is that windows may
4040 * not be smaller than their size request; to override this
4041 * constraint, call gtk_widget_set_size_request() to set the window's
4042 * request to a smaller value.
4044 * If gtk_window_resize() is called before showing a window for the
4045 * first time, it overrides any default size set with
4046 * gtk_window_set_default_size().
4048 * Windows may not be resized smaller than 1 by 1 pixels.
4052 gtk_window_resize (GtkWindow *window,
4056 GtkWindowGeometryInfo *info;
4058 g_return_if_fail (GTK_IS_WINDOW (window));
4059 g_return_if_fail (width > 0);
4060 g_return_if_fail (height > 0);
4062 info = gtk_window_get_geometry_info (window, TRUE);
4064 info->resize_width = width;
4065 info->resize_height = height;
4066 info->resize_is_geometry = FALSE;
4068 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4072 * gtk_window_resize_to_geometry:
4073 * @window: a #GtkWindow
4074 * @width: width in resize increments to resize the window to
4075 * @height: height in resize increments to resize the window to
4077 * Like gtk_window_resize(), but @width and @height are interpreted
4078 * in terms of the base size and increment set with
4079 * gtk_window_set_geometry_hints.
4084 gtk_window_resize_to_geometry (GtkWindow *window,
4088 GtkWindowGeometryInfo *info;
4090 g_return_if_fail (GTK_IS_WINDOW (window));
4091 g_return_if_fail (width > 0);
4092 g_return_if_fail (height > 0);
4094 info = gtk_window_get_geometry_info (window, TRUE);
4096 info->resize_width = width;
4097 info->resize_height = height;
4098 info->resize_is_geometry = TRUE;
4100 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4104 * gtk_window_get_size:
4105 * @window: a #GtkWindow
4106 * @width: (out) (allow-none): return location for width, or %NULL
4107 * @height: (out) (allow-none): return location for height, or %NULL
4109 * Obtains the current size of @window. If @window is not onscreen,
4110 * it returns the size GTK+ will suggest to the <link
4111 * linkend="gtk-X11-arch">window manager</link> for the initial window
4112 * size (but this is not reliably the same as the size the window
4113 * manager will actually select). The size obtained by
4114 * gtk_window_get_size() is the last size received in a
4115 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4116 * rather than querying the X server for the size. As a result, if you
4117 * call gtk_window_resize() then immediately call
4118 * gtk_window_get_size(), the size won't have taken effect yet. After
4119 * the window manager processes the resize request, GTK+ receives
4120 * notification that the size has changed via a configure event, and
4121 * the size of the window gets updated.
4123 * Note 1: Nearly any use of this function creates a race condition,
4124 * because the size of the window may change between the time that you
4125 * get the size and the time that you perform some action assuming
4126 * that size is the current size. To avoid race conditions, connect to
4127 * "configure-event" on the window and adjust your size-dependent
4128 * state to match the size delivered in the #GdkEventConfigure.
4130 * Note 2: The returned size does <emphasis>not</emphasis> include the
4131 * size of the window manager decorations (aka the window frame or
4132 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4133 * method of determining their size.
4135 * Note 3: If you are getting a window size in order to position
4136 * the window onscreen, there may be a better way. The preferred
4137 * way is to simply set the window's semantic type with
4138 * gtk_window_set_type_hint(), which allows the window manager to
4139 * e.g. center dialogs. Also, if you set the transient parent of
4140 * dialogs with gtk_window_set_transient_for() window managers
4141 * will often center the dialog over its parent window. It's
4142 * much preferred to let the window manager handle these
4143 * things rather than doing it yourself, because all apps will
4144 * behave consistently and according to user prefs if the window
4145 * manager handles it. Also, the window manager can take the size
4146 * of the window decorations/border into account, while your
4147 * application cannot.
4149 * In any case, if you insist on application-specified window
4150 * positioning, there's <emphasis>still</emphasis> a better way than
4151 * doing it yourself - gtk_window_set_position() will frequently
4152 * handle the details for you.
4156 gtk_window_get_size (GtkWindow *window,
4162 g_return_if_fail (GTK_IS_WINDOW (window));
4164 if (width == NULL && height == NULL)
4167 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4169 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4170 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4174 GdkRectangle configure_request;
4176 gtk_window_compute_configure_request (window,
4180 w = configure_request.width;
4181 h = configure_request.height;
4192 * @window: a #GtkWindow
4193 * @x: X coordinate to move window to
4194 * @y: Y coordinate to move window to
4196 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4197 * @window to the given position. Window managers are free to ignore
4198 * this; most window managers ignore requests for initial window
4199 * positions (instead using a user-defined placement algorithm) and
4200 * honor requests after the window has already been shown.
4202 * Note: the position is the position of the gravity-determined
4203 * reference point for the window. The gravity determines two things:
4204 * first, the location of the reference point in root window
4205 * coordinates; and second, which point on the window is positioned at
4206 * the reference point.
4208 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4209 * point is simply the @x, @y supplied to gtk_window_move(). The
4210 * top-left corner of the window decorations (aka window frame or
4211 * border) will be placed at @x, @y. Therefore, to position a window
4212 * at the top left of the screen, you want to use the default gravity
4213 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4215 * To position a window at the bottom right corner of the screen, you
4216 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4217 * point is at @x + the window width and @y + the window height, and
4218 * the bottom-right corner of the window border will be placed at that
4219 * reference point. So, to place a window in the bottom right corner
4220 * you would first set gravity to south east, then write:
4221 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4222 * gdk_screen_height () - window_height)</literal> (note that this
4223 * example does not take multi-head scenarios into account).
4225 * The Extended Window Manager Hints specification at <ulink
4226 * url="http://www.freedesktop.org/Standards/wm-spec">
4227 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4228 * nice table of gravities in the "implementation notes" section.
4230 * The gtk_window_get_position() documentation may also be relevant.
4233 gtk_window_move (GtkWindow *window,
4237 GtkWindowGeometryInfo *info;
4240 g_return_if_fail (GTK_IS_WINDOW (window));
4242 widget = GTK_WIDGET (window);
4244 info = gtk_window_get_geometry_info (window, TRUE);
4246 if (gtk_widget_get_mapped (widget))
4248 GtkAllocation allocation;
4250 gtk_widget_get_allocation (widget, &allocation);
4252 /* we have now sent a request with this position
4253 * with currently-active constraints, so toggle flag.
4255 info->position_constraints_changed = FALSE;
4257 /* we only constrain if mapped - if not mapped,
4258 * then gtk_window_compute_configure_request()
4259 * will apply the constraints later, and we
4260 * don't want to lose information about
4261 * what position the user set before then.
4262 * i.e. if you do a move() then turn off POS_CENTER
4263 * then show the window, your move() will work.
4265 gtk_window_constrain_position (window,
4266 allocation.width, allocation.height,
4269 /* Note that this request doesn't go through our standard request
4270 * framework, e.g. doesn't increment configure_request_count,
4271 * doesn't set info->last, etc.; that's because
4272 * we don't save the info needed to arrive at this same request
4275 * To gtk_window_move_resize(), this will end up looking exactly
4276 * the same as the position being changed by the window
4279 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4283 /* Save this position to apply on mapping */
4284 info->initial_x = x;
4285 info->initial_y = y;
4286 info->initial_pos_set = TRUE;
4291 * gtk_window_get_position:
4292 * @window: a #GtkWindow
4293 * @root_x: (out) (allow-none): eturn location for X coordinate of
4294 * gravity-determined reference point, or %NULL
4295 * @root_y: (out) (allow-none): return location for Y coordinate of
4296 * gravity-determined reference point, or %NULL
4298 * This function returns the position you need to pass to
4299 * gtk_window_move() to keep @window in its current position.
4300 * This means that the meaning of the returned value varies with
4301 * window gravity. See gtk_window_move() for more details.
4303 * If you haven't changed the window gravity, its gravity will be
4304 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4305 * gets the position of the top-left corner of the window manager
4306 * frame for the window. gtk_window_move() sets the position of this
4307 * same top-left corner.
4309 * gtk_window_get_position() is not 100% reliable because the X Window System
4310 * does not specify a way to obtain the geometry of the
4311 * decorations placed on a window by the window manager.
4312 * Thus GTK+ is using a "best guess" that works with most
4315 * Moreover, nearly all window managers are historically broken with
4316 * respect to their handling of window gravity. So moving a window to
4317 * its current position as returned by gtk_window_get_position() tends
4318 * to result in moving the window slightly. Window managers are
4319 * slowly getting better over time.
4321 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4322 * frame is not relevant, and thus gtk_window_get_position() will
4323 * always produce accurate results. However you can't use static
4324 * gravity to do things like place a window in a corner of the screen,
4325 * because static gravity ignores the window manager decorations.
4327 * If you are saving and restoring your application's window
4328 * positions, you should know that it's impossible for applications to
4329 * do this without getting it somewhat wrong because applications do
4330 * not have sufficient knowledge of window manager state. The Correct
4331 * Mechanism is to support the session management protocol (see the
4332 * "GnomeClient" object in the GNOME libraries for example) and allow
4333 * the window manager to save your window sizes and positions.
4338 gtk_window_get_position (GtkWindow *window,
4342 GtkWindowPrivate *priv;
4344 GdkWindow *gdk_window;
4346 g_return_if_fail (GTK_IS_WINDOW (window));
4348 priv = window->priv;
4349 widget = GTK_WIDGET (window);
4350 gdk_window = gtk_widget_get_window (widget);
4352 if (priv->gravity == GDK_GRAVITY_STATIC)
4354 if (gtk_widget_get_mapped (widget))
4356 /* This does a server round-trip, which is sort of wrong;
4357 * but a server round-trip is inevitable for
4358 * gdk_window_get_frame_extents() in the usual
4359 * NorthWestGravity case below, so not sure what else to
4360 * do. We should likely be consistent about whether we get
4361 * the client-side info or the server-side info.
4363 gdk_window_get_origin (gdk_window, root_x, root_y);
4367 GdkRectangle configure_request;
4369 gtk_window_compute_configure_request (window,
4373 *root_x = configure_request.x;
4374 *root_y = configure_request.y;
4379 GdkRectangle frame_extents;
4384 if (gtk_widget_get_mapped (widget))
4386 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4387 x = frame_extents.x;
4388 y = frame_extents.y;
4389 gtk_window_get_size (window, &w, &h);
4393 /* We just say the frame has 0 size on all sides.
4394 * Not sure what else to do.
4396 gtk_window_compute_configure_request (window,
4399 x = frame_extents.x;
4400 y = frame_extents.y;
4401 w = frame_extents.width;
4402 h = frame_extents.height;
4405 switch (priv->gravity)
4407 case GDK_GRAVITY_NORTH:
4408 case GDK_GRAVITY_CENTER:
4409 case GDK_GRAVITY_SOUTH:
4410 /* Find center of frame. */
4411 x += frame_extents.width / 2;
4412 /* Center client window on that point. */
4416 case GDK_GRAVITY_SOUTH_EAST:
4417 case GDK_GRAVITY_EAST:
4418 case GDK_GRAVITY_NORTH_EAST:
4419 /* Find right edge of frame */
4420 x += frame_extents.width;
4421 /* Align left edge of client at that point. */
4428 switch (priv->gravity)
4430 case GDK_GRAVITY_WEST:
4431 case GDK_GRAVITY_CENTER:
4432 case GDK_GRAVITY_EAST:
4433 /* Find center of frame. */
4434 y += frame_extents.height / 2;
4435 /* Center client window there. */
4438 case GDK_GRAVITY_SOUTH_WEST:
4439 case GDK_GRAVITY_SOUTH:
4440 case GDK_GRAVITY_SOUTH_EAST:
4441 /* Find south edge of frame */
4442 y += frame_extents.height;
4443 /* Place bottom edge of client there */
4458 * gtk_window_reshow_with_initial_size:
4459 * @window: a #GtkWindow
4461 * Hides @window, then reshows it, resetting the
4462 * default size and position of the window. Used
4463 * by GUI builders only.
4466 gtk_window_reshow_with_initial_size (GtkWindow *window)
4470 g_return_if_fail (GTK_IS_WINDOW (window));
4472 widget = GTK_WIDGET (window);
4474 gtk_widget_hide (widget);
4475 gtk_widget_unrealize (widget);
4476 gtk_widget_show (widget);
4480 gtk_window_destroy (GtkWidget *widget)
4482 GtkWindow *window = GTK_WINDOW (widget);
4483 GtkWindowPrivate *priv = window->priv;
4485 gtk_window_release_application (window);
4487 toplevel_list = g_slist_remove (toplevel_list, window);
4489 if (priv->transient_parent)
4490 gtk_window_set_transient_for (window, NULL);
4492 /* frees the icons */
4493 gtk_window_set_icon_list (window, NULL);
4495 if (priv->has_user_ref_count)
4497 priv->has_user_ref_count = FALSE;
4498 g_object_unref (window);
4502 gtk_window_group_remove_window (priv->group, window);
4504 gtk_window_free_key_hash (window);
4506 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4510 gtk_window_finalize (GObject *object)
4512 GtkWindow *window = GTK_WINDOW (object);
4513 GtkWindowPrivate *priv = window->priv;
4514 GtkMnemonicHash *mnemonic_hash;
4516 g_free (priv->title);
4517 g_free (priv->wmclass_name);
4518 g_free (priv->wmclass_class);
4519 g_free (priv->wm_role);
4520 gtk_window_release_application (window);
4522 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4524 _gtk_mnemonic_hash_free (mnemonic_hash);
4526 if (priv->geometry_info)
4528 if (priv->geometry_info->widget)
4529 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4530 gtk_widget_destroyed,
4531 &priv->geometry_info->widget);
4532 g_free (priv->geometry_info);
4535 if (priv->keys_changed_handler)
4537 g_source_remove (priv->keys_changed_handler);
4538 priv->keys_changed_handler = 0;
4542 g_signal_handlers_disconnect_by_func (priv->screen,
4543 gtk_window_on_composited_changed, window);
4545 g_free (priv->startup_id);
4547 #ifdef GDK_WINDOWING_X11
4548 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4549 gtk_window_on_theme_variant_changed,
4553 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4557 gtk_window_show (GtkWidget *widget)
4559 GtkWindow *window = GTK_WINDOW (widget);
4560 GtkWindowPrivate *priv = window->priv;
4561 GtkContainer *container = GTK_CONTAINER (window);
4562 gboolean need_resize;
4565 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4567 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4571 _gtk_widget_set_visible_flag (widget, TRUE);
4573 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4574 _gtk_container_set_need_resize (container, FALSE);
4578 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4579 GtkAllocation allocation = { 0, 0 };
4580 GdkRectangle configure_request;
4581 GdkGeometry new_geometry;
4583 gboolean was_realized;
4585 /* We are going to go ahead and perform this configure request
4586 * and then emulate a configure notify by going ahead and
4587 * doing a size allocate. Sort of a synchronous
4588 * mini-copy of gtk_window_move_resize() here.
4590 gtk_window_compute_configure_request (window,
4595 /* We update this because we are going to go ahead
4596 * and gdk_window_resize() below, rather than
4599 info->last.configure_request.width = configure_request.width;
4600 info->last.configure_request.height = configure_request.height;
4602 /* and allocate the window - this is normally done
4603 * in move_resize in response to configure notify
4605 allocation.width = configure_request.width;
4606 allocation.height = configure_request.height;
4607 gtk_widget_size_allocate (widget, &allocation);
4609 /* Then we guarantee we have a realize */
4610 was_realized = FALSE;
4611 if (!gtk_widget_get_realized (widget))
4613 gtk_widget_realize (widget);
4614 was_realized = TRUE;
4617 /* We only send configure request if we didn't just finish
4618 * creating the window; if we just created the window
4619 * then we created it with widget->allocation anyhow.
4622 gdk_window_move_resize (gtk_widget_get_window (widget),
4623 configure_request.x,
4624 configure_request.y,
4625 configure_request.width,
4626 configure_request.height);
4629 gtk_container_check_resize (container);
4631 gtk_widget_map (widget);
4633 /* Try to make sure that we have some focused widget
4635 #ifdef GDK_WINDOWING_X11
4636 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4637 GTK_IS_PLUG (window);
4641 if (!priv->focus_widget && !is_plug)
4642 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4645 gtk_grab_add (widget);
4649 gtk_window_hide (GtkWidget *widget)
4651 GtkWindow *window = GTK_WINDOW (widget);
4652 GtkWindowPrivate *priv = window->priv;
4654 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4656 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4660 _gtk_widget_set_visible_flag (widget, FALSE);
4661 gtk_widget_unmap (widget);
4664 gtk_grab_remove (widget);
4668 gtk_window_map (GtkWidget *widget)
4671 GtkWindow *window = GTK_WINDOW (widget);
4672 GtkWindowPrivate *priv = window->priv;
4673 GdkWindow *toplevel;
4674 GdkWindow *gdk_window;
4675 gboolean auto_mnemonics;
4677 gdk_window = gtk_widget_get_window (widget);
4679 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4681 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4685 gtk_widget_set_mapped (widget, TRUE);
4687 child = gtk_bin_get_child (&(window->bin));
4689 gtk_widget_get_visible (child) &&
4690 !gtk_widget_get_mapped (child))
4691 gtk_widget_map (child);
4693 toplevel = gdk_window;
4695 if (priv->maximize_initially)
4696 gdk_window_maximize (toplevel);
4698 gdk_window_unmaximize (toplevel);
4700 if (priv->stick_initially)
4701 gdk_window_stick (toplevel);
4703 gdk_window_unstick (toplevel);
4705 if (priv->iconify_initially)
4706 gdk_window_iconify (toplevel);
4708 gdk_window_deiconify (toplevel);
4710 if (priv->fullscreen_initially)
4711 gdk_window_fullscreen (toplevel);
4713 gdk_window_unfullscreen (toplevel);
4715 gdk_window_set_keep_above (toplevel, priv->above_initially);
4717 gdk_window_set_keep_below (toplevel, priv->below_initially);
4719 if (priv->type == GTK_WINDOW_TOPLEVEL)
4720 gtk_window_set_theme_variant (window);
4722 /* No longer use the default settings */
4723 priv->need_default_size = FALSE;
4724 priv->need_default_position = FALSE;
4726 if (priv->reset_type_hint)
4728 /* We should only reset the type hint when the application
4729 * used gtk_window_set_type_hint() to change the hint.
4730 * Some applications use X directly to change the properties;
4731 * in that case, we shouldn't overwrite what they did.
4733 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4734 priv->reset_type_hint = FALSE;
4737 gdk_window_show (gdk_window);
4739 if (priv->grip_window)
4740 gdk_window_show (priv->grip_window);
4742 if (!disable_startup_notification)
4744 /* Do we have a custom startup-notification id? */
4745 if (priv->startup_id != NULL)
4747 /* Make sure we have a "real" id */
4748 if (!startup_id_is_fake (priv->startup_id))
4749 gdk_notify_startup_complete_with_id (priv->startup_id);
4751 g_free (priv->startup_id);
4752 priv->startup_id = NULL;
4754 else if (!sent_startup_notification)
4756 sent_startup_notification = TRUE;
4757 gdk_notify_startup_complete ();
4761 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4762 * (as in the case of popup menus), then hide mnemonics initially
4764 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4765 &auto_mnemonics, NULL);
4766 if (auto_mnemonics && !priv->mnemonics_visible_set)
4767 gtk_window_set_mnemonics_visible (window, FALSE);
4771 gtk_window_map_event (GtkWidget *widget,
4774 if (!gtk_widget_get_mapped (widget))
4776 /* we should be be unmapped, but are getting a MapEvent, this may happen
4777 * to toplevel XWindows if mapping was intercepted by a window manager
4778 * and an unmap request occoured while the MapRequestEvent was still
4779 * being handled. we work around this situaiton here by re-requesting
4780 * the window being unmapped. more details can be found in:
4781 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4783 gdk_window_hide (gtk_widget_get_window (widget));
4789 gtk_window_unmap (GtkWidget *widget)
4791 GtkWindow *window = GTK_WINDOW (widget);
4792 GtkWindowPrivate *priv = window->priv;
4794 GtkWindowGeometryInfo *info;
4795 GdkWindow *gdk_window;
4796 GdkWindowState state;
4798 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4800 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
4804 gdk_window = gtk_widget_get_window (widget);
4806 gtk_widget_set_mapped (widget, FALSE);
4807 gdk_window_withdraw (gdk_window);
4809 priv->configure_request_count = 0;
4810 priv->configure_notify_received = FALSE;
4812 /* on unmap, we reset the default positioning of the window,
4813 * so it's placed again, but we don't reset the default
4814 * size of the window, so it's remembered.
4816 priv->need_default_position = TRUE;
4818 info = gtk_window_get_geometry_info (window, FALSE);
4821 info->initial_pos_set = FALSE;
4822 info->position_constraints_changed = FALSE;
4825 state = gdk_window_get_state (gdk_window);
4826 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4827 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4828 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4829 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4830 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4832 child = gtk_bin_get_child (&(window->bin));
4834 gtk_widget_unmap (child);
4837 /* (Note: Replace "size" with "width" or "height". Also, the request
4838 * mode is honoured.)
4839 * For selecting the default window size, the following conditions
4840 * should hold (in order of importance):
4841 * - the size is not below the minimum size
4842 * Windows cannot be resized below their minimum size, so we must
4843 * ensure we don't do that either.
4844 * - the size is not above the natural size
4845 * It seems weird to allocate more than this in an initial guess.
4846 * - the size does not exceed that of a maximized window
4847 * We want to see the whole window after all.
4848 * (Note that this may not be possible to achieve due to imperfect
4849 * information from the windowing system.)
4852 /* We use these for now to not make windows too big by accident. Note
4853 * that we still clamp these numbers by screen size. Also note that
4854 * minimum size still overrides this. So keep your windows small! :)
4856 #define MAX_DEFAULT_WINDOW_WIDTH 640
4857 #define MAX_DEFAULT_WINDOW_HEIGHT 480
4860 gtk_window_guess_default_size (GtkWindow *window,
4864 GtkWidget *widget = GTK_WIDGET (window);
4866 int minimum, natural;
4868 screen = gtk_widget_get_screen (widget);
4870 *width = gdk_screen_get_width (screen);
4871 *height = gdk_screen_get_height (screen);
4873 if (*width >= *height)
4876 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
4877 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
4882 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
4883 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
4886 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
4888 gtk_widget_get_preferred_height (widget, &minimum, &natural);
4889 *height = MAX (minimum, MIN (*height, natural));
4891 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
4892 *width = MAX (minimum, MIN (*width, natural));
4894 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
4896 gtk_widget_get_preferred_width (widget, &minimum, &natural);
4897 *width = MAX (minimum, MIN (*width, natural));
4899 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
4900 *height = MAX (minimum, MIN (*height, natural));
4905 gtk_window_realize (GtkWidget *widget)
4907 GtkAllocation allocation;
4909 GdkWindow *parent_window;
4910 GdkWindow *gdk_window;
4911 GdkWindowAttr attributes;
4912 gint attributes_mask;
4913 GtkWindowPrivate *priv;
4914 GtkStyleContext *context;
4916 window = GTK_WINDOW (widget);
4917 priv = window->priv;
4919 gtk_widget_get_allocation (widget, &allocation);
4921 if (gtk_widget_get_parent_window (widget))
4923 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
4925 gtk_widget_set_realized (widget, TRUE);
4927 attributes.x = allocation.x;
4928 attributes.y = allocation.y;
4929 attributes.width = allocation.width;
4930 attributes.height = allocation.height;
4931 attributes.window_type = GDK_WINDOW_CHILD;
4933 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
4935 attributes.visual = gtk_widget_get_visual (widget);
4936 attributes.wclass = GDK_INPUT_OUTPUT;
4938 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
4940 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
4941 &attributes, attributes_mask);
4942 gtk_widget_set_window (widget, gdk_window);
4943 gdk_window_set_user_data (gdk_window, widget);
4945 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
4947 gdk_window_enable_synchronized_configure (gdk_window);
4951 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
4953 /* ensure widget tree is properly size allocated */
4954 if (allocation.x == -1 &&
4955 allocation.y == -1 &&
4956 allocation.width == 1 &&
4957 allocation.height == 1)
4963 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
4964 if (allocation.width == 0 || allocation.height == 0)
4966 /* non-empty window */
4967 allocation.width = 200;
4968 allocation.height = 200;
4970 gtk_widget_size_allocate (widget, &allocation);
4972 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4974 g_return_if_fail (!gtk_widget_get_realized (widget));
4977 gtk_widget_set_realized (widget, TRUE);
4981 case GTK_WINDOW_TOPLEVEL:
4982 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4984 case GTK_WINDOW_POPUP:
4985 attributes.window_type = GDK_WINDOW_TEMP;
4988 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4992 attributes.title = priv->title;
4993 attributes.wmclass_name = priv->wmclass_name;
4994 attributes.wmclass_class = priv->wmclass_class;
4995 attributes.wclass = GDK_INPUT_OUTPUT;
4996 attributes.visual = gtk_widget_get_visual (widget);
4998 attributes_mask = 0;
4999 parent_window = gtk_widget_get_root_window (widget);
5001 gtk_widget_get_allocation (widget, &allocation);
5002 attributes.width = allocation.width;
5003 attributes.height = allocation.height;
5004 attributes.event_mask = gtk_widget_get_events (widget);
5005 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5006 GDK_KEY_PRESS_MASK |
5007 GDK_KEY_RELEASE_MASK |
5008 GDK_ENTER_NOTIFY_MASK |
5009 GDK_LEAVE_NOTIFY_MASK |
5010 GDK_FOCUS_CHANGE_MASK |
5011 GDK_STRUCTURE_MASK);
5012 attributes.type_hint = priv->type_hint;
5014 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5015 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5016 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5018 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5019 gtk_widget_set_window (widget, gdk_window);
5021 if (priv->opacity_set)
5022 gdk_window_set_opacity (gdk_window, priv->opacity);
5024 gdk_window_enable_synchronized_configure (gdk_window);
5026 gdk_window_set_user_data (gdk_window, window);
5028 context = gtk_widget_get_style_context (widget);
5029 gtk_style_context_set_background (context, gdk_window);
5032 if (priv->transient_parent &&
5033 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5034 gdk_window_set_transient_for (gdk_window,
5035 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5038 gdk_window_set_role (gdk_window, priv->wm_role);
5040 if (!priv->decorated)
5041 gdk_window_set_decorations (gdk_window, 0);
5043 if (!priv->deletable)
5044 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5046 if (gtk_window_get_skip_pager_hint (window))
5047 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5049 if (gtk_window_get_skip_taskbar_hint (window))
5050 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5052 if (gtk_window_get_accept_focus (window))
5053 gdk_window_set_accept_focus (gdk_window, TRUE);
5055 gdk_window_set_accept_focus (gdk_window, FALSE);
5057 if (gtk_window_get_focus_on_map (window))
5058 gdk_window_set_focus_on_map (gdk_window, TRUE);
5060 gdk_window_set_focus_on_map (gdk_window, FALSE);
5063 gdk_window_set_modal_hint (gdk_window, TRUE);
5065 gdk_window_set_modal_hint (gdk_window, FALSE);
5067 if (priv->startup_id)
5069 #ifdef GDK_WINDOWING_X11
5070 if (GDK_IS_X11_WINDOW (gdk_window))
5072 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5073 if (timestamp != GDK_CURRENT_TIME)
5074 gdk_x11_window_set_user_time (gdk_window, timestamp);
5077 if (!startup_id_is_fake (priv->startup_id))
5078 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5081 #ifdef GDK_WINDOWING_X11
5082 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5084 if (GDK_IS_X11_WINDOW (gdk_window))
5085 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5090 gtk_window_realize_icon (window);
5092 if (priv->has_resize_grip)
5093 resize_grip_create_window (window);
5097 gtk_window_unrealize (GtkWidget *widget)
5099 GtkWindow *window = GTK_WINDOW (widget);
5100 GtkWindowPrivate *priv = window->priv;
5101 GtkWindowGeometryInfo *info;
5103 /* On unrealize, we reset the size of the window such
5104 * that we will re-apply the default sizing stuff
5105 * next time we show the window.
5107 * Default positioning is reset on unmap, instead of unrealize.
5109 priv->need_default_size = TRUE;
5110 info = gtk_window_get_geometry_info (window, FALSE);
5113 info->resize_width = -1;
5114 info->resize_height = -1;
5115 info->last.configure_request.x = 0;
5116 info->last.configure_request.y = 0;
5117 info->last.configure_request.width = -1;
5118 info->last.configure_request.height = -1;
5119 /* be sure we reset geom hints on re-realize */
5120 info->last.flags = 0;
5124 gtk_window_unrealize_icon (window);
5126 if (priv->grip_window != NULL)
5127 resize_grip_destroy_window (window);
5129 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5132 static GtkJunctionSides
5133 get_grip_junction (GtkWidget *widget)
5135 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5136 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5138 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5142 get_drag_edge (GtkWidget *widget,
5143 GdkWindowEdge *edge)
5145 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5146 gboolean hresizable;
5147 gboolean vresizable;
5148 GtkTextDirection dir;
5149 GtkWindowGeometryInfo *info;
5154 info = priv->geometry_info;
5157 GdkWindowHints flags = info->last.flags;
5158 GdkGeometry *geometry = &info->last.geometry;
5160 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5162 hresizable = geometry->min_width < geometry->max_width;
5163 vresizable = geometry->min_height < geometry->max_height;
5167 dir = gtk_widget_get_direction (widget);
5169 if (hresizable && vresizable)
5170 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5171 else if (hresizable)
5172 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5173 else if (vresizable)
5174 *edge = GDK_WINDOW_EDGE_SOUTH;
5182 set_grip_cursor (GtkWindow *window)
5184 GtkWidget *widget = GTK_WIDGET (window);
5185 GtkWindowPrivate *priv = window->priv;
5187 if (priv->grip_window == NULL)
5190 if (gtk_widget_is_sensitive (widget))
5193 GdkDisplay *display;
5194 GdkCursorType cursor_type;
5197 cursor_type = GDK_LEFT_PTR;
5199 if (get_drag_edge (widget, &edge))
5203 case GDK_WINDOW_EDGE_EAST:
5204 cursor_type = GDK_RIGHT_SIDE;
5206 case GDK_WINDOW_EDGE_SOUTH_EAST:
5207 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5209 case GDK_WINDOW_EDGE_SOUTH:
5210 cursor_type = GDK_BOTTOM_SIDE;
5212 case GDK_WINDOW_EDGE_SOUTH_WEST:
5213 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5215 case GDK_WINDOW_EDGE_WEST:
5216 cursor_type = GDK_LEFT_SIDE;
5222 display = gtk_widget_get_display (widget);
5223 cursor = gdk_cursor_new_for_display (display, cursor_type);
5224 gdk_window_set_cursor (priv->grip_window, cursor);
5225 g_object_unref (cursor);
5228 gdk_window_set_cursor (priv->grip_window, NULL);
5232 set_grip_shape (GtkWindow *window)
5234 GtkWindowPrivate *priv = window->priv;
5235 cairo_region_t *region;
5236 cairo_surface_t *surface;
5238 double width, height;
5240 if (priv->grip_window == NULL)
5243 width = gdk_window_get_width (priv->grip_window);
5244 height = gdk_window_get_height (priv->grip_window);
5245 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5247 cr = cairo_create (surface);
5248 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5250 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5251 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5253 cairo_move_to (cr, width, 0.0);
5254 cairo_line_to (cr, width, height);
5255 cairo_line_to (cr, 0.0, height);
5259 cairo_move_to (cr, 0.0, 0.0);
5260 cairo_line_to (cr, width, height);
5261 cairo_line_to (cr, 0.0, height);
5263 cairo_close_path (cr);
5266 region = gdk_cairo_region_create_from_surface (surface);
5267 cairo_surface_destroy (surface);
5269 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5270 cairo_region_destroy (region);
5274 set_grip_position (GtkWindow *window)
5276 GtkWindowPrivate *priv = window->priv;
5279 if (priv->grip_window == NULL)
5282 gtk_window_get_resize_grip_area (window, &rect);
5283 gdk_window_raise (priv->grip_window);
5284 gdk_window_move_resize (priv->grip_window,
5286 rect.width, rect.height);
5290 gtk_window_size_allocate (GtkWidget *widget,
5291 GtkAllocation *allocation)
5293 GtkWindow *window = GTK_WINDOW (widget);
5294 GtkAllocation child_allocation;
5298 gtk_widget_set_allocation (widget, allocation);
5300 if (gtk_widget_get_realized (widget))
5302 /* If it's not a toplevel we're embedded, we need to resize the window's
5303 * window and skip the grip.
5305 if (!gtk_widget_is_toplevel (widget))
5307 gdk_window_move_resize (gtk_widget_get_window (widget),
5308 allocation->x, allocation->y,
5309 allocation->width, allocation->height);
5313 update_grip_visibility (window);
5314 set_grip_position (window);
5318 child = gtk_bin_get_child (&(window->bin));
5319 if (child && gtk_widget_get_visible (child))
5321 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5322 child_allocation.x = border_width;
5323 child_allocation.y = border_width;
5324 child_allocation.width =
5325 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5326 child_allocation.height =
5327 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5329 gtk_widget_size_allocate (child, &child_allocation);
5334 gtk_window_configure_event (GtkWidget *widget,
5335 GdkEventConfigure *event)
5337 GtkAllocation allocation;
5338 GtkWindow *window = GTK_WINDOW (widget);
5339 GtkWindowPrivate *priv = window->priv;
5340 gboolean expected_reply = priv->configure_request_count > 0;
5342 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5344 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5345 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5347 gdk_window_configure_finished (gtk_widget_get_window (widget));
5351 /* priv->configure_request_count incremented for each
5352 * configure request, and decremented to a min of 0 for
5353 * each configure notify.
5355 * All it means is that we know we will get at least
5356 * priv->configure_request_count more configure notifies.
5357 * We could get more configure notifies than that; some
5358 * of the configure notifies we get may be unrelated to
5359 * the configure requests. But we will get at least
5360 * priv->configure_request_count notifies.
5363 if (priv->configure_request_count > 0)
5365 priv->configure_request_count -= 1;
5366 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5369 /* As an optimization, we avoid a resize when possible.
5371 * The only times we can avoid a resize are:
5372 * - we know only the position changed, not the size
5373 * - we know we have made more requests and so will get more
5374 * notifies and can wait to resize when we get them
5376 gtk_widget_get_allocation (widget, &allocation);
5377 if (!expected_reply &&
5378 (allocation.width == event->width &&
5379 allocation.height == event->height))
5381 gdk_window_configure_finished (gtk_widget_get_window (widget));
5386 * If we do need to resize, we do that by:
5387 * - filling in widget->allocation with the new size
5388 * - setting configure_notify_received to TRUE
5389 * for use in gtk_window_move_resize()
5390 * - queueing a resize, leading to invocation of
5391 * gtk_window_move_resize() in an idle handler
5395 priv->configure_notify_received = TRUE;
5397 allocation.width = event->width;
5398 allocation.height = event->height;
5399 gtk_widget_set_allocation (widget, &allocation);
5401 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5403 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5409 gtk_window_state_event (GtkWidget *widget,
5410 GdkEventWindowState *event)
5412 update_grip_visibility (GTK_WINDOW (widget));
5418 gtk_window_direction_changed (GtkWidget *widget,
5419 GtkTextDirection prev_dir)
5421 GtkWindow *window = GTK_WINDOW (widget);
5423 set_grip_cursor (window);
5424 set_grip_position (window);
5425 set_grip_shape (window);
5429 gtk_window_state_changed (GtkWidget *widget,
5430 GtkStateType previous_state)
5432 GtkWindow *window = GTK_WINDOW (widget);
5434 update_grip_visibility (window);
5438 gtk_window_style_updated (GtkWidget *widget)
5440 GtkWindow *window = GTK_WINDOW (widget);
5441 GtkWindowPrivate *priv = window->priv;
5444 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5446 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5448 gdk_window_move_resize (priv->grip_window,
5450 rect.width, rect.height);
5452 set_grip_shape (window);
5453 gtk_widget_queue_resize (widget);
5458 resize_grip_create_window (GtkWindow *window)
5461 GtkWindowPrivate *priv;
5462 GdkWindowAttr attributes;
5463 gint attributes_mask;
5466 priv = window->priv;
5467 widget = GTK_WIDGET (window);
5469 g_return_if_fail (gtk_widget_get_realized (widget));
5470 g_return_if_fail (priv->grip_window == NULL);
5472 gtk_window_get_resize_grip_area (window, &rect);
5474 attributes.x = rect.x;
5475 attributes.y = rect.y;
5476 attributes.width = rect.width;
5477 attributes.height = rect.height;
5478 attributes.window_type = GDK_WINDOW_CHILD;
5479 attributes.wclass = GDK_INPUT_OUTPUT;
5480 attributes.event_mask = gtk_widget_get_events (widget) |
5482 GDK_BUTTON_PRESS_MASK;
5484 attributes_mask = GDK_WA_X | GDK_WA_Y;
5486 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5490 gdk_window_set_user_data (priv->grip_window, widget);
5492 gdk_window_raise (priv->grip_window);
5494 set_grip_shape (window);
5495 update_grip_visibility (window);
5499 resize_grip_destroy_window (GtkWindow *window)
5501 GtkWindowPrivate *priv = window->priv;
5503 gdk_window_set_user_data (priv->grip_window, NULL);
5504 gdk_window_destroy (priv->grip_window);
5505 priv->grip_window = NULL;
5506 update_grip_visibility (window);
5510 * gtk_window_set_has_resize_grip:
5511 * @window: a #GtkWindow
5512 * @value: %TRUE to allow a resize grip
5514 * Sets whether @window has a corner resize grip.
5516 * Note that the resize grip is only shown if the window
5517 * is actually resizable and not maximized. Use
5518 * gtk_window_resize_grip_is_visible() to find out if the
5519 * resize grip is currently shown.
5524 gtk_window_set_has_resize_grip (GtkWindow *window,
5527 GtkWidget *widget = GTK_WIDGET (window);
5528 GtkWindowPrivate *priv = window->priv;
5530 value = value != FALSE;
5532 if (value != priv->has_resize_grip)
5534 priv->has_resize_grip = value;
5535 gtk_widget_queue_draw (widget);
5537 if (gtk_widget_get_realized (widget) &&
5538 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5540 if (priv->has_resize_grip && priv->grip_window == NULL)
5541 resize_grip_create_window (window);
5542 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5543 resize_grip_destroy_window (window);
5546 g_object_notify (G_OBJECT (window), "has-resize-grip");
5551 update_grip_visibility (GtkWindow *window)
5553 GtkWindowPrivate *priv = window->priv;
5556 val = gtk_window_resize_grip_is_visible (window);
5558 if (priv->grip_window != NULL)
5562 gdk_window_show (priv->grip_window);
5563 set_grip_cursor (window);
5567 gdk_window_hide (priv->grip_window);
5571 if (priv->resize_grip_visible != val)
5573 priv->resize_grip_visible = val;
5575 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5580 * gtk_window_resize_grip_is_visible:
5581 * @window: a #GtkWindow
5583 * Determines whether a resize grip is visible for the specified window.
5585 * Returns: %TRUE if a resize grip exists and is visible
5590 gtk_window_resize_grip_is_visible (GtkWindow *window)
5593 GtkWindowPrivate *priv;
5596 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5598 priv = window->priv;
5599 widget = GTK_WIDGET (window);
5601 if (priv->type == GTK_WINDOW_POPUP)
5604 if (!priv->resizable)
5607 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5610 if (gtk_widget_get_realized (widget))
5612 GdkWindowState state;
5614 state = gdk_window_get_state (gtk_widget_get_window (widget));
5616 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5620 if (!get_drag_edge (widget, &edge))
5623 return window->priv->has_resize_grip;
5627 * gtk_window_get_has_resize_grip:
5628 * @window: a #GtkWindow
5630 * Determines whether the window may have a resize grip.
5632 * Returns: %TRUE if the window has a resize grip
5637 gtk_window_get_has_resize_grip (GtkWindow *window)
5639 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5641 return window->priv->has_resize_grip;
5645 * gtk_window_get_resize_grip_area:
5646 * @window: a #GtkWindow
5647 * @rect: (out): a pointer to a #GdkRectangle which we should store
5648 * the resize grip area
5650 * If a window has a resize grip, this will retrieve the grip
5651 * position, width and height into the specified #GdkRectangle.
5653 * Returns: %TRUE if the resize grip's area was retrieved
5658 gtk_window_get_resize_grip_area (GtkWindow *window,
5661 GtkWidget *widget = GTK_WIDGET (window);
5662 GtkAllocation allocation;
5666 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5668 if (!window->priv->has_resize_grip)
5671 gtk_widget_get_allocation (widget, &allocation);
5673 gtk_widget_style_get (widget,
5674 "resize-grip-width", &grip_width,
5675 "resize-grip-height", &grip_height,
5678 if (grip_width > allocation.width)
5679 grip_width = allocation.width;
5681 if (grip_height > allocation.height)
5682 grip_height = allocation.height;
5684 rect->width = grip_width;
5685 rect->height = grip_height;
5686 rect->y = allocation.y + allocation.height - grip_height;
5688 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5689 rect->x = allocation.x + allocation.width - grip_width;
5691 rect->x = allocation.x;
5696 /* the accel_key and accel_mods fields of the key have to be setup
5697 * upon calling this function. it'll then return whether that key
5698 * is at all used as accelerator, and if so will OR in the
5699 * accel_flags member of the key.
5702 _gtk_window_query_nonaccels (GtkWindow *window,
5704 GdkModifierType accel_mods)
5706 GtkWindowPrivate *priv;
5708 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5710 priv = window->priv;
5712 /* movement keys are considered locked accels */
5715 static const guint bindings[] = {
5716 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,
5717 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,
5721 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5722 if (bindings[i] == accel_key)
5726 /* mnemonics are considered locked accels */
5727 if (accel_mods == priv->mnemonic_modifier)
5729 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5730 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5738 * gtk_window_propagate_key_event:
5739 * @window: a #GtkWindow
5740 * @event: a #GdkEventKey
5742 * Propagate a key press or release event to the focus widget and
5743 * up the focus container chain until a widget handles @event.
5744 * This is normally called by the default ::key_press_event and
5745 * ::key_release_event handlers for toplevel windows,
5746 * however in some cases it may be useful to call this directly when
5747 * overriding the standard key handling for a toplevel window.
5749 * Return value: %TRUE if a widget in the focus chain handled the event.
5754 gtk_window_propagate_key_event (GtkWindow *window,
5757 GtkWindowPrivate *priv;
5758 gboolean handled = FALSE;
5759 GtkWidget *widget, *focus;
5761 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5763 priv = window->priv;
5764 widget = GTK_WIDGET (window);
5766 focus = priv->focus_widget;
5768 g_object_ref (focus);
5771 focus && focus != widget &&
5772 gtk_widget_get_toplevel (focus) == widget)
5776 if (gtk_widget_is_sensitive (focus))
5777 handled = gtk_widget_event (focus, (GdkEvent*) event);
5779 parent = gtk_widget_get_parent (focus);
5781 g_object_ref (parent);
5783 g_object_unref (focus);
5789 g_object_unref (focus);
5795 gtk_window_key_press_event (GtkWidget *widget,
5798 GtkWindow *window = GTK_WINDOW (widget);
5799 gboolean handled = FALSE;
5801 /* handle mnemonics and accelerators */
5803 handled = gtk_window_activate_key (window, event);
5805 /* handle focus widget key events */
5807 handled = gtk_window_propagate_key_event (window, event);
5809 /* Chain up, invokes binding set */
5811 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5817 gtk_window_key_release_event (GtkWidget *widget,
5820 GtkWindow *window = GTK_WINDOW (widget);
5821 gboolean handled = FALSE;
5823 /* handle focus widget key events */
5825 handled = gtk_window_propagate_key_event (window, event);
5827 /* Chain up, invokes binding set */
5829 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5835 gtk_window_button_press_event (GtkWidget *widget,
5836 GdkEventButton *event)
5838 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5841 if (event->window == priv->grip_window)
5843 if (get_drag_edge (widget, &edge))
5844 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5858 gtk_window_real_activate_default (GtkWindow *window)
5860 gtk_window_activate_default (window);
5864 gtk_window_real_activate_focus (GtkWindow *window)
5866 gtk_window_activate_focus (window);
5870 gtk_window_enter_notify_event (GtkWidget *widget,
5871 GdkEventCrossing *event)
5877 gtk_window_leave_notify_event (GtkWidget *widget,
5878 GdkEventCrossing *event)
5884 do_focus_change (GtkWidget *widget,
5888 GdkDeviceManager *device_manager;
5891 g_object_ref (widget);
5893 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5894 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5895 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5896 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5898 for (d = devices; d; d = d->next)
5900 GdkDevice *dev = d->data;
5903 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5906 /* Skip non-master keyboards that haven't
5907 * selected for events from this window
5909 window = gtk_widget_get_window (widget);
5910 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5911 window && !gdk_window_get_device_events (window, dev))
5914 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5916 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5917 fevent->focus_change.window = window;
5919 g_object_ref (window);
5920 fevent->focus_change.in = in;
5921 gdk_event_set_device (fevent, dev);
5923 gtk_widget_send_focus_change (widget, fevent);
5925 gdk_event_free (fevent);
5928 g_list_free (devices);
5929 g_object_unref (widget);
5933 maybe_set_mnemonics_visible (GtkWindow *window)
5936 GdkDeviceManager *device_manager;
5938 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
5939 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5941 for (d = devices; d; d = d->next)
5943 GdkDevice *dev = d->data;
5945 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
5947 GdkModifierType mask;
5949 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
5951 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
5953 gtk_window_set_mnemonics_visible (window, TRUE);
5959 g_list_free (devices);
5963 gtk_window_focus_in_event (GtkWidget *widget,
5964 GdkEventFocus *event)
5966 GtkWindow *window = GTK_WINDOW (widget);
5967 gboolean auto_mnemonics;
5969 /* It appears spurious focus in events can occur when
5970 * the window is hidden. So we'll just check to see if
5971 * the window is visible before actually handling the
5974 if (gtk_widget_get_visible (widget))
5976 _gtk_window_set_has_toplevel_focus (window, TRUE);
5977 _gtk_window_set_is_active (window, TRUE);
5979 g_object_get (gtk_widget_get_settings (widget),
5980 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5982 maybe_set_mnemonics_visible (window);
5989 gtk_window_focus_out_event (GtkWidget *widget,
5990 GdkEventFocus *event)
5992 GtkWindow *window = GTK_WINDOW (widget);
5993 gboolean auto_mnemonics;
5995 _gtk_window_set_has_toplevel_focus (window, FALSE);
5996 _gtk_window_set_is_active (window, FALSE);
5998 /* set the mnemonic-visible property to false */
5999 g_object_get (gtk_widget_get_settings (widget),
6000 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6002 gtk_window_set_mnemonics_visible (window, FALSE);
6008 gtk_window_check_resize (GtkContainer *container)
6010 /* If the window is not toplevel anymore than it's embedded somewhere,
6011 * so handle it like a normal window */
6012 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6013 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6014 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6015 gtk_window_move_resize (GTK_WINDOW (container));
6019 gtk_window_focus (GtkWidget *widget,
6020 GtkDirectionType direction)
6022 GtkWindowPrivate *priv;
6025 GtkContainer *container;
6027 GtkWidget *old_focus_child;
6030 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6031 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6033 container = GTK_CONTAINER (widget);
6034 window = GTK_WINDOW (widget);
6035 priv = window->priv;
6036 bin = GTK_BIN (widget);
6038 old_focus_child = gtk_container_get_focus_child (container);
6040 /* We need a special implementation here to deal properly with wrapping
6041 * around in the tab chain without the danger of going into an
6044 if (old_focus_child)
6046 if (gtk_widget_child_focus (old_focus_child, direction))
6050 if (priv->focus_widget)
6052 if (direction == GTK_DIR_LEFT ||
6053 direction == GTK_DIR_RIGHT ||
6054 direction == GTK_DIR_UP ||
6055 direction == GTK_DIR_DOWN)
6060 /* Wrapped off the end, clear the focus setting for the toplpevel */
6061 parent = gtk_widget_get_parent (priv->focus_widget);
6064 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6065 parent = gtk_widget_get_parent (parent);
6068 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6071 /* Now try to focus the first widget in the window */
6072 child = gtk_bin_get_child (bin);
6075 if (gtk_widget_child_focus (child, direction))
6083 gtk_window_move_focus (GtkWidget *widget,
6084 GtkDirectionType dir)
6086 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6088 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6092 gtk_widget_child_focus (widget, dir);
6094 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6095 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6099 gtk_window_real_set_focus (GtkWindow *window,
6102 GtkWindowPrivate *priv = window->priv;
6103 GtkWidget *old_focus = priv->focus_widget;
6104 gboolean had_default = FALSE;
6105 gboolean focus_had_default = FALSE;
6106 gboolean old_focus_had_default = FALSE;
6110 g_object_ref (old_focus);
6111 g_object_freeze_notify (G_OBJECT (old_focus));
6112 old_focus_had_default = gtk_widget_has_default (old_focus);
6116 g_object_ref (focus);
6117 g_object_freeze_notify (G_OBJECT (focus));
6118 focus_had_default = gtk_widget_has_default (focus);
6121 if (priv->default_widget)
6122 had_default = gtk_widget_has_default (priv->default_widget);
6124 if (priv->focus_widget)
6126 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6127 (priv->focus_widget != priv->default_widget))
6129 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6130 gtk_widget_queue_draw (priv->focus_widget);
6132 if (priv->default_widget)
6133 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6136 priv->focus_widget = NULL;
6138 if (priv->has_focus)
6139 do_focus_change (old_focus, FALSE);
6141 g_object_notify (G_OBJECT (old_focus), "is-focus");
6144 /* The above notifications may have set a new focus widget,
6145 * if so, we don't want to override it.
6147 if (focus && !priv->focus_widget)
6149 priv->focus_widget = focus;
6151 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6152 (priv->focus_widget != priv->default_widget))
6154 if (gtk_widget_get_can_default (priv->focus_widget))
6155 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6157 if (priv->default_widget)
6158 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6161 if (priv->has_focus)
6162 do_focus_change (priv->focus_widget, TRUE);
6164 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6167 /* If the default widget changed, a redraw will have been queued
6168 * on the old and new default widgets by gtk_window_set_default(), so
6169 * we only have to worry about the case where it didn't change.
6170 * We'll sometimes queue a draw twice on the new widget but that
6173 if (priv->default_widget &&
6174 (had_default != gtk_widget_has_default (priv->default_widget)))
6175 gtk_widget_queue_draw (priv->default_widget);
6179 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6180 gtk_widget_queue_draw (old_focus);
6182 g_object_thaw_notify (G_OBJECT (old_focus));
6183 g_object_unref (old_focus);
6187 if (focus_had_default != gtk_widget_has_default (focus))
6188 gtk_widget_queue_draw (focus);
6190 g_object_thaw_notify (G_OBJECT (focus));
6191 g_object_unref (focus);
6197 gtk_window_get_preferred_width (GtkWidget *widget,
6205 window = GTK_WINDOW (widget);
6206 child = gtk_bin_get_child (GTK_BIN (window));
6208 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6209 *minimum_size = border_width * 2;
6210 *natural_size = border_width * 2;
6212 if (child && gtk_widget_get_visible (child))
6214 gint child_min, child_nat;
6215 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6217 *minimum_size += child_min;
6218 *natural_size += child_nat;
6223 gtk_window_get_preferred_height (GtkWidget *widget,
6231 window = GTK_WINDOW (widget);
6232 child = gtk_bin_get_child (GTK_BIN (window));
6234 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6235 *minimum_size = border_width * 2;
6236 *natural_size = border_width * 2;
6238 if (child && gtk_widget_get_visible (child))
6240 gint child_min, child_nat;
6241 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6243 *minimum_size += child_min;
6244 *natural_size += child_nat;
6250 * _gtk_window_unset_focus_and_default:
6251 * @window: a #GtkWindow
6252 * @widget: a widget inside of @window
6254 * Checks whether the focus and default widgets of @window are
6255 * @widget or a descendent of @widget, and if so, unset them.
6258 _gtk_window_unset_focus_and_default (GtkWindow *window,
6262 GtkWindowPrivate *priv = window->priv;
6266 g_object_ref (window);
6267 g_object_ref (widget);
6269 parent = gtk_widget_get_parent (widget);
6270 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6272 child = priv->focus_widget;
6274 while (child && child != widget)
6275 child = gtk_widget_get_parent (child);
6277 if (child == widget)
6278 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6281 child = priv->default_widget;
6283 while (child && child != widget)
6284 child = gtk_widget_get_parent (child);
6286 if (child == widget)
6287 gtk_window_set_default (window, NULL);
6289 g_object_unref (widget);
6290 g_object_unref (window);
6293 /*********************************
6294 * Functions related to resizing *
6295 *********************************/
6298 geometry_size_to_pixels (GdkGeometry *geometry,
6303 gint base_width = 0;
6304 gint base_height = 0;
6306 gint min_height = 0;
6308 gint height_inc = 1;
6310 if (flags & GDK_HINT_BASE_SIZE)
6312 base_width = geometry->base_width;
6313 base_height = geometry->base_height;
6315 if (flags & GDK_HINT_MIN_SIZE)
6317 min_width = geometry->min_width;
6318 min_height = geometry->min_height;
6320 if (flags & GDK_HINT_RESIZE_INC)
6322 width_inc = geometry->width_inc;
6323 height_inc = geometry->height_inc;
6327 *width = MAX (*width * width_inc + base_width, min_width);
6329 *height = MAX (*height * height_inc + base_height, min_height);
6332 /* This function doesn't constrain to geometry hints */
6334 gtk_window_compute_configure_request_size (GtkWindow *window,
6335 GdkGeometry *geometry,
6340 GtkWindowPrivate *priv = window->priv;
6341 GtkWindowGeometryInfo *info;
6344 * - we've done a size request
6347 info = gtk_window_get_geometry_info (window, FALSE);
6349 if (priv->need_default_size)
6351 gtk_window_guess_default_size (window, width, height);
6353 /* If window is empty so requests 0, default to random nonzero size */
6354 if (*width == 0 && *height == 0)
6360 /* Override with default size */
6364 if (info->default_width > 0)
6365 *width = info->default_width;
6366 if (info->default_height > 0)
6367 *height = info->default_height;
6369 if (info->default_is_geometry)
6370 geometry_size_to_pixels (geometry, flags,
6371 info->default_width > 0 ? width : NULL,
6372 info->default_height > 0 ? height : NULL);
6377 GtkAllocation allocation;
6379 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6381 /* Default to keeping current size */
6382 *width = allocation.width;
6383 *height = allocation.height;
6386 /* Override any size with gtk_window_resize() values */
6389 if (info->resize_width > 0)
6390 *width = info->resize_width;
6391 if (info->resize_height > 0)
6392 *height = info->resize_height;
6394 if (info->resize_is_geometry)
6395 geometry_size_to_pixels (geometry, flags,
6396 info->resize_width > 0 ? width : NULL,
6397 info->resize_height > 0 ? height : NULL);
6400 /* Don't ever request zero width or height, its not supported by
6401 gdk. The size allocation code will round it to 1 anyway but if
6402 we do it then the value returned from this function will is
6403 not comparable to the size allocation read from the GtkWindow. */
6404 *width = MAX (*width, 1);
6405 *height = MAX (*height, 1);
6408 static GtkWindowPosition
6409 get_effective_position (GtkWindow *window)
6411 GtkWindowPrivate *priv = window->priv;
6412 GtkWindowPosition pos = priv->position;
6414 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6415 (priv->transient_parent == NULL ||
6416 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6417 pos = GTK_WIN_POS_NONE;
6423 get_center_monitor_of_window (GtkWindow *window)
6425 /* We could try to sort out the relative positions of the monitors and
6426 * stuff, or we could just be losers and assume you have a row
6427 * or column of monitors.
6429 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6433 get_monitor_containing_pointer (GtkWindow *window)
6437 GdkScreen *window_screen;
6438 GdkScreen *pointer_screen;
6439 GdkDisplay *display;
6440 GdkDeviceManager *device_manager;
6443 window_screen = gtk_window_check_screen (window);
6444 display = gdk_screen_get_display (window_screen);
6445 device_manager = gdk_display_get_device_manager (display);
6446 pointer = gdk_device_manager_get_client_pointer (device_manager);
6448 gdk_device_get_position (pointer,
6452 if (pointer_screen == window_screen)
6453 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6461 center_window_on_monitor (GtkWindow *window,
6467 GdkRectangle monitor;
6470 monitor_num = get_monitor_containing_pointer (window);
6472 if (monitor_num == -1)
6473 monitor_num = get_center_monitor_of_window (window);
6475 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6476 monitor_num, &monitor);
6478 *x = (monitor.width - w) / 2 + monitor.x;
6479 *y = (monitor.height - h) / 2 + monitor.y;
6481 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6482 * and WM decorations.
6496 if (extent > clamp_extent)
6498 *base = clamp_base + clamp_extent/2 - extent/2;
6499 else if (*base < clamp_base)
6501 else if (*base + extent > clamp_base + clamp_extent)
6502 *base = clamp_base + clamp_extent - extent;
6506 clamp_window_to_rectangle (gint *x,
6510 const GdkRectangle *rect)
6512 #ifdef DEBUGGING_OUTPUT
6513 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);
6516 /* If it is too large, center it. If it fits on the monitor but is
6517 * partially outside, move it to the closest edge. Do this
6518 * separately in x and y directions.
6520 clamp (x, w, rect->x, rect->width);
6521 clamp (y, h, rect->y, rect->height);
6522 #ifdef DEBUGGING_OUTPUT
6523 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6529 gtk_window_compute_configure_request (GtkWindow *window,
6530 GdkRectangle *request,
6531 GdkGeometry *geometry,
6534 GtkWindowPrivate *priv = window->priv;
6535 GdkGeometry new_geometry;
6538 GtkWindowPosition pos;
6539 GtkWidget *parent_widget;
6540 GtkWindowGeometryInfo *info;
6544 screen = gtk_window_check_screen (window);
6546 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6547 gtk_window_compute_configure_request_size (window,
6548 &new_geometry, new_flags,
6551 gtk_window_constrain_size (window,
6552 &new_geometry, new_flags,
6556 parent_widget = (GtkWidget*) priv->transient_parent;
6558 pos = get_effective_position (window);
6559 info = gtk_window_get_geometry_info (window, FALSE);
6561 /* by default, don't change position requested */
6564 x = info->last.configure_request.x;
6565 y = info->last.configure_request.y;
6574 if (priv->need_default_position)
6577 /* FIXME this all interrelates with window gravity.
6578 * For most of them I think we want to set GRAVITY_CENTER.
6580 * Not sure how to go about that.
6584 /* here we are only handling CENTER_ALWAYS
6585 * as it relates to default positioning,
6586 * where it's equivalent to simply CENTER
6588 case GTK_WIN_POS_CENTER_ALWAYS:
6589 case GTK_WIN_POS_CENTER:
6590 center_window_on_monitor (window, w, h, &x, &y);
6593 case GTK_WIN_POS_CENTER_ON_PARENT:
6595 GtkAllocation allocation;
6596 GdkWindow *gdk_window;
6598 GdkRectangle monitor;
6601 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6603 gdk_window = gtk_widget_get_window (parent_widget);
6605 if (gdk_window != NULL)
6606 monitor_num = gdk_screen_get_monitor_at_window (screen,
6611 gdk_window_get_origin (gdk_window,
6614 gtk_widget_get_allocation (parent_widget, &allocation);
6615 x = ox + (allocation.width - w) / 2;
6616 y = oy + (allocation.height - h) / 2;
6618 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6619 * WM decorations. If parent wasn't on a monitor, just
6622 if (monitor_num >= 0)
6624 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6625 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6630 case GTK_WIN_POS_MOUSE:
6632 gint screen_width = gdk_screen_get_width (screen);
6633 gint screen_height = gdk_screen_get_height (screen);
6635 GdkRectangle monitor;
6636 GdkDisplay *display;
6637 GdkDeviceManager *device_manager;
6639 GdkScreen *pointer_screen;
6642 display = gdk_screen_get_display (screen);
6643 device_manager = gdk_display_get_device_manager (display);
6644 pointer = gdk_device_manager_get_client_pointer (device_manager);
6646 gdk_device_get_position (pointer,
6650 if (pointer_screen == screen)
6651 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6657 x = CLAMP (x, 0, screen_width - w);
6658 y = CLAMP (y, 0, screen_height - h);
6660 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6661 * WM decorations. Don't try to figure out what's going
6662 * on if the mouse wasn't inside a monitor.
6664 if (monitor_num >= 0)
6666 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6667 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6675 } /* if (priv->need_default_position) */
6677 if (priv->need_default_position && info &&
6678 info->initial_pos_set)
6680 x = info->initial_x;
6681 y = info->initial_y;
6682 gtk_window_constrain_position (window, w, h, &x, &y);
6688 request->height = h;
6691 *geometry = new_geometry;
6697 gtk_window_constrain_position (GtkWindow *window,
6703 GtkWindowPrivate *priv = window->priv;
6705 /* See long comments in gtk_window_move_resize()
6706 * on when it's safe to call this function.
6708 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6710 gint center_x, center_y;
6712 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6720 gtk_window_move_resize (GtkWindow *window)
6724 * First we determine whether any information has changed that would
6725 * cause us to revise our last configure request. If we would send
6726 * a different configure request from last time, then
6727 * configure_request_size_changed = TRUE or
6728 * configure_request_pos_changed = TRUE. configure_request_size_changed
6729 * may be true due to new hints, a gtk_window_resize(), or whatever.
6730 * configure_request_pos_changed may be true due to gtk_window_set_position()
6731 * or gtk_window_move().
6733 * If the configure request has changed, we send off a new one. To
6734 * ensure GTK+ invariants are maintained (resize queue does what it
6735 * should), we go ahead and size_allocate the requested size in this
6738 * If the configure request has not changed, we don't ever resend
6739 * it, because it could mean fighting the user or window manager.
6742 * To prepare the configure request, we come up with a base size/pos:
6743 * - the one from gtk_window_move()/gtk_window_resize()
6744 * - else default_width, default_height if we haven't ever
6746 * - else the size request if we haven't ever been mapped,
6747 * as a substitute default size
6748 * - else the current size of the window, as received from
6749 * configure notifies (i.e. the current allocation)
6751 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6752 * the position request to be centered.
6754 GtkWindowPrivate *priv = window->priv;
6755 GtkAllocation allocation;
6757 GtkContainer *container;
6758 GtkWindowGeometryInfo *info;
6759 GdkGeometry new_geometry;
6760 GdkWindow *gdk_window;
6762 GdkRectangle new_request;
6763 gboolean configure_request_size_changed;
6764 gboolean configure_request_pos_changed;
6765 gboolean hints_changed; /* do we need to send these again */
6766 GtkWindowLastGeometryInfo saved_last_info;
6768 widget = GTK_WIDGET (window);
6770 gdk_window = gtk_widget_get_window (widget);
6771 container = GTK_CONTAINER (widget);
6772 info = gtk_window_get_geometry_info (window, TRUE);
6774 configure_request_size_changed = FALSE;
6775 configure_request_pos_changed = FALSE;
6777 gtk_window_compute_configure_request (window, &new_request,
6778 &new_geometry, &new_flags);
6780 /* This check implies the invariant that we never set info->last
6781 * without setting the hints and sending off a configure request.
6783 * If we change info->last without sending the request, we may
6786 if (info->last.configure_request.x != new_request.x ||
6787 info->last.configure_request.y != new_request.y)
6788 configure_request_pos_changed = TRUE;
6790 if ((info->last.configure_request.width != new_request.width ||
6791 info->last.configure_request.height != new_request.height))
6792 configure_request_size_changed = TRUE;
6794 hints_changed = FALSE;
6796 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6797 &new_geometry, new_flags))
6799 hints_changed = TRUE;
6802 /* Position Constraints
6803 * ====================
6805 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6806 * a default. The other POS_ values are used only when the
6807 * window is shown, not after that.
6809 * However, we can't implement a position constraint as
6810 * "anytime the window size changes, center the window"
6811 * because this may well end up fighting the WM or user. In
6812 * fact it gets in an infinite loop with at least one WM.
6814 * Basically, applications are in no way in a position to
6815 * constrain the position of a window, with one exception:
6816 * override redirect windows. (Really the intended purpose
6817 * of CENTER_ALWAYS anyhow, I would think.)
6819 * So the way we implement this "constraint" is to say that when WE
6820 * cause a move or resize, i.e. we make a configure request changing
6821 * window size, we recompute the CENTER_ALWAYS position to reflect
6822 * the new window size, and include it in our request. Also, if we
6823 * just turned on CENTER_ALWAYS we snap to center with a new
6824 * request. Otherwise, if we are just NOTIFIED of a move or resize
6825 * done by someone else e.g. the window manager, we do NOT send a
6826 * new configure request.
6828 * For override redirect windows, this works fine; all window
6829 * sizes are from our configure requests. For managed windows,
6830 * it is at least semi-sane, though who knows what the
6831 * app author is thinking.
6834 /* This condition should be kept in sync with the condition later on
6835 * that determines whether we send a configure request. i.e. we
6836 * should do this position constraining anytime we were going to
6837 * send a configure request anyhow, plus when constraints have
6840 if (configure_request_pos_changed ||
6841 configure_request_size_changed ||
6843 info->position_constraints_changed)
6845 /* We request the constrained position if:
6846 * - we were changing position, and need to clamp
6847 * the change to the constraint
6848 * - we're changing the size anyway
6849 * - set_position() was called to toggle CENTER_ALWAYS on
6852 gtk_window_constrain_position (window,
6858 /* Update whether we need to request a move */
6859 if (info->last.configure_request.x != new_request.x ||
6860 info->last.configure_request.y != new_request.y)
6861 configure_request_pos_changed = TRUE;
6863 configure_request_pos_changed = FALSE;
6867 if (priv->type == GTK_WINDOW_TOPLEVEL)
6869 int notify_x, notify_y;
6871 /* this is the position from the last configure notify */
6872 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6874 g_message ("--- %s ---\n"
6875 "last : %d,%d\t%d x %d\n"
6876 "this : %d,%d\t%d x %d\n"
6877 "alloc : %d,%d\t%d x %d\n"
6879 "resize: \t%d x %d\n"
6880 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6881 "configure_notify_received: %d\n"
6882 "configure_request_count: %d\n"
6883 "position_constraints_changed: %d\n",
6884 priv->title ? priv->title : "(no title)",
6885 info->last.configure_request.x,
6886 info->last.configure_request.y,
6887 info->last.configure_request.width,
6888 info->last.configure_request.height,
6894 widget->allocation.width,
6895 widget->allocation.height,
6896 widget->requisition.width,
6897 widget->requisition.height,
6899 info->resize_height,
6900 configure_request_pos_changed,
6901 configure_request_size_changed,
6903 priv->configure_notify_received,
6904 priv->configure_request_count,
6905 info->position_constraints_changed);
6909 saved_last_info = info->last;
6910 info->last.geometry = new_geometry;
6911 info->last.flags = new_flags;
6912 info->last.configure_request = new_request;
6914 /* need to set PPosition so the WM will look at our position,
6915 * but we don't want to count PPosition coming and going as a hints
6916 * change for future iterations. So we saved info->last prior to
6920 /* Also, if the initial position was explicitly set, then we always
6921 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6925 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6926 * this is an initial map
6929 if ((configure_request_pos_changed ||
6930 info->initial_pos_set ||
6931 (priv->need_default_position &&
6932 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6933 (new_flags & GDK_HINT_POS) == 0)
6935 new_flags |= GDK_HINT_POS;
6936 hints_changed = TRUE;
6939 /* Set hints if necessary
6942 gdk_window_set_geometry_hints (gdk_window,
6946 gtk_widget_get_allocation (widget, &allocation);
6948 /* handle resizing/moving and widget tree allocation
6950 if (priv->configure_notify_received)
6952 /* If we have received a configure event since
6953 * the last time in this function, we need to
6954 * accept our new size and size_allocate child widgets.
6955 * (see gtk_window_configure_event() for more details).
6957 * 1 or more configure notifies may have been received.
6958 * Also, configure_notify_received will only be TRUE
6959 * if all expected configure notifies have been received
6960 * (one per configure request), as an optimization.
6963 priv->configure_notify_received = FALSE;
6965 /* gtk_window_configure_event() filled in widget->allocation */
6966 gtk_widget_size_allocate (widget, &allocation);
6968 set_grip_position (window);
6969 update_grip_visibility (window);
6971 gdk_window_process_updates (gdk_window, TRUE);
6973 gdk_window_configure_finished (gdk_window);
6975 /* If the configure request changed, it means that
6977 * 1) coincidentally changed hints or widget properties
6978 * impacting the configure request before getting
6979 * a configure notify, or
6980 * 2) some broken widget is changing its size request
6981 * during size allocation, resulting in
6982 * a false appearance of changed configure request.
6984 * For 1), we could just go ahead and ask for the
6985 * new size right now, but doing that for 2)
6986 * might well be fighting the user (and can even
6987 * trigger a loop). Since we really don't want to
6988 * do that, we requeue a resize in hopes that
6989 * by the time it gets handled, the child has seen
6990 * the light and is willing to go along with the
6991 * new size. (this happens for the zvt widget, since
6992 * the size_allocate() above will have stored the
6993 * requisition corresponding to the new size in the
6996 * This doesn't buy us anything for 1), but it shouldn't
6997 * hurt us too badly, since it is what would have
6998 * happened if we had gotten the configure event before
6999 * the new size had been set.
7002 if (configure_request_size_changed ||
7003 configure_request_pos_changed)
7005 /* Don't change the recorded last info after all, because we
7006 * haven't actually updated to the new info yet - we decided
7007 * to postpone our configure request until later.
7009 info->last = saved_last_info;
7011 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7014 return; /* Bail out, we didn't really process the move/resize */
7016 else if ((configure_request_size_changed || hints_changed) &&
7017 (allocation.width != new_request.width || allocation.height != new_request.height))
7020 /* We are in one of the following situations:
7021 * A. configure_request_size_changed
7022 * our requisition has changed and we need a different window size,
7023 * so we request it from the window manager.
7024 * B. !configure_request_size_changed && hints_changed
7025 * the window manager rejects our size, but we have just changed the
7026 * window manager hints, so there's a chance our request will
7027 * be honoured this time, so we try again.
7029 * However, if the new requisition is the same as the current allocation,
7030 * we don't request it again, since we won't get a ConfigureNotify back from
7031 * the window manager unless it decides to change our requisition. If
7032 * we don't get the ConfigureNotify back, the resize queue will never be run.
7035 /* Now send the configure request */
7036 if (configure_request_pos_changed)
7038 gdk_window_move_resize (gdk_window,
7039 new_request.x, new_request.y,
7040 new_request.width, new_request.height);
7042 else /* only size changed */
7044 gdk_window_resize (gdk_window,
7045 new_request.width, new_request.height);
7048 if (priv->type == GTK_WINDOW_POPUP)
7050 GtkAllocation allocation;
7052 /* Directly size allocate for override redirect (popup) windows. */
7055 allocation.width = new_request.width;
7056 allocation.height = new_request.height;
7058 gtk_widget_size_allocate (widget, &allocation);
7060 gdk_window_process_updates (gdk_window, TRUE);
7062 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7063 gtk_widget_queue_draw (widget);
7067 /* Increment the number of have-not-yet-received-notify requests */
7068 priv->configure_request_count += 1;
7069 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7071 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7072 * configure event in response to our resizing request.
7073 * the configure event will cause a new resize with
7074 * ->configure_notify_received=TRUE.
7075 * until then, we want to
7076 * - discard expose events
7077 * - coalesce resizes for our children
7078 * - defer any window resizes until the configure event arrived
7079 * to achieve this, we queue a resize for the window, but remove its
7080 * resizing handler, so resizing will not be handled from the next
7081 * idle handler but when the configure event arrives.
7083 * FIXME: we should also dequeue the pending redraws here, since
7084 * we handle those ourselves upon ->configure_notify_received==TRUE.
7086 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7088 gtk_widget_queue_resize_no_redraw (widget);
7089 _gtk_container_dequeue_resize_handler (container);
7095 /* Handle any position changes.
7097 if (configure_request_pos_changed)
7099 gdk_window_move (gdk_window,
7100 new_request.x, new_request.y);
7103 /* And run the resize queue.
7105 gtk_container_resize_children (container);
7108 /* We have now processed a move/resize since the last position
7109 * constraint change, setting of the initial position, or resize.
7110 * (Not resetting these flags here can lead to infinite loops for
7111 * GTK_RESIZE_IMMEDIATE containers)
7113 info->position_constraints_changed = FALSE;
7114 info->initial_pos_set = FALSE;
7115 info->resize_width = -1;
7116 info->resize_height = -1;
7119 /* Compare two sets of Geometry hints for equality.
7122 gtk_window_compare_hints (GdkGeometry *geometry_a,
7124 GdkGeometry *geometry_b,
7127 if (flags_a != flags_b)
7130 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7131 (geometry_a->min_width != geometry_b->min_width ||
7132 geometry_a->min_height != geometry_b->min_height))
7135 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7136 (geometry_a->max_width != geometry_b->max_width ||
7137 geometry_a->max_height != geometry_b->max_height))
7140 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7141 (geometry_a->base_width != geometry_b->base_width ||
7142 geometry_a->base_height != geometry_b->base_height))
7145 if ((flags_a & GDK_HINT_ASPECT) &&
7146 (geometry_a->min_aspect != geometry_b->min_aspect ||
7147 geometry_a->max_aspect != geometry_b->max_aspect))
7150 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7151 (geometry_a->width_inc != geometry_b->width_inc ||
7152 geometry_a->height_inc != geometry_b->height_inc))
7155 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7156 geometry_a->win_gravity != geometry_b->win_gravity)
7163 _gtk_window_constrain_size (GtkWindow *window,
7169 GtkWindowPrivate *priv;
7170 GtkWindowGeometryInfo *info;
7172 g_return_if_fail (GTK_IS_WINDOW (window));
7174 priv = window->priv;
7176 info = priv->geometry_info;
7179 GdkWindowHints flags = info->last.flags;
7180 GdkGeometry *geometry = &info->last.geometry;
7182 gtk_window_constrain_size (window,
7193 gtk_window_constrain_size (GtkWindow *window,
7194 GdkGeometry *geometry,
7201 gdk_window_constrain_size (geometry, flags, width, height,
7202 new_width, new_height);
7205 /* Compute the set of geometry hints and flags for a window
7206 * based on the application set geometry, and requisition
7207 * of the window. gtk_widget_get_preferred_size() must have been
7211 gtk_window_compute_hints (GtkWindow *window,
7212 GdkGeometry *new_geometry,
7215 GtkWindowPrivate *priv = window->priv;
7217 gint extra_width = 0;
7218 gint extra_height = 0;
7219 GtkWindowGeometryInfo *geometry_info;
7220 GtkRequisition requisition;
7222 widget = GTK_WIDGET (window);
7224 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7225 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7229 *new_flags = geometry_info->mask;
7230 *new_geometry = geometry_info->geometry;
7237 if (geometry_info && geometry_info->widget)
7239 /* If the geometry widget is set, then the hints really apply to that
7240 * widget. This is pretty much meaningless unless the window layout
7241 * is such that the rest of the window adds fixed size borders to
7242 * the geometry widget. Our job is to figure the size of the borders;
7243 * We do that by asking how big the toplevel would be if the
7244 * geometry widget was *really big*.
7247 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7248 * |GGGGG B| in the border can confuse things
7254 * |AAAAAAAAA | When the geometry widget is large, things are
7255 * |GGGGGGGGGGB| clearer.
7260 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7261 GtkRequisition requisition;
7262 int current_width, current_height;
7264 _gtk_widget_override_size_request (geometry_info->widget,
7265 TEMPORARY_SIZE, TEMPORARY_SIZE,
7266 ¤t_width, ¤t_height);
7267 gtk_widget_get_preferred_size (widget,
7268 &requisition, NULL);
7269 _gtk_widget_restore_size_request (geometry_info->widget,
7270 current_width, current_height);
7272 extra_width = requisition.width - TEMPORARY_SIZE;
7273 extra_height = requisition.height - TEMPORARY_SIZE;
7275 if (extra_width < 0 || extra_height < 0)
7277 g_warning("Toplevel size doesn't seem to directly depend on the "
7278 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7279 "The geometry widget might not be in the window, or it might not "
7280 "be packed into the window appropriately");
7281 extra_width = MAX(extra_width, 0);
7282 extra_height = MAX(extra_height, 0);
7284 #undef TEMPORARY_SIZE
7287 /* We don't want to set GDK_HINT_POS in here, we just set it
7288 * in gtk_window_move_resize() when we want the position
7292 if (*new_flags & GDK_HINT_BASE_SIZE)
7294 new_geometry->base_width += extra_width;
7295 new_geometry->base_height += extra_height;
7299 /* For simplicity, we always set the base hint, even when we
7300 * don't expect it to have any visible effect.
7301 * (Note: geometry_size_to_pixels() depends on this.)
7303 *new_flags |= GDK_HINT_BASE_SIZE;
7305 new_geometry->base_width = extra_width;
7306 new_geometry->base_height = extra_height;
7308 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7309 * base size is the minimum size */
7310 if (*new_flags & GDK_HINT_MIN_SIZE)
7312 if (new_geometry->min_width > 0)
7313 new_geometry->base_width += new_geometry->min_width;
7314 if (new_geometry->min_height > 0)
7315 new_geometry->base_height += new_geometry->min_height;
7319 /* Please use a good size for unresizable widgets, not the minimum one. */
7320 if (!priv->resizable)
7321 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7323 if (*new_flags & GDK_HINT_MIN_SIZE)
7325 if (new_geometry->min_width < 0)
7326 new_geometry->min_width = requisition.width;
7328 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7330 if (new_geometry->min_height < 0)
7331 new_geometry->min_height = requisition.height;
7333 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7337 *new_flags |= GDK_HINT_MIN_SIZE;
7339 new_geometry->min_width = requisition.width;
7340 new_geometry->min_height = requisition.height;
7343 if (*new_flags & GDK_HINT_MAX_SIZE)
7345 if (new_geometry->max_width < 0)
7346 new_geometry->max_width = requisition.width;
7348 new_geometry->max_width += extra_width;
7350 if (new_geometry->max_height < 0)
7351 new_geometry->max_height = requisition.height;
7353 new_geometry->max_height += extra_height;
7355 else if (!priv->resizable)
7357 *new_flags |= GDK_HINT_MAX_SIZE;
7359 new_geometry->max_width = requisition.width;
7360 new_geometry->max_height = requisition.height;
7363 *new_flags |= GDK_HINT_WIN_GRAVITY;
7364 new_geometry->win_gravity = priv->gravity;
7367 /***********************
7368 * Redrawing functions *
7369 ***********************/
7372 gtk_window_draw (GtkWidget *widget,
7375 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7376 GtkStyleContext *context;
7377 gboolean ret = FALSE;
7379 context = gtk_widget_get_style_context (widget);
7381 gtk_style_context_save (context);
7383 if (!gtk_widget_get_app_paintable (widget))
7385 GtkStateFlags state;
7387 state = gtk_widget_get_state_flags (widget);
7389 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7390 state |= GTK_STATE_FLAG_FOCUSED;
7392 gtk_style_context_set_state (context, state);
7393 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7394 gtk_render_background (context, cr, 0, 0,
7395 gtk_widget_get_allocated_width (widget),
7396 gtk_widget_get_allocated_height (widget));
7399 gtk_style_context_restore (context);
7401 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7402 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7404 if (priv->grip_window &&
7405 gtk_cairo_should_draw_window (cr, priv->grip_window))
7409 gtk_style_context_save (context);
7412 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7413 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7415 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7416 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7417 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7420 gtk_style_context_restore (context);
7427 * gtk_window_present:
7428 * @window: a #GtkWindow
7430 * Presents a window to the user. This may mean raising the window
7431 * in the stacking order, deiconifying it, moving it to the current
7432 * desktop, and/or giving it the keyboard focus, possibly dependent
7433 * on the user's platform, window manager, and preferences.
7435 * If @window is hidden, this function calls gtk_widget_show()
7438 * This function should be used when the user tries to open a window
7439 * that's already open. Say for example the preferences dialog is
7440 * currently open, and the user chooses Preferences from the menu
7441 * a second time; use gtk_window_present() to move the already-open dialog
7442 * where the user can see it.
7444 * If you are calling this function in response to a user interaction,
7445 * it is preferable to use gtk_window_present_with_time().
7449 gtk_window_present (GtkWindow *window)
7451 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7455 * gtk_window_present_with_time:
7456 * @window: a #GtkWindow
7457 * @timestamp: the timestamp of the user interaction (typically a
7458 * button or key press event) which triggered this call
7460 * Presents a window to the user in response to a user interaction.
7461 * If you need to present a window without a timestamp, use
7462 * gtk_window_present(). See gtk_window_present() for details.
7467 gtk_window_present_with_time (GtkWindow *window,
7470 GtkWindowPrivate *priv;
7472 GdkWindow *gdk_window;
7474 g_return_if_fail (GTK_IS_WINDOW (window));
7476 priv = window->priv;
7477 widget = GTK_WIDGET (window);
7479 if (gtk_widget_get_visible (widget))
7481 gdk_window = gtk_widget_get_window (widget);
7483 g_assert (gdk_window != NULL);
7485 gdk_window_show (gdk_window);
7487 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7488 if (timestamp == GDK_CURRENT_TIME)
7490 #ifdef GDK_WINDOWING_X11
7491 if (GDK_IS_X11_WINDOW(gdk_window))
7493 GdkDisplay *display;
7495 display = gtk_widget_get_display (GTK_WIDGET (window));
7496 timestamp = gdk_x11_display_get_user_time (display);
7500 timestamp = gtk_get_current_event_time ();
7503 gdk_window_focus (gdk_window, timestamp);
7507 priv->initial_timestamp = timestamp;
7508 gtk_widget_show (widget);
7513 * gtk_window_iconify:
7514 * @window: a #GtkWindow
7516 * Asks to iconify (i.e. minimize) the specified @window. Note that
7517 * you shouldn't assume the window is definitely iconified afterward,
7518 * because other entities (e.g. the user or <link
7519 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7520 * again, or there may not be a window manager in which case
7521 * iconification isn't possible, etc. But normally the window will end
7522 * up iconified. Just don't write code that crashes if not.
7524 * It's permitted to call this function before showing a window,
7525 * in which case the window will be iconified before it ever appears
7528 * You can track iconification via the "window-state-event" signal
7533 gtk_window_iconify (GtkWindow *window)
7535 GtkWindowPrivate *priv;
7537 GdkWindow *toplevel;
7539 g_return_if_fail (GTK_IS_WINDOW (window));
7541 priv = window->priv;
7542 widget = GTK_WIDGET (window);
7544 priv->iconify_initially = TRUE;
7546 toplevel = gtk_widget_get_window (widget);
7548 if (toplevel != NULL)
7549 gdk_window_iconify (toplevel);
7553 * gtk_window_deiconify:
7554 * @window: a #GtkWindow
7556 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7557 * that you shouldn't assume the window is definitely deiconified
7558 * afterward, because other entities (e.g. the user or <link
7559 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7560 * again before your code which assumes deiconification gets to run.
7562 * You can track iconification via the "window-state-event" signal
7566 gtk_window_deiconify (GtkWindow *window)
7568 GtkWindowPrivate *priv;
7570 GdkWindow *toplevel;
7572 g_return_if_fail (GTK_IS_WINDOW (window));
7574 priv = window->priv;
7575 widget = GTK_WIDGET (window);
7577 priv->iconify_initially = FALSE;
7579 toplevel = gtk_widget_get_window (widget);
7581 if (toplevel != NULL)
7582 gdk_window_deiconify (toplevel);
7587 * @window: a #GtkWindow
7589 * Asks to stick @window, which means that it will appear on all user
7590 * desktops. Note that you shouldn't assume the window is definitely
7591 * stuck afterward, because other entities (e.g. the user or <link
7592 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7593 * again, and some window managers do not support sticking
7594 * windows. But normally the window will end up stuck. Just don't
7595 * write code that crashes if not.
7597 * It's permitted to call this function before showing a window.
7599 * You can track stickiness via the "window-state-event" signal
7604 gtk_window_stick (GtkWindow *window)
7606 GtkWindowPrivate *priv;
7608 GdkWindow *toplevel;
7610 g_return_if_fail (GTK_IS_WINDOW (window));
7612 priv = window->priv;
7613 widget = GTK_WIDGET (window);
7615 priv->stick_initially = TRUE;
7617 toplevel = gtk_widget_get_window (widget);
7619 if (toplevel != NULL)
7620 gdk_window_stick (toplevel);
7624 * gtk_window_unstick:
7625 * @window: a #GtkWindow
7627 * Asks to unstick @window, which means that it will appear on only
7628 * one of the user's desktops. Note that you shouldn't assume the
7629 * window is definitely unstuck afterward, because other entities
7630 * (e.g. the user or <link linkend="gtk-X11-arch">window
7631 * manager</link>) could stick it again. But normally the window will
7632 * end up stuck. Just don't write code that crashes if not.
7634 * You can track stickiness via the "window-state-event" signal
7639 gtk_window_unstick (GtkWindow *window)
7641 GtkWindowPrivate *priv;
7643 GdkWindow *toplevel;
7645 g_return_if_fail (GTK_IS_WINDOW (window));
7647 priv = window->priv;
7648 widget = GTK_WIDGET (window);
7650 priv->stick_initially = FALSE;
7652 toplevel = gtk_widget_get_window (widget);
7654 if (toplevel != NULL)
7655 gdk_window_unstick (toplevel);
7659 * gtk_window_maximize:
7660 * @window: a #GtkWindow
7662 * Asks to maximize @window, so that it becomes full-screen. Note that
7663 * you shouldn't assume the window is definitely maximized afterward,
7664 * because other entities (e.g. the user or <link
7665 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7666 * again, and not all window managers support maximization. But
7667 * normally the window will end up maximized. Just don't write code
7668 * that crashes if not.
7670 * It's permitted to call this function before showing a window,
7671 * in which case the window will be maximized when it appears onscreen
7674 * You can track maximization via the "window-state-event" signal
7679 gtk_window_maximize (GtkWindow *window)
7681 GtkWindowPrivate *priv;
7683 GdkWindow *toplevel;
7685 g_return_if_fail (GTK_IS_WINDOW (window));
7687 priv = window->priv;
7688 widget = GTK_WIDGET (window);
7690 priv->maximize_initially = TRUE;
7692 toplevel = gtk_widget_get_window (widget);
7694 if (toplevel != NULL)
7695 gdk_window_maximize (toplevel);
7699 * gtk_window_unmaximize:
7700 * @window: a #GtkWindow
7702 * Asks to unmaximize @window. Note that you shouldn't assume the
7703 * window is definitely unmaximized afterward, because other entities
7704 * (e.g. the user or <link linkend="gtk-X11-arch">window
7705 * manager</link>) could maximize it again, and not all window
7706 * managers honor requests to unmaximize. But normally the window will
7707 * end up unmaximized. Just don't write code that crashes if not.
7709 * You can track maximization via the "window-state-event" signal
7714 gtk_window_unmaximize (GtkWindow *window)
7716 GtkWindowPrivate *priv;
7718 GdkWindow *toplevel;
7720 g_return_if_fail (GTK_IS_WINDOW (window));
7722 priv = window->priv;
7723 widget = GTK_WIDGET (window);
7725 priv->maximize_initially = FALSE;
7727 toplevel = gtk_widget_get_window (widget);
7729 if (toplevel != NULL)
7730 gdk_window_unmaximize (toplevel);
7734 * gtk_window_fullscreen:
7735 * @window: a #GtkWindow
7737 * Asks to place @window in the fullscreen state. Note that you
7738 * shouldn't assume the window is definitely full screen afterward,
7739 * because other entities (e.g. the user or <link
7740 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7741 * again, and not all window managers honor requests to fullscreen
7742 * windows. But normally the window will end up fullscreen. Just
7743 * don't write code that crashes if not.
7745 * You can track the fullscreen state via the "window-state-event" signal
7751 gtk_window_fullscreen (GtkWindow *window)
7753 GtkWindowPrivate *priv;
7755 GdkWindow *toplevel;
7757 g_return_if_fail (GTK_IS_WINDOW (window));
7759 priv = window->priv;
7760 widget = GTK_WIDGET (window);
7762 priv->fullscreen_initially = TRUE;
7764 toplevel = gtk_widget_get_window (widget);
7766 if (toplevel != NULL)
7767 gdk_window_fullscreen (toplevel);
7771 * gtk_window_unfullscreen:
7772 * @window: a #GtkWindow
7774 * Asks to toggle off the fullscreen state for @window. Note that you
7775 * shouldn't assume the window is definitely not full screen
7776 * afterward, because other entities (e.g. the user or <link
7777 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7778 * again, and not all window managers honor requests to unfullscreen
7779 * windows. But normally the window will end up restored to its normal
7780 * state. Just don't write code that crashes if not.
7782 * You can track the fullscreen state via the "window-state-event" signal
7788 gtk_window_unfullscreen (GtkWindow *window)
7791 GdkWindow *toplevel;
7792 GtkWindowPrivate *priv;
7794 g_return_if_fail (GTK_IS_WINDOW (window));
7796 priv = window->priv;
7797 widget = GTK_WIDGET (window);
7799 priv->fullscreen_initially = FALSE;
7801 toplevel = gtk_widget_get_window (widget);
7803 if (toplevel != NULL)
7804 gdk_window_unfullscreen (toplevel);
7808 * gtk_window_set_keep_above:
7809 * @window: a #GtkWindow
7810 * @setting: whether to keep @window above other windows
7812 * Asks to keep @window above, so that it stays on top. Note that
7813 * you shouldn't assume the window is definitely above afterward,
7814 * because other entities (e.g. the user or <link
7815 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7816 * and not all window managers support keeping windows above. But
7817 * normally the window will end kept above. Just don't write code
7818 * that crashes if not.
7820 * It's permitted to call this function before showing a window,
7821 * in which case the window will be kept above when it appears onscreen
7824 * You can track the above state via the "window-state-event" signal
7827 * Note that, according to the <ulink
7828 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7829 * Manager Hints</ulink> specification, the above state is mainly meant
7830 * for user preferences and should not be used by applications e.g. for
7831 * drawing attention to their dialogs.
7836 gtk_window_set_keep_above (GtkWindow *window,
7840 GtkWindowPrivate *priv;
7841 GdkWindow *toplevel;
7843 g_return_if_fail (GTK_IS_WINDOW (window));
7845 priv = window->priv;
7846 widget = GTK_WIDGET (window);
7848 priv->above_initially = setting != FALSE;
7850 priv->below_initially = FALSE;
7852 toplevel = gtk_widget_get_window (widget);
7854 if (toplevel != NULL)
7855 gdk_window_set_keep_above (toplevel, setting);
7859 * gtk_window_set_keep_below:
7860 * @window: a #GtkWindow
7861 * @setting: whether to keep @window below other windows
7863 * Asks to keep @window below, so that it stays in bottom. Note that
7864 * you shouldn't assume the window is definitely below afterward,
7865 * because other entities (e.g. the user or <link
7866 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7867 * and not all window managers support putting windows below. But
7868 * normally the window will be kept below. Just don't write code
7869 * that crashes if not.
7871 * It's permitted to call this function before showing a window,
7872 * in which case the window will be kept below when it appears onscreen
7875 * You can track the below state via the "window-state-event" signal
7878 * Note that, according to the <ulink
7879 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7880 * Manager Hints</ulink> specification, the above state is mainly meant
7881 * for user preferences and should not be used by applications e.g. for
7882 * drawing attention to their dialogs.
7887 gtk_window_set_keep_below (GtkWindow *window,
7891 GtkWindowPrivate *priv;
7892 GdkWindow *toplevel;
7894 g_return_if_fail (GTK_IS_WINDOW (window));
7896 priv = window->priv;
7897 widget = GTK_WIDGET (window);
7899 priv->below_initially = setting != FALSE;
7901 priv->above_initially = FALSE;
7903 toplevel = gtk_widget_get_window (widget);
7905 if (toplevel != NULL)
7906 gdk_window_set_keep_below (toplevel, setting);
7910 * gtk_window_set_resizable:
7911 * @window: a #GtkWindow
7912 * @resizable: %TRUE if the user can resize this window
7914 * Sets whether the user can resize a window. Windows are user resizable
7918 gtk_window_set_resizable (GtkWindow *window,
7921 GtkWindowPrivate *priv;
7923 g_return_if_fail (GTK_IS_WINDOW (window));
7925 priv = window->priv;
7927 resizable = (resizable != FALSE);
7929 if (priv->resizable != resizable)
7931 priv->resizable = (resizable != FALSE);
7933 update_grip_visibility (window);
7935 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7937 g_object_notify (G_OBJECT (window), "resizable");
7942 * gtk_window_get_resizable:
7943 * @window: a #GtkWindow
7945 * Gets the value set by gtk_window_set_resizable().
7947 * Return value: %TRUE if the user can resize the window
7950 gtk_window_get_resizable (GtkWindow *window)
7952 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7954 return window->priv->resizable;
7958 * gtk_window_set_gravity:
7959 * @window: a #GtkWindow
7960 * @gravity: window gravity
7962 * Window gravity defines the meaning of coordinates passed to
7963 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7966 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7967 * typically "do what you mean."
7971 gtk_window_set_gravity (GtkWindow *window,
7974 GtkWindowPrivate *priv;
7976 g_return_if_fail (GTK_IS_WINDOW (window));
7978 priv = window->priv;
7980 if (gravity != priv->gravity)
7982 priv->gravity = gravity;
7984 /* gtk_window_move_resize() will adapt gravity
7986 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7988 g_object_notify (G_OBJECT (window), "gravity");
7993 * gtk_window_get_gravity:
7994 * @window: a #GtkWindow
7996 * Gets the value set by gtk_window_set_gravity().
7998 * Return value: (transfer none): window gravity
8001 gtk_window_get_gravity (GtkWindow *window)
8003 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8005 return window->priv->gravity;
8009 * gtk_window_begin_resize_drag:
8010 * @window: a #GtkWindow
8011 * @button: mouse button that initiated the drag
8012 * @edge: position of the resize control
8013 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8014 * @root_y: Y position where the user clicked to initiate the drag
8015 * @timestamp: timestamp from the click event that initiated the drag
8017 * Starts resizing a window. This function is used if an application
8018 * has window resizing controls. When GDK can support it, the resize
8019 * will be done using the standard mechanism for the <link
8020 * linkend="gtk-X11-arch">window manager</link> or windowing
8021 * system. Otherwise, GDK will try to emulate window resizing,
8022 * potentially not all that well, depending on the windowing system.
8026 gtk_window_begin_resize_drag (GtkWindow *window,
8034 GdkWindow *toplevel;
8036 g_return_if_fail (GTK_IS_WINDOW (window));
8037 widget = GTK_WIDGET (window);
8038 g_return_if_fail (gtk_widget_get_visible (widget));
8040 toplevel = gtk_widget_get_window (widget);
8042 gdk_window_begin_resize_drag (toplevel,
8049 * gtk_window_begin_move_drag:
8050 * @window: a #GtkWindow
8051 * @button: mouse button that initiated the drag
8052 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8053 * @root_y: Y position where the user clicked to initiate the drag
8054 * @timestamp: timestamp from the click event that initiated the drag
8056 * Starts moving a window. This function is used if an application has
8057 * window movement grips. When GDK can support it, the window movement
8058 * will be done using the standard mechanism for the <link
8059 * linkend="gtk-X11-arch">window manager</link> or windowing
8060 * system. Otherwise, GDK will try to emulate window movement,
8061 * potentially not all that well, depending on the windowing system.
8065 gtk_window_begin_move_drag (GtkWindow *window,
8072 GdkWindow *toplevel;
8074 g_return_if_fail (GTK_IS_WINDOW (window));
8075 widget = GTK_WIDGET (window);
8076 g_return_if_fail (gtk_widget_get_visible (widget));
8078 toplevel = gtk_widget_get_window (widget);
8080 gdk_window_begin_move_drag (toplevel,
8087 * gtk_window_set_screen:
8088 * @window: a #GtkWindow.
8089 * @screen: a #GdkScreen.
8091 * Sets the #GdkScreen where the @window is displayed; if
8092 * the window is already mapped, it will be unmapped, and
8093 * then remapped on the new screen.
8098 gtk_window_set_screen (GtkWindow *window,
8101 GtkWindowPrivate *priv;
8103 GdkScreen *previous_screen;
8104 gboolean was_mapped;
8106 g_return_if_fail (GTK_IS_WINDOW (window));
8107 g_return_if_fail (GDK_IS_SCREEN (screen));
8109 priv = window->priv;
8111 if (screen == priv->screen)
8114 widget = GTK_WIDGET (window);
8116 previous_screen = priv->screen;
8117 was_mapped = gtk_widget_get_mapped (widget);
8120 gtk_widget_unmap (widget);
8121 if (gtk_widget_get_realized (widget))
8122 gtk_widget_unrealize (widget);
8124 gtk_window_free_key_hash (window);
8125 priv->screen = screen;
8126 gtk_widget_reset_rc_styles (widget);
8127 if (screen != previous_screen)
8129 if (previous_screen)
8131 g_signal_handlers_disconnect_by_func (previous_screen,
8132 gtk_window_on_composited_changed, window);
8133 #ifdef GDK_WINDOWING_X11
8134 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8135 gtk_window_on_theme_variant_changed, window);
8138 g_signal_connect (screen, "composited-changed",
8139 G_CALLBACK (gtk_window_on_composited_changed), window);
8140 #ifdef GDK_WINDOWING_X11
8141 g_signal_connect (gtk_settings_get_for_screen (screen),
8142 "notify::gtk-application-prefer-dark-theme",
8143 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8146 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8147 _gtk_widget_propagate_composited_changed (widget);
8149 g_object_notify (G_OBJECT (window), "screen");
8152 gtk_widget_map (widget);
8156 gtk_window_set_theme_variant (GtkWindow *window)
8158 #ifdef GDK_WINDOWING_X11
8159 GdkWindow *gdk_window;
8160 gboolean dark_theme_requested;
8162 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8163 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8166 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8168 if (GDK_IS_X11_WINDOW (gdk_window))
8169 gdk_x11_window_set_theme_variant (gdk_window,
8170 dark_theme_requested ? "dark" : NULL);
8175 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8179 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8180 gtk_window_set_theme_variant (window);
8184 gtk_window_on_composited_changed (GdkScreen *screen,
8187 gtk_widget_queue_draw (GTK_WIDGET (window));
8189 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8193 gtk_window_check_screen (GtkWindow *window)
8195 GtkWindowPrivate *priv = window->priv;
8198 return priv->screen;
8201 g_warning ("Screen for GtkWindow not set; you must always set\n"
8202 "a screen for a GtkWindow before using the window");
8208 * gtk_window_get_screen:
8209 * @window: a #GtkWindow.
8211 * Returns the #GdkScreen associated with @window.
8213 * Return value: (transfer none): a #GdkScreen.
8218 gtk_window_get_screen (GtkWindow *window)
8220 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8222 return window->priv->screen;
8226 * gtk_window_is_active:
8227 * @window: a #GtkWindow
8229 * Returns whether the window is part of the current active toplevel.
8230 * (That is, the toplevel window receiving keystrokes.)
8231 * The return value is %TRUE if the window is active toplevel
8232 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8233 * You might use this function if you wanted to draw a widget
8234 * differently in an active window from a widget in an inactive window.
8235 * See gtk_window_has_toplevel_focus()
8237 * Return value: %TRUE if the window part of the current active window.
8242 gtk_window_is_active (GtkWindow *window)
8244 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8246 return window->priv->is_active;
8250 * gtk_window_has_toplevel_focus:
8251 * @window: a #GtkWindow
8253 * Returns whether the input focus is within this GtkWindow.
8254 * For real toplevel windows, this is identical to gtk_window_is_active(),
8255 * but for embedded windows, like #GtkPlug, the results will differ.
8257 * Return value: %TRUE if the input focus is within this GtkWindow
8262 gtk_window_has_toplevel_focus (GtkWindow *window)
8264 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8266 return window->priv->has_toplevel_focus;
8271 * SECTION:gtkwindowgroup
8272 * @Short_description: Limit the effect of grabs
8273 * @Title: GtkWindowGroup
8275 * #GtkWindowGroup objects are referenced by each window in the group,
8276 * so once you have added all windows to a #GtkWindowGroup, you can drop
8277 * the initial reference to the window group with g_object_unref(). If the
8278 * windows in the window group are subsequently destroyed, then they will
8279 * be removed from the window group and drop their references on the window
8280 * group; when all window have been removed, the window group will be
8284 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8287 gtk_window_group_init (GtkWindowGroup *group)
8289 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8290 GTK_TYPE_WINDOW_GROUP,
8291 GtkWindowGroupPrivate);
8295 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8297 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8301 * gtk_window_group_new:
8303 * Creates a new #GtkWindowGroup object. Grabs added with
8304 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8306 * Return value: a new #GtkWindowGroup.
8309 gtk_window_group_new (void)
8311 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8315 window_group_cleanup_grabs (GtkWindowGroup *group,
8318 GtkWindowGroupPrivate *priv;
8319 GtkDeviceGrabInfo *info;
8321 GSList *to_remove = NULL;
8325 tmp_list = priv->grabs;
8328 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8329 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8330 tmp_list = tmp_list->next;
8335 gtk_grab_remove (to_remove->data);
8336 g_object_unref (to_remove->data);
8337 to_remove = g_slist_delete_link (to_remove, to_remove);
8340 tmp_list = priv->device_grabs;
8344 info = tmp_list->data;
8346 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8347 to_remove = g_slist_prepend (to_remove, info);
8349 tmp_list = tmp_list->next;
8354 info = to_remove->data;
8356 gtk_device_grab_remove (info->widget, info->device);
8357 to_remove = g_slist_delete_link (to_remove, to_remove);
8362 * gtk_window_group_add_window:
8363 * @window_group: a #GtkWindowGroup
8364 * @window: the #GtkWindow to add
8366 * Adds a window to a #GtkWindowGroup.
8369 gtk_window_group_add_window (GtkWindowGroup *window_group,
8372 GtkWindowPrivate *priv;
8374 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8375 g_return_if_fail (GTK_IS_WINDOW (window));
8377 priv = window->priv;
8379 if (priv->group != window_group)
8381 g_object_ref (window);
8382 g_object_ref (window_group);
8385 gtk_window_group_remove_window (priv->group, window);
8387 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8389 priv->group = window_group;
8391 g_object_unref (window);
8396 * gtk_window_group_remove_window:
8397 * @window_group: a #GtkWindowGroup
8398 * @window: the #GtkWindow to remove
8400 * Removes a window from a #GtkWindowGroup.
8403 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8406 GtkWindowPrivate *priv;
8408 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8409 g_return_if_fail (GTK_IS_WINDOW (window));
8410 priv = window->priv;
8411 g_return_if_fail (priv->group == window_group);
8413 g_object_ref (window);
8415 window_group_cleanup_grabs (window_group, window);
8418 g_object_unref (window_group);
8419 g_object_unref (window);
8423 * gtk_window_group_list_windows:
8424 * @window_group: a #GtkWindowGroup
8426 * Returns a list of the #GtkWindows that belong to @window_group.
8428 * Returns: (element-type GtkWindow) (transfer container): A
8429 * newly-allocated list of windows inside the group.
8434 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8436 GList *toplevels, *toplevel, *group_windows;
8438 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8440 group_windows = NULL;
8441 toplevels = gtk_window_list_toplevels ();
8443 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8445 GtkWindow *window = toplevel->data;
8447 if (window_group == window->priv->group)
8448 group_windows = g_list_prepend (group_windows, window);
8451 g_list_free (toplevels);
8453 return g_list_reverse (group_windows);
8457 * gtk_window_get_group:
8458 * @window: (allow-none): a #GtkWindow, or %NULL
8460 * Returns the group for @window or the default group, if
8461 * @window is %NULL or if @window does not have an explicit
8464 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8469 gtk_window_get_group (GtkWindow *window)
8471 if (window && window->priv->group)
8472 return window->priv->group;
8475 static GtkWindowGroup *default_group = NULL;
8478 default_group = gtk_window_group_new ();
8480 return default_group;
8485 * gtk_window_has_group:
8486 * @window: a #GtkWindow
8488 * Returns whether @window has an explicit window group.
8490 * Return value: %TRUE if @window has an explicit window group.
8495 gtk_window_has_group (GtkWindow *window)
8497 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8499 return window->priv->group != NULL;
8503 * gtk_window_group_get_current_grab:
8504 * @window_group: a #GtkWindowGroup
8506 * Gets the current grab widget of the given group,
8507 * see gtk_grab_add().
8509 * Returns: (transfer none): the current grab widget of the group
8514 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8516 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8518 if (window_group->priv->grabs)
8519 return GTK_WIDGET (window_group->priv->grabs->data);
8524 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8527 GtkWindowGroupPrivate *priv;
8529 priv = window_group->priv;
8530 priv->grabs = g_slist_prepend (priv->grabs, widget);
8534 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8537 GtkWindowGroupPrivate *priv;
8539 priv = window_group->priv;
8540 priv->grabs = g_slist_remove (priv->grabs, widget);
8545 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8548 gboolean block_others)
8550 GtkWindowGroupPrivate *priv;
8551 GtkDeviceGrabInfo *info;
8553 priv = window_group->priv;
8555 info = g_slice_new0 (GtkDeviceGrabInfo);
8556 info->widget = widget;
8557 info->device = device;
8558 info->block_others = block_others;
8560 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8564 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8568 GtkWindowGroupPrivate *priv;
8569 GtkDeviceGrabInfo *info;
8570 GSList *list, *node = NULL;
8571 GdkDevice *other_device;
8573 priv = window_group->priv;
8574 other_device = gdk_device_get_associated_device (device);
8575 list = priv->device_grabs;
8581 if (info->widget == widget &&
8582 (info->device == device ||
8583 info->device == other_device))
8596 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8597 g_slice_free (GtkDeviceGrabInfo, info);
8602 * gtk_window_group_get_current_device_grab:
8603 * @window_group: a #GtkWindowGroup
8604 * @device: a #GdkDevice
8606 * Returns the current grab widget for @device, or %NULL if none.
8608 * Returns: (transfer none): The grab widget, or %NULL
8613 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8616 GtkWindowGroupPrivate *priv;
8617 GtkDeviceGrabInfo *info;
8618 GdkDevice *other_device;
8621 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8622 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8624 priv = window_group->priv;
8625 list = priv->device_grabs;
8626 other_device = gdk_device_get_associated_device (device);
8633 if (info->device == device ||
8634 info->device == other_device)
8635 return info->widget;
8642 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8646 GtkWindowGroupPrivate *priv;
8647 GtkDeviceGrabInfo *info;
8648 GdkDevice *other_device;
8651 priv = window_group->priv;
8652 other_device = gdk_device_get_associated_device (device);
8653 list = priv->device_grabs;
8660 /* Look for blocking grabs on other device pairs
8661 * that have the passed widget within the GTK+ grab.
8663 if (info->block_others &&
8664 info->device != device &&
8665 info->device != other_device &&
8666 (info->widget == widget ||
8667 gtk_widget_is_ancestor (widget, info->widget)))
8675 Derived from XParseGeometry() in XFree86
8677 Copyright 1985, 1986, 1987,1998 The Open Group
8679 All Rights Reserved.
8681 The above copyright notice and this permission notice shall be included
8682 in all copies or substantial portions of the Software.
8684 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8685 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8686 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8687 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8688 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8689 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8690 OTHER DEALINGS IN THE SOFTWARE.
8692 Except as contained in this notice, the name of The Open Group shall
8693 not be used in advertising or otherwise to promote the sale, use or
8694 other dealings in this Software without prior written authorization
8695 from The Open Group.
8700 * XParseGeometry parses strings of the form
8701 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8702 * width, height, xoffset, and yoffset are unsigned integers.
8703 * Example: "=80x24+300-49"
8704 * The equal sign is optional.
8705 * It returns a bitmask that indicates which of the four values
8706 * were actually found in the string. For each value found,
8707 * the corresponding argument is updated; for each value
8708 * not found, the corresponding argument is left unchanged.
8711 /* The following code is from Xlib, and is minimally modified, so we
8712 * can track any upstream changes if required. Don't change this
8713 * code. Or if you do, put in a huge comment marking which thing
8718 read_int (gchar *string,
8726 else if (*string == '-')
8732 for (; (*string >= '0') && (*string <= '9'); string++)
8734 result = (result * 10) + (*string - '0');
8746 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8747 * value (x, y, width, height) was found in the parsed string.
8749 #define NoValue 0x0000
8750 #define XValue 0x0001
8751 #define YValue 0x0002
8752 #define WidthValue 0x0004
8753 #define HeightValue 0x0008
8754 #define AllValues 0x000F
8755 #define XNegative 0x0010
8756 #define YNegative 0x0020
8758 /* Try not to reformat/modify, so we can compare/sync with X sources */
8760 gtk_XParseGeometry (const char *string,
8763 unsigned int *width,
8764 unsigned int *height)
8768 unsigned int tempWidth, tempHeight;
8770 char *nextCharacter;
8772 /* These initializations are just to silence gcc */
8778 if ( (string == NULL) || (*string == '\0')) return(mask);
8780 string++; /* ignore possible '=' at beg of geometry spec */
8782 strind = (char *)string;
8783 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8784 tempWidth = read_int(strind, &nextCharacter);
8785 if (strind == nextCharacter)
8787 strind = nextCharacter;
8791 if (*strind == 'x' || *strind == 'X') {
8793 tempHeight = read_int(strind, &nextCharacter);
8794 if (strind == nextCharacter)
8796 strind = nextCharacter;
8797 mask |= HeightValue;
8800 if ((*strind == '+') || (*strind == '-')) {
8801 if (*strind == '-') {
8803 tempX = -read_int(strind, &nextCharacter);
8804 if (strind == nextCharacter)
8806 strind = nextCharacter;
8812 tempX = read_int(strind, &nextCharacter);
8813 if (strind == nextCharacter)
8815 strind = nextCharacter;
8818 if ((*strind == '+') || (*strind == '-')) {
8819 if (*strind == '-') {
8821 tempY = -read_int(strind, &nextCharacter);
8822 if (strind == nextCharacter)
8824 strind = nextCharacter;
8831 tempY = read_int(strind, &nextCharacter);
8832 if (strind == nextCharacter)
8834 strind = nextCharacter;
8840 /* If strind isn't at the end of the string the it's an invalid
8841 geometry specification. */
8843 if (*strind != '\0') return (0);
8849 if (mask & WidthValue)
8851 if (mask & HeightValue)
8852 *height = tempHeight;
8857 * gtk_window_parse_geometry:
8858 * @window: a #GtkWindow
8859 * @geometry: geometry string
8861 * Parses a standard X Window System geometry string - see the
8862 * manual page for X (type 'man X') for details on this.
8863 * gtk_window_parse_geometry() does work on all GTK+ ports
8864 * including Win32 but is primarily intended for an X environment.
8866 * If either a size or a position can be extracted from the
8867 * geometry string, gtk_window_parse_geometry() returns %TRUE
8868 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8869 * to resize/move the window.
8871 * If gtk_window_parse_geometry() returns %TRUE, it will also
8872 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8873 * indicating to the window manager that the size/position of
8874 * the window was user-specified. This causes most window
8875 * managers to honor the geometry.
8877 * Note that for gtk_window_parse_geometry() to work as expected, it has
8878 * to be called when the window has its "final" size, i.e. after calling
8879 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8882 * #include <gtk/gtk.h>
8885 * fill_with_content (GtkWidget *vbox)
8887 * /* fill with content... */
8891 * main (int argc, char *argv[])
8893 * GtkWidget *window, *vbox;
8894 * GdkGeometry size_hints = {
8895 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8898 * gtk_init (&argc, &argv);
8900 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8901 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8903 * gtk_container_add (GTK_CONTAINER (window), vbox);
8904 * fill_with_content (vbox);
8905 * gtk_widget_show_all (vbox);
8907 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8910 * GDK_HINT_MIN_SIZE |
8911 * GDK_HINT_BASE_SIZE |
8912 * GDK_HINT_RESIZE_INC);
8916 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8917 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8920 * gtk_widget_show_all (window);
8927 * Return value: %TRUE if string was parsed successfully
8930 gtk_window_parse_geometry (GtkWindow *window,
8931 const gchar *geometry)
8933 gint result, x = 0, y = 0;
8937 gboolean size_set, pos_set;
8940 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8941 g_return_val_if_fail (geometry != NULL, FALSE);
8943 child = gtk_bin_get_child (GTK_BIN (window));
8944 if (!child || !gtk_widget_get_visible (child))
8945 g_warning ("gtk_window_parse_geometry() called on a window with no "
8946 "visible children; the window should be set up before "
8947 "gtk_window_parse_geometry() is called.");
8949 screen = gtk_window_check_screen (window);
8951 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8954 if ((result & WidthValue) || (result & HeightValue))
8956 gtk_window_set_default_size_internal (window,
8957 TRUE, result & WidthValue ? w : -1,
8958 TRUE, result & HeightValue ? h : -1,
8963 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8965 grav = GDK_GRAVITY_NORTH_WEST;
8967 if ((result & XNegative) && (result & YNegative))
8968 grav = GDK_GRAVITY_SOUTH_EAST;
8969 else if (result & XNegative)
8970 grav = GDK_GRAVITY_NORTH_EAST;
8971 else if (result & YNegative)
8972 grav = GDK_GRAVITY_SOUTH_WEST;
8974 if ((result & XValue) == 0)
8977 if ((result & YValue) == 0)
8980 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8981 grav == GDK_GRAVITY_SOUTH_EAST)
8982 y = gdk_screen_get_height (screen) - h + y;
8984 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8985 grav == GDK_GRAVITY_NORTH_EAST)
8986 x = gdk_screen_get_width (screen) - w + x;
8988 /* we don't let you put a window offscreen; maybe some people would
8989 * prefer to be able to, but it's kind of a bogus thing to do.
8998 if ((result & XValue) || (result & YValue))
9000 gtk_window_set_gravity (window, grav);
9001 gtk_window_move (window, x, y);
9005 if (size_set || pos_set)
9007 /* Set USSize, USPosition hints */
9008 GtkWindowGeometryInfo *info;
9010 info = gtk_window_get_geometry_info (window, TRUE);
9013 info->mask |= GDK_HINT_USER_POS;
9015 info->mask |= GDK_HINT_USER_SIZE;
9022 gtk_window_mnemonic_hash_foreach (guint keyval,
9028 GtkWindowKeysForeachFunc func;
9032 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9036 _gtk_window_keys_foreach (GtkWindow *window,
9037 GtkWindowKeysForeachFunc func,
9041 GtkMnemonicHash *mnemonic_hash;
9045 GtkWindowKeysForeachFunc func;
9049 info.window = window;
9051 info.func_data = func_data;
9053 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9055 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9056 gtk_window_mnemonic_hash_foreach, &info);
9058 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9061 GtkAccelGroup *group = groups->data;
9064 for (i = 0; i < group->priv->n_accels; i++)
9066 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9069 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9072 groups = groups->next;
9077 gtk_window_keys_changed (GtkWindow *window)
9079 gtk_window_free_key_hash (window);
9080 gtk_window_get_key_hash (window);
9083 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9085 struct _GtkWindowKeyEntry
9089 guint is_mnemonic : 1;
9093 window_key_entry_destroy (gpointer data)
9095 g_slice_free (GtkWindowKeyEntry, data);
9099 add_to_key_hash (GtkWindow *window,
9101 GdkModifierType modifiers,
9102 gboolean is_mnemonic,
9105 GtkKeyHash *key_hash = data;
9107 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9109 entry->keyval = keyval;
9110 entry->modifiers = modifiers;
9111 entry->is_mnemonic = is_mnemonic;
9113 /* GtkAccelGroup stores lowercased accelerators. To deal
9114 * with this, if <Shift> was specified, uppercase.
9116 if (modifiers & GDK_SHIFT_MASK)
9118 if (keyval == GDK_KEY_Tab)
9119 keyval = GDK_KEY_ISO_Left_Tab;
9121 keyval = gdk_keyval_to_upper (keyval);
9124 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9128 gtk_window_get_key_hash (GtkWindow *window)
9130 GdkScreen *screen = gtk_window_check_screen (window);
9131 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9136 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9137 (GDestroyNotify)window_key_entry_destroy);
9138 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9139 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9145 gtk_window_free_key_hash (GtkWindow *window)
9147 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9150 _gtk_key_hash_free (key_hash);
9151 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9156 * gtk_window_activate_key:
9157 * @window: a #GtkWindow
9158 * @event: a #GdkEventKey
9160 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9161 * called by the default ::key_press_event handler for toplevel windows,
9162 * however in some cases it may be useful to call this directly when
9163 * overriding the standard key handling for a toplevel window.
9165 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9170 gtk_window_activate_key (GtkWindow *window,
9173 GtkKeyHash *key_hash;
9174 GtkWindowKeyEntry *found_entry = NULL;
9175 gboolean enable_mnemonics;
9176 gboolean enable_accels;
9178 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9179 g_return_val_if_fail (event != NULL, FALSE);
9181 key_hash = gtk_window_get_key_hash (window);
9186 GSList *entries = _gtk_key_hash_lookup (key_hash,
9187 event->hardware_keycode,
9189 gtk_accelerator_get_default_mod_mask (),
9192 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9193 "gtk-enable-mnemonics", &enable_mnemonics,
9194 "gtk-enable-accels", &enable_accels,
9197 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9199 GtkWindowKeyEntry *entry = tmp_list->data;
9200 if (entry->is_mnemonic)
9202 if (enable_mnemonics)
9204 found_entry = entry;
9210 if (enable_accels && !found_entry)
9212 found_entry = entry;
9217 g_slist_free (entries);
9222 if (found_entry->is_mnemonic)
9224 if (enable_mnemonics)
9225 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9226 found_entry->modifiers);
9231 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9232 found_entry->modifiers);
9240 window_update_has_focus (GtkWindow *window)
9242 GtkWindowPrivate *priv = window->priv;
9243 GtkWidget *widget = GTK_WIDGET (window);
9244 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9246 if (has_focus != priv->has_focus)
9248 priv->has_focus = has_focus;
9252 if (priv->focus_widget &&
9253 priv->focus_widget != widget &&
9254 !gtk_widget_has_focus (priv->focus_widget))
9255 do_focus_change (priv->focus_widget, TRUE);
9259 if (priv->focus_widget &&
9260 priv->focus_widget != widget &&
9261 gtk_widget_has_focus (priv->focus_widget))
9262 do_focus_change (priv->focus_widget, FALSE);
9268 * _gtk_window_set_is_active:
9269 * @window: a #GtkWindow
9270 * @is_active: %TRUE if the window is in the currently active toplevel
9272 * Internal function that sets whether the #GtkWindow is part
9273 * of the currently active toplevel window (taking into account inter-process
9277 _gtk_window_set_is_active (GtkWindow *window,
9280 GtkWindowPrivate *priv;
9282 g_return_if_fail (GTK_IS_WINDOW (window));
9284 priv = window->priv;
9286 is_active = is_active != FALSE;
9288 if (is_active != priv->is_active)
9290 priv->is_active = is_active;
9291 window_update_has_focus (window);
9293 g_object_notify (G_OBJECT (window), "is-active");
9298 * _gtk_window_set_is_toplevel:
9299 * @window: a #GtkWindow
9300 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9301 * child of the root window); %FALSE if it is not (for example, for an
9302 * in-process, parented GtkPlug)
9304 * Internal function used by #GtkPlug when it gets parented/unparented by a
9305 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9306 * global list of toplevel windows.
9309 _gtk_window_set_is_toplevel (GtkWindow *window,
9310 gboolean is_toplevel)
9313 GtkWidget *toplevel;
9315 widget = GTK_WIDGET (window);
9317 if (gtk_widget_is_toplevel (widget))
9318 g_assert (g_slist_find (toplevel_list, window) != NULL);
9320 g_assert (g_slist_find (toplevel_list, window) == NULL);
9322 if (is_toplevel == gtk_widget_is_toplevel (widget))
9327 /* Pass through regular pathways of an embedded toplevel
9328 * to go through unmapping and hiding the widget before
9329 * becomming a toplevel again.
9331 * We remain hidden after becomming toplevel in order to
9332 * avoid problems during an embedded toplevel's dispose cycle
9333 * (When a toplevel window is shown it tries to grab focus again,
9334 * this causes problems while disposing).
9336 gtk_widget_hide (widget);
9338 /* Save the toplevel this widget was previously anchored into before
9339 * propagating a hierarchy-changed.
9341 * Usually this happens by way of gtk_widget_unparent() and we are
9342 * already unanchored at this point, just adding this clause incase
9343 * things happen differently.
9345 toplevel = gtk_widget_get_toplevel (widget);
9346 if (!gtk_widget_is_toplevel (toplevel))
9349 _gtk_widget_set_is_toplevel (widget, TRUE);
9351 /* When a window becomes toplevel after being embedded and anchored
9352 * into another window we need to unset its anchored flag so that
9353 * the hierarchy changed signal kicks in properly.
9355 _gtk_widget_set_anchored (widget, FALSE);
9356 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9358 toplevel_list = g_slist_prepend (toplevel_list, window);
9362 _gtk_widget_set_is_toplevel (widget, FALSE);
9363 toplevel_list = g_slist_remove (toplevel_list, window);
9365 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9370 * _gtk_window_set_has_toplevel_focus:
9371 * @window: a #GtkWindow
9372 * @has_toplevel_focus: %TRUE if the in
9374 * Internal function that sets whether the keyboard focus for the
9375 * toplevel window (taking into account inter-process embedding.)
9378 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9379 gboolean has_toplevel_focus)
9381 GtkWindowPrivate *priv;
9383 g_return_if_fail (GTK_IS_WINDOW (window));
9385 priv = window->priv;
9387 has_toplevel_focus = has_toplevel_focus != FALSE;
9389 if (has_toplevel_focus != priv->has_toplevel_focus)
9391 priv->has_toplevel_focus = has_toplevel_focus;
9392 window_update_has_focus (window);
9394 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9399 * gtk_window_set_auto_startup_notification:
9400 * @setting: %TRUE to automatically do startup notification
9402 * By default, after showing the first #GtkWindow, GTK+ calls
9403 * gdk_notify_startup_complete(). Call this function to disable
9404 * the automatic startup notification. You might do this if your
9405 * first window is a splash screen, and you want to delay notification
9406 * until after your real main window has been shown, for example.
9408 * In that example, you would disable startup notification
9409 * temporarily, show your splash screen, then re-enable it so that
9410 * showing the main window would automatically result in notification.
9415 gtk_window_set_auto_startup_notification (gboolean setting)
9417 disable_startup_notification = !setting;
9421 * gtk_window_get_window_type:
9422 * @window: a #GtkWindow
9424 * Gets the type of the window. See #GtkWindowType.
9426 * Return value: the type of the window
9431 gtk_window_get_window_type (GtkWindow *window)
9433 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9435 return window->priv->type;
9439 * gtk_window_get_mnemonics_visible:
9440 * @window: a #GtkWindow
9442 * Gets the value of the #GtkWindow:mnemonics-visible property.
9444 * Returns: %TRUE if mnemonics are supposed to be visible
9450 gtk_window_get_mnemonics_visible (GtkWindow *window)
9452 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9454 return window->priv->mnemonics_visible;
9458 * gtk_window_set_mnemonics_visible:
9459 * @window: a #GtkWindow
9460 * @setting: the new value
9462 * Sets the #GtkWindow:mnemonics-visible property.
9467 gtk_window_set_mnemonics_visible (GtkWindow *window,
9470 GtkWindowPrivate *priv;
9472 g_return_if_fail (GTK_IS_WINDOW (window));
9474 priv = window->priv;
9476 setting = setting != FALSE;
9478 if (priv->mnemonics_visible != setting)
9480 priv->mnemonics_visible = setting;
9481 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9484 priv->mnemonics_visible_set = TRUE;
9488 _gtk_window_get_wmclass (GtkWindow *window,
9489 gchar **wmclass_name,
9490 gchar **wmclass_class)
9492 GtkWindowPrivate *priv = window->priv;
9494 *wmclass_name = priv->wmclass_name;
9495 *wmclass_class = priv->wmclass_class;
9499 * gtk_window_set_has_user_ref_count:
9500 * @window: a #GtkWindow
9501 * @setting: the new value
9503 * Tells GTK+ whether to drop its extra reference to the window
9504 * when gtk_window_destroy() is called.
9506 * This function is only exported for the benefit of language
9507 * bindings which may need to keep the window alive until their
9508 * wrapper object is garbage collected. There is no justification
9509 * for ever calling this function in an application.
9514 gtk_window_set_has_user_ref_count (GtkWindow *window,
9517 g_return_if_fail (GTK_IS_WINDOW (window));
9519 window->priv->has_user_ref_count = setting;