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/.
36 #include "gdk/gdkkeysyms.h"
38 #include "gtkprivate.h"
40 #include "gtkwindow.h"
41 #include "gtkwindowprivate.h"
42 #include "gtkaccelgroupprivate.h"
43 #include "gtkbindings.h"
44 #include "gtkkeyhash.h"
46 #include "gtkmnemonichash.h"
47 #include "gtkmenubar.h"
48 #include "gtkiconfactory.h"
49 #include "gtkicontheme.h"
50 #include "gtkmarshalers.h"
52 #include "gtkbuildable.h"
53 #include "gtkwidgetprivate.h"
55 #ifdef GDK_WINDOWING_X11
62 * @short_description: Toplevel which can contain other widgets
64 * A GtkWindow is a toplevel window which can contain other widgets.
65 * Windows normally have decorations that are under the control
66 * of the windowing system and allow the user to manipulate the window
67 * (resize it, move it, close it,...).
69 * GTK+ also allows windows to have a resize grip (a small area in the lower
70 * right or left corner) which can be clicked to reszie the window. To
71 * control whether a window has a resize grip, use
72 * gtk_window_set_has_resize_grip().
74 * <refsect2 id="GtkWindow-BUILDER-UI">
75 * <title>GtkWindow as GtkBuildable</title>
77 * The GtkWindow implementation of the GtkBuildable interface supports a
78 * custom <tag class="starttag">accel-groups</tag> element, which supports
79 * any number of <tag class="starttag">group</tag> elements representing the
80 * #GtkAccelGroup objects you want to add to your window (synonymous with
81 * gtk_window_add_accel_group().
84 * <title>A UI definition fragment with accel groups</title>
85 * <programlisting><![CDATA[
86 * <object class="GtkWindow">
88 * <group name="accelgroup1"/>
94 * <object class="GtkAccelGroup" id="accelgroup1"/>
95 * ]]></programlisting>
100 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
102 struct _GtkWindowPrivate
104 GtkMnemonicHash *mnemonic_hash;
106 GtkWidget *default_widget;
107 GtkWidget *focus_widget;
108 GtkWindow *transient_parent;
109 GtkWindowGeometryInfo *geometry_info;
110 GtkWindowGroup *group;
112 GdkModifierType mnemonic_modifier;
114 GdkWindowTypeHint gdk_type_hint;
116 GtkApplication *application;
120 GdkWindow *grip_window;
124 gchar *wmclass_class;
128 guint keys_changed_handler;
130 guint16 configure_request_count;
132 /* The following flags are initially TRUE (before a window is mapped).
133 * They cause us to compute a configure request that involves
134 * default-only parameters. Once mapped, we set them to FALSE.
135 * Then we set them to TRUE again on unmap (for position)
136 * and on unrealize (for size).
138 guint need_default_position : 1;
139 guint need_default_size : 1;
141 guint above_initially : 1;
142 guint accept_focus : 1;
143 guint below_initially : 1;
144 guint builder_visible : 1;
145 guint configure_notify_received : 1;
148 guint destroy_with_parent : 1;
149 guint focus_on_map : 1;
150 guint fullscreen_initially : 1;
151 guint gravity : 5; /* GdkGravity */
153 guint has_user_ref_count : 1;
154 guint has_toplevel_focus : 1;
155 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
157 guint maximize_initially : 1;
158 guint mnemonics_visible : 1;
159 guint mnemonics_visible_set : 1;
161 guint opacity_set : 1;
163 guint reset_type_hint : 1;
165 guint skips_pager : 1;
166 guint skips_taskbar : 1;
167 guint stick_initially : 1;
168 guint transient_parent_group : 1;
169 guint type : 4; /* GtkWindowType */
170 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
171 * one of the original eight. If not,
173 * GDK_WINDOW_TYPE_HINT_NORMAL
176 guint has_resize_grip : 1;
177 guint resize_grip_visible : 1; /* don't use, just for "resize-
178 * grip-visible" notification
206 PROP_DESTROY_WITH_PARENT,
211 PROP_SKIP_TASKBAR_HINT,
212 PROP_SKIP_PAGER_HINT,
221 PROP_HAS_RESIZE_GRIP,
222 PROP_RESIZE_GRIP_VISIBLE,
224 /* Readonly properties */
226 PROP_HAS_TOPLEVEL_FOCUS,
228 /* Writeonly properties */
231 PROP_MNEMONICS_VISIBLE,
241 guint using_default_icon : 1;
242 guint using_parent_icon : 1;
243 guint using_themed_icon : 1;
247 GdkGeometry geometry; /* Last set of geometry hints we set */
248 GdkWindowHints flags;
249 GdkRectangle configure_request;
250 } GtkWindowLastGeometryInfo;
252 struct _GtkWindowGeometryInfo
254 /* Properties that the app has set on the window
256 GdkGeometry geometry; /* Geometry hints */
258 GtkWidget *widget; /* subwidget to which hints apply */
259 /* from last gtk_window_resize () - if > 0, indicates that
260 * we should resize to this size.
265 /* From last gtk_window_move () prior to mapping -
266 * only used if initial_pos_set
271 /* Default size - used only the FIRST time we map a window,
276 /* whether to use initial_x, initial_y */
277 guint initial_pos_set : 1;
278 /* CENTER_ALWAYS or other position constraint changed since
279 * we sent the last configure request.
281 guint position_constraints_changed : 1;
283 /* if true, default_width, height should be multiplied by the
284 * increments and affect the geometry widget only
286 guint default_is_geometry : 1;
288 /* if true, resize_width, height should be multiplied by the
289 * increments and affect the geometry widget only
291 guint resize_is_geometry : 1;
293 GtkWindowLastGeometryInfo last;
297 struct _GtkDeviceGrabInfo
301 guint block_others : 1;
304 struct _GtkWindowGroupPrivate
307 GSList *device_grabs;
310 static void gtk_window_dispose (GObject *object);
311 static void gtk_window_finalize (GObject *object);
312 static void gtk_window_destroy (GtkWidget *widget);
313 static void gtk_window_show (GtkWidget *widget);
314 static void gtk_window_hide (GtkWidget *widget);
315 static void gtk_window_map (GtkWidget *widget);
316 static void gtk_window_unmap (GtkWidget *widget);
317 static void gtk_window_realize (GtkWidget *widget);
318 static void gtk_window_unrealize (GtkWidget *widget);
319 static void gtk_window_size_allocate (GtkWidget *widget,
320 GtkAllocation *allocation);
321 static gboolean gtk_window_map_event (GtkWidget *widget,
323 static gint gtk_window_configure_event (GtkWidget *widget,
324 GdkEventConfigure *event);
325 static gint gtk_window_key_press_event (GtkWidget *widget,
327 static gint gtk_window_key_release_event (GtkWidget *widget,
329 static gint gtk_window_button_press_event (GtkWidget *widget,
330 GdkEventButton *event);
331 static gint gtk_window_enter_notify_event (GtkWidget *widget,
332 GdkEventCrossing *event);
333 static gint gtk_window_leave_notify_event (GtkWidget *widget,
334 GdkEventCrossing *event);
335 static gint gtk_window_focus_in_event (GtkWidget *widget,
336 GdkEventFocus *event);
337 static gint gtk_window_focus_out_event (GtkWidget *widget,
338 GdkEventFocus *event);
339 static void gtk_window_style_updated (GtkWidget *widget);
340 static gint gtk_window_client_event (GtkWidget *widget,
341 GdkEventClient *event);
342 static gboolean gtk_window_state_event (GtkWidget *widget,
343 GdkEventWindowState *event);
344 static void gtk_window_check_resize (GtkContainer *container);
345 static gint gtk_window_focus (GtkWidget *widget,
346 GtkDirectionType direction);
347 static void gtk_window_move_focus (GtkWidget *widget,
348 GtkDirectionType dir);
349 static void gtk_window_real_set_focus (GtkWindow *window,
351 static void gtk_window_direction_changed (GtkWidget *widget,
352 GtkTextDirection prev_dir);
353 static void gtk_window_state_changed (GtkWidget *widget,
354 GtkStateType previous_state);
356 static void gtk_window_real_activate_default (GtkWindow *window);
357 static void gtk_window_real_activate_focus (GtkWindow *window);
358 static void gtk_window_keys_changed (GtkWindow *window);
359 static gint gtk_window_draw (GtkWidget *widget,
361 static void gtk_window_unset_transient_for (GtkWindow *window);
362 static void gtk_window_transient_parent_realized (GtkWidget *parent,
364 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
367 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
369 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
372 static void gtk_window_move_resize (GtkWindow *window);
373 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
375 GdkGeometry *geometry_b,
377 static void gtk_window_constrain_size (GtkWindow *window,
378 GdkGeometry *geometry,
384 static void gtk_window_constrain_position (GtkWindow *window,
389 static void gtk_window_compute_hints (GtkWindow *window,
390 GdkGeometry *new_geometry,
392 static void gtk_window_compute_configure_request (GtkWindow *window,
393 GdkRectangle *request,
394 GdkGeometry *geometry,
397 static void gtk_window_set_default_size_internal (GtkWindow *window,
398 gboolean change_width,
400 gboolean change_height,
402 gboolean is_geometry);
404 static void update_themed_icon (GtkIconTheme *theme,
406 static GList *icon_list_from_theme (GtkWidget *widget,
408 static void gtk_window_realize_icon (GtkWindow *window);
409 static void gtk_window_unrealize_icon (GtkWindow *window);
410 static void resize_grip_create_window (GtkWindow *window);
411 static void resize_grip_destroy_window (GtkWindow *window);
412 static void update_grip_visibility (GtkWindow *window);
414 static void gtk_window_notify_keys_changed (GtkWindow *window);
415 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
416 static void gtk_window_free_key_hash (GtkWindow *window);
417 static void gtk_window_on_composited_changed (GdkScreen *screen,
420 static GSList *toplevel_list = NULL;
421 static guint window_signals[LAST_SIGNAL] = { 0 };
422 static GList *default_icon_list = NULL;
423 static gchar *default_icon_name = NULL;
424 static guint default_icon_serial = 0;
425 static gboolean disable_startup_notification = FALSE;
426 static gboolean sent_startup_notification = FALSE;
428 static GQuark quark_gtk_embedded = 0;
429 static GQuark quark_gtk_window_key_hash = 0;
430 static GQuark quark_gtk_window_icon_info = 0;
431 static GQuark quark_gtk_buildable_accels = 0;
433 static GtkBuildableIface *parent_buildable_iface;
435 static void gtk_window_set_property (GObject *object,
439 static void gtk_window_get_property (GObject *object,
445 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
446 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
449 const GValue *value);
450 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
451 GtkBuilder *builder);
452 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
455 const gchar *tagname,
456 GMarkupParser *parser,
458 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
461 const gchar *tagname,
465 static void gtk_window_get_preferred_width (GtkWidget *widget,
468 static void gtk_window_get_preferred_height (GtkWidget *widget,
472 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
473 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
474 gtk_window_buildable_interface_init))
477 add_tab_bindings (GtkBindingSet *binding_set,
478 GdkModifierType modifiers,
479 GtkDirectionType direction)
481 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
483 GTK_TYPE_DIRECTION_TYPE, direction);
484 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
486 GTK_TYPE_DIRECTION_TYPE, direction);
490 add_arrow_bindings (GtkBindingSet *binding_set,
492 GtkDirectionType direction)
494 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
496 gtk_binding_entry_add_signal (binding_set, keysym, 0,
498 GTK_TYPE_DIRECTION_TYPE, direction);
499 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
501 GTK_TYPE_DIRECTION_TYPE, direction);
502 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
504 GTK_TYPE_DIRECTION_TYPE, direction);
505 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
507 GTK_TYPE_DIRECTION_TYPE, direction);
511 extract_time_from_startup_id (const gchar* startup_id)
513 gchar *timestr = g_strrstr (startup_id, "_TIME");
514 guint32 retval = GDK_CURRENT_TIME;
521 /* Skip past the "_TIME" part */
526 timestamp = g_ascii_strtoull (timestr, &end, 0);
527 if (errno == 0 && end != timestr)
535 startup_id_is_fake (const gchar* startup_id)
537 return strncmp (startup_id, "_TIME", 5) == 0;
541 gtk_window_class_init (GtkWindowClass *klass)
543 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
544 GtkWidgetClass *widget_class;
545 GtkContainerClass *container_class;
546 GtkBindingSet *binding_set;
548 widget_class = (GtkWidgetClass*) klass;
549 container_class = (GtkContainerClass*) klass;
551 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
552 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
553 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
554 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
556 gobject_class->dispose = gtk_window_dispose;
557 gobject_class->finalize = gtk_window_finalize;
559 gobject_class->set_property = gtk_window_set_property;
560 gobject_class->get_property = gtk_window_get_property;
562 widget_class->destroy = gtk_window_destroy;
563 widget_class->show = gtk_window_show;
564 widget_class->hide = gtk_window_hide;
565 widget_class->map = gtk_window_map;
566 widget_class->map_event = gtk_window_map_event;
567 widget_class->unmap = gtk_window_unmap;
568 widget_class->realize = gtk_window_realize;
569 widget_class->unrealize = gtk_window_unrealize;
570 widget_class->size_allocate = gtk_window_size_allocate;
571 widget_class->configure_event = gtk_window_configure_event;
572 widget_class->key_press_event = gtk_window_key_press_event;
573 widget_class->key_release_event = gtk_window_key_release_event;
574 widget_class->enter_notify_event = gtk_window_enter_notify_event;
575 widget_class->leave_notify_event = gtk_window_leave_notify_event;
576 widget_class->focus_in_event = gtk_window_focus_in_event;
577 widget_class->button_press_event = gtk_window_button_press_event;
578 widget_class->focus_out_event = gtk_window_focus_out_event;
579 widget_class->client_event = gtk_window_client_event;
580 widget_class->focus = gtk_window_focus;
581 widget_class->move_focus = gtk_window_move_focus;
582 widget_class->draw = gtk_window_draw;
583 widget_class->get_preferred_width = gtk_window_get_preferred_width;
584 widget_class->get_preferred_height = gtk_window_get_preferred_height;
585 widget_class->window_state_event = gtk_window_state_event;
586 widget_class->direction_changed = gtk_window_direction_changed;
587 widget_class->state_changed = gtk_window_state_changed;
588 widget_class->style_updated = gtk_window_style_updated;
590 container_class->check_resize = gtk_window_check_resize;
592 klass->set_focus = gtk_window_real_set_focus;
594 klass->activate_default = gtk_window_real_activate_default;
595 klass->activate_focus = gtk_window_real_activate_focus;
596 klass->keys_changed = gtk_window_keys_changed;
598 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
601 g_object_class_install_property (gobject_class,
603 g_param_spec_enum ("type",
605 P_("The type of the window"),
606 GTK_TYPE_WINDOW_TYPE,
608 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
610 g_object_class_install_property (gobject_class,
612 g_param_spec_string ("title",
614 P_("The title of the window"),
616 GTK_PARAM_READWRITE));
618 g_object_class_install_property (gobject_class,
620 g_param_spec_string ("role",
622 P_("Unique identifier for the window to be used when restoring a session"),
624 GTK_PARAM_READWRITE));
627 * GtkWindow:startup-id:
629 * The :startup-id is a write-only property for setting window's
630 * startup notification identifier. See gtk_window_set_startup_id()
635 g_object_class_install_property (gobject_class,
637 g_param_spec_string ("startup-id",
639 P_("Unique startup identifier for the window used by startup-notification"),
641 GTK_PARAM_WRITABLE));
643 g_object_class_install_property (gobject_class,
645 g_param_spec_boolean ("resizable",
647 P_("If TRUE, users can resize the window"),
649 GTK_PARAM_READWRITE));
651 g_object_class_install_property (gobject_class,
653 g_param_spec_boolean ("modal",
655 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
657 GTK_PARAM_READWRITE));
659 g_object_class_install_property (gobject_class,
661 g_param_spec_enum ("window-position",
662 P_("Window Position"),
663 P_("The initial position of the window"),
664 GTK_TYPE_WINDOW_POSITION,
666 GTK_PARAM_READWRITE));
668 g_object_class_install_property (gobject_class,
670 g_param_spec_int ("default-width",
672 P_("The default width of the window, used when initially showing the window"),
676 GTK_PARAM_READWRITE));
678 g_object_class_install_property (gobject_class,
680 g_param_spec_int ("default-height",
681 P_("Default Height"),
682 P_("The default height of the window, used when initially showing the window"),
686 GTK_PARAM_READWRITE));
688 g_object_class_install_property (gobject_class,
689 PROP_DESTROY_WITH_PARENT,
690 g_param_spec_boolean ("destroy-with-parent",
691 P_("Destroy with Parent"),
692 P_("If this window should be destroyed when the parent is destroyed"),
694 GTK_PARAM_READWRITE));
696 g_object_class_install_property (gobject_class,
698 g_param_spec_object ("icon",
700 P_("Icon for this window"),
702 GTK_PARAM_READWRITE));
703 g_object_class_install_property (gobject_class,
704 PROP_MNEMONICS_VISIBLE,
705 g_param_spec_boolean ("mnemonics-visible",
706 P_("Mnemonics Visible"),
707 P_("Whether mnemonics are currently visible in this window"),
709 GTK_PARAM_READWRITE));
712 * GtkWindow:icon-name:
714 * The :icon-name property specifies the name of the themed icon to
715 * use as the window icon. See #GtkIconTheme for more details.
719 g_object_class_install_property (gobject_class,
721 g_param_spec_string ("icon-name",
723 P_("Name of the themed icon for this window"),
725 GTK_PARAM_READWRITE));
727 g_object_class_install_property (gobject_class,
729 g_param_spec_object ("screen",
731 P_("The screen where this window will be displayed"),
733 GTK_PARAM_READWRITE));
735 g_object_class_install_property (gobject_class,
737 g_param_spec_boolean ("is-active",
739 P_("Whether the toplevel is the current active window"),
741 GTK_PARAM_READABLE));
743 g_object_class_install_property (gobject_class,
744 PROP_HAS_TOPLEVEL_FOCUS,
745 g_param_spec_boolean ("has-toplevel-focus",
746 P_("Focus in Toplevel"),
747 P_("Whether the input focus is within this GtkWindow"),
749 GTK_PARAM_READABLE));
751 g_object_class_install_property (gobject_class,
753 g_param_spec_enum ("type-hint",
755 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
756 GDK_TYPE_WINDOW_TYPE_HINT,
757 GDK_WINDOW_TYPE_HINT_NORMAL,
758 GTK_PARAM_READWRITE));
760 g_object_class_install_property (gobject_class,
761 PROP_SKIP_TASKBAR_HINT,
762 g_param_spec_boolean ("skip-taskbar-hint",
764 P_("TRUE if the window should not be in the task bar."),
766 GTK_PARAM_READWRITE));
768 g_object_class_install_property (gobject_class,
769 PROP_SKIP_PAGER_HINT,
770 g_param_spec_boolean ("skip-pager-hint",
772 P_("TRUE if the window should not be in the pager."),
774 GTK_PARAM_READWRITE));
776 g_object_class_install_property (gobject_class,
778 g_param_spec_boolean ("urgency-hint",
780 P_("TRUE if the window should be brought to the user's attention."),
782 GTK_PARAM_READWRITE));
785 * GtkWindow:accept-focus:
787 * Whether the window should receive the input focus.
791 g_object_class_install_property (gobject_class,
793 g_param_spec_boolean ("accept-focus",
795 P_("TRUE if the window should receive the input focus."),
797 GTK_PARAM_READWRITE));
800 * GtkWindow:focus-on-map:
802 * Whether the window should receive the input focus when mapped.
806 g_object_class_install_property (gobject_class,
808 g_param_spec_boolean ("focus-on-map",
810 P_("TRUE if the window should receive the input focus when mapped."),
812 GTK_PARAM_READWRITE));
815 * GtkWindow:decorated:
817 * Whether the window should be decorated by the window manager.
821 g_object_class_install_property (gobject_class,
823 g_param_spec_boolean ("decorated",
825 P_("Whether the window should be decorated by the window manager"),
827 GTK_PARAM_READWRITE));
830 * GtkWindow:deletable:
832 * Whether the window frame should have a close button.
836 g_object_class_install_property (gobject_class,
838 g_param_spec_boolean ("deletable",
840 P_("Whether the window frame should have a close button"),
842 GTK_PARAM_READWRITE));
845 * GtkWindow:has-resize-grip
847 * Whether the window has a corner resize grip.
849 * Note that the resize grip is only shown if the window is
850 * actually resizable and not maximized. Use
851 * #GtkWindow:resize-grip-visible to find out if the resize
852 * grip is currently shown.
856 g_object_class_install_property (gobject_class,
857 PROP_HAS_RESIZE_GRIP,
858 g_param_spec_boolean ("has-resize-grip",
860 P_("Specifies whether the window should have a resize grip"),
862 GTK_PARAM_READWRITE));
865 * GtkWindow: resize-grip-visible:
867 * Whether a corner resize grip is currently shown.
871 g_object_class_install_property (gobject_class,
872 PROP_RESIZE_GRIP_VISIBLE,
873 g_param_spec_boolean ("resize-grip-visible",
874 P_("Resize grip is visible"),
875 P_("Specifies whether the window's resize grip is visible."),
877 GTK_PARAM_READABLE));
883 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
884 * more details about window gravity.
888 g_object_class_install_property (gobject_class,
890 g_param_spec_enum ("gravity",
892 P_("The window gravity of the window"),
894 GDK_GRAVITY_NORTH_WEST,
895 GTK_PARAM_READWRITE));
899 * GtkWindow:transient-for:
901 * The transient parent of the window. See gtk_window_set_transient_for() for
902 * more details about transient windows.
906 g_object_class_install_property (gobject_class,
908 g_param_spec_object ("transient-for",
909 P_("Transient for Window"),
910 P_("The transient parent of the dialog"),
912 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
917 * The requested opacity of the window. See gtk_window_set_opacity() for
918 * more details about window opacity.
922 g_object_class_install_property (gobject_class,
924 g_param_spec_double ("opacity",
925 P_("Opacity for Window"),
926 P_("The opacity of the window, from 0 to 1"),
930 GTK_PARAM_READWRITE));
934 gtk_widget_class_install_style_property (widget_class,
935 g_param_spec_int ("resize-grip-width",
936 P_("Width of resize grip"),
937 P_("Width of resize grip"),
938 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
940 gtk_widget_class_install_style_property (widget_class,
941 g_param_spec_int ("resize-grip-height",
942 P_("Height of resize grip"),
943 P_("Height of resize grip"),
944 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
950 * GtkWindow:application:
952 * The #GtkApplication associated with the window.
954 * The application will be kept alive for at least as long as the
959 g_object_class_install_property (gobject_class,
961 g_param_spec_object ("application",
962 P_("GtkApplication"),
963 P_("The GtkApplication for the window"),
964 GTK_TYPE_APPLICATION,
965 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
967 window_signals[SET_FOCUS] =
968 g_signal_new (I_("set-focus"),
969 G_TYPE_FROM_CLASS (gobject_class),
971 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
973 _gtk_marshal_VOID__OBJECT,
978 * GtkWindow::activate-focus:
979 * @window: the window which received the signal
981 * The ::activate-focus signal is a
982 * <link linkend="keybinding-signals">keybinding signal</link>
983 * which gets emitted when the user activates the currently
984 * focused widget of @window.
986 window_signals[ACTIVATE_FOCUS] =
987 g_signal_new (I_("activate-focus"),
988 G_TYPE_FROM_CLASS (gobject_class),
989 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
990 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
992 _gtk_marshal_VOID__VOID,
997 * GtkWindow::activate-default:
998 * @window: the window which received the signal
1000 * The ::activate-default signal is a
1001 * <link linkend="keybinding-signals">keybinding signal</link>
1002 * which gets emitted when the user activates the default widget
1005 window_signals[ACTIVATE_DEFAULT] =
1006 g_signal_new (I_("activate-default"),
1007 G_TYPE_FROM_CLASS (gobject_class),
1008 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1009 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1011 _gtk_marshal_VOID__VOID,
1016 * GtkWindow::keys-changed:
1017 * @window: the window which received the signal
1019 * The ::keys-changed signal gets emitted when the set of accelerators
1020 * or mnemonics that are associated with @window changes.
1022 window_signals[KEYS_CHANGED] =
1023 g_signal_new (I_("keys-changed"),
1024 G_TYPE_FROM_CLASS (gobject_class),
1026 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1028 _gtk_marshal_VOID__VOID,
1036 binding_set = gtk_binding_set_by_class (klass);
1038 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1039 "activate-focus", 0);
1040 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1041 "activate-focus", 0);
1043 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1044 "activate-default", 0);
1045 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1046 "activate-default", 0);
1047 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1048 "activate-default", 0);
1050 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1051 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1052 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1053 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1055 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1056 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1057 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1058 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1062 gtk_window_init (GtkWindow *window)
1064 GtkWindowPrivate *priv;
1066 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1069 priv = window->priv;
1071 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1072 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1074 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1076 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1079 priv->wmclass_name = g_strdup (g_get_prgname ());
1080 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1081 priv->wm_role = NULL;
1082 priv->geometry_info = NULL;
1083 priv->type = GTK_WINDOW_TOPLEVEL;
1084 priv->focus_widget = NULL;
1085 priv->default_widget = NULL;
1086 priv->configure_request_count = 0;
1087 priv->resizable = TRUE;
1088 priv->configure_notify_received = FALSE;
1089 priv->position = GTK_WIN_POS_NONE;
1090 priv->need_default_size = TRUE;
1091 priv->need_default_position = TRUE;
1092 priv->modal = FALSE;
1093 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1094 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1095 priv->decorated = TRUE;
1096 priv->mnemonic_modifier = GDK_MOD1_MASK;
1097 priv->screen = gdk_screen_get_default ();
1099 priv->accept_focus = TRUE;
1100 priv->focus_on_map = TRUE;
1101 priv->deletable = TRUE;
1102 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1103 priv->opacity = 1.0;
1104 priv->startup_id = NULL;
1105 priv->has_resize_grip = TRUE;
1106 priv->mnemonics_visible = TRUE;
1108 g_object_ref_sink (window);
1109 priv->has_user_ref_count = TRUE;
1110 toplevel_list = g_slist_prepend (toplevel_list, window);
1112 g_signal_connect (priv->screen, "composited-changed",
1113 G_CALLBACK (gtk_window_on_composited_changed), window);
1117 gtk_window_set_property (GObject *object,
1119 const GValue *value,
1122 GtkWindow *window = GTK_WINDOW (object);
1123 GtkWindowPrivate *priv = window->priv;
1128 priv->type = g_value_get_enum (value);
1131 gtk_window_set_title (window, g_value_get_string (value));
1134 gtk_window_set_role (window, g_value_get_string (value));
1136 case PROP_STARTUP_ID:
1137 gtk_window_set_startup_id (window, g_value_get_string (value));
1139 case PROP_RESIZABLE:
1140 gtk_window_set_resizable (window, g_value_get_boolean (value));
1143 gtk_window_set_modal (window, g_value_get_boolean (value));
1146 gtk_window_set_position (window, g_value_get_enum (value));
1148 case PROP_DEFAULT_WIDTH:
1149 gtk_window_set_default_size_internal (window,
1150 TRUE, g_value_get_int (value),
1153 case PROP_DEFAULT_HEIGHT:
1154 gtk_window_set_default_size_internal (window,
1156 TRUE, g_value_get_int (value), FALSE);
1158 case PROP_DESTROY_WITH_PARENT:
1159 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1162 gtk_window_set_icon (window,
1163 g_value_get_object (value));
1165 case PROP_ICON_NAME:
1166 gtk_window_set_icon_name (window, g_value_get_string (value));
1169 gtk_window_set_screen (window, g_value_get_object (value));
1171 case PROP_TYPE_HINT:
1172 gtk_window_set_type_hint (window,
1173 g_value_get_enum (value));
1175 case PROP_SKIP_TASKBAR_HINT:
1176 gtk_window_set_skip_taskbar_hint (window,
1177 g_value_get_boolean (value));
1179 case PROP_SKIP_PAGER_HINT:
1180 gtk_window_set_skip_pager_hint (window,
1181 g_value_get_boolean (value));
1183 case PROP_URGENCY_HINT:
1184 gtk_window_set_urgency_hint (window,
1185 g_value_get_boolean (value));
1187 case PROP_ACCEPT_FOCUS:
1188 gtk_window_set_accept_focus (window,
1189 g_value_get_boolean (value));
1191 case PROP_FOCUS_ON_MAP:
1192 gtk_window_set_focus_on_map (window,
1193 g_value_get_boolean (value));
1195 case PROP_DECORATED:
1196 gtk_window_set_decorated (window, g_value_get_boolean (value));
1198 case PROP_DELETABLE:
1199 gtk_window_set_deletable (window, g_value_get_boolean (value));
1202 gtk_window_set_gravity (window, g_value_get_enum (value));
1204 case PROP_TRANSIENT_FOR:
1205 gtk_window_set_transient_for (window, g_value_get_object (value));
1208 gtk_window_set_opacity (window, g_value_get_double (value));
1210 case PROP_HAS_RESIZE_GRIP:
1211 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1213 case PROP_APPLICATION:
1214 gtk_window_set_application (window, g_value_get_object (value));
1216 case PROP_MNEMONICS_VISIBLE:
1217 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1220 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1226 gtk_window_get_property (GObject *object,
1231 GtkWindow *window = GTK_WINDOW (object);
1232 GtkWindowPrivate *priv = window->priv;
1236 GtkWindowGeometryInfo *info;
1238 g_value_set_enum (value, priv->type);
1241 g_value_set_string (value, priv->wm_role);
1244 g_value_set_string (value, priv->title);
1246 case PROP_RESIZABLE:
1247 g_value_set_boolean (value, priv->resizable);
1250 g_value_set_boolean (value, priv->modal);
1253 g_value_set_enum (value, priv->position);
1255 case PROP_DEFAULT_WIDTH:
1256 info = gtk_window_get_geometry_info (window, FALSE);
1258 g_value_set_int (value, -1);
1260 g_value_set_int (value, info->default_width);
1262 case PROP_DEFAULT_HEIGHT:
1263 info = gtk_window_get_geometry_info (window, FALSE);
1265 g_value_set_int (value, -1);
1267 g_value_set_int (value, info->default_height);
1269 case PROP_DESTROY_WITH_PARENT:
1270 g_value_set_boolean (value, priv->destroy_with_parent);
1273 g_value_set_object (value, gtk_window_get_icon (window));
1275 case PROP_ICON_NAME:
1276 g_value_set_string (value, gtk_window_get_icon_name (window));
1279 g_value_set_object (value, priv->screen);
1281 case PROP_IS_ACTIVE:
1282 g_value_set_boolean (value, priv->is_active);
1284 case PROP_HAS_TOPLEVEL_FOCUS:
1285 g_value_set_boolean (value, priv->has_toplevel_focus);
1287 case PROP_TYPE_HINT:
1288 g_value_set_enum (value, priv->type_hint);
1290 case PROP_SKIP_TASKBAR_HINT:
1291 g_value_set_boolean (value,
1292 gtk_window_get_skip_taskbar_hint (window));
1294 case PROP_SKIP_PAGER_HINT:
1295 g_value_set_boolean (value,
1296 gtk_window_get_skip_pager_hint (window));
1298 case PROP_URGENCY_HINT:
1299 g_value_set_boolean (value,
1300 gtk_window_get_urgency_hint (window));
1302 case PROP_ACCEPT_FOCUS:
1303 g_value_set_boolean (value,
1304 gtk_window_get_accept_focus (window));
1306 case PROP_FOCUS_ON_MAP:
1307 g_value_set_boolean (value,
1308 gtk_window_get_focus_on_map (window));
1310 case PROP_DECORATED:
1311 g_value_set_boolean (value, gtk_window_get_decorated (window));
1313 case PROP_DELETABLE:
1314 g_value_set_boolean (value, gtk_window_get_deletable (window));
1317 g_value_set_enum (value, gtk_window_get_gravity (window));
1319 case PROP_TRANSIENT_FOR:
1320 g_value_set_object (value, gtk_window_get_transient_for (window));
1323 g_value_set_double (value, gtk_window_get_opacity (window));
1325 case PROP_HAS_RESIZE_GRIP:
1326 g_value_set_boolean (value, priv->has_resize_grip);
1328 case PROP_RESIZE_GRIP_VISIBLE:
1329 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1331 case PROP_APPLICATION:
1332 g_value_set_object (value, gtk_window_get_application (window));
1334 case PROP_MNEMONICS_VISIBLE:
1335 g_value_set_boolean (value, priv->mnemonics_visible);
1338 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1344 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1346 parent_buildable_iface = g_type_interface_peek_parent (iface);
1347 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1348 iface->parser_finished = gtk_window_buildable_parser_finished;
1349 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1350 iface->custom_finished = gtk_window_buildable_custom_finished;
1354 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1355 GtkBuilder *builder,
1357 const GValue *value)
1359 GtkWindow *window = GTK_WINDOW (buildable);
1360 GtkWindowPrivate *priv = window->priv;
1362 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1363 priv->builder_visible = TRUE;
1365 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1369 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1370 GtkBuilder *builder)
1372 GtkWindow *window = GTK_WINDOW (buildable);
1373 GtkWindowPrivate *priv = window->priv;
1377 if (priv->builder_visible)
1378 gtk_widget_show (GTK_WIDGET (buildable));
1380 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1381 for (l = accels; l; l = l->next)
1383 object = gtk_builder_get_object (builder, l->data);
1386 g_warning ("Unknown accel group %s specified in window %s",
1387 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1390 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1391 GTK_ACCEL_GROUP (object));
1395 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1397 parent_buildable_iface->parser_finished (buildable, builder);
1403 } GSListSubParserData;
1406 window_start_element (GMarkupParseContext *context,
1407 const gchar *element_name,
1408 const gchar **names,
1409 const gchar **values,
1414 GSListSubParserData *data = (GSListSubParserData*)user_data;
1416 if (strcmp (element_name, "group") == 0)
1418 for (i = 0; names[i]; i++)
1420 if (strcmp (names[i], "name") == 0)
1421 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1424 else if (strcmp (element_name, "accel-groups") == 0)
1427 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1432 static const GMarkupParser window_parser =
1434 window_start_element
1438 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1439 GtkBuilder *builder,
1441 const gchar *tagname,
1442 GMarkupParser *parser,
1445 GSListSubParserData *parser_data;
1447 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1448 tagname, parser, data))
1451 if (strcmp (tagname, "accel-groups") == 0)
1453 parser_data = g_slice_new0 (GSListSubParserData);
1454 parser_data->items = NULL;
1455 parser_data->object = G_OBJECT (buildable);
1457 *parser = window_parser;
1458 *data = parser_data;
1466 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1467 GtkBuilder *builder,
1469 const gchar *tagname,
1472 GSListSubParserData *data;
1474 parent_buildable_iface->custom_finished (buildable, builder, child,
1475 tagname, user_data);
1477 if (strcmp (tagname, "accel-groups") != 0)
1480 data = (GSListSubParserData*)user_data;
1482 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1483 data->items, (GDestroyNotify) g_slist_free);
1485 g_slice_free (GSListSubParserData, data);
1490 * @type: type of window
1492 * Creates a new #GtkWindow, which is a toplevel window that can
1493 * contain other widgets. Nearly always, the type of the window should
1494 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1495 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1496 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1497 * dialogs, though in some other toolkits dialogs are called "popups".
1498 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1499 * On X11, popup windows are not controlled by the <link
1500 * linkend="gtk-X11-arch">window manager</link>.
1502 * If you simply want an undecorated window (no window borders), use
1503 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1505 * Return value: a new #GtkWindow.
1508 gtk_window_new (GtkWindowType type)
1510 GtkWindowPrivate *priv;
1513 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1515 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1516 priv = window->priv;
1520 return GTK_WIDGET (window);
1524 * gtk_window_set_title:
1525 * @window: a #GtkWindow
1526 * @title: title of the window
1528 * Sets the title of the #GtkWindow. The title of a window will be
1529 * displayed in its title bar; on the X Window System, the title bar
1530 * is rendered by the <link linkend="gtk-X11-arch">window
1531 * manager</link>, so exactly how the title appears to users may vary
1532 * according to a user's exact configuration. The title should help a
1533 * user distinguish this window from other windows they may have
1534 * open. A good title might include the application name and current
1535 * document filename, for example.
1539 gtk_window_set_title (GtkWindow *window,
1542 GtkWindowPrivate *priv;
1546 g_return_if_fail (GTK_IS_WINDOW (window));
1548 priv = window->priv;
1549 widget = GTK_WIDGET (window);
1551 new_title = g_strdup (title);
1552 g_free (priv->title);
1553 priv->title = new_title;
1555 if (gtk_widget_get_realized (widget))
1557 gdk_window_set_title (gtk_widget_get_window (widget),
1561 g_object_notify (G_OBJECT (window), "title");
1565 * gtk_window_get_title:
1566 * @window: a #GtkWindow
1568 * Retrieves the title of the window. See gtk_window_set_title().
1570 * Return value: the title of the window, or %NULL if none has
1571 * been set explicitely. The returned string is owned by the widget
1572 * and must not be modified or freed.
1574 G_CONST_RETURN gchar *
1575 gtk_window_get_title (GtkWindow *window)
1577 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1579 return window->priv->title;
1583 * gtk_window_set_wmclass:
1584 * @window: a #GtkWindow
1585 * @wmclass_name: window name hint
1586 * @wmclass_class: window class hint
1588 * Don't use this function. It sets the X Window System "class" and
1589 * "name" hints for a window. According to the ICCCM, you should
1590 * always set these to the same value for all windows in an
1591 * application, and GTK+ sets them to that value by default, so calling
1592 * this function is sort of pointless. However, you may want to call
1593 * gtk_window_set_role() on each window in your application, for the
1594 * benefit of the session manager. Setting the role allows the window
1595 * manager to restore window positions when loading a saved session.
1599 gtk_window_set_wmclass (GtkWindow *window,
1600 const gchar *wmclass_name,
1601 const gchar *wmclass_class)
1603 GtkWindowPrivate *priv;
1605 g_return_if_fail (GTK_IS_WINDOW (window));
1607 priv = window->priv;
1609 g_free (priv->wmclass_name);
1610 priv->wmclass_name = g_strdup (wmclass_name);
1612 g_free (priv->wmclass_class);
1613 priv->wmclass_class = g_strdup (wmclass_class);
1615 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1616 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1620 * gtk_window_set_role:
1621 * @window: a #GtkWindow
1622 * @role: unique identifier for the window to be used when restoring a session
1624 * This function is only useful on X11, not with other GTK+ targets.
1626 * In combination with the window title, the window role allows a
1627 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1628 * same" window when an application is restarted. So for example you
1629 * might set the "toolbox" role on your app's toolbox window, so that
1630 * when the user restarts their session, the window manager can put
1631 * the toolbox back in the same place.
1633 * If a window already has a unique title, you don't need to set the
1634 * role, since the WM can use the title to identify the window when
1635 * restoring the session.
1639 gtk_window_set_role (GtkWindow *window,
1642 GtkWindowPrivate *priv;
1645 g_return_if_fail (GTK_IS_WINDOW (window));
1647 priv = window->priv;
1649 new_role = g_strdup (role);
1650 g_free (priv->wm_role);
1651 priv->wm_role = new_role;
1653 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1654 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1657 g_object_notify (G_OBJECT (window), "role");
1661 * gtk_window_set_startup_id:
1662 * @window: a #GtkWindow
1663 * @startup_id: a string with startup-notification identifier
1665 * Startup notification identifiers are used by desktop environment to
1666 * track application startup, to provide user feedback and other
1667 * features. This function changes the corresponding property on the
1668 * underlying GdkWindow. Normally, startup identifier is managed
1669 * automatically and you should only use this function in special cases
1670 * like transferring focus from other processes. You should use this
1671 * function before calling gtk_window_present() or any equivalent
1672 * function generating a window map event.
1674 * This function is only useful on X11, not with other GTK+ targets.
1679 gtk_window_set_startup_id (GtkWindow *window,
1680 const gchar *startup_id)
1682 GtkWindowPrivate *priv;
1685 g_return_if_fail (GTK_IS_WINDOW (window));
1687 priv = window->priv;
1688 widget = GTK_WIDGET (window);
1690 g_free (priv->startup_id);
1691 priv->startup_id = g_strdup (startup_id);
1693 if (gtk_widget_get_realized (widget))
1695 GdkWindow *gdk_window;
1696 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1698 gdk_window = gtk_widget_get_window (widget);
1700 #ifdef GDK_WINDOWING_X11
1701 if (timestamp != GDK_CURRENT_TIME)
1702 gdk_x11_window_set_user_time (gdk_window, timestamp);
1705 /* Here we differentiate real and "fake" startup notification IDs,
1706 * constructed on purpose just to pass interaction timestamp
1708 if (startup_id_is_fake (priv->startup_id))
1709 gtk_window_present_with_time (window, timestamp);
1712 gdk_window_set_startup_id (gdk_window,
1715 /* If window is mapped, terminate the startup-notification too */
1716 if (gtk_widget_get_mapped (widget) &&
1717 !disable_startup_notification)
1718 gdk_notify_startup_complete_with_id (priv->startup_id);
1722 g_object_notify (G_OBJECT (window), "startup-id");
1726 * gtk_window_get_role:
1727 * @window: a #GtkWindow
1729 * Returns the role of the window. See gtk_window_set_role() for
1730 * further explanation.
1732 * Return value: the role of the window if set, or %NULL. The
1733 * returned is owned by the widget and must not be modified
1736 G_CONST_RETURN gchar *
1737 gtk_window_get_role (GtkWindow *window)
1739 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1741 return window->priv->wm_role;
1745 * gtk_window_set_focus:
1746 * @window: a #GtkWindow
1747 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1748 * any focus widget for the toplevel window.
1750 * If @focus is not the current focus widget, and is focusable, sets
1751 * it as the focus widget for the window. If @focus is %NULL, unsets
1752 * the focus widget for this window. To set the focus to a particular
1753 * widget in the toplevel, it is usually more convenient to use
1754 * gtk_widget_grab_focus() instead of this function.
1757 gtk_window_set_focus (GtkWindow *window,
1760 GtkWindowPrivate *priv;
1763 g_return_if_fail (GTK_IS_WINDOW (window));
1765 priv = window->priv;
1769 g_return_if_fail (GTK_IS_WIDGET (focus));
1770 g_return_if_fail (gtk_widget_get_can_focus (focus));
1774 gtk_widget_grab_focus (focus);
1777 /* Clear the existing focus chain, so that when we focus into
1778 * the window again, we start at the beginnning.
1780 GtkWidget *widget = priv->focus_widget;
1783 while ((parent = gtk_widget_get_parent (widget)))
1786 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1790 _gtk_window_internal_set_focus (window, NULL);
1795 _gtk_window_internal_set_focus (GtkWindow *window,
1798 GtkWindowPrivate *priv;
1800 g_return_if_fail (GTK_IS_WINDOW (window));
1802 priv = window->priv;
1804 if ((priv->focus_widget != focus) ||
1805 (focus && !gtk_widget_has_focus (focus)))
1806 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1810 * gtk_window_set_default:
1811 * @window: a #GtkWindow
1812 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1813 * default widget for the toplevel.
1815 * The default widget is the widget that's activated when the user
1816 * presses Enter in a dialog (for example). This function sets or
1817 * unsets the default widget for a #GtkWindow about. When setting
1818 * (rather than unsetting) the default widget it's generally easier to
1819 * call gtk_widget_grab_focus() on the widget. Before making a widget
1820 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1821 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1824 gtk_window_set_default (GtkWindow *window,
1825 GtkWidget *default_widget)
1827 GtkWindowPrivate *priv;
1829 g_return_if_fail (GTK_IS_WINDOW (window));
1831 priv = window->priv;
1834 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1836 if (priv->default_widget != default_widget)
1838 GtkWidget *old_default_widget = NULL;
1841 g_object_ref (default_widget);
1843 if (priv->default_widget)
1845 old_default_widget = priv->default_widget;
1847 if (priv->focus_widget != priv->default_widget ||
1848 !gtk_widget_get_receives_default (priv->default_widget))
1849 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1851 gtk_widget_queue_draw (priv->default_widget);
1854 priv->default_widget = default_widget;
1856 if (priv->default_widget)
1858 if (priv->focus_widget == NULL ||
1859 !gtk_widget_get_receives_default (priv->focus_widget))
1860 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1862 gtk_widget_queue_draw (priv->default_widget);
1865 if (old_default_widget)
1866 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1870 g_object_notify (G_OBJECT (default_widget), "has-default");
1871 g_object_unref (default_widget);
1877 * gtk_window_get_default_widget:
1878 * @window: a #GtkWindow
1880 * Returns the default widget for @window. See gtk_window_set_default()
1883 * Returns: (transfer none): the default widget, or %NULL if there is none.
1888 gtk_window_get_default_widget (GtkWindow *window)
1890 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1892 return window->priv->default_widget;
1896 handle_keys_changed (gpointer data)
1898 GtkWindow *window = GTK_WINDOW (data);
1899 GtkWindowPrivate *priv = window->priv;
1901 if (priv->keys_changed_handler)
1903 g_source_remove (priv->keys_changed_handler);
1904 priv->keys_changed_handler = 0;
1907 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1913 gtk_window_notify_keys_changed (GtkWindow *window)
1915 GtkWindowPrivate *priv = window->priv;
1917 if (!priv->keys_changed_handler)
1918 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1922 * gtk_window_add_accel_group:
1923 * @window: window to attach accelerator group to
1924 * @accel_group: a #GtkAccelGroup
1926 * Associate @accel_group with @window, such that calling
1927 * gtk_accel_groups_activate() on @window will activate accelerators
1931 gtk_window_add_accel_group (GtkWindow *window,
1932 GtkAccelGroup *accel_group)
1934 g_return_if_fail (GTK_IS_WINDOW (window));
1935 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1937 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1938 g_signal_connect_object (accel_group, "accel-changed",
1939 G_CALLBACK (gtk_window_notify_keys_changed),
1940 window, G_CONNECT_SWAPPED);
1941 gtk_window_notify_keys_changed (window);
1945 * gtk_window_remove_accel_group:
1946 * @window: a #GtkWindow
1947 * @accel_group: a #GtkAccelGroup
1949 * Reverses the effects of gtk_window_add_accel_group().
1952 gtk_window_remove_accel_group (GtkWindow *window,
1953 GtkAccelGroup *accel_group)
1955 g_return_if_fail (GTK_IS_WINDOW (window));
1956 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1958 g_signal_handlers_disconnect_by_func (accel_group,
1959 gtk_window_notify_keys_changed,
1961 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1962 gtk_window_notify_keys_changed (window);
1965 static GtkMnemonicHash *
1966 gtk_window_get_mnemonic_hash (GtkWindow *window,
1969 GtkWindowPrivate *private = window->priv;
1971 if (!private->mnemonic_hash && create)
1972 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1974 return private->mnemonic_hash;
1978 * gtk_window_add_mnemonic:
1979 * @window: a #GtkWindow
1980 * @keyval: the mnemonic
1981 * @target: the widget that gets activated by the mnemonic
1983 * Adds a mnemonic to this window.
1986 gtk_window_add_mnemonic (GtkWindow *window,
1990 g_return_if_fail (GTK_IS_WINDOW (window));
1991 g_return_if_fail (GTK_IS_WIDGET (target));
1993 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1995 gtk_window_notify_keys_changed (window);
1999 * gtk_window_remove_mnemonic:
2000 * @window: a #GtkWindow
2001 * @keyval: the mnemonic
2002 * @target: the widget that gets activated by the mnemonic
2004 * Removes a mnemonic from this window.
2007 gtk_window_remove_mnemonic (GtkWindow *window,
2011 g_return_if_fail (GTK_IS_WINDOW (window));
2012 g_return_if_fail (GTK_IS_WIDGET (target));
2014 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2016 gtk_window_notify_keys_changed (window);
2020 * gtk_window_mnemonic_activate:
2021 * @window: a #GtkWindow
2022 * @keyval: the mnemonic
2023 * @modifier: the modifiers
2024 * @returns: %TRUE if the activation is done.
2026 * Activates the targets associated with the mnemonic.
2029 gtk_window_mnemonic_activate (GtkWindow *window,
2031 GdkModifierType modifier)
2033 GtkWindowPrivate *priv;
2035 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2037 priv = window->priv;
2039 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2041 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2043 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2050 * gtk_window_set_mnemonic_modifier:
2051 * @window: a #GtkWindow
2052 * @modifier: the modifier mask used to activate
2053 * mnemonics on this window.
2055 * Sets the mnemonic modifier for this window.
2058 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2059 GdkModifierType modifier)
2061 GtkWindowPrivate *priv;
2063 g_return_if_fail (GTK_IS_WINDOW (window));
2064 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2066 priv = window->priv;
2068 priv->mnemonic_modifier = modifier;
2069 gtk_window_notify_keys_changed (window);
2073 * gtk_window_get_mnemonic_modifier:
2074 * @window: a #GtkWindow
2076 * Returns the mnemonic modifier for this window. See
2077 * gtk_window_set_mnemonic_modifier().
2079 * Return value: the modifier mask used to activate
2080 * mnemonics on this window.
2083 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2085 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2087 return window->priv->mnemonic_modifier;
2091 * gtk_window_set_position:
2092 * @window: a #GtkWindow.
2093 * @position: a position constraint.
2095 * Sets a position constraint for this window. If the old or new
2096 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2097 * the window to be repositioned to satisfy the new constraint.
2100 gtk_window_set_position (GtkWindow *window,
2101 GtkWindowPosition position)
2103 GtkWindowPrivate *priv;
2105 g_return_if_fail (GTK_IS_WINDOW (window));
2107 priv = window->priv;
2109 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2110 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2112 GtkWindowGeometryInfo *info;
2114 info = gtk_window_get_geometry_info (window, TRUE);
2116 /* this flag causes us to re-request the CENTER_ALWAYS
2117 * constraint in gtk_window_move_resize(), see
2118 * comment in that function.
2120 info->position_constraints_changed = TRUE;
2122 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2125 priv->position = position;
2127 g_object_notify (G_OBJECT (window), "window-position");
2131 * gtk_window_activate_focus:
2132 * @window: a #GtkWindow
2134 * Activates the current focused widget within the window.
2136 * Return value: %TRUE if a widget got activated.
2139 gtk_window_activate_focus (GtkWindow *window)
2141 GtkWindowPrivate *priv;
2143 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2145 priv = window->priv;
2147 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2148 return gtk_widget_activate (priv->focus_widget);
2154 * gtk_window_get_focus:
2155 * @window: a #GtkWindow
2157 * Retrieves the current focused widget within the window.
2158 * Note that this is the widget that would have the focus
2159 * if the toplevel window focused; if the toplevel window
2160 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2161 * not be %TRUE for the widget.
2163 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2166 gtk_window_get_focus (GtkWindow *window)
2168 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2170 return window->priv->focus_widget;
2174 * gtk_window_activate_default:
2175 * @window: a #GtkWindow
2177 * Activates the default widget for the window, unless the current
2178 * focused widget has been configured to receive the default action
2179 * (see gtk_widget_set_receives_default()), in which case the
2180 * focused widget is activated.
2182 * Return value: %TRUE if a widget got activated.
2185 gtk_window_activate_default (GtkWindow *window)
2187 GtkWindowPrivate *priv;
2189 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2191 priv = window->priv;
2193 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2194 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2195 return gtk_widget_activate (priv->default_widget);
2196 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2197 return gtk_widget_activate (priv->focus_widget);
2203 * gtk_window_set_modal:
2204 * @window: a #GtkWindow
2205 * @modal: whether the window is modal
2207 * Sets a window modal or non-modal. Modal windows prevent interaction
2208 * with other windows in the same application. To keep modal dialogs
2209 * on top of main application windows, use
2210 * gtk_window_set_transient_for() to make the dialog transient for the
2211 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2212 * will then disallow lowering the dialog below the parent.
2217 gtk_window_set_modal (GtkWindow *window,
2220 GtkWindowPrivate *priv;
2223 g_return_if_fail (GTK_IS_WINDOW (window));
2225 priv = window->priv;
2227 modal = modal != FALSE;
2228 if (priv->modal == modal)
2231 priv->modal = modal;
2232 widget = GTK_WIDGET (window);
2234 /* adjust desired modality state */
2235 if (gtk_widget_get_realized (widget))
2238 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2240 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2243 if (gtk_widget_get_visible (widget))
2246 gtk_grab_add (widget);
2248 gtk_grab_remove (widget);
2251 g_object_notify (G_OBJECT (window), "modal");
2255 * gtk_window_get_modal:
2256 * @window: a #GtkWindow
2258 * Returns whether the window is modal. See gtk_window_set_modal().
2260 * Return value: %TRUE if the window is set to be modal and
2261 * establishes a grab when shown
2264 gtk_window_get_modal (GtkWindow *window)
2266 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2268 return window->priv->modal;
2272 * gtk_window_list_toplevels:
2274 * Returns a list of all existing toplevel windows. The widgets
2275 * in the list are not individually referenced. If you want
2276 * to iterate through the list and perform actions involving
2277 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2278 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2279 * then unref all the widgets afterwards.
2281 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2284 gtk_window_list_toplevels (void)
2289 for (slist = toplevel_list; slist; slist = slist->next)
2290 list = g_list_prepend (list, slist->data);
2296 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2298 GList *embedded_windows;
2300 g_return_if_fail (GTK_IS_WINDOW (window));
2302 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2303 if (embedded_windows)
2304 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2305 embedded_windows = g_list_prepend (embedded_windows,
2306 GUINT_TO_POINTER (xid));
2308 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2311 (GDestroyNotify) g_list_free : NULL);
2315 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2317 GList *embedded_windows;
2320 g_return_if_fail (GTK_IS_WINDOW (window));
2322 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2323 if (embedded_windows)
2324 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2326 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2329 embedded_windows = g_list_remove_link (embedded_windows, node);
2330 g_list_free_1 (node);
2333 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2336 (GDestroyNotify) g_list_free : NULL);
2340 gtk_window_dispose (GObject *object)
2342 GtkWindow *window = GTK_WINDOW (object);
2344 gtk_window_set_focus (window, NULL);
2345 gtk_window_set_default (window, NULL);
2347 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2351 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2353 gtk_widget_destroy (GTK_WIDGET (child));
2357 connect_parent_destroyed (GtkWindow *window)
2359 GtkWindowPrivate *priv = window->priv;
2361 if (priv->transient_parent)
2363 g_signal_connect (priv->transient_parent,
2365 G_CALLBACK (parent_destroyed_callback),
2371 disconnect_parent_destroyed (GtkWindow *window)
2373 GtkWindowPrivate *priv = window->priv;
2375 if (priv->transient_parent)
2377 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2378 parent_destroyed_callback,
2384 gtk_window_transient_parent_realized (GtkWidget *parent,
2387 if (gtk_widget_get_realized (window))
2388 gdk_window_set_transient_for (gtk_widget_get_window (window),
2389 gtk_widget_get_window (parent));
2393 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2396 if (gtk_widget_get_realized (window))
2397 gdk_property_delete (gtk_widget_get_window (window),
2398 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2402 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2406 gtk_window_set_screen (window, parent->priv->screen);
2410 gtk_window_unset_transient_for (GtkWindow *window)
2412 GtkWindowPrivate *priv = window->priv;
2414 if (priv->transient_parent)
2416 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2417 gtk_window_transient_parent_realized,
2419 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2420 gtk_window_transient_parent_unrealized,
2422 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2423 gtk_window_transient_parent_screen_changed,
2425 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2426 gtk_widget_destroyed,
2427 &priv->transient_parent);
2429 if (priv->destroy_with_parent)
2430 disconnect_parent_destroyed (window);
2432 priv->transient_parent = NULL;
2434 if (priv->transient_parent_group)
2436 priv->transient_parent_group = FALSE;
2437 gtk_window_group_remove_window (priv->group,
2444 * gtk_window_set_transient_for:
2445 * @window: a #GtkWindow
2446 * @parent: (allow-none): parent window, or %NULL
2448 * Dialog windows should be set transient for the main application
2449 * window they were spawned from. This allows <link
2450 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2451 * dialog on top of the main window, or center the dialog over the
2452 * main window. gtk_dialog_new_with_buttons() and other convenience
2453 * functions in GTK+ will sometimes call
2454 * gtk_window_set_transient_for() on your behalf.
2456 * Passing %NULL for @parent unsets the current transient window.
2458 * On Windows, this function puts the child window on top of the parent,
2459 * much as the window manager would have done on X.
2462 gtk_window_set_transient_for (GtkWindow *window,
2465 GtkWindowPrivate *priv;
2467 g_return_if_fail (GTK_IS_WINDOW (window));
2468 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2469 g_return_if_fail (window != parent);
2471 priv = window->priv;
2473 if (priv->transient_parent)
2475 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2476 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2477 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2478 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2479 GTK_WIDGET (window));
2481 gtk_window_unset_transient_for (window);
2484 priv->transient_parent = parent;
2488 g_signal_connect (parent, "destroy",
2489 G_CALLBACK (gtk_widget_destroyed),
2490 &priv->transient_parent);
2491 g_signal_connect (parent, "realize",
2492 G_CALLBACK (gtk_window_transient_parent_realized),
2494 g_signal_connect (parent, "unrealize",
2495 G_CALLBACK (gtk_window_transient_parent_unrealized),
2497 g_signal_connect (parent, "notify::screen",
2498 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2501 gtk_window_set_screen (window, parent->priv->screen);
2503 if (priv->destroy_with_parent)
2504 connect_parent_destroyed (window);
2506 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2507 gtk_widget_get_realized (GTK_WIDGET (parent)))
2508 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2509 GTK_WIDGET (window));
2511 if (parent->priv->group)
2513 gtk_window_group_add_window (parent->priv->group, window);
2514 priv->transient_parent_group = TRUE;
2520 * gtk_window_get_transient_for:
2521 * @window: a #GtkWindow
2523 * Fetches the transient parent for this window. See
2524 * gtk_window_set_transient_for().
2526 * Return value: (transfer none): the transient parent for this window, or %NULL
2527 * if no transient parent has been set.
2530 gtk_window_get_transient_for (GtkWindow *window)
2532 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2534 return window->priv->transient_parent;
2538 * gtk_window_set_opacity:
2539 * @window: a #GtkWindow
2540 * @opacity: desired opacity, between 0 and 1
2542 * Request the windowing system to make @window partially transparent,
2543 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2544 * of the opacity parameter are clamped to the [0,1] range.) On X11
2545 * this has any effect only on X screens with a compositing manager
2546 * running. See gtk_widget_is_composited(). On Windows it should work
2549 * Note that setting a window's opacity after the window has been
2550 * shown causes it to flicker once on Windows.
2555 gtk_window_set_opacity (GtkWindow *window,
2558 GtkWindowPrivate *priv;
2560 g_return_if_fail (GTK_IS_WINDOW (window));
2562 priv = window->priv;
2566 else if (opacity > 1.0)
2569 priv->opacity_set = TRUE;
2570 priv->opacity = opacity;
2572 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2573 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2578 * gtk_window_get_opacity:
2579 * @window: a #GtkWindow
2581 * Fetches the requested opacity for this window. See
2582 * gtk_window_set_opacity().
2584 * Return value: the requested opacity for this window.
2589 gtk_window_get_opacity (GtkWindow *window)
2591 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2593 return window->priv->opacity;
2597 * gtk_window_get_application:
2598 * @window: a #GtkWindow
2600 * Gets the #GtkApplication associated with the window (if any).
2602 * Return value: a #GtkApplication, or %NULL
2607 gtk_window_get_application (GtkWindow *window)
2609 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2611 return window->priv->application;
2615 gtk_window_release_application (GtkWindow *window)
2617 if (window->priv->application)
2619 GtkApplication *application;
2621 /* steal reference into temp variable */
2622 application = window->priv->application;
2623 window->priv->application = NULL;
2625 gtk_application_remove_window (application, window);
2626 g_object_unref (application);
2631 * gtk_window_set_application:
2632 * @window: a #GtkWindow
2633 * @application: a #GtkApplication, or %NULL
2635 * Sets or unsets the #GtkApplication associated with the window.
2637 * The application will be kept alive for at least as long as the window
2643 gtk_window_set_application (GtkWindow *window,
2644 GtkApplication *application)
2646 GtkWindowPrivate *priv;
2648 g_return_if_fail (GTK_IS_WINDOW (window));
2650 priv = window->priv;
2651 if (priv->application != application)
2653 gtk_window_release_application (window);
2655 priv->application = application;
2657 if (priv->application != NULL)
2659 g_object_ref (priv->application);
2661 gtk_application_add_window (priv->application, window);
2664 g_object_notify (G_OBJECT (window), "application");
2669 * gtk_window_set_type_hint:
2670 * @window: a #GtkWindow
2671 * @hint: the window type
2673 * By setting the type hint for the window, you allow the window
2674 * manager to decorate and handle the window in a way which is
2675 * suitable to the function of the window in your application.
2677 * This function should be called before the window becomes visible.
2679 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2680 * will sometimes call gtk_window_set_type_hint() on your behalf.
2684 gtk_window_set_type_hint (GtkWindow *window,
2685 GdkWindowTypeHint hint)
2687 GtkWindowPrivate *priv;
2689 g_return_if_fail (GTK_IS_WINDOW (window));
2690 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2692 priv = window->priv;
2694 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2695 priv->gdk_type_hint = hint;
2697 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2699 priv->reset_type_hint = TRUE;
2700 priv->type_hint = hint;
2704 * gtk_window_get_type_hint:
2705 * @window: a #GtkWindow
2707 * Gets the type hint for this window. See gtk_window_set_type_hint().
2709 * Return value: the type hint for @window.
2712 gtk_window_get_type_hint (GtkWindow *window)
2714 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2716 return window->priv->type_hint;
2720 * gtk_window_set_skip_taskbar_hint:
2721 * @window: a #GtkWindow
2722 * @setting: %TRUE to keep this window from appearing in the task bar
2724 * Windows may set a hint asking the desktop environment not to display
2725 * the window in the task bar. This function sets this hint.
2730 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2733 GtkWindowPrivate *priv;
2735 g_return_if_fail (GTK_IS_WINDOW (window));
2737 priv = window->priv;
2739 setting = setting != FALSE;
2741 if (priv->skips_taskbar != setting)
2743 priv->skips_taskbar = setting;
2744 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2745 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2746 priv->skips_taskbar);
2747 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2752 * gtk_window_get_skip_taskbar_hint:
2753 * @window: a #GtkWindow
2755 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2757 * Return value: %TRUE if window shouldn't be in taskbar
2762 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2764 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2766 return window->priv->skips_taskbar;
2770 * gtk_window_set_skip_pager_hint:
2771 * @window: a #GtkWindow
2772 * @setting: %TRUE to keep this window from appearing in the pager
2774 * Windows may set a hint asking the desktop environment not to display
2775 * the window in the pager. This function sets this hint.
2776 * (A "pager" is any desktop navigation tool such as a workspace
2777 * switcher that displays a thumbnail representation of the windows
2783 gtk_window_set_skip_pager_hint (GtkWindow *window,
2786 GtkWindowPrivate *priv;
2788 g_return_if_fail (GTK_IS_WINDOW (window));
2790 priv = window->priv;
2792 setting = setting != FALSE;
2794 if (priv->skips_pager != setting)
2796 priv->skips_pager = setting;
2797 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2798 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2800 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2805 * gtk_window_get_skip_pager_hint:
2806 * @window: a #GtkWindow
2808 * Gets the value set by gtk_window_set_skip_pager_hint().
2810 * Return value: %TRUE if window shouldn't be in pager
2815 gtk_window_get_skip_pager_hint (GtkWindow *window)
2817 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2819 return window->priv->skips_pager;
2823 * gtk_window_set_urgency_hint:
2824 * @window: a #GtkWindow
2825 * @setting: %TRUE to mark this window as urgent
2827 * Windows may set a hint asking the desktop environment to draw
2828 * the users attention to the window. This function sets this hint.
2833 gtk_window_set_urgency_hint (GtkWindow *window,
2836 GtkWindowPrivate *priv;
2838 g_return_if_fail (GTK_IS_WINDOW (window));
2840 priv = window->priv;
2842 setting = setting != FALSE;
2844 if (priv->urgent != setting)
2846 priv->urgent = setting;
2847 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2848 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2850 g_object_notify (G_OBJECT (window), "urgency-hint");
2855 * gtk_window_get_urgency_hint:
2856 * @window: a #GtkWindow
2858 * Gets the value set by gtk_window_set_urgency_hint()
2860 * Return value: %TRUE if window is urgent
2865 gtk_window_get_urgency_hint (GtkWindow *window)
2867 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2869 return window->priv->urgent;
2873 * gtk_window_set_accept_focus:
2874 * @window: a #GtkWindow
2875 * @setting: %TRUE to let this window receive input focus
2877 * Windows may set a hint asking the desktop environment not to receive
2878 * the input focus. This function sets this hint.
2883 gtk_window_set_accept_focus (GtkWindow *window,
2886 GtkWindowPrivate *priv;
2888 g_return_if_fail (GTK_IS_WINDOW (window));
2890 priv = window->priv;
2892 setting = setting != FALSE;
2894 if (priv->accept_focus != setting)
2896 priv->accept_focus = setting;
2897 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2898 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2899 priv->accept_focus);
2900 g_object_notify (G_OBJECT (window), "accept-focus");
2905 * gtk_window_get_accept_focus:
2906 * @window: a #GtkWindow
2908 * Gets the value set by gtk_window_set_accept_focus().
2910 * Return value: %TRUE if window should receive the input focus
2915 gtk_window_get_accept_focus (GtkWindow *window)
2917 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2919 return window->priv->accept_focus;
2923 * gtk_window_set_focus_on_map:
2924 * @window: a #GtkWindow
2925 * @setting: %TRUE to let this window receive input focus on map
2927 * Windows may set a hint asking the desktop environment not to receive
2928 * the input focus when the window is mapped. This function sets this
2934 gtk_window_set_focus_on_map (GtkWindow *window,
2937 GtkWindowPrivate *priv;
2939 g_return_if_fail (GTK_IS_WINDOW (window));
2941 priv = window->priv;
2943 setting = setting != FALSE;
2945 if (priv->focus_on_map != setting)
2947 priv->focus_on_map = setting;
2948 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2949 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2950 priv->focus_on_map);
2951 g_object_notify (G_OBJECT (window), "focus-on-map");
2956 * gtk_window_get_focus_on_map:
2957 * @window: a #GtkWindow
2959 * Gets the value set by gtk_window_set_focus_on_map().
2961 * Return value: %TRUE if window should receive the input focus when
2967 gtk_window_get_focus_on_map (GtkWindow *window)
2969 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2971 return window->priv->focus_on_map;
2975 * gtk_window_set_destroy_with_parent:
2976 * @window: a #GtkWindow
2977 * @setting: whether to destroy @window with its transient parent
2979 * If @setting is %TRUE, then destroying the transient parent of @window
2980 * will also destroy @window itself. This is useful for dialogs that
2981 * shouldn't persist beyond the lifetime of the main window they're
2982 * associated with, for example.
2985 gtk_window_set_destroy_with_parent (GtkWindow *window,
2988 GtkWindowPrivate *priv;
2990 g_return_if_fail (GTK_IS_WINDOW (window));
2992 priv = window->priv;
2994 if (priv->destroy_with_parent == (setting != FALSE))
2997 if (priv->destroy_with_parent)
2999 disconnect_parent_destroyed (window);
3003 connect_parent_destroyed (window);
3006 priv->destroy_with_parent = setting;
3008 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3012 * gtk_window_get_destroy_with_parent:
3013 * @window: a #GtkWindow
3015 * Returns whether the window will be destroyed with its transient parent. See
3016 * gtk_window_set_destroy_with_parent ().
3018 * Return value: %TRUE if the window will be destroyed with its transient parent.
3021 gtk_window_get_destroy_with_parent (GtkWindow *window)
3023 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3025 return window->priv->destroy_with_parent;
3028 static GtkWindowGeometryInfo*
3029 gtk_window_get_geometry_info (GtkWindow *window,
3032 GtkWindowPrivate *priv = window->priv;
3033 GtkWindowGeometryInfo *info;
3035 info = priv->geometry_info;
3036 if (!info && create)
3038 info = g_new0 (GtkWindowGeometryInfo, 1);
3040 info->default_width = -1;
3041 info->default_height = -1;
3042 info->resize_width = -1;
3043 info->resize_height = -1;
3044 info->initial_x = 0;
3045 info->initial_y = 0;
3046 info->initial_pos_set = FALSE;
3047 info->default_is_geometry = FALSE;
3048 info->position_constraints_changed = FALSE;
3049 info->last.configure_request.x = 0;
3050 info->last.configure_request.y = 0;
3051 info->last.configure_request.width = -1;
3052 info->last.configure_request.height = -1;
3053 info->widget = NULL;
3055 priv->geometry_info = info;
3062 * gtk_window_set_geometry_hints:
3063 * @window: a #GtkWindow
3064 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3065 * @geometry: (allow-none): struct containing geometry information or %NULL
3066 * @geom_mask: mask indicating which struct fields should be paid attention to
3068 * This function sets up hints about how a window can be resized by
3069 * the user. You can set a minimum and maximum size; allowed resize
3070 * increments (e.g. for xterm, you can only resize by the size of a
3071 * character); aspect ratios; and more. See the #GdkGeometry struct.
3075 gtk_window_set_geometry_hints (GtkWindow *window,
3076 GtkWidget *geometry_widget,
3077 GdkGeometry *geometry,
3078 GdkWindowHints geom_mask)
3080 GtkWindowGeometryInfo *info;
3082 g_return_if_fail (GTK_IS_WINDOW (window));
3083 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3085 info = gtk_window_get_geometry_info (window, TRUE);
3088 g_signal_handlers_disconnect_by_func (info->widget,
3089 gtk_widget_destroyed,
3092 info->widget = geometry_widget;
3094 g_signal_connect (geometry_widget, "destroy",
3095 G_CALLBACK (gtk_widget_destroyed),
3099 info->geometry = *geometry;
3101 /* We store gravity in priv->gravity not in the hints. */
3102 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3104 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3106 gtk_window_set_gravity (window, geometry->win_gravity);
3109 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3113 * gtk_window_set_decorated:
3114 * @window: a #GtkWindow
3115 * @setting: %TRUE to decorate the window
3117 * By default, windows are decorated with a title bar, resize
3118 * controls, etc. Some <link linkend="gtk-X11-arch">window
3119 * managers</link> allow GTK+ to disable these decorations, creating a
3120 * borderless window. If you set the decorated property to %FALSE
3121 * using this function, GTK+ will do its best to convince the window
3122 * manager not to decorate the window. Depending on the system, this
3123 * function may not have any effect when called on a window that is
3124 * already visible, so you should call it before calling gtk_widget_show().
3126 * On Windows, this function always works, since there's no window manager
3131 gtk_window_set_decorated (GtkWindow *window,
3134 GtkWindowPrivate *priv;
3135 GdkWindow *gdk_window;
3137 g_return_if_fail (GTK_IS_WINDOW (window));
3139 priv = window->priv;
3141 setting = setting != FALSE;
3143 if (setting == priv->decorated)
3146 priv->decorated = setting;
3148 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3151 if (priv->decorated)
3152 gdk_window_set_decorations (gdk_window,
3155 gdk_window_set_decorations (gdk_window,
3159 g_object_notify (G_OBJECT (window), "decorated");
3163 * gtk_window_get_decorated:
3164 * @window: a #GtkWindow
3166 * Returns whether the window has been set to have decorations
3167 * such as a title bar via gtk_window_set_decorated().
3169 * Return value: %TRUE if the window has been set to have decorations
3172 gtk_window_get_decorated (GtkWindow *window)
3174 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3176 return window->priv->decorated;
3180 * gtk_window_set_deletable:
3181 * @window: a #GtkWindow
3182 * @setting: %TRUE to decorate the window as deletable
3184 * By default, windows have a close button in the window frame. Some
3185 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3186 * disable this button. If you set the deletable property to %FALSE
3187 * using this function, GTK+ will do its best to convince the window
3188 * manager not to show a close button. Depending on the system, this
3189 * function may not have any effect when called on a window that is
3190 * already visible, so you should call it before calling gtk_window_show().
3192 * On Windows, this function always works, since there's no window manager
3198 gtk_window_set_deletable (GtkWindow *window,
3201 GtkWindowPrivate *priv;
3202 GdkWindow *gdk_window;
3204 g_return_if_fail (GTK_IS_WINDOW (window));
3206 priv = window->priv;
3208 setting = setting != FALSE;
3210 if (setting == priv->deletable)
3213 priv->deletable = setting;
3215 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3218 if (priv->deletable)
3219 gdk_window_set_functions (gdk_window,
3222 gdk_window_set_functions (gdk_window,
3223 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3226 g_object_notify (G_OBJECT (window), "deletable");
3230 * gtk_window_get_deletable:
3231 * @window: a #GtkWindow
3233 * Returns whether the window has been set to have a close button
3234 * via gtk_window_set_deletable().
3236 * Return value: %TRUE if the window has been set to have a close button
3241 gtk_window_get_deletable (GtkWindow *window)
3243 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3245 return window->priv->deletable;
3248 static GtkWindowIconInfo*
3249 get_icon_info (GtkWindow *window)
3251 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3255 free_icon_info (GtkWindowIconInfo *info)
3257 g_free (info->icon_name);
3258 g_slice_free (GtkWindowIconInfo, info);
3262 static GtkWindowIconInfo*
3263 ensure_icon_info (GtkWindow *window)
3265 GtkWindowIconInfo *info;
3267 info = get_icon_info (window);
3271 info = g_slice_new0 (GtkWindowIconInfo);
3272 g_object_set_qdata_full (G_OBJECT (window),
3273 quark_gtk_window_icon_info,
3275 (GDestroyNotify)free_icon_info);
3282 icon_list_from_theme (GtkWidget *widget,
3287 GtkIconTheme *icon_theme;
3292 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3294 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3297 for (i = 0; sizes[i]; i++)
3300 * We need an EWMH extension to handle scalable icons
3301 * by passing their name to the WM. For now just use a
3305 icon = gtk_icon_theme_load_icon (icon_theme, name,
3308 icon = gtk_icon_theme_load_icon (icon_theme, name,
3311 list = g_list_append (list, icon);
3321 gtk_window_realize_icon (GtkWindow *window)
3323 GtkWindowPrivate *priv = window->priv;
3325 GtkWindowIconInfo *info;
3326 GdkWindow *gdk_window;
3329 widget = GTK_WIDGET (window);
3330 gdk_window = gtk_widget_get_window (widget);
3332 g_return_if_fail (gdk_window != NULL);
3334 /* no point setting an icon on override-redirect */
3335 if (priv->type == GTK_WINDOW_POPUP)
3340 info = ensure_icon_info (window);
3345 info->using_default_icon = FALSE;
3346 info->using_parent_icon = FALSE;
3347 info->using_themed_icon = FALSE;
3349 icon_list = info->icon_list;
3351 /* Look up themed icon */
3352 if (icon_list == NULL && info->icon_name)
3354 icon_list = icon_list_from_theme (widget, info->icon_name);
3356 info->using_themed_icon = TRUE;
3359 /* Inherit from transient parent */
3360 if (icon_list == NULL && priv->transient_parent)
3362 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3364 info->using_parent_icon = TRUE;
3367 /* Inherit from default */
3368 if (icon_list == NULL)
3370 icon_list = default_icon_list;
3372 info->using_default_icon = TRUE;
3375 /* Look up themed icon */
3376 if (icon_list == NULL && default_icon_name)
3378 icon_list = icon_list_from_theme (widget, default_icon_name);
3379 info->using_default_icon = TRUE;
3380 info->using_themed_icon = TRUE;
3383 info->realized = TRUE;
3385 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3387 if (info->using_themed_icon)
3389 GtkIconTheme *icon_theme;
3391 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3392 g_list_free (icon_list);
3394 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3395 g_signal_connect (icon_theme, "changed",
3396 G_CALLBACK (update_themed_icon), window);
3401 gtk_window_unrealize_icon (GtkWindow *window)
3403 GtkWindowIconInfo *info;
3405 info = get_icon_info (window);
3410 if (info->using_themed_icon)
3412 GtkIconTheme *icon_theme;
3414 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3416 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3419 /* We don't clear the properties on the window, just figure the
3420 * window is going away.
3423 info->realized = FALSE;
3428 * gtk_window_set_icon_list:
3429 * @window: a #GtkWindow
3430 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3432 * Sets up the icon representing a #GtkWindow. The icon is used when
3433 * the window is minimized (also known as iconified). Some window
3434 * managers or desktop environments may also place it in the window
3435 * frame, or display it in other contexts.
3437 * gtk_window_set_icon_list() allows you to pass in the same icon in
3438 * several hand-drawn sizes. The list should contain the natural sizes
3439 * your icon is available in; that is, don't scale the image before
3440 * passing it to GTK+. Scaling is postponed until the last minute,
3441 * when the desired final size is known, to allow best quality.
3443 * By passing several sizes, you may improve the final image quality
3444 * of the icon, by reducing or eliminating automatic image scaling.
3446 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3447 * larger images (64x64, 128x128) if you have them.
3449 * See also gtk_window_set_default_icon_list() to set the icon
3450 * for all windows in your application in one go.
3452 * Note that transient windows (those who have been set transient for another
3453 * window using gtk_window_set_transient_for()) will inherit their
3454 * icon from their transient parent. So there's no need to explicitly
3455 * set the icon on transient windows.
3458 gtk_window_set_icon_list (GtkWindow *window,
3461 GtkWindowIconInfo *info;
3463 g_return_if_fail (GTK_IS_WINDOW (window));
3465 info = ensure_icon_info (window);
3467 if (info->icon_list == list) /* check for NULL mostly */
3470 g_list_foreach (list,
3471 (GFunc) g_object_ref, NULL);
3473 g_list_foreach (info->icon_list,
3474 (GFunc) g_object_unref, NULL);
3476 g_list_free (info->icon_list);
3478 info->icon_list = g_list_copy (list);
3480 g_object_notify (G_OBJECT (window), "icon");
3482 gtk_window_unrealize_icon (window);
3484 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3485 gtk_window_realize_icon (window);
3487 /* We could try to update our transient children, but I don't think
3488 * it's really worth it. If we did it, the best way would probably
3489 * be to have children connect to notify::icon-list
3494 * gtk_window_get_icon_list:
3495 * @window: a #GtkWindow
3497 * Retrieves the list of icons set by gtk_window_set_icon_list().
3498 * The list is copied, but the reference count on each
3499 * member won't be incremented.
3501 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3504 gtk_window_get_icon_list (GtkWindow *window)
3506 GtkWindowIconInfo *info;
3508 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3510 info = get_icon_info (window);
3513 return g_list_copy (info->icon_list);
3519 * gtk_window_set_icon:
3520 * @window: a #GtkWindow
3521 * @icon: (allow-none): icon image, or %NULL
3523 * Sets up the icon representing a #GtkWindow. This icon is used when
3524 * the window is minimized (also known as iconified). Some window
3525 * managers or desktop environments may also place it in the window
3526 * frame, or display it in other contexts.
3528 * The icon should be provided in whatever size it was naturally
3529 * drawn; that is, don't scale the image before passing it to
3530 * GTK+. Scaling is postponed until the last minute, when the desired
3531 * final size is known, to allow best quality.
3533 * If you have your icon hand-drawn in multiple sizes, use
3534 * gtk_window_set_icon_list(). Then the best size will be used.
3536 * This function is equivalent to calling gtk_window_set_icon_list()
3537 * with a 1-element list.
3539 * See also gtk_window_set_default_icon_list() to set the icon
3540 * for all windows in your application in one go.
3543 gtk_window_set_icon (GtkWindow *window,
3548 g_return_if_fail (GTK_IS_WINDOW (window));
3549 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3554 list = g_list_append (list, icon);
3556 gtk_window_set_icon_list (window, list);
3562 update_themed_icon (GtkIconTheme *icon_theme,
3565 g_object_notify (G_OBJECT (window), "icon");
3567 gtk_window_unrealize_icon (window);
3569 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3570 gtk_window_realize_icon (window);
3574 * gtk_window_set_icon_name:
3575 * @window: a #GtkWindow
3576 * @name: (allow-none): the name of the themed icon
3578 * Sets the icon for the window from a named themed icon. See
3579 * the docs for #GtkIconTheme for more details.
3581 * Note that this has nothing to do with the WM_ICON_NAME
3582 * property which is mentioned in the ICCCM.
3587 gtk_window_set_icon_name (GtkWindow *window,
3590 GtkWindowIconInfo *info;
3593 g_return_if_fail (GTK_IS_WINDOW (window));
3595 info = ensure_icon_info (window);
3597 if (g_strcmp0 (info->icon_name, name) == 0)
3600 tmp = info->icon_name;
3601 info->icon_name = g_strdup (name);
3604 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3605 g_list_free (info->icon_list);
3606 info->icon_list = NULL;
3608 update_themed_icon (NULL, window);
3610 g_object_notify (G_OBJECT (window), "icon-name");
3614 * gtk_window_get_icon_name:
3615 * @window: a #GtkWindow
3617 * Returns the name of the themed icon for the window,
3618 * see gtk_window_set_icon_name().
3620 * Returns: the icon name or %NULL if the window has
3626 gtk_window_get_icon_name (GtkWindow *window)
3628 GtkWindowIconInfo *info;
3630 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3632 info = ensure_icon_info (window);
3634 return info->icon_name;
3638 * gtk_window_get_icon:
3639 * @window: a #GtkWindow
3641 * Gets the value set by gtk_window_set_icon() (or if you've
3642 * called gtk_window_set_icon_list(), gets the first icon in
3645 * Return value: (transfer none): icon for window
3648 gtk_window_get_icon (GtkWindow *window)
3650 GtkWindowIconInfo *info;
3652 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3654 info = get_icon_info (window);
3655 if (info && info->icon_list)
3656 return GDK_PIXBUF (info->icon_list->data);
3661 /* Load pixbuf, printing warning on failure if error == NULL
3664 load_pixbuf_verbosely (const char *filename,
3667 GError *local_err = NULL;
3670 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3678 g_warning ("Error loading icon from file '%s':\n\t%s",
3679 filename, local_err->message);
3680 g_error_free (local_err);
3688 * gtk_window_set_icon_from_file:
3689 * @window: a #GtkWindow
3690 * @filename: location of icon file
3691 * @err: (allow-none): location to store error, or %NULL.
3693 * Sets the icon for @window.
3694 * Warns on failure if @err is %NULL.
3696 * This function is equivalent to calling gtk_window_set_icon()
3697 * with a pixbuf created by loading the image from @filename.
3699 * Returns: %TRUE if setting the icon succeeded.
3704 gtk_window_set_icon_from_file (GtkWindow *window,
3705 const gchar *filename,
3708 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3712 gtk_window_set_icon (window, pixbuf);
3713 g_object_unref (pixbuf);
3722 * gtk_window_set_default_icon_list:
3723 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3725 * Sets an icon list to be used as fallback for windows that haven't
3726 * had gtk_window_set_icon_list() called on them to set up a
3727 * window-specific icon list. This function allows you to set up the
3728 * icon for all windows in your app at once.
3730 * See gtk_window_set_icon_list() for more details.
3734 gtk_window_set_default_icon_list (GList *list)
3738 if (list == default_icon_list)
3741 /* Update serial so we don't used cached pixmaps/masks
3743 default_icon_serial++;
3745 g_list_foreach (list,
3746 (GFunc) g_object_ref, NULL);
3748 g_list_foreach (default_icon_list,
3749 (GFunc) g_object_unref, NULL);
3751 g_list_free (default_icon_list);
3753 default_icon_list = g_list_copy (list);
3755 /* Update all toplevels */
3756 toplevels = gtk_window_list_toplevels ();
3757 tmp_list = toplevels;
3758 while (tmp_list != NULL)
3760 GtkWindowIconInfo *info;
3761 GtkWindow *w = tmp_list->data;
3763 info = get_icon_info (w);
3764 if (info && info->using_default_icon)
3766 gtk_window_unrealize_icon (w);
3767 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3768 gtk_window_realize_icon (w);
3771 tmp_list = tmp_list->next;
3773 g_list_free (toplevels);
3777 * gtk_window_set_default_icon:
3780 * Sets an icon to be used as fallback for windows that haven't
3781 * had gtk_window_set_icon() called on them from a pixbuf.
3786 gtk_window_set_default_icon (GdkPixbuf *icon)
3790 g_return_if_fail (GDK_IS_PIXBUF (icon));
3792 list = g_list_prepend (NULL, icon);
3793 gtk_window_set_default_icon_list (list);
3798 * gtk_window_set_default_icon_name:
3799 * @name: the name of the themed icon
3801 * Sets an icon to be used as fallback for windows that haven't
3802 * had gtk_window_set_icon_list() called on them from a named
3803 * themed icon, see gtk_window_set_icon_name().
3808 gtk_window_set_default_icon_name (const gchar *name)
3813 /* Update serial so we don't used cached pixmaps/masks
3815 default_icon_serial++;
3817 g_free (default_icon_name);
3818 default_icon_name = g_strdup (name);
3820 g_list_foreach (default_icon_list,
3821 (GFunc) g_object_unref, NULL);
3823 g_list_free (default_icon_list);
3824 default_icon_list = NULL;
3826 /* Update all toplevels */
3827 toplevels = gtk_window_list_toplevels ();
3828 tmp_list = toplevels;
3829 while (tmp_list != NULL)
3831 GtkWindowIconInfo *info;
3832 GtkWindow *w = tmp_list->data;
3834 info = get_icon_info (w);
3835 if (info && info->using_default_icon && info->using_themed_icon)
3837 gtk_window_unrealize_icon (w);
3838 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3839 gtk_window_realize_icon (w);
3842 tmp_list = tmp_list->next;
3844 g_list_free (toplevels);
3848 * gtk_window_get_default_icon_name:
3850 * Returns the fallback icon name for windows that has been set
3851 * with gtk_window_set_default_icon_name(). The returned
3852 * string is owned by GTK+ and should not be modified. It
3853 * is only valid until the next call to
3854 * gtk_window_set_default_icon_name().
3856 * Returns: the fallback icon name for windows
3861 gtk_window_get_default_icon_name (void)
3863 return default_icon_name;
3867 * gtk_window_set_default_icon_from_file:
3868 * @filename: location of icon file
3869 * @err: (allow-none): location to store error, or %NULL.
3871 * Sets an icon to be used as fallback for windows that haven't
3872 * had gtk_window_set_icon_list() called on them from a file
3873 * on disk. Warns on failure if @err is %NULL.
3875 * Returns: %TRUE if setting the icon succeeded.
3880 gtk_window_set_default_icon_from_file (const gchar *filename,
3883 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3887 gtk_window_set_default_icon (pixbuf);
3888 g_object_unref (pixbuf);
3897 * gtk_window_get_default_icon_list:
3899 * Gets the value set by gtk_window_set_default_icon_list().
3900 * The list is a copy and should be freed with g_list_free(),
3901 * but the pixbufs in the list have not had their reference count
3904 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3907 gtk_window_get_default_icon_list (void)
3909 return g_list_copy (default_icon_list);
3913 gtk_window_set_default_size_internal (GtkWindow *window,
3914 gboolean change_width,
3916 gboolean change_height,
3918 gboolean is_geometry)
3920 GtkWindowGeometryInfo *info;
3922 g_return_if_fail (change_width == FALSE || width >= -1);
3923 g_return_if_fail (change_height == FALSE || height >= -1);
3925 info = gtk_window_get_geometry_info (window, TRUE);
3927 g_object_freeze_notify (G_OBJECT (window));
3929 info->default_is_geometry = is_geometry != FALSE;
3939 info->default_width = width;
3941 g_object_notify (G_OBJECT (window), "default-width");
3952 info->default_height = height;
3954 g_object_notify (G_OBJECT (window), "default-height");
3957 g_object_thaw_notify (G_OBJECT (window));
3959 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3963 * gtk_window_set_default_size:
3964 * @window: a #GtkWindow
3965 * @width: width in pixels, or -1 to unset the default width
3966 * @height: height in pixels, or -1 to unset the default height
3968 * Sets the default size of a window. If the window's "natural" size
3969 * (its size request) is larger than the default, the default will be
3970 * ignored. More generally, if the default size does not obey the
3971 * geometry hints for the window (gtk_window_set_geometry_hints() can
3972 * be used to set these explicitly), the default size will be clamped
3973 * to the nearest permitted size.
3975 * Unlike gtk_widget_set_size_request(), which sets a size request for
3976 * a widget and thus would keep users from shrinking the window, this
3977 * function only sets the initial size, just as if the user had
3978 * resized the window themselves. Users can still shrink the window
3979 * again as they normally would. Setting a default size of -1 means to
3980 * use the "natural" default size (the size request of the window).
3982 * For more control over a window's initial size and how resizing works,
3983 * investigate gtk_window_set_geometry_hints().
3985 * For some uses, gtk_window_resize() is a more appropriate function.
3986 * gtk_window_resize() changes the current size of the window, rather
3987 * than the size to be used on initial display. gtk_window_resize() always
3988 * affects the window itself, not the geometry widget.
3990 * The default size of a window only affects the first time a window is
3991 * shown; if a window is hidden and re-shown, it will remember the size
3992 * it had prior to hiding, rather than using the default size.
3994 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3995 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3998 gtk_window_set_default_size (GtkWindow *window,
4002 g_return_if_fail (GTK_IS_WINDOW (window));
4003 g_return_if_fail (width >= -1);
4004 g_return_if_fail (height >= -1);
4006 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4010 * gtk_window_set_default_geometry:
4011 * @window: a #GtkWindow
4012 * @width: width in resize increments, or -1 to unset the default width
4013 * @height: height in resize increments, or -1 to unset the default height
4015 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4016 * in terms of the base size and increment set with
4017 * gtk_window_set_geometry_hints.
4022 gtk_window_set_default_geometry (GtkWindow *window,
4026 g_return_if_fail (GTK_IS_WINDOW (window));
4027 g_return_if_fail (width >= -1);
4028 g_return_if_fail (height >= -1);
4030 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4034 * gtk_window_get_default_size:
4035 * @window: a #GtkWindow
4036 * @width: (out) (allow-none): location to store the default width, or %NULL
4037 * @height: (out) (allow-none): location to store the default height, or %NULL
4039 * Gets the default size of the window. A value of -1 for the width or
4040 * height indicates that a default size has not been explicitly set
4041 * for that dimension, so the "natural" size of the window will be
4046 gtk_window_get_default_size (GtkWindow *window,
4050 GtkWindowGeometryInfo *info;
4052 g_return_if_fail (GTK_IS_WINDOW (window));
4054 info = gtk_window_get_geometry_info (window, FALSE);
4057 *width = info ? info->default_width : -1;
4060 *height = info ? info->default_height : -1;
4064 * gtk_window_resize:
4065 * @window: a #GtkWindow
4066 * @width: width in pixels to resize the window to
4067 * @height: height in pixels to resize the window to
4069 * Resizes the window as if the user had done so, obeying geometry
4070 * constraints. The default geometry constraint is that windows may
4071 * not be smaller than their size request; to override this
4072 * constraint, call gtk_widget_set_size_request() to set the window's
4073 * request to a smaller value.
4075 * If gtk_window_resize() is called before showing a window for the
4076 * first time, it overrides any default size set with
4077 * gtk_window_set_default_size().
4079 * Windows may not be resized smaller than 1 by 1 pixels.
4083 gtk_window_resize (GtkWindow *window,
4087 GtkWindowGeometryInfo *info;
4089 g_return_if_fail (GTK_IS_WINDOW (window));
4090 g_return_if_fail (width > 0);
4091 g_return_if_fail (height > 0);
4093 info = gtk_window_get_geometry_info (window, TRUE);
4095 info->resize_width = width;
4096 info->resize_height = height;
4097 info->resize_is_geometry = FALSE;
4099 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4103 * gtk_window_resize_to_geometry:
4104 * @window: a #GtkWindow
4105 * @width: width in resize increments to resize the window to
4106 * @height: height in resize increments to resize the window to
4108 * Like gtk_window_resize(), but @width and @height are interpreted
4109 * in terms of the base size and increment set with
4110 * gtk_window_set_geometry_hints.
4115 gtk_window_resize_to_geometry (GtkWindow *window,
4119 GtkWindowGeometryInfo *info;
4121 g_return_if_fail (GTK_IS_WINDOW (window));
4122 g_return_if_fail (width > 0);
4123 g_return_if_fail (height > 0);
4125 info = gtk_window_get_geometry_info (window, TRUE);
4127 info->resize_width = width;
4128 info->resize_height = height;
4129 info->resize_is_geometry = TRUE;
4131 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4135 * gtk_window_get_size:
4136 * @window: a #GtkWindow
4137 * @width: (out) (allow-none): return location for width, or %NULL
4138 * @height: (out) (allow-none): return location for height, or %NULL
4140 * Obtains the current size of @window. If @window is not onscreen,
4141 * it returns the size GTK+ will suggest to the <link
4142 * linkend="gtk-X11-arch">window manager</link> for the initial window
4143 * size (but this is not reliably the same as the size the window
4144 * manager will actually select). The size obtained by
4145 * gtk_window_get_size() is the last size received in a
4146 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4147 * rather than querying the X server for the size. As a result, if you
4148 * call gtk_window_resize() then immediately call
4149 * gtk_window_get_size(), the size won't have taken effect yet. After
4150 * the window manager processes the resize request, GTK+ receives
4151 * notification that the size has changed via a configure event, and
4152 * the size of the window gets updated.
4154 * Note 1: Nearly any use of this function creates a race condition,
4155 * because the size of the window may change between the time that you
4156 * get the size and the time that you perform some action assuming
4157 * that size is the current size. To avoid race conditions, connect to
4158 * "configure-event" on the window and adjust your size-dependent
4159 * state to match the size delivered in the #GdkEventConfigure.
4161 * Note 2: The returned size does <emphasis>not</emphasis> include the
4162 * size of the window manager decorations (aka the window frame or
4163 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4164 * method of determining their size.
4166 * Note 3: If you are getting a window size in order to position
4167 * the window onscreen, there may be a better way. The preferred
4168 * way is to simply set the window's semantic type with
4169 * gtk_window_set_type_hint(), which allows the window manager to
4170 * e.g. center dialogs. Also, if you set the transient parent of
4171 * dialogs with gtk_window_set_transient_for() window managers
4172 * will often center the dialog over its parent window. It's
4173 * much preferred to let the window manager handle these
4174 * things rather than doing it yourself, because all apps will
4175 * behave consistently and according to user prefs if the window
4176 * manager handles it. Also, the window manager can take the size
4177 * of the window decorations/border into account, while your
4178 * application cannot.
4180 * In any case, if you insist on application-specified window
4181 * positioning, there's <emphasis>still</emphasis> a better way than
4182 * doing it yourself - gtk_window_set_position() will frequently
4183 * handle the details for you.
4187 gtk_window_get_size (GtkWindow *window,
4193 g_return_if_fail (GTK_IS_WINDOW (window));
4195 if (width == NULL && height == NULL)
4198 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4200 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4201 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4205 GdkRectangle configure_request;
4207 gtk_window_compute_configure_request (window,
4211 w = configure_request.width;
4212 h = configure_request.height;
4223 * @window: a #GtkWindow
4224 * @x: X coordinate to move window to
4225 * @y: Y coordinate to move window to
4227 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4228 * @window to the given position. Window managers are free to ignore
4229 * this; most window managers ignore requests for initial window
4230 * positions (instead using a user-defined placement algorithm) and
4231 * honor requests after the window has already been shown.
4233 * Note: the position is the position of the gravity-determined
4234 * reference point for the window. The gravity determines two things:
4235 * first, the location of the reference point in root window
4236 * coordinates; and second, which point on the window is positioned at
4237 * the reference point.
4239 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4240 * point is simply the @x, @y supplied to gtk_window_move(). The
4241 * top-left corner of the window decorations (aka window frame or
4242 * border) will be placed at @x, @y. Therefore, to position a window
4243 * at the top left of the screen, you want to use the default gravity
4244 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4246 * To position a window at the bottom right corner of the screen, you
4247 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4248 * point is at @x + the window width and @y + the window height, and
4249 * the bottom-right corner of the window border will be placed at that
4250 * reference point. So, to place a window in the bottom right corner
4251 * you would first set gravity to south east, then write:
4252 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4253 * gdk_screen_height () - window_height)</literal> (note that this
4254 * example does not take multi-head scenarios into account).
4256 * The Extended Window Manager Hints specification at <ulink
4257 * url="http://www.freedesktop.org/Standards/wm-spec">
4258 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4259 * nice table of gravities in the "implementation notes" section.
4261 * The gtk_window_get_position() documentation may also be relevant.
4264 gtk_window_move (GtkWindow *window,
4268 GtkWindowPrivate *priv;
4269 GtkWindowGeometryInfo *info;
4272 g_return_if_fail (GTK_IS_WINDOW (window));
4274 priv = window->priv;
4275 widget = GTK_WIDGET (window);
4277 info = gtk_window_get_geometry_info (window, TRUE);
4279 if (gtk_widget_get_mapped (widget))
4281 GtkAllocation allocation;
4283 gtk_widget_get_allocation (widget, &allocation);
4285 /* we have now sent a request with this position
4286 * with currently-active constraints, so toggle flag.
4288 info->position_constraints_changed = FALSE;
4290 /* we only constrain if mapped - if not mapped,
4291 * then gtk_window_compute_configure_request()
4292 * will apply the constraints later, and we
4293 * don't want to lose information about
4294 * what position the user set before then.
4295 * i.e. if you do a move() then turn off POS_CENTER
4296 * then show the window, your move() will work.
4298 gtk_window_constrain_position (window,
4299 allocation.width, allocation.height,
4302 /* Note that this request doesn't go through our standard request
4303 * framework, e.g. doesn't increment configure_request_count,
4304 * doesn't set info->last, etc.; that's because
4305 * we don't save the info needed to arrive at this same request
4308 * To gtk_window_move_resize(), this will end up looking exactly
4309 * the same as the position being changed by the window
4312 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4316 /* Save this position to apply on mapping */
4317 info->initial_x = x;
4318 info->initial_y = y;
4319 info->initial_pos_set = TRUE;
4324 * gtk_window_get_position:
4325 * @window: a #GtkWindow
4326 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4327 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4329 * This function returns the position you need to pass to
4330 * gtk_window_move() to keep @window in its current position. This
4331 * means that the meaning of the returned value varies with window
4332 * gravity. See gtk_window_move() for more details.
4334 * If you haven't changed the window gravity, its gravity will be
4335 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4336 * gets the position of the top-left corner of the window manager
4337 * frame for the window. gtk_window_move() sets the position of this
4338 * same top-left corner.
4340 * gtk_window_get_position() is not 100% reliable because the X Window System
4341 * does not specify a way to obtain the geometry of the
4342 * decorations placed on a window by the window manager.
4343 * Thus GTK+ is using a "best guess" that works with most
4346 * Moreover, nearly all window managers are historically broken with
4347 * respect to their handling of window gravity. So moving a window to
4348 * its current position as returned by gtk_window_get_position() tends
4349 * to result in moving the window slightly. Window managers are
4350 * slowly getting better over time.
4352 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4353 * frame is not relevant, and thus gtk_window_get_position() will
4354 * always produce accurate results. However you can't use static
4355 * gravity to do things like place a window in a corner of the screen,
4356 * because static gravity ignores the window manager decorations.
4358 * If you are saving and restoring your application's window
4359 * positions, you should know that it's impossible for applications to
4360 * do this without getting it somewhat wrong because applications do
4361 * not have sufficient knowledge of window manager state. The Correct
4362 * Mechanism is to support the session management protocol (see the
4363 * "GnomeClient" object in the GNOME libraries for example) and allow
4364 * the window manager to save your window sizes and positions.
4369 gtk_window_get_position (GtkWindow *window,
4373 GtkWindowPrivate *priv;
4375 GdkWindow *gdk_window;
4377 g_return_if_fail (GTK_IS_WINDOW (window));
4379 priv = window->priv;
4380 widget = GTK_WIDGET (window);
4381 gdk_window = gtk_widget_get_window (widget);
4383 if (priv->gravity == GDK_GRAVITY_STATIC)
4385 if (gtk_widget_get_mapped (widget))
4387 /* This does a server round-trip, which is sort of wrong;
4388 * but a server round-trip is inevitable for
4389 * gdk_window_get_frame_extents() in the usual
4390 * NorthWestGravity case below, so not sure what else to
4391 * do. We should likely be consistent about whether we get
4392 * the client-side info or the server-side info.
4394 gdk_window_get_origin (gdk_window, root_x, root_y);
4398 GdkRectangle configure_request;
4400 gtk_window_compute_configure_request (window,
4404 *root_x = configure_request.x;
4405 *root_y = configure_request.y;
4410 GdkRectangle frame_extents;
4415 if (gtk_widget_get_mapped (widget))
4417 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4418 x = frame_extents.x;
4419 y = frame_extents.y;
4420 gtk_window_get_size (window, &w, &h);
4424 /* We just say the frame has 0 size on all sides.
4425 * Not sure what else to do.
4427 gtk_window_compute_configure_request (window,
4430 x = frame_extents.x;
4431 y = frame_extents.y;
4432 w = frame_extents.width;
4433 h = frame_extents.height;
4436 switch (priv->gravity)
4438 case GDK_GRAVITY_NORTH:
4439 case GDK_GRAVITY_CENTER:
4440 case GDK_GRAVITY_SOUTH:
4441 /* Find center of frame. */
4442 x += frame_extents.width / 2;
4443 /* Center client window on that point. */
4447 case GDK_GRAVITY_SOUTH_EAST:
4448 case GDK_GRAVITY_EAST:
4449 case GDK_GRAVITY_NORTH_EAST:
4450 /* Find right edge of frame */
4451 x += frame_extents.width;
4452 /* Align left edge of client at that point. */
4459 switch (priv->gravity)
4461 case GDK_GRAVITY_WEST:
4462 case GDK_GRAVITY_CENTER:
4463 case GDK_GRAVITY_EAST:
4464 /* Find center of frame. */
4465 y += frame_extents.height / 2;
4466 /* Center client window there. */
4469 case GDK_GRAVITY_SOUTH_WEST:
4470 case GDK_GRAVITY_SOUTH:
4471 case GDK_GRAVITY_SOUTH_EAST:
4472 /* Find south edge of frame */
4473 y += frame_extents.height;
4474 /* Place bottom edge of client there */
4489 * gtk_window_reshow_with_initial_size:
4490 * @window: a #GtkWindow
4492 * Hides @window, then reshows it, resetting the
4493 * default size and position of the window. Used
4494 * by GUI builders only.
4497 gtk_window_reshow_with_initial_size (GtkWindow *window)
4501 g_return_if_fail (GTK_IS_WINDOW (window));
4503 widget = GTK_WIDGET (window);
4505 gtk_widget_hide (widget);
4506 gtk_widget_unrealize (widget);
4507 gtk_widget_show (widget);
4511 gtk_window_destroy (GtkWidget *widget)
4513 GtkWindow *window = GTK_WINDOW (widget);
4514 GtkWindowPrivate *priv = window->priv;
4516 gtk_window_release_application (window);
4518 toplevel_list = g_slist_remove (toplevel_list, window);
4520 if (priv->transient_parent)
4521 gtk_window_set_transient_for (window, NULL);
4523 /* frees the icons */
4524 gtk_window_set_icon_list (window, NULL);
4526 if (priv->has_user_ref_count)
4528 priv->has_user_ref_count = FALSE;
4529 g_object_unref (window);
4533 gtk_window_group_remove_window (priv->group, window);
4535 gtk_window_free_key_hash (window);
4537 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4541 gtk_window_finalize (GObject *object)
4543 GtkWindow *window = GTK_WINDOW (object);
4544 GtkWindowPrivate *priv = window->priv;
4545 GtkMnemonicHash *mnemonic_hash;
4547 g_free (priv->title);
4548 g_free (priv->wmclass_name);
4549 g_free (priv->wmclass_class);
4550 g_free (priv->wm_role);
4551 gtk_window_release_application (window);
4553 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4555 _gtk_mnemonic_hash_free (mnemonic_hash);
4557 if (priv->geometry_info)
4559 if (priv->geometry_info->widget)
4560 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4561 gtk_widget_destroyed,
4562 &priv->geometry_info->widget);
4563 g_free (priv->geometry_info);
4566 if (priv->keys_changed_handler)
4568 g_source_remove (priv->keys_changed_handler);
4569 priv->keys_changed_handler = 0;
4573 g_signal_handlers_disconnect_by_func (priv->screen,
4574 gtk_window_on_composited_changed, window);
4576 g_free (priv->startup_id);
4578 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4582 gtk_window_show (GtkWidget *widget)
4584 GtkWindow *window = GTK_WINDOW (widget);
4585 GtkWindowPrivate *priv = window->priv;
4586 GtkContainer *container = GTK_CONTAINER (window);
4587 gboolean need_resize;
4589 _gtk_widget_set_visible_flag (widget, TRUE);
4591 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4592 _gtk_container_set_need_resize (container, FALSE);
4596 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4597 GtkAllocation allocation = { 0, 0 };
4598 GdkRectangle configure_request;
4599 GdkGeometry new_geometry;
4601 gboolean was_realized;
4603 /* We are going to go ahead and perform this configure request
4604 * and then emulate a configure notify by going ahead and
4605 * doing a size allocate. Sort of a synchronous
4606 * mini-copy of gtk_window_move_resize() here.
4608 gtk_window_compute_configure_request (window,
4613 /* We update this because we are going to go ahead
4614 * and gdk_window_resize() below, rather than
4617 info->last.configure_request.width = configure_request.width;
4618 info->last.configure_request.height = configure_request.height;
4620 /* and allocate the window - this is normally done
4621 * in move_resize in response to configure notify
4623 allocation.width = configure_request.width;
4624 allocation.height = configure_request.height;
4625 gtk_widget_size_allocate (widget, &allocation);
4627 /* Then we guarantee we have a realize */
4628 was_realized = FALSE;
4629 if (!gtk_widget_get_realized (widget))
4631 gtk_widget_realize (widget);
4632 was_realized = TRUE;
4635 /* We only send configure request if we didn't just finish
4636 * creating the window; if we just created the window
4637 * then we created it with widget->allocation anyhow.
4640 gdk_window_move_resize (gtk_widget_get_window (widget),
4641 configure_request.x,
4642 configure_request.y,
4643 configure_request.width,
4644 configure_request.height);
4647 gtk_container_check_resize (container);
4649 gtk_widget_map (widget);
4651 /* Try to make sure that we have some focused widget
4653 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4654 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4657 gtk_grab_add (widget);
4661 gtk_window_hide (GtkWidget *widget)
4663 GtkWindow *window = GTK_WINDOW (widget);
4664 GtkWindowPrivate *priv = window->priv;
4666 _gtk_widget_set_visible_flag (widget, FALSE);
4667 gtk_widget_unmap (widget);
4670 gtk_grab_remove (widget);
4674 gtk_window_map (GtkWidget *widget)
4677 GtkWindow *window = GTK_WINDOW (widget);
4678 GtkWindowPrivate *priv = window->priv;
4679 GdkWindow *toplevel;
4680 GdkWindow *gdk_window;
4681 gboolean auto_mnemonics;
4683 gdk_window = gtk_widget_get_window (widget);
4685 gtk_widget_set_mapped (widget, TRUE);
4687 child = gtk_bin_get_child (&(window->bin));
4689 gtk_widget_get_visible (child) &&
4690 !gtk_widget_get_mapped (child))
4691 gtk_widget_map (child);
4693 toplevel = gdk_window;
4695 if (priv->maximize_initially)
4696 gdk_window_maximize (toplevel);
4698 gdk_window_unmaximize (toplevel);
4700 if (priv->stick_initially)
4701 gdk_window_stick (toplevel);
4703 gdk_window_unstick (toplevel);
4705 if (priv->iconify_initially)
4706 gdk_window_iconify (toplevel);
4708 gdk_window_deiconify (toplevel);
4710 if (priv->fullscreen_initially)
4711 gdk_window_fullscreen (toplevel);
4713 gdk_window_unfullscreen (toplevel);
4715 gdk_window_set_keep_above (toplevel, priv->above_initially);
4717 gdk_window_set_keep_below (toplevel, priv->below_initially);
4719 /* No longer use the default settings */
4720 priv->need_default_size = FALSE;
4721 priv->need_default_position = FALSE;
4723 if (priv->reset_type_hint)
4725 /* We should only reset the type hint when the application
4726 * used gtk_window_set_type_hint() to change the hint.
4727 * Some applications use X directly to change the properties;
4728 * in that case, we shouldn't overwrite what they did.
4730 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4731 priv->reset_type_hint = FALSE;
4734 gdk_window_show (gdk_window);
4736 if (priv->grip_window)
4737 gdk_window_show (priv->grip_window);
4739 if (!disable_startup_notification)
4741 /* Do we have a custom startup-notification id? */
4742 if (priv->startup_id != NULL)
4744 /* Make sure we have a "real" id */
4745 if (!startup_id_is_fake (priv->startup_id))
4746 gdk_notify_startup_complete_with_id (priv->startup_id);
4748 g_free (priv->startup_id);
4749 priv->startup_id = NULL;
4751 else if (!sent_startup_notification)
4753 sent_startup_notification = TRUE;
4754 gdk_notify_startup_complete ();
4758 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4759 * (as in the case of popup menus), then hide mnemonics initially
4761 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4762 &auto_mnemonics, NULL);
4763 if (auto_mnemonics && !priv->mnemonics_visible_set)
4764 gtk_window_set_mnemonics_visible (window, FALSE);
4768 gtk_window_map_event (GtkWidget *widget,
4771 if (!gtk_widget_get_mapped (widget))
4773 /* we should be be unmapped, but are getting a MapEvent, this may happen
4774 * to toplevel XWindows if mapping was intercepted by a window manager
4775 * and an unmap request occoured while the MapRequestEvent was still
4776 * being handled. we work around this situaiton here by re-requesting
4777 * the window being unmapped. more details can be found in:
4778 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4780 gdk_window_hide (gtk_widget_get_window (widget));
4786 gtk_window_unmap (GtkWidget *widget)
4788 GtkWindow *window = GTK_WINDOW (widget);
4789 GtkWindowPrivate *priv = window->priv;
4791 GtkWindowGeometryInfo *info;
4792 GdkWindow *gdk_window;
4793 GdkWindowState state;
4795 gdk_window = gtk_widget_get_window (widget);
4797 gtk_widget_set_mapped (widget, FALSE);
4798 gdk_window_withdraw (gdk_window);
4800 priv->configure_request_count = 0;
4801 priv->configure_notify_received = FALSE;
4803 /* on unmap, we reset the default positioning of the window,
4804 * so it's placed again, but we don't reset the default
4805 * size of the window, so it's remembered.
4807 priv->need_default_position = TRUE;
4809 info = gtk_window_get_geometry_info (window, FALSE);
4812 info->initial_pos_set = FALSE;
4813 info->position_constraints_changed = FALSE;
4816 state = gdk_window_get_state (gdk_window);
4817 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4818 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4819 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4820 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4821 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4823 child = gtk_bin_get_child (&(window->bin));
4825 gtk_widget_unmap (child);
4829 gtk_window_realize (GtkWidget *widget)
4831 GtkAllocation allocation;
4833 GdkWindow *parent_window;
4834 GdkWindow *gdk_window;
4835 GdkWindowAttr attributes;
4836 gint attributes_mask;
4837 GtkWindowPrivate *priv;
4838 GtkStyleContext *context;
4840 window = GTK_WINDOW (widget);
4841 priv = window->priv;
4843 gtk_widget_get_allocation (widget, &allocation);
4845 /* ensure widget tree is properly size allocated */
4846 if (allocation.x == -1 &&
4847 allocation.y == -1 &&
4848 allocation.width == 1 &&
4849 allocation.height == 1)
4851 GtkRequisition requisition;
4855 allocation.width = 200;
4856 allocation.height = 200;
4858 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4859 if (requisition.width || requisition.height)
4861 /* non-empty window */
4862 allocation.width = requisition.width;
4863 allocation.height = requisition.height;
4865 gtk_widget_size_allocate (widget, &allocation);
4867 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4869 g_return_if_fail (!gtk_widget_get_realized (widget));
4872 gtk_widget_set_realized (widget, TRUE);
4876 case GTK_WINDOW_TOPLEVEL:
4877 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4879 case GTK_WINDOW_POPUP:
4880 attributes.window_type = GDK_WINDOW_TEMP;
4883 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4887 attributes.title = priv->title;
4888 attributes.wmclass_name = priv->wmclass_name;
4889 attributes.wmclass_class = priv->wmclass_class;
4890 attributes.wclass = GDK_INPUT_OUTPUT;
4891 attributes.visual = gtk_widget_get_visual (widget);
4893 attributes_mask = 0;
4894 parent_window = gtk_widget_get_root_window (widget);
4896 gtk_widget_get_allocation (widget, &allocation);
4897 attributes.width = allocation.width;
4898 attributes.height = allocation.height;
4899 attributes.event_mask = gtk_widget_get_events (widget);
4900 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4901 GDK_KEY_PRESS_MASK |
4902 GDK_KEY_RELEASE_MASK |
4903 GDK_ENTER_NOTIFY_MASK |
4904 GDK_LEAVE_NOTIFY_MASK |
4905 GDK_FOCUS_CHANGE_MASK |
4906 GDK_STRUCTURE_MASK);
4907 attributes.type_hint = priv->type_hint;
4909 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4910 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4911 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4913 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4914 gtk_widget_set_window (widget, gdk_window);
4916 if (priv->opacity_set)
4917 gdk_window_set_opacity (gdk_window, priv->opacity);
4919 gdk_window_enable_synchronized_configure (gdk_window);
4921 gdk_window_set_user_data (gdk_window, window);
4923 gtk_widget_style_attach (widget);
4924 context = gtk_widget_get_style_context (widget);
4926 gtk_style_context_set_background (context, gdk_window);
4928 if (priv->transient_parent &&
4929 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4930 gdk_window_set_transient_for (gdk_window,
4931 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4934 gdk_window_set_role (gdk_window, priv->wm_role);
4936 if (!priv->decorated)
4937 gdk_window_set_decorations (gdk_window, 0);
4939 if (!priv->deletable)
4940 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4942 if (gtk_window_get_skip_pager_hint (window))
4943 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4945 if (gtk_window_get_skip_taskbar_hint (window))
4946 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4948 if (gtk_window_get_accept_focus (window))
4949 gdk_window_set_accept_focus (gdk_window, TRUE);
4951 gdk_window_set_accept_focus (gdk_window, FALSE);
4953 if (gtk_window_get_focus_on_map (window))
4954 gdk_window_set_focus_on_map (gdk_window, TRUE);
4956 gdk_window_set_focus_on_map (gdk_window, FALSE);
4959 gdk_window_set_modal_hint (gdk_window, TRUE);
4961 gdk_window_set_modal_hint (gdk_window, FALSE);
4963 if (priv->startup_id)
4965 #ifdef GDK_WINDOWING_X11
4966 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4967 if (timestamp != GDK_CURRENT_TIME)
4968 gdk_x11_window_set_user_time (gdk_window, timestamp);
4970 if (!startup_id_is_fake (priv->startup_id))
4971 gdk_window_set_startup_id (gdk_window, priv->startup_id);
4975 gtk_window_realize_icon (window);
4977 if (priv->has_resize_grip)
4978 resize_grip_create_window (window);
4982 gtk_window_unrealize (GtkWidget *widget)
4984 GtkWindow *window = GTK_WINDOW (widget);
4985 GtkWindowPrivate *priv = window->priv;
4986 GtkWindowGeometryInfo *info;
4988 /* On unrealize, we reset the size of the window such
4989 * that we will re-apply the default sizing stuff
4990 * next time we show the window.
4992 * Default positioning is reset on unmap, instead of unrealize.
4994 priv->need_default_size = TRUE;
4995 info = gtk_window_get_geometry_info (window, FALSE);
4998 info->resize_width = -1;
4999 info->resize_height = -1;
5000 info->last.configure_request.x = 0;
5001 info->last.configure_request.y = 0;
5002 info->last.configure_request.width = -1;
5003 info->last.configure_request.height = -1;
5004 /* be sure we reset geom hints on re-realize */
5005 info->last.flags = 0;
5009 gtk_window_unrealize_icon (window);
5011 if (priv->grip_window != NULL)
5012 resize_grip_destroy_window (window);
5014 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5017 static GtkJunctionSides
5018 get_grip_junction (GtkWidget *widget)
5020 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5021 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5023 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5027 get_drag_edge (GtkWidget *widget,
5028 GdkWindowEdge *edge)
5030 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5031 gboolean hresizable;
5032 gboolean vresizable;
5033 GtkTextDirection dir;
5034 GtkWindowGeometryInfo *info;
5039 info = priv->geometry_info;
5042 GdkWindowHints flags = info->last.flags;
5043 GdkGeometry *geometry = &info->last.geometry;
5045 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5047 hresizable = geometry->min_width < geometry->max_width;
5048 vresizable = geometry->min_height < geometry->max_height;
5052 dir = gtk_widget_get_direction (widget);
5054 if (hresizable && vresizable)
5055 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5056 else if (hresizable)
5057 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5058 else if (vresizable)
5059 *edge = GDK_WINDOW_EDGE_SOUTH;
5067 set_grip_cursor (GtkWindow *window)
5069 GtkWidget *widget = GTK_WIDGET (window);
5070 GtkWindowPrivate *priv = window->priv;
5072 if (priv->grip_window == NULL)
5075 if (gtk_widget_is_sensitive (widget))
5078 GdkDisplay *display;
5079 GdkCursorType cursor_type;
5082 cursor_type = GDK_LEFT_PTR;
5084 if (get_drag_edge (widget, &edge))
5088 case GDK_WINDOW_EDGE_EAST:
5089 cursor_type = GDK_RIGHT_SIDE;
5091 case GDK_WINDOW_EDGE_SOUTH_EAST:
5092 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5094 case GDK_WINDOW_EDGE_SOUTH:
5095 cursor_type = GDK_BOTTOM_SIDE;
5097 case GDK_WINDOW_EDGE_SOUTH_WEST:
5098 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5100 case GDK_WINDOW_EDGE_WEST:
5101 cursor_type = GDK_LEFT_SIDE;
5107 display = gtk_widget_get_display (widget);
5108 cursor = gdk_cursor_new_for_display (display, cursor_type);
5109 gdk_window_set_cursor (priv->grip_window, cursor);
5110 g_object_unref (cursor);
5113 gdk_window_set_cursor (priv->grip_window, NULL);
5117 set_grip_shape (GtkWindow *window)
5119 GtkWindowPrivate *priv = window->priv;
5120 cairo_region_t *region;
5121 cairo_surface_t *surface;
5123 double width, height;
5125 if (priv->grip_window == NULL)
5128 width = gdk_window_get_width (priv->grip_window);
5129 height = gdk_window_get_height (priv->grip_window);
5130 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5132 cr = cairo_create (surface);
5133 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5135 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5136 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5138 cairo_move_to (cr, width, 0.0);
5139 cairo_line_to (cr, width, height);
5140 cairo_line_to (cr, 0.0, height);
5144 cairo_move_to (cr, 0.0, 0.0);
5145 cairo_line_to (cr, width, height);
5146 cairo_line_to (cr, 0.0, height);
5148 cairo_close_path (cr);
5151 region = gdk_cairo_region_create_from_surface (surface);
5152 cairo_surface_destroy (surface);
5154 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5155 cairo_region_destroy (region);
5159 set_grip_position (GtkWindow *window)
5161 GtkWindowPrivate *priv = window->priv;
5164 if (priv->grip_window == NULL)
5167 gtk_window_get_resize_grip_area (window, &rect);
5168 gdk_window_raise (priv->grip_window);
5169 gdk_window_move_resize (priv->grip_window,
5171 rect.width, rect.height);
5175 gtk_window_size_allocate (GtkWidget *widget,
5176 GtkAllocation *allocation)
5178 GtkWindow *window = GTK_WINDOW (widget);
5179 GtkAllocation child_allocation;
5183 gtk_widget_set_allocation (widget, allocation);
5185 child = gtk_bin_get_child (&(window->bin));
5186 if (child && gtk_widget_get_visible (child))
5188 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5189 child_allocation.x = border_width;
5190 child_allocation.y = border_width;
5191 child_allocation.width =
5192 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5193 child_allocation.height =
5194 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5196 gtk_widget_size_allocate (child, &child_allocation);
5199 if (gtk_widget_get_realized (widget))
5201 update_grip_visibility (window);
5202 set_grip_position (window);
5207 gtk_window_configure_event (GtkWidget *widget,
5208 GdkEventConfigure *event)
5210 GtkAllocation allocation;
5211 GtkWindow *window = GTK_WINDOW (widget);
5212 GtkWindowPrivate *priv = window->priv;
5213 gboolean expected_reply = priv->configure_request_count > 0;
5215 /* priv->configure_request_count incremented for each
5216 * configure request, and decremented to a min of 0 for
5217 * each configure notify.
5219 * All it means is that we know we will get at least
5220 * priv->configure_request_count more configure notifies.
5221 * We could get more configure notifies than that; some
5222 * of the configure notifies we get may be unrelated to
5223 * the configure requests. But we will get at least
5224 * priv->configure_request_count notifies.
5227 if (priv->configure_request_count > 0)
5229 priv->configure_request_count -= 1;
5230 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5233 /* As an optimization, we avoid a resize when possible.
5235 * The only times we can avoid a resize are:
5236 * - we know only the position changed, not the size
5237 * - we know we have made more requests and so will get more
5238 * notifies and can wait to resize when we get them
5240 gtk_widget_get_allocation (widget, &allocation);
5241 if (!expected_reply &&
5242 (allocation.width == event->width &&
5243 allocation.height == event->height))
5245 gdk_window_configure_finished (gtk_widget_get_window (widget));
5250 * If we do need to resize, we do that by:
5251 * - filling in widget->allocation with the new size
5252 * - setting configure_notify_received to TRUE
5253 * for use in gtk_window_move_resize()
5254 * - queueing a resize, leading to invocation of
5255 * gtk_window_move_resize() in an idle handler
5259 priv->configure_notify_received = TRUE;
5261 allocation.width = event->width;
5262 allocation.height = event->height;
5263 gtk_widget_set_allocation (widget, &allocation);
5265 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5267 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5273 gtk_window_state_event (GtkWidget *widget,
5274 GdkEventWindowState *event)
5276 update_grip_visibility (GTK_WINDOW (widget));
5282 gtk_window_direction_changed (GtkWidget *widget,
5283 GtkTextDirection prev_dir)
5285 GtkWindow *window = GTK_WINDOW (widget);
5287 set_grip_cursor (window);
5288 set_grip_position (window);
5289 set_grip_shape (window);
5293 gtk_window_state_changed (GtkWidget *widget,
5294 GtkStateType previous_state)
5296 GtkWindow *window = GTK_WINDOW (widget);
5298 update_grip_visibility (window);
5302 gtk_window_style_updated (GtkWidget *widget)
5304 GtkWindow *window = GTK_WINDOW (widget);
5305 GtkWindowPrivate *priv = window->priv;
5308 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5310 gdk_window_move_resize (priv->grip_window,
5312 rect.width, rect.height);
5314 set_grip_shape (window);
5315 gtk_widget_queue_resize (widget);
5320 resize_grip_create_window (GtkWindow *window)
5323 GtkWindowPrivate *priv;
5324 GdkWindowAttr attributes;
5325 gint attributes_mask;
5328 priv = window->priv;
5329 widget = GTK_WIDGET (window);
5331 g_return_if_fail (gtk_widget_get_realized (widget));
5332 g_return_if_fail (priv->grip_window == NULL);
5334 gtk_window_get_resize_grip_area (window, &rect);
5336 attributes.x = rect.x;
5337 attributes.y = rect.y;
5338 attributes.width = rect.width;
5339 attributes.height = rect.height;
5340 attributes.window_type = GDK_WINDOW_CHILD;
5341 attributes.wclass = GDK_INPUT_OUTPUT;
5342 attributes.event_mask = gtk_widget_get_events (widget) |
5344 GDK_BUTTON_PRESS_MASK;
5346 attributes_mask = GDK_WA_X | GDK_WA_Y;
5348 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5352 gdk_window_set_user_data (priv->grip_window, widget);
5354 gdk_window_raise (priv->grip_window);
5356 set_grip_shape (window);
5357 update_grip_visibility (window);
5361 resize_grip_destroy_window (GtkWindow *window)
5363 GtkWindowPrivate *priv = window->priv;
5365 gdk_window_set_user_data (priv->grip_window, NULL);
5366 gdk_window_destroy (priv->grip_window);
5367 priv->grip_window = NULL;
5368 update_grip_visibility (window);
5372 * gtk_window_set_has_resize_grip:
5373 * @window: a #GtkWindow
5374 * @value: %TRUE to allow a resize grip
5376 * Sets whether @window has a corner resize grip.
5378 * Note that the resize grip is only shown if the window
5379 * is actually resizable and not maximized. Use
5380 * gtk_window_resize_grip_is_visible() to find out if the
5381 * resize grip is currently shown.
5386 gtk_window_set_has_resize_grip (GtkWindow *window,
5389 GtkWidget *widget = GTK_WIDGET (window);
5390 GtkWindowPrivate *priv = window->priv;
5392 value = value != FALSE;
5394 if (value != priv->has_resize_grip)
5396 priv->has_resize_grip = value;
5397 gtk_widget_queue_draw (widget);
5399 if (gtk_widget_get_realized (widget))
5401 if (priv->has_resize_grip && priv->grip_window == NULL)
5402 resize_grip_create_window (window);
5403 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5404 resize_grip_destroy_window (window);
5407 g_object_notify (G_OBJECT (window), "has-resize-grip");
5412 update_grip_visibility (GtkWindow *window)
5414 GtkWindowPrivate *priv = window->priv;
5417 val = gtk_window_resize_grip_is_visible (window);
5419 if (priv->grip_window != NULL)
5423 gdk_window_show (priv->grip_window);
5424 set_grip_cursor (window);
5428 gdk_window_hide (priv->grip_window);
5432 if (priv->resize_grip_visible != val)
5434 priv->resize_grip_visible = val;
5436 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5441 * gtk_window_resize_grip_is_visible:
5442 * @window: a #GtkWindow
5444 * Determines whether a resize grip is visible for the specified window.
5446 * Returns %TRUE if a resize grip exists and is visible.
5451 gtk_window_resize_grip_is_visible (GtkWindow *window)
5454 GtkWindowPrivate *priv;
5457 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5459 priv = window->priv;
5460 widget = GTK_WIDGET (window);
5462 if (priv->type == GTK_WINDOW_POPUP)
5465 if (!priv->resizable)
5468 if (gtk_widget_get_realized (widget))
5470 GdkWindowState state;
5472 state = gdk_window_get_state (gtk_widget_get_window (widget));
5474 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5478 if (!get_drag_edge (widget, &edge))
5481 return window->priv->has_resize_grip;
5485 * gtk_window_get_has_resize_grip:
5486 * @window: a #GtkWindow
5488 * Determines whether the window may have a resize grip.
5490 * Returns: %TRUE if the window has a resize grip.
5495 gtk_window_get_has_resize_grip (GtkWindow *window)
5497 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5499 return window->priv->has_resize_grip;
5503 * gtk_window_get_resize_grip_area:
5504 * @window: a #GtkWindow
5505 * @rect: a pointer to a #GdkRectangle which we should store the
5508 * If a window has a resize grip, this will retrieve the grip
5509 * position, width and height into the specified #GdkRectangle.
5511 * Returns: %TRUE if the resize grip's area was retrieved.
5516 gtk_window_get_resize_grip_area (GtkWindow *window,
5519 GtkWidget *widget = GTK_WIDGET (window);
5520 GtkAllocation allocation;
5524 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5526 if (!window->priv->has_resize_grip)
5529 gtk_widget_get_allocation (widget, &allocation);
5531 gtk_widget_style_get (widget,
5532 "resize-grip-width", &grip_width,
5533 "resize-grip-height", &grip_height,
5536 if (grip_width > allocation.width)
5537 grip_width = allocation.width;
5539 if (grip_height > allocation.height)
5540 grip_height = allocation.height;
5542 rect->width = grip_width;
5543 rect->height = grip_height;
5544 rect->y = allocation.y + allocation.height - grip_height;
5546 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5547 rect->x = allocation.x + allocation.width - grip_width;
5549 rect->x = allocation.x;
5554 /* the accel_key and accel_mods fields of the key have to be setup
5555 * upon calling this function. it'll then return whether that key
5556 * is at all used as accelerator, and if so will OR in the
5557 * accel_flags member of the key.
5560 _gtk_window_query_nonaccels (GtkWindow *window,
5562 GdkModifierType accel_mods)
5564 GtkWindowPrivate *priv;
5566 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5568 priv = window->priv;
5570 /* movement keys are considered locked accels */
5573 static const guint bindings[] = {
5574 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,
5575 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,
5579 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5580 if (bindings[i] == accel_key)
5584 /* mnemonics are considered locked accels */
5585 if (accel_mods == priv->mnemonic_modifier)
5587 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5588 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5596 * gtk_window_propagate_key_event:
5597 * @window: a #GtkWindow
5598 * @event: a #GdkEventKey
5600 * Propagate a key press or release event to the focus widget and
5601 * up the focus container chain until a widget handles @event.
5602 * This is normally called by the default ::key_press_event and
5603 * ::key_release_event handlers for toplevel windows,
5604 * however in some cases it may be useful to call this directly when
5605 * overriding the standard key handling for a toplevel window.
5607 * Return value: %TRUE if a widget in the focus chain handled the event.
5612 gtk_window_propagate_key_event (GtkWindow *window,
5615 GtkWindowPrivate *priv;
5616 gboolean handled = FALSE;
5617 GtkWidget *widget, *focus;
5619 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5621 priv = window->priv;
5622 widget = GTK_WIDGET (window);
5624 focus = priv->focus_widget;
5626 g_object_ref (focus);
5629 focus && focus != widget &&
5630 gtk_widget_get_toplevel (focus) == widget)
5634 if (gtk_widget_is_sensitive (focus))
5635 handled = gtk_widget_event (focus, (GdkEvent*) event);
5637 parent = gtk_widget_get_parent (focus);
5639 g_object_ref (parent);
5641 g_object_unref (focus);
5647 g_object_unref (focus);
5653 gtk_window_key_press_event (GtkWidget *widget,
5656 GtkWindow *window = GTK_WINDOW (widget);
5657 gboolean handled = FALSE;
5659 /* handle mnemonics and accelerators */
5661 handled = gtk_window_activate_key (window, event);
5663 /* handle focus widget key events */
5665 handled = gtk_window_propagate_key_event (window, event);
5667 /* Chain up, invokes binding set */
5669 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5675 gtk_window_key_release_event (GtkWidget *widget,
5678 GtkWindow *window = GTK_WINDOW (widget);
5679 gboolean handled = FALSE;
5681 /* handle focus widget key events */
5683 handled = gtk_window_propagate_key_event (window, event);
5685 /* Chain up, invokes binding set */
5687 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5693 gtk_window_button_press_event (GtkWidget *widget,
5694 GdkEventButton *event)
5696 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5699 if (event->window == priv->grip_window)
5701 if (get_drag_edge (widget, &edge))
5702 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5716 gtk_window_real_activate_default (GtkWindow *window)
5718 gtk_window_activate_default (window);
5722 gtk_window_real_activate_focus (GtkWindow *window)
5724 gtk_window_activate_focus (window);
5728 gtk_window_enter_notify_event (GtkWidget *widget,
5729 GdkEventCrossing *event)
5735 gtk_window_leave_notify_event (GtkWidget *widget,
5736 GdkEventCrossing *event)
5742 do_focus_change (GtkWidget *widget,
5746 GdkDeviceManager *device_manager;
5749 g_object_ref (widget);
5751 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5752 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5753 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5754 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5756 for (d = devices; d; d = d->next)
5758 GdkDevice *dev = d->data;
5761 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5764 /* Skip non-master keyboards that haven't
5765 * selected for events from this window
5767 window = gtk_widget_get_window (widget);
5768 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5769 window && !gdk_window_get_device_events (window, dev))
5772 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5774 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5775 fevent->focus_change.window = window;
5777 g_object_ref (window);
5778 fevent->focus_change.in = in;
5779 gdk_event_set_device (fevent, dev);
5781 gtk_widget_send_focus_change (widget, fevent);
5783 gdk_event_free (fevent);
5786 g_list_free (devices);
5787 g_object_unref (widget);
5791 gtk_window_focus_in_event (GtkWidget *widget,
5792 GdkEventFocus *event)
5794 GtkWindow *window = GTK_WINDOW (widget);
5796 /* It appears spurious focus in events can occur when
5797 * the window is hidden. So we'll just check to see if
5798 * the window is visible before actually handling the
5801 if (gtk_widget_get_visible (widget))
5803 _gtk_window_set_has_toplevel_focus (window, TRUE);
5804 _gtk_window_set_is_active (window, TRUE);
5811 gtk_window_focus_out_event (GtkWidget *widget,
5812 GdkEventFocus *event)
5814 GtkWindow *window = GTK_WINDOW (widget);
5815 gboolean auto_mnemonics;
5817 _gtk_window_set_has_toplevel_focus (window, FALSE);
5818 _gtk_window_set_is_active (window, FALSE);
5820 /* set the mnemonic-visible property to false */
5821 g_object_get (gtk_widget_get_settings (widget),
5822 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5824 gtk_window_set_mnemonics_visible (window, FALSE);
5829 static GdkAtom atom_rcfiles = GDK_NONE;
5830 static GdkAtom atom_iconthemes = GDK_NONE;
5833 send_client_message_to_embedded_windows (GtkWidget *widget,
5834 GdkAtom message_type)
5836 GList *embedded_windows;
5838 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5839 if (embedded_windows)
5841 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5844 for (i = 0; i < 5; i++)
5845 send_event->client.data.l[i] = 0;
5846 send_event->client.data_format = 32;
5847 send_event->client.message_type = message_type;
5849 while (embedded_windows)
5851 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5852 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5853 embedded_windows = embedded_windows->next;
5856 gdk_event_free (send_event);
5861 gtk_window_client_event (GtkWidget *widget,
5862 GdkEventClient *event)
5866 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5867 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5870 if (event->message_type == atom_rcfiles)
5872 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5873 gtk_style_context_reset_widgets (gtk_widget_get_screen (widget));
5876 if (event->message_type == atom_iconthemes)
5878 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5879 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5886 gtk_window_check_resize (GtkContainer *container)
5888 if (gtk_widget_get_visible (GTK_WIDGET (container)))
5889 gtk_window_move_resize (GTK_WINDOW (container));
5893 gtk_window_focus (GtkWidget *widget,
5894 GtkDirectionType direction)
5896 GtkWindowPrivate *priv;
5899 GtkContainer *container;
5901 GtkWidget *old_focus_child;
5904 container = GTK_CONTAINER (widget);
5905 window = GTK_WINDOW (widget);
5906 priv = window->priv;
5907 bin = GTK_BIN (widget);
5909 old_focus_child = gtk_container_get_focus_child (container);
5911 /* We need a special implementation here to deal properly with wrapping
5912 * around in the tab chain without the danger of going into an
5915 if (old_focus_child)
5917 if (gtk_widget_child_focus (old_focus_child, direction))
5921 if (priv->focus_widget)
5923 if (direction == GTK_DIR_LEFT ||
5924 direction == GTK_DIR_RIGHT ||
5925 direction == GTK_DIR_UP ||
5926 direction == GTK_DIR_DOWN)
5931 /* Wrapped off the end, clear the focus setting for the toplpevel */
5932 parent = gtk_widget_get_parent (priv->focus_widget);
5935 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5936 parent = gtk_widget_get_parent (parent);
5939 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5942 /* Now try to focus the first widget in the window */
5943 child = gtk_bin_get_child (bin);
5946 if (gtk_widget_child_focus (child, direction))
5954 gtk_window_move_focus (GtkWidget *widget,
5955 GtkDirectionType dir)
5957 gtk_widget_child_focus (widget, dir);
5959 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
5960 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
5964 gtk_window_real_set_focus (GtkWindow *window,
5967 GtkWindowPrivate *priv = window->priv;
5968 GtkWidget *old_focus = priv->focus_widget;
5969 gboolean had_default = FALSE;
5970 gboolean focus_had_default = FALSE;
5971 gboolean old_focus_had_default = FALSE;
5975 g_object_ref (old_focus);
5976 g_object_freeze_notify (G_OBJECT (old_focus));
5977 old_focus_had_default = gtk_widget_has_default (old_focus);
5981 g_object_ref (focus);
5982 g_object_freeze_notify (G_OBJECT (focus));
5983 focus_had_default = gtk_widget_has_default (focus);
5986 if (priv->default_widget)
5987 had_default = gtk_widget_has_default (priv->default_widget);
5989 if (priv->focus_widget)
5991 if (gtk_widget_get_receives_default (priv->focus_widget) &&
5992 (priv->focus_widget != priv->default_widget))
5994 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
5995 gtk_widget_queue_draw (priv->focus_widget);
5997 if (priv->default_widget)
5998 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6001 priv->focus_widget = NULL;
6003 if (priv->has_focus)
6004 do_focus_change (old_focus, FALSE);
6006 g_object_notify (G_OBJECT (old_focus), "is-focus");
6009 /* The above notifications may have set a new focus widget,
6010 * if so, we don't want to override it.
6012 if (focus && !priv->focus_widget)
6014 priv->focus_widget = focus;
6016 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6017 (priv->focus_widget != priv->default_widget))
6019 if (gtk_widget_get_can_default (priv->focus_widget))
6020 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6022 if (priv->default_widget)
6023 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6026 if (priv->has_focus)
6027 do_focus_change (priv->focus_widget, TRUE);
6029 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6032 /* If the default widget changed, a redraw will have been queued
6033 * on the old and new default widgets by gtk_window_set_default(), so
6034 * we only have to worry about the case where it didn't change.
6035 * We'll sometimes queue a draw twice on the new widget but that
6038 if (priv->default_widget &&
6039 (had_default != gtk_widget_has_default (priv->default_widget)))
6040 gtk_widget_queue_draw (priv->default_widget);
6044 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6045 gtk_widget_queue_draw (old_focus);
6047 g_object_thaw_notify (G_OBJECT (old_focus));
6048 g_object_unref (old_focus);
6052 if (focus_had_default != gtk_widget_has_default (focus))
6053 gtk_widget_queue_draw (focus);
6055 g_object_thaw_notify (G_OBJECT (focus));
6056 g_object_unref (focus);
6062 gtk_window_get_preferred_width (GtkWidget *widget,
6070 window = GTK_WINDOW (widget);
6071 child = gtk_bin_get_child (GTK_BIN (window));
6073 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6074 *minimum_size = border_width * 2;
6075 *natural_size = border_width * 2;
6077 if (child && gtk_widget_get_visible (child))
6079 gint child_min, child_nat;
6080 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6082 *minimum_size += child_min;
6083 *natural_size += child_nat;
6088 gtk_window_get_preferred_height (GtkWidget *widget,
6096 window = GTK_WINDOW (widget);
6097 child = gtk_bin_get_child (GTK_BIN (window));
6099 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6100 *minimum_size = border_width * 2;
6101 *natural_size = border_width * 2;
6103 if (child && gtk_widget_get_visible (child))
6105 gint child_min, child_nat;
6106 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6108 *minimum_size += child_min;
6109 *natural_size += child_nat;
6115 * _gtk_window_unset_focus_and_default:
6116 * @window: a #GtkWindow
6117 * @widget: a widget inside of @window
6119 * Checks whether the focus and default widgets of @window are
6120 * @widget or a descendent of @widget, and if so, unset them.
6123 _gtk_window_unset_focus_and_default (GtkWindow *window,
6127 GtkWindowPrivate *priv = window->priv;
6131 g_object_ref (window);
6132 g_object_ref (widget);
6134 parent = gtk_widget_get_parent (widget);
6135 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6137 child = priv->focus_widget;
6139 while (child && child != widget)
6140 child = gtk_widget_get_parent (child);
6142 if (child == widget)
6143 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6146 child = priv->default_widget;
6148 while (child && child != widget)
6149 child = gtk_widget_get_parent (child);
6151 if (child == widget)
6152 gtk_window_set_default (window, NULL);
6154 g_object_unref (widget);
6155 g_object_unref (window);
6158 /*********************************
6159 * Functions related to resizing *
6160 *********************************/
6163 geometry_size_to_pixels (GdkGeometry *geometry,
6168 gint base_width = 0;
6169 gint base_height = 0;
6171 gint min_height = 0;
6173 gint height_inc = 1;
6175 if (flags & GDK_HINT_BASE_SIZE)
6177 base_width = geometry->base_width;
6178 base_height = geometry->base_height;
6180 if (flags & GDK_HINT_MIN_SIZE)
6182 min_width = geometry->min_width;
6183 min_height = geometry->min_height;
6185 if (flags & GDK_HINT_RESIZE_INC)
6187 width_inc = geometry->width_inc;
6188 height_inc = geometry->height_inc;
6192 *width = MAX (*width * width_inc + base_width, min_width);
6194 *height = MAX (*height * height_inc + base_height, min_height);
6197 /* This function doesn't constrain to geometry hints */
6199 gtk_window_compute_configure_request_size (GtkWindow *window,
6200 GdkGeometry *geometry,
6205 GtkWindowPrivate *priv = window->priv;
6206 GtkRequisition requisition;
6207 GtkWindowGeometryInfo *info;
6211 * - we've done a size request
6214 widget = GTK_WIDGET (window);
6216 info = gtk_window_get_geometry_info (window, FALSE);
6218 if (priv->need_default_size)
6220 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6222 /* Default to requisition */
6223 *width = requisition.width;
6224 *height = requisition.height;
6226 /* If window is empty so requests 0, default to random nonzero size */
6227 if (*width == 0 && *height == 0)
6233 /* Override requisition with default size */
6237 if (info->default_width > 0)
6238 *width = info->default_width;
6239 if (info->default_height > 0)
6240 *height = info->default_height;
6242 if (info->default_is_geometry)
6243 geometry_size_to_pixels (geometry, flags,
6244 info->default_width > 0 ? width : NULL,
6245 info->default_height > 0 ? height : NULL);
6250 GtkAllocation allocation;
6252 gtk_widget_get_allocation (widget, &allocation);
6254 /* Default to keeping current size */
6255 *width = allocation.width;
6256 *height = allocation.height;
6259 /* Override any size with gtk_window_resize() values */
6262 if (info->resize_width > 0)
6263 *width = info->resize_width;
6264 if (info->resize_height > 0)
6265 *height = info->resize_height;
6267 if (info->resize_is_geometry)
6268 geometry_size_to_pixels (geometry, flags,
6269 info->resize_width > 0 ? width : NULL,
6270 info->resize_height > 0 ? height : NULL);
6273 /* Don't ever request zero width or height, its not supported by
6274 gdk. The size allocation code will round it to 1 anyway but if
6275 we do it then the value returned from this function will is
6276 not comparable to the size allocation read from the GtkWindow. */
6277 *width = MAX (*width, 1);
6278 *height = MAX (*height, 1);
6281 static GtkWindowPosition
6282 get_effective_position (GtkWindow *window)
6284 GtkWindowPrivate *priv = window->priv;
6285 GtkWindowPosition pos = priv->position;
6287 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6288 (priv->transient_parent == NULL ||
6289 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6290 pos = GTK_WIN_POS_NONE;
6296 get_center_monitor_of_window (GtkWindow *window)
6298 /* We could try to sort out the relative positions of the monitors and
6299 * stuff, or we could just be losers and assume you have a row
6300 * or column of monitors.
6302 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6306 get_monitor_containing_pointer (GtkWindow *window)
6310 GdkScreen *window_screen;
6311 GdkScreen *pointer_screen;
6312 GdkDisplay *display;
6313 GdkDeviceManager *device_manager;
6316 window_screen = gtk_window_check_screen (window);
6317 display = gdk_screen_get_display (window_screen);
6318 device_manager = gdk_display_get_device_manager (display);
6319 pointer = gdk_device_manager_get_client_pointer (device_manager);
6321 gdk_device_get_position (pointer,
6325 if (pointer_screen == window_screen)
6326 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6334 center_window_on_monitor (GtkWindow *window,
6340 GdkRectangle monitor;
6343 monitor_num = get_monitor_containing_pointer (window);
6345 if (monitor_num == -1)
6346 monitor_num = get_center_monitor_of_window (window);
6348 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6349 monitor_num, &monitor);
6351 *x = (monitor.width - w) / 2 + monitor.x;
6352 *y = (monitor.height - h) / 2 + monitor.y;
6354 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6355 * and WM decorations.
6369 if (extent > clamp_extent)
6371 *base = clamp_base + clamp_extent/2 - extent/2;
6372 else if (*base < clamp_base)
6374 else if (*base + extent > clamp_base + clamp_extent)
6375 *base = clamp_base + clamp_extent - extent;
6379 clamp_window_to_rectangle (gint *x,
6383 const GdkRectangle *rect)
6385 #ifdef DEBUGGING_OUTPUT
6386 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);
6389 /* If it is too large, center it. If it fits on the monitor but is
6390 * partially outside, move it to the closest edge. Do this
6391 * separately in x and y directions.
6393 clamp (x, w, rect->x, rect->width);
6394 clamp (y, h, rect->y, rect->height);
6395 #ifdef DEBUGGING_OUTPUT
6396 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6402 gtk_window_compute_configure_request (GtkWindow *window,
6403 GdkRectangle *request,
6404 GdkGeometry *geometry,
6407 GtkWindowPrivate *priv = window->priv;
6408 GdkGeometry new_geometry;
6412 GtkWindowPosition pos;
6413 GtkWidget *parent_widget;
6414 GtkWindowGeometryInfo *info;
6418 widget = GTK_WIDGET (window);
6420 screen = gtk_window_check_screen (window);
6422 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6423 gtk_window_compute_configure_request_size (window,
6424 &new_geometry, new_flags,
6425 (guint *)&w, (guint *)&h);
6427 gtk_window_constrain_size (window,
6428 &new_geometry, new_flags,
6432 parent_widget = (GtkWidget*) priv->transient_parent;
6434 pos = get_effective_position (window);
6435 info = gtk_window_get_geometry_info (window, FALSE);
6437 /* by default, don't change position requested */
6440 x = info->last.configure_request.x;
6441 y = info->last.configure_request.y;
6450 if (priv->need_default_position)
6453 /* FIXME this all interrelates with window gravity.
6454 * For most of them I think we want to set GRAVITY_CENTER.
6456 * Not sure how to go about that.
6461 /* here we are only handling CENTER_ALWAYS
6462 * as it relates to default positioning,
6463 * where it's equivalent to simply CENTER
6465 case GTK_WIN_POS_CENTER_ALWAYS:
6466 case GTK_WIN_POS_CENTER:
6467 center_window_on_monitor (window, w, h, &x, &y);
6470 case GTK_WIN_POS_CENTER_ON_PARENT:
6472 GtkAllocation allocation;
6473 GdkWindow *gdk_window;
6475 GdkRectangle monitor;
6478 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6480 gdk_window = gtk_widget_get_window (parent_widget);
6482 if (gdk_window != NULL)
6483 monitor_num = gdk_screen_get_monitor_at_window (screen,
6488 gdk_window_get_origin (gdk_window,
6491 gtk_widget_get_allocation (parent_widget, &allocation);
6492 x = ox + (allocation.width - w) / 2;
6493 y = oy + (allocation.height - h) / 2;
6495 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6496 * WM decorations. If parent wasn't on a monitor, just
6499 if (monitor_num >= 0)
6501 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6502 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6507 case GTK_WIN_POS_MOUSE:
6509 gint screen_width = gdk_screen_get_width (screen);
6510 gint screen_height = gdk_screen_get_height (screen);
6512 GdkRectangle monitor;
6513 GdkDisplay *display;
6514 GdkDeviceManager *device_manager;
6516 GdkScreen *pointer_screen;
6519 display = gdk_screen_get_display (screen);
6520 device_manager = gdk_display_get_device_manager (display);
6521 pointer = gdk_device_manager_get_client_pointer (device_manager);
6523 gdk_device_get_position (pointer,
6527 if (pointer_screen == screen)
6528 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6534 x = CLAMP (x, 0, screen_width - w);
6535 y = CLAMP (y, 0, screen_height - h);
6537 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6538 * WM decorations. Don't try to figure out what's going
6539 * on if the mouse wasn't inside a monitor.
6541 if (monitor_num >= 0)
6543 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6544 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6552 } /* if (priv->need_default_position) */
6554 if (priv->need_default_position && info &&
6555 info->initial_pos_set)
6557 x = info->initial_x;
6558 y = info->initial_y;
6559 gtk_window_constrain_position (window, w, h, &x, &y);
6565 request->height = h;
6568 *geometry = new_geometry;
6574 gtk_window_constrain_position (GtkWindow *window,
6580 GtkWindowPrivate *priv = window->priv;
6582 /* See long comments in gtk_window_move_resize()
6583 * on when it's safe to call this function.
6585 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6587 gint center_x, center_y;
6589 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6597 gtk_window_move_resize (GtkWindow *window)
6601 * First we determine whether any information has changed that would
6602 * cause us to revise our last configure request. If we would send
6603 * a different configure request from last time, then
6604 * configure_request_size_changed = TRUE or
6605 * configure_request_pos_changed = TRUE. configure_request_size_changed
6606 * may be true due to new hints, a gtk_window_resize(), or whatever.
6607 * configure_request_pos_changed may be true due to gtk_window_set_position()
6608 * or gtk_window_move().
6610 * If the configure request has changed, we send off a new one. To
6611 * ensure GTK+ invariants are maintained (resize queue does what it
6612 * should), we go ahead and size_allocate the requested size in this
6615 * If the configure request has not changed, we don't ever resend
6616 * it, because it could mean fighting the user or window manager.
6619 * To prepare the configure request, we come up with a base size/pos:
6620 * - the one from gtk_window_move()/gtk_window_resize()
6621 * - else default_width, default_height if we haven't ever
6623 * - else the size request if we haven't ever been mapped,
6624 * as a substitute default size
6625 * - else the current size of the window, as received from
6626 * configure notifies (i.e. the current allocation)
6628 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6629 * the position request to be centered.
6631 GtkWindowPrivate *priv = window->priv;
6632 GtkAllocation allocation;
6634 GtkContainer *container;
6635 GtkWindowGeometryInfo *info;
6636 GdkGeometry new_geometry;
6637 GdkWindow *gdk_window;
6639 GdkRectangle new_request;
6640 gboolean configure_request_size_changed;
6641 gboolean configure_request_pos_changed;
6642 gboolean hints_changed; /* do we need to send these again */
6643 GtkWindowLastGeometryInfo saved_last_info;
6645 widget = GTK_WIDGET (window);
6646 gdk_window = gtk_widget_get_window (widget);
6647 container = GTK_CONTAINER (widget);
6648 info = gtk_window_get_geometry_info (window, TRUE);
6650 configure_request_size_changed = FALSE;
6651 configure_request_pos_changed = FALSE;
6653 gtk_window_compute_configure_request (window, &new_request,
6654 &new_geometry, &new_flags);
6656 /* This check implies the invariant that we never set info->last
6657 * without setting the hints and sending off a configure request.
6659 * If we change info->last without sending the request, we may
6662 if (info->last.configure_request.x != new_request.x ||
6663 info->last.configure_request.y != new_request.y)
6664 configure_request_pos_changed = TRUE;
6666 if ((info->last.configure_request.width != new_request.width ||
6667 info->last.configure_request.height != new_request.height))
6668 configure_request_size_changed = TRUE;
6670 hints_changed = FALSE;
6672 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6673 &new_geometry, new_flags))
6675 hints_changed = TRUE;
6678 /* Position Constraints
6679 * ====================
6681 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6682 * a default. The other POS_ values are used only when the
6683 * window is shown, not after that.
6685 * However, we can't implement a position constraint as
6686 * "anytime the window size changes, center the window"
6687 * because this may well end up fighting the WM or user. In
6688 * fact it gets in an infinite loop with at least one WM.
6690 * Basically, applications are in no way in a position to
6691 * constrain the position of a window, with one exception:
6692 * override redirect windows. (Really the intended purpose
6693 * of CENTER_ALWAYS anyhow, I would think.)
6695 * So the way we implement this "constraint" is to say that when WE
6696 * cause a move or resize, i.e. we make a configure request changing
6697 * window size, we recompute the CENTER_ALWAYS position to reflect
6698 * the new window size, and include it in our request. Also, if we
6699 * just turned on CENTER_ALWAYS we snap to center with a new
6700 * request. Otherwise, if we are just NOTIFIED of a move or resize
6701 * done by someone else e.g. the window manager, we do NOT send a
6702 * new configure request.
6704 * For override redirect windows, this works fine; all window
6705 * sizes are from our configure requests. For managed windows,
6706 * it is at least semi-sane, though who knows what the
6707 * app author is thinking.
6710 /* This condition should be kept in sync with the condition later on
6711 * that determines whether we send a configure request. i.e. we
6712 * should do this position constraining anytime we were going to
6713 * send a configure request anyhow, plus when constraints have
6716 if (configure_request_pos_changed ||
6717 configure_request_size_changed ||
6719 info->position_constraints_changed)
6721 /* We request the constrained position if:
6722 * - we were changing position, and need to clamp
6723 * the change to the constraint
6724 * - we're changing the size anyway
6725 * - set_position() was called to toggle CENTER_ALWAYS on
6728 gtk_window_constrain_position (window,
6734 /* Update whether we need to request a move */
6735 if (info->last.configure_request.x != new_request.x ||
6736 info->last.configure_request.y != new_request.y)
6737 configure_request_pos_changed = TRUE;
6739 configure_request_pos_changed = FALSE;
6743 if (priv->type == GTK_WINDOW_TOPLEVEL)
6745 int notify_x, notify_y;
6747 /* this is the position from the last configure notify */
6748 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6750 g_message ("--- %s ---\n"
6751 "last : %d,%d\t%d x %d\n"
6752 "this : %d,%d\t%d x %d\n"
6753 "alloc : %d,%d\t%d x %d\n"
6755 "resize: \t%d x %d\n"
6756 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6757 "configure_notify_received: %d\n"
6758 "configure_request_count: %d\n"
6759 "position_constraints_changed: %d\n",
6760 priv->title ? priv->title : "(no title)",
6761 info->last.configure_request.x,
6762 info->last.configure_request.y,
6763 info->last.configure_request.width,
6764 info->last.configure_request.height,
6770 widget->allocation.width,
6771 widget->allocation.height,
6772 widget->requisition.width,
6773 widget->requisition.height,
6775 info->resize_height,
6776 configure_request_pos_changed,
6777 configure_request_size_changed,
6779 priv->configure_notify_received,
6780 priv->configure_request_count,
6781 info->position_constraints_changed);
6785 saved_last_info = info->last;
6786 info->last.geometry = new_geometry;
6787 info->last.flags = new_flags;
6788 info->last.configure_request = new_request;
6790 /* need to set PPosition so the WM will look at our position,
6791 * but we don't want to count PPosition coming and going as a hints
6792 * change for future iterations. So we saved info->last prior to
6796 /* Also, if the initial position was explicitly set, then we always
6797 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6801 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6802 * this is an initial map
6805 if ((configure_request_pos_changed ||
6806 info->initial_pos_set ||
6807 (priv->need_default_position &&
6808 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6809 (new_flags & GDK_HINT_POS) == 0)
6811 new_flags |= GDK_HINT_POS;
6812 hints_changed = TRUE;
6815 /* Set hints if necessary
6818 gdk_window_set_geometry_hints (gdk_window,
6822 gtk_widget_get_allocation (widget, &allocation);
6824 /* handle resizing/moving and widget tree allocation
6826 if (priv->configure_notify_received)
6828 /* If we have received a configure event since
6829 * the last time in this function, we need to
6830 * accept our new size and size_allocate child widgets.
6831 * (see gtk_window_configure_event() for more details).
6833 * 1 or more configure notifies may have been received.
6834 * Also, configure_notify_received will only be TRUE
6835 * if all expected configure notifies have been received
6836 * (one per configure request), as an optimization.
6839 priv->configure_notify_received = FALSE;
6841 /* gtk_window_configure_event() filled in widget->allocation */
6842 gtk_widget_size_allocate (widget, &allocation);
6844 set_grip_position (window);
6845 update_grip_visibility (window);
6847 gdk_window_process_updates (gdk_window, TRUE);
6849 gdk_window_configure_finished (gdk_window);
6851 /* If the configure request changed, it means that
6853 * 1) coincidentally changed hints or widget properties
6854 * impacting the configure request before getting
6855 * a configure notify, or
6856 * 2) some broken widget is changing its size request
6857 * during size allocation, resulting in
6858 * a false appearance of changed configure request.
6860 * For 1), we could just go ahead and ask for the
6861 * new size right now, but doing that for 2)
6862 * might well be fighting the user (and can even
6863 * trigger a loop). Since we really don't want to
6864 * do that, we requeue a resize in hopes that
6865 * by the time it gets handled, the child has seen
6866 * the light and is willing to go along with the
6867 * new size. (this happens for the zvt widget, since
6868 * the size_allocate() above will have stored the
6869 * requisition corresponding to the new size in the
6872 * This doesn't buy us anything for 1), but it shouldn't
6873 * hurt us too badly, since it is what would have
6874 * happened if we had gotten the configure event before
6875 * the new size had been set.
6878 if (configure_request_size_changed ||
6879 configure_request_pos_changed)
6881 /* Don't change the recorded last info after all, because we
6882 * haven't actually updated to the new info yet - we decided
6883 * to postpone our configure request until later.
6885 info->last = saved_last_info;
6887 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6890 return; /* Bail out, we didn't really process the move/resize */
6892 else if ((configure_request_size_changed || hints_changed) &&
6893 (allocation.width != new_request.width || allocation.height != new_request.height))
6896 /* We are in one of the following situations:
6897 * A. configure_request_size_changed
6898 * our requisition has changed and we need a different window size,
6899 * so we request it from the window manager.
6900 * B. !configure_request_size_changed && hints_changed
6901 * the window manager rejects our size, but we have just changed the
6902 * window manager hints, so there's a chance our request will
6903 * be honoured this time, so we try again.
6905 * However, if the new requisition is the same as the current allocation,
6906 * we don't request it again, since we won't get a ConfigureNotify back from
6907 * the window manager unless it decides to change our requisition. If
6908 * we don't get the ConfigureNotify back, the resize queue will never be run.
6911 /* Now send the configure request */
6912 if (configure_request_pos_changed)
6914 gdk_window_move_resize (gdk_window,
6915 new_request.x, new_request.y,
6916 new_request.width, new_request.height);
6918 else /* only size changed */
6920 gdk_window_resize (gdk_window,
6921 new_request.width, new_request.height);
6924 if (priv->type == GTK_WINDOW_POPUP)
6926 GtkAllocation allocation;
6928 /* Directly size allocate for override redirect (popup) windows. */
6931 allocation.width = new_request.width;
6932 allocation.height = new_request.height;
6934 gtk_widget_size_allocate (widget, &allocation);
6936 gdk_window_process_updates (gdk_window, TRUE);
6938 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6939 gtk_widget_queue_draw (widget);
6943 /* Increment the number of have-not-yet-received-notify requests */
6944 priv->configure_request_count += 1;
6945 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
6947 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6948 * configure event in response to our resizing request.
6949 * the configure event will cause a new resize with
6950 * ->configure_notify_received=TRUE.
6951 * until then, we want to
6952 * - discard expose events
6953 * - coalesce resizes for our children
6954 * - defer any window resizes until the configure event arrived
6955 * to achieve this, we queue a resize for the window, but remove its
6956 * resizing handler, so resizing will not be handled from the next
6957 * idle handler but when the configure event arrives.
6959 * FIXME: we should also dequeue the pending redraws here, since
6960 * we handle those ourselves upon ->configure_notify_received==TRUE.
6962 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6964 gtk_widget_queue_resize_no_redraw (widget);
6965 _gtk_container_dequeue_resize_handler (container);
6971 /* Handle any position changes.
6973 if (configure_request_pos_changed)
6975 gdk_window_move (gdk_window,
6976 new_request.x, new_request.y);
6979 /* And run the resize queue.
6981 gtk_container_resize_children (container);
6984 /* We have now processed a move/resize since the last position
6985 * constraint change, setting of the initial position, or resize.
6986 * (Not resetting these flags here can lead to infinite loops for
6987 * GTK_RESIZE_IMMEDIATE containers)
6989 info->position_constraints_changed = FALSE;
6990 info->initial_pos_set = FALSE;
6991 info->resize_width = -1;
6992 info->resize_height = -1;
6995 /* Compare two sets of Geometry hints for equality.
6998 gtk_window_compare_hints (GdkGeometry *geometry_a,
7000 GdkGeometry *geometry_b,
7003 if (flags_a != flags_b)
7006 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7007 (geometry_a->min_width != geometry_b->min_width ||
7008 geometry_a->min_height != geometry_b->min_height))
7011 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7012 (geometry_a->max_width != geometry_b->max_width ||
7013 geometry_a->max_height != geometry_b->max_height))
7016 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7017 (geometry_a->base_width != geometry_b->base_width ||
7018 geometry_a->base_height != geometry_b->base_height))
7021 if ((flags_a & GDK_HINT_ASPECT) &&
7022 (geometry_a->min_aspect != geometry_b->min_aspect ||
7023 geometry_a->max_aspect != geometry_b->max_aspect))
7026 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7027 (geometry_a->width_inc != geometry_b->width_inc ||
7028 geometry_a->height_inc != geometry_b->height_inc))
7031 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7032 geometry_a->win_gravity != geometry_b->win_gravity)
7039 _gtk_window_constrain_size (GtkWindow *window,
7045 GtkWindowPrivate *priv;
7046 GtkWindowGeometryInfo *info;
7048 g_return_if_fail (GTK_IS_WINDOW (window));
7050 priv = window->priv;
7052 info = priv->geometry_info;
7055 GdkWindowHints flags = info->last.flags;
7056 GdkGeometry *geometry = &info->last.geometry;
7058 gtk_window_constrain_size (window,
7069 gtk_window_constrain_size (GtkWindow *window,
7070 GdkGeometry *geometry,
7077 gdk_window_constrain_size (geometry, flags, width, height,
7078 new_width, new_height);
7081 /* Compute the set of geometry hints and flags for a window
7082 * based on the application set geometry, and requisition
7083 * of the window. gtk_widget_get_preferred_size() must have been
7087 gtk_window_compute_hints (GtkWindow *window,
7088 GdkGeometry *new_geometry,
7091 GtkWindowPrivate *priv = window->priv;
7093 gint extra_width = 0;
7094 gint extra_height = 0;
7095 GtkWindowGeometryInfo *geometry_info;
7096 GtkRequisition requisition;
7098 widget = GTK_WIDGET (window);
7100 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7101 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7105 *new_flags = geometry_info->mask;
7106 *new_geometry = geometry_info->geometry;
7113 if (geometry_info && geometry_info->widget)
7115 /* If the geometry widget is set, then the hints really apply to that
7116 * widget. This is pretty much meaningless unless the window layout
7117 * is such that the rest of the window adds fixed size borders to
7118 * the geometry widget. Our job is to figure the size of the borders;
7119 * We do that by asking how big the toplevel would be if the
7120 * geometry widget was *really big*.
7123 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7124 * |GGGGG B| in the border can confuse things
7130 * |AAAAAAAAA | When the geometry widget is large, things are
7131 * |GGGGGGGGGGB| clearer.
7136 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7137 GtkRequisition requisition;
7138 int current_width, current_height;
7140 _gtk_widget_override_size_request (geometry_info->widget,
7141 TEMPORARY_SIZE, TEMPORARY_SIZE,
7142 ¤t_width, ¤t_height);
7143 gtk_widget_get_preferred_size (widget,
7144 &requisition, NULL);
7145 _gtk_widget_restore_size_request (geometry_info->widget,
7146 current_width, current_height);
7148 extra_width = requisition.width - TEMPORARY_SIZE;
7149 extra_height = requisition.height - TEMPORARY_SIZE;
7151 if (extra_width < 0 || extra_width < 0)
7153 g_warning("Toplevel size doesn't seem to directly depend on the "
7154 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7155 "The geometry widget might not be in the window, or it might not "
7156 "be packed into the window appropriately");
7157 extra_width = MAX(extra_width, 0);
7158 extra_height = MAX(extra_height, 0);
7160 #undef TEMPORARY_SIZE
7163 /* We don't want to set GDK_HINT_POS in here, we just set it
7164 * in gtk_window_move_resize() when we want the position
7168 if (*new_flags & GDK_HINT_BASE_SIZE)
7170 new_geometry->base_width += extra_width;
7171 new_geometry->base_height += extra_height;
7175 /* For simplicity, we always set the base hint, even when we
7176 * don't expect it to have any visible effect.
7177 * (Note: geometry_size_to_pixels() depends on this.)
7179 *new_flags |= GDK_HINT_BASE_SIZE;
7181 new_geometry->base_width = extra_width;
7182 new_geometry->base_height = extra_height;
7184 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7185 * base size is the minimum size */
7186 if (*new_flags & GDK_HINT_MIN_SIZE)
7188 if (new_geometry->min_width > 0)
7189 new_geometry->base_width += new_geometry->min_width;
7190 if (new_geometry->min_height > 0)
7191 new_geometry->base_height += new_geometry->min_height;
7195 if (*new_flags & GDK_HINT_MIN_SIZE)
7197 if (new_geometry->min_width < 0)
7198 new_geometry->min_width = requisition.width;
7200 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7202 if (new_geometry->min_height < 0)
7203 new_geometry->min_height = requisition.height;
7205 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7209 *new_flags |= GDK_HINT_MIN_SIZE;
7211 new_geometry->min_width = requisition.width;
7212 new_geometry->min_height = requisition.height;
7215 if (*new_flags & GDK_HINT_MAX_SIZE)
7217 if (new_geometry->max_width < 0)
7218 new_geometry->max_width = requisition.width;
7220 new_geometry->max_width += extra_width;
7222 if (new_geometry->max_height < 0)
7223 new_geometry->max_height = requisition.height;
7225 new_geometry->max_height += extra_height;
7227 else if (!priv->resizable)
7229 *new_flags |= GDK_HINT_MAX_SIZE;
7231 new_geometry->max_width = requisition.width;
7232 new_geometry->max_height = requisition.height;
7235 *new_flags |= GDK_HINT_WIN_GRAVITY;
7236 new_geometry->win_gravity = priv->gravity;
7239 /***********************
7240 * Redrawing functions *
7241 ***********************/
7244 gtk_window_draw (GtkWidget *widget,
7247 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7248 GtkStyleContext *context;
7249 gboolean ret = FALSE;
7251 context = gtk_widget_get_style_context (widget);
7253 gtk_style_context_save (context);
7255 if (!gtk_widget_get_app_paintable (widget))
7257 GtkStateFlags state;
7259 state = gtk_widget_get_state_flags (widget);
7261 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7262 state |= GTK_STATE_FLAG_FOCUSED;
7264 gtk_style_context_set_state (context, state);
7265 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7266 gtk_render_background (context, cr, 0, 0,
7267 gtk_widget_get_allocated_width (widget),
7268 gtk_widget_get_allocated_height (widget));
7271 gtk_style_context_restore (context);
7273 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7274 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7276 if (priv->grip_window != NULL &&
7277 gtk_cairo_should_draw_window (cr, priv->grip_window))
7281 gtk_style_context_save (context);
7284 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7285 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7287 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7288 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7289 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7292 gtk_style_context_restore (context);
7299 * gtk_window_present:
7300 * @window: a #GtkWindow
7302 * Presents a window to the user. This may mean raising the window
7303 * in the stacking order, deiconifying it, moving it to the current
7304 * desktop, and/or giving it the keyboard focus, possibly dependent
7305 * on the user's platform, window manager, and preferences.
7307 * If @window is hidden, this function calls gtk_widget_show()
7310 * This function should be used when the user tries to open a window
7311 * that's already open. Say for example the preferences dialog is
7312 * currently open, and the user chooses Preferences from the menu
7313 * a second time; use gtk_window_present() to move the already-open dialog
7314 * where the user can see it.
7316 * If you are calling this function in response to a user interaction,
7317 * it is preferable to use gtk_window_present_with_time().
7321 gtk_window_present (GtkWindow *window)
7323 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7327 * gtk_window_present_with_time:
7328 * @window: a #GtkWindow
7329 * @timestamp: the timestamp of the user interaction (typically a
7330 * button or key press event) which triggered this call
7332 * Presents a window to the user in response to a user interaction.
7333 * If you need to present a window without a timestamp, use
7334 * gtk_window_present(). See gtk_window_present() for details.
7339 gtk_window_present_with_time (GtkWindow *window,
7343 GdkWindow *gdk_window;
7345 g_return_if_fail (GTK_IS_WINDOW (window));
7347 widget = GTK_WIDGET (window);
7349 if (gtk_widget_get_visible (widget))
7351 gdk_window = gtk_widget_get_window (widget);
7353 g_assert (gdk_window != NULL);
7355 gdk_window_show (gdk_window);
7357 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7358 if (timestamp == GDK_CURRENT_TIME)
7360 #ifdef GDK_WINDOWING_X11
7361 GdkDisplay *display;
7363 display = gtk_widget_get_display (GTK_WIDGET (window));
7364 timestamp = gdk_x11_display_get_user_time (display);
7366 timestamp = gtk_get_current_event_time ();
7370 gdk_window_focus (gdk_window, timestamp);
7374 gtk_widget_show (widget);
7379 * gtk_window_iconify:
7380 * @window: a #GtkWindow
7382 * Asks to iconify (i.e. minimize) the specified @window. Note that
7383 * you shouldn't assume the window is definitely iconified afterward,
7384 * because other entities (e.g. the user or <link
7385 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7386 * again, or there may not be a window manager in which case
7387 * iconification isn't possible, etc. But normally the window will end
7388 * up iconified. Just don't write code that crashes if not.
7390 * It's permitted to call this function before showing a window,
7391 * in which case the window will be iconified before it ever appears
7394 * You can track iconification via the "window-state-event" signal
7399 gtk_window_iconify (GtkWindow *window)
7401 GtkWindowPrivate *priv;
7403 GdkWindow *toplevel;
7405 g_return_if_fail (GTK_IS_WINDOW (window));
7407 priv = window->priv;
7408 widget = GTK_WIDGET (window);
7410 priv->iconify_initially = TRUE;
7412 toplevel = gtk_widget_get_window (widget);
7414 if (toplevel != NULL)
7415 gdk_window_iconify (toplevel);
7419 * gtk_window_deiconify:
7420 * @window: a #GtkWindow
7422 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7423 * that you shouldn't assume the window is definitely deiconified
7424 * afterward, because other entities (e.g. the user or <link
7425 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7426 * again before your code which assumes deiconification gets to run.
7428 * You can track iconification via the "window-state-event" signal
7432 gtk_window_deiconify (GtkWindow *window)
7434 GtkWindowPrivate *priv;
7436 GdkWindow *toplevel;
7438 g_return_if_fail (GTK_IS_WINDOW (window));
7440 priv = window->priv;
7441 widget = GTK_WIDGET (window);
7443 priv->iconify_initially = FALSE;
7445 toplevel = gtk_widget_get_window (widget);
7447 if (toplevel != NULL)
7448 gdk_window_deiconify (toplevel);
7453 * @window: a #GtkWindow
7455 * Asks to stick @window, which means that it will appear on all user
7456 * desktops. Note that you shouldn't assume the window is definitely
7457 * stuck afterward, because other entities (e.g. the user or <link
7458 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7459 * again, and some window managers do not support sticking
7460 * windows. But normally the window will end up stuck. Just don't
7461 * write code that crashes if not.
7463 * It's permitted to call this function before showing a window.
7465 * You can track stickiness via the "window-state-event" signal
7470 gtk_window_stick (GtkWindow *window)
7472 GtkWindowPrivate *priv;
7474 GdkWindow *toplevel;
7476 g_return_if_fail (GTK_IS_WINDOW (window));
7478 priv = window->priv;
7479 widget = GTK_WIDGET (window);
7481 priv->stick_initially = TRUE;
7483 toplevel = gtk_widget_get_window (widget);
7485 if (toplevel != NULL)
7486 gdk_window_stick (toplevel);
7490 * gtk_window_unstick:
7491 * @window: a #GtkWindow
7493 * Asks to unstick @window, which means that it will appear on only
7494 * one of the user's desktops. Note that you shouldn't assume the
7495 * window is definitely unstuck afterward, because other entities
7496 * (e.g. the user or <link linkend="gtk-X11-arch">window
7497 * manager</link>) could stick it again. But normally the window will
7498 * end up stuck. Just don't write code that crashes if not.
7500 * You can track stickiness via the "window-state-event" signal
7505 gtk_window_unstick (GtkWindow *window)
7507 GtkWindowPrivate *priv;
7509 GdkWindow *toplevel;
7511 g_return_if_fail (GTK_IS_WINDOW (window));
7513 priv = window->priv;
7514 widget = GTK_WIDGET (window);
7516 priv->stick_initially = FALSE;
7518 toplevel = gtk_widget_get_window (widget);
7520 if (toplevel != NULL)
7521 gdk_window_unstick (toplevel);
7525 * gtk_window_maximize:
7526 * @window: a #GtkWindow
7528 * Asks to maximize @window, so that it becomes full-screen. Note that
7529 * you shouldn't assume the window is definitely maximized afterward,
7530 * because other entities (e.g. the user or <link
7531 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7532 * again, and not all window managers support maximization. But
7533 * normally the window will end up maximized. Just don't write code
7534 * that crashes if not.
7536 * It's permitted to call this function before showing a window,
7537 * in which case the window will be maximized when it appears onscreen
7540 * You can track maximization via the "window-state-event" signal
7545 gtk_window_maximize (GtkWindow *window)
7547 GtkWindowPrivate *priv;
7549 GdkWindow *toplevel;
7551 g_return_if_fail (GTK_IS_WINDOW (window));
7553 priv = window->priv;
7554 widget = GTK_WIDGET (window);
7556 priv->maximize_initially = TRUE;
7558 toplevel = gtk_widget_get_window (widget);
7560 if (toplevel != NULL)
7561 gdk_window_maximize (toplevel);
7565 * gtk_window_unmaximize:
7566 * @window: a #GtkWindow
7568 * Asks to unmaximize @window. Note that you shouldn't assume the
7569 * window is definitely unmaximized afterward, because other entities
7570 * (e.g. the user or <link linkend="gtk-X11-arch">window
7571 * manager</link>) could maximize it again, and not all window
7572 * managers honor requests to unmaximize. But normally the window will
7573 * end up unmaximized. Just don't write code that crashes if not.
7575 * You can track maximization via the "window-state-event" signal
7580 gtk_window_unmaximize (GtkWindow *window)
7582 GtkWindowPrivate *priv;
7584 GdkWindow *toplevel;
7586 g_return_if_fail (GTK_IS_WINDOW (window));
7588 priv = window->priv;
7589 widget = GTK_WIDGET (window);
7591 priv->maximize_initially = FALSE;
7593 toplevel = gtk_widget_get_window (widget);
7595 if (toplevel != NULL)
7596 gdk_window_unmaximize (toplevel);
7600 * gtk_window_fullscreen:
7601 * @window: a #GtkWindow
7603 * Asks to place @window in the fullscreen state. Note that you
7604 * shouldn't assume the window is definitely full screen afterward,
7605 * because other entities (e.g. the user or <link
7606 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7607 * again, and not all window managers honor requests to fullscreen
7608 * windows. But normally the window will end up fullscreen. Just
7609 * don't write code that crashes if not.
7611 * You can track the fullscreen state via the "window-state-event" signal
7617 gtk_window_fullscreen (GtkWindow *window)
7619 GtkWindowPrivate *priv;
7621 GdkWindow *toplevel;
7623 g_return_if_fail (GTK_IS_WINDOW (window));
7625 priv = window->priv;
7626 widget = GTK_WIDGET (window);
7628 priv->fullscreen_initially = TRUE;
7630 toplevel = gtk_widget_get_window (widget);
7632 if (toplevel != NULL)
7633 gdk_window_fullscreen (toplevel);
7637 * gtk_window_unfullscreen:
7638 * @window: a #GtkWindow
7640 * Asks to toggle off the fullscreen state for @window. Note that you
7641 * shouldn't assume the window is definitely not full screen
7642 * afterward, because other entities (e.g. the user or <link
7643 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7644 * again, and not all window managers honor requests to unfullscreen
7645 * windows. But normally the window will end up restored to its normal
7646 * state. Just don't write code that crashes if not.
7648 * You can track the fullscreen state via the "window-state-event" signal
7654 gtk_window_unfullscreen (GtkWindow *window)
7657 GdkWindow *toplevel;
7658 GtkWindowPrivate *priv;
7660 g_return_if_fail (GTK_IS_WINDOW (window));
7662 priv = window->priv;
7663 widget = GTK_WIDGET (window);
7665 priv->fullscreen_initially = FALSE;
7667 toplevel = gtk_widget_get_window (widget);
7669 if (toplevel != NULL)
7670 gdk_window_unfullscreen (toplevel);
7674 * gtk_window_set_keep_above:
7675 * @window: a #GtkWindow
7676 * @setting: whether to keep @window above other windows
7678 * Asks to keep @window above, so that it stays on top. Note that
7679 * you shouldn't assume the window is definitely above afterward,
7680 * because other entities (e.g. the user or <link
7681 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7682 * and not all window managers support keeping windows above. But
7683 * normally the window will end kept above. Just don't write code
7684 * that crashes if not.
7686 * It's permitted to call this function before showing a window,
7687 * in which case the window will be kept above when it appears onscreen
7690 * You can track the above state via the "window-state-event" signal
7693 * Note that, according to the <ulink
7694 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7695 * Manager Hints</ulink> specification, the above state is mainly meant
7696 * for user preferences and should not be used by applications e.g. for
7697 * drawing attention to their dialogs.
7702 gtk_window_set_keep_above (GtkWindow *window,
7706 GtkWindowPrivate *priv;
7707 GdkWindow *toplevel;
7709 g_return_if_fail (GTK_IS_WINDOW (window));
7711 priv = window->priv;
7712 widget = GTK_WIDGET (window);
7714 priv->above_initially = setting != FALSE;
7716 priv->below_initially = FALSE;
7718 toplevel = gtk_widget_get_window (widget);
7720 if (toplevel != NULL)
7721 gdk_window_set_keep_above (toplevel, setting);
7725 * gtk_window_set_keep_below:
7726 * @window: a #GtkWindow
7727 * @setting: whether to keep @window below other windows
7729 * Asks to keep @window below, so that it stays in bottom. Note that
7730 * you shouldn't assume the window is definitely below afterward,
7731 * because other entities (e.g. the user or <link
7732 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7733 * and not all window managers support putting windows below. But
7734 * normally the window will be kept below. Just don't write code
7735 * that crashes if not.
7737 * It's permitted to call this function before showing a window,
7738 * in which case the window will be kept below when it appears onscreen
7741 * You can track the below state via the "window-state-event" signal
7744 * Note that, according to the <ulink
7745 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7746 * Manager Hints</ulink> specification, the above state is mainly meant
7747 * for user preferences and should not be used by applications e.g. for
7748 * drawing attention to their dialogs.
7753 gtk_window_set_keep_below (GtkWindow *window,
7757 GtkWindowPrivate *priv;
7758 GdkWindow *toplevel;
7760 g_return_if_fail (GTK_IS_WINDOW (window));
7762 priv = window->priv;
7763 widget = GTK_WIDGET (window);
7765 priv->below_initially = setting != FALSE;
7767 priv->above_initially = FALSE;
7769 toplevel = gtk_widget_get_window (widget);
7771 if (toplevel != NULL)
7772 gdk_window_set_keep_below (toplevel, setting);
7776 * gtk_window_set_resizable:
7777 * @window: a #GtkWindow
7778 * @resizable: %TRUE if the user can resize this window
7780 * Sets whether the user can resize a window. Windows are user resizable
7784 gtk_window_set_resizable (GtkWindow *window,
7787 GtkWindowPrivate *priv;
7789 g_return_if_fail (GTK_IS_WINDOW (window));
7791 priv = window->priv;
7793 resizable = (resizable != FALSE);
7795 if (priv->resizable != resizable)
7797 priv->resizable = (resizable != FALSE);
7799 update_grip_visibility (window);
7801 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7803 g_object_notify (G_OBJECT (window), "resizable");
7808 * gtk_window_get_resizable:
7809 * @window: a #GtkWindow
7811 * Gets the value set by gtk_window_set_resizable().
7813 * Return value: %TRUE if the user can resize the window
7816 gtk_window_get_resizable (GtkWindow *window)
7818 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7820 return window->priv->resizable;
7824 * gtk_window_set_gravity:
7825 * @window: a #GtkWindow
7826 * @gravity: window gravity
7828 * Window gravity defines the meaning of coordinates passed to
7829 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7832 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7833 * typically "do what you mean."
7837 gtk_window_set_gravity (GtkWindow *window,
7840 GtkWindowPrivate *priv;
7842 g_return_if_fail (GTK_IS_WINDOW (window));
7844 priv = window->priv;
7846 if (gravity != priv->gravity)
7848 priv->gravity = gravity;
7850 /* gtk_window_move_resize() will adapt gravity
7852 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7854 g_object_notify (G_OBJECT (window), "gravity");
7859 * gtk_window_get_gravity:
7860 * @window: a #GtkWindow
7862 * Gets the value set by gtk_window_set_gravity().
7864 * Return value: (transfer none): window gravity
7867 gtk_window_get_gravity (GtkWindow *window)
7869 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7871 return window->priv->gravity;
7875 * gtk_window_begin_resize_drag:
7876 * @window: a #GtkWindow
7877 * @button: mouse button that initiated the drag
7878 * @edge: position of the resize control
7879 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7880 * @root_y: Y position where the user clicked to initiate the drag
7881 * @timestamp: timestamp from the click event that initiated the drag
7883 * Starts resizing a window. This function is used if an application
7884 * has window resizing controls. When GDK can support it, the resize
7885 * will be done using the standard mechanism for the <link
7886 * linkend="gtk-X11-arch">window manager</link> or windowing
7887 * system. Otherwise, GDK will try to emulate window resizing,
7888 * potentially not all that well, depending on the windowing system.
7892 gtk_window_begin_resize_drag (GtkWindow *window,
7899 GtkWindowPrivate *priv;
7901 GdkWindow *toplevel;
7903 g_return_if_fail (GTK_IS_WINDOW (window));
7904 widget = GTK_WIDGET (window);
7905 g_return_if_fail (gtk_widget_get_visible (widget));
7907 priv = window->priv;
7909 toplevel = gtk_widget_get_window (widget);
7911 gdk_window_begin_resize_drag (toplevel,
7918 * gtk_window_begin_move_drag:
7919 * @window: a #GtkWindow
7920 * @button: mouse button that initiated the drag
7921 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7922 * @root_y: Y position where the user clicked to initiate the drag
7923 * @timestamp: timestamp from the click event that initiated the drag
7925 * Starts moving a window. This function is used if an application has
7926 * window movement grips. When GDK can support it, the window movement
7927 * will be done using the standard mechanism for the <link
7928 * linkend="gtk-X11-arch">window manager</link> or windowing
7929 * system. Otherwise, GDK will try to emulate window movement,
7930 * potentially not all that well, depending on the windowing system.
7934 gtk_window_begin_move_drag (GtkWindow *window,
7940 GtkWindowPrivate *priv;
7942 GdkWindow *toplevel;
7944 g_return_if_fail (GTK_IS_WINDOW (window));
7945 widget = GTK_WIDGET (window);
7946 g_return_if_fail (gtk_widget_get_visible (widget));
7948 priv = window->priv;
7950 toplevel = gtk_widget_get_window (widget);
7952 gdk_window_begin_move_drag (toplevel,
7959 * gtk_window_set_screen:
7960 * @window: a #GtkWindow.
7961 * @screen: a #GdkScreen.
7963 * Sets the #GdkScreen where the @window is displayed; if
7964 * the window is already mapped, it will be unmapped, and
7965 * then remapped on the new screen.
7970 gtk_window_set_screen (GtkWindow *window,
7973 GtkWindowPrivate *priv;
7975 GdkScreen *previous_screen;
7976 gboolean was_mapped;
7978 g_return_if_fail (GTK_IS_WINDOW (window));
7979 g_return_if_fail (GDK_IS_SCREEN (screen));
7981 priv = window->priv;
7983 if (screen == priv->screen)
7986 widget = GTK_WIDGET (window);
7988 previous_screen = priv->screen;
7989 was_mapped = gtk_widget_get_mapped (widget);
7992 gtk_widget_unmap (widget);
7993 if (gtk_widget_get_realized (widget))
7994 gtk_widget_unrealize (widget);
7996 gtk_window_free_key_hash (window);
7997 priv->screen = screen;
7998 gtk_widget_reset_rc_styles (widget);
7999 if (screen != previous_screen)
8001 g_signal_handlers_disconnect_by_func (previous_screen,
8002 gtk_window_on_composited_changed, window);
8003 g_signal_connect (screen, "composited-changed",
8004 G_CALLBACK (gtk_window_on_composited_changed), window);
8006 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8007 _gtk_widget_propagate_composited_changed (widget);
8009 g_object_notify (G_OBJECT (window), "screen");
8012 gtk_widget_map (widget);
8016 gtk_window_on_composited_changed (GdkScreen *screen,
8019 gtk_widget_queue_draw (GTK_WIDGET (window));
8021 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8025 gtk_window_check_screen (GtkWindow *window)
8027 GtkWindowPrivate *priv = window->priv;
8030 return priv->screen;
8033 g_warning ("Screen for GtkWindow not set; you must always set\n"
8034 "a screen for a GtkWindow before using the window");
8040 * gtk_window_get_screen:
8041 * @window: a #GtkWindow.
8043 * Returns the #GdkScreen associated with @window.
8045 * Return value: (transfer none): a #GdkScreen.
8050 gtk_window_get_screen (GtkWindow *window)
8052 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8054 return window->priv->screen;
8058 * gtk_window_is_active:
8059 * @window: a #GtkWindow
8061 * Returns whether the window is part of the current active toplevel.
8062 * (That is, the toplevel window receiving keystrokes.)
8063 * The return value is %TRUE if the window is active toplevel
8064 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8065 * You might use this function if you wanted to draw a widget
8066 * differently in an active window from a widget in an inactive window.
8067 * See gtk_window_has_toplevel_focus()
8069 * Return value: %TRUE if the window part of the current active window.
8074 gtk_window_is_active (GtkWindow *window)
8076 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8078 return window->priv->is_active;
8082 * gtk_window_has_toplevel_focus:
8083 * @window: a #GtkWindow
8085 * Returns whether the input focus is within this GtkWindow.
8086 * For real toplevel windows, this is identical to gtk_window_is_active(),
8087 * but for embedded windows, like #GtkPlug, the results will differ.
8089 * Return value: %TRUE if the input focus is within this GtkWindow
8094 gtk_window_has_toplevel_focus (GtkWindow *window)
8096 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8098 return window->priv->has_toplevel_focus;
8101 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8104 gtk_window_group_init (GtkWindowGroup *group)
8106 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8107 GTK_TYPE_WINDOW_GROUP,
8108 GtkWindowGroupPrivate);
8112 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8114 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8118 * gtk_window_group_new:
8120 * Creates a new #GtkWindowGroup object. Grabs added with
8121 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8123 * Return value: a new #GtkWindowGroup.
8126 gtk_window_group_new (void)
8128 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8132 window_group_cleanup_grabs (GtkWindowGroup *group,
8135 GtkWindowGroupPrivate *priv;
8136 GtkDeviceGrabInfo *info;
8138 GSList *to_remove = NULL;
8142 tmp_list = priv->grabs;
8145 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8146 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8147 tmp_list = tmp_list->next;
8152 gtk_grab_remove (to_remove->data);
8153 g_object_unref (to_remove->data);
8154 to_remove = g_slist_delete_link (to_remove, to_remove);
8157 tmp_list = priv->device_grabs;
8161 info = tmp_list->data;
8163 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8164 to_remove = g_slist_prepend (to_remove, info);
8166 tmp_list = tmp_list->next;
8171 info = to_remove->data;
8173 gtk_device_grab_remove (info->widget, info->device);
8174 to_remove = g_slist_delete_link (to_remove, to_remove);
8179 * gtk_window_group_add_window:
8180 * @window_group: a #GtkWindowGroup
8181 * @window: the #GtkWindow to add
8183 * Adds a window to a #GtkWindowGroup.
8186 gtk_window_group_add_window (GtkWindowGroup *window_group,
8189 GtkWindowPrivate *priv;
8191 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8192 g_return_if_fail (GTK_IS_WINDOW (window));
8194 priv = window->priv;
8196 if (priv->group != window_group)
8198 g_object_ref (window);
8199 g_object_ref (window_group);
8202 gtk_window_group_remove_window (priv->group, window);
8204 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8206 priv->group = window_group;
8208 g_object_unref (window);
8213 * gtk_window_group_remove_window:
8214 * @window_group: a #GtkWindowGroup
8215 * @window: the #GtkWindow to remove
8217 * Removes a window from a #GtkWindowGroup.
8220 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8223 GtkWindowPrivate *priv;
8225 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8226 g_return_if_fail (GTK_IS_WINDOW (window));
8227 priv = window->priv;
8228 g_return_if_fail (priv->group == window_group);
8230 g_object_ref (window);
8232 window_group_cleanup_grabs (window_group, window);
8235 g_object_unref (window_group);
8236 g_object_unref (window);
8240 * gtk_window_group_list_windows:
8241 * @window_group: a #GtkWindowGroup
8243 * Returns a list of the #GtkWindows that belong to @window_group.
8245 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8246 * windows inside the group.
8251 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8253 GList *toplevels, *toplevel, *group_windows;
8255 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8257 group_windows = NULL;
8258 toplevels = gtk_window_list_toplevels ();
8260 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8262 GtkWindow *window = toplevel->data;
8264 if (window_group == window->priv->group)
8265 group_windows = g_list_prepend (group_windows, window);
8268 return g_list_reverse (group_windows);
8272 * gtk_window_get_group:
8273 * @window: (allow-none): a #GtkWindow, or %NULL
8275 * Returns the group for @window or the default group, if
8276 * @window is %NULL or if @window does not have an explicit
8279 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8284 gtk_window_get_group (GtkWindow *window)
8286 if (window && window->priv->group)
8287 return window->priv->group;
8290 static GtkWindowGroup *default_group = NULL;
8293 default_group = gtk_window_group_new ();
8295 return default_group;
8300 * gtk_window_has_group:
8301 * @window: a #GtkWindow
8303 * Returns whether @window has an explicit window group.
8305 * Return value: %TRUE if @window has an explicit window group.
8310 gtk_window_has_group (GtkWindow *window)
8312 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8314 return window->priv->group != NULL;
8318 * gtk_window_group_get_current_grab:
8319 * @window_group: a #GtkWindowGroup
8321 * Gets the current grab widget of the given group,
8322 * see gtk_grab_add().
8324 * Returns: the current grab widget of the group
8329 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8331 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8333 if (window_group->priv->grabs)
8334 return GTK_WIDGET (window_group->priv->grabs->data);
8339 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8342 GtkWindowGroupPrivate *priv;
8344 priv = window_group->priv;
8345 priv->grabs = g_slist_prepend (priv->grabs, widget);
8349 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8352 GtkWindowGroupPrivate *priv;
8354 priv = window_group->priv;
8355 priv->grabs = g_slist_remove (priv->grabs, widget);
8360 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8363 gboolean block_others)
8365 GtkWindowGroupPrivate *priv;
8366 GtkDeviceGrabInfo *info;
8368 priv = window_group->priv;
8370 info = g_slice_new0 (GtkDeviceGrabInfo);
8371 info->widget = widget;
8372 info->device = device;
8373 info->block_others = block_others;
8375 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8379 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8383 GtkWindowGroupPrivate *priv;
8384 GtkDeviceGrabInfo *info;
8385 GSList *list, *node = NULL;
8386 GdkDevice *other_device;
8388 priv = window_group->priv;
8389 other_device = gdk_device_get_associated_device (device);
8390 list = priv->device_grabs;
8396 if (info->widget == widget &&
8397 (info->device == device ||
8398 info->device == other_device))
8411 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8412 g_slice_free (GtkDeviceGrabInfo, info);
8417 * gtk_window_group_get_current_device_grab:
8418 * @window_group: a #GtkWindowGroup
8419 * @device: a #GdkDevice
8421 * Returns the current grab widget for @device, or %NULL if none.
8423 * Returns: The grab widget, or %NULL
8428 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8431 GtkWindowGroupPrivate *priv;
8432 GtkDeviceGrabInfo *info;
8433 GdkDevice *other_device;
8436 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8437 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8439 priv = window_group->priv;
8440 list = priv->device_grabs;
8441 other_device = gdk_device_get_associated_device (device);
8448 if (info->device == device ||
8449 info->device == other_device)
8450 return info->widget;
8457 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8461 GtkWindowGroupPrivate *priv;
8462 GtkDeviceGrabInfo *info;
8463 GdkDevice *other_device;
8466 priv = window_group->priv;
8467 other_device = gdk_device_get_associated_device (device);
8468 list = priv->device_grabs;
8475 /* Look for blocking grabs on other device pairs
8476 * that have the passed widget within the GTK+ grab.
8478 if (info->block_others &&
8479 info->device != device &&
8480 info->device != other_device &&
8481 (info->widget == widget ||
8482 gtk_widget_is_ancestor (widget, info->widget)))
8490 Derived from XParseGeometry() in XFree86
8492 Copyright 1985, 1986, 1987,1998 The Open Group
8494 All Rights Reserved.
8496 The above copyright notice and this permission notice shall be included
8497 in all copies or substantial portions of the Software.
8499 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8500 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8501 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8502 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8503 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8504 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8505 OTHER DEALINGS IN THE SOFTWARE.
8507 Except as contained in this notice, the name of The Open Group shall
8508 not be used in advertising or otherwise to promote the sale, use or
8509 other dealings in this Software without prior written authorization
8510 from The Open Group.
8515 * XParseGeometry parses strings of the form
8516 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8517 * width, height, xoffset, and yoffset are unsigned integers.
8518 * Example: "=80x24+300-49"
8519 * The equal sign is optional.
8520 * It returns a bitmask that indicates which of the four values
8521 * were actually found in the string. For each value found,
8522 * the corresponding argument is updated; for each value
8523 * not found, the corresponding argument is left unchanged.
8526 /* The following code is from Xlib, and is minimally modified, so we
8527 * can track any upstream changes if required. Don't change this
8528 * code. Or if you do, put in a huge comment marking which thing
8533 read_int (gchar *string,
8541 else if (*string == '-')
8547 for (; (*string >= '0') && (*string <= '9'); string++)
8549 result = (result * 10) + (*string - '0');
8561 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8562 * value (x, y, width, height) was found in the parsed string.
8564 #define NoValue 0x0000
8565 #define XValue 0x0001
8566 #define YValue 0x0002
8567 #define WidthValue 0x0004
8568 #define HeightValue 0x0008
8569 #define AllValues 0x000F
8570 #define XNegative 0x0010
8571 #define YNegative 0x0020
8573 /* Try not to reformat/modify, so we can compare/sync with X sources */
8575 gtk_XParseGeometry (const char *string,
8578 unsigned int *width,
8579 unsigned int *height)
8583 unsigned int tempWidth, tempHeight;
8585 char *nextCharacter;
8587 /* These initializations are just to silence gcc */
8593 if ( (string == NULL) || (*string == '\0')) return(mask);
8595 string++; /* ignore possible '=' at beg of geometry spec */
8597 strind = (char *)string;
8598 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8599 tempWidth = read_int(strind, &nextCharacter);
8600 if (strind == nextCharacter)
8602 strind = nextCharacter;
8606 if (*strind == 'x' || *strind == 'X') {
8608 tempHeight = read_int(strind, &nextCharacter);
8609 if (strind == nextCharacter)
8611 strind = nextCharacter;
8612 mask |= HeightValue;
8615 if ((*strind == '+') || (*strind == '-')) {
8616 if (*strind == '-') {
8618 tempX = -read_int(strind, &nextCharacter);
8619 if (strind == nextCharacter)
8621 strind = nextCharacter;
8627 tempX = read_int(strind, &nextCharacter);
8628 if (strind == nextCharacter)
8630 strind = nextCharacter;
8633 if ((*strind == '+') || (*strind == '-')) {
8634 if (*strind == '-') {
8636 tempY = -read_int(strind, &nextCharacter);
8637 if (strind == nextCharacter)
8639 strind = nextCharacter;
8646 tempY = read_int(strind, &nextCharacter);
8647 if (strind == nextCharacter)
8649 strind = nextCharacter;
8655 /* If strind isn't at the end of the string the it's an invalid
8656 geometry specification. */
8658 if (*strind != '\0') return (0);
8664 if (mask & WidthValue)
8666 if (mask & HeightValue)
8667 *height = tempHeight;
8672 * gtk_window_parse_geometry:
8673 * @window: a #GtkWindow
8674 * @geometry: geometry string
8676 * Parses a standard X Window System geometry string - see the
8677 * manual page for X (type 'man X') for details on this.
8678 * gtk_window_parse_geometry() does work on all GTK+ ports
8679 * including Win32 but is primarily intended for an X environment.
8681 * If either a size or a position can be extracted from the
8682 * geometry string, gtk_window_parse_geometry() returns %TRUE
8683 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8684 * to resize/move the window.
8686 * If gtk_window_parse_geometry() returns %TRUE, it will also
8687 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8688 * indicating to the window manager that the size/position of
8689 * the window was user-specified. This causes most window
8690 * managers to honor the geometry.
8692 * Note that for gtk_window_parse_geometry() to work as expected, it has
8693 * to be called when the window has its "final" size, i.e. after calling
8694 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8697 * #include <gtk/gtk.h>
8700 * fill_with_content (GtkWidget *vbox)
8702 * /* fill with content... */
8706 * main (int argc, char *argv[])
8708 * GtkWidget *window, *vbox;
8709 * GdkGeometry size_hints = {
8710 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8713 * gtk_init (&argc, &argv);
8715 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8716 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8718 * gtk_container_add (GTK_CONTAINER (window), vbox);
8719 * fill_with_content (vbox);
8720 * gtk_widget_show_all (vbox);
8722 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8725 * GDK_HINT_MIN_SIZE |
8726 * GDK_HINT_BASE_SIZE |
8727 * GDK_HINT_RESIZE_INC);
8731 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8732 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8735 * gtk_widget_show_all (window);
8742 * Return value: %TRUE if string was parsed successfully
8745 gtk_window_parse_geometry (GtkWindow *window,
8746 const gchar *geometry)
8748 gint result, x = 0, y = 0;
8752 gboolean size_set, pos_set;
8755 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8756 g_return_val_if_fail (geometry != NULL, FALSE);
8758 child = gtk_bin_get_child (GTK_BIN (window));
8759 if (!child || !gtk_widget_get_visible (child))
8760 g_warning ("gtk_window_parse_geometry() called on a window with no "
8761 "visible children; the window should be set up before "
8762 "gtk_window_parse_geometry() is called.");
8764 screen = gtk_window_check_screen (window);
8766 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8769 if ((result & WidthValue) || (result & HeightValue))
8771 gtk_window_set_default_size_internal (window,
8772 TRUE, result & WidthValue ? w : -1,
8773 TRUE, result & HeightValue ? h : -1,
8778 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8780 grav = GDK_GRAVITY_NORTH_WEST;
8782 if ((result & XNegative) && (result & YNegative))
8783 grav = GDK_GRAVITY_SOUTH_EAST;
8784 else if (result & XNegative)
8785 grav = GDK_GRAVITY_NORTH_EAST;
8786 else if (result & YNegative)
8787 grav = GDK_GRAVITY_SOUTH_WEST;
8789 if ((result & XValue) == 0)
8792 if ((result & YValue) == 0)
8795 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8796 grav == GDK_GRAVITY_SOUTH_EAST)
8797 y = gdk_screen_get_height (screen) - h + y;
8799 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8800 grav == GDK_GRAVITY_NORTH_EAST)
8801 x = gdk_screen_get_width (screen) - w + x;
8803 /* we don't let you put a window offscreen; maybe some people would
8804 * prefer to be able to, but it's kind of a bogus thing to do.
8813 if ((result & XValue) || (result & YValue))
8815 gtk_window_set_gravity (window, grav);
8816 gtk_window_move (window, x, y);
8820 if (size_set || pos_set)
8822 /* Set USSize, USPosition hints */
8823 GtkWindowGeometryInfo *info;
8825 info = gtk_window_get_geometry_info (window, TRUE);
8828 info->mask |= GDK_HINT_USER_POS;
8830 info->mask |= GDK_HINT_USER_SIZE;
8837 gtk_window_mnemonic_hash_foreach (guint keyval,
8843 GtkWindowKeysForeachFunc func;
8847 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8851 _gtk_window_keys_foreach (GtkWindow *window,
8852 GtkWindowKeysForeachFunc func,
8856 GtkMnemonicHash *mnemonic_hash;
8860 GtkWindowKeysForeachFunc func;
8864 info.window = window;
8866 info.func_data = func_data;
8868 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8870 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8871 gtk_window_mnemonic_hash_foreach, &info);
8873 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8876 GtkAccelGroup *group = groups->data;
8879 for (i = 0; i < group->priv->n_accels; i++)
8881 GtkAccelKey *key = &group->priv->priv_accels[i].key;
8884 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8887 groups = groups->next;
8892 gtk_window_keys_changed (GtkWindow *window)
8894 gtk_window_free_key_hash (window);
8895 gtk_window_get_key_hash (window);
8898 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8900 struct _GtkWindowKeyEntry
8904 guint is_mnemonic : 1;
8908 window_key_entry_destroy (gpointer data)
8910 g_slice_free (GtkWindowKeyEntry, data);
8914 add_to_key_hash (GtkWindow *window,
8916 GdkModifierType modifiers,
8917 gboolean is_mnemonic,
8920 GtkKeyHash *key_hash = data;
8922 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8924 entry->keyval = keyval;
8925 entry->modifiers = modifiers;
8926 entry->is_mnemonic = is_mnemonic;
8928 /* GtkAccelGroup stores lowercased accelerators. To deal
8929 * with this, if <Shift> was specified, uppercase.
8931 if (modifiers & GDK_SHIFT_MASK)
8933 if (keyval == GDK_KEY_Tab)
8934 keyval = GDK_KEY_ISO_Left_Tab;
8936 keyval = gdk_keyval_to_upper (keyval);
8939 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8943 gtk_window_get_key_hash (GtkWindow *window)
8945 GdkScreen *screen = gtk_window_check_screen (window);
8946 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8951 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8952 (GDestroyNotify)window_key_entry_destroy);
8953 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8954 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8960 gtk_window_free_key_hash (GtkWindow *window)
8962 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8965 _gtk_key_hash_free (key_hash);
8966 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8971 * gtk_window_activate_key:
8972 * @window: a #GtkWindow
8973 * @event: a #GdkEventKey
8975 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8976 * called by the default ::key_press_event handler for toplevel windows,
8977 * however in some cases it may be useful to call this directly when
8978 * overriding the standard key handling for a toplevel window.
8980 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8985 gtk_window_activate_key (GtkWindow *window,
8988 GtkKeyHash *key_hash;
8989 GtkWindowKeyEntry *found_entry = NULL;
8990 gboolean enable_mnemonics;
8991 gboolean enable_accels;
8993 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8994 g_return_val_if_fail (event != NULL, FALSE);
8996 key_hash = gtk_window_get_key_hash (window);
9001 GSList *entries = _gtk_key_hash_lookup (key_hash,
9002 event->hardware_keycode,
9004 gtk_accelerator_get_default_mod_mask (),
9007 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9008 "gtk-enable-mnemonics", &enable_mnemonics,
9009 "gtk-enable-accels", &enable_accels,
9012 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9014 GtkWindowKeyEntry *entry = tmp_list->data;
9015 if (entry->is_mnemonic)
9017 if (enable_mnemonics)
9019 found_entry = entry;
9025 if (enable_accels && !found_entry)
9027 found_entry = entry;
9032 g_slist_free (entries);
9037 if (found_entry->is_mnemonic)
9039 if (enable_mnemonics)
9040 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9041 found_entry->modifiers);
9046 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9047 found_entry->modifiers);
9055 window_update_has_focus (GtkWindow *window)
9057 GtkWindowPrivate *priv = window->priv;
9058 GtkWidget *widget = GTK_WIDGET (window);
9059 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9061 if (has_focus != priv->has_focus)
9063 priv->has_focus = has_focus;
9067 if (priv->focus_widget &&
9068 priv->focus_widget != widget &&
9069 !gtk_widget_has_focus (priv->focus_widget))
9070 do_focus_change (priv->focus_widget, TRUE);
9074 if (priv->focus_widget &&
9075 priv->focus_widget != widget &&
9076 gtk_widget_has_focus (priv->focus_widget))
9077 do_focus_change (priv->focus_widget, FALSE);
9083 * _gtk_window_set_is_active:
9084 * @window: a #GtkWindow
9085 * @is_active: %TRUE if the window is in the currently active toplevel
9087 * Internal function that sets whether the #GtkWindow is part
9088 * of the currently active toplevel window (taking into account inter-process
9092 _gtk_window_set_is_active (GtkWindow *window,
9095 GtkWindowPrivate *priv;
9097 g_return_if_fail (GTK_IS_WINDOW (window));
9099 priv = window->priv;
9101 is_active = is_active != FALSE;
9103 if (is_active != priv->is_active)
9105 priv->is_active = is_active;
9106 window_update_has_focus (window);
9108 g_object_notify (G_OBJECT (window), "is-active");
9113 * _gtk_window_set_is_toplevel:
9114 * @window: a #GtkWindow
9115 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9116 * child of the root window); %FALSE if it is not (for example, for an
9117 * in-process, parented GtkPlug)
9119 * Internal function used by #GtkPlug when it gets parented/unparented by a
9120 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9121 * global list of toplevel windows.
9124 _gtk_window_set_is_toplevel (GtkWindow *window,
9125 gboolean is_toplevel)
9129 widget = GTK_WIDGET (window);
9131 if (gtk_widget_is_toplevel (widget))
9132 g_assert (g_slist_find (toplevel_list, window) != NULL);
9134 g_assert (g_slist_find (toplevel_list, window) == NULL);
9136 if (is_toplevel == gtk_widget_is_toplevel (widget))
9141 _gtk_widget_set_is_toplevel (widget, TRUE);
9142 toplevel_list = g_slist_prepend (toplevel_list, window);
9146 _gtk_widget_set_is_toplevel (widget, FALSE);
9147 toplevel_list = g_slist_remove (toplevel_list, window);
9152 * _gtk_window_set_has_toplevel_focus:
9153 * @window: a #GtkWindow
9154 * @has_toplevel_focus: %TRUE if the in
9156 * Internal function that sets whether the keyboard focus for the
9157 * toplevel window (taking into account inter-process embedding.)
9160 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9161 gboolean has_toplevel_focus)
9163 GtkWindowPrivate *priv;
9165 g_return_if_fail (GTK_IS_WINDOW (window));
9167 priv = window->priv;
9169 has_toplevel_focus = has_toplevel_focus != FALSE;
9171 if (has_toplevel_focus != priv->has_toplevel_focus)
9173 priv->has_toplevel_focus = has_toplevel_focus;
9174 window_update_has_focus (window);
9176 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9181 * gtk_window_set_auto_startup_notification:
9182 * @setting: %TRUE to automatically do startup notification
9184 * By default, after showing the first #GtkWindow, GTK+ calls
9185 * gdk_notify_startup_complete(). Call this function to disable
9186 * the automatic startup notification. You might do this if your
9187 * first window is a splash screen, and you want to delay notification
9188 * until after your real main window has been shown, for example.
9190 * In that example, you would disable startup notification
9191 * temporarily, show your splash screen, then re-enable it so that
9192 * showing the main window would automatically result in notification.
9197 gtk_window_set_auto_startup_notification (gboolean setting)
9199 disable_startup_notification = !setting;
9203 * gtk_window_get_window_type:
9204 * @window: a #GtkWindow
9206 * Gets the type of the window. See #GtkWindowType.
9208 * Return value: the type of the window
9213 gtk_window_get_window_type (GtkWindow *window)
9215 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9217 return window->priv->type;
9221 * gtk_window_get_mnemonics_visible:
9222 * @window: a #GtkWindow
9224 * Gets the value of the #GtkWindow:mnemonics-visible property.
9226 * Returns: %TRUE if mnemonics are supposed to be visible
9232 gtk_window_get_mnemonics_visible (GtkWindow *window)
9234 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9236 return window->priv->mnemonics_visible;
9240 * gtk_window_set_mnemonics_visible:
9241 * @window: a #GtkWindow
9242 * @setting: the new value
9244 * Sets the #GtkWindow:mnemonics-visible property.
9249 gtk_window_set_mnemonics_visible (GtkWindow *window,
9252 GtkWindowPrivate *priv;
9254 g_return_if_fail (GTK_IS_WINDOW (window));
9256 priv = window->priv;
9258 setting = setting != FALSE;
9260 if (priv->mnemonics_visible != setting)
9262 priv->mnemonics_visible = setting;
9263 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9266 priv->mnemonics_visible_set = TRUE;
9270 _gtk_window_get_wmclass (GtkWindow *window,
9271 gchar **wmclass_name,
9272 gchar **wmclass_class)
9274 GtkWindowPrivate *priv = window->priv;
9276 *wmclass_name = priv->wmclass_name;
9277 *wmclass_class = priv->wmclass_class;