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/.
33 #include "gdk/gdkkeysyms.h"
37 #include "gtkprivate.h"
39 #include "gtkwindow.h"
40 #include "gtkwindow-decorate.h"
41 #include "gtkbindings.h"
42 #include "gtkkeyhash.h"
44 #include "gtkmnemonichash.h"
45 #include "gtkmenubar.h"
46 #include "gtkiconfactory.h"
47 #include "gtkicontheme.h"
48 #include "gtkmarshalers.h"
50 #include "gtkbuildable.h"
51 #include "gtkwidgetprivate.h"
53 #ifdef GDK_WINDOWING_X11
60 * @short_description: Toplevel which can contain other widgets
62 * A GtkWindow is a toplevel window which can contain other widgets.
63 * Windows normally have decorations that are under the control
64 * of the windowing system and allow the user to manipulate the window
65 * (resize it, move it, close it,...).
67 * GTK+ also allows windows to have a resize grip (a small area in the lower
68 * right or left corner) which can be clicked to reszie the window. To
69 * control whether a window has a resize grip, use
70 * gtk_window_set_has_resize_grip().
72 * <refsect2 id="GtkWindow-BUILDER-UI">
73 * <title>GtkWindow as GtkBuildable</title>
75 * The GtkWindow implementation of the GtkBuildable interface supports a
76 * custom <tag class="starttag">accel-groups</tag> element, which supports
77 * any number of <tag class="starttag">group</tag> elements representing the
78 * #GtkAccelGroup objects you want to add to your window (synonymous with
79 * gtk_window_add_accel_group().
82 * <title>A UI definition fragment with accel groups</title>
83 * <programlisting><![CDATA[
84 * <object class="GtkWindow">
86 * <group name="accelgroup1"/>
92 * <object class="GtkAccelGroup" id="accelgroup1"/>
93 * ]]></programlisting>
98 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
99 typedef struct _GtkWindowGroupPrivate GtkWindowGroupPrivate;
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;
301 #define GTK_WINDOW_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW_GROUP, GtkWindowGroupPrivate))
303 struct _GtkDeviceGrabInfo
307 guint block_others : 1;
310 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 gtk_decorated_window_init (window);
1140 g_signal_connect (priv->screen, "composited-changed",
1141 G_CALLBACK (gtk_window_on_composited_changed), window);
1145 gtk_window_set_property (GObject *object,
1147 const GValue *value,
1150 GtkWindow *window = GTK_WINDOW (object);
1151 GtkWindowPrivate *priv = window->priv;
1156 priv->type = g_value_get_enum (value);
1159 gtk_window_set_title (window, g_value_get_string (value));
1162 gtk_window_set_role (window, g_value_get_string (value));
1164 case PROP_STARTUP_ID:
1165 gtk_window_set_startup_id (window, g_value_get_string (value));
1167 case PROP_RESIZABLE:
1168 gtk_window_set_resizable (window, g_value_get_boolean (value));
1171 gtk_window_set_modal (window, g_value_get_boolean (value));
1174 gtk_window_set_position (window, g_value_get_enum (value));
1176 case PROP_DEFAULT_WIDTH:
1177 gtk_window_set_default_size_internal (window,
1178 TRUE, g_value_get_int (value),
1181 case PROP_DEFAULT_HEIGHT:
1182 gtk_window_set_default_size_internal (window,
1184 TRUE, g_value_get_int (value), FALSE);
1186 case PROP_DESTROY_WITH_PARENT:
1187 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1190 gtk_window_set_icon (window,
1191 g_value_get_object (value));
1193 case PROP_ICON_NAME:
1194 gtk_window_set_icon_name (window, g_value_get_string (value));
1197 gtk_window_set_screen (window, g_value_get_object (value));
1199 case PROP_TYPE_HINT:
1200 gtk_window_set_type_hint (window,
1201 g_value_get_enum (value));
1203 case PROP_SKIP_TASKBAR_HINT:
1204 gtk_window_set_skip_taskbar_hint (window,
1205 g_value_get_boolean (value));
1207 case PROP_SKIP_PAGER_HINT:
1208 gtk_window_set_skip_pager_hint (window,
1209 g_value_get_boolean (value));
1211 case PROP_URGENCY_HINT:
1212 gtk_window_set_urgency_hint (window,
1213 g_value_get_boolean (value));
1215 case PROP_ACCEPT_FOCUS:
1216 gtk_window_set_accept_focus (window,
1217 g_value_get_boolean (value));
1219 case PROP_FOCUS_ON_MAP:
1220 gtk_window_set_focus_on_map (window,
1221 g_value_get_boolean (value));
1223 case PROP_DECORATED:
1224 gtk_window_set_decorated (window, g_value_get_boolean (value));
1226 case PROP_DELETABLE:
1227 gtk_window_set_deletable (window, g_value_get_boolean (value));
1230 gtk_window_set_gravity (window, g_value_get_enum (value));
1232 case PROP_TRANSIENT_FOR:
1233 gtk_window_set_transient_for (window, g_value_get_object (value));
1236 gtk_window_set_opacity (window, g_value_get_double (value));
1238 case PROP_HAS_RESIZE_GRIP:
1239 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1241 case PROP_APPLICATION:
1242 gtk_window_set_application (window, g_value_get_object (value));
1244 case PROP_MNEMONICS_VISIBLE:
1245 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1248 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1254 gtk_window_get_property (GObject *object,
1259 GtkWindow *window = GTK_WINDOW (object);
1260 GtkWindowPrivate *priv = window->priv;
1264 GtkWindowGeometryInfo *info;
1266 g_value_set_enum (value, priv->type);
1269 g_value_set_string (value, priv->wm_role);
1272 g_value_set_string (value, priv->title);
1274 case PROP_RESIZABLE:
1275 g_value_set_boolean (value, priv->resizable);
1278 g_value_set_boolean (value, priv->modal);
1281 g_value_set_enum (value, priv->position);
1283 case PROP_DEFAULT_WIDTH:
1284 info = gtk_window_get_geometry_info (window, FALSE);
1286 g_value_set_int (value, -1);
1288 g_value_set_int (value, info->default_width);
1290 case PROP_DEFAULT_HEIGHT:
1291 info = gtk_window_get_geometry_info (window, FALSE);
1293 g_value_set_int (value, -1);
1295 g_value_set_int (value, info->default_height);
1297 case PROP_DESTROY_WITH_PARENT:
1298 g_value_set_boolean (value, priv->destroy_with_parent);
1301 g_value_set_object (value, gtk_window_get_icon (window));
1303 case PROP_ICON_NAME:
1304 g_value_set_string (value, gtk_window_get_icon_name (window));
1307 g_value_set_object (value, priv->screen);
1309 case PROP_IS_ACTIVE:
1310 g_value_set_boolean (value, priv->is_active);
1312 case PROP_HAS_TOPLEVEL_FOCUS:
1313 g_value_set_boolean (value, priv->has_toplevel_focus);
1315 case PROP_TYPE_HINT:
1316 g_value_set_enum (value, priv->type_hint);
1318 case PROP_SKIP_TASKBAR_HINT:
1319 g_value_set_boolean (value,
1320 gtk_window_get_skip_taskbar_hint (window));
1322 case PROP_SKIP_PAGER_HINT:
1323 g_value_set_boolean (value,
1324 gtk_window_get_skip_pager_hint (window));
1326 case PROP_URGENCY_HINT:
1327 g_value_set_boolean (value,
1328 gtk_window_get_urgency_hint (window));
1330 case PROP_ACCEPT_FOCUS:
1331 g_value_set_boolean (value,
1332 gtk_window_get_accept_focus (window));
1334 case PROP_FOCUS_ON_MAP:
1335 g_value_set_boolean (value,
1336 gtk_window_get_focus_on_map (window));
1338 case PROP_DECORATED:
1339 g_value_set_boolean (value, gtk_window_get_decorated (window));
1341 case PROP_DELETABLE:
1342 g_value_set_boolean (value, gtk_window_get_deletable (window));
1345 g_value_set_enum (value, gtk_window_get_gravity (window));
1347 case PROP_TRANSIENT_FOR:
1348 g_value_set_object (value, gtk_window_get_transient_for (window));
1351 g_value_set_double (value, gtk_window_get_opacity (window));
1353 case PROP_HAS_RESIZE_GRIP:
1354 g_value_set_boolean (value, priv->has_resize_grip);
1356 case PROP_RESIZE_GRIP_VISIBLE:
1357 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1359 case PROP_APPLICATION:
1360 g_value_set_object (value, gtk_window_get_application (window));
1362 case PROP_MNEMONICS_VISIBLE:
1363 g_value_set_boolean (value, priv->mnemonics_visible);
1366 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1372 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1374 parent_buildable_iface = g_type_interface_peek_parent (iface);
1375 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1376 iface->parser_finished = gtk_window_buildable_parser_finished;
1377 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1378 iface->custom_finished = gtk_window_buildable_custom_finished;
1382 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1383 GtkBuilder *builder,
1385 const GValue *value)
1387 GtkWindow *window = GTK_WINDOW (buildable);
1388 GtkWindowPrivate *priv = window->priv;
1390 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1391 priv->builder_visible = TRUE;
1393 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1397 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1398 GtkBuilder *builder)
1400 GtkWindow *window = GTK_WINDOW (buildable);
1401 GtkWindowPrivate *priv = window->priv;
1405 if (priv->builder_visible)
1406 gtk_widget_show (GTK_WIDGET (buildable));
1408 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1409 for (l = accels; l; l = l->next)
1411 object = gtk_builder_get_object (builder, l->data);
1414 g_warning ("Unknown accel group %s specified in window %s",
1415 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1418 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1419 GTK_ACCEL_GROUP (object));
1423 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1425 parent_buildable_iface->parser_finished (buildable, builder);
1431 } GSListSubParserData;
1434 window_start_element (GMarkupParseContext *context,
1435 const gchar *element_name,
1436 const gchar **names,
1437 const gchar **values,
1442 GSListSubParserData *data = (GSListSubParserData*)user_data;
1444 if (strcmp (element_name, "group") == 0)
1446 for (i = 0; names[i]; i++)
1448 if (strcmp (names[i], "name") == 0)
1449 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1452 else if (strcmp (element_name, "accel-groups") == 0)
1455 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1460 static const GMarkupParser window_parser =
1462 window_start_element
1466 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1467 GtkBuilder *builder,
1469 const gchar *tagname,
1470 GMarkupParser *parser,
1473 GSListSubParserData *parser_data;
1475 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1476 tagname, parser, data))
1479 if (strcmp (tagname, "accel-groups") == 0)
1481 parser_data = g_slice_new0 (GSListSubParserData);
1482 parser_data->items = NULL;
1483 parser_data->object = G_OBJECT (buildable);
1485 *parser = window_parser;
1486 *data = parser_data;
1494 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1495 GtkBuilder *builder,
1497 const gchar *tagname,
1500 GSListSubParserData *data;
1502 parent_buildable_iface->custom_finished (buildable, builder, child,
1503 tagname, user_data);
1505 if (strcmp (tagname, "accel-groups") != 0)
1508 data = (GSListSubParserData*)user_data;
1510 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1511 data->items, (GDestroyNotify) g_slist_free);
1513 g_slice_free (GSListSubParserData, data);
1518 * @type: type of window
1520 * Creates a new #GtkWindow, which is a toplevel window that can
1521 * contain other widgets. Nearly always, the type of the window should
1522 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1523 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1524 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1525 * dialogs, though in some other toolkits dialogs are called "popups".
1526 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1527 * On X11, popup windows are not controlled by the <link
1528 * linkend="gtk-X11-arch">window manager</link>.
1530 * If you simply want an undecorated window (no window borders), use
1531 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1533 * Return value: a new #GtkWindow.
1536 gtk_window_new (GtkWindowType type)
1538 GtkWindowPrivate *priv;
1541 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1543 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1544 priv = window->priv;
1548 return GTK_WIDGET (window);
1552 * gtk_window_set_title:
1553 * @window: a #GtkWindow
1554 * @title: title of the window
1556 * Sets the title of the #GtkWindow. The title of a window will be
1557 * displayed in its title bar; on the X Window System, the title bar
1558 * is rendered by the <link linkend="gtk-X11-arch">window
1559 * manager</link>, so exactly how the title appears to users may vary
1560 * according to a user's exact configuration. The title should help a
1561 * user distinguish this window from other windows they may have
1562 * open. A good title might include the application name and current
1563 * document filename, for example.
1567 gtk_window_set_title (GtkWindow *window,
1570 GtkWindowPrivate *priv;
1574 g_return_if_fail (GTK_IS_WINDOW (window));
1576 priv = window->priv;
1577 widget = GTK_WIDGET (window);
1579 new_title = g_strdup (title);
1580 g_free (priv->title);
1581 priv->title = new_title;
1583 if (gtk_widget_get_realized (widget))
1585 gdk_window_set_title (gtk_widget_get_window (widget),
1588 gtk_decorated_window_set_title (window, title);
1591 g_object_notify (G_OBJECT (window), "title");
1595 * gtk_window_get_title:
1596 * @window: a #GtkWindow
1598 * Retrieves the title of the window. See gtk_window_set_title().
1600 * Return value: the title of the window, or %NULL if none has
1601 * been set explicitely. The returned string is owned by the widget
1602 * and must not be modified or freed.
1604 G_CONST_RETURN gchar *
1605 gtk_window_get_title (GtkWindow *window)
1607 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1609 return window->priv->title;
1613 * gtk_window_set_wmclass:
1614 * @window: a #GtkWindow
1615 * @wmclass_name: window name hint
1616 * @wmclass_class: window class hint
1618 * Don't use this function. It sets the X Window System "class" and
1619 * "name" hints for a window. According to the ICCCM, you should
1620 * always set these to the same value for all windows in an
1621 * application, and GTK+ sets them to that value by default, so calling
1622 * this function is sort of pointless. However, you may want to call
1623 * gtk_window_set_role() on each window in your application, for the
1624 * benefit of the session manager. Setting the role allows the window
1625 * manager to restore window positions when loading a saved session.
1629 gtk_window_set_wmclass (GtkWindow *window,
1630 const gchar *wmclass_name,
1631 const gchar *wmclass_class)
1633 GtkWindowPrivate *priv;
1635 g_return_if_fail (GTK_IS_WINDOW (window));
1637 priv = window->priv;
1639 g_free (priv->wmclass_name);
1640 priv->wmclass_name = g_strdup (wmclass_name);
1642 g_free (priv->wmclass_class);
1643 priv->wmclass_class = g_strdup (wmclass_class);
1645 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1646 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1650 * gtk_window_set_role:
1651 * @window: a #GtkWindow
1652 * @role: unique identifier for the window to be used when restoring a session
1654 * This function is only useful on X11, not with other GTK+ targets.
1656 * In combination with the window title, the window role allows a
1657 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1658 * same" window when an application is restarted. So for example you
1659 * might set the "toolbox" role on your app's toolbox window, so that
1660 * when the user restarts their session, the window manager can put
1661 * the toolbox back in the same place.
1663 * If a window already has a unique title, you don't need to set the
1664 * role, since the WM can use the title to identify the window when
1665 * restoring the session.
1669 gtk_window_set_role (GtkWindow *window,
1672 GtkWindowPrivate *priv;
1675 g_return_if_fail (GTK_IS_WINDOW (window));
1677 priv = window->priv;
1679 new_role = g_strdup (role);
1680 g_free (priv->wm_role);
1681 priv->wm_role = new_role;
1683 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1684 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1687 g_object_notify (G_OBJECT (window), "role");
1691 * gtk_window_set_startup_id:
1692 * @window: a #GtkWindow
1693 * @startup_id: a string with startup-notification identifier
1695 * Startup notification identifiers are used by desktop environment to
1696 * track application startup, to provide user feedback and other
1697 * features. This function changes the corresponding property on the
1698 * underlying GdkWindow. Normally, startup identifier is managed
1699 * automatically and you should only use this function in special cases
1700 * like transferring focus from other processes. You should use this
1701 * function before calling gtk_window_present() or any equivalent
1702 * function generating a window map event.
1704 * This function is only useful on X11, not with other GTK+ targets.
1709 gtk_window_set_startup_id (GtkWindow *window,
1710 const gchar *startup_id)
1712 GtkWindowPrivate *priv;
1715 g_return_if_fail (GTK_IS_WINDOW (window));
1717 priv = window->priv;
1718 widget = GTK_WIDGET (window);
1720 g_free (priv->startup_id);
1721 priv->startup_id = g_strdup (startup_id);
1723 if (gtk_widget_get_realized (widget))
1725 GdkWindow *gdk_window;
1726 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1728 gdk_window = gtk_widget_get_window (widget);
1730 #ifdef GDK_WINDOWING_X11
1731 if (timestamp != GDK_CURRENT_TIME)
1732 gdk_x11_window_set_user_time (gdk_window, timestamp);
1735 /* Here we differentiate real and "fake" startup notification IDs,
1736 * constructed on purpose just to pass interaction timestamp
1738 if (startup_id_is_fake (priv->startup_id))
1739 gtk_window_present_with_time (window, timestamp);
1742 gdk_window_set_startup_id (gdk_window,
1745 /* If window is mapped, terminate the startup-notification too */
1746 if (gtk_widget_get_mapped (widget) &&
1747 !disable_startup_notification)
1748 gdk_notify_startup_complete_with_id (priv->startup_id);
1752 g_object_notify (G_OBJECT (window), "startup-id");
1756 * gtk_window_get_role:
1757 * @window: a #GtkWindow
1759 * Returns the role of the window. See gtk_window_set_role() for
1760 * further explanation.
1762 * Return value: the role of the window if set, or %NULL. The
1763 * returned is owned by the widget and must not be modified
1766 G_CONST_RETURN gchar *
1767 gtk_window_get_role (GtkWindow *window)
1769 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1771 return window->priv->wm_role;
1775 * gtk_window_set_focus:
1776 * @window: a #GtkWindow
1777 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1778 * any focus widget for the toplevel window.
1780 * If @focus is not the current focus widget, and is focusable, sets
1781 * it as the focus widget for the window. If @focus is %NULL, unsets
1782 * the focus widget for this window. To set the focus to a particular
1783 * widget in the toplevel, it is usually more convenient to use
1784 * gtk_widget_grab_focus() instead of this function.
1787 gtk_window_set_focus (GtkWindow *window,
1790 GtkWindowPrivate *priv;
1793 g_return_if_fail (GTK_IS_WINDOW (window));
1795 priv = window->priv;
1799 g_return_if_fail (GTK_IS_WIDGET (focus));
1800 g_return_if_fail (gtk_widget_get_can_focus (focus));
1804 gtk_widget_grab_focus (focus);
1807 /* Clear the existing focus chain, so that when we focus into
1808 * the window again, we start at the beginnning.
1810 GtkWidget *widget = priv->focus_widget;
1813 while ((parent = gtk_widget_get_parent (widget)))
1816 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1820 _gtk_window_internal_set_focus (window, NULL);
1825 _gtk_window_internal_set_focus (GtkWindow *window,
1828 GtkWindowPrivate *priv;
1830 g_return_if_fail (GTK_IS_WINDOW (window));
1832 priv = window->priv;
1834 if ((priv->focus_widget != focus) ||
1835 (focus && !gtk_widget_has_focus (focus)))
1836 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1840 * gtk_window_set_default:
1841 * @window: a #GtkWindow
1842 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1843 * default widget for the toplevel.
1845 * The default widget is the widget that's activated when the user
1846 * presses Enter in a dialog (for example). This function sets or
1847 * unsets the default widget for a #GtkWindow about. When setting
1848 * (rather than unsetting) the default widget it's generally easier to
1849 * call gtk_widget_grab_focus() on the widget. Before making a widget
1850 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1851 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1854 gtk_window_set_default (GtkWindow *window,
1855 GtkWidget *default_widget)
1857 GtkWindowPrivate *priv;
1859 g_return_if_fail (GTK_IS_WINDOW (window));
1861 priv = window->priv;
1864 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1866 if (priv->default_widget != default_widget)
1868 GtkWidget *old_default_widget = NULL;
1871 g_object_ref (default_widget);
1873 if (priv->default_widget)
1875 old_default_widget = priv->default_widget;
1877 if (priv->focus_widget != priv->default_widget ||
1878 !gtk_widget_get_receives_default (priv->default_widget))
1879 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1881 gtk_widget_queue_draw (priv->default_widget);
1884 priv->default_widget = default_widget;
1886 if (priv->default_widget)
1888 if (priv->focus_widget == NULL ||
1889 !gtk_widget_get_receives_default (priv->focus_widget))
1890 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1892 gtk_widget_queue_draw (priv->default_widget);
1895 if (old_default_widget)
1896 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1900 g_object_notify (G_OBJECT (default_widget), "has-default");
1901 g_object_unref (default_widget);
1907 * gtk_window_get_default_widget:
1908 * @window: a #GtkWindow
1910 * Returns the default widget for @window. See gtk_window_set_default()
1913 * Returns: (transfer none): the default widget, or %NULL if there is none.
1918 gtk_window_get_default_widget (GtkWindow *window)
1920 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1922 return window->priv->default_widget;
1926 handle_keys_changed (gpointer data)
1928 GtkWindow *window = GTK_WINDOW (data);
1929 GtkWindowPrivate *priv = window->priv;
1931 if (priv->keys_changed_handler)
1933 g_source_remove (priv->keys_changed_handler);
1934 priv->keys_changed_handler = 0;
1937 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1943 gtk_window_notify_keys_changed (GtkWindow *window)
1945 GtkWindowPrivate *priv = window->priv;
1947 if (!priv->keys_changed_handler)
1948 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1952 * gtk_window_add_accel_group:
1953 * @window: window to attach accelerator group to
1954 * @accel_group: a #GtkAccelGroup
1956 * Associate @accel_group with @window, such that calling
1957 * gtk_accel_groups_activate() on @window will activate accelerators
1961 gtk_window_add_accel_group (GtkWindow *window,
1962 GtkAccelGroup *accel_group)
1964 g_return_if_fail (GTK_IS_WINDOW (window));
1965 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1967 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1968 g_signal_connect_object (accel_group, "accel-changed",
1969 G_CALLBACK (gtk_window_notify_keys_changed),
1970 window, G_CONNECT_SWAPPED);
1971 gtk_window_notify_keys_changed (window);
1975 * gtk_window_remove_accel_group:
1976 * @window: a #GtkWindow
1977 * @accel_group: a #GtkAccelGroup
1979 * Reverses the effects of gtk_window_add_accel_group().
1982 gtk_window_remove_accel_group (GtkWindow *window,
1983 GtkAccelGroup *accel_group)
1985 g_return_if_fail (GTK_IS_WINDOW (window));
1986 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1988 g_signal_handlers_disconnect_by_func (accel_group,
1989 gtk_window_notify_keys_changed,
1991 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1992 gtk_window_notify_keys_changed (window);
1995 static GtkMnemonicHash *
1996 gtk_window_get_mnemonic_hash (GtkWindow *window,
1999 GtkWindowPrivate *private = window->priv;
2001 if (!private->mnemonic_hash && create)
2002 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2004 return private->mnemonic_hash;
2008 * gtk_window_add_mnemonic:
2009 * @window: a #GtkWindow
2010 * @keyval: the mnemonic
2011 * @target: the widget that gets activated by the mnemonic
2013 * Adds a mnemonic to this window.
2016 gtk_window_add_mnemonic (GtkWindow *window,
2020 g_return_if_fail (GTK_IS_WINDOW (window));
2021 g_return_if_fail (GTK_IS_WIDGET (target));
2023 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2025 gtk_window_notify_keys_changed (window);
2029 * gtk_window_remove_mnemonic:
2030 * @window: a #GtkWindow
2031 * @keyval: the mnemonic
2032 * @target: the widget that gets activated by the mnemonic
2034 * Removes a mnemonic from this window.
2037 gtk_window_remove_mnemonic (GtkWindow *window,
2041 g_return_if_fail (GTK_IS_WINDOW (window));
2042 g_return_if_fail (GTK_IS_WIDGET (target));
2044 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2046 gtk_window_notify_keys_changed (window);
2050 * gtk_window_mnemonic_activate:
2051 * @window: a #GtkWindow
2052 * @keyval: the mnemonic
2053 * @modifier: the modifiers
2054 * @returns: %TRUE if the activation is done.
2056 * Activates the targets associated with the mnemonic.
2059 gtk_window_mnemonic_activate (GtkWindow *window,
2061 GdkModifierType modifier)
2063 GtkWindowPrivate *priv;
2065 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2067 priv = window->priv;
2069 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2071 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2073 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2080 * gtk_window_set_mnemonic_modifier:
2081 * @window: a #GtkWindow
2082 * @modifier: the modifier mask used to activate
2083 * mnemonics on this window.
2085 * Sets the mnemonic modifier for this window.
2088 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2089 GdkModifierType modifier)
2091 GtkWindowPrivate *priv;
2093 g_return_if_fail (GTK_IS_WINDOW (window));
2094 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2096 priv = window->priv;
2098 priv->mnemonic_modifier = modifier;
2099 gtk_window_notify_keys_changed (window);
2103 * gtk_window_get_mnemonic_modifier:
2104 * @window: a #GtkWindow
2106 * Returns the mnemonic modifier for this window. See
2107 * gtk_window_set_mnemonic_modifier().
2109 * Return value: the modifier mask used to activate
2110 * mnemonics on this window.
2113 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2115 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2117 return window->priv->mnemonic_modifier;
2121 * gtk_window_set_position:
2122 * @window: a #GtkWindow.
2123 * @position: a position constraint.
2125 * Sets a position constraint for this window. If the old or new
2126 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2127 * the window to be repositioned to satisfy the new constraint.
2130 gtk_window_set_position (GtkWindow *window,
2131 GtkWindowPosition position)
2133 GtkWindowPrivate *priv;
2135 g_return_if_fail (GTK_IS_WINDOW (window));
2137 priv = window->priv;
2139 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2140 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2142 GtkWindowGeometryInfo *info;
2144 info = gtk_window_get_geometry_info (window, TRUE);
2146 /* this flag causes us to re-request the CENTER_ALWAYS
2147 * constraint in gtk_window_move_resize(), see
2148 * comment in that function.
2150 info->position_constraints_changed = TRUE;
2152 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2155 priv->position = position;
2157 g_object_notify (G_OBJECT (window), "window-position");
2161 * gtk_window_activate_focus:
2162 * @window: a #GtkWindow
2164 * Activates the current focused widget within the window.
2166 * Return value: %TRUE if a widget got activated.
2169 gtk_window_activate_focus (GtkWindow *window)
2171 GtkWindowPrivate *priv;
2173 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2175 priv = window->priv;
2177 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2178 return gtk_widget_activate (priv->focus_widget);
2184 * gtk_window_get_focus:
2185 * @window: a #GtkWindow
2187 * Retrieves the current focused widget within the window.
2188 * Note that this is the widget that would have the focus
2189 * if the toplevel window focused; if the toplevel window
2190 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2191 * not be %TRUE for the widget.
2193 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2196 gtk_window_get_focus (GtkWindow *window)
2198 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2200 return window->priv->focus_widget;
2204 * gtk_window_activate_default:
2205 * @window: a #GtkWindow
2207 * Activates the default widget for the window, unless the current
2208 * focused widget has been configured to receive the default action
2209 * (see gtk_widget_set_receives_default()), in which case the
2210 * focused widget is activated.
2212 * Return value: %TRUE if a widget got activated.
2215 gtk_window_activate_default (GtkWindow *window)
2217 GtkWindowPrivate *priv;
2219 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2221 priv = window->priv;
2223 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2224 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2225 return gtk_widget_activate (priv->default_widget);
2226 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2227 return gtk_widget_activate (priv->focus_widget);
2233 * gtk_window_set_modal:
2234 * @window: a #GtkWindow
2235 * @modal: whether the window is modal
2237 * Sets a window modal or non-modal. Modal windows prevent interaction
2238 * with other windows in the same application. To keep modal dialogs
2239 * on top of main application windows, use
2240 * gtk_window_set_transient_for() to make the dialog transient for the
2241 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2242 * will then disallow lowering the dialog below the parent.
2247 gtk_window_set_modal (GtkWindow *window,
2250 GtkWindowPrivate *priv;
2253 g_return_if_fail (GTK_IS_WINDOW (window));
2255 priv = window->priv;
2257 modal = modal != FALSE;
2258 if (priv->modal == modal)
2261 priv->modal = modal;
2262 widget = GTK_WIDGET (window);
2264 /* adjust desired modality state */
2265 if (gtk_widget_get_realized (widget))
2268 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2270 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2273 if (gtk_widget_get_visible (widget))
2276 gtk_grab_add (widget);
2278 gtk_grab_remove (widget);
2281 g_object_notify (G_OBJECT (window), "modal");
2285 * gtk_window_get_modal:
2286 * @window: a #GtkWindow
2288 * Returns whether the window is modal. See gtk_window_set_modal().
2290 * Return value: %TRUE if the window is set to be modal and
2291 * establishes a grab when shown
2294 gtk_window_get_modal (GtkWindow *window)
2296 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2298 return window->priv->modal;
2302 * gtk_window_list_toplevels:
2304 * Returns a list of all existing toplevel windows. The widgets
2305 * in the list are not individually referenced. If you want
2306 * to iterate through the list and perform actions involving
2307 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2308 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2309 * then unref all the widgets afterwards.
2311 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2314 gtk_window_list_toplevels (void)
2319 for (slist = toplevel_list; slist; slist = slist->next)
2320 list = g_list_prepend (list, slist->data);
2326 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2328 GList *embedded_windows;
2330 g_return_if_fail (GTK_IS_WINDOW (window));
2332 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2333 if (embedded_windows)
2334 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2335 embedded_windows = g_list_prepend (embedded_windows,
2336 GUINT_TO_POINTER (xid));
2338 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2341 (GDestroyNotify) g_list_free : NULL);
2345 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2347 GList *embedded_windows;
2350 g_return_if_fail (GTK_IS_WINDOW (window));
2352 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2353 if (embedded_windows)
2354 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2356 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2359 embedded_windows = g_list_remove_link (embedded_windows, node);
2360 g_list_free_1 (node);
2363 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2366 (GDestroyNotify) g_list_free : NULL);
2370 gtk_window_dispose (GObject *object)
2372 GtkWindow *window = GTK_WINDOW (object);
2374 gtk_window_set_focus (window, NULL);
2375 gtk_window_set_default (window, NULL);
2377 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2381 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2383 gtk_widget_destroy (GTK_WIDGET (child));
2387 connect_parent_destroyed (GtkWindow *window)
2389 GtkWindowPrivate *priv = window->priv;
2391 if (priv->transient_parent)
2393 g_signal_connect (priv->transient_parent,
2395 G_CALLBACK (parent_destroyed_callback),
2401 disconnect_parent_destroyed (GtkWindow *window)
2403 GtkWindowPrivate *priv = window->priv;
2405 if (priv->transient_parent)
2407 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2408 parent_destroyed_callback,
2414 gtk_window_transient_parent_realized (GtkWidget *parent,
2417 if (gtk_widget_get_realized (window))
2418 gdk_window_set_transient_for (gtk_widget_get_window (window),
2419 gtk_widget_get_window (parent));
2423 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2426 if (gtk_widget_get_realized (window))
2427 gdk_property_delete (gtk_widget_get_window (window),
2428 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2432 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2436 gtk_window_set_screen (window, parent->priv->screen);
2440 gtk_window_unset_transient_for (GtkWindow *window)
2442 GtkWindowPrivate *priv = window->priv;
2444 if (priv->transient_parent)
2446 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2447 gtk_window_transient_parent_realized,
2449 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2450 gtk_window_transient_parent_unrealized,
2452 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2453 gtk_window_transient_parent_screen_changed,
2455 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2456 gtk_widget_destroyed,
2457 &priv->transient_parent);
2459 if (priv->destroy_with_parent)
2460 disconnect_parent_destroyed (window);
2462 priv->transient_parent = NULL;
2464 if (priv->transient_parent_group)
2466 priv->transient_parent_group = FALSE;
2467 gtk_window_group_remove_window (priv->group,
2474 * gtk_window_set_transient_for:
2475 * @window: a #GtkWindow
2476 * @parent: (allow-none): parent window, or %NULL
2478 * Dialog windows should be set transient for the main application
2479 * window they were spawned from. This allows <link
2480 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2481 * dialog on top of the main window, or center the dialog over the
2482 * main window. gtk_dialog_new_with_buttons() and other convenience
2483 * functions in GTK+ will sometimes call
2484 * gtk_window_set_transient_for() on your behalf.
2486 * Passing %NULL for @parent unsets the current transient window.
2488 * On Windows, this function puts the child window on top of the parent,
2489 * much as the window manager would have done on X.
2492 gtk_window_set_transient_for (GtkWindow *window,
2495 GtkWindowPrivate *priv;
2497 g_return_if_fail (GTK_IS_WINDOW (window));
2498 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2499 g_return_if_fail (window != parent);
2501 priv = window->priv;
2503 if (priv->transient_parent)
2505 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2506 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2507 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2508 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2509 GTK_WIDGET (window));
2511 gtk_window_unset_transient_for (window);
2514 priv->transient_parent = parent;
2518 g_signal_connect (parent, "destroy",
2519 G_CALLBACK (gtk_widget_destroyed),
2520 &priv->transient_parent);
2521 g_signal_connect (parent, "realize",
2522 G_CALLBACK (gtk_window_transient_parent_realized),
2524 g_signal_connect (parent, "unrealize",
2525 G_CALLBACK (gtk_window_transient_parent_unrealized),
2527 g_signal_connect (parent, "notify::screen",
2528 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2531 gtk_window_set_screen (window, parent->priv->screen);
2533 if (priv->destroy_with_parent)
2534 connect_parent_destroyed (window);
2536 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2537 gtk_widget_get_realized (GTK_WIDGET (parent)))
2538 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2539 GTK_WIDGET (window));
2541 if (parent->priv->group)
2543 gtk_window_group_add_window (parent->priv->group, window);
2544 priv->transient_parent_group = TRUE;
2550 * gtk_window_get_transient_for:
2551 * @window: a #GtkWindow
2553 * Fetches the transient parent for this window. See
2554 * gtk_window_set_transient_for().
2556 * Return value: (transfer none): the transient parent for this window, or %NULL
2557 * if no transient parent has been set.
2560 gtk_window_get_transient_for (GtkWindow *window)
2562 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2564 return window->priv->transient_parent;
2568 * gtk_window_set_opacity:
2569 * @window: a #GtkWindow
2570 * @opacity: desired opacity, between 0 and 1
2572 * Request the windowing system to make @window partially transparent,
2573 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2574 * of the opacity parameter are clamped to the [0,1] range.) On X11
2575 * this has any effect only on X screens with a compositing manager
2576 * running. See gtk_widget_is_composited(). On Windows it should work
2579 * Note that setting a window's opacity after the window has been
2580 * shown causes it to flicker once on Windows.
2585 gtk_window_set_opacity (GtkWindow *window,
2588 GtkWindowPrivate *priv;
2590 g_return_if_fail (GTK_IS_WINDOW (window));
2592 priv = window->priv;
2596 else if (opacity > 1.0)
2599 priv->opacity_set = TRUE;
2600 priv->opacity = opacity;
2602 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2603 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2608 * gtk_window_get_opacity:
2609 * @window: a #GtkWindow
2611 * Fetches the requested opacity for this window. See
2612 * gtk_window_set_opacity().
2614 * Return value: the requested opacity for this window.
2619 gtk_window_get_opacity (GtkWindow *window)
2621 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2623 return window->priv->opacity;
2627 * gtk_window_get_application:
2628 * @window: a #GtkWindow
2630 * Gets the #GtkApplication associated with the window (if any).
2632 * Return value: a #GtkApplication, or %NULL
2637 gtk_window_get_application (GtkWindow *window)
2639 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2641 return window->priv->application;
2645 gtk_window_release_application (GtkWindow *window)
2647 if (window->priv->application)
2649 GtkApplication *application;
2651 /* steal reference into temp variable */
2652 application = window->priv->application;
2653 window->priv->application = NULL;
2655 gtk_application_remove_window (application, window);
2656 g_object_unref (application);
2661 * gtk_window_set_application:
2662 * @window: a #GtkWindow
2663 * @application: a #GtkApplication, or %NULL
2665 * Sets or unsets the #GtkApplication associated with the window.
2667 * The application will be kept alive for at least as long as the window
2673 gtk_window_set_application (GtkWindow *window,
2674 GtkApplication *application)
2676 GtkWindowPrivate *priv;
2678 g_return_if_fail (GTK_IS_WINDOW (window));
2680 priv = window->priv;
2681 if (priv->application != application)
2683 gtk_window_release_application (window);
2685 priv->application = application;
2687 if (priv->application != NULL)
2689 g_object_ref (priv->application);
2691 gtk_application_add_window (priv->application, window);
2694 g_object_notify (G_OBJECT (window), "application");
2699 * gtk_window_set_type_hint:
2700 * @window: a #GtkWindow
2701 * @hint: the window type
2703 * By setting the type hint for the window, you allow the window
2704 * manager to decorate and handle the window in a way which is
2705 * suitable to the function of the window in your application.
2707 * This function should be called before the window becomes visible.
2709 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2710 * will sometimes call gtk_window_set_type_hint() on your behalf.
2714 gtk_window_set_type_hint (GtkWindow *window,
2715 GdkWindowTypeHint hint)
2717 GtkWindowPrivate *priv;
2719 g_return_if_fail (GTK_IS_WINDOW (window));
2720 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2722 priv = window->priv;
2724 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2725 priv->gdk_type_hint = hint;
2727 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2729 priv->reset_type_hint = TRUE;
2730 priv->type_hint = hint;
2734 * gtk_window_get_type_hint:
2735 * @window: a #GtkWindow
2737 * Gets the type hint for this window. See gtk_window_set_type_hint().
2739 * Return value: the type hint for @window.
2742 gtk_window_get_type_hint (GtkWindow *window)
2744 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2746 return window->priv->type_hint;
2750 * gtk_window_set_skip_taskbar_hint:
2751 * @window: a #GtkWindow
2752 * @setting: %TRUE to keep this window from appearing in the task bar
2754 * Windows may set a hint asking the desktop environment not to display
2755 * the window in the task bar. This function sets this hint.
2760 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2763 GtkWindowPrivate *priv;
2765 g_return_if_fail (GTK_IS_WINDOW (window));
2767 priv = window->priv;
2769 setting = setting != FALSE;
2771 if (priv->skips_taskbar != setting)
2773 priv->skips_taskbar = setting;
2774 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2775 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2776 priv->skips_taskbar);
2777 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2782 * gtk_window_get_skip_taskbar_hint:
2783 * @window: a #GtkWindow
2785 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2787 * Return value: %TRUE if window shouldn't be in taskbar
2792 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2794 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2796 return window->priv->skips_taskbar;
2800 * gtk_window_set_skip_pager_hint:
2801 * @window: a #GtkWindow
2802 * @setting: %TRUE to keep this window from appearing in the pager
2804 * Windows may set a hint asking the desktop environment not to display
2805 * the window in the pager. This function sets this hint.
2806 * (A "pager" is any desktop navigation tool such as a workspace
2807 * switcher that displays a thumbnail representation of the windows
2813 gtk_window_set_skip_pager_hint (GtkWindow *window,
2816 GtkWindowPrivate *priv;
2818 g_return_if_fail (GTK_IS_WINDOW (window));
2820 priv = window->priv;
2822 setting = setting != FALSE;
2824 if (priv->skips_pager != setting)
2826 priv->skips_pager = setting;
2827 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2828 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2830 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2835 * gtk_window_get_skip_pager_hint:
2836 * @window: a #GtkWindow
2838 * Gets the value set by gtk_window_set_skip_pager_hint().
2840 * Return value: %TRUE if window shouldn't be in pager
2845 gtk_window_get_skip_pager_hint (GtkWindow *window)
2847 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2849 return window->priv->skips_pager;
2853 * gtk_window_set_urgency_hint:
2854 * @window: a #GtkWindow
2855 * @setting: %TRUE to mark this window as urgent
2857 * Windows may set a hint asking the desktop environment to draw
2858 * the users attention to the window. This function sets this hint.
2863 gtk_window_set_urgency_hint (GtkWindow *window,
2866 GtkWindowPrivate *priv;
2868 g_return_if_fail (GTK_IS_WINDOW (window));
2870 priv = window->priv;
2872 setting = setting != FALSE;
2874 if (priv->urgent != setting)
2876 priv->urgent = setting;
2877 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2878 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2880 g_object_notify (G_OBJECT (window), "urgency-hint");
2885 * gtk_window_get_urgency_hint:
2886 * @window: a #GtkWindow
2888 * Gets the value set by gtk_window_set_urgency_hint()
2890 * Return value: %TRUE if window is urgent
2895 gtk_window_get_urgency_hint (GtkWindow *window)
2897 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2899 return window->priv->urgent;
2903 * gtk_window_set_accept_focus:
2904 * @window: a #GtkWindow
2905 * @setting: %TRUE to let this window receive input focus
2907 * Windows may set a hint asking the desktop environment not to receive
2908 * the input focus. This function sets this hint.
2913 gtk_window_set_accept_focus (GtkWindow *window,
2916 GtkWindowPrivate *priv;
2918 g_return_if_fail (GTK_IS_WINDOW (window));
2920 priv = window->priv;
2922 setting = setting != FALSE;
2924 if (priv->accept_focus != setting)
2926 priv->accept_focus = setting;
2927 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2928 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2929 priv->accept_focus);
2930 g_object_notify (G_OBJECT (window), "accept-focus");
2935 * gtk_window_get_accept_focus:
2936 * @window: a #GtkWindow
2938 * Gets the value set by gtk_window_set_accept_focus().
2940 * Return value: %TRUE if window should receive the input focus
2945 gtk_window_get_accept_focus (GtkWindow *window)
2947 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2949 return window->priv->accept_focus;
2953 * gtk_window_set_focus_on_map:
2954 * @window: a #GtkWindow
2955 * @setting: %TRUE to let this window receive input focus on map
2957 * Windows may set a hint asking the desktop environment not to receive
2958 * the input focus when the window is mapped. This function sets this
2964 gtk_window_set_focus_on_map (GtkWindow *window,
2967 GtkWindowPrivate *priv;
2969 g_return_if_fail (GTK_IS_WINDOW (window));
2971 priv = window->priv;
2973 setting = setting != FALSE;
2975 if (priv->focus_on_map != setting)
2977 priv->focus_on_map = setting;
2978 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2979 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2980 priv->focus_on_map);
2981 g_object_notify (G_OBJECT (window), "focus-on-map");
2986 * gtk_window_get_focus_on_map:
2987 * @window: a #GtkWindow
2989 * Gets the value set by gtk_window_set_focus_on_map().
2991 * Return value: %TRUE if window should receive the input focus when
2997 gtk_window_get_focus_on_map (GtkWindow *window)
2999 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3001 return window->priv->focus_on_map;
3005 * gtk_window_set_destroy_with_parent:
3006 * @window: a #GtkWindow
3007 * @setting: whether to destroy @window with its transient parent
3009 * If @setting is %TRUE, then destroying the transient parent of @window
3010 * will also destroy @window itself. This is useful for dialogs that
3011 * shouldn't persist beyond the lifetime of the main window they're
3012 * associated with, for example.
3015 gtk_window_set_destroy_with_parent (GtkWindow *window,
3018 GtkWindowPrivate *priv;
3020 g_return_if_fail (GTK_IS_WINDOW (window));
3022 priv = window->priv;
3024 if (priv->destroy_with_parent == (setting != FALSE))
3027 if (priv->destroy_with_parent)
3029 disconnect_parent_destroyed (window);
3033 connect_parent_destroyed (window);
3036 priv->destroy_with_parent = setting;
3038 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3042 * gtk_window_get_destroy_with_parent:
3043 * @window: a #GtkWindow
3045 * Returns whether the window will be destroyed with its transient parent. See
3046 * gtk_window_set_destroy_with_parent ().
3048 * Return value: %TRUE if the window will be destroyed with its transient parent.
3051 gtk_window_get_destroy_with_parent (GtkWindow *window)
3053 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3055 return window->priv->destroy_with_parent;
3058 static GtkWindowGeometryInfo*
3059 gtk_window_get_geometry_info (GtkWindow *window,
3062 GtkWindowPrivate *priv = window->priv;
3063 GtkWindowGeometryInfo *info;
3065 info = priv->geometry_info;
3066 if (!info && create)
3068 info = g_new0 (GtkWindowGeometryInfo, 1);
3070 info->default_width = -1;
3071 info->default_height = -1;
3072 info->resize_width = -1;
3073 info->resize_height = -1;
3074 info->initial_x = 0;
3075 info->initial_y = 0;
3076 info->initial_pos_set = FALSE;
3077 info->default_is_geometry = FALSE;
3078 info->position_constraints_changed = FALSE;
3079 info->last.configure_request.x = 0;
3080 info->last.configure_request.y = 0;
3081 info->last.configure_request.width = -1;
3082 info->last.configure_request.height = -1;
3083 info->widget = NULL;
3085 priv->geometry_info = info;
3092 * gtk_window_set_geometry_hints:
3093 * @window: a #GtkWindow
3094 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3095 * @geometry: (allow-none): struct containing geometry information or %NULL
3096 * @geom_mask: mask indicating which struct fields should be paid attention to
3098 * This function sets up hints about how a window can be resized by
3099 * the user. You can set a minimum and maximum size; allowed resize
3100 * increments (e.g. for xterm, you can only resize by the size of a
3101 * character); aspect ratios; and more. See the #GdkGeometry struct.
3105 gtk_window_set_geometry_hints (GtkWindow *window,
3106 GtkWidget *geometry_widget,
3107 GdkGeometry *geometry,
3108 GdkWindowHints geom_mask)
3110 GtkWindowGeometryInfo *info;
3112 g_return_if_fail (GTK_IS_WINDOW (window));
3113 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3115 info = gtk_window_get_geometry_info (window, TRUE);
3118 g_signal_handlers_disconnect_by_func (info->widget,
3119 gtk_widget_destroyed,
3122 info->widget = geometry_widget;
3124 g_signal_connect (geometry_widget, "destroy",
3125 G_CALLBACK (gtk_widget_destroyed),
3129 info->geometry = *geometry;
3131 /* We store gravity in priv->gravity not in the hints. */
3132 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3134 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3136 gtk_window_set_gravity (window, geometry->win_gravity);
3139 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3143 * gtk_window_set_decorated:
3144 * @window: a #GtkWindow
3145 * @setting: %TRUE to decorate the window
3147 * By default, windows are decorated with a title bar, resize
3148 * controls, etc. Some <link linkend="gtk-X11-arch">window
3149 * managers</link> allow GTK+ to disable these decorations, creating a
3150 * borderless window. If you set the decorated property to %FALSE
3151 * using this function, GTK+ will do its best to convince the window
3152 * manager not to decorate the window. Depending on the system, this
3153 * function may not have any effect when called on a window that is
3154 * already visible, so you should call it before calling gtk_window_show().
3156 * On Windows, this function always works, since there's no window manager
3161 gtk_window_set_decorated (GtkWindow *window,
3164 GtkWindowPrivate *priv;
3165 GdkWindow *gdk_window;
3167 g_return_if_fail (GTK_IS_WINDOW (window));
3169 priv = window->priv;
3171 setting = setting != FALSE;
3173 if (setting == priv->decorated)
3176 priv->decorated = setting;
3178 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3181 if (priv->decorated)
3182 gdk_window_set_decorations (gdk_window,
3185 gdk_window_set_decorations (gdk_window,
3189 g_object_notify (G_OBJECT (window), "decorated");
3193 * gtk_window_get_decorated:
3194 * @window: a #GtkWindow
3196 * Returns whether the window has been set to have decorations
3197 * such as a title bar via gtk_window_set_decorated().
3199 * Return value: %TRUE if the window has been set to have decorations
3202 gtk_window_get_decorated (GtkWindow *window)
3204 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3206 return window->priv->decorated;
3210 * gtk_window_set_deletable:
3211 * @window: a #GtkWindow
3212 * @setting: %TRUE to decorate the window as deletable
3214 * By default, windows have a close button in the window frame. Some
3215 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3216 * disable this button. If you set the deletable property to %FALSE
3217 * using this function, GTK+ will do its best to convince the window
3218 * manager not to show a close button. Depending on the system, this
3219 * function may not have any effect when called on a window that is
3220 * already visible, so you should call it before calling gtk_window_show().
3222 * On Windows, this function always works, since there's no window manager
3228 gtk_window_set_deletable (GtkWindow *window,
3231 GtkWindowPrivate *priv;
3232 GdkWindow *gdk_window;
3234 g_return_if_fail (GTK_IS_WINDOW (window));
3236 priv = window->priv;
3238 setting = setting != FALSE;
3240 if (setting == priv->deletable)
3243 priv->deletable = setting;
3245 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3248 if (priv->deletable)
3249 gdk_window_set_functions (gdk_window,
3252 gdk_window_set_functions (gdk_window,
3253 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3256 g_object_notify (G_OBJECT (window), "deletable");
3260 * gtk_window_get_deletable:
3261 * @window: a #GtkWindow
3263 * Returns whether the window has been set to have a close button
3264 * via gtk_window_set_deletable().
3266 * Return value: %TRUE if the window has been set to have a close button
3271 gtk_window_get_deletable (GtkWindow *window)
3273 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3275 return window->priv->deletable;
3278 static GtkWindowIconInfo*
3279 get_icon_info (GtkWindow *window)
3281 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3285 free_icon_info (GtkWindowIconInfo *info)
3287 g_free (info->icon_name);
3288 g_slice_free (GtkWindowIconInfo, info);
3292 static GtkWindowIconInfo*
3293 ensure_icon_info (GtkWindow *window)
3295 GtkWindowIconInfo *info;
3297 info = get_icon_info (window);
3301 info = g_slice_new0 (GtkWindowIconInfo);
3302 g_object_set_qdata_full (G_OBJECT (window),
3303 quark_gtk_window_icon_info,
3305 (GDestroyNotify)free_icon_info);
3312 icon_list_from_theme (GtkWidget *widget,
3317 GtkIconTheme *icon_theme;
3322 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3324 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3327 for (i = 0; sizes[i]; i++)
3330 * We need an EWMH extension to handle scalable icons
3331 * by passing their name to the WM. For now just use a
3335 icon = gtk_icon_theme_load_icon (icon_theme, name,
3338 icon = gtk_icon_theme_load_icon (icon_theme, name,
3341 list = g_list_append (list, icon);
3351 gtk_window_realize_icon (GtkWindow *window)
3353 GtkWindowPrivate *priv = window->priv;
3355 GtkWindowIconInfo *info;
3356 GdkWindow *gdk_window;
3359 widget = GTK_WIDGET (window);
3360 gdk_window = gtk_widget_get_window (widget);
3362 g_return_if_fail (gdk_window != NULL);
3364 /* no point setting an icon on override-redirect */
3365 if (priv->type == GTK_WINDOW_POPUP)
3370 info = ensure_icon_info (window);
3375 info->using_default_icon = FALSE;
3376 info->using_parent_icon = FALSE;
3377 info->using_themed_icon = FALSE;
3379 icon_list = info->icon_list;
3381 /* Look up themed icon */
3382 if (icon_list == NULL && info->icon_name)
3384 icon_list = icon_list_from_theme (widget, info->icon_name);
3386 info->using_themed_icon = TRUE;
3389 /* Inherit from transient parent */
3390 if (icon_list == NULL && priv->transient_parent)
3392 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3394 info->using_parent_icon = TRUE;
3397 /* Inherit from default */
3398 if (icon_list == NULL)
3400 icon_list = default_icon_list;
3402 info->using_default_icon = TRUE;
3405 /* Look up themed icon */
3406 if (icon_list == NULL && default_icon_name)
3408 icon_list = icon_list_from_theme (widget, default_icon_name);
3409 info->using_default_icon = TRUE;
3410 info->using_themed_icon = TRUE;
3413 info->realized = TRUE;
3415 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3417 if (info->using_themed_icon)
3419 GtkIconTheme *icon_theme;
3421 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3422 g_list_free (icon_list);
3424 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3425 g_signal_connect (icon_theme, "changed",
3426 G_CALLBACK (update_themed_icon), window);
3431 gtk_window_unrealize_icon (GtkWindow *window)
3433 GtkWindowIconInfo *info;
3435 info = get_icon_info (window);
3440 if (info->using_themed_icon)
3442 GtkIconTheme *icon_theme;
3444 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3446 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3449 /* We don't clear the properties on the window, just figure the
3450 * window is going away.
3453 info->realized = FALSE;
3458 * gtk_window_set_icon_list:
3459 * @window: a #GtkWindow
3460 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3462 * Sets up the icon representing a #GtkWindow. The icon is used when
3463 * the window is minimized (also known as iconified). Some window
3464 * managers or desktop environments may also place it in the window
3465 * frame, or display it in other contexts.
3467 * gtk_window_set_icon_list() allows you to pass in the same icon in
3468 * several hand-drawn sizes. The list should contain the natural sizes
3469 * your icon is available in; that is, don't scale the image before
3470 * passing it to GTK+. Scaling is postponed until the last minute,
3471 * when the desired final size is known, to allow best quality.
3473 * By passing several sizes, you may improve the final image quality
3474 * of the icon, by reducing or eliminating automatic image scaling.
3476 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3477 * larger images (64x64, 128x128) if you have them.
3479 * See also gtk_window_set_default_icon_list() to set the icon
3480 * for all windows in your application in one go.
3482 * Note that transient windows (those who have been set transient for another
3483 * window using gtk_window_set_transient_for()) will inherit their
3484 * icon from their transient parent. So there's no need to explicitly
3485 * set the icon on transient windows.
3488 gtk_window_set_icon_list (GtkWindow *window,
3491 GtkWindowIconInfo *info;
3493 g_return_if_fail (GTK_IS_WINDOW (window));
3495 info = ensure_icon_info (window);
3497 if (info->icon_list == list) /* check for NULL mostly */
3500 g_list_foreach (list,
3501 (GFunc) g_object_ref, NULL);
3503 g_list_foreach (info->icon_list,
3504 (GFunc) g_object_unref, NULL);
3506 g_list_free (info->icon_list);
3508 info->icon_list = g_list_copy (list);
3510 g_object_notify (G_OBJECT (window), "icon");
3512 gtk_window_unrealize_icon (window);
3514 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3515 gtk_window_realize_icon (window);
3517 /* We could try to update our transient children, but I don't think
3518 * it's really worth it. If we did it, the best way would probably
3519 * be to have children connect to notify::icon-list
3524 * gtk_window_get_icon_list:
3525 * @window: a #GtkWindow
3527 * Retrieves the list of icons set by gtk_window_set_icon_list().
3528 * The list is copied, but the reference count on each
3529 * member won't be incremented.
3531 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3534 gtk_window_get_icon_list (GtkWindow *window)
3536 GtkWindowIconInfo *info;
3538 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3540 info = get_icon_info (window);
3543 return g_list_copy (info->icon_list);
3549 * gtk_window_set_icon:
3550 * @window: a #GtkWindow
3551 * @icon: (allow-none): icon image, or %NULL
3553 * Sets up the icon representing a #GtkWindow. This icon is used when
3554 * the window is minimized (also known as iconified). Some window
3555 * managers or desktop environments may also place it in the window
3556 * frame, or display it in other contexts.
3558 * The icon should be provided in whatever size it was naturally
3559 * drawn; that is, don't scale the image before passing it to
3560 * GTK+. Scaling is postponed until the last minute, when the desired
3561 * final size is known, to allow best quality.
3563 * If you have your icon hand-drawn in multiple sizes, use
3564 * gtk_window_set_icon_list(). Then the best size will be used.
3566 * This function is equivalent to calling gtk_window_set_icon_list()
3567 * with a 1-element list.
3569 * See also gtk_window_set_default_icon_list() to set the icon
3570 * for all windows in your application in one go.
3573 gtk_window_set_icon (GtkWindow *window,
3578 g_return_if_fail (GTK_IS_WINDOW (window));
3579 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3584 list = g_list_append (list, icon);
3586 gtk_window_set_icon_list (window, list);
3592 update_themed_icon (GtkIconTheme *icon_theme,
3595 g_object_notify (G_OBJECT (window), "icon");
3597 gtk_window_unrealize_icon (window);
3599 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3600 gtk_window_realize_icon (window);
3604 * gtk_window_set_icon_name:
3605 * @window: a #GtkWindow
3606 * @name: (allow-none): the name of the themed icon
3608 * Sets the icon for the window from a named themed icon. See
3609 * the docs for #GtkIconTheme for more details.
3611 * Note that this has nothing to do with the WM_ICON_NAME
3612 * property which is mentioned in the ICCCM.
3617 gtk_window_set_icon_name (GtkWindow *window,
3620 GtkWindowIconInfo *info;
3623 g_return_if_fail (GTK_IS_WINDOW (window));
3625 info = ensure_icon_info (window);
3627 if (g_strcmp0 (info->icon_name, name) == 0)
3630 tmp = info->icon_name;
3631 info->icon_name = g_strdup (name);
3634 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3635 g_list_free (info->icon_list);
3636 info->icon_list = NULL;
3638 update_themed_icon (NULL, window);
3640 g_object_notify (G_OBJECT (window), "icon-name");
3644 * gtk_window_get_icon_name:
3645 * @window: a #GtkWindow
3647 * Returns the name of the themed icon for the window,
3648 * see gtk_window_set_icon_name().
3650 * Returns: the icon name or %NULL if the window has
3656 gtk_window_get_icon_name (GtkWindow *window)
3658 GtkWindowIconInfo *info;
3660 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3662 info = ensure_icon_info (window);
3664 return info->icon_name;
3668 * gtk_window_get_icon:
3669 * @window: a #GtkWindow
3671 * Gets the value set by gtk_window_set_icon() (or if you've
3672 * called gtk_window_set_icon_list(), gets the first icon in
3675 * Return value: (transfer none): icon for window
3678 gtk_window_get_icon (GtkWindow *window)
3680 GtkWindowIconInfo *info;
3682 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3684 info = get_icon_info (window);
3685 if (info && info->icon_list)
3686 return GDK_PIXBUF (info->icon_list->data);
3691 /* Load pixbuf, printing warning on failure if error == NULL
3694 load_pixbuf_verbosely (const char *filename,
3697 GError *local_err = NULL;
3700 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3708 g_warning ("Error loading icon from file '%s':\n\t%s",
3709 filename, local_err->message);
3710 g_error_free (local_err);
3718 * gtk_window_set_icon_from_file:
3719 * @window: a #GtkWindow
3720 * @filename: location of icon file
3721 * @err: (allow-none): location to store error, or %NULL.
3723 * Sets the icon for @window.
3724 * Warns on failure if @err is %NULL.
3726 * This function is equivalent to calling gtk_window_set_icon()
3727 * with a pixbuf created by loading the image from @filename.
3729 * Returns: %TRUE if setting the icon succeeded.
3734 gtk_window_set_icon_from_file (GtkWindow *window,
3735 const gchar *filename,
3738 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3742 gtk_window_set_icon (window, pixbuf);
3743 g_object_unref (pixbuf);
3752 * gtk_window_set_default_icon_list:
3753 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3755 * Sets an icon list to be used as fallback for windows that haven't
3756 * had gtk_window_set_icon_list() called on them to set up a
3757 * window-specific icon list. This function allows you to set up the
3758 * icon for all windows in your app at once.
3760 * See gtk_window_set_icon_list() for more details.
3764 gtk_window_set_default_icon_list (GList *list)
3768 if (list == default_icon_list)
3771 /* Update serial so we don't used cached pixmaps/masks
3773 default_icon_serial++;
3775 g_list_foreach (list,
3776 (GFunc) g_object_ref, NULL);
3778 g_list_foreach (default_icon_list,
3779 (GFunc) g_object_unref, NULL);
3781 g_list_free (default_icon_list);
3783 default_icon_list = g_list_copy (list);
3785 /* Update all toplevels */
3786 toplevels = gtk_window_list_toplevels ();
3787 tmp_list = toplevels;
3788 while (tmp_list != NULL)
3790 GtkWindowIconInfo *info;
3791 GtkWindow *w = tmp_list->data;
3793 info = get_icon_info (w);
3794 if (info && info->using_default_icon)
3796 gtk_window_unrealize_icon (w);
3797 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3798 gtk_window_realize_icon (w);
3801 tmp_list = tmp_list->next;
3803 g_list_free (toplevels);
3807 * gtk_window_set_default_icon:
3810 * Sets an icon to be used as fallback for windows that haven't
3811 * had gtk_window_set_icon() called on them from a pixbuf.
3816 gtk_window_set_default_icon (GdkPixbuf *icon)
3820 g_return_if_fail (GDK_IS_PIXBUF (icon));
3822 list = g_list_prepend (NULL, icon);
3823 gtk_window_set_default_icon_list (list);
3828 * gtk_window_set_default_icon_name:
3829 * @name: the name of the themed icon
3831 * Sets an icon to be used as fallback for windows that haven't
3832 * had gtk_window_set_icon_list() called on them from a named
3833 * themed icon, see gtk_window_set_icon_name().
3838 gtk_window_set_default_icon_name (const gchar *name)
3843 /* Update serial so we don't used cached pixmaps/masks
3845 default_icon_serial++;
3847 g_free (default_icon_name);
3848 default_icon_name = g_strdup (name);
3850 g_list_foreach (default_icon_list,
3851 (GFunc) g_object_unref, NULL);
3853 g_list_free (default_icon_list);
3854 default_icon_list = NULL;
3856 /* Update all toplevels */
3857 toplevels = gtk_window_list_toplevels ();
3858 tmp_list = toplevels;
3859 while (tmp_list != NULL)
3861 GtkWindowIconInfo *info;
3862 GtkWindow *w = tmp_list->data;
3864 info = get_icon_info (w);
3865 if (info && info->using_default_icon && info->using_themed_icon)
3867 gtk_window_unrealize_icon (w);
3868 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3869 gtk_window_realize_icon (w);
3872 tmp_list = tmp_list->next;
3874 g_list_free (toplevels);
3878 * gtk_window_get_default_icon_name:
3880 * Returns the fallback icon name for windows that has been set
3881 * with gtk_window_set_default_icon_name(). The returned
3882 * string is owned by GTK+ and should not be modified. It
3883 * is only valid until the next call to
3884 * gtk_window_set_default_icon_name().
3886 * Returns: the fallback icon name for windows
3891 gtk_window_get_default_icon_name (void)
3893 return default_icon_name;
3897 * gtk_window_set_default_icon_from_file:
3898 * @filename: location of icon file
3899 * @err: (allow-none): location to store error, or %NULL.
3901 * Sets an icon to be used as fallback for windows that haven't
3902 * had gtk_window_set_icon_list() called on them from a file
3903 * on disk. Warns on failure if @err is %NULL.
3905 * Returns: %TRUE if setting the icon succeeded.
3910 gtk_window_set_default_icon_from_file (const gchar *filename,
3913 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3917 gtk_window_set_default_icon (pixbuf);
3918 g_object_unref (pixbuf);
3927 * gtk_window_get_default_icon_list:
3929 * Gets the value set by gtk_window_set_default_icon_list().
3930 * The list is a copy and should be freed with g_list_free(),
3931 * but the pixbufs in the list have not had their reference count
3934 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3937 gtk_window_get_default_icon_list (void)
3939 return g_list_copy (default_icon_list);
3943 gtk_window_set_default_size_internal (GtkWindow *window,
3944 gboolean change_width,
3946 gboolean change_height,
3948 gboolean is_geometry)
3950 GtkWindowGeometryInfo *info;
3952 g_return_if_fail (change_width == FALSE || width >= -1);
3953 g_return_if_fail (change_height == FALSE || height >= -1);
3955 info = gtk_window_get_geometry_info (window, TRUE);
3957 g_object_freeze_notify (G_OBJECT (window));
3959 info->default_is_geometry = is_geometry != FALSE;
3969 info->default_width = width;
3971 g_object_notify (G_OBJECT (window), "default-width");
3982 info->default_height = height;
3984 g_object_notify (G_OBJECT (window), "default-height");
3987 g_object_thaw_notify (G_OBJECT (window));
3989 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3993 * gtk_window_set_default_size:
3994 * @window: a #GtkWindow
3995 * @width: width in pixels, or -1 to unset the default width
3996 * @height: height in pixels, or -1 to unset the default height
3998 * Sets the default size of a window. If the window's "natural" size
3999 * (its size request) is larger than the default, the default will be
4000 * ignored. More generally, if the default size does not obey the
4001 * geometry hints for the window (gtk_window_set_geometry_hints() can
4002 * be used to set these explicitly), the default size will be clamped
4003 * to the nearest permitted size.
4005 * Unlike gtk_widget_set_size_request(), which sets a size request for
4006 * a widget and thus would keep users from shrinking the window, this
4007 * function only sets the initial size, just as if the user had
4008 * resized the window themselves. Users can still shrink the window
4009 * again as they normally would. Setting a default size of -1 means to
4010 * use the "natural" default size (the size request of the window).
4012 * For more control over a window's initial size and how resizing works,
4013 * investigate gtk_window_set_geometry_hints().
4015 * For some uses, gtk_window_resize() is a more appropriate function.
4016 * gtk_window_resize() changes the current size of the window, rather
4017 * than the size to be used on initial display. gtk_window_resize() always
4018 * affects the window itself, not the geometry widget.
4020 * The default size of a window only affects the first time a window is
4021 * shown; if a window is hidden and re-shown, it will remember the size
4022 * it had prior to hiding, rather than using the default size.
4024 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4025 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4028 gtk_window_set_default_size (GtkWindow *window,
4032 g_return_if_fail (GTK_IS_WINDOW (window));
4033 g_return_if_fail (width >= -1);
4034 g_return_if_fail (height >= -1);
4036 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4040 * gtk_window_set_default_geometry:
4041 * @window: a #GtkWindow
4042 * @width: width in resize increments, or -1 to unset the default width
4043 * @height: height in resize increments, or -1 to unset the default height
4045 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4046 * in terms of the base size and increment set with
4047 * gtk_window_set_geometry_hints.
4052 gtk_window_set_default_geometry (GtkWindow *window,
4056 g_return_if_fail (GTK_IS_WINDOW (window));
4057 g_return_if_fail (width >= -1);
4058 g_return_if_fail (height >= -1);
4060 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4064 * gtk_window_get_default_size:
4065 * @window: a #GtkWindow
4066 * @width: (out) (allow-none): location to store the default width, or %NULL
4067 * @height: (out) (allow-none): location to store the default height, or %NULL
4069 * Gets the default size of the window. A value of -1 for the width or
4070 * height indicates that a default size has not been explicitly set
4071 * for that dimension, so the "natural" size of the window will be
4076 gtk_window_get_default_size (GtkWindow *window,
4080 GtkWindowGeometryInfo *info;
4082 g_return_if_fail (GTK_IS_WINDOW (window));
4084 info = gtk_window_get_geometry_info (window, FALSE);
4087 *width = info ? info->default_width : -1;
4090 *height = info ? info->default_height : -1;
4094 * gtk_window_resize:
4095 * @window: a #GtkWindow
4096 * @width: width in pixels to resize the window to
4097 * @height: height in pixels to resize the window to
4099 * Resizes the window as if the user had done so, obeying geometry
4100 * constraints. The default geometry constraint is that windows may
4101 * not be smaller than their size request; to override this
4102 * constraint, call gtk_widget_set_size_request() to set the window's
4103 * request to a smaller value.
4105 * If gtk_window_resize() is called before showing a window for the
4106 * first time, it overrides any default size set with
4107 * gtk_window_set_default_size().
4109 * Windows may not be resized smaller than 1 by 1 pixels.
4113 gtk_window_resize (GtkWindow *window,
4117 GtkWindowGeometryInfo *info;
4119 g_return_if_fail (GTK_IS_WINDOW (window));
4120 g_return_if_fail (width > 0);
4121 g_return_if_fail (height > 0);
4123 info = gtk_window_get_geometry_info (window, TRUE);
4125 info->resize_width = width;
4126 info->resize_height = height;
4127 info->resize_is_geometry = FALSE;
4129 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4133 * gtk_window_resize_to_geometry:
4134 * @window: a #GtkWindow
4135 * @width: width in resize increments to resize the window to
4136 * @height: height in resize increments to resize the window to
4138 * Like gtk_window_resize(), but @width and @height are interpreted
4139 * in terms of the base size and increment set with
4140 * gtk_window_set_geometry_hints.
4145 gtk_window_resize_to_geometry (GtkWindow *window,
4149 GtkWindowGeometryInfo *info;
4151 g_return_if_fail (GTK_IS_WINDOW (window));
4152 g_return_if_fail (width > 0);
4153 g_return_if_fail (height > 0);
4155 info = gtk_window_get_geometry_info (window, TRUE);
4157 info->resize_width = width;
4158 info->resize_height = height;
4159 info->resize_is_geometry = TRUE;
4161 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4165 * gtk_window_get_size:
4166 * @window: a #GtkWindow
4167 * @width: (out) (allow-none): return location for width, or %NULL
4168 * @height: (out) (allow-none): return location for height, or %NULL
4170 * Obtains the current size of @window. If @window is not onscreen,
4171 * it returns the size GTK+ will suggest to the <link
4172 * linkend="gtk-X11-arch">window manager</link> for the initial window
4173 * size (but this is not reliably the same as the size the window
4174 * manager will actually select). The size obtained by
4175 * gtk_window_get_size() is the last size received in a
4176 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4177 * rather than querying the X server for the size. As a result, if you
4178 * call gtk_window_resize() then immediately call
4179 * gtk_window_get_size(), the size won't have taken effect yet. After
4180 * the window manager processes the resize request, GTK+ receives
4181 * notification that the size has changed via a configure event, and
4182 * the size of the window gets updated.
4184 * Note 1: Nearly any use of this function creates a race condition,
4185 * because the size of the window may change between the time that you
4186 * get the size and the time that you perform some action assuming
4187 * that size is the current size. To avoid race conditions, connect to
4188 * "configure-event" on the window and adjust your size-dependent
4189 * state to match the size delivered in the #GdkEventConfigure.
4191 * Note 2: The returned size does <emphasis>not</emphasis> include the
4192 * size of the window manager decorations (aka the window frame or
4193 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4194 * method of determining their size.
4196 * Note 3: If you are getting a window size in order to position
4197 * the window onscreen, there may be a better way. The preferred
4198 * way is to simply set the window's semantic type with
4199 * gtk_window_set_type_hint(), which allows the window manager to
4200 * e.g. center dialogs. Also, if you set the transient parent of
4201 * dialogs with gtk_window_set_transient_for() window managers
4202 * will often center the dialog over its parent window. It's
4203 * much preferred to let the window manager handle these
4204 * things rather than doing it yourself, because all apps will
4205 * behave consistently and according to user prefs if the window
4206 * manager handles it. Also, the window manager can take the size
4207 * of the window decorations/border into account, while your
4208 * application cannot.
4210 * In any case, if you insist on application-specified window
4211 * positioning, there's <emphasis>still</emphasis> a better way than
4212 * doing it yourself - gtk_window_set_position() will frequently
4213 * handle the details for you.
4217 gtk_window_get_size (GtkWindow *window,
4223 g_return_if_fail (GTK_IS_WINDOW (window));
4225 if (width == NULL && height == NULL)
4228 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4230 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4231 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4235 GdkRectangle configure_request;
4237 gtk_window_compute_configure_request (window,
4241 w = configure_request.width;
4242 h = configure_request.height;
4253 * @window: a #GtkWindow
4254 * @x: X coordinate to move window to
4255 * @y: Y coordinate to move window to
4257 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4258 * @window to the given position. Window managers are free to ignore
4259 * this; most window managers ignore requests for initial window
4260 * positions (instead using a user-defined placement algorithm) and
4261 * honor requests after the window has already been shown.
4263 * Note: the position is the position of the gravity-determined
4264 * reference point for the window. The gravity determines two things:
4265 * first, the location of the reference point in root window
4266 * coordinates; and second, which point on the window is positioned at
4267 * the reference point.
4269 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4270 * point is simply the @x, @y supplied to gtk_window_move(). The
4271 * top-left corner of the window decorations (aka window frame or
4272 * border) will be placed at @x, @y. Therefore, to position a window
4273 * at the top left of the screen, you want to use the default gravity
4274 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4276 * To position a window at the bottom right corner of the screen, you
4277 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4278 * point is at @x + the window width and @y + the window height, and
4279 * the bottom-right corner of the window border will be placed at that
4280 * reference point. So, to place a window in the bottom right corner
4281 * you would first set gravity to south east, then write:
4282 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4283 * gdk_screen_height () - window_height)</literal> (note that this
4284 * example does not take multi-head scenarios into account).
4286 * The Extended Window Manager Hints specification at <ulink
4287 * url="http://www.freedesktop.org/Standards/wm-spec">
4288 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4289 * nice table of gravities in the "implementation notes" section.
4291 * The gtk_window_get_position() documentation may also be relevant.
4294 gtk_window_move (GtkWindow *window,
4298 GtkWindowPrivate *priv;
4299 GtkWindowGeometryInfo *info;
4302 g_return_if_fail (GTK_IS_WINDOW (window));
4304 priv = window->priv;
4305 widget = GTK_WIDGET (window);
4307 info = gtk_window_get_geometry_info (window, TRUE);
4309 if (gtk_widget_get_mapped (widget))
4311 GtkAllocation allocation;
4313 gtk_widget_get_allocation (widget, &allocation);
4315 /* we have now sent a request with this position
4316 * with currently-active constraints, so toggle flag.
4318 info->position_constraints_changed = FALSE;
4320 /* we only constrain if mapped - if not mapped,
4321 * then gtk_window_compute_configure_request()
4322 * will apply the constraints later, and we
4323 * don't want to lose information about
4324 * what position the user set before then.
4325 * i.e. if you do a move() then turn off POS_CENTER
4326 * then show the window, your move() will work.
4328 gtk_window_constrain_position (window,
4329 allocation.width, allocation.height,
4332 /* Note that this request doesn't go through our standard request
4333 * framework, e.g. doesn't increment configure_request_count,
4334 * doesn't set info->last, etc.; that's because
4335 * we don't save the info needed to arrive at this same request
4338 * To gtk_window_move_resize(), this will end up looking exactly
4339 * the same as the position being changed by the window
4343 /* FIXME are we handling gravity properly for framed windows? */
4345 gdk_window_move (priv->frame,
4346 x - priv->frame_left,
4347 y - priv->frame_top);
4349 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)),
4354 /* Save this position to apply on mapping */
4355 info->initial_x = x;
4356 info->initial_y = y;
4357 info->initial_pos_set = TRUE;
4362 * gtk_window_get_position:
4363 * @window: a #GtkWindow
4364 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4365 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4367 * This function returns the position you need to pass to
4368 * gtk_window_move() to keep @window in its current position. This
4369 * means that the meaning of the returned value varies with window
4370 * gravity. See gtk_window_move() for more details.
4372 * If you haven't changed the window gravity, its gravity will be
4373 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4374 * gets the position of the top-left corner of the window manager
4375 * frame for the window. gtk_window_move() sets the position of this
4376 * same top-left corner.
4378 * gtk_window_get_position() is not 100% reliable because the X Window System
4379 * does not specify a way to obtain the geometry of the
4380 * decorations placed on a window by the window manager.
4381 * Thus GTK+ is using a "best guess" that works with most
4384 * Moreover, nearly all window managers are historically broken with
4385 * respect to their handling of window gravity. So moving a window to
4386 * its current position as returned by gtk_window_get_position() tends
4387 * to result in moving the window slightly. Window managers are
4388 * slowly getting better over time.
4390 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4391 * frame is not relevant, and thus gtk_window_get_position() will
4392 * always produce accurate results. However you can't use static
4393 * gravity to do things like place a window in a corner of the screen,
4394 * because static gravity ignores the window manager decorations.
4396 * If you are saving and restoring your application's window
4397 * positions, you should know that it's impossible for applications to
4398 * do this without getting it somewhat wrong because applications do
4399 * not have sufficient knowledge of window manager state. The Correct
4400 * Mechanism is to support the session management protocol (see the
4401 * "GnomeClient" object in the GNOME libraries for example) and allow
4402 * the window manager to save your window sizes and positions.
4407 gtk_window_get_position (GtkWindow *window,
4411 GtkWindowPrivate *priv;
4413 GdkWindow *gdk_window;
4415 g_return_if_fail (GTK_IS_WINDOW (window));
4417 priv = window->priv;
4418 widget = GTK_WIDGET (window);
4419 gdk_window = gtk_widget_get_window (widget);
4421 if (priv->gravity == GDK_GRAVITY_STATIC)
4423 if (gtk_widget_get_mapped (widget))
4425 /* This does a server round-trip, which is sort of wrong;
4426 * but a server round-trip is inevitable for
4427 * gdk_window_get_frame_extents() in the usual
4428 * NorthWestGravity case below, so not sure what else to
4429 * do. We should likely be consistent about whether we get
4430 * the client-side info or the server-side info.
4432 gdk_window_get_origin (gdk_window, root_x, root_y);
4436 GdkRectangle configure_request;
4438 gtk_window_compute_configure_request (window,
4442 *root_x = configure_request.x;
4443 *root_y = configure_request.y;
4448 GdkRectangle frame_extents;
4453 if (gtk_widget_get_mapped (widget))
4456 gdk_window_get_frame_extents (priv->frame, &frame_extents);
4458 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4459 x = frame_extents.x;
4460 y = frame_extents.y;
4461 gtk_window_get_size (window, &w, &h);
4465 /* We just say the frame has 0 size on all sides.
4466 * Not sure what else to do.
4468 gtk_window_compute_configure_request (window,
4471 x = frame_extents.x;
4472 y = frame_extents.y;
4473 w = frame_extents.width;
4474 h = frame_extents.height;
4477 switch (priv->gravity)
4479 case GDK_GRAVITY_NORTH:
4480 case GDK_GRAVITY_CENTER:
4481 case GDK_GRAVITY_SOUTH:
4482 /* Find center of frame. */
4483 x += frame_extents.width / 2;
4484 /* Center client window on that point. */
4488 case GDK_GRAVITY_SOUTH_EAST:
4489 case GDK_GRAVITY_EAST:
4490 case GDK_GRAVITY_NORTH_EAST:
4491 /* Find right edge of frame */
4492 x += frame_extents.width;
4493 /* Align left edge of client at that point. */
4500 switch (priv->gravity)
4502 case GDK_GRAVITY_WEST:
4503 case GDK_GRAVITY_CENTER:
4504 case GDK_GRAVITY_EAST:
4505 /* Find center of frame. */
4506 y += frame_extents.height / 2;
4507 /* Center client window there. */
4510 case GDK_GRAVITY_SOUTH_WEST:
4511 case GDK_GRAVITY_SOUTH:
4512 case GDK_GRAVITY_SOUTH_EAST:
4513 /* Find south edge of frame */
4514 y += frame_extents.height;
4515 /* Place bottom edge of client there */
4530 * gtk_window_reshow_with_initial_size:
4531 * @window: a #GtkWindow
4533 * Hides @window, then reshows it, resetting the
4534 * default size and position of the window. Used
4535 * by GUI builders only.
4538 gtk_window_reshow_with_initial_size (GtkWindow *window)
4542 g_return_if_fail (GTK_IS_WINDOW (window));
4544 widget = GTK_WIDGET (window);
4546 gtk_widget_hide (widget);
4547 gtk_widget_unrealize (widget);
4548 gtk_widget_show (widget);
4552 gtk_window_destroy (GtkWidget *widget)
4554 GtkWindow *window = GTK_WINDOW (widget);
4555 GtkWindowPrivate *priv = window->priv;
4557 toplevel_list = g_slist_remove (toplevel_list, window);
4559 if (priv->transient_parent)
4560 gtk_window_set_transient_for (window, NULL);
4562 /* frees the icons */
4563 gtk_window_set_icon_list (window, NULL);
4565 if (priv->has_user_ref_count)
4567 priv->has_user_ref_count = FALSE;
4568 g_object_unref (window);
4572 gtk_window_group_remove_window (priv->group, window);
4574 gtk_window_free_key_hash (window);
4576 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4580 gtk_window_finalize (GObject *object)
4582 GtkWindow *window = GTK_WINDOW (object);
4583 GtkWindowPrivate *priv = window->priv;
4584 GtkMnemonicHash *mnemonic_hash;
4586 g_free (priv->title);
4587 g_free (priv->wmclass_name);
4588 g_free (priv->wmclass_class);
4589 g_free (priv->wm_role);
4590 gtk_window_release_application (window);
4592 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4594 _gtk_mnemonic_hash_free (mnemonic_hash);
4596 if (priv->geometry_info)
4598 if (priv->geometry_info->widget)
4599 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4600 gtk_widget_destroyed,
4601 &priv->geometry_info->widget);
4602 g_free (priv->geometry_info);
4605 if (priv->keys_changed_handler)
4607 g_source_remove (priv->keys_changed_handler);
4608 priv->keys_changed_handler = 0;
4612 g_signal_handlers_disconnect_by_func (priv->screen,
4613 gtk_window_on_composited_changed, window);
4615 g_free (priv->startup_id);
4617 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4621 gtk_window_show (GtkWidget *widget)
4623 GtkWindow *window = GTK_WINDOW (widget);
4624 GtkWindowPrivate *priv = window->priv;
4625 GtkContainer *container = GTK_CONTAINER (window);
4626 gboolean need_resize;
4628 _gtk_widget_set_visible_flag (widget, TRUE);
4630 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4631 _gtk_container_set_need_resize (container, FALSE);
4635 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4636 GtkAllocation allocation = { 0, 0 };
4637 GdkRectangle configure_request;
4638 GdkGeometry new_geometry;
4640 gboolean was_realized;
4642 /* We are going to go ahead and perform this configure request
4643 * and then emulate a configure notify by going ahead and
4644 * doing a size allocate. Sort of a synchronous
4645 * mini-copy of gtk_window_move_resize() here.
4647 gtk_window_compute_configure_request (window,
4652 /* We update this because we are going to go ahead
4653 * and gdk_window_resize() below, rather than
4656 info->last.configure_request.width = configure_request.width;
4657 info->last.configure_request.height = configure_request.height;
4659 /* and allocate the window - this is normally done
4660 * in move_resize in response to configure notify
4662 allocation.width = configure_request.width;
4663 allocation.height = configure_request.height;
4664 gtk_widget_size_allocate (widget, &allocation);
4666 /* Then we guarantee we have a realize */
4667 was_realized = FALSE;
4668 if (!gtk_widget_get_realized (widget))
4670 gtk_widget_realize (widget);
4671 was_realized = TRUE;
4674 /* Must be done after the windows are realized,
4675 * so that the decorations can be read
4677 gtk_decorated_window_calculate_frame_size (window);
4679 /* We only send configure request if we didn't just finish
4680 * creating the window; if we just created the window
4681 * then we created it with widget->allocation anyhow.
4684 gdk_window_move_resize (gtk_widget_get_window (widget),
4685 configure_request.x,
4686 configure_request.y,
4687 configure_request.width,
4688 configure_request.height);
4691 gtk_container_check_resize (container);
4693 gtk_widget_map (widget);
4695 /* Try to make sure that we have some focused widget
4697 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4698 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4701 gtk_grab_add (widget);
4705 gtk_window_hide (GtkWidget *widget)
4707 GtkWindow *window = GTK_WINDOW (widget);
4708 GtkWindowPrivate *priv = window->priv;
4710 _gtk_widget_set_visible_flag (widget, FALSE);
4711 gtk_widget_unmap (widget);
4714 gtk_grab_remove (widget);
4718 gtk_window_map (GtkWidget *widget)
4721 GtkWindow *window = GTK_WINDOW (widget);
4722 GtkWindowPrivate *priv = window->priv;
4723 GdkWindow *toplevel;
4724 GdkWindow *gdk_window;
4725 gboolean auto_mnemonics;
4727 gdk_window = gtk_widget_get_window (widget);
4729 gtk_widget_set_mapped (widget, TRUE);
4731 child = gtk_bin_get_child (&(window->bin));
4733 gtk_widget_get_visible (child) &&
4734 !gtk_widget_get_mapped (child))
4735 gtk_widget_map (child);
4738 toplevel = priv->frame;
4740 toplevel = gdk_window;
4742 if (priv->maximize_initially)
4743 gdk_window_maximize (toplevel);
4745 gdk_window_unmaximize (toplevel);
4747 if (priv->stick_initially)
4748 gdk_window_stick (toplevel);
4750 gdk_window_unstick (toplevel);
4752 if (priv->iconify_initially)
4753 gdk_window_iconify (toplevel);
4755 gdk_window_deiconify (toplevel);
4757 if (priv->fullscreen_initially)
4758 gdk_window_fullscreen (toplevel);
4760 gdk_window_unfullscreen (toplevel);
4762 gdk_window_set_keep_above (toplevel, priv->above_initially);
4764 gdk_window_set_keep_below (toplevel, priv->below_initially);
4766 /* No longer use the default settings */
4767 priv->need_default_size = FALSE;
4768 priv->need_default_position = FALSE;
4770 if (priv->reset_type_hint)
4772 /* We should only reset the type hint when the application
4773 * used gtk_window_set_type_hint() to change the hint.
4774 * Some applications use X directly to change the properties;
4775 * in that case, we shouldn't overwrite what they did.
4777 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4778 priv->reset_type_hint = FALSE;
4781 gdk_window_show (gdk_window);
4784 gdk_window_show (priv->frame);
4786 if (priv->grip_window)
4787 gdk_window_show (priv->grip_window);
4789 if (!disable_startup_notification)
4791 /* Do we have a custom startup-notification id? */
4792 if (priv->startup_id != NULL)
4794 /* Make sure we have a "real" id */
4795 if (!startup_id_is_fake (priv->startup_id))
4796 gdk_notify_startup_complete_with_id (priv->startup_id);
4798 g_free (priv->startup_id);
4799 priv->startup_id = NULL;
4801 else if (!sent_startup_notification)
4803 sent_startup_notification = TRUE;
4804 gdk_notify_startup_complete ();
4808 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4809 * (as in the case of popup menus), then hide mnemonics initially
4811 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4812 &auto_mnemonics, NULL);
4813 if (auto_mnemonics && !priv->mnemonics_visible_set)
4814 gtk_window_set_mnemonics_visible (window, FALSE);
4818 gtk_window_map_event (GtkWidget *widget,
4821 if (!gtk_widget_get_mapped (widget))
4823 /* we should be be unmapped, but are getting a MapEvent, this may happen
4824 * to toplevel XWindows if mapping was intercepted by a window manager
4825 * and an unmap request occoured while the MapRequestEvent was still
4826 * being handled. we work around this situaiton here by re-requesting
4827 * the window being unmapped. more details can be found in:
4828 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4830 gdk_window_hide (gtk_widget_get_window (widget));
4836 gtk_window_unmap (GtkWidget *widget)
4838 GtkWindow *window = GTK_WINDOW (widget);
4839 GtkWindowPrivate *priv = window->priv;
4840 GtkWindowGeometryInfo *info;
4841 GdkWindow *gdk_window;
4842 GdkWindowState state;
4844 gdk_window = gtk_widget_get_window (widget);
4846 gtk_widget_set_mapped (widget, FALSE);
4848 gdk_window_withdraw (priv->frame);
4850 gdk_window_withdraw (gdk_window);
4852 priv->configure_request_count = 0;
4853 priv->configure_notify_received = FALSE;
4855 /* on unmap, we reset the default positioning of the window,
4856 * so it's placed again, but we don't reset the default
4857 * size of the window, so it's remembered.
4859 priv->need_default_position = TRUE;
4861 info = gtk_window_get_geometry_info (window, FALSE);
4864 info->initial_pos_set = FALSE;
4865 info->position_constraints_changed = FALSE;
4868 state = gdk_window_get_state (gdk_window);
4869 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4870 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4871 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4872 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4873 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4877 gtk_window_realize (GtkWidget *widget)
4879 GtkAllocation allocation;
4881 GdkWindow *parent_window;
4882 GdkWindow *gdk_window;
4883 GdkWindowAttr attributes;
4884 gint attributes_mask;
4885 GtkWindowPrivate *priv;
4886 GtkStyleContext *context;
4888 window = GTK_WINDOW (widget);
4889 priv = window->priv;
4891 gtk_widget_get_allocation (widget, &allocation);
4893 /* ensure widget tree is properly size allocated */
4894 if (allocation.x == -1 &&
4895 allocation.y == -1 &&
4896 allocation.width == 1 &&
4897 allocation.height == 1)
4899 GtkRequisition requisition;
4903 allocation.width = 200;
4904 allocation.height = 200;
4906 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4907 if (requisition.width || requisition.height)
4909 /* non-empty window */
4910 allocation.width = requisition.width;
4911 allocation.height = requisition.height;
4913 gtk_widget_size_allocate (widget, &allocation);
4915 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4917 g_return_if_fail (!gtk_widget_get_realized (widget));
4920 gtk_widget_set_realized (widget, TRUE);
4924 case GTK_WINDOW_TOPLEVEL:
4925 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4927 case GTK_WINDOW_POPUP:
4928 attributes.window_type = GDK_WINDOW_TEMP;
4931 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4935 attributes.title = priv->title;
4936 attributes.wmclass_name = priv->wmclass_name;
4937 attributes.wmclass_class = priv->wmclass_class;
4938 attributes.wclass = GDK_INPUT_OUTPUT;
4939 attributes.visual = gtk_widget_get_visual (widget);
4941 if (priv->has_frame)
4943 gtk_widget_get_allocation (widget, &allocation);
4944 attributes.width = allocation.width + priv->frame_left + priv->frame_right;
4945 attributes.height = allocation.height + priv->frame_top + priv->frame_bottom;
4946 attributes.event_mask = (GDK_EXPOSURE_MASK |
4947 GDK_KEY_PRESS_MASK |
4948 GDK_ENTER_NOTIFY_MASK |
4949 GDK_LEAVE_NOTIFY_MASK |
4950 GDK_FOCUS_CHANGE_MASK |
4951 GDK_STRUCTURE_MASK |
4952 GDK_BUTTON_MOTION_MASK |
4953 GDK_POINTER_MOTION_HINT_MASK |
4954 GDK_BUTTON_PRESS_MASK |
4955 GDK_BUTTON_RELEASE_MASK);
4957 attributes_mask = GDK_WA_VISUAL;
4959 priv->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4960 &attributes, attributes_mask);
4962 if (priv->opacity_set)
4963 gdk_window_set_opacity (priv->frame, priv->opacity);
4965 gdk_window_set_user_data (priv->frame, widget);
4967 attributes.window_type = GDK_WINDOW_CHILD;
4968 attributes.x = priv->frame_left;
4969 attributes.y = priv->frame_top;
4971 attributes_mask = GDK_WA_X | GDK_WA_Y;
4973 parent_window = priv->frame;
4975 g_signal_connect (window,
4977 G_CALLBACK (gtk_window_event),
4982 attributes_mask = 0;
4983 parent_window = gtk_widget_get_root_window (widget);
4986 gtk_widget_get_allocation (widget, &allocation);
4987 attributes.width = allocation.width;
4988 attributes.height = allocation.height;
4989 attributes.event_mask = gtk_widget_get_events (widget);
4990 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4991 GDK_KEY_PRESS_MASK |
4992 GDK_KEY_RELEASE_MASK |
4993 GDK_ENTER_NOTIFY_MASK |
4994 GDK_LEAVE_NOTIFY_MASK |
4995 GDK_FOCUS_CHANGE_MASK |
4996 GDK_STRUCTURE_MASK);
4997 attributes.type_hint = priv->type_hint;
4999 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5000 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5001 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5003 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5004 gtk_widget_set_window (widget, gdk_window);
5006 if (!priv->has_frame && priv->opacity_set)
5007 gdk_window_set_opacity (gdk_window, priv->opacity);
5009 gdk_window_enable_synchronized_configure (gdk_window);
5011 gdk_window_set_user_data (gdk_window, window);
5013 gtk_widget_style_attach (widget);
5014 context = gtk_widget_get_style_context (widget);
5016 gtk_style_context_set_background (context, gdk_window);
5018 gtk_style_context_set_background (context, priv->frame);
5020 if (priv->transient_parent &&
5021 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5022 gdk_window_set_transient_for (gdk_window,
5023 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5026 gdk_window_set_role (gdk_window, priv->wm_role);
5028 if (!priv->decorated)
5029 gdk_window_set_decorations (gdk_window, 0);
5031 if (!priv->deletable)
5032 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5034 if (gtk_window_get_skip_pager_hint (window))
5035 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5037 if (gtk_window_get_skip_taskbar_hint (window))
5038 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5040 if (gtk_window_get_accept_focus (window))
5041 gdk_window_set_accept_focus (gdk_window, TRUE);
5043 gdk_window_set_accept_focus (gdk_window, FALSE);
5045 if (gtk_window_get_focus_on_map (window))
5046 gdk_window_set_focus_on_map (gdk_window, TRUE);
5048 gdk_window_set_focus_on_map (gdk_window, FALSE);
5051 gdk_window_set_modal_hint (gdk_window, TRUE);
5053 gdk_window_set_modal_hint (gdk_window, FALSE);
5055 if (priv->startup_id)
5057 #ifdef GDK_WINDOWING_X11
5058 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5059 if (timestamp != GDK_CURRENT_TIME)
5060 gdk_x11_window_set_user_time (gdk_window, timestamp);
5062 if (!startup_id_is_fake (priv->startup_id))
5063 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5067 gtk_window_realize_icon (window);
5069 if (priv->has_resize_grip)
5070 resize_grip_create_window (window);
5074 gtk_window_unrealize (GtkWidget *widget)
5076 GtkWindow *window = GTK_WINDOW (widget);
5077 GtkWindowPrivate *priv = window->priv;
5078 GtkWindowGeometryInfo *info;
5080 /* On unrealize, we reset the size of the window such
5081 * that we will re-apply the default sizing stuff
5082 * next time we show the window.
5084 * Default positioning is reset on unmap, instead of unrealize.
5086 priv->need_default_size = TRUE;
5087 info = gtk_window_get_geometry_info (window, FALSE);
5090 info->resize_width = -1;
5091 info->resize_height = -1;
5092 info->last.configure_request.x = 0;
5093 info->last.configure_request.y = 0;
5094 info->last.configure_request.width = -1;
5095 info->last.configure_request.height = -1;
5096 /* be sure we reset geom hints on re-realize */
5097 info->last.flags = 0;
5102 gdk_window_set_user_data (priv->frame, NULL);
5103 gdk_window_destroy (priv->frame);
5108 gtk_window_unrealize_icon (window);
5110 if (priv->grip_window != NULL)
5111 resize_grip_destroy_window (window);
5113 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5116 static GtkJunctionSides
5117 get_grip_junction (GtkWidget *widget)
5119 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5120 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5122 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5126 get_drag_edge (GtkWidget *widget,
5127 GdkWindowEdge *edge)
5129 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5130 gboolean hresizable;
5131 gboolean vresizable;
5132 GtkTextDirection dir;
5133 GtkWindowGeometryInfo *info;
5138 info = priv->geometry_info;
5141 GdkWindowHints flags = info->last.flags;
5142 GdkGeometry *geometry = &info->last.geometry;
5144 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5146 hresizable = geometry->min_width < geometry->max_width;
5147 vresizable = geometry->min_height < geometry->max_height;
5151 dir = gtk_widget_get_direction (widget);
5153 if (hresizable && vresizable)
5154 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5155 else if (hresizable)
5156 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5157 else if (vresizable)
5158 *edge = GDK_WINDOW_EDGE_SOUTH;
5166 set_grip_cursor (GtkWindow *window)
5168 GtkWidget *widget = GTK_WIDGET (window);
5169 GtkWindowPrivate *priv = window->priv;
5171 if (priv->grip_window == NULL)
5174 if (gtk_widget_is_sensitive (widget))
5177 GdkDisplay *display;
5178 GdkCursorType cursor_type;
5181 cursor_type = GDK_LEFT_PTR;
5183 if (get_drag_edge (widget, &edge))
5187 case GDK_WINDOW_EDGE_EAST:
5188 cursor_type = GDK_RIGHT_SIDE;
5190 case GDK_WINDOW_EDGE_SOUTH_EAST:
5191 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5193 case GDK_WINDOW_EDGE_SOUTH:
5194 cursor_type = GDK_BOTTOM_SIDE;
5196 case GDK_WINDOW_EDGE_SOUTH_WEST:
5197 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5199 case GDK_WINDOW_EDGE_WEST:
5200 cursor_type = GDK_LEFT_SIDE;
5206 display = gtk_widget_get_display (widget);
5207 cursor = gdk_cursor_new_for_display (display, cursor_type);
5208 gdk_window_set_cursor (priv->grip_window, cursor);
5209 gdk_cursor_unref (cursor);
5212 gdk_window_set_cursor (priv->grip_window, NULL);
5216 set_grip_shape (GtkWindow *window)
5218 GtkWindowPrivate *priv = window->priv;
5219 cairo_region_t *region;
5220 cairo_surface_t *surface;
5222 double width, height;
5224 if (priv->grip_window == NULL)
5227 width = gdk_window_get_width (priv->grip_window);
5228 height = gdk_window_get_height (priv->grip_window);
5229 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5231 cr = cairo_create (surface);
5232 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5234 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5235 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5237 cairo_move_to (cr, width, 0.0);
5238 cairo_line_to (cr, width, height);
5239 cairo_line_to (cr, 0.0, height);
5243 cairo_move_to (cr, 0.0, 0.0);
5244 cairo_line_to (cr, width, height);
5245 cairo_line_to (cr, 0.0, height);
5247 cairo_close_path (cr);
5250 region = gdk_cairo_region_create_from_surface (surface);
5251 cairo_surface_destroy (surface);
5253 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5254 cairo_region_destroy (region);
5258 set_grip_position (GtkWindow *window)
5260 GtkWindowPrivate *priv = window->priv;
5263 if (priv->grip_window == NULL)
5266 gtk_window_get_resize_grip_area (window, &rect);
5267 gdk_window_raise (priv->grip_window);
5268 gdk_window_move_resize (priv->grip_window,
5270 rect.width, rect.height);
5274 gtk_window_size_allocate (GtkWidget *widget,
5275 GtkAllocation *allocation)
5277 GtkWindow *window = GTK_WINDOW (widget);
5278 GtkWindowPrivate *priv = window->priv;
5279 GtkAllocation child_allocation;
5283 gtk_widget_set_allocation (widget, allocation);
5285 child = gtk_bin_get_child (&(window->bin));
5286 if (child && gtk_widget_get_visible (child))
5288 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5289 child_allocation.x = border_width;
5290 child_allocation.y = border_width;
5291 child_allocation.width =
5292 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5293 child_allocation.height =
5294 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5296 gtk_widget_size_allocate (child, &child_allocation);
5299 if (gtk_widget_get_realized (widget))
5302 gdk_window_resize (priv->frame,
5303 allocation->width + priv->frame_left + priv->frame_right,
5304 allocation->height + priv->frame_top + priv->frame_bottom);
5305 update_grip_visibility (window);
5306 set_grip_position (window);
5311 gtk_window_event (GtkWidget *widget, GdkEvent *event)
5313 GtkWindow *window = GTK_WINDOW (widget);
5314 GtkWindowPrivate *priv = window->priv;
5315 gboolean return_val;
5317 if (priv->frame && (event->any.window == priv->frame))
5319 if ((event->type != GDK_KEY_PRESS) &&
5320 (event->type != GDK_KEY_RELEASE) &&
5321 (event->type != GDK_FOCUS_CHANGE))
5323 g_signal_stop_emission_by_name (widget, "event");
5325 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
5330 g_object_unref (event->any.window);
5331 event->any.window = g_object_ref (gtk_widget_get_window (widget));
5339 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
5341 GtkWindowPrivate *priv = window->priv;
5342 GdkEventConfigure *configure_event;
5345 switch (event->type)
5348 configure_event = (GdkEventConfigure *)event;
5350 /* Invalidate the decorations */
5353 rect.width = configure_event->width;
5354 rect.height = configure_event->height;
5356 gdk_window_invalidate_rect (priv->frame, &rect, FALSE);
5358 /* Pass on the (modified) configure event */
5359 configure_event->width -= priv->frame_left + priv->frame_right;
5360 configure_event->height -= priv->frame_top + priv->frame_bottom;
5361 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5370 gtk_window_configure_event (GtkWidget *widget,
5371 GdkEventConfigure *event)
5373 GtkAllocation allocation;
5374 GtkWindow *window = GTK_WINDOW (widget);
5375 GtkWindowPrivate *priv = window->priv;
5376 gboolean expected_reply = priv->configure_request_count > 0;
5378 /* priv->configure_request_count incremented for each
5379 * configure request, and decremented to a min of 0 for
5380 * each configure notify.
5382 * All it means is that we know we will get at least
5383 * priv->configure_request_count more configure notifies.
5384 * We could get more configure notifies than that; some
5385 * of the configure notifies we get may be unrelated to
5386 * the configure requests. But we will get at least
5387 * priv->configure_request_count notifies.
5390 if (priv->configure_request_count > 0)
5392 priv->configure_request_count -= 1;
5393 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5396 /* As an optimization, we avoid a resize when possible.
5398 * The only times we can avoid a resize are:
5399 * - we know only the position changed, not the size
5400 * - we know we have made more requests and so will get more
5401 * notifies and can wait to resize when we get them
5403 gtk_widget_get_allocation (widget, &allocation);
5404 if (!expected_reply &&
5405 (allocation.width == event->width &&
5406 allocation.height == event->height))
5408 gdk_window_configure_finished (gtk_widget_get_window (widget));
5413 * If we do need to resize, we do that by:
5414 * - filling in widget->allocation with the new size
5415 * - setting configure_notify_received to TRUE
5416 * for use in gtk_window_move_resize()
5417 * - queueing a resize, leading to invocation of
5418 * gtk_window_move_resize() in an idle handler
5422 priv->configure_notify_received = TRUE;
5424 allocation.width = event->width;
5425 allocation.height = event->height;
5426 gtk_widget_set_allocation (widget, &allocation);
5428 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5430 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5436 gtk_window_state_event (GtkWidget *widget,
5437 GdkEventWindowState *event)
5439 update_grip_visibility (GTK_WINDOW (widget));
5445 gtk_window_direction_changed (GtkWidget *widget,
5446 GtkTextDirection prev_dir)
5448 GtkWindow *window = GTK_WINDOW (widget);
5450 set_grip_cursor (window);
5451 set_grip_position (window);
5452 set_grip_shape (window);
5456 gtk_window_state_changed (GtkWidget *widget,
5457 GtkStateType previous_state)
5459 GtkWindow *window = GTK_WINDOW (widget);
5461 update_grip_visibility (window);
5465 gtk_window_style_updated (GtkWidget *widget)
5467 GtkWindow *window = GTK_WINDOW (widget);
5468 GtkWindowPrivate *priv = window->priv;
5471 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5473 gdk_window_move_resize (priv->grip_window,
5475 rect.width, rect.height);
5477 set_grip_shape (window);
5478 gtk_widget_queue_resize (widget);
5483 resize_grip_create_window (GtkWindow *window)
5486 GtkWindowPrivate *priv;
5487 GdkWindowAttr attributes;
5488 gint attributes_mask;
5491 priv = window->priv;
5492 widget = GTK_WIDGET (window);
5494 g_return_if_fail (gtk_widget_get_realized (widget));
5495 g_return_if_fail (priv->grip_window == NULL);
5497 gtk_window_get_resize_grip_area (window, &rect);
5499 attributes.x = rect.x;
5500 attributes.y = rect.y;
5501 attributes.width = rect.width;
5502 attributes.height = rect.height;
5503 attributes.window_type = GDK_WINDOW_CHILD;
5504 attributes.wclass = GDK_INPUT_OUTPUT;
5505 attributes.event_mask = gtk_widget_get_events (widget) |
5507 GDK_BUTTON_PRESS_MASK;
5509 attributes_mask = GDK_WA_X | GDK_WA_Y;
5511 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5515 gdk_window_set_user_data (priv->grip_window, widget);
5517 gdk_window_raise (priv->grip_window);
5519 set_grip_shape (window);
5520 update_grip_visibility (window);
5524 resize_grip_destroy_window (GtkWindow *window)
5526 GtkWindowPrivate *priv = window->priv;
5528 gdk_window_set_user_data (priv->grip_window, NULL);
5529 gdk_window_destroy (priv->grip_window);
5530 priv->grip_window = NULL;
5531 update_grip_visibility (window);
5535 * gtk_window_set_has_resize_grip:
5536 * @window: a #GtkWindow
5537 * @value: %TRUE to allow a resize grip
5539 * Sets whether @window has a corner resize grip.
5541 * Note that the resize grip is only shown if the window
5542 * is actually resizable and not maximized. Use
5543 * gtk_window_resize_grip_is_visible() to find out if the
5544 * resize grip is currently shown.
5549 gtk_window_set_has_resize_grip (GtkWindow *window,
5552 GtkWidget *widget = GTK_WIDGET (window);
5553 GtkWindowPrivate *priv = window->priv;
5555 value = value != FALSE;
5557 if (value != priv->has_resize_grip)
5559 priv->has_resize_grip = value;
5560 gtk_widget_queue_draw (widget);
5562 if (gtk_widget_get_realized (widget))
5564 if (priv->has_resize_grip && priv->grip_window == NULL)
5565 resize_grip_create_window (window);
5566 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5567 resize_grip_destroy_window (window);
5570 g_object_notify (G_OBJECT (window), "has-resize-grip");
5575 update_grip_visibility (GtkWindow *window)
5577 GtkWindowPrivate *priv = window->priv;
5580 val = gtk_window_resize_grip_is_visible (window);
5582 if (priv->grip_window != NULL)
5586 gdk_window_show (priv->grip_window);
5587 set_grip_cursor (window);
5591 gdk_window_hide (priv->grip_window);
5595 if (priv->resize_grip_visible != val)
5597 priv->resize_grip_visible = val;
5599 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5604 * gtk_window_resize_grip_is_visible:
5605 * @window: a #GtkWindow
5607 * Determines whether a resize grip is visible for the specified window.
5609 * Returns %TRUE if a resize grip exists and is visible.
5614 gtk_window_resize_grip_is_visible (GtkWindow *window)
5617 GtkWindowPrivate *priv;
5620 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5622 priv = window->priv;
5623 widget = GTK_WIDGET (window);
5625 if (priv->type == GTK_WINDOW_POPUP)
5628 if (!priv->resizable)
5631 if (gtk_widget_get_realized (widget))
5633 GdkWindowState state;
5635 state = gdk_window_get_state (gtk_widget_get_window (widget));
5637 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5641 if (!get_drag_edge (widget, &edge))
5644 return window->priv->has_resize_grip;
5648 * gtk_window_get_has_resize_grip:
5649 * @window: a #GtkWindow
5651 * Determines whether the window may have a resize grip.
5653 * Returns: %TRUE if the window has a resize grip.
5658 gtk_window_get_has_resize_grip (GtkWindow *window)
5660 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5662 return window->priv->has_resize_grip;
5666 * gtk_window_get_resize_grip_area:
5667 * @window: a #GtkWindow
5668 * @rect: a pointer to a #GdkRectangle which we should store the
5671 * If a window has a resize grip, this will retrieve the grip
5672 * position, width and height into the specified #GdkRectangle.
5674 * Returns: %TRUE if the resize grip's area was retrieved.
5679 gtk_window_get_resize_grip_area (GtkWindow *window,
5682 GtkWidget *widget = GTK_WIDGET (window);
5683 GtkAllocation allocation;
5687 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5689 if (!window->priv->has_resize_grip)
5692 gtk_widget_get_allocation (widget, &allocation);
5694 gtk_widget_style_get (widget,
5695 "resize-grip-width", &grip_width,
5696 "resize-grip-height", &grip_height,
5699 if (grip_width > allocation.width)
5700 grip_width = allocation.width;
5702 if (grip_height > allocation.height)
5703 grip_height = allocation.height;
5705 rect->width = grip_width;
5706 rect->height = grip_height;
5707 rect->y = allocation.y + allocation.height - grip_height;
5709 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5710 rect->x = allocation.x + allocation.width - grip_width;
5712 rect->x = allocation.x;
5717 /* the accel_key and accel_mods fields of the key have to be setup
5718 * upon calling this function. it'll then return whether that key
5719 * is at all used as accelerator, and if so will OR in the
5720 * accel_flags member of the key.
5723 _gtk_window_query_nonaccels (GtkWindow *window,
5725 GdkModifierType accel_mods)
5727 GtkWindowPrivate *priv;
5729 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5731 priv = window->priv;
5733 /* movement keys are considered locked accels */
5736 static const guint bindings[] = {
5737 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,
5738 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,
5742 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5743 if (bindings[i] == accel_key)
5747 /* mnemonics are considered locked accels */
5748 if (accel_mods == priv->mnemonic_modifier)
5750 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5751 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5759 * gtk_window_propagate_key_event:
5760 * @window: a #GtkWindow
5761 * @event: a #GdkEventKey
5763 * Propagate a key press or release event to the focus widget and
5764 * up the focus container chain until a widget handles @event.
5765 * This is normally called by the default ::key_press_event and
5766 * ::key_release_event handlers for toplevel windows,
5767 * however in some cases it may be useful to call this directly when
5768 * overriding the standard key handling for a toplevel window.
5770 * Return value: %TRUE if a widget in the focus chain handled the event.
5775 gtk_window_propagate_key_event (GtkWindow *window,
5778 GtkWindowPrivate *priv;
5779 gboolean handled = FALSE;
5780 GtkWidget *widget, *focus;
5782 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5784 priv = window->priv;
5785 widget = GTK_WIDGET (window);
5787 focus = priv->focus_widget;
5789 g_object_ref (focus);
5792 focus && focus != widget &&
5793 gtk_widget_get_toplevel (focus) == widget)
5797 if (gtk_widget_is_sensitive (focus))
5798 handled = gtk_widget_event (focus, (GdkEvent*) event);
5800 parent = gtk_widget_get_parent (focus);
5802 g_object_ref (parent);
5804 g_object_unref (focus);
5810 g_object_unref (focus);
5816 gtk_window_key_press_event (GtkWidget *widget,
5819 GtkWindow *window = GTK_WINDOW (widget);
5820 gboolean handled = FALSE;
5822 /* handle mnemonics and accelerators */
5824 handled = gtk_window_activate_key (window, event);
5826 /* handle focus widget key events */
5828 handled = gtk_window_propagate_key_event (window, event);
5830 /* Chain up, invokes binding set */
5832 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5838 gtk_window_key_release_event (GtkWidget *widget,
5841 GtkWindow *window = GTK_WINDOW (widget);
5842 gboolean handled = FALSE;
5844 /* handle focus widget key events */
5846 handled = gtk_window_propagate_key_event (window, event);
5848 /* Chain up, invokes binding set */
5850 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5856 gtk_window_button_press_event (GtkWidget *widget,
5857 GdkEventButton *event)
5859 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5862 if (event->window == priv->grip_window)
5864 if (get_drag_edge (widget, &edge))
5865 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5879 gtk_window_real_activate_default (GtkWindow *window)
5881 gtk_window_activate_default (window);
5885 gtk_window_real_activate_focus (GtkWindow *window)
5887 gtk_window_activate_focus (window);
5891 gtk_window_enter_notify_event (GtkWidget *widget,
5892 GdkEventCrossing *event)
5898 gtk_window_leave_notify_event (GtkWidget *widget,
5899 GdkEventCrossing *event)
5905 do_focus_change (GtkWidget *widget,
5909 GdkDeviceManager *device_manager;
5912 g_object_ref (widget);
5914 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5915 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5916 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5917 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5919 for (d = devices; d; d = d->next)
5921 GdkDevice *dev = d->data;
5924 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5927 /* Skip non-master keyboards that haven't
5928 * selected for events from this window
5930 window = gtk_widget_get_window (widget);
5931 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5932 window && !gdk_window_get_device_events (window, dev))
5935 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5937 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5938 fevent->focus_change.window = window;
5940 g_object_ref (window);
5941 fevent->focus_change.in = in;
5942 gdk_event_set_device (fevent, dev);
5944 gtk_widget_send_focus_change (widget, fevent);
5946 gdk_event_free (fevent);
5949 g_list_free (devices);
5950 g_object_unref (widget);
5954 gtk_window_focus_in_event (GtkWidget *widget,
5955 GdkEventFocus *event)
5957 GtkWindow *window = GTK_WINDOW (widget);
5959 /* It appears spurious focus in events can occur when
5960 * the window is hidden. So we'll just check to see if
5961 * the window is visible before actually handling the
5964 if (gtk_widget_get_visible (widget))
5966 _gtk_window_set_has_toplevel_focus (window, TRUE);
5967 _gtk_window_set_is_active (window, TRUE);
5974 gtk_window_focus_out_event (GtkWidget *widget,
5975 GdkEventFocus *event)
5977 GtkWindow *window = GTK_WINDOW (widget);
5978 gboolean auto_mnemonics;
5980 _gtk_window_set_has_toplevel_focus (window, FALSE);
5981 _gtk_window_set_is_active (window, FALSE);
5983 /* set the mnemonic-visible property to false */
5984 g_object_get (gtk_widget_get_settings (widget),
5985 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5987 gtk_window_set_mnemonics_visible (window, FALSE);
5992 static GdkAtom atom_rcfiles = GDK_NONE;
5993 static GdkAtom atom_iconthemes = GDK_NONE;
5996 send_client_message_to_embedded_windows (GtkWidget *widget,
5997 GdkAtom message_type)
5999 GList *embedded_windows;
6001 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
6002 if (embedded_windows)
6004 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
6007 for (i = 0; i < 5; i++)
6008 send_event->client.data.l[i] = 0;
6009 send_event->client.data_format = 32;
6010 send_event->client.message_type = message_type;
6012 while (embedded_windows)
6014 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
6015 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
6016 embedded_windows = embedded_windows->next;
6019 gdk_event_free (send_event);
6024 gtk_window_client_event (GtkWidget *widget,
6025 GdkEventClient *event)
6029 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
6030 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
6033 if (event->message_type == atom_rcfiles)
6035 send_client_message_to_embedded_windows (widget, atom_rcfiles);
6036 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
6039 if (event->message_type == atom_iconthemes)
6041 send_client_message_to_embedded_windows (widget, atom_iconthemes);
6042 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
6049 gtk_window_check_resize (GtkContainer *container)
6051 if (gtk_widget_get_visible (GTK_WIDGET (container)))
6052 gtk_window_move_resize (GTK_WINDOW (container));
6056 gtk_window_focus (GtkWidget *widget,
6057 GtkDirectionType direction)
6059 GtkWindowPrivate *priv;
6062 GtkContainer *container;
6064 GtkWidget *old_focus_child;
6067 container = GTK_CONTAINER (widget);
6068 window = GTK_WINDOW (widget);
6069 priv = window->priv;
6070 bin = GTK_BIN (widget);
6072 old_focus_child = gtk_container_get_focus_child (container);
6074 /* We need a special implementation here to deal properly with wrapping
6075 * around in the tab chain without the danger of going into an
6078 if (old_focus_child)
6080 if (gtk_widget_child_focus (old_focus_child, direction))
6084 if (priv->focus_widget)
6086 if (direction == GTK_DIR_LEFT ||
6087 direction == GTK_DIR_RIGHT ||
6088 direction == GTK_DIR_UP ||
6089 direction == GTK_DIR_DOWN)
6094 /* Wrapped off the end, clear the focus setting for the toplpevel */
6095 parent = gtk_widget_get_parent (priv->focus_widget);
6098 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6099 parent = gtk_widget_get_parent (parent);
6102 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6105 /* Now try to focus the first widget in the window */
6106 child = gtk_bin_get_child (bin);
6109 if (gtk_widget_child_focus (child, direction))
6117 gtk_window_move_focus (GtkWidget *widget,
6118 GtkDirectionType dir)
6120 gtk_widget_child_focus (widget, dir);
6122 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6123 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6127 gtk_window_real_set_focus (GtkWindow *window,
6130 GtkWindowPrivate *priv = window->priv;
6131 GtkWidget *old_focus = priv->focus_widget;
6132 gboolean had_default = FALSE;
6133 gboolean focus_had_default = FALSE;
6134 gboolean old_focus_had_default = FALSE;
6138 g_object_ref (old_focus);
6139 g_object_freeze_notify (G_OBJECT (old_focus));
6140 old_focus_had_default = gtk_widget_has_default (old_focus);
6144 g_object_ref (focus);
6145 g_object_freeze_notify (G_OBJECT (focus));
6146 focus_had_default = gtk_widget_has_default (focus);
6149 if (priv->default_widget)
6150 had_default = gtk_widget_has_default (priv->default_widget);
6152 if (priv->focus_widget)
6154 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6155 (priv->focus_widget != priv->default_widget))
6157 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6158 gtk_widget_queue_draw (priv->focus_widget);
6160 if (priv->default_widget)
6161 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6164 priv->focus_widget = NULL;
6166 if (priv->has_focus)
6167 do_focus_change (old_focus, FALSE);
6169 g_object_notify (G_OBJECT (old_focus), "is-focus");
6172 /* The above notifications may have set a new focus widget,
6173 * if so, we don't want to override it.
6175 if (focus && !priv->focus_widget)
6177 priv->focus_widget = focus;
6179 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6180 (priv->focus_widget != priv->default_widget))
6182 if (gtk_widget_get_can_default (priv->focus_widget))
6183 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6185 if (priv->default_widget)
6186 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6189 if (priv->has_focus)
6190 do_focus_change (priv->focus_widget, TRUE);
6192 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6195 /* If the default widget changed, a redraw will have been queued
6196 * on the old and new default widgets by gtk_window_set_default(), so
6197 * we only have to worry about the case where it didn't change.
6198 * We'll sometimes queue a draw twice on the new widget but that
6201 if (priv->default_widget &&
6202 (had_default != gtk_widget_has_default (priv->default_widget)))
6203 gtk_widget_queue_draw (priv->default_widget);
6207 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6208 gtk_widget_queue_draw (old_focus);
6210 g_object_thaw_notify (G_OBJECT (old_focus));
6211 g_object_unref (old_focus);
6215 if (focus_had_default != gtk_widget_has_default (focus))
6216 gtk_widget_queue_draw (focus);
6218 g_object_thaw_notify (G_OBJECT (focus));
6219 g_object_unref (focus);
6225 gtk_window_get_preferred_width (GtkWidget *widget,
6233 window = GTK_WINDOW (widget);
6234 child = gtk_bin_get_child (GTK_BIN (window));
6236 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6237 *minimum_size = border_width * 2;
6238 *natural_size = border_width * 2;
6240 if (child && gtk_widget_get_visible (child))
6242 gint child_min, child_nat;
6243 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6245 *minimum_size += child_min;
6246 *natural_size += child_nat;
6251 gtk_window_get_preferred_height (GtkWidget *widget,
6259 window = GTK_WINDOW (widget);
6260 child = gtk_bin_get_child (GTK_BIN (window));
6262 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6263 *minimum_size = border_width * 2;
6264 *natural_size = border_width * 2;
6266 if (child && gtk_widget_get_visible (child))
6268 gint child_min, child_nat;
6269 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6271 *minimum_size += child_min;
6272 *natural_size += child_nat;
6278 * _gtk_window_unset_focus_and_default:
6279 * @window: a #GtkWindow
6280 * @widget: a widget inside of @window
6282 * Checks whether the focus and default widgets of @window are
6283 * @widget or a descendent of @widget, and if so, unset them.
6286 _gtk_window_unset_focus_and_default (GtkWindow *window,
6290 GtkWindowPrivate *priv = window->priv;
6294 g_object_ref (window);
6295 g_object_ref (widget);
6297 parent = gtk_widget_get_parent (widget);
6298 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6300 child = priv->focus_widget;
6302 while (child && child != widget)
6303 child = gtk_widget_get_parent (child);
6305 if (child == widget)
6306 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6309 child = priv->default_widget;
6311 while (child && child != widget)
6312 child = gtk_widget_get_parent (child);
6314 if (child == widget)
6315 gtk_window_set_default (window, NULL);
6317 g_object_unref (widget);
6318 g_object_unref (window);
6321 /*********************************
6322 * Functions related to resizing *
6323 *********************************/
6326 geometry_size_to_pixels (GdkGeometry *geometry,
6331 gint base_width = 0;
6332 gint base_height = 0;
6334 gint min_height = 0;
6336 gint height_inc = 1;
6338 if (flags & GDK_HINT_BASE_SIZE)
6340 base_width = geometry->base_width;
6341 base_height = geometry->base_height;
6343 if (flags & GDK_HINT_MIN_SIZE)
6345 min_width = geometry->min_width;
6346 min_height = geometry->min_height;
6348 if (flags & GDK_HINT_RESIZE_INC)
6350 width_inc = geometry->width_inc;
6351 height_inc = geometry->height_inc;
6355 *width = MAX (*width * width_inc + base_width, min_width);
6357 *height = MAX (*height * height_inc + base_height, min_height);
6360 /* This function doesn't constrain to geometry hints */
6362 gtk_window_compute_configure_request_size (GtkWindow *window,
6363 GdkGeometry *geometry,
6368 GtkWindowPrivate *priv = window->priv;
6369 GtkRequisition requisition;
6370 GtkWindowGeometryInfo *info;
6374 * - we've done a size request
6377 widget = GTK_WIDGET (window);
6379 info = gtk_window_get_geometry_info (window, FALSE);
6381 if (priv->need_default_size)
6383 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6385 /* Default to requisition */
6386 *width = requisition.width;
6387 *height = requisition.height;
6389 /* If window is empty so requests 0, default to random nonzero size */
6390 if (*width == 0 && *height == 0)
6396 /* Override requisition with default size */
6400 if (info->default_width > 0)
6401 *width = info->default_width;
6402 if (info->default_height > 0)
6403 *height = info->default_height;
6405 if (info->default_is_geometry)
6406 geometry_size_to_pixels (geometry, flags,
6407 info->default_width > 0 ? width : NULL,
6408 info->default_height > 0 ? height : NULL);
6413 GtkAllocation allocation;
6415 gtk_widget_get_allocation (widget, &allocation);
6417 /* Default to keeping current size */
6418 *width = allocation.width;
6419 *height = allocation.height;
6422 /* Override any size with gtk_window_resize() values */
6425 if (info->resize_width > 0)
6426 *width = info->resize_width;
6427 if (info->resize_height > 0)
6428 *height = info->resize_height;
6430 if (info->resize_is_geometry)
6431 geometry_size_to_pixels (geometry, flags,
6432 info->resize_width > 0 ? width : NULL,
6433 info->resize_height > 0 ? height : NULL);
6436 /* Don't ever request zero width or height, its not supported by
6437 gdk. The size allocation code will round it to 1 anyway but if
6438 we do it then the value returned from this function will is
6439 not comparable to the size allocation read from the GtkWindow. */
6440 *width = MAX (*width, 1);
6441 *height = MAX (*height, 1);
6444 static GtkWindowPosition
6445 get_effective_position (GtkWindow *window)
6447 GtkWindowPrivate *priv = window->priv;
6448 GtkWindowPosition pos = priv->position;
6450 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6451 (priv->transient_parent == NULL ||
6452 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6453 pos = GTK_WIN_POS_NONE;
6459 get_center_monitor_of_window (GtkWindow *window)
6461 /* We could try to sort out the relative positions of the monitors and
6462 * stuff, or we could just be losers and assume you have a row
6463 * or column of monitors.
6465 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6469 get_monitor_containing_pointer (GtkWindow *window)
6473 GdkScreen *window_screen;
6474 GdkScreen *pointer_screen;
6475 GdkDisplay *display;
6476 GdkDeviceManager *device_manager;
6479 window_screen = gtk_window_check_screen (window);
6480 display = gdk_screen_get_display (window_screen);
6481 device_manager = gdk_display_get_device_manager (display);
6482 pointer = gdk_device_manager_get_client_pointer (device_manager);
6484 gdk_display_get_device_state (display, pointer,
6488 if (pointer_screen == window_screen)
6489 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6497 center_window_on_monitor (GtkWindow *window,
6503 GdkRectangle monitor;
6506 monitor_num = get_monitor_containing_pointer (window);
6508 if (monitor_num == -1)
6509 monitor_num = get_center_monitor_of_window (window);
6511 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6512 monitor_num, &monitor);
6514 *x = (monitor.width - w) / 2 + monitor.x;
6515 *y = (monitor.height - h) / 2 + monitor.y;
6517 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6518 * and WM decorations.
6532 if (extent > clamp_extent)
6534 *base = clamp_base + clamp_extent/2 - extent/2;
6535 else if (*base < clamp_base)
6537 else if (*base + extent > clamp_base + clamp_extent)
6538 *base = clamp_base + clamp_extent - extent;
6542 clamp_window_to_rectangle (gint *x,
6546 const GdkRectangle *rect)
6548 #ifdef DEBUGGING_OUTPUT
6549 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);
6552 /* If it is too large, center it. If it fits on the monitor but is
6553 * partially outside, move it to the closest edge. Do this
6554 * separately in x and y directions.
6556 clamp (x, w, rect->x, rect->width);
6557 clamp (y, h, rect->y, rect->height);
6558 #ifdef DEBUGGING_OUTPUT
6559 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6565 gtk_window_compute_configure_request (GtkWindow *window,
6566 GdkRectangle *request,
6567 GdkGeometry *geometry,
6570 GtkWindowPrivate *priv = window->priv;
6571 GdkGeometry new_geometry;
6575 GtkWindowPosition pos;
6576 GtkWidget *parent_widget;
6577 GtkWindowGeometryInfo *info;
6581 widget = GTK_WIDGET (window);
6583 screen = gtk_window_check_screen (window);
6585 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6586 gtk_window_compute_configure_request_size (window,
6587 &new_geometry, new_flags,
6588 (guint *)&w, (guint *)&h);
6590 gtk_window_constrain_size (window,
6591 &new_geometry, new_flags,
6595 parent_widget = (GtkWidget*) priv->transient_parent;
6597 pos = get_effective_position (window);
6598 info = gtk_window_get_geometry_info (window, FALSE);
6600 /* by default, don't change position requested */
6603 x = info->last.configure_request.x;
6604 y = info->last.configure_request.y;
6613 if (priv->need_default_position)
6616 /* FIXME this all interrelates with window gravity.
6617 * For most of them I think we want to set GRAVITY_CENTER.
6619 * Not sure how to go about that.
6624 /* here we are only handling CENTER_ALWAYS
6625 * as it relates to default positioning,
6626 * where it's equivalent to simply CENTER
6628 case GTK_WIN_POS_CENTER_ALWAYS:
6629 case GTK_WIN_POS_CENTER:
6630 center_window_on_monitor (window, w, h, &x, &y);
6633 case GTK_WIN_POS_CENTER_ON_PARENT:
6635 GtkAllocation allocation;
6636 GdkWindow *gdk_window;
6638 GdkRectangle monitor;
6641 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6643 gdk_window = gtk_widget_get_window (parent_widget);
6645 if (gdk_window != NULL)
6646 monitor_num = gdk_screen_get_monitor_at_window (screen,
6651 gdk_window_get_origin (gdk_window,
6654 gtk_widget_get_allocation (parent_widget, &allocation);
6655 x = ox + (allocation.width - w) / 2;
6656 y = oy + (allocation.height - h) / 2;
6658 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6659 * WM decorations. If parent wasn't on a monitor, just
6662 if (monitor_num >= 0)
6664 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6665 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6670 case GTK_WIN_POS_MOUSE:
6672 gint screen_width = gdk_screen_get_width (screen);
6673 gint screen_height = gdk_screen_get_height (screen);
6675 GdkRectangle monitor;
6676 GdkDisplay *display;
6677 GdkDeviceManager *device_manager;
6679 GdkScreen *pointer_screen;
6682 display = gdk_screen_get_display (screen);
6683 device_manager = gdk_display_get_device_manager (display);
6684 pointer = gdk_device_manager_get_client_pointer (device_manager);
6686 gdk_display_get_device_state (display, pointer,
6690 if (pointer_screen == screen)
6691 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6697 x = CLAMP (x, 0, screen_width - w);
6698 y = CLAMP (y, 0, screen_height - h);
6700 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6701 * WM decorations. Don't try to figure out what's going
6702 * on if the mouse wasn't inside a monitor.
6704 if (monitor_num >= 0)
6706 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6707 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6715 } /* if (priv->need_default_position) */
6717 if (priv->need_default_position && info &&
6718 info->initial_pos_set)
6720 x = info->initial_x;
6721 y = info->initial_y;
6722 gtk_window_constrain_position (window, w, h, &x, &y);
6728 request->height = h;
6731 *geometry = new_geometry;
6737 gtk_window_constrain_position (GtkWindow *window,
6743 GtkWindowPrivate *priv = window->priv;
6745 /* See long comments in gtk_window_move_resize()
6746 * on when it's safe to call this function.
6748 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6750 gint center_x, center_y;
6752 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6760 gtk_window_move_resize (GtkWindow *window)
6764 * First we determine whether any information has changed that would
6765 * cause us to revise our last configure request. If we would send
6766 * a different configure request from last time, then
6767 * configure_request_size_changed = TRUE or
6768 * configure_request_pos_changed = TRUE. configure_request_size_changed
6769 * may be true due to new hints, a gtk_window_resize(), or whatever.
6770 * configure_request_pos_changed may be true due to gtk_window_set_position()
6771 * or gtk_window_move().
6773 * If the configure request has changed, we send off a new one. To
6774 * ensure GTK+ invariants are maintained (resize queue does what it
6775 * should), we go ahead and size_allocate the requested size in this
6778 * If the configure request has not changed, we don't ever resend
6779 * it, because it could mean fighting the user or window manager.
6782 * To prepare the configure request, we come up with a base size/pos:
6783 * - the one from gtk_window_move()/gtk_window_resize()
6784 * - else default_width, default_height if we haven't ever
6786 * - else the size request if we haven't ever been mapped,
6787 * as a substitute default size
6788 * - else the current size of the window, as received from
6789 * configure notifies (i.e. the current allocation)
6791 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6792 * the position request to be centered.
6794 GtkWindowPrivate *priv = window->priv;
6795 GtkAllocation allocation;
6797 GtkContainer *container;
6798 GtkWindowGeometryInfo *info;
6799 GdkGeometry new_geometry;
6800 GdkWindow *gdk_window;
6802 GdkRectangle new_request;
6803 gboolean configure_request_size_changed;
6804 gboolean configure_request_pos_changed;
6805 gboolean hints_changed; /* do we need to send these again */
6806 GtkWindowLastGeometryInfo saved_last_info;
6808 widget = GTK_WIDGET (window);
6809 gdk_window = gtk_widget_get_window (widget);
6810 container = GTK_CONTAINER (widget);
6811 info = gtk_window_get_geometry_info (window, TRUE);
6813 configure_request_size_changed = FALSE;
6814 configure_request_pos_changed = FALSE;
6816 gtk_window_compute_configure_request (window, &new_request,
6817 &new_geometry, &new_flags);
6819 /* This check implies the invariant that we never set info->last
6820 * without setting the hints and sending off a configure request.
6822 * If we change info->last without sending the request, we may
6825 if (info->last.configure_request.x != new_request.x ||
6826 info->last.configure_request.y != new_request.y)
6827 configure_request_pos_changed = TRUE;
6829 if ((info->last.configure_request.width != new_request.width ||
6830 info->last.configure_request.height != new_request.height))
6831 configure_request_size_changed = TRUE;
6833 hints_changed = FALSE;
6835 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6836 &new_geometry, new_flags))
6838 hints_changed = TRUE;
6841 /* Position Constraints
6842 * ====================
6844 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6845 * a default. The other POS_ values are used only when the
6846 * window is shown, not after that.
6848 * However, we can't implement a position constraint as
6849 * "anytime the window size changes, center the window"
6850 * because this may well end up fighting the WM or user. In
6851 * fact it gets in an infinite loop with at least one WM.
6853 * Basically, applications are in no way in a position to
6854 * constrain the position of a window, with one exception:
6855 * override redirect windows. (Really the intended purpose
6856 * of CENTER_ALWAYS anyhow, I would think.)
6858 * So the way we implement this "constraint" is to say that when WE
6859 * cause a move or resize, i.e. we make a configure request changing
6860 * window size, we recompute the CENTER_ALWAYS position to reflect
6861 * the new window size, and include it in our request. Also, if we
6862 * just turned on CENTER_ALWAYS we snap to center with a new
6863 * request. Otherwise, if we are just NOTIFIED of a move or resize
6864 * done by someone else e.g. the window manager, we do NOT send a
6865 * new configure request.
6867 * For override redirect windows, this works fine; all window
6868 * sizes are from our configure requests. For managed windows,
6869 * it is at least semi-sane, though who knows what the
6870 * app author is thinking.
6873 /* This condition should be kept in sync with the condition later on
6874 * that determines whether we send a configure request. i.e. we
6875 * should do this position constraining anytime we were going to
6876 * send a configure request anyhow, plus when constraints have
6879 if (configure_request_pos_changed ||
6880 configure_request_size_changed ||
6882 info->position_constraints_changed)
6884 /* We request the constrained position if:
6885 * - we were changing position, and need to clamp
6886 * the change to the constraint
6887 * - we're changing the size anyway
6888 * - set_position() was called to toggle CENTER_ALWAYS on
6891 gtk_window_constrain_position (window,
6897 /* Update whether we need to request a move */
6898 if (info->last.configure_request.x != new_request.x ||
6899 info->last.configure_request.y != new_request.y)
6900 configure_request_pos_changed = TRUE;
6902 configure_request_pos_changed = FALSE;
6906 if (priv->type == GTK_WINDOW_TOPLEVEL)
6908 int notify_x, notify_y;
6910 /* this is the position from the last configure notify */
6911 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6913 g_message ("--- %s ---\n"
6914 "last : %d,%d\t%d x %d\n"
6915 "this : %d,%d\t%d x %d\n"
6916 "alloc : %d,%d\t%d x %d\n"
6918 "resize: \t%d x %d\n"
6919 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6920 "configure_notify_received: %d\n"
6921 "configure_request_count: %d\n"
6922 "position_constraints_changed: %d\n",
6923 priv->title ? priv->title : "(no title)",
6924 info->last.configure_request.x,
6925 info->last.configure_request.y,
6926 info->last.configure_request.width,
6927 info->last.configure_request.height,
6933 widget->allocation.width,
6934 widget->allocation.height,
6935 widget->requisition.width,
6936 widget->requisition.height,
6938 info->resize_height,
6939 configure_request_pos_changed,
6940 configure_request_size_changed,
6942 priv->configure_notify_received,
6943 priv->configure_request_count,
6944 info->position_constraints_changed);
6948 saved_last_info = info->last;
6949 info->last.geometry = new_geometry;
6950 info->last.flags = new_flags;
6951 info->last.configure_request = new_request;
6953 /* need to set PPosition so the WM will look at our position,
6954 * but we don't want to count PPosition coming and going as a hints
6955 * change for future iterations. So we saved info->last prior to
6959 /* Also, if the initial position was explicitly set, then we always
6960 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6964 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6965 * this is an initial map
6968 if ((configure_request_pos_changed ||
6969 info->initial_pos_set ||
6970 (priv->need_default_position &&
6971 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6972 (new_flags & GDK_HINT_POS) == 0)
6974 new_flags |= GDK_HINT_POS;
6975 hints_changed = TRUE;
6978 /* Set hints if necessary
6981 gdk_window_set_geometry_hints (gdk_window,
6985 gtk_widget_get_allocation (widget, &allocation);
6987 /* handle resizing/moving and widget tree allocation
6989 if (priv->configure_notify_received)
6991 /* If we have received a configure event since
6992 * the last time in this function, we need to
6993 * accept our new size and size_allocate child widgets.
6994 * (see gtk_window_configure_event() for more details).
6996 * 1 or more configure notifies may have been received.
6997 * Also, configure_notify_received will only be TRUE
6998 * if all expected configure notifies have been received
6999 * (one per configure request), as an optimization.
7002 priv->configure_notify_received = FALSE;
7004 /* gtk_window_configure_event() filled in widget->allocation */
7005 gtk_widget_size_allocate (widget, &allocation);
7007 set_grip_position (window);
7008 update_grip_visibility (window);
7010 gdk_window_process_updates (gdk_window, TRUE);
7012 gdk_window_configure_finished (gdk_window);
7014 /* If the configure request changed, it means that
7016 * 1) coincidentally changed hints or widget properties
7017 * impacting the configure request before getting
7018 * a configure notify, or
7019 * 2) some broken widget is changing its size request
7020 * during size allocation, resulting in
7021 * a false appearance of changed configure request.
7023 * For 1), we could just go ahead and ask for the
7024 * new size right now, but doing that for 2)
7025 * might well be fighting the user (and can even
7026 * trigger a loop). Since we really don't want to
7027 * do that, we requeue a resize in hopes that
7028 * by the time it gets handled, the child has seen
7029 * the light and is willing to go along with the
7030 * new size. (this happens for the zvt widget, since
7031 * the size_allocate() above will have stored the
7032 * requisition corresponding to the new size in the
7035 * This doesn't buy us anything for 1), but it shouldn't
7036 * hurt us too badly, since it is what would have
7037 * happened if we had gotten the configure event before
7038 * the new size had been set.
7041 if (configure_request_size_changed ||
7042 configure_request_pos_changed)
7044 /* Don't change the recorded last info after all, because we
7045 * haven't actually updated to the new info yet - we decided
7046 * to postpone our configure request until later.
7048 info->last = saved_last_info;
7050 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7053 return; /* Bail out, we didn't really process the move/resize */
7055 else if ((configure_request_size_changed || hints_changed) &&
7056 (allocation.width != new_request.width || allocation.height != new_request.height))
7059 /* We are in one of the following situations:
7060 * A. configure_request_size_changed
7061 * our requisition has changed and we need a different window size,
7062 * so we request it from the window manager.
7063 * B. !configure_request_size_changed && hints_changed
7064 * the window manager rejects our size, but we have just changed the
7065 * window manager hints, so there's a chance our request will
7066 * be honoured this time, so we try again.
7068 * However, if the new requisition is the same as the current allocation,
7069 * we don't request it again, since we won't get a ConfigureNotify back from
7070 * the window manager unless it decides to change our requisition. If
7071 * we don't get the ConfigureNotify back, the resize queue will never be run.
7074 /* Now send the configure request */
7075 if (configure_request_pos_changed)
7079 gdk_window_move_resize (priv->frame,
7080 new_request.x - priv->frame_left,
7081 new_request.y - priv->frame_top,
7082 new_request.width + priv->frame_left + priv->frame_right,
7083 new_request.height + priv->frame_top + priv->frame_bottom);
7084 gdk_window_resize (gdk_window,
7085 new_request.width, new_request.height);
7088 gdk_window_move_resize (gdk_window,
7089 new_request.x, new_request.y,
7090 new_request.width, new_request.height);
7092 else /* only size changed */
7095 gdk_window_resize (priv->frame,
7096 new_request.width + priv->frame_left + priv->frame_right,
7097 new_request.height + priv->frame_top + priv->frame_bottom);
7098 gdk_window_resize (gdk_window,
7099 new_request.width, new_request.height);
7102 if (priv->type == GTK_WINDOW_POPUP)
7104 GtkAllocation allocation;
7106 /* Directly size allocate for override redirect (popup) windows. */
7109 allocation.width = new_request.width;
7110 allocation.height = new_request.height;
7112 gtk_widget_size_allocate (widget, &allocation);
7114 gdk_window_process_updates (gdk_window, TRUE);
7116 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7117 gtk_widget_queue_draw (widget);
7121 /* Increment the number of have-not-yet-received-notify requests */
7122 priv->configure_request_count += 1;
7123 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7125 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7126 * configure event in response to our resizing request.
7127 * the configure event will cause a new resize with
7128 * ->configure_notify_received=TRUE.
7129 * until then, we want to
7130 * - discard expose events
7131 * - coalesce resizes for our children
7132 * - defer any window resizes until the configure event arrived
7133 * to achieve this, we queue a resize for the window, but remove its
7134 * resizing handler, so resizing will not be handled from the next
7135 * idle handler but when the configure event arrives.
7137 * FIXME: we should also dequeue the pending redraws here, since
7138 * we handle those ourselves upon ->configure_notify_received==TRUE.
7140 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7142 gtk_widget_queue_resize_no_redraw (widget);
7143 _gtk_container_dequeue_resize_handler (container);
7149 /* Handle any position changes.
7151 if (configure_request_pos_changed)
7155 gdk_window_move (priv->frame,
7156 new_request.x - priv->frame_left,
7157 new_request.y - priv->frame_top);
7160 gdk_window_move (gdk_window,
7161 new_request.x, new_request.y);
7164 /* And run the resize queue.
7166 gtk_container_resize_children (container);
7169 /* We have now processed a move/resize since the last position
7170 * constraint change, setting of the initial position, or resize.
7171 * (Not resetting these flags here can lead to infinite loops for
7172 * GTK_RESIZE_IMMEDIATE containers)
7174 info->position_constraints_changed = FALSE;
7175 info->initial_pos_set = FALSE;
7176 info->resize_width = -1;
7177 info->resize_height = -1;
7180 /* Compare two sets of Geometry hints for equality.
7183 gtk_window_compare_hints (GdkGeometry *geometry_a,
7185 GdkGeometry *geometry_b,
7188 if (flags_a != flags_b)
7191 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7192 (geometry_a->min_width != geometry_b->min_width ||
7193 geometry_a->min_height != geometry_b->min_height))
7196 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7197 (geometry_a->max_width != geometry_b->max_width ||
7198 geometry_a->max_height != geometry_b->max_height))
7201 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7202 (geometry_a->base_width != geometry_b->base_width ||
7203 geometry_a->base_height != geometry_b->base_height))
7206 if ((flags_a & GDK_HINT_ASPECT) &&
7207 (geometry_a->min_aspect != geometry_b->min_aspect ||
7208 geometry_a->max_aspect != geometry_b->max_aspect))
7211 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7212 (geometry_a->width_inc != geometry_b->width_inc ||
7213 geometry_a->height_inc != geometry_b->height_inc))
7216 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7217 geometry_a->win_gravity != geometry_b->win_gravity)
7224 _gtk_window_constrain_size (GtkWindow *window,
7230 GtkWindowPrivate *priv;
7231 GtkWindowGeometryInfo *info;
7233 g_return_if_fail (GTK_IS_WINDOW (window));
7235 priv = window->priv;
7237 info = priv->geometry_info;
7240 GdkWindowHints flags = info->last.flags;
7241 GdkGeometry *geometry = &info->last.geometry;
7243 gtk_window_constrain_size (window,
7254 gtk_window_constrain_size (GtkWindow *window,
7255 GdkGeometry *geometry,
7262 gdk_window_constrain_size (geometry, flags, width, height,
7263 new_width, new_height);
7266 /* Compute the set of geometry hints and flags for a window
7267 * based on the application set geometry, and requisition
7268 * of the window. gtk_widget_get_preferred_size() must have been
7272 gtk_window_compute_hints (GtkWindow *window,
7273 GdkGeometry *new_geometry,
7276 GtkWindowPrivate *priv = window->priv;
7278 gint extra_width = 0;
7279 gint extra_height = 0;
7280 GtkWindowGeometryInfo *geometry_info;
7281 GtkRequisition requisition;
7283 widget = GTK_WIDGET (window);
7285 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7286 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7290 *new_flags = geometry_info->mask;
7291 *new_geometry = geometry_info->geometry;
7298 if (geometry_info && geometry_info->widget)
7300 /* If the geometry widget is set, then the hints really apply to that
7301 * widget. This is pretty much meaningless unless the window layout
7302 * is such that the rest of the window adds fixed size borders to
7303 * the geometry widget. Our job is to figure the size of the borders;
7304 * We do that by asking how big the toplevel would be if the
7305 * geometry widget was *really big*.
7308 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7309 * |GGGGG B| in the border can confuse things
7315 * |AAAAAAAAA | When the geometry widget is large, things are
7316 * |GGGGGGGGGGB| clearer.
7321 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7322 GtkRequisition requisition;
7323 int current_width, current_height;
7325 _gtk_widget_override_size_request (geometry_info->widget,
7326 TEMPORARY_SIZE, TEMPORARY_SIZE,
7327 ¤t_width, ¤t_height);
7328 gtk_widget_get_preferred_size (widget,
7329 &requisition, NULL);
7330 _gtk_widget_restore_size_request (geometry_info->widget,
7331 current_width, current_height);
7333 extra_width = requisition.width - TEMPORARY_SIZE;
7334 extra_height = requisition.height - TEMPORARY_SIZE;
7336 if (extra_width < 0 || extra_width < 0)
7338 g_warning("Toplevel size doesn't seem to directly depend on the "
7339 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7340 "The geometry widget might not be in the window, or it might not "
7341 "be packed into the window appropriately");
7342 extra_width = MAX(extra_width, 0);
7343 extra_height = MAX(extra_height, 0);
7345 #undef TEMPORARY_SIZE
7348 /* We don't want to set GDK_HINT_POS in here, we just set it
7349 * in gtk_window_move_resize() when we want the position
7353 if (*new_flags & GDK_HINT_BASE_SIZE)
7355 new_geometry->base_width += extra_width;
7356 new_geometry->base_height += extra_height;
7360 /* For simplicity, we always set the base hint, even when we
7361 * don't expect it to have any visible effect.
7362 * (Note: geometry_size_to_pixels() depends on this.)
7364 *new_flags |= GDK_HINT_BASE_SIZE;
7366 new_geometry->base_width = extra_width;
7367 new_geometry->base_height = extra_height;
7369 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7370 * base size is the minimum size */
7371 if (*new_flags & GDK_HINT_MIN_SIZE)
7373 if (new_geometry->min_width > 0)
7374 new_geometry->base_width += new_geometry->min_width;
7375 if (new_geometry->min_height > 0)
7376 new_geometry->base_height += new_geometry->min_height;
7380 if (*new_flags & GDK_HINT_MIN_SIZE)
7382 if (new_geometry->min_width < 0)
7383 new_geometry->min_width = requisition.width;
7385 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7387 if (new_geometry->min_height < 0)
7388 new_geometry->min_height = requisition.height;
7390 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7394 *new_flags |= GDK_HINT_MIN_SIZE;
7396 new_geometry->min_width = requisition.width;
7397 new_geometry->min_height = requisition.height;
7400 if (*new_flags & GDK_HINT_MAX_SIZE)
7402 if (new_geometry->max_width < 0)
7403 new_geometry->max_width = requisition.width;
7405 new_geometry->max_width += extra_width;
7407 if (new_geometry->max_height < 0)
7408 new_geometry->max_height = requisition.height;
7410 new_geometry->max_height += extra_height;
7412 else if (!priv->resizable)
7414 *new_flags |= GDK_HINT_MAX_SIZE;
7416 new_geometry->max_width = requisition.width;
7417 new_geometry->max_height = requisition.height;
7420 *new_flags |= GDK_HINT_WIN_GRAVITY;
7421 new_geometry->win_gravity = priv->gravity;
7424 /***********************
7425 * Redrawing functions *
7426 ***********************/
7429 gtk_window_draw (GtkWidget *widget,
7432 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7433 GtkStyleContext *context;
7434 gboolean ret = FALSE;
7436 context = gtk_widget_get_style_context (widget);
7438 gtk_style_context_save (context);
7440 if (!gtk_widget_get_app_paintable (widget))
7442 GtkStateFlags state;
7444 state = gtk_widget_get_state_flags (widget);
7446 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7447 state |= GTK_STATE_FLAG_FOCUSED;
7449 gtk_style_context_set_state (context, state);
7450 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7451 gtk_render_background (context, cr, 0, 0,
7452 gtk_widget_get_allocated_width (widget),
7453 gtk_widget_get_allocated_height (widget));
7456 gtk_style_context_restore (context);
7458 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7459 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7461 if (priv->grip_window != NULL &&
7462 gtk_cairo_should_draw_window (cr, priv->grip_window))
7466 gtk_style_context_save (context);
7469 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7470 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7472 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7473 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7474 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7477 gtk_style_context_restore (context);
7484 * gtk_window_set_has_frame:
7485 * @window: a #GtkWindow
7486 * @setting: a boolean
7488 * (Note: this is a special-purpose function for the framebuffer port,
7489 * that causes GTK+ to draw its own window border. For most applications,
7490 * you want gtk_window_set_decorated() instead, which tells the window
7491 * manager whether to draw the window border.)
7493 * If this function is called on a window with setting of %TRUE, before
7494 * it is realized or showed, it will have a "frame" window around
7495 * @window->window, accessible in @window->frame. Using the signal
7496 * frame_event you can receive all events targeted at the frame.
7498 * This function is used by the linux-fb port to implement managed
7499 * windows, but it could conceivably be used by X-programs that
7500 * want to do their own window decorations.
7504 gtk_window_set_has_frame (GtkWindow *window,
7507 GtkWindowPrivate *priv;
7509 g_return_if_fail (GTK_IS_WINDOW (window));
7510 g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
7512 priv = window->priv;
7514 priv->has_frame = setting != FALSE;
7518 * gtk_window_get_has_frame:
7519 * @window: a #GtkWindow
7521 * Accessor for whether the window has a frame window exterior to
7522 * @window->window. Gets the value set by gtk_window_set_has_frame ().
7524 * Return value: %TRUE if a frame has been added to the window
7525 * via gtk_window_set_has_frame().
7528 gtk_window_get_has_frame (GtkWindow *window)
7530 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7532 return window->priv->has_frame;
7536 * gtk_window_set_frame_dimensions:
7537 * @window: a #GtkWindow that has a frame
7538 * @left: The width of the left border
7539 * @top: The height of the top border
7540 * @right: The width of the right border
7541 * @bottom: The height of the bottom border
7543 * (Note: this is a special-purpose function intended for the framebuffer
7544 * port; see gtk_window_set_has_frame(). It will have no effect on the
7545 * window border drawn by the window manager, which is the normal
7546 * case when using the X Window system.)
7548 * For windows with frames (see gtk_window_set_has_frame()) this function
7549 * can be used to change the size of the frame border.
7552 gtk_window_set_frame_dimensions (GtkWindow *window,
7558 GtkWindowPrivate *priv;
7559 GtkAllocation allocation;
7562 g_return_if_fail (GTK_IS_WINDOW (window));
7564 priv = window->priv;
7565 widget = GTK_WIDGET (window);
7567 if (priv->frame_left == left &&
7568 priv->frame_top == top &&
7569 priv->frame_right == right &&
7570 priv->frame_bottom == bottom)
7573 priv->frame_left = left;
7574 priv->frame_top = top;
7575 priv->frame_right = right;
7576 priv->frame_bottom = bottom;
7578 if (gtk_widget_get_realized (widget) && priv->frame)
7581 gtk_widget_get_allocation (widget, &allocation);
7583 width = allocation.width + left + right;
7584 height = allocation.height + top + bottom;
7585 gdk_window_resize (priv->frame, width, height);
7586 gtk_decorated_window_move_resize_window (window,
7594 * gtk_window_present:
7595 * @window: a #GtkWindow
7597 * Presents a window to the user. This may mean raising the window
7598 * in the stacking order, deiconifying it, moving it to the current
7599 * desktop, and/or giving it the keyboard focus, possibly dependent
7600 * on the user's platform, window manager, and preferences.
7602 * If @window is hidden, this function calls gtk_widget_show()
7605 * This function should be used when the user tries to open a window
7606 * that's already open. Say for example the preferences dialog is
7607 * currently open, and the user chooses Preferences from the menu
7608 * a second time; use gtk_window_present() to move the already-open dialog
7609 * where the user can see it.
7611 * If you are calling this function in response to a user interaction,
7612 * it is preferable to use gtk_window_present_with_time().
7616 gtk_window_present (GtkWindow *window)
7618 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7622 * gtk_window_present_with_time:
7623 * @window: a #GtkWindow
7624 * @timestamp: the timestamp of the user interaction (typically a
7625 * button or key press event) which triggered this call
7627 * Presents a window to the user in response to a user interaction.
7628 * If you need to present a window without a timestamp, use
7629 * gtk_window_present(). See gtk_window_present() for details.
7634 gtk_window_present_with_time (GtkWindow *window,
7638 GdkWindow *gdk_window;
7640 g_return_if_fail (GTK_IS_WINDOW (window));
7642 widget = GTK_WIDGET (window);
7644 if (gtk_widget_get_visible (widget))
7646 gdk_window = gtk_widget_get_window (widget);
7648 g_assert (gdk_window != NULL);
7650 gdk_window_show (gdk_window);
7652 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7653 if (timestamp == GDK_CURRENT_TIME)
7655 #ifdef GDK_WINDOWING_X11
7656 GdkDisplay *display;
7658 display = gtk_widget_get_display (GTK_WIDGET (window));
7659 timestamp = gdk_x11_display_get_user_time (display);
7661 timestamp = gtk_get_current_event_time ();
7665 gdk_window_focus (gdk_window, timestamp);
7669 gtk_widget_show (widget);
7674 * gtk_window_iconify:
7675 * @window: a #GtkWindow
7677 * Asks to iconify (i.e. minimize) the specified @window. Note that
7678 * you shouldn't assume the window is definitely iconified afterward,
7679 * because other entities (e.g. the user or <link
7680 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7681 * again, or there may not be a window manager in which case
7682 * iconification isn't possible, etc. But normally the window will end
7683 * up iconified. Just don't write code that crashes if not.
7685 * It's permitted to call this function before showing a window,
7686 * in which case the window will be iconified before it ever appears
7689 * You can track iconification via the "window-state-event" signal
7694 gtk_window_iconify (GtkWindow *window)
7696 GtkWindowPrivate *priv;
7698 GdkWindow *toplevel;
7700 g_return_if_fail (GTK_IS_WINDOW (window));
7702 priv = window->priv;
7703 widget = GTK_WIDGET (window);
7705 priv->iconify_initially = TRUE;
7708 toplevel = priv->frame;
7710 toplevel = gtk_widget_get_window (widget);
7712 if (toplevel != NULL)
7713 gdk_window_iconify (toplevel);
7717 * gtk_window_deiconify:
7718 * @window: a #GtkWindow
7720 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7721 * that you shouldn't assume the window is definitely deiconified
7722 * afterward, because other entities (e.g. the user or <link
7723 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7724 * again before your code which assumes deiconification gets to run.
7726 * You can track iconification via the "window-state-event" signal
7730 gtk_window_deiconify (GtkWindow *window)
7732 GtkWindowPrivate *priv;
7734 GdkWindow *toplevel;
7736 g_return_if_fail (GTK_IS_WINDOW (window));
7738 priv = window->priv;
7739 widget = GTK_WIDGET (window);
7741 priv->iconify_initially = FALSE;
7744 toplevel = priv->frame;
7746 toplevel = gtk_widget_get_window (widget);
7748 if (toplevel != NULL)
7749 gdk_window_deiconify (toplevel);
7754 * @window: a #GtkWindow
7756 * Asks to stick @window, which means that it will appear on all user
7757 * desktops. Note that you shouldn't assume the window is definitely
7758 * stuck afterward, because other entities (e.g. the user or <link
7759 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7760 * again, and some window managers do not support sticking
7761 * windows. But normally the window will end up stuck. Just don't
7762 * write code that crashes if not.
7764 * It's permitted to call this function before showing a window.
7766 * You can track stickiness via the "window-state-event" signal
7771 gtk_window_stick (GtkWindow *window)
7773 GtkWindowPrivate *priv;
7775 GdkWindow *toplevel;
7777 g_return_if_fail (GTK_IS_WINDOW (window));
7779 priv = window->priv;
7780 widget = GTK_WIDGET (window);
7782 priv->stick_initially = TRUE;
7785 toplevel = priv->frame;
7787 toplevel = gtk_widget_get_window (widget);
7789 if (toplevel != NULL)
7790 gdk_window_stick (toplevel);
7794 * gtk_window_unstick:
7795 * @window: a #GtkWindow
7797 * Asks to unstick @window, which means that it will appear on only
7798 * one of the user's desktops. Note that you shouldn't assume the
7799 * window is definitely unstuck afterward, because other entities
7800 * (e.g. the user or <link linkend="gtk-X11-arch">window
7801 * manager</link>) could stick it again. But normally the window will
7802 * end up stuck. Just don't write code that crashes if not.
7804 * You can track stickiness via the "window-state-event" signal
7809 gtk_window_unstick (GtkWindow *window)
7811 GtkWindowPrivate *priv;
7813 GdkWindow *toplevel;
7815 g_return_if_fail (GTK_IS_WINDOW (window));
7817 priv = window->priv;
7818 widget = GTK_WIDGET (window);
7820 priv->stick_initially = FALSE;
7823 toplevel = priv->frame;
7825 toplevel = gtk_widget_get_window (widget);
7827 if (toplevel != NULL)
7828 gdk_window_unstick (toplevel);
7832 * gtk_window_maximize:
7833 * @window: a #GtkWindow
7835 * Asks to maximize @window, so that it becomes full-screen. Note that
7836 * you shouldn't assume the window is definitely maximized afterward,
7837 * because other entities (e.g. the user or <link
7838 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7839 * again, and not all window managers support maximization. But
7840 * normally the window will end up maximized. Just don't write code
7841 * that crashes if not.
7843 * It's permitted to call this function before showing a window,
7844 * in which case the window will be maximized when it appears onscreen
7847 * You can track maximization via the "window-state-event" signal
7852 gtk_window_maximize (GtkWindow *window)
7854 GtkWindowPrivate *priv;
7856 GdkWindow *toplevel;
7858 g_return_if_fail (GTK_IS_WINDOW (window));
7860 priv = window->priv;
7861 widget = GTK_WIDGET (window);
7863 priv->maximize_initially = TRUE;
7866 toplevel = priv->frame;
7868 toplevel = gtk_widget_get_window (widget);
7870 if (toplevel != NULL)
7871 gdk_window_maximize (toplevel);
7875 * gtk_window_unmaximize:
7876 * @window: a #GtkWindow
7878 * Asks to unmaximize @window. Note that you shouldn't assume the
7879 * window is definitely unmaximized afterward, because other entities
7880 * (e.g. the user or <link linkend="gtk-X11-arch">window
7881 * manager</link>) could maximize it again, and not all window
7882 * managers honor requests to unmaximize. But normally the window will
7883 * end up unmaximized. Just don't write code that crashes if not.
7885 * You can track maximization via the "window-state-event" signal
7890 gtk_window_unmaximize (GtkWindow *window)
7892 GtkWindowPrivate *priv;
7894 GdkWindow *toplevel;
7896 g_return_if_fail (GTK_IS_WINDOW (window));
7898 priv = window->priv;
7899 widget = GTK_WIDGET (window);
7901 priv->maximize_initially = FALSE;
7904 toplevel = priv->frame;
7906 toplevel = gtk_widget_get_window (widget);
7908 if (toplevel != NULL)
7909 gdk_window_unmaximize (toplevel);
7913 * gtk_window_fullscreen:
7914 * @window: a #GtkWindow
7916 * Asks to place @window in the fullscreen state. Note that you
7917 * shouldn't assume the window is definitely full screen afterward,
7918 * because other entities (e.g. the user or <link
7919 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7920 * again, and not all window managers honor requests to fullscreen
7921 * windows. But normally the window will end up fullscreen. Just
7922 * don't write code that crashes if not.
7924 * You can track the fullscreen state via the "window-state-event" signal
7930 gtk_window_fullscreen (GtkWindow *window)
7932 GtkWindowPrivate *priv;
7934 GdkWindow *toplevel;
7936 g_return_if_fail (GTK_IS_WINDOW (window));
7938 priv = window->priv;
7939 widget = GTK_WIDGET (window);
7941 priv->fullscreen_initially = TRUE;
7944 toplevel = priv->frame;
7946 toplevel = gtk_widget_get_window (widget);
7948 if (toplevel != NULL)
7949 gdk_window_fullscreen (toplevel);
7953 * gtk_window_unfullscreen:
7954 * @window: a #GtkWindow
7956 * Asks to toggle off the fullscreen state for @window. Note that you
7957 * shouldn't assume the window is definitely not full screen
7958 * afterward, because other entities (e.g. the user or <link
7959 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7960 * again, and not all window managers honor requests to unfullscreen
7961 * windows. But normally the window will end up restored to its normal
7962 * state. Just don't write code that crashes if not.
7964 * You can track the fullscreen state via the "window-state-event" signal
7970 gtk_window_unfullscreen (GtkWindow *window)
7973 GdkWindow *toplevel;
7974 GtkWindowPrivate *priv;
7976 g_return_if_fail (GTK_IS_WINDOW (window));
7978 priv = window->priv;
7979 widget = GTK_WIDGET (window);
7981 priv->fullscreen_initially = FALSE;
7984 toplevel = priv->frame;
7986 toplevel = gtk_widget_get_window (widget);
7988 if (toplevel != NULL)
7989 gdk_window_unfullscreen (toplevel);
7993 * gtk_window_set_keep_above:
7994 * @window: a #GtkWindow
7995 * @setting: whether to keep @window above other windows
7997 * Asks to keep @window above, so that it stays on top. Note that
7998 * you shouldn't assume the window is definitely above afterward,
7999 * because other entities (e.g. the user or <link
8000 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
8001 * and not all window managers support keeping windows above. But
8002 * normally the window will end kept above. Just don't write code
8003 * that crashes if not.
8005 * It's permitted to call this function before showing a window,
8006 * in which case the window will be kept above when it appears onscreen
8009 * You can track the above state via the "window-state-event" signal
8012 * Note that, according to the <ulink
8013 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8014 * Manager Hints</ulink> specification, the above state is mainly meant
8015 * for user preferences and should not be used by applications e.g. for
8016 * drawing attention to their dialogs.
8021 gtk_window_set_keep_above (GtkWindow *window,
8025 GtkWindowPrivate *priv;
8026 GdkWindow *toplevel;
8028 g_return_if_fail (GTK_IS_WINDOW (window));
8030 priv = window->priv;
8031 widget = GTK_WIDGET (window);
8033 priv->above_initially = setting != FALSE;
8035 priv->below_initially = FALSE;
8038 toplevel = priv->frame;
8040 toplevel = gtk_widget_get_window (widget);
8042 if (toplevel != NULL)
8043 gdk_window_set_keep_above (toplevel, setting);
8047 * gtk_window_set_keep_below:
8048 * @window: a #GtkWindow
8049 * @setting: whether to keep @window below other windows
8051 * Asks to keep @window below, so that it stays in bottom. Note that
8052 * you shouldn't assume the window is definitely below afterward,
8053 * because other entities (e.g. the user or <link
8054 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8055 * and not all window managers support putting windows below. But
8056 * normally the window will be kept below. Just don't write code
8057 * that crashes if not.
8059 * It's permitted to call this function before showing a window,
8060 * in which case the window will be kept below when it appears onscreen
8063 * You can track the below state via the "window-state-event" signal
8066 * Note that, according to the <ulink
8067 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8068 * Manager Hints</ulink> specification, the above state is mainly meant
8069 * for user preferences and should not be used by applications e.g. for
8070 * drawing attention to their dialogs.
8075 gtk_window_set_keep_below (GtkWindow *window,
8079 GtkWindowPrivate *priv;
8080 GdkWindow *toplevel;
8082 g_return_if_fail (GTK_IS_WINDOW (window));
8084 priv = window->priv;
8085 widget = GTK_WIDGET (window);
8087 priv->below_initially = setting != FALSE;
8089 priv->above_initially = FALSE;
8092 toplevel = priv->frame;
8094 toplevel = gtk_widget_get_window (widget);
8096 if (toplevel != NULL)
8097 gdk_window_set_keep_below (toplevel, setting);
8101 * gtk_window_set_resizable:
8102 * @window: a #GtkWindow
8103 * @resizable: %TRUE if the user can resize this window
8105 * Sets whether the user can resize a window. Windows are user resizable
8109 gtk_window_set_resizable (GtkWindow *window,
8112 GtkWindowPrivate *priv;
8114 g_return_if_fail (GTK_IS_WINDOW (window));
8116 priv = window->priv;
8118 resizable = (resizable != FALSE);
8120 if (priv->resizable != resizable)
8122 priv->resizable = (resizable != FALSE);
8124 update_grip_visibility (window);
8126 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8128 g_object_notify (G_OBJECT (window), "resizable");
8133 * gtk_window_get_resizable:
8134 * @window: a #GtkWindow
8136 * Gets the value set by gtk_window_set_resizable().
8138 * Return value: %TRUE if the user can resize the window
8141 gtk_window_get_resizable (GtkWindow *window)
8143 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8145 return window->priv->resizable;
8149 * gtk_window_set_gravity:
8150 * @window: a #GtkWindow
8151 * @gravity: window gravity
8153 * Window gravity defines the meaning of coordinates passed to
8154 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8157 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8158 * typically "do what you mean."
8162 gtk_window_set_gravity (GtkWindow *window,
8165 GtkWindowPrivate *priv;
8167 g_return_if_fail (GTK_IS_WINDOW (window));
8169 priv = window->priv;
8171 if (gravity != priv->gravity)
8173 priv->gravity = gravity;
8175 /* gtk_window_move_resize() will adapt gravity
8177 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8179 g_object_notify (G_OBJECT (window), "gravity");
8184 * gtk_window_get_gravity:
8185 * @window: a #GtkWindow
8187 * Gets the value set by gtk_window_set_gravity().
8189 * Return value: (transfer none): window gravity
8192 gtk_window_get_gravity (GtkWindow *window)
8194 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8196 return window->priv->gravity;
8200 * gtk_window_begin_resize_drag:
8201 * @window: a #GtkWindow
8202 * @button: mouse button that initiated the drag
8203 * @edge: position of the resize control
8204 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8205 * @root_y: Y position where the user clicked to initiate the drag
8206 * @timestamp: timestamp from the click event that initiated the drag
8208 * Starts resizing a window. This function is used if an application
8209 * has window resizing controls. When GDK can support it, the resize
8210 * will be done using the standard mechanism for the <link
8211 * linkend="gtk-X11-arch">window manager</link> or windowing
8212 * system. Otherwise, GDK will try to emulate window resizing,
8213 * potentially not all that well, depending on the windowing system.
8217 gtk_window_begin_resize_drag (GtkWindow *window,
8224 GtkWindowPrivate *priv;
8226 GdkWindow *toplevel;
8228 g_return_if_fail (GTK_IS_WINDOW (window));
8229 widget = GTK_WIDGET (window);
8230 g_return_if_fail (gtk_widget_get_visible (widget));
8232 priv = window->priv;
8235 toplevel = priv->frame;
8237 toplevel = gtk_widget_get_window (widget);
8239 gdk_window_begin_resize_drag (toplevel,
8246 * gtk_window_get_frame_dimensions:
8247 * @window: a #GtkWindow
8248 * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
8249 * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
8250 * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
8251 * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
8253 * (Note: this is a special-purpose function intended for the
8254 * framebuffer port; see gtk_window_set_has_frame(). It will not
8255 * return the size of the window border drawn by the <link
8256 * linkend="gtk-X11-arch">window manager</link>, which is the normal
8257 * case when using a windowing system. See
8258 * gdk_window_get_frame_extents() to get the standard window border
8261 * Retrieves the dimensions of the frame window for this toplevel.
8262 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
8265 gtk_window_get_frame_dimensions (GtkWindow *window,
8271 GtkWindowPrivate *priv;
8273 g_return_if_fail (GTK_IS_WINDOW (window));
8275 priv = window->priv;
8278 *left = priv->frame_left;
8280 *top = priv->frame_top;
8282 *right = priv->frame_right;
8284 *bottom = priv->frame_bottom;
8288 * gtk_window_begin_move_drag:
8289 * @window: a #GtkWindow
8290 * @button: mouse button that initiated the drag
8291 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8292 * @root_y: Y position where the user clicked to initiate the drag
8293 * @timestamp: timestamp from the click event that initiated the drag
8295 * Starts moving a window. This function is used if an application has
8296 * window movement grips. When GDK can support it, the window movement
8297 * will be done using the standard mechanism for the <link
8298 * linkend="gtk-X11-arch">window manager</link> or windowing
8299 * system. Otherwise, GDK will try to emulate window movement,
8300 * potentially not all that well, depending on the windowing system.
8304 gtk_window_begin_move_drag (GtkWindow *window,
8310 GtkWindowPrivate *priv;
8312 GdkWindow *toplevel;
8314 g_return_if_fail (GTK_IS_WINDOW (window));
8315 widget = GTK_WIDGET (window);
8316 g_return_if_fail (gtk_widget_get_visible (widget));
8318 priv = window->priv;
8321 toplevel = priv->frame;
8323 toplevel = gtk_widget_get_window (widget);
8325 gdk_window_begin_move_drag (toplevel,
8332 * gtk_window_set_screen:
8333 * @window: a #GtkWindow.
8334 * @screen: a #GdkScreen.
8336 * Sets the #GdkScreen where the @window is displayed; if
8337 * the window is already mapped, it will be unmapped, and
8338 * then remapped on the new screen.
8343 gtk_window_set_screen (GtkWindow *window,
8346 GtkWindowPrivate *priv;
8348 GdkScreen *previous_screen;
8349 gboolean was_mapped;
8351 g_return_if_fail (GTK_IS_WINDOW (window));
8352 g_return_if_fail (GDK_IS_SCREEN (screen));
8354 priv = window->priv;
8356 if (screen == priv->screen)
8359 widget = GTK_WIDGET (window);
8361 previous_screen = priv->screen;
8362 was_mapped = gtk_widget_get_mapped (widget);
8365 gtk_widget_unmap (widget);
8366 if (gtk_widget_get_realized (widget))
8367 gtk_widget_unrealize (widget);
8369 gtk_window_free_key_hash (window);
8370 priv->screen = screen;
8371 gtk_widget_reset_rc_styles (widget);
8372 if (screen != previous_screen)
8374 g_signal_handlers_disconnect_by_func (previous_screen,
8375 gtk_window_on_composited_changed, window);
8376 g_signal_connect (screen, "composited-changed",
8377 G_CALLBACK (gtk_window_on_composited_changed), window);
8379 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8380 _gtk_widget_propagate_composited_changed (widget);
8382 g_object_notify (G_OBJECT (window), "screen");
8385 gtk_widget_map (widget);
8389 gtk_window_on_composited_changed (GdkScreen *screen,
8392 gtk_widget_queue_draw (GTK_WIDGET (window));
8394 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8398 gtk_window_check_screen (GtkWindow *window)
8400 GtkWindowPrivate *priv = window->priv;
8403 return priv->screen;
8406 g_warning ("Screen for GtkWindow not set; you must always set\n"
8407 "a screen for a GtkWindow before using the window");
8413 * gtk_window_get_screen:
8414 * @window: a #GtkWindow.
8416 * Returns the #GdkScreen associated with @window.
8418 * Return value: (transfer none): a #GdkScreen.
8423 gtk_window_get_screen (GtkWindow *window)
8425 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8427 return window->priv->screen;
8431 * gtk_window_is_active:
8432 * @window: a #GtkWindow
8434 * Returns whether the window is part of the current active toplevel.
8435 * (That is, the toplevel window receiving keystrokes.)
8436 * The return value is %TRUE if the window is active toplevel
8437 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8438 * You might use this function if you wanted to draw a widget
8439 * differently in an active window from a widget in an inactive window.
8440 * See gtk_window_has_toplevel_focus()
8442 * Return value: %TRUE if the window part of the current active window.
8447 gtk_window_is_active (GtkWindow *window)
8449 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8451 return window->priv->is_active;
8455 * gtk_window_has_toplevel_focus:
8456 * @window: a #GtkWindow
8458 * Returns whether the input focus is within this GtkWindow.
8459 * For real toplevel windows, this is identical to gtk_window_is_active(),
8460 * but for embedded windows, like #GtkPlug, the results will differ.
8462 * Return value: %TRUE if the input focus is within this GtkWindow
8467 gtk_window_has_toplevel_focus (GtkWindow *window)
8469 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8471 return window->priv->has_toplevel_focus;
8475 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8477 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8481 gtk_window_group_get_type (void)
8483 static GType window_group_type = 0;
8485 if (!window_group_type)
8487 const GTypeInfo window_group_info =
8489 sizeof (GtkWindowGroupClass),
8490 NULL, /* base_init */
8491 NULL, /* base_finalize */
8492 (GClassInitFunc) gtk_window_group_class_init,
8493 NULL, /* class_finalize */
8494 NULL, /* class_data */
8495 sizeof (GtkWindowGroup),
8496 0, /* n_preallocs */
8497 (GInstanceInitFunc) NULL,
8500 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
8501 &window_group_info, 0);
8504 return window_group_type;
8508 * gtk_window_group_new:
8510 * Creates a new #GtkWindowGroup object. Grabs added with
8511 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8513 * Return value: a new #GtkWindowGroup.
8516 gtk_window_group_new (void)
8518 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8522 window_group_cleanup_grabs (GtkWindowGroup *group,
8525 GtkWindowGroupPrivate *priv;
8526 GtkDeviceGrabInfo *info;
8528 GSList *to_remove = NULL;
8530 tmp_list = group->grabs;
8533 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8534 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8535 tmp_list = tmp_list->next;
8540 gtk_grab_remove (to_remove->data);
8541 g_object_unref (to_remove->data);
8542 to_remove = g_slist_delete_link (to_remove, to_remove);
8545 priv = GTK_WINDOW_GROUP_GET_PRIVATE (group);
8546 tmp_list = priv->device_grabs;
8550 info = tmp_list->data;
8552 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8553 to_remove = g_slist_prepend (to_remove, info);
8555 tmp_list = tmp_list->next;
8560 info = to_remove->data;
8562 gtk_device_grab_remove (info->widget, info->device);
8563 to_remove = g_slist_delete_link (to_remove, to_remove);
8568 * gtk_window_group_add_window:
8569 * @window_group: a #GtkWindowGroup
8570 * @window: the #GtkWindow to add
8572 * Adds a window to a #GtkWindowGroup.
8575 gtk_window_group_add_window (GtkWindowGroup *window_group,
8578 GtkWindowPrivate *priv;
8580 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8581 g_return_if_fail (GTK_IS_WINDOW (window));
8583 priv = window->priv;
8585 if (priv->group != window_group)
8587 g_object_ref (window);
8588 g_object_ref (window_group);
8591 gtk_window_group_remove_window (priv->group, window);
8593 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8595 priv->group = window_group;
8597 g_object_unref (window);
8602 * gtk_window_group_remove_window:
8603 * @window_group: a #GtkWindowGroup
8604 * @window: the #GtkWindow to remove
8606 * Removes a window from a #GtkWindowGroup.
8609 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8612 GtkWindowPrivate *priv;
8614 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8615 g_return_if_fail (GTK_IS_WINDOW (window));
8616 priv = window->priv;
8617 g_return_if_fail (priv->group == window_group);
8619 g_object_ref (window);
8621 window_group_cleanup_grabs (window_group, window);
8624 g_object_unref (window_group);
8625 g_object_unref (window);
8629 * gtk_window_group_list_windows:
8630 * @window_group: a #GtkWindowGroup
8632 * Returns a list of the #GtkWindows that belong to @window_group.
8634 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8635 * windows inside the group.
8640 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8642 GList *toplevels, *toplevel, *group_windows;
8644 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8646 group_windows = NULL;
8647 toplevels = gtk_window_list_toplevels ();
8649 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8651 GtkWindow *window = toplevel->data;
8653 if (window_group == window->priv->group)
8654 group_windows = g_list_prepend (group_windows, window);
8657 return g_list_reverse (group_windows);
8661 * gtk_window_get_group:
8662 * @window: (allow-none): a #GtkWindow, or %NULL
8664 * Returns the group for @window or the default group, if
8665 * @window is %NULL or if @window does not have an explicit
8668 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8673 gtk_window_get_group (GtkWindow *window)
8675 if (window && window->priv->group)
8676 return window->priv->group;
8679 static GtkWindowGroup *default_group = NULL;
8682 default_group = gtk_window_group_new ();
8684 return default_group;
8689 * gtk_window_has_group:
8690 * @window: a #GtkWindow
8692 * Returns whether @window has an explicit window group.
8694 * Return value: %TRUE if @window has an explicit window group.
8699 gtk_window_has_group (GtkWindow *window)
8701 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8703 return window->priv->group != NULL;
8707 * gtk_window_group_get_current_grab:
8708 * @window_group: a #GtkWindowGroup
8710 * Gets the current grab widget of the given group,
8711 * see gtk_grab_add().
8713 * Returns: the current grab widget of the group
8718 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8720 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8722 if (window_group->grabs)
8723 return GTK_WIDGET (window_group->grabs->data);
8728 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8731 gboolean block_others)
8733 GtkWindowGroupPrivate *priv;
8734 GtkDeviceGrabInfo *info;
8736 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8738 info = g_slice_new0 (GtkDeviceGrabInfo);
8739 info->widget = widget;
8740 info->device = device;
8741 info->block_others = block_others;
8743 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8747 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8751 GtkWindowGroupPrivate *priv;
8752 GtkDeviceGrabInfo *info;
8753 GSList *list, *node = NULL;
8754 GdkDevice *other_device;
8756 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8757 other_device = gdk_device_get_associated_device (device);
8758 list = priv->device_grabs;
8764 if (info->widget == widget &&
8765 (info->device == device ||
8766 info->device == other_device))
8779 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8780 g_slice_free (GtkDeviceGrabInfo, info);
8785 * gtk_window_group_get_current_device_grab:
8786 * @window_group: a #GtkWindowGroup
8787 * @device: a #GdkDevice
8789 * Returns the current grab widget for @device, or %NULL if none.
8791 * Returns: The grab widget, or %NULL
8796 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8799 GtkWindowGroupPrivate *priv;
8800 GtkDeviceGrabInfo *info;
8801 GdkDevice *other_device;
8804 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8805 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8807 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8808 list = priv->device_grabs;
8809 other_device = gdk_device_get_associated_device (device);
8816 if (info->device == device ||
8817 info->device == other_device)
8818 return info->widget;
8825 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8829 GtkWindowGroupPrivate *priv;
8830 GtkDeviceGrabInfo *info;
8831 GdkDevice *other_device;
8834 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8835 other_device = gdk_device_get_associated_device (device);
8836 list = priv->device_grabs;
8843 /* Look for blocking grabs on other device pairs
8844 * that have the passed widget within the GTK+ grab.
8846 if (info->block_others &&
8847 info->device != device &&
8848 info->device != other_device &&
8849 (info->widget == widget ||
8850 gtk_widget_is_ancestor (widget, info->widget)))
8858 Derived from XParseGeometry() in XFree86
8860 Copyright 1985, 1986, 1987,1998 The Open Group
8862 All Rights Reserved.
8864 The above copyright notice and this permission notice shall be included
8865 in all copies or substantial portions of the Software.
8867 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8868 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8869 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8870 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8871 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8872 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8873 OTHER DEALINGS IN THE SOFTWARE.
8875 Except as contained in this notice, the name of The Open Group shall
8876 not be used in advertising or otherwise to promote the sale, use or
8877 other dealings in this Software without prior written authorization
8878 from The Open Group.
8883 * XParseGeometry parses strings of the form
8884 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8885 * width, height, xoffset, and yoffset are unsigned integers.
8886 * Example: "=80x24+300-49"
8887 * The equal sign is optional.
8888 * It returns a bitmask that indicates which of the four values
8889 * were actually found in the string. For each value found,
8890 * the corresponding argument is updated; for each value
8891 * not found, the corresponding argument is left unchanged.
8894 /* The following code is from Xlib, and is minimally modified, so we
8895 * can track any upstream changes if required. Don't change this
8896 * code. Or if you do, put in a huge comment marking which thing
8901 read_int (gchar *string,
8909 else if (*string == '-')
8915 for (; (*string >= '0') && (*string <= '9'); string++)
8917 result = (result * 10) + (*string - '0');
8929 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8930 * value (x, y, width, height) was found in the parsed string.
8932 #define NoValue 0x0000
8933 #define XValue 0x0001
8934 #define YValue 0x0002
8935 #define WidthValue 0x0004
8936 #define HeightValue 0x0008
8937 #define AllValues 0x000F
8938 #define XNegative 0x0010
8939 #define YNegative 0x0020
8941 /* Try not to reformat/modify, so we can compare/sync with X sources */
8943 gtk_XParseGeometry (const char *string,
8946 unsigned int *width,
8947 unsigned int *height)
8951 unsigned int tempWidth, tempHeight;
8953 char *nextCharacter;
8955 /* These initializations are just to silence gcc */
8961 if ( (string == NULL) || (*string == '\0')) return(mask);
8963 string++; /* ignore possible '=' at beg of geometry spec */
8965 strind = (char *)string;
8966 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8967 tempWidth = read_int(strind, &nextCharacter);
8968 if (strind == nextCharacter)
8970 strind = nextCharacter;
8974 if (*strind == 'x' || *strind == 'X') {
8976 tempHeight = read_int(strind, &nextCharacter);
8977 if (strind == nextCharacter)
8979 strind = nextCharacter;
8980 mask |= HeightValue;
8983 if ((*strind == '+') || (*strind == '-')) {
8984 if (*strind == '-') {
8986 tempX = -read_int(strind, &nextCharacter);
8987 if (strind == nextCharacter)
8989 strind = nextCharacter;
8995 tempX = read_int(strind, &nextCharacter);
8996 if (strind == nextCharacter)
8998 strind = nextCharacter;
9001 if ((*strind == '+') || (*strind == '-')) {
9002 if (*strind == '-') {
9004 tempY = -read_int(strind, &nextCharacter);
9005 if (strind == nextCharacter)
9007 strind = nextCharacter;
9014 tempY = read_int(strind, &nextCharacter);
9015 if (strind == nextCharacter)
9017 strind = nextCharacter;
9023 /* If strind isn't at the end of the string the it's an invalid
9024 geometry specification. */
9026 if (*strind != '\0') return (0);
9032 if (mask & WidthValue)
9034 if (mask & HeightValue)
9035 *height = tempHeight;
9040 * gtk_window_parse_geometry:
9041 * @window: a #GtkWindow
9042 * @geometry: geometry string
9044 * Parses a standard X Window System geometry string - see the
9045 * manual page for X (type 'man X') for details on this.
9046 * gtk_window_parse_geometry() does work on all GTK+ ports
9047 * including Win32 but is primarily intended for an X environment.
9049 * If either a size or a position can be extracted from the
9050 * geometry string, gtk_window_parse_geometry() returns %TRUE
9051 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9052 * to resize/move the window.
9054 * If gtk_window_parse_geometry() returns %TRUE, it will also
9055 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9056 * indicating to the window manager that the size/position of
9057 * the window was user-specified. This causes most window
9058 * managers to honor the geometry.
9060 * Note that for gtk_window_parse_geometry() to work as expected, it has
9061 * to be called when the window has its "final" size, i.e. after calling
9062 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9065 * #include <gtk/gtk.h>
9068 * fill_with_content (GtkWidget *vbox)
9070 * /* fill with content... */
9074 * main (int argc, char *argv[])
9076 * GtkWidget *window, *vbox;
9077 * GdkGeometry size_hints = {
9078 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9081 * gtk_init (&argc, &argv);
9083 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9084 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9086 * gtk_container_add (GTK_CONTAINER (window), vbox);
9087 * fill_with_content (vbox);
9088 * gtk_widget_show_all (vbox);
9090 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9093 * GDK_HINT_MIN_SIZE |
9094 * GDK_HINT_BASE_SIZE |
9095 * GDK_HINT_RESIZE_INC);
9099 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9100 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9103 * gtk_widget_show_all (window);
9110 * Return value: %TRUE if string was parsed successfully
9113 gtk_window_parse_geometry (GtkWindow *window,
9114 const gchar *geometry)
9116 gint result, x = 0, y = 0;
9120 gboolean size_set, pos_set;
9123 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9124 g_return_val_if_fail (geometry != NULL, FALSE);
9126 child = gtk_bin_get_child (GTK_BIN (window));
9127 if (!child || !gtk_widget_get_visible (child))
9128 g_warning ("gtk_window_parse_geometry() called on a window with no "
9129 "visible children; the window should be set up before "
9130 "gtk_window_parse_geometry() is called.");
9132 screen = gtk_window_check_screen (window);
9134 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9137 if ((result & WidthValue) || (result & HeightValue))
9139 gtk_window_set_default_size_internal (window,
9140 TRUE, result & WidthValue ? w : -1,
9141 TRUE, result & HeightValue ? h : -1,
9146 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9148 grav = GDK_GRAVITY_NORTH_WEST;
9150 if ((result & XNegative) && (result & YNegative))
9151 grav = GDK_GRAVITY_SOUTH_EAST;
9152 else if (result & XNegative)
9153 grav = GDK_GRAVITY_NORTH_EAST;
9154 else if (result & YNegative)
9155 grav = GDK_GRAVITY_SOUTH_WEST;
9157 if ((result & XValue) == 0)
9160 if ((result & YValue) == 0)
9163 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9164 grav == GDK_GRAVITY_SOUTH_EAST)
9165 y = gdk_screen_get_height (screen) - h + y;
9167 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9168 grav == GDK_GRAVITY_NORTH_EAST)
9169 x = gdk_screen_get_width (screen) - w + x;
9171 /* we don't let you put a window offscreen; maybe some people would
9172 * prefer to be able to, but it's kind of a bogus thing to do.
9181 if ((result & XValue) || (result & YValue))
9183 gtk_window_set_gravity (window, grav);
9184 gtk_window_move (window, x, y);
9188 if (size_set || pos_set)
9190 /* Set USSize, USPosition hints */
9191 GtkWindowGeometryInfo *info;
9193 info = gtk_window_get_geometry_info (window, TRUE);
9196 info->mask |= GDK_HINT_USER_POS;
9198 info->mask |= GDK_HINT_USER_SIZE;
9205 gtk_window_mnemonic_hash_foreach (guint keyval,
9211 GtkWindowKeysForeachFunc func;
9215 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9219 _gtk_window_keys_foreach (GtkWindow *window,
9220 GtkWindowKeysForeachFunc func,
9224 GtkMnemonicHash *mnemonic_hash;
9228 GtkWindowKeysForeachFunc func;
9232 info.window = window;
9234 info.func_data = func_data;
9236 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9238 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9239 gtk_window_mnemonic_hash_foreach, &info);
9241 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9244 GtkAccelGroup *group = groups->data;
9247 for (i = 0; i < group->priv->n_accels; i++)
9249 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9252 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9255 groups = groups->next;
9260 gtk_window_keys_changed (GtkWindow *window)
9262 gtk_window_free_key_hash (window);
9263 gtk_window_get_key_hash (window);
9266 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9268 struct _GtkWindowKeyEntry
9272 guint is_mnemonic : 1;
9276 window_key_entry_destroy (gpointer data)
9278 g_slice_free (GtkWindowKeyEntry, data);
9282 add_to_key_hash (GtkWindow *window,
9284 GdkModifierType modifiers,
9285 gboolean is_mnemonic,
9288 GtkKeyHash *key_hash = data;
9290 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9292 entry->keyval = keyval;
9293 entry->modifiers = modifiers;
9294 entry->is_mnemonic = is_mnemonic;
9296 /* GtkAccelGroup stores lowercased accelerators. To deal
9297 * with this, if <Shift> was specified, uppercase.
9299 if (modifiers & GDK_SHIFT_MASK)
9301 if (keyval == GDK_KEY_Tab)
9302 keyval = GDK_KEY_ISO_Left_Tab;
9304 keyval = gdk_keyval_to_upper (keyval);
9307 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9311 gtk_window_get_key_hash (GtkWindow *window)
9313 GdkScreen *screen = gtk_window_check_screen (window);
9314 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9319 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9320 (GDestroyNotify)window_key_entry_destroy);
9321 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9322 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9328 gtk_window_free_key_hash (GtkWindow *window)
9330 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9333 _gtk_key_hash_free (key_hash);
9334 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9339 * gtk_window_activate_key:
9340 * @window: a #GtkWindow
9341 * @event: a #GdkEventKey
9343 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9344 * called by the default ::key_press_event handler for toplevel windows,
9345 * however in some cases it may be useful to call this directly when
9346 * overriding the standard key handling for a toplevel window.
9348 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9353 gtk_window_activate_key (GtkWindow *window,
9356 GtkKeyHash *key_hash;
9357 GtkWindowKeyEntry *found_entry = NULL;
9358 gboolean enable_mnemonics;
9359 gboolean enable_accels;
9361 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9362 g_return_val_if_fail (event != NULL, FALSE);
9364 key_hash = gtk_window_get_key_hash (window);
9369 GSList *entries = _gtk_key_hash_lookup (key_hash,
9370 event->hardware_keycode,
9372 gtk_accelerator_get_default_mod_mask (),
9375 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9376 "gtk-enable-mnemonics", &enable_mnemonics,
9377 "gtk-enable-accels", &enable_accels,
9380 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9382 GtkWindowKeyEntry *entry = tmp_list->data;
9383 if (entry->is_mnemonic)
9385 if (enable_mnemonics)
9387 found_entry = entry;
9393 if (enable_accels && !found_entry)
9395 found_entry = entry;
9400 g_slist_free (entries);
9405 if (found_entry->is_mnemonic)
9407 if (enable_mnemonics)
9408 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9409 found_entry->modifiers);
9414 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9415 found_entry->modifiers);
9423 window_update_has_focus (GtkWindow *window)
9425 GtkWindowPrivate *priv = window->priv;
9426 GtkWidget *widget = GTK_WIDGET (window);
9427 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9429 if (has_focus != priv->has_focus)
9431 priv->has_focus = has_focus;
9435 if (priv->focus_widget &&
9436 priv->focus_widget != widget &&
9437 !gtk_widget_has_focus (priv->focus_widget))
9438 do_focus_change (priv->focus_widget, TRUE);
9442 if (priv->focus_widget &&
9443 priv->focus_widget != widget &&
9444 gtk_widget_has_focus (priv->focus_widget))
9445 do_focus_change (priv->focus_widget, FALSE);
9451 * _gtk_window_set_is_active:
9452 * @window: a #GtkWindow
9453 * @is_active: %TRUE if the window is in the currently active toplevel
9455 * Internal function that sets whether the #GtkWindow is part
9456 * of the currently active toplevel window (taking into account inter-process
9460 _gtk_window_set_is_active (GtkWindow *window,
9463 GtkWindowPrivate *priv;
9465 g_return_if_fail (GTK_IS_WINDOW (window));
9467 priv = window->priv;
9469 is_active = is_active != FALSE;
9471 if (is_active != priv->is_active)
9473 priv->is_active = is_active;
9474 window_update_has_focus (window);
9476 g_object_notify (G_OBJECT (window), "is-active");
9481 * _gtk_window_set_is_toplevel:
9482 * @window: a #GtkWindow
9483 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9484 * parent of the root window); %FALSE if it is not (for example, for an
9485 * in-process, parented GtkPlug)
9487 * Internal function used by #GtkPlug when it gets parented/unparented by a
9488 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9489 * global list of toplevel windows.
9492 _gtk_window_set_is_toplevel (GtkWindow *window,
9493 gboolean is_toplevel)
9497 widget = GTK_WIDGET (window);
9499 if (gtk_widget_is_toplevel (widget))
9500 g_assert (g_slist_find (toplevel_list, window) != NULL);
9502 g_assert (g_slist_find (toplevel_list, window) == NULL);
9504 if (is_toplevel == gtk_widget_is_toplevel (widget))
9509 _gtk_widget_set_is_toplevel (widget, TRUE);
9510 toplevel_list = g_slist_prepend (toplevel_list, window);
9514 _gtk_widget_set_is_toplevel (widget, FALSE);
9515 toplevel_list = g_slist_remove (toplevel_list, window);
9520 * _gtk_window_set_has_toplevel_focus:
9521 * @window: a #GtkWindow
9522 * @has_toplevel_focus: %TRUE if the in
9524 * Internal function that sets whether the keyboard focus for the
9525 * toplevel window (taking into account inter-process embedding.)
9528 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9529 gboolean has_toplevel_focus)
9531 GtkWindowPrivate *priv;
9533 g_return_if_fail (GTK_IS_WINDOW (window));
9535 priv = window->priv;
9537 has_toplevel_focus = has_toplevel_focus != FALSE;
9539 if (has_toplevel_focus != priv->has_toplevel_focus)
9541 priv->has_toplevel_focus = has_toplevel_focus;
9542 window_update_has_focus (window);
9544 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9549 * gtk_window_set_auto_startup_notification:
9550 * @setting: %TRUE to automatically do startup notification
9552 * By default, after showing the first #GtkWindow, GTK+ calls
9553 * gdk_notify_startup_complete(). Call this function to disable
9554 * the automatic startup notification. You might do this if your
9555 * first window is a splash screen, and you want to delay notification
9556 * until after your real main window has been shown, for example.
9558 * In that example, you would disable startup notification
9559 * temporarily, show your splash screen, then re-enable it so that
9560 * showing the main window would automatically result in notification.
9565 gtk_window_set_auto_startup_notification (gboolean setting)
9567 disable_startup_notification = !setting;
9571 * gtk_window_get_window_type:
9572 * @window: a #GtkWindow
9574 * Gets the type of the window. See #GtkWindowType.
9576 * Return value: the type of the window
9581 gtk_window_get_window_type (GtkWindow *window)
9583 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9585 return window->priv->type;
9589 * gtk_window_get_mnemonics_visible:
9590 * @window: a #GtkWindow
9592 * Gets the value of the #GtkWindow:mnemonics-visible property.
9594 * Returns: %TRUE if mnemonics are supposed to be visible
9600 gtk_window_get_mnemonics_visible (GtkWindow *window)
9602 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9604 return window->priv->mnemonics_visible;
9608 * gtk_window_set_mnemonics_visible:
9609 * @window: a #GtkWindow
9610 * @setting: the new value
9612 * Sets the #GtkWindow:mnemonics-visible property.
9617 gtk_window_set_mnemonics_visible (GtkWindow *window,
9620 GtkWindowPrivate *priv;
9622 g_return_if_fail (GTK_IS_WINDOW (window));
9624 priv = window->priv;
9626 setting = setting != FALSE;
9628 if (priv->mnemonics_visible != setting)
9630 priv->mnemonics_visible = setting;
9631 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9634 priv->mnemonics_visible_set = TRUE;
9638 _gtk_window_get_wmclass (GtkWindow *window,
9639 gchar **wmclass_name,
9640 gchar **wmclass_class)
9642 GtkWindowPrivate *priv = window->priv;
9644 *wmclass_name = priv->wmclass_name;
9645 *wmclass_class = priv->wmclass_class;