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 "gtkbindings.h"
43 #include "gtkkeyhash.h"
45 #include "gtkmnemonichash.h"
46 #include "gtkmenubar.h"
47 #include "gtkiconfactory.h"
48 #include "gtkicontheme.h"
49 #include "gtkmarshalers.h"
51 #include "gtkbuildable.h"
52 #include "gtkwidgetprivate.h"
54 #ifdef GDK_WINDOWING_X11
61 * @short_description: Toplevel which can contain other widgets
63 * A GtkWindow is a toplevel window which can contain other widgets.
64 * Windows normally have decorations that are under the control
65 * of the windowing system and allow the user to manipulate the window
66 * (resize it, move it, close it,...).
68 * GTK+ also allows windows to have a resize grip (a small area in the lower
69 * right or left corner) which can be clicked to reszie the window. To
70 * control whether a window has a resize grip, use
71 * gtk_window_set_has_resize_grip().
73 * <refsect2 id="GtkWindow-BUILDER-UI">
74 * <title>GtkWindow as GtkBuildable</title>
76 * The GtkWindow implementation of the GtkBuildable interface supports a
77 * custom <tag class="starttag">accel-groups</tag> element, which supports
78 * any number of <tag class="starttag">group</tag> elements representing the
79 * #GtkAccelGroup objects you want to add to your window (synonymous with
80 * gtk_window_add_accel_group().
83 * <title>A UI definition fragment with accel groups</title>
84 * <programlisting><![CDATA[
85 * <object class="GtkWindow">
87 * <group name="accelgroup1"/>
93 * <object class="GtkAccelGroup" id="accelgroup1"/>
94 * ]]></programlisting>
99 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
101 struct _GtkWindowPrivate
103 GtkMnemonicHash *mnemonic_hash;
105 GtkWidget *default_widget;
106 GtkWidget *focus_widget;
107 GtkWindow *transient_parent;
108 GtkWindowGeometryInfo *geometry_info;
109 GtkWindowGroup *group;
111 GdkModifierType mnemonic_modifier;
114 GdkWindowTypeHint gdk_type_hint;
116 GtkApplication *application;
120 GdkWindow *grip_window;
124 gchar *wmclass_class;
132 guint keys_changed_handler;
134 guint16 configure_request_count;
136 /* The following flags are initially TRUE (before a window is mapped).
137 * They cause us to compute a configure request that involves
138 * default-only parameters. Once mapped, we set them to FALSE.
139 * Then we set them to TRUE again on unmap (for position)
140 * and on unrealize (for size).
142 guint need_default_position : 1;
143 guint need_default_size : 1;
145 guint above_initially : 1;
146 guint accept_focus : 1;
147 guint below_initially : 1;
148 guint builder_visible : 1;
149 guint configure_notify_received : 1;
152 guint destroy_with_parent : 1;
153 guint focus_on_map : 1;
154 guint fullscreen_initially : 1;
155 guint gravity : 5; /* GdkGravity */
157 guint has_user_ref_count : 1;
159 guint has_toplevel_focus : 1;
160 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
162 guint maximize_initially : 1;
163 guint mnemonics_visible : 1;
164 guint mnemonics_visible_set : 1;
166 guint opacity_set : 1;
168 guint reset_type_hint : 1;
170 guint skips_pager : 1;
171 guint skips_taskbar : 1;
172 guint stick_initially : 1;
173 guint transient_parent_group : 1;
174 guint type : 4; /* GtkWindowType */
175 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
176 * one of the original eight. If not,
178 * GDK_WINDOW_TYPE_HINT_NORMAL
181 guint has_resize_grip : 1;
182 guint resize_grip_visible : 1; /* don't use, just for "resize-
183 * grip-visible" notification
211 PROP_DESTROY_WITH_PARENT,
216 PROP_SKIP_TASKBAR_HINT,
217 PROP_SKIP_PAGER_HINT,
226 PROP_HAS_RESIZE_GRIP,
227 PROP_RESIZE_GRIP_VISIBLE,
229 /* Readonly properties */
231 PROP_HAS_TOPLEVEL_FOCUS,
233 /* Writeonly properties */
236 PROP_MNEMONICS_VISIBLE,
246 guint using_default_icon : 1;
247 guint using_parent_icon : 1;
248 guint using_themed_icon : 1;
252 GdkGeometry geometry; /* Last set of geometry hints we set */
253 GdkWindowHints flags;
254 GdkRectangle configure_request;
255 } GtkWindowLastGeometryInfo;
257 struct _GtkWindowGeometryInfo
259 /* Properties that the app has set on the window
261 GdkGeometry geometry; /* Geometry hints */
263 GtkWidget *widget; /* subwidget to which hints apply */
264 /* from last gtk_window_resize () - if > 0, indicates that
265 * we should resize to this size.
270 /* From last gtk_window_move () prior to mapping -
271 * only used if initial_pos_set
276 /* Default size - used only the FIRST time we map a window,
281 /* whether to use initial_x, initial_y */
282 guint initial_pos_set : 1;
283 /* CENTER_ALWAYS or other position constraint changed since
284 * we sent the last configure request.
286 guint position_constraints_changed : 1;
288 /* if true, default_width, height should be multiplied by the
289 * increments and affect the geometry widget only
291 guint default_is_geometry : 1;
293 /* if true, resize_width, height should be multiplied by the
294 * increments and affect the geometry widget only
296 guint resize_is_geometry : 1;
298 GtkWindowLastGeometryInfo last;
302 struct _GtkDeviceGrabInfo
306 guint block_others : 1;
309 struct _GtkWindowGroupPrivate
312 GSList *device_grabs;
315 static void gtk_window_dispose (GObject *object);
316 static void gtk_window_finalize (GObject *object);
317 static void gtk_window_destroy (GtkWidget *widget);
318 static void gtk_window_show (GtkWidget *widget);
319 static void gtk_window_hide (GtkWidget *widget);
320 static void gtk_window_map (GtkWidget *widget);
321 static void gtk_window_unmap (GtkWidget *widget);
322 static void gtk_window_realize (GtkWidget *widget);
323 static void gtk_window_unrealize (GtkWidget *widget);
324 static void gtk_window_size_allocate (GtkWidget *widget,
325 GtkAllocation *allocation);
326 static gint gtk_window_event (GtkWidget *widget,
328 static gboolean gtk_window_map_event (GtkWidget *widget,
330 static gboolean gtk_window_frame_event (GtkWindow *window,
332 static gint gtk_window_configure_event (GtkWidget *widget,
333 GdkEventConfigure *event);
334 static gint gtk_window_key_press_event (GtkWidget *widget,
336 static gint gtk_window_key_release_event (GtkWidget *widget,
338 static gint gtk_window_button_press_event (GtkWidget *widget,
339 GdkEventButton *event);
340 static gint gtk_window_enter_notify_event (GtkWidget *widget,
341 GdkEventCrossing *event);
342 static gint gtk_window_leave_notify_event (GtkWidget *widget,
343 GdkEventCrossing *event);
344 static gint gtk_window_focus_in_event (GtkWidget *widget,
345 GdkEventFocus *event);
346 static gint gtk_window_focus_out_event (GtkWidget *widget,
347 GdkEventFocus *event);
348 static void gtk_window_style_updated (GtkWidget *widget);
349 static gint gtk_window_client_event (GtkWidget *widget,
350 GdkEventClient *event);
351 static gboolean gtk_window_state_event (GtkWidget *widget,
352 GdkEventWindowState *event);
353 static void gtk_window_check_resize (GtkContainer *container);
354 static gint gtk_window_focus (GtkWidget *widget,
355 GtkDirectionType direction);
356 static void gtk_window_move_focus (GtkWidget *widget,
357 GtkDirectionType dir);
358 static void gtk_window_real_set_focus (GtkWindow *window,
360 static void gtk_window_direction_changed (GtkWidget *widget,
361 GtkTextDirection prev_dir);
362 static void gtk_window_state_changed (GtkWidget *widget,
363 GtkStateType previous_state);
365 static void gtk_window_real_activate_default (GtkWindow *window);
366 static void gtk_window_real_activate_focus (GtkWindow *window);
367 static void gtk_window_keys_changed (GtkWindow *window);
368 static gint gtk_window_draw (GtkWidget *widget,
370 static void gtk_window_unset_transient_for (GtkWindow *window);
371 static void gtk_window_transient_parent_realized (GtkWidget *parent,
373 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
376 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
378 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
381 static void gtk_window_move_resize (GtkWindow *window);
382 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
384 GdkGeometry *geometry_b,
386 static void gtk_window_constrain_size (GtkWindow *window,
387 GdkGeometry *geometry,
393 static void gtk_window_constrain_position (GtkWindow *window,
398 static void gtk_window_compute_hints (GtkWindow *window,
399 GdkGeometry *new_geometry,
401 static void gtk_window_compute_configure_request (GtkWindow *window,
402 GdkRectangle *request,
403 GdkGeometry *geometry,
406 static void gtk_window_set_default_size_internal (GtkWindow *window,
407 gboolean change_width,
409 gboolean change_height,
411 gboolean is_geometry);
413 static void update_themed_icon (GtkIconTheme *theme,
415 static GList *icon_list_from_theme (GtkWidget *widget,
417 static void gtk_window_realize_icon (GtkWindow *window);
418 static void gtk_window_unrealize_icon (GtkWindow *window);
419 static void resize_grip_create_window (GtkWindow *window);
420 static void resize_grip_destroy_window (GtkWindow *window);
421 static void update_grip_visibility (GtkWindow *window);
423 static void gtk_window_notify_keys_changed (GtkWindow *window);
424 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
425 static void gtk_window_free_key_hash (GtkWindow *window);
426 static void gtk_window_on_composited_changed (GdkScreen *screen,
429 static GSList *toplevel_list = NULL;
430 static guint window_signals[LAST_SIGNAL] = { 0 };
431 static GList *default_icon_list = NULL;
432 static gchar *default_icon_name = NULL;
433 static guint default_icon_serial = 0;
434 static gboolean disable_startup_notification = FALSE;
435 static gboolean sent_startup_notification = FALSE;
437 static GQuark quark_gtk_embedded = 0;
438 static GQuark quark_gtk_window_key_hash = 0;
439 static GQuark quark_gtk_window_icon_info = 0;
440 static GQuark quark_gtk_buildable_accels = 0;
442 static GtkBuildableIface *parent_buildable_iface;
444 static void gtk_window_set_property (GObject *object,
448 static void gtk_window_get_property (GObject *object,
454 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
455 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
458 const GValue *value);
459 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
460 GtkBuilder *builder);
461 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
464 const gchar *tagname,
465 GMarkupParser *parser,
467 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
470 const gchar *tagname,
474 static void gtk_window_get_preferred_width (GtkWidget *widget,
477 static void gtk_window_get_preferred_height (GtkWidget *widget,
481 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
482 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
483 gtk_window_buildable_interface_init))
486 add_tab_bindings (GtkBindingSet *binding_set,
487 GdkModifierType modifiers,
488 GtkDirectionType direction)
490 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
492 GTK_TYPE_DIRECTION_TYPE, direction);
493 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
495 GTK_TYPE_DIRECTION_TYPE, direction);
499 add_arrow_bindings (GtkBindingSet *binding_set,
501 GtkDirectionType direction)
503 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
505 gtk_binding_entry_add_signal (binding_set, keysym, 0,
507 GTK_TYPE_DIRECTION_TYPE, direction);
508 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
510 GTK_TYPE_DIRECTION_TYPE, direction);
511 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
513 GTK_TYPE_DIRECTION_TYPE, direction);
514 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
516 GTK_TYPE_DIRECTION_TYPE, direction);
520 extract_time_from_startup_id (const gchar* startup_id)
522 gchar *timestr = g_strrstr (startup_id, "_TIME");
523 guint32 retval = GDK_CURRENT_TIME;
530 /* Skip past the "_TIME" part */
535 timestamp = g_ascii_strtoull (timestr, &end, 0);
536 if (errno == 0 && end != timestr)
544 startup_id_is_fake (const gchar* startup_id)
546 return strncmp (startup_id, "_TIME", 5) == 0;
550 gtk_window_class_init (GtkWindowClass *klass)
552 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
553 GtkWidgetClass *widget_class;
554 GtkContainerClass *container_class;
555 GtkBindingSet *binding_set;
557 widget_class = (GtkWidgetClass*) klass;
558 container_class = (GtkContainerClass*) klass;
560 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
561 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
562 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
563 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
565 gobject_class->dispose = gtk_window_dispose;
566 gobject_class->finalize = gtk_window_finalize;
568 gobject_class->set_property = gtk_window_set_property;
569 gobject_class->get_property = gtk_window_get_property;
571 widget_class->destroy = gtk_window_destroy;
572 widget_class->show = gtk_window_show;
573 widget_class->hide = gtk_window_hide;
574 widget_class->map = gtk_window_map;
575 widget_class->map_event = gtk_window_map_event;
576 widget_class->unmap = gtk_window_unmap;
577 widget_class->realize = gtk_window_realize;
578 widget_class->unrealize = gtk_window_unrealize;
579 widget_class->size_allocate = gtk_window_size_allocate;
580 widget_class->configure_event = gtk_window_configure_event;
581 widget_class->key_press_event = gtk_window_key_press_event;
582 widget_class->key_release_event = gtk_window_key_release_event;
583 widget_class->enter_notify_event = gtk_window_enter_notify_event;
584 widget_class->leave_notify_event = gtk_window_leave_notify_event;
585 widget_class->focus_in_event = gtk_window_focus_in_event;
586 widget_class->button_press_event = gtk_window_button_press_event;
587 widget_class->focus_out_event = gtk_window_focus_out_event;
588 widget_class->client_event = gtk_window_client_event;
589 widget_class->focus = gtk_window_focus;
590 widget_class->move_focus = gtk_window_move_focus;
591 widget_class->draw = gtk_window_draw;
592 widget_class->get_preferred_width = gtk_window_get_preferred_width;
593 widget_class->get_preferred_height = gtk_window_get_preferred_height;
594 widget_class->window_state_event = gtk_window_state_event;
595 widget_class->direction_changed = gtk_window_direction_changed;
596 widget_class->state_changed = gtk_window_state_changed;
597 widget_class->style_updated = gtk_window_style_updated;
599 container_class->check_resize = gtk_window_check_resize;
601 klass->set_focus = gtk_window_real_set_focus;
602 klass->frame_event = gtk_window_frame_event;
604 klass->activate_default = gtk_window_real_activate_default;
605 klass->activate_focus = gtk_window_real_activate_focus;
606 klass->keys_changed = gtk_window_keys_changed;
608 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
611 g_object_class_install_property (gobject_class,
613 g_param_spec_enum ("type",
615 P_("The type of the window"),
616 GTK_TYPE_WINDOW_TYPE,
618 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
620 g_object_class_install_property (gobject_class,
622 g_param_spec_string ("title",
624 P_("The title of the window"),
626 GTK_PARAM_READWRITE));
628 g_object_class_install_property (gobject_class,
630 g_param_spec_string ("role",
632 P_("Unique identifier for the window to be used when restoring a session"),
634 GTK_PARAM_READWRITE));
637 * GtkWindow:startup-id:
639 * The :startup-id is a write-only property for setting window's
640 * startup notification identifier. See gtk_window_set_startup_id()
645 g_object_class_install_property (gobject_class,
647 g_param_spec_string ("startup-id",
649 P_("Unique startup identifier for the window used by startup-notification"),
651 GTK_PARAM_WRITABLE));
653 g_object_class_install_property (gobject_class,
655 g_param_spec_boolean ("resizable",
657 P_("If TRUE, users can resize the window"),
659 GTK_PARAM_READWRITE));
661 g_object_class_install_property (gobject_class,
663 g_param_spec_boolean ("modal",
665 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
667 GTK_PARAM_READWRITE));
669 g_object_class_install_property (gobject_class,
671 g_param_spec_enum ("window-position",
672 P_("Window Position"),
673 P_("The initial position of the window"),
674 GTK_TYPE_WINDOW_POSITION,
676 GTK_PARAM_READWRITE));
678 g_object_class_install_property (gobject_class,
680 g_param_spec_int ("default-width",
682 P_("The default width of the window, used when initially showing the window"),
686 GTK_PARAM_READWRITE));
688 g_object_class_install_property (gobject_class,
690 g_param_spec_int ("default-height",
691 P_("Default Height"),
692 P_("The default height of the window, used when initially showing the window"),
696 GTK_PARAM_READWRITE));
698 g_object_class_install_property (gobject_class,
699 PROP_DESTROY_WITH_PARENT,
700 g_param_spec_boolean ("destroy-with-parent",
701 P_("Destroy with Parent"),
702 P_("If this window should be destroyed when the parent is destroyed"),
704 GTK_PARAM_READWRITE));
706 g_object_class_install_property (gobject_class,
708 g_param_spec_object ("icon",
710 P_("Icon for this window"),
712 GTK_PARAM_READWRITE));
713 g_object_class_install_property (gobject_class,
714 PROP_MNEMONICS_VISIBLE,
715 g_param_spec_boolean ("mnemonics-visible",
716 P_("Mnemonics Visible"),
717 P_("Whether mnemonics are currently visible in this window"),
719 GTK_PARAM_READWRITE));
722 * GtkWindow:icon-name:
724 * The :icon-name property specifies the name of the themed icon to
725 * use as the window icon. See #GtkIconTheme for more details.
729 g_object_class_install_property (gobject_class,
731 g_param_spec_string ("icon-name",
733 P_("Name of the themed icon for this window"),
735 GTK_PARAM_READWRITE));
737 g_object_class_install_property (gobject_class,
739 g_param_spec_object ("screen",
741 P_("The screen where this window will be displayed"),
743 GTK_PARAM_READWRITE));
745 g_object_class_install_property (gobject_class,
747 g_param_spec_boolean ("is-active",
749 P_("Whether the toplevel is the current active window"),
751 GTK_PARAM_READABLE));
753 g_object_class_install_property (gobject_class,
754 PROP_HAS_TOPLEVEL_FOCUS,
755 g_param_spec_boolean ("has-toplevel-focus",
756 P_("Focus in Toplevel"),
757 P_("Whether the input focus is within this GtkWindow"),
759 GTK_PARAM_READABLE));
761 g_object_class_install_property (gobject_class,
763 g_param_spec_enum ("type-hint",
765 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
766 GDK_TYPE_WINDOW_TYPE_HINT,
767 GDK_WINDOW_TYPE_HINT_NORMAL,
768 GTK_PARAM_READWRITE));
770 g_object_class_install_property (gobject_class,
771 PROP_SKIP_TASKBAR_HINT,
772 g_param_spec_boolean ("skip-taskbar-hint",
774 P_("TRUE if the window should not be in the task bar."),
776 GTK_PARAM_READWRITE));
778 g_object_class_install_property (gobject_class,
779 PROP_SKIP_PAGER_HINT,
780 g_param_spec_boolean ("skip-pager-hint",
782 P_("TRUE if the window should not be in the pager."),
784 GTK_PARAM_READWRITE));
786 g_object_class_install_property (gobject_class,
788 g_param_spec_boolean ("urgency-hint",
790 P_("TRUE if the window should be brought to the user's attention."),
792 GTK_PARAM_READWRITE));
795 * GtkWindow:accept-focus:
797 * Whether the window should receive the input focus.
801 g_object_class_install_property (gobject_class,
803 g_param_spec_boolean ("accept-focus",
805 P_("TRUE if the window should receive the input focus."),
807 GTK_PARAM_READWRITE));
810 * GtkWindow:focus-on-map:
812 * Whether the window should receive the input focus when mapped.
816 g_object_class_install_property (gobject_class,
818 g_param_spec_boolean ("focus-on-map",
820 P_("TRUE if the window should receive the input focus when mapped."),
822 GTK_PARAM_READWRITE));
825 * GtkWindow:decorated:
827 * Whether the window should be decorated by the window manager.
831 g_object_class_install_property (gobject_class,
833 g_param_spec_boolean ("decorated",
835 P_("Whether the window should be decorated by the window manager"),
837 GTK_PARAM_READWRITE));
840 * GtkWindow:deletable:
842 * Whether the window frame should have a close button.
846 g_object_class_install_property (gobject_class,
848 g_param_spec_boolean ("deletable",
850 P_("Whether the window frame should have a close button"),
852 GTK_PARAM_READWRITE));
855 * GtkWindow:has-resize-grip
857 * Whether the window has a corner resize grip.
859 * Note that the resize grip is only shown if the window is
860 * actually resizable and not maximized. Use
861 * #GtkWindow:resize-grip-visible to find out if the resize
862 * grip is currently shown.
866 g_object_class_install_property (gobject_class,
867 PROP_HAS_RESIZE_GRIP,
868 g_param_spec_boolean ("has-resize-grip",
870 P_("Specifies whether the window should have a resize grip"),
872 GTK_PARAM_READWRITE));
875 * GtkWindow: resize-grip-visible:
877 * Whether a corner resize grip is currently shown.
881 g_object_class_install_property (gobject_class,
882 PROP_RESIZE_GRIP_VISIBLE,
883 g_param_spec_boolean ("resize-grip-visible",
884 P_("Resize grip is visible"),
885 P_("Specifies whether the window's resize grip is visible."),
887 GTK_PARAM_READABLE));
893 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
894 * more details about window gravity.
898 g_object_class_install_property (gobject_class,
900 g_param_spec_enum ("gravity",
902 P_("The window gravity of the window"),
904 GDK_GRAVITY_NORTH_WEST,
905 GTK_PARAM_READWRITE));
909 * GtkWindow:transient-for:
911 * The transient parent of the window. See gtk_window_set_transient_for() for
912 * more details about transient windows.
916 g_object_class_install_property (gobject_class,
918 g_param_spec_object ("transient-for",
919 P_("Transient for Window"),
920 P_("The transient parent of the dialog"),
922 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
927 * The requested opacity of the window. See gtk_window_set_opacity() for
928 * more details about window opacity.
932 g_object_class_install_property (gobject_class,
934 g_param_spec_double ("opacity",
935 P_("Opacity for Window"),
936 P_("The opacity of the window, from 0 to 1"),
940 GTK_PARAM_READWRITE));
944 gtk_widget_class_install_style_property (widget_class,
945 g_param_spec_int ("resize-grip-width",
946 P_("Width of resize grip"),
947 P_("Width of resize grip"),
948 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
950 gtk_widget_class_install_style_property (widget_class,
951 g_param_spec_int ("resize-grip-height",
952 P_("Height of resize grip"),
953 P_("Height of resize grip"),
954 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
960 * GtkWindow:application:
962 * The #GtkApplication associated with the window.
964 * The application will be kept alive for at least as long as the
969 g_object_class_install_property (gobject_class,
971 g_param_spec_object ("application",
972 P_("GtkApplication"),
973 P_("The GtkApplication for the window"),
974 GTK_TYPE_APPLICATION,
975 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
977 window_signals[SET_FOCUS] =
978 g_signal_new (I_("set-focus"),
979 G_TYPE_FROM_CLASS (gobject_class),
981 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
983 _gtk_marshal_VOID__OBJECT,
987 window_signals[FRAME_EVENT] =
988 g_signal_new (I_("frame-event"),
989 G_TYPE_FROM_CLASS (gobject_class),
991 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
992 _gtk_boolean_handled_accumulator, NULL,
993 _gtk_marshal_BOOLEAN__BOXED,
998 * GtkWindow::activate-focus:
999 * @window: the window which received the signal
1001 * The ::activate-focus signal is a
1002 * <link linkend="keybinding-signals">keybinding signal</link>
1003 * which gets emitted when the user activates the currently
1004 * focused widget of @window.
1006 window_signals[ACTIVATE_FOCUS] =
1007 g_signal_new (I_("activate-focus"),
1008 G_TYPE_FROM_CLASS (gobject_class),
1009 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1010 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1012 _gtk_marshal_VOID__VOID,
1017 * GtkWindow::activate-default:
1018 * @window: the window which received the signal
1020 * The ::activate-default signal is a
1021 * <link linkend="keybinding-signals">keybinding signal</link>
1022 * which gets emitted when the user activates the default widget
1025 window_signals[ACTIVATE_DEFAULT] =
1026 g_signal_new (I_("activate-default"),
1027 G_TYPE_FROM_CLASS (gobject_class),
1028 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1029 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1031 _gtk_marshal_VOID__VOID,
1036 * GtkWindow::keys-changed:
1037 * @window: the window which received the signal
1039 * The ::keys-changed signal gets emitted when the set of accelerators
1040 * or mnemonics that are associated with @window changes.
1042 window_signals[KEYS_CHANGED] =
1043 g_signal_new (I_("keys-changed"),
1044 G_TYPE_FROM_CLASS (gobject_class),
1046 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1048 _gtk_marshal_VOID__VOID,
1056 binding_set = gtk_binding_set_by_class (klass);
1058 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1059 "activate-focus", 0);
1060 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1061 "activate-focus", 0);
1063 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1064 "activate-default", 0);
1065 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1066 "activate-default", 0);
1067 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1068 "activate-default", 0);
1070 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1071 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1072 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1073 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1075 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1076 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1077 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1078 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1082 gtk_window_init (GtkWindow *window)
1084 GtkWindowPrivate *priv;
1086 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1089 priv = window->priv;
1091 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1092 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1094 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1096 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1099 priv->wmclass_name = g_strdup (g_get_prgname ());
1100 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1101 priv->wm_role = NULL;
1102 priv->geometry_info = NULL;
1103 priv->type = GTK_WINDOW_TOPLEVEL;
1104 priv->focus_widget = NULL;
1105 priv->default_widget = NULL;
1106 priv->configure_request_count = 0;
1107 priv->resizable = TRUE;
1108 priv->configure_notify_received = FALSE;
1109 priv->position = GTK_WIN_POS_NONE;
1110 priv->need_default_size = TRUE;
1111 priv->need_default_position = TRUE;
1112 priv->modal = FALSE;
1114 priv->has_frame = FALSE;
1115 priv->frame_left = 0;
1116 priv->frame_right = 0;
1117 priv->frame_top = 0;
1118 priv->frame_bottom = 0;
1119 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1120 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1121 priv->decorated = TRUE;
1122 priv->mnemonic_modifier = GDK_MOD1_MASK;
1123 priv->screen = gdk_screen_get_default ();
1125 priv->accept_focus = TRUE;
1126 priv->focus_on_map = TRUE;
1127 priv->deletable = TRUE;
1128 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1129 priv->opacity = 1.0;
1130 priv->startup_id = NULL;
1131 priv->has_resize_grip = TRUE;
1132 priv->mnemonics_visible = TRUE;
1134 g_object_ref_sink (window);
1135 priv->has_user_ref_count = TRUE;
1136 toplevel_list = g_slist_prepend (toplevel_list, window);
1138 g_signal_connect (priv->screen, "composited-changed",
1139 G_CALLBACK (gtk_window_on_composited_changed), window);
1143 gtk_window_set_property (GObject *object,
1145 const GValue *value,
1148 GtkWindow *window = GTK_WINDOW (object);
1149 GtkWindowPrivate *priv = window->priv;
1154 priv->type = g_value_get_enum (value);
1157 gtk_window_set_title (window, g_value_get_string (value));
1160 gtk_window_set_role (window, g_value_get_string (value));
1162 case PROP_STARTUP_ID:
1163 gtk_window_set_startup_id (window, g_value_get_string (value));
1165 case PROP_RESIZABLE:
1166 gtk_window_set_resizable (window, g_value_get_boolean (value));
1169 gtk_window_set_modal (window, g_value_get_boolean (value));
1172 gtk_window_set_position (window, g_value_get_enum (value));
1174 case PROP_DEFAULT_WIDTH:
1175 gtk_window_set_default_size_internal (window,
1176 TRUE, g_value_get_int (value),
1179 case PROP_DEFAULT_HEIGHT:
1180 gtk_window_set_default_size_internal (window,
1182 TRUE, g_value_get_int (value), FALSE);
1184 case PROP_DESTROY_WITH_PARENT:
1185 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1188 gtk_window_set_icon (window,
1189 g_value_get_object (value));
1191 case PROP_ICON_NAME:
1192 gtk_window_set_icon_name (window, g_value_get_string (value));
1195 gtk_window_set_screen (window, g_value_get_object (value));
1197 case PROP_TYPE_HINT:
1198 gtk_window_set_type_hint (window,
1199 g_value_get_enum (value));
1201 case PROP_SKIP_TASKBAR_HINT:
1202 gtk_window_set_skip_taskbar_hint (window,
1203 g_value_get_boolean (value));
1205 case PROP_SKIP_PAGER_HINT:
1206 gtk_window_set_skip_pager_hint (window,
1207 g_value_get_boolean (value));
1209 case PROP_URGENCY_HINT:
1210 gtk_window_set_urgency_hint (window,
1211 g_value_get_boolean (value));
1213 case PROP_ACCEPT_FOCUS:
1214 gtk_window_set_accept_focus (window,
1215 g_value_get_boolean (value));
1217 case PROP_FOCUS_ON_MAP:
1218 gtk_window_set_focus_on_map (window,
1219 g_value_get_boolean (value));
1221 case PROP_DECORATED:
1222 gtk_window_set_decorated (window, g_value_get_boolean (value));
1224 case PROP_DELETABLE:
1225 gtk_window_set_deletable (window, g_value_get_boolean (value));
1228 gtk_window_set_gravity (window, g_value_get_enum (value));
1230 case PROP_TRANSIENT_FOR:
1231 gtk_window_set_transient_for (window, g_value_get_object (value));
1234 gtk_window_set_opacity (window, g_value_get_double (value));
1236 case PROP_HAS_RESIZE_GRIP:
1237 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1239 case PROP_APPLICATION:
1240 gtk_window_set_application (window, g_value_get_object (value));
1242 case PROP_MNEMONICS_VISIBLE:
1243 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1246 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1252 gtk_window_get_property (GObject *object,
1257 GtkWindow *window = GTK_WINDOW (object);
1258 GtkWindowPrivate *priv = window->priv;
1262 GtkWindowGeometryInfo *info;
1264 g_value_set_enum (value, priv->type);
1267 g_value_set_string (value, priv->wm_role);
1270 g_value_set_string (value, priv->title);
1272 case PROP_RESIZABLE:
1273 g_value_set_boolean (value, priv->resizable);
1276 g_value_set_boolean (value, priv->modal);
1279 g_value_set_enum (value, priv->position);
1281 case PROP_DEFAULT_WIDTH:
1282 info = gtk_window_get_geometry_info (window, FALSE);
1284 g_value_set_int (value, -1);
1286 g_value_set_int (value, info->default_width);
1288 case PROP_DEFAULT_HEIGHT:
1289 info = gtk_window_get_geometry_info (window, FALSE);
1291 g_value_set_int (value, -1);
1293 g_value_set_int (value, info->default_height);
1295 case PROP_DESTROY_WITH_PARENT:
1296 g_value_set_boolean (value, priv->destroy_with_parent);
1299 g_value_set_object (value, gtk_window_get_icon (window));
1301 case PROP_ICON_NAME:
1302 g_value_set_string (value, gtk_window_get_icon_name (window));
1305 g_value_set_object (value, priv->screen);
1307 case PROP_IS_ACTIVE:
1308 g_value_set_boolean (value, priv->is_active);
1310 case PROP_HAS_TOPLEVEL_FOCUS:
1311 g_value_set_boolean (value, priv->has_toplevel_focus);
1313 case PROP_TYPE_HINT:
1314 g_value_set_enum (value, priv->type_hint);
1316 case PROP_SKIP_TASKBAR_HINT:
1317 g_value_set_boolean (value,
1318 gtk_window_get_skip_taskbar_hint (window));
1320 case PROP_SKIP_PAGER_HINT:
1321 g_value_set_boolean (value,
1322 gtk_window_get_skip_pager_hint (window));
1324 case PROP_URGENCY_HINT:
1325 g_value_set_boolean (value,
1326 gtk_window_get_urgency_hint (window));
1328 case PROP_ACCEPT_FOCUS:
1329 g_value_set_boolean (value,
1330 gtk_window_get_accept_focus (window));
1332 case PROP_FOCUS_ON_MAP:
1333 g_value_set_boolean (value,
1334 gtk_window_get_focus_on_map (window));
1336 case PROP_DECORATED:
1337 g_value_set_boolean (value, gtk_window_get_decorated (window));
1339 case PROP_DELETABLE:
1340 g_value_set_boolean (value, gtk_window_get_deletable (window));
1343 g_value_set_enum (value, gtk_window_get_gravity (window));
1345 case PROP_TRANSIENT_FOR:
1346 g_value_set_object (value, gtk_window_get_transient_for (window));
1349 g_value_set_double (value, gtk_window_get_opacity (window));
1351 case PROP_HAS_RESIZE_GRIP:
1352 g_value_set_boolean (value, priv->has_resize_grip);
1354 case PROP_RESIZE_GRIP_VISIBLE:
1355 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1357 case PROP_APPLICATION:
1358 g_value_set_object (value, gtk_window_get_application (window));
1360 case PROP_MNEMONICS_VISIBLE:
1361 g_value_set_boolean (value, priv->mnemonics_visible);
1364 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1370 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1372 parent_buildable_iface = g_type_interface_peek_parent (iface);
1373 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1374 iface->parser_finished = gtk_window_buildable_parser_finished;
1375 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1376 iface->custom_finished = gtk_window_buildable_custom_finished;
1380 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1381 GtkBuilder *builder,
1383 const GValue *value)
1385 GtkWindow *window = GTK_WINDOW (buildable);
1386 GtkWindowPrivate *priv = window->priv;
1388 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1389 priv->builder_visible = TRUE;
1391 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1395 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1396 GtkBuilder *builder)
1398 GtkWindow *window = GTK_WINDOW (buildable);
1399 GtkWindowPrivate *priv = window->priv;
1403 if (priv->builder_visible)
1404 gtk_widget_show (GTK_WIDGET (buildable));
1406 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1407 for (l = accels; l; l = l->next)
1409 object = gtk_builder_get_object (builder, l->data);
1412 g_warning ("Unknown accel group %s specified in window %s",
1413 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1416 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1417 GTK_ACCEL_GROUP (object));
1421 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1423 parent_buildable_iface->parser_finished (buildable, builder);
1429 } GSListSubParserData;
1432 window_start_element (GMarkupParseContext *context,
1433 const gchar *element_name,
1434 const gchar **names,
1435 const gchar **values,
1440 GSListSubParserData *data = (GSListSubParserData*)user_data;
1442 if (strcmp (element_name, "group") == 0)
1444 for (i = 0; names[i]; i++)
1446 if (strcmp (names[i], "name") == 0)
1447 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1450 else if (strcmp (element_name, "accel-groups") == 0)
1453 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1458 static const GMarkupParser window_parser =
1460 window_start_element
1464 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1465 GtkBuilder *builder,
1467 const gchar *tagname,
1468 GMarkupParser *parser,
1471 GSListSubParserData *parser_data;
1473 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1474 tagname, parser, data))
1477 if (strcmp (tagname, "accel-groups") == 0)
1479 parser_data = g_slice_new0 (GSListSubParserData);
1480 parser_data->items = NULL;
1481 parser_data->object = G_OBJECT (buildable);
1483 *parser = window_parser;
1484 *data = parser_data;
1492 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1493 GtkBuilder *builder,
1495 const gchar *tagname,
1498 GSListSubParserData *data;
1500 parent_buildable_iface->custom_finished (buildable, builder, child,
1501 tagname, user_data);
1503 if (strcmp (tagname, "accel-groups") != 0)
1506 data = (GSListSubParserData*)user_data;
1508 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1509 data->items, (GDestroyNotify) g_slist_free);
1511 g_slice_free (GSListSubParserData, data);
1516 * @type: type of window
1518 * Creates a new #GtkWindow, which is a toplevel window that can
1519 * contain other widgets. Nearly always, the type of the window should
1520 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1521 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1522 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1523 * dialogs, though in some other toolkits dialogs are called "popups".
1524 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1525 * On X11, popup windows are not controlled by the <link
1526 * linkend="gtk-X11-arch">window manager</link>.
1528 * If you simply want an undecorated window (no window borders), use
1529 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1531 * Return value: a new #GtkWindow.
1534 gtk_window_new (GtkWindowType type)
1536 GtkWindowPrivate *priv;
1539 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1541 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1542 priv = window->priv;
1546 return GTK_WIDGET (window);
1550 * gtk_window_set_title:
1551 * @window: a #GtkWindow
1552 * @title: title of the window
1554 * Sets the title of the #GtkWindow. The title of a window will be
1555 * displayed in its title bar; on the X Window System, the title bar
1556 * is rendered by the <link linkend="gtk-X11-arch">window
1557 * manager</link>, so exactly how the title appears to users may vary
1558 * according to a user's exact configuration. The title should help a
1559 * user distinguish this window from other windows they may have
1560 * open. A good title might include the application name and current
1561 * document filename, for example.
1565 gtk_window_set_title (GtkWindow *window,
1568 GtkWindowPrivate *priv;
1572 g_return_if_fail (GTK_IS_WINDOW (window));
1574 priv = window->priv;
1575 widget = GTK_WIDGET (window);
1577 new_title = g_strdup (title);
1578 g_free (priv->title);
1579 priv->title = new_title;
1581 if (gtk_widget_get_realized (widget))
1583 gdk_window_set_title (gtk_widget_get_window (widget),
1587 g_object_notify (G_OBJECT (window), "title");
1591 * gtk_window_get_title:
1592 * @window: a #GtkWindow
1594 * Retrieves the title of the window. See gtk_window_set_title().
1596 * Return value: the title of the window, or %NULL if none has
1597 * been set explicitely. The returned string is owned by the widget
1598 * and must not be modified or freed.
1600 G_CONST_RETURN gchar *
1601 gtk_window_get_title (GtkWindow *window)
1603 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1605 return window->priv->title;
1609 * gtk_window_set_wmclass:
1610 * @window: a #GtkWindow
1611 * @wmclass_name: window name hint
1612 * @wmclass_class: window class hint
1614 * Don't use this function. It sets the X Window System "class" and
1615 * "name" hints for a window. According to the ICCCM, you should
1616 * always set these to the same value for all windows in an
1617 * application, and GTK+ sets them to that value by default, so calling
1618 * this function is sort of pointless. However, you may want to call
1619 * gtk_window_set_role() on each window in your application, for the
1620 * benefit of the session manager. Setting the role allows the window
1621 * manager to restore window positions when loading a saved session.
1625 gtk_window_set_wmclass (GtkWindow *window,
1626 const gchar *wmclass_name,
1627 const gchar *wmclass_class)
1629 GtkWindowPrivate *priv;
1631 g_return_if_fail (GTK_IS_WINDOW (window));
1633 priv = window->priv;
1635 g_free (priv->wmclass_name);
1636 priv->wmclass_name = g_strdup (wmclass_name);
1638 g_free (priv->wmclass_class);
1639 priv->wmclass_class = g_strdup (wmclass_class);
1641 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1642 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1646 * gtk_window_set_role:
1647 * @window: a #GtkWindow
1648 * @role: unique identifier for the window to be used when restoring a session
1650 * This function is only useful on X11, not with other GTK+ targets.
1652 * In combination with the window title, the window role allows a
1653 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1654 * same" window when an application is restarted. So for example you
1655 * might set the "toolbox" role on your app's toolbox window, so that
1656 * when the user restarts their session, the window manager can put
1657 * the toolbox back in the same place.
1659 * If a window already has a unique title, you don't need to set the
1660 * role, since the WM can use the title to identify the window when
1661 * restoring the session.
1665 gtk_window_set_role (GtkWindow *window,
1668 GtkWindowPrivate *priv;
1671 g_return_if_fail (GTK_IS_WINDOW (window));
1673 priv = window->priv;
1675 new_role = g_strdup (role);
1676 g_free (priv->wm_role);
1677 priv->wm_role = new_role;
1679 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1680 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1683 g_object_notify (G_OBJECT (window), "role");
1687 * gtk_window_set_startup_id:
1688 * @window: a #GtkWindow
1689 * @startup_id: a string with startup-notification identifier
1691 * Startup notification identifiers are used by desktop environment to
1692 * track application startup, to provide user feedback and other
1693 * features. This function changes the corresponding property on the
1694 * underlying GdkWindow. Normally, startup identifier is managed
1695 * automatically and you should only use this function in special cases
1696 * like transferring focus from other processes. You should use this
1697 * function before calling gtk_window_present() or any equivalent
1698 * function generating a window map event.
1700 * This function is only useful on X11, not with other GTK+ targets.
1705 gtk_window_set_startup_id (GtkWindow *window,
1706 const gchar *startup_id)
1708 GtkWindowPrivate *priv;
1711 g_return_if_fail (GTK_IS_WINDOW (window));
1713 priv = window->priv;
1714 widget = GTK_WIDGET (window);
1716 g_free (priv->startup_id);
1717 priv->startup_id = g_strdup (startup_id);
1719 if (gtk_widget_get_realized (widget))
1721 GdkWindow *gdk_window;
1722 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1724 gdk_window = gtk_widget_get_window (widget);
1726 #ifdef GDK_WINDOWING_X11
1727 if (timestamp != GDK_CURRENT_TIME)
1728 gdk_x11_window_set_user_time (gdk_window, timestamp);
1731 /* Here we differentiate real and "fake" startup notification IDs,
1732 * constructed on purpose just to pass interaction timestamp
1734 if (startup_id_is_fake (priv->startup_id))
1735 gtk_window_present_with_time (window, timestamp);
1738 gdk_window_set_startup_id (gdk_window,
1741 /* If window is mapped, terminate the startup-notification too */
1742 if (gtk_widget_get_mapped (widget) &&
1743 !disable_startup_notification)
1744 gdk_notify_startup_complete_with_id (priv->startup_id);
1748 g_object_notify (G_OBJECT (window), "startup-id");
1752 * gtk_window_get_role:
1753 * @window: a #GtkWindow
1755 * Returns the role of the window. See gtk_window_set_role() for
1756 * further explanation.
1758 * Return value: the role of the window if set, or %NULL. The
1759 * returned is owned by the widget and must not be modified
1762 G_CONST_RETURN gchar *
1763 gtk_window_get_role (GtkWindow *window)
1765 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1767 return window->priv->wm_role;
1771 * gtk_window_set_focus:
1772 * @window: a #GtkWindow
1773 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1774 * any focus widget for the toplevel window.
1776 * If @focus is not the current focus widget, and is focusable, sets
1777 * it as the focus widget for the window. If @focus is %NULL, unsets
1778 * the focus widget for this window. To set the focus to a particular
1779 * widget in the toplevel, it is usually more convenient to use
1780 * gtk_widget_grab_focus() instead of this function.
1783 gtk_window_set_focus (GtkWindow *window,
1786 GtkWindowPrivate *priv;
1789 g_return_if_fail (GTK_IS_WINDOW (window));
1791 priv = window->priv;
1795 g_return_if_fail (GTK_IS_WIDGET (focus));
1796 g_return_if_fail (gtk_widget_get_can_focus (focus));
1800 gtk_widget_grab_focus (focus);
1803 /* Clear the existing focus chain, so that when we focus into
1804 * the window again, we start at the beginnning.
1806 GtkWidget *widget = priv->focus_widget;
1809 while ((parent = gtk_widget_get_parent (widget)))
1812 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1816 _gtk_window_internal_set_focus (window, NULL);
1821 _gtk_window_internal_set_focus (GtkWindow *window,
1824 GtkWindowPrivate *priv;
1826 g_return_if_fail (GTK_IS_WINDOW (window));
1828 priv = window->priv;
1830 if ((priv->focus_widget != focus) ||
1831 (focus && !gtk_widget_has_focus (focus)))
1832 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1836 * gtk_window_set_default:
1837 * @window: a #GtkWindow
1838 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1839 * default widget for the toplevel.
1841 * The default widget is the widget that's activated when the user
1842 * presses Enter in a dialog (for example). This function sets or
1843 * unsets the default widget for a #GtkWindow about. When setting
1844 * (rather than unsetting) the default widget it's generally easier to
1845 * call gtk_widget_grab_focus() on the widget. Before making a widget
1846 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1847 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1850 gtk_window_set_default (GtkWindow *window,
1851 GtkWidget *default_widget)
1853 GtkWindowPrivate *priv;
1855 g_return_if_fail (GTK_IS_WINDOW (window));
1857 priv = window->priv;
1860 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1862 if (priv->default_widget != default_widget)
1864 GtkWidget *old_default_widget = NULL;
1867 g_object_ref (default_widget);
1869 if (priv->default_widget)
1871 old_default_widget = priv->default_widget;
1873 if (priv->focus_widget != priv->default_widget ||
1874 !gtk_widget_get_receives_default (priv->default_widget))
1875 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1877 gtk_widget_queue_draw (priv->default_widget);
1880 priv->default_widget = default_widget;
1882 if (priv->default_widget)
1884 if (priv->focus_widget == NULL ||
1885 !gtk_widget_get_receives_default (priv->focus_widget))
1886 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1888 gtk_widget_queue_draw (priv->default_widget);
1891 if (old_default_widget)
1892 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1896 g_object_notify (G_OBJECT (default_widget), "has-default");
1897 g_object_unref (default_widget);
1903 * gtk_window_get_default_widget:
1904 * @window: a #GtkWindow
1906 * Returns the default widget for @window. See gtk_window_set_default()
1909 * Returns: (transfer none): the default widget, or %NULL if there is none.
1914 gtk_window_get_default_widget (GtkWindow *window)
1916 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1918 return window->priv->default_widget;
1922 handle_keys_changed (gpointer data)
1924 GtkWindow *window = GTK_WINDOW (data);
1925 GtkWindowPrivate *priv = window->priv;
1927 if (priv->keys_changed_handler)
1929 g_source_remove (priv->keys_changed_handler);
1930 priv->keys_changed_handler = 0;
1933 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1939 gtk_window_notify_keys_changed (GtkWindow *window)
1941 GtkWindowPrivate *priv = window->priv;
1943 if (!priv->keys_changed_handler)
1944 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1948 * gtk_window_add_accel_group:
1949 * @window: window to attach accelerator group to
1950 * @accel_group: a #GtkAccelGroup
1952 * Associate @accel_group with @window, such that calling
1953 * gtk_accel_groups_activate() on @window will activate accelerators
1957 gtk_window_add_accel_group (GtkWindow *window,
1958 GtkAccelGroup *accel_group)
1960 g_return_if_fail (GTK_IS_WINDOW (window));
1961 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1963 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1964 g_signal_connect_object (accel_group, "accel-changed",
1965 G_CALLBACK (gtk_window_notify_keys_changed),
1966 window, G_CONNECT_SWAPPED);
1967 gtk_window_notify_keys_changed (window);
1971 * gtk_window_remove_accel_group:
1972 * @window: a #GtkWindow
1973 * @accel_group: a #GtkAccelGroup
1975 * Reverses the effects of gtk_window_add_accel_group().
1978 gtk_window_remove_accel_group (GtkWindow *window,
1979 GtkAccelGroup *accel_group)
1981 g_return_if_fail (GTK_IS_WINDOW (window));
1982 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1984 g_signal_handlers_disconnect_by_func (accel_group,
1985 gtk_window_notify_keys_changed,
1987 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1988 gtk_window_notify_keys_changed (window);
1991 static GtkMnemonicHash *
1992 gtk_window_get_mnemonic_hash (GtkWindow *window,
1995 GtkWindowPrivate *private = window->priv;
1997 if (!private->mnemonic_hash && create)
1998 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2000 return private->mnemonic_hash;
2004 * gtk_window_add_mnemonic:
2005 * @window: a #GtkWindow
2006 * @keyval: the mnemonic
2007 * @target: the widget that gets activated by the mnemonic
2009 * Adds a mnemonic to this window.
2012 gtk_window_add_mnemonic (GtkWindow *window,
2016 g_return_if_fail (GTK_IS_WINDOW (window));
2017 g_return_if_fail (GTK_IS_WIDGET (target));
2019 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2021 gtk_window_notify_keys_changed (window);
2025 * gtk_window_remove_mnemonic:
2026 * @window: a #GtkWindow
2027 * @keyval: the mnemonic
2028 * @target: the widget that gets activated by the mnemonic
2030 * Removes a mnemonic from this window.
2033 gtk_window_remove_mnemonic (GtkWindow *window,
2037 g_return_if_fail (GTK_IS_WINDOW (window));
2038 g_return_if_fail (GTK_IS_WIDGET (target));
2040 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2042 gtk_window_notify_keys_changed (window);
2046 * gtk_window_mnemonic_activate:
2047 * @window: a #GtkWindow
2048 * @keyval: the mnemonic
2049 * @modifier: the modifiers
2050 * @returns: %TRUE if the activation is done.
2052 * Activates the targets associated with the mnemonic.
2055 gtk_window_mnemonic_activate (GtkWindow *window,
2057 GdkModifierType modifier)
2059 GtkWindowPrivate *priv;
2061 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2063 priv = window->priv;
2065 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2067 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2069 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2076 * gtk_window_set_mnemonic_modifier:
2077 * @window: a #GtkWindow
2078 * @modifier: the modifier mask used to activate
2079 * mnemonics on this window.
2081 * Sets the mnemonic modifier for this window.
2084 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2085 GdkModifierType modifier)
2087 GtkWindowPrivate *priv;
2089 g_return_if_fail (GTK_IS_WINDOW (window));
2090 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2092 priv = window->priv;
2094 priv->mnemonic_modifier = modifier;
2095 gtk_window_notify_keys_changed (window);
2099 * gtk_window_get_mnemonic_modifier:
2100 * @window: a #GtkWindow
2102 * Returns the mnemonic modifier for this window. See
2103 * gtk_window_set_mnemonic_modifier().
2105 * Return value: the modifier mask used to activate
2106 * mnemonics on this window.
2109 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2111 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2113 return window->priv->mnemonic_modifier;
2117 * gtk_window_set_position:
2118 * @window: a #GtkWindow.
2119 * @position: a position constraint.
2121 * Sets a position constraint for this window. If the old or new
2122 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2123 * the window to be repositioned to satisfy the new constraint.
2126 gtk_window_set_position (GtkWindow *window,
2127 GtkWindowPosition position)
2129 GtkWindowPrivate *priv;
2131 g_return_if_fail (GTK_IS_WINDOW (window));
2133 priv = window->priv;
2135 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2136 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2138 GtkWindowGeometryInfo *info;
2140 info = gtk_window_get_geometry_info (window, TRUE);
2142 /* this flag causes us to re-request the CENTER_ALWAYS
2143 * constraint in gtk_window_move_resize(), see
2144 * comment in that function.
2146 info->position_constraints_changed = TRUE;
2148 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2151 priv->position = position;
2153 g_object_notify (G_OBJECT (window), "window-position");
2157 * gtk_window_activate_focus:
2158 * @window: a #GtkWindow
2160 * Activates the current focused widget within the window.
2162 * Return value: %TRUE if a widget got activated.
2165 gtk_window_activate_focus (GtkWindow *window)
2167 GtkWindowPrivate *priv;
2169 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2171 priv = window->priv;
2173 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2174 return gtk_widget_activate (priv->focus_widget);
2180 * gtk_window_get_focus:
2181 * @window: a #GtkWindow
2183 * Retrieves the current focused widget within the window.
2184 * Note that this is the widget that would have the focus
2185 * if the toplevel window focused; if the toplevel window
2186 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2187 * not be %TRUE for the widget.
2189 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2192 gtk_window_get_focus (GtkWindow *window)
2194 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2196 return window->priv->focus_widget;
2200 * gtk_window_activate_default:
2201 * @window: a #GtkWindow
2203 * Activates the default widget for the window, unless the current
2204 * focused widget has been configured to receive the default action
2205 * (see gtk_widget_set_receives_default()), in which case the
2206 * focused widget is activated.
2208 * Return value: %TRUE if a widget got activated.
2211 gtk_window_activate_default (GtkWindow *window)
2213 GtkWindowPrivate *priv;
2215 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2217 priv = window->priv;
2219 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2220 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2221 return gtk_widget_activate (priv->default_widget);
2222 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2223 return gtk_widget_activate (priv->focus_widget);
2229 * gtk_window_set_modal:
2230 * @window: a #GtkWindow
2231 * @modal: whether the window is modal
2233 * Sets a window modal or non-modal. Modal windows prevent interaction
2234 * with other windows in the same application. To keep modal dialogs
2235 * on top of main application windows, use
2236 * gtk_window_set_transient_for() to make the dialog transient for the
2237 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2238 * will then disallow lowering the dialog below the parent.
2243 gtk_window_set_modal (GtkWindow *window,
2246 GtkWindowPrivate *priv;
2249 g_return_if_fail (GTK_IS_WINDOW (window));
2251 priv = window->priv;
2253 modal = modal != FALSE;
2254 if (priv->modal == modal)
2257 priv->modal = modal;
2258 widget = GTK_WIDGET (window);
2260 /* adjust desired modality state */
2261 if (gtk_widget_get_realized (widget))
2264 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2266 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2269 if (gtk_widget_get_visible (widget))
2272 gtk_grab_add (widget);
2274 gtk_grab_remove (widget);
2277 g_object_notify (G_OBJECT (window), "modal");
2281 * gtk_window_get_modal:
2282 * @window: a #GtkWindow
2284 * Returns whether the window is modal. See gtk_window_set_modal().
2286 * Return value: %TRUE if the window is set to be modal and
2287 * establishes a grab when shown
2290 gtk_window_get_modal (GtkWindow *window)
2292 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2294 return window->priv->modal;
2298 * gtk_window_list_toplevels:
2300 * Returns a list of all existing toplevel windows. The widgets
2301 * in the list are not individually referenced. If you want
2302 * to iterate through the list and perform actions involving
2303 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2304 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2305 * then unref all the widgets afterwards.
2307 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2310 gtk_window_list_toplevels (void)
2315 for (slist = toplevel_list; slist; slist = slist->next)
2316 list = g_list_prepend (list, slist->data);
2322 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2324 GList *embedded_windows;
2326 g_return_if_fail (GTK_IS_WINDOW (window));
2328 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2329 if (embedded_windows)
2330 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2331 embedded_windows = g_list_prepend (embedded_windows,
2332 GUINT_TO_POINTER (xid));
2334 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2337 (GDestroyNotify) g_list_free : NULL);
2341 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2343 GList *embedded_windows;
2346 g_return_if_fail (GTK_IS_WINDOW (window));
2348 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2349 if (embedded_windows)
2350 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2352 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2355 embedded_windows = g_list_remove_link (embedded_windows, node);
2356 g_list_free_1 (node);
2359 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2362 (GDestroyNotify) g_list_free : NULL);
2366 gtk_window_dispose (GObject *object)
2368 GtkWindow *window = GTK_WINDOW (object);
2370 gtk_window_set_focus (window, NULL);
2371 gtk_window_set_default (window, NULL);
2373 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2377 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2379 gtk_widget_destroy (GTK_WIDGET (child));
2383 connect_parent_destroyed (GtkWindow *window)
2385 GtkWindowPrivate *priv = window->priv;
2387 if (priv->transient_parent)
2389 g_signal_connect (priv->transient_parent,
2391 G_CALLBACK (parent_destroyed_callback),
2397 disconnect_parent_destroyed (GtkWindow *window)
2399 GtkWindowPrivate *priv = window->priv;
2401 if (priv->transient_parent)
2403 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2404 parent_destroyed_callback,
2410 gtk_window_transient_parent_realized (GtkWidget *parent,
2413 if (gtk_widget_get_realized (window))
2414 gdk_window_set_transient_for (gtk_widget_get_window (window),
2415 gtk_widget_get_window (parent));
2419 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2422 if (gtk_widget_get_realized (window))
2423 gdk_property_delete (gtk_widget_get_window (window),
2424 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2428 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2432 gtk_window_set_screen (window, parent->priv->screen);
2436 gtk_window_unset_transient_for (GtkWindow *window)
2438 GtkWindowPrivate *priv = window->priv;
2440 if (priv->transient_parent)
2442 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2443 gtk_window_transient_parent_realized,
2445 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2446 gtk_window_transient_parent_unrealized,
2448 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2449 gtk_window_transient_parent_screen_changed,
2451 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2452 gtk_widget_destroyed,
2453 &priv->transient_parent);
2455 if (priv->destroy_with_parent)
2456 disconnect_parent_destroyed (window);
2458 priv->transient_parent = NULL;
2460 if (priv->transient_parent_group)
2462 priv->transient_parent_group = FALSE;
2463 gtk_window_group_remove_window (priv->group,
2470 * gtk_window_set_transient_for:
2471 * @window: a #GtkWindow
2472 * @parent: (allow-none): parent window, or %NULL
2474 * Dialog windows should be set transient for the main application
2475 * window they were spawned from. This allows <link
2476 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2477 * dialog on top of the main window, or center the dialog over the
2478 * main window. gtk_dialog_new_with_buttons() and other convenience
2479 * functions in GTK+ will sometimes call
2480 * gtk_window_set_transient_for() on your behalf.
2482 * Passing %NULL for @parent unsets the current transient window.
2484 * On Windows, this function puts the child window on top of the parent,
2485 * much as the window manager would have done on X.
2488 gtk_window_set_transient_for (GtkWindow *window,
2491 GtkWindowPrivate *priv;
2493 g_return_if_fail (GTK_IS_WINDOW (window));
2494 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2495 g_return_if_fail (window != parent);
2497 priv = window->priv;
2499 if (priv->transient_parent)
2501 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2502 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2503 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2504 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2505 GTK_WIDGET (window));
2507 gtk_window_unset_transient_for (window);
2510 priv->transient_parent = parent;
2514 g_signal_connect (parent, "destroy",
2515 G_CALLBACK (gtk_widget_destroyed),
2516 &priv->transient_parent);
2517 g_signal_connect (parent, "realize",
2518 G_CALLBACK (gtk_window_transient_parent_realized),
2520 g_signal_connect (parent, "unrealize",
2521 G_CALLBACK (gtk_window_transient_parent_unrealized),
2523 g_signal_connect (parent, "notify::screen",
2524 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2527 gtk_window_set_screen (window, parent->priv->screen);
2529 if (priv->destroy_with_parent)
2530 connect_parent_destroyed (window);
2532 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2533 gtk_widget_get_realized (GTK_WIDGET (parent)))
2534 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2535 GTK_WIDGET (window));
2537 if (parent->priv->group)
2539 gtk_window_group_add_window (parent->priv->group, window);
2540 priv->transient_parent_group = TRUE;
2546 * gtk_window_get_transient_for:
2547 * @window: a #GtkWindow
2549 * Fetches the transient parent for this window. See
2550 * gtk_window_set_transient_for().
2552 * Return value: (transfer none): the transient parent for this window, or %NULL
2553 * if no transient parent has been set.
2556 gtk_window_get_transient_for (GtkWindow *window)
2558 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2560 return window->priv->transient_parent;
2564 * gtk_window_set_opacity:
2565 * @window: a #GtkWindow
2566 * @opacity: desired opacity, between 0 and 1
2568 * Request the windowing system to make @window partially transparent,
2569 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2570 * of the opacity parameter are clamped to the [0,1] range.) On X11
2571 * this has any effect only on X screens with a compositing manager
2572 * running. See gtk_widget_is_composited(). On Windows it should work
2575 * Note that setting a window's opacity after the window has been
2576 * shown causes it to flicker once on Windows.
2581 gtk_window_set_opacity (GtkWindow *window,
2584 GtkWindowPrivate *priv;
2586 g_return_if_fail (GTK_IS_WINDOW (window));
2588 priv = window->priv;
2592 else if (opacity > 1.0)
2595 priv->opacity_set = TRUE;
2596 priv->opacity = opacity;
2598 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2599 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2604 * gtk_window_get_opacity:
2605 * @window: a #GtkWindow
2607 * Fetches the requested opacity for this window. See
2608 * gtk_window_set_opacity().
2610 * Return value: the requested opacity for this window.
2615 gtk_window_get_opacity (GtkWindow *window)
2617 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2619 return window->priv->opacity;
2623 * gtk_window_get_application:
2624 * @window: a #GtkWindow
2626 * Gets the #GtkApplication associated with the window (if any).
2628 * Return value: a #GtkApplication, or %NULL
2633 gtk_window_get_application (GtkWindow *window)
2635 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2637 return window->priv->application;
2641 gtk_window_release_application (GtkWindow *window)
2643 if (window->priv->application)
2645 GtkApplication *application;
2647 /* steal reference into temp variable */
2648 application = window->priv->application;
2649 window->priv->application = NULL;
2651 gtk_application_remove_window (application, window);
2652 g_object_unref (application);
2657 * gtk_window_set_application:
2658 * @window: a #GtkWindow
2659 * @application: a #GtkApplication, or %NULL
2661 * Sets or unsets the #GtkApplication associated with the window.
2663 * The application will be kept alive for at least as long as the window
2669 gtk_window_set_application (GtkWindow *window,
2670 GtkApplication *application)
2672 GtkWindowPrivate *priv;
2674 g_return_if_fail (GTK_IS_WINDOW (window));
2676 priv = window->priv;
2677 if (priv->application != application)
2679 gtk_window_release_application (window);
2681 priv->application = application;
2683 if (priv->application != NULL)
2685 g_object_ref (priv->application);
2687 gtk_application_add_window (priv->application, window);
2690 g_object_notify (G_OBJECT (window), "application");
2695 * gtk_window_set_type_hint:
2696 * @window: a #GtkWindow
2697 * @hint: the window type
2699 * By setting the type hint for the window, you allow the window
2700 * manager to decorate and handle the window in a way which is
2701 * suitable to the function of the window in your application.
2703 * This function should be called before the window becomes visible.
2705 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2706 * will sometimes call gtk_window_set_type_hint() on your behalf.
2710 gtk_window_set_type_hint (GtkWindow *window,
2711 GdkWindowTypeHint hint)
2713 GtkWindowPrivate *priv;
2715 g_return_if_fail (GTK_IS_WINDOW (window));
2716 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2718 priv = window->priv;
2720 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2721 priv->gdk_type_hint = hint;
2723 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2725 priv->reset_type_hint = TRUE;
2726 priv->type_hint = hint;
2730 * gtk_window_get_type_hint:
2731 * @window: a #GtkWindow
2733 * Gets the type hint for this window. See gtk_window_set_type_hint().
2735 * Return value: the type hint for @window.
2738 gtk_window_get_type_hint (GtkWindow *window)
2740 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2742 return window->priv->type_hint;
2746 * gtk_window_set_skip_taskbar_hint:
2747 * @window: a #GtkWindow
2748 * @setting: %TRUE to keep this window from appearing in the task bar
2750 * Windows may set a hint asking the desktop environment not to display
2751 * the window in the task bar. This function sets this hint.
2756 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2759 GtkWindowPrivate *priv;
2761 g_return_if_fail (GTK_IS_WINDOW (window));
2763 priv = window->priv;
2765 setting = setting != FALSE;
2767 if (priv->skips_taskbar != setting)
2769 priv->skips_taskbar = setting;
2770 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2771 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2772 priv->skips_taskbar);
2773 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2778 * gtk_window_get_skip_taskbar_hint:
2779 * @window: a #GtkWindow
2781 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2783 * Return value: %TRUE if window shouldn't be in taskbar
2788 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2790 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2792 return window->priv->skips_taskbar;
2796 * gtk_window_set_skip_pager_hint:
2797 * @window: a #GtkWindow
2798 * @setting: %TRUE to keep this window from appearing in the pager
2800 * Windows may set a hint asking the desktop environment not to display
2801 * the window in the pager. This function sets this hint.
2802 * (A "pager" is any desktop navigation tool such as a workspace
2803 * switcher that displays a thumbnail representation of the windows
2809 gtk_window_set_skip_pager_hint (GtkWindow *window,
2812 GtkWindowPrivate *priv;
2814 g_return_if_fail (GTK_IS_WINDOW (window));
2816 priv = window->priv;
2818 setting = setting != FALSE;
2820 if (priv->skips_pager != setting)
2822 priv->skips_pager = setting;
2823 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2824 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2826 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2831 * gtk_window_get_skip_pager_hint:
2832 * @window: a #GtkWindow
2834 * Gets the value set by gtk_window_set_skip_pager_hint().
2836 * Return value: %TRUE if window shouldn't be in pager
2841 gtk_window_get_skip_pager_hint (GtkWindow *window)
2843 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2845 return window->priv->skips_pager;
2849 * gtk_window_set_urgency_hint:
2850 * @window: a #GtkWindow
2851 * @setting: %TRUE to mark this window as urgent
2853 * Windows may set a hint asking the desktop environment to draw
2854 * the users attention to the window. This function sets this hint.
2859 gtk_window_set_urgency_hint (GtkWindow *window,
2862 GtkWindowPrivate *priv;
2864 g_return_if_fail (GTK_IS_WINDOW (window));
2866 priv = window->priv;
2868 setting = setting != FALSE;
2870 if (priv->urgent != setting)
2872 priv->urgent = setting;
2873 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2874 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2876 g_object_notify (G_OBJECT (window), "urgency-hint");
2881 * gtk_window_get_urgency_hint:
2882 * @window: a #GtkWindow
2884 * Gets the value set by gtk_window_set_urgency_hint()
2886 * Return value: %TRUE if window is urgent
2891 gtk_window_get_urgency_hint (GtkWindow *window)
2893 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2895 return window->priv->urgent;
2899 * gtk_window_set_accept_focus:
2900 * @window: a #GtkWindow
2901 * @setting: %TRUE to let this window receive input focus
2903 * Windows may set a hint asking the desktop environment not to receive
2904 * the input focus. This function sets this hint.
2909 gtk_window_set_accept_focus (GtkWindow *window,
2912 GtkWindowPrivate *priv;
2914 g_return_if_fail (GTK_IS_WINDOW (window));
2916 priv = window->priv;
2918 setting = setting != FALSE;
2920 if (priv->accept_focus != setting)
2922 priv->accept_focus = setting;
2923 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2924 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2925 priv->accept_focus);
2926 g_object_notify (G_OBJECT (window), "accept-focus");
2931 * gtk_window_get_accept_focus:
2932 * @window: a #GtkWindow
2934 * Gets the value set by gtk_window_set_accept_focus().
2936 * Return value: %TRUE if window should receive the input focus
2941 gtk_window_get_accept_focus (GtkWindow *window)
2943 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2945 return window->priv->accept_focus;
2949 * gtk_window_set_focus_on_map:
2950 * @window: a #GtkWindow
2951 * @setting: %TRUE to let this window receive input focus on map
2953 * Windows may set a hint asking the desktop environment not to receive
2954 * the input focus when the window is mapped. This function sets this
2960 gtk_window_set_focus_on_map (GtkWindow *window,
2963 GtkWindowPrivate *priv;
2965 g_return_if_fail (GTK_IS_WINDOW (window));
2967 priv = window->priv;
2969 setting = setting != FALSE;
2971 if (priv->focus_on_map != setting)
2973 priv->focus_on_map = setting;
2974 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2975 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2976 priv->focus_on_map);
2977 g_object_notify (G_OBJECT (window), "focus-on-map");
2982 * gtk_window_get_focus_on_map:
2983 * @window: a #GtkWindow
2985 * Gets the value set by gtk_window_set_focus_on_map().
2987 * Return value: %TRUE if window should receive the input focus when
2993 gtk_window_get_focus_on_map (GtkWindow *window)
2995 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2997 return window->priv->focus_on_map;
3001 * gtk_window_set_destroy_with_parent:
3002 * @window: a #GtkWindow
3003 * @setting: whether to destroy @window with its transient parent
3005 * If @setting is %TRUE, then destroying the transient parent of @window
3006 * will also destroy @window itself. This is useful for dialogs that
3007 * shouldn't persist beyond the lifetime of the main window they're
3008 * associated with, for example.
3011 gtk_window_set_destroy_with_parent (GtkWindow *window,
3014 GtkWindowPrivate *priv;
3016 g_return_if_fail (GTK_IS_WINDOW (window));
3018 priv = window->priv;
3020 if (priv->destroy_with_parent == (setting != FALSE))
3023 if (priv->destroy_with_parent)
3025 disconnect_parent_destroyed (window);
3029 connect_parent_destroyed (window);
3032 priv->destroy_with_parent = setting;
3034 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3038 * gtk_window_get_destroy_with_parent:
3039 * @window: a #GtkWindow
3041 * Returns whether the window will be destroyed with its transient parent. See
3042 * gtk_window_set_destroy_with_parent ().
3044 * Return value: %TRUE if the window will be destroyed with its transient parent.
3047 gtk_window_get_destroy_with_parent (GtkWindow *window)
3049 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3051 return window->priv->destroy_with_parent;
3054 static GtkWindowGeometryInfo*
3055 gtk_window_get_geometry_info (GtkWindow *window,
3058 GtkWindowPrivate *priv = window->priv;
3059 GtkWindowGeometryInfo *info;
3061 info = priv->geometry_info;
3062 if (!info && create)
3064 info = g_new0 (GtkWindowGeometryInfo, 1);
3066 info->default_width = -1;
3067 info->default_height = -1;
3068 info->resize_width = -1;
3069 info->resize_height = -1;
3070 info->initial_x = 0;
3071 info->initial_y = 0;
3072 info->initial_pos_set = FALSE;
3073 info->default_is_geometry = FALSE;
3074 info->position_constraints_changed = FALSE;
3075 info->last.configure_request.x = 0;
3076 info->last.configure_request.y = 0;
3077 info->last.configure_request.width = -1;
3078 info->last.configure_request.height = -1;
3079 info->widget = NULL;
3081 priv->geometry_info = info;
3088 * gtk_window_set_geometry_hints:
3089 * @window: a #GtkWindow
3090 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3091 * @geometry: (allow-none): struct containing geometry information or %NULL
3092 * @geom_mask: mask indicating which struct fields should be paid attention to
3094 * This function sets up hints about how a window can be resized by
3095 * the user. You can set a minimum and maximum size; allowed resize
3096 * increments (e.g. for xterm, you can only resize by the size of a
3097 * character); aspect ratios; and more. See the #GdkGeometry struct.
3101 gtk_window_set_geometry_hints (GtkWindow *window,
3102 GtkWidget *geometry_widget,
3103 GdkGeometry *geometry,
3104 GdkWindowHints geom_mask)
3106 GtkWindowGeometryInfo *info;
3108 g_return_if_fail (GTK_IS_WINDOW (window));
3109 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3111 info = gtk_window_get_geometry_info (window, TRUE);
3114 g_signal_handlers_disconnect_by_func (info->widget,
3115 gtk_widget_destroyed,
3118 info->widget = geometry_widget;
3120 g_signal_connect (geometry_widget, "destroy",
3121 G_CALLBACK (gtk_widget_destroyed),
3125 info->geometry = *geometry;
3127 /* We store gravity in priv->gravity not in the hints. */
3128 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3130 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3132 gtk_window_set_gravity (window, geometry->win_gravity);
3135 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3139 * gtk_window_set_decorated:
3140 * @window: a #GtkWindow
3141 * @setting: %TRUE to decorate the window
3143 * By default, windows are decorated with a title bar, resize
3144 * controls, etc. Some <link linkend="gtk-X11-arch">window
3145 * managers</link> allow GTK+ to disable these decorations, creating a
3146 * borderless window. If you set the decorated property to %FALSE
3147 * using this function, GTK+ will do its best to convince the window
3148 * manager not to decorate the window. Depending on the system, this
3149 * function may not have any effect when called on a window that is
3150 * already visible, so you should call it before calling gtk_window_show().
3152 * On Windows, this function always works, since there's no window manager
3157 gtk_window_set_decorated (GtkWindow *window,
3160 GtkWindowPrivate *priv;
3161 GdkWindow *gdk_window;
3163 g_return_if_fail (GTK_IS_WINDOW (window));
3165 priv = window->priv;
3167 setting = setting != FALSE;
3169 if (setting == priv->decorated)
3172 priv->decorated = setting;
3174 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3177 if (priv->decorated)
3178 gdk_window_set_decorations (gdk_window,
3181 gdk_window_set_decorations (gdk_window,
3185 g_object_notify (G_OBJECT (window), "decorated");
3189 * gtk_window_get_decorated:
3190 * @window: a #GtkWindow
3192 * Returns whether the window has been set to have decorations
3193 * such as a title bar via gtk_window_set_decorated().
3195 * Return value: %TRUE if the window has been set to have decorations
3198 gtk_window_get_decorated (GtkWindow *window)
3200 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3202 return window->priv->decorated;
3206 * gtk_window_set_deletable:
3207 * @window: a #GtkWindow
3208 * @setting: %TRUE to decorate the window as deletable
3210 * By default, windows have a close button in the window frame. Some
3211 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3212 * disable this button. If you set the deletable property to %FALSE
3213 * using this function, GTK+ will do its best to convince the window
3214 * manager not to show a close button. Depending on the system, this
3215 * function may not have any effect when called on a window that is
3216 * already visible, so you should call it before calling gtk_window_show().
3218 * On Windows, this function always works, since there's no window manager
3224 gtk_window_set_deletable (GtkWindow *window,
3227 GtkWindowPrivate *priv;
3228 GdkWindow *gdk_window;
3230 g_return_if_fail (GTK_IS_WINDOW (window));
3232 priv = window->priv;
3234 setting = setting != FALSE;
3236 if (setting == priv->deletable)
3239 priv->deletable = setting;
3241 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3244 if (priv->deletable)
3245 gdk_window_set_functions (gdk_window,
3248 gdk_window_set_functions (gdk_window,
3249 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3252 g_object_notify (G_OBJECT (window), "deletable");
3256 * gtk_window_get_deletable:
3257 * @window: a #GtkWindow
3259 * Returns whether the window has been set to have a close button
3260 * via gtk_window_set_deletable().
3262 * Return value: %TRUE if the window has been set to have a close button
3267 gtk_window_get_deletable (GtkWindow *window)
3269 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3271 return window->priv->deletable;
3274 static GtkWindowIconInfo*
3275 get_icon_info (GtkWindow *window)
3277 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3281 free_icon_info (GtkWindowIconInfo *info)
3283 g_free (info->icon_name);
3284 g_slice_free (GtkWindowIconInfo, info);
3288 static GtkWindowIconInfo*
3289 ensure_icon_info (GtkWindow *window)
3291 GtkWindowIconInfo *info;
3293 info = get_icon_info (window);
3297 info = g_slice_new0 (GtkWindowIconInfo);
3298 g_object_set_qdata_full (G_OBJECT (window),
3299 quark_gtk_window_icon_info,
3301 (GDestroyNotify)free_icon_info);
3308 icon_list_from_theme (GtkWidget *widget,
3313 GtkIconTheme *icon_theme;
3318 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3320 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3323 for (i = 0; sizes[i]; i++)
3326 * We need an EWMH extension to handle scalable icons
3327 * by passing their name to the WM. For now just use a
3331 icon = gtk_icon_theme_load_icon (icon_theme, name,
3334 icon = gtk_icon_theme_load_icon (icon_theme, name,
3337 list = g_list_append (list, icon);
3347 gtk_window_realize_icon (GtkWindow *window)
3349 GtkWindowPrivate *priv = window->priv;
3351 GtkWindowIconInfo *info;
3352 GdkWindow *gdk_window;
3355 widget = GTK_WIDGET (window);
3356 gdk_window = gtk_widget_get_window (widget);
3358 g_return_if_fail (gdk_window != NULL);
3360 /* no point setting an icon on override-redirect */
3361 if (priv->type == GTK_WINDOW_POPUP)
3366 info = ensure_icon_info (window);
3371 info->using_default_icon = FALSE;
3372 info->using_parent_icon = FALSE;
3373 info->using_themed_icon = FALSE;
3375 icon_list = info->icon_list;
3377 /* Look up themed icon */
3378 if (icon_list == NULL && info->icon_name)
3380 icon_list = icon_list_from_theme (widget, info->icon_name);
3382 info->using_themed_icon = TRUE;
3385 /* Inherit from transient parent */
3386 if (icon_list == NULL && priv->transient_parent)
3388 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3390 info->using_parent_icon = TRUE;
3393 /* Inherit from default */
3394 if (icon_list == NULL)
3396 icon_list = default_icon_list;
3398 info->using_default_icon = TRUE;
3401 /* Look up themed icon */
3402 if (icon_list == NULL && default_icon_name)
3404 icon_list = icon_list_from_theme (widget, default_icon_name);
3405 info->using_default_icon = TRUE;
3406 info->using_themed_icon = TRUE;
3409 info->realized = TRUE;
3411 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3413 if (info->using_themed_icon)
3415 GtkIconTheme *icon_theme;
3417 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3418 g_list_free (icon_list);
3420 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3421 g_signal_connect (icon_theme, "changed",
3422 G_CALLBACK (update_themed_icon), window);
3427 gtk_window_unrealize_icon (GtkWindow *window)
3429 GtkWindowIconInfo *info;
3431 info = get_icon_info (window);
3436 if (info->using_themed_icon)
3438 GtkIconTheme *icon_theme;
3440 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3442 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3445 /* We don't clear the properties on the window, just figure the
3446 * window is going away.
3449 info->realized = FALSE;
3454 * gtk_window_set_icon_list:
3455 * @window: a #GtkWindow
3456 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3458 * Sets up the icon representing a #GtkWindow. The icon is used when
3459 * the window is minimized (also known as iconified). Some window
3460 * managers or desktop environments may also place it in the window
3461 * frame, or display it in other contexts.
3463 * gtk_window_set_icon_list() allows you to pass in the same icon in
3464 * several hand-drawn sizes. The list should contain the natural sizes
3465 * your icon is available in; that is, don't scale the image before
3466 * passing it to GTK+. Scaling is postponed until the last minute,
3467 * when the desired final size is known, to allow best quality.
3469 * By passing several sizes, you may improve the final image quality
3470 * of the icon, by reducing or eliminating automatic image scaling.
3472 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3473 * larger images (64x64, 128x128) if you have them.
3475 * See also gtk_window_set_default_icon_list() to set the icon
3476 * for all windows in your application in one go.
3478 * Note that transient windows (those who have been set transient for another
3479 * window using gtk_window_set_transient_for()) will inherit their
3480 * icon from their transient parent. So there's no need to explicitly
3481 * set the icon on transient windows.
3484 gtk_window_set_icon_list (GtkWindow *window,
3487 GtkWindowIconInfo *info;
3489 g_return_if_fail (GTK_IS_WINDOW (window));
3491 info = ensure_icon_info (window);
3493 if (info->icon_list == list) /* check for NULL mostly */
3496 g_list_foreach (list,
3497 (GFunc) g_object_ref, NULL);
3499 g_list_foreach (info->icon_list,
3500 (GFunc) g_object_unref, NULL);
3502 g_list_free (info->icon_list);
3504 info->icon_list = g_list_copy (list);
3506 g_object_notify (G_OBJECT (window), "icon");
3508 gtk_window_unrealize_icon (window);
3510 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3511 gtk_window_realize_icon (window);
3513 /* We could try to update our transient children, but I don't think
3514 * it's really worth it. If we did it, the best way would probably
3515 * be to have children connect to notify::icon-list
3520 * gtk_window_get_icon_list:
3521 * @window: a #GtkWindow
3523 * Retrieves the list of icons set by gtk_window_set_icon_list().
3524 * The list is copied, but the reference count on each
3525 * member won't be incremented.
3527 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3530 gtk_window_get_icon_list (GtkWindow *window)
3532 GtkWindowIconInfo *info;
3534 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3536 info = get_icon_info (window);
3539 return g_list_copy (info->icon_list);
3545 * gtk_window_set_icon:
3546 * @window: a #GtkWindow
3547 * @icon: (allow-none): icon image, or %NULL
3549 * Sets up the icon representing a #GtkWindow. This icon is used when
3550 * the window is minimized (also known as iconified). Some window
3551 * managers or desktop environments may also place it in the window
3552 * frame, or display it in other contexts.
3554 * The icon should be provided in whatever size it was naturally
3555 * drawn; that is, don't scale the image before passing it to
3556 * GTK+. Scaling is postponed until the last minute, when the desired
3557 * final size is known, to allow best quality.
3559 * If you have your icon hand-drawn in multiple sizes, use
3560 * gtk_window_set_icon_list(). Then the best size will be used.
3562 * This function is equivalent to calling gtk_window_set_icon_list()
3563 * with a 1-element list.
3565 * See also gtk_window_set_default_icon_list() to set the icon
3566 * for all windows in your application in one go.
3569 gtk_window_set_icon (GtkWindow *window,
3574 g_return_if_fail (GTK_IS_WINDOW (window));
3575 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3580 list = g_list_append (list, icon);
3582 gtk_window_set_icon_list (window, list);
3588 update_themed_icon (GtkIconTheme *icon_theme,
3591 g_object_notify (G_OBJECT (window), "icon");
3593 gtk_window_unrealize_icon (window);
3595 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3596 gtk_window_realize_icon (window);
3600 * gtk_window_set_icon_name:
3601 * @window: a #GtkWindow
3602 * @name: (allow-none): the name of the themed icon
3604 * Sets the icon for the window from a named themed icon. See
3605 * the docs for #GtkIconTheme for more details.
3607 * Note that this has nothing to do with the WM_ICON_NAME
3608 * property which is mentioned in the ICCCM.
3613 gtk_window_set_icon_name (GtkWindow *window,
3616 GtkWindowIconInfo *info;
3619 g_return_if_fail (GTK_IS_WINDOW (window));
3621 info = ensure_icon_info (window);
3623 if (g_strcmp0 (info->icon_name, name) == 0)
3626 tmp = info->icon_name;
3627 info->icon_name = g_strdup (name);
3630 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3631 g_list_free (info->icon_list);
3632 info->icon_list = NULL;
3634 update_themed_icon (NULL, window);
3636 g_object_notify (G_OBJECT (window), "icon-name");
3640 * gtk_window_get_icon_name:
3641 * @window: a #GtkWindow
3643 * Returns the name of the themed icon for the window,
3644 * see gtk_window_set_icon_name().
3646 * Returns: the icon name or %NULL if the window has
3652 gtk_window_get_icon_name (GtkWindow *window)
3654 GtkWindowIconInfo *info;
3656 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3658 info = ensure_icon_info (window);
3660 return info->icon_name;
3664 * gtk_window_get_icon:
3665 * @window: a #GtkWindow
3667 * Gets the value set by gtk_window_set_icon() (or if you've
3668 * called gtk_window_set_icon_list(), gets the first icon in
3671 * Return value: (transfer none): icon for window
3674 gtk_window_get_icon (GtkWindow *window)
3676 GtkWindowIconInfo *info;
3678 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3680 info = get_icon_info (window);
3681 if (info && info->icon_list)
3682 return GDK_PIXBUF (info->icon_list->data);
3687 /* Load pixbuf, printing warning on failure if error == NULL
3690 load_pixbuf_verbosely (const char *filename,
3693 GError *local_err = NULL;
3696 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3704 g_warning ("Error loading icon from file '%s':\n\t%s",
3705 filename, local_err->message);
3706 g_error_free (local_err);
3714 * gtk_window_set_icon_from_file:
3715 * @window: a #GtkWindow
3716 * @filename: location of icon file
3717 * @err: (allow-none): location to store error, or %NULL.
3719 * Sets the icon for @window.
3720 * Warns on failure if @err is %NULL.
3722 * This function is equivalent to calling gtk_window_set_icon()
3723 * with a pixbuf created by loading the image from @filename.
3725 * Returns: %TRUE if setting the icon succeeded.
3730 gtk_window_set_icon_from_file (GtkWindow *window,
3731 const gchar *filename,
3734 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3738 gtk_window_set_icon (window, pixbuf);
3739 g_object_unref (pixbuf);
3748 * gtk_window_set_default_icon_list:
3749 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3751 * Sets an icon list to be used as fallback for windows that haven't
3752 * had gtk_window_set_icon_list() called on them to set up a
3753 * window-specific icon list. This function allows you to set up the
3754 * icon for all windows in your app at once.
3756 * See gtk_window_set_icon_list() for more details.
3760 gtk_window_set_default_icon_list (GList *list)
3764 if (list == default_icon_list)
3767 /* Update serial so we don't used cached pixmaps/masks
3769 default_icon_serial++;
3771 g_list_foreach (list,
3772 (GFunc) g_object_ref, NULL);
3774 g_list_foreach (default_icon_list,
3775 (GFunc) g_object_unref, NULL);
3777 g_list_free (default_icon_list);
3779 default_icon_list = g_list_copy (list);
3781 /* Update all toplevels */
3782 toplevels = gtk_window_list_toplevels ();
3783 tmp_list = toplevels;
3784 while (tmp_list != NULL)
3786 GtkWindowIconInfo *info;
3787 GtkWindow *w = tmp_list->data;
3789 info = get_icon_info (w);
3790 if (info && info->using_default_icon)
3792 gtk_window_unrealize_icon (w);
3793 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3794 gtk_window_realize_icon (w);
3797 tmp_list = tmp_list->next;
3799 g_list_free (toplevels);
3803 * gtk_window_set_default_icon:
3806 * Sets an icon to be used as fallback for windows that haven't
3807 * had gtk_window_set_icon() called on them from a pixbuf.
3812 gtk_window_set_default_icon (GdkPixbuf *icon)
3816 g_return_if_fail (GDK_IS_PIXBUF (icon));
3818 list = g_list_prepend (NULL, icon);
3819 gtk_window_set_default_icon_list (list);
3824 * gtk_window_set_default_icon_name:
3825 * @name: the name of the themed icon
3827 * Sets an icon to be used as fallback for windows that haven't
3828 * had gtk_window_set_icon_list() called on them from a named
3829 * themed icon, see gtk_window_set_icon_name().
3834 gtk_window_set_default_icon_name (const gchar *name)
3839 /* Update serial so we don't used cached pixmaps/masks
3841 default_icon_serial++;
3843 g_free (default_icon_name);
3844 default_icon_name = g_strdup (name);
3846 g_list_foreach (default_icon_list,
3847 (GFunc) g_object_unref, NULL);
3849 g_list_free (default_icon_list);
3850 default_icon_list = NULL;
3852 /* Update all toplevels */
3853 toplevels = gtk_window_list_toplevels ();
3854 tmp_list = toplevels;
3855 while (tmp_list != NULL)
3857 GtkWindowIconInfo *info;
3858 GtkWindow *w = tmp_list->data;
3860 info = get_icon_info (w);
3861 if (info && info->using_default_icon && info->using_themed_icon)
3863 gtk_window_unrealize_icon (w);
3864 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3865 gtk_window_realize_icon (w);
3868 tmp_list = tmp_list->next;
3870 g_list_free (toplevels);
3874 * gtk_window_get_default_icon_name:
3876 * Returns the fallback icon name for windows that has been set
3877 * with gtk_window_set_default_icon_name(). The returned
3878 * string is owned by GTK+ and should not be modified. It
3879 * is only valid until the next call to
3880 * gtk_window_set_default_icon_name().
3882 * Returns: the fallback icon name for windows
3887 gtk_window_get_default_icon_name (void)
3889 return default_icon_name;
3893 * gtk_window_set_default_icon_from_file:
3894 * @filename: location of icon file
3895 * @err: (allow-none): location to store error, or %NULL.
3897 * Sets an icon to be used as fallback for windows that haven't
3898 * had gtk_window_set_icon_list() called on them from a file
3899 * on disk. Warns on failure if @err is %NULL.
3901 * Returns: %TRUE if setting the icon succeeded.
3906 gtk_window_set_default_icon_from_file (const gchar *filename,
3909 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3913 gtk_window_set_default_icon (pixbuf);
3914 g_object_unref (pixbuf);
3923 * gtk_window_get_default_icon_list:
3925 * Gets the value set by gtk_window_set_default_icon_list().
3926 * The list is a copy and should be freed with g_list_free(),
3927 * but the pixbufs in the list have not had their reference count
3930 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3933 gtk_window_get_default_icon_list (void)
3935 return g_list_copy (default_icon_list);
3939 gtk_window_set_default_size_internal (GtkWindow *window,
3940 gboolean change_width,
3942 gboolean change_height,
3944 gboolean is_geometry)
3946 GtkWindowGeometryInfo *info;
3948 g_return_if_fail (change_width == FALSE || width >= -1);
3949 g_return_if_fail (change_height == FALSE || height >= -1);
3951 info = gtk_window_get_geometry_info (window, TRUE);
3953 g_object_freeze_notify (G_OBJECT (window));
3955 info->default_is_geometry = is_geometry != FALSE;
3965 info->default_width = width;
3967 g_object_notify (G_OBJECT (window), "default-width");
3978 info->default_height = height;
3980 g_object_notify (G_OBJECT (window), "default-height");
3983 g_object_thaw_notify (G_OBJECT (window));
3985 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3989 * gtk_window_set_default_size:
3990 * @window: a #GtkWindow
3991 * @width: width in pixels, or -1 to unset the default width
3992 * @height: height in pixels, or -1 to unset the default height
3994 * Sets the default size of a window. If the window's "natural" size
3995 * (its size request) is larger than the default, the default will be
3996 * ignored. More generally, if the default size does not obey the
3997 * geometry hints for the window (gtk_window_set_geometry_hints() can
3998 * be used to set these explicitly), the default size will be clamped
3999 * to the nearest permitted size.
4001 * Unlike gtk_widget_set_size_request(), which sets a size request for
4002 * a widget and thus would keep users from shrinking the window, this
4003 * function only sets the initial size, just as if the user had
4004 * resized the window themselves. Users can still shrink the window
4005 * again as they normally would. Setting a default size of -1 means to
4006 * use the "natural" default size (the size request of the window).
4008 * For more control over a window's initial size and how resizing works,
4009 * investigate gtk_window_set_geometry_hints().
4011 * For some uses, gtk_window_resize() is a more appropriate function.
4012 * gtk_window_resize() changes the current size of the window, rather
4013 * than the size to be used on initial display. gtk_window_resize() always
4014 * affects the window itself, not the geometry widget.
4016 * The default size of a window only affects the first time a window is
4017 * shown; if a window is hidden and re-shown, it will remember the size
4018 * it had prior to hiding, rather than using the default size.
4020 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4021 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4024 gtk_window_set_default_size (GtkWindow *window,
4028 g_return_if_fail (GTK_IS_WINDOW (window));
4029 g_return_if_fail (width >= -1);
4030 g_return_if_fail (height >= -1);
4032 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4036 * gtk_window_set_default_geometry:
4037 * @window: a #GtkWindow
4038 * @width: width in resize increments, or -1 to unset the default width
4039 * @height: height in resize increments, or -1 to unset the default height
4041 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4042 * in terms of the base size and increment set with
4043 * gtk_window_set_geometry_hints.
4048 gtk_window_set_default_geometry (GtkWindow *window,
4052 g_return_if_fail (GTK_IS_WINDOW (window));
4053 g_return_if_fail (width >= -1);
4054 g_return_if_fail (height >= -1);
4056 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4060 * gtk_window_get_default_size:
4061 * @window: a #GtkWindow
4062 * @width: (out) (allow-none): location to store the default width, or %NULL
4063 * @height: (out) (allow-none): location to store the default height, or %NULL
4065 * Gets the default size of the window. A value of -1 for the width or
4066 * height indicates that a default size has not been explicitly set
4067 * for that dimension, so the "natural" size of the window will be
4072 gtk_window_get_default_size (GtkWindow *window,
4076 GtkWindowGeometryInfo *info;
4078 g_return_if_fail (GTK_IS_WINDOW (window));
4080 info = gtk_window_get_geometry_info (window, FALSE);
4083 *width = info ? info->default_width : -1;
4086 *height = info ? info->default_height : -1;
4090 * gtk_window_resize:
4091 * @window: a #GtkWindow
4092 * @width: width in pixels to resize the window to
4093 * @height: height in pixels to resize the window to
4095 * Resizes the window as if the user had done so, obeying geometry
4096 * constraints. The default geometry constraint is that windows may
4097 * not be smaller than their size request; to override this
4098 * constraint, call gtk_widget_set_size_request() to set the window's
4099 * request to a smaller value.
4101 * If gtk_window_resize() is called before showing a window for the
4102 * first time, it overrides any default size set with
4103 * gtk_window_set_default_size().
4105 * Windows may not be resized smaller than 1 by 1 pixels.
4109 gtk_window_resize (GtkWindow *window,
4113 GtkWindowGeometryInfo *info;
4115 g_return_if_fail (GTK_IS_WINDOW (window));
4116 g_return_if_fail (width > 0);
4117 g_return_if_fail (height > 0);
4119 info = gtk_window_get_geometry_info (window, TRUE);
4121 info->resize_width = width;
4122 info->resize_height = height;
4123 info->resize_is_geometry = FALSE;
4125 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4129 * gtk_window_resize_to_geometry:
4130 * @window: a #GtkWindow
4131 * @width: width in resize increments to resize the window to
4132 * @height: height in resize increments to resize the window to
4134 * Like gtk_window_resize(), but @width and @height are interpreted
4135 * in terms of the base size and increment set with
4136 * gtk_window_set_geometry_hints.
4141 gtk_window_resize_to_geometry (GtkWindow *window,
4145 GtkWindowGeometryInfo *info;
4147 g_return_if_fail (GTK_IS_WINDOW (window));
4148 g_return_if_fail (width > 0);
4149 g_return_if_fail (height > 0);
4151 info = gtk_window_get_geometry_info (window, TRUE);
4153 info->resize_width = width;
4154 info->resize_height = height;
4155 info->resize_is_geometry = TRUE;
4157 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4161 * gtk_window_get_size:
4162 * @window: a #GtkWindow
4163 * @width: (out) (allow-none): return location for width, or %NULL
4164 * @height: (out) (allow-none): return location for height, or %NULL
4166 * Obtains the current size of @window. If @window is not onscreen,
4167 * it returns the size GTK+ will suggest to the <link
4168 * linkend="gtk-X11-arch">window manager</link> for the initial window
4169 * size (but this is not reliably the same as the size the window
4170 * manager will actually select). The size obtained by
4171 * gtk_window_get_size() is the last size received in a
4172 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4173 * rather than querying the X server for the size. As a result, if you
4174 * call gtk_window_resize() then immediately call
4175 * gtk_window_get_size(), the size won't have taken effect yet. After
4176 * the window manager processes the resize request, GTK+ receives
4177 * notification that the size has changed via a configure event, and
4178 * the size of the window gets updated.
4180 * Note 1: Nearly any use of this function creates a race condition,
4181 * because the size of the window may change between the time that you
4182 * get the size and the time that you perform some action assuming
4183 * that size is the current size. To avoid race conditions, connect to
4184 * "configure-event" on the window and adjust your size-dependent
4185 * state to match the size delivered in the #GdkEventConfigure.
4187 * Note 2: The returned size does <emphasis>not</emphasis> include the
4188 * size of the window manager decorations (aka the window frame or
4189 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4190 * method of determining their size.
4192 * Note 3: If you are getting a window size in order to position
4193 * the window onscreen, there may be a better way. The preferred
4194 * way is to simply set the window's semantic type with
4195 * gtk_window_set_type_hint(), which allows the window manager to
4196 * e.g. center dialogs. Also, if you set the transient parent of
4197 * dialogs with gtk_window_set_transient_for() window managers
4198 * will often center the dialog over its parent window. It's
4199 * much preferred to let the window manager handle these
4200 * things rather than doing it yourself, because all apps will
4201 * behave consistently and according to user prefs if the window
4202 * manager handles it. Also, the window manager can take the size
4203 * of the window decorations/border into account, while your
4204 * application cannot.
4206 * In any case, if you insist on application-specified window
4207 * positioning, there's <emphasis>still</emphasis> a better way than
4208 * doing it yourself - gtk_window_set_position() will frequently
4209 * handle the details for you.
4213 gtk_window_get_size (GtkWindow *window,
4219 g_return_if_fail (GTK_IS_WINDOW (window));
4221 if (width == NULL && height == NULL)
4224 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4226 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4227 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4231 GdkRectangle configure_request;
4233 gtk_window_compute_configure_request (window,
4237 w = configure_request.width;
4238 h = configure_request.height;
4249 * @window: a #GtkWindow
4250 * @x: X coordinate to move window to
4251 * @y: Y coordinate to move window to
4253 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4254 * @window to the given position. Window managers are free to ignore
4255 * this; most window managers ignore requests for initial window
4256 * positions (instead using a user-defined placement algorithm) and
4257 * honor requests after the window has already been shown.
4259 * Note: the position is the position of the gravity-determined
4260 * reference point for the window. The gravity determines two things:
4261 * first, the location of the reference point in root window
4262 * coordinates; and second, which point on the window is positioned at
4263 * the reference point.
4265 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4266 * point is simply the @x, @y supplied to gtk_window_move(). The
4267 * top-left corner of the window decorations (aka window frame or
4268 * border) will be placed at @x, @y. Therefore, to position a window
4269 * at the top left of the screen, you want to use the default gravity
4270 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4272 * To position a window at the bottom right corner of the screen, you
4273 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4274 * point is at @x + the window width and @y + the window height, and
4275 * the bottom-right corner of the window border will be placed at that
4276 * reference point. So, to place a window in the bottom right corner
4277 * you would first set gravity to south east, then write:
4278 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4279 * gdk_screen_height () - window_height)</literal> (note that this
4280 * example does not take multi-head scenarios into account).
4282 * The Extended Window Manager Hints specification at <ulink
4283 * url="http://www.freedesktop.org/Standards/wm-spec">
4284 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4285 * nice table of gravities in the "implementation notes" section.
4287 * The gtk_window_get_position() documentation may also be relevant.
4290 gtk_window_move (GtkWindow *window,
4294 GtkWindowPrivate *priv;
4295 GtkWindowGeometryInfo *info;
4298 g_return_if_fail (GTK_IS_WINDOW (window));
4300 priv = window->priv;
4301 widget = GTK_WIDGET (window);
4303 info = gtk_window_get_geometry_info (window, TRUE);
4305 if (gtk_widget_get_mapped (widget))
4307 GtkAllocation allocation;
4309 gtk_widget_get_allocation (widget, &allocation);
4311 /* we have now sent a request with this position
4312 * with currently-active constraints, so toggle flag.
4314 info->position_constraints_changed = FALSE;
4316 /* we only constrain if mapped - if not mapped,
4317 * then gtk_window_compute_configure_request()
4318 * will apply the constraints later, and we
4319 * don't want to lose information about
4320 * what position the user set before then.
4321 * i.e. if you do a move() then turn off POS_CENTER
4322 * then show the window, your move() will work.
4324 gtk_window_constrain_position (window,
4325 allocation.width, allocation.height,
4328 /* Note that this request doesn't go through our standard request
4329 * framework, e.g. doesn't increment configure_request_count,
4330 * doesn't set info->last, etc.; that's because
4331 * we don't save the info needed to arrive at this same request
4334 * To gtk_window_move_resize(), this will end up looking exactly
4335 * the same as the position being changed by the window
4339 /* FIXME are we handling gravity properly for framed windows? */
4341 gdk_window_move (priv->frame,
4342 x - priv->frame_left,
4343 y - priv->frame_top);
4345 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)),
4350 /* Save this position to apply on mapping */
4351 info->initial_x = x;
4352 info->initial_y = y;
4353 info->initial_pos_set = TRUE;
4358 * gtk_window_get_position:
4359 * @window: a #GtkWindow
4360 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4361 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4363 * This function returns the position you need to pass to
4364 * gtk_window_move() to keep @window in its current position. This
4365 * means that the meaning of the returned value varies with window
4366 * gravity. See gtk_window_move() for more details.
4368 * If you haven't changed the window gravity, its gravity will be
4369 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4370 * gets the position of the top-left corner of the window manager
4371 * frame for the window. gtk_window_move() sets the position of this
4372 * same top-left corner.
4374 * gtk_window_get_position() is not 100% reliable because the X Window System
4375 * does not specify a way to obtain the geometry of the
4376 * decorations placed on a window by the window manager.
4377 * Thus GTK+ is using a "best guess" that works with most
4380 * Moreover, nearly all window managers are historically broken with
4381 * respect to their handling of window gravity. So moving a window to
4382 * its current position as returned by gtk_window_get_position() tends
4383 * to result in moving the window slightly. Window managers are
4384 * slowly getting better over time.
4386 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4387 * frame is not relevant, and thus gtk_window_get_position() will
4388 * always produce accurate results. However you can't use static
4389 * gravity to do things like place a window in a corner of the screen,
4390 * because static gravity ignores the window manager decorations.
4392 * If you are saving and restoring your application's window
4393 * positions, you should know that it's impossible for applications to
4394 * do this without getting it somewhat wrong because applications do
4395 * not have sufficient knowledge of window manager state. The Correct
4396 * Mechanism is to support the session management protocol (see the
4397 * "GnomeClient" object in the GNOME libraries for example) and allow
4398 * the window manager to save your window sizes and positions.
4403 gtk_window_get_position (GtkWindow *window,
4407 GtkWindowPrivate *priv;
4409 GdkWindow *gdk_window;
4411 g_return_if_fail (GTK_IS_WINDOW (window));
4413 priv = window->priv;
4414 widget = GTK_WIDGET (window);
4415 gdk_window = gtk_widget_get_window (widget);
4417 if (priv->gravity == GDK_GRAVITY_STATIC)
4419 if (gtk_widget_get_mapped (widget))
4421 /* This does a server round-trip, which is sort of wrong;
4422 * but a server round-trip is inevitable for
4423 * gdk_window_get_frame_extents() in the usual
4424 * NorthWestGravity case below, so not sure what else to
4425 * do. We should likely be consistent about whether we get
4426 * the client-side info or the server-side info.
4428 gdk_window_get_origin (gdk_window, root_x, root_y);
4432 GdkRectangle configure_request;
4434 gtk_window_compute_configure_request (window,
4438 *root_x = configure_request.x;
4439 *root_y = configure_request.y;
4444 GdkRectangle frame_extents;
4449 if (gtk_widget_get_mapped (widget))
4452 gdk_window_get_frame_extents (priv->frame, &frame_extents);
4454 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4455 x = frame_extents.x;
4456 y = frame_extents.y;
4457 gtk_window_get_size (window, &w, &h);
4461 /* We just say the frame has 0 size on all sides.
4462 * Not sure what else to do.
4464 gtk_window_compute_configure_request (window,
4467 x = frame_extents.x;
4468 y = frame_extents.y;
4469 w = frame_extents.width;
4470 h = frame_extents.height;
4473 switch (priv->gravity)
4475 case GDK_GRAVITY_NORTH:
4476 case GDK_GRAVITY_CENTER:
4477 case GDK_GRAVITY_SOUTH:
4478 /* Find center of frame. */
4479 x += frame_extents.width / 2;
4480 /* Center client window on that point. */
4484 case GDK_GRAVITY_SOUTH_EAST:
4485 case GDK_GRAVITY_EAST:
4486 case GDK_GRAVITY_NORTH_EAST:
4487 /* Find right edge of frame */
4488 x += frame_extents.width;
4489 /* Align left edge of client at that point. */
4496 switch (priv->gravity)
4498 case GDK_GRAVITY_WEST:
4499 case GDK_GRAVITY_CENTER:
4500 case GDK_GRAVITY_EAST:
4501 /* Find center of frame. */
4502 y += frame_extents.height / 2;
4503 /* Center client window there. */
4506 case GDK_GRAVITY_SOUTH_WEST:
4507 case GDK_GRAVITY_SOUTH:
4508 case GDK_GRAVITY_SOUTH_EAST:
4509 /* Find south edge of frame */
4510 y += frame_extents.height;
4511 /* Place bottom edge of client there */
4526 * gtk_window_reshow_with_initial_size:
4527 * @window: a #GtkWindow
4529 * Hides @window, then reshows it, resetting the
4530 * default size and position of the window. Used
4531 * by GUI builders only.
4534 gtk_window_reshow_with_initial_size (GtkWindow *window)
4538 g_return_if_fail (GTK_IS_WINDOW (window));
4540 widget = GTK_WIDGET (window);
4542 gtk_widget_hide (widget);
4543 gtk_widget_unrealize (widget);
4544 gtk_widget_show (widget);
4548 gtk_window_destroy (GtkWidget *widget)
4550 GtkWindow *window = GTK_WINDOW (widget);
4551 GtkWindowPrivate *priv = window->priv;
4553 toplevel_list = g_slist_remove (toplevel_list, window);
4555 if (priv->transient_parent)
4556 gtk_window_set_transient_for (window, NULL);
4558 /* frees the icons */
4559 gtk_window_set_icon_list (window, NULL);
4561 if (priv->has_user_ref_count)
4563 priv->has_user_ref_count = FALSE;
4564 g_object_unref (window);
4568 gtk_window_group_remove_window (priv->group, window);
4570 gtk_window_free_key_hash (window);
4572 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4576 gtk_window_finalize (GObject *object)
4578 GtkWindow *window = GTK_WINDOW (object);
4579 GtkWindowPrivate *priv = window->priv;
4580 GtkMnemonicHash *mnemonic_hash;
4582 g_free (priv->title);
4583 g_free (priv->wmclass_name);
4584 g_free (priv->wmclass_class);
4585 g_free (priv->wm_role);
4586 gtk_window_release_application (window);
4588 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4590 _gtk_mnemonic_hash_free (mnemonic_hash);
4592 if (priv->geometry_info)
4594 if (priv->geometry_info->widget)
4595 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4596 gtk_widget_destroyed,
4597 &priv->geometry_info->widget);
4598 g_free (priv->geometry_info);
4601 if (priv->keys_changed_handler)
4603 g_source_remove (priv->keys_changed_handler);
4604 priv->keys_changed_handler = 0;
4608 g_signal_handlers_disconnect_by_func (priv->screen,
4609 gtk_window_on_composited_changed, window);
4611 g_free (priv->startup_id);
4613 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4617 gtk_window_show (GtkWidget *widget)
4619 GtkWindow *window = GTK_WINDOW (widget);
4620 GtkWindowPrivate *priv = window->priv;
4621 GtkContainer *container = GTK_CONTAINER (window);
4622 gboolean need_resize;
4624 _gtk_widget_set_visible_flag (widget, TRUE);
4626 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4627 _gtk_container_set_need_resize (container, FALSE);
4631 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4632 GtkAllocation allocation = { 0, 0 };
4633 GdkRectangle configure_request;
4634 GdkGeometry new_geometry;
4636 gboolean was_realized;
4638 /* We are going to go ahead and perform this configure request
4639 * and then emulate a configure notify by going ahead and
4640 * doing a size allocate. Sort of a synchronous
4641 * mini-copy of gtk_window_move_resize() here.
4643 gtk_window_compute_configure_request (window,
4648 /* We update this because we are going to go ahead
4649 * and gdk_window_resize() below, rather than
4652 info->last.configure_request.width = configure_request.width;
4653 info->last.configure_request.height = configure_request.height;
4655 /* and allocate the window - this is normally done
4656 * in move_resize in response to configure notify
4658 allocation.width = configure_request.width;
4659 allocation.height = configure_request.height;
4660 gtk_widget_size_allocate (widget, &allocation);
4662 /* Then we guarantee we have a realize */
4663 was_realized = FALSE;
4664 if (!gtk_widget_get_realized (widget))
4666 gtk_widget_realize (widget);
4667 was_realized = TRUE;
4670 /* We only send configure request if we didn't just finish
4671 * creating the window; if we just created the window
4672 * then we created it with widget->allocation anyhow.
4675 gdk_window_move_resize (gtk_widget_get_window (widget),
4676 configure_request.x,
4677 configure_request.y,
4678 configure_request.width,
4679 configure_request.height);
4682 gtk_container_check_resize (container);
4684 gtk_widget_map (widget);
4686 /* Try to make sure that we have some focused widget
4688 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4689 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4692 gtk_grab_add (widget);
4696 gtk_window_hide (GtkWidget *widget)
4698 GtkWindow *window = GTK_WINDOW (widget);
4699 GtkWindowPrivate *priv = window->priv;
4701 _gtk_widget_set_visible_flag (widget, FALSE);
4702 gtk_widget_unmap (widget);
4705 gtk_grab_remove (widget);
4709 gtk_window_map (GtkWidget *widget)
4712 GtkWindow *window = GTK_WINDOW (widget);
4713 GtkWindowPrivate *priv = window->priv;
4714 GdkWindow *toplevel;
4715 GdkWindow *gdk_window;
4716 gboolean auto_mnemonics;
4718 gdk_window = gtk_widget_get_window (widget);
4720 gtk_widget_set_mapped (widget, TRUE);
4722 child = gtk_bin_get_child (&(window->bin));
4724 gtk_widget_get_visible (child) &&
4725 !gtk_widget_get_mapped (child))
4726 gtk_widget_map (child);
4729 toplevel = priv->frame;
4731 toplevel = gdk_window;
4733 if (priv->maximize_initially)
4734 gdk_window_maximize (toplevel);
4736 gdk_window_unmaximize (toplevel);
4738 if (priv->stick_initially)
4739 gdk_window_stick (toplevel);
4741 gdk_window_unstick (toplevel);
4743 if (priv->iconify_initially)
4744 gdk_window_iconify (toplevel);
4746 gdk_window_deiconify (toplevel);
4748 if (priv->fullscreen_initially)
4749 gdk_window_fullscreen (toplevel);
4751 gdk_window_unfullscreen (toplevel);
4753 gdk_window_set_keep_above (toplevel, priv->above_initially);
4755 gdk_window_set_keep_below (toplevel, priv->below_initially);
4757 /* No longer use the default settings */
4758 priv->need_default_size = FALSE;
4759 priv->need_default_position = FALSE;
4761 if (priv->reset_type_hint)
4763 /* We should only reset the type hint when the application
4764 * used gtk_window_set_type_hint() to change the hint.
4765 * Some applications use X directly to change the properties;
4766 * in that case, we shouldn't overwrite what they did.
4768 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4769 priv->reset_type_hint = FALSE;
4772 gdk_window_show (gdk_window);
4775 gdk_window_show (priv->frame);
4777 if (priv->grip_window)
4778 gdk_window_show (priv->grip_window);
4780 if (!disable_startup_notification)
4782 /* Do we have a custom startup-notification id? */
4783 if (priv->startup_id != NULL)
4785 /* Make sure we have a "real" id */
4786 if (!startup_id_is_fake (priv->startup_id))
4787 gdk_notify_startup_complete_with_id (priv->startup_id);
4789 g_free (priv->startup_id);
4790 priv->startup_id = NULL;
4792 else if (!sent_startup_notification)
4794 sent_startup_notification = TRUE;
4795 gdk_notify_startup_complete ();
4799 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4800 * (as in the case of popup menus), then hide mnemonics initially
4802 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4803 &auto_mnemonics, NULL);
4804 if (auto_mnemonics && !priv->mnemonics_visible_set)
4805 gtk_window_set_mnemonics_visible (window, FALSE);
4809 gtk_window_map_event (GtkWidget *widget,
4812 if (!gtk_widget_get_mapped (widget))
4814 /* we should be be unmapped, but are getting a MapEvent, this may happen
4815 * to toplevel XWindows if mapping was intercepted by a window manager
4816 * and an unmap request occoured while the MapRequestEvent was still
4817 * being handled. we work around this situaiton here by re-requesting
4818 * the window being unmapped. more details can be found in:
4819 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4821 gdk_window_hide (gtk_widget_get_window (widget));
4827 gtk_window_unmap (GtkWidget *widget)
4829 GtkWindow *window = GTK_WINDOW (widget);
4830 GtkWindowPrivate *priv = window->priv;
4831 GtkWindowGeometryInfo *info;
4832 GdkWindow *gdk_window;
4833 GdkWindowState state;
4835 gdk_window = gtk_widget_get_window (widget);
4837 gtk_widget_set_mapped (widget, FALSE);
4839 gdk_window_withdraw (priv->frame);
4841 gdk_window_withdraw (gdk_window);
4843 priv->configure_request_count = 0;
4844 priv->configure_notify_received = FALSE;
4846 /* on unmap, we reset the default positioning of the window,
4847 * so it's placed again, but we don't reset the default
4848 * size of the window, so it's remembered.
4850 priv->need_default_position = TRUE;
4852 info = gtk_window_get_geometry_info (window, FALSE);
4855 info->initial_pos_set = FALSE;
4856 info->position_constraints_changed = FALSE;
4859 state = gdk_window_get_state (gdk_window);
4860 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4861 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4862 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4863 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4864 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4868 gtk_window_realize (GtkWidget *widget)
4870 GtkAllocation allocation;
4872 GdkWindow *parent_window;
4873 GdkWindow *gdk_window;
4874 GdkWindowAttr attributes;
4875 gint attributes_mask;
4876 GtkWindowPrivate *priv;
4877 GtkStyleContext *context;
4879 window = GTK_WINDOW (widget);
4880 priv = window->priv;
4882 gtk_widget_get_allocation (widget, &allocation);
4884 /* ensure widget tree is properly size allocated */
4885 if (allocation.x == -1 &&
4886 allocation.y == -1 &&
4887 allocation.width == 1 &&
4888 allocation.height == 1)
4890 GtkRequisition requisition;
4894 allocation.width = 200;
4895 allocation.height = 200;
4897 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4898 if (requisition.width || requisition.height)
4900 /* non-empty window */
4901 allocation.width = requisition.width;
4902 allocation.height = requisition.height;
4904 gtk_widget_size_allocate (widget, &allocation);
4906 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4908 g_return_if_fail (!gtk_widget_get_realized (widget));
4911 gtk_widget_set_realized (widget, TRUE);
4915 case GTK_WINDOW_TOPLEVEL:
4916 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4918 case GTK_WINDOW_POPUP:
4919 attributes.window_type = GDK_WINDOW_TEMP;
4922 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4926 attributes.title = priv->title;
4927 attributes.wmclass_name = priv->wmclass_name;
4928 attributes.wmclass_class = priv->wmclass_class;
4929 attributes.wclass = GDK_INPUT_OUTPUT;
4930 attributes.visual = gtk_widget_get_visual (widget);
4932 if (priv->has_frame)
4934 gtk_widget_get_allocation (widget, &allocation);
4935 attributes.width = allocation.width + priv->frame_left + priv->frame_right;
4936 attributes.height = allocation.height + priv->frame_top + priv->frame_bottom;
4937 attributes.event_mask = (GDK_EXPOSURE_MASK |
4938 GDK_KEY_PRESS_MASK |
4939 GDK_ENTER_NOTIFY_MASK |
4940 GDK_LEAVE_NOTIFY_MASK |
4941 GDK_FOCUS_CHANGE_MASK |
4942 GDK_STRUCTURE_MASK |
4943 GDK_BUTTON_MOTION_MASK |
4944 GDK_POINTER_MOTION_HINT_MASK |
4945 GDK_BUTTON_PRESS_MASK |
4946 GDK_BUTTON_RELEASE_MASK);
4948 attributes_mask = GDK_WA_VISUAL;
4950 priv->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4951 &attributes, attributes_mask);
4953 if (priv->opacity_set)
4954 gdk_window_set_opacity (priv->frame, priv->opacity);
4956 gdk_window_set_user_data (priv->frame, widget);
4958 attributes.window_type = GDK_WINDOW_CHILD;
4959 attributes.x = priv->frame_left;
4960 attributes.y = priv->frame_top;
4962 attributes_mask = GDK_WA_X | GDK_WA_Y;
4964 parent_window = priv->frame;
4966 g_signal_connect (window,
4968 G_CALLBACK (gtk_window_event),
4973 attributes_mask = 0;
4974 parent_window = gtk_widget_get_root_window (widget);
4977 gtk_widget_get_allocation (widget, &allocation);
4978 attributes.width = allocation.width;
4979 attributes.height = allocation.height;
4980 attributes.event_mask = gtk_widget_get_events (widget);
4981 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4982 GDK_KEY_PRESS_MASK |
4983 GDK_KEY_RELEASE_MASK |
4984 GDK_ENTER_NOTIFY_MASK |
4985 GDK_LEAVE_NOTIFY_MASK |
4986 GDK_FOCUS_CHANGE_MASK |
4987 GDK_STRUCTURE_MASK);
4988 attributes.type_hint = priv->type_hint;
4990 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4991 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4992 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4994 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4995 gtk_widget_set_window (widget, gdk_window);
4997 if (!priv->has_frame && priv->opacity_set)
4998 gdk_window_set_opacity (gdk_window, priv->opacity);
5000 gdk_window_enable_synchronized_configure (gdk_window);
5002 gdk_window_set_user_data (gdk_window, window);
5004 gtk_widget_style_attach (widget);
5005 context = gtk_widget_get_style_context (widget);
5007 gtk_style_context_set_background (context, gdk_window);
5009 gtk_style_context_set_background (context, priv->frame);
5011 if (priv->transient_parent &&
5012 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5013 gdk_window_set_transient_for (gdk_window,
5014 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5017 gdk_window_set_role (gdk_window, priv->wm_role);
5019 if (!priv->decorated)
5020 gdk_window_set_decorations (gdk_window, 0);
5022 if (!priv->deletable)
5023 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5025 if (gtk_window_get_skip_pager_hint (window))
5026 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5028 if (gtk_window_get_skip_taskbar_hint (window))
5029 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5031 if (gtk_window_get_accept_focus (window))
5032 gdk_window_set_accept_focus (gdk_window, TRUE);
5034 gdk_window_set_accept_focus (gdk_window, FALSE);
5036 if (gtk_window_get_focus_on_map (window))
5037 gdk_window_set_focus_on_map (gdk_window, TRUE);
5039 gdk_window_set_focus_on_map (gdk_window, FALSE);
5042 gdk_window_set_modal_hint (gdk_window, TRUE);
5044 gdk_window_set_modal_hint (gdk_window, FALSE);
5046 if (priv->startup_id)
5048 #ifdef GDK_WINDOWING_X11
5049 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5050 if (timestamp != GDK_CURRENT_TIME)
5051 gdk_x11_window_set_user_time (gdk_window, timestamp);
5053 if (!startup_id_is_fake (priv->startup_id))
5054 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5058 gtk_window_realize_icon (window);
5060 if (priv->has_resize_grip)
5061 resize_grip_create_window (window);
5065 gtk_window_unrealize (GtkWidget *widget)
5067 GtkWindow *window = GTK_WINDOW (widget);
5068 GtkWindowPrivate *priv = window->priv;
5069 GtkWindowGeometryInfo *info;
5071 /* On unrealize, we reset the size of the window such
5072 * that we will re-apply the default sizing stuff
5073 * next time we show the window.
5075 * Default positioning is reset on unmap, instead of unrealize.
5077 priv->need_default_size = TRUE;
5078 info = gtk_window_get_geometry_info (window, FALSE);
5081 info->resize_width = -1;
5082 info->resize_height = -1;
5083 info->last.configure_request.x = 0;
5084 info->last.configure_request.y = 0;
5085 info->last.configure_request.width = -1;
5086 info->last.configure_request.height = -1;
5087 /* be sure we reset geom hints on re-realize */
5088 info->last.flags = 0;
5093 gdk_window_set_user_data (priv->frame, NULL);
5094 gdk_window_destroy (priv->frame);
5099 gtk_window_unrealize_icon (window);
5101 if (priv->grip_window != NULL)
5102 resize_grip_destroy_window (window);
5104 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5107 static GtkJunctionSides
5108 get_grip_junction (GtkWidget *widget)
5110 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5111 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5113 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5117 get_drag_edge (GtkWidget *widget,
5118 GdkWindowEdge *edge)
5120 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5121 gboolean hresizable;
5122 gboolean vresizable;
5123 GtkTextDirection dir;
5124 GtkWindowGeometryInfo *info;
5129 info = priv->geometry_info;
5132 GdkWindowHints flags = info->last.flags;
5133 GdkGeometry *geometry = &info->last.geometry;
5135 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5137 hresizable = geometry->min_width < geometry->max_width;
5138 vresizable = geometry->min_height < geometry->max_height;
5142 dir = gtk_widget_get_direction (widget);
5144 if (hresizable && vresizable)
5145 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5146 else if (hresizable)
5147 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5148 else if (vresizable)
5149 *edge = GDK_WINDOW_EDGE_SOUTH;
5157 set_grip_cursor (GtkWindow *window)
5159 GtkWidget *widget = GTK_WIDGET (window);
5160 GtkWindowPrivate *priv = window->priv;
5162 if (priv->grip_window == NULL)
5165 if (gtk_widget_is_sensitive (widget))
5168 GdkDisplay *display;
5169 GdkCursorType cursor_type;
5172 cursor_type = GDK_LEFT_PTR;
5174 if (get_drag_edge (widget, &edge))
5178 case GDK_WINDOW_EDGE_EAST:
5179 cursor_type = GDK_RIGHT_SIDE;
5181 case GDK_WINDOW_EDGE_SOUTH_EAST:
5182 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5184 case GDK_WINDOW_EDGE_SOUTH:
5185 cursor_type = GDK_BOTTOM_SIDE;
5187 case GDK_WINDOW_EDGE_SOUTH_WEST:
5188 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5190 case GDK_WINDOW_EDGE_WEST:
5191 cursor_type = GDK_LEFT_SIDE;
5197 display = gtk_widget_get_display (widget);
5198 cursor = gdk_cursor_new_for_display (display, cursor_type);
5199 gdk_window_set_cursor (priv->grip_window, cursor);
5200 gdk_cursor_unref (cursor);
5203 gdk_window_set_cursor (priv->grip_window, NULL);
5207 set_grip_shape (GtkWindow *window)
5209 GtkWindowPrivate *priv = window->priv;
5210 cairo_region_t *region;
5211 cairo_surface_t *surface;
5213 double width, height;
5215 if (priv->grip_window == NULL)
5218 width = gdk_window_get_width (priv->grip_window);
5219 height = gdk_window_get_height (priv->grip_window);
5220 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5222 cr = cairo_create (surface);
5223 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5225 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5226 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5228 cairo_move_to (cr, width, 0.0);
5229 cairo_line_to (cr, width, height);
5230 cairo_line_to (cr, 0.0, height);
5234 cairo_move_to (cr, 0.0, 0.0);
5235 cairo_line_to (cr, width, height);
5236 cairo_line_to (cr, 0.0, height);
5238 cairo_close_path (cr);
5241 region = gdk_cairo_region_create_from_surface (surface);
5242 cairo_surface_destroy (surface);
5244 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5245 cairo_region_destroy (region);
5249 set_grip_position (GtkWindow *window)
5251 GtkWindowPrivate *priv = window->priv;
5254 if (priv->grip_window == NULL)
5257 gtk_window_get_resize_grip_area (window, &rect);
5258 gdk_window_raise (priv->grip_window);
5259 gdk_window_move_resize (priv->grip_window,
5261 rect.width, rect.height);
5265 gtk_window_size_allocate (GtkWidget *widget,
5266 GtkAllocation *allocation)
5268 GtkWindow *window = GTK_WINDOW (widget);
5269 GtkWindowPrivate *priv = window->priv;
5270 GtkAllocation child_allocation;
5274 gtk_widget_set_allocation (widget, allocation);
5276 child = gtk_bin_get_child (&(window->bin));
5277 if (child && gtk_widget_get_visible (child))
5279 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5280 child_allocation.x = border_width;
5281 child_allocation.y = border_width;
5282 child_allocation.width =
5283 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5284 child_allocation.height =
5285 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5287 gtk_widget_size_allocate (child, &child_allocation);
5290 if (gtk_widget_get_realized (widget))
5293 gdk_window_resize (priv->frame,
5294 allocation->width + priv->frame_left + priv->frame_right,
5295 allocation->height + priv->frame_top + priv->frame_bottom);
5296 update_grip_visibility (window);
5297 set_grip_position (window);
5302 gtk_window_event (GtkWidget *widget, GdkEvent *event)
5304 GtkWindow *window = GTK_WINDOW (widget);
5305 GtkWindowPrivate *priv = window->priv;
5306 gboolean return_val;
5308 if (priv->frame && (event->any.window == priv->frame))
5310 if ((event->type != GDK_KEY_PRESS) &&
5311 (event->type != GDK_KEY_RELEASE) &&
5312 (event->type != GDK_FOCUS_CHANGE))
5314 g_signal_stop_emission_by_name (widget, "event");
5316 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
5321 g_object_unref (event->any.window);
5322 event->any.window = g_object_ref (gtk_widget_get_window (widget));
5330 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
5332 GtkWindowPrivate *priv = window->priv;
5333 GdkEventConfigure *configure_event;
5336 switch (event->type)
5339 configure_event = (GdkEventConfigure *)event;
5341 /* Invalidate the decorations */
5344 rect.width = configure_event->width;
5345 rect.height = configure_event->height;
5347 gdk_window_invalidate_rect (priv->frame, &rect, FALSE);
5349 /* Pass on the (modified) configure event */
5350 configure_event->width -= priv->frame_left + priv->frame_right;
5351 configure_event->height -= priv->frame_top + priv->frame_bottom;
5352 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5361 gtk_window_configure_event (GtkWidget *widget,
5362 GdkEventConfigure *event)
5364 GtkAllocation allocation;
5365 GtkWindow *window = GTK_WINDOW (widget);
5366 GtkWindowPrivate *priv = window->priv;
5367 gboolean expected_reply = priv->configure_request_count > 0;
5369 /* priv->configure_request_count incremented for each
5370 * configure request, and decremented to a min of 0 for
5371 * each configure notify.
5373 * All it means is that we know we will get at least
5374 * priv->configure_request_count more configure notifies.
5375 * We could get more configure notifies than that; some
5376 * of the configure notifies we get may be unrelated to
5377 * the configure requests. But we will get at least
5378 * priv->configure_request_count notifies.
5381 if (priv->configure_request_count > 0)
5383 priv->configure_request_count -= 1;
5384 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5387 /* As an optimization, we avoid a resize when possible.
5389 * The only times we can avoid a resize are:
5390 * - we know only the position changed, not the size
5391 * - we know we have made more requests and so will get more
5392 * notifies and can wait to resize when we get them
5394 gtk_widget_get_allocation (widget, &allocation);
5395 if (!expected_reply &&
5396 (allocation.width == event->width &&
5397 allocation.height == event->height))
5399 gdk_window_configure_finished (gtk_widget_get_window (widget));
5404 * If we do need to resize, we do that by:
5405 * - filling in widget->allocation with the new size
5406 * - setting configure_notify_received to TRUE
5407 * for use in gtk_window_move_resize()
5408 * - queueing a resize, leading to invocation of
5409 * gtk_window_move_resize() in an idle handler
5413 priv->configure_notify_received = TRUE;
5415 allocation.width = event->width;
5416 allocation.height = event->height;
5417 gtk_widget_set_allocation (widget, &allocation);
5419 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5421 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5427 gtk_window_state_event (GtkWidget *widget,
5428 GdkEventWindowState *event)
5430 update_grip_visibility (GTK_WINDOW (widget));
5436 gtk_window_direction_changed (GtkWidget *widget,
5437 GtkTextDirection prev_dir)
5439 GtkWindow *window = GTK_WINDOW (widget);
5441 set_grip_cursor (window);
5442 set_grip_position (window);
5443 set_grip_shape (window);
5447 gtk_window_state_changed (GtkWidget *widget,
5448 GtkStateType previous_state)
5450 GtkWindow *window = GTK_WINDOW (widget);
5452 update_grip_visibility (window);
5456 gtk_window_style_updated (GtkWidget *widget)
5458 GtkWindow *window = GTK_WINDOW (widget);
5459 GtkWindowPrivate *priv = window->priv;
5462 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5464 gdk_window_move_resize (priv->grip_window,
5466 rect.width, rect.height);
5468 set_grip_shape (window);
5469 gtk_widget_queue_resize (widget);
5474 resize_grip_create_window (GtkWindow *window)
5477 GtkWindowPrivate *priv;
5478 GdkWindowAttr attributes;
5479 gint attributes_mask;
5482 priv = window->priv;
5483 widget = GTK_WIDGET (window);
5485 g_return_if_fail (gtk_widget_get_realized (widget));
5486 g_return_if_fail (priv->grip_window == NULL);
5488 gtk_window_get_resize_grip_area (window, &rect);
5490 attributes.x = rect.x;
5491 attributes.y = rect.y;
5492 attributes.width = rect.width;
5493 attributes.height = rect.height;
5494 attributes.window_type = GDK_WINDOW_CHILD;
5495 attributes.wclass = GDK_INPUT_OUTPUT;
5496 attributes.event_mask = gtk_widget_get_events (widget) |
5498 GDK_BUTTON_PRESS_MASK;
5500 attributes_mask = GDK_WA_X | GDK_WA_Y;
5502 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5506 gdk_window_set_user_data (priv->grip_window, widget);
5508 gdk_window_raise (priv->grip_window);
5510 set_grip_shape (window);
5511 update_grip_visibility (window);
5515 resize_grip_destroy_window (GtkWindow *window)
5517 GtkWindowPrivate *priv = window->priv;
5519 gdk_window_set_user_data (priv->grip_window, NULL);
5520 gdk_window_destroy (priv->grip_window);
5521 priv->grip_window = NULL;
5522 update_grip_visibility (window);
5526 * gtk_window_set_has_resize_grip:
5527 * @window: a #GtkWindow
5528 * @value: %TRUE to allow a resize grip
5530 * Sets whether @window has a corner resize grip.
5532 * Note that the resize grip is only shown if the window
5533 * is actually resizable and not maximized. Use
5534 * gtk_window_resize_grip_is_visible() to find out if the
5535 * resize grip is currently shown.
5540 gtk_window_set_has_resize_grip (GtkWindow *window,
5543 GtkWidget *widget = GTK_WIDGET (window);
5544 GtkWindowPrivate *priv = window->priv;
5546 value = value != FALSE;
5548 if (value != priv->has_resize_grip)
5550 priv->has_resize_grip = value;
5551 gtk_widget_queue_draw (widget);
5553 if (gtk_widget_get_realized (widget))
5555 if (priv->has_resize_grip && priv->grip_window == NULL)
5556 resize_grip_create_window (window);
5557 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5558 resize_grip_destroy_window (window);
5561 g_object_notify (G_OBJECT (window), "has-resize-grip");
5566 update_grip_visibility (GtkWindow *window)
5568 GtkWindowPrivate *priv = window->priv;
5571 val = gtk_window_resize_grip_is_visible (window);
5573 if (priv->grip_window != NULL)
5577 gdk_window_show (priv->grip_window);
5578 set_grip_cursor (window);
5582 gdk_window_hide (priv->grip_window);
5586 if (priv->resize_grip_visible != val)
5588 priv->resize_grip_visible = val;
5590 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5595 * gtk_window_resize_grip_is_visible:
5596 * @window: a #GtkWindow
5598 * Determines whether a resize grip is visible for the specified window.
5600 * Returns %TRUE if a resize grip exists and is visible.
5605 gtk_window_resize_grip_is_visible (GtkWindow *window)
5608 GtkWindowPrivate *priv;
5611 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5613 priv = window->priv;
5614 widget = GTK_WIDGET (window);
5616 if (priv->type == GTK_WINDOW_POPUP)
5619 if (!priv->resizable)
5622 if (gtk_widget_get_realized (widget))
5624 GdkWindowState state;
5626 state = gdk_window_get_state (gtk_widget_get_window (widget));
5628 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5632 if (!get_drag_edge (widget, &edge))
5635 return window->priv->has_resize_grip;
5639 * gtk_window_get_has_resize_grip:
5640 * @window: a #GtkWindow
5642 * Determines whether the window may have a resize grip.
5644 * Returns: %TRUE if the window has a resize grip.
5649 gtk_window_get_has_resize_grip (GtkWindow *window)
5651 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5653 return window->priv->has_resize_grip;
5657 * gtk_window_get_resize_grip_area:
5658 * @window: a #GtkWindow
5659 * @rect: a pointer to a #GdkRectangle which we should store the
5662 * If a window has a resize grip, this will retrieve the grip
5663 * position, width and height into the specified #GdkRectangle.
5665 * Returns: %TRUE if the resize grip's area was retrieved.
5670 gtk_window_get_resize_grip_area (GtkWindow *window,
5673 GtkWidget *widget = GTK_WIDGET (window);
5674 GtkAllocation allocation;
5678 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5680 if (!window->priv->has_resize_grip)
5683 gtk_widget_get_allocation (widget, &allocation);
5685 gtk_widget_style_get (widget,
5686 "resize-grip-width", &grip_width,
5687 "resize-grip-height", &grip_height,
5690 if (grip_width > allocation.width)
5691 grip_width = allocation.width;
5693 if (grip_height > allocation.height)
5694 grip_height = allocation.height;
5696 rect->width = grip_width;
5697 rect->height = grip_height;
5698 rect->y = allocation.y + allocation.height - grip_height;
5700 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5701 rect->x = allocation.x + allocation.width - grip_width;
5703 rect->x = allocation.x;
5708 /* the accel_key and accel_mods fields of the key have to be setup
5709 * upon calling this function. it'll then return whether that key
5710 * is at all used as accelerator, and if so will OR in the
5711 * accel_flags member of the key.
5714 _gtk_window_query_nonaccels (GtkWindow *window,
5716 GdkModifierType accel_mods)
5718 GtkWindowPrivate *priv;
5720 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5722 priv = window->priv;
5724 /* movement keys are considered locked accels */
5727 static const guint bindings[] = {
5728 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,
5729 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,
5733 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5734 if (bindings[i] == accel_key)
5738 /* mnemonics are considered locked accels */
5739 if (accel_mods == priv->mnemonic_modifier)
5741 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5742 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5750 * gtk_window_propagate_key_event:
5751 * @window: a #GtkWindow
5752 * @event: a #GdkEventKey
5754 * Propagate a key press or release event to the focus widget and
5755 * up the focus container chain until a widget handles @event.
5756 * This is normally called by the default ::key_press_event and
5757 * ::key_release_event handlers for toplevel windows,
5758 * however in some cases it may be useful to call this directly when
5759 * overriding the standard key handling for a toplevel window.
5761 * Return value: %TRUE if a widget in the focus chain handled the event.
5766 gtk_window_propagate_key_event (GtkWindow *window,
5769 GtkWindowPrivate *priv;
5770 gboolean handled = FALSE;
5771 GtkWidget *widget, *focus;
5773 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5775 priv = window->priv;
5776 widget = GTK_WIDGET (window);
5778 focus = priv->focus_widget;
5780 g_object_ref (focus);
5783 focus && focus != widget &&
5784 gtk_widget_get_toplevel (focus) == widget)
5788 if (gtk_widget_is_sensitive (focus))
5789 handled = gtk_widget_event (focus, (GdkEvent*) event);
5791 parent = gtk_widget_get_parent (focus);
5793 g_object_ref (parent);
5795 g_object_unref (focus);
5801 g_object_unref (focus);
5807 gtk_window_key_press_event (GtkWidget *widget,
5810 GtkWindow *window = GTK_WINDOW (widget);
5811 gboolean handled = FALSE;
5813 /* handle mnemonics and accelerators */
5815 handled = gtk_window_activate_key (window, event);
5817 /* handle focus widget key events */
5819 handled = gtk_window_propagate_key_event (window, event);
5821 /* Chain up, invokes binding set */
5823 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5829 gtk_window_key_release_event (GtkWidget *widget,
5832 GtkWindow *window = GTK_WINDOW (widget);
5833 gboolean handled = FALSE;
5835 /* handle focus widget key events */
5837 handled = gtk_window_propagate_key_event (window, event);
5839 /* Chain up, invokes binding set */
5841 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5847 gtk_window_button_press_event (GtkWidget *widget,
5848 GdkEventButton *event)
5850 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5853 if (event->window == priv->grip_window)
5855 if (get_drag_edge (widget, &edge))
5856 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5870 gtk_window_real_activate_default (GtkWindow *window)
5872 gtk_window_activate_default (window);
5876 gtk_window_real_activate_focus (GtkWindow *window)
5878 gtk_window_activate_focus (window);
5882 gtk_window_enter_notify_event (GtkWidget *widget,
5883 GdkEventCrossing *event)
5889 gtk_window_leave_notify_event (GtkWidget *widget,
5890 GdkEventCrossing *event)
5896 do_focus_change (GtkWidget *widget,
5900 GdkDeviceManager *device_manager;
5903 g_object_ref (widget);
5905 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5906 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5907 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5908 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5910 for (d = devices; d; d = d->next)
5912 GdkDevice *dev = d->data;
5915 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5918 /* Skip non-master keyboards that haven't
5919 * selected for events from this window
5921 window = gtk_widget_get_window (widget);
5922 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5923 window && !gdk_window_get_device_events (window, dev))
5926 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5928 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5929 fevent->focus_change.window = window;
5931 g_object_ref (window);
5932 fevent->focus_change.in = in;
5933 gdk_event_set_device (fevent, dev);
5935 gtk_widget_send_focus_change (widget, fevent);
5937 gdk_event_free (fevent);
5940 g_list_free (devices);
5941 g_object_unref (widget);
5945 gtk_window_focus_in_event (GtkWidget *widget,
5946 GdkEventFocus *event)
5948 GtkWindow *window = GTK_WINDOW (widget);
5950 /* It appears spurious focus in events can occur when
5951 * the window is hidden. So we'll just check to see if
5952 * the window is visible before actually handling the
5955 if (gtk_widget_get_visible (widget))
5957 _gtk_window_set_has_toplevel_focus (window, TRUE);
5958 _gtk_window_set_is_active (window, TRUE);
5965 gtk_window_focus_out_event (GtkWidget *widget,
5966 GdkEventFocus *event)
5968 GtkWindow *window = GTK_WINDOW (widget);
5969 gboolean auto_mnemonics;
5971 _gtk_window_set_has_toplevel_focus (window, FALSE);
5972 _gtk_window_set_is_active (window, FALSE);
5974 /* set the mnemonic-visible property to false */
5975 g_object_get (gtk_widget_get_settings (widget),
5976 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5978 gtk_window_set_mnemonics_visible (window, FALSE);
5983 static GdkAtom atom_rcfiles = GDK_NONE;
5984 static GdkAtom atom_iconthemes = GDK_NONE;
5987 send_client_message_to_embedded_windows (GtkWidget *widget,
5988 GdkAtom message_type)
5990 GList *embedded_windows;
5992 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5993 if (embedded_windows)
5995 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5998 for (i = 0; i < 5; i++)
5999 send_event->client.data.l[i] = 0;
6000 send_event->client.data_format = 32;
6001 send_event->client.message_type = message_type;
6003 while (embedded_windows)
6005 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
6006 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
6007 embedded_windows = embedded_windows->next;
6010 gdk_event_free (send_event);
6015 gtk_window_client_event (GtkWidget *widget,
6016 GdkEventClient *event)
6020 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
6021 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
6024 if (event->message_type == atom_rcfiles)
6026 send_client_message_to_embedded_windows (widget, atom_rcfiles);
6027 gtk_style_context_reset_widgets (gtk_widget_get_screen (widget));
6030 if (event->message_type == atom_iconthemes)
6032 send_client_message_to_embedded_windows (widget, atom_iconthemes);
6033 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
6040 gtk_window_check_resize (GtkContainer *container)
6042 if (gtk_widget_get_visible (GTK_WIDGET (container)))
6043 gtk_window_move_resize (GTK_WINDOW (container));
6047 gtk_window_focus (GtkWidget *widget,
6048 GtkDirectionType direction)
6050 GtkWindowPrivate *priv;
6053 GtkContainer *container;
6055 GtkWidget *old_focus_child;
6058 container = GTK_CONTAINER (widget);
6059 window = GTK_WINDOW (widget);
6060 priv = window->priv;
6061 bin = GTK_BIN (widget);
6063 old_focus_child = gtk_container_get_focus_child (container);
6065 /* We need a special implementation here to deal properly with wrapping
6066 * around in the tab chain without the danger of going into an
6069 if (old_focus_child)
6071 if (gtk_widget_child_focus (old_focus_child, direction))
6075 if (priv->focus_widget)
6077 if (direction == GTK_DIR_LEFT ||
6078 direction == GTK_DIR_RIGHT ||
6079 direction == GTK_DIR_UP ||
6080 direction == GTK_DIR_DOWN)
6085 /* Wrapped off the end, clear the focus setting for the toplpevel */
6086 parent = gtk_widget_get_parent (priv->focus_widget);
6089 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6090 parent = gtk_widget_get_parent (parent);
6093 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6096 /* Now try to focus the first widget in the window */
6097 child = gtk_bin_get_child (bin);
6100 if (gtk_widget_child_focus (child, direction))
6108 gtk_window_move_focus (GtkWidget *widget,
6109 GtkDirectionType dir)
6111 gtk_widget_child_focus (widget, dir);
6113 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6114 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6118 gtk_window_real_set_focus (GtkWindow *window,
6121 GtkWindowPrivate *priv = window->priv;
6122 GtkWidget *old_focus = priv->focus_widget;
6123 gboolean had_default = FALSE;
6124 gboolean focus_had_default = FALSE;
6125 gboolean old_focus_had_default = FALSE;
6129 g_object_ref (old_focus);
6130 g_object_freeze_notify (G_OBJECT (old_focus));
6131 old_focus_had_default = gtk_widget_has_default (old_focus);
6135 g_object_ref (focus);
6136 g_object_freeze_notify (G_OBJECT (focus));
6137 focus_had_default = gtk_widget_has_default (focus);
6140 if (priv->default_widget)
6141 had_default = gtk_widget_has_default (priv->default_widget);
6143 if (priv->focus_widget)
6145 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6146 (priv->focus_widget != priv->default_widget))
6148 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6149 gtk_widget_queue_draw (priv->focus_widget);
6151 if (priv->default_widget)
6152 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6155 priv->focus_widget = NULL;
6157 if (priv->has_focus)
6158 do_focus_change (old_focus, FALSE);
6160 g_object_notify (G_OBJECT (old_focus), "is-focus");
6163 /* The above notifications may have set a new focus widget,
6164 * if so, we don't want to override it.
6166 if (focus && !priv->focus_widget)
6168 priv->focus_widget = focus;
6170 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6171 (priv->focus_widget != priv->default_widget))
6173 if (gtk_widget_get_can_default (priv->focus_widget))
6174 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6176 if (priv->default_widget)
6177 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6180 if (priv->has_focus)
6181 do_focus_change (priv->focus_widget, TRUE);
6183 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6186 /* If the default widget changed, a redraw will have been queued
6187 * on the old and new default widgets by gtk_window_set_default(), so
6188 * we only have to worry about the case where it didn't change.
6189 * We'll sometimes queue a draw twice on the new widget but that
6192 if (priv->default_widget &&
6193 (had_default != gtk_widget_has_default (priv->default_widget)))
6194 gtk_widget_queue_draw (priv->default_widget);
6198 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6199 gtk_widget_queue_draw (old_focus);
6201 g_object_thaw_notify (G_OBJECT (old_focus));
6202 g_object_unref (old_focus);
6206 if (focus_had_default != gtk_widget_has_default (focus))
6207 gtk_widget_queue_draw (focus);
6209 g_object_thaw_notify (G_OBJECT (focus));
6210 g_object_unref (focus);
6216 gtk_window_get_preferred_width (GtkWidget *widget,
6224 window = GTK_WINDOW (widget);
6225 child = gtk_bin_get_child (GTK_BIN (window));
6227 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6228 *minimum_size = border_width * 2;
6229 *natural_size = border_width * 2;
6231 if (child && gtk_widget_get_visible (child))
6233 gint child_min, child_nat;
6234 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6236 *minimum_size += child_min;
6237 *natural_size += child_nat;
6242 gtk_window_get_preferred_height (GtkWidget *widget,
6250 window = GTK_WINDOW (widget);
6251 child = gtk_bin_get_child (GTK_BIN (window));
6253 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6254 *minimum_size = border_width * 2;
6255 *natural_size = border_width * 2;
6257 if (child && gtk_widget_get_visible (child))
6259 gint child_min, child_nat;
6260 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6262 *minimum_size += child_min;
6263 *natural_size += child_nat;
6269 * _gtk_window_unset_focus_and_default:
6270 * @window: a #GtkWindow
6271 * @widget: a widget inside of @window
6273 * Checks whether the focus and default widgets of @window are
6274 * @widget or a descendent of @widget, and if so, unset them.
6277 _gtk_window_unset_focus_and_default (GtkWindow *window,
6281 GtkWindowPrivate *priv = window->priv;
6285 g_object_ref (window);
6286 g_object_ref (widget);
6288 parent = gtk_widget_get_parent (widget);
6289 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6291 child = priv->focus_widget;
6293 while (child && child != widget)
6294 child = gtk_widget_get_parent (child);
6296 if (child == widget)
6297 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6300 child = priv->default_widget;
6302 while (child && child != widget)
6303 child = gtk_widget_get_parent (child);
6305 if (child == widget)
6306 gtk_window_set_default (window, NULL);
6308 g_object_unref (widget);
6309 g_object_unref (window);
6312 /*********************************
6313 * Functions related to resizing *
6314 *********************************/
6317 geometry_size_to_pixels (GdkGeometry *geometry,
6322 gint base_width = 0;
6323 gint base_height = 0;
6325 gint min_height = 0;
6327 gint height_inc = 1;
6329 if (flags & GDK_HINT_BASE_SIZE)
6331 base_width = geometry->base_width;
6332 base_height = geometry->base_height;
6334 if (flags & GDK_HINT_MIN_SIZE)
6336 min_width = geometry->min_width;
6337 min_height = geometry->min_height;
6339 if (flags & GDK_HINT_RESIZE_INC)
6341 width_inc = geometry->width_inc;
6342 height_inc = geometry->height_inc;
6346 *width = MAX (*width * width_inc + base_width, min_width);
6348 *height = MAX (*height * height_inc + base_height, min_height);
6351 /* This function doesn't constrain to geometry hints */
6353 gtk_window_compute_configure_request_size (GtkWindow *window,
6354 GdkGeometry *geometry,
6359 GtkWindowPrivate *priv = window->priv;
6360 GtkRequisition requisition;
6361 GtkWindowGeometryInfo *info;
6365 * - we've done a size request
6368 widget = GTK_WIDGET (window);
6370 info = gtk_window_get_geometry_info (window, FALSE);
6372 if (priv->need_default_size)
6374 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6376 /* Default to requisition */
6377 *width = requisition.width;
6378 *height = requisition.height;
6380 /* If window is empty so requests 0, default to random nonzero size */
6381 if (*width == 0 && *height == 0)
6387 /* Override requisition with default size */
6391 if (info->default_width > 0)
6392 *width = info->default_width;
6393 if (info->default_height > 0)
6394 *height = info->default_height;
6396 if (info->default_is_geometry)
6397 geometry_size_to_pixels (geometry, flags,
6398 info->default_width > 0 ? width : NULL,
6399 info->default_height > 0 ? height : NULL);
6404 GtkAllocation allocation;
6406 gtk_widget_get_allocation (widget, &allocation);
6408 /* Default to keeping current size */
6409 *width = allocation.width;
6410 *height = allocation.height;
6413 /* Override any size with gtk_window_resize() values */
6416 if (info->resize_width > 0)
6417 *width = info->resize_width;
6418 if (info->resize_height > 0)
6419 *height = info->resize_height;
6421 if (info->resize_is_geometry)
6422 geometry_size_to_pixels (geometry, flags,
6423 info->resize_width > 0 ? width : NULL,
6424 info->resize_height > 0 ? height : NULL);
6427 /* Don't ever request zero width or height, its not supported by
6428 gdk. The size allocation code will round it to 1 anyway but if
6429 we do it then the value returned from this function will is
6430 not comparable to the size allocation read from the GtkWindow. */
6431 *width = MAX (*width, 1);
6432 *height = MAX (*height, 1);
6435 static GtkWindowPosition
6436 get_effective_position (GtkWindow *window)
6438 GtkWindowPrivate *priv = window->priv;
6439 GtkWindowPosition pos = priv->position;
6441 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6442 (priv->transient_parent == NULL ||
6443 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6444 pos = GTK_WIN_POS_NONE;
6450 get_center_monitor_of_window (GtkWindow *window)
6452 /* We could try to sort out the relative positions of the monitors and
6453 * stuff, or we could just be losers and assume you have a row
6454 * or column of monitors.
6456 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6460 get_monitor_containing_pointer (GtkWindow *window)
6464 GdkScreen *window_screen;
6465 GdkScreen *pointer_screen;
6466 GdkDisplay *display;
6467 GdkDeviceManager *device_manager;
6470 window_screen = gtk_window_check_screen (window);
6471 display = gdk_screen_get_display (window_screen);
6472 device_manager = gdk_display_get_device_manager (display);
6473 pointer = gdk_device_manager_get_client_pointer (device_manager);
6475 gdk_display_get_device_state (display, pointer,
6479 if (pointer_screen == window_screen)
6480 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6488 center_window_on_monitor (GtkWindow *window,
6494 GdkRectangle monitor;
6497 monitor_num = get_monitor_containing_pointer (window);
6499 if (monitor_num == -1)
6500 monitor_num = get_center_monitor_of_window (window);
6502 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6503 monitor_num, &monitor);
6505 *x = (monitor.width - w) / 2 + monitor.x;
6506 *y = (monitor.height - h) / 2 + monitor.y;
6508 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6509 * and WM decorations.
6523 if (extent > clamp_extent)
6525 *base = clamp_base + clamp_extent/2 - extent/2;
6526 else if (*base < clamp_base)
6528 else if (*base + extent > clamp_base + clamp_extent)
6529 *base = clamp_base + clamp_extent - extent;
6533 clamp_window_to_rectangle (gint *x,
6537 const GdkRectangle *rect)
6539 #ifdef DEBUGGING_OUTPUT
6540 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);
6543 /* If it is too large, center it. If it fits on the monitor but is
6544 * partially outside, move it to the closest edge. Do this
6545 * separately in x and y directions.
6547 clamp (x, w, rect->x, rect->width);
6548 clamp (y, h, rect->y, rect->height);
6549 #ifdef DEBUGGING_OUTPUT
6550 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6556 gtk_window_compute_configure_request (GtkWindow *window,
6557 GdkRectangle *request,
6558 GdkGeometry *geometry,
6561 GtkWindowPrivate *priv = window->priv;
6562 GdkGeometry new_geometry;
6566 GtkWindowPosition pos;
6567 GtkWidget *parent_widget;
6568 GtkWindowGeometryInfo *info;
6572 widget = GTK_WIDGET (window);
6574 screen = gtk_window_check_screen (window);
6576 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6577 gtk_window_compute_configure_request_size (window,
6578 &new_geometry, new_flags,
6579 (guint *)&w, (guint *)&h);
6581 gtk_window_constrain_size (window,
6582 &new_geometry, new_flags,
6586 parent_widget = (GtkWidget*) priv->transient_parent;
6588 pos = get_effective_position (window);
6589 info = gtk_window_get_geometry_info (window, FALSE);
6591 /* by default, don't change position requested */
6594 x = info->last.configure_request.x;
6595 y = info->last.configure_request.y;
6604 if (priv->need_default_position)
6607 /* FIXME this all interrelates with window gravity.
6608 * For most of them I think we want to set GRAVITY_CENTER.
6610 * Not sure how to go about that.
6615 /* here we are only handling CENTER_ALWAYS
6616 * as it relates to default positioning,
6617 * where it's equivalent to simply CENTER
6619 case GTK_WIN_POS_CENTER_ALWAYS:
6620 case GTK_WIN_POS_CENTER:
6621 center_window_on_monitor (window, w, h, &x, &y);
6624 case GTK_WIN_POS_CENTER_ON_PARENT:
6626 GtkAllocation allocation;
6627 GdkWindow *gdk_window;
6629 GdkRectangle monitor;
6632 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6634 gdk_window = gtk_widget_get_window (parent_widget);
6636 if (gdk_window != NULL)
6637 monitor_num = gdk_screen_get_monitor_at_window (screen,
6642 gdk_window_get_origin (gdk_window,
6645 gtk_widget_get_allocation (parent_widget, &allocation);
6646 x = ox + (allocation.width - w) / 2;
6647 y = oy + (allocation.height - h) / 2;
6649 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6650 * WM decorations. If parent wasn't on a monitor, just
6653 if (monitor_num >= 0)
6655 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6656 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6661 case GTK_WIN_POS_MOUSE:
6663 gint screen_width = gdk_screen_get_width (screen);
6664 gint screen_height = gdk_screen_get_height (screen);
6666 GdkRectangle monitor;
6667 GdkDisplay *display;
6668 GdkDeviceManager *device_manager;
6670 GdkScreen *pointer_screen;
6673 display = gdk_screen_get_display (screen);
6674 device_manager = gdk_display_get_device_manager (display);
6675 pointer = gdk_device_manager_get_client_pointer (device_manager);
6677 gdk_display_get_device_state (display, pointer,
6681 if (pointer_screen == screen)
6682 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6688 x = CLAMP (x, 0, screen_width - w);
6689 y = CLAMP (y, 0, screen_height - h);
6691 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6692 * WM decorations. Don't try to figure out what's going
6693 * on if the mouse wasn't inside a monitor.
6695 if (monitor_num >= 0)
6697 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6698 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6706 } /* if (priv->need_default_position) */
6708 if (priv->need_default_position && info &&
6709 info->initial_pos_set)
6711 x = info->initial_x;
6712 y = info->initial_y;
6713 gtk_window_constrain_position (window, w, h, &x, &y);
6719 request->height = h;
6722 *geometry = new_geometry;
6728 gtk_window_constrain_position (GtkWindow *window,
6734 GtkWindowPrivate *priv = window->priv;
6736 /* See long comments in gtk_window_move_resize()
6737 * on when it's safe to call this function.
6739 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6741 gint center_x, center_y;
6743 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6751 gtk_window_move_resize (GtkWindow *window)
6755 * First we determine whether any information has changed that would
6756 * cause us to revise our last configure request. If we would send
6757 * a different configure request from last time, then
6758 * configure_request_size_changed = TRUE or
6759 * configure_request_pos_changed = TRUE. configure_request_size_changed
6760 * may be true due to new hints, a gtk_window_resize(), or whatever.
6761 * configure_request_pos_changed may be true due to gtk_window_set_position()
6762 * or gtk_window_move().
6764 * If the configure request has changed, we send off a new one. To
6765 * ensure GTK+ invariants are maintained (resize queue does what it
6766 * should), we go ahead and size_allocate the requested size in this
6769 * If the configure request has not changed, we don't ever resend
6770 * it, because it could mean fighting the user or window manager.
6773 * To prepare the configure request, we come up with a base size/pos:
6774 * - the one from gtk_window_move()/gtk_window_resize()
6775 * - else default_width, default_height if we haven't ever
6777 * - else the size request if we haven't ever been mapped,
6778 * as a substitute default size
6779 * - else the current size of the window, as received from
6780 * configure notifies (i.e. the current allocation)
6782 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6783 * the position request to be centered.
6785 GtkWindowPrivate *priv = window->priv;
6786 GtkAllocation allocation;
6788 GtkContainer *container;
6789 GtkWindowGeometryInfo *info;
6790 GdkGeometry new_geometry;
6791 GdkWindow *gdk_window;
6793 GdkRectangle new_request;
6794 gboolean configure_request_size_changed;
6795 gboolean configure_request_pos_changed;
6796 gboolean hints_changed; /* do we need to send these again */
6797 GtkWindowLastGeometryInfo saved_last_info;
6799 widget = GTK_WIDGET (window);
6800 gdk_window = gtk_widget_get_window (widget);
6801 container = GTK_CONTAINER (widget);
6802 info = gtk_window_get_geometry_info (window, TRUE);
6804 configure_request_size_changed = FALSE;
6805 configure_request_pos_changed = FALSE;
6807 gtk_window_compute_configure_request (window, &new_request,
6808 &new_geometry, &new_flags);
6810 /* This check implies the invariant that we never set info->last
6811 * without setting the hints and sending off a configure request.
6813 * If we change info->last without sending the request, we may
6816 if (info->last.configure_request.x != new_request.x ||
6817 info->last.configure_request.y != new_request.y)
6818 configure_request_pos_changed = TRUE;
6820 if ((info->last.configure_request.width != new_request.width ||
6821 info->last.configure_request.height != new_request.height))
6822 configure_request_size_changed = TRUE;
6824 hints_changed = FALSE;
6826 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6827 &new_geometry, new_flags))
6829 hints_changed = TRUE;
6832 /* Position Constraints
6833 * ====================
6835 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6836 * a default. The other POS_ values are used only when the
6837 * window is shown, not after that.
6839 * However, we can't implement a position constraint as
6840 * "anytime the window size changes, center the window"
6841 * because this may well end up fighting the WM or user. In
6842 * fact it gets in an infinite loop with at least one WM.
6844 * Basically, applications are in no way in a position to
6845 * constrain the position of a window, with one exception:
6846 * override redirect windows. (Really the intended purpose
6847 * of CENTER_ALWAYS anyhow, I would think.)
6849 * So the way we implement this "constraint" is to say that when WE
6850 * cause a move or resize, i.e. we make a configure request changing
6851 * window size, we recompute the CENTER_ALWAYS position to reflect
6852 * the new window size, and include it in our request. Also, if we
6853 * just turned on CENTER_ALWAYS we snap to center with a new
6854 * request. Otherwise, if we are just NOTIFIED of a move or resize
6855 * done by someone else e.g. the window manager, we do NOT send a
6856 * new configure request.
6858 * For override redirect windows, this works fine; all window
6859 * sizes are from our configure requests. For managed windows,
6860 * it is at least semi-sane, though who knows what the
6861 * app author is thinking.
6864 /* This condition should be kept in sync with the condition later on
6865 * that determines whether we send a configure request. i.e. we
6866 * should do this position constraining anytime we were going to
6867 * send a configure request anyhow, plus when constraints have
6870 if (configure_request_pos_changed ||
6871 configure_request_size_changed ||
6873 info->position_constraints_changed)
6875 /* We request the constrained position if:
6876 * - we were changing position, and need to clamp
6877 * the change to the constraint
6878 * - we're changing the size anyway
6879 * - set_position() was called to toggle CENTER_ALWAYS on
6882 gtk_window_constrain_position (window,
6888 /* Update whether we need to request a move */
6889 if (info->last.configure_request.x != new_request.x ||
6890 info->last.configure_request.y != new_request.y)
6891 configure_request_pos_changed = TRUE;
6893 configure_request_pos_changed = FALSE;
6897 if (priv->type == GTK_WINDOW_TOPLEVEL)
6899 int notify_x, notify_y;
6901 /* this is the position from the last configure notify */
6902 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6904 g_message ("--- %s ---\n"
6905 "last : %d,%d\t%d x %d\n"
6906 "this : %d,%d\t%d x %d\n"
6907 "alloc : %d,%d\t%d x %d\n"
6909 "resize: \t%d x %d\n"
6910 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6911 "configure_notify_received: %d\n"
6912 "configure_request_count: %d\n"
6913 "position_constraints_changed: %d\n",
6914 priv->title ? priv->title : "(no title)",
6915 info->last.configure_request.x,
6916 info->last.configure_request.y,
6917 info->last.configure_request.width,
6918 info->last.configure_request.height,
6924 widget->allocation.width,
6925 widget->allocation.height,
6926 widget->requisition.width,
6927 widget->requisition.height,
6929 info->resize_height,
6930 configure_request_pos_changed,
6931 configure_request_size_changed,
6933 priv->configure_notify_received,
6934 priv->configure_request_count,
6935 info->position_constraints_changed);
6939 saved_last_info = info->last;
6940 info->last.geometry = new_geometry;
6941 info->last.flags = new_flags;
6942 info->last.configure_request = new_request;
6944 /* need to set PPosition so the WM will look at our position,
6945 * but we don't want to count PPosition coming and going as a hints
6946 * change for future iterations. So we saved info->last prior to
6950 /* Also, if the initial position was explicitly set, then we always
6951 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6955 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6956 * this is an initial map
6959 if ((configure_request_pos_changed ||
6960 info->initial_pos_set ||
6961 (priv->need_default_position &&
6962 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6963 (new_flags & GDK_HINT_POS) == 0)
6965 new_flags |= GDK_HINT_POS;
6966 hints_changed = TRUE;
6969 /* Set hints if necessary
6972 gdk_window_set_geometry_hints (gdk_window,
6976 gtk_widget_get_allocation (widget, &allocation);
6978 /* handle resizing/moving and widget tree allocation
6980 if (priv->configure_notify_received)
6982 /* If we have received a configure event since
6983 * the last time in this function, we need to
6984 * accept our new size and size_allocate child widgets.
6985 * (see gtk_window_configure_event() for more details).
6987 * 1 or more configure notifies may have been received.
6988 * Also, configure_notify_received will only be TRUE
6989 * if all expected configure notifies have been received
6990 * (one per configure request), as an optimization.
6993 priv->configure_notify_received = FALSE;
6995 /* gtk_window_configure_event() filled in widget->allocation */
6996 gtk_widget_size_allocate (widget, &allocation);
6998 set_grip_position (window);
6999 update_grip_visibility (window);
7001 gdk_window_process_updates (gdk_window, TRUE);
7003 gdk_window_configure_finished (gdk_window);
7005 /* If the configure request changed, it means that
7007 * 1) coincidentally changed hints or widget properties
7008 * impacting the configure request before getting
7009 * a configure notify, or
7010 * 2) some broken widget is changing its size request
7011 * during size allocation, resulting in
7012 * a false appearance of changed configure request.
7014 * For 1), we could just go ahead and ask for the
7015 * new size right now, but doing that for 2)
7016 * might well be fighting the user (and can even
7017 * trigger a loop). Since we really don't want to
7018 * do that, we requeue a resize in hopes that
7019 * by the time it gets handled, the child has seen
7020 * the light and is willing to go along with the
7021 * new size. (this happens for the zvt widget, since
7022 * the size_allocate() above will have stored the
7023 * requisition corresponding to the new size in the
7026 * This doesn't buy us anything for 1), but it shouldn't
7027 * hurt us too badly, since it is what would have
7028 * happened if we had gotten the configure event before
7029 * the new size had been set.
7032 if (configure_request_size_changed ||
7033 configure_request_pos_changed)
7035 /* Don't change the recorded last info after all, because we
7036 * haven't actually updated to the new info yet - we decided
7037 * to postpone our configure request until later.
7039 info->last = saved_last_info;
7041 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7044 return; /* Bail out, we didn't really process the move/resize */
7046 else if ((configure_request_size_changed || hints_changed) &&
7047 (allocation.width != new_request.width || allocation.height != new_request.height))
7050 /* We are in one of the following situations:
7051 * A. configure_request_size_changed
7052 * our requisition has changed and we need a different window size,
7053 * so we request it from the window manager.
7054 * B. !configure_request_size_changed && hints_changed
7055 * the window manager rejects our size, but we have just changed the
7056 * window manager hints, so there's a chance our request will
7057 * be honoured this time, so we try again.
7059 * However, if the new requisition is the same as the current allocation,
7060 * we don't request it again, since we won't get a ConfigureNotify back from
7061 * the window manager unless it decides to change our requisition. If
7062 * we don't get the ConfigureNotify back, the resize queue will never be run.
7065 /* Now send the configure request */
7066 if (configure_request_pos_changed)
7070 gdk_window_move_resize (priv->frame,
7071 new_request.x - priv->frame_left,
7072 new_request.y - priv->frame_top,
7073 new_request.width + priv->frame_left + priv->frame_right,
7074 new_request.height + priv->frame_top + priv->frame_bottom);
7075 gdk_window_resize (gdk_window,
7076 new_request.width, new_request.height);
7079 gdk_window_move_resize (gdk_window,
7080 new_request.x, new_request.y,
7081 new_request.width, new_request.height);
7083 else /* only size changed */
7086 gdk_window_resize (priv->frame,
7087 new_request.width + priv->frame_left + priv->frame_right,
7088 new_request.height + priv->frame_top + priv->frame_bottom);
7089 gdk_window_resize (gdk_window,
7090 new_request.width, new_request.height);
7093 if (priv->type == GTK_WINDOW_POPUP)
7095 GtkAllocation allocation;
7097 /* Directly size allocate for override redirect (popup) windows. */
7100 allocation.width = new_request.width;
7101 allocation.height = new_request.height;
7103 gtk_widget_size_allocate (widget, &allocation);
7105 gdk_window_process_updates (gdk_window, TRUE);
7107 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7108 gtk_widget_queue_draw (widget);
7112 /* Increment the number of have-not-yet-received-notify requests */
7113 priv->configure_request_count += 1;
7114 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7116 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7117 * configure event in response to our resizing request.
7118 * the configure event will cause a new resize with
7119 * ->configure_notify_received=TRUE.
7120 * until then, we want to
7121 * - discard expose events
7122 * - coalesce resizes for our children
7123 * - defer any window resizes until the configure event arrived
7124 * to achieve this, we queue a resize for the window, but remove its
7125 * resizing handler, so resizing will not be handled from the next
7126 * idle handler but when the configure event arrives.
7128 * FIXME: we should also dequeue the pending redraws here, since
7129 * we handle those ourselves upon ->configure_notify_received==TRUE.
7131 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7133 gtk_widget_queue_resize_no_redraw (widget);
7134 _gtk_container_dequeue_resize_handler (container);
7140 /* Handle any position changes.
7142 if (configure_request_pos_changed)
7146 gdk_window_move (priv->frame,
7147 new_request.x - priv->frame_left,
7148 new_request.y - priv->frame_top);
7151 gdk_window_move (gdk_window,
7152 new_request.x, new_request.y);
7155 /* And run the resize queue.
7157 gtk_container_resize_children (container);
7160 /* We have now processed a move/resize since the last position
7161 * constraint change, setting of the initial position, or resize.
7162 * (Not resetting these flags here can lead to infinite loops for
7163 * GTK_RESIZE_IMMEDIATE containers)
7165 info->position_constraints_changed = FALSE;
7166 info->initial_pos_set = FALSE;
7167 info->resize_width = -1;
7168 info->resize_height = -1;
7171 /* Compare two sets of Geometry hints for equality.
7174 gtk_window_compare_hints (GdkGeometry *geometry_a,
7176 GdkGeometry *geometry_b,
7179 if (flags_a != flags_b)
7182 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7183 (geometry_a->min_width != geometry_b->min_width ||
7184 geometry_a->min_height != geometry_b->min_height))
7187 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7188 (geometry_a->max_width != geometry_b->max_width ||
7189 geometry_a->max_height != geometry_b->max_height))
7192 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7193 (geometry_a->base_width != geometry_b->base_width ||
7194 geometry_a->base_height != geometry_b->base_height))
7197 if ((flags_a & GDK_HINT_ASPECT) &&
7198 (geometry_a->min_aspect != geometry_b->min_aspect ||
7199 geometry_a->max_aspect != geometry_b->max_aspect))
7202 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7203 (geometry_a->width_inc != geometry_b->width_inc ||
7204 geometry_a->height_inc != geometry_b->height_inc))
7207 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7208 geometry_a->win_gravity != geometry_b->win_gravity)
7215 _gtk_window_constrain_size (GtkWindow *window,
7221 GtkWindowPrivate *priv;
7222 GtkWindowGeometryInfo *info;
7224 g_return_if_fail (GTK_IS_WINDOW (window));
7226 priv = window->priv;
7228 info = priv->geometry_info;
7231 GdkWindowHints flags = info->last.flags;
7232 GdkGeometry *geometry = &info->last.geometry;
7234 gtk_window_constrain_size (window,
7245 gtk_window_constrain_size (GtkWindow *window,
7246 GdkGeometry *geometry,
7253 gdk_window_constrain_size (geometry, flags, width, height,
7254 new_width, new_height);
7257 /* Compute the set of geometry hints and flags for a window
7258 * based on the application set geometry, and requisition
7259 * of the window. gtk_widget_get_preferred_size() must have been
7263 gtk_window_compute_hints (GtkWindow *window,
7264 GdkGeometry *new_geometry,
7267 GtkWindowPrivate *priv = window->priv;
7269 gint extra_width = 0;
7270 gint extra_height = 0;
7271 GtkWindowGeometryInfo *geometry_info;
7272 GtkRequisition requisition;
7274 widget = GTK_WIDGET (window);
7276 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7277 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7281 *new_flags = geometry_info->mask;
7282 *new_geometry = geometry_info->geometry;
7289 if (geometry_info && geometry_info->widget)
7291 /* If the geometry widget is set, then the hints really apply to that
7292 * widget. This is pretty much meaningless unless the window layout
7293 * is such that the rest of the window adds fixed size borders to
7294 * the geometry widget. Our job is to figure the size of the borders;
7295 * We do that by asking how big the toplevel would be if the
7296 * geometry widget was *really big*.
7299 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7300 * |GGGGG B| in the border can confuse things
7306 * |AAAAAAAAA | When the geometry widget is large, things are
7307 * |GGGGGGGGGGB| clearer.
7312 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7313 GtkRequisition requisition;
7314 int current_width, current_height;
7316 _gtk_widget_override_size_request (geometry_info->widget,
7317 TEMPORARY_SIZE, TEMPORARY_SIZE,
7318 ¤t_width, ¤t_height);
7319 gtk_widget_get_preferred_size (widget,
7320 &requisition, NULL);
7321 _gtk_widget_restore_size_request (geometry_info->widget,
7322 current_width, current_height);
7324 extra_width = requisition.width - TEMPORARY_SIZE;
7325 extra_height = requisition.height - TEMPORARY_SIZE;
7327 if (extra_width < 0 || extra_width < 0)
7329 g_warning("Toplevel size doesn't seem to directly depend on the "
7330 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7331 "The geometry widget might not be in the window, or it might not "
7332 "be packed into the window appropriately");
7333 extra_width = MAX(extra_width, 0);
7334 extra_height = MAX(extra_height, 0);
7336 #undef TEMPORARY_SIZE
7339 /* We don't want to set GDK_HINT_POS in here, we just set it
7340 * in gtk_window_move_resize() when we want the position
7344 if (*new_flags & GDK_HINT_BASE_SIZE)
7346 new_geometry->base_width += extra_width;
7347 new_geometry->base_height += extra_height;
7351 /* For simplicity, we always set the base hint, even when we
7352 * don't expect it to have any visible effect.
7353 * (Note: geometry_size_to_pixels() depends on this.)
7355 *new_flags |= GDK_HINT_BASE_SIZE;
7357 new_geometry->base_width = extra_width;
7358 new_geometry->base_height = extra_height;
7360 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7361 * base size is the minimum size */
7362 if (*new_flags & GDK_HINT_MIN_SIZE)
7364 if (new_geometry->min_width > 0)
7365 new_geometry->base_width += new_geometry->min_width;
7366 if (new_geometry->min_height > 0)
7367 new_geometry->base_height += new_geometry->min_height;
7371 if (*new_flags & GDK_HINT_MIN_SIZE)
7373 if (new_geometry->min_width < 0)
7374 new_geometry->min_width = requisition.width;
7376 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7378 if (new_geometry->min_height < 0)
7379 new_geometry->min_height = requisition.height;
7381 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7385 *new_flags |= GDK_HINT_MIN_SIZE;
7387 new_geometry->min_width = requisition.width;
7388 new_geometry->min_height = requisition.height;
7391 if (*new_flags & GDK_HINT_MAX_SIZE)
7393 if (new_geometry->max_width < 0)
7394 new_geometry->max_width = requisition.width;
7396 new_geometry->max_width += extra_width;
7398 if (new_geometry->max_height < 0)
7399 new_geometry->max_height = requisition.height;
7401 new_geometry->max_height += extra_height;
7403 else if (!priv->resizable)
7405 *new_flags |= GDK_HINT_MAX_SIZE;
7407 new_geometry->max_width = requisition.width;
7408 new_geometry->max_height = requisition.height;
7411 *new_flags |= GDK_HINT_WIN_GRAVITY;
7412 new_geometry->win_gravity = priv->gravity;
7415 /***********************
7416 * Redrawing functions *
7417 ***********************/
7420 gtk_window_draw (GtkWidget *widget,
7423 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7424 GtkStyleContext *context;
7425 gboolean ret = FALSE;
7427 context = gtk_widget_get_style_context (widget);
7429 gtk_style_context_save (context);
7431 if (!gtk_widget_get_app_paintable (widget))
7433 GtkStateFlags state;
7435 state = gtk_widget_get_state_flags (widget);
7437 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7438 state |= GTK_STATE_FLAG_FOCUSED;
7440 gtk_style_context_set_state (context, state);
7441 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7442 gtk_render_background (context, cr, 0, 0,
7443 gtk_widget_get_allocated_width (widget),
7444 gtk_widget_get_allocated_height (widget));
7447 gtk_style_context_restore (context);
7449 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7450 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7452 if (priv->grip_window != NULL &&
7453 gtk_cairo_should_draw_window (cr, priv->grip_window))
7457 gtk_style_context_save (context);
7460 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7461 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7463 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7464 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7465 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7468 gtk_style_context_restore (context);
7475 * gtk_window_set_has_frame:
7476 * @window: a #GtkWindow
7477 * @setting: a boolean
7479 * (Note: this is a special-purpose function for the framebuffer port,
7480 * that causes GTK+ to draw its own window border. For most applications,
7481 * you want gtk_window_set_decorated() instead, which tells the window
7482 * manager whether to draw the window border.)
7484 * If this function is called on a window with setting of %TRUE, before
7485 * it is realized or showed, it will have a "frame" window around
7486 * @window->window, accessible in @window->frame. Using the signal
7487 * frame_event you can receive all events targeted at the frame.
7489 * This function is used by the linux-fb port to implement managed
7490 * windows, but it could conceivably be used by X-programs that
7491 * want to do their own window decorations.
7495 gtk_window_set_has_frame (GtkWindow *window,
7498 GtkWindowPrivate *priv;
7500 g_return_if_fail (GTK_IS_WINDOW (window));
7501 g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
7503 priv = window->priv;
7505 priv->has_frame = setting != FALSE;
7509 * gtk_window_get_has_frame:
7510 * @window: a #GtkWindow
7512 * Accessor for whether the window has a frame window exterior to
7513 * @window->window. Gets the value set by gtk_window_set_has_frame ().
7515 * Return value: %TRUE if a frame has been added to the window
7516 * via gtk_window_set_has_frame().
7519 gtk_window_get_has_frame (GtkWindow *window)
7521 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7523 return window->priv->has_frame;
7527 * gtk_window_set_frame_dimensions:
7528 * @window: a #GtkWindow that has a frame
7529 * @left: The width of the left border
7530 * @top: The height of the top border
7531 * @right: The width of the right border
7532 * @bottom: The height of the bottom border
7534 * (Note: this is a special-purpose function intended for the framebuffer
7535 * port; see gtk_window_set_has_frame(). It will have no effect on the
7536 * window border drawn by the window manager, which is the normal
7537 * case when using the X Window system.)
7539 * For windows with frames (see gtk_window_set_has_frame()) this function
7540 * can be used to change the size of the frame border.
7543 gtk_window_set_frame_dimensions (GtkWindow *window,
7549 GtkWindowPrivate *priv;
7550 GtkAllocation allocation;
7553 g_return_if_fail (GTK_IS_WINDOW (window));
7555 priv = window->priv;
7556 widget = GTK_WIDGET (window);
7558 if (priv->frame_left == left &&
7559 priv->frame_top == top &&
7560 priv->frame_right == right &&
7561 priv->frame_bottom == bottom)
7564 priv->frame_left = left;
7565 priv->frame_top = top;
7566 priv->frame_right = right;
7567 priv->frame_bottom = bottom;
7569 if (gtk_widget_get_realized (widget) && priv->frame)
7572 gtk_widget_get_allocation (widget, &allocation);
7574 width = allocation.width + left + right;
7575 height = allocation.height + top + bottom;
7576 gdk_window_resize (priv->frame, width, height);
7577 gdk_window_move_resize (gtk_widget_get_window (GTK_WIDGET (window)),
7585 * gtk_window_present:
7586 * @window: a #GtkWindow
7588 * Presents a window to the user. This may mean raising the window
7589 * in the stacking order, deiconifying it, moving it to the current
7590 * desktop, and/or giving it the keyboard focus, possibly dependent
7591 * on the user's platform, window manager, and preferences.
7593 * If @window is hidden, this function calls gtk_widget_show()
7596 * This function should be used when the user tries to open a window
7597 * that's already open. Say for example the preferences dialog is
7598 * currently open, and the user chooses Preferences from the menu
7599 * a second time; use gtk_window_present() to move the already-open dialog
7600 * where the user can see it.
7602 * If you are calling this function in response to a user interaction,
7603 * it is preferable to use gtk_window_present_with_time().
7607 gtk_window_present (GtkWindow *window)
7609 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7613 * gtk_window_present_with_time:
7614 * @window: a #GtkWindow
7615 * @timestamp: the timestamp of the user interaction (typically a
7616 * button or key press event) which triggered this call
7618 * Presents a window to the user in response to a user interaction.
7619 * If you need to present a window without a timestamp, use
7620 * gtk_window_present(). See gtk_window_present() for details.
7625 gtk_window_present_with_time (GtkWindow *window,
7629 GdkWindow *gdk_window;
7631 g_return_if_fail (GTK_IS_WINDOW (window));
7633 widget = GTK_WIDGET (window);
7635 if (gtk_widget_get_visible (widget))
7637 gdk_window = gtk_widget_get_window (widget);
7639 g_assert (gdk_window != NULL);
7641 gdk_window_show (gdk_window);
7643 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7644 if (timestamp == GDK_CURRENT_TIME)
7646 #ifdef GDK_WINDOWING_X11
7647 GdkDisplay *display;
7649 display = gtk_widget_get_display (GTK_WIDGET (window));
7650 timestamp = gdk_x11_display_get_user_time (display);
7652 timestamp = gtk_get_current_event_time ();
7656 gdk_window_focus (gdk_window, timestamp);
7660 gtk_widget_show (widget);
7665 * gtk_window_iconify:
7666 * @window: a #GtkWindow
7668 * Asks to iconify (i.e. minimize) the specified @window. Note that
7669 * you shouldn't assume the window is definitely iconified afterward,
7670 * because other entities (e.g. the user or <link
7671 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7672 * again, or there may not be a window manager in which case
7673 * iconification isn't possible, etc. But normally the window will end
7674 * up iconified. Just don't write code that crashes if not.
7676 * It's permitted to call this function before showing a window,
7677 * in which case the window will be iconified before it ever appears
7680 * You can track iconification via the "window-state-event" signal
7685 gtk_window_iconify (GtkWindow *window)
7687 GtkWindowPrivate *priv;
7689 GdkWindow *toplevel;
7691 g_return_if_fail (GTK_IS_WINDOW (window));
7693 priv = window->priv;
7694 widget = GTK_WIDGET (window);
7696 priv->iconify_initially = TRUE;
7699 toplevel = priv->frame;
7701 toplevel = gtk_widget_get_window (widget);
7703 if (toplevel != NULL)
7704 gdk_window_iconify (toplevel);
7708 * gtk_window_deiconify:
7709 * @window: a #GtkWindow
7711 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7712 * that you shouldn't assume the window is definitely deiconified
7713 * afterward, because other entities (e.g. the user or <link
7714 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7715 * again before your code which assumes deiconification gets to run.
7717 * You can track iconification via the "window-state-event" signal
7721 gtk_window_deiconify (GtkWindow *window)
7723 GtkWindowPrivate *priv;
7725 GdkWindow *toplevel;
7727 g_return_if_fail (GTK_IS_WINDOW (window));
7729 priv = window->priv;
7730 widget = GTK_WIDGET (window);
7732 priv->iconify_initially = FALSE;
7735 toplevel = priv->frame;
7737 toplevel = gtk_widget_get_window (widget);
7739 if (toplevel != NULL)
7740 gdk_window_deiconify (toplevel);
7745 * @window: a #GtkWindow
7747 * Asks to stick @window, which means that it will appear on all user
7748 * desktops. Note that you shouldn't assume the window is definitely
7749 * stuck afterward, because other entities (e.g. the user or <link
7750 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7751 * again, and some window managers do not support sticking
7752 * windows. But normally the window will end up stuck. Just don't
7753 * write code that crashes if not.
7755 * It's permitted to call this function before showing a window.
7757 * You can track stickiness via the "window-state-event" signal
7762 gtk_window_stick (GtkWindow *window)
7764 GtkWindowPrivate *priv;
7766 GdkWindow *toplevel;
7768 g_return_if_fail (GTK_IS_WINDOW (window));
7770 priv = window->priv;
7771 widget = GTK_WIDGET (window);
7773 priv->stick_initially = TRUE;
7776 toplevel = priv->frame;
7778 toplevel = gtk_widget_get_window (widget);
7780 if (toplevel != NULL)
7781 gdk_window_stick (toplevel);
7785 * gtk_window_unstick:
7786 * @window: a #GtkWindow
7788 * Asks to unstick @window, which means that it will appear on only
7789 * one of the user's desktops. Note that you shouldn't assume the
7790 * window is definitely unstuck afterward, because other entities
7791 * (e.g. the user or <link linkend="gtk-X11-arch">window
7792 * manager</link>) could stick it again. But normally the window will
7793 * end up stuck. Just don't write code that crashes if not.
7795 * You can track stickiness via the "window-state-event" signal
7800 gtk_window_unstick (GtkWindow *window)
7802 GtkWindowPrivate *priv;
7804 GdkWindow *toplevel;
7806 g_return_if_fail (GTK_IS_WINDOW (window));
7808 priv = window->priv;
7809 widget = GTK_WIDGET (window);
7811 priv->stick_initially = FALSE;
7814 toplevel = priv->frame;
7816 toplevel = gtk_widget_get_window (widget);
7818 if (toplevel != NULL)
7819 gdk_window_unstick (toplevel);
7823 * gtk_window_maximize:
7824 * @window: a #GtkWindow
7826 * Asks to maximize @window, so that it becomes full-screen. Note that
7827 * you shouldn't assume the window is definitely maximized afterward,
7828 * because other entities (e.g. the user or <link
7829 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7830 * again, and not all window managers support maximization. But
7831 * normally the window will end up maximized. Just don't write code
7832 * that crashes if not.
7834 * It's permitted to call this function before showing a window,
7835 * in which case the window will be maximized when it appears onscreen
7838 * You can track maximization via the "window-state-event" signal
7843 gtk_window_maximize (GtkWindow *window)
7845 GtkWindowPrivate *priv;
7847 GdkWindow *toplevel;
7849 g_return_if_fail (GTK_IS_WINDOW (window));
7851 priv = window->priv;
7852 widget = GTK_WIDGET (window);
7854 priv->maximize_initially = TRUE;
7857 toplevel = priv->frame;
7859 toplevel = gtk_widget_get_window (widget);
7861 if (toplevel != NULL)
7862 gdk_window_maximize (toplevel);
7866 * gtk_window_unmaximize:
7867 * @window: a #GtkWindow
7869 * Asks to unmaximize @window. Note that you shouldn't assume the
7870 * window is definitely unmaximized afterward, because other entities
7871 * (e.g. the user or <link linkend="gtk-X11-arch">window
7872 * manager</link>) could maximize it again, and not all window
7873 * managers honor requests to unmaximize. But normally the window will
7874 * end up unmaximized. Just don't write code that crashes if not.
7876 * You can track maximization via the "window-state-event" signal
7881 gtk_window_unmaximize (GtkWindow *window)
7883 GtkWindowPrivate *priv;
7885 GdkWindow *toplevel;
7887 g_return_if_fail (GTK_IS_WINDOW (window));
7889 priv = window->priv;
7890 widget = GTK_WIDGET (window);
7892 priv->maximize_initially = FALSE;
7895 toplevel = priv->frame;
7897 toplevel = gtk_widget_get_window (widget);
7899 if (toplevel != NULL)
7900 gdk_window_unmaximize (toplevel);
7904 * gtk_window_fullscreen:
7905 * @window: a #GtkWindow
7907 * Asks to place @window in the fullscreen state. Note that you
7908 * shouldn't assume the window is definitely full screen afterward,
7909 * because other entities (e.g. the user or <link
7910 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7911 * again, and not all window managers honor requests to fullscreen
7912 * windows. But normally the window will end up fullscreen. Just
7913 * don't write code that crashes if not.
7915 * You can track the fullscreen state via the "window-state-event" signal
7921 gtk_window_fullscreen (GtkWindow *window)
7923 GtkWindowPrivate *priv;
7925 GdkWindow *toplevel;
7927 g_return_if_fail (GTK_IS_WINDOW (window));
7929 priv = window->priv;
7930 widget = GTK_WIDGET (window);
7932 priv->fullscreen_initially = TRUE;
7935 toplevel = priv->frame;
7937 toplevel = gtk_widget_get_window (widget);
7939 if (toplevel != NULL)
7940 gdk_window_fullscreen (toplevel);
7944 * gtk_window_unfullscreen:
7945 * @window: a #GtkWindow
7947 * Asks to toggle off the fullscreen state for @window. Note that you
7948 * shouldn't assume the window is definitely not full screen
7949 * afterward, because other entities (e.g. the user or <link
7950 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7951 * again, and not all window managers honor requests to unfullscreen
7952 * windows. But normally the window will end up restored to its normal
7953 * state. Just don't write code that crashes if not.
7955 * You can track the fullscreen state via the "window-state-event" signal
7961 gtk_window_unfullscreen (GtkWindow *window)
7964 GdkWindow *toplevel;
7965 GtkWindowPrivate *priv;
7967 g_return_if_fail (GTK_IS_WINDOW (window));
7969 priv = window->priv;
7970 widget = GTK_WIDGET (window);
7972 priv->fullscreen_initially = FALSE;
7975 toplevel = priv->frame;
7977 toplevel = gtk_widget_get_window (widget);
7979 if (toplevel != NULL)
7980 gdk_window_unfullscreen (toplevel);
7984 * gtk_window_set_keep_above:
7985 * @window: a #GtkWindow
7986 * @setting: whether to keep @window above other windows
7988 * Asks to keep @window above, so that it stays on top. Note that
7989 * you shouldn't assume the window is definitely above afterward,
7990 * because other entities (e.g. the user or <link
7991 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7992 * and not all window managers support keeping windows above. But
7993 * normally the window will end kept above. Just don't write code
7994 * that crashes if not.
7996 * It's permitted to call this function before showing a window,
7997 * in which case the window will be kept above when it appears onscreen
8000 * You can track the above state via the "window-state-event" signal
8003 * Note that, according to the <ulink
8004 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8005 * Manager Hints</ulink> specification, the above state is mainly meant
8006 * for user preferences and should not be used by applications e.g. for
8007 * drawing attention to their dialogs.
8012 gtk_window_set_keep_above (GtkWindow *window,
8016 GtkWindowPrivate *priv;
8017 GdkWindow *toplevel;
8019 g_return_if_fail (GTK_IS_WINDOW (window));
8021 priv = window->priv;
8022 widget = GTK_WIDGET (window);
8024 priv->above_initially = setting != FALSE;
8026 priv->below_initially = FALSE;
8029 toplevel = priv->frame;
8031 toplevel = gtk_widget_get_window (widget);
8033 if (toplevel != NULL)
8034 gdk_window_set_keep_above (toplevel, setting);
8038 * gtk_window_set_keep_below:
8039 * @window: a #GtkWindow
8040 * @setting: whether to keep @window below other windows
8042 * Asks to keep @window below, so that it stays in bottom. Note that
8043 * you shouldn't assume the window is definitely below afterward,
8044 * because other entities (e.g. the user or <link
8045 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8046 * and not all window managers support putting windows below. But
8047 * normally the window will be kept below. Just don't write code
8048 * that crashes if not.
8050 * It's permitted to call this function before showing a window,
8051 * in which case the window will be kept below when it appears onscreen
8054 * You can track the below state via the "window-state-event" signal
8057 * Note that, according to the <ulink
8058 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8059 * Manager Hints</ulink> specification, the above state is mainly meant
8060 * for user preferences and should not be used by applications e.g. for
8061 * drawing attention to their dialogs.
8066 gtk_window_set_keep_below (GtkWindow *window,
8070 GtkWindowPrivate *priv;
8071 GdkWindow *toplevel;
8073 g_return_if_fail (GTK_IS_WINDOW (window));
8075 priv = window->priv;
8076 widget = GTK_WIDGET (window);
8078 priv->below_initially = setting != FALSE;
8080 priv->above_initially = FALSE;
8083 toplevel = priv->frame;
8085 toplevel = gtk_widget_get_window (widget);
8087 if (toplevel != NULL)
8088 gdk_window_set_keep_below (toplevel, setting);
8092 * gtk_window_set_resizable:
8093 * @window: a #GtkWindow
8094 * @resizable: %TRUE if the user can resize this window
8096 * Sets whether the user can resize a window. Windows are user resizable
8100 gtk_window_set_resizable (GtkWindow *window,
8103 GtkWindowPrivate *priv;
8105 g_return_if_fail (GTK_IS_WINDOW (window));
8107 priv = window->priv;
8109 resizable = (resizable != FALSE);
8111 if (priv->resizable != resizable)
8113 priv->resizable = (resizable != FALSE);
8115 update_grip_visibility (window);
8117 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8119 g_object_notify (G_OBJECT (window), "resizable");
8124 * gtk_window_get_resizable:
8125 * @window: a #GtkWindow
8127 * Gets the value set by gtk_window_set_resizable().
8129 * Return value: %TRUE if the user can resize the window
8132 gtk_window_get_resizable (GtkWindow *window)
8134 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8136 return window->priv->resizable;
8140 * gtk_window_set_gravity:
8141 * @window: a #GtkWindow
8142 * @gravity: window gravity
8144 * Window gravity defines the meaning of coordinates passed to
8145 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8148 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8149 * typically "do what you mean."
8153 gtk_window_set_gravity (GtkWindow *window,
8156 GtkWindowPrivate *priv;
8158 g_return_if_fail (GTK_IS_WINDOW (window));
8160 priv = window->priv;
8162 if (gravity != priv->gravity)
8164 priv->gravity = gravity;
8166 /* gtk_window_move_resize() will adapt gravity
8168 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8170 g_object_notify (G_OBJECT (window), "gravity");
8175 * gtk_window_get_gravity:
8176 * @window: a #GtkWindow
8178 * Gets the value set by gtk_window_set_gravity().
8180 * Return value: (transfer none): window gravity
8183 gtk_window_get_gravity (GtkWindow *window)
8185 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8187 return window->priv->gravity;
8191 * gtk_window_begin_resize_drag:
8192 * @window: a #GtkWindow
8193 * @button: mouse button that initiated the drag
8194 * @edge: position of the resize control
8195 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8196 * @root_y: Y position where the user clicked to initiate the drag
8197 * @timestamp: timestamp from the click event that initiated the drag
8199 * Starts resizing a window. This function is used if an application
8200 * has window resizing controls. When GDK can support it, the resize
8201 * will be done using the standard mechanism for the <link
8202 * linkend="gtk-X11-arch">window manager</link> or windowing
8203 * system. Otherwise, GDK will try to emulate window resizing,
8204 * potentially not all that well, depending on the windowing system.
8208 gtk_window_begin_resize_drag (GtkWindow *window,
8215 GtkWindowPrivate *priv;
8217 GdkWindow *toplevel;
8219 g_return_if_fail (GTK_IS_WINDOW (window));
8220 widget = GTK_WIDGET (window);
8221 g_return_if_fail (gtk_widget_get_visible (widget));
8223 priv = window->priv;
8226 toplevel = priv->frame;
8228 toplevel = gtk_widget_get_window (widget);
8230 gdk_window_begin_resize_drag (toplevel,
8237 * gtk_window_get_frame_dimensions:
8238 * @window: a #GtkWindow
8239 * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
8240 * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
8241 * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
8242 * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
8244 * (Note: this is a special-purpose function intended for the
8245 * framebuffer port; see gtk_window_set_has_frame(). It will not
8246 * return the size of the window border drawn by the <link
8247 * linkend="gtk-X11-arch">window manager</link>, which is the normal
8248 * case when using a windowing system. See
8249 * gdk_window_get_frame_extents() to get the standard window border
8252 * Retrieves the dimensions of the frame window for this toplevel.
8253 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
8256 gtk_window_get_frame_dimensions (GtkWindow *window,
8262 GtkWindowPrivate *priv;
8264 g_return_if_fail (GTK_IS_WINDOW (window));
8266 priv = window->priv;
8269 *left = priv->frame_left;
8271 *top = priv->frame_top;
8273 *right = priv->frame_right;
8275 *bottom = priv->frame_bottom;
8279 * gtk_window_begin_move_drag:
8280 * @window: a #GtkWindow
8281 * @button: mouse button that initiated the drag
8282 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8283 * @root_y: Y position where the user clicked to initiate the drag
8284 * @timestamp: timestamp from the click event that initiated the drag
8286 * Starts moving a window. This function is used if an application has
8287 * window movement grips. When GDK can support it, the window movement
8288 * will be done using the standard mechanism for the <link
8289 * linkend="gtk-X11-arch">window manager</link> or windowing
8290 * system. Otherwise, GDK will try to emulate window movement,
8291 * potentially not all that well, depending on the windowing system.
8295 gtk_window_begin_move_drag (GtkWindow *window,
8301 GtkWindowPrivate *priv;
8303 GdkWindow *toplevel;
8305 g_return_if_fail (GTK_IS_WINDOW (window));
8306 widget = GTK_WIDGET (window);
8307 g_return_if_fail (gtk_widget_get_visible (widget));
8309 priv = window->priv;
8312 toplevel = priv->frame;
8314 toplevel = gtk_widget_get_window (widget);
8316 gdk_window_begin_move_drag (toplevel,
8323 * gtk_window_set_screen:
8324 * @window: a #GtkWindow.
8325 * @screen: a #GdkScreen.
8327 * Sets the #GdkScreen where the @window is displayed; if
8328 * the window is already mapped, it will be unmapped, and
8329 * then remapped on the new screen.
8334 gtk_window_set_screen (GtkWindow *window,
8337 GtkWindowPrivate *priv;
8339 GdkScreen *previous_screen;
8340 gboolean was_mapped;
8342 g_return_if_fail (GTK_IS_WINDOW (window));
8343 g_return_if_fail (GDK_IS_SCREEN (screen));
8345 priv = window->priv;
8347 if (screen == priv->screen)
8350 widget = GTK_WIDGET (window);
8352 previous_screen = priv->screen;
8353 was_mapped = gtk_widget_get_mapped (widget);
8356 gtk_widget_unmap (widget);
8357 if (gtk_widget_get_realized (widget))
8358 gtk_widget_unrealize (widget);
8360 gtk_window_free_key_hash (window);
8361 priv->screen = screen;
8362 gtk_widget_reset_rc_styles (widget);
8363 if (screen != previous_screen)
8365 g_signal_handlers_disconnect_by_func (previous_screen,
8366 gtk_window_on_composited_changed, window);
8367 g_signal_connect (screen, "composited-changed",
8368 G_CALLBACK (gtk_window_on_composited_changed), window);
8370 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8371 _gtk_widget_propagate_composited_changed (widget);
8373 g_object_notify (G_OBJECT (window), "screen");
8376 gtk_widget_map (widget);
8380 gtk_window_on_composited_changed (GdkScreen *screen,
8383 gtk_widget_queue_draw (GTK_WIDGET (window));
8385 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8389 gtk_window_check_screen (GtkWindow *window)
8391 GtkWindowPrivate *priv = window->priv;
8394 return priv->screen;
8397 g_warning ("Screen for GtkWindow not set; you must always set\n"
8398 "a screen for a GtkWindow before using the window");
8404 * gtk_window_get_screen:
8405 * @window: a #GtkWindow.
8407 * Returns the #GdkScreen associated with @window.
8409 * Return value: (transfer none): a #GdkScreen.
8414 gtk_window_get_screen (GtkWindow *window)
8416 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8418 return window->priv->screen;
8422 * gtk_window_is_active:
8423 * @window: a #GtkWindow
8425 * Returns whether the window is part of the current active toplevel.
8426 * (That is, the toplevel window receiving keystrokes.)
8427 * The return value is %TRUE if the window is active toplevel
8428 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8429 * You might use this function if you wanted to draw a widget
8430 * differently in an active window from a widget in an inactive window.
8431 * See gtk_window_has_toplevel_focus()
8433 * Return value: %TRUE if the window part of the current active window.
8438 gtk_window_is_active (GtkWindow *window)
8440 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8442 return window->priv->is_active;
8446 * gtk_window_has_toplevel_focus:
8447 * @window: a #GtkWindow
8449 * Returns whether the input focus is within this GtkWindow.
8450 * For real toplevel windows, this is identical to gtk_window_is_active(),
8451 * but for embedded windows, like #GtkPlug, the results will differ.
8453 * Return value: %TRUE if the input focus is within this GtkWindow
8458 gtk_window_has_toplevel_focus (GtkWindow *window)
8460 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8462 return window->priv->has_toplevel_focus;
8465 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8468 gtk_window_group_init (GtkWindowGroup *group)
8470 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8471 GTK_TYPE_WINDOW_GROUP,
8472 GtkWindowGroupPrivate);
8476 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8478 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8482 * gtk_window_group_new:
8484 * Creates a new #GtkWindowGroup object. Grabs added with
8485 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8487 * Return value: a new #GtkWindowGroup.
8490 gtk_window_group_new (void)
8492 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8496 window_group_cleanup_grabs (GtkWindowGroup *group,
8499 GtkWindowGroupPrivate *priv;
8500 GtkDeviceGrabInfo *info;
8502 GSList *to_remove = NULL;
8506 tmp_list = priv->grabs;
8509 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8510 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8511 tmp_list = tmp_list->next;
8516 gtk_grab_remove (to_remove->data);
8517 g_object_unref (to_remove->data);
8518 to_remove = g_slist_delete_link (to_remove, to_remove);
8521 tmp_list = priv->device_grabs;
8525 info = tmp_list->data;
8527 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8528 to_remove = g_slist_prepend (to_remove, info);
8530 tmp_list = tmp_list->next;
8535 info = to_remove->data;
8537 gtk_device_grab_remove (info->widget, info->device);
8538 to_remove = g_slist_delete_link (to_remove, to_remove);
8543 * gtk_window_group_add_window:
8544 * @window_group: a #GtkWindowGroup
8545 * @window: the #GtkWindow to add
8547 * Adds a window to a #GtkWindowGroup.
8550 gtk_window_group_add_window (GtkWindowGroup *window_group,
8553 GtkWindowPrivate *priv;
8555 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8556 g_return_if_fail (GTK_IS_WINDOW (window));
8558 priv = window->priv;
8560 if (priv->group != window_group)
8562 g_object_ref (window);
8563 g_object_ref (window_group);
8566 gtk_window_group_remove_window (priv->group, window);
8568 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8570 priv->group = window_group;
8572 g_object_unref (window);
8577 * gtk_window_group_remove_window:
8578 * @window_group: a #GtkWindowGroup
8579 * @window: the #GtkWindow to remove
8581 * Removes a window from a #GtkWindowGroup.
8584 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8587 GtkWindowPrivate *priv;
8589 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8590 g_return_if_fail (GTK_IS_WINDOW (window));
8591 priv = window->priv;
8592 g_return_if_fail (priv->group == window_group);
8594 g_object_ref (window);
8596 window_group_cleanup_grabs (window_group, window);
8599 g_object_unref (window_group);
8600 g_object_unref (window);
8604 * gtk_window_group_list_windows:
8605 * @window_group: a #GtkWindowGroup
8607 * Returns a list of the #GtkWindows that belong to @window_group.
8609 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8610 * windows inside the group.
8615 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8617 GList *toplevels, *toplevel, *group_windows;
8619 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8621 group_windows = NULL;
8622 toplevels = gtk_window_list_toplevels ();
8624 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8626 GtkWindow *window = toplevel->data;
8628 if (window_group == window->priv->group)
8629 group_windows = g_list_prepend (group_windows, window);
8632 return g_list_reverse (group_windows);
8636 * gtk_window_get_group:
8637 * @window: (allow-none): a #GtkWindow, or %NULL
8639 * Returns the group for @window or the default group, if
8640 * @window is %NULL or if @window does not have an explicit
8643 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8648 gtk_window_get_group (GtkWindow *window)
8650 if (window && window->priv->group)
8651 return window->priv->group;
8654 static GtkWindowGroup *default_group = NULL;
8657 default_group = gtk_window_group_new ();
8659 return default_group;
8664 * gtk_window_has_group:
8665 * @window: a #GtkWindow
8667 * Returns whether @window has an explicit window group.
8669 * Return value: %TRUE if @window has an explicit window group.
8674 gtk_window_has_group (GtkWindow *window)
8676 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8678 return window->priv->group != NULL;
8682 * gtk_window_group_get_current_grab:
8683 * @window_group: a #GtkWindowGroup
8685 * Gets the current grab widget of the given group,
8686 * see gtk_grab_add().
8688 * Returns: the current grab widget of the group
8693 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8695 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8697 if (window_group->priv->grabs)
8698 return GTK_WIDGET (window_group->priv->grabs->data);
8703 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8706 GtkWindowGroupPrivate *priv;
8708 priv = window_group->priv;
8709 priv->grabs = g_slist_prepend (priv->grabs, widget);
8713 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8716 GtkWindowGroupPrivate *priv;
8718 priv = window_group->priv;
8719 priv->grabs = g_slist_remove (priv->grabs, widget);
8724 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8727 gboolean block_others)
8729 GtkWindowGroupPrivate *priv;
8730 GtkDeviceGrabInfo *info;
8732 priv = window_group->priv;
8734 info = g_slice_new0 (GtkDeviceGrabInfo);
8735 info->widget = widget;
8736 info->device = device;
8737 info->block_others = block_others;
8739 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8743 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8747 GtkWindowGroupPrivate *priv;
8748 GtkDeviceGrabInfo *info;
8749 GSList *list, *node = NULL;
8750 GdkDevice *other_device;
8752 priv = window_group->priv;
8753 other_device = gdk_device_get_associated_device (device);
8754 list = priv->device_grabs;
8760 if (info->widget == widget &&
8761 (info->device == device ||
8762 info->device == other_device))
8775 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8776 g_slice_free (GtkDeviceGrabInfo, info);
8781 * gtk_window_group_get_current_device_grab:
8782 * @window_group: a #GtkWindowGroup
8783 * @device: a #GdkDevice
8785 * Returns the current grab widget for @device, or %NULL if none.
8787 * Returns: The grab widget, or %NULL
8792 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8795 GtkWindowGroupPrivate *priv;
8796 GtkDeviceGrabInfo *info;
8797 GdkDevice *other_device;
8800 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8801 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8803 priv = window_group->priv;
8804 list = priv->device_grabs;
8805 other_device = gdk_device_get_associated_device (device);
8812 if (info->device == device ||
8813 info->device == other_device)
8814 return info->widget;
8821 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8825 GtkWindowGroupPrivate *priv;
8826 GtkDeviceGrabInfo *info;
8827 GdkDevice *other_device;
8830 priv = window_group->priv;
8831 other_device = gdk_device_get_associated_device (device);
8832 list = priv->device_grabs;
8839 /* Look for blocking grabs on other device pairs
8840 * that have the passed widget within the GTK+ grab.
8842 if (info->block_others &&
8843 info->device != device &&
8844 info->device != other_device &&
8845 (info->widget == widget ||
8846 gtk_widget_is_ancestor (widget, info->widget)))
8854 Derived from XParseGeometry() in XFree86
8856 Copyright 1985, 1986, 1987,1998 The Open Group
8858 All Rights Reserved.
8860 The above copyright notice and this permission notice shall be included
8861 in all copies or substantial portions of the Software.
8863 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8864 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8865 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8866 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8867 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8868 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8869 OTHER DEALINGS IN THE SOFTWARE.
8871 Except as contained in this notice, the name of The Open Group shall
8872 not be used in advertising or otherwise to promote the sale, use or
8873 other dealings in this Software without prior written authorization
8874 from The Open Group.
8879 * XParseGeometry parses strings of the form
8880 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8881 * width, height, xoffset, and yoffset are unsigned integers.
8882 * Example: "=80x24+300-49"
8883 * The equal sign is optional.
8884 * It returns a bitmask that indicates which of the four values
8885 * were actually found in the string. For each value found,
8886 * the corresponding argument is updated; for each value
8887 * not found, the corresponding argument is left unchanged.
8890 /* The following code is from Xlib, and is minimally modified, so we
8891 * can track any upstream changes if required. Don't change this
8892 * code. Or if you do, put in a huge comment marking which thing
8897 read_int (gchar *string,
8905 else if (*string == '-')
8911 for (; (*string >= '0') && (*string <= '9'); string++)
8913 result = (result * 10) + (*string - '0');
8925 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8926 * value (x, y, width, height) was found in the parsed string.
8928 #define NoValue 0x0000
8929 #define XValue 0x0001
8930 #define YValue 0x0002
8931 #define WidthValue 0x0004
8932 #define HeightValue 0x0008
8933 #define AllValues 0x000F
8934 #define XNegative 0x0010
8935 #define YNegative 0x0020
8937 /* Try not to reformat/modify, so we can compare/sync with X sources */
8939 gtk_XParseGeometry (const char *string,
8942 unsigned int *width,
8943 unsigned int *height)
8947 unsigned int tempWidth, tempHeight;
8949 char *nextCharacter;
8951 /* These initializations are just to silence gcc */
8957 if ( (string == NULL) || (*string == '\0')) return(mask);
8959 string++; /* ignore possible '=' at beg of geometry spec */
8961 strind = (char *)string;
8962 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8963 tempWidth = read_int(strind, &nextCharacter);
8964 if (strind == nextCharacter)
8966 strind = nextCharacter;
8970 if (*strind == 'x' || *strind == 'X') {
8972 tempHeight = read_int(strind, &nextCharacter);
8973 if (strind == nextCharacter)
8975 strind = nextCharacter;
8976 mask |= HeightValue;
8979 if ((*strind == '+') || (*strind == '-')) {
8980 if (*strind == '-') {
8982 tempX = -read_int(strind, &nextCharacter);
8983 if (strind == nextCharacter)
8985 strind = nextCharacter;
8991 tempX = read_int(strind, &nextCharacter);
8992 if (strind == nextCharacter)
8994 strind = nextCharacter;
8997 if ((*strind == '+') || (*strind == '-')) {
8998 if (*strind == '-') {
9000 tempY = -read_int(strind, &nextCharacter);
9001 if (strind == nextCharacter)
9003 strind = nextCharacter;
9010 tempY = read_int(strind, &nextCharacter);
9011 if (strind == nextCharacter)
9013 strind = nextCharacter;
9019 /* If strind isn't at the end of the string the it's an invalid
9020 geometry specification. */
9022 if (*strind != '\0') return (0);
9028 if (mask & WidthValue)
9030 if (mask & HeightValue)
9031 *height = tempHeight;
9036 * gtk_window_parse_geometry:
9037 * @window: a #GtkWindow
9038 * @geometry: geometry string
9040 * Parses a standard X Window System geometry string - see the
9041 * manual page for X (type 'man X') for details on this.
9042 * gtk_window_parse_geometry() does work on all GTK+ ports
9043 * including Win32 but is primarily intended for an X environment.
9045 * If either a size or a position can be extracted from the
9046 * geometry string, gtk_window_parse_geometry() returns %TRUE
9047 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9048 * to resize/move the window.
9050 * If gtk_window_parse_geometry() returns %TRUE, it will also
9051 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9052 * indicating to the window manager that the size/position of
9053 * the window was user-specified. This causes most window
9054 * managers to honor the geometry.
9056 * Note that for gtk_window_parse_geometry() to work as expected, it has
9057 * to be called when the window has its "final" size, i.e. after calling
9058 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9061 * #include <gtk/gtk.h>
9064 * fill_with_content (GtkWidget *vbox)
9066 * /* fill with content... */
9070 * main (int argc, char *argv[])
9072 * GtkWidget *window, *vbox;
9073 * GdkGeometry size_hints = {
9074 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9077 * gtk_init (&argc, &argv);
9079 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9080 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9082 * gtk_container_add (GTK_CONTAINER (window), vbox);
9083 * fill_with_content (vbox);
9084 * gtk_widget_show_all (vbox);
9086 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9089 * GDK_HINT_MIN_SIZE |
9090 * GDK_HINT_BASE_SIZE |
9091 * GDK_HINT_RESIZE_INC);
9095 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9096 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9099 * gtk_widget_show_all (window);
9106 * Return value: %TRUE if string was parsed successfully
9109 gtk_window_parse_geometry (GtkWindow *window,
9110 const gchar *geometry)
9112 gint result, x = 0, y = 0;
9116 gboolean size_set, pos_set;
9119 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9120 g_return_val_if_fail (geometry != NULL, FALSE);
9122 child = gtk_bin_get_child (GTK_BIN (window));
9123 if (!child || !gtk_widget_get_visible (child))
9124 g_warning ("gtk_window_parse_geometry() called on a window with no "
9125 "visible children; the window should be set up before "
9126 "gtk_window_parse_geometry() is called.");
9128 screen = gtk_window_check_screen (window);
9130 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9133 if ((result & WidthValue) || (result & HeightValue))
9135 gtk_window_set_default_size_internal (window,
9136 TRUE, result & WidthValue ? w : -1,
9137 TRUE, result & HeightValue ? h : -1,
9142 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9144 grav = GDK_GRAVITY_NORTH_WEST;
9146 if ((result & XNegative) && (result & YNegative))
9147 grav = GDK_GRAVITY_SOUTH_EAST;
9148 else if (result & XNegative)
9149 grav = GDK_GRAVITY_NORTH_EAST;
9150 else if (result & YNegative)
9151 grav = GDK_GRAVITY_SOUTH_WEST;
9153 if ((result & XValue) == 0)
9156 if ((result & YValue) == 0)
9159 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9160 grav == GDK_GRAVITY_SOUTH_EAST)
9161 y = gdk_screen_get_height (screen) - h + y;
9163 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9164 grav == GDK_GRAVITY_NORTH_EAST)
9165 x = gdk_screen_get_width (screen) - w + x;
9167 /* we don't let you put a window offscreen; maybe some people would
9168 * prefer to be able to, but it's kind of a bogus thing to do.
9177 if ((result & XValue) || (result & YValue))
9179 gtk_window_set_gravity (window, grav);
9180 gtk_window_move (window, x, y);
9184 if (size_set || pos_set)
9186 /* Set USSize, USPosition hints */
9187 GtkWindowGeometryInfo *info;
9189 info = gtk_window_get_geometry_info (window, TRUE);
9192 info->mask |= GDK_HINT_USER_POS;
9194 info->mask |= GDK_HINT_USER_SIZE;
9201 gtk_window_mnemonic_hash_foreach (guint keyval,
9207 GtkWindowKeysForeachFunc func;
9211 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9215 _gtk_window_keys_foreach (GtkWindow *window,
9216 GtkWindowKeysForeachFunc func,
9220 GtkMnemonicHash *mnemonic_hash;
9224 GtkWindowKeysForeachFunc func;
9228 info.window = window;
9230 info.func_data = func_data;
9232 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9234 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9235 gtk_window_mnemonic_hash_foreach, &info);
9237 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9240 GtkAccelGroup *group = groups->data;
9243 for (i = 0; i < group->priv->n_accels; i++)
9245 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9248 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9251 groups = groups->next;
9256 gtk_window_keys_changed (GtkWindow *window)
9258 gtk_window_free_key_hash (window);
9259 gtk_window_get_key_hash (window);
9262 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9264 struct _GtkWindowKeyEntry
9268 guint is_mnemonic : 1;
9272 window_key_entry_destroy (gpointer data)
9274 g_slice_free (GtkWindowKeyEntry, data);
9278 add_to_key_hash (GtkWindow *window,
9280 GdkModifierType modifiers,
9281 gboolean is_mnemonic,
9284 GtkKeyHash *key_hash = data;
9286 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9288 entry->keyval = keyval;
9289 entry->modifiers = modifiers;
9290 entry->is_mnemonic = is_mnemonic;
9292 /* GtkAccelGroup stores lowercased accelerators. To deal
9293 * with this, if <Shift> was specified, uppercase.
9295 if (modifiers & GDK_SHIFT_MASK)
9297 if (keyval == GDK_KEY_Tab)
9298 keyval = GDK_KEY_ISO_Left_Tab;
9300 keyval = gdk_keyval_to_upper (keyval);
9303 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9307 gtk_window_get_key_hash (GtkWindow *window)
9309 GdkScreen *screen = gtk_window_check_screen (window);
9310 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9315 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9316 (GDestroyNotify)window_key_entry_destroy);
9317 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9318 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9324 gtk_window_free_key_hash (GtkWindow *window)
9326 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9329 _gtk_key_hash_free (key_hash);
9330 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9335 * gtk_window_activate_key:
9336 * @window: a #GtkWindow
9337 * @event: a #GdkEventKey
9339 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9340 * called by the default ::key_press_event handler for toplevel windows,
9341 * however in some cases it may be useful to call this directly when
9342 * overriding the standard key handling for a toplevel window.
9344 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9349 gtk_window_activate_key (GtkWindow *window,
9352 GtkKeyHash *key_hash;
9353 GtkWindowKeyEntry *found_entry = NULL;
9354 gboolean enable_mnemonics;
9355 gboolean enable_accels;
9357 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9358 g_return_val_if_fail (event != NULL, FALSE);
9360 key_hash = gtk_window_get_key_hash (window);
9365 GSList *entries = _gtk_key_hash_lookup (key_hash,
9366 event->hardware_keycode,
9368 gtk_accelerator_get_default_mod_mask (),
9371 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9372 "gtk-enable-mnemonics", &enable_mnemonics,
9373 "gtk-enable-accels", &enable_accels,
9376 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9378 GtkWindowKeyEntry *entry = tmp_list->data;
9379 if (entry->is_mnemonic)
9381 if (enable_mnemonics)
9383 found_entry = entry;
9389 if (enable_accels && !found_entry)
9391 found_entry = entry;
9396 g_slist_free (entries);
9401 if (found_entry->is_mnemonic)
9403 if (enable_mnemonics)
9404 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9405 found_entry->modifiers);
9410 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9411 found_entry->modifiers);
9419 window_update_has_focus (GtkWindow *window)
9421 GtkWindowPrivate *priv = window->priv;
9422 GtkWidget *widget = GTK_WIDGET (window);
9423 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9425 if (has_focus != priv->has_focus)
9427 priv->has_focus = has_focus;
9431 if (priv->focus_widget &&
9432 priv->focus_widget != widget &&
9433 !gtk_widget_has_focus (priv->focus_widget))
9434 do_focus_change (priv->focus_widget, TRUE);
9438 if (priv->focus_widget &&
9439 priv->focus_widget != widget &&
9440 gtk_widget_has_focus (priv->focus_widget))
9441 do_focus_change (priv->focus_widget, FALSE);
9447 * _gtk_window_set_is_active:
9448 * @window: a #GtkWindow
9449 * @is_active: %TRUE if the window is in the currently active toplevel
9451 * Internal function that sets whether the #GtkWindow is part
9452 * of the currently active toplevel window (taking into account inter-process
9456 _gtk_window_set_is_active (GtkWindow *window,
9459 GtkWindowPrivate *priv;
9461 g_return_if_fail (GTK_IS_WINDOW (window));
9463 priv = window->priv;
9465 is_active = is_active != FALSE;
9467 if (is_active != priv->is_active)
9469 priv->is_active = is_active;
9470 window_update_has_focus (window);
9472 g_object_notify (G_OBJECT (window), "is-active");
9477 * _gtk_window_set_is_toplevel:
9478 * @window: a #GtkWindow
9479 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9480 * parent of the root window); %FALSE if it is not (for example, for an
9481 * in-process, parented GtkPlug)
9483 * Internal function used by #GtkPlug when it gets parented/unparented by a
9484 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9485 * global list of toplevel windows.
9488 _gtk_window_set_is_toplevel (GtkWindow *window,
9489 gboolean is_toplevel)
9493 widget = GTK_WIDGET (window);
9495 if (gtk_widget_is_toplevel (widget))
9496 g_assert (g_slist_find (toplevel_list, window) != NULL);
9498 g_assert (g_slist_find (toplevel_list, window) == NULL);
9500 if (is_toplevel == gtk_widget_is_toplevel (widget))
9505 _gtk_widget_set_is_toplevel (widget, TRUE);
9506 toplevel_list = g_slist_prepend (toplevel_list, window);
9510 _gtk_widget_set_is_toplevel (widget, FALSE);
9511 toplevel_list = g_slist_remove (toplevel_list, window);
9516 * _gtk_window_set_has_toplevel_focus:
9517 * @window: a #GtkWindow
9518 * @has_toplevel_focus: %TRUE if the in
9520 * Internal function that sets whether the keyboard focus for the
9521 * toplevel window (taking into account inter-process embedding.)
9524 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9525 gboolean has_toplevel_focus)
9527 GtkWindowPrivate *priv;
9529 g_return_if_fail (GTK_IS_WINDOW (window));
9531 priv = window->priv;
9533 has_toplevel_focus = has_toplevel_focus != FALSE;
9535 if (has_toplevel_focus != priv->has_toplevel_focus)
9537 priv->has_toplevel_focus = has_toplevel_focus;
9538 window_update_has_focus (window);
9540 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9545 * gtk_window_set_auto_startup_notification:
9546 * @setting: %TRUE to automatically do startup notification
9548 * By default, after showing the first #GtkWindow, GTK+ calls
9549 * gdk_notify_startup_complete(). Call this function to disable
9550 * the automatic startup notification. You might do this if your
9551 * first window is a splash screen, and you want to delay notification
9552 * until after your real main window has been shown, for example.
9554 * In that example, you would disable startup notification
9555 * temporarily, show your splash screen, then re-enable it so that
9556 * showing the main window would automatically result in notification.
9561 gtk_window_set_auto_startup_notification (gboolean setting)
9563 disable_startup_notification = !setting;
9567 * gtk_window_get_window_type:
9568 * @window: a #GtkWindow
9570 * Gets the type of the window. See #GtkWindowType.
9572 * Return value: the type of the window
9577 gtk_window_get_window_type (GtkWindow *window)
9579 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9581 return window->priv->type;
9585 * gtk_window_get_mnemonics_visible:
9586 * @window: a #GtkWindow
9588 * Gets the value of the #GtkWindow:mnemonics-visible property.
9590 * Returns: %TRUE if mnemonics are supposed to be visible
9596 gtk_window_get_mnemonics_visible (GtkWindow *window)
9598 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9600 return window->priv->mnemonics_visible;
9604 * gtk_window_set_mnemonics_visible:
9605 * @window: a #GtkWindow
9606 * @setting: the new value
9608 * Sets the #GtkWindow:mnemonics-visible property.
9613 gtk_window_set_mnemonics_visible (GtkWindow *window,
9616 GtkWindowPrivate *priv;
9618 g_return_if_fail (GTK_IS_WINDOW (window));
9620 priv = window->priv;
9622 setting = setting != FALSE;
9624 if (priv->mnemonics_visible != setting)
9626 priv->mnemonics_visible = setting;
9627 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9630 priv->mnemonics_visible_set = TRUE;
9634 _gtk_window_get_wmclass (GtkWindow *window,
9635 gchar **wmclass_name,
9636 gchar **wmclass_class)
9638 GtkWindowPrivate *priv = window->priv;
9640 *wmclass_name = priv->wmclass_name;
9641 *wmclass_class = priv->wmclass_class;