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 toplevel_list = g_slist_remove (toplevel_list, window);
4518 if (priv->transient_parent)
4519 gtk_window_set_transient_for (window, NULL);
4521 /* frees the icons */
4522 gtk_window_set_icon_list (window, NULL);
4524 if (priv->has_user_ref_count)
4526 priv->has_user_ref_count = FALSE;
4527 g_object_unref (window);
4531 gtk_window_group_remove_window (priv->group, window);
4533 gtk_window_free_key_hash (window);
4535 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4539 gtk_window_finalize (GObject *object)
4541 GtkWindow *window = GTK_WINDOW (object);
4542 GtkWindowPrivate *priv = window->priv;
4543 GtkMnemonicHash *mnemonic_hash;
4545 g_free (priv->title);
4546 g_free (priv->wmclass_name);
4547 g_free (priv->wmclass_class);
4548 g_free (priv->wm_role);
4549 gtk_window_release_application (window);
4551 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4553 _gtk_mnemonic_hash_free (mnemonic_hash);
4555 if (priv->geometry_info)
4557 if (priv->geometry_info->widget)
4558 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4559 gtk_widget_destroyed,
4560 &priv->geometry_info->widget);
4561 g_free (priv->geometry_info);
4564 if (priv->keys_changed_handler)
4566 g_source_remove (priv->keys_changed_handler);
4567 priv->keys_changed_handler = 0;
4571 g_signal_handlers_disconnect_by_func (priv->screen,
4572 gtk_window_on_composited_changed, window);
4574 g_free (priv->startup_id);
4576 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4580 gtk_window_show (GtkWidget *widget)
4582 GtkWindow *window = GTK_WINDOW (widget);
4583 GtkWindowPrivate *priv = window->priv;
4584 GtkContainer *container = GTK_CONTAINER (window);
4585 gboolean need_resize;
4587 _gtk_widget_set_visible_flag (widget, TRUE);
4589 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4590 _gtk_container_set_need_resize (container, FALSE);
4594 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4595 GtkAllocation allocation = { 0, 0 };
4596 GdkRectangle configure_request;
4597 GdkGeometry new_geometry;
4599 gboolean was_realized;
4601 /* We are going to go ahead and perform this configure request
4602 * and then emulate a configure notify by going ahead and
4603 * doing a size allocate. Sort of a synchronous
4604 * mini-copy of gtk_window_move_resize() here.
4606 gtk_window_compute_configure_request (window,
4611 /* We update this because we are going to go ahead
4612 * and gdk_window_resize() below, rather than
4615 info->last.configure_request.width = configure_request.width;
4616 info->last.configure_request.height = configure_request.height;
4618 /* and allocate the window - this is normally done
4619 * in move_resize in response to configure notify
4621 allocation.width = configure_request.width;
4622 allocation.height = configure_request.height;
4623 gtk_widget_size_allocate (widget, &allocation);
4625 /* Then we guarantee we have a realize */
4626 was_realized = FALSE;
4627 if (!gtk_widget_get_realized (widget))
4629 gtk_widget_realize (widget);
4630 was_realized = TRUE;
4633 /* We only send configure request if we didn't just finish
4634 * creating the window; if we just created the window
4635 * then we created it with widget->allocation anyhow.
4638 gdk_window_move_resize (gtk_widget_get_window (widget),
4639 configure_request.x,
4640 configure_request.y,
4641 configure_request.width,
4642 configure_request.height);
4645 gtk_container_check_resize (container);
4647 gtk_widget_map (widget);
4649 /* Try to make sure that we have some focused widget
4651 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4652 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4655 gtk_grab_add (widget);
4659 gtk_window_hide (GtkWidget *widget)
4661 GtkWindow *window = GTK_WINDOW (widget);
4662 GtkWindowPrivate *priv = window->priv;
4664 _gtk_widget_set_visible_flag (widget, FALSE);
4665 gtk_widget_unmap (widget);
4668 gtk_grab_remove (widget);
4672 gtk_window_map (GtkWidget *widget)
4675 GtkWindow *window = GTK_WINDOW (widget);
4676 GtkWindowPrivate *priv = window->priv;
4677 GdkWindow *toplevel;
4678 GdkWindow *gdk_window;
4679 gboolean auto_mnemonics;
4681 gdk_window = gtk_widget_get_window (widget);
4683 gtk_widget_set_mapped (widget, TRUE);
4685 child = gtk_bin_get_child (&(window->bin));
4687 gtk_widget_get_visible (child) &&
4688 !gtk_widget_get_mapped (child))
4689 gtk_widget_map (child);
4691 toplevel = gdk_window;
4693 if (priv->maximize_initially)
4694 gdk_window_maximize (toplevel);
4696 gdk_window_unmaximize (toplevel);
4698 if (priv->stick_initially)
4699 gdk_window_stick (toplevel);
4701 gdk_window_unstick (toplevel);
4703 if (priv->iconify_initially)
4704 gdk_window_iconify (toplevel);
4706 gdk_window_deiconify (toplevel);
4708 if (priv->fullscreen_initially)
4709 gdk_window_fullscreen (toplevel);
4711 gdk_window_unfullscreen (toplevel);
4713 gdk_window_set_keep_above (toplevel, priv->above_initially);
4715 gdk_window_set_keep_below (toplevel, priv->below_initially);
4717 /* No longer use the default settings */
4718 priv->need_default_size = FALSE;
4719 priv->need_default_position = FALSE;
4721 if (priv->reset_type_hint)
4723 /* We should only reset the type hint when the application
4724 * used gtk_window_set_type_hint() to change the hint.
4725 * Some applications use X directly to change the properties;
4726 * in that case, we shouldn't overwrite what they did.
4728 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4729 priv->reset_type_hint = FALSE;
4732 gdk_window_show (gdk_window);
4734 if (priv->grip_window)
4735 gdk_window_show (priv->grip_window);
4737 if (!disable_startup_notification)
4739 /* Do we have a custom startup-notification id? */
4740 if (priv->startup_id != NULL)
4742 /* Make sure we have a "real" id */
4743 if (!startup_id_is_fake (priv->startup_id))
4744 gdk_notify_startup_complete_with_id (priv->startup_id);
4746 g_free (priv->startup_id);
4747 priv->startup_id = NULL;
4749 else if (!sent_startup_notification)
4751 sent_startup_notification = TRUE;
4752 gdk_notify_startup_complete ();
4756 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4757 * (as in the case of popup menus), then hide mnemonics initially
4759 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4760 &auto_mnemonics, NULL);
4761 if (auto_mnemonics && !priv->mnemonics_visible_set)
4762 gtk_window_set_mnemonics_visible (window, FALSE);
4766 gtk_window_map_event (GtkWidget *widget,
4769 if (!gtk_widget_get_mapped (widget))
4771 /* we should be be unmapped, but are getting a MapEvent, this may happen
4772 * to toplevel XWindows if mapping was intercepted by a window manager
4773 * and an unmap request occoured while the MapRequestEvent was still
4774 * being handled. we work around this situaiton here by re-requesting
4775 * the window being unmapped. more details can be found in:
4776 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4778 gdk_window_hide (gtk_widget_get_window (widget));
4784 gtk_window_unmap (GtkWidget *widget)
4786 GtkWindow *window = GTK_WINDOW (widget);
4787 GtkWindowPrivate *priv = window->priv;
4789 GtkWindowGeometryInfo *info;
4790 GdkWindow *gdk_window;
4791 GdkWindowState state;
4793 gdk_window = gtk_widget_get_window (widget);
4795 gtk_widget_set_mapped (widget, FALSE);
4796 gdk_window_withdraw (gdk_window);
4798 priv->configure_request_count = 0;
4799 priv->configure_notify_received = FALSE;
4801 /* on unmap, we reset the default positioning of the window,
4802 * so it's placed again, but we don't reset the default
4803 * size of the window, so it's remembered.
4805 priv->need_default_position = TRUE;
4807 info = gtk_window_get_geometry_info (window, FALSE);
4810 info->initial_pos_set = FALSE;
4811 info->position_constraints_changed = FALSE;
4814 state = gdk_window_get_state (gdk_window);
4815 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4816 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4817 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4818 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4819 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4821 child = gtk_bin_get_child (&(window->bin));
4823 gtk_widget_unmap (child);
4827 gtk_window_realize (GtkWidget *widget)
4829 GtkAllocation allocation;
4831 GdkWindow *parent_window;
4832 GdkWindow *gdk_window;
4833 GdkWindowAttr attributes;
4834 gint attributes_mask;
4835 GtkWindowPrivate *priv;
4836 GtkStyleContext *context;
4838 window = GTK_WINDOW (widget);
4839 priv = window->priv;
4841 gtk_widget_get_allocation (widget, &allocation);
4843 /* ensure widget tree is properly size allocated */
4844 if (allocation.x == -1 &&
4845 allocation.y == -1 &&
4846 allocation.width == 1 &&
4847 allocation.height == 1)
4849 GtkRequisition requisition;
4853 allocation.width = 200;
4854 allocation.height = 200;
4856 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4857 if (requisition.width || requisition.height)
4859 /* non-empty window */
4860 allocation.width = requisition.width;
4861 allocation.height = requisition.height;
4863 gtk_widget_size_allocate (widget, &allocation);
4865 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4867 g_return_if_fail (!gtk_widget_get_realized (widget));
4870 gtk_widget_set_realized (widget, TRUE);
4874 case GTK_WINDOW_TOPLEVEL:
4875 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4877 case GTK_WINDOW_POPUP:
4878 attributes.window_type = GDK_WINDOW_TEMP;
4881 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4885 attributes.title = priv->title;
4886 attributes.wmclass_name = priv->wmclass_name;
4887 attributes.wmclass_class = priv->wmclass_class;
4888 attributes.wclass = GDK_INPUT_OUTPUT;
4889 attributes.visual = gtk_widget_get_visual (widget);
4891 attributes_mask = 0;
4892 parent_window = gtk_widget_get_root_window (widget);
4894 gtk_widget_get_allocation (widget, &allocation);
4895 attributes.width = allocation.width;
4896 attributes.height = allocation.height;
4897 attributes.event_mask = gtk_widget_get_events (widget);
4898 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4899 GDK_KEY_PRESS_MASK |
4900 GDK_KEY_RELEASE_MASK |
4901 GDK_ENTER_NOTIFY_MASK |
4902 GDK_LEAVE_NOTIFY_MASK |
4903 GDK_FOCUS_CHANGE_MASK |
4904 GDK_STRUCTURE_MASK);
4905 attributes.type_hint = priv->type_hint;
4907 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4908 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4909 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4911 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4912 gtk_widget_set_window (widget, gdk_window);
4914 if (priv->opacity_set)
4915 gdk_window_set_opacity (gdk_window, priv->opacity);
4917 gdk_window_enable_synchronized_configure (gdk_window);
4919 gdk_window_set_user_data (gdk_window, window);
4921 gtk_widget_style_attach (widget);
4922 context = gtk_widget_get_style_context (widget);
4924 gtk_style_context_set_background (context, gdk_window);
4926 if (priv->transient_parent &&
4927 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4928 gdk_window_set_transient_for (gdk_window,
4929 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4932 gdk_window_set_role (gdk_window, priv->wm_role);
4934 if (!priv->decorated)
4935 gdk_window_set_decorations (gdk_window, 0);
4937 if (!priv->deletable)
4938 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4940 if (gtk_window_get_skip_pager_hint (window))
4941 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4943 if (gtk_window_get_skip_taskbar_hint (window))
4944 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4946 if (gtk_window_get_accept_focus (window))
4947 gdk_window_set_accept_focus (gdk_window, TRUE);
4949 gdk_window_set_accept_focus (gdk_window, FALSE);
4951 if (gtk_window_get_focus_on_map (window))
4952 gdk_window_set_focus_on_map (gdk_window, TRUE);
4954 gdk_window_set_focus_on_map (gdk_window, FALSE);
4957 gdk_window_set_modal_hint (gdk_window, TRUE);
4959 gdk_window_set_modal_hint (gdk_window, FALSE);
4961 if (priv->startup_id)
4963 #ifdef GDK_WINDOWING_X11
4964 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4965 if (timestamp != GDK_CURRENT_TIME)
4966 gdk_x11_window_set_user_time (gdk_window, timestamp);
4968 if (!startup_id_is_fake (priv->startup_id))
4969 gdk_window_set_startup_id (gdk_window, priv->startup_id);
4973 gtk_window_realize_icon (window);
4975 if (priv->has_resize_grip)
4976 resize_grip_create_window (window);
4980 gtk_window_unrealize (GtkWidget *widget)
4982 GtkWindow *window = GTK_WINDOW (widget);
4983 GtkWindowPrivate *priv = window->priv;
4984 GtkWindowGeometryInfo *info;
4986 /* On unrealize, we reset the size of the window such
4987 * that we will re-apply the default sizing stuff
4988 * next time we show the window.
4990 * Default positioning is reset on unmap, instead of unrealize.
4992 priv->need_default_size = TRUE;
4993 info = gtk_window_get_geometry_info (window, FALSE);
4996 info->resize_width = -1;
4997 info->resize_height = -1;
4998 info->last.configure_request.x = 0;
4999 info->last.configure_request.y = 0;
5000 info->last.configure_request.width = -1;
5001 info->last.configure_request.height = -1;
5002 /* be sure we reset geom hints on re-realize */
5003 info->last.flags = 0;
5007 gtk_window_unrealize_icon (window);
5009 if (priv->grip_window != NULL)
5010 resize_grip_destroy_window (window);
5012 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5015 static GtkJunctionSides
5016 get_grip_junction (GtkWidget *widget)
5018 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5019 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5021 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5025 get_drag_edge (GtkWidget *widget,
5026 GdkWindowEdge *edge)
5028 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5029 gboolean hresizable;
5030 gboolean vresizable;
5031 GtkTextDirection dir;
5032 GtkWindowGeometryInfo *info;
5037 info = priv->geometry_info;
5040 GdkWindowHints flags = info->last.flags;
5041 GdkGeometry *geometry = &info->last.geometry;
5043 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5045 hresizable = geometry->min_width < geometry->max_width;
5046 vresizable = geometry->min_height < geometry->max_height;
5050 dir = gtk_widget_get_direction (widget);
5052 if (hresizable && vresizable)
5053 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5054 else if (hresizable)
5055 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5056 else if (vresizable)
5057 *edge = GDK_WINDOW_EDGE_SOUTH;
5065 set_grip_cursor (GtkWindow *window)
5067 GtkWidget *widget = GTK_WIDGET (window);
5068 GtkWindowPrivate *priv = window->priv;
5070 if (priv->grip_window == NULL)
5073 if (gtk_widget_is_sensitive (widget))
5076 GdkDisplay *display;
5077 GdkCursorType cursor_type;
5080 cursor_type = GDK_LEFT_PTR;
5082 if (get_drag_edge (widget, &edge))
5086 case GDK_WINDOW_EDGE_EAST:
5087 cursor_type = GDK_RIGHT_SIDE;
5089 case GDK_WINDOW_EDGE_SOUTH_EAST:
5090 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5092 case GDK_WINDOW_EDGE_SOUTH:
5093 cursor_type = GDK_BOTTOM_SIDE;
5095 case GDK_WINDOW_EDGE_SOUTH_WEST:
5096 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5098 case GDK_WINDOW_EDGE_WEST:
5099 cursor_type = GDK_LEFT_SIDE;
5105 display = gtk_widget_get_display (widget);
5106 cursor = gdk_cursor_new_for_display (display, cursor_type);
5107 gdk_window_set_cursor (priv->grip_window, cursor);
5108 g_object_unref (cursor);
5111 gdk_window_set_cursor (priv->grip_window, NULL);
5115 set_grip_shape (GtkWindow *window)
5117 GtkWindowPrivate *priv = window->priv;
5118 cairo_region_t *region;
5119 cairo_surface_t *surface;
5121 double width, height;
5123 if (priv->grip_window == NULL)
5126 width = gdk_window_get_width (priv->grip_window);
5127 height = gdk_window_get_height (priv->grip_window);
5128 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5130 cr = cairo_create (surface);
5131 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5133 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5134 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5136 cairo_move_to (cr, width, 0.0);
5137 cairo_line_to (cr, width, height);
5138 cairo_line_to (cr, 0.0, height);
5142 cairo_move_to (cr, 0.0, 0.0);
5143 cairo_line_to (cr, width, height);
5144 cairo_line_to (cr, 0.0, height);
5146 cairo_close_path (cr);
5149 region = gdk_cairo_region_create_from_surface (surface);
5150 cairo_surface_destroy (surface);
5152 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5153 cairo_region_destroy (region);
5157 set_grip_position (GtkWindow *window)
5159 GtkWindowPrivate *priv = window->priv;
5162 if (priv->grip_window == NULL)
5165 gtk_window_get_resize_grip_area (window, &rect);
5166 gdk_window_raise (priv->grip_window);
5167 gdk_window_move_resize (priv->grip_window,
5169 rect.width, rect.height);
5173 gtk_window_size_allocate (GtkWidget *widget,
5174 GtkAllocation *allocation)
5176 GtkWindow *window = GTK_WINDOW (widget);
5177 GtkAllocation child_allocation;
5181 gtk_widget_set_allocation (widget, allocation);
5183 child = gtk_bin_get_child (&(window->bin));
5184 if (child && gtk_widget_get_visible (child))
5186 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5187 child_allocation.x = border_width;
5188 child_allocation.y = border_width;
5189 child_allocation.width =
5190 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5191 child_allocation.height =
5192 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5194 gtk_widget_size_allocate (child, &child_allocation);
5197 if (gtk_widget_get_realized (widget))
5199 update_grip_visibility (window);
5200 set_grip_position (window);
5205 gtk_window_configure_event (GtkWidget *widget,
5206 GdkEventConfigure *event)
5208 GtkAllocation allocation;
5209 GtkWindow *window = GTK_WINDOW (widget);
5210 GtkWindowPrivate *priv = window->priv;
5211 gboolean expected_reply = priv->configure_request_count > 0;
5213 /* priv->configure_request_count incremented for each
5214 * configure request, and decremented to a min of 0 for
5215 * each configure notify.
5217 * All it means is that we know we will get at least
5218 * priv->configure_request_count more configure notifies.
5219 * We could get more configure notifies than that; some
5220 * of the configure notifies we get may be unrelated to
5221 * the configure requests. But we will get at least
5222 * priv->configure_request_count notifies.
5225 if (priv->configure_request_count > 0)
5227 priv->configure_request_count -= 1;
5228 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5231 /* As an optimization, we avoid a resize when possible.
5233 * The only times we can avoid a resize are:
5234 * - we know only the position changed, not the size
5235 * - we know we have made more requests and so will get more
5236 * notifies and can wait to resize when we get them
5238 gtk_widget_get_allocation (widget, &allocation);
5239 if (!expected_reply &&
5240 (allocation.width == event->width &&
5241 allocation.height == event->height))
5243 gdk_window_configure_finished (gtk_widget_get_window (widget));
5248 * If we do need to resize, we do that by:
5249 * - filling in widget->allocation with the new size
5250 * - setting configure_notify_received to TRUE
5251 * for use in gtk_window_move_resize()
5252 * - queueing a resize, leading to invocation of
5253 * gtk_window_move_resize() in an idle handler
5257 priv->configure_notify_received = TRUE;
5259 allocation.width = event->width;
5260 allocation.height = event->height;
5261 gtk_widget_set_allocation (widget, &allocation);
5263 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5265 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5271 gtk_window_state_event (GtkWidget *widget,
5272 GdkEventWindowState *event)
5274 update_grip_visibility (GTK_WINDOW (widget));
5280 gtk_window_direction_changed (GtkWidget *widget,
5281 GtkTextDirection prev_dir)
5283 GtkWindow *window = GTK_WINDOW (widget);
5285 set_grip_cursor (window);
5286 set_grip_position (window);
5287 set_grip_shape (window);
5291 gtk_window_state_changed (GtkWidget *widget,
5292 GtkStateType previous_state)
5294 GtkWindow *window = GTK_WINDOW (widget);
5296 update_grip_visibility (window);
5300 gtk_window_style_updated (GtkWidget *widget)
5302 GtkWindow *window = GTK_WINDOW (widget);
5303 GtkWindowPrivate *priv = window->priv;
5306 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5308 gdk_window_move_resize (priv->grip_window,
5310 rect.width, rect.height);
5312 set_grip_shape (window);
5313 gtk_widget_queue_resize (widget);
5318 resize_grip_create_window (GtkWindow *window)
5321 GtkWindowPrivate *priv;
5322 GdkWindowAttr attributes;
5323 gint attributes_mask;
5326 priv = window->priv;
5327 widget = GTK_WIDGET (window);
5329 g_return_if_fail (gtk_widget_get_realized (widget));
5330 g_return_if_fail (priv->grip_window == NULL);
5332 gtk_window_get_resize_grip_area (window, &rect);
5334 attributes.x = rect.x;
5335 attributes.y = rect.y;
5336 attributes.width = rect.width;
5337 attributes.height = rect.height;
5338 attributes.window_type = GDK_WINDOW_CHILD;
5339 attributes.wclass = GDK_INPUT_OUTPUT;
5340 attributes.event_mask = gtk_widget_get_events (widget) |
5342 GDK_BUTTON_PRESS_MASK;
5344 attributes_mask = GDK_WA_X | GDK_WA_Y;
5346 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5350 gdk_window_set_user_data (priv->grip_window, widget);
5352 gdk_window_raise (priv->grip_window);
5354 set_grip_shape (window);
5355 update_grip_visibility (window);
5359 resize_grip_destroy_window (GtkWindow *window)
5361 GtkWindowPrivate *priv = window->priv;
5363 gdk_window_set_user_data (priv->grip_window, NULL);
5364 gdk_window_destroy (priv->grip_window);
5365 priv->grip_window = NULL;
5366 update_grip_visibility (window);
5370 * gtk_window_set_has_resize_grip:
5371 * @window: a #GtkWindow
5372 * @value: %TRUE to allow a resize grip
5374 * Sets whether @window has a corner resize grip.
5376 * Note that the resize grip is only shown if the window
5377 * is actually resizable and not maximized. Use
5378 * gtk_window_resize_grip_is_visible() to find out if the
5379 * resize grip is currently shown.
5384 gtk_window_set_has_resize_grip (GtkWindow *window,
5387 GtkWidget *widget = GTK_WIDGET (window);
5388 GtkWindowPrivate *priv = window->priv;
5390 value = value != FALSE;
5392 if (value != priv->has_resize_grip)
5394 priv->has_resize_grip = value;
5395 gtk_widget_queue_draw (widget);
5397 if (gtk_widget_get_realized (widget))
5399 if (priv->has_resize_grip && priv->grip_window == NULL)
5400 resize_grip_create_window (window);
5401 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5402 resize_grip_destroy_window (window);
5405 g_object_notify (G_OBJECT (window), "has-resize-grip");
5410 update_grip_visibility (GtkWindow *window)
5412 GtkWindowPrivate *priv = window->priv;
5415 val = gtk_window_resize_grip_is_visible (window);
5417 if (priv->grip_window != NULL)
5421 gdk_window_show (priv->grip_window);
5422 set_grip_cursor (window);
5426 gdk_window_hide (priv->grip_window);
5430 if (priv->resize_grip_visible != val)
5432 priv->resize_grip_visible = val;
5434 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5439 * gtk_window_resize_grip_is_visible:
5440 * @window: a #GtkWindow
5442 * Determines whether a resize grip is visible for the specified window.
5444 * Returns %TRUE if a resize grip exists and is visible.
5449 gtk_window_resize_grip_is_visible (GtkWindow *window)
5452 GtkWindowPrivate *priv;
5455 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5457 priv = window->priv;
5458 widget = GTK_WIDGET (window);
5460 if (priv->type == GTK_WINDOW_POPUP)
5463 if (!priv->resizable)
5466 if (gtk_widget_get_realized (widget))
5468 GdkWindowState state;
5470 state = gdk_window_get_state (gtk_widget_get_window (widget));
5472 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5476 if (!get_drag_edge (widget, &edge))
5479 return window->priv->has_resize_grip;
5483 * gtk_window_get_has_resize_grip:
5484 * @window: a #GtkWindow
5486 * Determines whether the window may have a resize grip.
5488 * Returns: %TRUE if the window has a resize grip.
5493 gtk_window_get_has_resize_grip (GtkWindow *window)
5495 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5497 return window->priv->has_resize_grip;
5501 * gtk_window_get_resize_grip_area:
5502 * @window: a #GtkWindow
5503 * @rect: a pointer to a #GdkRectangle which we should store the
5506 * If a window has a resize grip, this will retrieve the grip
5507 * position, width and height into the specified #GdkRectangle.
5509 * Returns: %TRUE if the resize grip's area was retrieved.
5514 gtk_window_get_resize_grip_area (GtkWindow *window,
5517 GtkWidget *widget = GTK_WIDGET (window);
5518 GtkAllocation allocation;
5522 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5524 if (!window->priv->has_resize_grip)
5527 gtk_widget_get_allocation (widget, &allocation);
5529 gtk_widget_style_get (widget,
5530 "resize-grip-width", &grip_width,
5531 "resize-grip-height", &grip_height,
5534 if (grip_width > allocation.width)
5535 grip_width = allocation.width;
5537 if (grip_height > allocation.height)
5538 grip_height = allocation.height;
5540 rect->width = grip_width;
5541 rect->height = grip_height;
5542 rect->y = allocation.y + allocation.height - grip_height;
5544 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5545 rect->x = allocation.x + allocation.width - grip_width;
5547 rect->x = allocation.x;
5552 /* the accel_key and accel_mods fields of the key have to be setup
5553 * upon calling this function. it'll then return whether that key
5554 * is at all used as accelerator, and if so will OR in the
5555 * accel_flags member of the key.
5558 _gtk_window_query_nonaccels (GtkWindow *window,
5560 GdkModifierType accel_mods)
5562 GtkWindowPrivate *priv;
5564 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5566 priv = window->priv;
5568 /* movement keys are considered locked accels */
5571 static const guint bindings[] = {
5572 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,
5573 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,
5577 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5578 if (bindings[i] == accel_key)
5582 /* mnemonics are considered locked accels */
5583 if (accel_mods == priv->mnemonic_modifier)
5585 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5586 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5594 * gtk_window_propagate_key_event:
5595 * @window: a #GtkWindow
5596 * @event: a #GdkEventKey
5598 * Propagate a key press or release event to the focus widget and
5599 * up the focus container chain until a widget handles @event.
5600 * This is normally called by the default ::key_press_event and
5601 * ::key_release_event handlers for toplevel windows,
5602 * however in some cases it may be useful to call this directly when
5603 * overriding the standard key handling for a toplevel window.
5605 * Return value: %TRUE if a widget in the focus chain handled the event.
5610 gtk_window_propagate_key_event (GtkWindow *window,
5613 GtkWindowPrivate *priv;
5614 gboolean handled = FALSE;
5615 GtkWidget *widget, *focus;
5617 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5619 priv = window->priv;
5620 widget = GTK_WIDGET (window);
5622 focus = priv->focus_widget;
5624 g_object_ref (focus);
5627 focus && focus != widget &&
5628 gtk_widget_get_toplevel (focus) == widget)
5632 if (gtk_widget_is_sensitive (focus))
5633 handled = gtk_widget_event (focus, (GdkEvent*) event);
5635 parent = gtk_widget_get_parent (focus);
5637 g_object_ref (parent);
5639 g_object_unref (focus);
5645 g_object_unref (focus);
5651 gtk_window_key_press_event (GtkWidget *widget,
5654 GtkWindow *window = GTK_WINDOW (widget);
5655 gboolean handled = FALSE;
5657 /* handle mnemonics and accelerators */
5659 handled = gtk_window_activate_key (window, event);
5661 /* handle focus widget key events */
5663 handled = gtk_window_propagate_key_event (window, event);
5665 /* Chain up, invokes binding set */
5667 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5673 gtk_window_key_release_event (GtkWidget *widget,
5676 GtkWindow *window = GTK_WINDOW (widget);
5677 gboolean handled = FALSE;
5679 /* handle focus widget key events */
5681 handled = gtk_window_propagate_key_event (window, event);
5683 /* Chain up, invokes binding set */
5685 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5691 gtk_window_button_press_event (GtkWidget *widget,
5692 GdkEventButton *event)
5694 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5697 if (event->window == priv->grip_window)
5699 if (get_drag_edge (widget, &edge))
5700 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5714 gtk_window_real_activate_default (GtkWindow *window)
5716 gtk_window_activate_default (window);
5720 gtk_window_real_activate_focus (GtkWindow *window)
5722 gtk_window_activate_focus (window);
5726 gtk_window_enter_notify_event (GtkWidget *widget,
5727 GdkEventCrossing *event)
5733 gtk_window_leave_notify_event (GtkWidget *widget,
5734 GdkEventCrossing *event)
5740 do_focus_change (GtkWidget *widget,
5744 GdkDeviceManager *device_manager;
5747 g_object_ref (widget);
5749 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5750 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5751 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5752 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5754 for (d = devices; d; d = d->next)
5756 GdkDevice *dev = d->data;
5759 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5762 /* Skip non-master keyboards that haven't
5763 * selected for events from this window
5765 window = gtk_widget_get_window (widget);
5766 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5767 window && !gdk_window_get_device_events (window, dev))
5770 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5772 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5773 fevent->focus_change.window = window;
5775 g_object_ref (window);
5776 fevent->focus_change.in = in;
5777 gdk_event_set_device (fevent, dev);
5779 gtk_widget_send_focus_change (widget, fevent);
5781 gdk_event_free (fevent);
5784 g_list_free (devices);
5785 g_object_unref (widget);
5789 gtk_window_focus_in_event (GtkWidget *widget,
5790 GdkEventFocus *event)
5792 GtkWindow *window = GTK_WINDOW (widget);
5794 /* It appears spurious focus in events can occur when
5795 * the window is hidden. So we'll just check to see if
5796 * the window is visible before actually handling the
5799 if (gtk_widget_get_visible (widget))
5801 _gtk_window_set_has_toplevel_focus (window, TRUE);
5802 _gtk_window_set_is_active (window, TRUE);
5809 gtk_window_focus_out_event (GtkWidget *widget,
5810 GdkEventFocus *event)
5812 GtkWindow *window = GTK_WINDOW (widget);
5813 gboolean auto_mnemonics;
5815 _gtk_window_set_has_toplevel_focus (window, FALSE);
5816 _gtk_window_set_is_active (window, FALSE);
5818 /* set the mnemonic-visible property to false */
5819 g_object_get (gtk_widget_get_settings (widget),
5820 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5822 gtk_window_set_mnemonics_visible (window, FALSE);
5827 static GdkAtom atom_rcfiles = GDK_NONE;
5828 static GdkAtom atom_iconthemes = GDK_NONE;
5831 send_client_message_to_embedded_windows (GtkWidget *widget,
5832 GdkAtom message_type)
5834 GList *embedded_windows;
5836 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5837 if (embedded_windows)
5839 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5842 for (i = 0; i < 5; i++)
5843 send_event->client.data.l[i] = 0;
5844 send_event->client.data_format = 32;
5845 send_event->client.message_type = message_type;
5847 while (embedded_windows)
5849 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5850 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5851 embedded_windows = embedded_windows->next;
5854 gdk_event_free (send_event);
5859 gtk_window_client_event (GtkWidget *widget,
5860 GdkEventClient *event)
5864 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5865 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5868 if (event->message_type == atom_rcfiles)
5870 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5871 gtk_style_context_reset_widgets (gtk_widget_get_screen (widget));
5874 if (event->message_type == atom_iconthemes)
5876 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5877 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5884 gtk_window_check_resize (GtkContainer *container)
5886 if (gtk_widget_get_visible (GTK_WIDGET (container)))
5887 gtk_window_move_resize (GTK_WINDOW (container));
5891 gtk_window_focus (GtkWidget *widget,
5892 GtkDirectionType direction)
5894 GtkWindowPrivate *priv;
5897 GtkContainer *container;
5899 GtkWidget *old_focus_child;
5902 container = GTK_CONTAINER (widget);
5903 window = GTK_WINDOW (widget);
5904 priv = window->priv;
5905 bin = GTK_BIN (widget);
5907 old_focus_child = gtk_container_get_focus_child (container);
5909 /* We need a special implementation here to deal properly with wrapping
5910 * around in the tab chain without the danger of going into an
5913 if (old_focus_child)
5915 if (gtk_widget_child_focus (old_focus_child, direction))
5919 if (priv->focus_widget)
5921 if (direction == GTK_DIR_LEFT ||
5922 direction == GTK_DIR_RIGHT ||
5923 direction == GTK_DIR_UP ||
5924 direction == GTK_DIR_DOWN)
5929 /* Wrapped off the end, clear the focus setting for the toplpevel */
5930 parent = gtk_widget_get_parent (priv->focus_widget);
5933 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5934 parent = gtk_widget_get_parent (parent);
5937 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5940 /* Now try to focus the first widget in the window */
5941 child = gtk_bin_get_child (bin);
5944 if (gtk_widget_child_focus (child, direction))
5952 gtk_window_move_focus (GtkWidget *widget,
5953 GtkDirectionType dir)
5955 gtk_widget_child_focus (widget, dir);
5957 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
5958 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
5962 gtk_window_real_set_focus (GtkWindow *window,
5965 GtkWindowPrivate *priv = window->priv;
5966 GtkWidget *old_focus = priv->focus_widget;
5967 gboolean had_default = FALSE;
5968 gboolean focus_had_default = FALSE;
5969 gboolean old_focus_had_default = FALSE;
5973 g_object_ref (old_focus);
5974 g_object_freeze_notify (G_OBJECT (old_focus));
5975 old_focus_had_default = gtk_widget_has_default (old_focus);
5979 g_object_ref (focus);
5980 g_object_freeze_notify (G_OBJECT (focus));
5981 focus_had_default = gtk_widget_has_default (focus);
5984 if (priv->default_widget)
5985 had_default = gtk_widget_has_default (priv->default_widget);
5987 if (priv->focus_widget)
5989 if (gtk_widget_get_receives_default (priv->focus_widget) &&
5990 (priv->focus_widget != priv->default_widget))
5992 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
5993 gtk_widget_queue_draw (priv->focus_widget);
5995 if (priv->default_widget)
5996 _gtk_widget_set_has_default (priv->default_widget, TRUE);
5999 priv->focus_widget = NULL;
6001 if (priv->has_focus)
6002 do_focus_change (old_focus, FALSE);
6004 g_object_notify (G_OBJECT (old_focus), "is-focus");
6007 /* The above notifications may have set a new focus widget,
6008 * if so, we don't want to override it.
6010 if (focus && !priv->focus_widget)
6012 priv->focus_widget = focus;
6014 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6015 (priv->focus_widget != priv->default_widget))
6017 if (gtk_widget_get_can_default (priv->focus_widget))
6018 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6020 if (priv->default_widget)
6021 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6024 if (priv->has_focus)
6025 do_focus_change (priv->focus_widget, TRUE);
6027 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6030 /* If the default widget changed, a redraw will have been queued
6031 * on the old and new default widgets by gtk_window_set_default(), so
6032 * we only have to worry about the case where it didn't change.
6033 * We'll sometimes queue a draw twice on the new widget but that
6036 if (priv->default_widget &&
6037 (had_default != gtk_widget_has_default (priv->default_widget)))
6038 gtk_widget_queue_draw (priv->default_widget);
6042 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6043 gtk_widget_queue_draw (old_focus);
6045 g_object_thaw_notify (G_OBJECT (old_focus));
6046 g_object_unref (old_focus);
6050 if (focus_had_default != gtk_widget_has_default (focus))
6051 gtk_widget_queue_draw (focus);
6053 g_object_thaw_notify (G_OBJECT (focus));
6054 g_object_unref (focus);
6060 gtk_window_get_preferred_width (GtkWidget *widget,
6068 window = GTK_WINDOW (widget);
6069 child = gtk_bin_get_child (GTK_BIN (window));
6071 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6072 *minimum_size = border_width * 2;
6073 *natural_size = border_width * 2;
6075 if (child && gtk_widget_get_visible (child))
6077 gint child_min, child_nat;
6078 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6080 *minimum_size += child_min;
6081 *natural_size += child_nat;
6086 gtk_window_get_preferred_height (GtkWidget *widget,
6094 window = GTK_WINDOW (widget);
6095 child = gtk_bin_get_child (GTK_BIN (window));
6097 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6098 *minimum_size = border_width * 2;
6099 *natural_size = border_width * 2;
6101 if (child && gtk_widget_get_visible (child))
6103 gint child_min, child_nat;
6104 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6106 *minimum_size += child_min;
6107 *natural_size += child_nat;
6113 * _gtk_window_unset_focus_and_default:
6114 * @window: a #GtkWindow
6115 * @widget: a widget inside of @window
6117 * Checks whether the focus and default widgets of @window are
6118 * @widget or a descendent of @widget, and if so, unset them.
6121 _gtk_window_unset_focus_and_default (GtkWindow *window,
6125 GtkWindowPrivate *priv = window->priv;
6129 g_object_ref (window);
6130 g_object_ref (widget);
6132 parent = gtk_widget_get_parent (widget);
6133 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6135 child = priv->focus_widget;
6137 while (child && child != widget)
6138 child = gtk_widget_get_parent (child);
6140 if (child == widget)
6141 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6144 child = priv->default_widget;
6146 while (child && child != widget)
6147 child = gtk_widget_get_parent (child);
6149 if (child == widget)
6150 gtk_window_set_default (window, NULL);
6152 g_object_unref (widget);
6153 g_object_unref (window);
6156 /*********************************
6157 * Functions related to resizing *
6158 *********************************/
6161 geometry_size_to_pixels (GdkGeometry *geometry,
6166 gint base_width = 0;
6167 gint base_height = 0;
6169 gint min_height = 0;
6171 gint height_inc = 1;
6173 if (flags & GDK_HINT_BASE_SIZE)
6175 base_width = geometry->base_width;
6176 base_height = geometry->base_height;
6178 if (flags & GDK_HINT_MIN_SIZE)
6180 min_width = geometry->min_width;
6181 min_height = geometry->min_height;
6183 if (flags & GDK_HINT_RESIZE_INC)
6185 width_inc = geometry->width_inc;
6186 height_inc = geometry->height_inc;
6190 *width = MAX (*width * width_inc + base_width, min_width);
6192 *height = MAX (*height * height_inc + base_height, min_height);
6195 /* This function doesn't constrain to geometry hints */
6197 gtk_window_compute_configure_request_size (GtkWindow *window,
6198 GdkGeometry *geometry,
6203 GtkWindowPrivate *priv = window->priv;
6204 GtkRequisition requisition;
6205 GtkWindowGeometryInfo *info;
6209 * - we've done a size request
6212 widget = GTK_WIDGET (window);
6214 info = gtk_window_get_geometry_info (window, FALSE);
6216 if (priv->need_default_size)
6218 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6220 /* Default to requisition */
6221 *width = requisition.width;
6222 *height = requisition.height;
6224 /* If window is empty so requests 0, default to random nonzero size */
6225 if (*width == 0 && *height == 0)
6231 /* Override requisition with default size */
6235 if (info->default_width > 0)
6236 *width = info->default_width;
6237 if (info->default_height > 0)
6238 *height = info->default_height;
6240 if (info->default_is_geometry)
6241 geometry_size_to_pixels (geometry, flags,
6242 info->default_width > 0 ? width : NULL,
6243 info->default_height > 0 ? height : NULL);
6248 GtkAllocation allocation;
6250 gtk_widget_get_allocation (widget, &allocation);
6252 /* Default to keeping current size */
6253 *width = allocation.width;
6254 *height = allocation.height;
6257 /* Override any size with gtk_window_resize() values */
6260 if (info->resize_width > 0)
6261 *width = info->resize_width;
6262 if (info->resize_height > 0)
6263 *height = info->resize_height;
6265 if (info->resize_is_geometry)
6266 geometry_size_to_pixels (geometry, flags,
6267 info->resize_width > 0 ? width : NULL,
6268 info->resize_height > 0 ? height : NULL);
6271 /* Don't ever request zero width or height, its not supported by
6272 gdk. The size allocation code will round it to 1 anyway but if
6273 we do it then the value returned from this function will is
6274 not comparable to the size allocation read from the GtkWindow. */
6275 *width = MAX (*width, 1);
6276 *height = MAX (*height, 1);
6279 static GtkWindowPosition
6280 get_effective_position (GtkWindow *window)
6282 GtkWindowPrivate *priv = window->priv;
6283 GtkWindowPosition pos = priv->position;
6285 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6286 (priv->transient_parent == NULL ||
6287 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6288 pos = GTK_WIN_POS_NONE;
6294 get_center_monitor_of_window (GtkWindow *window)
6296 /* We could try to sort out the relative positions of the monitors and
6297 * stuff, or we could just be losers and assume you have a row
6298 * or column of monitors.
6300 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6304 get_monitor_containing_pointer (GtkWindow *window)
6308 GdkScreen *window_screen;
6309 GdkScreen *pointer_screen;
6310 GdkDisplay *display;
6311 GdkDeviceManager *device_manager;
6314 window_screen = gtk_window_check_screen (window);
6315 display = gdk_screen_get_display (window_screen);
6316 device_manager = gdk_display_get_device_manager (display);
6317 pointer = gdk_device_manager_get_client_pointer (device_manager);
6319 gdk_display_get_device_state (display, pointer,
6323 if (pointer_screen == window_screen)
6324 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6332 center_window_on_monitor (GtkWindow *window,
6338 GdkRectangle monitor;
6341 monitor_num = get_monitor_containing_pointer (window);
6343 if (monitor_num == -1)
6344 monitor_num = get_center_monitor_of_window (window);
6346 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6347 monitor_num, &monitor);
6349 *x = (monitor.width - w) / 2 + monitor.x;
6350 *y = (monitor.height - h) / 2 + monitor.y;
6352 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6353 * and WM decorations.
6367 if (extent > clamp_extent)
6369 *base = clamp_base + clamp_extent/2 - extent/2;
6370 else if (*base < clamp_base)
6372 else if (*base + extent > clamp_base + clamp_extent)
6373 *base = clamp_base + clamp_extent - extent;
6377 clamp_window_to_rectangle (gint *x,
6381 const GdkRectangle *rect)
6383 #ifdef DEBUGGING_OUTPUT
6384 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);
6387 /* If it is too large, center it. If it fits on the monitor but is
6388 * partially outside, move it to the closest edge. Do this
6389 * separately in x and y directions.
6391 clamp (x, w, rect->x, rect->width);
6392 clamp (y, h, rect->y, rect->height);
6393 #ifdef DEBUGGING_OUTPUT
6394 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6400 gtk_window_compute_configure_request (GtkWindow *window,
6401 GdkRectangle *request,
6402 GdkGeometry *geometry,
6405 GtkWindowPrivate *priv = window->priv;
6406 GdkGeometry new_geometry;
6410 GtkWindowPosition pos;
6411 GtkWidget *parent_widget;
6412 GtkWindowGeometryInfo *info;
6416 widget = GTK_WIDGET (window);
6418 screen = gtk_window_check_screen (window);
6420 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6421 gtk_window_compute_configure_request_size (window,
6422 &new_geometry, new_flags,
6423 (guint *)&w, (guint *)&h);
6425 gtk_window_constrain_size (window,
6426 &new_geometry, new_flags,
6430 parent_widget = (GtkWidget*) priv->transient_parent;
6432 pos = get_effective_position (window);
6433 info = gtk_window_get_geometry_info (window, FALSE);
6435 /* by default, don't change position requested */
6438 x = info->last.configure_request.x;
6439 y = info->last.configure_request.y;
6448 if (priv->need_default_position)
6451 /* FIXME this all interrelates with window gravity.
6452 * For most of them I think we want to set GRAVITY_CENTER.
6454 * Not sure how to go about that.
6459 /* here we are only handling CENTER_ALWAYS
6460 * as it relates to default positioning,
6461 * where it's equivalent to simply CENTER
6463 case GTK_WIN_POS_CENTER_ALWAYS:
6464 case GTK_WIN_POS_CENTER:
6465 center_window_on_monitor (window, w, h, &x, &y);
6468 case GTK_WIN_POS_CENTER_ON_PARENT:
6470 GtkAllocation allocation;
6471 GdkWindow *gdk_window;
6473 GdkRectangle monitor;
6476 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6478 gdk_window = gtk_widget_get_window (parent_widget);
6480 if (gdk_window != NULL)
6481 monitor_num = gdk_screen_get_monitor_at_window (screen,
6486 gdk_window_get_origin (gdk_window,
6489 gtk_widget_get_allocation (parent_widget, &allocation);
6490 x = ox + (allocation.width - w) / 2;
6491 y = oy + (allocation.height - h) / 2;
6493 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6494 * WM decorations. If parent wasn't on a monitor, just
6497 if (monitor_num >= 0)
6499 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6500 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6505 case GTK_WIN_POS_MOUSE:
6507 gint screen_width = gdk_screen_get_width (screen);
6508 gint screen_height = gdk_screen_get_height (screen);
6510 GdkRectangle monitor;
6511 GdkDisplay *display;
6512 GdkDeviceManager *device_manager;
6514 GdkScreen *pointer_screen;
6517 display = gdk_screen_get_display (screen);
6518 device_manager = gdk_display_get_device_manager (display);
6519 pointer = gdk_device_manager_get_client_pointer (device_manager);
6521 gdk_display_get_device_state (display, pointer,
6525 if (pointer_screen == screen)
6526 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6532 x = CLAMP (x, 0, screen_width - w);
6533 y = CLAMP (y, 0, screen_height - h);
6535 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6536 * WM decorations. Don't try to figure out what's going
6537 * on if the mouse wasn't inside a monitor.
6539 if (monitor_num >= 0)
6541 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6542 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6550 } /* if (priv->need_default_position) */
6552 if (priv->need_default_position && info &&
6553 info->initial_pos_set)
6555 x = info->initial_x;
6556 y = info->initial_y;
6557 gtk_window_constrain_position (window, w, h, &x, &y);
6563 request->height = h;
6566 *geometry = new_geometry;
6572 gtk_window_constrain_position (GtkWindow *window,
6578 GtkWindowPrivate *priv = window->priv;
6580 /* See long comments in gtk_window_move_resize()
6581 * on when it's safe to call this function.
6583 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6585 gint center_x, center_y;
6587 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6595 gtk_window_move_resize (GtkWindow *window)
6599 * First we determine whether any information has changed that would
6600 * cause us to revise our last configure request. If we would send
6601 * a different configure request from last time, then
6602 * configure_request_size_changed = TRUE or
6603 * configure_request_pos_changed = TRUE. configure_request_size_changed
6604 * may be true due to new hints, a gtk_window_resize(), or whatever.
6605 * configure_request_pos_changed may be true due to gtk_window_set_position()
6606 * or gtk_window_move().
6608 * If the configure request has changed, we send off a new one. To
6609 * ensure GTK+ invariants are maintained (resize queue does what it
6610 * should), we go ahead and size_allocate the requested size in this
6613 * If the configure request has not changed, we don't ever resend
6614 * it, because it could mean fighting the user or window manager.
6617 * To prepare the configure request, we come up with a base size/pos:
6618 * - the one from gtk_window_move()/gtk_window_resize()
6619 * - else default_width, default_height if we haven't ever
6621 * - else the size request if we haven't ever been mapped,
6622 * as a substitute default size
6623 * - else the current size of the window, as received from
6624 * configure notifies (i.e. the current allocation)
6626 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6627 * the position request to be centered.
6629 GtkWindowPrivate *priv = window->priv;
6630 GtkAllocation allocation;
6632 GtkContainer *container;
6633 GtkWindowGeometryInfo *info;
6634 GdkGeometry new_geometry;
6635 GdkWindow *gdk_window;
6637 GdkRectangle new_request;
6638 gboolean configure_request_size_changed;
6639 gboolean configure_request_pos_changed;
6640 gboolean hints_changed; /* do we need to send these again */
6641 GtkWindowLastGeometryInfo saved_last_info;
6643 widget = GTK_WIDGET (window);
6644 gdk_window = gtk_widget_get_window (widget);
6645 container = GTK_CONTAINER (widget);
6646 info = gtk_window_get_geometry_info (window, TRUE);
6648 configure_request_size_changed = FALSE;
6649 configure_request_pos_changed = FALSE;
6651 gtk_window_compute_configure_request (window, &new_request,
6652 &new_geometry, &new_flags);
6654 /* This check implies the invariant that we never set info->last
6655 * without setting the hints and sending off a configure request.
6657 * If we change info->last without sending the request, we may
6660 if (info->last.configure_request.x != new_request.x ||
6661 info->last.configure_request.y != new_request.y)
6662 configure_request_pos_changed = TRUE;
6664 if ((info->last.configure_request.width != new_request.width ||
6665 info->last.configure_request.height != new_request.height))
6666 configure_request_size_changed = TRUE;
6668 hints_changed = FALSE;
6670 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6671 &new_geometry, new_flags))
6673 hints_changed = TRUE;
6676 /* Position Constraints
6677 * ====================
6679 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6680 * a default. The other POS_ values are used only when the
6681 * window is shown, not after that.
6683 * However, we can't implement a position constraint as
6684 * "anytime the window size changes, center the window"
6685 * because this may well end up fighting the WM or user. In
6686 * fact it gets in an infinite loop with at least one WM.
6688 * Basically, applications are in no way in a position to
6689 * constrain the position of a window, with one exception:
6690 * override redirect windows. (Really the intended purpose
6691 * of CENTER_ALWAYS anyhow, I would think.)
6693 * So the way we implement this "constraint" is to say that when WE
6694 * cause a move or resize, i.e. we make a configure request changing
6695 * window size, we recompute the CENTER_ALWAYS position to reflect
6696 * the new window size, and include it in our request. Also, if we
6697 * just turned on CENTER_ALWAYS we snap to center with a new
6698 * request. Otherwise, if we are just NOTIFIED of a move or resize
6699 * done by someone else e.g. the window manager, we do NOT send a
6700 * new configure request.
6702 * For override redirect windows, this works fine; all window
6703 * sizes are from our configure requests. For managed windows,
6704 * it is at least semi-sane, though who knows what the
6705 * app author is thinking.
6708 /* This condition should be kept in sync with the condition later on
6709 * that determines whether we send a configure request. i.e. we
6710 * should do this position constraining anytime we were going to
6711 * send a configure request anyhow, plus when constraints have
6714 if (configure_request_pos_changed ||
6715 configure_request_size_changed ||
6717 info->position_constraints_changed)
6719 /* We request the constrained position if:
6720 * - we were changing position, and need to clamp
6721 * the change to the constraint
6722 * - we're changing the size anyway
6723 * - set_position() was called to toggle CENTER_ALWAYS on
6726 gtk_window_constrain_position (window,
6732 /* Update whether we need to request a move */
6733 if (info->last.configure_request.x != new_request.x ||
6734 info->last.configure_request.y != new_request.y)
6735 configure_request_pos_changed = TRUE;
6737 configure_request_pos_changed = FALSE;
6741 if (priv->type == GTK_WINDOW_TOPLEVEL)
6743 int notify_x, notify_y;
6745 /* this is the position from the last configure notify */
6746 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6748 g_message ("--- %s ---\n"
6749 "last : %d,%d\t%d x %d\n"
6750 "this : %d,%d\t%d x %d\n"
6751 "alloc : %d,%d\t%d x %d\n"
6753 "resize: \t%d x %d\n"
6754 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6755 "configure_notify_received: %d\n"
6756 "configure_request_count: %d\n"
6757 "position_constraints_changed: %d\n",
6758 priv->title ? priv->title : "(no title)",
6759 info->last.configure_request.x,
6760 info->last.configure_request.y,
6761 info->last.configure_request.width,
6762 info->last.configure_request.height,
6768 widget->allocation.width,
6769 widget->allocation.height,
6770 widget->requisition.width,
6771 widget->requisition.height,
6773 info->resize_height,
6774 configure_request_pos_changed,
6775 configure_request_size_changed,
6777 priv->configure_notify_received,
6778 priv->configure_request_count,
6779 info->position_constraints_changed);
6783 saved_last_info = info->last;
6784 info->last.geometry = new_geometry;
6785 info->last.flags = new_flags;
6786 info->last.configure_request = new_request;
6788 /* need to set PPosition so the WM will look at our position,
6789 * but we don't want to count PPosition coming and going as a hints
6790 * change for future iterations. So we saved info->last prior to
6794 /* Also, if the initial position was explicitly set, then we always
6795 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6799 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6800 * this is an initial map
6803 if ((configure_request_pos_changed ||
6804 info->initial_pos_set ||
6805 (priv->need_default_position &&
6806 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6807 (new_flags & GDK_HINT_POS) == 0)
6809 new_flags |= GDK_HINT_POS;
6810 hints_changed = TRUE;
6813 /* Set hints if necessary
6816 gdk_window_set_geometry_hints (gdk_window,
6820 gtk_widget_get_allocation (widget, &allocation);
6822 /* handle resizing/moving and widget tree allocation
6824 if (priv->configure_notify_received)
6826 /* If we have received a configure event since
6827 * the last time in this function, we need to
6828 * accept our new size and size_allocate child widgets.
6829 * (see gtk_window_configure_event() for more details).
6831 * 1 or more configure notifies may have been received.
6832 * Also, configure_notify_received will only be TRUE
6833 * if all expected configure notifies have been received
6834 * (one per configure request), as an optimization.
6837 priv->configure_notify_received = FALSE;
6839 /* gtk_window_configure_event() filled in widget->allocation */
6840 gtk_widget_size_allocate (widget, &allocation);
6842 set_grip_position (window);
6843 update_grip_visibility (window);
6845 gdk_window_process_updates (gdk_window, TRUE);
6847 gdk_window_configure_finished (gdk_window);
6849 /* If the configure request changed, it means that
6851 * 1) coincidentally changed hints or widget properties
6852 * impacting the configure request before getting
6853 * a configure notify, or
6854 * 2) some broken widget is changing its size request
6855 * during size allocation, resulting in
6856 * a false appearance of changed configure request.
6858 * For 1), we could just go ahead and ask for the
6859 * new size right now, but doing that for 2)
6860 * might well be fighting the user (and can even
6861 * trigger a loop). Since we really don't want to
6862 * do that, we requeue a resize in hopes that
6863 * by the time it gets handled, the child has seen
6864 * the light and is willing to go along with the
6865 * new size. (this happens for the zvt widget, since
6866 * the size_allocate() above will have stored the
6867 * requisition corresponding to the new size in the
6870 * This doesn't buy us anything for 1), but it shouldn't
6871 * hurt us too badly, since it is what would have
6872 * happened if we had gotten the configure event before
6873 * the new size had been set.
6876 if (configure_request_size_changed ||
6877 configure_request_pos_changed)
6879 /* Don't change the recorded last info after all, because we
6880 * haven't actually updated to the new info yet - we decided
6881 * to postpone our configure request until later.
6883 info->last = saved_last_info;
6885 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6888 return; /* Bail out, we didn't really process the move/resize */
6890 else if ((configure_request_size_changed || hints_changed) &&
6891 (allocation.width != new_request.width || allocation.height != new_request.height))
6894 /* We are in one of the following situations:
6895 * A. configure_request_size_changed
6896 * our requisition has changed and we need a different window size,
6897 * so we request it from the window manager.
6898 * B. !configure_request_size_changed && hints_changed
6899 * the window manager rejects our size, but we have just changed the
6900 * window manager hints, so there's a chance our request will
6901 * be honoured this time, so we try again.
6903 * However, if the new requisition is the same as the current allocation,
6904 * we don't request it again, since we won't get a ConfigureNotify back from
6905 * the window manager unless it decides to change our requisition. If
6906 * we don't get the ConfigureNotify back, the resize queue will never be run.
6909 /* Now send the configure request */
6910 if (configure_request_pos_changed)
6912 gdk_window_move_resize (gdk_window,
6913 new_request.x, new_request.y,
6914 new_request.width, new_request.height);
6916 else /* only size changed */
6918 gdk_window_resize (gdk_window,
6919 new_request.width, new_request.height);
6922 if (priv->type == GTK_WINDOW_POPUP)
6924 GtkAllocation allocation;
6926 /* Directly size allocate for override redirect (popup) windows. */
6929 allocation.width = new_request.width;
6930 allocation.height = new_request.height;
6932 gtk_widget_size_allocate (widget, &allocation);
6934 gdk_window_process_updates (gdk_window, TRUE);
6936 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6937 gtk_widget_queue_draw (widget);
6941 /* Increment the number of have-not-yet-received-notify requests */
6942 priv->configure_request_count += 1;
6943 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
6945 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6946 * configure event in response to our resizing request.
6947 * the configure event will cause a new resize with
6948 * ->configure_notify_received=TRUE.
6949 * until then, we want to
6950 * - discard expose events
6951 * - coalesce resizes for our children
6952 * - defer any window resizes until the configure event arrived
6953 * to achieve this, we queue a resize for the window, but remove its
6954 * resizing handler, so resizing will not be handled from the next
6955 * idle handler but when the configure event arrives.
6957 * FIXME: we should also dequeue the pending redraws here, since
6958 * we handle those ourselves upon ->configure_notify_received==TRUE.
6960 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6962 gtk_widget_queue_resize_no_redraw (widget);
6963 _gtk_container_dequeue_resize_handler (container);
6969 /* Handle any position changes.
6971 if (configure_request_pos_changed)
6973 gdk_window_move (gdk_window,
6974 new_request.x, new_request.y);
6977 /* And run the resize queue.
6979 gtk_container_resize_children (container);
6982 /* We have now processed a move/resize since the last position
6983 * constraint change, setting of the initial position, or resize.
6984 * (Not resetting these flags here can lead to infinite loops for
6985 * GTK_RESIZE_IMMEDIATE containers)
6987 info->position_constraints_changed = FALSE;
6988 info->initial_pos_set = FALSE;
6989 info->resize_width = -1;
6990 info->resize_height = -1;
6993 /* Compare two sets of Geometry hints for equality.
6996 gtk_window_compare_hints (GdkGeometry *geometry_a,
6998 GdkGeometry *geometry_b,
7001 if (flags_a != flags_b)
7004 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7005 (geometry_a->min_width != geometry_b->min_width ||
7006 geometry_a->min_height != geometry_b->min_height))
7009 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7010 (geometry_a->max_width != geometry_b->max_width ||
7011 geometry_a->max_height != geometry_b->max_height))
7014 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7015 (geometry_a->base_width != geometry_b->base_width ||
7016 geometry_a->base_height != geometry_b->base_height))
7019 if ((flags_a & GDK_HINT_ASPECT) &&
7020 (geometry_a->min_aspect != geometry_b->min_aspect ||
7021 geometry_a->max_aspect != geometry_b->max_aspect))
7024 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7025 (geometry_a->width_inc != geometry_b->width_inc ||
7026 geometry_a->height_inc != geometry_b->height_inc))
7029 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7030 geometry_a->win_gravity != geometry_b->win_gravity)
7037 _gtk_window_constrain_size (GtkWindow *window,
7043 GtkWindowPrivate *priv;
7044 GtkWindowGeometryInfo *info;
7046 g_return_if_fail (GTK_IS_WINDOW (window));
7048 priv = window->priv;
7050 info = priv->geometry_info;
7053 GdkWindowHints flags = info->last.flags;
7054 GdkGeometry *geometry = &info->last.geometry;
7056 gtk_window_constrain_size (window,
7067 gtk_window_constrain_size (GtkWindow *window,
7068 GdkGeometry *geometry,
7075 gdk_window_constrain_size (geometry, flags, width, height,
7076 new_width, new_height);
7079 /* Compute the set of geometry hints and flags for a window
7080 * based on the application set geometry, and requisition
7081 * of the window. gtk_widget_get_preferred_size() must have been
7085 gtk_window_compute_hints (GtkWindow *window,
7086 GdkGeometry *new_geometry,
7089 GtkWindowPrivate *priv = window->priv;
7091 gint extra_width = 0;
7092 gint extra_height = 0;
7093 GtkWindowGeometryInfo *geometry_info;
7094 GtkRequisition requisition;
7096 widget = GTK_WIDGET (window);
7098 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7099 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7103 *new_flags = geometry_info->mask;
7104 *new_geometry = geometry_info->geometry;
7111 if (geometry_info && geometry_info->widget)
7113 /* If the geometry widget is set, then the hints really apply to that
7114 * widget. This is pretty much meaningless unless the window layout
7115 * is such that the rest of the window adds fixed size borders to
7116 * the geometry widget. Our job is to figure the size of the borders;
7117 * We do that by asking how big the toplevel would be if the
7118 * geometry widget was *really big*.
7121 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7122 * |GGGGG B| in the border can confuse things
7128 * |AAAAAAAAA | When the geometry widget is large, things are
7129 * |GGGGGGGGGGB| clearer.
7134 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7135 GtkRequisition requisition;
7136 int current_width, current_height;
7138 _gtk_widget_override_size_request (geometry_info->widget,
7139 TEMPORARY_SIZE, TEMPORARY_SIZE,
7140 ¤t_width, ¤t_height);
7141 gtk_widget_get_preferred_size (widget,
7142 &requisition, NULL);
7143 _gtk_widget_restore_size_request (geometry_info->widget,
7144 current_width, current_height);
7146 extra_width = requisition.width - TEMPORARY_SIZE;
7147 extra_height = requisition.height - TEMPORARY_SIZE;
7149 if (extra_width < 0 || extra_width < 0)
7151 g_warning("Toplevel size doesn't seem to directly depend on the "
7152 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7153 "The geometry widget might not be in the window, or it might not "
7154 "be packed into the window appropriately");
7155 extra_width = MAX(extra_width, 0);
7156 extra_height = MAX(extra_height, 0);
7158 #undef TEMPORARY_SIZE
7161 /* We don't want to set GDK_HINT_POS in here, we just set it
7162 * in gtk_window_move_resize() when we want the position
7166 if (*new_flags & GDK_HINT_BASE_SIZE)
7168 new_geometry->base_width += extra_width;
7169 new_geometry->base_height += extra_height;
7173 /* For simplicity, we always set the base hint, even when we
7174 * don't expect it to have any visible effect.
7175 * (Note: geometry_size_to_pixels() depends on this.)
7177 *new_flags |= GDK_HINT_BASE_SIZE;
7179 new_geometry->base_width = extra_width;
7180 new_geometry->base_height = extra_height;
7182 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7183 * base size is the minimum size */
7184 if (*new_flags & GDK_HINT_MIN_SIZE)
7186 if (new_geometry->min_width > 0)
7187 new_geometry->base_width += new_geometry->min_width;
7188 if (new_geometry->min_height > 0)
7189 new_geometry->base_height += new_geometry->min_height;
7193 if (*new_flags & GDK_HINT_MIN_SIZE)
7195 if (new_geometry->min_width < 0)
7196 new_geometry->min_width = requisition.width;
7198 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7200 if (new_geometry->min_height < 0)
7201 new_geometry->min_height = requisition.height;
7203 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7207 *new_flags |= GDK_HINT_MIN_SIZE;
7209 new_geometry->min_width = requisition.width;
7210 new_geometry->min_height = requisition.height;
7213 if (*new_flags & GDK_HINT_MAX_SIZE)
7215 if (new_geometry->max_width < 0)
7216 new_geometry->max_width = requisition.width;
7218 new_geometry->max_width += extra_width;
7220 if (new_geometry->max_height < 0)
7221 new_geometry->max_height = requisition.height;
7223 new_geometry->max_height += extra_height;
7225 else if (!priv->resizable)
7227 *new_flags |= GDK_HINT_MAX_SIZE;
7229 new_geometry->max_width = requisition.width;
7230 new_geometry->max_height = requisition.height;
7233 *new_flags |= GDK_HINT_WIN_GRAVITY;
7234 new_geometry->win_gravity = priv->gravity;
7237 /***********************
7238 * Redrawing functions *
7239 ***********************/
7242 gtk_window_draw (GtkWidget *widget,
7245 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7246 GtkStyleContext *context;
7247 gboolean ret = FALSE;
7249 context = gtk_widget_get_style_context (widget);
7251 gtk_style_context_save (context);
7253 if (!gtk_widget_get_app_paintable (widget))
7255 GtkStateFlags state;
7257 state = gtk_widget_get_state_flags (widget);
7259 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7260 state |= GTK_STATE_FLAG_FOCUSED;
7262 gtk_style_context_set_state (context, state);
7263 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7264 gtk_render_background (context, cr, 0, 0,
7265 gtk_widget_get_allocated_width (widget),
7266 gtk_widget_get_allocated_height (widget));
7269 gtk_style_context_restore (context);
7271 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7272 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7274 if (priv->grip_window != NULL &&
7275 gtk_cairo_should_draw_window (cr, priv->grip_window))
7279 gtk_style_context_save (context);
7282 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7283 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7285 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7286 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7287 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7290 gtk_style_context_restore (context);
7297 * gtk_window_present:
7298 * @window: a #GtkWindow
7300 * Presents a window to the user. This may mean raising the window
7301 * in the stacking order, deiconifying it, moving it to the current
7302 * desktop, and/or giving it the keyboard focus, possibly dependent
7303 * on the user's platform, window manager, and preferences.
7305 * If @window is hidden, this function calls gtk_widget_show()
7308 * This function should be used when the user tries to open a window
7309 * that's already open. Say for example the preferences dialog is
7310 * currently open, and the user chooses Preferences from the menu
7311 * a second time; use gtk_window_present() to move the already-open dialog
7312 * where the user can see it.
7314 * If you are calling this function in response to a user interaction,
7315 * it is preferable to use gtk_window_present_with_time().
7319 gtk_window_present (GtkWindow *window)
7321 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7325 * gtk_window_present_with_time:
7326 * @window: a #GtkWindow
7327 * @timestamp: the timestamp of the user interaction (typically a
7328 * button or key press event) which triggered this call
7330 * Presents a window to the user in response to a user interaction.
7331 * If you need to present a window without a timestamp, use
7332 * gtk_window_present(). See gtk_window_present() for details.
7337 gtk_window_present_with_time (GtkWindow *window,
7341 GdkWindow *gdk_window;
7343 g_return_if_fail (GTK_IS_WINDOW (window));
7345 widget = GTK_WIDGET (window);
7347 if (gtk_widget_get_visible (widget))
7349 gdk_window = gtk_widget_get_window (widget);
7351 g_assert (gdk_window != NULL);
7353 gdk_window_show (gdk_window);
7355 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7356 if (timestamp == GDK_CURRENT_TIME)
7358 #ifdef GDK_WINDOWING_X11
7359 GdkDisplay *display;
7361 display = gtk_widget_get_display (GTK_WIDGET (window));
7362 timestamp = gdk_x11_display_get_user_time (display);
7364 timestamp = gtk_get_current_event_time ();
7368 gdk_window_focus (gdk_window, timestamp);
7372 gtk_widget_show (widget);
7377 * gtk_window_iconify:
7378 * @window: a #GtkWindow
7380 * Asks to iconify (i.e. minimize) the specified @window. Note that
7381 * you shouldn't assume the window is definitely iconified afterward,
7382 * because other entities (e.g. the user or <link
7383 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7384 * again, or there may not be a window manager in which case
7385 * iconification isn't possible, etc. But normally the window will end
7386 * up iconified. Just don't write code that crashes if not.
7388 * It's permitted to call this function before showing a window,
7389 * in which case the window will be iconified before it ever appears
7392 * You can track iconification via the "window-state-event" signal
7397 gtk_window_iconify (GtkWindow *window)
7399 GtkWindowPrivate *priv;
7401 GdkWindow *toplevel;
7403 g_return_if_fail (GTK_IS_WINDOW (window));
7405 priv = window->priv;
7406 widget = GTK_WIDGET (window);
7408 priv->iconify_initially = TRUE;
7410 toplevel = gtk_widget_get_window (widget);
7412 if (toplevel != NULL)
7413 gdk_window_iconify (toplevel);
7417 * gtk_window_deiconify:
7418 * @window: a #GtkWindow
7420 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7421 * that you shouldn't assume the window is definitely deiconified
7422 * afterward, because other entities (e.g. the user or <link
7423 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7424 * again before your code which assumes deiconification gets to run.
7426 * You can track iconification via the "window-state-event" signal
7430 gtk_window_deiconify (GtkWindow *window)
7432 GtkWindowPrivate *priv;
7434 GdkWindow *toplevel;
7436 g_return_if_fail (GTK_IS_WINDOW (window));
7438 priv = window->priv;
7439 widget = GTK_WIDGET (window);
7441 priv->iconify_initially = FALSE;
7443 toplevel = gtk_widget_get_window (widget);
7445 if (toplevel != NULL)
7446 gdk_window_deiconify (toplevel);
7451 * @window: a #GtkWindow
7453 * Asks to stick @window, which means that it will appear on all user
7454 * desktops. Note that you shouldn't assume the window is definitely
7455 * stuck afterward, because other entities (e.g. the user or <link
7456 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7457 * again, and some window managers do not support sticking
7458 * windows. But normally the window will end up stuck. Just don't
7459 * write code that crashes if not.
7461 * It's permitted to call this function before showing a window.
7463 * You can track stickiness via the "window-state-event" signal
7468 gtk_window_stick (GtkWindow *window)
7470 GtkWindowPrivate *priv;
7472 GdkWindow *toplevel;
7474 g_return_if_fail (GTK_IS_WINDOW (window));
7476 priv = window->priv;
7477 widget = GTK_WIDGET (window);
7479 priv->stick_initially = TRUE;
7481 toplevel = gtk_widget_get_window (widget);
7483 if (toplevel != NULL)
7484 gdk_window_stick (toplevel);
7488 * gtk_window_unstick:
7489 * @window: a #GtkWindow
7491 * Asks to unstick @window, which means that it will appear on only
7492 * one of the user's desktops. Note that you shouldn't assume the
7493 * window is definitely unstuck afterward, because other entities
7494 * (e.g. the user or <link linkend="gtk-X11-arch">window
7495 * manager</link>) could stick it again. But normally the window will
7496 * end up stuck. Just don't write code that crashes if not.
7498 * You can track stickiness via the "window-state-event" signal
7503 gtk_window_unstick (GtkWindow *window)
7505 GtkWindowPrivate *priv;
7507 GdkWindow *toplevel;
7509 g_return_if_fail (GTK_IS_WINDOW (window));
7511 priv = window->priv;
7512 widget = GTK_WIDGET (window);
7514 priv->stick_initially = FALSE;
7516 toplevel = gtk_widget_get_window (widget);
7518 if (toplevel != NULL)
7519 gdk_window_unstick (toplevel);
7523 * gtk_window_maximize:
7524 * @window: a #GtkWindow
7526 * Asks to maximize @window, so that it becomes full-screen. Note that
7527 * you shouldn't assume the window is definitely maximized afterward,
7528 * because other entities (e.g. the user or <link
7529 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7530 * again, and not all window managers support maximization. But
7531 * normally the window will end up maximized. Just don't write code
7532 * that crashes if not.
7534 * It's permitted to call this function before showing a window,
7535 * in which case the window will be maximized when it appears onscreen
7538 * You can track maximization via the "window-state-event" signal
7543 gtk_window_maximize (GtkWindow *window)
7545 GtkWindowPrivate *priv;
7547 GdkWindow *toplevel;
7549 g_return_if_fail (GTK_IS_WINDOW (window));
7551 priv = window->priv;
7552 widget = GTK_WIDGET (window);
7554 priv->maximize_initially = TRUE;
7556 toplevel = gtk_widget_get_window (widget);
7558 if (toplevel != NULL)
7559 gdk_window_maximize (toplevel);
7563 * gtk_window_unmaximize:
7564 * @window: a #GtkWindow
7566 * Asks to unmaximize @window. Note that you shouldn't assume the
7567 * window is definitely unmaximized afterward, because other entities
7568 * (e.g. the user or <link linkend="gtk-X11-arch">window
7569 * manager</link>) could maximize it again, and not all window
7570 * managers honor requests to unmaximize. But normally the window will
7571 * end up unmaximized. Just don't write code that crashes if not.
7573 * You can track maximization via the "window-state-event" signal
7578 gtk_window_unmaximize (GtkWindow *window)
7580 GtkWindowPrivate *priv;
7582 GdkWindow *toplevel;
7584 g_return_if_fail (GTK_IS_WINDOW (window));
7586 priv = window->priv;
7587 widget = GTK_WIDGET (window);
7589 priv->maximize_initially = FALSE;
7591 toplevel = gtk_widget_get_window (widget);
7593 if (toplevel != NULL)
7594 gdk_window_unmaximize (toplevel);
7598 * gtk_window_fullscreen:
7599 * @window: a #GtkWindow
7601 * Asks to place @window in the fullscreen state. Note that you
7602 * shouldn't assume the window is definitely full screen afterward,
7603 * because other entities (e.g. the user or <link
7604 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7605 * again, and not all window managers honor requests to fullscreen
7606 * windows. But normally the window will end up fullscreen. Just
7607 * don't write code that crashes if not.
7609 * You can track the fullscreen state via the "window-state-event" signal
7615 gtk_window_fullscreen (GtkWindow *window)
7617 GtkWindowPrivate *priv;
7619 GdkWindow *toplevel;
7621 g_return_if_fail (GTK_IS_WINDOW (window));
7623 priv = window->priv;
7624 widget = GTK_WIDGET (window);
7626 priv->fullscreen_initially = TRUE;
7628 toplevel = gtk_widget_get_window (widget);
7630 if (toplevel != NULL)
7631 gdk_window_fullscreen (toplevel);
7635 * gtk_window_unfullscreen:
7636 * @window: a #GtkWindow
7638 * Asks to toggle off the fullscreen state for @window. Note that you
7639 * shouldn't assume the window is definitely not full screen
7640 * afterward, because other entities (e.g. the user or <link
7641 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7642 * again, and not all window managers honor requests to unfullscreen
7643 * windows. But normally the window will end up restored to its normal
7644 * state. Just don't write code that crashes if not.
7646 * You can track the fullscreen state via the "window-state-event" signal
7652 gtk_window_unfullscreen (GtkWindow *window)
7655 GdkWindow *toplevel;
7656 GtkWindowPrivate *priv;
7658 g_return_if_fail (GTK_IS_WINDOW (window));
7660 priv = window->priv;
7661 widget = GTK_WIDGET (window);
7663 priv->fullscreen_initially = FALSE;
7665 toplevel = gtk_widget_get_window (widget);
7667 if (toplevel != NULL)
7668 gdk_window_unfullscreen (toplevel);
7672 * gtk_window_set_keep_above:
7673 * @window: a #GtkWindow
7674 * @setting: whether to keep @window above other windows
7676 * Asks to keep @window above, so that it stays on top. Note that
7677 * you shouldn't assume the window is definitely above afterward,
7678 * because other entities (e.g. the user or <link
7679 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7680 * and not all window managers support keeping windows above. But
7681 * normally the window will end kept above. Just don't write code
7682 * that crashes if not.
7684 * It's permitted to call this function before showing a window,
7685 * in which case the window will be kept above when it appears onscreen
7688 * You can track the above state via the "window-state-event" signal
7691 * Note that, according to the <ulink
7692 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7693 * Manager Hints</ulink> specification, the above state is mainly meant
7694 * for user preferences and should not be used by applications e.g. for
7695 * drawing attention to their dialogs.
7700 gtk_window_set_keep_above (GtkWindow *window,
7704 GtkWindowPrivate *priv;
7705 GdkWindow *toplevel;
7707 g_return_if_fail (GTK_IS_WINDOW (window));
7709 priv = window->priv;
7710 widget = GTK_WIDGET (window);
7712 priv->above_initially = setting != FALSE;
7714 priv->below_initially = FALSE;
7716 toplevel = gtk_widget_get_window (widget);
7718 if (toplevel != NULL)
7719 gdk_window_set_keep_above (toplevel, setting);
7723 * gtk_window_set_keep_below:
7724 * @window: a #GtkWindow
7725 * @setting: whether to keep @window below other windows
7727 * Asks to keep @window below, so that it stays in bottom. Note that
7728 * you shouldn't assume the window is definitely below afterward,
7729 * because other entities (e.g. the user or <link
7730 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7731 * and not all window managers support putting windows below. But
7732 * normally the window will be kept below. Just don't write code
7733 * that crashes if not.
7735 * It's permitted to call this function before showing a window,
7736 * in which case the window will be kept below when it appears onscreen
7739 * You can track the below state via the "window-state-event" signal
7742 * Note that, according to the <ulink
7743 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7744 * Manager Hints</ulink> specification, the above state is mainly meant
7745 * for user preferences and should not be used by applications e.g. for
7746 * drawing attention to their dialogs.
7751 gtk_window_set_keep_below (GtkWindow *window,
7755 GtkWindowPrivate *priv;
7756 GdkWindow *toplevel;
7758 g_return_if_fail (GTK_IS_WINDOW (window));
7760 priv = window->priv;
7761 widget = GTK_WIDGET (window);
7763 priv->below_initially = setting != FALSE;
7765 priv->above_initially = FALSE;
7767 toplevel = gtk_widget_get_window (widget);
7769 if (toplevel != NULL)
7770 gdk_window_set_keep_below (toplevel, setting);
7774 * gtk_window_set_resizable:
7775 * @window: a #GtkWindow
7776 * @resizable: %TRUE if the user can resize this window
7778 * Sets whether the user can resize a window. Windows are user resizable
7782 gtk_window_set_resizable (GtkWindow *window,
7785 GtkWindowPrivate *priv;
7787 g_return_if_fail (GTK_IS_WINDOW (window));
7789 priv = window->priv;
7791 resizable = (resizable != FALSE);
7793 if (priv->resizable != resizable)
7795 priv->resizable = (resizable != FALSE);
7797 update_grip_visibility (window);
7799 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7801 g_object_notify (G_OBJECT (window), "resizable");
7806 * gtk_window_get_resizable:
7807 * @window: a #GtkWindow
7809 * Gets the value set by gtk_window_set_resizable().
7811 * Return value: %TRUE if the user can resize the window
7814 gtk_window_get_resizable (GtkWindow *window)
7816 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7818 return window->priv->resizable;
7822 * gtk_window_set_gravity:
7823 * @window: a #GtkWindow
7824 * @gravity: window gravity
7826 * Window gravity defines the meaning of coordinates passed to
7827 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7830 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7831 * typically "do what you mean."
7835 gtk_window_set_gravity (GtkWindow *window,
7838 GtkWindowPrivate *priv;
7840 g_return_if_fail (GTK_IS_WINDOW (window));
7842 priv = window->priv;
7844 if (gravity != priv->gravity)
7846 priv->gravity = gravity;
7848 /* gtk_window_move_resize() will adapt gravity
7850 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7852 g_object_notify (G_OBJECT (window), "gravity");
7857 * gtk_window_get_gravity:
7858 * @window: a #GtkWindow
7860 * Gets the value set by gtk_window_set_gravity().
7862 * Return value: (transfer none): window gravity
7865 gtk_window_get_gravity (GtkWindow *window)
7867 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7869 return window->priv->gravity;
7873 * gtk_window_begin_resize_drag:
7874 * @window: a #GtkWindow
7875 * @button: mouse button that initiated the drag
7876 * @edge: position of the resize control
7877 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7878 * @root_y: Y position where the user clicked to initiate the drag
7879 * @timestamp: timestamp from the click event that initiated the drag
7881 * Starts resizing a window. This function is used if an application
7882 * has window resizing controls. When GDK can support it, the resize
7883 * will be done using the standard mechanism for the <link
7884 * linkend="gtk-X11-arch">window manager</link> or windowing
7885 * system. Otherwise, GDK will try to emulate window resizing,
7886 * potentially not all that well, depending on the windowing system.
7890 gtk_window_begin_resize_drag (GtkWindow *window,
7897 GtkWindowPrivate *priv;
7899 GdkWindow *toplevel;
7901 g_return_if_fail (GTK_IS_WINDOW (window));
7902 widget = GTK_WIDGET (window);
7903 g_return_if_fail (gtk_widget_get_visible (widget));
7905 priv = window->priv;
7907 toplevel = gtk_widget_get_window (widget);
7909 gdk_window_begin_resize_drag (toplevel,
7916 * gtk_window_begin_move_drag:
7917 * @window: a #GtkWindow
7918 * @button: mouse button that initiated the drag
7919 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7920 * @root_y: Y position where the user clicked to initiate the drag
7921 * @timestamp: timestamp from the click event that initiated the drag
7923 * Starts moving a window. This function is used if an application has
7924 * window movement grips. When GDK can support it, the window movement
7925 * will be done using the standard mechanism for the <link
7926 * linkend="gtk-X11-arch">window manager</link> or windowing
7927 * system. Otherwise, GDK will try to emulate window movement,
7928 * potentially not all that well, depending on the windowing system.
7932 gtk_window_begin_move_drag (GtkWindow *window,
7938 GtkWindowPrivate *priv;
7940 GdkWindow *toplevel;
7942 g_return_if_fail (GTK_IS_WINDOW (window));
7943 widget = GTK_WIDGET (window);
7944 g_return_if_fail (gtk_widget_get_visible (widget));
7946 priv = window->priv;
7948 toplevel = gtk_widget_get_window (widget);
7950 gdk_window_begin_move_drag (toplevel,
7957 * gtk_window_set_screen:
7958 * @window: a #GtkWindow.
7959 * @screen: a #GdkScreen.
7961 * Sets the #GdkScreen where the @window is displayed; if
7962 * the window is already mapped, it will be unmapped, and
7963 * then remapped on the new screen.
7968 gtk_window_set_screen (GtkWindow *window,
7971 GtkWindowPrivate *priv;
7973 GdkScreen *previous_screen;
7974 gboolean was_mapped;
7976 g_return_if_fail (GTK_IS_WINDOW (window));
7977 g_return_if_fail (GDK_IS_SCREEN (screen));
7979 priv = window->priv;
7981 if (screen == priv->screen)
7984 widget = GTK_WIDGET (window);
7986 previous_screen = priv->screen;
7987 was_mapped = gtk_widget_get_mapped (widget);
7990 gtk_widget_unmap (widget);
7991 if (gtk_widget_get_realized (widget))
7992 gtk_widget_unrealize (widget);
7994 gtk_window_free_key_hash (window);
7995 priv->screen = screen;
7996 gtk_widget_reset_rc_styles (widget);
7997 if (screen != previous_screen)
7999 g_signal_handlers_disconnect_by_func (previous_screen,
8000 gtk_window_on_composited_changed, window);
8001 g_signal_connect (screen, "composited-changed",
8002 G_CALLBACK (gtk_window_on_composited_changed), window);
8004 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8005 _gtk_widget_propagate_composited_changed (widget);
8007 g_object_notify (G_OBJECT (window), "screen");
8010 gtk_widget_map (widget);
8014 gtk_window_on_composited_changed (GdkScreen *screen,
8017 gtk_widget_queue_draw (GTK_WIDGET (window));
8019 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8023 gtk_window_check_screen (GtkWindow *window)
8025 GtkWindowPrivate *priv = window->priv;
8028 return priv->screen;
8031 g_warning ("Screen for GtkWindow not set; you must always set\n"
8032 "a screen for a GtkWindow before using the window");
8038 * gtk_window_get_screen:
8039 * @window: a #GtkWindow.
8041 * Returns the #GdkScreen associated with @window.
8043 * Return value: (transfer none): a #GdkScreen.
8048 gtk_window_get_screen (GtkWindow *window)
8050 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8052 return window->priv->screen;
8056 * gtk_window_is_active:
8057 * @window: a #GtkWindow
8059 * Returns whether the window is part of the current active toplevel.
8060 * (That is, the toplevel window receiving keystrokes.)
8061 * The return value is %TRUE if the window is active toplevel
8062 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8063 * You might use this function if you wanted to draw a widget
8064 * differently in an active window from a widget in an inactive window.
8065 * See gtk_window_has_toplevel_focus()
8067 * Return value: %TRUE if the window part of the current active window.
8072 gtk_window_is_active (GtkWindow *window)
8074 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8076 return window->priv->is_active;
8080 * gtk_window_has_toplevel_focus:
8081 * @window: a #GtkWindow
8083 * Returns whether the input focus is within this GtkWindow.
8084 * For real toplevel windows, this is identical to gtk_window_is_active(),
8085 * but for embedded windows, like #GtkPlug, the results will differ.
8087 * Return value: %TRUE if the input focus is within this GtkWindow
8092 gtk_window_has_toplevel_focus (GtkWindow *window)
8094 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8096 return window->priv->has_toplevel_focus;
8099 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8102 gtk_window_group_init (GtkWindowGroup *group)
8104 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8105 GTK_TYPE_WINDOW_GROUP,
8106 GtkWindowGroupPrivate);
8110 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8112 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8116 * gtk_window_group_new:
8118 * Creates a new #GtkWindowGroup object. Grabs added with
8119 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8121 * Return value: a new #GtkWindowGroup.
8124 gtk_window_group_new (void)
8126 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8130 window_group_cleanup_grabs (GtkWindowGroup *group,
8133 GtkWindowGroupPrivate *priv;
8134 GtkDeviceGrabInfo *info;
8136 GSList *to_remove = NULL;
8140 tmp_list = priv->grabs;
8143 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8144 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8145 tmp_list = tmp_list->next;
8150 gtk_grab_remove (to_remove->data);
8151 g_object_unref (to_remove->data);
8152 to_remove = g_slist_delete_link (to_remove, to_remove);
8155 tmp_list = priv->device_grabs;
8159 info = tmp_list->data;
8161 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8162 to_remove = g_slist_prepend (to_remove, info);
8164 tmp_list = tmp_list->next;
8169 info = to_remove->data;
8171 gtk_device_grab_remove (info->widget, info->device);
8172 to_remove = g_slist_delete_link (to_remove, to_remove);
8177 * gtk_window_group_add_window:
8178 * @window_group: a #GtkWindowGroup
8179 * @window: the #GtkWindow to add
8181 * Adds a window to a #GtkWindowGroup.
8184 gtk_window_group_add_window (GtkWindowGroup *window_group,
8187 GtkWindowPrivate *priv;
8189 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8190 g_return_if_fail (GTK_IS_WINDOW (window));
8192 priv = window->priv;
8194 if (priv->group != window_group)
8196 g_object_ref (window);
8197 g_object_ref (window_group);
8200 gtk_window_group_remove_window (priv->group, window);
8202 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8204 priv->group = window_group;
8206 g_object_unref (window);
8211 * gtk_window_group_remove_window:
8212 * @window_group: a #GtkWindowGroup
8213 * @window: the #GtkWindow to remove
8215 * Removes a window from a #GtkWindowGroup.
8218 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8221 GtkWindowPrivate *priv;
8223 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8224 g_return_if_fail (GTK_IS_WINDOW (window));
8225 priv = window->priv;
8226 g_return_if_fail (priv->group == window_group);
8228 g_object_ref (window);
8230 window_group_cleanup_grabs (window_group, window);
8233 g_object_unref (window_group);
8234 g_object_unref (window);
8238 * gtk_window_group_list_windows:
8239 * @window_group: a #GtkWindowGroup
8241 * Returns a list of the #GtkWindows that belong to @window_group.
8243 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8244 * windows inside the group.
8249 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8251 GList *toplevels, *toplevel, *group_windows;
8253 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8255 group_windows = NULL;
8256 toplevels = gtk_window_list_toplevels ();
8258 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8260 GtkWindow *window = toplevel->data;
8262 if (window_group == window->priv->group)
8263 group_windows = g_list_prepend (group_windows, window);
8266 return g_list_reverse (group_windows);
8270 * gtk_window_get_group:
8271 * @window: (allow-none): a #GtkWindow, or %NULL
8273 * Returns the group for @window or the default group, if
8274 * @window is %NULL or if @window does not have an explicit
8277 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8282 gtk_window_get_group (GtkWindow *window)
8284 if (window && window->priv->group)
8285 return window->priv->group;
8288 static GtkWindowGroup *default_group = NULL;
8291 default_group = gtk_window_group_new ();
8293 return default_group;
8298 * gtk_window_has_group:
8299 * @window: a #GtkWindow
8301 * Returns whether @window has an explicit window group.
8303 * Return value: %TRUE if @window has an explicit window group.
8308 gtk_window_has_group (GtkWindow *window)
8310 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8312 return window->priv->group != NULL;
8316 * gtk_window_group_get_current_grab:
8317 * @window_group: a #GtkWindowGroup
8319 * Gets the current grab widget of the given group,
8320 * see gtk_grab_add().
8322 * Returns: the current grab widget of the group
8327 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8329 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8331 if (window_group->priv->grabs)
8332 return GTK_WIDGET (window_group->priv->grabs->data);
8337 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8340 GtkWindowGroupPrivate *priv;
8342 priv = window_group->priv;
8343 priv->grabs = g_slist_prepend (priv->grabs, widget);
8347 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8350 GtkWindowGroupPrivate *priv;
8352 priv = window_group->priv;
8353 priv->grabs = g_slist_remove (priv->grabs, widget);
8358 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8361 gboolean block_others)
8363 GtkWindowGroupPrivate *priv;
8364 GtkDeviceGrabInfo *info;
8366 priv = window_group->priv;
8368 info = g_slice_new0 (GtkDeviceGrabInfo);
8369 info->widget = widget;
8370 info->device = device;
8371 info->block_others = block_others;
8373 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8377 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8381 GtkWindowGroupPrivate *priv;
8382 GtkDeviceGrabInfo *info;
8383 GSList *list, *node = NULL;
8384 GdkDevice *other_device;
8386 priv = window_group->priv;
8387 other_device = gdk_device_get_associated_device (device);
8388 list = priv->device_grabs;
8394 if (info->widget == widget &&
8395 (info->device == device ||
8396 info->device == other_device))
8409 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8410 g_slice_free (GtkDeviceGrabInfo, info);
8415 * gtk_window_group_get_current_device_grab:
8416 * @window_group: a #GtkWindowGroup
8417 * @device: a #GdkDevice
8419 * Returns the current grab widget for @device, or %NULL if none.
8421 * Returns: The grab widget, or %NULL
8426 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8429 GtkWindowGroupPrivate *priv;
8430 GtkDeviceGrabInfo *info;
8431 GdkDevice *other_device;
8434 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8435 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8437 priv = window_group->priv;
8438 list = priv->device_grabs;
8439 other_device = gdk_device_get_associated_device (device);
8446 if (info->device == device ||
8447 info->device == other_device)
8448 return info->widget;
8455 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8459 GtkWindowGroupPrivate *priv;
8460 GtkDeviceGrabInfo *info;
8461 GdkDevice *other_device;
8464 priv = window_group->priv;
8465 other_device = gdk_device_get_associated_device (device);
8466 list = priv->device_grabs;
8473 /* Look for blocking grabs on other device pairs
8474 * that have the passed widget within the GTK+ grab.
8476 if (info->block_others &&
8477 info->device != device &&
8478 info->device != other_device &&
8479 (info->widget == widget ||
8480 gtk_widget_is_ancestor (widget, info->widget)))
8488 Derived from XParseGeometry() in XFree86
8490 Copyright 1985, 1986, 1987,1998 The Open Group
8492 All Rights Reserved.
8494 The above copyright notice and this permission notice shall be included
8495 in all copies or substantial portions of the Software.
8497 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8498 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8499 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8500 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8501 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8502 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8503 OTHER DEALINGS IN THE SOFTWARE.
8505 Except as contained in this notice, the name of The Open Group shall
8506 not be used in advertising or otherwise to promote the sale, use or
8507 other dealings in this Software without prior written authorization
8508 from The Open Group.
8513 * XParseGeometry parses strings of the form
8514 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8515 * width, height, xoffset, and yoffset are unsigned integers.
8516 * Example: "=80x24+300-49"
8517 * The equal sign is optional.
8518 * It returns a bitmask that indicates which of the four values
8519 * were actually found in the string. For each value found,
8520 * the corresponding argument is updated; for each value
8521 * not found, the corresponding argument is left unchanged.
8524 /* The following code is from Xlib, and is minimally modified, so we
8525 * can track any upstream changes if required. Don't change this
8526 * code. Or if you do, put in a huge comment marking which thing
8531 read_int (gchar *string,
8539 else if (*string == '-')
8545 for (; (*string >= '0') && (*string <= '9'); string++)
8547 result = (result * 10) + (*string - '0');
8559 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8560 * value (x, y, width, height) was found in the parsed string.
8562 #define NoValue 0x0000
8563 #define XValue 0x0001
8564 #define YValue 0x0002
8565 #define WidthValue 0x0004
8566 #define HeightValue 0x0008
8567 #define AllValues 0x000F
8568 #define XNegative 0x0010
8569 #define YNegative 0x0020
8571 /* Try not to reformat/modify, so we can compare/sync with X sources */
8573 gtk_XParseGeometry (const char *string,
8576 unsigned int *width,
8577 unsigned int *height)
8581 unsigned int tempWidth, tempHeight;
8583 char *nextCharacter;
8585 /* These initializations are just to silence gcc */
8591 if ( (string == NULL) || (*string == '\0')) return(mask);
8593 string++; /* ignore possible '=' at beg of geometry spec */
8595 strind = (char *)string;
8596 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8597 tempWidth = read_int(strind, &nextCharacter);
8598 if (strind == nextCharacter)
8600 strind = nextCharacter;
8604 if (*strind == 'x' || *strind == 'X') {
8606 tempHeight = read_int(strind, &nextCharacter);
8607 if (strind == nextCharacter)
8609 strind = nextCharacter;
8610 mask |= HeightValue;
8613 if ((*strind == '+') || (*strind == '-')) {
8614 if (*strind == '-') {
8616 tempX = -read_int(strind, &nextCharacter);
8617 if (strind == nextCharacter)
8619 strind = nextCharacter;
8625 tempX = read_int(strind, &nextCharacter);
8626 if (strind == nextCharacter)
8628 strind = nextCharacter;
8631 if ((*strind == '+') || (*strind == '-')) {
8632 if (*strind == '-') {
8634 tempY = -read_int(strind, &nextCharacter);
8635 if (strind == nextCharacter)
8637 strind = nextCharacter;
8644 tempY = read_int(strind, &nextCharacter);
8645 if (strind == nextCharacter)
8647 strind = nextCharacter;
8653 /* If strind isn't at the end of the string the it's an invalid
8654 geometry specification. */
8656 if (*strind != '\0') return (0);
8662 if (mask & WidthValue)
8664 if (mask & HeightValue)
8665 *height = tempHeight;
8670 * gtk_window_parse_geometry:
8671 * @window: a #GtkWindow
8672 * @geometry: geometry string
8674 * Parses a standard X Window System geometry string - see the
8675 * manual page for X (type 'man X') for details on this.
8676 * gtk_window_parse_geometry() does work on all GTK+ ports
8677 * including Win32 but is primarily intended for an X environment.
8679 * If either a size or a position can be extracted from the
8680 * geometry string, gtk_window_parse_geometry() returns %TRUE
8681 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8682 * to resize/move the window.
8684 * If gtk_window_parse_geometry() returns %TRUE, it will also
8685 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8686 * indicating to the window manager that the size/position of
8687 * the window was user-specified. This causes most window
8688 * managers to honor the geometry.
8690 * Note that for gtk_window_parse_geometry() to work as expected, it has
8691 * to be called when the window has its "final" size, i.e. after calling
8692 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8695 * #include <gtk/gtk.h>
8698 * fill_with_content (GtkWidget *vbox)
8700 * /* fill with content... */
8704 * main (int argc, char *argv[])
8706 * GtkWidget *window, *vbox;
8707 * GdkGeometry size_hints = {
8708 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8711 * gtk_init (&argc, &argv);
8713 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8714 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8716 * gtk_container_add (GTK_CONTAINER (window), vbox);
8717 * fill_with_content (vbox);
8718 * gtk_widget_show_all (vbox);
8720 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8723 * GDK_HINT_MIN_SIZE |
8724 * GDK_HINT_BASE_SIZE |
8725 * GDK_HINT_RESIZE_INC);
8729 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8730 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8733 * gtk_widget_show_all (window);
8740 * Return value: %TRUE if string was parsed successfully
8743 gtk_window_parse_geometry (GtkWindow *window,
8744 const gchar *geometry)
8746 gint result, x = 0, y = 0;
8750 gboolean size_set, pos_set;
8753 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8754 g_return_val_if_fail (geometry != NULL, FALSE);
8756 child = gtk_bin_get_child (GTK_BIN (window));
8757 if (!child || !gtk_widget_get_visible (child))
8758 g_warning ("gtk_window_parse_geometry() called on a window with no "
8759 "visible children; the window should be set up before "
8760 "gtk_window_parse_geometry() is called.");
8762 screen = gtk_window_check_screen (window);
8764 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8767 if ((result & WidthValue) || (result & HeightValue))
8769 gtk_window_set_default_size_internal (window,
8770 TRUE, result & WidthValue ? w : -1,
8771 TRUE, result & HeightValue ? h : -1,
8776 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8778 grav = GDK_GRAVITY_NORTH_WEST;
8780 if ((result & XNegative) && (result & YNegative))
8781 grav = GDK_GRAVITY_SOUTH_EAST;
8782 else if (result & XNegative)
8783 grav = GDK_GRAVITY_NORTH_EAST;
8784 else if (result & YNegative)
8785 grav = GDK_GRAVITY_SOUTH_WEST;
8787 if ((result & XValue) == 0)
8790 if ((result & YValue) == 0)
8793 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8794 grav == GDK_GRAVITY_SOUTH_EAST)
8795 y = gdk_screen_get_height (screen) - h + y;
8797 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8798 grav == GDK_GRAVITY_NORTH_EAST)
8799 x = gdk_screen_get_width (screen) - w + x;
8801 /* we don't let you put a window offscreen; maybe some people would
8802 * prefer to be able to, but it's kind of a bogus thing to do.
8811 if ((result & XValue) || (result & YValue))
8813 gtk_window_set_gravity (window, grav);
8814 gtk_window_move (window, x, y);
8818 if (size_set || pos_set)
8820 /* Set USSize, USPosition hints */
8821 GtkWindowGeometryInfo *info;
8823 info = gtk_window_get_geometry_info (window, TRUE);
8826 info->mask |= GDK_HINT_USER_POS;
8828 info->mask |= GDK_HINT_USER_SIZE;
8835 gtk_window_mnemonic_hash_foreach (guint keyval,
8841 GtkWindowKeysForeachFunc func;
8845 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8849 _gtk_window_keys_foreach (GtkWindow *window,
8850 GtkWindowKeysForeachFunc func,
8854 GtkMnemonicHash *mnemonic_hash;
8858 GtkWindowKeysForeachFunc func;
8862 info.window = window;
8864 info.func_data = func_data;
8866 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8868 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8869 gtk_window_mnemonic_hash_foreach, &info);
8871 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8874 GtkAccelGroup *group = groups->data;
8877 for (i = 0; i < group->priv->n_accels; i++)
8879 GtkAccelKey *key = &group->priv->priv_accels[i].key;
8882 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8885 groups = groups->next;
8890 gtk_window_keys_changed (GtkWindow *window)
8892 gtk_window_free_key_hash (window);
8893 gtk_window_get_key_hash (window);
8896 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8898 struct _GtkWindowKeyEntry
8902 guint is_mnemonic : 1;
8906 window_key_entry_destroy (gpointer data)
8908 g_slice_free (GtkWindowKeyEntry, data);
8912 add_to_key_hash (GtkWindow *window,
8914 GdkModifierType modifiers,
8915 gboolean is_mnemonic,
8918 GtkKeyHash *key_hash = data;
8920 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8922 entry->keyval = keyval;
8923 entry->modifiers = modifiers;
8924 entry->is_mnemonic = is_mnemonic;
8926 /* GtkAccelGroup stores lowercased accelerators. To deal
8927 * with this, if <Shift> was specified, uppercase.
8929 if (modifiers & GDK_SHIFT_MASK)
8931 if (keyval == GDK_KEY_Tab)
8932 keyval = GDK_KEY_ISO_Left_Tab;
8934 keyval = gdk_keyval_to_upper (keyval);
8937 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8941 gtk_window_get_key_hash (GtkWindow *window)
8943 GdkScreen *screen = gtk_window_check_screen (window);
8944 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8949 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8950 (GDestroyNotify)window_key_entry_destroy);
8951 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8952 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8958 gtk_window_free_key_hash (GtkWindow *window)
8960 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8963 _gtk_key_hash_free (key_hash);
8964 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8969 * gtk_window_activate_key:
8970 * @window: a #GtkWindow
8971 * @event: a #GdkEventKey
8973 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8974 * called by the default ::key_press_event handler for toplevel windows,
8975 * however in some cases it may be useful to call this directly when
8976 * overriding the standard key handling for a toplevel window.
8978 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8983 gtk_window_activate_key (GtkWindow *window,
8986 GtkKeyHash *key_hash;
8987 GtkWindowKeyEntry *found_entry = NULL;
8988 gboolean enable_mnemonics;
8989 gboolean enable_accels;
8991 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8992 g_return_val_if_fail (event != NULL, FALSE);
8994 key_hash = gtk_window_get_key_hash (window);
8999 GSList *entries = _gtk_key_hash_lookup (key_hash,
9000 event->hardware_keycode,
9002 gtk_accelerator_get_default_mod_mask (),
9005 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9006 "gtk-enable-mnemonics", &enable_mnemonics,
9007 "gtk-enable-accels", &enable_accels,
9010 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9012 GtkWindowKeyEntry *entry = tmp_list->data;
9013 if (entry->is_mnemonic)
9015 if (enable_mnemonics)
9017 found_entry = entry;
9023 if (enable_accels && !found_entry)
9025 found_entry = entry;
9030 g_slist_free (entries);
9035 if (found_entry->is_mnemonic)
9037 if (enable_mnemonics)
9038 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9039 found_entry->modifiers);
9044 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9045 found_entry->modifiers);
9053 window_update_has_focus (GtkWindow *window)
9055 GtkWindowPrivate *priv = window->priv;
9056 GtkWidget *widget = GTK_WIDGET (window);
9057 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9059 if (has_focus != priv->has_focus)
9061 priv->has_focus = has_focus;
9065 if (priv->focus_widget &&
9066 priv->focus_widget != widget &&
9067 !gtk_widget_has_focus (priv->focus_widget))
9068 do_focus_change (priv->focus_widget, TRUE);
9072 if (priv->focus_widget &&
9073 priv->focus_widget != widget &&
9074 gtk_widget_has_focus (priv->focus_widget))
9075 do_focus_change (priv->focus_widget, FALSE);
9081 * _gtk_window_set_is_active:
9082 * @window: a #GtkWindow
9083 * @is_active: %TRUE if the window is in the currently active toplevel
9085 * Internal function that sets whether the #GtkWindow is part
9086 * of the currently active toplevel window (taking into account inter-process
9090 _gtk_window_set_is_active (GtkWindow *window,
9093 GtkWindowPrivate *priv;
9095 g_return_if_fail (GTK_IS_WINDOW (window));
9097 priv = window->priv;
9099 is_active = is_active != FALSE;
9101 if (is_active != priv->is_active)
9103 priv->is_active = is_active;
9104 window_update_has_focus (window);
9106 g_object_notify (G_OBJECT (window), "is-active");
9111 * _gtk_window_set_is_toplevel:
9112 * @window: a #GtkWindow
9113 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9114 * child of the root window); %FALSE if it is not (for example, for an
9115 * in-process, parented GtkPlug)
9117 * Internal function used by #GtkPlug when it gets parented/unparented by a
9118 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9119 * global list of toplevel windows.
9122 _gtk_window_set_is_toplevel (GtkWindow *window,
9123 gboolean is_toplevel)
9127 widget = GTK_WIDGET (window);
9129 if (gtk_widget_is_toplevel (widget))
9130 g_assert (g_slist_find (toplevel_list, window) != NULL);
9132 g_assert (g_slist_find (toplevel_list, window) == NULL);
9134 if (is_toplevel == gtk_widget_is_toplevel (widget))
9139 _gtk_widget_set_is_toplevel (widget, TRUE);
9140 toplevel_list = g_slist_prepend (toplevel_list, window);
9144 _gtk_widget_set_is_toplevel (widget, FALSE);
9145 toplevel_list = g_slist_remove (toplevel_list, window);
9150 * _gtk_window_set_has_toplevel_focus:
9151 * @window: a #GtkWindow
9152 * @has_toplevel_focus: %TRUE if the in
9154 * Internal function that sets whether the keyboard focus for the
9155 * toplevel window (taking into account inter-process embedding.)
9158 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9159 gboolean has_toplevel_focus)
9161 GtkWindowPrivate *priv;
9163 g_return_if_fail (GTK_IS_WINDOW (window));
9165 priv = window->priv;
9167 has_toplevel_focus = has_toplevel_focus != FALSE;
9169 if (has_toplevel_focus != priv->has_toplevel_focus)
9171 priv->has_toplevel_focus = has_toplevel_focus;
9172 window_update_has_focus (window);
9174 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9179 * gtk_window_set_auto_startup_notification:
9180 * @setting: %TRUE to automatically do startup notification
9182 * By default, after showing the first #GtkWindow, GTK+ calls
9183 * gdk_notify_startup_complete(). Call this function to disable
9184 * the automatic startup notification. You might do this if your
9185 * first window is a splash screen, and you want to delay notification
9186 * until after your real main window has been shown, for example.
9188 * In that example, you would disable startup notification
9189 * temporarily, show your splash screen, then re-enable it so that
9190 * showing the main window would automatically result in notification.
9195 gtk_window_set_auto_startup_notification (gboolean setting)
9197 disable_startup_notification = !setting;
9201 * gtk_window_get_window_type:
9202 * @window: a #GtkWindow
9204 * Gets the type of the window. See #GtkWindowType.
9206 * Return value: the type of the window
9211 gtk_window_get_window_type (GtkWindow *window)
9213 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9215 return window->priv->type;
9219 * gtk_window_get_mnemonics_visible:
9220 * @window: a #GtkWindow
9222 * Gets the value of the #GtkWindow:mnemonics-visible property.
9224 * Returns: %TRUE if mnemonics are supposed to be visible
9230 gtk_window_get_mnemonics_visible (GtkWindow *window)
9232 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9234 return window->priv->mnemonics_visible;
9238 * gtk_window_set_mnemonics_visible:
9239 * @window: a #GtkWindow
9240 * @setting: the new value
9242 * Sets the #GtkWindow:mnemonics-visible property.
9247 gtk_window_set_mnemonics_visible (GtkWindow *window,
9250 GtkWindowPrivate *priv;
9252 g_return_if_fail (GTK_IS_WINDOW (window));
9254 priv = window->priv;
9256 setting = setting != FALSE;
9258 if (priv->mnemonics_visible != setting)
9260 priv->mnemonics_visible = setting;
9261 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9264 priv->mnemonics_visible_set = TRUE;
9268 _gtk_window_get_wmclass (GtkWindow *window,
9269 gchar **wmclass_name,
9270 gchar **wmclass_class)
9272 GtkWindowPrivate *priv = window->priv;
9274 *wmclass_name = priv->wmclass_name;
9275 *wmclass_class = priv->wmclass_class;