1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gtkwindow.h"
36 #include "gtkprivate.h"
37 #include "gtkwindowprivate.h"
38 #include "gtkaccelgroupprivate.h"
39 #include "gtkbindings.h"
40 #include "gtkkeyhash.h"
42 #include "gtkmnemonichash.h"
43 #include "gtkmenubar.h"
44 #include "gtkiconfactory.h"
45 #include "gtkicontheme.h"
46 #include "gtkmarshalers.h"
48 #include "gtkbuildable.h"
49 #include "gtkwidgetprivate.h"
50 #include "gtkcontainerprivate.h"
52 #include "gtktypebuiltins.h"
53 #include "a11y/gtkwindowaccessible.h"
55 #include "deprecated/gtkstyle.h"
57 #ifdef GDK_WINDOWING_X11
64 * @short_description: Toplevel which can contain other widgets
66 * A GtkWindow is a toplevel window which can contain other widgets.
67 * Windows normally have decorations that are under the control
68 * of the windowing system and allow the user to manipulate the window
69 * (resize it, move it, close it,...).
71 * GTK+ also allows windows to have a resize grip (a small area in the lower
72 * right or left corner) which can be clicked to reszie the window. To
73 * control whether a window has a resize grip, use
74 * gtk_window_set_has_resize_grip().
76 * <refsect2 id="GtkWindow-BUILDER-UI">
77 * <title>GtkWindow as GtkBuildable</title>
79 * The GtkWindow implementation of the GtkBuildable interface supports a
80 * custom <tag class="starttag">accel-groups</tag> element, which supports
81 * any number of <tag class="starttag">group</tag> elements representing the
82 * #GtkAccelGroup objects you want to add to your window (synonymous with
83 * gtk_window_add_accel_group().
86 * <title>A UI definition fragment with accel groups</title>
87 * <programlisting><![CDATA[
88 * <object class="GtkWindow">
90 * <group name="accelgroup1"/>
96 * <object class="GtkAccelGroup" id="accelgroup1"/>
97 * ]]></programlisting>
102 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
104 struct _GtkWindowPrivate
106 GtkMnemonicHash *mnemonic_hash;
108 GtkWidget *attach_widget;
109 GtkWidget *default_widget;
110 GtkWidget *focus_widget;
111 GtkWindow *transient_parent;
112 GtkWindowGeometryInfo *geometry_info;
113 GtkWindowGroup *group;
115 GtkApplication *application;
117 GdkModifierType mnemonic_modifier;
118 GdkWindowTypeHint gdk_type_hint;
122 GdkWindow *grip_window;
126 gchar *wmclass_class;
130 guint keys_changed_handler;
132 guint32 initial_timestamp;
134 guint16 configure_request_count;
136 /* The following flags are initially TRUE (before a window is mapped).
137 * They cause us to compute a configure request that involves
138 * default-only parameters. Once mapped, we set them to FALSE.
139 * Then we set them to TRUE again on unmap (for position)
140 * and on unrealize (for size).
142 guint need_default_position : 1;
143 guint need_default_size : 1;
145 guint above_initially : 1;
146 guint accept_focus : 1;
147 guint below_initially : 1;
148 guint builder_visible : 1;
149 guint configure_notify_received : 1;
152 guint destroy_with_parent : 1;
153 guint focus_on_map : 1;
154 guint fullscreen_initially : 1;
156 guint has_user_ref_count : 1;
157 guint has_toplevel_focus : 1;
158 guint hide_titlebar_when_maximized : 1;
159 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
161 guint maximize_initially : 1;
162 guint mnemonics_visible : 1;
163 guint mnemonics_visible_set : 1;
164 guint focus_visible : 1;
166 guint opacity_set : 1;
168 guint reset_type_hint : 1;
170 guint skips_pager : 1;
171 guint skips_taskbar : 1;
172 guint stick_initially : 1;
173 guint transient_parent_group : 1;
174 guint type : 4; /* GtkWindowType */
175 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
176 * one of the original eight. If not,
178 * GDK_WINDOW_TYPE_HINT_NORMAL
181 guint has_resize_grip : 1;
182 guint resize_grip_visible : 1; /* don't use, just for "resize-
183 * grip-visible" notification
185 guint gravity : 5; /* GdkGravity */
212 PROP_DESTROY_WITH_PARENT,
213 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
218 PROP_SKIP_TASKBAR_HINT,
219 PROP_SKIP_PAGER_HINT,
229 PROP_HAS_RESIZE_GRIP,
230 PROP_RESIZE_GRIP_VISIBLE,
232 /* Readonly properties */
234 PROP_HAS_TOPLEVEL_FOCUS,
236 /* Writeonly properties */
239 PROP_MNEMONICS_VISIBLE,
250 guint using_default_icon : 1;
251 guint using_parent_icon : 1;
252 guint using_themed_icon : 1;
256 GdkGeometry geometry; /* Last set of geometry hints we set */
257 GdkWindowHints flags;
258 GdkRectangle configure_request;
259 } GtkWindowLastGeometryInfo;
261 struct _GtkWindowGeometryInfo
263 /* Properties that the app has set on the window
265 GdkGeometry geometry; /* Geometry hints */
267 GtkWidget *widget; /* subwidget to which hints apply */
268 /* from last gtk_window_resize () - if > 0, indicates that
269 * we should resize to this size.
274 /* From last gtk_window_move () prior to mapping -
275 * only used if initial_pos_set
280 /* Default size - used only the FIRST time we map a window,
285 /* whether to use initial_x, initial_y */
286 guint initial_pos_set : 1;
287 /* CENTER_ALWAYS or other position constraint changed since
288 * we sent the last configure request.
290 guint position_constraints_changed : 1;
292 /* if true, default_width, height should be multiplied by the
293 * increments and affect the geometry widget only
295 guint default_is_geometry : 1;
297 /* if true, resize_width, height should be multiplied by the
298 * increments and affect the geometry widget only
300 guint resize_is_geometry : 1;
302 GtkWindowLastGeometryInfo last;
306 struct _GtkDeviceGrabInfo
310 guint block_others : 1;
313 struct _GtkWindowGroupPrivate
316 GSList *device_grabs;
319 static void gtk_window_dispose (GObject *object);
320 static void gtk_window_finalize (GObject *object);
321 static void gtk_window_destroy (GtkWidget *widget);
322 static void gtk_window_show (GtkWidget *widget);
323 static void gtk_window_hide (GtkWidget *widget);
324 static void gtk_window_map (GtkWidget *widget);
325 static void gtk_window_unmap (GtkWidget *widget);
326 static void gtk_window_realize (GtkWidget *widget);
327 static void gtk_window_unrealize (GtkWidget *widget);
328 static void gtk_window_size_allocate (GtkWidget *widget,
329 GtkAllocation *allocation);
330 static gboolean gtk_window_map_event (GtkWidget *widget,
332 static gint gtk_window_configure_event (GtkWidget *widget,
333 GdkEventConfigure *event);
334 static gint gtk_window_key_press_event (GtkWidget *widget,
336 static gint gtk_window_key_release_event (GtkWidget *widget,
338 static gint gtk_window_button_press_event (GtkWidget *widget,
339 GdkEventButton *event);
340 static gint gtk_window_enter_notify_event (GtkWidget *widget,
341 GdkEventCrossing *event);
342 static gint gtk_window_leave_notify_event (GtkWidget *widget,
343 GdkEventCrossing *event);
344 static gint gtk_window_focus_in_event (GtkWidget *widget,
345 GdkEventFocus *event);
346 static gint gtk_window_focus_out_event (GtkWidget *widget,
347 GdkEventFocus *event);
348 static void gtk_window_style_updated (GtkWidget *widget);
349 static gboolean gtk_window_state_event (GtkWidget *widget,
350 GdkEventWindowState *event);
351 static void gtk_window_check_resize (GtkContainer *container);
352 static gint gtk_window_focus (GtkWidget *widget,
353 GtkDirectionType direction);
354 static void gtk_window_move_focus (GtkWidget *widget,
355 GtkDirectionType dir);
356 static void gtk_window_real_set_focus (GtkWindow *window,
358 static void gtk_window_direction_changed (GtkWidget *widget,
359 GtkTextDirection prev_dir);
360 static void gtk_window_state_changed (GtkWidget *widget,
361 GtkStateType previous_state);
363 static void gtk_window_real_activate_default (GtkWindow *window);
364 static void gtk_window_real_activate_focus (GtkWindow *window);
365 static void gtk_window_keys_changed (GtkWindow *window);
366 static gint gtk_window_draw (GtkWidget *widget,
368 static void gtk_window_unset_transient_for (GtkWindow *window);
369 static void gtk_window_transient_parent_realized (GtkWidget *parent,
371 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
374 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
376 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
379 static void gtk_window_move_resize (GtkWindow *window);
380 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
382 GdkGeometry *geometry_b,
384 static void gtk_window_constrain_size (GtkWindow *window,
385 GdkGeometry *geometry,
391 static void gtk_window_constrain_position (GtkWindow *window,
396 static void gtk_window_compute_hints (GtkWindow *window,
397 GdkGeometry *new_geometry,
399 static void gtk_window_compute_configure_request (GtkWindow *window,
400 GdkRectangle *request,
401 GdkGeometry *geometry,
404 static void gtk_window_set_default_size_internal (GtkWindow *window,
405 gboolean change_width,
407 gboolean change_height,
409 gboolean is_geometry);
411 static void update_themed_icon (GtkIconTheme *theme,
413 static GList *icon_list_from_theme (GtkWidget *widget,
415 static void gtk_window_realize_icon (GtkWindow *window);
416 static void gtk_window_unrealize_icon (GtkWindow *window);
417 static void resize_grip_create_window (GtkWindow *window);
418 static void resize_grip_destroy_window (GtkWindow *window);
419 static void update_grip_visibility (GtkWindow *window);
421 static void gtk_window_notify_keys_changed (GtkWindow *window);
422 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
423 static void gtk_window_free_key_hash (GtkWindow *window);
424 static void gtk_window_on_composited_changed (GdkScreen *screen,
426 static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
429 static void gtk_window_set_theme_variant (GtkWindow *window);
431 static GSList *toplevel_list = NULL;
432 static guint window_signals[LAST_SIGNAL] = { 0 };
433 static GList *default_icon_list = NULL;
434 static gchar *default_icon_name = NULL;
435 static guint default_icon_serial = 0;
436 static gboolean disable_startup_notification = FALSE;
437 static gboolean sent_startup_notification = FALSE;
439 static GQuark quark_gtk_embedded = 0;
440 static GQuark quark_gtk_window_key_hash = 0;
441 static GQuark quark_gtk_window_icon_info = 0;
442 static GQuark quark_gtk_buildable_accels = 0;
444 static GtkBuildableIface *parent_buildable_iface;
446 static void gtk_window_set_property (GObject *object,
450 static void gtk_window_get_property (GObject *object,
456 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
457 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
460 const GValue *value);
461 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
462 GtkBuilder *builder);
463 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
466 const gchar *tagname,
467 GMarkupParser *parser,
469 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
472 const gchar *tagname,
476 static void gtk_window_get_preferred_width (GtkWidget *widget,
479 static void gtk_window_get_preferred_height (GtkWidget *widget,
483 static void ensure_state_flag_backdrop (GtkWidget *widget);
485 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
486 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
487 gtk_window_buildable_interface_init))
490 add_tab_bindings (GtkBindingSet *binding_set,
491 GdkModifierType modifiers,
492 GtkDirectionType direction)
494 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
496 GTK_TYPE_DIRECTION_TYPE, direction);
497 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
499 GTK_TYPE_DIRECTION_TYPE, direction);
503 add_arrow_bindings (GtkBindingSet *binding_set,
505 GtkDirectionType direction)
507 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
509 gtk_binding_entry_add_signal (binding_set, keysym, 0,
511 GTK_TYPE_DIRECTION_TYPE, direction);
512 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
514 GTK_TYPE_DIRECTION_TYPE, direction);
515 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
517 GTK_TYPE_DIRECTION_TYPE, direction);
518 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
520 GTK_TYPE_DIRECTION_TYPE, direction);
524 extract_time_from_startup_id (const gchar* startup_id)
526 gchar *timestr = g_strrstr (startup_id, "_TIME");
527 guint32 retval = GDK_CURRENT_TIME;
534 /* Skip past the "_TIME" part */
539 timestamp = g_ascii_strtoull (timestr, &end, 0);
540 if (errno == 0 && end != timestr)
548 startup_id_is_fake (const gchar* startup_id)
550 return strncmp (startup_id, "_TIME", 5) == 0;
554 gtk_window_class_init (GtkWindowClass *klass)
556 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
557 GtkWidgetClass *widget_class;
558 GtkContainerClass *container_class;
559 GtkBindingSet *binding_set;
561 widget_class = (GtkWidgetClass*) klass;
562 container_class = (GtkContainerClass*) klass;
564 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
565 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
566 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
567 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
569 gobject_class->dispose = gtk_window_dispose;
570 gobject_class->finalize = gtk_window_finalize;
572 gobject_class->set_property = gtk_window_set_property;
573 gobject_class->get_property = gtk_window_get_property;
575 widget_class->destroy = gtk_window_destroy;
576 widget_class->show = gtk_window_show;
577 widget_class->hide = gtk_window_hide;
578 widget_class->map = gtk_window_map;
579 widget_class->map_event = gtk_window_map_event;
580 widget_class->unmap = gtk_window_unmap;
581 widget_class->realize = gtk_window_realize;
582 widget_class->unrealize = gtk_window_unrealize;
583 widget_class->size_allocate = gtk_window_size_allocate;
584 widget_class->configure_event = gtk_window_configure_event;
585 widget_class->key_press_event = gtk_window_key_press_event;
586 widget_class->key_release_event = gtk_window_key_release_event;
587 widget_class->enter_notify_event = gtk_window_enter_notify_event;
588 widget_class->leave_notify_event = gtk_window_leave_notify_event;
589 widget_class->focus_in_event = gtk_window_focus_in_event;
590 widget_class->button_press_event = gtk_window_button_press_event;
591 widget_class->focus_out_event = gtk_window_focus_out_event;
592 widget_class->focus = gtk_window_focus;
593 widget_class->move_focus = gtk_window_move_focus;
594 widget_class->draw = gtk_window_draw;
595 widget_class->get_preferred_width = gtk_window_get_preferred_width;
596 widget_class->get_preferred_height = gtk_window_get_preferred_height;
597 widget_class->window_state_event = gtk_window_state_event;
598 widget_class->direction_changed = gtk_window_direction_changed;
599 widget_class->state_changed = gtk_window_state_changed;
600 widget_class->style_updated = gtk_window_style_updated;
602 container_class->check_resize = gtk_window_check_resize;
604 klass->set_focus = gtk_window_real_set_focus;
606 klass->activate_default = gtk_window_real_activate_default;
607 klass->activate_focus = gtk_window_real_activate_focus;
608 klass->keys_changed = gtk_window_keys_changed;
610 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
613 g_object_class_install_property (gobject_class,
615 g_param_spec_enum ("type",
617 P_("The type of the window"),
618 GTK_TYPE_WINDOW_TYPE,
620 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
622 g_object_class_install_property (gobject_class,
624 g_param_spec_string ("title",
626 P_("The title of the window"),
628 GTK_PARAM_READWRITE));
630 g_object_class_install_property (gobject_class,
632 g_param_spec_string ("role",
634 P_("Unique identifier for the window to be used when restoring a session"),
636 GTK_PARAM_READWRITE));
639 * GtkWindow:startup-id:
641 * The :startup-id is a write-only property for setting window's
642 * startup notification identifier. See gtk_window_set_startup_id()
647 g_object_class_install_property (gobject_class,
649 g_param_spec_string ("startup-id",
651 P_("Unique startup identifier for the window used by startup-notification"),
653 GTK_PARAM_WRITABLE));
655 g_object_class_install_property (gobject_class,
657 g_param_spec_boolean ("resizable",
659 P_("If TRUE, users can resize the window"),
661 GTK_PARAM_READWRITE));
663 g_object_class_install_property (gobject_class,
665 g_param_spec_boolean ("modal",
667 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
669 GTK_PARAM_READWRITE));
671 g_object_class_install_property (gobject_class,
673 g_param_spec_enum ("window-position",
674 P_("Window Position"),
675 P_("The initial position of the window"),
676 GTK_TYPE_WINDOW_POSITION,
678 GTK_PARAM_READWRITE));
680 g_object_class_install_property (gobject_class,
682 g_param_spec_int ("default-width",
684 P_("The default width of the window, used when initially showing the window"),
688 GTK_PARAM_READWRITE));
690 g_object_class_install_property (gobject_class,
692 g_param_spec_int ("default-height",
693 P_("Default Height"),
694 P_("The default height of the window, used when initially showing the window"),
698 GTK_PARAM_READWRITE));
700 g_object_class_install_property (gobject_class,
701 PROP_DESTROY_WITH_PARENT,
702 g_param_spec_boolean ("destroy-with-parent",
703 P_("Destroy with Parent"),
704 P_("If this window should be destroyed when the parent is destroyed"),
706 GTK_PARAM_READWRITE));
709 * GtkWindow:hide-titlebar-when-maximized:
711 * Whether the titlebar should be hidden during maximization.
715 g_object_class_install_property (gobject_class,
716 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
717 g_param_spec_boolean ("hide-titlebar-when-maximized",
718 P_("Hide the titlebar during maximization"),
719 P_("If this window's titlebar should be hidden when the window is maximized"),
721 GTK_PARAM_READWRITE));
723 g_object_class_install_property (gobject_class,
725 g_param_spec_object ("icon",
727 P_("Icon for this window"),
729 GTK_PARAM_READWRITE));
732 * GtkWindow:mnemonics-visible:
734 * Whether mnemonics are currently visible in this window.
736 * This property is maintained by GTK+ based on the
737 * #GtkSettings:gtk-auto-mnemonics setting and user input,
738 * and should not be set by applications.
742 g_object_class_install_property (gobject_class,
743 PROP_MNEMONICS_VISIBLE,
744 g_param_spec_boolean ("mnemonics-visible",
745 P_("Mnemonics Visible"),
746 P_("Whether mnemonics are currently visible in this window"),
748 GTK_PARAM_READWRITE));
751 * GtkWindow:focus-visible:
753 * Whether 'focus rectangles' are currently visible in this window.
755 * This property is maintained by GTK+ based on the
756 * #GtkSettings:gtk-visible-focus setting and user input
757 * and should not be set by applications.
761 g_object_class_install_property (gobject_class,
763 g_param_spec_boolean ("focus-visible",
765 P_("Whether focus rectangles are currently visible in this window"),
767 GTK_PARAM_READWRITE));
770 * GtkWindow:icon-name:
772 * The :icon-name property specifies the name of the themed icon to
773 * use as the window icon. See #GtkIconTheme for more details.
777 g_object_class_install_property (gobject_class,
779 g_param_spec_string ("icon-name",
781 P_("Name of the themed icon for this window"),
783 GTK_PARAM_READWRITE));
785 g_object_class_install_property (gobject_class,
787 g_param_spec_object ("screen",
789 P_("The screen where this window will be displayed"),
791 GTK_PARAM_READWRITE));
793 g_object_class_install_property (gobject_class,
795 g_param_spec_boolean ("is-active",
797 P_("Whether the toplevel is the current active window"),
799 GTK_PARAM_READABLE));
801 g_object_class_install_property (gobject_class,
802 PROP_HAS_TOPLEVEL_FOCUS,
803 g_param_spec_boolean ("has-toplevel-focus",
804 P_("Focus in Toplevel"),
805 P_("Whether the input focus is within this GtkWindow"),
807 GTK_PARAM_READABLE));
809 g_object_class_install_property (gobject_class,
811 g_param_spec_enum ("type-hint",
813 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
814 GDK_TYPE_WINDOW_TYPE_HINT,
815 GDK_WINDOW_TYPE_HINT_NORMAL,
816 GTK_PARAM_READWRITE));
818 g_object_class_install_property (gobject_class,
819 PROP_SKIP_TASKBAR_HINT,
820 g_param_spec_boolean ("skip-taskbar-hint",
822 P_("TRUE if the window should not be in the task bar."),
824 GTK_PARAM_READWRITE));
826 g_object_class_install_property (gobject_class,
827 PROP_SKIP_PAGER_HINT,
828 g_param_spec_boolean ("skip-pager-hint",
830 P_("TRUE if the window should not be in the pager."),
832 GTK_PARAM_READWRITE));
834 g_object_class_install_property (gobject_class,
836 g_param_spec_boolean ("urgency-hint",
838 P_("TRUE if the window should be brought to the user's attention."),
840 GTK_PARAM_READWRITE));
843 * GtkWindow:accept-focus:
845 * Whether the window should receive the input focus.
849 g_object_class_install_property (gobject_class,
851 g_param_spec_boolean ("accept-focus",
853 P_("TRUE if the window should receive the input focus."),
855 GTK_PARAM_READWRITE));
858 * GtkWindow:focus-on-map:
860 * Whether the window should receive the input focus when mapped.
864 g_object_class_install_property (gobject_class,
866 g_param_spec_boolean ("focus-on-map",
868 P_("TRUE if the window should receive the input focus when mapped."),
870 GTK_PARAM_READWRITE));
873 * GtkWindow:decorated:
875 * Whether the window should be decorated by the window manager.
879 g_object_class_install_property (gobject_class,
881 g_param_spec_boolean ("decorated",
883 P_("Whether the window should be decorated by the window manager"),
885 GTK_PARAM_READWRITE));
888 * GtkWindow:deletable:
890 * Whether the window frame should have a close button.
894 g_object_class_install_property (gobject_class,
896 g_param_spec_boolean ("deletable",
898 P_("Whether the window frame should have a close button"),
900 GTK_PARAM_READWRITE));
903 * GtkWindow:has-resize-grip
905 * Whether the window has a corner resize grip.
907 * Note that the resize grip is only shown if the window is
908 * actually resizable and not maximized. Use
909 * #GtkWindow:resize-grip-visible to find out if the resize
910 * grip is currently shown.
914 g_object_class_install_property (gobject_class,
915 PROP_HAS_RESIZE_GRIP,
916 g_param_spec_boolean ("has-resize-grip",
918 P_("Specifies whether the window should have a resize grip"),
920 GTK_PARAM_READWRITE));
923 * GtkWindow:resize-grip-visible:
925 * Whether a corner resize grip is currently shown.
929 g_object_class_install_property (gobject_class,
930 PROP_RESIZE_GRIP_VISIBLE,
931 g_param_spec_boolean ("resize-grip-visible",
932 P_("Resize grip is visible"),
933 P_("Specifies whether the window's resize grip is visible."),
935 GTK_PARAM_READABLE));
941 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
942 * more details about window gravity.
946 g_object_class_install_property (gobject_class,
948 g_param_spec_enum ("gravity",
950 P_("The window gravity of the window"),
952 GDK_GRAVITY_NORTH_WEST,
953 GTK_PARAM_READWRITE));
957 * GtkWindow:transient-for:
959 * The transient parent of the window. See gtk_window_set_transient_for() for
960 * more details about transient windows.
964 g_object_class_install_property (gobject_class,
966 g_param_spec_object ("transient-for",
967 P_("Transient for Window"),
968 P_("The transient parent of the dialog"),
970 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
973 * GtkWindow:attached-to:
975 * the widget attached to the window.
979 g_object_class_install_property (gobject_class,
981 g_param_spec_object ("attached-to",
982 P_("Attached to Widget"),
983 P_("The widget where the window is attached"),
985 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
990 * The requested opacity of the window. See gtk_window_set_opacity() for
991 * more details about window opacity.
995 g_object_class_install_property (gobject_class,
997 g_param_spec_double ("opacity",
998 P_("Opacity for Window"),
999 P_("The opacity of the window, from 0 to 1"),
1003 GTK_PARAM_READWRITE));
1005 /* Style properties.
1007 gtk_widget_class_install_style_property (widget_class,
1008 g_param_spec_int ("resize-grip-width",
1009 P_("Width of resize grip"),
1010 P_("Width of resize grip"),
1011 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1013 gtk_widget_class_install_style_property (widget_class,
1014 g_param_spec_int ("resize-grip-height",
1015 P_("Height of resize grip"),
1016 P_("Height of resize grip"),
1017 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
1021 * GtkWindow:application:
1023 * The #GtkApplication associated with the window.
1025 * The application will be kept alive for at least as long as it
1026 * has any windows associated with it (see g_application_hold()
1027 * for a way to keep it alive without windows).
1029 * Normally, the connection between the application and the window
1030 * will remain until the window is destroyed, but you can explicitly
1031 * remove it by setting the ::application property to %NULL.
1035 g_object_class_install_property (gobject_class,
1037 g_param_spec_object ("application",
1038 P_("GtkApplication"),
1039 P_("The GtkApplication for the window"),
1040 GTK_TYPE_APPLICATION,
1041 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
1043 window_signals[SET_FOCUS] =
1044 g_signal_new (I_("set-focus"),
1045 G_TYPE_FROM_CLASS (gobject_class),
1047 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1049 _gtk_marshal_VOID__OBJECT,
1054 * GtkWindow::activate-focus:
1055 * @window: the window which received the signal
1057 * The ::activate-focus signal is a
1058 * <link linkend="keybinding-signals">keybinding signal</link>
1059 * which gets emitted when the user activates the currently
1060 * focused widget of @window.
1062 window_signals[ACTIVATE_FOCUS] =
1063 g_signal_new (I_("activate-focus"),
1064 G_TYPE_FROM_CLASS (gobject_class),
1065 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1066 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1068 _gtk_marshal_VOID__VOID,
1073 * GtkWindow::activate-default:
1074 * @window: the window which received the signal
1076 * The ::activate-default signal is a
1077 * <link linkend="keybinding-signals">keybinding signal</link>
1078 * which gets emitted when the user activates the default widget
1081 window_signals[ACTIVATE_DEFAULT] =
1082 g_signal_new (I_("activate-default"),
1083 G_TYPE_FROM_CLASS (gobject_class),
1084 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1085 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1087 _gtk_marshal_VOID__VOID,
1092 * GtkWindow::keys-changed:
1093 * @window: the window which received the signal
1095 * The ::keys-changed signal gets emitted when the set of accelerators
1096 * or mnemonics that are associated with @window changes.
1098 window_signals[KEYS_CHANGED] =
1099 g_signal_new (I_("keys-changed"),
1100 G_TYPE_FROM_CLASS (gobject_class),
1102 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1104 _gtk_marshal_VOID__VOID,
1112 binding_set = gtk_binding_set_by_class (klass);
1114 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1115 "activate-focus", 0);
1116 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1117 "activate-focus", 0);
1119 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1120 "activate-default", 0);
1121 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1122 "activate-default", 0);
1123 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1124 "activate-default", 0);
1126 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1127 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1128 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1129 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1131 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1132 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1133 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1134 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1136 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1140 gtk_window_init (GtkWindow *window)
1142 GtkWindowPrivate *priv;
1144 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1147 priv = window->priv;
1149 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1150 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1152 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1154 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1157 priv->wmclass_name = g_strdup (g_get_prgname ());
1158 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1159 priv->wm_role = NULL;
1160 priv->geometry_info = NULL;
1161 priv->type = GTK_WINDOW_TOPLEVEL;
1162 priv->focus_widget = NULL;
1163 priv->default_widget = NULL;
1164 priv->configure_request_count = 0;
1165 priv->resizable = TRUE;
1166 priv->configure_notify_received = FALSE;
1167 priv->position = GTK_WIN_POS_NONE;
1168 priv->need_default_size = TRUE;
1169 priv->need_default_position = TRUE;
1170 priv->modal = FALSE;
1171 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1172 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1173 priv->decorated = TRUE;
1174 priv->mnemonic_modifier = GDK_MOD1_MASK;
1175 priv->screen = gdk_screen_get_default ();
1177 priv->accept_focus = TRUE;
1178 priv->focus_on_map = TRUE;
1179 priv->deletable = TRUE;
1180 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1181 priv->opacity = 1.0;
1182 priv->startup_id = NULL;
1183 priv->initial_timestamp = GDK_CURRENT_TIME;
1184 priv->has_resize_grip = TRUE;
1185 priv->mnemonics_visible = TRUE;
1186 priv->focus_visible = TRUE;
1188 g_object_ref_sink (window);
1189 priv->has_user_ref_count = TRUE;
1190 toplevel_list = g_slist_prepend (toplevel_list, window);
1193 g_signal_connect (priv->screen, "composited-changed",
1194 G_CALLBACK (gtk_window_on_composited_changed), window);
1196 #ifdef GDK_WINDOWING_X11
1197 g_signal_connect (gtk_settings_get_for_screen (priv->screen),
1198 "notify::gtk-application-prefer-dark-theme",
1199 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
1204 gtk_window_set_property (GObject *object,
1206 const GValue *value,
1209 GtkWindow *window = GTK_WINDOW (object);
1210 GtkWindowPrivate *priv = window->priv;
1215 priv->type = g_value_get_enum (value);
1218 gtk_window_set_title (window, g_value_get_string (value));
1221 gtk_window_set_role (window, g_value_get_string (value));
1223 case PROP_STARTUP_ID:
1224 gtk_window_set_startup_id (window, g_value_get_string (value));
1226 case PROP_RESIZABLE:
1227 gtk_window_set_resizable (window, g_value_get_boolean (value));
1230 gtk_window_set_modal (window, g_value_get_boolean (value));
1233 gtk_window_set_position (window, g_value_get_enum (value));
1235 case PROP_DEFAULT_WIDTH:
1236 gtk_window_set_default_size_internal (window,
1237 TRUE, g_value_get_int (value),
1240 case PROP_DEFAULT_HEIGHT:
1241 gtk_window_set_default_size_internal (window,
1243 TRUE, g_value_get_int (value), FALSE);
1245 case PROP_DESTROY_WITH_PARENT:
1246 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1248 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1249 gtk_window_set_hide_titlebar_when_maximized (window, g_value_get_boolean (value));
1252 gtk_window_set_icon (window,
1253 g_value_get_object (value));
1255 case PROP_ICON_NAME:
1256 gtk_window_set_icon_name (window, g_value_get_string (value));
1259 gtk_window_set_screen (window, g_value_get_object (value));
1261 case PROP_TYPE_HINT:
1262 gtk_window_set_type_hint (window,
1263 g_value_get_enum (value));
1265 case PROP_SKIP_TASKBAR_HINT:
1266 gtk_window_set_skip_taskbar_hint (window,
1267 g_value_get_boolean (value));
1269 case PROP_SKIP_PAGER_HINT:
1270 gtk_window_set_skip_pager_hint (window,
1271 g_value_get_boolean (value));
1273 case PROP_URGENCY_HINT:
1274 gtk_window_set_urgency_hint (window,
1275 g_value_get_boolean (value));
1277 case PROP_ACCEPT_FOCUS:
1278 gtk_window_set_accept_focus (window,
1279 g_value_get_boolean (value));
1281 case PROP_FOCUS_ON_MAP:
1282 gtk_window_set_focus_on_map (window,
1283 g_value_get_boolean (value));
1285 case PROP_DECORATED:
1286 gtk_window_set_decorated (window, g_value_get_boolean (value));
1288 case PROP_DELETABLE:
1289 gtk_window_set_deletable (window, g_value_get_boolean (value));
1292 gtk_window_set_gravity (window, g_value_get_enum (value));
1294 case PROP_TRANSIENT_FOR:
1295 gtk_window_set_transient_for (window, g_value_get_object (value));
1297 case PROP_ATTACHED_TO:
1298 gtk_window_set_attached_to (window, g_value_get_object (value));
1301 gtk_window_set_opacity (window, g_value_get_double (value));
1303 case PROP_HAS_RESIZE_GRIP:
1304 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1306 case PROP_APPLICATION:
1307 gtk_window_set_application (window, g_value_get_object (value));
1309 case PROP_MNEMONICS_VISIBLE:
1310 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1312 case PROP_FOCUS_VISIBLE:
1313 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1316 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1322 gtk_window_get_property (GObject *object,
1327 GtkWindow *window = GTK_WINDOW (object);
1328 GtkWindowPrivate *priv = window->priv;
1332 GtkWindowGeometryInfo *info;
1334 g_value_set_enum (value, priv->type);
1337 g_value_set_string (value, priv->wm_role);
1340 g_value_set_string (value, priv->title);
1342 case PROP_RESIZABLE:
1343 g_value_set_boolean (value, priv->resizable);
1346 g_value_set_boolean (value, priv->modal);
1349 g_value_set_enum (value, priv->position);
1351 case PROP_DEFAULT_WIDTH:
1352 info = gtk_window_get_geometry_info (window, FALSE);
1354 g_value_set_int (value, -1);
1356 g_value_set_int (value, info->default_width);
1358 case PROP_DEFAULT_HEIGHT:
1359 info = gtk_window_get_geometry_info (window, FALSE);
1361 g_value_set_int (value, -1);
1363 g_value_set_int (value, info->default_height);
1365 case PROP_DESTROY_WITH_PARENT:
1366 g_value_set_boolean (value, priv->destroy_with_parent);
1368 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1369 g_value_set_boolean (value, priv->hide_titlebar_when_maximized);
1372 g_value_set_object (value, gtk_window_get_icon (window));
1374 case PROP_ICON_NAME:
1375 g_value_set_string (value, gtk_window_get_icon_name (window));
1378 g_value_set_object (value, priv->screen);
1380 case PROP_IS_ACTIVE:
1381 g_value_set_boolean (value, priv->is_active);
1383 case PROP_HAS_TOPLEVEL_FOCUS:
1384 g_value_set_boolean (value, priv->has_toplevel_focus);
1386 case PROP_TYPE_HINT:
1387 g_value_set_enum (value, priv->type_hint);
1389 case PROP_SKIP_TASKBAR_HINT:
1390 g_value_set_boolean (value,
1391 gtk_window_get_skip_taskbar_hint (window));
1393 case PROP_SKIP_PAGER_HINT:
1394 g_value_set_boolean (value,
1395 gtk_window_get_skip_pager_hint (window));
1397 case PROP_URGENCY_HINT:
1398 g_value_set_boolean (value,
1399 gtk_window_get_urgency_hint (window));
1401 case PROP_ACCEPT_FOCUS:
1402 g_value_set_boolean (value,
1403 gtk_window_get_accept_focus (window));
1405 case PROP_FOCUS_ON_MAP:
1406 g_value_set_boolean (value,
1407 gtk_window_get_focus_on_map (window));
1409 case PROP_DECORATED:
1410 g_value_set_boolean (value, gtk_window_get_decorated (window));
1412 case PROP_DELETABLE:
1413 g_value_set_boolean (value, gtk_window_get_deletable (window));
1416 g_value_set_enum (value, gtk_window_get_gravity (window));
1418 case PROP_TRANSIENT_FOR:
1419 g_value_set_object (value, gtk_window_get_transient_for (window));
1421 case PROP_ATTACHED_TO:
1422 g_value_set_object (value, gtk_window_get_attached_to (window));
1425 g_value_set_double (value, gtk_window_get_opacity (window));
1427 case PROP_HAS_RESIZE_GRIP:
1428 g_value_set_boolean (value, priv->has_resize_grip);
1430 case PROP_RESIZE_GRIP_VISIBLE:
1431 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1433 case PROP_APPLICATION:
1434 g_value_set_object (value, gtk_window_get_application (window));
1436 case PROP_MNEMONICS_VISIBLE:
1437 g_value_set_boolean (value, priv->mnemonics_visible);
1439 case PROP_FOCUS_VISIBLE:
1440 g_value_set_boolean (value, priv->focus_visible);
1443 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1449 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1451 parent_buildable_iface = g_type_interface_peek_parent (iface);
1452 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1453 iface->parser_finished = gtk_window_buildable_parser_finished;
1454 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1455 iface->custom_finished = gtk_window_buildable_custom_finished;
1459 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1460 GtkBuilder *builder,
1462 const GValue *value)
1464 GtkWindow *window = GTK_WINDOW (buildable);
1465 GtkWindowPrivate *priv = window->priv;
1467 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1468 priv->builder_visible = TRUE;
1470 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1474 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1475 GtkBuilder *builder)
1477 GtkWindow *window = GTK_WINDOW (buildable);
1478 GtkWindowPrivate *priv = window->priv;
1482 if (priv->builder_visible)
1483 gtk_widget_show (GTK_WIDGET (buildable));
1485 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1486 for (l = accels; l; l = l->next)
1488 object = gtk_builder_get_object (builder, l->data);
1491 g_warning ("Unknown accel group %s specified in window %s",
1492 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1495 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1496 GTK_ACCEL_GROUP (object));
1500 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1502 parent_buildable_iface->parser_finished (buildable, builder);
1508 } GSListSubParserData;
1511 window_start_element (GMarkupParseContext *context,
1512 const gchar *element_name,
1513 const gchar **names,
1514 const gchar **values,
1519 GSListSubParserData *data = (GSListSubParserData*)user_data;
1521 if (strcmp (element_name, "group") == 0)
1523 for (i = 0; names[i]; i++)
1525 if (strcmp (names[i], "name") == 0)
1526 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1529 else if (strcmp (element_name, "accel-groups") == 0)
1532 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1537 static const GMarkupParser window_parser =
1539 window_start_element
1543 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1544 GtkBuilder *builder,
1546 const gchar *tagname,
1547 GMarkupParser *parser,
1550 GSListSubParserData *parser_data;
1552 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1553 tagname, parser, data))
1556 if (strcmp (tagname, "accel-groups") == 0)
1558 parser_data = g_slice_new0 (GSListSubParserData);
1559 parser_data->items = NULL;
1560 parser_data->object = G_OBJECT (buildable);
1562 *parser = window_parser;
1563 *data = parser_data;
1571 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1572 GtkBuilder *builder,
1574 const gchar *tagname,
1577 GSListSubParserData *data;
1579 parent_buildable_iface->custom_finished (buildable, builder, child,
1580 tagname, user_data);
1582 if (strcmp (tagname, "accel-groups") != 0)
1585 data = (GSListSubParserData*)user_data;
1587 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1588 data->items, (GDestroyNotify) g_slist_free);
1590 g_slice_free (GSListSubParserData, data);
1595 * @type: type of window
1597 * Creates a new #GtkWindow, which is a toplevel window that can
1598 * contain other widgets. Nearly always, the type of the window should
1599 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1600 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1601 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1602 * dialogs, though in some other toolkits dialogs are called "popups".
1603 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1604 * On X11, popup windows are not controlled by the <link
1605 * linkend="gtk-X11-arch">window manager</link>.
1607 * If you simply want an undecorated window (no window borders), use
1608 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1610 * Return value: a new #GtkWindow.
1613 gtk_window_new (GtkWindowType type)
1615 GtkWindowPrivate *priv;
1618 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1620 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1621 priv = window->priv;
1625 return GTK_WIDGET (window);
1629 * gtk_window_set_title:
1630 * @window: a #GtkWindow
1631 * @title: title of the window
1633 * Sets the title of the #GtkWindow. The title of a window will be
1634 * displayed in its title bar; on the X Window System, the title bar
1635 * is rendered by the <link linkend="gtk-X11-arch">window
1636 * manager</link>, so exactly how the title appears to users may vary
1637 * according to a user's exact configuration. The title should help a
1638 * user distinguish this window from other windows they may have
1639 * open. A good title might include the application name and current
1640 * document filename, for example.
1644 gtk_window_set_title (GtkWindow *window,
1647 GtkWindowPrivate *priv;
1651 g_return_if_fail (GTK_IS_WINDOW (window));
1653 priv = window->priv;
1654 widget = GTK_WIDGET (window);
1656 new_title = g_strdup (title);
1657 g_free (priv->title);
1658 priv->title = new_title;
1660 if (gtk_widget_get_realized (widget))
1662 gdk_window_set_title (gtk_widget_get_window (widget),
1666 g_object_notify (G_OBJECT (window), "title");
1670 * gtk_window_get_title:
1671 * @window: a #GtkWindow
1673 * Retrieves the title of the window. See gtk_window_set_title().
1675 * Return value: the title of the window, or %NULL if none has
1676 * been set explicitely. The returned string is owned by the widget
1677 * and must not be modified or freed.
1680 gtk_window_get_title (GtkWindow *window)
1682 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1684 return window->priv->title;
1688 * gtk_window_set_wmclass:
1689 * @window: a #GtkWindow
1690 * @wmclass_name: window name hint
1691 * @wmclass_class: window class hint
1693 * Don't use this function. It sets the X Window System "class" and
1694 * "name" hints for a window. According to the ICCCM, you should
1695 * always set these to the same value for all windows in an
1696 * application, and GTK+ sets them to that value by default, so calling
1697 * this function is sort of pointless. However, you may want to call
1698 * gtk_window_set_role() on each window in your application, for the
1699 * benefit of the session manager. Setting the role allows the window
1700 * manager to restore window positions when loading a saved session.
1704 gtk_window_set_wmclass (GtkWindow *window,
1705 const gchar *wmclass_name,
1706 const gchar *wmclass_class)
1708 GtkWindowPrivate *priv;
1710 g_return_if_fail (GTK_IS_WINDOW (window));
1712 priv = window->priv;
1714 g_free (priv->wmclass_name);
1715 priv->wmclass_name = g_strdup (wmclass_name);
1717 g_free (priv->wmclass_class);
1718 priv->wmclass_class = g_strdup (wmclass_class);
1720 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1721 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1725 * gtk_window_set_role:
1726 * @window: a #GtkWindow
1727 * @role: unique identifier for the window to be used when restoring a session
1729 * This function is only useful on X11, not with other GTK+ targets.
1731 * In combination with the window title, the window role allows a
1732 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1733 * same" window when an application is restarted. So for example you
1734 * might set the "toolbox" role on your app's toolbox window, so that
1735 * when the user restarts their session, the window manager can put
1736 * the toolbox back in the same place.
1738 * If a window already has a unique title, you don't need to set the
1739 * role, since the WM can use the title to identify the window when
1740 * restoring the session.
1744 gtk_window_set_role (GtkWindow *window,
1747 GtkWindowPrivate *priv;
1750 g_return_if_fail (GTK_IS_WINDOW (window));
1752 priv = window->priv;
1754 new_role = g_strdup (role);
1755 g_free (priv->wm_role);
1756 priv->wm_role = new_role;
1758 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1759 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1762 g_object_notify (G_OBJECT (window), "role");
1766 * gtk_window_set_startup_id:
1767 * @window: a #GtkWindow
1768 * @startup_id: a string with startup-notification identifier
1770 * Startup notification identifiers are used by desktop environment to
1771 * track application startup, to provide user feedback and other
1772 * features. This function changes the corresponding property on the
1773 * underlying GdkWindow. Normally, startup identifier is managed
1774 * automatically and you should only use this function in special cases
1775 * like transferring focus from other processes. You should use this
1776 * function before calling gtk_window_present() or any equivalent
1777 * function generating a window map event.
1779 * This function is only useful on X11, not with other GTK+ targets.
1784 gtk_window_set_startup_id (GtkWindow *window,
1785 const gchar *startup_id)
1787 GtkWindowPrivate *priv;
1790 g_return_if_fail (GTK_IS_WINDOW (window));
1792 priv = window->priv;
1793 widget = GTK_WIDGET (window);
1795 g_free (priv->startup_id);
1796 priv->startup_id = g_strdup (startup_id);
1798 if (gtk_widget_get_realized (widget))
1800 GdkWindow *gdk_window;
1801 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1803 gdk_window = gtk_widget_get_window (widget);
1805 #ifdef GDK_WINDOWING_X11
1806 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
1807 gdk_x11_window_set_user_time (gdk_window, timestamp);
1810 /* Here we differentiate real and "fake" startup notification IDs,
1811 * constructed on purpose just to pass interaction timestamp
1813 if (startup_id_is_fake (priv->startup_id))
1814 gtk_window_present_with_time (window, timestamp);
1817 gdk_window_set_startup_id (gdk_window,
1820 /* If window is mapped, terminate the startup-notification too */
1821 if (gtk_widget_get_mapped (widget) &&
1822 !disable_startup_notification)
1823 gdk_notify_startup_complete_with_id (priv->startup_id);
1827 g_object_notify (G_OBJECT (window), "startup-id");
1831 * gtk_window_get_role:
1832 * @window: a #GtkWindow
1834 * Returns the role of the window. See gtk_window_set_role() for
1835 * further explanation.
1837 * Return value: the role of the window if set, or %NULL. The
1838 * returned is owned by the widget and must not be modified
1842 gtk_window_get_role (GtkWindow *window)
1844 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1846 return window->priv->wm_role;
1850 * gtk_window_set_focus:
1851 * @window: a #GtkWindow
1852 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1853 * any focus widget for the toplevel window.
1855 * If @focus is not the current focus widget, and is focusable, sets
1856 * it as the focus widget for the window. If @focus is %NULL, unsets
1857 * the focus widget for this window. To set the focus to a particular
1858 * widget in the toplevel, it is usually more convenient to use
1859 * gtk_widget_grab_focus() instead of this function.
1862 gtk_window_set_focus (GtkWindow *window,
1865 GtkWindowPrivate *priv;
1868 g_return_if_fail (GTK_IS_WINDOW (window));
1870 priv = window->priv;
1874 g_return_if_fail (GTK_IS_WIDGET (focus));
1875 g_return_if_fail (gtk_widget_get_can_focus (focus));
1879 gtk_widget_grab_focus (focus);
1882 /* Clear the existing focus chain, so that when we focus into
1883 * the window again, we start at the beginnning.
1885 GtkWidget *widget = priv->focus_widget;
1888 while ((parent = gtk_widget_get_parent (widget)))
1891 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1895 _gtk_window_internal_set_focus (window, NULL);
1900 _gtk_window_internal_set_focus (GtkWindow *window,
1903 GtkWindowPrivate *priv;
1905 g_return_if_fail (GTK_IS_WINDOW (window));
1907 priv = window->priv;
1909 if ((priv->focus_widget != focus) ||
1910 (focus && !gtk_widget_has_focus (focus)))
1911 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1915 * gtk_window_set_default:
1916 * @window: a #GtkWindow
1917 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1918 * default widget for the toplevel.
1920 * The default widget is the widget that's activated when the user
1921 * presses Enter in a dialog (for example). This function sets or
1922 * unsets the default widget for a #GtkWindow about. When setting
1923 * (rather than unsetting) the default widget it's generally easier to
1924 * call gtk_widget_grab_focus() on the widget. Before making a widget
1925 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1926 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1929 gtk_window_set_default (GtkWindow *window,
1930 GtkWidget *default_widget)
1932 GtkWindowPrivate *priv;
1934 g_return_if_fail (GTK_IS_WINDOW (window));
1936 priv = window->priv;
1939 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1941 if (priv->default_widget != default_widget)
1943 GtkWidget *old_default_widget = NULL;
1946 g_object_ref (default_widget);
1948 if (priv->default_widget)
1950 old_default_widget = priv->default_widget;
1952 if (priv->focus_widget != priv->default_widget ||
1953 !gtk_widget_get_receives_default (priv->default_widget))
1954 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1956 gtk_widget_queue_draw (priv->default_widget);
1959 priv->default_widget = default_widget;
1961 if (priv->default_widget)
1963 if (priv->focus_widget == NULL ||
1964 !gtk_widget_get_receives_default (priv->focus_widget))
1965 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1967 gtk_widget_queue_draw (priv->default_widget);
1970 if (old_default_widget)
1971 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1975 g_object_notify (G_OBJECT (default_widget), "has-default");
1976 g_object_unref (default_widget);
1982 * gtk_window_get_default_widget:
1983 * @window: a #GtkWindow
1985 * Returns the default widget for @window. See gtk_window_set_default()
1988 * Returns: (transfer none): the default widget, or %NULL if there is none.
1993 gtk_window_get_default_widget (GtkWindow *window)
1995 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1997 return window->priv->default_widget;
2001 handle_keys_changed (gpointer data)
2003 GtkWindow *window = GTK_WINDOW (data);
2004 GtkWindowPrivate *priv = window->priv;
2006 if (priv->keys_changed_handler)
2008 g_source_remove (priv->keys_changed_handler);
2009 priv->keys_changed_handler = 0;
2012 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
2018 gtk_window_notify_keys_changed (GtkWindow *window)
2020 GtkWindowPrivate *priv = window->priv;
2022 if (!priv->keys_changed_handler)
2023 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
2027 * gtk_window_add_accel_group:
2028 * @window: window to attach accelerator group to
2029 * @accel_group: a #GtkAccelGroup
2031 * Associate @accel_group with @window, such that calling
2032 * gtk_accel_groups_activate() on @window will activate accelerators
2036 gtk_window_add_accel_group (GtkWindow *window,
2037 GtkAccelGroup *accel_group)
2039 g_return_if_fail (GTK_IS_WINDOW (window));
2040 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2042 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
2043 g_signal_connect_object (accel_group, "accel-changed",
2044 G_CALLBACK (gtk_window_notify_keys_changed),
2045 window, G_CONNECT_SWAPPED);
2046 gtk_window_notify_keys_changed (window);
2050 * gtk_window_remove_accel_group:
2051 * @window: a #GtkWindow
2052 * @accel_group: a #GtkAccelGroup
2054 * Reverses the effects of gtk_window_add_accel_group().
2057 gtk_window_remove_accel_group (GtkWindow *window,
2058 GtkAccelGroup *accel_group)
2060 g_return_if_fail (GTK_IS_WINDOW (window));
2061 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2063 g_signal_handlers_disconnect_by_func (accel_group,
2064 gtk_window_notify_keys_changed,
2066 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2067 gtk_window_notify_keys_changed (window);
2070 static GtkMnemonicHash *
2071 gtk_window_get_mnemonic_hash (GtkWindow *window,
2074 GtkWindowPrivate *private = window->priv;
2076 if (!private->mnemonic_hash && create)
2077 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2079 return private->mnemonic_hash;
2083 * gtk_window_add_mnemonic:
2084 * @window: a #GtkWindow
2085 * @keyval: the mnemonic
2086 * @target: the widget that gets activated by the mnemonic
2088 * Adds a mnemonic to this window.
2091 gtk_window_add_mnemonic (GtkWindow *window,
2095 g_return_if_fail (GTK_IS_WINDOW (window));
2096 g_return_if_fail (GTK_IS_WIDGET (target));
2098 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2100 gtk_window_notify_keys_changed (window);
2104 * gtk_window_remove_mnemonic:
2105 * @window: a #GtkWindow
2106 * @keyval: the mnemonic
2107 * @target: the widget that gets activated by the mnemonic
2109 * Removes a mnemonic from this window.
2112 gtk_window_remove_mnemonic (GtkWindow *window,
2116 g_return_if_fail (GTK_IS_WINDOW (window));
2117 g_return_if_fail (GTK_IS_WIDGET (target));
2119 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2121 gtk_window_notify_keys_changed (window);
2125 * gtk_window_mnemonic_activate:
2126 * @window: a #GtkWindow
2127 * @keyval: the mnemonic
2128 * @modifier: the modifiers
2130 * Activates the targets associated with the mnemonic.
2132 * Returns: %TRUE if the activation is done.
2135 gtk_window_mnemonic_activate (GtkWindow *window,
2137 GdkModifierType modifier)
2139 GtkWindowPrivate *priv;
2141 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2143 priv = window->priv;
2145 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2147 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2149 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2156 * gtk_window_set_mnemonic_modifier:
2157 * @window: a #GtkWindow
2158 * @modifier: the modifier mask used to activate
2159 * mnemonics on this window.
2161 * Sets the mnemonic modifier for this window.
2164 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2165 GdkModifierType modifier)
2167 GtkWindowPrivate *priv;
2169 g_return_if_fail (GTK_IS_WINDOW (window));
2170 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2172 priv = window->priv;
2174 priv->mnemonic_modifier = modifier;
2175 gtk_window_notify_keys_changed (window);
2179 * gtk_window_get_mnemonic_modifier:
2180 * @window: a #GtkWindow
2182 * Returns the mnemonic modifier for this window. See
2183 * gtk_window_set_mnemonic_modifier().
2185 * Return value: the modifier mask used to activate
2186 * mnemonics on this window.
2189 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2191 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2193 return window->priv->mnemonic_modifier;
2197 * gtk_window_set_position:
2198 * @window: a #GtkWindow.
2199 * @position: a position constraint.
2201 * Sets a position constraint for this window. If the old or new
2202 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2203 * the window to be repositioned to satisfy the new constraint.
2206 gtk_window_set_position (GtkWindow *window,
2207 GtkWindowPosition position)
2209 GtkWindowPrivate *priv;
2211 g_return_if_fail (GTK_IS_WINDOW (window));
2213 priv = window->priv;
2215 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2216 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2218 GtkWindowGeometryInfo *info;
2220 info = gtk_window_get_geometry_info (window, TRUE);
2222 /* this flag causes us to re-request the CENTER_ALWAYS
2223 * constraint in gtk_window_move_resize(), see
2224 * comment in that function.
2226 info->position_constraints_changed = TRUE;
2228 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2231 priv->position = position;
2233 g_object_notify (G_OBJECT (window), "window-position");
2237 * gtk_window_activate_focus:
2238 * @window: a #GtkWindow
2240 * Activates the current focused widget within the window.
2242 * Return value: %TRUE if a widget got activated.
2245 gtk_window_activate_focus (GtkWindow *window)
2247 GtkWindowPrivate *priv;
2249 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2251 priv = window->priv;
2253 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2254 return gtk_widget_activate (priv->focus_widget);
2260 * gtk_window_get_focus:
2261 * @window: a #GtkWindow
2263 * Retrieves the current focused widget within the window.
2264 * Note that this is the widget that would have the focus
2265 * if the toplevel window focused; if the toplevel window
2266 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2267 * not be %TRUE for the widget.
2269 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2272 gtk_window_get_focus (GtkWindow *window)
2274 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2276 return window->priv->focus_widget;
2280 * gtk_window_activate_default:
2281 * @window: a #GtkWindow
2283 * Activates the default widget for the window, unless the current
2284 * focused widget has been configured to receive the default action
2285 * (see gtk_widget_set_receives_default()), in which case the
2286 * focused widget is activated.
2288 * Return value: %TRUE if a widget got activated.
2291 gtk_window_activate_default (GtkWindow *window)
2293 GtkWindowPrivate *priv;
2295 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2297 priv = window->priv;
2299 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2300 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2301 return gtk_widget_activate (priv->default_widget);
2302 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2303 return gtk_widget_activate (priv->focus_widget);
2309 * gtk_window_set_modal:
2310 * @window: a #GtkWindow
2311 * @modal: whether the window is modal
2313 * Sets a window modal or non-modal. Modal windows prevent interaction
2314 * with other windows in the same application. To keep modal dialogs
2315 * on top of main application windows, use
2316 * gtk_window_set_transient_for() to make the dialog transient for the
2317 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2318 * will then disallow lowering the dialog below the parent.
2323 gtk_window_set_modal (GtkWindow *window,
2326 GtkWindowPrivate *priv;
2329 g_return_if_fail (GTK_IS_WINDOW (window));
2331 priv = window->priv;
2333 modal = modal != FALSE;
2334 if (priv->modal == modal)
2337 priv->modal = modal;
2338 widget = GTK_WIDGET (window);
2340 /* adjust desired modality state */
2341 if (gtk_widget_get_realized (widget))
2344 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2346 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2349 if (gtk_widget_get_visible (widget))
2352 gtk_grab_add (widget);
2354 gtk_grab_remove (widget);
2357 g_object_notify (G_OBJECT (window), "modal");
2361 * gtk_window_get_modal:
2362 * @window: a #GtkWindow
2364 * Returns whether the window is modal. See gtk_window_set_modal().
2366 * Return value: %TRUE if the window is set to be modal and
2367 * establishes a grab when shown
2370 gtk_window_get_modal (GtkWindow *window)
2372 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2374 return window->priv->modal;
2378 * gtk_window_list_toplevels:
2380 * Returns a list of all existing toplevel windows. The widgets
2381 * in the list are not individually referenced. If you want
2382 * to iterate through the list and perform actions involving
2383 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2384 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2385 * then unref all the widgets afterwards.
2387 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2390 gtk_window_list_toplevels (void)
2395 for (slist = toplevel_list; slist; slist = slist->next)
2396 list = g_list_prepend (list, slist->data);
2402 remove_attach_widget (GtkWindow *window)
2404 GtkWindowPrivate *priv = window->priv;
2406 if (priv->attach_widget)
2408 _gtk_widget_remove_attached_window (priv->attach_widget, window);
2410 g_object_unref (priv->attach_widget);
2411 priv->attach_widget = NULL;
2416 gtk_window_dispose (GObject *object)
2418 GtkWindow *window = GTK_WINDOW (object);
2420 gtk_window_set_focus (window, NULL);
2421 gtk_window_set_default (window, NULL);
2423 remove_attach_widget (GTK_WINDOW (object));
2425 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2429 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2431 gtk_widget_destroy (GTK_WIDGET (child));
2435 connect_parent_destroyed (GtkWindow *window)
2437 GtkWindowPrivate *priv = window->priv;
2439 if (priv->transient_parent)
2441 g_signal_connect (priv->transient_parent,
2443 G_CALLBACK (parent_destroyed_callback),
2449 disconnect_parent_destroyed (GtkWindow *window)
2451 GtkWindowPrivate *priv = window->priv;
2453 if (priv->transient_parent)
2455 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2456 parent_destroyed_callback,
2462 gtk_window_transient_parent_realized (GtkWidget *parent,
2465 if (gtk_widget_get_realized (window))
2466 gdk_window_set_transient_for (gtk_widget_get_window (window),
2467 gtk_widget_get_window (parent));
2471 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2474 if (gtk_widget_get_realized (window))
2475 gdk_property_delete (gtk_widget_get_window (window),
2476 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2480 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2484 gtk_window_set_screen (window, parent->priv->screen);
2488 gtk_window_unset_transient_for (GtkWindow *window)
2490 GtkWindowPrivate *priv = window->priv;
2492 if (priv->transient_parent)
2494 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2495 gtk_window_transient_parent_realized,
2497 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2498 gtk_window_transient_parent_unrealized,
2500 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2501 gtk_window_transient_parent_screen_changed,
2503 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2504 gtk_widget_destroyed,
2505 &priv->transient_parent);
2507 if (priv->destroy_with_parent)
2508 disconnect_parent_destroyed (window);
2510 priv->transient_parent = NULL;
2512 if (priv->transient_parent_group)
2514 priv->transient_parent_group = FALSE;
2515 gtk_window_group_remove_window (priv->group,
2522 * gtk_window_set_transient_for:
2523 * @window: a #GtkWindow
2524 * @parent: (allow-none): parent window, or %NULL
2526 * Dialog windows should be set transient for the main application
2527 * window they were spawned from. This allows <link
2528 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2529 * dialog on top of the main window, or center the dialog over the
2530 * main window. gtk_dialog_new_with_buttons() and other convenience
2531 * functions in GTK+ will sometimes call
2532 * gtk_window_set_transient_for() on your behalf.
2534 * Passing %NULL for @parent unsets the current transient window.
2536 * On Windows, this function puts the child window on top of the parent,
2537 * much as the window manager would have done on X.
2540 gtk_window_set_transient_for (GtkWindow *window,
2543 GtkWindowPrivate *priv;
2545 g_return_if_fail (GTK_IS_WINDOW (window));
2546 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2547 g_return_if_fail (window != parent);
2549 priv = window->priv;
2551 if (priv->transient_parent)
2553 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2554 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2555 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2556 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2557 GTK_WIDGET (window));
2559 gtk_window_unset_transient_for (window);
2562 priv->transient_parent = parent;
2566 g_signal_connect (parent, "destroy",
2567 G_CALLBACK (gtk_widget_destroyed),
2568 &priv->transient_parent);
2569 g_signal_connect (parent, "realize",
2570 G_CALLBACK (gtk_window_transient_parent_realized),
2572 g_signal_connect (parent, "unrealize",
2573 G_CALLBACK (gtk_window_transient_parent_unrealized),
2575 g_signal_connect (parent, "notify::screen",
2576 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2579 gtk_window_set_screen (window, parent->priv->screen);
2581 if (priv->destroy_with_parent)
2582 connect_parent_destroyed (window);
2584 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2585 gtk_widget_get_realized (GTK_WIDGET (parent)))
2586 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2587 GTK_WIDGET (window));
2589 if (parent->priv->group)
2591 gtk_window_group_add_window (parent->priv->group, window);
2592 priv->transient_parent_group = TRUE;
2598 * gtk_window_get_transient_for:
2599 * @window: a #GtkWindow
2601 * Fetches the transient parent for this window. See
2602 * gtk_window_set_transient_for().
2604 * Return value: (transfer none): the transient parent for this window, or %NULL
2605 * if no transient parent has been set.
2608 gtk_window_get_transient_for (GtkWindow *window)
2610 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2612 return window->priv->transient_parent;
2616 * gtk_window_set_attached_to:
2617 * @window: a #GtkWindow
2618 * @attach_widget (allow-none): a #GtkWidget, or %NULL
2620 * Attach the window to a widget. Indicates that @window belongs to @widget.
2621 * For example the window of a GtkMenu could belong to a GtkMenuBar or
2622 * a GtkEntry or a GtkComboBox, and so on...
2624 * GTK will use this information for styling the @window,
2625 * for presenting it as a child of @widget in the accessibility tree
2628 * Passing %NULL for @attach_widget detaches the window.
2633 gtk_window_set_attached_to (GtkWindow *window,
2634 GtkWidget *attach_widget)
2636 GtkWindowPrivate *priv;
2638 g_return_if_fail (GTK_IS_WINDOW (window));
2639 g_return_if_fail (GTK_WIDGET (window) != attach_widget);
2641 priv = window->priv;
2643 remove_attach_widget (window);
2645 priv->attach_widget = attach_widget;
2647 if (priv->attach_widget)
2649 _gtk_widget_add_attached_window (priv->attach_widget, window);
2651 g_object_ref_sink (priv->attach_widget);
2654 /* Update the style, as the widget path might change. */
2655 gtk_widget_reset_style (GTK_WIDGET (window));
2659 * gtk_window_get_attached_to:
2660 * @window: a #GtkWindow
2662 * Fetches the attach widget for this window. See
2663 * gtk_window_set_attached_to().
2665 * Return value: (transfer none): the widget where the window is attached,
2666 * or %NULL if the window is not attached to any widget.
2671 gtk_window_get_attached_to (GtkWindow *window)
2673 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2675 return window->priv->attach_widget;
2679 * gtk_window_set_opacity:
2680 * @window: a #GtkWindow
2681 * @opacity: desired opacity, between 0 and 1
2683 * Request the windowing system to make @window partially transparent,
2684 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2685 * of the opacity parameter are clamped to the [0,1] range.) On X11
2686 * this has any effect only on X screens with a compositing manager
2687 * running. See gtk_widget_is_composited(). On Windows it should work
2690 * Note that setting a window's opacity after the window has been
2691 * shown causes it to flicker once on Windows.
2696 gtk_window_set_opacity (GtkWindow *window,
2699 GtkWindowPrivate *priv;
2701 g_return_if_fail (GTK_IS_WINDOW (window));
2703 priv = window->priv;
2707 else if (opacity > 1.0)
2710 priv->opacity_set = TRUE;
2711 priv->opacity = opacity;
2713 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2714 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2719 * gtk_window_get_opacity:
2720 * @window: a #GtkWindow
2722 * Fetches the requested opacity for this window. See
2723 * gtk_window_set_opacity().
2725 * Return value: the requested opacity for this window.
2730 gtk_window_get_opacity (GtkWindow *window)
2732 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2734 return window->priv->opacity;
2738 * gtk_window_get_application:
2739 * @window: a #GtkWindow
2741 * Gets the #GtkApplication associated with the window (if any).
2743 * Return value: (transfer none): a #GtkApplication, or %NULL
2748 gtk_window_get_application (GtkWindow *window)
2750 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2752 return window->priv->application;
2756 gtk_window_release_application (GtkWindow *window)
2758 if (window->priv->application)
2760 GtkApplication *application;
2762 /* steal reference into temp variable */
2763 application = window->priv->application;
2764 window->priv->application = NULL;
2766 gtk_application_remove_window (application, window);
2767 g_object_unref (application);
2772 * gtk_window_set_application:
2773 * @window: a #GtkWindow
2774 * @application: (allow-none): a #GtkApplication, or %NULL
2776 * Sets or unsets the #GtkApplication associated with the window.
2778 * The application will be kept alive for at least as long as the window
2784 gtk_window_set_application (GtkWindow *window,
2785 GtkApplication *application)
2787 GtkWindowPrivate *priv;
2789 g_return_if_fail (GTK_IS_WINDOW (window));
2791 priv = window->priv;
2792 if (priv->application != application)
2794 gtk_window_release_application (window);
2796 priv->application = application;
2798 if (priv->application != NULL)
2800 g_object_ref (priv->application);
2802 gtk_application_add_window (priv->application, window);
2805 g_object_notify (G_OBJECT (window), "application");
2810 * gtk_window_set_type_hint:
2811 * @window: a #GtkWindow
2812 * @hint: the window type
2814 * By setting the type hint for the window, you allow the window
2815 * manager to decorate and handle the window in a way which is
2816 * suitable to the function of the window in your application.
2818 * This function should be called before the window becomes visible.
2820 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2821 * will sometimes call gtk_window_set_type_hint() on your behalf.
2825 gtk_window_set_type_hint (GtkWindow *window,
2826 GdkWindowTypeHint hint)
2828 GtkWindowPrivate *priv;
2830 g_return_if_fail (GTK_IS_WINDOW (window));
2831 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2833 priv = window->priv;
2835 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2836 priv->type_hint = hint;
2838 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2840 priv->reset_type_hint = TRUE;
2841 priv->gdk_type_hint = hint;
2845 * gtk_window_get_type_hint:
2846 * @window: a #GtkWindow
2848 * Gets the type hint for this window. See gtk_window_set_type_hint().
2850 * Return value: the type hint for @window.
2853 gtk_window_get_type_hint (GtkWindow *window)
2855 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2857 return window->priv->gdk_type_hint;
2861 * gtk_window_set_skip_taskbar_hint:
2862 * @window: a #GtkWindow
2863 * @setting: %TRUE to keep this window from appearing in the task bar
2865 * Windows may set a hint asking the desktop environment not to display
2866 * the window in the task bar. This function sets this hint.
2871 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2874 GtkWindowPrivate *priv;
2876 g_return_if_fail (GTK_IS_WINDOW (window));
2878 priv = window->priv;
2880 setting = setting != FALSE;
2882 if (priv->skips_taskbar != setting)
2884 priv->skips_taskbar = setting;
2885 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2886 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2887 priv->skips_taskbar);
2888 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2893 * gtk_window_get_skip_taskbar_hint:
2894 * @window: a #GtkWindow
2896 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2898 * Return value: %TRUE if window shouldn't be in taskbar
2903 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2905 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2907 return window->priv->skips_taskbar;
2911 * gtk_window_set_skip_pager_hint:
2912 * @window: a #GtkWindow
2913 * @setting: %TRUE to keep this window from appearing in the pager
2915 * Windows may set a hint asking the desktop environment not to display
2916 * the window in the pager. This function sets this hint.
2917 * (A "pager" is any desktop navigation tool such as a workspace
2918 * switcher that displays a thumbnail representation of the windows
2924 gtk_window_set_skip_pager_hint (GtkWindow *window,
2927 GtkWindowPrivate *priv;
2929 g_return_if_fail (GTK_IS_WINDOW (window));
2931 priv = window->priv;
2933 setting = setting != FALSE;
2935 if (priv->skips_pager != setting)
2937 priv->skips_pager = setting;
2938 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2939 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2941 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2946 * gtk_window_get_skip_pager_hint:
2947 * @window: a #GtkWindow
2949 * Gets the value set by gtk_window_set_skip_pager_hint().
2951 * Return value: %TRUE if window shouldn't be in pager
2956 gtk_window_get_skip_pager_hint (GtkWindow *window)
2958 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2960 return window->priv->skips_pager;
2964 * gtk_window_set_urgency_hint:
2965 * @window: a #GtkWindow
2966 * @setting: %TRUE to mark this window as urgent
2968 * Windows may set a hint asking the desktop environment to draw
2969 * the users attention to the window. This function sets this hint.
2974 gtk_window_set_urgency_hint (GtkWindow *window,
2977 GtkWindowPrivate *priv;
2979 g_return_if_fail (GTK_IS_WINDOW (window));
2981 priv = window->priv;
2983 setting = setting != FALSE;
2985 if (priv->urgent != setting)
2987 priv->urgent = setting;
2988 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2989 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2991 g_object_notify (G_OBJECT (window), "urgency-hint");
2996 * gtk_window_get_urgency_hint:
2997 * @window: a #GtkWindow
2999 * Gets the value set by gtk_window_set_urgency_hint()
3001 * Return value: %TRUE if window is urgent
3006 gtk_window_get_urgency_hint (GtkWindow *window)
3008 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3010 return window->priv->urgent;
3014 * gtk_window_set_accept_focus:
3015 * @window: a #GtkWindow
3016 * @setting: %TRUE to let this window receive input focus
3018 * Windows may set a hint asking the desktop environment not to receive
3019 * the input focus. This function sets this hint.
3024 gtk_window_set_accept_focus (GtkWindow *window,
3027 GtkWindowPrivate *priv;
3029 g_return_if_fail (GTK_IS_WINDOW (window));
3031 priv = window->priv;
3033 setting = setting != FALSE;
3035 if (priv->accept_focus != setting)
3037 priv->accept_focus = setting;
3038 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3039 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
3040 priv->accept_focus);
3041 g_object_notify (G_OBJECT (window), "accept-focus");
3046 * gtk_window_get_accept_focus:
3047 * @window: a #GtkWindow
3049 * Gets the value set by gtk_window_set_accept_focus().
3051 * Return value: %TRUE if window should receive the input focus
3056 gtk_window_get_accept_focus (GtkWindow *window)
3058 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3060 return window->priv->accept_focus;
3064 * gtk_window_set_focus_on_map:
3065 * @window: a #GtkWindow
3066 * @setting: %TRUE to let this window receive input focus on map
3068 * Windows may set a hint asking the desktop environment not to receive
3069 * the input focus when the window is mapped. This function sets this
3075 gtk_window_set_focus_on_map (GtkWindow *window,
3078 GtkWindowPrivate *priv;
3080 g_return_if_fail (GTK_IS_WINDOW (window));
3082 priv = window->priv;
3084 setting = setting != FALSE;
3086 if (priv->focus_on_map != setting)
3088 priv->focus_on_map = setting;
3089 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3090 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
3091 priv->focus_on_map);
3092 g_object_notify (G_OBJECT (window), "focus-on-map");
3097 * gtk_window_get_focus_on_map:
3098 * @window: a #GtkWindow
3100 * Gets the value set by gtk_window_set_focus_on_map().
3102 * Return value: %TRUE if window should receive the input focus when
3108 gtk_window_get_focus_on_map (GtkWindow *window)
3110 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3112 return window->priv->focus_on_map;
3116 * gtk_window_set_destroy_with_parent:
3117 * @window: a #GtkWindow
3118 * @setting: whether to destroy @window with its transient parent
3120 * If @setting is %TRUE, then destroying the transient parent of @window
3121 * will also destroy @window itself. This is useful for dialogs that
3122 * shouldn't persist beyond the lifetime of the main window they're
3123 * associated with, for example.
3126 gtk_window_set_destroy_with_parent (GtkWindow *window,
3129 GtkWindowPrivate *priv;
3131 g_return_if_fail (GTK_IS_WINDOW (window));
3133 priv = window->priv;
3135 if (priv->destroy_with_parent == (setting != FALSE))
3138 if (priv->destroy_with_parent)
3140 disconnect_parent_destroyed (window);
3144 connect_parent_destroyed (window);
3147 priv->destroy_with_parent = setting;
3149 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3153 * gtk_window_get_destroy_with_parent:
3154 * @window: a #GtkWindow
3156 * Returns whether the window will be destroyed with its transient parent. See
3157 * gtk_window_set_destroy_with_parent ().
3159 * Return value: %TRUE if the window will be destroyed with its transient parent.
3162 gtk_window_get_destroy_with_parent (GtkWindow *window)
3164 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3166 return window->priv->destroy_with_parent;
3170 * gtk_window_set_hide_titlebar_when_maximized:
3171 * @window: a #GtkWindow
3172 * @setting: whether to hide the titlebar when @window is maximized
3174 * If @setting is %TRUE, then @window will request that it's titlebar
3175 * should be hidden when maximized.
3176 * This is useful for windows that don't convey any information other
3177 * than the application name in the titlebar, to put the available
3178 * screen space to better use. If the underlying window system does not
3179 * support the request, the setting will not have any effect.
3184 gtk_window_set_hide_titlebar_when_maximized (GtkWindow *window,
3187 g_return_if_fail (GTK_IS_WINDOW (window));
3189 #ifdef GDK_WINDOWING_X11
3191 GdkWindow *gdk_window;
3193 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3195 if (GDK_IS_X11_WINDOW (gdk_window))
3196 gdk_x11_window_set_hide_titlebar_when_maximized (gdk_window, setting);
3200 window->priv->hide_titlebar_when_maximized = setting;
3201 g_object_notify (G_OBJECT (window), "hide-titlebar-when-maximized");
3205 * gtk_window_get_hide_titlebar_when_maximized:
3206 * @window: a #GtkWindow
3208 * Returns whether the window has requested to have its titlebar hidden
3209 * when maximized. See gtk_window_set_hide_titlebar_when_maximized ().
3211 * Return value: %TRUE if the window has requested to have its titlebar
3212 * hidden when maximized
3217 gtk_window_get_hide_titlebar_when_maximized (GtkWindow *window)
3219 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3221 return window->priv->hide_titlebar_when_maximized;
3224 static GtkWindowGeometryInfo*
3225 gtk_window_get_geometry_info (GtkWindow *window,
3228 GtkWindowPrivate *priv = window->priv;
3229 GtkWindowGeometryInfo *info;
3231 info = priv->geometry_info;
3232 if (!info && create)
3234 info = g_new0 (GtkWindowGeometryInfo, 1);
3236 info->default_width = -1;
3237 info->default_height = -1;
3238 info->resize_width = -1;
3239 info->resize_height = -1;
3240 info->initial_x = 0;
3241 info->initial_y = 0;
3242 info->initial_pos_set = FALSE;
3243 info->default_is_geometry = FALSE;
3244 info->position_constraints_changed = FALSE;
3245 info->last.configure_request.x = 0;
3246 info->last.configure_request.y = 0;
3247 info->last.configure_request.width = -1;
3248 info->last.configure_request.height = -1;
3249 info->widget = NULL;
3251 priv->geometry_info = info;
3258 * gtk_window_set_geometry_hints:
3259 * @window: a #GtkWindow
3260 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3261 * @geometry: (allow-none): struct containing geometry information or %NULL
3262 * @geom_mask: mask indicating which struct fields should be paid attention to
3264 * This function sets up hints about how a window can be resized by
3265 * the user. You can set a minimum and maximum size; allowed resize
3266 * increments (e.g. for xterm, you can only resize by the size of a
3267 * character); aspect ratios; and more. See the #GdkGeometry struct.
3271 gtk_window_set_geometry_hints (GtkWindow *window,
3272 GtkWidget *geometry_widget,
3273 GdkGeometry *geometry,
3274 GdkWindowHints geom_mask)
3276 GtkWindowGeometryInfo *info;
3278 g_return_if_fail (GTK_IS_WINDOW (window));
3279 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3281 info = gtk_window_get_geometry_info (window, TRUE);
3284 g_signal_handlers_disconnect_by_func (info->widget,
3285 gtk_widget_destroyed,
3288 info->widget = geometry_widget;
3290 g_signal_connect (geometry_widget, "destroy",
3291 G_CALLBACK (gtk_widget_destroyed),
3295 info->geometry = *geometry;
3297 /* We store gravity in priv->gravity not in the hints. */
3298 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3300 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3302 gtk_window_set_gravity (window, geometry->win_gravity);
3305 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3309 * gtk_window_set_decorated:
3310 * @window: a #GtkWindow
3311 * @setting: %TRUE to decorate the window
3313 * By default, windows are decorated with a title bar, resize
3314 * controls, etc. Some <link linkend="gtk-X11-arch">window
3315 * managers</link> allow GTK+ to disable these decorations, creating a
3316 * borderless window. If you set the decorated property to %FALSE
3317 * using this function, GTK+ will do its best to convince the window
3318 * manager not to decorate the window. Depending on the system, this
3319 * function may not have any effect when called on a window that is
3320 * already visible, so you should call it before calling gtk_widget_show().
3322 * On Windows, this function always works, since there's no window manager
3327 gtk_window_set_decorated (GtkWindow *window,
3330 GtkWindowPrivate *priv;
3331 GdkWindow *gdk_window;
3333 g_return_if_fail (GTK_IS_WINDOW (window));
3335 priv = window->priv;
3337 setting = setting != FALSE;
3339 if (setting == priv->decorated)
3342 priv->decorated = setting;
3344 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3347 if (priv->decorated)
3348 gdk_window_set_decorations (gdk_window,
3351 gdk_window_set_decorations (gdk_window,
3355 g_object_notify (G_OBJECT (window), "decorated");
3359 * gtk_window_get_decorated:
3360 * @window: a #GtkWindow
3362 * Returns whether the window has been set to have decorations
3363 * such as a title bar via gtk_window_set_decorated().
3365 * Return value: %TRUE if the window has been set to have decorations
3368 gtk_window_get_decorated (GtkWindow *window)
3370 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3372 return window->priv->decorated;
3376 * gtk_window_set_deletable:
3377 * @window: a #GtkWindow
3378 * @setting: %TRUE to decorate the window as deletable
3380 * By default, windows have a close button in the window frame. Some
3381 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3382 * disable this button. If you set the deletable property to %FALSE
3383 * using this function, GTK+ will do its best to convince the window
3384 * manager not to show a close button. Depending on the system, this
3385 * function may not have any effect when called on a window that is
3386 * already visible, so you should call it before calling gtk_window_show().
3388 * On Windows, this function always works, since there's no window manager
3394 gtk_window_set_deletable (GtkWindow *window,
3397 GtkWindowPrivate *priv;
3398 GdkWindow *gdk_window;
3400 g_return_if_fail (GTK_IS_WINDOW (window));
3402 priv = window->priv;
3404 setting = setting != FALSE;
3406 if (setting == priv->deletable)
3409 priv->deletable = setting;
3411 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3414 if (priv->deletable)
3415 gdk_window_set_functions (gdk_window,
3418 gdk_window_set_functions (gdk_window,
3419 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3422 g_object_notify (G_OBJECT (window), "deletable");
3426 * gtk_window_get_deletable:
3427 * @window: a #GtkWindow
3429 * Returns whether the window has been set to have a close button
3430 * via gtk_window_set_deletable().
3432 * Return value: %TRUE if the window has been set to have a close button
3437 gtk_window_get_deletable (GtkWindow *window)
3439 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3441 return window->priv->deletable;
3444 static GtkWindowIconInfo*
3445 get_icon_info (GtkWindow *window)
3447 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3451 free_icon_info (GtkWindowIconInfo *info)
3453 g_free (info->icon_name);
3454 g_slice_free (GtkWindowIconInfo, info);
3458 static GtkWindowIconInfo*
3459 ensure_icon_info (GtkWindow *window)
3461 GtkWindowIconInfo *info;
3463 info = get_icon_info (window);
3467 info = g_slice_new0 (GtkWindowIconInfo);
3468 g_object_set_qdata_full (G_OBJECT (window),
3469 quark_gtk_window_icon_info,
3471 (GDestroyNotify)free_icon_info);
3478 icon_list_from_theme (GtkWidget *widget,
3483 GtkIconTheme *icon_theme;
3488 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3490 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3493 for (i = 0; sizes[i]; i++)
3496 * We need an EWMH extension to handle scalable icons
3497 * by passing their name to the WM. For now just use a
3501 icon = gtk_icon_theme_load_icon (icon_theme, name,
3504 icon = gtk_icon_theme_load_icon (icon_theme, name,
3507 list = g_list_append (list, icon);
3517 gtk_window_realize_icon (GtkWindow *window)
3519 GtkWindowPrivate *priv = window->priv;
3521 GtkWindowIconInfo *info;
3522 GdkWindow *gdk_window;
3525 widget = GTK_WIDGET (window);
3526 gdk_window = gtk_widget_get_window (widget);
3528 g_return_if_fail (gdk_window != NULL);
3530 /* no point setting an icon on override-redirect */
3531 if (priv->type == GTK_WINDOW_POPUP)
3536 info = ensure_icon_info (window);
3541 info->using_default_icon = FALSE;
3542 info->using_parent_icon = FALSE;
3543 info->using_themed_icon = FALSE;
3545 icon_list = info->icon_list;
3547 /* Look up themed icon */
3548 if (icon_list == NULL && info->icon_name)
3550 icon_list = icon_list_from_theme (widget, info->icon_name);
3552 info->using_themed_icon = TRUE;
3555 /* Inherit from transient parent */
3556 if (icon_list == NULL && priv->transient_parent)
3558 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3560 info->using_parent_icon = TRUE;
3563 /* Inherit from default */
3564 if (icon_list == NULL)
3566 icon_list = default_icon_list;
3568 info->using_default_icon = TRUE;
3571 /* Look up themed icon */
3572 if (icon_list == NULL && default_icon_name)
3574 icon_list = icon_list_from_theme (widget, default_icon_name);
3575 info->using_default_icon = TRUE;
3576 info->using_themed_icon = TRUE;
3579 info->realized = TRUE;
3581 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3583 if (info->using_themed_icon)
3585 GtkIconTheme *icon_theme;
3587 g_list_free_full (icon_list, g_object_unref);
3589 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3590 g_signal_connect (icon_theme, "changed",
3591 G_CALLBACK (update_themed_icon), window);
3596 gtk_window_unrealize_icon (GtkWindow *window)
3598 GtkWindowIconInfo *info;
3600 info = get_icon_info (window);
3605 if (info->using_themed_icon)
3607 GtkIconTheme *icon_theme;
3609 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3611 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3614 /* We don't clear the properties on the window, just figure the
3615 * window is going away.
3618 info->realized = FALSE;
3623 * gtk_window_set_icon_list:
3624 * @window: a #GtkWindow
3625 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3627 * Sets up the icon representing a #GtkWindow. The icon is used when
3628 * the window is minimized (also known as iconified). Some window
3629 * managers or desktop environments may also place it in the window
3630 * frame, or display it in other contexts.
3632 * gtk_window_set_icon_list() allows you to pass in the same icon in
3633 * several hand-drawn sizes. The list should contain the natural sizes
3634 * your icon is available in; that is, don't scale the image before
3635 * passing it to GTK+. Scaling is postponed until the last minute,
3636 * when the desired final size is known, to allow best quality.
3638 * By passing several sizes, you may improve the final image quality
3639 * of the icon, by reducing or eliminating automatic image scaling.
3641 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3642 * larger images (64x64, 128x128) if you have them.
3644 * See also gtk_window_set_default_icon_list() to set the icon
3645 * for all windows in your application in one go.
3647 * Note that transient windows (those who have been set transient for another
3648 * window using gtk_window_set_transient_for()) will inherit their
3649 * icon from their transient parent. So there's no need to explicitly
3650 * set the icon on transient windows.
3653 gtk_window_set_icon_list (GtkWindow *window,
3656 GtkWindowIconInfo *info;
3658 g_return_if_fail (GTK_IS_WINDOW (window));
3660 info = ensure_icon_info (window);
3662 if (info->icon_list == list) /* check for NULL mostly */
3665 g_list_foreach (list,
3666 (GFunc) g_object_ref, NULL);
3668 g_list_free_full (info->icon_list, g_object_unref);
3670 info->icon_list = g_list_copy (list);
3672 g_object_notify (G_OBJECT (window), "icon");
3674 gtk_window_unrealize_icon (window);
3676 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3677 gtk_window_realize_icon (window);
3679 /* We could try to update our transient children, but I don't think
3680 * it's really worth it. If we did it, the best way would probably
3681 * be to have children connect to notify::icon-list
3686 * gtk_window_get_icon_list:
3687 * @window: a #GtkWindow
3689 * Retrieves the list of icons set by gtk_window_set_icon_list().
3690 * The list is copied, but the reference count on each
3691 * member won't be incremented.
3693 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3696 gtk_window_get_icon_list (GtkWindow *window)
3698 GtkWindowIconInfo *info;
3700 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3702 info = get_icon_info (window);
3705 return g_list_copy (info->icon_list);
3711 * gtk_window_set_icon:
3712 * @window: a #GtkWindow
3713 * @icon: (allow-none): icon image, or %NULL
3715 * Sets up the icon representing a #GtkWindow. This icon is used when
3716 * the window is minimized (also known as iconified). Some window
3717 * managers or desktop environments may also place it in the window
3718 * frame, or display it in other contexts.
3720 * The icon should be provided in whatever size it was naturally
3721 * drawn; that is, don't scale the image before passing it to
3722 * GTK+. Scaling is postponed until the last minute, when the desired
3723 * final size is known, to allow best quality.
3725 * If you have your icon hand-drawn in multiple sizes, use
3726 * gtk_window_set_icon_list(). Then the best size will be used.
3728 * This function is equivalent to calling gtk_window_set_icon_list()
3729 * with a 1-element list.
3731 * See also gtk_window_set_default_icon_list() to set the icon
3732 * for all windows in your application in one go.
3735 gtk_window_set_icon (GtkWindow *window,
3740 g_return_if_fail (GTK_IS_WINDOW (window));
3741 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3746 list = g_list_append (list, icon);
3748 gtk_window_set_icon_list (window, list);
3754 update_themed_icon (GtkIconTheme *icon_theme,
3757 g_object_notify (G_OBJECT (window), "icon");
3759 gtk_window_unrealize_icon (window);
3761 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3762 gtk_window_realize_icon (window);
3766 * gtk_window_set_icon_name:
3767 * @window: a #GtkWindow
3768 * @name: (allow-none): the name of the themed icon
3770 * Sets the icon for the window from a named themed icon. See
3771 * the docs for #GtkIconTheme for more details.
3773 * Note that this has nothing to do with the WM_ICON_NAME
3774 * property which is mentioned in the ICCCM.
3779 gtk_window_set_icon_name (GtkWindow *window,
3782 GtkWindowIconInfo *info;
3785 g_return_if_fail (GTK_IS_WINDOW (window));
3787 info = ensure_icon_info (window);
3789 if (g_strcmp0 (info->icon_name, name) == 0)
3792 tmp = info->icon_name;
3793 info->icon_name = g_strdup (name);
3796 g_list_free_full (info->icon_list, g_object_unref);
3797 info->icon_list = NULL;
3799 update_themed_icon (NULL, window);
3801 g_object_notify (G_OBJECT (window), "icon-name");
3805 * gtk_window_get_icon_name:
3806 * @window: a #GtkWindow
3808 * Returns the name of the themed icon for the window,
3809 * see gtk_window_set_icon_name().
3811 * Returns: the icon name or %NULL if the window has
3817 gtk_window_get_icon_name (GtkWindow *window)
3819 GtkWindowIconInfo *info;
3821 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3823 info = ensure_icon_info (window);
3825 return info->icon_name;
3829 * gtk_window_get_icon:
3830 * @window: a #GtkWindow
3832 * Gets the value set by gtk_window_set_icon() (or if you've
3833 * called gtk_window_set_icon_list(), gets the first icon in
3836 * Return value: (transfer none): icon for window
3839 gtk_window_get_icon (GtkWindow *window)
3841 GtkWindowIconInfo *info;
3843 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3845 info = get_icon_info (window);
3846 if (info && info->icon_list)
3847 return GDK_PIXBUF (info->icon_list->data);
3852 /* Load pixbuf, printing warning on failure if error == NULL
3855 load_pixbuf_verbosely (const char *filename,
3858 GError *local_err = NULL;
3861 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3869 g_warning ("Error loading icon from file '%s':\n\t%s",
3870 filename, local_err->message);
3871 g_error_free (local_err);
3879 * gtk_window_set_icon_from_file:
3880 * @window: a #GtkWindow
3881 * @filename: (type filename): location of icon file
3882 * @err: (allow-none): location to store error, or %NULL.
3884 * Sets the icon for @window.
3885 * Warns on failure if @err is %NULL.
3887 * This function is equivalent to calling gtk_window_set_icon()
3888 * with a pixbuf created by loading the image from @filename.
3890 * Returns: %TRUE if setting the icon succeeded.
3895 gtk_window_set_icon_from_file (GtkWindow *window,
3896 const gchar *filename,
3899 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3903 gtk_window_set_icon (window, pixbuf);
3904 g_object_unref (pixbuf);
3913 * gtk_window_set_default_icon_list:
3914 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3916 * Sets an icon list to be used as fallback for windows that haven't
3917 * had gtk_window_set_icon_list() called on them to set up a
3918 * window-specific icon list. This function allows you to set up the
3919 * icon for all windows in your app at once.
3921 * See gtk_window_set_icon_list() for more details.
3925 gtk_window_set_default_icon_list (GList *list)
3929 if (list == default_icon_list)
3932 /* Update serial so we don't used cached pixmaps/masks
3934 default_icon_serial++;
3936 g_list_foreach (list,
3937 (GFunc) g_object_ref, NULL);
3939 g_list_free_full (default_icon_list, g_object_unref);
3941 default_icon_list = g_list_copy (list);
3943 /* Update all toplevels */
3944 toplevels = gtk_window_list_toplevels ();
3945 tmp_list = toplevels;
3946 while (tmp_list != NULL)
3948 GtkWindowIconInfo *info;
3949 GtkWindow *w = tmp_list->data;
3951 info = get_icon_info (w);
3952 if (info && info->using_default_icon)
3954 gtk_window_unrealize_icon (w);
3955 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3956 gtk_window_realize_icon (w);
3959 tmp_list = tmp_list->next;
3961 g_list_free (toplevels);
3965 * gtk_window_set_default_icon:
3968 * Sets an icon to be used as fallback for windows that haven't
3969 * had gtk_window_set_icon() called on them from a pixbuf.
3974 gtk_window_set_default_icon (GdkPixbuf *icon)
3978 g_return_if_fail (GDK_IS_PIXBUF (icon));
3980 list = g_list_prepend (NULL, icon);
3981 gtk_window_set_default_icon_list (list);
3986 * gtk_window_set_default_icon_name:
3987 * @name: the name of the themed icon
3989 * Sets an icon to be used as fallback for windows that haven't
3990 * had gtk_window_set_icon_list() called on them from a named
3991 * themed icon, see gtk_window_set_icon_name().
3996 gtk_window_set_default_icon_name (const gchar *name)
4001 /* Update serial so we don't used cached pixmaps/masks
4003 default_icon_serial++;
4005 g_free (default_icon_name);
4006 default_icon_name = g_strdup (name);
4008 g_list_free_full (default_icon_list, g_object_unref);
4009 default_icon_list = NULL;
4011 /* Update all toplevels */
4012 toplevels = gtk_window_list_toplevels ();
4013 tmp_list = toplevels;
4014 while (tmp_list != NULL)
4016 GtkWindowIconInfo *info;
4017 GtkWindow *w = tmp_list->data;
4019 info = get_icon_info (w);
4020 if (info && info->using_default_icon && info->using_themed_icon)
4022 gtk_window_unrealize_icon (w);
4023 if (gtk_widget_get_realized (GTK_WIDGET (w)))
4024 gtk_window_realize_icon (w);
4027 tmp_list = tmp_list->next;
4029 g_list_free (toplevels);
4033 * gtk_window_get_default_icon_name:
4035 * Returns the fallback icon name for windows that has been set
4036 * with gtk_window_set_default_icon_name(). The returned
4037 * string is owned by GTK+ and should not be modified. It
4038 * is only valid until the next call to
4039 * gtk_window_set_default_icon_name().
4041 * Returns: the fallback icon name for windows
4046 gtk_window_get_default_icon_name (void)
4048 return default_icon_name;
4052 * gtk_window_set_default_icon_from_file:
4053 * @filename: (type filename): location of icon file
4054 * @err: (allow-none): location to store error, or %NULL.
4056 * Sets an icon to be used as fallback for windows that haven't
4057 * had gtk_window_set_icon_list() called on them from a file
4058 * on disk. Warns on failure if @err is %NULL.
4060 * Returns: %TRUE if setting the icon succeeded.
4065 gtk_window_set_default_icon_from_file (const gchar *filename,
4068 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
4072 gtk_window_set_default_icon (pixbuf);
4073 g_object_unref (pixbuf);
4082 * gtk_window_get_default_icon_list:
4084 * Gets the value set by gtk_window_set_default_icon_list().
4085 * The list is a copy and should be freed with g_list_free(),
4086 * but the pixbufs in the list have not had their reference count
4089 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
4092 gtk_window_get_default_icon_list (void)
4094 return g_list_copy (default_icon_list);
4098 gtk_window_set_default_size_internal (GtkWindow *window,
4099 gboolean change_width,
4101 gboolean change_height,
4103 gboolean is_geometry)
4105 GtkWindowGeometryInfo *info;
4107 g_return_if_fail (change_width == FALSE || width >= -1);
4108 g_return_if_fail (change_height == FALSE || height >= -1);
4110 info = gtk_window_get_geometry_info (window, TRUE);
4112 g_object_freeze_notify (G_OBJECT (window));
4114 info->default_is_geometry = is_geometry != FALSE;
4124 info->default_width = width;
4126 g_object_notify (G_OBJECT (window), "default-width");
4137 info->default_height = height;
4139 g_object_notify (G_OBJECT (window), "default-height");
4142 g_object_thaw_notify (G_OBJECT (window));
4144 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4148 * gtk_window_set_default_size:
4149 * @window: a #GtkWindow
4150 * @width: width in pixels, or -1 to unset the default width
4151 * @height: height in pixels, or -1 to unset the default height
4153 * Sets the default size of a window. If the window's "natural" size
4154 * (its size request) is larger than the default, the default will be
4155 * ignored. More generally, if the default size does not obey the
4156 * geometry hints for the window (gtk_window_set_geometry_hints() can
4157 * be used to set these explicitly), the default size will be clamped
4158 * to the nearest permitted size.
4160 * Unlike gtk_widget_set_size_request(), which sets a size request for
4161 * a widget and thus would keep users from shrinking the window, this
4162 * function only sets the initial size, just as if the user had
4163 * resized the window themselves. Users can still shrink the window
4164 * again as they normally would. Setting a default size of -1 means to
4165 * use the "natural" default size (the size request of the window).
4167 * For more control over a window's initial size and how resizing works,
4168 * investigate gtk_window_set_geometry_hints().
4170 * For some uses, gtk_window_resize() is a more appropriate function.
4171 * gtk_window_resize() changes the current size of the window, rather
4172 * than the size to be used on initial display. gtk_window_resize() always
4173 * affects the window itself, not the geometry widget.
4175 * The default size of a window only affects the first time a window is
4176 * shown; if a window is hidden and re-shown, it will remember the size
4177 * it had prior to hiding, rather than using the default size.
4179 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4180 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4183 gtk_window_set_default_size (GtkWindow *window,
4187 g_return_if_fail (GTK_IS_WINDOW (window));
4188 g_return_if_fail (width >= -1);
4189 g_return_if_fail (height >= -1);
4191 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4195 * gtk_window_set_default_geometry:
4196 * @window: a #GtkWindow
4197 * @width: width in resize increments, or -1 to unset the default width
4198 * @height: height in resize increments, or -1 to unset the default height
4200 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4201 * in terms of the base size and increment set with
4202 * gtk_window_set_geometry_hints.
4207 gtk_window_set_default_geometry (GtkWindow *window,
4211 g_return_if_fail (GTK_IS_WINDOW (window));
4212 g_return_if_fail (width >= -1);
4213 g_return_if_fail (height >= -1);
4215 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4219 * gtk_window_get_default_size:
4220 * @window: a #GtkWindow
4221 * @width: (out) (allow-none): location to store the default width, or %NULL
4222 * @height: (out) (allow-none): location to store the default height, or %NULL
4224 * Gets the default size of the window. A value of -1 for the width or
4225 * height indicates that a default size has not been explicitly set
4226 * for that dimension, so the "natural" size of the window will be
4231 gtk_window_get_default_size (GtkWindow *window,
4235 GtkWindowGeometryInfo *info;
4237 g_return_if_fail (GTK_IS_WINDOW (window));
4239 info = gtk_window_get_geometry_info (window, FALSE);
4242 *width = info ? info->default_width : -1;
4245 *height = info ? info->default_height : -1;
4249 * gtk_window_resize:
4250 * @window: a #GtkWindow
4251 * @width: width in pixels to resize the window to
4252 * @height: height in pixels to resize the window to
4254 * Resizes the window as if the user had done so, obeying geometry
4255 * constraints. The default geometry constraint is that windows may
4256 * not be smaller than their size request; to override this
4257 * constraint, call gtk_widget_set_size_request() to set the window's
4258 * request to a smaller value.
4260 * If gtk_window_resize() is called before showing a window for the
4261 * first time, it overrides any default size set with
4262 * gtk_window_set_default_size().
4264 * Windows may not be resized smaller than 1 by 1 pixels.
4268 gtk_window_resize (GtkWindow *window,
4272 GtkWindowGeometryInfo *info;
4274 g_return_if_fail (GTK_IS_WINDOW (window));
4275 g_return_if_fail (width > 0);
4276 g_return_if_fail (height > 0);
4278 info = gtk_window_get_geometry_info (window, TRUE);
4280 info->resize_width = width;
4281 info->resize_height = height;
4282 info->resize_is_geometry = FALSE;
4284 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4288 * gtk_window_resize_to_geometry:
4289 * @window: a #GtkWindow
4290 * @width: width in resize increments to resize the window to
4291 * @height: height in resize increments to resize the window to
4293 * Like gtk_window_resize(), but @width and @height are interpreted
4294 * in terms of the base size and increment set with
4295 * gtk_window_set_geometry_hints.
4300 gtk_window_resize_to_geometry (GtkWindow *window,
4304 GtkWindowGeometryInfo *info;
4306 g_return_if_fail (GTK_IS_WINDOW (window));
4307 g_return_if_fail (width > 0);
4308 g_return_if_fail (height > 0);
4310 info = gtk_window_get_geometry_info (window, TRUE);
4312 info->resize_width = width;
4313 info->resize_height = height;
4314 info->resize_is_geometry = TRUE;
4316 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4320 * gtk_window_get_size:
4321 * @window: a #GtkWindow
4322 * @width: (out) (allow-none): return location for width, or %NULL
4323 * @height: (out) (allow-none): return location for height, or %NULL
4325 * Obtains the current size of @window. If @window is not onscreen,
4326 * it returns the size GTK+ will suggest to the <link
4327 * linkend="gtk-X11-arch">window manager</link> for the initial window
4328 * size (but this is not reliably the same as the size the window
4329 * manager will actually select). The size obtained by
4330 * gtk_window_get_size() is the last size received in a
4331 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4332 * rather than querying the X server for the size. As a result, if you
4333 * call gtk_window_resize() then immediately call
4334 * gtk_window_get_size(), the size won't have taken effect yet. After
4335 * the window manager processes the resize request, GTK+ receives
4336 * notification that the size has changed via a configure event, and
4337 * the size of the window gets updated.
4339 * Note 1: Nearly any use of this function creates a race condition,
4340 * because the size of the window may change between the time that you
4341 * get the size and the time that you perform some action assuming
4342 * that size is the current size. To avoid race conditions, connect to
4343 * "configure-event" on the window and adjust your size-dependent
4344 * state to match the size delivered in the #GdkEventConfigure.
4346 * Note 2: The returned size does <emphasis>not</emphasis> include the
4347 * size of the window manager decorations (aka the window frame or
4348 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4349 * method of determining their size.
4351 * Note 3: If you are getting a window size in order to position
4352 * the window onscreen, there may be a better way. The preferred
4353 * way is to simply set the window's semantic type with
4354 * gtk_window_set_type_hint(), which allows the window manager to
4355 * e.g. center dialogs. Also, if you set the transient parent of
4356 * dialogs with gtk_window_set_transient_for() window managers
4357 * will often center the dialog over its parent window. It's
4358 * much preferred to let the window manager handle these
4359 * things rather than doing it yourself, because all apps will
4360 * behave consistently and according to user prefs if the window
4361 * manager handles it. Also, the window manager can take the size
4362 * of the window decorations/border into account, while your
4363 * application cannot.
4365 * In any case, if you insist on application-specified window
4366 * positioning, there's <emphasis>still</emphasis> a better way than
4367 * doing it yourself - gtk_window_set_position() will frequently
4368 * handle the details for you.
4372 gtk_window_get_size (GtkWindow *window,
4378 g_return_if_fail (GTK_IS_WINDOW (window));
4380 if (width == NULL && height == NULL)
4383 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4385 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4386 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4390 GdkRectangle configure_request;
4392 gtk_window_compute_configure_request (window,
4396 w = configure_request.width;
4397 h = configure_request.height;
4408 * @window: a #GtkWindow
4409 * @x: X coordinate to move window to
4410 * @y: Y coordinate to move window to
4412 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4413 * @window to the given position. Window managers are free to ignore
4414 * this; most window managers ignore requests for initial window
4415 * positions (instead using a user-defined placement algorithm) and
4416 * honor requests after the window has already been shown.
4418 * Note: the position is the position of the gravity-determined
4419 * reference point for the window. The gravity determines two things:
4420 * first, the location of the reference point in root window
4421 * coordinates; and second, which point on the window is positioned at
4422 * the reference point.
4424 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4425 * point is simply the @x, @y supplied to gtk_window_move(). The
4426 * top-left corner of the window decorations (aka window frame or
4427 * border) will be placed at @x, @y. Therefore, to position a window
4428 * at the top left of the screen, you want to use the default gravity
4429 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4431 * To position a window at the bottom right corner of the screen, you
4432 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4433 * point is at @x + the window width and @y + the window height, and
4434 * the bottom-right corner of the window border will be placed at that
4435 * reference point. So, to place a window in the bottom right corner
4436 * you would first set gravity to south east, then write:
4437 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4438 * gdk_screen_height () - window_height)</literal> (note that this
4439 * example does not take multi-head scenarios into account).
4441 * The Extended Window Manager Hints specification at <ulink
4442 * url="http://www.freedesktop.org/Standards/wm-spec">
4443 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4444 * nice table of gravities in the "implementation notes" section.
4446 * The gtk_window_get_position() documentation may also be relevant.
4449 gtk_window_move (GtkWindow *window,
4453 GtkWindowGeometryInfo *info;
4456 g_return_if_fail (GTK_IS_WINDOW (window));
4458 widget = GTK_WIDGET (window);
4460 info = gtk_window_get_geometry_info (window, TRUE);
4462 if (gtk_widget_get_mapped (widget))
4464 GtkAllocation allocation;
4466 gtk_widget_get_allocation (widget, &allocation);
4468 /* we have now sent a request with this position
4469 * with currently-active constraints, so toggle flag.
4471 info->position_constraints_changed = FALSE;
4473 /* we only constrain if mapped - if not mapped,
4474 * then gtk_window_compute_configure_request()
4475 * will apply the constraints later, and we
4476 * don't want to lose information about
4477 * what position the user set before then.
4478 * i.e. if you do a move() then turn off POS_CENTER
4479 * then show the window, your move() will work.
4481 gtk_window_constrain_position (window,
4482 allocation.width, allocation.height,
4485 /* Note that this request doesn't go through our standard request
4486 * framework, e.g. doesn't increment configure_request_count,
4487 * doesn't set info->last, etc.; that's because
4488 * we don't save the info needed to arrive at this same request
4491 * To gtk_window_move_resize(), this will end up looking exactly
4492 * the same as the position being changed by the window
4495 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4499 /* Save this position to apply on mapping */
4500 info->initial_x = x;
4501 info->initial_y = y;
4502 info->initial_pos_set = TRUE;
4507 * gtk_window_get_position:
4508 * @window: a #GtkWindow
4509 * @root_x: (out) (allow-none): eturn location for X coordinate of
4510 * gravity-determined reference point, or %NULL
4511 * @root_y: (out) (allow-none): return location for Y coordinate of
4512 * gravity-determined reference point, or %NULL
4514 * This function returns the position you need to pass to
4515 * gtk_window_move() to keep @window in its current position.
4516 * This means that the meaning of the returned value varies with
4517 * window gravity. See gtk_window_move() for more details.
4519 * If you haven't changed the window gravity, its gravity will be
4520 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4521 * gets the position of the top-left corner of the window manager
4522 * frame for the window. gtk_window_move() sets the position of this
4523 * same top-left corner.
4525 * gtk_window_get_position() is not 100% reliable because the X Window System
4526 * does not specify a way to obtain the geometry of the
4527 * decorations placed on a window by the window manager.
4528 * Thus GTK+ is using a "best guess" that works with most
4531 * Moreover, nearly all window managers are historically broken with
4532 * respect to their handling of window gravity. So moving a window to
4533 * its current position as returned by gtk_window_get_position() tends
4534 * to result in moving the window slightly. Window managers are
4535 * slowly getting better over time.
4537 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4538 * frame is not relevant, and thus gtk_window_get_position() will
4539 * always produce accurate results. However you can't use static
4540 * gravity to do things like place a window in a corner of the screen,
4541 * because static gravity ignores the window manager decorations.
4543 * If you are saving and restoring your application's window
4544 * positions, you should know that it's impossible for applications to
4545 * do this without getting it somewhat wrong because applications do
4546 * not have sufficient knowledge of window manager state. The Correct
4547 * Mechanism is to support the session management protocol (see the
4548 * "GnomeClient" object in the GNOME libraries for example) and allow
4549 * the window manager to save your window sizes and positions.
4554 gtk_window_get_position (GtkWindow *window,
4558 GtkWindowPrivate *priv;
4560 GdkWindow *gdk_window;
4562 g_return_if_fail (GTK_IS_WINDOW (window));
4564 priv = window->priv;
4565 widget = GTK_WIDGET (window);
4566 gdk_window = gtk_widget_get_window (widget);
4568 if (priv->gravity == GDK_GRAVITY_STATIC)
4570 if (gtk_widget_get_mapped (widget))
4572 /* This does a server round-trip, which is sort of wrong;
4573 * but a server round-trip is inevitable for
4574 * gdk_window_get_frame_extents() in the usual
4575 * NorthWestGravity case below, so not sure what else to
4576 * do. We should likely be consistent about whether we get
4577 * the client-side info or the server-side info.
4579 gdk_window_get_origin (gdk_window, root_x, root_y);
4583 GdkRectangle configure_request;
4585 gtk_window_compute_configure_request (window,
4589 *root_x = configure_request.x;
4590 *root_y = configure_request.y;
4595 GdkRectangle frame_extents;
4600 if (gtk_widget_get_mapped (widget))
4602 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4603 x = frame_extents.x;
4604 y = frame_extents.y;
4605 gtk_window_get_size (window, &w, &h);
4609 /* We just say the frame has 0 size on all sides.
4610 * Not sure what else to do.
4612 gtk_window_compute_configure_request (window,
4615 x = frame_extents.x;
4616 y = frame_extents.y;
4617 w = frame_extents.width;
4618 h = frame_extents.height;
4621 switch (priv->gravity)
4623 case GDK_GRAVITY_NORTH:
4624 case GDK_GRAVITY_CENTER:
4625 case GDK_GRAVITY_SOUTH:
4626 /* Find center of frame. */
4627 x += frame_extents.width / 2;
4628 /* Center client window on that point. */
4632 case GDK_GRAVITY_SOUTH_EAST:
4633 case GDK_GRAVITY_EAST:
4634 case GDK_GRAVITY_NORTH_EAST:
4635 /* Find right edge of frame */
4636 x += frame_extents.width;
4637 /* Align left edge of client at that point. */
4644 switch (priv->gravity)
4646 case GDK_GRAVITY_WEST:
4647 case GDK_GRAVITY_CENTER:
4648 case GDK_GRAVITY_EAST:
4649 /* Find center of frame. */
4650 y += frame_extents.height / 2;
4651 /* Center client window there. */
4654 case GDK_GRAVITY_SOUTH_WEST:
4655 case GDK_GRAVITY_SOUTH:
4656 case GDK_GRAVITY_SOUTH_EAST:
4657 /* Find south edge of frame */
4658 y += frame_extents.height;
4659 /* Place bottom edge of client there */
4674 * gtk_window_reshow_with_initial_size:
4675 * @window: a #GtkWindow
4677 * Hides @window, then reshows it, resetting the
4678 * default size and position of the window. Used
4679 * by GUI builders only.
4682 gtk_window_reshow_with_initial_size (GtkWindow *window)
4686 g_return_if_fail (GTK_IS_WINDOW (window));
4688 widget = GTK_WIDGET (window);
4690 gtk_widget_hide (widget);
4691 gtk_widget_unrealize (widget);
4692 gtk_widget_show (widget);
4696 gtk_window_destroy (GtkWidget *widget)
4698 GtkWindow *window = GTK_WINDOW (widget);
4699 GtkWindowPrivate *priv = window->priv;
4701 gtk_window_release_application (window);
4703 toplevel_list = g_slist_remove (toplevel_list, window);
4705 if (priv->transient_parent)
4706 gtk_window_set_transient_for (window, NULL);
4708 remove_attach_widget (GTK_WINDOW (widget));
4710 /* frees the icons */
4711 gtk_window_set_icon_list (window, NULL);
4713 if (priv->has_user_ref_count)
4715 priv->has_user_ref_count = FALSE;
4716 g_object_unref (window);
4720 gtk_window_group_remove_window (priv->group, window);
4722 gtk_window_free_key_hash (window);
4724 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4728 gtk_window_finalize (GObject *object)
4730 GtkWindow *window = GTK_WINDOW (object);
4731 GtkWindowPrivate *priv = window->priv;
4732 GtkMnemonicHash *mnemonic_hash;
4734 g_free (priv->title);
4735 g_free (priv->wmclass_name);
4736 g_free (priv->wmclass_class);
4737 g_free (priv->wm_role);
4738 gtk_window_release_application (window);
4740 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4742 _gtk_mnemonic_hash_free (mnemonic_hash);
4744 if (priv->geometry_info)
4746 if (priv->geometry_info->widget)
4747 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4748 gtk_widget_destroyed,
4749 &priv->geometry_info->widget);
4750 g_free (priv->geometry_info);
4753 if (priv->keys_changed_handler)
4755 g_source_remove (priv->keys_changed_handler);
4756 priv->keys_changed_handler = 0;
4760 g_signal_handlers_disconnect_by_func (priv->screen,
4761 gtk_window_on_composited_changed, window);
4763 g_free (priv->startup_id);
4765 #ifdef GDK_WINDOWING_X11
4766 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
4767 gtk_window_on_theme_variant_changed,
4771 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4775 gtk_window_show (GtkWidget *widget)
4777 GtkWindow *window = GTK_WINDOW (widget);
4778 GtkWindowPrivate *priv = window->priv;
4779 GtkContainer *container = GTK_CONTAINER (window);
4780 gboolean need_resize;
4783 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4785 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4789 _gtk_widget_set_visible_flag (widget, TRUE);
4791 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4792 _gtk_container_set_need_resize (container, FALSE);
4796 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4797 GtkAllocation allocation = { 0, 0 };
4798 GdkRectangle configure_request;
4799 GdkGeometry new_geometry;
4801 gboolean was_realized;
4803 /* We are going to go ahead and perform this configure request
4804 * and then emulate a configure notify by going ahead and
4805 * doing a size allocate. Sort of a synchronous
4806 * mini-copy of gtk_window_move_resize() here.
4808 gtk_window_compute_configure_request (window,
4813 /* We update this because we are going to go ahead
4814 * and gdk_window_resize() below, rather than
4817 info->last.configure_request.width = configure_request.width;
4818 info->last.configure_request.height = configure_request.height;
4820 /* and allocate the window - this is normally done
4821 * in move_resize in response to configure notify
4823 allocation.width = configure_request.width;
4824 allocation.height = configure_request.height;
4825 gtk_widget_size_allocate (widget, &allocation);
4827 /* Then we guarantee we have a realize */
4828 was_realized = FALSE;
4829 if (!gtk_widget_get_realized (widget))
4831 gtk_widget_realize (widget);
4832 was_realized = TRUE;
4835 /* We only send configure request if we didn't just finish
4836 * creating the window; if we just created the window
4837 * then we created it with widget->allocation anyhow.
4840 gdk_window_move_resize (gtk_widget_get_window (widget),
4841 configure_request.x,
4842 configure_request.y,
4843 configure_request.width,
4844 configure_request.height);
4847 gtk_container_check_resize (container);
4849 gtk_widget_map (widget);
4851 /* Try to make sure that we have some focused widget
4853 #ifdef GDK_WINDOWING_X11
4854 is_plug = GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)) &&
4855 GTK_IS_PLUG (window);
4859 if (!priv->focus_widget && !is_plug)
4860 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4863 gtk_grab_add (widget);
4867 gtk_window_hide (GtkWidget *widget)
4869 GtkWindow *window = GTK_WINDOW (widget);
4870 GtkWindowPrivate *priv = window->priv;
4872 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4874 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4878 _gtk_widget_set_visible_flag (widget, FALSE);
4879 gtk_widget_unmap (widget);
4882 gtk_grab_remove (widget);
4886 gtk_window_map (GtkWidget *widget)
4889 GtkWindow *window = GTK_WINDOW (widget);
4890 GtkWindowPrivate *priv = window->priv;
4891 GdkWindow *gdk_window;
4892 gboolean auto_mnemonics;
4893 GtkPolicyType visible_focus;
4895 if (!gtk_widget_is_toplevel (widget))
4897 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4901 gtk_widget_set_mapped (widget, TRUE);
4903 child = gtk_bin_get_child (&(window->bin));
4905 gtk_widget_get_visible (child) &&
4906 !gtk_widget_get_mapped (child))
4907 gtk_widget_map (child);
4909 gdk_window = gtk_widget_get_window (widget);
4911 if (priv->maximize_initially)
4912 gdk_window_maximize (gdk_window);
4914 gdk_window_unmaximize (gdk_window);
4916 if (priv->stick_initially)
4917 gdk_window_stick (gdk_window);
4919 gdk_window_unstick (gdk_window);
4921 if (priv->iconify_initially)
4922 gdk_window_iconify (gdk_window);
4924 gdk_window_deiconify (gdk_window);
4926 if (priv->fullscreen_initially)
4927 gdk_window_fullscreen (gdk_window);
4929 gdk_window_unfullscreen (gdk_window);
4931 gdk_window_set_keep_above (gdk_window, priv->above_initially);
4933 gdk_window_set_keep_below (gdk_window, priv->below_initially);
4935 if (priv->type == GTK_WINDOW_TOPLEVEL)
4937 gtk_window_set_theme_variant (window);
4938 gtk_window_set_hide_titlebar_when_maximized (window,
4939 priv->hide_titlebar_when_maximized);
4942 /* No longer use the default settings */
4943 priv->need_default_size = FALSE;
4944 priv->need_default_position = FALSE;
4946 if (priv->reset_type_hint)
4948 /* We should only reset the type hint when the application
4949 * used gtk_window_set_type_hint() to change the hint.
4950 * Some applications use X directly to change the properties;
4951 * in that case, we shouldn't overwrite what they did.
4953 gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
4954 priv->reset_type_hint = FALSE;
4957 gdk_window_show (gdk_window);
4959 if (priv->grip_window)
4960 gdk_window_show (priv->grip_window);
4962 if (!disable_startup_notification)
4964 /* Do we have a custom startup-notification id? */
4965 if (priv->startup_id != NULL)
4967 /* Make sure we have a "real" id */
4968 if (!startup_id_is_fake (priv->startup_id))
4969 gdk_notify_startup_complete_with_id (priv->startup_id);
4971 g_free (priv->startup_id);
4972 priv->startup_id = NULL;
4974 else if (!sent_startup_notification)
4976 sent_startup_notification = TRUE;
4977 gdk_notify_startup_complete ();
4981 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4982 * (as in the case of popup menus), then hide mnemonics initially
4984 g_object_get (gtk_widget_get_settings (widget),
4985 "gtk-auto-mnemonics", &auto_mnemonics,
4986 "gtk-visible-focus", &visible_focus,
4989 if (auto_mnemonics && !priv->mnemonics_visible_set)
4990 gtk_window_set_mnemonics_visible (window, FALSE);
4992 /* inherit from transient parent, so that a dialog that is
4993 * opened via keynav shows focus initially
4995 if (priv->transient_parent)
4996 gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
4998 gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
5000 ensure_state_flag_backdrop (widget);
5004 gtk_window_map_event (GtkWidget *widget,
5007 if (!gtk_widget_get_mapped (widget))
5009 /* we should be be unmapped, but are getting a MapEvent, this may happen
5010 * to toplevel XWindows if mapping was intercepted by a window manager
5011 * and an unmap request occoured while the MapRequestEvent was still
5012 * being handled. we work around this situaiton here by re-requesting
5013 * the window being unmapped. more details can be found in:
5014 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
5016 gdk_window_hide (gtk_widget_get_window (widget));
5022 gtk_window_unmap (GtkWidget *widget)
5024 GtkWindow *window = GTK_WINDOW (widget);
5025 GtkWindowPrivate *priv = window->priv;
5027 GtkWindowGeometryInfo *info;
5028 GdkWindow *gdk_window;
5029 GdkWindowState state;
5031 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5033 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
5037 gdk_window = gtk_widget_get_window (widget);
5039 gtk_widget_set_mapped (widget, FALSE);
5040 gdk_window_withdraw (gdk_window);
5042 priv->configure_request_count = 0;
5043 priv->configure_notify_received = FALSE;
5045 /* on unmap, we reset the default positioning of the window,
5046 * so it's placed again, but we don't reset the default
5047 * size of the window, so it's remembered.
5049 priv->need_default_position = TRUE;
5051 info = gtk_window_get_geometry_info (window, FALSE);
5054 info->initial_pos_set = FALSE;
5055 info->position_constraints_changed = FALSE;
5058 state = gdk_window_get_state (gdk_window);
5059 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
5060 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
5061 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
5062 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
5063 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
5065 child = gtk_bin_get_child (&(window->bin));
5067 gtk_widget_unmap (child);
5070 /* (Note: Replace "size" with "width" or "height". Also, the request
5071 * mode is honoured.)
5072 * For selecting the default window size, the following conditions
5073 * should hold (in order of importance):
5074 * - the size is not below the minimum size
5075 * Windows cannot be resized below their minimum size, so we must
5076 * ensure we don't do that either.
5077 * - the size is not above the natural size
5078 * It seems weird to allocate more than this in an initial guess.
5079 * - the size does not exceed that of a maximized window
5080 * We want to see the whole window after all.
5081 * (Note that this may not be possible to achieve due to imperfect
5082 * information from the windowing system.)
5085 /* We use these for now to not make windows too big by accident. Note
5086 * that we still clamp these numbers by screen size. Also note that
5087 * minimum size still overrides this. So keep your windows small! :)
5089 #define MAX_DEFAULT_WINDOW_WIDTH 640
5090 #define MAX_DEFAULT_WINDOW_HEIGHT 480
5093 gtk_window_guess_default_size (GtkWindow *window,
5097 GtkWidget *widget = GTK_WIDGET (window);
5099 int minimum, natural;
5101 screen = gtk_widget_get_screen (widget);
5103 *width = gdk_screen_get_width (screen);
5104 *height = gdk_screen_get_height (screen);
5106 if (*width >= *height)
5109 *width = MIN (*width, MAX_DEFAULT_WINDOW_WIDTH);
5110 *height = MIN (*height, MAX_DEFAULT_WINDOW_HEIGHT);
5115 *width = MIN (*width, MAX_DEFAULT_WINDOW_HEIGHT);
5116 *height = MIN (*height, MAX_DEFAULT_WINDOW_WIDTH);
5119 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
5121 gtk_widget_get_preferred_height (widget, &minimum, &natural);
5122 *height = MAX (minimum, MIN (*height, natural));
5124 gtk_widget_get_preferred_width_for_height (widget, *height, &minimum, &natural);
5125 *width = MAX (minimum, MIN (*width, natural));
5127 else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
5129 gtk_widget_get_preferred_width (widget, &minimum, &natural);
5130 *width = MAX (minimum, MIN (*width, natural));
5132 gtk_widget_get_preferred_height_for_width (widget, *width, &minimum, &natural);
5133 *height = MAX (minimum, MIN (*height, natural));
5138 gtk_window_realize (GtkWidget *widget)
5140 GtkAllocation allocation;
5142 GdkWindow *parent_window;
5143 GdkWindow *gdk_window;
5144 GdkWindowAttr attributes;
5145 gint attributes_mask;
5146 GtkWindowPrivate *priv;
5147 GtkStyleContext *context;
5149 window = GTK_WINDOW (widget);
5150 priv = window->priv;
5152 gtk_widget_get_allocation (widget, &allocation);
5154 if (gtk_widget_get_parent_window (widget))
5156 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
5158 gtk_widget_set_realized (widget, TRUE);
5160 attributes.x = allocation.x;
5161 attributes.y = allocation.y;
5162 attributes.width = allocation.width;
5163 attributes.height = allocation.height;
5164 attributes.window_type = GDK_WINDOW_CHILD;
5166 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
5168 attributes.visual = gtk_widget_get_visual (widget);
5169 attributes.wclass = GDK_INPUT_OUTPUT;
5171 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
5173 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
5174 &attributes, attributes_mask);
5175 gtk_widget_set_window (widget, gdk_window);
5176 gdk_window_set_user_data (gdk_window, widget);
5178 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
5180 gdk_window_enable_synchronized_configure (gdk_window);
5184 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
5186 /* ensure widget tree is properly size allocated */
5187 if (allocation.x == -1 &&
5188 allocation.y == -1 &&
5189 allocation.width == 1 &&
5190 allocation.height == 1)
5196 gtk_window_guess_default_size (window, &allocation.width, &allocation.height);
5197 if (allocation.width == 0 || allocation.height == 0)
5199 /* non-empty window */
5200 allocation.width = 200;
5201 allocation.height = 200;
5203 gtk_widget_size_allocate (widget, &allocation);
5205 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5207 g_return_if_fail (!gtk_widget_get_realized (widget));
5210 gtk_widget_set_realized (widget, TRUE);
5214 case GTK_WINDOW_TOPLEVEL:
5215 attributes.window_type = GDK_WINDOW_TOPLEVEL;
5217 case GTK_WINDOW_POPUP:
5218 attributes.window_type = GDK_WINDOW_TEMP;
5221 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
5225 attributes.title = priv->title;
5226 attributes.wmclass_name = priv->wmclass_name;
5227 attributes.wmclass_class = priv->wmclass_class;
5228 attributes.wclass = GDK_INPUT_OUTPUT;
5229 attributes.visual = gtk_widget_get_visual (widget);
5231 attributes_mask = 0;
5232 parent_window = gtk_widget_get_root_window (widget);
5234 gtk_widget_get_allocation (widget, &allocation);
5235 attributes.width = allocation.width;
5236 attributes.height = allocation.height;
5237 attributes.event_mask = gtk_widget_get_events (widget);
5238 attributes.event_mask |= (GDK_EXPOSURE_MASK |
5239 GDK_KEY_PRESS_MASK |
5240 GDK_KEY_RELEASE_MASK |
5241 GDK_ENTER_NOTIFY_MASK |
5242 GDK_LEAVE_NOTIFY_MASK |
5243 GDK_FOCUS_CHANGE_MASK |
5244 GDK_STRUCTURE_MASK);
5245 attributes.type_hint = priv->type_hint;
5247 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5248 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5249 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5251 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5252 gtk_widget_set_window (widget, gdk_window);
5254 if (priv->opacity_set)
5255 gdk_window_set_opacity (gdk_window, priv->opacity);
5257 gdk_window_enable_synchronized_configure (gdk_window);
5259 gdk_window_set_user_data (gdk_window, window);
5261 context = gtk_widget_get_style_context (widget);
5262 gtk_style_context_set_background (context, gdk_window);
5265 if (priv->transient_parent &&
5266 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5267 gdk_window_set_transient_for (gdk_window,
5268 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5271 gdk_window_set_role (gdk_window, priv->wm_role);
5273 if (!priv->decorated)
5274 gdk_window_set_decorations (gdk_window, 0);
5276 if (!priv->deletable)
5277 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5279 if (gtk_window_get_skip_pager_hint (window))
5280 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5282 if (gtk_window_get_skip_taskbar_hint (window))
5283 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5285 if (gtk_window_get_accept_focus (window))
5286 gdk_window_set_accept_focus (gdk_window, TRUE);
5288 gdk_window_set_accept_focus (gdk_window, FALSE);
5290 if (gtk_window_get_focus_on_map (window))
5291 gdk_window_set_focus_on_map (gdk_window, TRUE);
5293 gdk_window_set_focus_on_map (gdk_window, FALSE);
5296 gdk_window_set_modal_hint (gdk_window, TRUE);
5298 gdk_window_set_modal_hint (gdk_window, FALSE);
5300 if (priv->startup_id)
5302 #ifdef GDK_WINDOWING_X11
5303 if (GDK_IS_X11_WINDOW (gdk_window))
5305 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5306 if (timestamp != GDK_CURRENT_TIME)
5307 gdk_x11_window_set_user_time (gdk_window, timestamp);
5310 if (!startup_id_is_fake (priv->startup_id))
5311 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5314 #ifdef GDK_WINDOWING_X11
5315 if (priv->initial_timestamp != GDK_CURRENT_TIME)
5317 if (GDK_IS_X11_WINDOW (gdk_window))
5318 gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
5322 gtk_window_set_application (window, gtk_window_get_application (window));
5325 gtk_window_realize_icon (window);
5327 if (priv->has_resize_grip)
5328 resize_grip_create_window (window);
5332 gtk_window_unrealize (GtkWidget *widget)
5334 GtkWindow *window = GTK_WINDOW (widget);
5335 GtkWindowPrivate *priv = window->priv;
5336 GtkWindowGeometryInfo *info;
5338 /* On unrealize, we reset the size of the window such
5339 * that we will re-apply the default sizing stuff
5340 * next time we show the window.
5342 * Default positioning is reset on unmap, instead of unrealize.
5344 priv->need_default_size = TRUE;
5345 info = gtk_window_get_geometry_info (window, FALSE);
5348 info->resize_width = -1;
5349 info->resize_height = -1;
5350 info->last.configure_request.x = 0;
5351 info->last.configure_request.y = 0;
5352 info->last.configure_request.width = -1;
5353 info->last.configure_request.height = -1;
5354 /* be sure we reset geom hints on re-realize */
5355 info->last.flags = 0;
5359 gtk_window_unrealize_icon (window);
5361 if (priv->grip_window != NULL)
5362 resize_grip_destroy_window (window);
5364 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5367 static GtkJunctionSides
5368 get_grip_junction (GtkWidget *widget)
5370 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5371 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5373 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5377 get_drag_edge (GtkWidget *widget,
5378 GdkWindowEdge *edge)
5380 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5381 gboolean hresizable;
5382 gboolean vresizable;
5383 GtkTextDirection dir;
5384 GtkWindowGeometryInfo *info;
5389 info = priv->geometry_info;
5392 GdkWindowHints flags = info->last.flags;
5393 GdkGeometry *geometry = &info->last.geometry;
5395 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5397 hresizable = geometry->min_width < geometry->max_width;
5398 vresizable = geometry->min_height < geometry->max_height;
5402 dir = gtk_widget_get_direction (widget);
5404 if (hresizable && vresizable)
5405 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5406 else if (hresizable)
5407 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5408 else if (vresizable)
5409 *edge = GDK_WINDOW_EDGE_SOUTH;
5417 set_grip_cursor (GtkWindow *window)
5419 GtkWidget *widget = GTK_WIDGET (window);
5420 GtkWindowPrivate *priv = window->priv;
5422 if (priv->grip_window == NULL)
5425 if (gtk_widget_is_sensitive (widget))
5428 GdkDisplay *display;
5429 GdkCursorType cursor_type;
5432 cursor_type = GDK_LEFT_PTR;
5434 if (get_drag_edge (widget, &edge))
5438 case GDK_WINDOW_EDGE_EAST:
5439 cursor_type = GDK_RIGHT_SIDE;
5441 case GDK_WINDOW_EDGE_SOUTH_EAST:
5442 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5444 case GDK_WINDOW_EDGE_SOUTH:
5445 cursor_type = GDK_BOTTOM_SIDE;
5447 case GDK_WINDOW_EDGE_SOUTH_WEST:
5448 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5450 case GDK_WINDOW_EDGE_WEST:
5451 cursor_type = GDK_LEFT_SIDE;
5457 display = gtk_widget_get_display (widget);
5458 cursor = gdk_cursor_new_for_display (display, cursor_type);
5459 gdk_window_set_cursor (priv->grip_window, cursor);
5460 g_object_unref (cursor);
5463 gdk_window_set_cursor (priv->grip_window, NULL);
5467 set_grip_shape (GtkWindow *window)
5469 GtkWindowPrivate *priv = window->priv;
5470 cairo_region_t *region;
5471 cairo_surface_t *surface;
5473 double width, height;
5475 if (priv->grip_window == NULL)
5478 width = gdk_window_get_width (priv->grip_window);
5479 height = gdk_window_get_height (priv->grip_window);
5480 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
5482 cr = cairo_create (surface);
5483 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5485 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5486 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5488 cairo_move_to (cr, width, 0.0);
5489 cairo_line_to (cr, width, height);
5490 cairo_line_to (cr, 0.0, height);
5494 cairo_move_to (cr, 0.0, 0.0);
5495 cairo_line_to (cr, width, height);
5496 cairo_line_to (cr, 0.0, height);
5498 cairo_close_path (cr);
5501 region = gdk_cairo_region_create_from_surface (surface);
5502 cairo_surface_destroy (surface);
5504 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5505 cairo_region_destroy (region);
5509 set_grip_position (GtkWindow *window)
5511 GtkWindowPrivate *priv = window->priv;
5514 if (priv->grip_window == NULL)
5517 gtk_window_get_resize_grip_area (window, &rect);
5518 gdk_window_raise (priv->grip_window);
5519 gdk_window_move_resize (priv->grip_window,
5521 rect.width, rect.height);
5525 gtk_window_size_allocate (GtkWidget *widget,
5526 GtkAllocation *allocation)
5528 GtkWindow *window = GTK_WINDOW (widget);
5529 GtkAllocation child_allocation;
5533 gtk_widget_set_allocation (widget, allocation);
5535 if (gtk_widget_get_realized (widget))
5537 /* If it's not a toplevel we're embedded, we need to resize the window's
5538 * window and skip the grip.
5540 if (!gtk_widget_is_toplevel (widget))
5542 gdk_window_move_resize (gtk_widget_get_window (widget),
5543 allocation->x, allocation->y,
5544 allocation->width, allocation->height);
5548 update_grip_visibility (window);
5549 set_grip_position (window);
5553 child = gtk_bin_get_child (&(window->bin));
5554 if (child && gtk_widget_get_visible (child))
5556 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5557 child_allocation.x = border_width;
5558 child_allocation.y = border_width;
5559 child_allocation.width =
5560 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5561 child_allocation.height =
5562 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5564 gtk_widget_size_allocate (child, &child_allocation);
5569 gtk_window_configure_event (GtkWidget *widget,
5570 GdkEventConfigure *event)
5572 GtkAllocation allocation;
5573 GtkWindow *window = GTK_WINDOW (widget);
5574 GtkWindowPrivate *priv = window->priv;
5575 gboolean expected_reply = priv->configure_request_count > 0;
5577 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5579 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5580 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5582 gdk_window_configure_finished (gtk_widget_get_window (widget));
5586 /* priv->configure_request_count incremented for each
5587 * configure request, and decremented to a min of 0 for
5588 * each configure notify.
5590 * All it means is that we know we will get at least
5591 * priv->configure_request_count more configure notifies.
5592 * We could get more configure notifies than that; some
5593 * of the configure notifies we get may be unrelated to
5594 * the configure requests. But we will get at least
5595 * priv->configure_request_count notifies.
5598 if (priv->configure_request_count > 0)
5600 priv->configure_request_count -= 1;
5601 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5604 /* As an optimization, we avoid a resize when possible.
5606 * The only times we can avoid a resize are:
5607 * - we know only the position changed, not the size
5608 * - we know we have made more requests and so will get more
5609 * notifies and can wait to resize when we get them
5611 gtk_widget_get_allocation (widget, &allocation);
5612 if (!expected_reply &&
5613 (allocation.width == event->width &&
5614 allocation.height == event->height))
5616 gdk_window_configure_finished (gtk_widget_get_window (widget));
5621 * If we do need to resize, we do that by:
5622 * - filling in widget->allocation with the new size
5623 * - setting configure_notify_received to TRUE
5624 * for use in gtk_window_move_resize()
5625 * - queueing a resize, leading to invocation of
5626 * gtk_window_move_resize() in an idle handler
5630 priv->configure_notify_received = TRUE;
5632 allocation.width = event->width;
5633 allocation.height = event->height;
5634 gtk_widget_set_allocation (widget, &allocation);
5636 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5638 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5644 gtk_window_state_event (GtkWidget *widget,
5645 GdkEventWindowState *event)
5647 update_grip_visibility (GTK_WINDOW (widget));
5649 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
5650 ensure_state_flag_backdrop (widget);
5656 gtk_window_direction_changed (GtkWidget *widget,
5657 GtkTextDirection prev_dir)
5659 GtkWindow *window = GTK_WINDOW (widget);
5661 set_grip_cursor (window);
5662 set_grip_position (window);
5663 set_grip_shape (window);
5667 gtk_window_state_changed (GtkWidget *widget,
5668 GtkStateType previous_state)
5670 GtkWindow *window = GTK_WINDOW (widget);
5672 update_grip_visibility (window);
5676 gtk_window_style_updated (GtkWidget *widget)
5678 GtkWindow *window = GTK_WINDOW (widget);
5679 GtkWindowPrivate *priv = window->priv;
5682 GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
5684 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5686 gdk_window_move_resize (priv->grip_window,
5688 rect.width, rect.height);
5690 set_grip_shape (window);
5691 gtk_widget_queue_resize (widget);
5696 resize_grip_create_window (GtkWindow *window)
5699 GtkWindowPrivate *priv;
5700 GdkWindowAttr attributes;
5701 gint attributes_mask;
5703 GdkRGBA transparent = {0, 0, 0, 0};
5705 priv = window->priv;
5706 widget = GTK_WIDGET (window);
5708 g_return_if_fail (gtk_widget_get_realized (widget));
5709 g_return_if_fail (priv->grip_window == NULL);
5711 gtk_window_get_resize_grip_area (window, &rect);
5713 attributes.x = rect.x;
5714 attributes.y = rect.y;
5715 attributes.width = rect.width;
5716 attributes.height = rect.height;
5717 attributes.window_type = GDK_WINDOW_CHILD;
5718 attributes.wclass = GDK_INPUT_OUTPUT;
5719 attributes.event_mask = gtk_widget_get_events (widget) |
5721 GDK_BUTTON_PRESS_MASK;
5723 attributes_mask = GDK_WA_X | GDK_WA_Y;
5725 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5728 gdk_window_set_background_rgba (priv->grip_window, &transparent);
5730 gdk_window_set_user_data (priv->grip_window, widget);
5732 gdk_window_raise (priv->grip_window);
5734 set_grip_shape (window);
5735 update_grip_visibility (window);
5739 resize_grip_destroy_window (GtkWindow *window)
5741 GtkWindowPrivate *priv = window->priv;
5743 gdk_window_set_user_data (priv->grip_window, NULL);
5744 gdk_window_destroy (priv->grip_window);
5745 priv->grip_window = NULL;
5746 update_grip_visibility (window);
5750 * gtk_window_set_has_resize_grip:
5751 * @window: a #GtkWindow
5752 * @value: %TRUE to allow a resize grip
5754 * Sets whether @window has a corner resize grip.
5756 * Note that the resize grip is only shown if the window
5757 * is actually resizable and not maximized. Use
5758 * gtk_window_resize_grip_is_visible() to find out if the
5759 * resize grip is currently shown.
5764 gtk_window_set_has_resize_grip (GtkWindow *window,
5767 GtkWidget *widget = GTK_WIDGET (window);
5768 GtkWindowPrivate *priv = window->priv;
5770 value = value != FALSE;
5772 if (value != priv->has_resize_grip)
5774 priv->has_resize_grip = value;
5775 gtk_widget_queue_draw (widget);
5777 if (gtk_widget_get_realized (widget) &&
5778 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5780 if (priv->has_resize_grip && priv->grip_window == NULL)
5781 resize_grip_create_window (window);
5782 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5783 resize_grip_destroy_window (window);
5786 g_object_notify (G_OBJECT (window), "has-resize-grip");
5791 update_grip_visibility (GtkWindow *window)
5793 GtkWindowPrivate *priv = window->priv;
5796 val = gtk_window_resize_grip_is_visible (window);
5798 if (priv->grip_window != NULL)
5802 gdk_window_show (priv->grip_window);
5803 set_grip_cursor (window);
5807 gdk_window_hide (priv->grip_window);
5811 if (priv->resize_grip_visible != val)
5813 priv->resize_grip_visible = val;
5815 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5820 * gtk_window_resize_grip_is_visible:
5821 * @window: a #GtkWindow
5823 * Determines whether a resize grip is visible for the specified window.
5825 * Returns: %TRUE if a resize grip exists and is visible
5830 gtk_window_resize_grip_is_visible (GtkWindow *window)
5833 GtkWindowPrivate *priv;
5836 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5838 priv = window->priv;
5839 widget = GTK_WIDGET (window);
5841 if (priv->type == GTK_WINDOW_POPUP)
5844 if (!priv->resizable)
5847 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5850 if (gtk_widget_get_realized (widget))
5852 GdkWindowState state;
5854 state = gdk_window_get_state (gtk_widget_get_window (widget));
5856 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5860 if (!get_drag_edge (widget, &edge))
5863 return window->priv->has_resize_grip;
5867 * gtk_window_get_has_resize_grip:
5868 * @window: a #GtkWindow
5870 * Determines whether the window may have a resize grip.
5872 * Returns: %TRUE if the window has a resize grip
5877 gtk_window_get_has_resize_grip (GtkWindow *window)
5879 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5881 return window->priv->has_resize_grip;
5885 * gtk_window_get_resize_grip_area:
5886 * @window: a #GtkWindow
5887 * @rect: (out): a pointer to a #GdkRectangle which we should store
5888 * the resize grip area
5890 * If a window has a resize grip, this will retrieve the grip
5891 * position, width and height into the specified #GdkRectangle.
5893 * Returns: %TRUE if the resize grip's area was retrieved
5898 gtk_window_get_resize_grip_area (GtkWindow *window,
5901 GtkWidget *widget = GTK_WIDGET (window);
5902 GtkAllocation allocation;
5906 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5908 if (!window->priv->has_resize_grip)
5911 gtk_widget_get_allocation (widget, &allocation);
5913 gtk_widget_style_get (widget,
5914 "resize-grip-width", &grip_width,
5915 "resize-grip-height", &grip_height,
5918 if (grip_width > allocation.width)
5919 grip_width = allocation.width;
5921 if (grip_height > allocation.height)
5922 grip_height = allocation.height;
5924 rect->width = grip_width;
5925 rect->height = grip_height;
5926 rect->y = allocation.y + allocation.height - grip_height;
5928 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5929 rect->x = allocation.x + allocation.width - grip_width;
5931 rect->x = allocation.x;
5936 /* the accel_key and accel_mods fields of the key have to be setup
5937 * upon calling this function. it'll then return whether that key
5938 * is at all used as accelerator, and if so will OR in the
5939 * accel_flags member of the key.
5942 _gtk_window_query_nonaccels (GtkWindow *window,
5944 GdkModifierType accel_mods)
5946 GtkWindowPrivate *priv;
5948 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5950 priv = window->priv;
5952 /* movement keys are considered locked accels */
5955 static const guint bindings[] = {
5956 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,
5957 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,
5961 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5962 if (bindings[i] == accel_key)
5966 /* mnemonics are considered locked accels */
5967 if (accel_mods == priv->mnemonic_modifier)
5969 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5970 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5978 * gtk_window_propagate_key_event:
5979 * @window: a #GtkWindow
5980 * @event: a #GdkEventKey
5982 * Propagate a key press or release event to the focus widget and
5983 * up the focus container chain until a widget handles @event.
5984 * This is normally called by the default ::key_press_event and
5985 * ::key_release_event handlers for toplevel windows,
5986 * however in some cases it may be useful to call this directly when
5987 * overriding the standard key handling for a toplevel window.
5989 * Return value: %TRUE if a widget in the focus chain handled the event.
5994 gtk_window_propagate_key_event (GtkWindow *window,
5997 GtkWindowPrivate *priv;
5998 gboolean handled = FALSE;
5999 GtkWidget *widget, *focus;
6001 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6003 priv = window->priv;
6004 widget = GTK_WIDGET (window);
6006 focus = priv->focus_widget;
6008 g_object_ref (focus);
6011 focus && focus != widget &&
6012 gtk_widget_get_toplevel (focus) == widget)
6016 if (gtk_widget_is_sensitive (focus))
6017 handled = gtk_widget_event (focus, (GdkEvent*) event);
6019 parent = gtk_widget_get_parent (focus);
6021 g_object_ref (parent);
6023 g_object_unref (focus);
6029 g_object_unref (focus);
6035 gtk_window_key_press_event (GtkWidget *widget,
6038 GtkWindow *window = GTK_WINDOW (widget);
6039 gboolean handled = FALSE;
6041 /* handle mnemonics and accelerators */
6043 handled = gtk_window_activate_key (window, event);
6045 /* handle focus widget key events */
6047 handled = gtk_window_propagate_key_event (window, event);
6049 /* Chain up, invokes binding set */
6051 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
6057 gtk_window_key_release_event (GtkWidget *widget,
6060 GtkWindow *window = GTK_WINDOW (widget);
6061 gboolean handled = FALSE;
6063 /* handle focus widget key events */
6065 handled = gtk_window_propagate_key_event (window, event);
6067 /* Chain up, invokes binding set */
6069 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
6075 gtk_window_button_press_event (GtkWidget *widget,
6076 GdkEventButton *event)
6078 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
6081 if (event->window == priv->grip_window)
6083 if (get_drag_edge (widget, &edge))
6084 gdk_window_begin_resize_drag_for_device (gtk_widget_get_window (widget),
6086 gdk_event_get_device ((GdkEvent *) event),
6099 gtk_window_real_activate_default (GtkWindow *window)
6101 gtk_window_activate_default (window);
6105 gtk_window_real_activate_focus (GtkWindow *window)
6107 gtk_window_activate_focus (window);
6111 gtk_window_enter_notify_event (GtkWidget *widget,
6112 GdkEventCrossing *event)
6118 gtk_window_leave_notify_event (GtkWidget *widget,
6119 GdkEventCrossing *event)
6125 do_focus_change (GtkWidget *widget,
6129 GdkDeviceManager *device_manager;
6132 g_object_ref (widget);
6134 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
6135 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6136 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
6137 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
6139 for (d = devices; d; d = d->next)
6141 GdkDevice *dev = d->data;
6144 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
6147 /* Skip non-master keyboards that haven't
6148 * selected for events from this window
6150 window = gtk_widget_get_window (widget);
6151 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
6152 window && !gdk_window_get_device_events (window, dev))
6155 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
6157 fevent->focus_change.type = GDK_FOCUS_CHANGE;
6158 fevent->focus_change.window = window;
6160 g_object_ref (window);
6161 fevent->focus_change.in = in;
6162 gdk_event_set_device (fevent, dev);
6164 gtk_widget_send_focus_change (widget, fevent);
6166 gdk_event_free (fevent);
6169 g_list_free (devices);
6170 g_object_unref (widget);
6174 maybe_set_mnemonics_visible (GtkWindow *window)
6177 GdkDeviceManager *device_manager;
6179 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (window)));
6180 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
6182 for (d = devices; d; d = d->next)
6184 GdkDevice *dev = d->data;
6186 if (gdk_device_get_source (dev) == GDK_SOURCE_MOUSE)
6188 GdkModifierType mask;
6190 gdk_device_get_state (dev, gtk_widget_get_window (GTK_WIDGET (window)),
6192 if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
6194 gtk_window_set_mnemonics_visible (window, TRUE);
6200 g_list_free (devices);
6204 gtk_window_focus_in_event (GtkWidget *widget,
6205 GdkEventFocus *event)
6207 GtkWindow *window = GTK_WINDOW (widget);
6208 gboolean auto_mnemonics;
6210 /* It appears spurious focus in events can occur when
6211 * the window is hidden. So we'll just check to see if
6212 * the window is visible before actually handling the
6215 if (gtk_widget_get_visible (widget))
6217 _gtk_window_set_has_toplevel_focus (window, TRUE);
6218 _gtk_window_set_is_active (window, TRUE);
6220 g_object_get (gtk_widget_get_settings (widget),
6221 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6223 maybe_set_mnemonics_visible (window);
6230 gtk_window_focus_out_event (GtkWidget *widget,
6231 GdkEventFocus *event)
6233 GtkWindow *window = GTK_WINDOW (widget);
6234 gboolean auto_mnemonics;
6236 _gtk_window_set_has_toplevel_focus (window, FALSE);
6237 _gtk_window_set_is_active (window, FALSE);
6239 /* set the mnemonic-visible property to false */
6240 g_object_get (gtk_widget_get_settings (widget),
6241 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
6243 gtk_window_set_mnemonics_visible (window, FALSE);
6249 gtk_window_check_resize (GtkContainer *container)
6251 /* If the window is not toplevel anymore than it's embedded somewhere,
6252 * so handle it like a normal window */
6253 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
6254 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
6255 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
6256 gtk_window_move_resize (GTK_WINDOW (container));
6260 gtk_window_focus (GtkWidget *widget,
6261 GtkDirectionType direction)
6263 GtkWindowPrivate *priv;
6266 GtkContainer *container;
6268 GtkWidget *old_focus_child;
6271 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6272 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
6274 container = GTK_CONTAINER (widget);
6275 window = GTK_WINDOW (widget);
6276 priv = window->priv;
6277 bin = GTK_BIN (widget);
6279 old_focus_child = gtk_container_get_focus_child (container);
6281 /* We need a special implementation here to deal properly with wrapping
6282 * around in the tab chain without the danger of going into an
6285 if (old_focus_child)
6287 if (gtk_widget_child_focus (old_focus_child, direction))
6291 if (priv->focus_widget)
6293 if (direction == GTK_DIR_LEFT ||
6294 direction == GTK_DIR_RIGHT ||
6295 direction == GTK_DIR_UP ||
6296 direction == GTK_DIR_DOWN)
6301 /* Wrapped off the end, clear the focus setting for the toplpevel */
6302 parent = gtk_widget_get_parent (priv->focus_widget);
6305 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6306 parent = gtk_widget_get_parent (parent);
6309 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6312 /* Now try to focus the first widget in the window */
6313 child = gtk_bin_get_child (bin);
6316 if (gtk_widget_child_focus (child, direction))
6324 gtk_window_move_focus (GtkWidget *widget,
6325 GtkDirectionType dir)
6327 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6329 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6333 gtk_widget_child_focus (widget, dir);
6335 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6336 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6340 gtk_window_real_set_focus (GtkWindow *window,
6343 GtkWindowPrivate *priv = window->priv;
6344 GtkWidget *old_focus = priv->focus_widget;
6345 gboolean had_default = FALSE;
6346 gboolean focus_had_default = FALSE;
6347 gboolean old_focus_had_default = FALSE;
6351 g_object_ref (old_focus);
6352 g_object_freeze_notify (G_OBJECT (old_focus));
6353 old_focus_had_default = gtk_widget_has_default (old_focus);
6357 g_object_ref (focus);
6358 g_object_freeze_notify (G_OBJECT (focus));
6359 focus_had_default = gtk_widget_has_default (focus);
6362 if (priv->default_widget)
6363 had_default = gtk_widget_has_default (priv->default_widget);
6365 if (priv->focus_widget)
6367 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6368 (priv->focus_widget != priv->default_widget))
6370 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6371 gtk_widget_queue_draw (priv->focus_widget);
6373 if (priv->default_widget)
6374 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6377 priv->focus_widget = NULL;
6379 if (priv->has_focus)
6380 do_focus_change (old_focus, FALSE);
6382 g_object_notify (G_OBJECT (old_focus), "is-focus");
6385 /* The above notifications may have set a new focus widget,
6386 * if so, we don't want to override it.
6388 if (focus && !priv->focus_widget)
6390 priv->focus_widget = focus;
6392 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6393 (priv->focus_widget != priv->default_widget))
6395 if (gtk_widget_get_can_default (priv->focus_widget))
6396 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6398 if (priv->default_widget)
6399 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6402 if (priv->has_focus)
6403 do_focus_change (priv->focus_widget, TRUE);
6405 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6408 /* If the default widget changed, a redraw will have been queued
6409 * on the old and new default widgets by gtk_window_set_default(), so
6410 * we only have to worry about the case where it didn't change.
6411 * We'll sometimes queue a draw twice on the new widget but that
6414 if (priv->default_widget &&
6415 (had_default != gtk_widget_has_default (priv->default_widget)))
6416 gtk_widget_queue_draw (priv->default_widget);
6420 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6421 gtk_widget_queue_draw (old_focus);
6423 g_object_thaw_notify (G_OBJECT (old_focus));
6424 g_object_unref (old_focus);
6428 if (focus_had_default != gtk_widget_has_default (focus))
6429 gtk_widget_queue_draw (focus);
6431 g_object_thaw_notify (G_OBJECT (focus));
6432 g_object_unref (focus);
6438 gtk_window_get_preferred_width (GtkWidget *widget,
6446 window = GTK_WINDOW (widget);
6447 child = gtk_bin_get_child (GTK_BIN (window));
6449 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6450 *minimum_size = border_width * 2;
6451 *natural_size = border_width * 2;
6453 if (child && gtk_widget_get_visible (child))
6455 gint child_min, child_nat;
6456 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6458 *minimum_size += child_min;
6459 *natural_size += child_nat;
6464 gtk_window_get_preferred_height (GtkWidget *widget,
6472 window = GTK_WINDOW (widget);
6473 child = gtk_bin_get_child (GTK_BIN (window));
6475 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6476 *minimum_size = border_width * 2;
6477 *natural_size = border_width * 2;
6479 if (child && gtk_widget_get_visible (child))
6481 gint child_min, child_nat;
6482 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6484 *minimum_size += child_min;
6485 *natural_size += child_nat;
6491 * _gtk_window_unset_focus_and_default:
6492 * @window: a #GtkWindow
6493 * @widget: a widget inside of @window
6495 * Checks whether the focus and default widgets of @window are
6496 * @widget or a descendent of @widget, and if so, unset them.
6499 _gtk_window_unset_focus_and_default (GtkWindow *window,
6503 GtkWindowPrivate *priv = window->priv;
6507 g_object_ref (window);
6508 g_object_ref (widget);
6510 parent = gtk_widget_get_parent (widget);
6511 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6513 child = priv->focus_widget;
6515 while (child && child != widget)
6516 child = gtk_widget_get_parent (child);
6518 if (child == widget)
6519 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6522 child = priv->default_widget;
6524 while (child && child != widget)
6525 child = gtk_widget_get_parent (child);
6527 if (child == widget)
6528 gtk_window_set_default (window, NULL);
6530 g_object_unref (widget);
6531 g_object_unref (window);
6534 /*********************************
6535 * Functions related to resizing *
6536 *********************************/
6539 geometry_size_to_pixels (GdkGeometry *geometry,
6544 gint base_width = 0;
6545 gint base_height = 0;
6547 gint min_height = 0;
6549 gint height_inc = 1;
6551 if (flags & GDK_HINT_BASE_SIZE)
6553 base_width = geometry->base_width;
6554 base_height = geometry->base_height;
6556 if (flags & GDK_HINT_MIN_SIZE)
6558 min_width = geometry->min_width;
6559 min_height = geometry->min_height;
6561 if (flags & GDK_HINT_RESIZE_INC)
6563 width_inc = geometry->width_inc;
6564 height_inc = geometry->height_inc;
6568 *width = MAX (*width * width_inc + base_width, min_width);
6570 *height = MAX (*height * height_inc + base_height, min_height);
6573 /* This function doesn't constrain to geometry hints */
6575 gtk_window_compute_configure_request_size (GtkWindow *window,
6576 GdkGeometry *geometry,
6581 GtkWindowPrivate *priv = window->priv;
6582 GtkWindowGeometryInfo *info;
6585 * - we've done a size request
6588 info = gtk_window_get_geometry_info (window, FALSE);
6590 if (priv->need_default_size)
6592 gtk_window_guess_default_size (window, width, height);
6594 /* If window is empty so requests 0, default to random nonzero size */
6595 if (*width == 0 && *height == 0)
6601 /* Override with default size */
6605 if (info->default_width > 0)
6606 *width = info->default_width;
6607 if (info->default_height > 0)
6608 *height = info->default_height;
6610 if (info->default_is_geometry)
6611 geometry_size_to_pixels (geometry, flags,
6612 info->default_width > 0 ? width : NULL,
6613 info->default_height > 0 ? height : NULL);
6618 GtkAllocation allocation;
6620 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
6622 /* Default to keeping current size */
6623 *width = allocation.width;
6624 *height = allocation.height;
6627 /* Override any size with gtk_window_resize() values */
6630 if (info->resize_width > 0)
6631 *width = info->resize_width;
6632 if (info->resize_height > 0)
6633 *height = info->resize_height;
6635 if (info->resize_is_geometry)
6636 geometry_size_to_pixels (geometry, flags,
6637 info->resize_width > 0 ? width : NULL,
6638 info->resize_height > 0 ? height : NULL);
6641 /* Don't ever request zero width or height, its not supported by
6642 gdk. The size allocation code will round it to 1 anyway but if
6643 we do it then the value returned from this function will is
6644 not comparable to the size allocation read from the GtkWindow. */
6645 *width = MAX (*width, 1);
6646 *height = MAX (*height, 1);
6649 static GtkWindowPosition
6650 get_effective_position (GtkWindow *window)
6652 GtkWindowPrivate *priv = window->priv;
6653 GtkWindowPosition pos = priv->position;
6655 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6656 (priv->transient_parent == NULL ||
6657 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6658 pos = GTK_WIN_POS_NONE;
6664 get_center_monitor_of_window (GtkWindow *window)
6666 /* We could try to sort out the relative positions of the monitors and
6667 * stuff, or we could just be losers and assume you have a row
6668 * or column of monitors.
6670 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6674 get_monitor_containing_pointer (GtkWindow *window)
6678 GdkScreen *window_screen;
6679 GdkScreen *pointer_screen;
6680 GdkDisplay *display;
6681 GdkDeviceManager *device_manager;
6684 window_screen = gtk_window_check_screen (window);
6685 display = gdk_screen_get_display (window_screen);
6686 device_manager = gdk_display_get_device_manager (display);
6687 pointer = gdk_device_manager_get_client_pointer (device_manager);
6689 gdk_device_get_position (pointer,
6693 if (pointer_screen == window_screen)
6694 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6702 center_window_on_monitor (GtkWindow *window,
6708 GdkRectangle monitor;
6711 monitor_num = get_monitor_containing_pointer (window);
6713 if (monitor_num == -1)
6714 monitor_num = get_center_monitor_of_window (window);
6716 gdk_screen_get_monitor_workarea (gtk_window_check_screen (window),
6717 monitor_num, &monitor);
6719 *x = (monitor.width - w) / 2 + monitor.x;
6720 *y = (monitor.height - h) / 2 + monitor.y;
6722 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6723 * and WM decorations.
6737 if (extent > clamp_extent)
6739 *base = clamp_base + clamp_extent/2 - extent/2;
6740 else if (*base < clamp_base)
6742 else if (*base + extent > clamp_base + clamp_extent)
6743 *base = clamp_base + clamp_extent - extent;
6747 clamp_window_to_rectangle (gint *x,
6751 const GdkRectangle *rect)
6753 #ifdef DEBUGGING_OUTPUT
6754 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);
6757 /* If it is too large, center it. If it fits on the monitor but is
6758 * partially outside, move it to the closest edge. Do this
6759 * separately in x and y directions.
6761 clamp (x, w, rect->x, rect->width);
6762 clamp (y, h, rect->y, rect->height);
6763 #ifdef DEBUGGING_OUTPUT
6764 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6770 gtk_window_compute_configure_request (GtkWindow *window,
6771 GdkRectangle *request,
6772 GdkGeometry *geometry,
6775 GtkWindowPrivate *priv = window->priv;
6776 GdkGeometry new_geometry;
6779 GtkWindowPosition pos;
6780 GtkWidget *parent_widget;
6781 GtkWindowGeometryInfo *info;
6785 screen = gtk_window_check_screen (window);
6787 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6788 gtk_window_compute_configure_request_size (window,
6789 &new_geometry, new_flags,
6792 gtk_window_constrain_size (window,
6793 &new_geometry, new_flags,
6797 parent_widget = (GtkWidget*) priv->transient_parent;
6799 pos = get_effective_position (window);
6800 info = gtk_window_get_geometry_info (window, FALSE);
6802 /* by default, don't change position requested */
6805 x = info->last.configure_request.x;
6806 y = info->last.configure_request.y;
6815 if (priv->need_default_position)
6818 /* FIXME this all interrelates with window gravity.
6819 * For most of them I think we want to set GRAVITY_CENTER.
6821 * Not sure how to go about that.
6825 /* here we are only handling CENTER_ALWAYS
6826 * as it relates to default positioning,
6827 * where it's equivalent to simply CENTER
6829 case GTK_WIN_POS_CENTER_ALWAYS:
6830 case GTK_WIN_POS_CENTER:
6831 center_window_on_monitor (window, w, h, &x, &y);
6834 case GTK_WIN_POS_CENTER_ON_PARENT:
6836 GtkAllocation allocation;
6837 GdkWindow *gdk_window;
6839 GdkRectangle monitor;
6842 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6844 gdk_window = gtk_widget_get_window (parent_widget);
6846 if (gdk_window != NULL)
6847 monitor_num = gdk_screen_get_monitor_at_window (screen,
6852 gdk_window_get_origin (gdk_window,
6855 gtk_widget_get_allocation (parent_widget, &allocation);
6856 x = ox + (allocation.width - w) / 2;
6857 y = oy + (allocation.height - h) / 2;
6859 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6860 * WM decorations. If parent wasn't on a monitor, just
6863 if (monitor_num >= 0)
6865 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6866 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6871 case GTK_WIN_POS_MOUSE:
6873 gint screen_width = gdk_screen_get_width (screen);
6874 gint screen_height = gdk_screen_get_height (screen);
6876 GdkRectangle monitor;
6877 GdkDisplay *display;
6878 GdkDeviceManager *device_manager;
6880 GdkScreen *pointer_screen;
6883 display = gdk_screen_get_display (screen);
6884 device_manager = gdk_display_get_device_manager (display);
6885 pointer = gdk_device_manager_get_client_pointer (device_manager);
6887 gdk_device_get_position (pointer,
6891 if (pointer_screen == screen)
6892 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6898 x = CLAMP (x, 0, screen_width - w);
6899 y = CLAMP (y, 0, screen_height - h);
6901 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6902 * WM decorations. Don't try to figure out what's going
6903 * on if the mouse wasn't inside a monitor.
6905 if (monitor_num >= 0)
6907 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6908 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6916 } /* if (priv->need_default_position) */
6918 if (priv->need_default_position && info &&
6919 info->initial_pos_set)
6921 x = info->initial_x;
6922 y = info->initial_y;
6923 gtk_window_constrain_position (window, w, h, &x, &y);
6929 request->height = h;
6932 *geometry = new_geometry;
6938 gtk_window_constrain_position (GtkWindow *window,
6944 GtkWindowPrivate *priv = window->priv;
6946 /* See long comments in gtk_window_move_resize()
6947 * on when it's safe to call this function.
6949 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6951 gint center_x, center_y;
6953 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6961 gtk_window_move_resize (GtkWindow *window)
6965 * First we determine whether any information has changed that would
6966 * cause us to revise our last configure request. If we would send
6967 * a different configure request from last time, then
6968 * configure_request_size_changed = TRUE or
6969 * configure_request_pos_changed = TRUE. configure_request_size_changed
6970 * may be true due to new hints, a gtk_window_resize(), or whatever.
6971 * configure_request_pos_changed may be true due to gtk_window_set_position()
6972 * or gtk_window_move().
6974 * If the configure request has changed, we send off a new one. To
6975 * ensure GTK+ invariants are maintained (resize queue does what it
6976 * should), we go ahead and size_allocate the requested size in this
6979 * If the configure request has not changed, we don't ever resend
6980 * it, because it could mean fighting the user or window manager.
6983 * To prepare the configure request, we come up with a base size/pos:
6984 * - the one from gtk_window_move()/gtk_window_resize()
6985 * - else default_width, default_height if we haven't ever
6987 * - else the size request if we haven't ever been mapped,
6988 * as a substitute default size
6989 * - else the current size of the window, as received from
6990 * configure notifies (i.e. the current allocation)
6992 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6993 * the position request to be centered.
6995 GtkWindowPrivate *priv = window->priv;
6996 GtkAllocation allocation;
6998 GtkContainer *container;
6999 GtkWindowGeometryInfo *info;
7000 GdkGeometry new_geometry;
7001 GdkWindow *gdk_window;
7003 GdkRectangle new_request;
7004 gboolean configure_request_size_changed;
7005 gboolean configure_request_pos_changed;
7006 gboolean hints_changed; /* do we need to send these again */
7007 GtkWindowLastGeometryInfo saved_last_info;
7009 widget = GTK_WIDGET (window);
7011 gdk_window = gtk_widget_get_window (widget);
7012 container = GTK_CONTAINER (widget);
7013 info = gtk_window_get_geometry_info (window, TRUE);
7015 configure_request_size_changed = FALSE;
7016 configure_request_pos_changed = FALSE;
7018 gtk_window_compute_configure_request (window, &new_request,
7019 &new_geometry, &new_flags);
7021 /* This check implies the invariant that we never set info->last
7022 * without setting the hints and sending off a configure request.
7024 * If we change info->last without sending the request, we may
7027 if (info->last.configure_request.x != new_request.x ||
7028 info->last.configure_request.y != new_request.y)
7029 configure_request_pos_changed = TRUE;
7031 if ((info->last.configure_request.width != new_request.width ||
7032 info->last.configure_request.height != new_request.height))
7033 configure_request_size_changed = TRUE;
7035 hints_changed = FALSE;
7037 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
7038 &new_geometry, new_flags))
7040 hints_changed = TRUE;
7043 /* Position Constraints
7044 * ====================
7046 * POS_CENTER_ALWAYS is conceptually a constraint rather than
7047 * a default. The other POS_ values are used only when the
7048 * window is shown, not after that.
7050 * However, we can't implement a position constraint as
7051 * "anytime the window size changes, center the window"
7052 * because this may well end up fighting the WM or user. In
7053 * fact it gets in an infinite loop with at least one WM.
7055 * Basically, applications are in no way in a position to
7056 * constrain the position of a window, with one exception:
7057 * override redirect windows. (Really the intended purpose
7058 * of CENTER_ALWAYS anyhow, I would think.)
7060 * So the way we implement this "constraint" is to say that when WE
7061 * cause a move or resize, i.e. we make a configure request changing
7062 * window size, we recompute the CENTER_ALWAYS position to reflect
7063 * the new window size, and include it in our request. Also, if we
7064 * just turned on CENTER_ALWAYS we snap to center with a new
7065 * request. Otherwise, if we are just NOTIFIED of a move or resize
7066 * done by someone else e.g. the window manager, we do NOT send a
7067 * new configure request.
7069 * For override redirect windows, this works fine; all window
7070 * sizes are from our configure requests. For managed windows,
7071 * it is at least semi-sane, though who knows what the
7072 * app author is thinking.
7075 /* This condition should be kept in sync with the condition later on
7076 * that determines whether we send a configure request. i.e. we
7077 * should do this position constraining anytime we were going to
7078 * send a configure request anyhow, plus when constraints have
7081 if (configure_request_pos_changed ||
7082 configure_request_size_changed ||
7084 info->position_constraints_changed)
7086 /* We request the constrained position if:
7087 * - we were changing position, and need to clamp
7088 * the change to the constraint
7089 * - we're changing the size anyway
7090 * - set_position() was called to toggle CENTER_ALWAYS on
7093 gtk_window_constrain_position (window,
7099 /* Update whether we need to request a move */
7100 if (info->last.configure_request.x != new_request.x ||
7101 info->last.configure_request.y != new_request.y)
7102 configure_request_pos_changed = TRUE;
7104 configure_request_pos_changed = FALSE;
7108 if (priv->type == GTK_WINDOW_TOPLEVEL)
7110 int notify_x, notify_y;
7112 /* this is the position from the last configure notify */
7113 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
7115 g_message ("--- %s ---\n"
7116 "last : %d,%d\t%d x %d\n"
7117 "this : %d,%d\t%d x %d\n"
7118 "alloc : %d,%d\t%d x %d\n"
7120 "resize: \t%d x %d\n"
7121 "size_changed: %d pos_changed: %d hints_changed: %d\n"
7122 "configure_notify_received: %d\n"
7123 "configure_request_count: %d\n"
7124 "position_constraints_changed: %d\n",
7125 priv->title ? priv->title : "(no title)",
7126 info->last.configure_request.x,
7127 info->last.configure_request.y,
7128 info->last.configure_request.width,
7129 info->last.configure_request.height,
7135 widget->allocation.width,
7136 widget->allocation.height,
7137 widget->requisition.width,
7138 widget->requisition.height,
7140 info->resize_height,
7141 configure_request_pos_changed,
7142 configure_request_size_changed,
7144 priv->configure_notify_received,
7145 priv->configure_request_count,
7146 info->position_constraints_changed);
7150 saved_last_info = info->last;
7151 info->last.geometry = new_geometry;
7152 info->last.flags = new_flags;
7153 info->last.configure_request = new_request;
7155 /* need to set PPosition so the WM will look at our position,
7156 * but we don't want to count PPosition coming and going as a hints
7157 * change for future iterations. So we saved info->last prior to
7161 /* Also, if the initial position was explicitly set, then we always
7162 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
7166 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
7167 * this is an initial map
7170 if ((configure_request_pos_changed ||
7171 info->initial_pos_set ||
7172 (priv->need_default_position &&
7173 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
7174 (new_flags & GDK_HINT_POS) == 0)
7176 new_flags |= GDK_HINT_POS;
7177 hints_changed = TRUE;
7180 /* Set hints if necessary
7183 gdk_window_set_geometry_hints (gdk_window,
7187 gtk_widget_get_allocation (widget, &allocation);
7189 /* handle resizing/moving and widget tree allocation
7191 if (priv->configure_notify_received)
7193 /* If we have received a configure event since
7194 * the last time in this function, we need to
7195 * accept our new size and size_allocate child widgets.
7196 * (see gtk_window_configure_event() for more details).
7198 * 1 or more configure notifies may have been received.
7199 * Also, configure_notify_received will only be TRUE
7200 * if all expected configure notifies have been received
7201 * (one per configure request), as an optimization.
7204 priv->configure_notify_received = FALSE;
7206 /* gtk_window_configure_event() filled in widget->allocation */
7207 gtk_widget_size_allocate (widget, &allocation);
7209 set_grip_position (window);
7210 update_grip_visibility (window);
7212 gdk_window_process_updates (gdk_window, TRUE);
7214 gdk_window_configure_finished (gdk_window);
7216 /* If the configure request changed, it means that
7218 * 1) coincidentally changed hints or widget properties
7219 * impacting the configure request before getting
7220 * a configure notify, or
7221 * 2) some broken widget is changing its size request
7222 * during size allocation, resulting in
7223 * a false appearance of changed configure request.
7225 * For 1), we could just go ahead and ask for the
7226 * new size right now, but doing that for 2)
7227 * might well be fighting the user (and can even
7228 * trigger a loop). Since we really don't want to
7229 * do that, we requeue a resize in hopes that
7230 * by the time it gets handled, the child has seen
7231 * the light and is willing to go along with the
7232 * new size. (this happens for the zvt widget, since
7233 * the size_allocate() above will have stored the
7234 * requisition corresponding to the new size in the
7237 * This doesn't buy us anything for 1), but it shouldn't
7238 * hurt us too badly, since it is what would have
7239 * happened if we had gotten the configure event before
7240 * the new size had been set.
7243 if (configure_request_size_changed ||
7244 configure_request_pos_changed)
7246 /* Don't change the recorded last info after all, because we
7247 * haven't actually updated to the new info yet - we decided
7248 * to postpone our configure request until later.
7250 info->last = saved_last_info;
7252 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7255 return; /* Bail out, we didn't really process the move/resize */
7257 else if ((configure_request_size_changed || hints_changed) &&
7258 (allocation.width != new_request.width || allocation.height != new_request.height))
7261 /* We are in one of the following situations:
7262 * A. configure_request_size_changed
7263 * our requisition has changed and we need a different window size,
7264 * so we request it from the window manager.
7265 * B. !configure_request_size_changed && hints_changed
7266 * the window manager rejects our size, but we have just changed the
7267 * window manager hints, so there's a chance our request will
7268 * be honoured this time, so we try again.
7270 * However, if the new requisition is the same as the current allocation,
7271 * we don't request it again, since we won't get a ConfigureNotify back from
7272 * the window manager unless it decides to change our requisition. If
7273 * we don't get the ConfigureNotify back, the resize queue will never be run.
7276 /* Now send the configure request */
7277 if (configure_request_pos_changed)
7279 gdk_window_move_resize (gdk_window,
7280 new_request.x, new_request.y,
7281 new_request.width, new_request.height);
7283 else /* only size changed */
7285 gdk_window_resize (gdk_window,
7286 new_request.width, new_request.height);
7289 if (priv->type == GTK_WINDOW_POPUP)
7291 GtkAllocation allocation;
7293 /* Directly size allocate for override redirect (popup) windows. */
7296 allocation.width = new_request.width;
7297 allocation.height = new_request.height;
7299 gtk_widget_size_allocate (widget, &allocation);
7301 gdk_window_process_updates (gdk_window, TRUE);
7303 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7304 gtk_widget_queue_draw (widget);
7308 /* Increment the number of have-not-yet-received-notify requests */
7309 priv->configure_request_count += 1;
7310 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7312 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7313 * configure event in response to our resizing request.
7314 * the configure event will cause a new resize with
7315 * ->configure_notify_received=TRUE.
7316 * until then, we want to
7317 * - discard expose events
7318 * - coalesce resizes for our children
7319 * - defer any window resizes until the configure event arrived
7320 * to achieve this, we queue a resize for the window, but remove its
7321 * resizing handler, so resizing will not be handled from the next
7322 * idle handler but when the configure event arrives.
7324 * FIXME: we should also dequeue the pending redraws here, since
7325 * we handle those ourselves upon ->configure_notify_received==TRUE.
7327 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7329 gtk_widget_queue_resize_no_redraw (widget);
7330 _gtk_container_dequeue_resize_handler (container);
7336 /* Handle any position changes.
7338 if (configure_request_pos_changed)
7340 gdk_window_move (gdk_window,
7341 new_request.x, new_request.y);
7344 /* And run the resize queue.
7346 gtk_container_resize_children (container);
7349 /* We have now processed a move/resize since the last position
7350 * constraint change, setting of the initial position, or resize.
7351 * (Not resetting these flags here can lead to infinite loops for
7352 * GTK_RESIZE_IMMEDIATE containers)
7354 info->position_constraints_changed = FALSE;
7355 info->initial_pos_set = FALSE;
7356 info->resize_width = -1;
7357 info->resize_height = -1;
7360 /* Compare two sets of Geometry hints for equality.
7363 gtk_window_compare_hints (GdkGeometry *geometry_a,
7365 GdkGeometry *geometry_b,
7368 if (flags_a != flags_b)
7371 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7372 (geometry_a->min_width != geometry_b->min_width ||
7373 geometry_a->min_height != geometry_b->min_height))
7376 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7377 (geometry_a->max_width != geometry_b->max_width ||
7378 geometry_a->max_height != geometry_b->max_height))
7381 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7382 (geometry_a->base_width != geometry_b->base_width ||
7383 geometry_a->base_height != geometry_b->base_height))
7386 if ((flags_a & GDK_HINT_ASPECT) &&
7387 (geometry_a->min_aspect != geometry_b->min_aspect ||
7388 geometry_a->max_aspect != geometry_b->max_aspect))
7391 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7392 (geometry_a->width_inc != geometry_b->width_inc ||
7393 geometry_a->height_inc != geometry_b->height_inc))
7396 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7397 geometry_a->win_gravity != geometry_b->win_gravity)
7404 _gtk_window_constrain_size (GtkWindow *window,
7410 GtkWindowPrivate *priv;
7411 GtkWindowGeometryInfo *info;
7413 g_return_if_fail (GTK_IS_WINDOW (window));
7415 priv = window->priv;
7417 info = priv->geometry_info;
7420 GdkWindowHints flags = info->last.flags;
7421 GdkGeometry *geometry = &info->last.geometry;
7423 gtk_window_constrain_size (window,
7434 gtk_window_constrain_size (GtkWindow *window,
7435 GdkGeometry *geometry,
7442 gdk_window_constrain_size (geometry, flags, width, height,
7443 new_width, new_height);
7446 /* Compute the set of geometry hints and flags for a window
7447 * based on the application set geometry, and requisition
7448 * of the window. gtk_widget_get_preferred_size() must have been
7452 gtk_window_compute_hints (GtkWindow *window,
7453 GdkGeometry *new_geometry,
7456 GtkWindowPrivate *priv = window->priv;
7458 gint extra_width = 0;
7459 gint extra_height = 0;
7460 GtkWindowGeometryInfo *geometry_info;
7461 GtkRequisition requisition;
7463 widget = GTK_WIDGET (window);
7465 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7466 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7470 *new_flags = geometry_info->mask;
7471 *new_geometry = geometry_info->geometry;
7478 if (geometry_info && geometry_info->widget)
7480 /* If the geometry widget is set, then the hints really apply to that
7481 * widget. This is pretty much meaningless unless the window layout
7482 * is such that the rest of the window adds fixed size borders to
7483 * the geometry widget. Our job is to figure the size of the borders;
7484 * We do that by asking how big the toplevel would be if the
7485 * geometry widget was *really big*.
7488 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7489 * |GGGGG B| in the border can confuse things
7495 * |AAAAAAAAA | When the geometry widget is large, things are
7496 * |GGGGGGGGGGB| clearer.
7501 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7502 GtkRequisition requisition;
7503 int current_width, current_height;
7505 _gtk_widget_override_size_request (geometry_info->widget,
7506 TEMPORARY_SIZE, TEMPORARY_SIZE,
7507 ¤t_width, ¤t_height);
7508 gtk_widget_get_preferred_size (widget,
7509 &requisition, NULL);
7510 _gtk_widget_restore_size_request (geometry_info->widget,
7511 current_width, current_height);
7513 extra_width = requisition.width - TEMPORARY_SIZE;
7514 extra_height = requisition.height - TEMPORARY_SIZE;
7516 if (extra_width < 0 || extra_height < 0)
7518 g_warning("Toplevel size doesn't seem to directly depend on the "
7519 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7520 "The geometry widget might not be in the window, or it might not "
7521 "be packed into the window appropriately");
7522 extra_width = MAX(extra_width, 0);
7523 extra_height = MAX(extra_height, 0);
7525 #undef TEMPORARY_SIZE
7528 /* We don't want to set GDK_HINT_POS in here, we just set it
7529 * in gtk_window_move_resize() when we want the position
7533 if (*new_flags & GDK_HINT_BASE_SIZE)
7535 new_geometry->base_width += extra_width;
7536 new_geometry->base_height += extra_height;
7540 /* For simplicity, we always set the base hint, even when we
7541 * don't expect it to have any visible effect.
7542 * (Note: geometry_size_to_pixels() depends on this.)
7544 *new_flags |= GDK_HINT_BASE_SIZE;
7546 new_geometry->base_width = extra_width;
7547 new_geometry->base_height = extra_height;
7549 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7550 * base size is the minimum size */
7551 if (*new_flags & GDK_HINT_MIN_SIZE)
7553 if (new_geometry->min_width > 0)
7554 new_geometry->base_width += new_geometry->min_width;
7555 if (new_geometry->min_height > 0)
7556 new_geometry->base_height += new_geometry->min_height;
7560 /* Please use a good size for unresizable widgets, not the minimum one. */
7561 if (!priv->resizable)
7562 gtk_window_guess_default_size (window, &requisition.width, &requisition.height);
7564 if (*new_flags & GDK_HINT_MIN_SIZE)
7566 if (new_geometry->min_width < 0)
7567 new_geometry->min_width = requisition.width;
7569 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7571 if (new_geometry->min_height < 0)
7572 new_geometry->min_height = requisition.height;
7574 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7578 *new_flags |= GDK_HINT_MIN_SIZE;
7580 new_geometry->min_width = requisition.width;
7581 new_geometry->min_height = requisition.height;
7584 if (*new_flags & GDK_HINT_MAX_SIZE)
7586 if (new_geometry->max_width < 0)
7587 new_geometry->max_width = requisition.width;
7589 new_geometry->max_width += extra_width;
7591 if (new_geometry->max_height < 0)
7592 new_geometry->max_height = requisition.height;
7594 new_geometry->max_height += extra_height;
7596 else if (!priv->resizable)
7598 *new_flags |= GDK_HINT_MAX_SIZE;
7600 new_geometry->max_width = requisition.width;
7601 new_geometry->max_height = requisition.height;
7604 *new_flags |= GDK_HINT_WIN_GRAVITY;
7605 new_geometry->win_gravity = priv->gravity;
7608 /***********************
7609 * Redrawing functions *
7610 ***********************/
7613 gtk_window_draw (GtkWidget *widget,
7616 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7617 GtkStyleContext *context;
7618 gboolean ret = FALSE;
7620 context = gtk_widget_get_style_context (widget);
7622 if (!gtk_widget_get_app_paintable (widget) &&
7623 gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
7625 gtk_style_context_save (context);
7627 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7628 gtk_render_background (context, cr, 0, 0,
7629 gtk_widget_get_allocated_width (widget),
7630 gtk_widget_get_allocated_height (widget));
7632 gtk_style_context_restore (context);
7635 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7636 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7638 if (priv->grip_window &&
7639 gtk_cairo_should_draw_window (cr, priv->grip_window))
7643 gtk_style_context_save (context);
7646 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7647 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7649 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7650 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7651 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7654 gtk_style_context_restore (context);
7661 * gtk_window_present:
7662 * @window: a #GtkWindow
7664 * Presents a window to the user. This may mean raising the window
7665 * in the stacking order, deiconifying it, moving it to the current
7666 * desktop, and/or giving it the keyboard focus, possibly dependent
7667 * on the user's platform, window manager, and preferences.
7669 * If @window is hidden, this function calls gtk_widget_show()
7672 * This function should be used when the user tries to open a window
7673 * that's already open. Say for example the preferences dialog is
7674 * currently open, and the user chooses Preferences from the menu
7675 * a second time; use gtk_window_present() to move the already-open dialog
7676 * where the user can see it.
7678 * If you are calling this function in response to a user interaction,
7679 * it is preferable to use gtk_window_present_with_time().
7683 gtk_window_present (GtkWindow *window)
7685 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7689 * gtk_window_present_with_time:
7690 * @window: a #GtkWindow
7691 * @timestamp: the timestamp of the user interaction (typically a
7692 * button or key press event) which triggered this call
7694 * Presents a window to the user in response to a user interaction.
7695 * If you need to present a window without a timestamp, use
7696 * gtk_window_present(). See gtk_window_present() for details.
7701 gtk_window_present_with_time (GtkWindow *window,
7704 GtkWindowPrivate *priv;
7706 GdkWindow *gdk_window;
7708 g_return_if_fail (GTK_IS_WINDOW (window));
7710 priv = window->priv;
7711 widget = GTK_WIDGET (window);
7713 if (gtk_widget_get_visible (widget))
7715 gdk_window = gtk_widget_get_window (widget);
7717 g_assert (gdk_window != NULL);
7719 gdk_window_show (gdk_window);
7721 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7722 if (timestamp == GDK_CURRENT_TIME)
7724 #ifdef GDK_WINDOWING_X11
7725 if (GDK_IS_X11_WINDOW(gdk_window))
7727 GdkDisplay *display;
7729 display = gtk_widget_get_display (GTK_WIDGET (window));
7730 timestamp = gdk_x11_display_get_user_time (display);
7734 timestamp = gtk_get_current_event_time ();
7737 gdk_window_focus (gdk_window, timestamp);
7741 priv->initial_timestamp = timestamp;
7742 gtk_widget_show (widget);
7747 * gtk_window_iconify:
7748 * @window: a #GtkWindow
7750 * Asks to iconify (i.e. minimize) the specified @window. Note that
7751 * you shouldn't assume the window is definitely iconified afterward,
7752 * because other entities (e.g. the user or <link
7753 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7754 * again, or there may not be a window manager in which case
7755 * iconification isn't possible, etc. But normally the window will end
7756 * up iconified. Just don't write code that crashes if not.
7758 * It's permitted to call this function before showing a window,
7759 * in which case the window will be iconified before it ever appears
7762 * You can track iconification via the "window-state-event" signal
7767 gtk_window_iconify (GtkWindow *window)
7769 GtkWindowPrivate *priv;
7771 GdkWindow *toplevel;
7773 g_return_if_fail (GTK_IS_WINDOW (window));
7775 priv = window->priv;
7776 widget = GTK_WIDGET (window);
7778 priv->iconify_initially = TRUE;
7780 toplevel = gtk_widget_get_window (widget);
7782 if (toplevel != NULL)
7783 gdk_window_iconify (toplevel);
7787 * gtk_window_deiconify:
7788 * @window: a #GtkWindow
7790 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7791 * that you shouldn't assume the window is definitely deiconified
7792 * afterward, because other entities (e.g. the user or <link
7793 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7794 * again before your code which assumes deiconification gets to run.
7796 * You can track iconification via the "window-state-event" signal
7800 gtk_window_deiconify (GtkWindow *window)
7802 GtkWindowPrivate *priv;
7804 GdkWindow *toplevel;
7806 g_return_if_fail (GTK_IS_WINDOW (window));
7808 priv = window->priv;
7809 widget = GTK_WIDGET (window);
7811 priv->iconify_initially = FALSE;
7813 toplevel = gtk_widget_get_window (widget);
7815 if (toplevel != NULL)
7816 gdk_window_deiconify (toplevel);
7821 * @window: a #GtkWindow
7823 * Asks to stick @window, which means that it will appear on all user
7824 * desktops. Note that you shouldn't assume the window is definitely
7825 * stuck afterward, because other entities (e.g. the user or <link
7826 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7827 * again, and some window managers do not support sticking
7828 * windows. But normally the window will end up stuck. Just don't
7829 * write code that crashes if not.
7831 * It's permitted to call this function before showing a window.
7833 * You can track stickiness via the "window-state-event" signal
7838 gtk_window_stick (GtkWindow *window)
7840 GtkWindowPrivate *priv;
7842 GdkWindow *toplevel;
7844 g_return_if_fail (GTK_IS_WINDOW (window));
7846 priv = window->priv;
7847 widget = GTK_WIDGET (window);
7849 priv->stick_initially = TRUE;
7851 toplevel = gtk_widget_get_window (widget);
7853 if (toplevel != NULL)
7854 gdk_window_stick (toplevel);
7858 * gtk_window_unstick:
7859 * @window: a #GtkWindow
7861 * Asks to unstick @window, which means that it will appear on only
7862 * one of the user's desktops. Note that you shouldn't assume the
7863 * window is definitely unstuck afterward, because other entities
7864 * (e.g. the user or <link linkend="gtk-X11-arch">window
7865 * manager</link>) could stick it again. But normally the window will
7866 * end up stuck. Just don't write code that crashes if not.
7868 * You can track stickiness via the "window-state-event" signal
7873 gtk_window_unstick (GtkWindow *window)
7875 GtkWindowPrivate *priv;
7877 GdkWindow *toplevel;
7879 g_return_if_fail (GTK_IS_WINDOW (window));
7881 priv = window->priv;
7882 widget = GTK_WIDGET (window);
7884 priv->stick_initially = FALSE;
7886 toplevel = gtk_widget_get_window (widget);
7888 if (toplevel != NULL)
7889 gdk_window_unstick (toplevel);
7893 * gtk_window_maximize:
7894 * @window: a #GtkWindow
7896 * Asks to maximize @window, so that it becomes full-screen. Note that
7897 * you shouldn't assume the window is definitely maximized afterward,
7898 * because other entities (e.g. the user or <link
7899 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7900 * again, and not all window managers support maximization. But
7901 * normally the window will end up maximized. Just don't write code
7902 * that crashes if not.
7904 * It's permitted to call this function before showing a window,
7905 * in which case the window will be maximized when it appears onscreen
7908 * You can track maximization via the "window-state-event" signal
7913 gtk_window_maximize (GtkWindow *window)
7915 GtkWindowPrivate *priv;
7917 GdkWindow *toplevel;
7919 g_return_if_fail (GTK_IS_WINDOW (window));
7921 priv = window->priv;
7922 widget = GTK_WIDGET (window);
7924 priv->maximize_initially = TRUE;
7926 toplevel = gtk_widget_get_window (widget);
7928 if (toplevel != NULL)
7929 gdk_window_maximize (toplevel);
7933 * gtk_window_unmaximize:
7934 * @window: a #GtkWindow
7936 * Asks to unmaximize @window. Note that you shouldn't assume the
7937 * window is definitely unmaximized afterward, because other entities
7938 * (e.g. the user or <link linkend="gtk-X11-arch">window
7939 * manager</link>) could maximize it again, and not all window
7940 * managers honor requests to unmaximize. But normally the window will
7941 * end up unmaximized. Just don't write code that crashes if not.
7943 * You can track maximization via the "window-state-event" signal
7948 gtk_window_unmaximize (GtkWindow *window)
7950 GtkWindowPrivate *priv;
7952 GdkWindow *toplevel;
7954 g_return_if_fail (GTK_IS_WINDOW (window));
7956 priv = window->priv;
7957 widget = GTK_WIDGET (window);
7959 priv->maximize_initially = FALSE;
7961 toplevel = gtk_widget_get_window (widget);
7963 if (toplevel != NULL)
7964 gdk_window_unmaximize (toplevel);
7968 * gtk_window_fullscreen:
7969 * @window: a #GtkWindow
7971 * Asks to place @window in the fullscreen state. Note that you
7972 * shouldn't assume the window is definitely full screen afterward,
7973 * because other entities (e.g. the user or <link
7974 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7975 * again, and not all window managers honor requests to fullscreen
7976 * windows. But normally the window will end up fullscreen. Just
7977 * don't write code that crashes if not.
7979 * You can track the fullscreen state via the "window-state-event" signal
7985 gtk_window_fullscreen (GtkWindow *window)
7987 GtkWindowPrivate *priv;
7989 GdkWindow *toplevel;
7991 g_return_if_fail (GTK_IS_WINDOW (window));
7993 priv = window->priv;
7994 widget = GTK_WIDGET (window);
7996 priv->fullscreen_initially = TRUE;
7998 toplevel = gtk_widget_get_window (widget);
8000 if (toplevel != NULL)
8001 gdk_window_fullscreen (toplevel);
8005 * gtk_window_unfullscreen:
8006 * @window: a #GtkWindow
8008 * Asks to toggle off the fullscreen state for @window. Note that you
8009 * shouldn't assume the window is definitely not full screen
8010 * afterward, because other entities (e.g. the user or <link
8011 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
8012 * again, and not all window managers honor requests to unfullscreen
8013 * windows. But normally the window will end up restored to its normal
8014 * state. Just don't write code that crashes if not.
8016 * You can track the fullscreen state via the "window-state-event" signal
8022 gtk_window_unfullscreen (GtkWindow *window)
8025 GdkWindow *toplevel;
8026 GtkWindowPrivate *priv;
8028 g_return_if_fail (GTK_IS_WINDOW (window));
8030 priv = window->priv;
8031 widget = GTK_WIDGET (window);
8033 priv->fullscreen_initially = FALSE;
8035 toplevel = gtk_widget_get_window (widget);
8037 if (toplevel != NULL)
8038 gdk_window_unfullscreen (toplevel);
8042 * gtk_window_set_keep_above:
8043 * @window: a #GtkWindow
8044 * @setting: whether to keep @window above other windows
8046 * Asks to keep @window above, so that it stays on top. Note that
8047 * you shouldn't assume the window is definitely above afterward,
8048 * because other entities (e.g. the user or <link
8049 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
8050 * and not all window managers support keeping windows above. But
8051 * normally the window will end kept above. Just don't write code
8052 * that crashes if not.
8054 * It's permitted to call this function before showing a window,
8055 * in which case the window will be kept above when it appears onscreen
8058 * You can track the above state via the "window-state-event" signal
8061 * Note that, according to the <ulink
8062 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8063 * Manager Hints</ulink> specification, the above state is mainly meant
8064 * for user preferences and should not be used by applications e.g. for
8065 * drawing attention to their dialogs.
8070 gtk_window_set_keep_above (GtkWindow *window,
8074 GtkWindowPrivate *priv;
8075 GdkWindow *toplevel;
8077 g_return_if_fail (GTK_IS_WINDOW (window));
8079 priv = window->priv;
8080 widget = GTK_WIDGET (window);
8082 priv->above_initially = setting != FALSE;
8084 priv->below_initially = FALSE;
8086 toplevel = gtk_widget_get_window (widget);
8088 if (toplevel != NULL)
8089 gdk_window_set_keep_above (toplevel, setting);
8093 * gtk_window_set_keep_below:
8094 * @window: a #GtkWindow
8095 * @setting: whether to keep @window below other windows
8097 * Asks to keep @window below, so that it stays in bottom. Note that
8098 * you shouldn't assume the window is definitely below afterward,
8099 * because other entities (e.g. the user or <link
8100 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8101 * and not all window managers support putting windows below. But
8102 * normally the window will be kept below. Just don't write code
8103 * that crashes if not.
8105 * It's permitted to call this function before showing a window,
8106 * in which case the window will be kept below when it appears onscreen
8109 * You can track the below state via the "window-state-event" signal
8112 * Note that, according to the <ulink
8113 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8114 * Manager Hints</ulink> specification, the above state is mainly meant
8115 * for user preferences and should not be used by applications e.g. for
8116 * drawing attention to their dialogs.
8121 gtk_window_set_keep_below (GtkWindow *window,
8125 GtkWindowPrivate *priv;
8126 GdkWindow *toplevel;
8128 g_return_if_fail (GTK_IS_WINDOW (window));
8130 priv = window->priv;
8131 widget = GTK_WIDGET (window);
8133 priv->below_initially = setting != FALSE;
8135 priv->above_initially = FALSE;
8137 toplevel = gtk_widget_get_window (widget);
8139 if (toplevel != NULL)
8140 gdk_window_set_keep_below (toplevel, setting);
8144 * gtk_window_set_resizable:
8145 * @window: a #GtkWindow
8146 * @resizable: %TRUE if the user can resize this window
8148 * Sets whether the user can resize a window. Windows are user resizable
8152 gtk_window_set_resizable (GtkWindow *window,
8155 GtkWindowPrivate *priv;
8157 g_return_if_fail (GTK_IS_WINDOW (window));
8159 priv = window->priv;
8161 resizable = (resizable != FALSE);
8163 if (priv->resizable != resizable)
8165 priv->resizable = (resizable != FALSE);
8167 update_grip_visibility (window);
8169 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8171 g_object_notify (G_OBJECT (window), "resizable");
8176 * gtk_window_get_resizable:
8177 * @window: a #GtkWindow
8179 * Gets the value set by gtk_window_set_resizable().
8181 * Return value: %TRUE if the user can resize the window
8184 gtk_window_get_resizable (GtkWindow *window)
8186 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8188 return window->priv->resizable;
8192 * gtk_window_set_gravity:
8193 * @window: a #GtkWindow
8194 * @gravity: window gravity
8196 * Window gravity defines the meaning of coordinates passed to
8197 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8200 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8201 * typically "do what you mean."
8205 gtk_window_set_gravity (GtkWindow *window,
8208 GtkWindowPrivate *priv;
8210 g_return_if_fail (GTK_IS_WINDOW (window));
8212 priv = window->priv;
8214 if (gravity != priv->gravity)
8216 priv->gravity = gravity;
8218 /* gtk_window_move_resize() will adapt gravity
8220 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8222 g_object_notify (G_OBJECT (window), "gravity");
8227 * gtk_window_get_gravity:
8228 * @window: a #GtkWindow
8230 * Gets the value set by gtk_window_set_gravity().
8232 * Return value: (transfer none): window gravity
8235 gtk_window_get_gravity (GtkWindow *window)
8237 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8239 return window->priv->gravity;
8243 * gtk_window_begin_resize_drag:
8244 * @window: a #GtkWindow
8245 * @button: mouse button that initiated the drag
8246 * @edge: position of the resize control
8247 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8248 * @root_y: Y position where the user clicked to initiate the drag
8249 * @timestamp: timestamp from the click event that initiated the drag
8251 * Starts resizing a window. This function is used if an application
8252 * has window resizing controls. When GDK can support it, the resize
8253 * will be done using the standard mechanism for the <link
8254 * linkend="gtk-X11-arch">window manager</link> or windowing
8255 * system. Otherwise, GDK will try to emulate window resizing,
8256 * potentially not all that well, depending on the windowing system.
8260 gtk_window_begin_resize_drag (GtkWindow *window,
8268 GdkWindow *toplevel;
8270 g_return_if_fail (GTK_IS_WINDOW (window));
8271 widget = GTK_WIDGET (window);
8272 g_return_if_fail (gtk_widget_get_visible (widget));
8274 toplevel = gtk_widget_get_window (widget);
8276 gdk_window_begin_resize_drag (toplevel,
8283 * gtk_window_begin_move_drag:
8284 * @window: a #GtkWindow
8285 * @button: mouse button that initiated the drag
8286 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8287 * @root_y: Y position where the user clicked to initiate the drag
8288 * @timestamp: timestamp from the click event that initiated the drag
8290 * Starts moving a window. This function is used if an application has
8291 * window movement grips. When GDK can support it, the window movement
8292 * will be done using the standard mechanism for the <link
8293 * linkend="gtk-X11-arch">window manager</link> or windowing
8294 * system. Otherwise, GDK will try to emulate window movement,
8295 * potentially not all that well, depending on the windowing system.
8299 gtk_window_begin_move_drag (GtkWindow *window,
8306 GdkWindow *toplevel;
8308 g_return_if_fail (GTK_IS_WINDOW (window));
8309 widget = GTK_WIDGET (window);
8310 g_return_if_fail (gtk_widget_get_visible (widget));
8312 toplevel = gtk_widget_get_window (widget);
8314 gdk_window_begin_move_drag (toplevel,
8321 * gtk_window_set_screen:
8322 * @window: a #GtkWindow.
8323 * @screen: a #GdkScreen.
8325 * Sets the #GdkScreen where the @window is displayed; if
8326 * the window is already mapped, it will be unmapped, and
8327 * then remapped on the new screen.
8332 gtk_window_set_screen (GtkWindow *window,
8335 GtkWindowPrivate *priv;
8337 GdkScreen *previous_screen;
8338 gboolean was_mapped;
8340 g_return_if_fail (GTK_IS_WINDOW (window));
8341 g_return_if_fail (GDK_IS_SCREEN (screen));
8343 priv = window->priv;
8345 if (screen == priv->screen)
8348 widget = GTK_WIDGET (window);
8350 previous_screen = priv->screen;
8351 was_mapped = gtk_widget_get_mapped (widget);
8354 gtk_widget_unmap (widget);
8355 if (gtk_widget_get_realized (widget))
8356 gtk_widget_unrealize (widget);
8358 gtk_window_free_key_hash (window);
8359 priv->screen = screen;
8360 gtk_widget_reset_rc_styles (widget);
8361 if (screen != previous_screen)
8363 if (previous_screen)
8365 g_signal_handlers_disconnect_by_func (previous_screen,
8366 gtk_window_on_composited_changed, window);
8367 #ifdef GDK_WINDOWING_X11
8368 g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
8369 gtk_window_on_theme_variant_changed, window);
8372 g_signal_connect (screen, "composited-changed",
8373 G_CALLBACK (gtk_window_on_composited_changed), window);
8374 #ifdef GDK_WINDOWING_X11
8375 g_signal_connect (gtk_settings_get_for_screen (screen),
8376 "notify::gtk-application-prefer-dark-theme",
8377 G_CALLBACK (gtk_window_on_theme_variant_changed), window);
8380 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8381 _gtk_widget_propagate_composited_changed (widget);
8383 g_object_notify (G_OBJECT (window), "screen");
8386 gtk_widget_map (widget);
8390 gtk_window_set_theme_variant (GtkWindow *window)
8392 #ifdef GDK_WINDOWING_X11
8393 GdkWindow *gdk_window;
8394 gboolean dark_theme_requested;
8396 g_object_get (gtk_settings_get_for_screen (window->priv->screen),
8397 "gtk-application-prefer-dark-theme", &dark_theme_requested,
8400 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
8402 if (GDK_IS_X11_WINDOW (gdk_window))
8403 gdk_x11_window_set_theme_variant (gdk_window,
8404 dark_theme_requested ? "dark" : NULL);
8409 gtk_window_on_theme_variant_changed (GtkSettings *settings,
8413 if (window->priv->type == GTK_WINDOW_TOPLEVEL)
8414 gtk_window_set_theme_variant (window);
8418 gtk_window_on_composited_changed (GdkScreen *screen,
8421 gtk_widget_queue_draw (GTK_WIDGET (window));
8423 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8427 gtk_window_check_screen (GtkWindow *window)
8429 GtkWindowPrivate *priv = window->priv;
8432 return priv->screen;
8435 g_warning ("Screen for GtkWindow not set; you must always set\n"
8436 "a screen for a GtkWindow before using the window");
8442 * gtk_window_get_screen:
8443 * @window: a #GtkWindow.
8445 * Returns the #GdkScreen associated with @window.
8447 * Return value: (transfer none): a #GdkScreen.
8452 gtk_window_get_screen (GtkWindow *window)
8454 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8456 return window->priv->screen;
8460 * gtk_window_is_active:
8461 * @window: a #GtkWindow
8463 * Returns whether the window is part of the current active toplevel.
8464 * (That is, the toplevel window receiving keystrokes.)
8465 * The return value is %TRUE if the window is active toplevel
8466 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8467 * You might use this function if you wanted to draw a widget
8468 * differently in an active window from a widget in an inactive window.
8469 * See gtk_window_has_toplevel_focus()
8471 * Return value: %TRUE if the window part of the current active window.
8476 gtk_window_is_active (GtkWindow *window)
8478 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8480 return window->priv->is_active;
8484 * gtk_window_has_toplevel_focus:
8485 * @window: a #GtkWindow
8487 * Returns whether the input focus is within this GtkWindow.
8488 * For real toplevel windows, this is identical to gtk_window_is_active(),
8489 * but for embedded windows, like #GtkPlug, the results will differ.
8491 * Return value: %TRUE if the input focus is within this GtkWindow
8496 gtk_window_has_toplevel_focus (GtkWindow *window)
8498 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8500 return window->priv->has_toplevel_focus;
8505 * SECTION:gtkwindowgroup
8506 * @Short_description: Limit the effect of grabs
8507 * @Title: GtkWindowGroup
8509 * #GtkWindowGroup objects are referenced by each window in the group,
8510 * so once you have added all windows to a #GtkWindowGroup, you can drop
8511 * the initial reference to the window group with g_object_unref(). If the
8512 * windows in the window group are subsequently destroyed, then they will
8513 * be removed from the window group and drop their references on the window
8514 * group; when all window have been removed, the window group will be
8518 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8521 gtk_window_group_init (GtkWindowGroup *group)
8523 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8524 GTK_TYPE_WINDOW_GROUP,
8525 GtkWindowGroupPrivate);
8529 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8531 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8535 * gtk_window_group_new:
8537 * Creates a new #GtkWindowGroup object. Grabs added with
8538 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8540 * Return value: a new #GtkWindowGroup.
8543 gtk_window_group_new (void)
8545 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8549 window_group_cleanup_grabs (GtkWindowGroup *group,
8552 GtkWindowGroupPrivate *priv;
8553 GtkDeviceGrabInfo *info;
8555 GSList *to_remove = NULL;
8559 tmp_list = priv->grabs;
8562 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8563 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8564 tmp_list = tmp_list->next;
8569 gtk_grab_remove (to_remove->data);
8570 g_object_unref (to_remove->data);
8571 to_remove = g_slist_delete_link (to_remove, to_remove);
8574 tmp_list = priv->device_grabs;
8578 info = tmp_list->data;
8580 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8581 to_remove = g_slist_prepend (to_remove, info);
8583 tmp_list = tmp_list->next;
8588 info = to_remove->data;
8590 gtk_device_grab_remove (info->widget, info->device);
8591 to_remove = g_slist_delete_link (to_remove, to_remove);
8596 * gtk_window_group_add_window:
8597 * @window_group: a #GtkWindowGroup
8598 * @window: the #GtkWindow to add
8600 * Adds a window to a #GtkWindowGroup.
8603 gtk_window_group_add_window (GtkWindowGroup *window_group,
8606 GtkWindowPrivate *priv;
8608 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8609 g_return_if_fail (GTK_IS_WINDOW (window));
8611 priv = window->priv;
8613 if (priv->group != window_group)
8615 g_object_ref (window);
8616 g_object_ref (window_group);
8619 gtk_window_group_remove_window (priv->group, window);
8621 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8623 priv->group = window_group;
8625 g_object_unref (window);
8630 * gtk_window_group_remove_window:
8631 * @window_group: a #GtkWindowGroup
8632 * @window: the #GtkWindow to remove
8634 * Removes a window from a #GtkWindowGroup.
8637 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8640 GtkWindowPrivate *priv;
8642 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8643 g_return_if_fail (GTK_IS_WINDOW (window));
8644 priv = window->priv;
8645 g_return_if_fail (priv->group == window_group);
8647 g_object_ref (window);
8649 window_group_cleanup_grabs (window_group, window);
8652 g_object_unref (window_group);
8653 g_object_unref (window);
8657 * gtk_window_group_list_windows:
8658 * @window_group: a #GtkWindowGroup
8660 * Returns a list of the #GtkWindows that belong to @window_group.
8662 * Returns: (element-type GtkWindow) (transfer container): A
8663 * newly-allocated list of windows inside the group.
8668 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8670 GList *toplevels, *toplevel, *group_windows;
8672 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8674 group_windows = NULL;
8675 toplevels = gtk_window_list_toplevels ();
8677 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8679 GtkWindow *window = toplevel->data;
8681 if (window_group == window->priv->group)
8682 group_windows = g_list_prepend (group_windows, window);
8685 g_list_free (toplevels);
8687 return g_list_reverse (group_windows);
8691 * gtk_window_get_group:
8692 * @window: (allow-none): a #GtkWindow, or %NULL
8694 * Returns the group for @window or the default group, if
8695 * @window is %NULL or if @window does not have an explicit
8698 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8703 gtk_window_get_group (GtkWindow *window)
8705 if (window && window->priv->group)
8706 return window->priv->group;
8709 static GtkWindowGroup *default_group = NULL;
8712 default_group = gtk_window_group_new ();
8714 return default_group;
8719 * gtk_window_has_group:
8720 * @window: a #GtkWindow
8722 * Returns whether @window has an explicit window group.
8724 * Return value: %TRUE if @window has an explicit window group.
8729 gtk_window_has_group (GtkWindow *window)
8731 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8733 return window->priv->group != NULL;
8737 * gtk_window_group_get_current_grab:
8738 * @window_group: a #GtkWindowGroup
8740 * Gets the current grab widget of the given group,
8741 * see gtk_grab_add().
8743 * Returns: (transfer none): the current grab widget of the group
8748 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8750 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8752 if (window_group->priv->grabs)
8753 return GTK_WIDGET (window_group->priv->grabs->data);
8758 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8761 GtkWindowGroupPrivate *priv;
8763 priv = window_group->priv;
8764 priv->grabs = g_slist_prepend (priv->grabs, widget);
8768 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8771 GtkWindowGroupPrivate *priv;
8773 priv = window_group->priv;
8774 priv->grabs = g_slist_remove (priv->grabs, widget);
8779 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8782 gboolean block_others)
8784 GtkWindowGroupPrivate *priv;
8785 GtkDeviceGrabInfo *info;
8787 priv = window_group->priv;
8789 info = g_slice_new0 (GtkDeviceGrabInfo);
8790 info->widget = widget;
8791 info->device = device;
8792 info->block_others = block_others;
8794 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8798 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8802 GtkWindowGroupPrivate *priv;
8803 GtkDeviceGrabInfo *info;
8804 GSList *list, *node = NULL;
8805 GdkDevice *other_device;
8807 priv = window_group->priv;
8808 other_device = gdk_device_get_associated_device (device);
8809 list = priv->device_grabs;
8815 if (info->widget == widget &&
8816 (info->device == device ||
8817 info->device == other_device))
8830 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8831 g_slice_free (GtkDeviceGrabInfo, info);
8836 * gtk_window_group_get_current_device_grab:
8837 * @window_group: a #GtkWindowGroup
8838 * @device: a #GdkDevice
8840 * Returns the current grab widget for @device, or %NULL if none.
8842 * Returns: (transfer none): The grab widget, or %NULL
8847 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8850 GtkWindowGroupPrivate *priv;
8851 GtkDeviceGrabInfo *info;
8852 GdkDevice *other_device;
8855 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8856 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8858 priv = window_group->priv;
8859 list = priv->device_grabs;
8860 other_device = gdk_device_get_associated_device (device);
8867 if (info->device == device ||
8868 info->device == other_device)
8869 return info->widget;
8876 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8880 GtkWindowGroupPrivate *priv;
8881 GtkDeviceGrabInfo *info;
8882 GdkDevice *other_device;
8885 priv = window_group->priv;
8886 other_device = gdk_device_get_associated_device (device);
8887 list = priv->device_grabs;
8894 /* Look for blocking grabs on other device pairs
8895 * that have the passed widget within the GTK+ grab.
8897 if (info->block_others &&
8898 info->device != device &&
8899 info->device != other_device &&
8900 (info->widget == widget ||
8901 gtk_widget_is_ancestor (widget, info->widget)))
8909 Derived from XParseGeometry() in XFree86
8911 Copyright 1985, 1986, 1987,1998 The Open Group
8913 All Rights Reserved.
8915 The above copyright notice and this permission notice shall be included
8916 in all copies or substantial portions of the Software.
8918 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8919 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8920 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8921 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8922 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8923 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8924 OTHER DEALINGS IN THE SOFTWARE.
8926 Except as contained in this notice, the name of The Open Group shall
8927 not be used in advertising or otherwise to promote the sale, use or
8928 other dealings in this Software without prior written authorization
8929 from The Open Group.
8934 * XParseGeometry parses strings of the form
8935 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8936 * width, height, xoffset, and yoffset are unsigned integers.
8937 * Example: "=80x24+300-49"
8938 * The equal sign is optional.
8939 * It returns a bitmask that indicates which of the four values
8940 * were actually found in the string. For each value found,
8941 * the corresponding argument is updated; for each value
8942 * not found, the corresponding argument is left unchanged.
8945 /* The following code is from Xlib, and is minimally modified, so we
8946 * can track any upstream changes if required. Don't change this
8947 * code. Or if you do, put in a huge comment marking which thing
8952 read_int (gchar *string,
8960 else if (*string == '-')
8966 for (; (*string >= '0') && (*string <= '9'); string++)
8968 result = (result * 10) + (*string - '0');
8980 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8981 * value (x, y, width, height) was found in the parsed string.
8983 #define NoValue 0x0000
8984 #define XValue 0x0001
8985 #define YValue 0x0002
8986 #define WidthValue 0x0004
8987 #define HeightValue 0x0008
8988 #define AllValues 0x000F
8989 #define XNegative 0x0010
8990 #define YNegative 0x0020
8992 /* Try not to reformat/modify, so we can compare/sync with X sources */
8994 gtk_XParseGeometry (const char *string,
8997 unsigned int *width,
8998 unsigned int *height)
9002 unsigned int tempWidth, tempHeight;
9004 char *nextCharacter;
9006 /* These initializations are just to silence gcc */
9012 if ( (string == NULL) || (*string == '\0')) return(mask);
9014 string++; /* ignore possible '=' at beg of geometry spec */
9016 strind = (char *)string;
9017 if (*strind != '+' && *strind != '-' && *strind != 'x') {
9018 tempWidth = read_int(strind, &nextCharacter);
9019 if (strind == nextCharacter)
9021 strind = nextCharacter;
9025 if (*strind == 'x' || *strind == 'X') {
9027 tempHeight = read_int(strind, &nextCharacter);
9028 if (strind == nextCharacter)
9030 strind = nextCharacter;
9031 mask |= HeightValue;
9034 if ((*strind == '+') || (*strind == '-')) {
9035 if (*strind == '-') {
9037 tempX = -read_int(strind, &nextCharacter);
9038 if (strind == nextCharacter)
9040 strind = nextCharacter;
9046 tempX = read_int(strind, &nextCharacter);
9047 if (strind == nextCharacter)
9049 strind = nextCharacter;
9052 if ((*strind == '+') || (*strind == '-')) {
9053 if (*strind == '-') {
9055 tempY = -read_int(strind, &nextCharacter);
9056 if (strind == nextCharacter)
9058 strind = nextCharacter;
9065 tempY = read_int(strind, &nextCharacter);
9066 if (strind == nextCharacter)
9068 strind = nextCharacter;
9074 /* If strind isn't at the end of the string the it's an invalid
9075 geometry specification. */
9077 if (*strind != '\0') return (0);
9083 if (mask & WidthValue)
9085 if (mask & HeightValue)
9086 *height = tempHeight;
9091 * gtk_window_parse_geometry:
9092 * @window: a #GtkWindow
9093 * @geometry: geometry string
9095 * Parses a standard X Window System geometry string - see the
9096 * manual page for X (type 'man X') for details on this.
9097 * gtk_window_parse_geometry() does work on all GTK+ ports
9098 * including Win32 but is primarily intended for an X environment.
9100 * If either a size or a position can be extracted from the
9101 * geometry string, gtk_window_parse_geometry() returns %TRUE
9102 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9103 * to resize/move the window.
9105 * If gtk_window_parse_geometry() returns %TRUE, it will also
9106 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9107 * indicating to the window manager that the size/position of
9108 * the window was user-specified. This causes most window
9109 * managers to honor the geometry.
9111 * Note that for gtk_window_parse_geometry() to work as expected, it has
9112 * to be called when the window has its "final" size, i.e. after calling
9113 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9116 * #include <gtk/gtk.h>
9119 * fill_with_content (GtkWidget *vbox)
9121 * /* fill with content... */
9125 * main (int argc, char *argv[])
9127 * GtkWidget *window, *vbox;
9128 * GdkGeometry size_hints = {
9129 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9132 * gtk_init (&argc, &argv);
9134 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9135 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9137 * gtk_container_add (GTK_CONTAINER (window), vbox);
9138 * fill_with_content (vbox);
9139 * gtk_widget_show_all (vbox);
9141 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9144 * GDK_HINT_MIN_SIZE |
9145 * GDK_HINT_BASE_SIZE |
9146 * GDK_HINT_RESIZE_INC);
9150 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9151 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9154 * gtk_widget_show_all (window);
9161 * Return value: %TRUE if string was parsed successfully
9164 gtk_window_parse_geometry (GtkWindow *window,
9165 const gchar *geometry)
9167 gint result, x = 0, y = 0;
9171 gboolean size_set, pos_set;
9174 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9175 g_return_val_if_fail (geometry != NULL, FALSE);
9177 child = gtk_bin_get_child (GTK_BIN (window));
9178 if (!child || !gtk_widget_get_visible (child))
9179 g_warning ("gtk_window_parse_geometry() called on a window with no "
9180 "visible children; the window should be set up before "
9181 "gtk_window_parse_geometry() is called.");
9183 screen = gtk_window_check_screen (window);
9185 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9188 if ((result & WidthValue) || (result & HeightValue))
9190 gtk_window_set_default_size_internal (window,
9191 TRUE, result & WidthValue ? w : -1,
9192 TRUE, result & HeightValue ? h : -1,
9197 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9199 grav = GDK_GRAVITY_NORTH_WEST;
9201 if ((result & XNegative) && (result & YNegative))
9202 grav = GDK_GRAVITY_SOUTH_EAST;
9203 else if (result & XNegative)
9204 grav = GDK_GRAVITY_NORTH_EAST;
9205 else if (result & YNegative)
9206 grav = GDK_GRAVITY_SOUTH_WEST;
9208 if ((result & XValue) == 0)
9211 if ((result & YValue) == 0)
9214 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9215 grav == GDK_GRAVITY_SOUTH_EAST)
9216 y = gdk_screen_get_height (screen) - h + y;
9218 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9219 grav == GDK_GRAVITY_NORTH_EAST)
9220 x = gdk_screen_get_width (screen) - w + x;
9222 /* we don't let you put a window offscreen; maybe some people would
9223 * prefer to be able to, but it's kind of a bogus thing to do.
9232 if ((result & XValue) || (result & YValue))
9234 gtk_window_set_gravity (window, grav);
9235 gtk_window_move (window, x, y);
9239 if (size_set || pos_set)
9241 /* Set USSize, USPosition hints */
9242 GtkWindowGeometryInfo *info;
9244 info = gtk_window_get_geometry_info (window, TRUE);
9247 info->mask |= GDK_HINT_USER_POS;
9249 info->mask |= GDK_HINT_USER_SIZE;
9256 gtk_window_mnemonic_hash_foreach (guint keyval,
9262 GtkWindowKeysForeachFunc func;
9266 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9270 _gtk_window_keys_foreach (GtkWindow *window,
9271 GtkWindowKeysForeachFunc func,
9275 GtkMnemonicHash *mnemonic_hash;
9279 GtkWindowKeysForeachFunc func;
9283 info.window = window;
9285 info.func_data = func_data;
9287 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9289 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9290 gtk_window_mnemonic_hash_foreach, &info);
9292 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9295 GtkAccelGroup *group = groups->data;
9298 for (i = 0; i < group->priv->n_accels; i++)
9300 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9303 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9306 groups = groups->next;
9311 gtk_window_keys_changed (GtkWindow *window)
9313 gtk_window_free_key_hash (window);
9314 gtk_window_get_key_hash (window);
9317 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9319 struct _GtkWindowKeyEntry
9323 guint is_mnemonic : 1;
9327 window_key_entry_destroy (gpointer data)
9329 g_slice_free (GtkWindowKeyEntry, data);
9333 add_to_key_hash (GtkWindow *window,
9335 GdkModifierType modifiers,
9336 gboolean is_mnemonic,
9339 GtkKeyHash *key_hash = data;
9341 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9343 entry->keyval = keyval;
9344 entry->modifiers = modifiers;
9345 entry->is_mnemonic = is_mnemonic;
9347 /* GtkAccelGroup stores lowercased accelerators. To deal
9348 * with this, if <Shift> was specified, uppercase.
9350 if (modifiers & GDK_SHIFT_MASK)
9352 if (keyval == GDK_KEY_Tab)
9353 keyval = GDK_KEY_ISO_Left_Tab;
9355 keyval = gdk_keyval_to_upper (keyval);
9358 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9362 gtk_window_get_key_hash (GtkWindow *window)
9364 GdkScreen *screen = gtk_window_check_screen (window);
9365 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9370 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9371 (GDestroyNotify)window_key_entry_destroy);
9372 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9373 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9379 gtk_window_free_key_hash (GtkWindow *window)
9381 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9384 _gtk_key_hash_free (key_hash);
9385 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9390 * gtk_window_activate_key:
9391 * @window: a #GtkWindow
9392 * @event: a #GdkEventKey
9394 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9395 * called by the default ::key_press_event handler for toplevel windows,
9396 * however in some cases it may be useful to call this directly when
9397 * overriding the standard key handling for a toplevel window.
9399 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9404 gtk_window_activate_key (GtkWindow *window,
9407 GtkKeyHash *key_hash;
9408 GtkWindowKeyEntry *found_entry = NULL;
9409 gboolean enable_mnemonics;
9410 gboolean enable_accels;
9412 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9413 g_return_val_if_fail (event != NULL, FALSE);
9415 key_hash = gtk_window_get_key_hash (window);
9420 GSList *entries = _gtk_key_hash_lookup (key_hash,
9421 event->hardware_keycode,
9423 gtk_accelerator_get_default_mod_mask (),
9426 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9427 "gtk-enable-mnemonics", &enable_mnemonics,
9428 "gtk-enable-accels", &enable_accels,
9431 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9433 GtkWindowKeyEntry *entry = tmp_list->data;
9434 if (entry->is_mnemonic)
9436 if (enable_mnemonics)
9438 found_entry = entry;
9444 if (enable_accels && !found_entry)
9446 found_entry = entry;
9451 g_slist_free (entries);
9456 if (found_entry->is_mnemonic)
9458 if (enable_mnemonics)
9459 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9460 found_entry->modifiers);
9465 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9466 found_entry->modifiers);
9474 window_update_has_focus (GtkWindow *window)
9476 GtkWindowPrivate *priv = window->priv;
9477 GtkWidget *widget = GTK_WIDGET (window);
9478 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9480 if (has_focus != priv->has_focus)
9482 priv->has_focus = has_focus;
9486 if (priv->focus_widget &&
9487 priv->focus_widget != widget &&
9488 !gtk_widget_has_focus (priv->focus_widget))
9489 do_focus_change (priv->focus_widget, TRUE);
9493 if (priv->focus_widget &&
9494 priv->focus_widget != widget &&
9495 gtk_widget_has_focus (priv->focus_widget))
9496 do_focus_change (priv->focus_widget, FALSE);
9502 * _gtk_window_set_is_active:
9503 * @window: a #GtkWindow
9504 * @is_active: %TRUE if the window is in the currently active toplevel
9506 * Internal function that sets whether the #GtkWindow is part
9507 * of the currently active toplevel window (taking into account inter-process
9511 _gtk_window_set_is_active (GtkWindow *window,
9514 GtkWindowPrivate *priv;
9516 g_return_if_fail (GTK_IS_WINDOW (window));
9518 priv = window->priv;
9520 is_active = is_active != FALSE;
9522 if (is_active != priv->is_active)
9524 priv->is_active = is_active;
9525 window_update_has_focus (window);
9527 g_object_notify (G_OBJECT (window), "is-active");
9532 * _gtk_window_set_is_toplevel:
9533 * @window: a #GtkWindow
9534 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9535 * child of the root window); %FALSE if it is not (for example, for an
9536 * in-process, parented GtkPlug)
9538 * Internal function used by #GtkPlug when it gets parented/unparented by a
9539 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9540 * global list of toplevel windows.
9543 _gtk_window_set_is_toplevel (GtkWindow *window,
9544 gboolean is_toplevel)
9547 GtkWidget *toplevel;
9549 widget = GTK_WIDGET (window);
9551 if (gtk_widget_is_toplevel (widget))
9552 g_assert (g_slist_find (toplevel_list, window) != NULL);
9554 g_assert (g_slist_find (toplevel_list, window) == NULL);
9556 if (is_toplevel == gtk_widget_is_toplevel (widget))
9561 /* Pass through regular pathways of an embedded toplevel
9562 * to go through unmapping and hiding the widget before
9563 * becomming a toplevel again.
9565 * We remain hidden after becomming toplevel in order to
9566 * avoid problems during an embedded toplevel's dispose cycle
9567 * (When a toplevel window is shown it tries to grab focus again,
9568 * this causes problems while disposing).
9570 gtk_widget_hide (widget);
9572 /* Save the toplevel this widget was previously anchored into before
9573 * propagating a hierarchy-changed.
9575 * Usually this happens by way of gtk_widget_unparent() and we are
9576 * already unanchored at this point, just adding this clause incase
9577 * things happen differently.
9579 toplevel = gtk_widget_get_toplevel (widget);
9580 if (!gtk_widget_is_toplevel (toplevel))
9583 _gtk_widget_set_is_toplevel (widget, TRUE);
9585 /* When a window becomes toplevel after being embedded and anchored
9586 * into another window we need to unset its anchored flag so that
9587 * the hierarchy changed signal kicks in properly.
9589 _gtk_widget_set_anchored (widget, FALSE);
9590 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9592 toplevel_list = g_slist_prepend (toplevel_list, window);
9596 _gtk_widget_set_is_toplevel (widget, FALSE);
9597 toplevel_list = g_slist_remove (toplevel_list, window);
9599 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9604 * _gtk_window_set_has_toplevel_focus:
9605 * @window: a #GtkWindow
9606 * @has_toplevel_focus: %TRUE if the in
9608 * Internal function that sets whether the keyboard focus for the
9609 * toplevel window (taking into account inter-process embedding.)
9612 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9613 gboolean has_toplevel_focus)
9615 GtkWindowPrivate *priv;
9617 g_return_if_fail (GTK_IS_WINDOW (window));
9619 priv = window->priv;
9621 has_toplevel_focus = has_toplevel_focus != FALSE;
9623 if (has_toplevel_focus != priv->has_toplevel_focus)
9625 priv->has_toplevel_focus = has_toplevel_focus;
9626 window_update_has_focus (window);
9628 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9633 * gtk_window_set_auto_startup_notification:
9634 * @setting: %TRUE to automatically do startup notification
9636 * By default, after showing the first #GtkWindow, GTK+ calls
9637 * gdk_notify_startup_complete(). Call this function to disable
9638 * the automatic startup notification. You might do this if your
9639 * first window is a splash screen, and you want to delay notification
9640 * until after your real main window has been shown, for example.
9642 * In that example, you would disable startup notification
9643 * temporarily, show your splash screen, then re-enable it so that
9644 * showing the main window would automatically result in notification.
9649 gtk_window_set_auto_startup_notification (gboolean setting)
9651 disable_startup_notification = !setting;
9655 * gtk_window_get_window_type:
9656 * @window: a #GtkWindow
9658 * Gets the type of the window. See #GtkWindowType.
9660 * Return value: the type of the window
9665 gtk_window_get_window_type (GtkWindow *window)
9667 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9669 return window->priv->type;
9673 * gtk_window_get_mnemonics_visible:
9674 * @window: a #GtkWindow
9676 * Gets the value of the #GtkWindow:mnemonics-visible property.
9678 * Returns: %TRUE if mnemonics are supposed to be visible
9684 gtk_window_get_mnemonics_visible (GtkWindow *window)
9686 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9688 return window->priv->mnemonics_visible;
9692 * gtk_window_set_mnemonics_visible:
9693 * @window: a #GtkWindow
9694 * @setting: the new value
9696 * Sets the #GtkWindow:mnemonics-visible property.
9701 gtk_window_set_mnemonics_visible (GtkWindow *window,
9704 GtkWindowPrivate *priv;
9706 g_return_if_fail (GTK_IS_WINDOW (window));
9708 priv = window->priv;
9710 setting = setting != FALSE;
9712 if (priv->mnemonics_visible != setting)
9714 priv->mnemonics_visible = setting;
9715 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9718 priv->mnemonics_visible_set = TRUE;
9722 * gtk_window_get_focus_visible:
9723 * @window: a #GtkWindow
9725 * Gets the value of the #GtkWindow:focus-visible property.
9727 * Returns: %TRUE if 'focus rectangles' are supposed to be visible
9733 gtk_window_get_focus_visible (GtkWindow *window)
9735 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9737 return window->priv->focus_visible;
9741 * gtk_window_set_focus_visible:
9742 * @window: a #GtkWindow
9743 * @setting: the new value
9745 * Sets the #GtkWindow:focus-visible property.
9750 gtk_window_set_focus_visible (GtkWindow *window,
9753 GtkWindowPrivate *priv;
9755 g_return_if_fail (GTK_IS_WINDOW (window));
9757 priv = window->priv;
9759 setting = setting != FALSE;
9761 if (priv->focus_visible != setting)
9763 priv->focus_visible = setting;
9764 g_object_notify (G_OBJECT (window), "focus-visible");
9769 _gtk_window_get_wmclass (GtkWindow *window,
9770 gchar **wmclass_name,
9771 gchar **wmclass_class)
9773 GtkWindowPrivate *priv = window->priv;
9775 *wmclass_name = priv->wmclass_name;
9776 *wmclass_class = priv->wmclass_class;
9780 * gtk_window_set_has_user_ref_count:
9781 * @window: a #GtkWindow
9782 * @setting: the new value
9784 * Tells GTK+ whether to drop its extra reference to the window
9785 * when gtk_window_destroy() is called.
9787 * This function is only exported for the benefit of language
9788 * bindings which may need to keep the window alive until their
9789 * wrapper object is garbage collected. There is no justification
9790 * for ever calling this function in an application.
9795 gtk_window_set_has_user_ref_count (GtkWindow *window,
9798 g_return_if_fail (GTK_IS_WINDOW (window));
9800 window->priv->has_user_ref_count = setting;
9804 ensure_state_flag_backdrop (GtkWidget *widget)
9807 gboolean window_focused = TRUE;
9809 window = gtk_widget_get_window (widget);
9811 window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
9813 if (!window_focused)
9814 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
9816 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
9818 gtk_widget_queue_draw (widget);